UNPKG

6.69 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = void 0;
7
8var _postcssValueParser = _interopRequireDefault(require("postcss-value-parser"));
9
10var _utils = require("../utils");
11
12function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
14function parseNode(atRule, key) {
15 // Convert only top-level @import
16 if (atRule.parent.type !== "root") {
17 return;
18 }
19
20 if (atRule.raws && atRule.raws.afterName && atRule.raws.afterName.trim().length > 0) {
21 const lastCommentIndex = atRule.raws.afterName.lastIndexOf("/*");
22 const matched = atRule.raws.afterName.slice(lastCommentIndex).match(_utils.WEBPACK_IGNORE_COMMENT_REGEXP);
23
24 if (matched && matched[2] === "true") {
25 return;
26 }
27 }
28
29 const prevNode = atRule.prev();
30
31 if (prevNode && prevNode.type === "comment") {
32 const matched = prevNode.text.match(_utils.WEBPACK_IGNORE_COMMENT_REGEXP);
33
34 if (matched && matched[2] === "true") {
35 return;
36 }
37 } // Nodes do not exists - `@import url('http://') :root {}`
38
39
40 if (atRule.nodes) {
41 const error = new Error("It looks like you didn't end your @import statement correctly. Child nodes are attached to it.");
42 error.node = atRule;
43 throw error;
44 }
45
46 const {
47 nodes: paramsNodes
48 } = (0, _postcssValueParser.default)(atRule[key]); // No nodes - `@import ;`
49 // Invalid type - `@import foo-bar;`
50
51 if (paramsNodes.length === 0 || paramsNodes[0].type !== "string" && paramsNodes[0].type !== "function") {
52 const error = new Error(`Unable to find uri in "${atRule.toString()}"`);
53 error.node = atRule;
54 throw error;
55 }
56
57 let isStringValue;
58 let url;
59
60 if (paramsNodes[0].type === "string") {
61 isStringValue = true;
62 url = paramsNodes[0].value;
63 } else {
64 // Invalid function - `@import nourl(test.css);`
65 if (paramsNodes[0].value.toLowerCase() !== "url") {
66 const error = new Error(`Unable to find uri in "${atRule.toString()}"`);
67 error.node = atRule;
68 throw error;
69 }
70
71 isStringValue = paramsNodes[0].nodes.length !== 0 && paramsNodes[0].nodes[0].type === "string";
72 url = isStringValue ? paramsNodes[0].nodes[0].value : _postcssValueParser.default.stringify(paramsNodes[0].nodes);
73 }
74
75 url = (0, _utils.normalizeUrl)(url, isStringValue);
76 const isRequestable = (0, _utils.isUrlRequestable)(url);
77 let prefix;
78
79 if (isRequestable) {
80 const queryParts = url.split("!");
81
82 if (queryParts.length > 1) {
83 url = queryParts.pop();
84 prefix = queryParts.join("!");
85 }
86 } // Empty url - `@import "";` or `@import url();`
87
88
89 if (url.trim().length === 0) {
90 const error = new Error(`Unable to find uri in "${atRule.toString()}"`);
91 error.node = atRule;
92 throw error;
93 }
94
95 const mediaNodes = paramsNodes.slice(1);
96 let media;
97
98 if (mediaNodes.length > 0) {
99 media = _postcssValueParser.default.stringify(mediaNodes).trim().toLowerCase();
100 } // eslint-disable-next-line consistent-return
101
102
103 return {
104 atRule,
105 prefix,
106 url,
107 media,
108 isRequestable
109 };
110}
111
112const plugin = (options = {}) => {
113 return {
114 postcssPlugin: "postcss-import-parser",
115
116 prepare(result) {
117 const parsedAtRules = [];
118 return {
119 AtRule: {
120 import(atRule) {
121 let parsedAtRule;
122
123 try {
124 parsedAtRule = parseNode(atRule, "params", result);
125 } catch (error) {
126 result.warn(error.message, {
127 node: error.node
128 });
129 }
130
131 if (!parsedAtRule) {
132 return;
133 }
134
135 parsedAtRules.push(parsedAtRule);
136 }
137
138 },
139
140 async OnceExit() {
141 if (parsedAtRules.length === 0) {
142 return;
143 }
144
145 const resolvedAtRules = await Promise.all(parsedAtRules.map(async parsedAtRule => {
146 const {
147 atRule,
148 isRequestable,
149 prefix,
150 url,
151 media
152 } = parsedAtRule;
153
154 if (options.filter) {
155 const needKeep = await options.filter(url, media);
156
157 if (!needKeep) {
158 return;
159 }
160 }
161
162 if (isRequestable) {
163 const request = (0, _utils.requestify)(url, options.rootContext);
164 const {
165 resolver,
166 context
167 } = options;
168 const resolvedUrl = await (0, _utils.resolveRequests)(resolver, context, [...new Set([request, url])]);
169
170 if (!resolvedUrl) {
171 return;
172 }
173
174 if (resolvedUrl === options.resourcePath) {
175 atRule.remove();
176 return;
177 }
178
179 atRule.remove(); // eslint-disable-next-line consistent-return
180
181 return {
182 url: resolvedUrl,
183 media,
184 prefix,
185 isRequestable
186 };
187 }
188
189 atRule.remove(); // eslint-disable-next-line consistent-return
190
191 return {
192 url,
193 media,
194 prefix,
195 isRequestable
196 };
197 }));
198 const urlToNameMap = new Map();
199
200 for (let index = 0; index <= resolvedAtRules.length - 1; index++) {
201 const resolvedAtRule = resolvedAtRules[index];
202
203 if (!resolvedAtRule) {
204 // eslint-disable-next-line no-continue
205 continue;
206 }
207
208 const {
209 url,
210 isRequestable,
211 media
212 } = resolvedAtRule;
213
214 if (!isRequestable) {
215 options.api.push({
216 url,
217 media,
218 index
219 }); // eslint-disable-next-line no-continue
220
221 continue;
222 }
223
224 const {
225 prefix
226 } = resolvedAtRule;
227 const newUrl = prefix ? `${prefix}!${url}` : url;
228 let importName = urlToNameMap.get(newUrl);
229
230 if (!importName) {
231 importName = `___CSS_LOADER_AT_RULE_IMPORT_${urlToNameMap.size}___`;
232 urlToNameMap.set(newUrl, importName);
233 options.imports.push({
234 type: "rule_import",
235 importName,
236 url: options.urlHandler(newUrl),
237 index
238 });
239 }
240
241 options.api.push({
242 importName,
243 media,
244 index
245 });
246 }
247 }
248
249 };
250 }
251
252 };
253};
254
255plugin.postcss = true;
256var _default = plugin;
257exports.default = _default;
\No newline at end of file