UNPKG

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