@tbela99/css-parser 1.4.1 → 1.4.3

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 (216) hide show
  1. package/.nyc_output/4874b20e-6f53-4d7a-be5a-cf68316925f2.json +1 -0
  2. package/.nyc_output/6193bc4c-6f5f-4898-8950-c628825e6342.json +1 -0
  3. package/.nyc_output/processinfo/4874b20e-6f53-4d7a-be5a-cf68316925f2.json +1 -0
  4. package/.nyc_output/processinfo/6193bc4c-6f5f-4898-8950-c628825e6342.json +1 -0
  5. package/.repl_history +4 -0
  6. package/CHANGELOG.md +168 -4
  7. package/README.md +82 -0
  8. package/badges/coverage.svg +20 -0
  9. package/deno.lock +2861 -0
  10. package/dist/config.json.js +33 -1
  11. package/dist/index-umd-web.js +24393 -18479
  12. package/dist/index.cjs +27430 -21519
  13. package/dist/index.d.ts +1403 -933
  14. package/dist/lib/ast/clone.d.ts +10 -0
  15. package/dist/lib/ast/clone.js +45 -0
  16. package/dist/lib/ast/expand.d.ts +14 -0
  17. package/dist/lib/ast/expand.js +89 -64
  18. package/dist/lib/ast/features/calc.d.ts +10 -0
  19. package/dist/lib/ast/features/calc.js +62 -24
  20. package/dist/lib/ast/features/if.d.ts +10 -0
  21. package/dist/lib/ast/features/if.js +215 -0
  22. package/dist/lib/ast/features/index.d.ts +6 -0
  23. package/dist/lib/ast/features/index.js +1 -0
  24. package/dist/lib/ast/features/inlinecssvariables.d.ts +15 -0
  25. package/dist/lib/ast/features/inlinecssvariables.js +32 -27
  26. package/dist/lib/ast/features/prefix.d.ts +8 -0
  27. package/dist/lib/ast/features/prefix.js +68 -43
  28. package/dist/lib/ast/features/shorthand.d.ts +12 -0
  29. package/dist/lib/ast/features/shorthand.js +6 -9
  30. package/dist/lib/ast/features/transform.d.ts +10 -0
  31. package/dist/lib/ast/features/transform.js +9 -13
  32. package/dist/lib/ast/features/type.d.ts +15 -0
  33. package/dist/lib/ast/find.d.ts +165 -0
  34. package/dist/lib/ast/find.js +175 -0
  35. package/dist/lib/ast/math/expression.d.ts +18 -0
  36. package/dist/lib/ast/math/expression.js +140 -98
  37. package/dist/lib/ast/math/math.d.ts +6 -0
  38. package/dist/lib/ast/math/math.js +30 -41
  39. package/dist/lib/ast/minify.d.ts +19 -0
  40. package/dist/lib/ast/minify.js +543 -215
  41. package/dist/lib/ast/transform/compute.d.ts +8 -0
  42. package/dist/lib/ast/transform/compute.js +82 -69
  43. package/dist/lib/ast/transform/matrix.d.ts +22 -0
  44. package/dist/lib/ast/transform/matrix.js +12 -26
  45. package/dist/lib/ast/transform/minify.d.ts +5 -0
  46. package/dist/lib/ast/transform/minify.js +20 -20
  47. package/dist/lib/ast/transform/perspective.d.ts +3 -0
  48. package/dist/lib/ast/transform/perspective.js +1 -1
  49. package/dist/lib/ast/transform/rotate.d.ts +12 -0
  50. package/dist/lib/ast/transform/rotate.js +1 -1
  51. package/dist/lib/ast/transform/scale.d.ts +6 -0
  52. package/dist/lib/ast/transform/scale.js +1 -1
  53. package/dist/lib/ast/transform/skew.d.ts +4 -0
  54. package/dist/lib/ast/transform/skew.js +1 -1
  55. package/dist/lib/ast/transform/translate.d.ts +6 -0
  56. package/dist/lib/ast/transform/translate.js +1 -1
  57. package/dist/lib/ast/transform/utils.d.ts +9 -0
  58. package/dist/lib/ast/types.d.ts +903 -0
  59. package/dist/lib/ast/types.js +277 -23
  60. package/dist/lib/ast/walk.d.ts +162 -0
  61. package/dist/lib/ast/walk.js +116 -60
  62. package/dist/lib/fs/resolve.d.ts +20 -0
  63. package/dist/lib/fs/resolve.js +37 -45
  64. package/dist/lib/parser/declaration/list.d.ts +16 -0
  65. package/dist/lib/parser/declaration/list.js +26 -24
  66. package/dist/lib/parser/declaration/map.d.ts +15 -0
  67. package/dist/lib/parser/declaration/map.js +140 -95
  68. package/dist/lib/parser/declaration/set.d.ts +9 -0
  69. package/dist/lib/parser/declaration/set.js +30 -25
  70. package/dist/lib/parser/node.d.ts +7 -0
  71. package/dist/lib/parser/parse.d.ts +107 -0
  72. package/dist/lib/parser/parse.js +1454 -1445
  73. package/dist/lib/parser/tokenize.d.ts +57 -0
  74. package/dist/lib/parser/tokenize.js +557 -404
  75. package/dist/lib/parser/utils/at-rule-container.d.ts +5 -0
  76. package/dist/lib/parser/utils/at-rule-container.js +486 -0
  77. package/dist/lib/parser/utils/at-rule-font-feature-values.d.ts +5 -0
  78. package/dist/lib/parser/utils/at-rule-font-feature-values.js +13 -0
  79. package/dist/lib/parser/utils/at-rule-generic.d.ts +5 -0
  80. package/dist/lib/parser/utils/at-rule-generic.js +118 -0
  81. package/dist/lib/parser/utils/at-rule-import.d.ts +5 -0
  82. package/dist/lib/parser/utils/at-rule-import.js +393 -0
  83. package/dist/lib/parser/utils/at-rule-media.d.ts +5 -0
  84. package/dist/lib/parser/utils/at-rule-media.js +603 -0
  85. package/dist/lib/parser/utils/at-rule-page.d.ts +5 -0
  86. package/dist/lib/parser/utils/at-rule-page.js +28 -0
  87. package/dist/lib/parser/utils/at-rule-support.d.ts +5 -0
  88. package/dist/lib/parser/utils/at-rule-support.js +366 -0
  89. package/dist/lib/parser/utils/at-rule-token.d.ts +1 -0
  90. package/dist/lib/parser/utils/at-rule-when-else.d.ts +5 -0
  91. package/dist/lib/parser/utils/at-rule-when-else.js +363 -0
  92. package/dist/lib/parser/utils/at-rule.d.ts +13 -0
  93. package/dist/lib/parser/utils/at-rule.js +37 -0
  94. package/dist/lib/parser/utils/cache.d.ts +6 -0
  95. package/dist/lib/parser/utils/cache.js +19 -0
  96. package/dist/lib/parser/utils/config.d.ts +2 -0
  97. package/dist/lib/parser/utils/config.js +1 -0
  98. package/dist/lib/parser/utils/declaration-list.d.ts +5 -0
  99. package/dist/lib/parser/utils/declaration.d.ts +18 -0
  100. package/dist/lib/parser/utils/declaration.js +569 -91
  101. package/dist/lib/parser/utils/eq.d.ts +1 -0
  102. package/dist/lib/parser/utils/hash.d.ts +21 -0
  103. package/dist/lib/parser/utils/hash.js +1 -1
  104. package/dist/lib/parser/utils/selector.d.ts +5 -0
  105. package/dist/lib/parser/utils/selector.js +476 -0
  106. package/dist/lib/parser/utils/text.d.ts +3 -0
  107. package/dist/lib/parser/utils/text.js +17 -1
  108. package/dist/lib/parser/utils/token.d.ts +14 -0
  109. package/dist/lib/parser/utils/token.js +102 -0
  110. package/dist/lib/parser/utils/type.d.ts +2 -0
  111. package/dist/lib/parser/utils/type.js +29 -18
  112. package/dist/lib/renderer/render.d.ts +28 -0
  113. package/dist/lib/renderer/render.js +421 -262
  114. package/dist/lib/renderer/sourcemap/lib/encode.d.ts +1 -0
  115. package/dist/lib/renderer/sourcemap/sourcemap.d.ts +26 -0
  116. package/dist/lib/renderer/sourcemap/sourcemap.js +17 -7
  117. package/dist/lib/syntax/color/a98rgb.d.ts +2 -0
  118. package/dist/lib/syntax/color/a98rgb.js +8 -12
  119. package/dist/lib/syntax/color/cmyk.d.ts +10 -0
  120. package/dist/lib/syntax/color/cmyk.js +23 -21
  121. package/dist/lib/syntax/color/color-mix.d.ts +2 -0
  122. package/dist/lib/syntax/color/color-mix.js +88 -77
  123. package/dist/lib/syntax/color/color.d.ts +42 -0
  124. package/dist/lib/syntax/color/color.js +65 -68
  125. package/dist/lib/syntax/color/hex.d.ts +16 -0
  126. package/dist/lib/syntax/color/hex.js +27 -31
  127. package/dist/lib/syntax/color/hsl.d.ts +20 -0
  128. package/dist/lib/syntax/color/hsl.js +5 -12
  129. package/dist/lib/syntax/color/hsv.d.ts +2 -0
  130. package/dist/lib/syntax/color/hwb.d.ts +21 -0
  131. package/dist/lib/syntax/color/hwb.js +8 -21
  132. package/dist/lib/syntax/color/lab.d.ts +25 -0
  133. package/dist/lib/syntax/color/lab.js +20 -21
  134. package/dist/lib/syntax/color/lch.d.ts +23 -0
  135. package/dist/lib/syntax/color/lch.js +13 -15
  136. package/dist/lib/syntax/color/oklab.d.ts +22 -0
  137. package/dist/lib/syntax/color/oklab.js +20 -39
  138. package/dist/lib/syntax/color/oklch.d.ts +20 -0
  139. package/dist/lib/syntax/color/oklch.js +14 -16
  140. package/dist/lib/syntax/color/p3.d.ts +6 -0
  141. package/dist/lib/syntax/color/p3.js +0 -8
  142. package/dist/lib/syntax/color/prophotorgb.d.ts +2 -0
  143. package/dist/lib/syntax/color/rec2020.d.ts +2 -0
  144. package/dist/lib/syntax/color/rec2020.js +9 -13
  145. package/dist/lib/syntax/color/relativecolor.d.ts +13 -0
  146. package/dist/lib/syntax/color/relativecolor.js +68 -41
  147. package/dist/lib/syntax/color/rgb.d.ts +20 -0
  148. package/dist/lib/syntax/color/rgb.js +14 -18
  149. package/dist/lib/syntax/color/srgb.d.ts +23 -0
  150. package/dist/lib/syntax/color/srgb.js +27 -26
  151. package/dist/lib/syntax/color/utils/components.d.ts +2 -0
  152. package/dist/lib/syntax/color/utils/components.js +30 -14
  153. package/dist/lib/syntax/color/utils/distance.d.ts +18 -0
  154. package/dist/lib/syntax/color/utils/distance.js +1 -8
  155. package/dist/lib/syntax/color/utils/matrix.d.ts +6 -0
  156. package/dist/lib/syntax/color/xyz.d.ts +5 -0
  157. package/dist/lib/syntax/color/xyz.js +8 -20
  158. package/dist/lib/syntax/color/xyzd50.d.ts +4 -0
  159. package/dist/lib/syntax/color/xyzd50.js +6 -20
  160. package/dist/lib/syntax/constants.d.ts +67 -0
  161. package/dist/lib/syntax/constants.js +436 -0
  162. package/dist/lib/syntax/syntax.d.ts +38 -0
  163. package/dist/lib/syntax/syntax.js +533 -568
  164. package/dist/lib/validation/config.d.ts +14 -0
  165. package/dist/lib/validation/config.js +72 -33
  166. package/dist/lib/validation/config.json.js +1159 -74
  167. package/dist/lib/validation/json.d.ts +2 -0
  168. package/dist/lib/validation/match.d.ts +38 -0
  169. package/dist/lib/validation/match.js +2985 -0
  170. package/dist/lib/validation/parser/parse.d.ts +8 -0
  171. package/dist/lib/validation/parser/parse.js +684 -935
  172. package/dist/lib/validation/parser/typedef.d.ts +95 -0
  173. package/dist/lib/validation/parser/typedef.js +100 -0
  174. package/dist/lib/validation/utils/list.d.ts +4 -0
  175. package/dist/lib/validation/utils/list.js +4 -11
  176. package/dist/lib/validation/utils/whitespace.d.ts +2 -0
  177. package/dist/lib/validation/utils/whitespace.js +2 -8
  178. package/dist/node.d.ts +207 -0
  179. package/dist/node.js +53 -47
  180. package/dist/web.d.ts +169 -0
  181. package/dist/web.js +50 -41
  182. package/package.json +18 -13
  183. package/playground/index.html +1328 -0
  184. package/playground/sw.js +55 -0
  185. package/playground/tree.js +176 -0
  186. package/dist/lib/syntax/color/utils/constants.js +0 -214
  187. package/dist/lib/syntax/utils.js +0 -70
  188. package/dist/lib/validation/at-rules/container.js +0 -342
  189. package/dist/lib/validation/at-rules/counter-style.js +0 -90
  190. package/dist/lib/validation/at-rules/custom-media.js +0 -50
  191. package/dist/lib/validation/at-rules/document.js +0 -89
  192. package/dist/lib/validation/at-rules/else.js +0 -5
  193. package/dist/lib/validation/at-rules/font-feature-values.js +0 -63
  194. package/dist/lib/validation/at-rules/import.js +0 -150
  195. package/dist/lib/validation/at-rules/keyframes.js +0 -67
  196. package/dist/lib/validation/at-rules/layer.js +0 -41
  197. package/dist/lib/validation/at-rules/media.js +0 -255
  198. package/dist/lib/validation/at-rules/namespace.js +0 -81
  199. package/dist/lib/validation/at-rules/page-margin-box.js +0 -64
  200. package/dist/lib/validation/at-rules/page.js +0 -100
  201. package/dist/lib/validation/at-rules/supports.js +0 -295
  202. package/dist/lib/validation/at-rules/when.js +0 -185
  203. package/dist/lib/validation/atrule.js +0 -184
  204. package/dist/lib/validation/selector.js +0 -36
  205. package/dist/lib/validation/syntax.js +0 -1073
  206. package/dist/lib/validation/syntaxes/complex-selector-list.js +0 -27
  207. package/dist/lib/validation/syntaxes/complex-selector.js +0 -52
  208. package/dist/lib/validation/syntaxes/compound-selector.js +0 -196
  209. package/dist/lib/validation/syntaxes/family-name.js +0 -57
  210. package/dist/lib/validation/syntaxes/keyframe-selector.js +0 -36
  211. package/dist/lib/validation/syntaxes/layer-name.js +0 -57
  212. package/dist/lib/validation/syntaxes/relative-selector-list.js +0 -31
  213. package/dist/lib/validation/syntaxes/relative-selector.js +0 -38
  214. package/dist/lib/validation/syntaxes/selector-list.js +0 -5
  215. package/dist/lib/validation/syntaxes/selector.js +0 -5
  216. package/dist/lib/validation/syntaxes/url.js +0 -40
@@ -1,77 +1,81 @@
1
- import { isIdentStart, isIdent, isIdentColor, mathFuncs, isColor, parseColor, isPseudo, pseudoElements, isAtKeyword, isFunction, isNumber, isPercentage, parseDimension, isHexColor, isHash, mediaTypes } from '../syntax/syntax.js';
2
- import { EnumToken, ColorType, ValidationLevel, ModuleCaseTransformEnum, ModuleScopeEnumOptions, SyntaxValidationResult } from '../ast/types.js';
3
- import { definedPropertySettings, minify, combinators } from '../ast/minify.js';
4
- import { walkValues, WalkerEvent, walk, WalkerOptionEnum } from '../ast/walk.js';
5
- import { expand } from '../ast/expand.js';
6
- import './utils/config.js';
7
- import { parseDeclarationNode } from './utils/declaration.js';
8
- import { camelize, dasherize } from './utils/text.js';
1
+ import { isIdentColor, isIdentStart, isIdent, isColor, parseColor } from '../syntax/syntax.js';
2
+ import { camelize, equalsIgnoreCase, dasherize } from './utils/text.js';
9
3
  import { renderToken } from '../renderer/render.js';
10
- import '../renderer/sourcemap/lib/encode.js';
11
- import { funcLike, timingFunc, timelineFunc, COLORS_NAMES, systemColors, deprecatedSystemColors, colorsFunc } from '../syntax/color/utils/constants.js';
12
- import { buildExpression } from '../ast/math/expression.js';
4
+ import { EnumToken, ValidationLevel, ModuleCaseTransformEnum, ModuleScopeEnumOptions } from '../ast/types.js';
5
+ import { minify } from '../ast/minify.js';
6
+ import { expand } from '../ast/expand.js';
7
+ import { WalkerEvent, walk, walkValues } from '../ast/walk.js';
13
8
  import { tokenize, tokenizeStream } from './tokenize.js';
14
- import '../validation/config.js';
15
- import '../validation/parser/parse.js';
16
- import { validateSelector } from '../validation/selector.js';
17
- import { validateAtRule } from '../validation/atrule.js';
9
+ import { definedPropertySettings, tokensfuncDefMap, funcLike, mathFuncs, urlTokenMatcher, pageMarginBoxType } from '../syntax/constants.js';
18
10
  import { splitTokenList } from '../validation/utils/list.js';
19
- import '../validation/syntaxes/complex-selector.js';
20
- import { validateKeyframeSelector } from '../validation/syntaxes/keyframe-selector.js';
21
- import { isNodeAllowedInContext, evaluateSyntax } from '../validation/syntax.js';
22
- import { validateAtRuleKeyframes } from '../validation/at-rules/keyframes.js';
11
+ import { buildExpression } from '../ast/math/expression.js';
23
12
  import { hashAlgorithms, hash } from './utils/hash.js';
13
+ import { parseSelector } from './utils/selector.js';
14
+ import { parseDeclaration } from './utils/declaration.js';
15
+ import { getSyntaxRule } from '../validation/config.js';
16
+ import { matchSelectorSyntax, trimArray, matchAllSyntax, createValidationContext } from '../validation/match.js';
17
+ import { ValidationSyntaxGroupEnum } from '../validation/parser/typedef.js';
18
+ import { matchAtRuleImportSyntax } from './utils/at-rule-import.js';
19
+ import { matchAtRuleWhenElseSyntax } from './utils/at-rule-when-else.js';
20
+ import { parseAtRuleSupportSyntax } from './utils/at-rule-support.js';
21
+ import { replaceToken, trimWhiteSpaceTokens } from './utils/token.js';
22
+ import { parseAtRuleContainerQueryList } from './utils/at-rule-container.js';
23
+ import { parseMediaqueryList } from './utils/at-rule-media.js';
24
+ import { matchAtRuleSyntax } from './utils/at-rule.js';
25
+ import { parseAtRulePage } from './utils/at-rule-page.js';
26
+ import { parseAtRuleFontFeatureValues } from './utils/at-rule-font-feature-values.js';
27
+ import { matchGenericSyntax } from './utils/at-rule-generic.js';
28
+ import { memoize } from './utils/cache.js';
24
29
 
25
- const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
26
- const trimWhiteSpace = [EnumToken.CommentTokenType, EnumToken.GtTokenType, EnumToken.GteTokenType, EnumToken.LtTokenType, EnumToken.LteTokenType, EnumToken.ColumnCombinatorTokenType];
30
+ function renderTokens(tokens, options) {
31
+ if (tokens == null || tokens.length === 0)
32
+ return "";
33
+ if (options != null)
34
+ return tokens.map((t) => renderToken(t, options)).join("");
35
+ return tokens.map((t) => renderToken(t)).join("");
36
+ }
37
+ const trimWhiteSpace = [
38
+ EnumToken.CommentTokenType,
39
+ EnumToken.GtTokenType,
40
+ EnumToken.GteTokenType,
41
+ EnumToken.LtTokenType,
42
+ EnumToken.LteTokenType,
43
+ EnumToken.ColumnCombinatorTokenType,
44
+ ];
27
45
  const BadTokensTypes = [
28
46
  EnumToken.BadCommentTokenType,
29
47
  EnumToken.BadCdoTokenType,
30
48
  EnumToken.BadUrlTokenType,
31
- EnumToken.BadStringTokenType
49
+ EnumToken.BadStringTokenType,
32
50
  ];
33
- const enumTokenHints = new Set([
34
- EnumToken.WhitespaceTokenType, EnumToken.SemiColonTokenType, EnumToken.ColonTokenType, EnumToken.BlockStartTokenType,
35
- EnumToken.BlockStartTokenType, EnumToken.AttrStartTokenType, EnumToken.AttrEndTokenType, EnumToken.StartParensTokenType, EnumToken.EndParensTokenType,
36
- EnumToken.CommaTokenType, EnumToken.GtTokenType, EnumToken.LtTokenType, EnumToken.GteTokenType, EnumToken.LteTokenType, EnumToken.CommaTokenType,
37
- EnumToken.StartMatchTokenType, EnumToken.EndMatchTokenType, EnumToken.IncludeMatchTokenType, EnumToken.DashMatchTokenType, EnumToken.ContainMatchTokenType,
38
- EnumToken.EOFTokenType
39
- ]);
40
- function reject(reason) {
41
- throw new Error(reason ?? 'Parsing aborted');
42
- }
51
+ let keyNameCounter = 0;
52
+ let keyNameCache = {};
53
+ const forbiddenStartCharacters = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"].map((c) => c.charCodeAt(0));
43
54
  /**
44
- * replace token in its parent node
45
- * @param parent
46
- * @param value
47
- * @param replacement
55
+ * short-scoped name generator.
56
+ *
57
+ * @param localName
58
+ * @param filePath
59
+ * @param pattern
60
+ * @param hashLength
61
+ *
62
+ * @returns string
48
63
  */
49
- function replaceToken(parent, value, replacement) {
50
- for (const node of (Array.isArray(replacement) ? replacement : [replacement])) {
51
- if ('parent' in value && value.parent != node.parent) {
52
- Object.defineProperty(node, 'parent', {
53
- ...definedPropertySettings,
54
- value: value.parent
55
- });
56
- }
57
- }
58
- if (parent.typ == EnumToken.BinaryExpressionTokenType) {
59
- if (parent.l == value) {
60
- parent.l = replacement;
61
- }
62
- else {
63
- parent.r = replacement;
64
- }
64
+ const getShortNameGenerator = memoize((localName, filePath, pattern, hashLength = 5) => {
65
+ const key = `${localName}_${filePath}_${pattern}_${hashLength}`;
66
+ if (key in keyNameCache) {
67
+ return keyNameCache[key];
65
68
  }
66
- else {
67
- const target = 'val' in parent && Array.isArray(parent.val) ? parent.val : parent.chi;
68
- // @ts-ignore
69
- const index = target.indexOf(value);
70
- if (index == -1) {
71
- return;
72
- }
73
- target.splice(index, 1, ...(Array.isArray(replacement) ? replacement : [replacement]));
69
+ let value = keyNameCounter.toString(36);
70
+ keyNameCounter++;
71
+ while (forbiddenStartCharacters.includes(value.charCodeAt(0))) {
72
+ value = keyNameCounter.toString(36);
73
+ keyNameCounter++;
74
74
  }
75
+ return (keyNameCache[key] = value);
76
+ });
77
+ function reject(reason) {
78
+ throw new Error(reason ?? "Parsing aborted");
75
79
  }
76
80
  /**
77
81
  * transform case of key name
@@ -81,7 +85,7 @@ function replaceToken(parent, value, replacement) {
81
85
  * @throws Error
82
86
  * @private
83
87
  */
84
- function getKeyName(key, how) {
88
+ const getKeyName = memoize((key, how) => {
85
89
  switch (how) {
86
90
  case ModuleCaseTransformEnum.CamelCase:
87
91
  case ModuleCaseTransformEnum.CamelCaseOnly:
@@ -91,7 +95,7 @@ function getKeyName(key, how) {
91
95
  return dasherize(key);
92
96
  }
93
97
  return key;
94
- }
98
+ });
95
99
  /**
96
100
  * generate scoped name
97
101
  * @param localName
@@ -102,46 +106,46 @@ function getKeyName(key, how) {
102
106
  * @throws Error
103
107
  * @private
104
108
  */
105
- async function generateScopedName(localName, filePath, pattern, hashLength = 5) {
106
- if (localName.startsWith('--')) {
109
+ const generateScopedName = memoize(async (localName, filePath, pattern, hashLength = 5) => {
110
+ if (localName.startsWith("--")) {
107
111
  localName = localName.slice(2);
108
112
  }
109
113
  const matches = /.*?(([^/]+)\/)?([^/\\]*?)(\.([^?/]+))?([?].*)?$/.exec(filePath);
110
- const folder = matches?.[2]?.replace?.(/[^A-Za-z0-9_-]/g, "_") ?? '';
111
- const fileBase = matches?.[3] ?? '';
112
- const ext = matches?.[5] ?? '';
114
+ const folder = matches?.[2]?.replace?.(/[^A-Za-z0-9_-]/g, "_") ?? "";
115
+ const fileBase = matches?.[3] ?? "";
116
+ const ext = matches?.[5] ?? "";
113
117
  const path = filePath.replace(/[^A-Za-z0-9_-]/g, "_");
114
118
  // sanitize localName for safe char set (replace spaces/illegal chars)
115
119
  const safeLocal = localName.replace(/[^A-Za-z0-9_-]/g, "_");
116
120
  const hashString = `${localName}::${filePath}`;
117
- let result = '';
121
+ let result = "";
118
122
  let inParens = 0;
119
- let key = '';
123
+ let key = "";
120
124
  let position = 0;
121
- // Compose final scoped name. Ensure the entire class doesn't start with digit:
125
+ // Compose final scoped name. Ensure the entire class doesn't start with a digit:
122
126
  for (const char of pattern) {
123
127
  position += char.length;
124
- if (char == '[') {
128
+ if (char == "[") {
125
129
  inParens++;
126
130
  if (inParens != 1) {
127
131
  throw new Error(`Unexpected character: '${char} at position ${position - 1}' in pattern '${pattern}'`);
128
132
  }
129
133
  continue;
130
134
  }
131
- if (char == ']') {
135
+ if (char == "]") {
132
136
  inParens--;
133
137
  if (inParens != 0) {
134
138
  throw new Error(`Unexpected character: '${char}:${position - 1}'`);
135
139
  }
136
140
  let hashAlgo = null;
137
141
  let length = null;
138
- if (key.includes(':')) {
139
- const parts = key.split(':');
142
+ if (key.includes(":")) {
143
+ const parts = key.split(":");
140
144
  if (parts.length == 2) {
141
145
  // @ts-ignore
142
146
  [key, length] = parts;
143
147
  // @ts-ignore
144
- if (key == 'hash' && hashAlgorithms.includes(length)) {
148
+ if (key == "hash" && hashAlgorithms.includes(length)) {
145
149
  // @ts-ignore
146
150
  hashAlgo = length;
147
151
  length = null;
@@ -155,29 +159,35 @@ async function generateScopedName(localName, filePath, pattern, hashLength = 5)
155
159
  throw new Error(`Unsupported hash length: '${length}'. expecting format [hash:length] or [hash:hash-algo:length]`);
156
160
  }
157
161
  }
162
+ const slice = length != null && length != fileBase.length;
158
163
  switch (key) {
159
- case 'hash':
164
+ case "hash":
160
165
  result += await hash(hashString, length ?? hashLength, hashAlgo);
161
166
  break;
162
- case 'name':
163
- result += length != null ? fileBase.slice(0, +length) : fileBase;
167
+ case "name":
168
+ // @ts-expect-error
169
+ result += slice ? fileBase.slice(0, +length) : fileBase;
164
170
  break;
165
- case 'local':
166
- result += length != null ? safeLocal.slice(0, +length) : localName;
171
+ case "local":
172
+ // @ts-expect-error
173
+ result += slice ? safeLocal.slice(0, +length) : localName;
167
174
  break;
168
- case 'ext':
169
- result += length != null ? ext.slice(0, +length) : ext;
175
+ case "ext":
176
+ // @ts-expect-error
177
+ result += slice ? ext.slice(0, +length) : ext;
170
178
  break;
171
- case 'path':
172
- result += length != null ? path.slice(0, +length) : path;
179
+ case "path":
180
+ // @ts-expect-error
181
+ result += slice ? path.slice(0, +length) : path;
173
182
  break;
174
- case 'folder':
175
- result += length != null ? folder.slice(0, +length) : folder;
183
+ case "folder":
184
+ // @ts-expect-error
185
+ result += slice ? folder.slice(0, +length) : folder;
176
186
  break;
177
187
  default:
178
188
  throw new Error(`Unsupported key: '${key}'`);
179
189
  }
180
- key = '';
190
+ key = "";
181
191
  continue;
182
192
  }
183
193
  if (inParens > 0) {
@@ -188,8 +198,8 @@ async function generateScopedName(localName, filePath, pattern, hashLength = 5)
188
198
  }
189
199
  }
190
200
  // if leading char is digit, prefix underscore (very rare)
191
- return (/^[0-9]/.test(result) ? '_' : '') + result;
192
- }
201
+ return (/^[0-9]/.test(result) ? "_" : "") + result;
202
+ });
193
203
  /**
194
204
  * parse css string
195
205
  * @param iter
@@ -200,13 +210,14 @@ async function generateScopedName(localName, filePath, pattern, hashLength = 5)
200
210
  */
201
211
  async function doParse(iter, options = {}) {
202
212
  if (options.signal != null) {
203
- options.signal.addEventListener('abort', reject);
213
+ options.signal.addEventListener("abort", reject);
204
214
  }
205
215
  options = {
206
- src: '',
216
+ src: "",
207
217
  sourcemap: false,
208
218
  minify: true,
209
219
  pass: 1,
220
+ expandIfSyntax: false,
210
221
  parseColor: true,
211
222
  nestingRules: true,
212
223
  resolveImport: false,
@@ -222,9 +233,9 @@ async function doParse(iter, options = {}) {
222
233
  removePrefix: false,
223
234
  validation: ValidationLevel.Default,
224
235
  lenient: true,
225
- ...options
236
+ ...options,
226
237
  };
227
- if (typeof options.validation == 'boolean') {
238
+ if (typeof options.validation == "boolean") {
228
239
  options.validation = options.validation ? ValidationLevel.All : ValidationLevel.None;
229
240
  }
230
241
  if (options.module) {
@@ -241,36 +252,36 @@ async function doParse(iter, options = {}) {
241
252
  const src = options.src;
242
253
  const stack = [];
243
254
  const stats = {
244
- src: options.src ?? '',
255
+ src: options.src ?? "",
245
256
  bytesIn: 0,
246
257
  nodesCount: 0,
247
258
  tokensCount: 0,
248
259
  importedBytesIn: 0,
260
+ tokenize: `0ms`,
249
261
  parse: `0ms`,
250
262
  minify: `0ms`,
251
263
  total: `0ms`,
252
- imports: []
264
+ imports: [],
253
265
  };
254
266
  let ast = {
255
267
  typ: EnumToken.StyleSheetNodeType,
256
- chi: []
268
+ chi: [],
257
269
  };
258
270
  let tokens = [];
259
- let map = new Map;
260
271
  let context = ast;
261
272
  if (options.sourcemap) {
262
273
  ast.loc = {
263
274
  sta: {
264
275
  ind: 0,
265
276
  lin: 1,
266
- col: 1
277
+ col: 1,
267
278
  },
268
279
  end: {
269
280
  ind: 0,
270
281
  lin: 1,
271
- col: 1
282
+ col: 1,
272
283
  },
273
- src: ''
284
+ src: "",
274
285
  };
275
286
  }
276
287
  let valuesHandlers;
@@ -279,19 +290,19 @@ async function doParse(iter, options = {}) {
279
290
  let preVisitorsHandlersMap;
280
291
  let visitorsHandlersMap;
281
292
  let postVisitorsHandlersMap;
282
- const rawTokens = [];
283
293
  const imports = [];
284
294
  let item;
285
295
  let node;
286
296
  // @ts-ignore ignore error
287
- let isAsync = typeof iter[Symbol.asyncIterator] === 'function';
297
+ let isAsync = typeof iter[Symbol.asyncIterator] === "function";
298
+ let parensMatch = 0;
288
299
  if (options.visitor != null) {
289
- valuesHandlers = new Map;
290
- preValuesHandlers = new Map;
291
- postValuesHandlers = new Map;
292
- preVisitorsHandlersMap = new Map;
293
- visitorsHandlersMap = new Map;
294
- postVisitorsHandlersMap = new Map;
300
+ valuesHandlers = new Map();
301
+ preValuesHandlers = new Map();
302
+ postValuesHandlers = new Map();
303
+ preVisitorsHandlersMap = new Map();
304
+ visitorsHandlersMap = new Map();
305
+ postVisitorsHandlersMap = new Map();
295
306
  const visitors = Object.entries(options.visitor);
296
307
  let key;
297
308
  let value;
@@ -309,181 +320,195 @@ async function doParse(iter, options = {}) {
309
320
  continue;
310
321
  }
311
322
  if (key in EnumToken) {
312
- if (typeof value == 'function') {
323
+ if (typeof value == "function") {
313
324
  if (!valuesHandlers.has(EnumToken[key])) {
314
325
  valuesHandlers.set(EnumToken[key], []);
315
326
  }
316
327
  valuesHandlers.get(EnumToken[key]).push(value);
317
328
  }
318
- else if (typeof value == 'object' && 'type' in value && 'handler' in value && value.type in WalkerEvent) {
329
+ else if (typeof value == "object" &&
330
+ "type" in value &&
331
+ "handler" in value &&
332
+ value.type in WalkerEvent) {
319
333
  if (value.type == WalkerEvent.Enter) {
320
334
  if (!preValuesHandlers.has(EnumToken[key])) {
321
335
  preValuesHandlers.set(EnumToken[key], []);
322
336
  }
323
- preValuesHandlers.get(EnumToken[key]).push(value.handler);
337
+ preValuesHandlers
338
+ .get(EnumToken[key])
339
+ .push(value.handler);
324
340
  }
325
341
  else if (value.type == WalkerEvent.Leave) {
326
342
  if (!postValuesHandlers.has(EnumToken[key])) {
327
343
  postValuesHandlers.set(EnumToken[key], []);
328
344
  }
329
- postValuesHandlers.get(EnumToken[key]).push(value.handler);
345
+ postValuesHandlers
346
+ .get(EnumToken[key])
347
+ .push(value.handler);
330
348
  }
331
349
  }
332
350
  else {
333
- errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
351
+ errors.push({ action: "ignore", message: `doParse: visitor.${key} is not a valid key name` });
334
352
  }
335
353
  }
336
- else if (['Declaration', 'Rule', 'AtRule', 'KeyframesRule', 'KeyframesAtRule'].includes(key)) {
337
- if (typeof value == 'function') {
354
+ else if (["Declaration", "Rule", "AtRule", "KeyframesRule", "KeyframesAtRule"].includes(key)) {
355
+ if (typeof value == "function") {
338
356
  if (!visitorsHandlersMap.has(key)) {
339
357
  visitorsHandlersMap.set(key, []);
340
358
  }
341
- visitorsHandlersMap.get(key).push(value);
359
+ visitorsHandlersMap
360
+ .get(key)
361
+ .push(value);
342
362
  }
343
- else if (typeof value == 'object') {
344
- if ('type' in value && 'handler' in value && value.type in WalkerEvent) {
363
+ else if (typeof value == "object") {
364
+ if ("type" in value && "handler" in value && value.type in WalkerEvent) {
345
365
  if (value.type == WalkerEvent.Enter) {
346
366
  if (!preVisitorsHandlersMap.has(key)) {
347
367
  preVisitorsHandlersMap.set(key, []);
348
368
  }
349
- preVisitorsHandlersMap.get(key).push(value.handler);
369
+ preVisitorsHandlersMap
370
+ .get(key)
371
+ .push(value.handler);
350
372
  }
351
373
  else if (value.type == WalkerEvent.Leave) {
352
374
  if (!postVisitorsHandlersMap.has(key)) {
353
375
  postVisitorsHandlersMap.set(key, []);
354
376
  }
355
- postVisitorsHandlersMap.get(key).push(value.handler);
377
+ postVisitorsHandlersMap
378
+ .get(key)
379
+ .push(value.handler);
356
380
  }
357
381
  }
358
382
  else {
359
383
  if (!visitorsHandlersMap.has(key)) {
360
384
  visitorsHandlersMap.set(key, []);
361
385
  }
362
- visitorsHandlersMap.get(key).push(value);
386
+ visitorsHandlersMap
387
+ .get(key)
388
+ .push(value);
363
389
  }
364
390
  }
365
391
  else {
366
- errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
392
+ errors.push({ action: "ignore", message: `doParse: visitor.${key} is not a valid key name` });
367
393
  }
368
394
  }
369
395
  else {
370
- errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
396
+ errors.push({ action: "ignore", message: `doParse: visitor.${key} is not a valid key name` });
371
397
  }
372
398
  }
373
399
  }
374
- while (item = isAsync ? (await iter.next()).value : iter.next().value) {
400
+ if (Array.isArray(iter)) {
401
+ // @ts-expect-error
402
+ iter = iter[Symbol.iterator]();
403
+ }
404
+ while ((item = isAsync
405
+ ? // @ts-expect-error
406
+ (await iter.next()).value
407
+ : // @ts-expect-error
408
+ iter.next().value)) {
375
409
  stats.bytesIn = item.bytesIn;
376
410
  stats.tokensCount++;
377
- rawTokens.push(item);
378
- if (item.hint != null && BadTokensTypes.includes(item.hint)) {
379
- const node = getTokenType(item.token, item.hint);
411
+ if (options.sourcemap !== false) {
412
+ Object.defineProperty(item.token, "loc", {
413
+ ...definedPropertySettings,
414
+ value: item.token.loc,
415
+ enumerable: true,
416
+ });
417
+ }
418
+ if (BadTokensTypes.includes(item.token.typ)) {
419
+ tokens.push(item.token);
380
420
  errors.push({
381
- action: 'drop',
382
- message: 'Bad token',
421
+ action: "drop",
422
+ message: "Bad token",
383
423
  syntax: null,
384
- node,
385
- location: {
386
- src,
387
- sta: item.sta,
388
- end: item.end
389
- }
424
+ node: item.token,
425
+ location: item.token.loc,
390
426
  });
391
427
  // bad token
392
428
  continue;
393
429
  }
394
- if (item.hint != EnumToken.EOFTokenType) {
395
- tokens.push(item);
430
+ if (item.token.typ === EnumToken.StartParensTokenType || tokensfuncDefMap.has(item.token.typ)) {
431
+ parensMatch++;
396
432
  }
397
- else if (ast.loc != null) {
398
- for (let i = stack.length - 1; i >= 0; i--) {
399
- stack[i].loc.end = { ...item.end };
400
- }
401
- ast.loc.end = item.end;
433
+ else if (item.token.typ === EnumToken.EndParensTokenType && parensMatch > 0) {
434
+ parensMatch--;
402
435
  }
403
- if (item.token == ';' || item.token == '{') {
404
- node = parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
405
- rawTokens.length = 0;
436
+ tokens.push(item.token);
437
+ if ((parensMatch === 0 &&
438
+ (item.token.typ === EnumToken.SemiColonTokenType ||
439
+ item.token.typ === EnumToken.BlockStartTokenType)) ||
440
+ item.token.typ === EnumToken.EOFTokenType) {
441
+ node = parseNode(tokens, context, options, errors, stats);
406
442
  if (node != null) {
407
- if ('chi' in node) {
443
+ if ("chi" in node) {
408
444
  stack.push(node);
409
445
  context = node;
410
446
  }
411
- else if (node.typ == EnumToken.AtRuleNodeType && node.nam == 'import') {
447
+ else if (node.typ == EnumToken.AtRuleNodeType && node.nam === "import") {
412
448
  imports.push(node);
413
449
  }
414
450
  }
415
- else if (item.token == '{') {
451
+ else if (item.token.typ == EnumToken.BlockStartTokenType) {
416
452
  let inBlock = 1;
417
- tokens = [item];
453
+ tokens = [item.token];
418
454
  do {
419
- item = isAsync ? (await iter.next()).value : iter.next().value;
455
+ item = isAsync
456
+ ? // @ts-expect-error
457
+ (await iter.next()).value
458
+ : // @ts-expect-error
459
+ iter.next().value;
420
460
  if (item == null) {
421
461
  break;
422
462
  }
423
- tokens.push(item);
424
- if (item.token == '{') {
463
+ tokens.push(item.token);
464
+ if (item.token.typ === EnumToken.BlockStartTokenType) {
425
465
  inBlock++;
426
466
  }
427
- else if (item.token == '}') {
467
+ else if (item.token.typ === EnumToken.BlockEndTokenType) {
428
468
  inBlock--;
429
469
  }
430
470
  } while (inBlock != 0);
431
471
  if (tokens.length > 0) {
432
472
  errors.push({
433
- action: 'drop',
434
- message: 'invalid block',
435
- rawTokens: tokens.slice(),
473
+ action: "drop",
474
+ message: "invalid block",
436
475
  location: {
437
476
  src,
438
- sta: tokens[0].sta,
439
- end: tokens[tokens.length - 1].end
440
- }
477
+ sta: tokens[0].loc.sta,
478
+ end: tokens[tokens.length - 1].loc.end,
479
+ },
441
480
  });
442
481
  }
443
482
  }
444
483
  tokens = [];
445
- map = new Map;
446
484
  }
447
- else if (item.token == '}') {
448
- parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
449
- rawTokens.length = 0;
485
+ else if (item.token.typ === EnumToken.BlockEndTokenType) {
486
+ parseNode(tokens, context, options, errors, stats);
450
487
  if (context.loc != null) {
451
- context.loc.end = item.end;
488
+ context.loc.end = item.token.loc.end;
452
489
  }
453
490
  const previousNode = stack.pop();
454
491
  context = (stack[stack.length - 1] ?? ast);
455
- if (previousNode != null && previousNode.typ == EnumToken.InvalidRuleTokenType) {
456
- const index = context.chi.findIndex(node => node == previousNode);
457
- if (index > -1) {
458
- context.chi.splice(index, 1);
459
- }
460
- }
461
- if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
492
+ if (options.removeEmpty &&
493
+ previousNode != null &&
494
+ previousNode.chi.length == 0 &&
495
+ context.chi[context.chi.length - 1] == previousNode) {
462
496
  context.chi.pop();
463
497
  }
464
498
  tokens = [];
465
- map = new Map;
466
499
  }
467
500
  }
468
501
  if (tokens.length > 0) {
469
- node = parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
470
- rawTokens.length = 0;
502
+ node = parseNode(tokens, context, options, errors, stats);
471
503
  if (node != null) {
472
- if (node.typ == EnumToken.AtRuleNodeType && node.nam == 'import') {
504
+ if (node.typ == EnumToken.AtRuleNodeType && "import" === node.val) {
473
505
  imports.push(node);
474
506
  }
475
- else if ('chi' in node && node.typ != EnumToken.InvalidRuleTokenType) {
507
+ if ("chi" in node /* && node.typ != EnumToken.InvalidRuleNodeType */) {
476
508
  stack.push(node);
477
509
  context = node;
478
510
  }
479
511
  }
480
- if (context != null && context.typ == EnumToken.InvalidRuleTokenType) {
481
- // @ts-ignore ignore error
482
- const index = context.chi.findIndex((node) => node === context);
483
- if (index > -1) {
484
- context.chi.splice(index, 1);
485
- }
486
- }
487
512
  }
488
513
  if (imports.length > 0 && options.resolveImport) {
489
514
  await Promise.all(imports.map(async (node) => {
@@ -491,17 +516,22 @@ async function doParse(iter, options = {}) {
491
516
  const url = token.typ == EnumToken.StringTokenType ? token.val.slice(1, -1) : token.val;
492
517
  try {
493
518
  const result = options.load(url, options.src);
494
- const stream = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction' ? await result : result;
495
- const root = await doParse(stream instanceof ReadableStream ? tokenizeStream(stream) : tokenize({
496
- stream,
497
- buffer: '',
498
- offset: 0,
499
- position: { ind: 0, lin: 1, col: 1 },
500
- currentPosition: { ind: -1, lin: 1, col: 0 }
501
- }), Object.assign({}, options, {
519
+ const stream = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == "AsyncFunction"
520
+ ? await result
521
+ : result;
522
+ const root = await doParse(stream instanceof ReadableStream
523
+ ? tokenizeStream(stream)
524
+ : tokenize({
525
+ stream,
526
+ src: options.resolve(url, options.src || options.cwd).relative,
527
+ buffer: "",
528
+ offset: 0,
529
+ position: { ind: 0, lin: 1, col: 1 },
530
+ currentPosition: { ind: -1, lin: 1, col: 0 },
531
+ }), Object.assign({}, options, {
502
532
  minify: false,
503
533
  setParent: false,
504
- src: options.resolve(url, options.src).absolute
534
+ src: options.resolve(url, options.src || options.cwd).relative,
505
535
  }));
506
536
  stats.importedBytesIn += root.stats.bytesIn;
507
537
  stats.imports.push(root.stats);
@@ -512,7 +542,7 @@ async function doParse(iter, options = {}) {
512
542
  }
513
543
  catch (error) {
514
544
  // @ts-ignore ignore error
515
- errors.push({ action: 'ignore', message: 'doParse: ' + error.message, error });
545
+ errors.push({ action: "ignore", message: ("doParse: " + error.message), error });
516
546
  }
517
547
  }));
518
548
  }
@@ -520,10 +550,25 @@ async function doParse(iter, options = {}) {
520
550
  const previousNode = stack.pop();
521
551
  context = (stack[stack.length - 1] ?? ast);
522
552
  // remove empty nodes
523
- if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
553
+ if (options.removeEmpty &&
554
+ previousNode != null &&
555
+ previousNode.chi.length == 0 &&
556
+ context.chi[context.chi.length - 1] == previousNode) {
524
557
  context.chi.pop();
525
558
  continue;
526
559
  }
560
+ // remove invalid nodes
561
+ if (!options.lenient &&
562
+ previousNode?.parent != null &&
563
+ // @ts-expect-error
564
+ (previousNode.typ == EnumToken.InvalidRuleNodeType || previousNode.typ == EnumToken.InvalidAtRuleNodeType)) {
565
+ for (let i = context.chi.length - 1; i >= 0; i--) {
566
+ if (context.chi[i] == previousNode) {
567
+ context.chi.splice(i, 1);
568
+ break;
569
+ }
570
+ }
571
+ }
527
572
  break;
528
573
  }
529
574
  const endParseTime = performance.now();
@@ -533,17 +578,35 @@ async function doParse(iter, options = {}) {
533
578
  let replacement;
534
579
  let callable;
535
580
  if (options.visitor != null) {
581
+ let parens;
536
582
  for (const result of walk(ast)) {
537
- if (valuesHandlers.size > 0 || preVisitorsHandlersMap.size > 0 || visitorsHandlersMap.size > 0 || postVisitorsHandlersMap.size > 0) {
583
+ parens = null;
584
+ if (valuesHandlers.size > 0 ||
585
+ preVisitorsHandlersMap.size > 0 ||
586
+ visitorsHandlersMap.size > 0 ||
587
+ postVisitorsHandlersMap.size > 0) {
538
588
  if ((result.node.typ == EnumToken.DeclarationNodeType &&
539
- (preVisitorsHandlersMap.has('Declaration') || visitorsHandlersMap.has('Declaration') || postVisitorsHandlersMap.has('Declaration'))) ||
540
- (result.node.typ == EnumToken.AtRuleNodeType && (preVisitorsHandlersMap.has('AtRule') || visitorsHandlersMap.has('AtRule') || postVisitorsHandlersMap.has('AtRule'))) ||
541
- (result.node.typ == EnumToken.KeyframesAtRuleNodeType && (preVisitorsHandlersMap.has('KeyframesAtRule') || visitorsHandlersMap.has('KeyframesAtRule') || postVisitorsHandlersMap.has('KeyframesAtRule')))) {
589
+ (preVisitorsHandlersMap.has("Declaration") ||
590
+ visitorsHandlersMap.has("Declaration") ||
591
+ postVisitorsHandlersMap.has("Declaration"))) ||
592
+ (result.node.typ == EnumToken.AtRuleNodeType &&
593
+ (preVisitorsHandlersMap.has("AtRule") ||
594
+ visitorsHandlersMap.has("AtRule") ||
595
+ postVisitorsHandlersMap.has("AtRule"))) ||
596
+ (result.node.typ == EnumToken.KeyframesAtRuleNodeType &&
597
+ (preVisitorsHandlersMap.has("KeyframesAtRule") ||
598
+ visitorsHandlersMap.has("KeyframesAtRule") ||
599
+ postVisitorsHandlersMap.has("KeyframesAtRule")))) {
542
600
  const handlers = [];
543
- const key = result.node.typ == EnumToken.DeclarationNodeType ? 'Declaration' : result.node.typ == EnumToken.AtRuleNodeType ? 'AtRule' : 'KeyframesAtRule';
601
+ const key = result.node.typ == EnumToken.DeclarationNodeType
602
+ ? "Declaration"
603
+ : result.node.typ == EnumToken.AtRuleNodeType
604
+ ? "AtRule"
605
+ : "KeyframesAtRule";
544
606
  if (preVisitorsHandlersMap.has(key)) {
545
- // @ts-ignore
546
- handlers.push(...preVisitorsHandlersMap.get(key));
607
+ handlers.push(
608
+ // @ts-expect-error
609
+ ...preVisitorsHandlersMap.get(key));
547
610
  }
548
611
  if (visitorsHandlersMap.has(key)) {
549
612
  // @ts-ignore
@@ -555,15 +618,30 @@ async function doParse(iter, options = {}) {
555
618
  }
556
619
  let node = result.node;
557
620
  for (const handler of handlers) {
558
- callable = typeof handler == 'function' ? handler : handler[camelize(node.typ == EnumToken.DeclarationNodeType || node.typ == EnumToken.AtRuleNodeType ? node.nam : node.val)];
621
+ callable =
622
+ typeof handler == "function"
623
+ ? handler
624
+ : handler[camelize(node.typ === EnumToken.DeclarationNodeType ||
625
+ node.typ === EnumToken.AtRuleNodeType
626
+ ? node.nam
627
+ : node.val)];
559
628
  if (callable == null) {
560
629
  continue;
561
630
  }
562
- replacement = callable(node, result.parent);
631
+ // @ts-expect-error
632
+ replacement = callable(node, result.parent, ast, function* () {
633
+ if (parens == null) {
634
+ // @ts-expect-error
635
+ parens = [...result.parents()];
636
+ }
637
+ yield* parens[Symbol.iterator]();
638
+ });
563
639
  if (replacement == null) {
564
640
  continue;
565
641
  }
566
- isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
642
+ isAsync =
643
+ replacement instanceof Promise ||
644
+ Object.getPrototypeOf(replacement).constructor.name == "AsyncFunction";
567
645
  if (replacement) {
568
646
  replacement = await replacement;
569
647
  }
@@ -572,20 +650,24 @@ async function doParse(iter, options = {}) {
572
650
  }
573
651
  // @ts-ignore
574
652
  node = replacement;
575
- //
576
653
  if (Array.isArray(node)) {
577
654
  break;
578
655
  }
579
656
  }
580
657
  if (node != result.node) {
581
- // @ts-ignore
582
658
  replaceToken(result.parent, result.node, node);
583
659
  }
584
660
  }
585
- else if ((result.node.typ == EnumToken.RuleNodeType && (preVisitorsHandlersMap.has('Rule') || visitorsHandlersMap.has('Rule') || postVisitorsHandlersMap.has('Rule'))) ||
586
- (result.node.typ == EnumToken.KeyFramesRuleNodeType && (preVisitorsHandlersMap.has('KeyframesRule') || visitorsHandlersMap.has('KeyframesRule') || postVisitorsHandlersMap.has('KeyframesRule')))) {
661
+ else if ((result.node.typ == EnumToken.RuleNodeType &&
662
+ (preVisitorsHandlersMap.has("Rule") ||
663
+ visitorsHandlersMap.has("Rule") ||
664
+ postVisitorsHandlersMap.has("Rule"))) ||
665
+ (result.node.typ == EnumToken.KeyFramesRuleNodeType &&
666
+ (preVisitorsHandlersMap.has("KeyframesRule") ||
667
+ visitorsHandlersMap.has("KeyframesRule") ||
668
+ postVisitorsHandlersMap.has("KeyframesRule")))) {
587
669
  const handlers = [];
588
- const key = result.node.typ == EnumToken.RuleNodeType ? 'Rule' : 'KeyframesRule';
670
+ const key = result.node.typ == EnumToken.RuleNodeType ? "Rule" : "KeyframesRule";
589
671
  if (preVisitorsHandlersMap.has(key)) {
590
672
  handlers.push(...preVisitorsHandlersMap.get(key));
591
673
  }
@@ -597,11 +679,21 @@ async function doParse(iter, options = {}) {
597
679
  }
598
680
  let node = result.node;
599
681
  for (const callable of handlers) {
600
- replacement = callable(node, result.parent);
682
+ replacement = callable(node, result.parent, result.root,
683
+ // @ts-expect-error
684
+ function* () {
685
+ if (parens == null) {
686
+ // @ts-expect-error
687
+ parens = [...result.parents()];
688
+ }
689
+ yield* parens[Symbol.iterator]();
690
+ });
601
691
  if (replacement == null) {
602
692
  continue;
603
693
  }
604
- isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
694
+ isAsync =
695
+ replacement instanceof Promise ||
696
+ Object.getPrototypeOf(replacement).constructor.name == "AsyncFunction";
605
697
  if (replacement) {
606
698
  replacement = await replacement;
607
699
  }
@@ -627,11 +719,21 @@ async function doParse(iter, options = {}) {
627
719
  if (valuesHandlers.has(node.typ)) {
628
720
  for (const valueHandler of valuesHandlers.get(node.typ)) {
629
721
  callable = valueHandler;
630
- replacement = callable(node, result.parent);
722
+ replacement = callable(node, result.parent, ast,
723
+ // @ts-expect-error
724
+ function* () {
725
+ if (parens == null) {
726
+ // @ts-expect-error
727
+ parens = [...result.parents()];
728
+ }
729
+ yield* parens[Symbol.iterator]();
730
+ });
631
731
  if (replacement == null) {
632
732
  continue;
633
733
  }
634
- isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
734
+ isAsync =
735
+ replacement instanceof Promise ||
736
+ Object.getPrototypeOf(replacement).constructor.name == "AsyncFunction";
635
737
  if (isAsync) {
636
738
  replacement = await replacement;
637
739
  }
@@ -644,30 +746,39 @@ async function doParse(iter, options = {}) {
644
746
  // @ts-ignore
645
747
  replaceToken(result.parent, value, node);
646
748
  }
647
- const tokens = 'tokens' in result.node ? result.node.tokens : [];
648
- if ('val' in result.node && Array.isArray(result.node.val)) {
749
+ const tokens = Array.isArray(result.node.tokens) ? result.node.tokens : [];
750
+ if (Array.isArray(result.node.val)) {
649
751
  tokens.push(...result.node.val);
650
752
  }
651
753
  if (tokens.length == 0) {
652
754
  continue;
653
755
  }
654
- for (const { value, parent, root } of walkValues(tokens, result.node)) {
756
+ for (const { value, parent, root, parents } of walkValues(tokens, result.node)) {
655
757
  node = value;
656
758
  if (valuesHandlers.has(node.typ)) {
759
+ let parens = null;
657
760
  for (const valueHandler of valuesHandlers.get(node.typ)) {
658
761
  callable = valueHandler;
659
- let result = callable(node, parent, root);
762
+ // @ts-expect-error
763
+ let result = callable(node, parent, root, function* () {
764
+ if (parens == null) {
765
+ // @ts-expect-error
766
+ parens = [...parents()];
767
+ }
768
+ yield* parens[Symbol.iterator]();
769
+ });
660
770
  if (result == null) {
661
771
  continue;
662
772
  }
663
- isAsync = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction';
773
+ isAsync =
774
+ result instanceof Promise ||
775
+ Object.getPrototypeOf(result).constructor.name == "AsyncFunction";
664
776
  if (isAsync) {
665
777
  result = await result;
666
778
  }
667
779
  if (result != null && result != node) {
668
780
  node = result;
669
781
  }
670
- //
671
782
  if (Array.isArray(node)) {
672
783
  break;
673
784
  }
@@ -699,32 +810,38 @@ async function doParse(iter, options = {}) {
699
810
  ...stats,
700
811
  parse: `${(endParseTime - startTime).toFixed(2)}ms`,
701
812
  minify: `${(endTime - endParseTime).toFixed(2)}ms`,
702
- total: `${(endTime - startTime).toFixed(2)}ms`
703
- }
813
+ tokenize: `${(options?.parseInfo?.time ?? 0).toFixed(2)}ms`,
814
+ total: `${(endTime - startTime).toFixed(2)}ms`,
815
+ },
704
816
  };
705
817
  if (options.module) {
706
818
  const moduleSettings = {
707
819
  hashLength: 5,
708
- filePath: '',
820
+ filePath: "",
709
821
  scoped: ModuleScopeEnumOptions.Local,
710
822
  naming: ModuleCaseTransformEnum.IgnoreCase,
711
- pattern: '',
823
+ pattern: "",
712
824
  generateScopedName,
713
- ...(typeof options.module != 'object' ? {} : options.module)
825
+ ...(typeof options.module != "object" ? {} : options.module),
714
826
  };
715
827
  const parseModuleTime = performance.now();
716
828
  const namesMapping = {};
717
- const global = new Set;
718
- const processed = new Set;
719
- const pattern = typeof options.module == 'boolean' ? null : moduleSettings.pattern;
829
+ const global = new Set();
830
+ const processed = new Set();
831
+ const pattern = typeof options.module == "boolean" ? null : moduleSettings.pattern;
720
832
  const importMapping = {};
721
833
  const cssVariablesMap = {};
722
834
  const importedCssVariables = {};
723
835
  let mapping = {};
724
836
  let revMapping = {};
725
- let filePath = typeof options.module == 'boolean' ? options.src : (moduleSettings.filePath ?? options.src);
726
- filePath = filePath === '' ? options.src : options.resolve(filePath, options.dirname(options.src), options.cwd).relative;
727
- if (typeof options.module == 'number') {
837
+ let filePath = typeof options.module == "boolean"
838
+ ? options.src
839
+ : (moduleSettings.filePath ?? options.src);
840
+ filePath =
841
+ filePath === ""
842
+ ? options.src
843
+ : options.resolve(filePath, options.dirname(options.src), options.cwd).relative;
844
+ if (typeof options.module == "number") {
728
845
  if (options.module & ModuleCaseTransformEnum.CamelCase) {
729
846
  moduleSettings.naming = ModuleCaseTransformEnum.CamelCase;
730
847
  }
@@ -744,44 +861,59 @@ async function doParse(iter, options = {}) {
744
861
  // @ts-ignore
745
862
  moduleSettings.scoped |= ModuleScopeEnumOptions.Pure;
746
863
  }
864
+ if (options.module & ModuleScopeEnumOptions.Shortest) {
865
+ // @ts-ignore
866
+ moduleSettings.scoped |= ModuleScopeEnumOptions.Shortest;
867
+ }
747
868
  if (options.module & ModuleScopeEnumOptions.ICSS) {
748
869
  // @ts-ignore
749
870
  moduleSettings.scoped |= ModuleScopeEnumOptions.ICSS;
750
871
  }
751
872
  }
752
- if (typeof moduleSettings.scoped == 'boolean') {
753
- moduleSettings.scoped = moduleSettings.scoped ? ModuleScopeEnumOptions.Local : ModuleScopeEnumOptions.Global;
873
+ if (typeof moduleSettings.scoped == "boolean") {
874
+ moduleSettings.scoped = moduleSettings.scoped
875
+ ? ModuleScopeEnumOptions.Local
876
+ : ModuleScopeEnumOptions.Global;
877
+ }
878
+ if (moduleSettings.scoped & ModuleScopeEnumOptions.Shortest) {
879
+ moduleSettings.generateScopedName = getShortNameGenerator;
754
880
  }
755
881
  moduleSettings.filePath = filePath;
756
- moduleSettings.pattern = pattern != null && pattern !== '' ? pattern : (filePath === '' ? `[local]_[hash]` : `[local]_[hash]_[name]`);
882
+ moduleSettings.pattern =
883
+ pattern != null && pattern !== "" ? pattern : filePath === "" ? `[local]_[hash]` : `[local]_[hash]_[name]`;
757
884
  for (const { node, parent } of walk(ast)) {
758
885
  if (node.typ == EnumToken.CssVariableImportTokenType) {
759
- const url = node.val.find(t => t.typ == EnumToken.StringTokenType).val.slice(1, -1);
886
+ const url = node.val.find((t) => t.typ == EnumToken.StringTokenType).val.slice(1, -1);
760
887
  const src = options.resolve(url, options.dirname(options.src), options.cwd);
761
888
  const result = options.load(url, options.src);
762
- const stream = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction' ? await result : result;
763
- const root = await doParse(stream instanceof ReadableStream ? tokenizeStream(stream) : tokenize({
889
+ const stream = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == "AsyncFunction"
890
+ ? await result
891
+ : result;
892
+ const parseInfo = {
764
893
  stream,
765
- buffer: '',
894
+ buffer: "",
766
895
  offset: 0,
896
+ time: 0,
767
897
  position: { ind: 0, lin: 1, col: 1 },
768
- currentPosition: { ind: -1, lin: 1, col: 0 }
769
- }), Object.assign({}, options, {
898
+ currentPosition: { ind: -1, lin: 1, col: 0 },
899
+ };
900
+ const root = await doParse(stream instanceof ReadableStream ? tokenizeStream(stream, parseInfo) : tokenize(parseInfo), Object.assign({}, options, {
770
901
  minify: false,
771
902
  setParent: false,
772
- src: src.relative
903
+ src: src.relative,
773
904
  }));
905
+ options.parseInfo.time += parseInfo.time;
774
906
  cssVariablesMap[node.nam] = root.cssModuleVariables;
775
907
  parent.chi.splice(parent.chi.indexOf(node), 1);
776
908
  continue;
777
909
  }
778
910
  if (node.typ == EnumToken.CssVariableDeclarationMapTokenType) {
779
- const from = node.from.find(t => t.typ == EnumToken.IdenTokenType || isIdentColor(t));
911
+ const from = node.from.find((t) => t.typ == EnumToken.IdenTokenType || isIdentColor(t));
780
912
  if (!(from.val in cssVariablesMap)) {
781
913
  errors.push({
782
914
  node,
783
915
  message: `could not resolve @value import from '${from.val}'`,
784
- action: 'drop'
916
+ action: "drop",
785
917
  });
786
918
  }
787
919
  else {
@@ -791,7 +923,7 @@ async function doParse(iter, options = {}) {
791
923
  errors.push({
792
924
  node,
793
925
  message: `value '${token.val}' is not exported from '${from.val}'`,
794
- action: 'drop'
926
+ action: "drop",
795
927
  });
796
928
  continue;
797
929
  }
@@ -814,29 +946,27 @@ async function doParse(iter, options = {}) {
814
946
  continue;
815
947
  }
816
948
  if (node.typ == EnumToken.DeclarationNodeType) {
817
- if (node.nam.startsWith('--')) {
949
+ if (node.nam.startsWith("--")) {
818
950
  if (!(node.nam in namesMapping)) {
819
- let result = (moduleSettings.scoped & ModuleScopeEnumOptions.Global) ? node.nam : moduleSettings.generateScopedName(node.nam, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
951
+ let result = moduleSettings.scoped & ModuleScopeEnumOptions.Global
952
+ ? node.nam
953
+ : moduleSettings.generateScopedName(node.nam, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
820
954
  let value = result instanceof Promise ? await result : result;
821
- mapping[node.nam] = '--' + (moduleSettings.naming & ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(value, moduleSettings.naming) : value);
955
+ mapping[node.nam] =
956
+ "--" +
957
+ (moduleSettings.naming & ModuleCaseTransformEnum.DashCaseOnly ||
958
+ moduleSettings.naming & ModuleCaseTransformEnum.CamelCaseOnly
959
+ ? getKeyName(value, moduleSettings.naming)
960
+ : value);
822
961
  revMapping[node.nam] = node.nam;
823
962
  }
824
963
  node.nam = mapping[node.nam];
825
964
  }
826
- if ('composes' == node.nam.toLowerCase()) {
965
+ if (equalsIgnoreCase("composes", node.nam)) {
827
966
  const tokens = [];
828
- let isValid = true;
967
+ // let isValid: boolean = true;
829
968
  for (const token of node.val) {
830
969
  if (token.typ == EnumToken.ComposesSelectorNodeType) {
831
- if (!(token.r == null || token.r.typ == EnumToken.StringTokenType || token.r.typ == EnumToken.IdenTokenType)) {
832
- errors.push({
833
- action: 'drop',
834
- message: `composes '${EnumToken[token.r.typ]}' is not supported`,
835
- node
836
- });
837
- isValid = false;
838
- break;
839
- }
840
970
  tokens.push(token);
841
971
  }
842
972
  }
@@ -845,14 +975,12 @@ async function doParse(iter, options = {}) {
845
975
  while (parentRule != null && parentRule.typ != EnumToken.RuleNodeType) {
846
976
  parentRule = parentRule.parent;
847
977
  }
848
- if (!isValid || tokens.length == 0) {
849
- if (tokens.length == 0) {
850
- errors.push({
851
- action: 'drop',
852
- message: `composes is empty`,
853
- node
854
- });
855
- }
978
+ if ( /* !isValid || */tokens.length == 0) {
979
+ errors.push({
980
+ action: "drop",
981
+ message: `composes is empty`,
982
+ node,
983
+ });
856
984
  parentRule.chi.splice(parentRule.chi.indexOf(node), 1);
857
985
  continue;
858
986
  }
@@ -860,13 +988,21 @@ async function doParse(iter, options = {}) {
860
988
  // composes: a b c;
861
989
  if (token.r == null) {
862
990
  for (const rule of token.l) {
863
- if (rule.typ == EnumToken.WhitespaceTokenType || rule.typ == EnumToken.CommentTokenType) {
991
+ if (rule.typ == EnumToken.WhitespaceTokenType ||
992
+ rule.typ == EnumToken.CommentTokenType) {
864
993
  continue;
865
994
  }
866
995
  if (!(rule.val in mapping)) {
867
- let result = (moduleSettings.scoped & ModuleScopeEnumOptions.Global) ? rule.val : moduleSettings.generateScopedName(rule.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
996
+ let result = moduleSettings.scoped & ModuleScopeEnumOptions.Global
997
+ ? rule.val
998
+ : moduleSettings.generateScopedName(rule.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
868
999
  let value = result instanceof Promise ? await result : result;
869
- mapping[rule.val] = (rule.typ == EnumToken.DashedIdenTokenType ? '--' : '') + (moduleSettings.naming & ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(value, moduleSettings.naming) : value);
1000
+ mapping[rule.val] =
1001
+ (rule.typ == EnumToken.DashedIdenTokenType ? "--" : "") +
1002
+ (moduleSettings.naming & ModuleCaseTransformEnum.DashCaseOnly ||
1003
+ moduleSettings.naming & ModuleCaseTransformEnum.CamelCaseOnly
1004
+ ? getKeyName(value, moduleSettings.naming)
1005
+ : value);
870
1006
  revMapping[mapping[rule.val]] = rule.val;
871
1007
  }
872
1008
  if (parentRule != null) {
@@ -875,7 +1011,12 @@ async function doParse(iter, options = {}) {
875
1011
  const val = tk.val.slice(1);
876
1012
  if (val in revMapping) {
877
1013
  const key = revMapping[val];
878
- mapping[key] = [...new Set([...mapping[key].split(' '), mapping[rule.val]])].join(' ');
1014
+ mapping[key] = [
1015
+ ...new Set([
1016
+ ...mapping[key].split(" "),
1017
+ mapping[rule.val],
1018
+ ]),
1019
+ ].join(" ");
879
1020
  }
880
1021
  }
881
1022
  }
@@ -887,19 +1028,25 @@ async function doParse(iter, options = {}) {
887
1028
  const url = token.r.val.slice(1, -1);
888
1029
  const src = options.resolve(url, options.dirname(options.src), options.cwd);
889
1030
  const result = options.load(url, options.src);
890
- const stream = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction' ? await result : result;
891
- const root = await doParse(stream instanceof ReadableStream ? tokenizeStream(stream) : tokenize({
892
- stream,
893
- buffer: '',
894
- offset: 0,
895
- position: { ind: 0, lin: 1, col: 1 },
896
- currentPosition: { ind: -1, lin: 1, col: 0 }
897
- }), Object.assign({}, options, {
1031
+ const stream = result instanceof Promise ||
1032
+ Object.getPrototypeOf(result).constructor.name == "AsyncFunction"
1033
+ ? await result
1034
+ : result;
1035
+ const root = await doParse(stream instanceof ReadableStream
1036
+ ? tokenizeStream(stream)
1037
+ : tokenize({
1038
+ stream,
1039
+ buffer: "",
1040
+ offset: 0,
1041
+ position: { ind: 0, lin: 1, col: 1 },
1042
+ currentPosition: { ind: -1, lin: 1, col: 0 },
1043
+ }), Object.assign({}, options, {
898
1044
  minify: false,
899
1045
  setParent: false,
900
- src: src.relative
1046
+ src: src.relative,
901
1047
  }));
902
- const srcIndex = (src.relative.startsWith('/') || src.relative.startsWith('../') ? '' : './') + src.relative;
1048
+ const srcIndex = (src.relative.startsWith("/") || src.relative.startsWith("../") ? "" : "./") +
1049
+ src.relative;
903
1050
  if (Object.keys(root.mapping).length > 0) {
904
1051
  importMapping[srcIndex] = {};
905
1052
  }
@@ -911,19 +1058,27 @@ async function doParse(iter, options = {}) {
911
1058
  const key = revMapping[val];
912
1059
  const values = [];
913
1060
  for (const iden of token.l) {
914
- if (iden.typ != EnumToken.IdenTokenType && iden.typ != EnumToken.DashedIdenTokenType) {
1061
+ if (iden.typ != EnumToken.IdenTokenType &&
1062
+ iden.typ != EnumToken.DashedIdenTokenType) {
915
1063
  continue;
916
1064
  }
917
1065
  if (!(iden.val in root.mapping)) {
918
- const result = (moduleSettings.scoped & ModuleScopeEnumOptions.Global) ? iden.val : moduleSettings.generateScopedName(iden.val, srcIndex, moduleSettings.pattern, moduleSettings.hashLength);
1066
+ const result = moduleSettings.scoped & ModuleScopeEnumOptions.Global
1067
+ ? iden.val
1068
+ : moduleSettings.generateScopedName(iden.val, srcIndex, moduleSettings.pattern, moduleSettings.hashLength);
919
1069
  let value = result instanceof Promise ? await result : result;
920
- root.mapping[iden.val] = (moduleSettings.naming & ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(value, moduleSettings.naming) : value);
1070
+ root.mapping[iden.val] =
1071
+ moduleSettings.naming & ModuleCaseTransformEnum.DashCaseOnly ||
1072
+ moduleSettings.naming & ModuleCaseTransformEnum.CamelCaseOnly
1073
+ ? getKeyName(value, moduleSettings.naming)
1074
+ : value;
921
1075
  root.revMapping[root.mapping[iden.val]] = iden.val;
922
1076
  }
923
- importMapping[srcIndex][iden.val] = root.mapping[iden.val];
1077
+ importMapping[srcIndex][iden.val] =
1078
+ root.mapping[iden.val];
924
1079
  values.push(root.mapping[iden.val]);
925
1080
  }
926
- mapping[key] = [...new Set([...mapping[key].split(' '), ...values])].join(' ');
1081
+ mapping[key] = [...new Set([...mapping[key].split(" "), ...values])].join(" ");
927
1082
  }
928
1083
  }
929
1084
  }
@@ -933,27 +1088,32 @@ async function doParse(iter, options = {}) {
933
1088
  else if (token.r.typ == EnumToken.IdenTokenType) {
934
1089
  // global
935
1090
  if (parentRule != null) {
936
- if ('global' == token.r.val.toLowerCase()) {
1091
+ if (equalsIgnoreCase("global", token.r.val)) {
937
1092
  for (const tk of parentRule.tokens) {
938
1093
  if (tk.typ == EnumToken.ClassSelectorTokenType) {
939
1094
  const val = tk.val.slice(1);
940
1095
  if (val in revMapping) {
941
1096
  const key = revMapping[val];
942
- mapping[key] = [...new Set([...mapping[key].split(' '), ...(token.l.reduce((acc, curr) => {
1097
+ mapping[key] = [
1098
+ ...new Set([
1099
+ ...mapping[key].split(" "),
1100
+ ...token.l.reduce((acc, curr) => {
943
1101
  if (curr.typ == EnumToken.IdenTokenType) {
944
1102
  acc.push(curr.val);
945
1103
  }
946
1104
  return acc;
947
- }, []))])].join(' ');
1105
+ }, []),
1106
+ ]),
1107
+ ].join(" ");
948
1108
  }
949
1109
  }
950
1110
  }
951
1111
  }
952
1112
  else {
953
1113
  errors.push({
954
- action: 'drop',
1114
+ action: "drop",
955
1115
  message: `composes '${token.r.val}' is not supported`,
956
- node
1116
+ node,
957
1117
  });
958
1118
  }
959
1119
  }
@@ -961,29 +1121,42 @@ async function doParse(iter, options = {}) {
961
1121
  }
962
1122
  parentRule.chi.splice(parentRule.chi.indexOf(node), 1);
963
1123
  }
964
- if (node.typ == EnumToken.DeclarationNodeType && ['grid-column', 'grid-column-start', 'grid-column-end', 'grid-row', 'grid-row-start', 'grid-row-end', 'grid-template', 'grid-template-columns', 'grid-template-rows'].includes(node.nam)) {
1124
+ if (node.typ == EnumToken.DeclarationNodeType &&
1125
+ [
1126
+ "grid-column",
1127
+ "grid-column-start",
1128
+ "grid-column-end",
1129
+ "grid-row",
1130
+ "grid-row-start",
1131
+ "grid-row-end",
1132
+ "grid-template",
1133
+ "grid-template-columns",
1134
+ "grid-template-rows",
1135
+ ].includes(node.nam)) {
965
1136
  for (const { value } of walkValues(node.val, node)) {
966
1137
  if (value.typ != EnumToken.IdenTokenType) {
967
1138
  continue;
968
1139
  }
969
1140
  let idenToken = value.val;
970
- let suffix = '';
971
- if (idenToken.endsWith('-start')) {
972
- suffix = '-start';
1141
+ let suffix = "";
1142
+ if (idenToken.endsWith("-start")) {
1143
+ suffix = "-start";
973
1144
  idenToken = idenToken.slice(0, -6);
974
1145
  }
975
- else if (idenToken.endsWith('-end')) {
976
- suffix = '-end';
1146
+ else if (idenToken.endsWith("-end")) {
1147
+ suffix = "-end";
977
1148
  idenToken = idenToken.slice(0, -4);
978
1149
  }
979
1150
  if (!(idenToken in mapping)) {
980
- let result = (moduleSettings.scoped & ModuleScopeEnumOptions.Global) ? idenToken : moduleSettings.generateScopedName(idenToken, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
1151
+ let result = moduleSettings.scoped & ModuleScopeEnumOptions.Global
1152
+ ? idenToken
1153
+ : moduleSettings.generateScopedName(idenToken, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
981
1154
  if (result instanceof Promise) {
982
1155
  result = await result;
983
1156
  }
984
1157
  mapping[idenToken] = result;
985
1158
  revMapping[result] = idenToken;
986
- if (suffix !== '') {
1159
+ if (suffix !== "") {
987
1160
  idenToken += suffix;
988
1161
  if (!(idenToken in mapping)) {
989
1162
  mapping[idenToken] = result + suffix;
@@ -994,17 +1167,22 @@ async function doParse(iter, options = {}) {
994
1167
  value.val = mapping[idenToken];
995
1168
  }
996
1169
  }
997
- else if (node.nam == 'grid-template-areas' || node.nam == 'grid-template') {
1170
+ else if (node.nam == "grid-template-areas" || node.nam == "grid-template") {
998
1171
  for (let i = 0; i < node.val.length; i++) {
999
1172
  if (node.val[i].typ == EnumToken.String) {
1000
- const tokens = parseString(node.val[i].val.slice(1, -1), { location: true });
1173
+ const tokens = parseString(node.val[i].val.slice(1, -1), {
1174
+ location: true,
1175
+ });
1001
1176
  for (const { value } of walkValues(tokens)) {
1002
- if (value.typ == EnumToken.IdenTokenType || value.typ == EnumToken.DashedIdenTokenType) {
1177
+ if (value.typ == EnumToken.IdenTokenType ||
1178
+ value.typ == EnumToken.DashedIdenTokenType) {
1003
1179
  if (value.val in mapping) {
1004
1180
  value.val = mapping[value.val];
1005
1181
  }
1006
1182
  else {
1007
- let result = (moduleSettings.scoped & ModuleScopeEnumOptions.Global) ? value.val : moduleSettings.generateScopedName(value.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
1183
+ let result = moduleSettings.scoped & ModuleScopeEnumOptions.Global
1184
+ ? value.val
1185
+ : moduleSettings.generateScopedName(value.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
1008
1186
  if (result instanceof Promise) {
1009
1187
  result = await result;
1010
1188
  }
@@ -1014,22 +1192,49 @@ async function doParse(iter, options = {}) {
1014
1192
  }
1015
1193
  }
1016
1194
  }
1017
- node.val[i].val = node.val[i].val.charAt(0) + tokens.reduce((acc, curr) => acc + renderToken(curr), '') + node.val[i].val.charAt(node.val[i].val.length - 1);
1195
+ node.val[i].val =
1196
+ node.val[i].val.charAt(0) +
1197
+ renderTokens(tokens) +
1198
+ node.val[i].val.charAt(node.val[i].val.length - 1);
1018
1199
  }
1019
1200
  }
1020
1201
  }
1021
- else if (node.nam == 'animation' || node.nam == 'animation-name') {
1202
+ else if (node.nam == "animation" || node.nam == "animation-name") {
1022
1203
  for (const { value } of walkValues(node.val, node)) {
1023
- if (value.typ == EnumToken.IdenTokenType && ![
1024
- 'none', 'infinite', 'normal', 'reverse', 'alternate',
1025
- 'alternate-reverse', 'forwards', 'backwards', 'both',
1026
- 'running', 'paused', 'linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out',
1027
- 'step-start', 'step-end', 'jump-start', 'jump-end',
1028
- 'jump-none', 'jump-both', 'start', 'end',
1029
- 'inherit', 'initial', 'unset'
1030
- ].includes(value.val)) {
1204
+ if (value.typ == EnumToken.IdenTokenType &&
1205
+ ![
1206
+ "none",
1207
+ "infinite",
1208
+ "normal",
1209
+ "reverse",
1210
+ "alternate",
1211
+ "alternate-reverse",
1212
+ "forwards",
1213
+ "backwards",
1214
+ "both",
1215
+ "running",
1216
+ "paused",
1217
+ "linear",
1218
+ "ease",
1219
+ "ease-in",
1220
+ "ease-out",
1221
+ "ease-in-out",
1222
+ "step-start",
1223
+ "step-end",
1224
+ "jump-start",
1225
+ "jump-end",
1226
+ "jump-none",
1227
+ "jump-both",
1228
+ "start",
1229
+ "end",
1230
+ "inherit",
1231
+ "initial",
1232
+ "unset",
1233
+ ].includes(value.val)) {
1031
1234
  if (!(value.val in mapping)) {
1032
- const result = (moduleSettings.scoped & ModuleScopeEnumOptions.Global) ? value.val : moduleSettings.generateScopedName(value.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
1235
+ const result = moduleSettings.scoped & ModuleScopeEnumOptions.Global
1236
+ ? value.val
1237
+ : moduleSettings.generateScopedName(value.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
1033
1238
  mapping[value.val] = result instanceof Promise ? await result : result;
1034
1239
  revMapping[mapping[value.val]] = value.val;
1035
1240
  }
@@ -1040,24 +1245,50 @@ async function doParse(iter, options = {}) {
1040
1245
  for (const { value, parent } of walkValues(node.val, node)) {
1041
1246
  if (value.typ == EnumToken.DashedIdenTokenType) {
1042
1247
  if (!(value.val in mapping)) {
1043
- const result = (moduleSettings.scoped & ModuleScopeEnumOptions.Global) ? value.val : moduleSettings.generateScopedName(value.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
1248
+ const result = moduleSettings.scoped & ModuleScopeEnumOptions.Global
1249
+ ? value.val
1250
+ : moduleSettings.generateScopedName(value.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
1044
1251
  let val = result instanceof Promise ? await result : result;
1045
- mapping[value.val] = '--' + (moduleSettings.naming & ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(val, moduleSettings.naming) : val);
1252
+ mapping[value.val] =
1253
+ "--" +
1254
+ (moduleSettings.naming & ModuleCaseTransformEnum.DashCaseOnly ||
1255
+ moduleSettings.naming & ModuleCaseTransformEnum.CamelCaseOnly
1256
+ ? getKeyName(val, moduleSettings.naming)
1257
+ : val);
1046
1258
  revMapping[mapping[value.val]] = value.val;
1047
1259
  }
1048
1260
  value.val = mapping[value.val];
1049
1261
  }
1050
- else if ((value.typ == EnumToken.IdenTokenType || isIdentColor(value)) && value.val in importedCssVariables) {
1262
+ else if ((value.typ == EnumToken.IdenTokenType || isIdentColor(value)) &&
1263
+ value.val in importedCssVariables) {
1051
1264
  replaceToken(parent, value, importedCssVariables[value.val].val);
1052
1265
  }
1053
1266
  }
1054
1267
  }
1055
1268
  else if (node.typ == EnumToken.RuleNodeType) {
1056
1269
  if (node.tokens == null) {
1057
- Object.defineProperty(node, 'tokens', {
1270
+ const tokens = parseString(node.sel, { location: true });
1271
+ matchSelectorSyntax(tokens, [], options);
1272
+ Object.defineProperty(node, "tokens", {
1058
1273
  ...definedPropertySettings,
1059
- value: parseSelector(parseString(node.sel, { location: true }))
1274
+ value: trimArray(tokens),
1060
1275
  });
1276
+ let i;
1277
+ const stack = [];
1278
+ for (i = 0; i < tokens.length; i++) {
1279
+ if (tokensfuncDefMap.has(tokens[i].typ)) {
1280
+ stack.push(tokens[i]);
1281
+ continue;
1282
+ }
1283
+ else if (tokens[i].typ == EnumToken.EndParensTokenType) {
1284
+ const func = stack.at(-1);
1285
+ tokens.splice(i, 1);
1286
+ // @ts-expect-error
1287
+ func.typ = tokensfuncDefMap.get(func.typ);
1288
+ func.chi = tokens.splice(tokens.indexOf(func) + 1, i - 1);
1289
+ stack.pop();
1290
+ }
1291
+ }
1061
1292
  }
1062
1293
  let hasIdOrClass = false;
1063
1294
  for (const { value } of walkValues(node.tokens, node,
@@ -1066,19 +1297,25 @@ async function doParse(iter, options = {}) {
1066
1297
  if (value.typ == EnumToken.PseudoClassTokenType) {
1067
1298
  const val = value.val.toLowerCase();
1068
1299
  switch (val) {
1069
- case ':local':
1070
- case ':global':
1300
+ case ":local":
1301
+ case ":global":
1071
1302
  {
1072
1303
  let index = parent.tokens.indexOf(value);
1073
1304
  parent.tokens.splice(index, 1);
1074
- if (parent.tokens[index]?.typ == EnumToken.WhitespaceTokenType || parent.tokens[index]?.typ == EnumToken.DescendantCombinatorTokenType) {
1305
+ if (parent.tokens[index]?.typ == EnumToken.WhitespaceTokenType ||
1306
+ parent.tokens[index]?.typ ==
1307
+ EnumToken.DescendantCombinatorTokenType) {
1075
1308
  parent.tokens.splice(index, 1);
1076
1309
  }
1077
- if (val == ':global') {
1310
+ if (val == ":global") {
1078
1311
  for (; index < parent.tokens.length; index++) {
1079
- if (parent.tokens[index].typ == EnumToken.CommaTokenType ||
1080
- ([EnumToken.PseudoClassFuncTokenType, EnumToken.PseudoClassTokenType].includes(parent.tokens[index].typ) &&
1081
- [':global', ':local'].includes(parent.tokens[index].val.toLowerCase()))) {
1312
+ if (parent.tokens[index].typ ==
1313
+ EnumToken.CommaTokenType ||
1314
+ ([
1315
+ EnumToken.PseudoClassFuncTokenType,
1316
+ EnumToken.PseudoClassTokenType,
1317
+ ].includes(parent.tokens[index].typ) &&
1318
+ [":global", ":local"].includes(parent.tokens[index].val.toLowerCase()))) {
1082
1319
  break;
1083
1320
  }
1084
1321
  global.add(parent.tokens[index]);
@@ -1090,13 +1327,13 @@ async function doParse(iter, options = {}) {
1090
1327
  }
1091
1328
  else if (value.typ == EnumToken.PseudoClassFuncTokenType) {
1092
1329
  switch (value.val.toLowerCase()) {
1093
- case ':global':
1330
+ case ":global":
1094
1331
  for (const token of value.chi) {
1095
1332
  global.add(token);
1096
1333
  }
1097
1334
  parent.tokens.splice(parent.tokens.indexOf(value), 1, ...value.chi);
1098
1335
  break;
1099
- case ':local':
1336
+ case ":local":
1100
1337
  parent.tokens.splice(parent.tokens.indexOf(value), 1, ...value.chi);
1101
1338
  break;
1102
1339
  }
@@ -1118,21 +1355,27 @@ async function doParse(iter, options = {}) {
1118
1355
  if (value.typ == EnumToken.ClassSelectorTokenType) {
1119
1356
  const val = value.val.slice(1);
1120
1357
  if (!(val in mapping)) {
1121
- const result = (moduleSettings.scoped & ModuleScopeEnumOptions.Global) ? val : moduleSettings.generateScopedName(val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
1358
+ const result = moduleSettings.scoped & ModuleScopeEnumOptions.Global
1359
+ ? val
1360
+ : moduleSettings.generateScopedName(val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
1122
1361
  let value = result instanceof Promise ? await result : result;
1123
- mapping[val] = (moduleSettings.naming & ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(value, moduleSettings.naming) : value);
1362
+ mapping[val] =
1363
+ moduleSettings.naming & ModuleCaseTransformEnum.DashCaseOnly ||
1364
+ moduleSettings.naming & ModuleCaseTransformEnum.CamelCaseOnly
1365
+ ? getKeyName(value, moduleSettings.naming)
1366
+ : value;
1124
1367
  revMapping[mapping[val]] = val;
1125
1368
  }
1126
- value.val = '.' + mapping[val];
1369
+ value.val = "." + mapping[val];
1127
1370
  }
1128
1371
  }
1129
1372
  }
1130
1373
  if (moduleSettings.scoped & ModuleScopeEnumOptions.Pure) {
1131
1374
  if (!hasIdOrClass) {
1132
- throw new Error(`pure module: No id or class found in selector '${node.sel}' at '${node.loc?.src ?? ''}':${node.loc?.sta?.lin ?? ''}:${node.loc?.sta?.col ?? ''}`);
1375
+ throw new Error(`pure module: No id or class found in selector '${node.sel}' at '${node.loc?.src ?? ""}':${node.loc?.sta?.lin ?? ""}:${node.loc?.sta?.col ?? ""}`);
1133
1376
  }
1134
1377
  }
1135
- node.sel = '';
1378
+ node.sel = "";
1136
1379
  for (const token of node.tokens) {
1137
1380
  node.sel += renderToken(token);
1138
1381
  }
@@ -1140,39 +1383,50 @@ async function doParse(iter, options = {}) {
1140
1383
  else if (node.typ == EnumToken.AtRuleNodeType || node.typ == EnumToken.KeyframesAtRuleNodeType) {
1141
1384
  const val = node.nam.toLowerCase();
1142
1385
  if (node.tokens == null) {
1143
- Object.defineProperty(node, 'tokens', {
1386
+ Object.defineProperty(node, "tokens", {
1144
1387
  ...definedPropertySettings,
1145
1388
  // @ts-ignore
1146
- value: parseAtRulePrelude(parseString(node.val), node)
1389
+ value: parseString(node.val),
1147
1390
  });
1148
1391
  }
1149
- if (val == 'property' || val == 'keyframes') {
1150
- const prefix = val == 'property' ? '--' : '';
1392
+ if (val == "property" || val == "keyframes") {
1393
+ const prefix = val == "property" ? "--" : "";
1151
1394
  for (const value of node.tokens) {
1152
- if ((prefix == '--' && value.typ == EnumToken.DashedIdenTokenType) || (prefix == '' && value.typ == EnumToken.IdenTokenType)) {
1395
+ if ((prefix == "--" && value.typ == EnumToken.DashedIdenTokenType) ||
1396
+ (prefix == "" && value.typ == EnumToken.IdenTokenType)) {
1153
1397
  if (!(value.val in mapping)) {
1154
- const result = (moduleSettings.scoped & ModuleScopeEnumOptions.Global) ? value.val : moduleSettings.generateScopedName(value.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
1398
+ const result = moduleSettings.scoped & ModuleScopeEnumOptions.Global
1399
+ ? value.val
1400
+ : moduleSettings.generateScopedName(value.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
1155
1401
  let val = result instanceof Promise ? await result : result;
1156
- mapping[value.val] = prefix + (moduleSettings.naming & ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(val, moduleSettings.naming) : val);
1402
+ mapping[value.val] =
1403
+ prefix +
1404
+ (moduleSettings.naming & ModuleCaseTransformEnum.DashCaseOnly ||
1405
+ moduleSettings.naming & ModuleCaseTransformEnum.CamelCaseOnly
1406
+ ? getKeyName(val, moduleSettings.naming)
1407
+ : val);
1157
1408
  revMapping[mapping[value.val]] = value.val;
1158
1409
  }
1159
1410
  value.val = mapping[value.val];
1160
1411
  }
1161
1412
  }
1162
- node.val = node.tokens.reduce((a, b) => a + renderToken(b), '');
1413
+ node.val = renderTokens(node.tokens);
1163
1414
  }
1164
1415
  else {
1165
1416
  let isReplaced = false;
1166
1417
  for (const { value, parent } of walkValues(node.tokens, node)) {
1167
- if (EnumToken.MediaQueryConditionTokenType == parent.typ && value != parent.l) {
1168
- if ((value.typ == EnumToken.IdenTokenType || isIdentColor(value)) && value.val in importedCssVariables) {
1418
+ if (EnumToken.MediaQueryConditionTokenType == parent.typ &&
1419
+ // @ts-expect-error
1420
+ value != parent.l) {
1421
+ if ((value.typ == EnumToken.IdenTokenType || isIdentColor(value)) &&
1422
+ value.val in importedCssVariables) {
1169
1423
  isReplaced = true;
1170
1424
  parent.r.splice(parent.r.indexOf(value), 1, ...importedCssVariables[value.val].val);
1171
1425
  }
1172
1426
  }
1173
1427
  }
1174
1428
  if (isReplaced) {
1175
- node.val = node.tokens.reduce((a, b) => a + renderToken(b), '');
1429
+ node.val = renderTokens(node.tokens);
1176
1430
  }
1177
1431
  }
1178
1432
  }
@@ -1188,7 +1442,7 @@ async function doParse(iter, options = {}) {
1188
1442
  }
1189
1443
  result.mapping = mapping;
1190
1444
  result.revMapping = revMapping;
1191
- if ((moduleSettings.scoped & ModuleScopeEnumOptions.ICSS) && Object.keys(importMapping).length > 0) {
1445
+ if (moduleSettings.scoped & ModuleScopeEnumOptions.ICSS && Object.keys(importMapping).length > 0) {
1192
1446
  result.importMapping = importMapping;
1193
1447
  }
1194
1448
  endTime = performance.now();
@@ -1196,887 +1450,872 @@ async function doParse(iter, options = {}) {
1196
1450
  result.stats.total = `${(endTime - startTime).toFixed(2)}ms`;
1197
1451
  }
1198
1452
  if (options.signal != null) {
1199
- options.signal.removeEventListener('abort', reject);
1453
+ options.signal.removeEventListener("abort", reject);
1200
1454
  }
1201
1455
  return result;
1202
1456
  }
1203
- function getLastNode(context) {
1204
- let i = context.chi.length;
1205
- while (i--) {
1206
- if ([EnumToken.CommentTokenType, EnumToken.CDOCOMMTokenType, EnumToken.WhitespaceTokenType].includes(context.chi[i].typ)) {
1457
+ function parseNode(tokens, context, options, errors, stats) {
1458
+ let i = 0;
1459
+ if (tokens.at(-1)?.typ === EnumToken.EOFTokenType) {
1460
+ tokens.pop();
1461
+ // check parenthesis are balanced
1462
+ let matchCount = 0;
1463
+ let position = tokens.at(-1)?.loc;
1464
+ for (let i = 0; i < tokens.length; i++) {
1465
+ const token = tokens[i];
1466
+ if (token.typ === EnumToken.StartParensTokenType || tokensfuncDefMap.has(token.typ)) {
1467
+ matchCount++;
1468
+ }
1469
+ else if (token.typ === EnumToken.EndParensTokenType) {
1470
+ matchCount--;
1471
+ }
1472
+ }
1473
+ if (matchCount > 0) {
1474
+ while (matchCount > 0) {
1475
+ position = {
1476
+ ...position,
1477
+ sta: { ...position.sta, ind: position.sta.ind + 1, col: position.sta.col + 1 },
1478
+ end: { ...position.end, ind: position.end.ind + 1, col: position.end.col + 1 },
1479
+ };
1480
+ tokens.push(Object.defineProperty({
1481
+ typ: EnumToken.EndParensTokenType,
1482
+ loc: tokens.at(-1)?.loc,
1483
+ }, "loc", {
1484
+ ...definedPropertySettings,
1485
+ value: { ...position },
1486
+ }));
1487
+ matchCount--;
1488
+ }
1489
+ }
1490
+ }
1491
+ for (; i < tokens.length; i++) {
1492
+ if (tokens[i].typ === EnumToken.CDOCOMMTokenType && context.typ !== EnumToken.StyleSheetNodeType) {
1493
+ errors.push({
1494
+ action: "drop",
1495
+ message: `CDOCOMM not allowed here ${JSON.stringify(tokens[i], null, 1)}`,
1496
+ node: tokens[i],
1497
+ location: tokens[i].loc,
1498
+ });
1499
+ tokens[i].typ = EnumToken.InvalidCommentTokenType;
1207
1500
  continue;
1208
1501
  }
1209
- return context.chi[i];
1502
+ if (tokens[i].typ === EnumToken.CommentTokenType ||
1503
+ tokens[i].typ === EnumToken.CDOCOMMTokenType ||
1504
+ tokens[i].typ === EnumToken.WhitespaceTokenType) {
1505
+ continue;
1506
+ }
1507
+ break;
1210
1508
  }
1211
- return null;
1212
- }
1213
- function parseNode(results, context, options, errors, src, map, rawTokens, stats) {
1214
- let tokens = [];
1215
- for (const t of results) {
1216
- const node = getTokenType(t.token, t.hint);
1217
- map.set(node, { sta: t.sta, end: t.end, src });
1218
- tokens.push(node);
1509
+ if (i > 0) {
1510
+ context.chi.push(...tokens.splice(0, i).filter((n) => n.typ !== EnumToken.WhitespaceTokenType));
1219
1511
  }
1220
- let i;
1221
- let loc;
1222
- for (i = 0; i < tokens.length; i++) {
1512
+ for (; i < tokens.length; i++) {
1223
1513
  if (tokens[i].typ == EnumToken.CommentTokenType || tokens[i].typ == EnumToken.CDOCOMMTokenType) {
1224
- const location = map.get(tokens[i]);
1514
+ const location = tokens[i]?.loc;
1225
1515
  if (tokens[i].typ == EnumToken.CDOCOMMTokenType && context.typ != EnumToken.StyleSheetNodeType) {
1226
1516
  errors.push({
1227
- action: 'drop',
1517
+ action: "drop",
1228
1518
  message: `CDOCOMM not allowed here ${JSON.stringify(tokens[i], null, 1)}`,
1229
1519
  node: tokens[i],
1230
- location
1520
+ location,
1231
1521
  });
1522
+ tokens[i].typ = EnumToken.InvalidCommentTokenType;
1232
1523
  continue;
1233
1524
  }
1234
- loc = location;
1235
1525
  context.chi.push(tokens[i]);
1236
1526
  stats.nodesCount++;
1237
- Object.defineProperty(tokens[i], 'loc', {
1238
- ...definedPropertySettings,
1239
- value: loc,
1240
- enumerable: options.sourcemap !== false
1241
- });
1242
1527
  }
1243
1528
  else if (tokens[i].typ != EnumToken.WhitespaceTokenType) {
1244
1529
  break;
1245
1530
  }
1246
1531
  }
1247
- tokens = tokens.slice(i);
1248
1532
  if (tokens.length == 0) {
1249
1533
  return null;
1250
1534
  }
1251
1535
  let delim = tokens.at(-1);
1252
- if (delim.typ == EnumToken.SemiColonTokenType || delim.typ == EnumToken.BlockStartTokenType || delim.typ == EnumToken.BlockEndTokenType) {
1253
- tokens.pop();
1254
- }
1255
- while ([EnumToken.WhitespaceTokenType, EnumToken.BadStringTokenType, EnumToken.BadCommentTokenType].includes(tokens.at(-1)?.typ)) {
1536
+ if (delim.typ == EnumToken.SemiColonTokenType ||
1537
+ delim.typ == EnumToken.BlockStartTokenType ||
1538
+ delim.typ == EnumToken.BlockEndTokenType) {
1256
1539
  tokens.pop();
1257
1540
  }
1258
1541
  if (tokens.length == 0) {
1259
1542
  return null;
1260
1543
  }
1261
1544
  if (tokens[0]?.typ == EnumToken.AtRuleTokenType) {
1262
- const atRule = tokens.shift();
1263
- const location = map.get(atRule);
1264
- // @ts-ignore
1265
- while ([EnumToken.WhitespaceTokenType].includes(tokens[0]?.typ)) {
1266
- tokens.shift();
1545
+ let nestedRule = false;
1546
+ let parent = context;
1547
+ let node;
1548
+ while (parent != null) {
1549
+ if (parent.typ == EnumToken.RuleNodeType) {
1550
+ nestedRule = true;
1551
+ break;
1552
+ }
1553
+ parent = parent.parent;
1267
1554
  }
1268
- rawTokens.shift();
1269
- if (atRule.val == 'import') {
1270
- // only @charset and @layer are accepted before @import
1271
- if (context.chi.length > 0) {
1272
- let i = context.chi.length;
1273
- while (i--) {
1274
- // @ts-ignore
1275
- const type = context.chi[i].typ;
1276
- if (type == EnumToken.CommentNodeType) {
1277
- continue;
1278
- }
1279
- if (type != EnumToken.AtRuleNodeType) {
1280
- if (!(type == EnumToken.InvalidAtRuleTokenType &&
1281
- ['charset', 'layer', 'import'].includes(context.chi[i].nam))) {
1282
- errors.push({
1283
- action: 'drop',
1284
- message: 'invalid @import',
1285
- location,
1286
- // @ts-ignore
1287
- rawTokens: [atRule, ...tokens]
1288
- });
1289
- return null;
1290
- }
1291
- }
1292
- const name = context.chi[i].nam;
1293
- if (name != 'charset' && name != 'import' && name != 'layer') {
1294
- errors.push({ action: 'drop', message: 'invalid @import', location });
1295
- return null;
1296
- }
1297
- break;
1298
- }
1555
+ node = parseAtRule(tokens, context, { ...options, nestedRule }, errors, delim.typ == EnumToken.BlockStartTokenType);
1556
+ if (node == null) {
1557
+ return null;
1558
+ }
1559
+ stats.nodesCount++;
1560
+ context.chi.push(node);
1561
+ // @ts-expect-error
1562
+ return Object.defineProperty(node, "parent", { ...definedPropertySettings, value: context });
1563
+ }
1564
+ else {
1565
+ stats.nodesCount++;
1566
+ // rule
1567
+ if (delim.typ == EnumToken.BlockStartTokenType) {
1568
+ const node = parseSelector(tokens, context, options, errors);
1569
+ context.chi.push(node);
1570
+ Object.defineProperty(node, "parent", { ...definedPropertySettings, value: context });
1571
+ return node;
1572
+ }
1573
+ else {
1574
+ const node = parseDeclaration(tokens, context, options, errors);
1575
+ Object.defineProperty(node, "parent", { ...definedPropertySettings, value: context });
1576
+ if (context.typ === EnumToken.StyleSheetNodeType && node.typ === EnumToken.DeclarationNodeType) {
1577
+ // @ts-expect-error
1578
+ node.typ = EnumToken.InvalidDeclarationNodeType;
1579
+ errors.push({
1580
+ message: "<declaration> not allowed in <stylesheet>",
1581
+ action: "drop",
1582
+ node,
1583
+ location: node.loc,
1584
+ });
1299
1585
  }
1300
- // @ts-ignore
1301
- if (tokens[0]?.typ != EnumToken.StringTokenType && tokens[0]?.typ != EnumToken.UrlFunctionTokenType) {
1586
+ else if (options.lenient || node.typ === EnumToken.DeclarationNodeType) {
1587
+ context.chi.push(node);
1588
+ }
1589
+ }
1590
+ }
1591
+ return null;
1592
+ }
1593
+ /**mjgvgyikjkml,kmbm b8790u89y70
1594
+ vbbnkit;;;jmjhyg77 * @param options
1595
+ * @param errors
1596
+ * @param parseAsBlock
1597
+ */
1598
+ function parseAtRule(stream, context, options, errors, parseAsBlock = null) {
1599
+ // const rules = getSyntaxRule(ValidationSyntaxGroupEnum.AtRules, "@" + (stream[0] as AtRuleToken).nam);
1600
+ let success = true;
1601
+ let atRuleName = stream[0].nam;
1602
+ if (atRuleName.startsWith("-")) {
1603
+ atRuleName = atRuleName.replace(/^-[a-z]+-/, "").toLowerCase();
1604
+ }
1605
+ const atRule = stream.shift();
1606
+ const syntaxRules = getSyntaxRule(ValidationSyntaxGroupEnum.AtRules, "@" + atRule.nam);
1607
+ const syntax = syntaxRules?.getPreludeRules()?.slice?.(1);
1608
+ const blockAllowed = syntaxRules?.getBlockRules() != null;
1609
+ if (syntaxRules == null) {
1610
+ if (!options.lenient) {
1611
+ errors.push({
1612
+ action: "drop",
1613
+ node: atRule,
1614
+ location: atRule.loc,
1615
+ message: "unknown at-rule",
1616
+ });
1617
+ // @ts-expect-error
1618
+ return {
1619
+ ...atRule,
1620
+ typ: EnumToken.InvalidRuleNodeType,
1621
+ val: renderTokens(trimArray(stream), options),
1622
+ ...(parseAsBlock ? { chi: [] } : {}),
1623
+ };
1624
+ }
1625
+ }
1626
+ else if (context.typ === EnumToken.AtRuleNodeType &&
1627
+ "page" === context.nam &&
1628
+ pageMarginBoxType.has(atRuleName.toLowerCase())) {
1629
+ if (parseAsBlock === false) {
1630
+ errors.push({
1631
+ action: "drop",
1632
+ node: atRule,
1633
+ location: atRule.loc,
1634
+ message: parseAsBlock ? "at-rule block not supported" : "at-rule block is required",
1635
+ });
1636
+ // @ts-expect-error
1637
+ return {
1638
+ ...atRule,
1639
+ typ: EnumToken.InvalidRuleNodeType,
1640
+ val: renderTokens(trimArray(stream), options),
1641
+ ...(parseAsBlock ? { chi: [] } : {}),
1642
+ };
1643
+ }
1644
+ const token = stream.find((t) => t.typ != EnumToken.WhitespaceTokenType && t.typ === EnumToken.CommentTokenType) ?? null;
1645
+ if (token != null) {
1646
+ errors.push({
1647
+ action: "drop",
1648
+ node: token,
1649
+ location: token.loc,
1650
+ message: `unexpected token ${EnumToken[token.typ]} at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
1651
+ });
1652
+ // @ts-expect-error
1653
+ return {
1654
+ ...atRule,
1655
+ typ: EnumToken.InvalidRuleNodeType,
1656
+ val: renderTokens(trimArray(stream), options),
1657
+ ...(parseAsBlock ? { chi: [] } : {}),
1658
+ };
1659
+ }
1660
+ }
1661
+ if (parseAsBlock === null) {
1662
+ parseAsBlock = blockAllowed;
1663
+ }
1664
+ if (syntax != null && atRule.nam !== "layer" && parseAsBlock !== blockAllowed) {
1665
+ success = false;
1666
+ errors.push({
1667
+ action: "drop",
1668
+ node: atRule,
1669
+ location: atRule.loc,
1670
+ message: parseAsBlock ? "at-rule block not supported" : "at-rule block is required",
1671
+ });
1672
+ // @ts-expect-error
1673
+ return {
1674
+ ...atRule,
1675
+ typ: EnumToken.InvalidRuleNodeType,
1676
+ val: renderTokens(trimArray(stream), options),
1677
+ ...(parseAsBlock ? { chi: [] } : {}),
1678
+ };
1679
+ }
1680
+ switch (atRuleName) {
1681
+ case "charset": {
1682
+ let success = true;
1683
+ if (stream.length === 0 ||
1684
+ stream[0].typ !== EnumToken.WhitespaceTokenType ||
1685
+ stream[0].val !== " ") {
1686
+ success = false;
1302
1687
  errors.push({
1303
- action: 'drop',
1304
- message: 'doParse: invalid @import',
1305
- location
1688
+ action: "drop",
1689
+ node: stream[0] ?? atRule,
1690
+ location: (stream[0] ?? atRule).loc,
1691
+ message: "expecting <space>",
1306
1692
  });
1307
- return null;
1308
1693
  }
1309
- // @ts-ignore
1310
- if (tokens[0].typ == EnumToken.UrlFunctionTokenType && tokens[1]?.typ != EnumToken.UrlTokenTokenType && tokens[1]?.typ != EnumToken.StringTokenType) {
1694
+ else if (stream[1].typ !== EnumToken.StringTokenType) {
1695
+ success = false;
1696
+ errors.push({
1697
+ action: "drop",
1698
+ node: stream[1] ?? atRule,
1699
+ location: (stream[1] ?? atRule).loc,
1700
+ message: "expecting <string>",
1701
+ });
1702
+ }
1703
+ if (success && stream[1].val.charCodeAt(0) !== 0x22) {
1704
+ success = false;
1311
1705
  errors.push({
1312
- action: 'drop',
1313
- message: 'doParse: invalid @import',
1314
- location
1706
+ action: "drop",
1707
+ node: stream[1] ?? atRule,
1708
+ location: (stream[1] ?? atRule).loc,
1709
+ message: "expecting double-quoted string",
1315
1710
  });
1711
+ }
1712
+ if (success && options.removeCharset) {
1316
1713
  return null;
1317
1714
  }
1715
+ // @ts-expect-error
1716
+ return Object.defineProperties(Object.assign(atRule, {
1717
+ typ: success ? EnumToken.AtRuleNodeType : EnumToken.InvalidRuleNodeType,
1718
+ val: renderTokens(trimArray(stream), options),
1719
+ }), {
1720
+ loc: {
1721
+ ...definedPropertySettings,
1722
+ value: { ...atRule.loc, end: (stream.at(-1) ?? atRule).loc.end },
1723
+ },
1724
+ tokens: { ...definedPropertySettings, value: stream },
1725
+ });
1318
1726
  }
1319
- if (atRule.val == 'import') {
1320
- // @ts-ignore
1321
- if (tokens[0].typ == EnumToken.UrlFunctionTokenType) {
1322
- if (tokens[1].typ == EnumToken.UrlTokenTokenType || tokens[1].typ == EnumToken.StringTokenType) {
1323
- tokens.shift();
1324
- if (tokens[0]?.typ == EnumToken.UrlTokenTokenType) {
1325
- // @ts-ignore
1326
- tokens[0].typ = EnumToken.StringTokenType;
1327
- // @ts-ignore
1328
- tokens[0].val = `"${tokens[0].val}"`;
1329
- }
1330
- // @ts-ignore
1331
- while (tokens[1]?.typ == EnumToken.WhitespaceTokenType || tokens[1]?.typ == EnumToken.CommentTokenType) {
1332
- tokens.splice(1, 1);
1727
+ case "font-feature-values": {
1728
+ const result = parseAtRuleFontFeatureValues(stream, atRule, options);
1729
+ if (result.errors.length > 0) {
1730
+ errors.push(...result.errors);
1731
+ }
1732
+ // @ts-expect-error
1733
+ return Object.defineProperties(Object.assign(atRule, {
1734
+ typ: result.success ? EnumToken.AtRuleNodeType : EnumToken.InvalidRuleNodeType,
1735
+ val: renderTokens(trimWhiteSpaceTokens(stream), options),
1736
+ chi: [],
1737
+ }), {
1738
+ loc: {
1739
+ ...definedPropertySettings,
1740
+ value: { ...atRule.loc, end: (stream.at(-1) ?? atRule).loc.end },
1741
+ },
1742
+ tokens: { ...definedPropertySettings, value: stream },
1743
+ });
1744
+ }
1745
+ case "stylistic":
1746
+ case "historical-forms":
1747
+ case "character-variant":
1748
+ case "swash":
1749
+ case "ornaments":
1750
+ case "annotation": {
1751
+ let success = context.typ === EnumToken.AtRuleNodeType && "font-feature-values" === context.nam;
1752
+ if (!success) {
1753
+ errors.push({
1754
+ action: "drop",
1755
+ node: atRule,
1756
+ location: atRule.loc,
1757
+ message: `unexpected at-rule ${atRule.nam}`,
1758
+ });
1759
+ }
1760
+ if (success) {
1761
+ for (const token of stream) {
1762
+ if (token.typ !== EnumToken.CommentTokenType && token.typ !== EnumToken.WhitespaceTokenType) {
1763
+ success = false;
1764
+ errors.push({
1765
+ action: "drop",
1766
+ node: token,
1767
+ location: token.loc,
1768
+ message: `unexpected token ${EnumToken[token.typ]} at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
1769
+ });
1333
1770
  }
1334
- // @ts-ignore
1335
- if (tokens[1]?.typ == EnumToken.EndParensTokenType) {
1336
- tokens.splice(1, 1);
1771
+ }
1772
+ }
1773
+ // @ts-expect-error
1774
+ return Object.defineProperties(Object.assign(atRule, {
1775
+ typ: success ? EnumToken.AtRuleNodeType : EnumToken.InvalidRuleNodeType,
1776
+ val: renderTokens(trimWhiteSpaceTokens(stream), options),
1777
+ chi: [],
1778
+ }), {
1779
+ loc: {
1780
+ ...definedPropertySettings,
1781
+ value: { ...atRule.loc, end: (stream.at(-1) ?? atRule).loc.end },
1782
+ },
1783
+ tokens: { ...definedPropertySettings, value: stream },
1784
+ });
1785
+ }
1786
+ case "container": {
1787
+ const result = parseAtRuleContainerQueryList(stream, atRule, options);
1788
+ if (result.errors.length > 0) {
1789
+ errors.push(...result.errors);
1790
+ }
1791
+ // @ts-expect-error
1792
+ return Object.defineProperties(Object.assign(atRule, {
1793
+ typ: result.success ? EnumToken.AtRuleNodeType : EnumToken.InvalidRuleNodeType,
1794
+ val: renderTokens(trimWhiteSpaceTokens(stream), options),
1795
+ chi: [],
1796
+ }), {
1797
+ loc: {
1798
+ ...definedPropertySettings,
1799
+ value: { ...atRule.loc, end: (stream.at(-1) ?? atRule).loc.end },
1800
+ },
1801
+ tokens: { ...definedPropertySettings, value: stream },
1802
+ });
1803
+ }
1804
+ case "custom-media": {
1805
+ const tokens = trimArray(stream.slice(1));
1806
+ const result = matchAllSyntax(syntax, createValidationContext(tokens), options);
1807
+ if (result.errors.length > 0) {
1808
+ errors.push(...result.errors);
1809
+ }
1810
+ // @ts-expect-error
1811
+ options = { ...options, convertColor: false };
1812
+ // @ts-expect-error
1813
+ return Object.defineProperties(Object.assign(atRule, {
1814
+ typ: result.success ? EnumToken.AtRuleNodeType : EnumToken.InvalidRuleNodeType,
1815
+ val: renderTokens(trimWhiteSpaceTokens(tokens), options),
1816
+ }), {
1817
+ loc: {
1818
+ ...definedPropertySettings,
1819
+ value: { ...atRule.loc, end: (tokens.at(-1) ?? atRule).loc.end },
1820
+ },
1821
+ tokens: { ...definedPropertySettings, value: tokens },
1822
+ });
1823
+ }
1824
+ case "keyframes": {
1825
+ const tokens = trimArray(stream.slice(1));
1826
+ const filtered = stream.filter((t) => t.typ !== EnumToken.WhitespaceTokenType && t.typ !== EnumToken.CommentTokenType);
1827
+ if (filtered.length != 1 ||
1828
+ (filtered[0].typ !== EnumToken.IdenTokenType &&
1829
+ filtered[0].typ !== EnumToken.StringTokenType &&
1830
+ filtered[0].typ !== EnumToken.DashedIdenTokenType)) {
1831
+ errors.push({
1832
+ action: "drop",
1833
+ node: atRule,
1834
+ location: atRule.loc,
1835
+ message: `expected <keyframe-name> at ${atRule.loc.src}:${atRule.loc.sta.lin}:${atRule.loc.sta.col}`,
1836
+ });
1837
+ success = false;
1838
+ }
1839
+ // @ts-expect-error
1840
+ options = { ...options, convertColor: false };
1841
+ // @ts-expect-error
1842
+ return Object.defineProperties(Object.assign(atRule, {
1843
+ typ: success ? EnumToken.KeyframesAtRuleNodeType : EnumToken.InvalidRuleNodeType,
1844
+ val: renderTokens(tokens, options),
1845
+ chi: [],
1846
+ }), {
1847
+ loc: {
1848
+ ...definedPropertySettings,
1849
+ value: { ...atRule.loc, end: (tokens.at(-1) ?? atRule).loc.end },
1850
+ },
1851
+ tokens: { ...definedPropertySettings, value: tokens },
1852
+ });
1853
+ }
1854
+ case "namespace": {
1855
+ const result = matchAllSyntax(syntax, createValidationContext(stream), options);
1856
+ if (!result.success) {
1857
+ errors.push(...result.errors);
1858
+ }
1859
+ const valid = blockAllowed === parseAsBlock && result.success;
1860
+ if (valid) {
1861
+ let start = 0;
1862
+ let end = -1;
1863
+ let hasString = false;
1864
+ for (start = 0; start < stream.length; start++) {
1865
+ if (stream[start].typ == EnumToken.UrlFunctionTokenDefType) {
1866
+ start++;
1867
+ for (end = start; end < stream.length; end++) {
1868
+ if (stream[end].typ == EnumToken.EndParensTokenType) {
1869
+ break;
1870
+ }
1871
+ if (stream[end].typ === EnumToken.StringTokenType) {
1872
+ hasString = true;
1873
+ }
1874
+ }
1875
+ break;
1337
1876
  }
1338
1877
  }
1878
+ // replace url(string) -> string
1879
+ if (hasString) {
1880
+ stream.splice(start - 1, end - start + 2, ...stream.slice(start, end));
1881
+ }
1882
+ }
1883
+ // @ts-expect-error
1884
+ options = { ...options, convertColor: false };
1885
+ // @ts-expect-error
1886
+ return Object.defineProperties(Object.assign(atRule, {
1887
+ typ: valid ? EnumToken.AtRuleNodeType : EnumToken.InvalidAtRuleNodeType,
1888
+ val: trimArray(stream).reduce((acc, t, index) => acc +
1889
+ (t.typ === EnumToken.CommentTokenType ||
1890
+ (t.typ === EnumToken.WhitespaceTokenType &&
1891
+ stream[index + 1]?.typ === EnumToken.CommentTokenType &&
1892
+ (stream.length < index + 3 || stream[index + 2]?.typ === EnumToken.WhitespaceTokenType))
1893
+ ? ""
1894
+ : renderToken(t, options)), ""),
1895
+ ...(parseAsBlock ? { chi: [] } : {}),
1896
+ }), {
1897
+ tokens: { ...definedPropertySettings, value: stream.slice() },
1898
+ loc: {
1899
+ ...definedPropertySettings,
1900
+ value: { ...atRule.loc, end: { ...(stream.at(-1)?.loc?.end ?? atRule.loc.end) } },
1901
+ },
1902
+ });
1903
+ }
1904
+ case "import": {
1905
+ const result = matchAtRuleImportSyntax(atRule, stream, context, options);
1906
+ if (result.errors.length > 0) {
1907
+ errors.push(...result.errors);
1339
1908
  }
1909
+ else {
1910
+ if (stream[0]?.typ == EnumToken.UrlFunctionTokenType &&
1911
+ stream[0].chi.some((t) => t.typ == EnumToken.StringTokenType)) {
1912
+ stream.splice(0, 1, ...stream[0].chi);
1913
+ }
1914
+ }
1915
+ // @ts-expect-error
1916
+ return Object.defineProperties(Object.assign(atRule, {
1917
+ typ: result.success ? EnumToken.AtRuleNodeType : EnumToken.InvalidRuleNodeType,
1918
+ val: stream.reduce((acc, t, index) => acc +
1919
+ (t.typ === EnumToken.CommentTokenType ||
1920
+ (t.typ === EnumToken.WhitespaceTokenType &&
1921
+ stream[index + 1]?.typ === EnumToken.CommentTokenType &&
1922
+ (stream.length < index + 3 || stream[index + 2]?.typ === EnumToken.WhitespaceTokenType))
1923
+ ? ""
1924
+ : renderToken(t, options)), ""),
1925
+ }), {
1926
+ tokens: { ...definedPropertySettings, value: stream.slice() },
1927
+ loc: {
1928
+ ...definedPropertySettings,
1929
+ value: { ...atRule.loc, end: { ...(stream.at(-1)?.loc?.end ?? atRule.loc.end) } },
1930
+ },
1931
+ });
1340
1932
  }
1341
- // https://www.w3.org/TR/css-nesting-1/#conditionals
1342
- // allowed nesting at-rules
1343
- // there must be a top level rule in the stack
1344
- if (atRule.val == 'charset') {
1345
- let spaces = 0;
1346
- // https://developer.mozilla.org/en-US/docs/Web/CSS/@charset
1347
- for (let k = 0; k < rawTokens.length; k++) {
1348
- if (rawTokens[k].hint == EnumToken.WhitespaceTokenType) {
1349
- spaces += rawTokens[k].len;
1350
- continue;
1933
+ case "supports":
1934
+ case "when":
1935
+ case "else": {
1936
+ trimWhiteSpaceTokens(stream);
1937
+ const result = atRuleName === "supports"
1938
+ ? parseAtRuleSupportSyntax(stream, atRule, options)
1939
+ : matchAtRuleWhenElseSyntax(stream, atRule, options);
1940
+ if (result.errors.length > 0) {
1941
+ errors.push(...result.errors);
1942
+ }
1943
+ let success = true;
1944
+ if (atRule.nam === "else") {
1945
+ const siblings = context.chi;
1946
+ let sibling = null;
1947
+ let l = siblings.length;
1948
+ while (l--) {
1949
+ if (siblings[l].typ === EnumToken.WhitespaceTokenType ||
1950
+ siblings[l].typ === EnumToken.CommentTokenType ||
1951
+ siblings[l].typ === EnumToken.CDOCOMMTokenType) {
1952
+ continue;
1953
+ }
1954
+ sibling = siblings[l];
1955
+ break;
1351
1956
  }
1352
- if (rawTokens[k].hint == EnumToken.CommentTokenType) {
1353
- continue;
1957
+ let missingWhen = false;
1958
+ let definedAfterLastElse = false;
1959
+ if (sibling == null || sibling.typ !== EnumToken.AtRuleNodeType) {
1960
+ missingWhen = true;
1354
1961
  }
1355
- if (rawTokens[k].hint == EnumToken.CDOCOMMTokenType) {
1356
- continue;
1962
+ else if (sibling.nam !== "when") {
1963
+ if (sibling.nam !== "else") {
1964
+ missingWhen = true;
1965
+ }
1966
+ else if (sibling.val === "") {
1967
+ definedAfterLastElse = true;
1968
+ }
1357
1969
  }
1358
- if (spaces > 1) {
1970
+ if (missingWhen) {
1971
+ success = false;
1359
1972
  errors.push({
1360
- action: 'drop',
1361
- message: '@charset must have only one space',
1362
- // @ts-ignore
1363
- location, rawTokens: [atRule, ...tokens]
1973
+ action: "drop",
1974
+ node: atRule,
1975
+ location: atRule.loc,
1976
+ message: "at-rule @when is required before @else block",
1364
1977
  });
1365
- return null;
1366
1978
  }
1367
- if (rawTokens[k].hint != EnumToken.StringTokenType || rawTokens[k].token[0] != '"') {
1979
+ else if (definedAfterLastElse) {
1980
+ success = false;
1368
1981
  errors.push({
1369
- action: 'drop',
1370
- message: '@charset expects a "<charset>"',
1371
- location
1982
+ action: "drop",
1983
+ node: atRule,
1984
+ location: atRule.loc,
1985
+ message: "at-rule @else block is defined after last @else block",
1372
1986
  });
1373
- return null;
1374
1987
  }
1375
- break;
1376
- }
1377
- if (options.removeCharset) {
1378
- return null;
1379
1988
  }
1989
+ // @ts-expect-error
1990
+ options = { ...options, minify: false, convertColor: false };
1991
+ // @ts-expect-error
1992
+ return Object.defineProperties(Object.assign(atRule, {
1993
+ typ: success && result.success ? EnumToken.AtRuleNodeType : EnumToken.InvalidRuleNodeType,
1994
+ val: renderTokens(stream, options),
1995
+ chi: [],
1996
+ }), {
1997
+ tokens: { ...definedPropertySettings, value: stream.slice() },
1998
+ loc: {
1999
+ ...definedPropertySettings,
2000
+ value: { ...atRule.loc, end: { ...(stream.at(-1)?.loc?.end ?? atRule.loc.end) } },
2001
+ },
2002
+ });
1380
2003
  }
1381
- const t = parseAtRulePrelude(parseTokens(tokens, { minify: options.minify }), atRule);
1382
- const raw = [];
1383
- for (const curr of t) {
1384
- raw.push(renderToken(curr, { removeComments: true, convertColor: false }));
1385
- }
1386
- const nam = renderToken(atRule, { removeComments: true });
1387
- // @ts-ignore
1388
- const node = {
1389
- typ: /^(-[a-z]+-)?keyframes$/.test(nam) ? EnumToken.KeyframesAtRuleNodeType : EnumToken.AtRuleNodeType,
1390
- nam,
1391
- val: raw.join('')
1392
- };
1393
- Object.defineProperties(node, {
1394
- tokens: { ...definedPropertySettings, enumerable: false, value: t.slice() },
1395
- raw: { ...definedPropertySettings, value: raw }
1396
- });
1397
- if (delim.typ == EnumToken.BlockStartTokenType) {
1398
- node.chi = [];
2004
+ case "media": {
2005
+ options = { ...options, parseColor: false };
2006
+ const result = parseMediaqueryList(stream, options);
2007
+ if (result.errors.length > 0) {
2008
+ errors.push(...result.errors);
2009
+ }
2010
+ // @ts-expect-error
2011
+ return Object.defineProperties(Object.assign(atRule, {
2012
+ typ: result.success ? EnumToken.AtRuleNodeType : EnumToken.InvalidRuleNodeType,
2013
+ val: renderTokens(stream, options),
2014
+ chi: [],
2015
+ }), {
2016
+ tokens: { ...definedPropertySettings, value: stream.slice() },
2017
+ loc: {
2018
+ ...definedPropertySettings,
2019
+ value: { ...atRule.loc, end: { ...(stream.at(-1)?.loc?.end ?? atRule.loc.end) } },
2020
+ },
2021
+ });
1399
2022
  }
1400
- loc = map.get(atRule);
1401
- Object.defineProperty(node, 'loc', {
1402
- ...definedPropertySettings,
1403
- value: loc,
1404
- enumerable: options.sourcemap !== false
1405
- });
1406
- node.loc.end = { ...map.get(delim).end };
1407
- let isValid = true;
1408
- if (node.nam == 'else') {
1409
- const prev = getLastNode(context);
1410
- if (prev != null && prev.typ == EnumToken.AtRuleNodeType && ['when', 'else'].includes(prev.nam)) {
1411
- if (prev.nam == 'else') {
1412
- isValid = Array.isArray(prev.tokens) && prev.tokens.length > 0;
1413
- }
2023
+ case "scope": {
2024
+ let context = createValidationContext(trimArray(stream));
2025
+ let success = true;
2026
+ // @ts-ignore
2027
+ let range = context.peekRange((t) => t.typ === EnumToken.EndParensTokenType);
2028
+ if (range[0]?.typ !== EnumToken.StartParensTokenType) {
2029
+ errors.push({
2030
+ action: "drop",
2031
+ node: range[0] ?? atRule,
2032
+ location: (range[0] ?? atRule).loc,
2033
+ message: "expected '(' at start of @scope block",
2034
+ });
2035
+ success = false;
1414
2036
  }
1415
- else {
1416
- isValid = false;
2037
+ else if (range.at(-1)?.typ !== EnumToken.EndParensTokenType) {
2038
+ errors.push({
2039
+ action: "drop",
2040
+ node: range.at(-1) ?? atRule,
2041
+ location: (range.at(-1) ?? atRule).loc,
2042
+ message: "expected ')' at end of @scope block",
2043
+ });
2044
+ success = false;
1417
2045
  }
1418
- }
1419
- if (node.nam == 'value') {
1420
- let i = 0;
1421
- while (i < tokens.length) {
1422
- if (tokens[i].typ == EnumToken.WhitespaceTokenType || tokens[i].typ == EnumToken.CommentTokenType) {
1423
- i++;
1424
- continue;
2046
+ else {
2047
+ const srange = range.slice(1, -1);
2048
+ const result = matchSelectorSyntax(srange, errors, options, true);
2049
+ if (!result.success) {
2050
+ success = false;
2051
+ }
2052
+ else {
2053
+ stream.splice(stream.indexOf(range[0]) + 1, range.length - 2, ...trimWhiteSpaceTokens(srange));
1425
2054
  }
1426
- break;
1427
2055
  }
1428
- if (i < tokens.length) {
1429
- if (tokens[i].typ == EnumToken.IdenTokenType || isIdentColor(tokens[i])) {
1430
- let k = i + 1;
1431
- while (k < tokens.length) {
1432
- if (tokens[k].typ == EnumToken.WhitespaceTokenType || tokens[k].typ == EnumToken.CommentTokenType) {
1433
- k++;
1434
- continue;
2056
+ let index = stream.indexOf(range.at(-1));
2057
+ if (stream.length > index + 1) {
2058
+ while (stream[++index]?.typ === EnumToken.WhitespaceTokenType ||
2059
+ stream[index]?.typ === EnumToken.CommentTokenType)
2060
+ ;
2061
+ if (index < stream.length) {
2062
+ if (stream[index].typ !== EnumToken.IdenTokenType ||
2063
+ "to" !== stream[index].val.toLowerCase()) {
2064
+ errors.push({
2065
+ action: "drop",
2066
+ node: stream[index],
2067
+ location: stream[index]?.loc,
2068
+ message: "expected 'to' at end of @scope block",
2069
+ });
2070
+ success = false;
2071
+ }
2072
+ else {
2073
+ while (stream[++index]?.typ === EnumToken.WhitespaceTokenType ||
2074
+ stream[index]?.typ === EnumToken.CommentTokenType)
2075
+ ;
2076
+ if (stream[index].typ !== EnumToken.StartParensTokenType) {
2077
+ errors.push({
2078
+ action: "drop",
2079
+ node: stream[index],
2080
+ location: stream[index]?.loc,
2081
+ message: "expected 'to' at end of @scope block",
2082
+ });
2083
+ success = false;
1435
2084
  }
1436
- // var or import
1437
- if (tokens[k].typ == EnumToken.ColonTokenType) {
1438
- let j = k;
1439
- while (++j < tokens.length) {
1440
- if (tokens[j].typ != EnumToken.WhitespaceTokenType && tokens[j].typ != EnumToken.CommentTokenType) {
1441
- break;
1442
- }
1443
- }
1444
- let offset = k + 1;
1445
- while (offset < tokens.length && tokens[offset].typ == EnumToken.WhitespaceTokenType) {
1446
- offset++;
1447
- }
1448
- if (tokens[j].typ == EnumToken.StringTokenType) {
1449
- Object.assign(node, {
1450
- typ: EnumToken.CssVariableImportTokenType,
1451
- nam: tokens[i].val,
1452
- val: tokens.slice(offset)
2085
+ else {
2086
+ context = createValidationContext(stream.slice(index));
2087
+ // @ts-ignore
2088
+ range = context.peekRange((t) => t.typ === EnumToken.EndParensTokenType);
2089
+ if (range.at(-1)?.typ !== EnumToken.EndParensTokenType) {
2090
+ errors.push({
2091
+ action: "drop",
2092
+ node: range.at(-1) ?? atRule,
2093
+ location: (range.at(-1) ?? atRule).loc,
2094
+ message: "expected ')' at end of @scope block",
1453
2095
  });
1454
- delete node.tokens;
1455
- context.chi.push(node);
1456
- return null;
2096
+ success = false;
2097
+ }
2098
+ else {
2099
+ const srange = range.slice(1, -1);
2100
+ const result = matchSelectorSyntax(srange, errors, options, true);
2101
+ if (!result.success) {
2102
+ success = false;
2103
+ }
2104
+ else {
2105
+ stream.splice(stream.indexOf(range[0]) + 1, range.length - 2, ...trimWhiteSpaceTokens(srange));
2106
+ }
1457
2107
  }
1458
- Object.assign(node, {
1459
- typ: EnumToken.CssVariableTokenType,
1460
- nam: tokens[i].val,
1461
- val: tokens.slice(offset)
1462
- });
1463
- context.chi.push(node);
1464
- return null;
1465
- }
1466
- if (tokens[k].typ == EnumToken.PseudoClassTokenType) {
1467
- Object.assign(tokens[k], {
1468
- typ: EnumToken.IdenTokenType,
1469
- val: tokens[k].val.slice(1)
1470
- });
1471
- Object.assign(node, {
1472
- typ: EnumToken.CssVariableTokenType,
1473
- nam: tokens[i].val,
1474
- val: tokens.slice(k)
1475
- });
1476
- context.chi.push(node);
1477
- return null;
1478
2108
  }
1479
- if (tokens[k].typ == EnumToken.CommaTokenType) {
1480
- let j = i;
1481
- while (++j < tokens.length) {
1482
- if (tokens[j].typ == EnumToken.IdenTokenType && tokens[j].val.toLowerCase() == 'from') {
1483
- const vars = tokens.slice(i, j);
1484
- const from = tokens.slice(j + 1);
1485
- let l = 0;
1486
- let expect = EnumToken.IdenTokenType;
1487
- for (; l < vars.length; l++) {
1488
- if (vars[l].typ == EnumToken.WhitespaceTokenType || vars[l].typ == EnumToken.CommentTokenType) {
1489
- continue;
1490
- }
1491
- if (expect == vars[l].typ || (expect == EnumToken.IdenTokenType && isIdentColor(vars[l]))) {
1492
- expect = expect == EnumToken.CommaTokenType ? EnumToken.IdenTokenType : EnumToken.CommaTokenType;
1493
- continue;
1494
- }
1495
- errors.push({
1496
- action: 'drop',
1497
- node: node,
1498
- location: map.get(vars[l]) ?? location,
1499
- message: `expecting '${EnumToken[expect]}' but found ${renderToken(vars[l])}`
1500
- });
1501
- return null;
1502
- }
1503
- l = 0;
1504
- expect = EnumToken.IdenTokenType;
1505
- for (; l < from.length; l++) {
1506
- if (from[l].typ == EnumToken.WhitespaceTokenType || from[l].typ == EnumToken.CommentTokenType) {
1507
- continue;
1508
- }
1509
- if (expect == from[l].typ || isIdentColor(from[l])) {
1510
- while (++l < from.length) {
1511
- if (from[l].typ == EnumToken.WhitespaceTokenType || from[l].typ == EnumToken.CommentTokenType) {
1512
- continue;
1513
- }
1514
- errors.push({
1515
- action: 'drop',
1516
- node: node,
1517
- location: map.get(from[l]) ?? location,
1518
- message: `unexpected '${renderToken(from[l])}'`
1519
- });
1520
- return null;
1521
- }
1522
- break;
1523
- }
1524
- errors.push({
1525
- action: 'drop',
1526
- node: node,
1527
- location: map.get(from[l]) ?? location,
1528
- message: `expecting <string> but found ${renderToken(from[l])}`
1529
- });
1530
- return null;
1531
- }
1532
- // @ts-ignore
1533
- delete node.nam;
1534
- // @ts-ignore
1535
- delete node.val;
1536
- Object.assign(node, {
1537
- typ: EnumToken.CssVariableDeclarationMapTokenType,
1538
- vars,
1539
- from
1540
- });
1541
- context.chi.push(node);
1542
- return null;
1543
- }
1544
- }
1545
- }
1546
- k++;
1547
2109
  }
1548
- Object.assign(node, {
1549
- typ: EnumToken.CssVariableTokenType,
1550
- nam: tokens[i].val,
1551
- val: tokens.slice(k)
1552
- });
1553
- context.chi.push(node);
1554
- return null;
1555
2110
  }
1556
2111
  }
1557
- }
1558
- // @ts-ignore
1559
- const skipValidate = (options.validation & ValidationLevel.AtRule) == 0;
1560
- const isAllowed = skipValidate || isNodeAllowedInContext(node, context);
1561
- // @ts-ignore
1562
- const valid = skipValidate ? {
1563
- valid: SyntaxValidationResult.Valid,
1564
- error: '',
1565
- node,
1566
- syntax: '@' + node.nam
1567
- } : !isAllowed ? {
1568
- valid: SyntaxValidationResult.Drop,
1569
- node,
1570
- syntax: '@' + node.nam,
1571
- error: `${EnumToken[context.typ]}: child ${EnumToken[node.typ]} not allowed in context${context.typ == EnumToken.AtRuleNodeType ? ` '@${context.nam}'` : context.typ == EnumToken.StyleSheetNodeType ? ` 'stylesheet'` : ''}`} : isValid ? (node.typ == EnumToken.KeyframesAtRuleNodeType ? validateAtRuleKeyframes(node) : validateAtRule(node, options, context)) : {
1572
- valid: SyntaxValidationResult.Drop,
1573
- node,
1574
- syntax: '@' + node.nam,
1575
- error: '@' + node.nam + ' not allowed here'};
1576
- if (valid.valid == SyntaxValidationResult.Drop) {
1577
- let message = '';
1578
- for (const token of tokens) {
1579
- message += renderToken(token, { minify: false });
1580
- }
1581
- errors.push({
1582
- action: 'drop',
1583
- message: valid.error + ' - "' + message + '"',
1584
- node,
1585
- // @ts-ignore
1586
- location: { src, ...(map.get(valid.node) ?? location) }
2112
+ // @ts-expect-error
2113
+ return Object.defineProperties(Object.assign(atRule, {
2114
+ typ: success ? EnumToken.AtRuleNodeType : EnumToken.InvalidRuleNodeType,
2115
+ val: renderTokens(stream, options),
2116
+ chi: [],
2117
+ }), {
2118
+ tokens: { ...definedPropertySettings, value: stream.slice() },
2119
+ loc: {
2120
+ ...definedPropertySettings,
2121
+ value: { ...atRule.loc, end: { ...(stream.at(-1)?.loc?.end ?? atRule.loc.end) } },
2122
+ },
1587
2123
  });
1588
- // @ts-ignore
1589
- node.typ = EnumToken.InvalidAtRuleTokenType;
1590
- }
1591
- else {
1592
- node.val = '';
1593
- for (const token of node.tokens) {
1594
- node.val += renderToken(token, {
1595
- minify: false,
1596
- convertColor: false,
1597
- removeComments: true
1598
- });
1599
- }
1600
2124
  }
1601
- context.chi.push(node);
1602
- stats.nodesCount++;
1603
- Object.defineProperties(node, {
1604
- parent: { ...definedPropertySettings, value: context },
1605
- validSyntax: { ...definedPropertySettings, value: valid.valid == SyntaxValidationResult.Valid }
1606
- });
1607
- return node;
1608
- }
1609
- else {
1610
- // rule
1611
- if (delim.typ == EnumToken.BlockStartTokenType) {
1612
- const location = map.get(tokens[0]);
1613
- const uniq = new Map;
1614
- parseTokens(tokens, { minify: true });
1615
- const ruleType = context.typ == EnumToken.KeyframesAtRuleNodeType ? EnumToken.KeyFramesRuleNodeType : EnumToken.RuleNodeType;
1616
- if (ruleType == EnumToken.RuleNodeType) {
1617
- parseSelector(tokens);
1618
- }
1619
- const node = {
1620
- typ: ruleType,
1621
- sel: [...tokens.reduce((acc, curr, index, array) => {
1622
- if (curr.typ == EnumToken.CommentTokenType) {
1623
- return acc;
1624
- }
1625
- if (options.minify) {
1626
- if (curr.typ == EnumToken.PseudoClassFuncTokenType && curr.val == ':nth-child') {
1627
- let i = 0;
1628
- for (; i < curr.chi.length; i++) {
1629
- if (curr.chi[i].typ == EnumToken.IdenTokenType && curr.chi[i].val == 'even') {
1630
- Object.assign(curr.chi[i], {
1631
- typ: EnumToken.Dimension,
1632
- val: 2,
1633
- unit: 'n'
1634
- });
1635
- }
1636
- else if (curr.chi[i].typ == EnumToken.Dimension &&
1637
- curr.chi[i].val == 2 &&
1638
- curr.chi[i].unit == 'n' &&
1639
- curr.chi[i + 1]?.typ == EnumToken.WhitespaceTokenType &&
1640
- curr.chi[i + 2]?.typ == EnumToken.LiteralTokenType &&
1641
- curr.chi[i + 2].val == '+' &&
1642
- curr.chi[i + 3]?.typ == EnumToken.WhitespaceTokenType &&
1643
- curr.chi[i + 4]?.typ == EnumToken.NumberTokenType &&
1644
- curr.chi[i + 4].val == 1) {
1645
- curr.chi.splice(i, 5, Object.assign(curr.chi[i], {
1646
- typ: EnumToken.IdenTokenType,
1647
- val: 'odd'
1648
- }));
1649
- }
1650
- }
1651
- }
1652
- }
1653
- if (curr.typ == EnumToken.WhitespaceTokenType) {
1654
- if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
1655
- trimWhiteSpace.includes(array[index + 1]?.typ) ||
1656
- combinators.includes(array[index - 1]?.val) ||
1657
- combinators.includes(array[index + 1]?.val)) {
1658
- return acc;
1659
- }
1660
- }
1661
- if (ruleType == EnumToken.KeyFramesRuleNodeType && options.minify) {
1662
- if (curr.typ == EnumToken.IdenTokenType && curr.val == 'from') {
1663
- Object.assign(curr, { typ: EnumToken.PercentageTokenType, val: '0' });
1664
- }
1665
- else if (curr.typ == EnumToken.PercentageTokenType && curr.val == 100) {
1666
- Object.assign(curr, { typ: EnumToken.IdenTokenType, val: 'to' });
1667
- }
1668
- }
1669
- let t = renderToken(curr, { minify: false });
1670
- if (t == ',') {
1671
- acc.push([]);
1672
- }
1673
- else {
1674
- acc[acc.length - 1].push(t);
1675
- }
1676
- return acc;
1677
- }, [[]]).reduce((acc, curr) => {
1678
- let i = 0;
1679
- for (; i < curr.length; i++) {
1680
- if (i + 1 < curr.length && curr[i] == '*') {
1681
- if (curr[i] == '*') {
1682
- let index = curr[i + 1] == ' ' ? 2 : 1;
1683
- if (!['>', '~', '+'].includes(curr[index])) {
1684
- curr.splice(i, index);
1685
- }
1686
- }
1687
- }
1688
- }
1689
- acc.set(curr.join(''), curr);
1690
- return acc;
1691
- }, uniq).keys()].join(','),
1692
- chi: []
1693
- };
1694
- Object.defineProperty(node, 'tokens', {
1695
- ...definedPropertySettings,
1696
- enumerable: false,
1697
- value: tokens.slice()
1698
- });
1699
- loc = location;
1700
- Object.defineProperty(node, 'loc', {
1701
- ...definedPropertySettings,
1702
- value: loc,
1703
- enumerable: options.sourcemap !== false
2125
+ case "page": {
2126
+ trimArray(stream);
2127
+ parseAtRulePage(atRule, stream, options, errors);
2128
+ // @ts-expect-error
2129
+ return Object.defineProperties(Object.assign(atRule, {
2130
+ typ: success ? EnumToken.AtRuleNodeType : EnumToken.InvalidRuleNodeType,
2131
+ val: renderTokens(stream, options),
2132
+ chi: [],
2133
+ }), {
2134
+ tokens: { ...definedPropertySettings, value: stream.slice() },
2135
+ loc: {
2136
+ ...definedPropertySettings,
2137
+ value: { ...atRule.loc, end: { ...(stream.at(-1)?.loc?.end ?? atRule.loc.end) } },
2138
+ },
1704
2139
  });
1705
- context.chi.push(node);
1706
- Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: context });
1707
- // @ts-ignore
1708
- const skipValidate = (options.validation & ValidationLevel.Selector) == 0;
1709
- const isAllowed = skipValidate || isNodeAllowedInContext(node, context);
1710
- // @ts-ignore
1711
- const valid = skipValidate ? {
1712
- valid: SyntaxValidationResult.Valid,
1713
- error: null
1714
- } : !isAllowed ? {
1715
- valid: SyntaxValidationResult.Drop,
1716
- error: `${EnumToken[context.typ]}: child ${EnumToken[node.typ]} not allowed in context${context.typ == EnumToken.AtRuleNodeType ? ` '@${context.nam}'` : context.typ == EnumToken.StyleSheetNodeType ? ` 'stylesheet'` : ''}`
1717
- } : ruleType == EnumToken.KeyFramesRuleNodeType ? validateKeyframeSelector(tokens) : validateSelector(tokens, options, context);
1718
- if (valid.valid != SyntaxValidationResult.Valid) {
1719
- // @ts-ignore
1720
- node.typ = EnumToken.InvalidRuleTokenType;
1721
- node.sel = tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '');
1722
- errors.push({
1723
- action: 'drop',
1724
- message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
1725
- node,
1726
- // @ts-ignore
1727
- location
1728
- });
1729
- }
1730
- Object.defineProperty(node, 'validSyntax', {
1731
- ...definedPropertySettings,
1732
- value: valid.valid == SyntaxValidationResult.Valid
1733
- });
1734
- return node;
1735
2140
  }
1736
- else {
1737
- let name = null;
1738
- let value = null;
1739
- let i = 0;
1740
- for (; i < tokens.length; i++) {
1741
- if (tokens[i].typ == EnumToken.LiteralTokenType && tokens[i].val.length > 1) {
1742
- const start = tokens[i].val.charAt(0);
1743
- const val = tokens[i].val.slice(1);
1744
- if (['/', '*'].includes(start) && isNumber(val)) {
1745
- tokens.splice(i, 1, {
1746
- typ: EnumToken.LiteralTokenType,
1747
- val: tokens[i].val.charAt(0)
1748
- }, {
1749
- typ: EnumToken.NumberTokenType,
1750
- val: +tokens[i].val.slice(1)
1751
- });
1752
- }
1753
- else if (start == '/' && isFunction(val)) {
1754
- tokens.splice(i, 1, { typ: EnumToken.LiteralTokenType, val: '/' }, getTokenType(val));
1755
- }
1756
- }
1757
- }
1758
- parseTokens(tokens, { ...options, parseColor: true });
1759
- for (i = 0; i < tokens.length; i++) {
1760
- if (tokens[i].typ == EnumToken.CommentTokenType) {
1761
- continue;
1762
- }
1763
- if (name == null && [EnumToken.IdenTokenType, EnumToken.DashedIdenTokenType].includes(tokens[i].typ)) {
1764
- name = tokens.slice(0, i + 1);
1765
- }
1766
- else if (name == null && tokens[i].typ == EnumToken.ColorTokenType && [ColorType.SYS, ColorType.DPSYS].includes(tokens[i].kin)) {
1767
- name = tokens.slice(0, i + 1);
1768
- tokens[i].typ = EnumToken.IdenTokenType;
1769
- }
1770
- else if (name != null && funcLike.concat([
1771
- EnumToken.LiteralTokenType,
1772
- EnumToken.IdenTokenType, EnumToken.DashedIdenTokenType,
1773
- EnumToken.PseudoClassTokenType, EnumToken.PseudoClassFuncTokenType
1774
- ]).includes(tokens[i].typ)) {
1775
- if (tokens[i].val?.charAt?.(0) == ':') {
1776
- Object.assign(tokens[i], getTokenType(tokens[i].val.slice(1)));
1777
- if ('chi' in tokens[i]) {
1778
- tokens[i].typ = EnumToken.FunctionTokenType;
1779
- if (colorsFunc.includes(tokens[i].val) && isColor(tokens[i])) {
1780
- parseColor(tokens[i]);
1781
- }
1782
- }
1783
- tokens.splice(i--, 0, { typ: EnumToken.ColonTokenType });
1784
- continue;
1785
- }
1786
- if ('chi' in tokens[i]) {
1787
- tokens[i].typ = EnumToken.FunctionTokenType;
1788
- }
1789
- value = tokens.slice(i);
1790
- }
1791
- if (tokens[i].typ == EnumToken.ColonTokenType) {
1792
- name = tokens.slice(0, i);
1793
- value = tokens.slice(i + 1);
1794
- break;
1795
- }
1796
- }
1797
- if (name == null) {
1798
- name = tokens;
1799
- }
1800
- const location = map.get(name[0]);
1801
- if (name.length > 0) {
1802
- for (let i = 1; i < name.length; i++) {
1803
- if (name[i].typ != EnumToken.WhitespaceTokenType && name[i].typ != EnumToken.CommentTokenType) {
1804
- errors.push({
1805
- action: 'drop',
1806
- message: 'doParse: invalid declaration',
1807
- location
1808
- });
1809
- return null;
1810
- }
1811
- }
1812
- }
1813
- const nam = renderToken(name.shift(), { removeComments: true });
1814
- if (value == null || (!nam.startsWith('--') && value.length == 0)) {
2141
+ case "top-left-corner":
2142
+ case "top-left":
2143
+ case "top-center":
2144
+ case "top-right":
2145
+ case "top-right-corner":
2146
+ case "bottom-left-corner":
2147
+ case "bottom-left":
2148
+ case "bottom-right":
2149
+ case "bottom-right-corner":
2150
+ case "left-top":
2151
+ case "left-middle":
2152
+ case "left-bottom":
2153
+ case "right-top":
2154
+ case "right-middle":
2155
+ case "right-bottom": {
2156
+ if (context.typ !== EnumToken.AtRuleNodeType || context.nam !== "page") {
2157
+ success = false;
1815
2158
  errors.push({
1816
- action: 'drop',
1817
- message: 'doParse: invalid declaration',
1818
- location
2159
+ action: "drop",
2160
+ node: atRule,
2161
+ location: atRule.loc,
2162
+ message: "node is allowd only in @page rule",
1819
2163
  });
1820
- if (options.lenient) {
1821
- const node = {
1822
- typ: EnumToken.InvalidDeclarationNodeType,
1823
- nam,
1824
- val: []
1825
- };
1826
- Object.defineProperty(node, 'loc', {
1827
- ...definedPropertySettings,
1828
- value: location,
1829
- enumerable: options.sourcemap !== false
1830
- });
1831
- context.chi.push(node);
1832
- stats.nodesCount++;
1833
- }
1834
- return null;
1835
2164
  }
1836
- for (const { value: token } of walkValues(value, null, {
1837
- fn: (node) => node.typ == EnumToken.FunctionTokenType && node.val == 'calc' ? WalkerOptionEnum.IgnoreChildren : null,
1838
- type: EnumToken.FunctionTokenType
1839
- })) {
1840
- if (token.typ == EnumToken.FunctionTokenType && token.val == 'calc') {
1841
- for (const { value: node, parent } of walkValues(token.chi, token)) {
1842
- // fix expressions starting with '/' or '*' such as '/4' in (1 + 1)/4
1843
- if (node.typ == EnumToken.LiteralTokenType && node.val.length > 0) {
1844
- if (node.val[0] == '/' || node.val[0] == '*') {
1845
- parent.chi.splice(parent.chi.indexOf(node), 1, { typ: node.val[0] == '/' ? EnumToken.Div : EnumToken.Mul }, ...parseString(node.val.slice(1)));
1846
- }
1847
- }
1848
- }
1849
- }
1850
- }
1851
- const node = {
1852
- typ: EnumToken.DeclarationNodeType,
1853
- nam,
1854
- val: value
1855
- };
1856
- Object.defineProperty(node, 'loc', {
1857
- ...definedPropertySettings,
1858
- value: location,
1859
- enumerable: options.sourcemap !== false
1860
- });
1861
- node.loc.end = { ...map.get(delim).end };
1862
- // do not allow declarations in style sheets
1863
- if (context.typ == EnumToken.StyleSheetNodeType && options.lenient) {
1864
- Object.assign(node, { typ: EnumToken.InvalidDeclarationNodeType });
1865
- context.chi.push(node);
1866
- stats.nodesCount++;
1867
- return null;
1868
- }
1869
- const result = parseDeclarationNode(node, errors, location);
1870
- Object.defineProperty(result, 'parent', { ...definedPropertySettings, value: context });
1871
- if (result != null) {
1872
- if (options.validation & ValidationLevel.Declaration) {
1873
- const isAllowed = isNodeAllowedInContext(node, context);
1874
- // @ts-ignore
1875
- const valid = !isAllowed ? {
1876
- valid: SyntaxValidationResult.Drop,
1877
- error: `${EnumToken[node.typ]} not allowed in context${context.typ == EnumToken.AtRuleNodeType ? ` '@${context.nam}'` : context.typ == EnumToken.StyleSheetNodeType ? ` 'stylesheet'` : ''}`,
1878
- node,
1879
- syntax: null
1880
- } : evaluateSyntax(result, context, options);
1881
- Object.defineProperty(result, 'validSyntax', {
1882
- ...definedPropertySettings,
1883
- value: valid.valid == SyntaxValidationResult.Valid
1884
- });
1885
- if (valid.valid == SyntaxValidationResult.Drop) {
2165
+ else {
2166
+ trimArray(stream);
2167
+ for (let i = 0; i < stream.length; i++) {
2168
+ if (stream[i].typ !== EnumToken.WhitespaceTokenType &&
2169
+ stream[i].typ !== EnumToken.CommentTokenType) {
2170
+ success = false;
1886
2171
  errors.push({
1887
- action: 'drop',
1888
- message: valid.error,
1889
- syntax: valid.syntax,
1890
- node: valid.node,
1891
- location: map.get(valid.node) ?? valid.node?.loc ?? result.loc ?? location
2172
+ action: "drop",
2173
+ node: stream[i],
2174
+ location: stream[i].loc,
2175
+ message: "expected whitespace or comment",
1892
2176
  });
1893
- if (!options.lenient) {
1894
- return null;
1895
- }
1896
- Object.assign(node, { typ: EnumToken.InvalidDeclarationNodeType });
1897
- }
1898
- }
1899
- context.chi.push(result);
1900
- stats.nodesCount++;
1901
- }
1902
- return null;
1903
- }
1904
- }
1905
- }
1906
- /**
1907
- * parse at-rule prelude
1908
- * @param tokens
1909
- * @param atRule
1910
- */
1911
- function parseAtRulePrelude(tokens, atRule) {
1912
- for (const { value, parent } of walkValues(tokens, null, null, true)) {
1913
- if (value.typ == EnumToken.CommentTokenType ||
1914
- value.typ == EnumToken.WhitespaceTokenType ||
1915
- value.typ == EnumToken.CommaTokenType) {
1916
- continue;
1917
- }
1918
- if (value.typ == EnumToken.PseudoClassFuncTokenType || value.typ == EnumToken.PseudoClassTokenType) {
1919
- if (parent?.typ == EnumToken.ParensTokenType) {
1920
- const index = parent.chi.indexOf(value);
1921
- let i = index;
1922
- while (i--) {
1923
- if (parent.chi[i].typ == EnumToken.IdenTokenType || parent.chi[i].typ == EnumToken.DashedIdenTokenType) {
1924
2177
  break;
1925
2178
  }
1926
2179
  }
1927
- if (i >= 0) {
1928
- const token = getTokenType(parent.chi[index].val.slice(1) + (funcLike.includes(parent.chi[index].typ) ? '(' : ''));
1929
- parent.chi[index].val = token.val;
1930
- parent.chi[index].typ = token.typ;
1931
- if (parent.chi[index].typ == EnumToken.FunctionTokenType && isColor(parent.chi[index])) {
1932
- parseColor(parent.chi[index]);
1933
- }
1934
- parent.chi.splice(i, index - i + 1, {
1935
- typ: EnumToken.MediaQueryConditionTokenType,
1936
- l: parent.chi[i],
1937
- r: parent.chi.slice(index),
1938
- op: {
1939
- typ: EnumToken.ColonTokenType
1940
- }
1941
- });
1942
- }
1943
- }
1944
- }
1945
- if (atRule.val == 'page' && value.typ == EnumToken.PseudoClassTokenType) {
1946
- if ([':left', ':right', ':first', ':blank'].includes(value.val)) {
1947
- Object.assign(value, { typ: EnumToken.PseudoPageTokenType });
1948
- }
1949
- }
1950
- if (atRule.val == 'layer') {
1951
- if (parent == null && value.typ == EnumToken.LiteralTokenType) {
1952
- if (value.val.charAt(0) == '.') {
1953
- if (isIdent(value.val.slice(1))) {
1954
- Object.assign(value, { typ: EnumToken.ClassSelectorTokenType });
1955
- }
1956
- }
1957
2180
  }
2181
+ // @ts-expect-error
2182
+ return Object.defineProperties(Object.assign(atRule, {
2183
+ typ: success ? EnumToken.AtRuleNodeType : EnumToken.InvalidRuleNodeType,
2184
+ val: renderTokens(stream, options),
2185
+ chi: [],
2186
+ }), {
2187
+ tokens: { ...definedPropertySettings, value: stream.slice() },
2188
+ loc: {
2189
+ ...definedPropertySettings,
2190
+ value: { ...atRule.loc, end: { ...(stream.at(-1)?.loc?.end ?? atRule.loc.end) } },
2191
+ },
2192
+ });
1958
2193
  }
1959
- const val = value.typ == EnumToken.IdenTokenType ? value.val.toLowerCase() : null;
1960
- if (value.typ == EnumToken.IdenTokenType) {
1961
- if (parent == null && mediaTypes.some((t) => {
1962
- if (val === t) {
1963
- Object.assign(value, { typ: EnumToken.MediaFeatureTokenType });
1964
- return true;
1965
- }
1966
- return false;
1967
- })) {
1968
- continue;
1969
- }
1970
- if (value.typ == EnumToken.IdenTokenType && 'and' === val) {
1971
- Object.assign(value, { typ: EnumToken.MediaFeatureAndTokenType });
1972
- continue;
1973
- }
1974
- if (value.typ == EnumToken.IdenTokenType && 'or' === val) {
1975
- Object.assign(value, { typ: EnumToken.MediaFeatureOrTokenType });
1976
- continue;
1977
- }
1978
- if (value.typ == EnumToken.IdenTokenType &&
1979
- ['not', 'only'].some((t) => val === t)) {
1980
- const array = parent?.chi ?? tokens;
1981
- const startIndex = array.indexOf(value);
1982
- let index = startIndex + 1;
1983
- if (index == 0) {
1984
- continue;
1985
- }
1986
- while (index < array.length && [EnumToken.CommentTokenType, EnumToken.WhitespaceTokenType].includes(array[index].typ)) {
1987
- index++;
1988
- }
1989
- if (array[index] == null || array[index].typ == EnumToken.CommaTokenType) {
1990
- continue;
2194
+ case "value": {
2195
+ let index = 0;
2196
+ let isVarDeclaration = false;
2197
+ for (; index < stream.length; index++) {
2198
+ if (stream[index].typ == EnumToken.PseudoClassTokenType) {
2199
+ Object.assign(stream[index], {
2200
+ typ: EnumToken.IdenTokenType,
2201
+ val: stream[index].val.slice(1),
2202
+ });
2203
+ stream.splice(index, 0, Object.defineProperty({
2204
+ typ: EnumToken.ColonTokenType,
2205
+ }, "loc", {
2206
+ ...definedPropertySettings,
2207
+ value: { ...stream[index].loc, end: { ...stream[index]?.loc?.sta } },
2208
+ }));
2209
+ isVarDeclaration = true;
2210
+ break;
1991
2211
  }
1992
- Object.assign(array[startIndex], {
1993
- typ: value.val.toLowerCase() == 'not' ? EnumToken.MediaFeatureNotTokenType : EnumToken.MediaFeatureOnlyTokenType,
1994
- val: array[index]
1995
- });
1996
- array.splice(startIndex + 1, index - startIndex);
1997
- continue;
1998
- }
1999
- }
2000
- if (value.typ == EnumToken.FunctionTokenType && value.val == 'selector') {
2001
- parseSelector(value.chi);
2002
- }
2003
- if (value.typ == EnumToken.ParensTokenType || (value.typ == EnumToken.FunctionTokenType && ['media', 'supports', 'style', 'scroll-state'].includes(value.val))) {
2004
- let i;
2005
- let nameIndex = -1;
2006
- let valueIndex = -1;
2007
- const dashedIdent = value.typ == EnumToken.FunctionTokenType && value.val == 'style';
2008
- for (let i = 0; i < value.chi.length; i++) {
2009
- if (value.chi[i].typ == EnumToken.CommentTokenType || value.chi[i].typ == EnumToken.WhitespaceTokenType) {
2010
- continue;
2212
+ else if (stream[index].typ == EnumToken.ColonTokenType) {
2213
+ isVarDeclaration = true;
2214
+ break;
2011
2215
  }
2012
- if ((dashedIdent && value.chi[i].typ == EnumToken.DashedIdenTokenType) || value.chi[i].typ == EnumToken.IdenTokenType || value.chi[i].typ == EnumToken.FunctionTokenType || value.chi[i].typ == EnumToken.ColorTokenType) {
2013
- nameIndex = i;
2216
+ else if (stream[index].typ == EnumToken.IdenTokenType &&
2217
+ equalsIgnoreCase("from", stream[index].val)) {
2218
+ break;
2014
2219
  }
2015
- break;
2016
2220
  }
2017
- if (nameIndex == -1) {
2018
- continue;
2221
+ // supported syntaxes:
2222
+ // @value <ident>: <string>; // import from file as alias
2223
+ // @value id : <declaration-value>; // variable declaration
2224
+ // @value <ident># from <ident>; // import variables from alias
2225
+ let result = matchAllSyntax(syntaxRules?.getPreludeRules()?.slice?.(1), createValidationContext(stream), options);
2226
+ if (!result.success) {
2227
+ errors.push(...result.errors);
2228
+ return Object.defineProperty({
2229
+ typ: EnumToken.InvalidAtRuleNodeType,
2230
+ val: renderTokens(stream, options),
2231
+ }, "loc", {
2232
+ ...definedPropertySettings,
2233
+ value: { ...atRule.loc, end: { ...(stream.at(-1)?.loc?.end ?? atRule.loc.end) } },
2234
+ });
2019
2235
  }
2020
- for (let i = nameIndex + 1; i < value.chi.length; i++) {
2021
- if (value.chi[i].typ == EnumToken.CommentTokenType || value.chi[i].typ == EnumToken.WhitespaceTokenType) {
2022
- continue;
2023
- }
2024
- if (value.chi[i].typ == EnumToken.LiteralTokenType && value.chi[i].val.startsWith(':')) {
2025
- const dimension = parseDimension(value.chi[i].val.slice(1));
2026
- if (dimension != null) {
2027
- value.chi.splice(i, 1, {
2028
- typ: EnumToken.ColonTokenType,
2029
- }, Object.assign(value.chi[i], dimension));
2030
- i--;
2031
- continue;
2032
- }
2236
+ if (isVarDeclaration) {
2237
+ const nam = stream.find((t) => t.typ == EnumToken.IdenTokenType);
2238
+ const value = trimArray(stream.slice(index + 1).filter((t) => t.typ != EnumToken.CommentTokenType));
2239
+ if (value.length == 1 && value[0].typ == EnumToken.StringTokenType) {
2240
+ // import from file as alias
2241
+ return {
2242
+ typ: EnumToken.CssVariableImportTokenType,
2243
+ nam: nam.val,
2244
+ val: value,
2245
+ };
2033
2246
  }
2034
- if (nameIndex != -1 && value.chi[i].typ == EnumToken.PseudoClassTokenType) {
2035
- value.chi.splice(i, 1, {
2036
- typ: EnumToken.ColonTokenType,
2037
- }, Object.assign(value.chi[i], {
2038
- typ: EnumToken.IdenTokenType,
2039
- val: value.chi[i].val.slice(1)
2040
- }));
2041
- i--;
2042
- continue;
2247
+ // import variables from alias
2248
+ return {
2249
+ typ: EnumToken.CssVariableTokenType,
2250
+ nam: nam.val,
2251
+ val: value,
2252
+ };
2253
+ }
2254
+ // @ts-expect-error
2255
+ return Object.defineProperties(Object.assign(atRule, {
2256
+ typ: EnumToken.CssVariableDeclarationMapTokenType,
2257
+ vars: trimArray(stream.slice(0, index)),
2258
+ from: stream.slice(index + 1),
2259
+ }), {
2260
+ tokens: { ...definedPropertySettings, value: stream.slice() },
2261
+ loc: {
2262
+ ...definedPropertySettings,
2263
+ value: { ...atRule.loc, end: { ...(stream.at(-1)?.loc?.end ?? atRule.loc.end) } },
2264
+ },
2265
+ });
2266
+ }
2267
+ default: {
2268
+ options = { ...options, parseColor: false };
2269
+ let result = null;
2270
+ if (syntax == null) {
2271
+ // check matching '(' and ')'
2272
+ // check commas , or ,,
2273
+ // check colon :
2274
+ // check or and and
2275
+ result = matchGenericSyntax(atRule, stream);
2276
+ if (result.errors.length > 0) {
2277
+ errors.push(...result.errors);
2043
2278
  }
2044
- valueIndex = i;
2045
- break;
2046
- }
2047
- if (valueIndex == -1) {
2048
- continue;
2049
2279
  }
2050
- for (i = nameIndex + 1; i < value.chi.length; i++) {
2051
- if ([
2052
- EnumToken.GtTokenType, EnumToken.LtTokenType,
2053
- EnumToken.GteTokenType, EnumToken.LteTokenType,
2054
- EnumToken.ColonTokenType
2055
- ].includes(value.chi[valueIndex].typ)) {
2056
- const val = value.chi.splice(valueIndex, 1)[0];
2057
- const node = value.chi.splice(nameIndex, 1)[0];
2058
- // 'background'
2059
- if (node.typ == EnumToken.ColorTokenType && node.kin == ColorType.DPSYS) {
2060
- Object.assign(node, { typ: EnumToken.IdenTokenType });
2061
- // @ts-ignore
2062
- delete node.kin;
2063
- }
2064
- while (value.chi[0]?.typ == EnumToken.WhitespaceTokenType) {
2065
- value.chi.shift();
2280
+ else {
2281
+ result = matchAtRuleSyntax(atRule, stream, options);
2282
+ if (result.success) {
2283
+ let i = 0;
2284
+ const stack = [];
2285
+ for (; i < stream.length; i++) {
2286
+ if (stream[i].typ === EnumToken.StartParensTokenType || tokensfuncDefMap.has(stream[i].typ)) {
2287
+ stack.push(stream[i]);
2288
+ continue;
2289
+ }
2290
+ if (stream[i].typ === EnumToken.EndParensTokenType && stack.length > 0) {
2291
+ const index = stream.indexOf(stack[stack.length - 1]);
2292
+ stream[index].loc.end = stream[i].loc.end;
2293
+ Object.assign(stream[index], {
2294
+ typ: tokensfuncDefMap.get(stream[index].typ),
2295
+ chi: stream.splice(index + 1, i - index - 1),
2296
+ });
2297
+ i = index;
2298
+ stream.splice(index + 1, 1);
2299
+ stack.pop();
2300
+ // continue;
2301
+ }
2066
2302
  }
2067
- const t = [{
2068
- typ: EnumToken.MediaQueryConditionTokenType,
2069
- l: node,
2070
- op: { typ: val.typ },
2071
- r: value.chi.slice()
2072
- }];
2073
- value.chi.length = 0;
2074
- value.chi.push(...t);
2075
2303
  }
2076
2304
  }
2305
+ // @ts-expect-error
2306
+ return Object.defineProperties(Object.assign(atRule, {
2307
+ typ: result.success ? EnumToken.AtRuleNodeType : EnumToken.InvalidRuleNodeType,
2308
+ val: renderTokens(trimWhiteSpaceTokens(stream), options),
2309
+ ...(parseAsBlock ? { chi: [] } : {}),
2310
+ }), {
2311
+ tokens: { ...definedPropertySettings, value: stream.slice() },
2312
+ loc: {
2313
+ ...definedPropertySettings,
2314
+ value: { ...atRule.loc, end: { ...(stream.at(-1)?.loc?.end ?? atRule.loc.end) } },
2315
+ },
2316
+ });
2077
2317
  }
2078
2318
  }
2079
- return tokens;
2080
2319
  }
2081
2320
  /**
2082
2321
  * parse a string as an array of declaration nodes
@@ -2092,104 +2331,16 @@ function parseAtRulePrelude(tokens, atRule) {
2092
2331
  async function parseDeclarations(declaration) {
2093
2332
  return doParse(tokenize({
2094
2333
  stream: `.x{${declaration}}`,
2095
- buffer: '',
2334
+ buffer: "",
2096
2335
  offset: 0,
2097
2336
  position: { ind: 0, lin: 1, col: 1 },
2098
- currentPosition: { ind: -1, lin: 1, col: 0 }
2099
- }), { setParent: false, minify: false, validation: false }).then(result => {
2100
- return result.ast.chi[0].chi.filter(t => t.typ == EnumToken.DeclarationNodeType || t.typ == EnumToken.CommentNodeType);
2337
+ currentPosition: { ind: -1, lin: 1, col: 0 },
2338
+ }), { setParent: false, minify: false, validation: false }).then((result) => {
2339
+ return result.ast.chi[0].chi.filter((t) => t.typ == EnumToken.DeclarationNodeType ||
2340
+ t.typ == EnumToken.CommentNodeType ||
2341
+ t.typ == EnumToken.InvalidDeclarationNodeType);
2101
2342
  });
2102
2343
  }
2103
- /**
2104
- * parse selector
2105
- * @param tokens
2106
- */
2107
- function parseSelector(tokens) {
2108
- for (const { value, parent } of walkValues(tokens)) {
2109
- if (value.typ == EnumToken.CommentTokenType ||
2110
- value.typ == EnumToken.WhitespaceTokenType ||
2111
- value.typ == EnumToken.CommaTokenType ||
2112
- value.typ == EnumToken.IdenTokenType ||
2113
- value.typ == EnumToken.HashTokenType) {
2114
- continue;
2115
- }
2116
- if (parent == null) {
2117
- if (value.typ == EnumToken.GtTokenType) {
2118
- Object.assign(value, { typ: EnumToken.ChildCombinatorTokenType });
2119
- }
2120
- else if (value.typ == EnumToken.LiteralTokenType) {
2121
- if (value.val.charAt(0) == '&') {
2122
- Object.assign(value, { typ: EnumToken.NestingSelectorTokenType });
2123
- // @ts-ignore
2124
- delete value.val;
2125
- }
2126
- else if (value.val.charAt(0) == '.') {
2127
- if (!isIdent(value.val.slice(1))) {
2128
- Object.assign(value, { typ: EnumToken.InvalidClassSelectorTokenType });
2129
- }
2130
- else {
2131
- Object.assign(value, { typ: EnumToken.ClassSelectorTokenType });
2132
- }
2133
- }
2134
- if (['*', '>', '+', '~'].includes(value.val)) {
2135
- switch (value.val) {
2136
- case '*':
2137
- Object.assign(value, { typ: EnumToken.UniversalSelectorTokenType });
2138
- break;
2139
- case '>':
2140
- Object.assign(value, { typ: EnumToken.ChildCombinatorTokenType });
2141
- break;
2142
- case '+':
2143
- Object.assign(value, { typ: EnumToken.NextSiblingCombinatorTokenType });
2144
- break;
2145
- case '~':
2146
- Object.assign(value, { typ: EnumToken.SubsequentSiblingCombinatorTokenType });
2147
- break;
2148
- }
2149
- // @ts-ignore
2150
- delete value.val;
2151
- }
2152
- }
2153
- else if (value.typ == EnumToken.ColorTokenType) {
2154
- if (value.kin == ColorType.LIT || value.kin == ColorType.HEX || value.kin == ColorType.SYS || value.kin == ColorType.DPSYS) {
2155
- if (value.kin == ColorType.HEX) {
2156
- if (!isIdent(value.val.slice(1))) {
2157
- continue;
2158
- }
2159
- Object.assign(value, { typ: EnumToken.HashTokenType });
2160
- }
2161
- else {
2162
- Object.assign(value, { typ: EnumToken.IdenTokenType });
2163
- }
2164
- // @ts-ignore
2165
- delete value.kin;
2166
- }
2167
- }
2168
- }
2169
- }
2170
- let i = 0;
2171
- const combinators = [
2172
- EnumToken.ChildCombinatorTokenType,
2173
- EnumToken.NextSiblingCombinatorTokenType,
2174
- EnumToken.SubsequentSiblingCombinatorTokenType
2175
- ];
2176
- for (; i < tokens.length; i++) {
2177
- if (combinators.includes(tokens[i].typ)) {
2178
- if (i + 1 < tokens.length && [EnumToken.WhitespaceTokenType, EnumToken.DescendantCombinatorTokenType].includes(tokens[i + 1].typ)) {
2179
- tokens.splice(i + 1, 1);
2180
- }
2181
- if (i > 0 && [EnumToken.WhitespaceTokenType, EnumToken.DescendantCombinatorTokenType].includes(tokens[i - 1].typ)) {
2182
- tokens.splice(i - 1, 1);
2183
- i--;
2184
- continue;
2185
- }
2186
- }
2187
- if (tokens[i].typ == EnumToken.WhitespaceTokenType) {
2188
- tokens[i].typ = EnumToken.DescendantCombinatorTokenType;
2189
- }
2190
- }
2191
- return tokens;
2192
- }
2193
2344
  /**
2194
2345
  * parse css string and return an array of tokens
2195
2346
  * @param src
@@ -2213,194 +2364,14 @@ function parseSelector(tokens) {
2213
2364
  function parseString(src, options = { location: false }) {
2214
2365
  const parseInfo = {
2215
2366
  stream: src,
2216
- buffer: '',
2367
+ src: options.src ?? "",
2368
+ buffer: "",
2217
2369
  offset: 0,
2370
+ time: 0,
2218
2371
  position: { ind: 0, lin: 1, col: 1 },
2219
- currentPosition: { ind: -1, lin: 1, col: 0 }
2220
- };
2221
- return parseTokens([...tokenize(parseInfo)].reduce((acc, t) => {
2222
- if (t.hint == EnumToken.EOFTokenType) {
2223
- return acc;
2224
- }
2225
- const token = getTokenType(t.token, t.hint);
2226
- Object.defineProperty(token, 'loc', {
2227
- ...definedPropertySettings,
2228
- value: { sta: t.sta },
2229
- enumerable: options.location !== false
2230
- });
2231
- acc.push(token);
2232
- return acc;
2233
- }, []));
2234
- }
2235
- /**
2236
- * get the token type from a string
2237
- * @param val
2238
- * @param hint
2239
- */
2240
- function getTokenType(val, hint) {
2241
- if (hint != null) {
2242
- return enumTokenHints.has(hint) ? { typ: hint } : { typ: hint, val };
2243
- }
2244
- switch (val) {
2245
- case ' ':
2246
- return { typ: EnumToken.WhitespaceTokenType };
2247
- case ';':
2248
- return { typ: EnumToken.SemiColonTokenType };
2249
- case '{':
2250
- return { typ: EnumToken.BlockStartTokenType };
2251
- case '}':
2252
- return { typ: EnumToken.BlockEndTokenType };
2253
- case '[':
2254
- return { typ: EnumToken.AttrStartTokenType };
2255
- case ']':
2256
- return { typ: EnumToken.AttrEndTokenType };
2257
- case ':':
2258
- return { typ: EnumToken.ColonTokenType };
2259
- case ')':
2260
- return { typ: EnumToken.EndParensTokenType };
2261
- case '(':
2262
- return { typ: EnumToken.StartParensTokenType };
2263
- case '=':
2264
- return { typ: EnumToken.DelimTokenType };
2265
- case ',':
2266
- return { typ: EnumToken.CommaTokenType };
2267
- case '<':
2268
- return { typ: EnumToken.LtTokenType };
2269
- case '>':
2270
- return { typ: EnumToken.GtTokenType };
2271
- }
2272
- if (val.charAt(0) == ':' && isPseudo(val)) {
2273
- return val.endsWith('(') ? {
2274
- typ: EnumToken.PseudoClassFuncTokenType,
2275
- val: val.slice(0, -1),
2276
- chi: []
2277
- }
2278
- : (
2279
- // https://www.w3.org/TR/selectors-4/#single-colon-pseudos
2280
- val.startsWith('::') || pseudoElements.includes(val) ? {
2281
- typ: EnumToken.PseudoElementTokenType,
2282
- val
2283
- } :
2284
- {
2285
- typ: EnumToken.PseudoClassTokenType,
2286
- val
2287
- });
2288
- }
2289
- if (val.charAt(0) == '@' && isAtKeyword(val)) {
2290
- return {
2291
- typ: EnumToken.AtRuleTokenType,
2292
- val: val.slice(1)
2293
- };
2294
- }
2295
- if (val.endsWith('(') && isFunction(val)) {
2296
- val = val.slice(0, -1);
2297
- if (val == 'url') {
2298
- return {
2299
- typ: EnumToken.UrlFunctionTokenType,
2300
- val,
2301
- chi: []
2302
- };
2303
- }
2304
- if (['linear-gradient', 'radial-gradient', 'repeating-linear-gradient', 'repeating-radial-gradient', 'conic-gradient', 'image', 'image-set', 'element', 'cross-fade', 'paint'].includes(val)) {
2305
- return {
2306
- typ: EnumToken.ImageFunctionTokenType,
2307
- val,
2308
- chi: []
2309
- };
2310
- }
2311
- if (timingFunc.includes(val.toLowerCase())) {
2312
- return {
2313
- typ: EnumToken.TimingFunctionTokenType,
2314
- val,
2315
- chi: []
2316
- };
2317
- }
2318
- if (timelineFunc.includes(val)) {
2319
- return {
2320
- typ: EnumToken.TimelineFunctionTokenType,
2321
- val,
2322
- chi: []
2323
- };
2324
- }
2325
- return {
2326
- typ: EnumToken.FunctionTokenType,
2327
- val,
2328
- chi: []
2329
- };
2330
- }
2331
- if (isNumber(val)) {
2332
- return {
2333
- typ: EnumToken.NumberTokenType,
2334
- val: +val
2335
- };
2336
- }
2337
- if (isPercentage(val)) {
2338
- return {
2339
- typ: EnumToken.PercentageTokenType,
2340
- val: +val.slice(0, -1)
2341
- };
2342
- }
2343
- const dimension = parseDimension(val);
2344
- if (dimension != null) {
2345
- return dimension;
2346
- }
2347
- const v = val.toLowerCase();
2348
- if (v == 'currentcolor' || v == 'transparent' || v in COLORS_NAMES) {
2349
- return {
2350
- typ: EnumToken.ColorTokenType,
2351
- val: v,
2352
- kin: ColorType.LIT
2353
- };
2354
- }
2355
- if (isIdent(val)) {
2356
- if (systemColors.has(v)) {
2357
- return {
2358
- typ: EnumToken.ColorTokenType,
2359
- val,
2360
- kin: ColorType.SYS
2361
- };
2362
- }
2363
- if (deprecatedSystemColors.has(v)) {
2364
- return {
2365
- typ: EnumToken.ColorTokenType,
2366
- val,
2367
- kin: ColorType.DPSYS
2368
- };
2369
- }
2370
- return {
2371
- typ: val.startsWith('--') ? EnumToken.DashedIdenTokenType : EnumToken.IdenTokenType,
2372
- val
2373
- };
2374
- }
2375
- if (val.charAt(0) == '.' && isIdent(val.slice(1))) {
2376
- return {
2377
- typ: EnumToken.ClassSelectorTokenType,
2378
- val
2379
- };
2380
- }
2381
- if (val.charAt(0) == '#' && isHexColor(val)) {
2382
- return {
2383
- typ: EnumToken.ColorTokenType,
2384
- val,
2385
- kin: ColorType.HEX
2386
- };
2387
- }
2388
- if (val.charAt(0) == '#' && isHash(val)) {
2389
- return {
2390
- typ: EnumToken.HashTokenType,
2391
- val
2392
- };
2393
- }
2394
- if ('"\''.includes(val.charAt(0))) {
2395
- return {
2396
- typ: EnumToken.UnclosedStringTokenType,
2397
- val
2398
- };
2399
- }
2400
- return {
2401
- typ: EnumToken.LiteralTokenType,
2402
- val
2372
+ currentPosition: { ind: -1, lin: 1, col: 0 },
2403
2373
  };
2374
+ return parseTokens([...tokenize(parseInfo)].map((t) => t.token), { sourcemap: options.location }).slice(0, -1);
2404
2375
  }
2405
2376
  /**
2406
2377
  * parse function tokens in a token array
@@ -2425,7 +2396,7 @@ function getTokenType(val, hint) {
2425
2396
  function parseTokens(tokens, options = {}) {
2426
2397
  for (let i = 0; i < tokens.length; i++) {
2427
2398
  const t = tokens[i];
2428
- if (t.typ == EnumToken.IdenTokenType && t.val == 'from' && i > 0) {
2399
+ if (t.typ == EnumToken.IdenTokenType && t.val == "from" && i > 0) {
2429
2400
  const left = [];
2430
2401
  const right = [];
2431
2402
  let foundLeft = 0;
@@ -2433,11 +2404,13 @@ function parseTokens(tokens, options = {}) {
2433
2404
  let k = i;
2434
2405
  let l = i;
2435
2406
  while (k > 0) {
2436
- if (tokens[k - 1].typ == EnumToken.CommentTokenType || tokens[k - 1].typ == EnumToken.WhitespaceTokenType) {
2407
+ if (tokens[k - 1].typ == EnumToken.CommentTokenType ||
2408
+ tokens[k - 1].typ == EnumToken.WhitespaceTokenType) {
2437
2409
  left.push(tokens[--k]);
2438
2410
  continue;
2439
2411
  }
2440
- if (tokens[k - 1].typ == EnumToken.IdenTokenType || tokens[k - 1].typ == EnumToken.DashedIdenTokenType) {
2412
+ if (tokens[k - 1].typ == EnumToken.IdenTokenType ||
2413
+ tokens[k - 1].typ == EnumToken.DashedIdenTokenType) {
2441
2414
  foundLeft++;
2442
2415
  left.push(tokens[--k]);
2443
2416
  continue;
@@ -2467,17 +2440,27 @@ function parseTokens(tokens, options = {}) {
2467
2440
  typ: EnumToken.ComposesSelectorNodeType,
2468
2441
  l: left,
2469
2442
  r: right.reduce((a, b) => {
2470
- return a == null ? b : b.typ == EnumToken.IdenTokenType || b.typ == EnumToken.StringTokenType ? b : a;
2471
- }, null)
2443
+ return a == null
2444
+ ? b
2445
+ : b.typ == EnumToken.IdenTokenType || b.typ == EnumToken.StringTokenType
2446
+ ? b
2447
+ : a;
2448
+ }, null),
2472
2449
  });
2473
2450
  i = k;
2474
2451
  continue;
2475
2452
  }
2476
2453
  }
2477
- if (t.typ == EnumToken.WhitespaceTokenType && ((i == 0 ||
2478
- i + 1 == tokens.length ||
2479
- [EnumToken.CommaTokenType, EnumToken.GteTokenType, EnumToken.LteTokenType, EnumToken.ColumnCombinatorTokenType].includes(tokens[i + 1].typ)) ||
2480
- (i > 0 && trimWhiteSpace.includes(tokens[i - 1].typ)))) {
2454
+ if (t.typ == EnumToken.WhitespaceTokenType &&
2455
+ (i == 0 ||
2456
+ i + 1 == tokens.length ||
2457
+ [
2458
+ EnumToken.CommaTokenType,
2459
+ EnumToken.GteTokenType,
2460
+ EnumToken.LteTokenType,
2461
+ EnumToken.ColumnCombinatorTokenType,
2462
+ ].includes(tokens[i + 1].typ) ||
2463
+ (i > 0 && trimWhiteSpace.includes(tokens[i - 1].typ)))) {
2481
2464
  tokens.splice(i--, 1);
2482
2465
  continue;
2483
2466
  }
@@ -2488,7 +2471,7 @@ function parseTokens(tokens, options = {}) {
2488
2471
  tokens[i + 1].typ = EnumToken.PseudoClassFuncTokenType;
2489
2472
  }
2490
2473
  else if (typ == EnumToken.IdenTokenType) {
2491
- tokens[i + 1].val = ':' + tokens[i + 1].val;
2474
+ tokens[i + 1].val = ":" + tokens[i + 1].val;
2492
2475
  tokens[i + 1].typ = EnumToken.PseudoClassTokenType;
2493
2476
  }
2494
2477
  if (typ == EnumToken.FunctionTokenType || typ == EnumToken.IdenTokenType) {
@@ -2514,7 +2497,7 @@ function parseTokens(tokens, options = {}) {
2514
2497
  }
2515
2498
  const attr = Object.assign(t, {
2516
2499
  typ: inAttr == 0 ? EnumToken.AttrTokenType : EnumToken.InvalidAttrTokenType,
2517
- chi: tokens.splice(i + 1, k - i)
2500
+ chi: tokens.splice(i + 1, k - i),
2518
2501
  });
2519
2502
  // @ts-ignore
2520
2503
  if (attr.chi.at(-1).typ == EnumToken.AttrEndTokenType) {
@@ -2532,11 +2515,12 @@ function parseTokens(tokens, options = {}) {
2532
2515
  val = attr.chi[m];
2533
2516
  if (val.typ == EnumToken.StringTokenType) {
2534
2517
  const slice = val.val.slice(1, -1);
2535
- if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
2518
+ if ((slice.charAt(0) != "-" || (slice.charAt(0) == "-" && isIdentStart(slice.charCodeAt(1)))) &&
2519
+ isIdent(slice)) {
2536
2520
  Object.assign(val, { typ: EnumToken.IdenTokenType, val: slice });
2537
2521
  }
2538
2522
  }
2539
- else if (val.typ == EnumToken.LiteralTokenType && val.val == '|') {
2523
+ else if (val.typ == EnumToken.LiteralTokenType && val.val == "|") {
2540
2524
  let upper = m;
2541
2525
  let lower = m;
2542
2526
  while (++upper < attr.chi.length) {
@@ -2555,7 +2539,7 @@ function parseTokens(tokens, options = {}) {
2555
2539
  attr.chi[m] = {
2556
2540
  typ: EnumToken.NameSpaceAttributeTokenType,
2557
2541
  l: attr.chi[lower],
2558
- r: attr.chi[upper]
2542
+ r: attr.chi[upper],
2559
2543
  };
2560
2544
  attr.chi.splice(upper, 1);
2561
2545
  if (lower >= 0) {
@@ -2564,7 +2548,12 @@ function parseTokens(tokens, options = {}) {
2564
2548
  }
2565
2549
  }
2566
2550
  else if ([
2567
- EnumToken.DashMatchTokenType, EnumToken.StartMatchTokenType, EnumToken.ContainMatchTokenType, EnumToken.EndMatchTokenType, EnumToken.IncludeMatchTokenType, EnumToken.DelimTokenType
2551
+ EnumToken.DashMatchTokenType,
2552
+ EnumToken.StartMatchTokenType,
2553
+ EnumToken.ContainMatchTokenType,
2554
+ EnumToken.EndMatchTokenType,
2555
+ EnumToken.IncludeMatchTokenType,
2556
+ EnumToken.DelimTokenType,
2568
2557
  ].includes(attr.chi[m].typ)) {
2569
2558
  let upper = m;
2570
2559
  let lower = m;
@@ -2583,14 +2572,16 @@ function parseTokens(tokens, options = {}) {
2583
2572
  val = attr.chi[lower];
2584
2573
  if (val.typ == EnumToken.StringTokenType) {
2585
2574
  const slice = val.val.slice(1, -1);
2586
- if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
2575
+ if ((slice.charAt(0) != "-" || (slice.charAt(0) == "-" && isIdentStart(slice.charCodeAt(1)))) &&
2576
+ isIdent(slice)) {
2587
2577
  Object.assign(val, { typ: EnumToken.IdenTokenType, val: slice });
2588
2578
  }
2589
2579
  }
2590
2580
  val = attr.chi[upper];
2591
2581
  if (val.typ == EnumToken.StringTokenType) {
2592
2582
  const slice = val.val.slice(1, -1);
2593
- if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
2583
+ if ((slice.charAt(0) != "-" || (slice.charAt(0) == "-" && isIdentStart(slice.charCodeAt(1)))) &&
2584
+ isIdent(slice)) {
2594
2585
  Object.assign(val, { typ: EnumToken.IdenTokenType, val: slice });
2595
2586
  }
2596
2587
  }
@@ -2601,28 +2592,31 @@ function parseTokens(tokens, options = {}) {
2601
2592
  typ: EnumToken.MatchExpressionTokenType,
2602
2593
  op: {
2603
2594
  // @ts-ignore
2604
- typ: typ == EnumToken.DelimTokenType ? EnumToken.EqualMatchTokenType : typ
2595
+ typ: typ == EnumToken.DelimTokenType ? EnumToken.EqualMatchTokenType : typ,
2605
2596
  },
2606
2597
  l: t.chi[lower],
2607
- r: t.chi[upper]
2598
+ r: t.chi[upper],
2608
2599
  };
2609
2600
  if (isIdentColor(t.chi[m].l)) {
2610
- t.chi[m].l.typ = EnumToken.IdenTokenType;
2601
+ t.chi[m].l.typ =
2602
+ EnumToken.IdenTokenType;
2611
2603
  }
2612
2604
  if (isIdentColor(t.chi[m].r)) {
2613
- t.chi[m].r.typ = EnumToken.IdenTokenType;
2605
+ t.chi[m].r.typ =
2606
+ EnumToken.IdenTokenType;
2614
2607
  }
2615
2608
  t.chi.splice(upper, 1);
2616
2609
  t.chi.splice(lower, 1);
2617
2610
  upper = m;
2618
2611
  m--;
2619
- while (upper < t.chi.length && t.chi[upper].typ == EnumToken.WhitespaceTokenType) {
2612
+ while (upper < t.chi.length &&
2613
+ t.chi[upper].typ == EnumToken.WhitespaceTokenType) {
2620
2614
  upper++;
2621
2615
  }
2622
2616
  if (upper < t.chi.length &&
2623
2617
  t.chi[upper].typ == EnumToken.IdenTokenType &&
2624
- ['i', 's'].includes(t.chi[upper].val.toLowerCase())) {
2625
- t.chi[m].attr = t.chi[upper].val;
2618
+ ["i", "s"].includes(t.chi[upper].val.toLowerCase())) {
2619
+ t.chi[m].attr = (t.chi[upper].val);
2626
2620
  t.chi.splice(upper, 1);
2627
2621
  }
2628
2622
  }
@@ -2642,11 +2636,12 @@ function parseTokens(tokens, options = {}) {
2642
2636
  if (typ != null) {
2643
2637
  if (typ == EnumToken.IdenTokenType) {
2644
2638
  tokens[k + 1].typ = EnumToken.PseudoClassTokenType;
2645
- tokens[k + 1].val = ':' + tokens[k + 1].val;
2639
+ tokens[k + 1].val = ":" + tokens[k + 1].val;
2646
2640
  }
2647
2641
  else if (typ == EnumToken.FunctionTokenType) {
2648
2642
  tokens[k + 1].typ = EnumToken.PseudoClassFuncTokenType;
2649
- tokens[k + 1].val = ':' + tokens[k + 1].val;
2643
+ tokens[k + 1].val =
2644
+ ":" + tokens[k + 1].val;
2650
2645
  }
2651
2646
  if (typ == EnumToken.FunctionTokenType || typ == EnumToken.IdenTokenType) {
2652
2647
  tokens.splice(k, 1);
@@ -2681,19 +2676,27 @@ function parseTokens(tokens, options = {}) {
2681
2676
  for (const { value, parent } of walkValues(t.chi)) {
2682
2677
  if (value.typ == EnumToken.WhitespaceTokenType) {
2683
2678
  const p = (parent ?? t);
2684
- for (let i = 0; i < (p).chi.length; i++) {
2679
+ for (let i = 0; i < p.chi.length; i++) {
2685
2680
  // @ts-ignore
2686
2681
  if (p.chi[i] == value) {
2687
2682
  // @ts-ignore
2688
- (p).chi.splice(i, 1);
2683
+ p.chi.splice(i, 1);
2689
2684
  i--;
2690
2685
  break;
2691
2686
  }
2692
2687
  }
2693
2688
  }
2694
- else if (value.typ == EnumToken.LiteralTokenType && ['+', '-', '/', '*'].includes(value.val)) {
2689
+ else if (value.typ == EnumToken.LiteralTokenType &&
2690
+ ["+", "-", "/", "*"].includes(value.val)) {
2695
2691
  // @ts-ignore
2696
- value.typ = value.val == '+' ? EnumToken.Add : (value.val == '-' ? EnumToken.Sub : (value.val == '*' ? EnumToken.Mul : EnumToken.Div));
2692
+ value.typ =
2693
+ value.val === "+"
2694
+ ? EnumToken.Add
2695
+ : value.val === "-"
2696
+ ? EnumToken.Sub
2697
+ : value.val === "*"
2698
+ ? EnumToken.Mul
2699
+ : EnumToken.Div;
2697
2700
  // @ts-ignore
2698
2701
  delete value.val;
2699
2702
  }
@@ -2706,7 +2709,8 @@ function parseTokens(tokens, options = {}) {
2706
2709
  return acc;
2707
2710
  }, []);
2708
2711
  }
2709
- else if (t.typ == EnumToken.FunctionTokenType && ['minmax', 'fit-content', 'repeat'].includes(t.val)) {
2712
+ else if (t.typ == EnumToken.FunctionTokenType &&
2713
+ ["minmax", "fit-content", "repeat"].includes(t.val)) {
2710
2714
  // @ts-ignore
2711
2715
  t.typ = EnumToken.GridTemplateFuncTokenType;
2712
2716
  }
@@ -2725,15 +2729,18 @@ function parseTokens(tokens, options = {}) {
2725
2729
  // @ts-ignore
2726
2730
  const value = t.chi[0].val.slice(1, -1);
2727
2731
  // @ts-ignore
2728
- if (t.chi[0].val.slice(1, 5) != 'data:' && urlTokenMatcher.test(value)) {
2732
+ if (t.chi[0].val.slice(1, 5) != "data:" && urlTokenMatcher.test(value)) {
2729
2733
  // @ts-ignore
2730
2734
  t.chi[0].typ = EnumToken.UrlTokenTokenType;
2731
2735
  // @ts-ignore
2732
- t.chi[0].val = options.src !== '' && options.resolveUrls ? options.resolve(value, options.src).absolute : value;
2736
+ t.chi[0].val =
2737
+ options.src !== "" && options.resolveUrls
2738
+ ? options.resolve(value, options.src)?.absolute
2739
+ : value;
2733
2740
  }
2734
2741
  }
2735
2742
  if (t.chi[0]?.typ == EnumToken.UrlTokenTokenType) {
2736
- if (options.src !== '' && options.resolveUrls) {
2743
+ if (options.src !== "" && options.resolveUrls) {
2737
2744
  // @ts-ignore
2738
2745
  t.chi[0].val = options.resolve(t.chi[0].val, options.src, options.cwd).relative;
2739
2746
  }
@@ -2741,12 +2748,14 @@ function parseTokens(tokens, options = {}) {
2741
2748
  }
2742
2749
  // @ts-ignore
2743
2750
  if (t.chi.length > 0) {
2744
- if (t.typ == EnumToken.PseudoClassFuncTokenType && t.val == ':is' && options.minify) {
2751
+ if (t.typ == EnumToken.PseudoClassFuncTokenType &&
2752
+ t.val === ":is" &&
2753
+ options.minify) {
2745
2754
  const count = t.chi.filter((t) => t.typ != EnumToken.CommentTokenType).length;
2746
2755
  if (count == 1 ||
2747
- (i == 0 &&
2748
- (tokens[i + 1]?.typ == EnumToken.CommaTokenType || tokens.length == i + 1)) ||
2749
- (tokens[i - 1]?.typ == EnumToken.CommaTokenType && (tokens[i + 1]?.typ == EnumToken.CommaTokenType || tokens.length == i + 1))) {
2756
+ (i == 0 && (tokens[i + 1]?.typ == EnumToken.CommaTokenType || tokens.length == i + 1)) ||
2757
+ (tokens[i - 1]?.typ == EnumToken.CommaTokenType &&
2758
+ (tokens[i + 1]?.typ == EnumToken.CommaTokenType || tokens.length == i + 1))) {
2750
2759
  tokens.splice(i, 1, ...t.chi);
2751
2760
  i = Math.max(0, i - t.chi.length);
2752
2761
  }
@@ -2757,4 +2766,4 @@ function parseTokens(tokens, options = {}) {
2757
2766
  return tokens;
2758
2767
  }
2759
2768
 
2760
- export { doParse, generateScopedName, getKeyName, getTokenType, parseAtRulePrelude, parseDeclarations, parseSelector, parseString, parseTokens, replaceToken, urlTokenMatcher };
2769
+ export { doParse, generateScopedName, getKeyName, getShortNameGenerator, parseAtRule, parseDeclarations, parseString, parseTokens, trimWhiteSpace };