index.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = loader;
  6. var _path = _interopRequireDefault(require("path"));
  7. var _package = _interopRequireDefault(require("postcss/package.json"));
  8. var _options = _interopRequireDefault(require("./options.json"));
  9. var _utils = require("./utils");
  10. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  11. let hasExplicitDependencyOnPostCSS = false;
  12. /**
  13. * **PostCSS Loader**
  14. *
  15. * Loads && processes CSS with [PostCSS](https://github.com/postcss/postcss)
  16. *
  17. * @method loader
  18. *
  19. * @param {String} content Source
  20. * @param {Object} sourceMap Source Map
  21. * @param {Object} meta Meta
  22. *
  23. * @return {callback} callback Result
  24. */
  25. async function loader(content, sourceMap, meta) {
  26. const options = this.getOptions(_options.default);
  27. const callback = this.async();
  28. const configOption = typeof options.postcssOptions === "undefined" || typeof options.postcssOptions.config === "undefined" ? true : options.postcssOptions.config;
  29. let implementation;
  30. try {
  31. implementation = (0, _utils.getPostcssImplementation)(this, options.implementation);
  32. } catch (error) {
  33. callback(error);
  34. return;
  35. }
  36. if (!implementation) {
  37. callback(new Error(`The Postcss implementation "${options.implementation}" not found`));
  38. return;
  39. }
  40. let loadedConfig;
  41. if (configOption) {
  42. try {
  43. loadedConfig = await (0, _utils.loadConfig)(this, configOption, options.postcssOptions);
  44. } catch (error) {
  45. callback(error);
  46. return;
  47. }
  48. }
  49. const {
  50. plugins,
  51. processOptions
  52. } = await (0, _utils.getPostcssOptions)(this, loadedConfig, options.postcssOptions);
  53. const useSourceMap = typeof options.sourceMap !== "undefined" ? options.sourceMap : this.sourceMap;
  54. if (useSourceMap) {
  55. processOptions.map = {
  56. inline: false,
  57. annotation: false,
  58. ...processOptions.map
  59. };
  60. }
  61. if (sourceMap && processOptions.map) {
  62. processOptions.map.prev = (0, _utils.normalizeSourceMap)(sourceMap, this.context);
  63. }
  64. let root;
  65. // Reuse PostCSS AST from other loaders
  66. if (meta && meta.ast && meta.ast.type === "postcss" &&
  67. // eslint-disable-next-line global-require
  68. require("semver").satisfies(meta.ast.version, `^${_package.default.version}`)) {
  69. ({
  70. root
  71. } = meta.ast);
  72. }
  73. if (!root && options.execute) {
  74. // eslint-disable-next-line no-param-reassign
  75. content = (0, _utils.exec)(content, this);
  76. }
  77. let result;
  78. let processor;
  79. try {
  80. processor = implementation(plugins);
  81. result = await processor.process(root || content, processOptions);
  82. } catch (error) {
  83. // Check postcss versions to avoid using PostCSS 7.
  84. // For caching reasons, we use the readFileSync and existsSync functions from the context,
  85. // not the functions from the `fs` module.
  86. if (!hasExplicitDependencyOnPostCSS && processor && processor.version && processor.version.startsWith("7.")) {
  87. // The `findPackageJsonDir` function returns `string` or `null`.
  88. // This is used to do for caching, that is, an explicit comparison with `undefined`
  89. // is used to make the condition body run once.
  90. const packageJSONDir = (0, _utils.findPackageJSONDir)(process.cwd(), this.fs.statSync);
  91. if (packageJSONDir) {
  92. let bufferOfPackageJSON;
  93. try {
  94. bufferOfPackageJSON = this.fs.readFileSync(_path.default.resolve(packageJSONDir, "package.json"), "utf8");
  95. } catch (_error) {
  96. // Nothing
  97. }
  98. if (bufferOfPackageJSON) {
  99. let pkg;
  100. try {
  101. pkg = JSON.parse(bufferOfPackageJSON);
  102. } catch (_error) {
  103. // Nothing
  104. }
  105. if (pkg) {
  106. if (!pkg.dependencies.postcss && !pkg.devDependencies.postcss) {
  107. this.emitWarning(new Error("Add postcss as project dependency. postcss is not a peer dependency for postcss-loader. " + "Use `npm install postcss` or `yarn add postcss`"));
  108. } else {
  109. hasExplicitDependencyOnPostCSS = true;
  110. }
  111. }
  112. }
  113. }
  114. }
  115. (0, _utils.reportError)(this, callback, error);
  116. return;
  117. }
  118. for (const warning of result.warnings()) {
  119. this.emitWarning((0, _utils.warningFactory)(warning));
  120. }
  121. for (const message of result.messages) {
  122. // eslint-disable-next-line default-case
  123. switch (message.type) {
  124. case "dependency":
  125. this.addDependency(message.file);
  126. break;
  127. case "build-dependency":
  128. this.addBuildDependency(message.file);
  129. break;
  130. case "missing-dependency":
  131. this.addMissingDependency(message.file);
  132. break;
  133. case "context-dependency":
  134. this.addContextDependency(message.file);
  135. break;
  136. case "dir-dependency":
  137. this.addContextDependency(message.dir);
  138. break;
  139. case "asset":
  140. if (message.content && message.file) {
  141. this.emitFile(message.file, message.content, message.sourceMap, message.info);
  142. }
  143. }
  144. }
  145. // eslint-disable-next-line no-undefined
  146. let map = result.map ? result.map.toJSON() : undefined;
  147. if (map && useSourceMap) {
  148. map = (0, _utils.normalizeSourceMapAfterPostcss)(map, this.context);
  149. }
  150. let ast;
  151. try {
  152. ast = {
  153. type: "postcss",
  154. version: result.processor.version,
  155. root: result.root
  156. };
  157. } catch (error) {
  158. (0, _utils.reportError)(this, callback, error);
  159. return;
  160. }
  161. callback(null, result.css, map, {
  162. ast
  163. });
  164. }