webpack 5.103.0 → 5.104.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.
Files changed (176) hide show
  1. package/hot/dev-server.js +18 -3
  2. package/hot/emitter-event-target.js +7 -0
  3. package/hot/lazy-compilation-node.js +45 -29
  4. package/hot/lazy-compilation-universal.js +18 -0
  5. package/hot/lazy-compilation-web.js +15 -5
  6. package/hot/load-http.js +7 -0
  7. package/hot/only-dev-server.js +19 -4
  8. package/lib/APIPlugin.js +6 -0
  9. package/lib/Chunk.js +1 -1
  10. package/lib/ChunkGraph.js +9 -7
  11. package/lib/ChunkGroup.js +8 -5
  12. package/lib/CleanPlugin.js +6 -3
  13. package/lib/CodeGenerationResults.js +2 -1
  14. package/lib/CompatibilityPlugin.js +3 -0
  15. package/lib/Compilation.js +33 -19
  16. package/lib/Compiler.js +3 -3
  17. package/lib/ContextModule.js +6 -3
  18. package/lib/ContextModuleFactory.js +6 -4
  19. package/lib/DefinePlugin.js +34 -3
  20. package/lib/DelegatedModule.js +7 -4
  21. package/lib/DllModule.js +6 -3
  22. package/lib/DotenvPlugin.js +11 -6
  23. package/lib/ExportsInfo.js +5 -5
  24. package/lib/ExternalModule.js +8 -7
  25. package/lib/ExternalModuleFactoryPlugin.js +1 -1
  26. package/lib/FileSystemInfo.js +1 -1
  27. package/lib/Generator.js +10 -7
  28. package/lib/HookWebpackError.js +33 -4
  29. package/lib/HotModuleReplacementPlugin.js +22 -0
  30. package/lib/ManifestPlugin.js +1 -1
  31. package/lib/Module.js +24 -15
  32. package/lib/ModuleBuildError.js +1 -1
  33. package/lib/ModuleError.js +1 -1
  34. package/lib/ModuleFilenameHelpers.js +1 -1
  35. package/lib/ModuleGraph.js +27 -12
  36. package/lib/ModuleGraphConnection.js +2 -2
  37. package/lib/ModuleSourceTypeConstants.js +189 -0
  38. package/lib/ModuleTypeConstants.js +1 -4
  39. package/lib/ModuleWarning.js +1 -1
  40. package/lib/NodeStuffPlugin.js +52 -42
  41. package/lib/NormalModule.js +6 -4
  42. package/lib/NormalModuleFactory.js +7 -10
  43. package/lib/Parser.js +1 -1
  44. package/lib/RawModule.js +7 -4
  45. package/lib/RuntimeModule.js +1 -1
  46. package/lib/RuntimeTemplate.js +5 -1
  47. package/lib/SourceMapDevToolPlugin.js +6 -1
  48. package/lib/Template.js +17 -6
  49. package/lib/TemplatedPathPlugin.js +5 -6
  50. package/lib/WebpackError.js +0 -1
  51. package/lib/WebpackOptionsApply.js +37 -9
  52. package/lib/asset/AssetBytesGenerator.js +15 -11
  53. package/lib/asset/AssetGenerator.js +30 -24
  54. package/lib/asset/AssetSourceGenerator.js +15 -11
  55. package/lib/asset/RawDataUrlModule.js +6 -3
  56. package/lib/buildChunkGraph.js +4 -2
  57. package/lib/cache/PackFileCacheStrategy.js +6 -5
  58. package/lib/cli.js +2 -43
  59. package/lib/config/browserslistTargetHandler.js +19 -0
  60. package/lib/config/defaults.js +128 -43
  61. package/lib/config/normalization.js +2 -2
  62. package/lib/config/target.js +5 -0
  63. package/lib/container/ContainerEntryModule.js +6 -3
  64. package/lib/container/FallbackModule.js +6 -3
  65. package/lib/container/RemoteModule.js +1 -3
  66. package/lib/css/CssGenerator.js +26 -24
  67. package/lib/css/CssLoadingRuntimeModule.js +12 -4
  68. package/lib/css/CssModulesPlugin.js +29 -74
  69. package/lib/css/CssParser.js +828 -341
  70. package/lib/css/walkCssTokens.js +33 -13
  71. package/lib/dependencies/CachedConstDependency.js +24 -10
  72. package/lib/dependencies/CommonJsRequireContextDependency.js +1 -1
  73. package/lib/dependencies/ContextDependencyHelpers.js +2 -2
  74. package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +3 -1
  75. package/lib/dependencies/CssIcssExportDependency.js +242 -104
  76. package/lib/dependencies/CssIcssImportDependency.js +61 -4
  77. package/lib/dependencies/CssIcssSymbolDependency.js +2 -6
  78. package/lib/dependencies/CssImportDependency.js +2 -1
  79. package/lib/dependencies/CssUrlDependency.js +3 -2
  80. package/lib/dependencies/DynamicExports.js +7 -7
  81. package/lib/dependencies/ExternalModuleDependency.js +7 -4
  82. package/lib/dependencies/ExternalModuleInitFragment.js +2 -1
  83. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +2 -1
  84. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +3 -2
  85. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +1 -1
  86. package/lib/dependencies/HarmonyExports.js +4 -4
  87. package/lib/dependencies/HarmonyImportDependency.js +8 -3
  88. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +1 -1
  89. package/lib/dependencies/ImportMetaPlugin.js +57 -0
  90. package/lib/dependencies/ImportParserPlugin.js +2 -2
  91. package/lib/dependencies/LocalModulesHelpers.js +3 -3
  92. package/lib/dependencies/WorkerPlugin.js +2 -2
  93. package/lib/dependencies/getFunctionExpression.js +1 -1
  94. package/lib/esm/ModuleChunkFormatPlugin.js +5 -4
  95. package/lib/hmr/HotModuleReplacement.runtime.js +2 -1
  96. package/lib/hmr/LazyCompilationPlugin.js +4 -3
  97. package/lib/ids/IdHelpers.js +16 -7
  98. package/lib/javascript/ChunkHelpers.js +1 -1
  99. package/lib/javascript/JavascriptGenerator.js +4 -3
  100. package/lib/javascript/JavascriptModulesPlugin.js +57 -24
  101. package/lib/javascript/JavascriptParser.js +19 -6
  102. package/lib/json/JsonGenerator.js +5 -4
  103. package/lib/json/JsonParser.js +2 -1
  104. package/lib/library/AbstractLibraryPlugin.js +1 -1
  105. package/lib/library/AmdLibraryPlugin.js +4 -1
  106. package/lib/library/ExportPropertyLibraryPlugin.js +4 -1
  107. package/lib/library/ModuleLibraryPlugin.js +41 -13
  108. package/lib/library/SystemLibraryPlugin.js +4 -1
  109. package/lib/library/UmdLibraryPlugin.js +1 -1
  110. package/lib/logging/Logger.js +5 -4
  111. package/lib/logging/createConsoleLogger.js +2 -2
  112. package/lib/optimize/ConcatenatedModule.js +47 -32
  113. package/lib/optimize/ModuleConcatenationPlugin.js +5 -4
  114. package/lib/optimize/SideEffectsFlagPlugin.js +3 -2
  115. package/lib/optimize/SplitChunksPlugin.js +60 -46
  116. package/lib/rules/RuleSetCompiler.js +1 -1
  117. package/lib/runtime/GetChunkFilenameRuntimeModule.js +3 -2
  118. package/lib/schemes/HttpUriPlugin.js +78 -7
  119. package/lib/serialization/AggregateErrorSerializer.js +1 -2
  120. package/lib/serialization/ObjectMiddleware.js +0 -2
  121. package/lib/serialization/SingleItemMiddleware.js +1 -1
  122. package/lib/sharing/ConsumeSharedModule.js +1 -1
  123. package/lib/sharing/ConsumeSharedPlugin.js +5 -3
  124. package/lib/sharing/ProvideSharedModule.js +1 -1
  125. package/lib/sharing/resolveMatchedConfigs.js +15 -9
  126. package/lib/sharing/utils.js +1 -1
  127. package/lib/stats/DefaultStatsFactoryPlugin.js +8 -5
  128. package/lib/stats/DefaultStatsPresetPlugin.js +1 -1
  129. package/lib/stats/DefaultStatsPrinterPlugin.js +1 -1
  130. package/lib/util/StringXor.js +1 -1
  131. package/lib/util/URLAbsoluteSpecifier.js +2 -2
  132. package/lib/util/binarySearchBounds.js +2 -2
  133. package/lib/util/comparators.js +53 -76
  134. package/lib/util/compileBooleanMatcher.js +78 -6
  135. package/lib/util/createHash.js +20 -199
  136. package/lib/util/deprecation.js +1 -1
  137. package/lib/util/deterministicGrouping.js +6 -3
  138. package/lib/util/fs.js +75 -75
  139. package/lib/util/hash/BatchedHash.js +10 -9
  140. package/lib/util/hash/BulkUpdateHash.js +138 -0
  141. package/lib/util/hash/DebugHash.js +75 -0
  142. package/lib/util/hash/hash-digest.js +216 -0
  143. package/lib/util/identifier.js +82 -17
  144. package/lib/util/internalSerializables.js +2 -6
  145. package/lib/util/runtime.js +3 -3
  146. package/lib/util/source.js +2 -2
  147. package/lib/wasm-async/AsyncWebAssemblyGenerator.js +3 -2
  148. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +3 -2
  149. package/lib/wasm-sync/WebAssemblyGenerator.js +9 -6
  150. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +3 -2
  151. package/lib/wasm-sync/WebAssemblyModulesPlugin.js +6 -2
  152. package/lib/webpack.js +1 -1
  153. package/package.json +29 -25
  154. package/schemas/WebpackOptions.check.js +1 -1
  155. package/schemas/WebpackOptions.json +59 -82
  156. package/schemas/plugins/css/CssModuleGeneratorOptions.check.js +1 -1
  157. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  158. package/types.d.ts +225 -157
  159. package/lib/ModuleSourceTypesConstants.js +0 -117
  160. package/lib/dependencies/CssIcssFromIdentifierDependency.js +0 -124
  161. package/lib/dependencies/CssIcssGlobalIdentifierDependency.js +0 -48
  162. package/lib/dependencies/CssIcssLocalIdentifierDependency.js +0 -61
  163. package/lib/dependencies/CssIcssSelfLocalIdentifierDependency.js +0 -190
  164. package/lib/util/jsonParseEvenBetterErrors.js +0 -10
  165. package/schemas/plugins/css/CssAutoGeneratorOptions.check.d.ts +0 -7
  166. package/schemas/plugins/css/CssAutoGeneratorOptions.check.js +0 -6
  167. package/schemas/plugins/css/CssAutoGeneratorOptions.json +0 -3
  168. package/schemas/plugins/css/CssAutoParserOptions.check.d.ts +0 -7
  169. package/schemas/plugins/css/CssAutoParserOptions.check.js +0 -6
  170. package/schemas/plugins/css/CssAutoParserOptions.json +0 -3
  171. package/schemas/plugins/css/CssGlobalGeneratorOptions.check.d.ts +0 -7
  172. package/schemas/plugins/css/CssGlobalGeneratorOptions.check.js +0 -6
  173. package/schemas/plugins/css/CssGlobalGeneratorOptions.json +0 -3
  174. package/schemas/plugins/css/CssGlobalParserOptions.check.d.ts +0 -7
  175. package/schemas/plugins/css/CssGlobalParserOptions.check.js +0 -6
  176. package/schemas/plugins/css/CssGlobalParserOptions.json +0 -3
@@ -15,11 +15,7 @@ const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
15
15
  const WebpackError = require("../WebpackError");
16
16
  const ConstDependency = require("../dependencies/ConstDependency");
17
17
  const CssIcssExportDependency = require("../dependencies/CssIcssExportDependency");
18
- const CssIcssFromIdentifierDependency = require("../dependencies/CssIcssFromIdentifierDependency");
19
- const CssIcssGlobalIdentifierDependency = require("../dependencies/CssIcssGlobalIdentifierDependency");
20
18
  const CssIcssImportDependency = require("../dependencies/CssIcssImportDependency");
21
- const CssIcssLocalIdentifierDependency = require("../dependencies/CssIcssLocalIdentifierDependency");
22
- const CssIcssSelfLocalIdentifierDependency = require("../dependencies/CssIcssSelfLocalIdentifierDependency");
23
19
  const CssIcssSymbolDependency = require("../dependencies/CssIcssSymbolDependency");
24
20
  const CssImportDependency = require("../dependencies/CssImportDependency");
25
21
  const CssUrlDependency = require("../dependencies/CssUrlDependency");
@@ -37,7 +33,7 @@ const walkCssTokens = require("./walkCssTokens");
37
33
  /** @typedef {import("../Parser").ParserState} ParserState */
38
34
  /** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
39
35
  /** @typedef {import("./walkCssTokens").CssTokenCallbacks} CssTokenCallbacks */
40
- /** @typedef {import("../../declarations/WebpackOptions").CssParserExportType} CssParserExportType */
36
+ /** @typedef {import("../../declarations/WebpackOptions").CssModuleParserOptions} CssModuleParserOptions */
41
37
 
42
38
  /** @typedef {[number, number]} Range */
43
39
  /** @typedef {{ line: number, column: number }} Position */
@@ -46,12 +42,14 @@ const walkCssTokens = require("./walkCssTokens");
46
42
  const CC_COLON = ":".charCodeAt(0);
47
43
  const CC_SEMICOLON = ";".charCodeAt(0);
48
44
  const CC_COMMA = ",".charCodeAt(0);
49
- const CC_SLASH = "/".charCodeAt(0);
50
45
  const CC_LEFT_PARENTHESIS = "(".charCodeAt(0);
51
46
  const CC_RIGHT_PARENTHESIS = ")".charCodeAt(0);
52
47
  const CC_LOWER_F = "f".charCodeAt(0);
53
48
  const CC_UPPER_F = "F".charCodeAt(0);
54
49
  const CC_RIGHT_CURLY = "}".charCodeAt(0);
50
+ const CC_HYPHEN_MINUS = "-".charCodeAt(0);
51
+ const CC_TILDE = "~".charCodeAt(0);
52
+ const CC_EQUAL = "=".charCodeAt(0);
55
53
 
56
54
  // https://www.w3.org/TR/css-syntax-3/#newline
57
55
  // We don't have `preprocessing` stage, so we need specify all of them
@@ -61,12 +59,30 @@ const TRIM_WHITE_SPACES = /(^[ \t\n\r\f]*|[ \t\n\r\f]*$)/g;
61
59
  const UNESCAPE = /\\([0-9a-fA-F]{1,6}[ \t\n\r\f]?|[\s\S])/g;
62
60
  const IMAGE_SET_FUNCTION = /^(-\w+-)?image-set$/i;
63
61
  const OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE = /^@(-\w+-)?keyframes$/;
64
- const OPTIONALLY_VENDOR_PREFIXED_ANIMATION_PROPERTY =
65
- /^(-\w+-)?animation(-name)?$/i;
66
62
  const COMPOSES_PROPERTY = /^(composes|compose-with)$/i;
67
63
  const IS_MODULES = /\.module(s)?\.[^.]+$/i;
68
64
  const CSS_COMMENT = /\/\*((?!\*\/).*?)\*\//g;
69
65
 
66
+ /**
67
+ * @param {RegExp} regexp a regexp
68
+ * @param {string} str a string
69
+ * @returns {RegExpExecArray[]} matches
70
+ */
71
+ const matchAll = (regexp, str) => {
72
+ /** @type {RegExpExecArray[]} */
73
+ const result = [];
74
+
75
+ let match;
76
+
77
+ // Use a while loop with exec() to find all matches
78
+ while ((match = regexp.exec(str)) !== null) {
79
+ result.push(match);
80
+ }
81
+ // Return an array to be easily iterable (note: a true spec-compliant polyfill
82
+ // returns an iterator object, but an array spread often suffices for basic use)
83
+ return result;
84
+ };
85
+
70
86
  /**
71
87
  * @param {string} str url string
72
88
  * @param {boolean} isString is url wrapped in quotes
@@ -238,32 +254,90 @@ const unescapeIdentifier = (str) => {
238
254
  return ret;
239
255
  };
240
256
 
257
+ /**
258
+ * A custom property is any property whose name starts with two dashes (U+002D HYPHEN-MINUS), like --foo.
259
+ * The <custom-property-name> production corresponds to this:
260
+ * it’s defined as any <dashed-ident> (a valid identifier that starts with two dashes),
261
+ * except -- itself, which is reserved for future use by CSS.
262
+ * @param {string} identifier identifier
263
+ * @returns {boolean} true when identifier is dashed, otherwise false
264
+ */
265
+ const isDashedIdentifier = (identifier) =>
266
+ identifier.startsWith("--") && identifier.length >= 3;
267
+
268
+ /** @type {Record<string, number>} */
269
+ const PREDEFINED_COUNTER_STYLES = {
270
+ decimal: 1,
271
+ "decimal-leading-zero": 1,
272
+ "arabic-indic": 1,
273
+ armenian: 1,
274
+ "upper-armenian": 1,
275
+ "lower-armenian": 1,
276
+ bengali: 1,
277
+ cambodian: 1,
278
+ khmer: 1,
279
+ "cjk-decimal": 1,
280
+ devanagari: 1,
281
+ georgian: 1,
282
+ gujarati: 1,
283
+ /* cspell:disable-next-line */
284
+ gurmukhi: 1,
285
+ hebrew: 1,
286
+ kannada: 1,
287
+ lao: 1,
288
+ malayalam: 1,
289
+ mongolian: 1,
290
+ myanmar: 1,
291
+ oriya: 1,
292
+ persian: 1,
293
+ "lower-roman": 1,
294
+ "upper-roman": 1,
295
+ tamil: 1,
296
+ telugu: 1,
297
+ thai: 1,
298
+ tibetan: 1,
299
+
300
+ "lower-alpha": 1,
301
+ "lower-latin": 1,
302
+ "upper-alpha": 1,
303
+ "upper-latin": 1,
304
+ "lower-greek": 1,
305
+ hiragana: 1,
306
+ /* cspell:disable-next-line */
307
+ "hiragana-iroha": 1,
308
+ katakana: 1,
309
+ /* cspell:disable-next-line */
310
+ "katakana-iroha": 1,
311
+
312
+ disc: 1,
313
+ circle: 1,
314
+ square: 1,
315
+ "disclosure-open": 1,
316
+ "disclosure-closed": 1,
317
+
318
+ "cjk-earthly-branch": 1,
319
+ "cjk-heavenly-stem": 1,
320
+
321
+ "japanese-informal": 1,
322
+ "japanese-formal": 1,
323
+
324
+ "korean-hangul-formal": 1,
325
+ /* cspell:disable-next-line */
326
+ "korean-hanja-informal": 1,
327
+ /* cspell:disable-next-line */
328
+ "korean-hanja-formal": 1,
329
+
330
+ "simp-chinese-informal": 1,
331
+ "simp-chinese-formal": 1,
332
+ "trad-chinese-informal": 1,
333
+ "trad-chinese-formal": 1,
334
+ "cjk-ideographic": 1,
335
+
336
+ "ethiopic-numeric": 1
337
+ };
338
+
241
339
  /** @type {Record<string, number>} */
242
- const ANIMATION_KEYWORDS = {
243
- // animation-direction
244
- normal: 1,
245
- reverse: 1,
246
- alternate: 1,
247
- "alternate-reverse": 1,
248
- // animation-fill-mode
249
- forwards: 1,
250
- backwards: 1,
251
- both: 1,
252
- // animation-iteration-count
253
- infinite: 1,
254
- // animation-play-state
255
- paused: 1,
256
- running: 1,
257
- // animation-timing-function
258
- ease: 1,
259
- "ease-in": 1,
260
- "ease-out": 1,
261
- "ease-in-out": 1,
262
- linear: 1,
263
- "step-end": 1,
264
- "step-start": 1,
265
- // Special
266
- none: Infinity, // No matter how many times you write none, it will never be an animation name
340
+ const GLOBAL_VALUES = {
267
341
  // Global values
268
342
  initial: Infinity,
269
343
  inherit: Infinity,
@@ -272,6 +346,184 @@ const ANIMATION_KEYWORDS = {
272
346
  "revert-layer": Infinity
273
347
  };
274
348
 
349
+ /** @type {Record<string, number>} */
350
+ const GRID_AREA_OR_COLUMN_OR_ROW = {
351
+ auto: Infinity,
352
+ span: Infinity,
353
+ ...GLOBAL_VALUES
354
+ };
355
+
356
+ /** @type {Record<string, number>} */
357
+ const GRID_AUTO_COLUMNS_OR_ROW = {
358
+ "min-content": Infinity,
359
+ "max-content": Infinity,
360
+ auto: Infinity,
361
+ ...GLOBAL_VALUES
362
+ };
363
+
364
+ /** @type {Record<string, number>} */
365
+ const GRID_AUTO_FLOW = {
366
+ row: 1,
367
+ column: 1,
368
+ dense: 1,
369
+ ...GLOBAL_VALUES
370
+ };
371
+
372
+ /** @type {Record<string, number>} */
373
+ const GRID_TEMPLATE_ARES = {
374
+ // Special
375
+ none: 1,
376
+ ...GLOBAL_VALUES
377
+ };
378
+
379
+ /** @type {Record<string, number>} */
380
+ const GRID_TEMPLATE_COLUMNS_OR_ROWS = {
381
+ none: 1,
382
+ subgrid: 1,
383
+ masonry: 1,
384
+ "max-content": Infinity,
385
+ "min-content": Infinity,
386
+ auto: Infinity,
387
+ ...GLOBAL_VALUES
388
+ };
389
+
390
+ /** @type {Record<string, number>} */
391
+ const GRID_TEMPLATE = {
392
+ ...GRID_TEMPLATE_ARES,
393
+ ...GRID_TEMPLATE_COLUMNS_OR_ROWS
394
+ };
395
+
396
+ /** @type {Record<string, number>} */
397
+ const GRID = {
398
+ "auto-flow": 1,
399
+ dense: 1,
400
+ ...GRID_AUTO_COLUMNS_OR_ROW,
401
+ ...GRID_AUTO_FLOW,
402
+ ...GRID_TEMPLATE_ARES,
403
+ ...GRID_TEMPLATE_COLUMNS_OR_ROWS
404
+ };
405
+
406
+ /**
407
+ * @param {{ animation?: boolean, container?: boolean, customIdents?: boolean, grid?: boolean }=} options options
408
+ * @returns {Map<string, Record<string, number>>} list of known properties
409
+ */
410
+ const getKnownProperties = (options = {}) => {
411
+ /** @type {Map<string, Record<string, number>>} */
412
+ const knownProperties = new Map();
413
+
414
+ if (options.animation) {
415
+ knownProperties.set("animation", {
416
+ // animation-direction
417
+ normal: 1,
418
+ reverse: 1,
419
+ alternate: 1,
420
+ "alternate-reverse": 1,
421
+ // animation-fill-mode
422
+ forwards: 1,
423
+ backwards: 1,
424
+ both: 1,
425
+ // animation-iteration-count
426
+ infinite: 1,
427
+ // animation-play-state
428
+ paused: 1,
429
+ running: 1,
430
+ // animation-timing-function
431
+ ease: 1,
432
+ "ease-in": 1,
433
+ "ease-out": 1,
434
+ "ease-in-out": 1,
435
+ linear: 1,
436
+ "step-end": 1,
437
+ "step-start": 1,
438
+ // Special
439
+ none: Infinity, // No matter how many times you write none, it will never be an animation name
440
+ ...GLOBAL_VALUES
441
+ });
442
+ knownProperties.set("animation-name", {
443
+ // Special
444
+ none: Infinity, // No matter how many times you write none, it will never be an animation name
445
+ ...GLOBAL_VALUES
446
+ });
447
+ }
448
+
449
+ if (options.container) {
450
+ knownProperties.set("container", {
451
+ // container-type
452
+ normal: 1,
453
+ size: 1,
454
+ "inline-size": 1,
455
+ "scroll-state": 1,
456
+ // Special
457
+ none: Infinity,
458
+ ...GLOBAL_VALUES
459
+ });
460
+ knownProperties.set("container-name", {
461
+ // Special
462
+ none: Infinity,
463
+ ...GLOBAL_VALUES
464
+ });
465
+ }
466
+
467
+ if (options.customIdents) {
468
+ knownProperties.set("list-style", {
469
+ // list-style-position
470
+ inside: 1,
471
+ outside: 1,
472
+ // list-style-type
473
+ ...PREDEFINED_COUNTER_STYLES,
474
+ // Special
475
+ none: Infinity,
476
+ ...GLOBAL_VALUES
477
+ });
478
+ knownProperties.set("list-style-type", {
479
+ // list-style-type
480
+ ...PREDEFINED_COUNTER_STYLES,
481
+ // Special
482
+ none: Infinity,
483
+ ...GLOBAL_VALUES
484
+ });
485
+ knownProperties.set("system", {
486
+ cyclic: 1,
487
+ numeric: 1,
488
+ alphabetic: 1,
489
+ symbolic: 1,
490
+ additive: 1,
491
+ fixed: 1,
492
+ extends: 1,
493
+ ...PREDEFINED_COUNTER_STYLES
494
+ });
495
+ knownProperties.set("fallback", {
496
+ ...PREDEFINED_COUNTER_STYLES
497
+ });
498
+ knownProperties.set("speak-as", {
499
+ auto: 1,
500
+ bullets: 1,
501
+ numbers: 1,
502
+ words: 1,
503
+ "spell-out": 1,
504
+ ...PREDEFINED_COUNTER_STYLES
505
+ });
506
+ }
507
+
508
+ if (options.grid) {
509
+ knownProperties.set("grid", GRID);
510
+ knownProperties.set("grid-area", GRID_AREA_OR_COLUMN_OR_ROW);
511
+ knownProperties.set("grid-column", GRID_AREA_OR_COLUMN_OR_ROW);
512
+ knownProperties.set("grid-column-end", GRID_AREA_OR_COLUMN_OR_ROW);
513
+ knownProperties.set("grid-column-start", GRID_AREA_OR_COLUMN_OR_ROW);
514
+ knownProperties.set("grid-column-start", GRID_AREA_OR_COLUMN_OR_ROW);
515
+ knownProperties.set("grid-row", GRID_AREA_OR_COLUMN_OR_ROW);
516
+ knownProperties.set("grid-row-end", GRID_AREA_OR_COLUMN_OR_ROW);
517
+ knownProperties.set("grid-row-start", GRID_AREA_OR_COLUMN_OR_ROW);
518
+ knownProperties.set("grid-template", GRID_TEMPLATE);
519
+ knownProperties.set("grid-template-areas", GRID_TEMPLATE_ARES);
520
+ knownProperties.set("grid-template-columns", GRID_TEMPLATE_COLUMNS_OR_ROWS);
521
+ knownProperties.set("grid-template-rows", GRID_TEMPLATE_COLUMNS_OR_ROWS);
522
+ }
523
+
524
+ return knownProperties;
525
+ };
526
+
275
527
  class LocConverter {
276
528
  /**
277
529
  * @param {string} input input
@@ -323,36 +575,39 @@ const EMPTY_COMMENT_OPTIONS = {
323
575
  const CSS_MODE_TOP_LEVEL = 0;
324
576
  const CSS_MODE_IN_BLOCK = 1;
325
577
 
578
+ const LOCAL_MODE = 0;
579
+ const GLOBAL_MODE = 1;
580
+
326
581
  const eatUntilSemi = walkCssTokens.eatUntil(";");
327
582
  const eatUntilLeftCurly = walkCssTokens.eatUntil("{");
328
- const eatSemi = walkCssTokens.eatUntil(";");
329
583
 
330
584
  /**
331
- * @typedef {object} CssParserOptions
332
- * @property {boolean=} importOption need handle `@import`
333
- * @property {boolean=} url need handle URLs
585
+ * @typedef {object} CssParserOwnOptions
334
586
  * @property {("pure" | "global" | "local" | "auto")=} defaultMode default mode
335
- * @property {boolean=} namedExports is named exports
336
- * @property {CssParserExportType=} exportType export type
337
587
  */
338
588
 
589
+ /** @typedef {CssModuleParserOptions & CssParserOwnOptions} CssParserOptions */
590
+
339
591
  class CssParser extends Parser {
340
592
  /**
341
593
  * @param {CssParserOptions=} options options
342
594
  */
343
- constructor({
344
- defaultMode = "pure",
345
- importOption = true,
346
- url = true,
347
- namedExports = true,
348
- exportType
349
- } = {}) {
595
+ constructor(options = {}) {
350
596
  super();
351
- this.defaultMode = defaultMode;
352
- this.import = importOption;
353
- this.url = url;
354
- this.namedExports = namedExports;
355
- this.exportType = exportType;
597
+ this.defaultMode =
598
+ typeof options.defaultMode !== "undefined" ? options.defaultMode : "pure";
599
+ this.options = {
600
+ url: true,
601
+ import: true,
602
+ namedExports: true,
603
+ animation: true,
604
+ container: true,
605
+ customIdents: true,
606
+ dashedIdents: true,
607
+ function: true,
608
+ grid: true,
609
+ ...options
610
+ };
356
611
  /** @type {Comment[] | undefined} */
357
612
  this.comments = undefined;
358
613
  this.magicCommentContext = createMagicCommentContext();
@@ -400,6 +655,7 @@ class CssParser extends Parser {
400
655
  mode === "auto" &&
401
656
  module.type === CSS_MODULE_TYPE_AUTO &&
402
657
  IS_MODULES.test(
658
+ // TODO matchResource
403
659
  parseResource(/** @type {string} */ (module.getResource())).path
404
660
  )
405
661
  ) {
@@ -407,6 +663,12 @@ class CssParser extends Parser {
407
663
  }
408
664
 
409
665
  const isModules = mode === "global" || mode === "local";
666
+ const knownProperties = getKnownProperties({
667
+ animation: this.options.animation,
668
+ container: this.options.container,
669
+ customIdents: this.options.customIdents,
670
+ grid: this.options.grid
671
+ });
410
672
 
411
673
  /** @type {BuildMeta} */
412
674
  (module.buildMeta).isCSSModule = isModules;
@@ -417,7 +679,7 @@ class CssParser extends Parser {
417
679
  let scope = CSS_MODE_TOP_LEVEL;
418
680
  /** @type {boolean} */
419
681
  let allowImportAtRule = true;
420
- /** @type {[string, number, number][]} */
682
+ /** @type {[string, number, number, boolean?][]} */
421
683
  const balanced = [];
422
684
  let lastTokenEndForComments = 0;
423
685
 
@@ -425,10 +687,8 @@ class CssParser extends Parser {
425
687
  let isNextRulePrelude = isModules;
426
688
  /** @type {number} */
427
689
  let blockNestingLevel = 0;
428
- /** @type {"local" | "global" | undefined} */
690
+ /** @type {0 | 1 | undefined} */
429
691
  let modeData;
430
- /** @type {Set<string>} */
431
- const declaredCssVariables = new Set();
432
692
 
433
693
  /** @type {string[]} */
434
694
  let lastLocalIdentifiers = [];
@@ -443,58 +703,36 @@ class CssParser extends Parser {
443
703
  * @returns {boolean} true, when next is nested syntax
444
704
  */
445
705
  const isNextNestedSyntax = (input, pos) => {
446
- pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
706
+ pos = walkCssTokens.eatWhitespaceAndComments(input, pos)[0];
447
707
 
448
- if (input[pos] === "}") {
708
+ if (
709
+ input.charCodeAt(pos) === CC_RIGHT_CURLY ||
710
+ (input.charCodeAt(pos) === CC_HYPHEN_MINUS &&
711
+ input.charCodeAt(pos + 1) === CC_HYPHEN_MINUS)
712
+ ) {
449
713
  return false;
450
714
  }
451
715
 
452
- // According spec only identifier can be used as a property name
453
- const isIdentifier = walkCssTokens.isIdentStartCodePoint(
454
- input.charCodeAt(pos)
455
- );
716
+ const identifier = walkCssTokens.eatIdentSequence(input, pos);
717
+
718
+ if (!identifier) {
719
+ return true;
720
+ }
721
+
722
+ const leftCurly = eatUntilLeftCurly(input, pos);
723
+ const content = input.slice(identifier[0], leftCurly);
724
+
725
+ if (content.includes(";") || content.includes("}")) {
726
+ return false;
727
+ }
456
728
 
457
- return !isIdentifier;
729
+ return true;
458
730
  };
459
731
  /**
460
732
  * @returns {boolean} true, when in local scope
461
733
  */
462
734
  const isLocalMode = () =>
463
- modeData === "local" || (mode === "local" && modeData === undefined);
464
-
465
- /**
466
- * @param {string} input input
467
- * @param {number} pos start position
468
- * @param {(input: string, pos: number) => number} eater eater
469
- * @returns {[number,string]} new position and text
470
- */
471
- const eatText = (input, pos, eater) => {
472
- let text = "";
473
- for (;;) {
474
- if (input.charCodeAt(pos) === CC_SLASH) {
475
- const newPos = walkCssTokens.eatComments(input, pos);
476
- if (pos !== newPos) {
477
- pos = newPos;
478
- if (pos === input.length) break;
479
- } else {
480
- text += "/";
481
- pos++;
482
- if (pos === input.length) break;
483
- }
484
- }
485
- const newPos = eater(input, pos);
486
- if (pos !== newPos) {
487
- text += input.slice(pos, newPos);
488
- pos = newPos;
489
- } else {
490
- break;
491
- }
492
- if (pos === input.length) break;
493
- }
494
- return [pos, text.trimEnd()];
495
- };
496
-
497
- const eatPropertyName = walkCssTokens.eatUntil(":{};");
735
+ modeData === LOCAL_MODE || (mode === "local" && modeData === undefined);
498
736
 
499
737
  /**
500
738
  * @param {string} input input
@@ -604,7 +842,10 @@ class CssParser extends Parser {
604
842
  }
605
843
 
606
844
  const last = tokens[2] || tokens[1] || tokens[0];
607
- const mediaStart = walkCssTokens.eatWhitespaceAndComments(input, last[1]);
845
+ const mediaStart = walkCssTokens.eatWhitespaceAndComments(
846
+ input,
847
+ last[1]
848
+ )[0];
608
849
 
609
850
  let media;
610
851
 
@@ -816,6 +1057,23 @@ class CssParser extends Parser {
816
1057
 
817
1058
  // CSS modules stuff
818
1059
 
1060
+ /**
1061
+ * @param {string} value value to resolve
1062
+ * @returns {string | [string, string, boolean]} resolved reexport
1063
+ */
1064
+ const getReexport = (value) => {
1065
+ const reexport = icssDefinitions.get(value);
1066
+
1067
+ if (reexport) {
1068
+ if (reexport.isReference) {
1069
+ return [value, reexport.value, true];
1070
+ }
1071
+ return [value, reexport.value, false];
1072
+ }
1073
+
1074
+ return value;
1075
+ };
1076
+
819
1077
  /**
820
1078
  * @param {0 | 1} type import or export
821
1079
  * @param {string} input input
@@ -823,7 +1081,7 @@ class CssParser extends Parser {
823
1081
  * @returns {number} position after parse
824
1082
  */
825
1083
  const processImportOrExport = (type, input, pos) => {
826
- pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
1084
+ pos = walkCssTokens.eatWhitespaceAndComments(input, pos)[0];
827
1085
  /** @type {string | undefined} */
828
1086
  let request;
829
1087
  if (type === 0) {
@@ -853,7 +1111,7 @@ class CssParser extends Parser {
853
1111
  }
854
1112
  request = input.slice(str[0] + 1, str[1] - 1);
855
1113
  pos = str[1];
856
- pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
1114
+ pos = walkCssTokens.eatWhitespaceAndComments(input, pos)[0];
857
1115
  cc = input.charCodeAt(pos);
858
1116
  if (cc !== CC_RIGHT_PARENTHESIS) {
859
1117
  this._emitWarning(
@@ -866,7 +1124,7 @@ class CssParser extends Parser {
866
1124
  return pos;
867
1125
  }
868
1126
  pos++;
869
- pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
1127
+ pos = walkCssTokens.eatWhitespaceAndComments(input, pos)[0];
870
1128
  }
871
1129
 
872
1130
  /**
@@ -892,13 +1150,7 @@ class CssParser extends Parser {
892
1150
 
893
1151
  icssDefinitions.set(name, { value, isReference: true });
894
1152
  } else if (type === 1) {
895
- const reexport = icssDefinitions.get(value);
896
- const dep = new CssIcssExportDependency(
897
- name,
898
- value,
899
- reexport && reexport.isReference ? reexport.value : undefined,
900
- undefined
901
- );
1153
+ const dep = new CssIcssExportDependency(name, getReexport(value));
902
1154
  const { line: sl, column: sc } = locConverter.get(start);
903
1155
  const { line: el, column: ec } = locConverter.get(end);
904
1156
  dep.setLoc(sl, sc, el, ec);
@@ -1044,27 +1296,13 @@ class CssParser extends Parser {
1044
1296
  });
1045
1297
  }
1046
1298
 
1047
- if (aliasName) {
1048
- const reexport = icssDefinitions.get(aliasName);
1049
- const dep = new CssIcssExportDependency(
1050
- aliasName,
1051
- name,
1052
- reexport && reexport.isReference ? reexport.value : undefined,
1053
- undefined
1054
- );
1055
- const { line: sl, column: sc } = locConverter.get(start);
1056
- const { line: el, column: ec } = locConverter.get(end);
1057
- dep.setLoc(sl, sc, el, ec);
1058
- module.addDependency(dep);
1059
- }
1060
-
1061
1299
  {
1062
- const reexport = icssDefinitions.get(name);
1063
1300
  const dep = new CssIcssExportDependency(
1064
- name,
1065
- name,
1066
- reexport && reexport.isReference ? reexport.value : undefined,
1067
- undefined
1301
+ aliasName || name,
1302
+ getReexport(aliasName || name),
1303
+ undefined,
1304
+ false,
1305
+ CssIcssExportDependency.EXPORT_MODE.REPLACE
1068
1306
  );
1069
1307
  const { line: sl, column: sc } = locConverter.get(start);
1070
1308
  const { line: el, column: ec } = locConverter.get(end);
@@ -1089,7 +1327,7 @@ class CssParser extends Parser {
1089
1327
  return atRuleEnd;
1090
1328
  }
1091
1329
 
1092
- const pos = walkCssTokens.eatWhitespaceAndComments(alias, ident[1]);
1330
+ const pos = walkCssTokens.eatWhitespaceAndComments(alias, ident[1])[0];
1093
1331
 
1094
1332
  const name = alias.slice(ident[0], ident[1]);
1095
1333
  let value =
@@ -1164,23 +1402,36 @@ class CssParser extends Parser {
1164
1402
  end = walkCssTokens.consumeUntil(
1165
1403
  input,
1166
1404
  start,
1167
- type === 1
1168
- ? {
1169
- identifier(input, start, end) {
1170
- const name = unescapeIdentifier(input.slice(start, end));
1171
- const { line: sl, column: sc } = locConverter.get(start);
1172
- const { line: el, column: ec } = locConverter.get(end);
1173
- const dep = new CssIcssLocalIdentifierDependency(name, [
1174
- start,
1175
- end
1176
- ]);
1177
- dep.setLoc(sl, sc, el, ec);
1178
- module.addDependency(dep);
1405
+ {
1406
+ identifier(input, start, end) {
1407
+ if (type === 1) {
1408
+ let identifier = unescapeIdentifier(input.slice(start, end));
1409
+ const { line: sl, column: sc } = locConverter.get(start);
1410
+ const { line: el, column: ec } = locConverter.get(end);
1411
+ const isDashedIdent = isDashedIdentifier(identifier);
1179
1412
 
1180
- return end;
1413
+ if (isDashedIdent) {
1414
+ identifier = identifier.slice(2);
1181
1415
  }
1416
+
1417
+ const dep = new CssIcssExportDependency(
1418
+ identifier,
1419
+ getReexport(identifier),
1420
+ [start, end],
1421
+ true,
1422
+ CssIcssExportDependency.EXPORT_MODE.ONCE,
1423
+ isDashedIdent
1424
+ ? CssIcssExportDependency.EXPORT_TYPE.CUSTOM_VARIABLE
1425
+ : CssIcssExportDependency.EXPORT_TYPE.NORMAL
1426
+ );
1427
+
1428
+ dep.setLoc(sl, sc, el, ec);
1429
+ module.addDependency(dep);
1182
1430
  }
1183
- : {},
1431
+
1432
+ return end;
1433
+ }
1434
+ },
1184
1435
  {},
1185
1436
  { onlyTopLevel: true, functionValue: true }
1186
1437
  );
@@ -1197,35 +1448,69 @@ class CssParser extends Parser {
1197
1448
  /**
1198
1449
  * @param {string} input input
1199
1450
  * @param {number} end name end position
1200
- * @param {{ string?: boolean, identifier: boolean, validate?: (name: string) => boolean, dashed?: boolean }} options types which allowed to handle
1451
+ * @param {{ string?: boolean, identifier?: boolean | RegExp }} options types which allowed to handle
1201
1452
  * @returns {number} position after handling
1202
1453
  */
1203
1454
  const processLocalAtRule = (input, end, options) => {
1204
- /** @type {[number, number, boolean] | undefined} */
1205
- let value;
1206
1455
  let found = false;
1207
1456
 
1208
- walkCssTokens.consumeUntil(
1457
+ return walkCssTokens.consumeUntil(
1209
1458
  input,
1210
1459
  end,
1211
1460
  {
1212
1461
  string(_input, start, end) {
1213
1462
  if (!found && options.string) {
1463
+ const value = unescapeIdentifier(input.slice(start + 1, end - 1));
1464
+ const { line: sl, column: sc } = locConverter.get(start);
1465
+ const { line: el, column: ec } = locConverter.get(end);
1466
+ const dep = new CssIcssExportDependency(
1467
+ value,
1468
+ value,
1469
+ [start, end],
1470
+ true,
1471
+ CssIcssExportDependency.EXPORT_MODE.ONCE
1472
+ );
1473
+ dep.setLoc(sl, sc, el, ec);
1474
+ module.addDependency(dep);
1214
1475
  found = true;
1215
- value = [start, end, true];
1216
1476
  }
1217
1477
  return end;
1218
1478
  },
1219
- identifier(_input, start, end) {
1220
- if (!found && options.identifier) {
1221
- found = true;
1222
- value = [start, end, false];
1479
+ identifier(input, start, end) {
1480
+ if (!found) {
1481
+ const value = input.slice(start, end);
1482
+
1483
+ if (options.identifier) {
1484
+ const identifier = unescapeIdentifier(value);
1485
+
1486
+ if (
1487
+ options.identifier instanceof RegExp &&
1488
+ options.identifier.test(identifier)
1489
+ ) {
1490
+ return end;
1491
+ }
1492
+
1493
+ const { line: sl, column: sc } = locConverter.get(start);
1494
+ const { line: el, column: ec } = locConverter.get(end);
1495
+
1496
+ const dep = new CssIcssExportDependency(
1497
+ identifier,
1498
+ getReexport(identifier),
1499
+ [start, end],
1500
+ true,
1501
+ CssIcssExportDependency.EXPORT_MODE.ONCE,
1502
+ CssIcssExportDependency.EXPORT_TYPE.NORMAL
1503
+ );
1504
+ dep.setLoc(sl, sc, el, ec);
1505
+ module.addDependency(dep);
1506
+ found = true;
1507
+ }
1223
1508
  }
1224
1509
  return end;
1225
1510
  }
1226
1511
  },
1227
1512
  {
1228
- function(input, start, end) {
1513
+ function: (input, start, end) => {
1229
1514
  // No need to handle `:` (COLON), because it's always a function
1230
1515
  const name = input
1231
1516
  .slice(start, end - 1)
@@ -1240,53 +1525,36 @@ class CssParser extends Parser {
1240
1525
  return processLocalOrGlobalFunction(input, type, start, end);
1241
1526
  }
1242
1527
 
1528
+ if (
1529
+ this.options.dashedIdents &&
1530
+ isLocalMode() &&
1531
+ (name === "var" || name === "style")
1532
+ ) {
1533
+ return processDashedIdent(input, end, end);
1534
+ }
1535
+
1243
1536
  return end;
1244
1537
  }
1245
1538
  },
1246
1539
  { onlyTopLevel: true, atRulePrelude: true }
1247
1540
  );
1248
- if (!value) return end;
1249
- let name = value[2]
1250
- ? input.slice(value[0] + 1, value[1] - 1)
1251
- : input.slice(value[0], value[1]);
1252
- if (options.validate && !options.validate(name)) return end;
1253
- name = unescapeIdentifier(name);
1254
- const { line: sl, column: sc } = locConverter.get(value[0]);
1255
- const { line: el, column: ec } = locConverter.get(value[1]);
1256
- if (options.dashed) {
1257
- name = name.slice(2);
1258
- declaredCssVariables.add(name);
1259
- }
1260
- const dep = new CssIcssLocalIdentifierDependency(
1261
- name,
1262
- [value[0], value[1]],
1263
- options.dashed ? "--" : ""
1264
- );
1265
- dep.setLoc(sl, sc, el, ec);
1266
- module.addDependency(dep);
1267
- return value[1];
1268
1541
  };
1269
1542
  /**
1270
1543
  * @param {string} input input
1544
+ * @param {number} start start position
1271
1545
  * @param {number} end end position
1272
1546
  * @returns {number} position after handling
1273
1547
  */
1274
- const processVarFunction = (input, end) => {
1275
- const customIdent = walkCssTokens.eatIdentSequence(input, end);
1548
+ const processDashedIdent = (input, start, end) => {
1549
+ const customIdent = walkCssTokens.eatIdentSequence(input, start);
1276
1550
  if (!customIdent) return end;
1277
- let name = input.slice(customIdent[0], customIdent[1]);
1278
- // A custom property is any property whose name starts with two dashes (U+002D HYPHEN-MINUS), like --foo.
1279
- // The <custom-property-name> production corresponds to this:
1280
- // it’s defined as any <dashed-ident> (a valid identifier that starts with two dashes),
1281
- // except -- itself, which is reserved for future use by CSS.
1282
- if (!name.startsWith("--") || name.length < 3) return end;
1283
- name = unescapeIdentifier(
1551
+ const identifier = unescapeIdentifier(
1284
1552
  input.slice(customIdent[0] + 2, customIdent[1])
1285
1553
  );
1286
1554
  const afterCustomIdent = walkCssTokens.eatWhitespaceAndComments(
1287
1555
  input,
1288
1556
  customIdent[1]
1289
- );
1557
+ )[0];
1290
1558
  if (
1291
1559
  input.charCodeAt(afterCustomIdent) === CC_LOWER_F ||
1292
1560
  input.charCodeAt(afterCustomIdent) === CC_UPPER_F
@@ -1303,7 +1571,7 @@ class CssParser extends Parser {
1303
1571
  }
1304
1572
  const from = walkCssTokens.eatIdentSequenceOrString(
1305
1573
  input,
1306
- walkCssTokens.eatWhitespaceAndComments(input, fromWord[1])
1574
+ walkCssTokens.eatWhitespaceAndComments(input, fromWord[1])[0]
1307
1575
  );
1308
1576
  if (!from) {
1309
1577
  return end;
@@ -1316,14 +1584,15 @@ class CssParser extends Parser {
1316
1584
  } else if (from[2] === false) {
1317
1585
  const { line: sl, column: sc } = locConverter.get(customIdent[0]);
1318
1586
  const { line: el, column: ec } = locConverter.get(from[1] - 1);
1319
- const dep = new CssIcssFromIdentifierDependency(
1587
+ const dep = new CssIcssImportDependency(
1320
1588
  path.slice(1, -1),
1589
+ [customIdent[0], from[1] - 1],
1321
1590
  /** @type {"local" | "global"} */
1322
1591
  (mode),
1323
- [customIdent[0], from[1] - 1],
1324
- name,
1325
- name,
1326
- "--"
1592
+ identifier,
1593
+ identifier,
1594
+ CssIcssExportDependency.EXPORT_MODE.NONE,
1595
+ CssIcssExportDependency.EXPORT_TYPE.CUSTOM_VARIABLE
1327
1596
  );
1328
1597
 
1329
1598
  dep.setLoc(sl, sc, el, ec);
@@ -1338,12 +1607,13 @@ class CssParser extends Parser {
1338
1607
  } else {
1339
1608
  const { line: sl, column: sc } = locConverter.get(customIdent[0]);
1340
1609
  const { line: el, column: ec } = locConverter.get(customIdent[1]);
1341
- const dep = new CssIcssSelfLocalIdentifierDependency(
1342
- name,
1343
- undefined,
1610
+ const dep = new CssIcssExportDependency(
1611
+ identifier,
1612
+ getReexport(identifier),
1344
1613
  [customIdent[0], customIdent[1]],
1345
- "--",
1346
- declaredCssVariables
1614
+ true,
1615
+ CssIcssExportDependency.EXPORT_MODE.ONCE,
1616
+ CssIcssExportDependency.EXPORT_TYPE.CUSTOM_VARIABLE
1347
1617
  );
1348
1618
  dep.setLoc(sl, sc, el, ec);
1349
1619
  module.addDependency(dep);
@@ -1359,81 +1629,131 @@ class CssParser extends Parser {
1359
1629
  * @returns {number} position after handling
1360
1630
  */
1361
1631
  const processLocalDeclaration = (input, pos, end) => {
1362
- modeData = undefined;
1363
- pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
1364
- const propertyNameStart = pos;
1365
- const [propertyNameEnd, propertyName] = eatText(
1366
- input,
1367
- pos,
1368
- eatPropertyName
1369
- );
1370
- if (input.charCodeAt(propertyNameEnd) !== CC_COLON) return end;
1371
- pos = propertyNameEnd + 1;
1372
- if (propertyName.startsWith("--") && propertyName.length >= 3) {
1373
- // CSS Variable
1374
- const { line: sl, column: sc } = locConverter.get(propertyNameStart);
1375
- const { line: el, column: ec } = locConverter.get(propertyNameEnd);
1376
- const name = unescapeIdentifier(propertyName.slice(2));
1377
- const dep = new CssIcssLocalIdentifierDependency(
1378
- name,
1379
- [propertyNameStart, propertyNameEnd],
1380
- "--"
1381
- );
1382
- dep.setLoc(sl, sc, el, ec);
1383
- module.addDependency(dep);
1384
- declaredCssVariables.add(name);
1385
- } else if (
1386
- OPTIONALLY_VENDOR_PREFIXED_ANIMATION_PROPERTY.test(propertyName)
1387
- ) {
1388
- /** @type {[number, number, boolean][]} */
1389
- const animationNames = [];
1632
+ pos = walkCssTokens.eatWhitespaceAndComments(input, pos)[0];
1633
+ const identifier = walkCssTokens.eatIdentSequence(input, pos);
1634
+
1635
+ if (!identifier) {
1636
+ return end;
1637
+ }
1638
+
1639
+ const propertyNameStart = identifier[0];
1640
+
1641
+ pos = walkCssTokens.eatWhitespaceAndComments(input, identifier[1])[0];
1642
+
1643
+ if (input.charCodeAt(pos) !== CC_COLON) {
1644
+ return end;
1645
+ }
1646
+
1647
+ pos += 1;
1648
+
1649
+ // Remove prefix and lowercase
1650
+ const propertyName = input
1651
+ .slice(identifier[0], identifier[1])
1652
+ .replace(/^(-\w+-)/, "")
1653
+ .toLowerCase();
1654
+
1655
+ if (isLocalMode() && knownProperties.has(propertyName)) {
1656
+ /** @type {[number, number, boolean?][]} */
1657
+ const values = [];
1390
1658
  /** @type {Record<string, number>} */
1391
- let parsedAnimationKeywords = Object.create(null);
1659
+ let parsedKeywords = Object.create(null);
1660
+
1661
+ const isGridProperty = Boolean(propertyName.startsWith("grid"));
1662
+ const isGridTemplate = isGridProperty
1663
+ ? Boolean(
1664
+ propertyName === "grid" ||
1665
+ propertyName === "grid-template" ||
1666
+ propertyName === "grid-template-columns" ||
1667
+ propertyName === "grid-template-rows"
1668
+ )
1669
+ : false;
1392
1670
 
1393
1671
  const end = walkCssTokens.consumeUntil(
1394
1672
  input,
1395
1673
  pos,
1396
1674
  {
1675
+ leftSquareBracket(input, start, end) {
1676
+ let i = end;
1677
+
1678
+ while (true) {
1679
+ i = walkCssTokens.eatWhitespaceAndComments(input, i)[0];
1680
+ const name = walkCssTokens.eatIdentSequence(input, i);
1681
+
1682
+ if (!name) {
1683
+ break;
1684
+ }
1685
+
1686
+ values.push(name);
1687
+ i = name[1];
1688
+ }
1689
+
1690
+ return end;
1691
+ },
1397
1692
  string(_input, start, end) {
1398
- animationNames.push([start, end, true]);
1693
+ if (
1694
+ propertyName === "animation" ||
1695
+ propertyName === "animation-name"
1696
+ ) {
1697
+ values.push([start, end, true]);
1698
+ }
1699
+
1700
+ if (
1701
+ propertyName === "grid" ||
1702
+ propertyName === "grid-template" ||
1703
+ propertyName === "grid-template-areas"
1704
+ ) {
1705
+ const areas = unescapeIdentifier(
1706
+ input.slice(start + 1, end - 1)
1707
+ );
1708
+ const matches = matchAll(/\b\w+\b/g, areas);
1709
+
1710
+ for (const match of matches) {
1711
+ const areaStart = start + 1 + match.index;
1712
+ values.push([areaStart, areaStart + match[0].length, false]);
1713
+ }
1714
+ }
1399
1715
 
1400
1716
  return end;
1401
1717
  },
1402
1718
  identifier(input, start, end) {
1403
- const keyword = input.slice(start, end).toLowerCase();
1719
+ if (isGridTemplate) {
1720
+ return end;
1721
+ }
1722
+
1723
+ const identifier = input.slice(start, end);
1724
+ const keyword = identifier.toLowerCase();
1404
1725
 
1405
- parsedAnimationKeywords[keyword] =
1406
- typeof parsedAnimationKeywords[keyword] !== "undefined"
1407
- ? parsedAnimationKeywords[keyword] + 1
1726
+ parsedKeywords[keyword] =
1727
+ typeof parsedKeywords[keyword] !== "undefined"
1728
+ ? parsedKeywords[keyword] + 1
1408
1729
  : 0;
1730
+ const keywords =
1731
+ /** @type {Record<string, number>} */
1732
+ (knownProperties.get(propertyName));
1409
1733
 
1410
1734
  if (
1411
- ANIMATION_KEYWORDS[keyword] &&
1412
- parsedAnimationKeywords[keyword] < ANIMATION_KEYWORDS[keyword]
1735
+ keywords[keyword] &&
1736
+ parsedKeywords[keyword] < keywords[keyword]
1413
1737
  ) {
1414
1738
  return end;
1415
1739
  }
1416
1740
 
1417
- animationNames.push([start, end, false]);
1741
+ values.push([start, end]);
1418
1742
  return end;
1419
1743
  },
1420
1744
  comma(_input, _start, end) {
1421
- parsedAnimationKeywords = {};
1745
+ parsedKeywords = {};
1422
1746
 
1423
1747
  return end;
1424
1748
  }
1425
1749
  },
1426
1750
  {
1427
- function(input, start, end) {
1751
+ function: (input, start, end) => {
1428
1752
  const name = input
1429
1753
  .slice(start, end - 1)
1430
1754
  .replace(/\\/g, "")
1431
1755
  .toLowerCase();
1432
1756
 
1433
- if (isLocalMode() && name === "var") {
1434
- return processVarFunction(input, end);
1435
- }
1436
-
1437
1757
  const type =
1438
1758
  name === "local" ? 1 : name === "global" ? 2 : undefined;
1439
1759
 
@@ -1441,26 +1761,50 @@ class CssParser extends Parser {
1441
1761
  return processLocalOrGlobalFunction(input, type, start, end);
1442
1762
  }
1443
1763
 
1764
+ if (
1765
+ this.options.dashedIdents &&
1766
+ isLocalMode() &&
1767
+ name === "var"
1768
+ ) {
1769
+ return processDashedIdent(input, end, end);
1770
+ }
1771
+
1772
+ if (this.options.url) {
1773
+ if (name === "src" || name === "url") {
1774
+ return processURLFunction(input, end, name);
1775
+ } else if (IMAGE_SET_FUNCTION.test(name)) {
1776
+ return processImageSetFunction(input, start, end);
1777
+ }
1778
+ }
1779
+
1444
1780
  return end;
1445
1781
  }
1446
1782
  },
1447
- { onlyTopLevel: true, declarationValue: true }
1783
+ {
1784
+ onlyTopLevel: !isGridTemplate,
1785
+ declarationValue: true
1786
+ }
1448
1787
  );
1449
1788
 
1450
- if (animationNames.length > 0) {
1451
- for (const animationName of animationNames) {
1452
- const { line: sl, column: sc } = locConverter.get(animationName[0]);
1453
- const { line: el, column: ec } = locConverter.get(animationName[1]);
1454
- const [start, end, isString] = animationName;
1789
+ if (values.length > 0) {
1790
+ for (const value of values) {
1791
+ const { line: sl, column: sc } = locConverter.get(value[0]);
1792
+ const { line: el, column: ec } = locConverter.get(value[1]);
1793
+ const [start, end, isString] = value;
1455
1794
  const name = unescapeIdentifier(
1456
1795
  isString
1457
1796
  ? input.slice(start + 1, end - 1)
1458
1797
  : input.slice(start, end)
1459
1798
  );
1460
- const dep = new CssIcssSelfLocalIdentifierDependency(
1799
+ const dep = new CssIcssExportDependency(
1461
1800
  name,
1462
- undefined,
1463
- [start, end]
1801
+ getReexport(name),
1802
+ [start, end],
1803
+ true,
1804
+ CssIcssExportDependency.EXPORT_MODE.ONCE,
1805
+ isGridProperty
1806
+ ? CssIcssExportDependency.EXPORT_TYPE.GRID_CUSTOM_IDENTIFIER
1807
+ : CssIcssExportDependency.EXPORT_TYPE.NORMAL
1464
1808
  );
1465
1809
  dep.setLoc(sl, sc, el, ec);
1466
1810
  module.addDependency(dep);
@@ -1491,7 +1835,7 @@ class CssParser extends Parser {
1491
1835
  const classNames = new Set();
1492
1836
 
1493
1837
  while (true) {
1494
- pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
1838
+ pos = walkCssTokens.eatWhitespaceAndComments(input, pos)[0];
1495
1839
 
1496
1840
  let className = walkCssTokens.eatIdentSequence(input, pos);
1497
1841
 
@@ -1509,14 +1853,20 @@ class CssParser extends Parser {
1509
1853
  pos = walkCssTokens.eatWhitespaceAndComments(
1510
1854
  input,
1511
1855
  className[1] + 1
1512
- );
1856
+ )[0];
1513
1857
  className = walkCssTokens.eatIdentSequence(input, pos);
1514
1858
  if (className) {
1515
- pos = walkCssTokens.eatWhitespaceAndComments(input, className[1]);
1859
+ pos = walkCssTokens.eatWhitespaceAndComments(
1860
+ input,
1861
+ className[1]
1862
+ )[0];
1516
1863
  pos += 1;
1517
1864
  }
1518
1865
  } else if (className) {
1519
- pos = walkCssTokens.eatWhitespaceAndComments(input, className[1]);
1866
+ pos = walkCssTokens.eatWhitespaceAndComments(
1867
+ input,
1868
+ className[1]
1869
+ )[0];
1520
1870
  pos = className[1];
1521
1871
  }
1522
1872
 
@@ -1533,26 +1883,16 @@ class CssParser extends Parser {
1533
1883
  for (const className of classNames) {
1534
1884
  const [start, end] = className;
1535
1885
  const identifier = unescapeIdentifier(input.slice(start, end));
1536
- const reexport = icssDefinitions.get(identifier);
1537
- const dep = isGlobalFunction
1538
- ? new CssIcssGlobalIdentifierDependency(
1539
- lastLocalIdentifier,
1540
- identifier,
1541
- reexport && reexport.isReference
1542
- ? reexport.value
1543
- : undefined,
1544
- [start, end]
1545
- )
1546
- : new CssIcssSelfLocalIdentifierDependency(
1547
- lastLocalIdentifier,
1548
- identifier,
1549
- [start, end],
1550
- undefined,
1551
- undefined,
1552
- reexport && reexport.isReference
1553
- ? reexport.value
1554
- : undefined
1555
- );
1886
+ const resolvedClassName = getReexport(identifier);
1887
+ const dep = new CssIcssExportDependency(
1888
+ lastLocalIdentifier,
1889
+ resolvedClassName,
1890
+ [start, end],
1891
+ isGlobalFunction ? false : !Array.isArray(resolvedClassName),
1892
+ isGlobalFunction
1893
+ ? CssIcssExportDependency.EXPORT_MODE.APPEND
1894
+ : CssIcssExportDependency.EXPORT_MODE.SELF_REFERENCE
1895
+ );
1556
1896
  const { line: sl, column: sc } = locConverter.get(start);
1557
1897
  const { line: el, column: ec } = locConverter.get(end);
1558
1898
  dep.setLoc(sl, sc, el, ec);
@@ -1582,14 +1922,15 @@ class CssParser extends Parser {
1582
1922
  for (const className of classNames) {
1583
1923
  const [start, end] = className;
1584
1924
  const identifier = unescapeIdentifier(input.slice(start, end));
1585
- const dep = new CssIcssFromIdentifierDependency(
1925
+ const dep = new CssIcssImportDependency(
1586
1926
  request,
1927
+ [start, end],
1587
1928
  /** @type {"local" | "global"} */
1588
1929
  (mode),
1589
- [start, end],
1590
1930
  identifier,
1591
1931
  /** @type {string} */
1592
- (lastLocalIdentifier)
1932
+ (lastLocalIdentifier),
1933
+ CssIcssExportDependency.EXPORT_MODE.APPEND
1593
1934
  );
1594
1935
  const { line: sl, column: sc } = locConverter.get(start);
1595
1936
  const { line: el, column: ec } = locConverter.get(end);
@@ -1608,15 +1949,13 @@ class CssParser extends Parser {
1608
1949
  const identifier = unescapeIdentifier(
1609
1950
  input.slice(start, end)
1610
1951
  );
1611
- const reexport = icssDefinitions.get(identifier);
1612
- const dep = new CssIcssGlobalIdentifierDependency(
1952
+ const dep = new CssIcssExportDependency(
1613
1953
  /** @type {string} */
1614
1954
  (lastLocalIdentifier),
1615
- identifier,
1616
- reexport && reexport.isReference
1617
- ? reexport.value
1618
- : undefined,
1619
- [start, end]
1955
+ getReexport(identifier),
1956
+ [start, end],
1957
+ false,
1958
+ CssIcssExportDependency.EXPORT_MODE.APPEND
1620
1959
  );
1621
1960
  const { line: sl, column: sc } = locConverter.get(start);
1622
1961
  const { line: el, column: ec } = locConverter.get(end);
@@ -1657,6 +1996,7 @@ class CssParser extends Parser {
1657
1996
  const dep = new ConstDependency("", [propertyNameStart, end]);
1658
1997
  module.addPresentationalDependency(dep);
1659
1998
  }
1999
+
1660
2000
  return pos;
1661
2001
  };
1662
2002
 
@@ -1666,10 +2006,16 @@ class CssParser extends Parser {
1666
2006
  * @param {number} end end position
1667
2007
  * @returns {number} position after handling
1668
2008
  */
1669
- const processHashID = (input, start, end) => {
2009
+ const processIdSelector = (input, start, end) => {
1670
2010
  const valueStart = start + 1;
1671
2011
  const name = unescapeIdentifier(input.slice(valueStart, end));
1672
- const dep = new CssIcssLocalIdentifierDependency(name, [valueStart, end]);
2012
+ const dep = new CssIcssExportDependency(
2013
+ name,
2014
+ getReexport(name),
2015
+ [valueStart, end],
2016
+ true,
2017
+ CssIcssExportDependency.EXPORT_MODE.ONCE
2018
+ );
1673
2019
  const { line: sl, column: sc } = locConverter.get(start);
1674
2020
  const { line: el, column: ec } = locConverter.get(end);
1675
2021
  dep.setLoc(sl, sc, el, ec);
@@ -1677,6 +2023,94 @@ class CssParser extends Parser {
1677
2023
  return end;
1678
2024
  };
1679
2025
 
2026
+ /**
2027
+ * @param {string} input input
2028
+ * @param {number} start start position
2029
+ * @param {number} end end position
2030
+ * @returns {number} position after handling
2031
+ */
2032
+ const processClassSelector = (input, start, end) => {
2033
+ const ident = walkCssTokens.skipCommentsAndEatIdentSequence(input, end);
2034
+ if (!ident) return end;
2035
+ const name = unescapeIdentifier(input.slice(ident[0], ident[1]));
2036
+ lastLocalIdentifiers.push(name);
2037
+ const dep = new CssIcssExportDependency(
2038
+ name,
2039
+ getReexport(name),
2040
+ [ident[0], ident[1]],
2041
+ true,
2042
+ CssIcssExportDependency.EXPORT_MODE.ONCE
2043
+ );
2044
+ const { line: sl, column: sc } = locConverter.get(ident[0]);
2045
+ const { line: el, column: ec } = locConverter.get(ident[1]);
2046
+ dep.setLoc(sl, sc, el, ec);
2047
+ module.addDependency(dep);
2048
+ return ident[1];
2049
+ };
2050
+
2051
+ /**
2052
+ * @param {string} input input
2053
+ * @param {number} start start position
2054
+ * @param {number} end end position
2055
+ * @returns {number} position after handling
2056
+ */
2057
+ const processAttributeSelector = (input, start, end) => {
2058
+ end = walkCssTokens.eatWhitespaceAndComments(input, end)[0];
2059
+ const identifier = walkCssTokens.eatIdentSequence(input, end);
2060
+ if (!identifier) return end;
2061
+ const name = unescapeIdentifier(
2062
+ input.slice(identifier[0], identifier[1])
2063
+ );
2064
+ if (name.toLowerCase() !== "class") {
2065
+ return end;
2066
+ }
2067
+ end = walkCssTokens.eatWhitespaceAndComments(input, identifier[1])[0];
2068
+
2069
+ const isTilde = input.charCodeAt(end) === CC_TILDE;
2070
+
2071
+ if (
2072
+ input.charCodeAt(end) !== CC_EQUAL &&
2073
+ input.charCodeAt(end) !== CC_TILDE
2074
+ ) {
2075
+ return end;
2076
+ }
2077
+
2078
+ end += 1;
2079
+
2080
+ if (isTilde) {
2081
+ if (input.charCodeAt(end) !== CC_EQUAL) {
2082
+ return end;
2083
+ }
2084
+
2085
+ end += 1;
2086
+ }
2087
+
2088
+ end = walkCssTokens.eatWhitespaceAndComments(input, end)[0];
2089
+ const value = walkCssTokens.eatIdentSequenceOrString(input, end);
2090
+
2091
+ if (!value) {
2092
+ return end;
2093
+ }
2094
+
2095
+ const classNameStart = value[2] ? value[0] : value[0] + 1;
2096
+ const classNameEnd = value[2] ? value[1] : value[1] - 1;
2097
+ const className = unescapeIdentifier(
2098
+ input.slice(classNameStart, classNameEnd)
2099
+ );
2100
+ const dep = new CssIcssExportDependency(
2101
+ className,
2102
+ getReexport(className),
2103
+ [classNameStart, classNameEnd],
2104
+ true,
2105
+ CssIcssExportDependency.EXPORT_MODE.NONE
2106
+ );
2107
+ const { line: sl, column: sc } = locConverter.get(classNameStart);
2108
+ const { line: el, column: ec } = locConverter.get(classNameEnd);
2109
+ dep.setLoc(sl, sc, el, ec);
2110
+ module.addDependency(dep);
2111
+ return value[2] ? classNameEnd : classNameEnd + 1;
2112
+ };
2113
+
1680
2114
  walkCssTokens(source, 0, {
1681
2115
  comment,
1682
2116
  leftCurlyBracket: (input, start, end) => {
@@ -1722,7 +2156,7 @@ class CssParser extends Parser {
1722
2156
  return end;
1723
2157
  },
1724
2158
  url: (input, start, end, contentStart, contentEnd) => {
1725
- if (!this.url) {
2159
+ if (!this.options.url) {
1726
2160
  return end;
1727
2161
  }
1728
2162
 
@@ -1750,8 +2184,8 @@ class CssParser extends Parser {
1750
2184
  return eatUntilSemi(input, start);
1751
2185
  }
1752
2186
  case "@import": {
1753
- if (!this.import) {
1754
- return eatSemi(input, end);
2187
+ if (!this.options.import) {
2188
+ return eatUntilSemi(input, end);
1755
2189
  }
1756
2190
 
1757
2191
  if (!allowImportAtRule) {
@@ -1772,6 +2206,7 @@ class CssParser extends Parser {
1772
2206
  if (name === "@value") {
1773
2207
  return processAtValue(input, start, end);
1774
2208
  } else if (
2209
+ this.options.animation &&
1775
2210
  OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE.test(name) &&
1776
2211
  isLocalMode()
1777
2212
  ) {
@@ -1779,11 +2214,21 @@ class CssParser extends Parser {
1779
2214
  string: true,
1780
2215
  identifier: true
1781
2216
  });
1782
- } else if (name === "@property" && isLocalMode()) {
2217
+ } else if (
2218
+ this.options.customIdents &&
2219
+ name === "@counter-style" &&
2220
+ isLocalMode()
2221
+ ) {
2222
+ return processLocalAtRule(input, end, {
2223
+ identifier: true
2224
+ });
2225
+ } else if (
2226
+ this.options.container &&
2227
+ name === "@container" &&
2228
+ isLocalMode()
2229
+ ) {
1783
2230
  return processLocalAtRule(input, end, {
1784
- identifier: true,
1785
- dashed: true,
1786
- validate: (name) => name.startsWith("--") && name.length >= 3
2231
+ identifier: /^(none|and|or|not)$/
1787
2232
  });
1788
2233
  } else if (name === "@scope") {
1789
2234
  isNextRulePrelude = true;
@@ -1805,15 +2250,23 @@ class CssParser extends Parser {
1805
2250
  },
1806
2251
  identifier: (input, start, end) => {
1807
2252
  if (isModules) {
1808
- const name = input.slice(start, end);
2253
+ const identifier = input.slice(start, end);
1809
2254
 
1810
- if (icssDefinitions.has(name)) {
1811
- return processICSSSymbol(name, start, end);
2255
+ if (icssDefinitions.has(identifier)) {
2256
+ return processICSSSymbol(identifier, start, end);
2257
+ }
2258
+
2259
+ if (
2260
+ this.options.dashedIdents &&
2261
+ isLocalMode() &&
2262
+ isDashedIdentifier(identifier)
2263
+ ) {
2264
+ return processDashedIdent(input, start, end);
1812
2265
  }
1813
2266
 
1814
2267
  switch (scope) {
1815
2268
  case CSS_MODE_IN_BLOCK: {
1816
- if (isLocalMode()) {
2269
+ if (isModules && !isNextRulePrelude) {
1817
2270
  // Handle only top level values and not inside functions
1818
2271
  return processLocalDeclaration(input, start, end);
1819
2272
  }
@@ -1826,29 +2279,14 @@ class CssParser extends Parser {
1826
2279
  },
1827
2280
  delim: (input, start, end) => {
1828
2281
  if (isNextRulePrelude && isLocalMode()) {
1829
- const ident = walkCssTokens.skipCommentsAndEatIdentSequence(
1830
- input,
1831
- end
1832
- );
1833
- if (!ident) return end;
1834
- const name = unescapeIdentifier(input.slice(ident[0], ident[1]));
1835
- lastLocalIdentifiers.push(name);
1836
- const dep = new CssIcssLocalIdentifierDependency(name, [
1837
- ident[0],
1838
- ident[1]
1839
- ]);
1840
- const { line: sl, column: sc } = locConverter.get(ident[0]);
1841
- const { line: el, column: ec } = locConverter.get(ident[1]);
1842
- dep.setLoc(sl, sc, el, ec);
1843
- module.addDependency(dep);
1844
- return ident[1];
2282
+ return processClassSelector(input, start, end);
1845
2283
  }
1846
2284
 
1847
2285
  return end;
1848
2286
  },
1849
2287
  hash: (input, start, end, isID) => {
1850
2288
  if (isNextRulePrelude && isLocalMode() && isID) {
1851
- return processHashID(input, start, end);
2289
+ return processIdSelector(input, start, end);
1852
2290
  }
1853
2291
 
1854
2292
  return end;
@@ -1883,18 +2321,23 @@ class CssParser extends Parser {
1883
2321
 
1884
2322
  if (isFn && name === "local") {
1885
2323
  // Eat extra whitespace
1886
- const end = walkCssTokens.eatWhitespace(input, ident[1] + 1);
1887
- modeData = "local";
2324
+ const end = walkCssTokens.eatWhitespaceAndComments(
2325
+ input,
2326
+ ident[1] + 1
2327
+ )[0];
2328
+ modeData = LOCAL_MODE;
1888
2329
  const dep = new ConstDependency("", [start, end]);
1889
2330
  module.addPresentationalDependency(dep);
1890
- balanced.push([":local", start, end]);
2331
+ balanced.push([":local", start, end, true]);
1891
2332
  return end;
1892
2333
  } else if (name === "local") {
1893
- modeData = "local";
1894
- // Eat extra whitespace
1895
- end = walkCssTokens.eatWhitespace(input, ident[1]);
2334
+ modeData = LOCAL_MODE;
2335
+ const found = walkCssTokens.eatWhitespaceAndComments(
2336
+ input,
2337
+ ident[1]
2338
+ );
1896
2339
 
1897
- if (ident[1] === end) {
2340
+ if (!found[1]) {
1898
2341
  this._emitWarning(
1899
2342
  state,
1900
2343
  `Missing whitespace after ':local' in '${input.slice(
@@ -1907,23 +2350,30 @@ class CssParser extends Parser {
1907
2350
  );
1908
2351
  }
1909
2352
 
2353
+ end = walkCssTokens.eatWhitespace(input, ident[1]);
1910
2354
  const dep = new ConstDependency("", [start, end]);
1911
2355
  module.addPresentationalDependency(dep);
1912
2356
  return end;
1913
2357
  } else if (isFn && name === "global") {
1914
2358
  // Eat extra whitespace
1915
- const end = walkCssTokens.eatWhitespace(input, ident[1] + 1);
1916
- modeData = "global";
2359
+ const end = walkCssTokens.eatWhitespaceAndComments(
2360
+ input,
2361
+ ident[1] + 1
2362
+ )[0];
2363
+ modeData = GLOBAL_MODE;
1917
2364
  const dep = new ConstDependency("", [start, end]);
1918
2365
  module.addPresentationalDependency(dep);
1919
- balanced.push([":global", start, end]);
2366
+ balanced.push([":global", start, end, true]);
1920
2367
  return end;
1921
2368
  } else if (name === "global") {
1922
- modeData = "global";
2369
+ modeData = GLOBAL_MODE;
1923
2370
  // Eat extra whitespace
1924
- end = walkCssTokens.eatWhitespace(input, ident[1]);
2371
+ const found = walkCssTokens.eatWhitespaceAndComments(
2372
+ input,
2373
+ ident[1]
2374
+ );
1925
2375
 
1926
- if (ident[1] === end) {
2376
+ if (!found[1]) {
1927
2377
  this._emitWarning(
1928
2378
  state,
1929
2379
  `Missing whitespace after ':global' in '${input.slice(
@@ -1936,6 +2386,7 @@ class CssParser extends Parser {
1936
2386
  );
1937
2387
  }
1938
2388
 
2389
+ end = walkCssTokens.eatWhitespace(input, ident[1]);
1939
2390
  const dep = new ConstDependency("", [start, end]);
1940
2391
  module.addPresentationalDependency(dep);
1941
2392
  return end;
@@ -1960,23 +2411,44 @@ class CssParser extends Parser {
1960
2411
  switch (name) {
1961
2412
  case "src":
1962
2413
  case "url": {
1963
- if (!this.url) {
2414
+ if (!this.options.url) {
1964
2415
  return end;
1965
2416
  }
1966
2417
 
1967
2418
  return processURLFunction(input, end, name);
1968
2419
  }
1969
2420
  default: {
1970
- if (this.url && IMAGE_SET_FUNCTION.test(name)) {
2421
+ if (this.options.url && IMAGE_SET_FUNCTION.test(name)) {
1971
2422
  return processImageSetFunction(input, start, end);
1972
- } else if (isLocalMode() && name === "var") {
1973
- return processVarFunction(input, end);
2423
+ }
2424
+
2425
+ if (isModules) {
2426
+ if (
2427
+ this.options.function &&
2428
+ isLocalMode() &&
2429
+ isDashedIdentifier(name)
2430
+ ) {
2431
+ return processDashedIdent(input, start, end);
2432
+ }
2433
+
2434
+ const type =
2435
+ name === "local" ? 1 : name === "global" ? 2 : undefined;
2436
+
2437
+ if (type && !isNextRulePrelude) {
2438
+ return processLocalOrGlobalFunction(input, type, start, end);
2439
+ }
1974
2440
  }
1975
2441
  }
1976
2442
  }
1977
2443
 
1978
2444
  return end;
1979
2445
  },
2446
+ leftSquareBracket: (input, start, end) => {
2447
+ if (isNextRulePrelude && isLocalMode()) {
2448
+ return processAttributeSelector(input, start, end);
2449
+ }
2450
+ return end;
2451
+ },
1980
2452
  leftParenthesis: (input, start, end) => {
1981
2453
  balanced.push(["(", start, end]);
1982
2454
 
@@ -1985,17 +2457,27 @@ class CssParser extends Parser {
1985
2457
  rightParenthesis: (input, start, end) => {
1986
2458
  const popped = balanced.pop();
1987
2459
 
1988
- if (
1989
- isModules &&
1990
- popped &&
1991
- (popped[0] === ":local" || popped[0] === ":global")
1992
- ) {
1993
- modeData = balanced[balanced.length - 1]
1994
- ? /** @type {"local" | "global"} */
1995
- (balanced[balanced.length - 1][0])
1996
- : undefined;
1997
- const dep = new ConstDependency("", [start, end]);
1998
- module.addPresentationalDependency(dep);
2460
+ if (isModules && popped) {
2461
+ const isLocal = popped[0] === ":local";
2462
+ const isGlobal = popped[0] === ":global";
2463
+ if (isLocal || isGlobal) {
2464
+ modeData = balanced[balanced.length - 1]
2465
+ ? balanced[balanced.length - 1][0] === ":local"
2466
+ ? LOCAL_MODE
2467
+ : balanced[balanced.length - 1][0] === ":global"
2468
+ ? GLOBAL_MODE
2469
+ : undefined
2470
+ : undefined;
2471
+ if (popped[3] && isLocal) {
2472
+ while (walkCssTokens.isWhiteSpace(input.charCodeAt(start - 1))) {
2473
+ start -= 1;
2474
+ }
2475
+ }
2476
+ const dep = new ConstDependency("", [start, end]);
2477
+ module.addPresentationalDependency(dep);
2478
+ } else if (isNextRulePrelude) {
2479
+ modeData = undefined;
2480
+ }
1999
2481
  }
2000
2482
 
2001
2483
  return end;
@@ -2021,9 +2503,11 @@ class CssParser extends Parser {
2021
2503
 
2022
2504
  const buildMeta = /** @type {BuildMeta} */ (state.module.buildMeta);
2023
2505
 
2024
- buildMeta.exportsType = this.namedExports ? "namespace" : "default";
2025
- buildMeta.defaultObject = this.namedExports ? false : "redirect-warn";
2026
- buildMeta.exportType = this.exportType;
2506
+ buildMeta.exportsType = this.options.namedExports ? "namespace" : "default";
2507
+ buildMeta.defaultObject = this.options.namedExports
2508
+ ? false
2509
+ : "redirect-warn";
2510
+ buildMeta.exportType = this.options.exportType;
2027
2511
 
2028
2512
  if (!buildMeta.exportType) {
2029
2513
  // Inherit exportType from parent module to ensure consistency.
@@ -2039,6 +2523,9 @@ class CssParser extends Parser {
2039
2523
  ).exportType;
2040
2524
  }
2041
2525
  }
2526
+ if (!buildMeta.exportType) {
2527
+ buildMeta.exportType = "link";
2528
+ }
2042
2529
 
2043
2530
  // TODO this.namedExports?
2044
2531
  if (
@@ -2091,7 +2578,7 @@ class CssParser extends Parser {
2091
2578
  if (comments.length === 0) {
2092
2579
  return EMPTY_COMMENT_OPTIONS;
2093
2580
  }
2094
- /** @type {Record<string, EXPECTED_ANY> } */
2581
+ /** @type {Record<string, EXPECTED_ANY>} */
2095
2582
  const options = {};
2096
2583
  /** @type {(Error & { comment: Comment })[]} */
2097
2584
  const errors = [];