webpack 5.96.1 → 5.97.1
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/lib/CssModule.js +5 -0
- package/lib/DefinePlugin.js +7 -1
- package/lib/DependencyTemplate.js +2 -2
- package/lib/EvalSourceMapDevToolPlugin.js +5 -0
- package/lib/FalseIIFEUmdWarning.js +19 -0
- package/lib/HotModuleReplacementPlugin.js +4 -0
- package/lib/Module.js +6 -0
- package/lib/ModuleSourceTypesConstants.js +12 -0
- package/lib/NormalModule.js +1 -0
- package/lib/RuntimeTemplate.js +7 -0
- package/lib/SourceMapDevToolPlugin.js +8 -0
- package/lib/WebpackOptionsApply.js +3 -1
- package/lib/asset/AssetModulesPlugin.js +7 -2
- package/lib/config/defaults.js +52 -36
- package/lib/config/normalization.js +0 -1
- package/lib/config/target.js +8 -8
- package/lib/css/CssGenerator.js +139 -35
- package/lib/css/CssLoadingRuntimeModule.js +108 -198
- package/lib/css/CssModulesPlugin.js +78 -124
- package/lib/css/CssParser.js +545 -121
- package/lib/css/walkCssTokens.js +41 -19
- package/lib/dependencies/CachedConstDependency.js +2 -1
- package/lib/dependencies/ContextDependencyTemplateAsId.js +3 -2
- package/lib/dependencies/{CssExportDependency.js → CssIcssExportDependency.js} +35 -35
- package/lib/dependencies/CssIcssImportDependency.js +118 -0
- package/lib/dependencies/CssIcssSymbolDependency.js +132 -0
- package/lib/dependencies/CssImportDependency.js +0 -8
- package/lib/dependencies/CssLocalIdentifierDependency.js +69 -73
- package/lib/dependencies/CssUrlDependency.js +1 -0
- package/lib/esm/ModuleChunkFormatPlugin.js +8 -4
- package/lib/esm/ModuleChunkLoadingRuntimeModule.js +17 -10
- package/lib/hmr/HotModuleReplacementRuntimeModule.js +0 -1
- package/lib/index.js +9 -3
- package/lib/javascript/EnableChunkLoadingPlugin.js +2 -4
- package/lib/javascript/JavascriptParser.js +1 -0
- package/lib/library/AssignLibraryPlugin.js +1 -1
- package/lib/library/EnableLibraryPlugin.js +17 -0
- package/lib/node/ReadFileCompileAsyncWasmPlugin.js +81 -78
- package/lib/node/ReadFileCompileWasmPlugin.js +76 -57
- package/lib/optimize/MergeDuplicateChunksPlugin.js +22 -2
- package/lib/sharing/ConsumeSharedPlugin.js +35 -12
- package/lib/sharing/utils.js +35 -4
- package/lib/stats/DefaultStatsFactoryPlugin.js +0 -5
- package/lib/util/Queue.js +1 -6
- package/lib/util/generateDebugId.js +33 -0
- package/lib/util/internalSerializables.js +6 -2
- package/lib/wasm/EnableWasmLoadingPlugin.js +36 -25
- package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +26 -2
- package/lib/wasm-async/UniversalCompileAsyncWasmPlugin.js +103 -0
- package/lib/wasm-sync/WebAssemblyParser.js +1 -1
- package/lib/web/FetchCompileAsyncWasmPlugin.js +43 -44
- package/lib/web/FetchCompileWasmPlugin.js +4 -4
- package/package.json +4 -4
- package/schemas/WebpackOptions.check.js +1 -1
- package/schemas/WebpackOptions.json +34 -12
- package/schemas/plugins/BannerPlugin.json +1 -1
- package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
- package/schemas/plugins/SourceMapDevToolPlugin.json +4 -0
- package/schemas/plugins/css/CssAutoParserOptions.check.js +1 -1
- package/schemas/plugins/css/CssGlobalParserOptions.check.js +1 -1
- package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
- package/schemas/plugins/css/CssParserOptions.check.js +1 -1
- package/schemas/plugins/optimize/MergeDuplicateChunksPlugin.check.d.ts +7 -0
- package/schemas/plugins/optimize/MergeDuplicateChunksPlugin.check.js +6 -0
- package/schemas/plugins/optimize/MergeDuplicateChunksPlugin.json +11 -0
- package/types.d.ts +94 -27
- package/lib/css/CssExportsGenerator.js +0 -207
package/lib/css/CssParser.js
CHANGED
@@ -13,7 +13,9 @@ const Parser = require("../Parser");
|
|
13
13
|
const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
|
14
14
|
const WebpackError = require("../WebpackError");
|
15
15
|
const ConstDependency = require("../dependencies/ConstDependency");
|
16
|
-
const
|
16
|
+
const CssIcssExportDependency = require("../dependencies/CssIcssExportDependency");
|
17
|
+
const CssIcssImportDependency = require("../dependencies/CssIcssImportDependency");
|
18
|
+
const CssIcssSymbolDependency = require("../dependencies/CssIcssSymbolDependency");
|
17
19
|
const CssImportDependency = require("../dependencies/CssImportDependency");
|
18
20
|
const CssLocalIdentifierDependency = require("../dependencies/CssLocalIdentifierDependency");
|
19
21
|
const CssSelfLocalIdentifierDependency = require("../dependencies/CssSelfLocalIdentifierDependency");
|
@@ -31,17 +33,18 @@ const walkCssTokens = require("./walkCssTokens");
|
|
31
33
|
/** @typedef {import("../Module").BuildMeta} BuildMeta */
|
32
34
|
/** @typedef {import("../Parser").ParserState} ParserState */
|
33
35
|
/** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
|
36
|
+
/** @typedef {import("./walkCssTokens").CssTokenCallbacks} CssTokenCallbacks */
|
34
37
|
|
35
38
|
/** @typedef {[number, number]} Range */
|
36
39
|
/** @typedef {{ line: number, column: number }} Position */
|
37
40
|
/** @typedef {{ value: string, range: Range, loc: { start: Position, end: Position } }} Comment */
|
38
41
|
|
39
|
-
const CC_LEFT_CURLY = "{".charCodeAt(0);
|
40
|
-
const CC_RIGHT_CURLY = "}".charCodeAt(0);
|
41
42
|
const CC_COLON = ":".charCodeAt(0);
|
42
43
|
const CC_SLASH = "/".charCodeAt(0);
|
43
|
-
const CC_SEMICOLON = ";".charCodeAt(0);
|
44
44
|
const CC_LEFT_PARENTHESIS = "(".charCodeAt(0);
|
45
|
+
const CC_RIGHT_PARENTHESIS = ")".charCodeAt(0);
|
46
|
+
const CC_LOWER_F = "f".charCodeAt(0);
|
47
|
+
const CC_UPPER_F = "F".charCodeAt(0);
|
45
48
|
|
46
49
|
// https://www.w3.org/TR/css-syntax-3/#newline
|
47
50
|
// We don't have `preprocessing` stage, so we need specify all of them
|
@@ -54,6 +57,7 @@ const OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE = /^@(-\w+-)?keyframes$/;
|
|
54
57
|
const OPTIONALLY_VENDOR_PREFIXED_ANIMATION_PROPERTY =
|
55
58
|
/^(-\w+-)?animation(-name)?$/i;
|
56
59
|
const IS_MODULES = /\.module(s)?\.[^.]+$/i;
|
60
|
+
const CSS_COMMENT = /\/\*((?!\*\/).*?)\*\//g;
|
57
61
|
|
58
62
|
/**
|
59
63
|
* @param {string} str url string
|
@@ -95,6 +99,136 @@ const normalizeUrl = (str, isString) => {
|
|
95
99
|
return str;
|
96
100
|
};
|
97
101
|
|
102
|
+
// eslint-disable-next-line no-useless-escape
|
103
|
+
const regexSingleEscape = /[ -,.\/:-@[\]\^`{-~]/;
|
104
|
+
const regexExcessiveSpaces =
|
105
|
+
/(^|\\+)?(\\[A-F0-9]{1,6})\u0020(?![a-fA-F0-9\u0020])/g;
|
106
|
+
|
107
|
+
/**
|
108
|
+
* @param {string} str string
|
109
|
+
* @returns {string} escaped identifier
|
110
|
+
*/
|
111
|
+
const escapeIdentifier = str => {
|
112
|
+
let output = "";
|
113
|
+
let counter = 0;
|
114
|
+
|
115
|
+
while (counter < str.length) {
|
116
|
+
const character = str.charAt(counter++);
|
117
|
+
|
118
|
+
let value;
|
119
|
+
|
120
|
+
if (/[\t\n\f\r\u000B]/.test(character)) {
|
121
|
+
const codePoint = character.charCodeAt(0);
|
122
|
+
|
123
|
+
value = `\\${codePoint.toString(16).toUpperCase()} `;
|
124
|
+
} else if (character === "\\" || regexSingleEscape.test(character)) {
|
125
|
+
value = `\\${character}`;
|
126
|
+
} else {
|
127
|
+
value = character;
|
128
|
+
}
|
129
|
+
|
130
|
+
output += value;
|
131
|
+
}
|
132
|
+
|
133
|
+
const firstChar = str.charAt(0);
|
134
|
+
|
135
|
+
if (/^-[-\d]/.test(output)) {
|
136
|
+
output = `\\-${output.slice(1)}`;
|
137
|
+
} else if (/\d/.test(firstChar)) {
|
138
|
+
output = `\\3${firstChar} ${output.slice(1)}`;
|
139
|
+
}
|
140
|
+
|
141
|
+
// Remove spaces after `\HEX` escapes that are not followed by a hex digit,
|
142
|
+
// since they’re redundant. Note that this is only possible if the escape
|
143
|
+
// sequence isn’t preceded by an odd number of backslashes.
|
144
|
+
output = output.replace(regexExcessiveSpaces, ($0, $1, $2) => {
|
145
|
+
if ($1 && $1.length % 2) {
|
146
|
+
// It’s not safe to remove the space, so don’t.
|
147
|
+
return $0;
|
148
|
+
}
|
149
|
+
|
150
|
+
// Strip the space.
|
151
|
+
return ($1 || "") + $2;
|
152
|
+
});
|
153
|
+
|
154
|
+
return output;
|
155
|
+
};
|
156
|
+
|
157
|
+
const CONTAINS_ESCAPE = /\\/;
|
158
|
+
|
159
|
+
/**
|
160
|
+
* @param {string} str string
|
161
|
+
* @returns {[string, number] | undefined} hex
|
162
|
+
*/
|
163
|
+
const gobbleHex = str => {
|
164
|
+
const lower = str.toLowerCase();
|
165
|
+
let hex = "";
|
166
|
+
let spaceTerminated = false;
|
167
|
+
|
168
|
+
for (let i = 0; i < 6 && lower[i] !== undefined; i++) {
|
169
|
+
const code = lower.charCodeAt(i);
|
170
|
+
// check to see if we are dealing with a valid hex char [a-f|0-9]
|
171
|
+
const valid = (code >= 97 && code <= 102) || (code >= 48 && code <= 57);
|
172
|
+
// https://drafts.csswg.org/css-syntax/#consume-escaped-code-point
|
173
|
+
spaceTerminated = code === 32;
|
174
|
+
if (!valid) break;
|
175
|
+
hex += lower[i];
|
176
|
+
}
|
177
|
+
|
178
|
+
if (hex.length === 0) return undefined;
|
179
|
+
|
180
|
+
const codePoint = Number.parseInt(hex, 16);
|
181
|
+
const isSurrogate = codePoint >= 0xd800 && codePoint <= 0xdfff;
|
182
|
+
|
183
|
+
// Add special case for
|
184
|
+
// "If this number is zero, or is for a surrogate, or is greater than the maximum allowed code point"
|
185
|
+
// https://drafts.csswg.org/css-syntax/#maximum-allowed-code-point
|
186
|
+
if (isSurrogate || codePoint === 0x0000 || codePoint > 0x10ffff) {
|
187
|
+
return ["\uFFFD", hex.length + (spaceTerminated ? 1 : 0)];
|
188
|
+
}
|
189
|
+
|
190
|
+
return [
|
191
|
+
String.fromCodePoint(codePoint),
|
192
|
+
hex.length + (spaceTerminated ? 1 : 0)
|
193
|
+
];
|
194
|
+
};
|
195
|
+
|
196
|
+
/**
|
197
|
+
* @param {string} str string
|
198
|
+
* @returns {string} unescaped string
|
199
|
+
*/
|
200
|
+
const unescapeIdentifier = str => {
|
201
|
+
const needToProcess = CONTAINS_ESCAPE.test(str);
|
202
|
+
if (!needToProcess) return str;
|
203
|
+
let ret = "";
|
204
|
+
for (let i = 0; i < str.length; i++) {
|
205
|
+
if (str[i] === "\\") {
|
206
|
+
const gobbled = gobbleHex(str.slice(i + 1, i + 7));
|
207
|
+
if (gobbled !== undefined) {
|
208
|
+
ret += gobbled[0];
|
209
|
+
i += gobbled[1];
|
210
|
+
continue;
|
211
|
+
}
|
212
|
+
// Retain a pair of \\ if double escaped `\\\\`
|
213
|
+
// https://github.com/postcss/postcss-selector-parser/commit/268c9a7656fb53f543dc620aa5b73a30ec3ff20e
|
214
|
+
if (str[i + 1] === "\\") {
|
215
|
+
ret += "\\";
|
216
|
+
i += 1;
|
217
|
+
continue;
|
218
|
+
}
|
219
|
+
// if \\ is at the end of the string retain it
|
220
|
+
// https://github.com/postcss/postcss-selector-parser/commit/01a6b346e3612ce1ab20219acc26abdc259ccefb
|
221
|
+
if (str.length === i + 1) {
|
222
|
+
ret += str[i];
|
223
|
+
}
|
224
|
+
continue;
|
225
|
+
}
|
226
|
+
ret += str[i];
|
227
|
+
}
|
228
|
+
|
229
|
+
return ret;
|
230
|
+
};
|
231
|
+
|
98
232
|
class LocConverter {
|
99
233
|
/**
|
100
234
|
* @param {string} input input
|
@@ -145,15 +279,28 @@ const EMPTY_COMMENT_OPTIONS = {
|
|
145
279
|
const CSS_MODE_TOP_LEVEL = 0;
|
146
280
|
const CSS_MODE_IN_BLOCK = 1;
|
147
281
|
|
282
|
+
const eatUntilSemi = walkCssTokens.eatUntil(";");
|
283
|
+
const eatUntilLeftCurly = walkCssTokens.eatUntil("{");
|
284
|
+
const eatSemi = walkCssTokens.eatUntil(";");
|
285
|
+
|
148
286
|
class CssParser extends Parser {
|
149
287
|
/**
|
150
288
|
* @param {object} options options
|
289
|
+
* @param {boolean=} options.importOption need handle `@import`
|
290
|
+
* @param {boolean=} options.url need handle URLs
|
151
291
|
* @param {("pure" | "global" | "local" | "auto")=} options.defaultMode default mode
|
152
292
|
* @param {boolean=} options.namedExports is named exports
|
153
293
|
*/
|
154
|
-
constructor({
|
294
|
+
constructor({
|
295
|
+
defaultMode = "pure",
|
296
|
+
importOption = true,
|
297
|
+
url = true,
|
298
|
+
namedExports = true
|
299
|
+
} = {}) {
|
155
300
|
super();
|
156
301
|
this.defaultMode = defaultMode;
|
302
|
+
this.import = importOption;
|
303
|
+
this.url = url;
|
157
304
|
this.namedExports = namedExports;
|
158
305
|
/** @type {Comment[] | undefined} */
|
159
306
|
this.comments = undefined;
|
@@ -228,10 +375,12 @@ class CssParser extends Parser {
|
|
228
375
|
let modeData;
|
229
376
|
/** @type {boolean} */
|
230
377
|
let inAnimationProperty = false;
|
231
|
-
/** @type {Set<string>} */
|
232
|
-
const declaredCssVariables = new Set();
|
233
378
|
/** @type {[number, number, boolean] | undefined} */
|
234
379
|
let lastIdentifier;
|
380
|
+
/** @type {Set<string>} */
|
381
|
+
const declaredCssVariables = new Set();
|
382
|
+
/** @type {Map<string, { path?: string, value: string }>} */
|
383
|
+
const icssDefinitions = new Map();
|
235
384
|
|
236
385
|
/**
|
237
386
|
* @param {string} input input
|
@@ -289,78 +438,156 @@ class CssParser extends Parser {
|
|
289
438
|
}
|
290
439
|
return [pos, text.trimEnd()];
|
291
440
|
};
|
292
|
-
|
293
|
-
const eatExportValue = walkCssTokens.eatUntil("};/");
|
441
|
+
|
294
442
|
/**
|
443
|
+
* @param {0 | 1} type import or export
|
295
444
|
* @param {string} input input
|
296
445
|
* @param {number} pos start position
|
297
446
|
* @returns {number} position after parse
|
298
447
|
*/
|
299
|
-
const
|
448
|
+
const parseImportOrExport = (type, input, pos) => {
|
300
449
|
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
|
301
|
-
|
302
|
-
if (
|
303
|
-
|
304
|
-
|
305
|
-
`Unexpected '${input[pos]}' at ${pos} during parsing of ':export' (expected '{')`,
|
306
|
-
locConverter,
|
307
|
-
pos,
|
308
|
-
pos
|
309
|
-
);
|
310
|
-
return pos;
|
311
|
-
}
|
312
|
-
pos++;
|
313
|
-
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
|
314
|
-
for (;;) {
|
315
|
-
if (input.charCodeAt(pos) === CC_RIGHT_CURLY) break;
|
316
|
-
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
|
317
|
-
if (pos === input.length) return pos;
|
318
|
-
const start = pos;
|
319
|
-
let name;
|
320
|
-
[pos, name] = eatText(input, pos, eatExportName);
|
321
|
-
if (pos === input.length) return pos;
|
322
|
-
if (input.charCodeAt(pos) !== CC_COLON) {
|
450
|
+
let importPath;
|
451
|
+
if (type === 0) {
|
452
|
+
let cc = input.charCodeAt(pos);
|
453
|
+
if (cc !== CC_LEFT_PARENTHESIS) {
|
323
454
|
this._emitWarning(
|
324
455
|
state,
|
325
|
-
`Unexpected '${input[pos]}' at ${pos} during parsing of
|
456
|
+
`Unexpected '${input[pos]}' at ${pos} during parsing of ':import' (expected '(')`,
|
326
457
|
locConverter,
|
327
|
-
|
458
|
+
pos,
|
328
459
|
pos
|
329
460
|
);
|
330
461
|
return pos;
|
331
462
|
}
|
332
463
|
pos++;
|
333
|
-
|
464
|
+
const stringStart = pos;
|
465
|
+
const str = walkCssTokens.eatString(input, pos);
|
466
|
+
if (!str) {
|
467
|
+
this._emitWarning(
|
468
|
+
state,
|
469
|
+
`Unexpected '${input[pos]}' at ${pos} during parsing of ':import' (expected string)`,
|
470
|
+
locConverter,
|
471
|
+
stringStart,
|
472
|
+
pos
|
473
|
+
);
|
474
|
+
return pos;
|
475
|
+
}
|
476
|
+
importPath = input.slice(str[0] + 1, str[1] - 1);
|
477
|
+
pos = str[1];
|
334
478
|
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
|
335
|
-
|
336
|
-
|
337
|
-
[pos, value] = eatText(input, pos, eatExportValue);
|
338
|
-
if (pos === input.length) return pos;
|
339
|
-
const cc = input.charCodeAt(pos);
|
340
|
-
if (cc === CC_SEMICOLON) {
|
341
|
-
pos++;
|
342
|
-
if (pos === input.length) return pos;
|
343
|
-
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
|
344
|
-
if (pos === input.length) return pos;
|
345
|
-
} else if (cc !== CC_RIGHT_CURLY) {
|
479
|
+
cc = input.charCodeAt(pos);
|
480
|
+
if (cc !== CC_RIGHT_PARENTHESIS) {
|
346
481
|
this._emitWarning(
|
347
482
|
state,
|
348
|
-
`Unexpected '${input[pos]}' at ${pos} during parsing of
|
483
|
+
`Unexpected '${input[pos]}' at ${pos} during parsing of ':import' (expected ')')`,
|
349
484
|
locConverter,
|
350
|
-
|
485
|
+
pos,
|
351
486
|
pos
|
352
487
|
);
|
353
488
|
return pos;
|
354
489
|
}
|
355
|
-
|
356
|
-
|
357
|
-
const { line: el, column: ec } = locConverter.get(pos);
|
358
|
-
dep.setLoc(sl, sc, el, ec);
|
359
|
-
module.addDependency(dep);
|
490
|
+
pos++;
|
491
|
+
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
|
360
492
|
}
|
361
|
-
|
362
|
-
|
493
|
+
|
494
|
+
/**
|
495
|
+
* @param {string} name name
|
496
|
+
* @param {string} value value
|
497
|
+
* @param {number} start start of position
|
498
|
+
* @param {number} end end of position
|
499
|
+
*/
|
500
|
+
const createDep = (name, value, start, end) => {
|
501
|
+
if (type === 0) {
|
502
|
+
icssDefinitions.set(name, {
|
503
|
+
path: /** @type {string} */ (importPath),
|
504
|
+
value
|
505
|
+
});
|
506
|
+
} else if (type === 1) {
|
507
|
+
const dep = new CssIcssExportDependency(name, value);
|
508
|
+
const { line: sl, column: sc } = locConverter.get(start);
|
509
|
+
const { line: el, column: ec } = locConverter.get(end);
|
510
|
+
dep.setLoc(sl, sc, el, ec);
|
511
|
+
module.addDependency(dep);
|
512
|
+
}
|
513
|
+
};
|
514
|
+
|
515
|
+
let needTerminate = false;
|
516
|
+
let balanced = 0;
|
517
|
+
/** @type {undefined | 0 | 1 | 2} */
|
518
|
+
let scope;
|
519
|
+
|
520
|
+
/** @type {[number, number] | undefined} */
|
521
|
+
let name;
|
522
|
+
/** @type {number | undefined} */
|
523
|
+
let value;
|
524
|
+
|
525
|
+
/** @type {CssTokenCallbacks} */
|
526
|
+
const callbacks = {
|
527
|
+
leftCurlyBracket: (_input, _start, end) => {
|
528
|
+
balanced++;
|
529
|
+
|
530
|
+
if (scope === undefined) {
|
531
|
+
scope = 0;
|
532
|
+
}
|
533
|
+
|
534
|
+
return end;
|
535
|
+
},
|
536
|
+
rightCurlyBracket: (_input, _start, end) => {
|
537
|
+
balanced--;
|
538
|
+
|
539
|
+
if (scope === 2) {
|
540
|
+
createDep(
|
541
|
+
input.slice(name[0], name[1]),
|
542
|
+
input.slice(value, end - 1).trim(),
|
543
|
+
name[1],
|
544
|
+
end - 1
|
545
|
+
);
|
546
|
+
scope = 0;
|
547
|
+
}
|
548
|
+
|
549
|
+
if (balanced === 0 && scope === 0) {
|
550
|
+
needTerminate = true;
|
551
|
+
}
|
552
|
+
|
553
|
+
return end;
|
554
|
+
},
|
555
|
+
identifier: (_input, start, end) => {
|
556
|
+
if (scope === 0) {
|
557
|
+
name = [start, end];
|
558
|
+
scope = 1;
|
559
|
+
}
|
560
|
+
|
561
|
+
return end;
|
562
|
+
},
|
563
|
+
colon: (_input, _start, end) => {
|
564
|
+
if (scope === 1) {
|
565
|
+
scope = 2;
|
566
|
+
value = walkCssTokens.eatWhitespace(input, end);
|
567
|
+
return value;
|
568
|
+
}
|
569
|
+
|
570
|
+
return end;
|
571
|
+
},
|
572
|
+
semicolon: (input, _start, end) => {
|
573
|
+
if (scope === 2) {
|
574
|
+
createDep(
|
575
|
+
input.slice(name[0], name[1]),
|
576
|
+
input.slice(value, end - 1),
|
577
|
+
name[1],
|
578
|
+
end - 1
|
579
|
+
);
|
580
|
+
scope = 0;
|
581
|
+
}
|
582
|
+
|
583
|
+
return end;
|
584
|
+
},
|
585
|
+
needTerminate: () => needTerminate
|
586
|
+
};
|
587
|
+
|
588
|
+
pos = walkCssTokens(input, pos, callbacks);
|
363
589
|
pos = walkCssTokens.eatWhiteLine(input, pos);
|
590
|
+
|
364
591
|
return pos;
|
365
592
|
};
|
366
593
|
const eatPropertyName = walkCssTokens.eatUntil(":{};");
|
@@ -381,11 +608,11 @@ class CssParser extends Parser {
|
|
381
608
|
);
|
382
609
|
if (input.charCodeAt(propertyNameEnd) !== CC_COLON) return end;
|
383
610
|
pos = propertyNameEnd + 1;
|
384
|
-
if (propertyName.startsWith("--")) {
|
611
|
+
if (propertyName.startsWith("--") && propertyName.length >= 3) {
|
385
612
|
// CSS Variable
|
386
613
|
const { line: sl, column: sc } = locConverter.get(propertyNameStart);
|
387
614
|
const { line: el, column: ec } = locConverter.get(propertyNameEnd);
|
388
|
-
const name = propertyName.slice(2);
|
615
|
+
const name = unescapeIdentifier(propertyName.slice(2));
|
389
616
|
const dep = new CssLocalIdentifierDependency(
|
390
617
|
name,
|
391
618
|
[propertyNameStart, propertyNameEnd],
|
@@ -408,9 +635,11 @@ class CssParser extends Parser {
|
|
408
635
|
if (inAnimationProperty && lastIdentifier) {
|
409
636
|
const { line: sl, column: sc } = locConverter.get(lastIdentifier[0]);
|
410
637
|
const { line: el, column: ec } = locConverter.get(lastIdentifier[1]);
|
411
|
-
const name =
|
412
|
-
|
413
|
-
|
638
|
+
const name = unescapeIdentifier(
|
639
|
+
lastIdentifier[2]
|
640
|
+
? input.slice(lastIdentifier[0], lastIdentifier[1])
|
641
|
+
: input.slice(lastIdentifier[0] + 1, lastIdentifier[1] - 1)
|
642
|
+
);
|
414
643
|
const dep = new CssSelfLocalIdentifierDependency(name, [
|
415
644
|
lastIdentifier[0],
|
416
645
|
lastIdentifier[1]
|
@@ -421,9 +650,6 @@ class CssParser extends Parser {
|
|
421
650
|
}
|
422
651
|
};
|
423
652
|
|
424
|
-
const eatUntilSemi = walkCssTokens.eatUntil(";");
|
425
|
-
const eatUntilLeftCurly = walkCssTokens.eatUntil("{");
|
426
|
-
|
427
653
|
/**
|
428
654
|
* @param {string} input input
|
429
655
|
* @param {number} start start
|
@@ -448,7 +674,7 @@ class CssParser extends Parser {
|
|
448
674
|
return end;
|
449
675
|
};
|
450
676
|
|
451
|
-
walkCssTokens(source, {
|
677
|
+
walkCssTokens(source, 0, {
|
452
678
|
comment,
|
453
679
|
leftCurlyBracket: (input, start, end) => {
|
454
680
|
switch (scope) {
|
@@ -497,6 +723,10 @@ class CssParser extends Parser {
|
|
497
723
|
return end;
|
498
724
|
},
|
499
725
|
url: (input, start, end, contentStart, contentEnd) => {
|
726
|
+
if (!this.url) {
|
727
|
+
return end;
|
728
|
+
}
|
729
|
+
|
500
730
|
const { options, errors: commentErrors } = this.parseCommentOptions([
|
501
731
|
lastTokenEndForComments,
|
502
732
|
end
|
@@ -572,6 +802,10 @@ class CssParser extends Parser {
|
|
572
802
|
return eatUntilSemi(input, start);
|
573
803
|
}
|
574
804
|
case "@import": {
|
805
|
+
if (!this.import) {
|
806
|
+
return eatSemi(input, end);
|
807
|
+
}
|
808
|
+
|
575
809
|
if (!allowImportAtRule) {
|
576
810
|
this._emitWarning(
|
577
811
|
state,
|
@@ -687,48 +921,129 @@ class CssParser extends Parser {
|
|
687
921
|
}
|
688
922
|
default: {
|
689
923
|
if (isModules) {
|
690
|
-
if (
|
924
|
+
if (name === "@value") {
|
925
|
+
const semi = eatUntilSemi(input, end);
|
926
|
+
const atRuleEnd = semi + 1;
|
927
|
+
const params = input.slice(end, semi);
|
928
|
+
let [alias, from] = params.split(/\s*from\s*/);
|
929
|
+
|
930
|
+
if (from) {
|
931
|
+
const aliases = alias
|
932
|
+
.replace(CSS_COMMENT, " ")
|
933
|
+
.trim()
|
934
|
+
.replace(/^\(|\)$/g, "")
|
935
|
+
.split(/\s*,\s*/);
|
936
|
+
|
937
|
+
from = from.replace(CSS_COMMENT, "").trim();
|
938
|
+
|
939
|
+
const isExplicitImport = from[0] === "'" || from[0] === '"';
|
940
|
+
|
941
|
+
if (isExplicitImport) {
|
942
|
+
from = from.slice(1, -1);
|
943
|
+
}
|
944
|
+
|
945
|
+
for (const alias of aliases) {
|
946
|
+
const [name, aliasName] = alias.split(/\s*as\s*/);
|
947
|
+
|
948
|
+
icssDefinitions.set(aliasName || name, {
|
949
|
+
value: name,
|
950
|
+
path: from
|
951
|
+
});
|
952
|
+
}
|
953
|
+
} else {
|
954
|
+
const ident = walkCssTokens.eatIdentSequence(alias, 0);
|
955
|
+
|
956
|
+
if (!ident) {
|
957
|
+
this._emitWarning(
|
958
|
+
state,
|
959
|
+
`Broken '@value' at-rule: ${input.slice(
|
960
|
+
start,
|
961
|
+
atRuleEnd
|
962
|
+
)}'`,
|
963
|
+
locConverter,
|
964
|
+
start,
|
965
|
+
atRuleEnd
|
966
|
+
);
|
967
|
+
|
968
|
+
const dep = new ConstDependency("", [start, atRuleEnd]);
|
969
|
+
module.addPresentationalDependency(dep);
|
970
|
+
return atRuleEnd;
|
971
|
+
}
|
972
|
+
|
973
|
+
const pos = walkCssTokens.eatWhitespaceAndComments(
|
974
|
+
alias,
|
975
|
+
ident[1]
|
976
|
+
);
|
977
|
+
|
978
|
+
const name = alias.slice(ident[0], ident[1]);
|
979
|
+
let value =
|
980
|
+
alias.charCodeAt(pos) === CC_COLON
|
981
|
+
? alias.slice(pos + 1)
|
982
|
+
: alias.slice(ident[1]);
|
983
|
+
|
984
|
+
if (value && !/^\s+$/.test(value)) {
|
985
|
+
value = value.trim();
|
986
|
+
}
|
987
|
+
|
988
|
+
if (icssDefinitions.has(value)) {
|
989
|
+
const def = icssDefinitions.get(value);
|
990
|
+
|
991
|
+
value = def.value;
|
992
|
+
}
|
993
|
+
|
994
|
+
icssDefinitions.set(name, { value });
|
995
|
+
|
996
|
+
const dep = new CssIcssExportDependency(name, value);
|
997
|
+
const { line: sl, column: sc } = locConverter.get(start);
|
998
|
+
const { line: el, column: ec } = locConverter.get(end);
|
999
|
+
dep.setLoc(sl, sc, el, ec);
|
1000
|
+
module.addDependency(dep);
|
1001
|
+
}
|
1002
|
+
|
1003
|
+
const dep = new ConstDependency("", [start, atRuleEnd]);
|
1004
|
+
module.addPresentationalDependency(dep);
|
1005
|
+
return atRuleEnd;
|
1006
|
+
} else if (
|
1007
|
+
OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE.test(name) &&
|
1008
|
+
isLocalMode()
|
1009
|
+
) {
|
691
1010
|
const ident = walkCssTokens.eatIdentSequenceOrString(
|
692
1011
|
input,
|
693
1012
|
end
|
694
1013
|
);
|
695
1014
|
if (!ident) return end;
|
696
|
-
const name =
|
1015
|
+
const name = unescapeIdentifier(
|
697
1016
|
ident[2] === true
|
698
1017
|
? input.slice(ident[0], ident[1])
|
699
|
-
: input.slice(ident[0] + 1, ident[1] - 1)
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
}
|
1018
|
+
: input.slice(ident[0] + 1, ident[1] - 1)
|
1019
|
+
);
|
1020
|
+
const { line: sl, column: sc } = locConverter.get(ident[0]);
|
1021
|
+
const { line: el, column: ec } = locConverter.get(ident[1]);
|
1022
|
+
const dep = new CssLocalIdentifierDependency(name, [
|
1023
|
+
ident[0],
|
1024
|
+
ident[1]
|
1025
|
+
]);
|
1026
|
+
dep.setLoc(sl, sc, el, ec);
|
1027
|
+
module.addDependency(dep);
|
710
1028
|
return ident[1];
|
711
|
-
} else if (name === "@property") {
|
1029
|
+
} else if (name === "@property" && isLocalMode()) {
|
712
1030
|
const ident = walkCssTokens.eatIdentSequence(input, end);
|
713
1031
|
if (!ident) return end;
|
714
1032
|
let name = input.slice(ident[0], ident[1]);
|
715
|
-
if (!name.startsWith("--")) return end;
|
716
|
-
name = name.slice(2);
|
1033
|
+
if (!name.startsWith("--") || name.length < 3) return end;
|
1034
|
+
name = unescapeIdentifier(name.slice(2));
|
717
1035
|
declaredCssVariables.add(name);
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
module.addDependency(dep);
|
728
|
-
}
|
1036
|
+
const { line: sl, column: sc } = locConverter.get(ident[0]);
|
1037
|
+
const { line: el, column: ec } = locConverter.get(ident[1]);
|
1038
|
+
const dep = new CssLocalIdentifierDependency(
|
1039
|
+
name,
|
1040
|
+
[ident[0], ident[1]],
|
1041
|
+
"--"
|
1042
|
+
);
|
1043
|
+
dep.setLoc(sl, sc, el, ec);
|
1044
|
+
module.addDependency(dep);
|
729
1045
|
return ident[1];
|
730
|
-
} else if (
|
731
|
-
modeData = isLocalMode() ? "local" : "global";
|
1046
|
+
} else if (name === "@scope") {
|
732
1047
|
isNextRulePrelude = true;
|
733
1048
|
return end;
|
734
1049
|
}
|
@@ -752,19 +1067,55 @@ class CssParser extends Parser {
|
|
752
1067
|
return end;
|
753
1068
|
},
|
754
1069
|
identifier: (input, start, end) => {
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
1070
|
+
if (isModules) {
|
1071
|
+
if (icssDefinitions.has(input.slice(start, end))) {
|
1072
|
+
const name = input.slice(start, end);
|
1073
|
+
let { path, value } = icssDefinitions.get(name);
|
1074
|
+
|
1075
|
+
if (path) {
|
1076
|
+
if (icssDefinitions.has(path)) {
|
1077
|
+
const definition = icssDefinitions.get(path);
|
1078
|
+
|
1079
|
+
path = definition.value.slice(1, -1);
|
763
1080
|
}
|
1081
|
+
|
1082
|
+
const dep = new CssIcssImportDependency(path, value, [
|
1083
|
+
start,
|
1084
|
+
end - 1
|
1085
|
+
]);
|
1086
|
+
const { line: sl, column: sc } = locConverter.get(start);
|
1087
|
+
const { line: el, column: ec } = locConverter.get(end - 1);
|
1088
|
+
dep.setLoc(sl, sc, el, ec);
|
1089
|
+
module.addDependency(dep);
|
1090
|
+
} else {
|
1091
|
+
const { line: sl, column: sc } = locConverter.get(start);
|
1092
|
+
const { line: el, column: ec } = locConverter.get(end);
|
1093
|
+
const dep = new CssIcssSymbolDependency(name, value, [
|
1094
|
+
start,
|
1095
|
+
end
|
1096
|
+
]);
|
1097
|
+
dep.setLoc(sl, sc, el, ec);
|
1098
|
+
module.addDependency(dep);
|
1099
|
+
}
|
1100
|
+
|
1101
|
+
return end;
|
1102
|
+
}
|
1103
|
+
|
1104
|
+
switch (scope) {
|
1105
|
+
case CSS_MODE_IN_BLOCK: {
|
1106
|
+
if (isLocalMode()) {
|
1107
|
+
// Handle only top level values and not inside functions
|
1108
|
+
if (inAnimationProperty && balanced.length === 0) {
|
1109
|
+
lastIdentifier = [start, end, true];
|
1110
|
+
} else {
|
1111
|
+
return processLocalDeclaration(input, start, end);
|
1112
|
+
}
|
1113
|
+
}
|
1114
|
+
break;
|
764
1115
|
}
|
765
|
-
break;
|
766
1116
|
}
|
767
1117
|
}
|
1118
|
+
|
768
1119
|
return end;
|
769
1120
|
},
|
770
1121
|
delim: (input, start, end) => {
|
@@ -774,7 +1125,7 @@ class CssParser extends Parser {
|
|
774
1125
|
end
|
775
1126
|
);
|
776
1127
|
if (!ident) return end;
|
777
|
-
const name = input.slice(ident[0], ident[1]);
|
1128
|
+
const name = unescapeIdentifier(input.slice(ident[0], ident[1]));
|
778
1129
|
const dep = new CssLocalIdentifierDependency(name, [
|
779
1130
|
ident[0],
|
780
1131
|
ident[1]
|
@@ -791,7 +1142,7 @@ class CssParser extends Parser {
|
|
791
1142
|
hash: (input, start, end, isID) => {
|
792
1143
|
if (isNextRulePrelude && isLocalMode() && isID) {
|
793
1144
|
const valueStart = start + 1;
|
794
|
-
const name = input.slice(valueStart, end);
|
1145
|
+
const name = unescapeIdentifier(input.slice(valueStart, end));
|
795
1146
|
const dep = new CssLocalIdentifierDependency(name, [valueStart, end]);
|
796
1147
|
const { line: sl, column: sc } = locConverter.get(start);
|
797
1148
|
const { line: el, column: ec } = locConverter.get(end);
|
@@ -812,8 +1163,13 @@ class CssParser extends Parser {
|
|
812
1163
|
|
813
1164
|
switch (scope) {
|
814
1165
|
case CSS_MODE_TOP_LEVEL: {
|
815
|
-
if (name === "
|
816
|
-
const pos =
|
1166
|
+
if (name === "import") {
|
1167
|
+
const pos = parseImportOrExport(0, input, ident[1]);
|
1168
|
+
const dep = new ConstDependency("", [start, pos]);
|
1169
|
+
module.addPresentationalDependency(dep);
|
1170
|
+
return pos;
|
1171
|
+
} else if (name === "export") {
|
1172
|
+
const pos = parseImportOrExport(1, input, ident[1]);
|
817
1173
|
const dep = new ConstDependency("", [start, pos]);
|
818
1174
|
module.addPresentationalDependency(dep);
|
819
1175
|
return pos;
|
@@ -901,6 +1257,10 @@ class CssParser extends Parser {
|
|
901
1257
|
switch (name) {
|
902
1258
|
case "src":
|
903
1259
|
case "url": {
|
1260
|
+
if (!this.url) {
|
1261
|
+
return end;
|
1262
|
+
}
|
1263
|
+
|
904
1264
|
const string = walkCssTokens.eatString(input, end);
|
905
1265
|
if (!string) return end;
|
906
1266
|
const { options, errors: commentErrors } = this.parseCommentOptions(
|
@@ -955,7 +1315,7 @@ class CssParser extends Parser {
|
|
955
1315
|
return string[1];
|
956
1316
|
}
|
957
1317
|
default: {
|
958
|
-
if (IMAGE_SET_FUNCTION.test(name)) {
|
1318
|
+
if (this.url && IMAGE_SET_FUNCTION.test(name)) {
|
959
1319
|
lastTokenEndForComments = end;
|
960
1320
|
const values = walkCssTokens.eatImageSetStrings(input, end, {
|
961
1321
|
comment
|
@@ -1025,21 +1385,83 @@ class CssParser extends Parser {
|
|
1025
1385
|
}
|
1026
1386
|
|
1027
1387
|
if (name === "var") {
|
1028
|
-
const
|
1029
|
-
if (!
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
declaredCssVariables
|
1388
|
+
const customIdent = walkCssTokens.eatIdentSequence(input, end);
|
1389
|
+
if (!customIdent) return end;
|
1390
|
+
let name = input.slice(customIdent[0], customIdent[1]);
|
1391
|
+
// A custom property is any property whose name starts with two dashes (U+002D HYPHEN-MINUS), like --foo.
|
1392
|
+
// The <custom-property-name> production corresponds to this:
|
1393
|
+
// it’s defined as any <dashed-ident> (a valid identifier that starts with two dashes),
|
1394
|
+
// except -- itself, which is reserved for future use by CSS.
|
1395
|
+
if (!name.startsWith("--") || name.length < 3) return end;
|
1396
|
+
name = unescapeIdentifier(
|
1397
|
+
input.slice(customIdent[0] + 2, customIdent[1])
|
1039
1398
|
);
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1399
|
+
const afterCustomIdent = walkCssTokens.eatWhitespaceAndComments(
|
1400
|
+
input,
|
1401
|
+
customIdent[1]
|
1402
|
+
);
|
1403
|
+
if (
|
1404
|
+
input.charCodeAt(afterCustomIdent) === CC_LOWER_F ||
|
1405
|
+
input.charCodeAt(afterCustomIdent) === CC_UPPER_F
|
1406
|
+
) {
|
1407
|
+
const fromWord = walkCssTokens.eatIdentSequence(
|
1408
|
+
input,
|
1409
|
+
afterCustomIdent
|
1410
|
+
);
|
1411
|
+
if (
|
1412
|
+
!fromWord ||
|
1413
|
+
input.slice(fromWord[0], fromWord[1]).toLowerCase() !==
|
1414
|
+
"from"
|
1415
|
+
) {
|
1416
|
+
return end;
|
1417
|
+
}
|
1418
|
+
const from = walkCssTokens.eatIdentSequenceOrString(
|
1419
|
+
input,
|
1420
|
+
walkCssTokens.eatWhitespaceAndComments(input, fromWord[1])
|
1421
|
+
);
|
1422
|
+
if (!from) {
|
1423
|
+
return end;
|
1424
|
+
}
|
1425
|
+
const path = input.slice(from[0], from[1]);
|
1426
|
+
if (from[2] === true && path === "global") {
|
1427
|
+
const dep = new ConstDependency("", [
|
1428
|
+
customIdent[1],
|
1429
|
+
from[1]
|
1430
|
+
]);
|
1431
|
+
module.addPresentationalDependency(dep);
|
1432
|
+
return end;
|
1433
|
+
} else if (from[2] === false) {
|
1434
|
+
const dep = new CssIcssImportDependency(
|
1435
|
+
path.slice(1, -1),
|
1436
|
+
name,
|
1437
|
+
[customIdent[0], from[1] - 1]
|
1438
|
+
);
|
1439
|
+
const { line: sl, column: sc } = locConverter.get(
|
1440
|
+
customIdent[0]
|
1441
|
+
);
|
1442
|
+
const { line: el, column: ec } = locConverter.get(
|
1443
|
+
from[1] - 1
|
1444
|
+
);
|
1445
|
+
dep.setLoc(sl, sc, el, ec);
|
1446
|
+
module.addDependency(dep);
|
1447
|
+
}
|
1448
|
+
} else {
|
1449
|
+
const { line: sl, column: sc } = locConverter.get(
|
1450
|
+
customIdent[0]
|
1451
|
+
);
|
1452
|
+
const { line: el, column: ec } = locConverter.get(
|
1453
|
+
customIdent[1]
|
1454
|
+
);
|
1455
|
+
const dep = new CssSelfLocalIdentifierDependency(
|
1456
|
+
name,
|
1457
|
+
[customIdent[0], customIdent[1]],
|
1458
|
+
"--",
|
1459
|
+
declaredCssVariables
|
1460
|
+
);
|
1461
|
+
dep.setLoc(sl, sc, el, ec);
|
1462
|
+
module.addDependency(dep);
|
1463
|
+
return end;
|
1464
|
+
}
|
1043
1465
|
}
|
1044
1466
|
}
|
1045
1467
|
}
|
@@ -1176,3 +1598,5 @@ class CssParser extends Parser {
|
|
1176
1598
|
}
|
1177
1599
|
|
1178
1600
|
module.exports = CssParser;
|
1601
|
+
module.exports.escapeIdentifier = escapeIdentifier;
|
1602
|
+
module.exports.unescapeIdentifier = unescapeIdentifier;
|