index.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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. const {
  107. dependencies = {},
  108. devDependencies = {}
  109. } = pkg;
  110. if (!dependencies.postcss && !devDependencies.postcss) {
  111. 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`"));
  112. } else {
  113. hasExplicitDependencyOnPostCSS = true;
  114. }
  115. }
  116. }
  117. }
  118. }
  119. (0, _utils.reportError)(this, callback, error);
  120. return;
  121. }
  122. for (const warning of result.warnings()) {
  123. this.emitWarning((0, _utils.warningFactory)(warning));
  124. }
  125. for (const message of result.messages) {
  126. // eslint-disable-next-line default-case
  127. switch (message.type) {
  128. case "dependency":
  129. this.addDependency(message.file);
  130. break;
  131. case "build-dependency":
  132. this.addBuildDependency(message.file);
  133. break;
  134. case "missing-dependency":
  135. this.addMissingDependency(message.file);
  136. break;
  137. case "context-dependency":
  138. this.addContextDependency(message.file);
  139. break;
  140. case "dir-dependency":
  141. this.addContextDependency(message.dir);
  142. break;
  143. case "asset":
  144. if (message.content && message.file) {
  145. this.emitFile(message.file, message.content, message.sourceMap, message.info);
  146. }
  147. }
  148. }
  149. // eslint-disable-next-line no-undefined
  150. let map = result.map ? result.map.toJSON() : undefined;
  151. if (map && useSourceMap) {
  152. map = (0, _utils.normalizeSourceMapAfterPostcss)(map, this.context);
  153. }
  154. let ast;
  155. try {
  156. ast = {
  157. type: "postcss",
  158. version: result.processor.version,
  159. root: result.root
  160. };
  161. } catch (error) {
  162. (0, _utils.reportError)(this, callback, error);
  163. return;
  164. }
  165. callback(null, result.css, map, {
  166. ast
  167. });
  168. }