@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
@@ -0,0 +1,2985 @@
1
+ import { getParsedSyntax, getSyntaxConfig } from './config.js';
2
+ import { EnumToken, ColorType } from '../ast/types.js';
3
+ import { ValidationSyntaxGroupEnum, ValidationTokenEnum, MediaFeatureType } from './parser/typedef.js';
4
+ import { tokensfuncDefMap, tokensfuncSet, funcLike, mFLT, mFGT } from '../syntax/constants.js';
5
+ import { pseudoElements, isValue, isColor } from '../syntax/syntax.js';
6
+ import { isDeclarationValue } from '../parser/utils/declaration.js';
7
+ import { renderSyntax } from './parser/parse.js';
8
+ import { equalsIgnoreCase } from '../parser/utils/text.js';
9
+
10
+ const config = getSyntaxConfig();
11
+ // @ts-expect-error
12
+ const allValues = config.declarations.all.syntax.split(/[\s|]+/g);
13
+ const funcTypes = [
14
+ ...tokensfuncDefMap.values(),
15
+ EnumToken.FunctionTokenType,
16
+ EnumToken.PseudoClassFuncTokenType,
17
+ ];
18
+ function trimArray(tokens) {
19
+ while (tokens[0]?.typ === EnumToken.WhitespaceTokenType) {
20
+ tokens.shift();
21
+ }
22
+ while (tokens[tokens.length - 1]?.typ === EnumToken.WhitespaceTokenType) {
23
+ tokens.pop();
24
+ }
25
+ return tokens;
26
+ }
27
+ function isMFName(featureName) {
28
+ return featureName.startsWith("--") || featureName.toLowerCase() in config.mediaFeatures;
29
+ }
30
+ /**
31
+ *
32
+ * @param featureName
33
+ * @returns
34
+ */
35
+ function getMFInfo(featureName) {
36
+ // @ts-expect-error
37
+ return config.mediaFeatures[featureName.toLowerCase()] ?? null;
38
+ }
39
+ /**
40
+ *
41
+ * @param featureName
42
+ * @param tokens
43
+ * @returns object with:
44
+ * - valid: boolean. true the media feaure is known or is a custom property. false otherwise
45
+ * - success: boolean. validation result
46
+ */
47
+ function isMFValue(featureName, tokens, isMFRange) {
48
+ // mf-value: <number> | <dimension> | <ident> | <ratio>
49
+ tokens = tokens.filter((token) => token.typ !== EnumToken.WhitespaceTokenType && token.typ !== EnumToken.CommentTokenType);
50
+ if (tokens.length === 0) {
51
+ return { valid: true, success: false };
52
+ }
53
+ // https://www.w3.org/TR/mediaqueries-5/#:~:text=Attempting%20to%20evaluate%20a%20min%2Fmax%20prefixed
54
+ // https://www.w3.org/TR/mediaqueries-5/#custom-mq
55
+ if (featureName.startsWith("--") || (isMFRange && /^((min)|(max))-/g.test(featureName))) {
56
+ return { valid: true, success: false, isValueAllowed: false };
57
+ }
58
+ featureName = featureName.toLowerCase();
59
+ if (!(featureName in config.mediaFeatures)) {
60
+ return { valid: false, success: false };
61
+ }
62
+ // @ts-expect-error
63
+ const mediaFeature = config.mediaFeatures[featureName];
64
+ if (tokens.length === 1 &&
65
+ tokens[0].typ === EnumToken.MathFunctionTokenType &&
66
+ tokens[0].val === "calc") {
67
+ // todo: check calc tokens are of compatible types : resolution, ratio, length, integer, number?
68
+ // https://github.com/web-platform-tests/wpt/blob/master/css/mediaqueries/mq-calc-sign-function-003.html
69
+ return {
70
+ valid: true,
71
+ success: mediaFeature.type !== MediaFeatureType.KeywordType && mediaFeature.type !== MediaFeatureType.StringType,
72
+ };
73
+ }
74
+ switch (mediaFeature.type) {
75
+ case MediaFeatureType.BooleanType:
76
+ return {
77
+ valid: true,
78
+ success: tokens.length === 1 &&
79
+ tokens[0].typ === EnumToken.NumberTokenType &&
80
+ (tokens[0].val === 0 || tokens[0].val === 1),
81
+ };
82
+ case MediaFeatureType.KeywordType:
83
+ return {
84
+ valid: true,
85
+ success: tokens.length === 1 &&
86
+ tokens[0].typ === EnumToken.IdenTokenType &&
87
+ mediaFeature.values.includes(tokens[0].val.toLowerCase()),
88
+ };
89
+ case MediaFeatureType.LengthType:
90
+ return { valid: true, success: tokens.length === 1 && tokens[0].typ == EnumToken.LengthTokenType };
91
+ case MediaFeatureType.IntergerType:
92
+ return {
93
+ valid: true,
94
+ success: tokens.length === 1 &&
95
+ tokens[0].typ == EnumToken.NumberTokenType &&
96
+ !tokens[0].val.toString().includes("."),
97
+ };
98
+ case MediaFeatureType.NumberType:
99
+ return {
100
+ valid: true,
101
+ success: tokens.length === 1 &&
102
+ tokens[0].typ == EnumToken.NumberTokenType &&
103
+ typeof tokens[0].val === "number",
104
+ };
105
+ case MediaFeatureType.StringType:
106
+ return { valid: true, success: tokens.length === 1 && tokens[0].typ == EnumToken.StringTokenType };
107
+ case MediaFeatureType.ResolutionType:
108
+ return { valid: true, success: tokens.length === 1 && tokens[0].typ == EnumToken.ResolutionTokenType };
109
+ case MediaFeatureType.RatioType:
110
+ return {
111
+ valid: true,
112
+ success: (tokens.length == 1 &&
113
+ tokens[0].typ == EnumToken.NumberTokenType &&
114
+ tokens[0].val.typ == EnumToken.FractionTokenType) ||
115
+ (tokens.length === 3 &&
116
+ tokens[0].typ == EnumToken.NumberTokenType &&
117
+ typeof tokens[0].val === "number" &&
118
+ tokens[1].typ == EnumToken.LiteralTokenType &&
119
+ tokens[1].val === "/" &&
120
+ tokens[2].typ == EnumToken.NumberTokenType &&
121
+ typeof tokens[2].val === "number"),
122
+ };
123
+ default:
124
+ console.debug("Unknown media feature type " + mediaFeature.type);
125
+ }
126
+ return {
127
+ valid: true,
128
+ success: true,
129
+ };
130
+ }
131
+ function isStyleRangeValue(tokens) {
132
+ const filtered = tokens.filter((token) => token.typ !== EnumToken.WhitespaceTokenType && token.typ !== EnumToken.CommentTokenType);
133
+ const result = isDeclarationValue(tokens);
134
+ if (result.success) {
135
+ result.success = filtered.length > 0;
136
+ }
137
+ return result;
138
+ }
139
+ function createValidationContext(tokens) {
140
+ tokens = trimArray(tokens.filter((t) => t.typ !== EnumToken.CommentTokenType));
141
+ if (tokens.at(-1)?.typ === EnumToken.ImportantTokenType) {
142
+ tokens.pop();
143
+ trimArray(tokens);
144
+ }
145
+ const token = {
146
+ tokens,
147
+ index: -1,
148
+ current() {
149
+ if (this.index < 0) {
150
+ return null;
151
+ }
152
+ while (this.tokens[this.index]?.typ == EnumToken.WhitespaceTokenType ||
153
+ this.tokens[this.index]?.typ == EnumToken.CommentTokenType ||
154
+ this.tokens[this.index]?.typ == EnumToken.CDOCOMMTokenType) {
155
+ this.index++;
156
+ }
157
+ return this.tokens[this.index];
158
+ },
159
+ peek(offset = 0, skipWhitespace = true) {
160
+ let index = this.index;
161
+ let token = this.tokens[++index];
162
+ if (!skipWhitespace) {
163
+ while (offset >= 0 && index < this.tokens.length) {
164
+ while (token != null && token.typ === EnumToken.CommentTokenType) {
165
+ token = this.tokens[++index];
166
+ }
167
+ if (offset === 0 || token == null) {
168
+ return token;
169
+ }
170
+ offset--;
171
+ token = this.tokens[++index];
172
+ }
173
+ return token;
174
+ }
175
+ while (offset >= 0 && index < this.tokens.length) {
176
+ while (token?.typ == EnumToken.WhitespaceTokenType ||
177
+ token?.typ == EnumToken.CommentTokenType ||
178
+ token?.typ == EnumToken.CDOCOMMTokenType) {
179
+ token = this.tokens[++index];
180
+ }
181
+ if (token == null || offset === 0) {
182
+ return token;
183
+ }
184
+ offset--;
185
+ token = this.tokens[++index];
186
+ }
187
+ return token;
188
+ },
189
+ /**
190
+ *
191
+ * @param stopCondition
192
+ * @param matchCount
193
+ * @returns
194
+ */
195
+ peekRange(open = EnumToken.StartParensTokenType, close = EnumToken.EndParensTokenType, counter = 0) {
196
+ let index = this.index;
197
+ let token = this.tokens[index];
198
+ // track balanced parens
199
+ let matchCount = 0;
200
+ const tokens = [];
201
+ while (index + 1 < this.tokens.length && this.tokens[index + 1]?.typ === EnumToken.WhitespaceTokenType) {
202
+ index++;
203
+ }
204
+ while (index + 1 < this.tokens.length) {
205
+ token = this.tokens[++index];
206
+ if (token?.typ === EnumToken.StartParensTokenType || tokensfuncDefMap.has(token?.typ)) {
207
+ matchCount++;
208
+ }
209
+ else if (token?.typ === EnumToken.EndParensTokenType) {
210
+ matchCount--;
211
+ }
212
+ if (matchCount >= 0) {
213
+ tokens.push(token);
214
+ }
215
+ if (matchCount === 0) {
216
+ if (close !== EnumToken.EndParensTokenType && token?.typ === close) {
217
+ counter--;
218
+ }
219
+ else if (open !== EnumToken.StartParensTokenType && token?.typ === open) {
220
+ counter++;
221
+ }
222
+ }
223
+ if (matchCount <= 0 && counter <= 0) {
224
+ break;
225
+ }
226
+ }
227
+ if (tokens[0]?.typ === EnumToken.WhitespaceTokenType) {
228
+ tokens.shift();
229
+ }
230
+ return tokens;
231
+ },
232
+ // 2
233
+ split(split = EnumToken.CommaTokenType) {
234
+ let index = this.index;
235
+ let token = this.tokens[index];
236
+ // track balanced parens
237
+ let matchCount = 0;
238
+ const tokens = [[]];
239
+ while (index + 1 < this.tokens.length) {
240
+ token = this.tokens[++index];
241
+ if (token?.typ === EnumToken.StartParensTokenType || tokensfuncDefMap.has(token?.typ)) {
242
+ matchCount++;
243
+ }
244
+ else if (token?.typ === EnumToken.EndParensTokenType) {
245
+ matchCount--;
246
+ }
247
+ if (matchCount === 0 && token.typ === split) {
248
+ tokens.at(-1).push(token);
249
+ tokens.push([]);
250
+ }
251
+ else {
252
+ tokens.at(-1).push(token);
253
+ }
254
+ }
255
+ return tokens;
256
+ },
257
+ getRemainingTokens() {
258
+ return this.tokens.slice(this.index + 1);
259
+ },
260
+ last() {
261
+ let index = this.tokens.length - 1;
262
+ let token = this.tokens[index];
263
+ while ((this.index >= 0 && token?.typ === EnumToken.WhitespaceTokenType) ||
264
+ token?.typ === EnumToken.CommentTokenType ||
265
+ token?.typ === EnumToken.CDOCOMMTokenType ||
266
+ token?.typ === EnumToken.InvalidCommentTokenType ||
267
+ token?.typ === EnumToken.BadCommentTokenType ||
268
+ token?.typ === EnumToken.BadStringTokenType) {
269
+ token = this.tokens[--index];
270
+ if (token == null) {
271
+ break;
272
+ }
273
+ }
274
+ return token;
275
+ },
276
+ end() {
277
+ this.index = this.tokens.length + 1;
278
+ return this;
279
+ },
280
+ next() {
281
+ let token = this.tokens[++this.index];
282
+ while (token?.typ === EnumToken.WhitespaceTokenType ||
283
+ token?.typ === EnumToken.CommentTokenType ||
284
+ token?.typ === EnumToken.CDOCOMMTokenType ||
285
+ token?.typ === EnumToken.InvalidCommentTokenType ||
286
+ token?.typ === EnumToken.BadCommentTokenType ||
287
+ token?.typ === EnumToken.BadStringTokenType) {
288
+ token = this.tokens[++this.index];
289
+ }
290
+ return token;
291
+ },
292
+ slice() {
293
+ return {
294
+ ...token,
295
+ index: this.index == -1 ? -1 : 0,
296
+ tokens: this.index == -1 ? this.tokens.slice() : this.tokens.slice(this.index),
297
+ };
298
+ },
299
+ update(token) {
300
+ const index = this.tokens.indexOf(token);
301
+ if (index != -1) {
302
+ this.index = index;
303
+ }
304
+ return this;
305
+ },
306
+ done() {
307
+ if (this.index + 1 < this.tokens.length) {
308
+ let index = this.index + 1;
309
+ while (index < this.tokens.length) {
310
+ if (this.tokens[index].typ === EnumToken.WhitespaceTokenType ||
311
+ this.tokens[index].typ === EnumToken.CommentTokenType) {
312
+ index++;
313
+ }
314
+ else {
315
+ return false;
316
+ }
317
+ }
318
+ }
319
+ return true;
320
+ },
321
+ };
322
+ return token;
323
+ }
324
+ function matchSelectorSyntax(stream, errors, options, nested) {
325
+ const stack = [];
326
+ const tokens = [];
327
+ const nodes = [
328
+ EnumToken.CommaTokenType,
329
+ EnumToken.ColumnCombinatorTokenType,
330
+ EnumToken.ChildCombinatorTokenType,
331
+ EnumToken.NextSiblingCombinatorTokenType,
332
+ EnumToken.SubsequentSiblingCombinatorTokenType,
333
+ ];
334
+ const trimWhitespaceBefore = nodes.concat(EnumToken.DelimTokenType, EnumToken.DashMatchTokenType, EnumToken.IncludeMatchTokenType, EnumToken.ContainMatchTokenType, EnumToken.StartMatchTokenType, EnumToken.EndMatchTokenType, EnumToken.AttrEndTokenType);
335
+ const trimWhitespaceAfter = nodes.concat(EnumToken.DelimTokenType, EnumToken.DashMatchTokenType, EnumToken.IncludeMatchTokenType, EnumToken.ContainMatchTokenType, EnumToken.StartMatchTokenType, EnumToken.EndMatchTokenType, EnumToken.AttrStartTokenType);
336
+ const enumMap = new Map([
337
+ [EnumToken.Tilda, EnumToken.SubsequentSiblingCombinatorTokenType],
338
+ [EnumToken.GtTokenType, EnumToken.ChildCombinatorTokenType],
339
+ ]);
340
+ let token;
341
+ let i = 0;
342
+ let success = true;
343
+ if (!nested) {
344
+ while (i < stream.length &&
345
+ (stream[i].typ === EnumToken.WhitespaceTokenType || stream[i].typ === EnumToken.CommentTokenType)) {
346
+ i++;
347
+ }
348
+ if (i < stream.length) {
349
+ switch (stream[i].typ) {
350
+ case EnumToken.Plus:
351
+ case EnumToken.Tilda:
352
+ case EnumToken.GtTokenType:
353
+ case EnumToken.ColumnCombinatorTokenType:
354
+ case EnumToken.ChildCombinatorTokenType:
355
+ case EnumToken.NextSiblingCombinatorTokenType:
356
+ case EnumToken.SubsequentSiblingCombinatorTokenType:
357
+ return {
358
+ success: false,
359
+ errors: [
360
+ {
361
+ action: "drop",
362
+ message: `Unexpected token ${EnumToken[stream[i].typ]} at ${stream[i].loc.src}:${stream[i].loc.sta.lin}:${stream[i].loc.sta.col}`,
363
+ node: stream[i],
364
+ location: stream[i].loc,
365
+ },
366
+ ],
367
+ };
368
+ }
369
+ }
370
+ }
371
+ for (; i < stream.length; i++) {
372
+ token = stream[i];
373
+ if (token.typ === EnumToken.EOF) {
374
+ break;
375
+ }
376
+ tokens.push(token);
377
+ if (tokensfuncDefMap.has(token.typ)) {
378
+ if (stack.at(-1)?.typ === EnumToken.CommaTokenType) {
379
+ stack.pop();
380
+ }
381
+ stack.push(token);
382
+ continue;
383
+ }
384
+ if (stack.length > 0 &&
385
+ nodes.includes(stack.at(-1).typ) &&
386
+ !nodes.includes(token.typ) &&
387
+ token.typ !== EnumToken.WhitespaceTokenType &&
388
+ token.typ !== EnumToken.CommentTokenType &&
389
+ token.typ !== EnumToken.CDOCOMMTokenType) {
390
+ stack.pop();
391
+ }
392
+ if (token.typ === EnumToken.LiteralTokenType && "+" === token.val) {
393
+ Object.assign(token, { typ: EnumToken.NextSiblingCombinatorTokenType });
394
+ continue;
395
+ }
396
+ switch (token.typ) {
397
+ case EnumToken.InvalidCommentTokenType:
398
+ case EnumToken.BadCommentTokenType:
399
+ case EnumToken.BadStringTokenType:
400
+ break;
401
+ case EnumToken.WhitespaceTokenType:
402
+ case EnumToken.CommentTokenType:
403
+ case EnumToken.CDOCOMMTokenType:
404
+ break;
405
+ case EnumToken.NestingSelectorTokenType:
406
+ if (nested === false && !options.nestedRule) {
407
+ return {
408
+ success: false,
409
+ errors: [
410
+ {
411
+ action: "drop",
412
+ message: `Nesting selector is not allowed at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
413
+ node: token,
414
+ location: token.loc,
415
+ },
416
+ ],
417
+ };
418
+ }
419
+ break;
420
+ case EnumToken.Plus:
421
+ Object.assign(token, { typ: EnumToken.NextSiblingCombinatorTokenType });
422
+ if (stack.length > 0 && nodes.includes(stack.at(-1)?.typ)) {
423
+ return {
424
+ success: false,
425
+ errors: [
426
+ {
427
+ action: "drop",
428
+ message: `Unexpected combinator ${EnumToken[token.typ]} at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
429
+ node: token,
430
+ location: token.loc,
431
+ },
432
+ ],
433
+ };
434
+ }
435
+ stack.push(token);
436
+ break;
437
+ case EnumToken.Tilda:
438
+ case EnumToken.GtTokenType:
439
+ Object.assign(token, { typ: enumMap.get(token.typ) });
440
+ case EnumToken.ColumnCombinatorTokenType:
441
+ case EnumToken.ChildCombinatorTokenType:
442
+ case EnumToken.UniversalSelectorTokenType:
443
+ case EnumToken.DescendantCombinatorTokenType:
444
+ case EnumToken.NextSiblingCombinatorTokenType:
445
+ case EnumToken.SubsequentSiblingCombinatorTokenType:
446
+ if (tokens.at(-1)?.typ === EnumToken.WhitespaceTokenType) {
447
+ tokens.pop();
448
+ }
449
+ if (stream[i + 1]?.typ === EnumToken.WhitespaceTokenType) {
450
+ i++;
451
+ }
452
+ if (stack.length > 0 && nodes.includes(stack.at(-1)?.typ)) {
453
+ return {
454
+ success: false,
455
+ errors: [
456
+ {
457
+ action: "drop",
458
+ message: `Unexpected combinator ${EnumToken[token.typ]} at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
459
+ node: token,
460
+ location: token.loc,
461
+ },
462
+ ],
463
+ };
464
+ }
465
+ stack.push(token);
466
+ break;
467
+ case EnumToken.CommaTokenType:
468
+ if (tokens.length === 0 || stack.at(-1)?.typ == EnumToken.CommaTokenType) {
469
+ return {
470
+ success: false,
471
+ errors: [
472
+ {
473
+ action: "drop",
474
+ message: `Unexpected token ${EnumToken[token.typ]} at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
475
+ node: token,
476
+ location: token.loc,
477
+ },
478
+ ],
479
+ };
480
+ }
481
+ stack.push(token);
482
+ if (!nested) {
483
+ let k = i + 1;
484
+ while (k < stream.length &&
485
+ (stream[k].typ === EnumToken.WhitespaceTokenType ||
486
+ stream[k].typ === EnumToken.CommentTokenType)) {
487
+ k++;
488
+ }
489
+ // :has(> a, ~b, +c)
490
+ if (!tokensfuncDefMap.has(stack.at(-2)?.typ) && k < stream.length) {
491
+ switch (stream[k].typ) {
492
+ case EnumToken.Plus:
493
+ case EnumToken.Tilda:
494
+ case EnumToken.GtTokenType:
495
+ case EnumToken.ColumnCombinatorTokenType:
496
+ case EnumToken.ChildCombinatorTokenType:
497
+ case EnumToken.NextSiblingCombinatorTokenType:
498
+ case EnumToken.SubsequentSiblingCombinatorTokenType:
499
+ return {
500
+ success: false,
501
+ errors: [
502
+ {
503
+ action: "drop",
504
+ message: `Unexpected token ${EnumToken[stream[k].typ]} at ${stream[k].loc.src}:${stream[k].loc.sta.lin}:${stream[k].loc.sta.col}`,
505
+ node: stream[k],
506
+ location: stream[k].loc,
507
+ },
508
+ ],
509
+ };
510
+ }
511
+ }
512
+ }
513
+ break;
514
+ case EnumToken.Pipe:
515
+ case EnumToken.DelimTokenType:
516
+ case EnumToken.StringTokenType:
517
+ case EnumToken.IncludeMatchTokenType:
518
+ case EnumToken.ContainMatchTokenType:
519
+ case EnumToken.StartMatchTokenType:
520
+ case EnumToken.EndMatchTokenType:
521
+ case EnumToken.DashMatchTokenType:
522
+ if (stack.at(-1)?.typ !== EnumToken.AttrStartTokenType) {
523
+ return {
524
+ success: false,
525
+ errors: [
526
+ {
527
+ action: "drop",
528
+ message: `Unexpected token ${EnumToken[token.typ]} at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
529
+ node: token,
530
+ location: token.loc,
531
+ },
532
+ ],
533
+ };
534
+ }
535
+ break;
536
+ case EnumToken.Star:
537
+ Object.assign(token, { typ: EnumToken.UniversalSelectorTokenType });
538
+ break;
539
+ case EnumToken.IdenTokenType:
540
+ case EnumToken.HashTokenType:
541
+ case EnumToken.PseudoElementTokenType:
542
+ case EnumToken.PseudoClassTokenType:
543
+ case EnumToken.ClassSelectorTokenType:
544
+ if (stack.at(-1)?.typ === EnumToken.CommaTokenType) {
545
+ stack.pop();
546
+ }
547
+ break;
548
+ case EnumToken.AttrStartTokenType:
549
+ if (stack.at(-1)?.typ === EnumToken.CommaTokenType) {
550
+ stack.pop();
551
+ }
552
+ stack.push(token);
553
+ break;
554
+ case EnumToken.AttrEndTokenType:
555
+ if (stack.at(-1)?.typ !== EnumToken.AttrStartTokenType) {
556
+ return {
557
+ success: false,
558
+ errors: [
559
+ {
560
+ action: "drop",
561
+ message: `Unexpected token ${EnumToken[token.typ]} at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
562
+ node: token,
563
+ location: token.loc,
564
+ },
565
+ ],
566
+ };
567
+ }
568
+ {
569
+ const k = tokens.length - 1;
570
+ let index = tokens.indexOf(stack.at(-1));
571
+ const slice = [];
572
+ for (let n = index + 1; n < k; n++) {
573
+ if (tokens[n].typ === EnumToken.WhitespaceTokenType ||
574
+ tokens[n].typ === EnumToken.CommentTokenType ||
575
+ tokens[n].typ === EnumToken.CDOCOMMTokenType) {
576
+ continue;
577
+ }
578
+ slice.push(tokens[n]);
579
+ }
580
+ if (slice.length === 0) {
581
+ return {
582
+ success: false,
583
+ errors: [
584
+ {
585
+ action: "drop",
586
+ message: `Invalid selector attribute at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
587
+ node: token,
588
+ location: token.loc,
589
+ },
590
+ ],
591
+ };
592
+ }
593
+ if (slice[1]?.typ === EnumToken.Pipe) {
594
+ if (slice[0].typ !== EnumToken.UniversalSelectorTokenType &&
595
+ slice[0].typ !== EnumToken.Star &&
596
+ slice[0].typ !== EnumToken.IdenTokenType) {
597
+ return {
598
+ success: false,
599
+ errors: [
600
+ {
601
+ action: "drop",
602
+ message: `Invalid selector attribute at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
603
+ node: token,
604
+ location: token.loc,
605
+ },
606
+ ],
607
+ };
608
+ }
609
+ slice.shift();
610
+ }
611
+ if (slice[0].typ === EnumToken.Pipe) {
612
+ if (slice.length === 1) {
613
+ return {
614
+ success: false,
615
+ errors: [
616
+ {
617
+ action: "drop",
618
+ message: `Invalid selector attribute at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
619
+ node: token,
620
+ location: token.loc,
621
+ },
622
+ ],
623
+ };
624
+ }
625
+ if (slice[1]?.typ !== EnumToken.IdenTokenType) {
626
+ return {
627
+ success: false,
628
+ errors: [
629
+ {
630
+ action: "drop",
631
+ message: `Invalid selector attribute at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
632
+ node: token,
633
+ location: token.loc,
634
+ },
635
+ ],
636
+ };
637
+ }
638
+ slice.shift();
639
+ }
640
+ if (slice.length === 1) {
641
+ if (slice[0].typ !== EnumToken.IdenTokenType) {
642
+ return {
643
+ success: false,
644
+ errors: [
645
+ {
646
+ action: "drop",
647
+ message: `Invalid selector attribute at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
648
+ node: token,
649
+ location: token.loc,
650
+ },
651
+ ],
652
+ };
653
+ }
654
+ stack.pop();
655
+ break;
656
+ }
657
+ slice.shift();
658
+ if (slice[0].typ != EnumToken.DelimTokenType &&
659
+ slice[0].typ !== EnumToken.DashMatchTokenType &&
660
+ slice[0].typ !== EnumToken.EndMatchTokenType &&
661
+ slice[0].typ !== EnumToken.IncludeMatchTokenType &&
662
+ slice[0].typ !== EnumToken.StartMatchTokenType &&
663
+ slice[0].typ !== EnumToken.ContainMatchTokenType) {
664
+ return {
665
+ success: false,
666
+ errors: [
667
+ {
668
+ action: "drop",
669
+ message: `Unexpected token ${EnumToken[slice[0].typ]} at ${slice[0].loc.src}:${slice[0].loc.sta.lin}:${slice[0].loc.sta.col}`,
670
+ node: slice[0],
671
+ location: slice[0].loc,
672
+ },
673
+ ],
674
+ };
675
+ }
676
+ slice.shift();
677
+ if (slice.length === 0) {
678
+ // expect iden or string
679
+ return {
680
+ success: false,
681
+ errors: [
682
+ {
683
+ action: "drop",
684
+ message: `Invalid selector attribute at ${slice[0].loc.src}:${slice[0].loc.sta.lin}:${slice[0].loc.sta.col}`,
685
+ node: slice[0],
686
+ location: slice[0].loc,
687
+ },
688
+ ],
689
+ };
690
+ }
691
+ if (slice[0].typ !== EnumToken.IdenTokenType && slice[0].typ !== EnumToken.StringTokenType) {
692
+ return {
693
+ success: false,
694
+ errors: [
695
+ {
696
+ action: "drop",
697
+ message: `Unexpected token ${EnumToken[slice[0].typ]} at ${slice[0].loc.src}:${slice[0].loc.sta.lin}:${slice[0].loc.sta.col}`,
698
+ node: slice[0],
699
+ location: slice[0].loc,
700
+ },
701
+ ],
702
+ };
703
+ }
704
+ if (slice[0]?.typ === EnumToken.StringTokenType &&
705
+ /^[a-zA-Z0-9_-]+$/.test(slice[0].val.slice(1, -1))) {
706
+ Object.assign(slice[0], {
707
+ typ: EnumToken.IdenTokenType,
708
+ val: slice[0].val.slice(1, -1),
709
+ });
710
+ }
711
+ slice.shift();
712
+ if (slice.length === 0) {
713
+ stack.pop();
714
+ break;
715
+ }
716
+ if (slice[0].typ !== EnumToken.IdenTokenType ||
717
+ (slice[0].val != "i" && slice[0].val != "s")) {
718
+ return {
719
+ success: false,
720
+ errors: [
721
+ {
722
+ action: "drop",
723
+ message: `Unexpected token ${EnumToken[slice[0].typ]} at ${slice[0].loc.src}:${slice[0].loc.sta.lin}:${slice[0].loc.sta.col}`,
724
+ node: slice[0],
725
+ location: slice[0].loc,
726
+ },
727
+ ],
728
+ };
729
+ }
730
+ slice.shift();
731
+ if (slice.length > 0) {
732
+ return {
733
+ success: false,
734
+ errors: [
735
+ {
736
+ action: "drop",
737
+ message: `Unexpected token ${EnumToken[slice[0].typ]} at ${slice[0].loc.src}:${slice[0].loc.sta.lin}:${slice[0].loc.sta.col}`,
738
+ node: slice[0],
739
+ location: slice[0].loc,
740
+ },
741
+ ],
742
+ };
743
+ }
744
+ stack.pop();
745
+ break;
746
+ }
747
+ case EnumToken.ColonTokenType:
748
+ if (stream[i + 1]?.typ === EnumToken.IdenTokenType) {
749
+ Object.assign(token, {
750
+ typ: stream[i + 1].val === "page"
751
+ ? EnumToken.PseudoPageTokenType
752
+ : pseudoElements.includes(token.val)
753
+ ? EnumToken.PseudoElementTokenType
754
+ : EnumToken.PseudoClassTokenType,
755
+ val: ":" + stream[i + 1].val,
756
+ });
757
+ token.loc.end = stream[++i].loc.end;
758
+ break;
759
+ }
760
+ else if (stream[i + 1]?.typ === EnumToken.FunctionTokenDefType) {
761
+ Object.assign(token, {
762
+ typ: EnumToken.PseudoClassFunctionTokenDefType,
763
+ val: ":" + stream[i + 1].val,
764
+ });
765
+ token.loc.end = stream[++i].loc.end;
766
+ stack.push(token);
767
+ break;
768
+ }
769
+ return {
770
+ success: false,
771
+ errors: [
772
+ {
773
+ action: "drop",
774
+ message: `Unexpected token ${EnumToken[token.typ]} at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
775
+ node: token,
776
+ location: token.loc,
777
+ },
778
+ ],
779
+ };
780
+ case EnumToken.DoubleColonTokenType:
781
+ if (stream[i + 1]?.typ === EnumToken.IdenTokenType) {
782
+ Object.assign(token, {
783
+ typ: stream[i + 1].val === "page"
784
+ ? EnumToken.PseudoPageTokenType
785
+ : EnumToken.PseudoElementTokenType,
786
+ val: "::" + stream[i + 1].val,
787
+ });
788
+ token.loc.end = stream[++i].loc.end;
789
+ break;
790
+ }
791
+ else if (stream[i + 1]?.typ === EnumToken.FunctionTokenDefType) {
792
+ Object.assign(token, {
793
+ typ: EnumToken.PseudoClassFunctionTokenDefType,
794
+ val: "::" + stream[i + 1].val,
795
+ });
796
+ token.loc.end = stream[++i].loc.end;
797
+ stack.push(token);
798
+ break;
799
+ }
800
+ return {
801
+ success: false,
802
+ errors: [
803
+ {
804
+ action: "drop",
805
+ message: `Unexpected token ${EnumToken[token.typ]} at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
806
+ node: token,
807
+ location: token.loc,
808
+ },
809
+ ],
810
+ };
811
+ case EnumToken.StartParensTokenType:
812
+ if (tokens.at(-2)?.typ === EnumToken.PseudoClassTokenType ||
813
+ tokens.at(-2)?.typ === EnumToken.PseudoElementTokenType) {
814
+ stack.push(Object.assign(tokens.at(-2), {
815
+ typ: EnumToken.PseudoClassFunctionTokenDefType,
816
+ chi: [],
817
+ }));
818
+ tokens.pop();
819
+ break;
820
+ }
821
+ return {
822
+ success: false,
823
+ errors: [
824
+ {
825
+ action: "drop",
826
+ message: `Unexpected token ${EnumToken[token.typ]} at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
827
+ node: token,
828
+ location: token.loc,
829
+ },
830
+ ],
831
+ };
832
+ case EnumToken.EndParensTokenType:
833
+ if (stack.at(-1)?.typ === EnumToken.PseudoClassFunctionTokenDefType ||
834
+ stack.at(-1)?.typ === EnumToken.PseudoElementTokenType) {
835
+ const token = stack.at(-1);
836
+ if (!(stack.at(-1).val + "()" in config.selectors)) {
837
+ return {
838
+ errors: [
839
+ {
840
+ action: "drop",
841
+ message: `Unknown class element ${token.val}`,
842
+ node: token,
843
+ location: token.loc,
844
+ },
845
+ ],
846
+ success: false,
847
+ };
848
+ }
849
+ const index = tokens.indexOf(token);
850
+ const result = matchAllSyntax(getParsedSyntax(ValidationSyntaxGroupEnum.Selectors, token.val + "()")?.[0]?.chi ?? [], createValidationContext(tokens.slice(index + 1, tokens.length - 1)), options);
851
+ if (!result.success) {
852
+ success = false;
853
+ if (result.errors.length > 0) {
854
+ errors.push(...result.errors);
855
+ }
856
+ }
857
+ stack.pop();
858
+ break;
859
+ }
860
+ return {
861
+ success: false,
862
+ errors: [
863
+ {
864
+ action: "drop",
865
+ message: `Unexpected token ${EnumToken[token.typ]} at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
866
+ node: token,
867
+ location: token.loc,
868
+ },
869
+ ],
870
+ };
871
+ case EnumToken.NumberTokenType:
872
+ case EnumToken.LiteralTokenType:
873
+ case EnumToken.DimensionTokenType:
874
+ if (stack.at(-1)?.typ === EnumToken.CommaTokenType) {
875
+ stack.pop();
876
+ }
877
+ if (stack.at(-1)?.typ === EnumToken.PseudoClassFunctionTokenDefType) {
878
+ break;
879
+ }
880
+ default:
881
+ return {
882
+ success: false,
883
+ errors: [
884
+ {
885
+ action: "drop",
886
+ message: `Unsupported selector token ${EnumToken[token.typ]} at ${token.loc.src}:${token.loc.sta.lin}:${token.loc.sta.col}`,
887
+ node: token,
888
+ location: token.loc,
889
+ },
890
+ ],
891
+ };
892
+ }
893
+ if (token.typ === EnumToken.WhitespaceTokenType &&
894
+ trimWhitespaceAfter.includes(tokens.at(-2)?.typ) &&
895
+ tokens.at(-1)?.typ === EnumToken.WhitespaceTokenType) {
896
+ tokens.pop();
897
+ }
898
+ else if (trimWhitespaceBefore.includes(token.typ) && tokens.at(-2)?.typ === EnumToken.WhitespaceTokenType) {
899
+ tokens.splice(tokens.length - 2, 1);
900
+ }
901
+ }
902
+ if (stack.length > 0) {
903
+ return {
904
+ success: false,
905
+ errors: [
906
+ {
907
+ action: "drop",
908
+ message: `Unmatched token ${EnumToken[stack.at(-1).typ]} at ${stack.at(-1).loc.src}:${stack.at(-1).loc.sta.lin}:${stack.at(-1).loc.sta.col}`,
909
+ node: stack.at(-1),
910
+ location: stack.at(-1).loc,
911
+ },
912
+ ],
913
+ };
914
+ }
915
+ stream.length = 0;
916
+ stream.push(...tokens);
917
+ if (!success && errors.length === 0) {
918
+ errors.push({
919
+ action: "drop",
920
+ message: "Invalid selector",
921
+ node: tokens[0],
922
+ location: tokens[0].loc,
923
+ });
924
+ }
925
+ return { success, errors };
926
+ }
927
+ function matchAllSyntax(syntaxes, context, options) {
928
+ const result = matchSyntax(syntaxes, context, {
929
+ ...options,
930
+ visited: new Map(),
931
+ });
932
+ if (result.success && !result.context.done()) {
933
+ const node = result.context.peek();
934
+ return {
935
+ ...result,
936
+ success: false,
937
+ token: context.peek(),
938
+ errors: [
939
+ ...result.errors,
940
+ {
941
+ action: "drop",
942
+ message: `Unexpected token ${EnumToken[node?.typ]} at ${node.loc?.src}:${node.loc?.sta?.lin}:${node.loc?.sta?.col}`,
943
+ node,
944
+ syntax: result.syntaxToken ??
945
+ syntaxes?.reduce?.((acc, b) => acc + renderSyntax(b), "")?.trim?.() ??
946
+ null,
947
+ },
948
+ ],
949
+ };
950
+ }
951
+ if (syntaxes != null && result.success && result.syntaxToken != null) {
952
+ const index = syntaxes.indexOf(result.syntaxToken);
953
+ if (index != -1) {
954
+ for (let i = index; i < syntaxes.length; i++) {
955
+ if (syntaxes[i].typ == ValidationTokenEnum.Whitespace ||
956
+ syntaxes[i].isOptional ||
957
+ syntaxes[i].isRepeatable) {
958
+ continue;
959
+ }
960
+ if (syntaxes[i].typ == ValidationTokenEnum.SemiColon && i === syntaxes.length - 1) {
961
+ continue;
962
+ }
963
+ return {
964
+ ...result,
965
+ success: false,
966
+ syntaxToken: syntaxes[i],
967
+ };
968
+ }
969
+ }
970
+ }
971
+ return {
972
+ ...result,
973
+ errors: !result.success && result.errors.length === 0
974
+ ? [
975
+ {
976
+ action: "drop",
977
+ message: result.errors[0]?.message || "could not match syntax",
978
+ node: result.token,
979
+ syntax: result.syntaxToken,
980
+ location: result.token?.loc ?? context.tokens.at(-1)?.loc,
981
+ },
982
+ ]
983
+ : result.errors,
984
+ syntaxToken: !result.success ? result.syntaxToken : null,
985
+ };
986
+ }
987
+ function matchListSyntax(syntax, context, options) {
988
+ const { isList, match, isOptional, ...rest } = syntax;
989
+ let success = true;
990
+ let result = null;
991
+ let tmpResult;
992
+ let count = 0;
993
+ let range;
994
+ success = false;
995
+ do {
996
+ range = context.peekRange(EnumToken.CommaTokenType, EnumToken.CommaTokenType, 1);
997
+ tmpResult = matchSyntax([rest], createValidationContext(range.at(-1)?.typ === EnumToken.CommaTokenType ? range.slice(0, -1) : range), options);
998
+ if (tmpResult.success) {
999
+ count++;
1000
+ success = true;
1001
+ result = tmpResult;
1002
+ context.update(range.at(-1));
1003
+ if (context.done()) {
1004
+ // context.end();
1005
+ break;
1006
+ }
1007
+ if (Number.isFinite(match?.max?.val) && count === match.max.val) {
1008
+ break;
1009
+ }
1010
+ }
1011
+ } while (tmpResult.success && !context.done());
1012
+ if (result?.success && match != null) {
1013
+ if (count < match.min.val || (Number.isFinite(match.max) && count > match.max.val)) {
1014
+ return {
1015
+ ...result,
1016
+ success: false,
1017
+ errors: [
1018
+ {
1019
+ action: "drop",
1020
+ message: "could not match syntax",
1021
+ node: context.peek(),
1022
+ location: context.peek()?.loc,
1023
+ },
1024
+ ],
1025
+ };
1026
+ }
1027
+ }
1028
+ return {
1029
+ ...(result ?? tmpResult),
1030
+ success,
1031
+ context,
1032
+ token: context.peek(),
1033
+ };
1034
+ }
1035
+ function matchOccurenceSyntax(syntax, context, options) {
1036
+ const { match, ...rest } = syntax;
1037
+ let result = null;
1038
+ let tmpResult;
1039
+ let count = 0;
1040
+ do {
1041
+ tmpResult = matchSyntax([rest], context.slice(), options);
1042
+ if (tmpResult.success) {
1043
+ count++;
1044
+ result = tmpResult;
1045
+ if (tmpResult.context.done()) {
1046
+ context.end();
1047
+ break;
1048
+ }
1049
+ context.update(tmpResult.context.current());
1050
+ if (match?.max?.val != null && Number.isFinite(match?.max?.val) && count === match.max.val) {
1051
+ break;
1052
+ }
1053
+ }
1054
+ } while (tmpResult.success && !context.done());
1055
+ if (match != null &&
1056
+ (count < match.min.val || (Number.isFinite(match.max?.val) && count > match.max.val))) {
1057
+ return {
1058
+ success: false,
1059
+ errors: [
1060
+ {
1061
+ action: "drop",
1062
+ message: "could not match syntax",
1063
+ node: context.peek(),
1064
+ location: context.peek()?.loc,
1065
+ },
1066
+ ],
1067
+ syntaxToken: null,
1068
+ valid: true,
1069
+ context,
1070
+ token: null,
1071
+ };
1072
+ }
1073
+ return (result ?? {
1074
+ success: false,
1075
+ errors: [
1076
+ {
1077
+ action: "drop",
1078
+ message: "could not match syntax",
1079
+ node: context.peek(),
1080
+ location: context.peek().loc,
1081
+ },
1082
+ ],
1083
+ syntaxToken: syntax,
1084
+ valid: true,
1085
+ context,
1086
+ token: context.peek(),
1087
+ });
1088
+ }
1089
+ function matchSyntax(syntaxes, context, options) {
1090
+ if (syntaxes == null) {
1091
+ return {
1092
+ syntaxToken: null,
1093
+ token: context.peek(),
1094
+ success: true,
1095
+ valid: false,
1096
+ context,
1097
+ errors: [],
1098
+ };
1099
+ }
1100
+ syntaxes = syntaxes.slice();
1101
+ let i = -1;
1102
+ let success;
1103
+ let token = null;
1104
+ let result = null;
1105
+ let isOptional;
1106
+ if (context.tokens.length == 1 &&
1107
+ context.tokens[0].typ == EnumToken.IdenTokenType &&
1108
+ allValues.some((v) => equalsIgnoreCase(v, context.tokens[0].val))) {
1109
+ context.end();
1110
+ return {
1111
+ syntaxToken: null,
1112
+ token: context.peek(),
1113
+ success: true,
1114
+ valid: true,
1115
+ context,
1116
+ errors: [],
1117
+ };
1118
+ }
1119
+ while (++i < syntaxes.length) {
1120
+ if (syntaxes[i].typ == ValidationTokenEnum.Whitespace) {
1121
+ continue;
1122
+ }
1123
+ isOptional =
1124
+ (syntaxes[i].isOptional === true ||
1125
+ syntaxes[i].isRepeatable === true ||
1126
+ syntaxes[i].isRepeatable === true) &&
1127
+ !syntaxes[i].isMandatatoryGroup;
1128
+ token = context.peek();
1129
+ if (token == null) {
1130
+ if (!isOptional) {
1131
+ return {
1132
+ success: false,
1133
+ errors: [
1134
+ {
1135
+ action: "drop",
1136
+ message: "could not match syntax",
1137
+ node: null,
1138
+ syntax: syntaxes[i],
1139
+ },
1140
+ ],
1141
+ syntaxToken: syntaxes[i],
1142
+ valid: true,
1143
+ context,
1144
+ token: null,
1145
+ };
1146
+ }
1147
+ break;
1148
+ }
1149
+ if (token.typ === EnumToken.WildCardFunctionTokenType && token.val === "var") {
1150
+ result = matchSyntax(getParsedSyntax(ValidationSyntaxGroupEnum.Syntaxes, token.val + "()")?.[0]?.chi, createValidationContext(token.chi), options);
1151
+ if (result.success || isOptional) {
1152
+ context.next();
1153
+ continue;
1154
+ }
1155
+ return {
1156
+ ...result,
1157
+ success: false,
1158
+ token,
1159
+ syntaxToken: syntaxes[i],
1160
+ errors: [
1161
+ {
1162
+ action: "drop",
1163
+ message: "could not match syntax",
1164
+ node: context.peek(),
1165
+ location: context.peek().loc,
1166
+ },
1167
+ ],
1168
+ };
1169
+ }
1170
+ // custom function token
1171
+ if (token.typ === EnumToken.CustomFunctionTokenDefType) {
1172
+ if (syntaxes[i].typ != ValidationTokenEnum.PropertyType ||
1173
+ syntaxes[i + 1].typ != ValidationTokenEnum.OpenParenthesis ||
1174
+ syntaxes[i + 2].typ == null) {
1175
+ if (!isOptional) {
1176
+ return {
1177
+ success: false,
1178
+ errors: [
1179
+ {
1180
+ action: "drop",
1181
+ message: "could not match syntax",
1182
+ node: token,
1183
+ syntax: syntaxes[i],
1184
+ },
1185
+ ],
1186
+ syntaxToken: syntaxes[i],
1187
+ valid: true,
1188
+ context,
1189
+ token: null,
1190
+ };
1191
+ }
1192
+ break;
1193
+ }
1194
+ const range = trimArray(context.peekRange());
1195
+ context.next();
1196
+ i++;
1197
+ result = matchSyntax([syntaxes[i + 1]], createValidationContext(range.slice(1, -1)), options);
1198
+ if (result.success) {
1199
+ context.update(range.at(-1));
1200
+ i += 2;
1201
+ }
1202
+ return result;
1203
+ }
1204
+ if (tokensfuncDefMap.has(token.typ) &&
1205
+ token.typ === EnumToken.WildCardFunctionTokenDefType) {
1206
+ const range = trimArray(context.peekRange());
1207
+ result = matchSyntax(getParsedSyntax(ValidationSyntaxGroupEnum.Syntaxes, token.val + "()")?.[0]?.chi, createValidationContext(range.slice(1, -1)), options);
1208
+ if (result.success) {
1209
+ context.update(range.at(-1));
1210
+ if (context.done()) {
1211
+ return {
1212
+ ...result,
1213
+ context,
1214
+ syntaxToken: syntaxes[i + 1],
1215
+ };
1216
+ }
1217
+ continue;
1218
+ }
1219
+ if (isOptional) {
1220
+ continue;
1221
+ }
1222
+ return result;
1223
+ }
1224
+ if (syntaxes[i].isRepeatableAtLeastOnce || syntaxes[i].isRepeatable) {
1225
+ result = matchRepeatableSyntax(syntaxes[i], context.slice(), options);
1226
+ if (result.success) {
1227
+ if (result.context.done()) {
1228
+ context.end();
1229
+ return { ...result, syntaxToken: syntaxes[i + 1] };
1230
+ }
1231
+ context.update(result.context.current());
1232
+ continue;
1233
+ }
1234
+ if (isOptional) {
1235
+ continue;
1236
+ }
1237
+ return result;
1238
+ }
1239
+ if (syntaxes[i].isList) {
1240
+ result = matchListSyntax(syntaxes[i], context.slice(), options);
1241
+ if (result.success) {
1242
+ options.visited.get(token).delete(syntaxes[i]);
1243
+ if (result.context.done()) {
1244
+ context.end();
1245
+ return {
1246
+ ...result,
1247
+ success: true,
1248
+ valid: true,
1249
+ context,
1250
+ token: null,
1251
+ syntaxToken: syntaxes[i + 1],
1252
+ };
1253
+ }
1254
+ context.update(result.context.current());
1255
+ let k = i + 1;
1256
+ for (; k < syntaxes.length; k++) {
1257
+ if (syntaxes[k].typ !== ValidationTokenEnum.Whitespace) {
1258
+ break;
1259
+ }
1260
+ if (syntaxes[k]?.typ === ValidationTokenEnum.Comma) {
1261
+ i = k;
1262
+ }
1263
+ }
1264
+ continue;
1265
+ }
1266
+ if (isOptional) {
1267
+ // eat the next ','
1268
+ if (syntaxes[i + 1]?.typ === ValidationTokenEnum.Whitespace ||
1269
+ syntaxes[i + 1]?.typ === ValidationTokenEnum.Comma) {
1270
+ i++;
1271
+ }
1272
+ continue;
1273
+ }
1274
+ return {
1275
+ success: false,
1276
+ valid: true,
1277
+ token,
1278
+ context,
1279
+ syntaxToken: syntaxes[i],
1280
+ errors: result.errors,
1281
+ };
1282
+ }
1283
+ if (syntaxes[i].match != null) {
1284
+ result = matchOccurenceSyntax(syntaxes[i], context.slice(), options);
1285
+ if (result.success) {
1286
+ options.visited.get(token).delete(syntaxes[i]);
1287
+ if (result.context.done()) {
1288
+ context.end();
1289
+ return {
1290
+ ...result,
1291
+ context,
1292
+ syntaxToken: syntaxes[++i],
1293
+ };
1294
+ }
1295
+ context.update(result.context.current());
1296
+ continue;
1297
+ }
1298
+ if (isOptional) {
1299
+ // eat the next ','
1300
+ if (syntaxes[i + 1]?.typ === ValidationTokenEnum.Whitespace) {
1301
+ i++;
1302
+ }
1303
+ if (syntaxes[i + 1]?.typ === ValidationTokenEnum.Comma) {
1304
+ i++;
1305
+ }
1306
+ continue;
1307
+ }
1308
+ return {
1309
+ success: false,
1310
+ valid: true,
1311
+ token,
1312
+ context,
1313
+ syntaxToken: syntaxes[i],
1314
+ errors: result.errors,
1315
+ };
1316
+ }
1317
+ if (!options.visited.has(token)) {
1318
+ options.visited.set(token, new Set());
1319
+ }
1320
+ if (options.visited.get(token).has(syntaxes[i])) {
1321
+ // cyclic definition
1322
+ return {
1323
+ success: false,
1324
+ valid: true,
1325
+ token,
1326
+ context,
1327
+ syntaxToken: syntaxes[i],
1328
+ errors: [],
1329
+ };
1330
+ }
1331
+ options.visited.get(token).add(syntaxes[i]);
1332
+ success = false;
1333
+ switch (syntaxes[i].typ) {
1334
+ case ValidationTokenEnum.Colon:
1335
+ if (token.typ == EnumToken.ColonTokenType) {
1336
+ success = true;
1337
+ options.visited.get(token).delete(syntaxes[i]);
1338
+ context.next();
1339
+ break;
1340
+ }
1341
+ if (isOptional) {
1342
+ break;
1343
+ }
1344
+ return {
1345
+ success: false,
1346
+ valid: true,
1347
+ token,
1348
+ context,
1349
+ syntaxToken: syntaxes[i],
1350
+ errors: [],
1351
+ };
1352
+ case ValidationTokenEnum.Keyword:
1353
+ if (token.typ == EnumToken.IdenTokenType &&
1354
+ token.val.toLowerCase() ===
1355
+ syntaxes[i].val.toLowerCase()) {
1356
+ success = true;
1357
+ options.visited.get(token).delete(syntaxes[i]);
1358
+ context.next();
1359
+ break;
1360
+ }
1361
+ if (isOptional) {
1362
+ break;
1363
+ }
1364
+ return {
1365
+ success: false,
1366
+ valid: true,
1367
+ token,
1368
+ context,
1369
+ syntaxToken: syntaxes[i],
1370
+ errors: [],
1371
+ };
1372
+ case ValidationTokenEnum.DeclarationType:
1373
+ result = matchSyntax(getParsedSyntax(ValidationSyntaxGroupEnum.Declarations, syntaxes[i].val), context, options);
1374
+ if (result.success) {
1375
+ success = true;
1376
+ options.visited.get(token).delete(syntaxes[i]);
1377
+ if (result.context.done()) {
1378
+ context.end();
1379
+ return {
1380
+ ...result,
1381
+ token,
1382
+ context,
1383
+ syntaxToken: syntaxes[1 + i],
1384
+ };
1385
+ }
1386
+ else {
1387
+ if (result.context.current() != null) {
1388
+ context.update(result.context.current());
1389
+ }
1390
+ }
1391
+ }
1392
+ if (success || isOptional) {
1393
+ break;
1394
+ }
1395
+ return {
1396
+ success: false,
1397
+ valid: true,
1398
+ token,
1399
+ context,
1400
+ syntaxToken: syntaxes[i],
1401
+ errors: result.errors,
1402
+ };
1403
+ case ValidationTokenEnum.OptionalGroupToken: {
1404
+ //
1405
+ const tokens = context.split();
1406
+ let j = 0;
1407
+ for (; j < tokens.length; j++) {
1408
+ result = matchSyntax(syntaxes[i].chi, context.slice(), options);
1409
+ if (result.success) {
1410
+ context.update(tokens[j].at(-1));
1411
+ }
1412
+ break;
1413
+ }
1414
+ if (result?.context?.done?.()) {
1415
+ return result;
1416
+ }
1417
+ break;
1418
+ }
1419
+ case ValidationTokenEnum.AtRule:
1420
+ if (token.typ == EnumToken.AtRuleTokenType) {
1421
+ success = true;
1422
+ options.visited.get(token).delete(syntaxes[i]);
1423
+ context.next();
1424
+ break;
1425
+ }
1426
+ if (isOptional) {
1427
+ break;
1428
+ }
1429
+ return {
1430
+ success: false,
1431
+ valid: true,
1432
+ token,
1433
+ context,
1434
+ syntaxToken: syntaxes[i],
1435
+ errors: [],
1436
+ };
1437
+ case ValidationTokenEnum.StringToken:
1438
+ if (token.typ == EnumToken.StringTokenType || token.typ == EnumToken.UrlFunctionTokenType) {
1439
+ success = true;
1440
+ }
1441
+ else if (token.typ === EnumToken.StringTokenType) {
1442
+ success = token.val === syntaxes[i].val.slice(1, -1);
1443
+ }
1444
+ else if (token.typ === EnumToken.Add) {
1445
+ success = syntaxes[i].val.slice(1, -1) === "+";
1446
+ }
1447
+ else if (token.typ === EnumToken.Mul) {
1448
+ success = syntaxes[i].val.slice(1, -1) === "*";
1449
+ }
1450
+ else if (token.typ === EnumToken.Div) {
1451
+ success = syntaxes[i].val.slice(1, -1) === "/";
1452
+ }
1453
+ else if (token.typ === EnumToken.Sub) {
1454
+ success = syntaxes[i].val.slice(1, -1) === "-";
1455
+ }
1456
+ else if (token.typ === EnumToken.LiteralTokenType) {
1457
+ success = token.val === syntaxes[i].val.slice(1, -1);
1458
+ }
1459
+ else if (token.typ == EnumToken.Plus) {
1460
+ success = true;
1461
+ }
1462
+ if (success) {
1463
+ context.next();
1464
+ break;
1465
+ }
1466
+ if (isOptional) {
1467
+ break;
1468
+ }
1469
+ return {
1470
+ success: false,
1471
+ valid: true,
1472
+ token,
1473
+ context,
1474
+ syntaxToken: syntaxes[i],
1475
+ errors: [],
1476
+ };
1477
+ case ValidationTokenEnum.SemiColon:
1478
+ if (token.typ == EnumToken.SemiColonTokenType) {
1479
+ success = true;
1480
+ options.visited.get(token).delete(syntaxes[i]);
1481
+ context.next();
1482
+ break;
1483
+ }
1484
+ if (isOptional) {
1485
+ break;
1486
+ }
1487
+ return {
1488
+ success: false,
1489
+ valid: true,
1490
+ token,
1491
+ context,
1492
+ syntaxToken: syntaxes[i],
1493
+ errors: [],
1494
+ };
1495
+ case ValidationTokenEnum.PropertyType:
1496
+ result = matchProperty(syntaxes[i], context, options);
1497
+ if (!result.success) {
1498
+ if (isOptional) {
1499
+ break;
1500
+ }
1501
+ return {
1502
+ success: false,
1503
+ valid: true,
1504
+ token: context.current() ?? token,
1505
+ context,
1506
+ syntaxToken: syntaxes[i],
1507
+ errors: [],
1508
+ };
1509
+ }
1510
+ success = true;
1511
+ options.visited.get(token).delete(syntaxes[i]);
1512
+ if (result.context.done()) {
1513
+ context.end();
1514
+ return {
1515
+ success,
1516
+ valid: true,
1517
+ token: null,
1518
+ context,
1519
+ syntaxToken: syntaxes[i + 1],
1520
+ errors: [],
1521
+ };
1522
+ }
1523
+ else {
1524
+ context.update(result.context.current());
1525
+ }
1526
+ break;
1527
+ case ValidationTokenEnum.PipeToken:
1528
+ {
1529
+ result = null;
1530
+ const results = [];
1531
+ let tmp = null;
1532
+ for (const syntax of syntaxes[i].chi) {
1533
+ tmp = matchSyntax(syntax, context.slice(), options);
1534
+ if (tmp.success) {
1535
+ results.push(tmp);
1536
+ if (tmp.context.done()) {
1537
+ context.end();
1538
+ return { ...tmp, context, syntaxToken: syntaxes[i + 1] };
1539
+ }
1540
+ }
1541
+ }
1542
+ if (results.length > 0) {
1543
+ result = results.reduce((a, b) => (a.context.index > b.context.index ? a : b));
1544
+ }
1545
+ if (result?.success) {
1546
+ success = true;
1547
+ options.visited.get(token).delete(syntaxes[i]);
1548
+ if (result.context.done()) {
1549
+ context.end();
1550
+ }
1551
+ else {
1552
+ context.update(result.context.current());
1553
+ }
1554
+ break;
1555
+ }
1556
+ }
1557
+ if (isOptional) {
1558
+ break;
1559
+ }
1560
+ return {
1561
+ success: false,
1562
+ valid: true,
1563
+ token,
1564
+ context,
1565
+ syntaxToken: syntaxes[i],
1566
+ errors: [
1567
+ {
1568
+ action: "drop",
1569
+ message: "could not match syntax",
1570
+ node: token,
1571
+ location: token.loc,
1572
+ syntax: syntaxes[i],
1573
+ },
1574
+ ],
1575
+ };
1576
+ case ValidationTokenEnum.Bracket:
1577
+ result = matchSyntax(syntaxes[i].chi, context.slice(), options);
1578
+ if (result.success) {
1579
+ success = true;
1580
+ options.visited.get(token).delete(syntaxes[i]);
1581
+ if (result.context.done()) {
1582
+ context.end();
1583
+ return {
1584
+ success,
1585
+ valid: true,
1586
+ token: null,
1587
+ context,
1588
+ syntaxToken: syntaxes[1 + i],
1589
+ errors: [],
1590
+ };
1591
+ }
1592
+ else {
1593
+ context.update(result.context.current());
1594
+ }
1595
+ break;
1596
+ }
1597
+ if (isOptional) {
1598
+ break;
1599
+ }
1600
+ return {
1601
+ success: false,
1602
+ valid: true,
1603
+ token,
1604
+ context,
1605
+ syntaxToken: syntaxes[i],
1606
+ errors: [],
1607
+ };
1608
+ case ValidationTokenEnum.ColumnToken:
1609
+ result = matchColumnSyntax(syntaxes[i], context.slice(), options);
1610
+ if (result.success) {
1611
+ success = true;
1612
+ options.visited.get(token).delete(syntaxes[i]);
1613
+ if (result.context.done()) {
1614
+ context.end();
1615
+ return {
1616
+ success,
1617
+ valid: true,
1618
+ token: null,
1619
+ context,
1620
+ syntaxToken: syntaxes[1 + i],
1621
+ errors: [],
1622
+ };
1623
+ }
1624
+ else {
1625
+ context.update(result.context.current());
1626
+ }
1627
+ break;
1628
+ }
1629
+ if (isOptional) {
1630
+ break;
1631
+ }
1632
+ return {
1633
+ success: false,
1634
+ valid: true,
1635
+ token,
1636
+ context,
1637
+ syntaxToken: syntaxes[i],
1638
+ errors: [],
1639
+ };
1640
+ case ValidationTokenEnum.AmpersandToken:
1641
+ result = matchAmpersandSyntax(syntaxes[i], context.slice(), options);
1642
+ if (result.success) {
1643
+ success = true;
1644
+ options.visited.get(token).delete(syntaxes[i]);
1645
+ if (result.context.done()) {
1646
+ context.end();
1647
+ return {
1648
+ success,
1649
+ valid: true,
1650
+ token: null,
1651
+ context,
1652
+ syntaxToken: syntaxes[1 + i],
1653
+ errors: [],
1654
+ };
1655
+ }
1656
+ else {
1657
+ context.update(result.context.current());
1658
+ }
1659
+ break;
1660
+ }
1661
+ if (isOptional) {
1662
+ break;
1663
+ }
1664
+ return {
1665
+ success: false,
1666
+ valid: true,
1667
+ token,
1668
+ context,
1669
+ syntaxToken: syntaxes[i],
1670
+ errors: [],
1671
+ };
1672
+ case ValidationTokenEnum.PseudoClassFunctionToken:
1673
+ if (!(token.val + "()" in config.selectors)) {
1674
+ return {
1675
+ success: false,
1676
+ valid: true,
1677
+ token,
1678
+ context,
1679
+ syntaxToken: syntaxes[i],
1680
+ errors: [
1681
+ {
1682
+ action: "drop",
1683
+ message: `Unknown pseudo-class selector ${token.val}()`,
1684
+ node: token,
1685
+ },
1686
+ ],
1687
+ };
1688
+ }
1689
+ result = matchSyntax(getParsedSyntax(ValidationSyntaxGroupEnum.Selectors, token.val + "()")?.[0]?.chi ?? [], createValidationContext(token.chi), options);
1690
+ if (result.success) {
1691
+ success = true;
1692
+ options.visited.get(token).delete(syntaxes[i]);
1693
+ context.next();
1694
+ break;
1695
+ }
1696
+ return {
1697
+ success: false,
1698
+ valid: true,
1699
+ token,
1700
+ context,
1701
+ syntaxToken: syntaxes[i],
1702
+ errors: result.errors,
1703
+ };
1704
+ case ValidationTokenEnum.Function:
1705
+ if ((!tokensfuncDefMap.has(token.typ) &&
1706
+ !funcLike.includes(token.typ) &&
1707
+ !funcTypes.includes(token.typ)) ||
1708
+ !("val" in token) ||
1709
+ !equalsIgnoreCase(syntaxes[i].val, token.val.toLowerCase())) {
1710
+ return {
1711
+ success: false,
1712
+ valid: true,
1713
+ token,
1714
+ context,
1715
+ syntaxToken: syntaxes[i],
1716
+ errors: [
1717
+ {
1718
+ action: "drop",
1719
+ message: `Expecting a function ${EnumToken[token.typ]}`,
1720
+ node: token,
1721
+ },
1722
+ ],
1723
+ };
1724
+ }
1725
+ if (tokensfuncDefMap.has(token.typ)) {
1726
+ const range = context.peekRange();
1727
+ if (range.at(-1)?.typ !== EnumToken.EndParensTokenType) {
1728
+ const tk = range.at(-1);
1729
+ return {
1730
+ success: false,
1731
+ valid: true,
1732
+ token,
1733
+ context,
1734
+ syntaxToken: syntaxes[i],
1735
+ errors: [
1736
+ {
1737
+ action: "drop",
1738
+ message: `Expecting ')' at ${tk.loc?.src}:${tk.loc?.sta?.lin}:${tk.loc?.sta?.col}`,
1739
+ node: token,
1740
+ },
1741
+ ],
1742
+ };
1743
+ }
1744
+ result = matchSyntax(syntaxes[i].chi, createValidationContext(range.slice(1, -1)), options);
1745
+ if (result.success) {
1746
+ context.update(range.at(-1));
1747
+ options.visited.get(token).delete(syntaxes[i]);
1748
+ }
1749
+ break;
1750
+ }
1751
+ else {
1752
+ result = matchSyntax(syntaxes[i].chi, createValidationContext(token.chi), options);
1753
+ }
1754
+ if (result.success) {
1755
+ success = true;
1756
+ options.visited.get(token).delete(syntaxes[i]);
1757
+ context.next();
1758
+ break;
1759
+ }
1760
+ return {
1761
+ success: false,
1762
+ valid: true,
1763
+ token,
1764
+ context,
1765
+ syntaxToken: syntaxes[i],
1766
+ errors: result.errors,
1767
+ };
1768
+ case ValidationTokenEnum.Comma:
1769
+ if (token.typ !== EnumToken.CommaTokenType && isOptional) {
1770
+ let k = i;
1771
+ while (syntaxes[--k]?.typ === ValidationTokenEnum.Whitespace) { }
1772
+ // ignore the comma if the previous token is a list
1773
+ if (syntaxes[k]?.isList) {
1774
+ continue;
1775
+ }
1776
+ }
1777
+ if (token.typ === EnumToken.CommaTokenType) {
1778
+ options.visited.get(token).delete(syntaxes[i]);
1779
+ context.next();
1780
+ break;
1781
+ }
1782
+ return {
1783
+ success: false,
1784
+ valid: true,
1785
+ token,
1786
+ context,
1787
+ syntaxToken: syntaxes[i],
1788
+ errors: [],
1789
+ };
1790
+ case ValidationTokenEnum.LessThan:
1791
+ if (token.typ === EnumToken.LtTokenType) {
1792
+ options.visited.get(token).delete(syntaxes[i]);
1793
+ context.next();
1794
+ break;
1795
+ }
1796
+ return {
1797
+ success: false,
1798
+ valid: true,
1799
+ token,
1800
+ context,
1801
+ syntaxToken: syntaxes[i],
1802
+ errors: [],
1803
+ };
1804
+ case ValidationTokenEnum.Separator:
1805
+ if (token.typ === EnumToken.LiteralTokenType && token.val === "/") {
1806
+ options.visited.get(token).delete(syntaxes[i]);
1807
+ context.next();
1808
+ break;
1809
+ }
1810
+ return {
1811
+ success: false,
1812
+ valid: true,
1813
+ token,
1814
+ context,
1815
+ syntaxToken: syntaxes[i],
1816
+ errors: [],
1817
+ };
1818
+ case ValidationTokenEnum.FunctionDefinition:
1819
+ if (tokensfuncDefMap.has(token.typ) &&
1820
+ equalsIgnoreCase(token.val, syntaxes[i].val)) {
1821
+ const children = trimArray(context.peekRange());
1822
+ result = matchSyntax((getParsedSyntax(ValidationSyntaxGroupEnum.Syntaxes, syntaxes[i].val + "()")?.[0]).chi ?? [], createValidationContext(children.slice(1, -1)), options);
1823
+ if (result.success) {
1824
+ success = true;
1825
+ options.visited.get(token).delete(syntaxes[i]);
1826
+ context.update(children.at(-1));
1827
+ break;
1828
+ }
1829
+ }
1830
+ else if (tokensfuncSet.has(token.typ) &&
1831
+ equalsIgnoreCase(token.val, syntaxes[i].val)) {
1832
+ result = matchSyntax(getParsedSyntax(ValidationSyntaxGroupEnum.Syntaxes, syntaxes[i].val + "()") ?? [], createValidationContext([token]), options);
1833
+ if (result.success) {
1834
+ success = true;
1835
+ options.visited.get(token).delete(syntaxes[i]);
1836
+ context.next();
1837
+ break;
1838
+ }
1839
+ }
1840
+ return {
1841
+ success: false,
1842
+ valid: true,
1843
+ token,
1844
+ context,
1845
+ syntaxToken: syntaxes[i],
1846
+ errors: [],
1847
+ };
1848
+ case ValidationTokenEnum.OpenParenthesis:
1849
+ if (token.typ === EnumToken.StartParensTokenType) {
1850
+ options.visited.get(token).delete(syntaxes[i]);
1851
+ context.next();
1852
+ break;
1853
+ }
1854
+ if (isOptional) {
1855
+ break;
1856
+ }
1857
+ return {
1858
+ success: false,
1859
+ valid: true,
1860
+ token,
1861
+ context,
1862
+ syntaxToken: syntaxes[i],
1863
+ errors: [],
1864
+ };
1865
+ case ValidationTokenEnum.CloseParenthesis:
1866
+ if (token.typ === EnumToken.EndParensTokenType) {
1867
+ options.visited.get(token).delete(syntaxes[i]);
1868
+ context.next();
1869
+ break;
1870
+ }
1871
+ if (isOptional) {
1872
+ break;
1873
+ }
1874
+ return {
1875
+ success: false,
1876
+ valid: true,
1877
+ token,
1878
+ context,
1879
+ syntaxToken: syntaxes[i],
1880
+ errors: [],
1881
+ };
1882
+ case ValidationTokenEnum.DeclarationNameToken:
1883
+ result = matchSyntax(getParsedSyntax(ValidationSyntaxGroupEnum.Declarations, syntaxes[i].val) ?? [], context.slice(), options);
1884
+ if (!result.success) {
1885
+ return {
1886
+ success: false,
1887
+ valid: true,
1888
+ token,
1889
+ context,
1890
+ syntaxToken: syntaxes[i],
1891
+ errors: result.errors,
1892
+ };
1893
+ }
1894
+ success = true;
1895
+ options.visited.get(token).delete(syntaxes[i]);
1896
+ if (result.context.done()) {
1897
+ context.end();
1898
+ return {
1899
+ success,
1900
+ valid: true,
1901
+ token: null,
1902
+ context,
1903
+ syntaxToken: syntaxes[1 + i],
1904
+ errors: [],
1905
+ };
1906
+ }
1907
+ else {
1908
+ context.update(result.context.current());
1909
+ }
1910
+ break;
1911
+ case ValidationTokenEnum.DisallowWhitespace:
1912
+ if (context.peek(0, false)?.typ === EnumToken.WhitespaceTokenType) {
1913
+ return {
1914
+ success: false,
1915
+ valid: true,
1916
+ token,
1917
+ context,
1918
+ syntaxToken: syntaxes[i],
1919
+ errors: [],
1920
+ };
1921
+ }
1922
+ break;
1923
+ default:
1924
+ throw new Error(`Unexpected syntax ${ValidationTokenEnum[syntaxes[i].typ]}`);
1925
+ }
1926
+ if (success &&
1927
+ "range" in syntaxes[i] &&
1928
+ !(token?.typ === EnumToken.MathFunctionTokenType ||
1929
+ token?.typ === EnumToken.MathFunctionTokenDefType ||
1930
+ token?.typ === EnumToken.WildCardFunctionTokenDefType)) {
1931
+ let success = false;
1932
+ success =
1933
+ typeof token.val === "number" &&
1934
+ token.val >=
1935
+ syntaxes[i].range.min.val;
1936
+ if (syntaxes[i].range.min.typ === ValidationTokenEnum.Dimension) {
1937
+ success =
1938
+ token.typ ===
1939
+ EnumToken[
1940
+ // @ts-expect-error
1941
+ syntaxes[i].range.min
1942
+ .unit];
1943
+ }
1944
+ if (success &&
1945
+ syntaxes[i].range.max != null) {
1946
+ success =
1947
+ token.val <=
1948
+ syntaxes[i].range.max.val;
1949
+ }
1950
+ if (!success) {
1951
+ return {
1952
+ success: false,
1953
+ valid: true,
1954
+ token,
1955
+ context,
1956
+ syntaxToken: syntaxes[i],
1957
+ errors: [],
1958
+ };
1959
+ }
1960
+ }
1961
+ }
1962
+ return result?.success
1963
+ ? result
1964
+ : {
1965
+ success: true,
1966
+ context,
1967
+ syntaxToken: syntaxes[i] ?? null,
1968
+ token,
1969
+ valid: true,
1970
+ errors: [],
1971
+ };
1972
+ }
1973
+ function matchColumnSyntax(syntax, context, options) {
1974
+ let syntaxes = syntax.chi.slice();
1975
+ let i = 0;
1976
+ let success = false;
1977
+ let result;
1978
+ syntaxes = syntaxes.slice();
1979
+ for (; i < syntaxes.length; i++) {
1980
+ result = matchSyntax(syntaxes[i], context.slice(), options);
1981
+ if (result.success) {
1982
+ const curr = result.context.current();
1983
+ if (curr == null && !result.context.done()) {
1984
+ continue;
1985
+ }
1986
+ if (result.context.done()) {
1987
+ context.end();
1988
+ return {
1989
+ ...result,
1990
+ context,
1991
+ syntaxToken: syntaxes[i + 1]?.[0],
1992
+ };
1993
+ }
1994
+ context.update(curr);
1995
+ success = true;
1996
+ syntaxes.splice(i, 1);
1997
+ i = -1;
1998
+ }
1999
+ }
2000
+ return {
2001
+ success,
2002
+ valid: true,
2003
+ token: context.current(),
2004
+ context,
2005
+ syntaxToken: syntax,
2006
+ errors: [],
2007
+ };
2008
+ }
2009
+ function matchAmpersandSyntax(syntax, context, options) {
2010
+ const syntaxes = [syntax.l, syntax.r];
2011
+ let result;
2012
+ let i;
2013
+ let success = false;
2014
+ for (i = 0; i < syntaxes.length; i++) {
2015
+ result = matchSyntax(syntaxes[i], context.slice(), options);
2016
+ if (result.success) {
2017
+ success = true;
2018
+ if (result.context.done()) {
2019
+ context.end();
2020
+ break;
2021
+ }
2022
+ context.update(result.context.current());
2023
+ syntaxes.splice(i, 1);
2024
+ i = -1;
2025
+ }
2026
+ }
2027
+ return (
2028
+ /* syntaxes.length === 0 ? */ result ?? {
2029
+ success,
2030
+ valid: true,
2031
+ token: context.peek(),
2032
+ context,
2033
+ syntaxToken: syntax,
2034
+ errors: [],
2035
+ });
2036
+ }
2037
+ function matchProperty(property, context, options) {
2038
+ let success = false;
2039
+ let checkCalc = context.peek()?.typ == EnumToken.MathFunctionTokenDefType &&
2040
+ [
2041
+ "number",
2042
+ "zero",
2043
+ "integer",
2044
+ "percentage",
2045
+ "dimension",
2046
+ "length-percentage",
2047
+ "length",
2048
+ "time",
2049
+ "calc-sum",
2050
+ "calc-product",
2051
+ ].includes(property.val);
2052
+ if (checkCalc && !["number", "zero", "integer", "percentage", "length-percentage"].includes(property.val)) {
2053
+ checkCalc = context.peek().val === "calc";
2054
+ }
2055
+ if (checkCalc) {
2056
+ const range = context.peekRange();
2057
+ const result = matchSyntax(getParsedSyntax(ValidationSyntaxGroupEnum.Syntaxes, context.peek().val + "()")?.[0]?.chi, createValidationContext(range.slice(1, -1)), options);
2058
+ if (result.success) {
2059
+ context.update(range.at(-1));
2060
+ return {
2061
+ success: true,
2062
+ valid: true,
2063
+ token: range.at(-1),
2064
+ context,
2065
+ syntaxToken: null,
2066
+ errors: [],
2067
+ };
2068
+ }
2069
+ return {
2070
+ success: false,
2071
+ valid: true,
2072
+ token: context.peek(),
2073
+ context,
2074
+ syntaxToken: property,
2075
+ errors: [],
2076
+ };
2077
+ }
2078
+ switch (property.val) {
2079
+ case "combinator":
2080
+ {
2081
+ const token = context.peek();
2082
+ success =
2083
+ token != null &&
2084
+ (token.typ == EnumToken.NextSiblingCombinatorTokenType ||
2085
+ token.typ == EnumToken.ChildCombinatorTokenType ||
2086
+ token.typ == EnumToken.SubsequentSiblingCombinatorTokenType ||
2087
+ token.typ == EnumToken.ColumnCombinatorTokenType);
2088
+ }
2089
+ break;
2090
+ case "declaration-value":
2091
+ {
2092
+ // consume a declaration value
2093
+ // consume a token,
2094
+ // if the next token is a comma consume it and expect a token
2095
+ // check the parenthises are balanced
2096
+ // if semicolon or end curly brace is encountered, stop
2097
+ let expectToken = true;
2098
+ let token;
2099
+ const stack = [];
2100
+ token = context.peek();
2101
+ if (token?.typ == EnumToken.WhitespaceTokenType) {
2102
+ context.next();
2103
+ token = context.peek();
2104
+ }
2105
+ if (token?.typ == EnumToken.CommentTokenType) {
2106
+ context.next();
2107
+ token = context.peek();
2108
+ }
2109
+ if (token?.typ == EnumToken.CommaTokenType) {
2110
+ context.next();
2111
+ expectToken = true;
2112
+ }
2113
+ while ((token = context.peek()) != null) {
2114
+ if (token.typ == EnumToken.WhitespaceTokenType || token.typ == EnumToken.CommentTokenType) {
2115
+ context.next();
2116
+ }
2117
+ if (expectToken) {
2118
+ if (token?.typ == EnumToken.CommaTokenType || token.typ == EnumToken.EndParensTokenType) {
2119
+ return {
2120
+ success: false,
2121
+ valid: true,
2122
+ token,
2123
+ context,
2124
+ syntaxToken: property,
2125
+ errors: [
2126
+ {
2127
+ action: "drop",
2128
+ message: `Unexpected token ${EnumToken[token?.typ]} at ${token.loc?.src}:${token.loc?.sta?.lin}:${token.loc?.sta?.col}`,
2129
+ node: token,
2130
+ location: token.loc,
2131
+ },
2132
+ ],
2133
+ };
2134
+ }
2135
+ expectToken = false;
2136
+ }
2137
+ if (token.typ == EnumToken.CommaTokenType) {
2138
+ expectToken = true;
2139
+ }
2140
+ if (token.typ == EnumToken.EndParensTokenType) {
2141
+ if (stack.length > 0) {
2142
+ stack.pop();
2143
+ }
2144
+ else {
2145
+ return {
2146
+ success: false,
2147
+ valid: true,
2148
+ token,
2149
+ context,
2150
+ syntaxToken: property,
2151
+ errors: [
2152
+ {
2153
+ action: "drop",
2154
+ message: `Unexpected token ${EnumToken[token?.typ]} at ${token.loc?.src}:${token.loc?.sta?.lin}:${token.loc?.sta?.col}`,
2155
+ node: token,
2156
+ location: token.loc,
2157
+ },
2158
+ ],
2159
+ };
2160
+ }
2161
+ }
2162
+ context.next();
2163
+ }
2164
+ if (stack.length > 0) {
2165
+ token = stack.at(-1);
2166
+ return {
2167
+ success: false,
2168
+ valid: true,
2169
+ token,
2170
+ context,
2171
+ syntaxToken: property,
2172
+ errors: [
2173
+ {
2174
+ action: "drop",
2175
+ message: `unbalanced parentheses ${EnumToken[token?.typ]} at ${token.loc?.src}:${token.loc?.sta?.lin}:${token.loc?.sta?.col}`,
2176
+ node: token,
2177
+ location: token.loc,
2178
+ },
2179
+ ],
2180
+ };
2181
+ }
2182
+ success = !expectToken;
2183
+ if (!success) {
2184
+ return {
2185
+ success: false,
2186
+ valid: true,
2187
+ token: token ?? context.current(),
2188
+ context,
2189
+ syntaxToken: property,
2190
+ errors: [],
2191
+ };
2192
+ }
2193
+ }
2194
+ break;
2195
+ case "calc-sum": {
2196
+ const token = context.peek();
2197
+ if (token?.typ === EnumToken.ParensTokenType) {
2198
+ const result = matchSyntax(getParsedSyntax(ValidationSyntaxGroupEnum.Syntaxes, "calc()")[0].chi, createValidationContext(token.chi), options);
2199
+ success = result.success;
2200
+ break;
2201
+ }
2202
+ if (token?.typ === EnumToken.BinaryExpressionTokenType) {
2203
+ let result = matchSyntax(getParsedSyntax(ValidationSyntaxGroupEnum.Syntaxes, "calc-sum"), createValidationContext([token.l]), options);
2204
+ if (result.success) {
2205
+ result = matchSyntax(getParsedSyntax(ValidationSyntaxGroupEnum.Syntaxes, "calc-sum"), createValidationContext([token.r]), options);
2206
+ }
2207
+ success = result.success;
2208
+ break;
2209
+ }
2210
+ const result = matchSyntax(getParsedSyntax(ValidationSyntaxGroupEnum.Syntaxes, "calc-sum"), context.slice(), options);
2211
+ success = result.success;
2212
+ if (success) {
2213
+ if (result.context.done()) {
2214
+ context.end();
2215
+ }
2216
+ else {
2217
+ context.update(result.context.current());
2218
+ }
2219
+ return {
2220
+ success: true,
2221
+ valid: true,
2222
+ token: null,
2223
+ context,
2224
+ syntaxToken: null,
2225
+ errors: [],
2226
+ };
2227
+ }
2228
+ break;
2229
+ }
2230
+ case "at-keyword-token":
2231
+ success = context.peek()?.typ === EnumToken.AtRuleTokenType;
2232
+ break;
2233
+ case "an+b":
2234
+ {
2235
+ let token = context.peek();
2236
+ if (token == null) {
2237
+ return {
2238
+ success: false,
2239
+ valid: true,
2240
+ token: null,
2241
+ context,
2242
+ syntaxToken: property,
2243
+ errors: [],
2244
+ };
2245
+ }
2246
+ if (token.typ === EnumToken.IdenTokenType &&
2247
+ ("even" === token.val || "odd" === token.val)) {
2248
+ success = true;
2249
+ break;
2250
+ }
2251
+ if (token.typ === EnumToken.NumberTokenType &&
2252
+ Number.isInteger(token.val) &&
2253
+ !token.toString().includes(".")) {
2254
+ success = true;
2255
+ break;
2256
+ }
2257
+ if (token.typ === EnumToken.LiteralTokenType || token.typ === EnumToken.IdenTokenType) {
2258
+ let match = /^(([+-]?[0-9]*)?n)?([+-]?[0-9]+)?$/.exec(token.val);
2259
+ success = match != null;
2260
+ if (!success) {
2261
+ success = /^(([+-]?[0-9]*)?n)?([+-])?$/.test(token.val);
2262
+ if (success) {
2263
+ token = context.peek(1);
2264
+ success =
2265
+ token?.typ === EnumToken.NumberTokenType &&
2266
+ Number.isInteger(token.val) &&
2267
+ !token.toString().includes(".") &&
2268
+ token.sign == null;
2269
+ context.next();
2270
+ }
2271
+ }
2272
+ else if (match?.[3] == null) {
2273
+ token = context.peek(1);
2274
+ if (token?.typ === EnumToken.Add ||
2275
+ token?.typ === EnumToken.NextSiblingCombinatorTokenType ||
2276
+ token?.typ === EnumToken.Sub) {
2277
+ token = context.peek(2);
2278
+ success =
2279
+ token?.typ === EnumToken.NumberTokenType &&
2280
+ Number.isInteger(token.val) &&
2281
+ !token.toString().includes(".") &&
2282
+ token.sign == null;
2283
+ }
2284
+ else if (token?.typ === EnumToken.NumberTokenType) {
2285
+ success =
2286
+ Number.isInteger(token.val) &&
2287
+ !token.toString().includes(".") &&
2288
+ token.sign != null;
2289
+ }
2290
+ if (success) {
2291
+ context.update(token);
2292
+ return {
2293
+ success: true,
2294
+ valid: true,
2295
+ token: null,
2296
+ context,
2297
+ syntaxToken: property,
2298
+ errors: [],
2299
+ };
2300
+ }
2301
+ }
2302
+ break;
2303
+ }
2304
+ if (token.typ === EnumToken.DimensionTokenType && token.unit === "n") {
2305
+ success =
2306
+ Number.isInteger(token.val) &&
2307
+ !token.toString().includes(".");
2308
+ if (!success) {
2309
+ return {
2310
+ success: false,
2311
+ valid: true,
2312
+ token: null,
2313
+ context,
2314
+ syntaxToken: property,
2315
+ errors: [
2316
+ {
2317
+ action: "drop",
2318
+ message: `expecting <dimension-token>`,
2319
+ node: token,
2320
+ location: token.loc,
2321
+ },
2322
+ ],
2323
+ };
2324
+ }
2325
+ if (token == null) {
2326
+ break;
2327
+ }
2328
+ token = context.peek(1);
2329
+ if (token == null) {
2330
+ break;
2331
+ }
2332
+ if (token.typ === EnumToken.NumberTokenType) {
2333
+ if (Number.isInteger(token.val) &&
2334
+ !token.toString().includes(".") &&
2335
+ ["+", "-"].includes(token.sign)) {
2336
+ success = true;
2337
+ context.next();
2338
+ }
2339
+ break;
2340
+ }
2341
+ if (token?.typ === EnumToken.NextSiblingCombinatorTokenType) {
2342
+ Object.assign(token, { typ: EnumToken.Add });
2343
+ }
2344
+ token = context.peek(2);
2345
+ if (token == null) {
2346
+ break;
2347
+ }
2348
+ if (token?.typ === EnumToken.NumberTokenType &&
2349
+ Number.isInteger(token.val) &&
2350
+ !token.toString().includes(".") &&
2351
+ token.sign == null) {
2352
+ success = true;
2353
+ context.next();
2354
+ context.next();
2355
+ }
2356
+ break;
2357
+ }
2358
+ }
2359
+ break;
2360
+ case "number-token":
2361
+ {
2362
+ const token = context.peek();
2363
+ success =
2364
+ token?.typ === EnumToken.NumberTokenType &&
2365
+ !token.val.toString().includes(".") &&
2366
+ Number.isInteger(token.val);
2367
+ }
2368
+ break;
2369
+ case "ndashdigit-ident":
2370
+ {
2371
+ const token = context.peek();
2372
+ success =
2373
+ (token?.typ === EnumToken.IdenTokenType || token?.typ === EnumToken.LiteralTokenType) &&
2374
+ /^-?n[-+]\d+$/.test(token.val);
2375
+ }
2376
+ break;
2377
+ case "dimension-token":
2378
+ {
2379
+ const token = context.peek();
2380
+ success =
2381
+ token?.typ === EnumToken.DimensionTokenType &&
2382
+ token.unit === "n" &&
2383
+ !token.val.toString().includes(".") &&
2384
+ Number.isInteger(token.val);
2385
+ }
2386
+ break;
2387
+ case "quote":
2388
+ case "display-box":
2389
+ case "display-inside":
2390
+ case "display-internal":
2391
+ case "display-outside":
2392
+ case "display-legacy":
2393
+ case "content-position":
2394
+ success =
2395
+ context.peek()?.typ == EnumToken.IdenTokenType &&
2396
+ // @ts-expect-error
2397
+ config.syntaxes[property.val].syntax
2398
+ .split(/[\s|]+/)
2399
+ .includes(context.peek().val.toLowerCase());
2400
+ break;
2401
+ case "mf-name":
2402
+ {
2403
+ const token = context.peek();
2404
+ success =
2405
+ token?.typ === EnumToken.IdenTokenType &&
2406
+ token.val.toLowerCase() in config.mediaFeatures;
2407
+ }
2408
+ break;
2409
+ case "mf-comparison":
2410
+ {
2411
+ const token = context.peek();
2412
+ success =
2413
+ token?.typ === EnumToken.LtTokenType ||
2414
+ token?.typ === EnumToken.LteTokenType ||
2415
+ token?.typ === EnumToken.GtTokenType ||
2416
+ token?.typ === EnumToken.GteTokenType ||
2417
+ token?.typ === EnumToken.DelimTokenType;
2418
+ }
2419
+ break;
2420
+ case "mf-gt":
2421
+ {
2422
+ const token = context.peek();
2423
+ success = token?.typ === EnumToken.GtTokenType || token?.typ === EnumToken.GteTokenType;
2424
+ }
2425
+ break;
2426
+ case "mf-lt":
2427
+ {
2428
+ const token = context.peek();
2429
+ success = token?.typ === EnumToken.LtTokenType || token?.typ === EnumToken.LteTokenType;
2430
+ }
2431
+ break;
2432
+ case "dashed-ident":
2433
+ case "extension-name":
2434
+ case "custom-property-name":
2435
+ success = context.peek()?.typ == EnumToken.DashedIdenTokenType;
2436
+ break;
2437
+ case "namespace-prefix":
2438
+ case "ident":
2439
+ case "ident-token":
2440
+ case "custom-ident":
2441
+ case "counter-name":
2442
+ case "counter-style-name":
2443
+ success =
2444
+ context.peek()?.typ == EnumToken.IdenTokenType || context.peek()?.typ == EnumToken.DashedIdenTokenType;
2445
+ if (success && context.peek()?.typ === EnumToken.IdenTokenType) {
2446
+ const val = context.peek().val.toLowerCase();
2447
+ success = "none" !== val && !allValues.includes(val);
2448
+ }
2449
+ break;
2450
+ case "any-value": {
2451
+ const token = context.peek();
2452
+ success =
2453
+ token == null ||
2454
+ [
2455
+ EnumToken.String,
2456
+ EnumToken.NumberTokenType,
2457
+ EnumToken.DashedIdenTokenType,
2458
+ EnumToken.IdenTokenType,
2459
+ EnumToken.DashedIdenTokenType,
2460
+ EnumToken.FunctionTokenType,
2461
+ EnumToken.ImageFunctionTokenType,
2462
+ EnumToken.UrlFunctionTokenType,
2463
+ EnumToken.TimingFunctionTokenType,
2464
+ EnumToken.TimelineFunctionTokenType,
2465
+ EnumToken.TransformFunctionTokenType,
2466
+ ].includes(token?.typ);
2467
+ break;
2468
+ }
2469
+ case "string": {
2470
+ const token = context.peek();
2471
+ if (token == null) {
2472
+ break;
2473
+ }
2474
+ success = token.typ === EnumToken.StringTokenType;
2475
+ break;
2476
+ }
2477
+ case "wq-name":
2478
+ // wq-name matches
2479
+ // a
2480
+ // |a
2481
+ // *|a
2482
+ // a|b
2483
+ if (context.peek()?.typ == EnumToken.Pipe) {
2484
+ const success = context.peek(1)?.typ == EnumToken.IdenTokenType;
2485
+ return {
2486
+ success,
2487
+ valid: true,
2488
+ token: success ? context.update(context.peek(1)).current() : context.peek(),
2489
+ context,
2490
+ syntaxToken: property,
2491
+ errors: [],
2492
+ };
2493
+ }
2494
+ else if (context.peek(1)?.typ == EnumToken.Pipe) {
2495
+ const success = context.peek()?.typ === EnumToken.Star && context.peek(2)?.typ === EnumToken.IdenTokenType;
2496
+ return {
2497
+ success,
2498
+ valid: true,
2499
+ token: success ? context.update(context.peek(2)).current() : context.peek(),
2500
+ context,
2501
+ syntaxToken: property,
2502
+ errors: [],
2503
+ };
2504
+ }
2505
+ else {
2506
+ const success = context.peek()?.typ == EnumToken.IdenTokenType;
2507
+ return {
2508
+ success,
2509
+ valid: true,
2510
+ token: success ? context.next() : context.peek(),
2511
+ context,
2512
+ syntaxToken: property,
2513
+ errors: [],
2514
+ };
2515
+ }
2516
+ case "id-selector":
2517
+ success = context.peek()?.typ == EnumToken.HashTokenType;
2518
+ break;
2519
+ case "class-selector":
2520
+ success = context.peek()?.typ == EnumToken.ClassSelectorTokenType;
2521
+ break;
2522
+ case "pseudo-class-selector":
2523
+ {
2524
+ const token = context.peek();
2525
+ success =
2526
+ token?.typ == EnumToken.PseudoClassTokenType ||
2527
+ token?.typ == EnumToken.PseudoClassFuncTokenType ||
2528
+ token?.typ == EnumToken.PseudoElementTokenType;
2529
+ }
2530
+ break;
2531
+ case "number":
2532
+ {
2533
+ const token = context.peek();
2534
+ if (token == null) {
2535
+ break;
2536
+ }
2537
+ success = token.typ == EnumToken.NumberTokenType;
2538
+ }
2539
+ break;
2540
+ case "zero": {
2541
+ const token = context.peek();
2542
+ success = token?.typ == EnumToken.NumberTokenType && token.val === 0;
2543
+ break;
2544
+ }
2545
+ case "integer":
2546
+ {
2547
+ const token = context.peek();
2548
+ success =
2549
+ token?.typ == EnumToken.NumberTokenType && Number.isInteger(Number(token.val));
2550
+ }
2551
+ break;
2552
+ case "dimension": {
2553
+ const token = context.peek();
2554
+ if (token == null) {
2555
+ break;
2556
+ }
2557
+ success =
2558
+ token?.typ == EnumToken.DimensionTokenType ||
2559
+ token?.typ == EnumToken.AngleTokenType ||
2560
+ token?.typ == EnumToken.LengthTokenType ||
2561
+ token?.typ == EnumToken.PercentageTokenType ||
2562
+ token?.typ == EnumToken.ResolutionTokenType ||
2563
+ token?.typ == EnumToken.TimeTokenType ||
2564
+ token?.typ == EnumToken.FrequencyTokenType ||
2565
+ token?.typ == EnumToken.FlexTokenType;
2566
+ break;
2567
+ }
2568
+ case "angle":
2569
+ {
2570
+ const token = context.peek();
2571
+ if (token == null) {
2572
+ break;
2573
+ }
2574
+ success = token.typ === EnumToken.AngleTokenType;
2575
+ }
2576
+ break;
2577
+ case "angle-percentage":
2578
+ {
2579
+ const token = context.peek();
2580
+ if (token == null) {
2581
+ break;
2582
+ }
2583
+ success = token.typ === EnumToken.AngleTokenType || token.typ === EnumToken.PercentageTokenType;
2584
+ }
2585
+ break;
2586
+ case "percentage":
2587
+ {
2588
+ const token = context.peek();
2589
+ if (token == null) {
2590
+ break;
2591
+ }
2592
+ success = token.typ === EnumToken.PercentageTokenType;
2593
+ }
2594
+ break;
2595
+ case "length-percentage":
2596
+ {
2597
+ const token = context.peek();
2598
+ if (token == null) {
2599
+ break;
2600
+ }
2601
+ success =
2602
+ token.typ == EnumToken.PercentageTokenType ||
2603
+ token.typ == EnumToken.LengthTokenType ||
2604
+ (token.typ == EnumToken.NumberTokenType && token.val === 0);
2605
+ }
2606
+ break;
2607
+ case "flex":
2608
+ success = context.peek()?.typ == EnumToken.FlexTokenType;
2609
+ break;
2610
+ case "length": {
2611
+ const token = context.peek();
2612
+ if (token == null) {
2613
+ break;
2614
+ }
2615
+ success =
2616
+ token.typ == EnumToken.LengthTokenType ||
2617
+ (token.typ == EnumToken.NumberTokenType && token.val === 0);
2618
+ break;
2619
+ }
2620
+ case "time":
2621
+ {
2622
+ const token = context.peek();
2623
+ if (token == null) {
2624
+ break;
2625
+ }
2626
+ success = token.typ == EnumToken.TimeTokenType;
2627
+ }
2628
+ break;
2629
+ case "hex-color": {
2630
+ const token = context.peek();
2631
+ success =
2632
+ token != null && token.typ == EnumToken.ColorTokenType && token.kin == ColorType.HEX;
2633
+ break;
2634
+ }
2635
+ case "color":
2636
+ case "color-function":
2637
+ {
2638
+ const token = context.peek();
2639
+ const errors = [];
2640
+ if (tokensfuncDefMap.has(token?.typ)) {
2641
+ const range = context.peekRange();
2642
+ const result = matchSyntax(getParsedSyntax(ValidationSyntaxGroupEnum.Syntaxes, token.val + "()"), createValidationContext(range), options);
2643
+ if (result.success) {
2644
+ context.update(range.at(-1));
2645
+ return {
2646
+ success: true,
2647
+ valid: true,
2648
+ token: context.peek(),
2649
+ context,
2650
+ syntaxToken: null,
2651
+ errors: [],
2652
+ };
2653
+ }
2654
+ return result;
2655
+ }
2656
+ // @ts-expect-error
2657
+ else if ("chi" in token) {
2658
+ success = isColor(token, errors);
2659
+ }
2660
+ success = token != null && isColor(token, errors);
2661
+ if (!success) {
2662
+ return {
2663
+ success,
2664
+ valid: false,
2665
+ token,
2666
+ context,
2667
+ syntaxToken: property,
2668
+ errors,
2669
+ };
2670
+ }
2671
+ }
2672
+ break;
2673
+ case "url-token":
2674
+ success =
2675
+ context.peek()?.typ == EnumToken.StringTokenType || context.peek()?.typ == EnumToken.UrlTokenTokenType;
2676
+ break;
2677
+ case "type-selector":
2678
+ case "compound-selector":
2679
+ case "complex-selector":
2680
+ case "subclass-selector":
2681
+ case "attribute-selector":
2682
+ case "complex-selector-unit":
2683
+ case "pseudo-compound-selector":
2684
+ case "complex-selector-list": {
2685
+ const tokens = context.getRemainingTokens();
2686
+ const result = matchSelectorSyntax(tokens, [], options);
2687
+ if (result.success) {
2688
+ context.update(tokens.at(-1));
2689
+ }
2690
+ return {
2691
+ success: result.success,
2692
+ valid: true,
2693
+ token: context.peek(),
2694
+ context,
2695
+ syntaxToken: property,
2696
+ errors: result.errors,
2697
+ };
2698
+ }
2699
+ case "function-token":
2700
+ if (context.peek()?.typ == EnumToken.IdenTokenType &&
2701
+ context.peek(1, false)?.typ == EnumToken.StartParensTokenType) {
2702
+ context.next();
2703
+ context.next();
2704
+ success = true;
2705
+ break;
2706
+ }
2707
+ if (tokensfuncDefMap.has(context.peek()?.typ)) {
2708
+ success = true;
2709
+ context.next();
2710
+ break;
2711
+ }
2712
+ return {
2713
+ success: false,
2714
+ valid: true,
2715
+ token: context.peek(),
2716
+ context,
2717
+ syntaxToken: property,
2718
+ errors: [],
2719
+ };
2720
+ case "language-code": {
2721
+ const token = context.peek();
2722
+ success =
2723
+ token?.typ == EnumToken.IdenTokenType &&
2724
+ // @ts-expect-error
2725
+ config.languages.some((t) => t === token.val || token.val.startsWith(t + "-"));
2726
+ break;
2727
+ }
2728
+ case "named-color": {
2729
+ const token = context.peek();
2730
+ success =
2731
+ token != null &&
2732
+ token.typ == EnumToken.ColorTokenType &&
2733
+ (token.kin == ColorType.LIT ||
2734
+ token.kin == ColorType.SYS ||
2735
+ token.kin == ColorType.DPSYS ||
2736
+ token.kin == ColorType.NON_STD);
2737
+ break;
2738
+ }
2739
+ case "size-feature": {
2740
+ const range = context.peekRange();
2741
+ const filteredRange = range.filter((token) => token.typ !== EnumToken.WhitespaceTokenType && token.typ !== EnumToken.CommentTokenType);
2742
+ if (filteredRange.length === 1) {
2743
+ success =
2744
+ filteredRange[0].typ === EnumToken.IdenTokenType ||
2745
+ filteredRange[0].typ === EnumToken.DashedIdenTokenType;
2746
+ context.update(filteredRange[0]);
2747
+ return {
2748
+ success,
2749
+ valid: true,
2750
+ token: filteredRange[0],
2751
+ context,
2752
+ syntaxToken: property,
2753
+ errors: [],
2754
+ };
2755
+ }
2756
+ if (!mFLT.has(filteredRange[1]?.typ) &&
2757
+ !mFGT.has(filteredRange[1]?.typ) &&
2758
+ filteredRange[1]?.typ !== EnumToken.ColonTokenType &&
2759
+ filteredRange[1]?.typ !== EnumToken.DelimTokenType) {
2760
+ return {
2761
+ success: false,
2762
+ valid: true,
2763
+ token: filteredRange[1],
2764
+ context,
2765
+ syntaxToken: property,
2766
+ errors: [],
2767
+ };
2768
+ }
2769
+ if (filteredRange.length === 3) {
2770
+ success = isValue(filteredRange[2]);
2771
+ if (success) {
2772
+ context.update(filteredRange[2]);
2773
+ return {
2774
+ success,
2775
+ valid: true,
2776
+ token: filteredRange[2],
2777
+ context,
2778
+ syntaxToken: property,
2779
+ errors: [],
2780
+ };
2781
+ }
2782
+ }
2783
+ break;
2784
+ }
2785
+ case "style-feature": {
2786
+ // case 'style-feature-value':
2787
+ // match <style-feature-plain>
2788
+ // match <style-feature-boolean>
2789
+ // match <style-range>
2790
+ const range = context.peekRange();
2791
+ const filteredRange = range.filter((token) => token.typ !== EnumToken.WhitespaceTokenType && token.typ !== EnumToken.CommentTokenType);
2792
+ if (filteredRange.length === 0) {
2793
+ return {
2794
+ success: false,
2795
+ valid: true,
2796
+ token: context.peek(),
2797
+ context,
2798
+ syntaxToken: property,
2799
+ errors: [],
2800
+ };
2801
+ }
2802
+ if (filteredRange.length === 1) {
2803
+ success =
2804
+ filteredRange[0].typ === EnumToken.IdenTokenType ||
2805
+ filteredRange[0].typ === EnumToken.DashedIdenTokenType;
2806
+ context.update(filteredRange[0]);
2807
+ return {
2808
+ success,
2809
+ valid: true,
2810
+ token: filteredRange[0],
2811
+ context,
2812
+ syntaxToken: property,
2813
+ errors: [],
2814
+ };
2815
+ }
2816
+ if (filteredRange[1]?.typ === EnumToken.ColonTokenType ||
2817
+ filteredRange[1]?.typ === EnumToken.DelimTokenType) {
2818
+ const result = isDeclarationValue(filteredRange.slice(2));
2819
+ if (result.success) {
2820
+ context.update(filteredRange.at(-1));
2821
+ return {
2822
+ success: true,
2823
+ valid: true,
2824
+ token: filteredRange.at(-1),
2825
+ context,
2826
+ syntaxToken: property,
2827
+ errors: [],
2828
+ };
2829
+ }
2830
+ return {
2831
+ success: false,
2832
+ valid: false,
2833
+ token: context.peek(),
2834
+ context,
2835
+ syntaxToken: property,
2836
+ errors: result.errors,
2837
+ };
2838
+ }
2839
+ return {
2840
+ success: false,
2841
+ valid: false,
2842
+ token: context.peek(),
2843
+ context,
2844
+ syntaxToken: property,
2845
+ errors: [],
2846
+ };
2847
+ }
2848
+ case "url": {
2849
+ const token = context.peek();
2850
+ if (token == null) {
2851
+ success = false;
2852
+ break;
2853
+ }
2854
+ let l;
2855
+ if (token.typ == EnumToken.UrlFunctionTokenDefType) {
2856
+ l = 0;
2857
+ let token;
2858
+ while ((token = context.peek(++l))) {
2859
+ if (token.typ !== EnumToken.WhitespaceTokenType && token.typ !== EnumToken.CommentTokenType) {
2860
+ break;
2861
+ }
2862
+ }
2863
+ if (token != null &&
2864
+ (token.typ == EnumToken.StringTokenType ||
2865
+ token.typ == EnumToken.IdenTokenType ||
2866
+ token.typ == EnumToken.UrlTokenTokenType)) {
2867
+ if (token.typ === EnumToken.IdenTokenType) {
2868
+ while (context.peek(l + 1)?.typ === EnumToken.ClassSelectorTokenType) {
2869
+ l++;
2870
+ }
2871
+ }
2872
+ while ((token = context.peek(++l))) {
2873
+ if (token.typ !== EnumToken.WhitespaceTokenType && token.typ !== EnumToken.CommentTokenType) {
2874
+ break;
2875
+ }
2876
+ }
2877
+ if (token?.typ == EnumToken.EndParensTokenType) {
2878
+ success = true;
2879
+ context.update(token);
2880
+ return {
2881
+ success: true,
2882
+ valid: true,
2883
+ token: null,
2884
+ context,
2885
+ syntaxToken: null,
2886
+ errors: [],
2887
+ };
2888
+ }
2889
+ }
2890
+ break;
2891
+ }
2892
+ if (token?.typ != EnumToken.UrlFunctionTokenType) {
2893
+ success = false;
2894
+ break;
2895
+ }
2896
+ l = -1;
2897
+ while (++l < token.chi.length) {
2898
+ if (token.chi[l].typ !== EnumToken.WhitespaceTokenType &&
2899
+ token.chi[l].typ !== EnumToken.CommentTokenType) {
2900
+ break;
2901
+ }
2902
+ }
2903
+ if (l < token.chi.length) {
2904
+ success =
2905
+ token.chi[l].typ == EnumToken.StringTokenType ||
2906
+ token.chi[l].typ == EnumToken.IdenTokenType ||
2907
+ token.chi[l].typ == EnumToken.UrlTokenTokenType;
2908
+ context.next();
2909
+ return {
2910
+ success: true,
2911
+ valid: true,
2912
+ token: null,
2913
+ context,
2914
+ syntaxToken: null,
2915
+ errors: [],
2916
+ };
2917
+ }
2918
+ break;
2919
+ }
2920
+ default:
2921
+ if (!(property.val in config.syntaxes)) {
2922
+ console.debug("Unknown syntax", context.peek(), property);
2923
+ console.debug(context.getRemainingTokens());
2924
+ throw new Error(`Unexpected validation property ${property.val}`);
2925
+ }
2926
+ return matchSyntax(getParsedSyntax(ValidationSyntaxGroupEnum.Syntaxes, property.val), context, options);
2927
+ }
2928
+ if (!success &&
2929
+ context.peek()?.typ == EnumToken.IdenTokenType &&
2930
+ allValues.includes(context.peek().val)) {
2931
+ success = true;
2932
+ }
2933
+ if (success) {
2934
+ context.next();
2935
+ return {
2936
+ success: true,
2937
+ valid: true,
2938
+ token: null,
2939
+ context,
2940
+ syntaxToken: null,
2941
+ errors: [],
2942
+ };
2943
+ }
2944
+ return {
2945
+ success: false,
2946
+ valid: true,
2947
+ token: context.peek(),
2948
+ context,
2949
+ syntaxToken: property,
2950
+ errors: [],
2951
+ };
2952
+ }
2953
+ function matchRepeatableSyntax(syntax, context, options) {
2954
+ const { isRepeatable, isOptional, isMandatatoryGroup, isRepeatableAtLeastOnce, ...rest } = syntax;
2955
+ let result = null;
2956
+ let tmpResult;
2957
+ let success = !!isRepeatable;
2958
+ do {
2959
+ tmpResult = matchSyntax([rest], context.slice(), options);
2960
+ if (tmpResult.success) {
2961
+ result = tmpResult;
2962
+ success = true;
2963
+ if (tmpResult.context.done()) {
2964
+ context.end();
2965
+ break;
2966
+ }
2967
+ if (context.current() === tmpResult.context.current()) {
2968
+ context.next();
2969
+ }
2970
+ else {
2971
+ context.update(result.context.current());
2972
+ }
2973
+ }
2974
+ } while (tmpResult.success && !context.done());
2975
+ return {
2976
+ success,
2977
+ valid: true,
2978
+ token: context.peek(),
2979
+ context,
2980
+ syntaxToken: syntax,
2981
+ errors: result?.errors ?? [],
2982
+ };
2983
+ }
2984
+
2985
+ export { createValidationContext, funcTypes, getMFInfo, isMFName, isMFValue, isStyleRangeValue, matchAllSyntax, matchOccurenceSyntax, matchSelectorSyntax, trimArray };