css-loader 5.1.4 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [5.2.0](https://github.com/webpack-contrib/css-loader/compare/v5.1.4...v5.2.0) (2021-03-24)
6
+
7
+
8
+ ### Features
9
+
10
+ * support async functions for `url` and `import` options ([#1277](https://github.com/webpack-contrib/css-loader/issues/1277)) ([c5062db](https://github.com/webpack-contrib/css-loader/commit/c5062db3fc849d882a07b9f2c9f66f00325c8896))
11
+
5
12
  ### [5.1.4](https://github.com/webpack-contrib/css-loader/compare/v5.1.3...v5.1.4) (2021-03-24)
6
13
 
7
14
 
@@ -11,22 +11,22 @@ var _utils = require("../utils");
11
11
 
12
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
13
 
14
- function visitor(result, parsedResults, node, key) {
14
+ function parseNode(atRule, key) {
15
15
  // Convert only top-level @import
16
- if (node.parent.type !== "root") {
16
+ if (atRule.parent.type !== "root") {
17
17
  return;
18
18
  }
19
19
 
20
- if (node.raws && node.raws.afterName && node.raws.afterName.trim().length > 0) {
21
- const lastCommentIndex = node.raws.afterName.lastIndexOf("/*");
22
- const matched = node.raws.afterName.slice(lastCommentIndex).match(_utils.webpackIgnoreCommentRegexp);
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.webpackIgnoreCommentRegexp);
23
23
 
24
24
  if (matched && matched[2] === "true") {
25
25
  return;
26
26
  }
27
27
  }
28
28
 
29
- const prevNode = node.prev();
29
+ const prevNode = atRule.prev();
30
30
 
31
31
  if (prevNode && prevNode.type === "comment") {
32
32
  const matched = prevNode.text.match(_utils.webpackIgnoreCommentRegexp);
@@ -37,23 +37,21 @@ function visitor(result, parsedResults, node, key) {
37
37
  } // Nodes do not exists - `@import url('http://') :root {}`
38
38
 
39
39
 
40
- if (node.nodes) {
41
- result.warn("It looks like you didn't end your @import statement correctly. Child nodes are attached to it.", {
42
- node
43
- });
44
- return;
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;
45
44
  }
46
45
 
47
46
  const {
48
47
  nodes: paramsNodes
49
- } = (0, _postcssValueParser.default)(node[key]); // No nodes - `@import ;`
48
+ } = (0, _postcssValueParser.default)(atRule[key]); // No nodes - `@import ;`
50
49
  // Invalid type - `@import foo-bar;`
51
50
 
52
51
  if (paramsNodes.length === 0 || paramsNodes[0].type !== "string" && paramsNodes[0].type !== "function") {
53
- result.warn(`Unable to find uri in "${node.toString()}"`, {
54
- node
55
- });
56
- return;
52
+ const error = new Error(`Unable to find uri in "${atRule.toString()}"`);
53
+ error.node = atRule;
54
+ throw error;
57
55
  }
58
56
 
59
57
  let isStringValue;
@@ -65,30 +63,50 @@ function visitor(result, parsedResults, node, key) {
65
63
  } else {
66
64
  // Invalid function - `@import nourl(test.css);`
67
65
  if (paramsNodes[0].value.toLowerCase() !== "url") {
68
- result.warn(`Unable to find uri in "${node.toString()}"`, {
69
- node
70
- });
71
- return;
66
+ const error = new Error(`Unable to find uri in "${atRule.toString()}"`);
67
+ error.node = atRule;
68
+ throw error;
72
69
  }
73
70
 
74
71
  isStringValue = paramsNodes[0].nodes.length !== 0 && paramsNodes[0].nodes[0].type === "string";
75
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
+ }
76
86
  } // Empty url - `@import "";` or `@import url();`
77
87
 
78
88
 
79
89
  if (url.trim().length === 0) {
80
- result.warn(`Unable to find uri in "${node.toString()}"`, {
81
- node
82
- });
83
- return;
90
+ const error = new Error(`Unable to find uri in "${atRule.toString()}"`);
91
+ error.node = atRule;
92
+ throw error;
84
93
  }
85
94
 
86
- parsedResults.push({
87
- node,
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,
88
106
  url,
89
- isStringValue,
90
- mediaNodes: paramsNodes.slice(1)
91
- });
107
+ media,
108
+ isRequestable
109
+ };
92
110
  }
93
111
 
94
112
  const plugin = (options = {}) => {
@@ -96,123 +114,94 @@ const plugin = (options = {}) => {
96
114
  postcssPlugin: "postcss-import-parser",
97
115
 
98
116
  prepare(result) {
99
- const parsedResults = [];
117
+ const parsedAtRules = [];
100
118
  return {
101
119
  AtRule: {
102
120
  import(atRule) {
103
- visitor(result, parsedResults, atRule, "params");
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);
104
136
  }
105
137
 
106
138
  },
107
139
 
108
140
  async OnceExit() {
109
- if (parsedResults.length === 0) {
141
+ if (parsedAtRules.length === 0) {
110
142
  return;
111
143
  }
112
144
 
113
- const imports = new Map();
114
- const tasks = [];
115
-
116
- for (const parsedResult of parsedResults) {
145
+ const resolvedAtRules = await Promise.all(parsedAtRules.map(async parsedAtRule => {
117
146
  const {
118
- node,
147
+ atRule,
148
+ isRequestable,
149
+ prefix,
119
150
  url,
120
- isStringValue,
121
- mediaNodes
122
- } = parsedResult;
123
- let normalizedUrl = url;
124
- let prefix = "";
125
- const isRequestable = (0, _utils.isUrlRequestable)(normalizedUrl);
126
-
127
- if (isRequestable) {
128
- const queryParts = normalizedUrl.split("!");
129
-
130
- if (queryParts.length > 1) {
131
- normalizedUrl = queryParts.pop();
132
- prefix = queryParts.join("!");
133
- }
134
-
135
- normalizedUrl = (0, _utils.normalizeUrl)(normalizedUrl, isStringValue); // Empty url after normalize - `@import '\
136
- // \
137
- // \
138
- // ';
151
+ media
152
+ } = parsedAtRule;
139
153
 
140
- if (normalizedUrl.trim().length === 0) {
141
- result.warn(`Unable to find uri in "${node.toString()}"`, {
142
- node
143
- }); // eslint-disable-next-line no-continue
154
+ if (options.filter) {
155
+ const needKeep = await options.filter(url, media);
144
156
 
145
- continue;
157
+ if (!needKeep) {
158
+ return null;
146
159
  }
147
160
  }
148
161
 
149
- let media;
150
-
151
- if (mediaNodes.length > 0) {
152
- media = _postcssValueParser.default.stringify(mediaNodes).trim().toLowerCase();
153
- }
154
-
155
- if (options.filter && !options.filter(normalizedUrl, media)) {
156
- // eslint-disable-next-line no-continue
157
- continue;
158
- }
159
-
160
- node.remove();
162
+ atRule.remove();
161
163
 
162
164
  if (isRequestable) {
163
- const request = (0, _utils.requestify)(normalizedUrl, options.rootContext);
164
- tasks.push((async () => {
165
- const {
166
- resolver,
167
- context
168
- } = options;
169
- const resolvedUrl = await (0, _utils.resolveRequests)(resolver, context, [...new Set([request, normalizedUrl])]);
170
- return {
171
- url: resolvedUrl,
172
- media,
173
- prefix,
174
- isRequestable
175
- };
176
- })());
177
- } else {
178
- tasks.push({
179
- url,
165
+ const request = (0, _utils.requestify)(url, options.rootContext);
166
+ const {
167
+ resolver,
168
+ context
169
+ } = options;
170
+ const resolvedUrl = await (0, _utils.resolveRequests)(resolver, context, [...new Set([request, url])]);
171
+ return {
172
+ url: resolvedUrl,
180
173
  media,
181
174
  prefix,
182
175
  isRequestable
183
- });
176
+ };
184
177
  }
185
- }
186
178
 
187
- const results = await Promise.all(tasks);
179
+ return {
180
+ url,
181
+ media,
182
+ prefix,
183
+ isRequestable
184
+ };
185
+ }));
186
+ const urlToNameMap = new Map();
187
+
188
+ for (let index = 0; index <= resolvedAtRules.length - 1; index++) {
189
+ const resolvedAtRule = resolvedAtRules[index];
190
+
191
+ if (!resolvedAtRule) {
192
+ // eslint-disable-next-line no-continue
193
+ continue;
194
+ }
188
195
 
189
- for (let index = 0; index <= results.length - 1; index++) {
190
196
  const {
191
197
  url,
192
198
  isRequestable,
193
199
  media
194
- } = results[index];
195
-
196
- if (isRequestable) {
197
- const {
198
- prefix
199
- } = results[index];
200
- const newUrl = prefix ? `${prefix}!${url}` : url;
201
- const importKey = newUrl;
202
- let importName = imports.get(importKey);
203
-
204
- if (!importName) {
205
- importName = `___CSS_LOADER_AT_RULE_IMPORT_${imports.size}___`;
206
- imports.set(importKey, importName);
207
- options.imports.push({
208
- importName,
209
- url: options.urlHandler(newUrl),
210
- index
211
- });
212
- }
200
+ } = resolvedAtRule;
213
201
 
202
+ if (!isRequestable) {
214
203
  options.api.push({
215
- importName,
204
+ url,
216
205
  media,
217
206
  index
218
207
  }); // eslint-disable-next-line no-continue
@@ -220,8 +209,24 @@ const plugin = (options = {}) => {
220
209
  continue;
221
210
  }
222
211
 
212
+ const {
213
+ prefix
214
+ } = resolvedAtRule;
215
+ const newUrl = prefix ? `${prefix}!${url}` : url;
216
+ let importName = urlToNameMap.get(newUrl);
217
+
218
+ if (!importName) {
219
+ importName = `___CSS_LOADER_AT_RULE_IMPORT_${urlToNameMap.size}___`;
220
+ urlToNameMap.set(newUrl, importName);
221
+ options.imports.push({
222
+ importName,
223
+ url: options.urlHandler(newUrl),
224
+ index
225
+ });
226
+ }
227
+
223
228
  options.api.push({
224
- url,
229
+ importName,
225
230
  media,
226
231
  index
227
232
  });
@@ -19,22 +19,6 @@ function getNodeFromUrlFunc(node) {
19
19
  return node.nodes && node.nodes[0];
20
20
  }
21
21
 
22
- function shouldHandleRule(rule, node, result) {
23
- // https://www.w3.org/TR/css-syntax-3/#typedef-url-token
24
- if (rule.url.replace(/^[\s]+|[\s]+$/g, "").length === 0) {
25
- result.warn(`Unable to find uri in '${node.toString()}'`, {
26
- node
27
- });
28
- return false;
29
- }
30
-
31
- if (!(0, _utils.isUrlRequestable)(rule.url)) {
32
- return false;
33
- }
34
-
35
- return true;
36
- }
37
-
38
22
  function getWebpackIgnoreCommentValue(index, nodes, inBetween) {
39
23
  if (index === 0 && typeof inBetween !== "undefined") {
40
24
  return inBetween;
@@ -65,17 +49,32 @@ function getWebpackIgnoreCommentValue(index, nodes, inBetween) {
65
49
  return matched && matched[2] === "true";
66
50
  }
67
51
 
68
- function visitor(result, parsedResults, node, key) {
69
- if (!needParseDeclaration.test(node[key])) {
52
+ function shouldHandleURL(url, declaration, result) {
53
+ if (url.length === 0) {
54
+ result.warn(`Unable to find uri in '${declaration.toString()}'`, {
55
+ node: declaration
56
+ });
57
+ return false;
58
+ }
59
+
60
+ if (!(0, _utils.isUrlRequestable)(url)) {
61
+ return false;
62
+ }
63
+
64
+ return true;
65
+ }
66
+
67
+ function parseDeclaration(declaration, key, result) {
68
+ if (!needParseDeclaration.test(declaration[key])) {
70
69
  return;
71
70
  }
72
71
 
73
- const parsed = (0, _postcssValueParser.default)(node.raws && node.raws.value && node.raws.value.raw ? node.raws.value.raw : node[key]);
72
+ const parsed = (0, _postcssValueParser.default)(declaration.raws && declaration.raws.value && declaration.raws.value.raw ? declaration.raws.value.raw : declaration[key]);
74
73
  let inBetween;
75
74
 
76
- if (node.raws && node.raws.between) {
77
- const lastCommentIndex = node.raws.between.lastIndexOf("/*");
78
- const matched = node.raws.between.slice(lastCommentIndex).match(_utils.webpackIgnoreCommentRegexp);
75
+ if (declaration.raws && declaration.raws.between) {
76
+ const lastCommentIndex = declaration.raws.between.lastIndexOf("/*");
77
+ const matched = declaration.raws.between.slice(lastCommentIndex).match(_utils.webpackIgnoreCommentRegexp);
79
78
 
80
79
  if (matched) {
81
80
  inBetween = matched[2] === "true";
@@ -83,7 +82,7 @@ function visitor(result, parsedResults, node, key) {
83
82
  }
84
83
 
85
84
  let isIgnoreOnDeclaration = false;
86
- const prevNode = node.prev();
85
+ const prevNode = declaration.prev();
87
86
 
88
87
  if (prevNode && prevNode.type === "comment") {
89
88
  const matched = prevNode.text.match(_utils.webpackIgnoreCommentRegexp);
@@ -94,6 +93,7 @@ function visitor(result, parsedResults, node, key) {
94
93
  }
95
94
 
96
95
  let needIgnore;
96
+ const parsedURLs = [];
97
97
  parsed.walk((valueNode, index, valueNodes) => {
98
98
  if (valueNode.type !== "function") {
99
99
  return;
@@ -115,23 +115,30 @@ function visitor(result, parsedResults, node, key) {
115
115
  nodes
116
116
  } = valueNode;
117
117
  const isStringValue = nodes.length !== 0 && nodes[0].type === "string";
118
- const url = isStringValue ? nodes[0].value : _postcssValueParser.default.stringify(nodes);
119
- const rule = {
120
- node: getNodeFromUrlFunc(valueNode),
121
- url,
122
- needQuotes: false,
123
- isStringValue
124
- };
118
+ let url = isStringValue ? nodes[0].value : _postcssValueParser.default.stringify(nodes);
119
+ url = (0, _utils.normalizeUrl)(url, isStringValue); // Do not traverse inside `url`
125
120
 
126
- if (shouldHandleRule(rule, node, result)) {
127
- parsedResults.push({
128
- node,
129
- rule,
130
- parsed
131
- });
132
- } // Do not traverse inside `url`
133
- // eslint-disable-next-line consistent-return
121
+ if (!shouldHandleURL(url, declaration, result)) {
122
+ // eslint-disable-next-line consistent-return
123
+ return false;
124
+ }
134
125
 
126
+ const queryParts = url.split("!");
127
+ let prefix;
128
+
129
+ if (queryParts.length > 1) {
130
+ url = queryParts.pop();
131
+ prefix = queryParts.join("!");
132
+ }
133
+
134
+ parsedURLs.push({
135
+ declaration,
136
+ parsed,
137
+ node: getNodeFromUrlFunc(valueNode),
138
+ prefix,
139
+ url,
140
+ needQuotes: false
141
+ }); // eslint-disable-next-line consistent-return
135
142
 
136
143
  return false;
137
144
  } else if (isImageSetFunc.test(valueNode.value)) {
@@ -158,21 +165,30 @@ function visitor(result, parsedResults, node, key) {
158
165
  nodes
159
166
  } = nNode;
160
167
  const isStringValue = nodes.length !== 0 && nodes[0].type === "string";
161
- const url = isStringValue ? nodes[0].value : _postcssValueParser.default.stringify(nodes);
162
- const rule = {
168
+ let url = isStringValue ? nodes[0].value : _postcssValueParser.default.stringify(nodes);
169
+ url = (0, _utils.normalizeUrl)(url, isStringValue); // Do not traverse inside `url`
170
+
171
+ if (!shouldHandleURL(url, declaration, result)) {
172
+ // eslint-disable-next-line consistent-return
173
+ return false;
174
+ }
175
+
176
+ const queryParts = url.split("!");
177
+ let prefix;
178
+
179
+ if (queryParts.length > 1) {
180
+ url = queryParts.pop();
181
+ prefix = queryParts.join("!");
182
+ }
183
+
184
+ parsedURLs.push({
185
+ declaration,
186
+ parsed,
163
187
  node: getNodeFromUrlFunc(nNode),
188
+ prefix,
164
189
  url,
165
- needQuotes: false,
166
- isStringValue
167
- };
168
-
169
- if (shouldHandleRule(rule, node, result)) {
170
- parsedResults.push({
171
- node,
172
- rule,
173
- parsed
174
- });
175
- }
190
+ needQuotes: false
191
+ });
176
192
  } else if (type === "string") {
177
193
  needIgnore = getWebpackIgnoreCommentValue(innerIndex, valueNode.nodes);
178
194
 
@@ -186,20 +202,29 @@ function visitor(result, parsedResults, node, key) {
186
202
  continue;
187
203
  }
188
204
 
189
- const rule = {
190
- node: nNode,
191
- url: value,
192
- needQuotes: true,
193
- isStringValue: true
194
- };
195
-
196
- if (shouldHandleRule(rule, node, result)) {
197
- parsedResults.push({
198
- node,
199
- rule,
200
- parsed
201
- });
205
+ let url = (0, _utils.normalizeUrl)(value, true); // Do not traverse inside `url`
206
+
207
+ if (!shouldHandleURL(url, declaration, result)) {
208
+ // eslint-disable-next-line consistent-return
209
+ return false;
210
+ }
211
+
212
+ const queryParts = url.split("!");
213
+ let prefix;
214
+
215
+ if (queryParts.length > 1) {
216
+ url = queryParts.pop();
217
+ prefix = queryParts.join("!");
202
218
  }
219
+
220
+ parsedURLs.push({
221
+ declaration,
222
+ parsed,
223
+ node: nNode,
224
+ prefix,
225
+ url,
226
+ needQuotes: true
227
+ });
203
228
  }
204
229
  } // Do not traverse inside `image-set`
205
230
  // eslint-disable-next-line consistent-return
@@ -207,7 +232,9 @@ function visitor(result, parsedResults, node, key) {
207
232
 
208
233
  return false;
209
234
  }
210
- });
235
+ }); // eslint-disable-next-line consistent-return
236
+
237
+ return parsedURLs;
211
238
  }
212
239
 
213
240
  const plugin = (options = {}) => {
@@ -215,39 +242,60 @@ const plugin = (options = {}) => {
215
242
  postcssPlugin: "postcss-url-parser",
216
243
 
217
244
  prepare(result) {
218
- const parsedResults = [];
245
+ const parsedDeclarations = [];
219
246
  return {
220
247
  Declaration(declaration) {
221
- visitor(result, parsedResults, declaration, "value");
248
+ const parsedURL = parseDeclaration(declaration, "value", result);
249
+
250
+ if (!parsedURL) {
251
+ return;
252
+ }
253
+
254
+ parsedDeclarations.push(...parsedURL);
222
255
  },
223
256
 
224
257
  async OnceExit() {
225
- if (parsedResults.length === 0) {
258
+ if (parsedDeclarations.length === 0) {
226
259
  return;
227
260
  }
228
261
 
229
- const tasks = [];
230
- const imports = new Map();
231
- const replacements = new Map();
232
- let hasUrlImportHelper = false;
233
-
234
- for (const parsedResult of parsedResults) {
262
+ const resolvedDeclarations = await Promise.all(parsedDeclarations.map(async parsedDeclaration => {
235
263
  const {
236
- url,
237
- isStringValue
238
- } = parsedResult.rule;
239
- let normalizedUrl = url;
240
- let prefix = "";
241
- const queryParts = normalizedUrl.split("!");
242
-
243
- if (queryParts.length > 1) {
244
- normalizedUrl = queryParts.pop();
245
- prefix = queryParts.join("!");
264
+ url
265
+ } = parsedDeclaration;
266
+
267
+ if (options.filter) {
268
+ const needKeep = await options.filter(url);
269
+
270
+ if (!needKeep) {
271
+ return null;
272
+ }
246
273
  }
247
274
 
248
- normalizedUrl = (0, _utils.normalizeUrl)(normalizedUrl, isStringValue);
275
+ const splittedUrl = url.split(/(\?)?#/);
276
+ const [pathname, query, hashOrQuery] = splittedUrl;
277
+ let hash = query ? "?" : "";
278
+ hash += hashOrQuery ? `#${hashOrQuery}` : "";
279
+ const request = (0, _utils.requestify)(pathname, options.rootContext);
280
+ const {
281
+ resolver,
282
+ context
283
+ } = options;
284
+ const resolvedUrl = await (0, _utils.resolveRequests)(resolver, context, [...new Set([request, url])]);
285
+ return { ...parsedDeclaration,
286
+ url: resolvedUrl,
287
+ hash
288
+ };
289
+ }));
290
+ const results = await Promise.all(resolvedDeclarations);
291
+ const urlToNameMap = new Map();
292
+ const urlToReplacementMap = new Map();
293
+ let hasUrlImportHelper = false;
249
294
 
250
- if (!options.filter(normalizedUrl)) {
295
+ for (let index = 0; index <= results.length - 1; index++) {
296
+ const item = results[index];
297
+
298
+ if (!item) {
251
299
  // eslint-disable-next-line no-continue
252
300
  continue;
253
301
  }
@@ -261,46 +309,16 @@ const plugin = (options = {}) => {
261
309
  hasUrlImportHelper = true;
262
310
  }
263
311
 
264
- const splittedUrl = normalizedUrl.split(/(\?)?#/);
265
- const [pathname, query, hashOrQuery] = splittedUrl;
266
- let hash = query ? "?" : "";
267
- hash += hashOrQuery ? `#${hashOrQuery}` : "";
268
- const request = (0, _utils.requestify)(pathname, options.rootContext);
269
- tasks.push((async () => {
270
- const {
271
- resolver,
272
- context
273
- } = options;
274
- const resolvedUrl = await (0, _utils.resolveRequests)(resolver, context, [...new Set([request, normalizedUrl])]);
275
- return {
276
- url: resolvedUrl,
277
- prefix,
278
- hash,
279
- parsedResult
280
- };
281
- })());
282
- }
283
-
284
- const results = await Promise.all(tasks);
285
-
286
- for (let index = 0; index <= results.length - 1; index++) {
287
312
  const {
288
313
  url,
289
- prefix,
290
- hash,
291
- parsedResult: {
292
- node,
293
- rule,
294
- parsed
295
- }
296
- } = results[index];
314
+ prefix
315
+ } = item;
297
316
  const newUrl = prefix ? `${prefix}!${url}` : url;
298
- const importKey = newUrl;
299
- let importName = imports.get(importKey);
317
+ let importName = urlToNameMap.get(newUrl);
300
318
 
301
319
  if (!importName) {
302
- importName = `___CSS_LOADER_URL_IMPORT_${imports.size}___`;
303
- imports.set(importKey, importName);
320
+ importName = `___CSS_LOADER_URL_IMPORT_${urlToNameMap.size}___`;
321
+ urlToNameMap.set(newUrl, importName);
304
322
  options.imports.push({
305
323
  importName,
306
324
  url: options.urlHandler(newUrl),
@@ -309,18 +327,19 @@ const plugin = (options = {}) => {
309
327
  }
310
328
 
311
329
  const {
330
+ hash,
312
331
  needQuotes
313
- } = rule;
332
+ } = item;
314
333
  const replacementKey = JSON.stringify({
315
334
  newUrl,
316
335
  hash,
317
336
  needQuotes
318
337
  });
319
- let replacementName = replacements.get(replacementKey);
338
+ let replacementName = urlToReplacementMap.get(replacementKey);
320
339
 
321
340
  if (!replacementName) {
322
- replacementName = `___CSS_LOADER_URL_REPLACEMENT_${replacements.size}___`;
323
- replacements.set(replacementKey, replacementName);
341
+ replacementName = `___CSS_LOADER_URL_REPLACEMENT_${urlToReplacementMap.size}___`;
342
+ urlToReplacementMap.set(replacementKey, replacementName);
324
343
  options.replacements.push({
325
344
  replacementName,
326
345
  importName,
@@ -330,11 +349,11 @@ const plugin = (options = {}) => {
330
349
  } // eslint-disable-next-line no-param-reassign
331
350
 
332
351
 
333
- rule.node.type = "word"; // eslint-disable-next-line no-param-reassign
352
+ item.node.type = "word"; // eslint-disable-next-line no-param-reassign
334
353
 
335
- rule.node.value = replacementName; // eslint-disable-next-line no-param-reassign
354
+ item.node.value = replacementName; // eslint-disable-next-line no-param-reassign
336
355
 
337
- node.value = parsed.toString();
356
+ item.declaration.value = item.parsed.toString();
338
357
  }
339
358
  }
340
359
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "css-loader",
3
- "version": "5.1.4",
3
+ "version": "5.2.0",
4
4
  "description": "css loader module for webpack",
5
5
  "license": "MIT",
6
6
  "repository": "webpack-contrib/css-loader",