@tbela99/css-parser 0.7.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/.editorconfig +484 -0
  2. package/README.md +140 -84
  3. package/dist/index-umd-web.js +8461 -51655
  4. package/dist/index.cjs +8437 -51636
  5. package/dist/index.d.ts +220 -68
  6. package/dist/lib/ast/expand.js +46 -9
  7. package/dist/lib/ast/features/calc.js +76 -12
  8. package/dist/lib/ast/features/inlinecssvariables.js +6 -1
  9. package/dist/lib/ast/features/prefix.js +17 -9
  10. package/dist/lib/ast/features/shorthand.js +1 -0
  11. package/dist/lib/ast/math/expression.js +299 -11
  12. package/dist/lib/ast/math/math.js +7 -1
  13. package/dist/lib/ast/minify.js +30 -16
  14. package/dist/lib/ast/types.js +59 -49
  15. package/dist/lib/ast/walk.js +92 -18
  16. package/dist/lib/parser/declaration/list.js +1 -0
  17. package/dist/lib/parser/declaration/map.js +60 -52
  18. package/dist/lib/parser/declaration/set.js +1 -12
  19. package/dist/lib/parser/parse.js +371 -119
  20. package/dist/lib/parser/tokenize.js +31 -6
  21. package/dist/lib/parser/utils/declaration.js +2 -2
  22. package/dist/lib/parser/utils/type.js +6 -6
  23. package/dist/lib/renderer/color/a98rgb.js +1 -0
  24. package/dist/lib/renderer/color/color.js +1 -0
  25. package/dist/lib/renderer/color/colormix.js +1 -0
  26. package/dist/lib/renderer/color/hex.js +2 -1
  27. package/dist/lib/renderer/color/hsl.js +2 -1
  28. package/dist/lib/renderer/color/hwb.js +3 -2
  29. package/dist/lib/renderer/color/lab.js +2 -1
  30. package/dist/lib/renderer/color/lch.js +2 -1
  31. package/dist/lib/renderer/color/oklab.js +3 -2
  32. package/dist/lib/renderer/color/oklch.js +2 -1
  33. package/dist/lib/renderer/color/p3.js +2 -1
  34. package/dist/lib/renderer/color/prophotoRgb.js +56 -0
  35. package/dist/lib/renderer/color/prophotorgb.js +1 -1
  36. package/dist/lib/renderer/color/rec2020.js +1 -0
  37. package/dist/lib/renderer/color/relativecolor.js +52 -28
  38. package/dist/lib/renderer/color/rgb.js +2 -1
  39. package/dist/lib/renderer/color/srgb.js +3 -2
  40. package/dist/lib/renderer/color/utils/components.js +1 -0
  41. package/dist/lib/renderer/color/utils/constants.js +2 -1
  42. package/dist/lib/renderer/color/xyz.js +2 -1
  43. package/dist/lib/renderer/color/xyzd50.js +1 -0
  44. package/dist/lib/renderer/render.js +62 -12
  45. package/dist/lib/syntax/syntax.js +362 -4
  46. package/dist/lib/validation/at-rules/container.js +353 -0
  47. package/dist/lib/validation/at-rules/counter-style.js +78 -0
  48. package/dist/lib/validation/at-rules/custom-media.js +52 -0
  49. package/dist/lib/validation/at-rules/document.js +114 -0
  50. package/dist/lib/validation/at-rules/else.js +5 -0
  51. package/dist/lib/validation/at-rules/font-feature-values.js +52 -0
  52. package/dist/lib/validation/at-rules/import.js +199 -0
  53. package/dist/lib/validation/at-rules/keyframes.js +70 -0
  54. package/dist/lib/validation/at-rules/layer.js +30 -0
  55. package/dist/lib/validation/at-rules/media.js +254 -0
  56. package/dist/lib/validation/at-rules/namespace.js +85 -0
  57. package/dist/lib/validation/at-rules/page-margin-box.js +56 -0
  58. package/dist/lib/validation/at-rules/page.js +88 -0
  59. package/dist/lib/validation/at-rules/supports.js +262 -0
  60. package/dist/lib/validation/at-rules/when.js +178 -0
  61. package/dist/lib/validation/atrule.js +187 -0
  62. package/dist/lib/validation/config.js +35 -2
  63. package/dist/lib/validation/config.json.js +1683 -50905
  64. package/dist/lib/validation/declaration.js +102 -0
  65. package/dist/lib/validation/parser/parse.js +1137 -7
  66. package/dist/lib/validation/parser/types.js +28 -12
  67. package/dist/lib/validation/selector.js +26 -444
  68. package/dist/lib/validation/syntax.js +1475 -0
  69. package/dist/lib/validation/syntaxes/complex-selector-list.js +45 -0
  70. package/dist/lib/validation/syntaxes/complex-selector.js +53 -0
  71. package/dist/lib/validation/syntaxes/compound-selector.js +226 -0
  72. package/dist/lib/validation/syntaxes/family-name.js +91 -0
  73. package/dist/lib/validation/syntaxes/image.js +29 -0
  74. package/dist/lib/validation/syntaxes/keyframe-block-list.js +27 -0
  75. package/dist/lib/validation/syntaxes/keyframe-selector.js +137 -0
  76. package/dist/lib/validation/syntaxes/layer-name.js +67 -0
  77. package/dist/lib/validation/syntaxes/relative-selector-list.js +57 -0
  78. package/dist/lib/validation/syntaxes/relative-selector.js +36 -0
  79. package/dist/lib/validation/syntaxes/selector-list.js +5 -0
  80. package/dist/lib/validation/syntaxes/selector.js +5 -0
  81. package/dist/lib/validation/syntaxes/url.js +75 -0
  82. package/dist/lib/validation/utils/list.js +24 -0
  83. package/dist/lib/validation/utils/whitespace.js +22 -0
  84. package/dist/node/index.js +5 -5
  85. package/dist/web/index.js +5 -1
  86. package/dist/web/load.js +1 -0
  87. package/package.json +16 -14
  88. package/dist/lib/ast/utils/minifyfeature.js +0 -9
  89. package/dist/lib/iterable/weakset.js +0 -58
  90. package/dist/lib/parser/utils/syntax.js +0 -450
@@ -0,0 +1,1475 @@
1
+ import { ValidationTokenEnum, specialValues } from './parser/types.js';
2
+ import { renderSyntax } from './parser/parse.js';
3
+ import { ValidationLevel, EnumToken, funcLike } from '../ast/types.js';
4
+ import '../ast/minify.js';
5
+ import '../ast/walk.js';
6
+ import '../parser/parse.js';
7
+ import { isLength } from '../syntax/syntax.js';
8
+ import '../parser/utils/config.js';
9
+ import '../renderer/color/utils/constants.js';
10
+ import '../renderer/sourcemap/lib/encode.js';
11
+ import { getSyntaxConfig, getParsedSyntax } from './config.js';
12
+ import { validateSelector } from './selector.js';
13
+ import './syntaxes/complex-selector.js';
14
+ import { validateImage } from './syntaxes/image.js';
15
+
16
+ const config = getSyntaxConfig();
17
+ function consumeToken(tokens) {
18
+ tokens.shift();
19
+ }
20
+ function consumeSyntax(syntaxes) {
21
+ syntaxes.shift();
22
+ }
23
+ function splice(tokens, matches) {
24
+ if (matches.length == 0) {
25
+ return tokens;
26
+ }
27
+ // @ts-ignore
28
+ const index = tokens.indexOf(matches.at(-1));
29
+ if (index > -1) {
30
+ tokens.splice(0, index + 1);
31
+ }
32
+ return tokens;
33
+ }
34
+ function validateSyntax(syntaxes, tokens, root, options, context = { level: 0 }) {
35
+ console.error(JSON.stringify({
36
+ syntax: syntaxes.reduce((acc, curr) => acc + renderSyntax(curr), ''),
37
+ syntaxes,
38
+ tokens,
39
+ s: new Error('bar').stack
40
+ }, null, 1));
41
+ if (syntaxes == null) {
42
+ // @ts-ignore
43
+ return {
44
+ valid: ValidationLevel.Drop,
45
+ matches: [],
46
+ node: tokens[0] ?? null,
47
+ syntax: null,
48
+ error: 'no matching syntaxes found',
49
+ tokens
50
+ };
51
+ }
52
+ let token = null;
53
+ let syntax;
54
+ let result = null;
55
+ let validSyntax = false;
56
+ let matched = false;
57
+ const matches = [];
58
+ tokens = tokens.slice();
59
+ syntaxes = syntaxes.slice();
60
+ tokens = tokens.slice();
61
+ if (context.cache == null) {
62
+ context.cache = new WeakMap;
63
+ }
64
+ if (context.tokens == null) {
65
+ context.tokens = tokens.slice();
66
+ }
67
+ context = { ...context };
68
+ main: while (tokens.length > 0) {
69
+ if (syntaxes.length == 0) {
70
+ break;
71
+ }
72
+ token = tokens[0];
73
+ syntax = syntaxes[0];
74
+ // @ts-ignore
75
+ context.position = context.tokens.indexOf(token);
76
+ const cached = context.cache.get(token)?.get(syntax.text) ?? null;
77
+ if (cached != null) {
78
+ if (cached.error.length > 0) {
79
+ return { ...cached, tokens, node: cached.valid == ValidationLevel.Valid ? null : token };
80
+ }
81
+ syntaxes.shift();
82
+ tokens.shift();
83
+ continue;
84
+ }
85
+ if (token.typ == EnumToken.DescendantCombinatorTokenType) {
86
+ tokens.shift();
87
+ if (syntax.typ == ValidationTokenEnum.Whitespace) {
88
+ syntaxes.shift();
89
+ }
90
+ continue;
91
+ }
92
+ else if (syntax.typ == ValidationTokenEnum.Whitespace) {
93
+ syntaxes.shift();
94
+ if (token.typ == EnumToken.WhitespaceTokenType) {
95
+ tokens.shift();
96
+ }
97
+ continue;
98
+ }
99
+ else if (syntax.typ == ValidationTokenEnum.Block && EnumToken.AtRuleTokenType == token.typ && ('chi' in token)) {
100
+ syntaxes.shift();
101
+ tokens.shift();
102
+ // @ts-ignore
103
+ matches.push(token);
104
+ continue;
105
+ }
106
+ if (syntax.isOptional) {
107
+ if (!context.cache.has(token)) {
108
+ context.cache.set(token, new Map);
109
+ }
110
+ if (context.cache.get(token).has(syntax.text)) {
111
+ result = context.cache.get(token).get(syntax.text);
112
+ return { ...result, tokens, node: result.valid == ValidationLevel.Valid ? null : token };
113
+ }
114
+ // @ts-ignore
115
+ const { isOptional, ...c } = syntax;
116
+ // @ts-ignore
117
+ let result2;
118
+ // @ts-ignore
119
+ result2 = validateSyntax([c], tokens, root, options, context);
120
+ if (result2.valid == ValidationLevel.Valid && result2.matches.length > 0) {
121
+ tokens = result2.tokens;
122
+ // splice(tokens, result2.matches);
123
+ // tokens = result2.tokens;
124
+ // @ts-ignore
125
+ matches.push(...result2.matches);
126
+ matched = true;
127
+ result = result2;
128
+ }
129
+ else {
130
+ syntaxes.shift();
131
+ continue;
132
+ }
133
+ syntaxes.shift();
134
+ if (syntaxes.length == 0) {
135
+ // @ts-ignore
136
+ return {
137
+ valid: ValidationLevel.Valid,
138
+ matches: result2.matches,
139
+ node: result2.node,
140
+ syntax: result2.syntax,
141
+ error: result2.error,
142
+ tokens
143
+ };
144
+ }
145
+ continue;
146
+ }
147
+ if (syntax.isList) {
148
+ let index = -1;
149
+ // @ts-ignore
150
+ let { isList, ...c } = syntax;
151
+ // const c: ValidationToken = {...syntaxes, isList: false} as ValidationToken;
152
+ let result2 = null;
153
+ validSyntax = false;
154
+ do {
155
+ for (let i = index + 1; i < tokens.length; i++) {
156
+ if (tokens[i].typ == EnumToken.CommaTokenType) {
157
+ index = i;
158
+ break;
159
+ }
160
+ }
161
+ if (tokens[index + 1]?.typ == EnumToken.CommaTokenType) {
162
+ return {
163
+ valid: ValidationLevel.Drop,
164
+ matches,
165
+ node: tokens[0],
166
+ syntax,
167
+ error: 'unexpected token',
168
+ tokens
169
+ };
170
+ }
171
+ if (index == -1) {
172
+ index = tokens.length;
173
+ }
174
+ if (index == 0) {
175
+ break;
176
+ }
177
+ // @ts-ignore
178
+ result2 = validateSyntax([c], tokens.slice(0, index), root, options, context);
179
+ matched = result2.valid == ValidationLevel.Valid && result2.matches.length > 0;
180
+ if (matched) {
181
+ const l = tokens.length;
182
+ validSyntax = true;
183
+ // @ts-ignore
184
+ // matches.push(...result2.matches);
185
+ // splice(tokens, result2.matches);
186
+ if (tokens.length == 1 && tokens[0].typ == EnumToken.CommaTokenType) {
187
+ return {
188
+ valid: ValidationLevel.Drop,
189
+ matches,
190
+ node: tokens[0],
191
+ syntax,
192
+ error: 'unexpected token',
193
+ tokens
194
+ };
195
+ }
196
+ tokens = tokens.slice(index);
197
+ result = result2;
198
+ // @ts-ignore
199
+ matches.push(...result2.matches);
200
+ if (result.tokens.length > 0) {
201
+ if (index == -1) {
202
+ tokens = result.tokens;
203
+ }
204
+ else {
205
+ tokens = tokens.slice(index - result.tokens.length);
206
+ }
207
+ }
208
+ else if (index > 0) {
209
+ tokens = tokens.slice(index);
210
+ }
211
+ index = -1;
212
+ if (l == tokens.length) {
213
+ break;
214
+ }
215
+ }
216
+ else {
217
+ break;
218
+ }
219
+ } while (tokens.length > 0);
220
+ // if (level == 0) {
221
+ // }
222
+ if (!matched) {
223
+ return {
224
+ valid: ValidationLevel.Drop,
225
+ // @ts-ignore
226
+ matches: [...new Set(matches)],
227
+ node: token,
228
+ syntax,
229
+ error: 'unexpected token',
230
+ tokens
231
+ };
232
+ }
233
+ syntaxes.shift();
234
+ continue;
235
+ }
236
+ if (syntax.isRepeatable) {
237
+ // @ts-ignore
238
+ let { isRepeatable, ...c } = syntax;
239
+ let result2 = null;
240
+ validSyntax = false;
241
+ let l = tokens.length;
242
+ let tok = null;
243
+ do {
244
+ // @ts-ignore
245
+ result2 = validateSyntax([c], tokens, root, options, context);
246
+ if (result2.matches.length == 0 && result2.error.length > 0) {
247
+ syntaxes.shift();
248
+ break main;
249
+ }
250
+ if (result2.valid == ValidationLevel.Valid) {
251
+ tokens = result2.tokens;
252
+ // @ts-ignore
253
+ matches.push(...result2.matches);
254
+ result = result2;
255
+ if (l == tokens.length) {
256
+ if (tok == tokens[0]) {
257
+ break;
258
+ }
259
+ if (result2.matches.length == 0 && tokens.length > 0) {
260
+ tokens = result2.tokens;
261
+ tok = tokens[0];
262
+ continue;
263
+ }
264
+ break;
265
+ }
266
+ if (matches.length == 0) {
267
+ tokens = result2.tokens;
268
+ }
269
+ l = tokens.length;
270
+ continue;
271
+ }
272
+ break;
273
+ } while (result2.valid == ValidationLevel.Valid && tokens.length > 0);
274
+ // if (lastResult != null) {
275
+ //
276
+ // splice(tokens, lastResult.matches);
277
+ // // tokens = lastResult.tokens;
278
+ // }
279
+ syntaxes.shift();
280
+ continue;
281
+ }
282
+ // at least one match
283
+ if (syntax.isRepeatableGroup) {
284
+ validSyntax = false;
285
+ let count = 0;
286
+ let l = tokens.length;
287
+ let result2 = null;
288
+ do {
289
+ // @ts-ignore
290
+ const { isRepeatableGroup, ...c } = syntax;
291
+ // @ts-ignore
292
+ result2 = validateSyntax([c], tokens, root, options, context);
293
+ if (result2.valid == ValidationLevel.Drop || result2.matches.length == 0) {
294
+ if (count > 0) {
295
+ syntaxes.shift();
296
+ // if (result2.matches.length == 0) {
297
+ tokens = result2.tokens;
298
+ // break main;
299
+ if (syntaxes.length == 0) {
300
+ return result2;
301
+ }
302
+ break main;
303
+ }
304
+ return result2;
305
+ }
306
+ if (result2.valid == ValidationLevel.Valid && result2.matches.length > 0) {
307
+ count++;
308
+ // lastResult = result;
309
+ validSyntax = true;
310
+ tokens = result2.tokens;
311
+ // splice(tokens, result2.matches);
312
+ // tokens = result2.tokens;
313
+ // @ts-ignore
314
+ matches.push(...result2.matches);
315
+ result = result2;
316
+ if (l == tokens.length) {
317
+ break;
318
+ }
319
+ l = tokens.length;
320
+ }
321
+ else {
322
+ break;
323
+ }
324
+ } while (tokens.length > 0 && result.valid == ValidationLevel.Valid);
325
+ // if (lastResult != null) {
326
+ //
327
+ // splice(tokens, lastResult.matches);
328
+ // // tokens = lastResult.tokens;
329
+ // }
330
+ // at least one match is expected
331
+ if (!validSyntax /* || result.matches.length == 0 */) {
332
+ // @ts-ignore
333
+ return {
334
+ valid: ValidationLevel.Drop,
335
+ node: token,
336
+ tokens,
337
+ syntax,
338
+ error: 'unexpected token',
339
+ matches: []
340
+ };
341
+ }
342
+ syntaxes.shift();
343
+ continue;
344
+ }
345
+ if (syntax.atLeastOnce) {
346
+ const { atLeastOnce, ...c } = syntax;
347
+ result = validateSyntax([c], tokens, root, options, context);
348
+ if (result.valid == ValidationLevel.Drop) {
349
+ return result;
350
+ }
351
+ splice(tokens, result.matches);
352
+ // tokens = result.tokens;
353
+ // @ts-ignore
354
+ matches.push(...result.matches);
355
+ let l = tokens.length;
356
+ let r = validateSyntax([c], tokens, root, options, context);
357
+ while (r.valid == ValidationLevel.Valid) {
358
+ splice(tokens, r.matches);
359
+ // tokens = r.tokens;
360
+ r = validateSyntax([c], tokens, root, options, context);
361
+ if (l == tokens.length) {
362
+ break;
363
+ }
364
+ if (r.valid == ValidationLevel.Valid && r.matches.length > 0) {
365
+ // @ts-ignore
366
+ matches.push(...result.matches);
367
+ }
368
+ l = tokens.length;
369
+ }
370
+ syntaxes.shift();
371
+ continue;
372
+ }
373
+ // @ts-ignore
374
+ if (syntax.occurence != null) {
375
+ // @ts-ignore
376
+ const { occurence, ...c } = syntax;
377
+ // && syntaxes.occurence.max != null
378
+ // consume all tokens
379
+ let match = 1;
380
+ // @ts-ignore
381
+ result = validateSyntax([c], tokens, root, options, context);
382
+ if (result.valid == ValidationLevel.Drop) {
383
+ return result;
384
+ }
385
+ if (result.matches.length == 0) {
386
+ syntaxes.shift();
387
+ continue;
388
+ }
389
+ // splice(tokens, result.matches);
390
+ // tokens = result.tokens;
391
+ // @ts-ignore
392
+ matches.push(...result.matches);
393
+ matched = true;
394
+ tokens = result.tokens;
395
+ while (occurence.max == null || match < occurence.max) {
396
+ // trim whitespace
397
+ if (tokens[0]?.typ == EnumToken.WhitespaceTokenType) {
398
+ tokens.shift();
399
+ }
400
+ // @ts-ignore
401
+ let r = validateSyntax([c], tokens, root, options, context);
402
+ if (r.valid != ValidationLevel.Valid || r.matches.length == 0) {
403
+ break;
404
+ }
405
+ result = r;
406
+ // splice(tokens, r.matches);
407
+ // tokens = r.tokens;
408
+ // @ts-ignore
409
+ matches.push(...result.matches);
410
+ match++;
411
+ tokens = r.tokens;
412
+ result = r;
413
+ if (tokens.length == 0 || (occurence.max != null && match >= occurence.max)) {
414
+ break;
415
+ }
416
+ // @ts-ignore
417
+ // r = validateSyntax([c], tokens, root, options, context);
418
+ }
419
+ syntaxes.shift();
420
+ continue;
421
+ }
422
+ // @ts-ignore
423
+ if (syntax.typ == ValidationTokenEnum.Whitespace) {
424
+ if (token.typ == EnumToken.WhitespaceTokenType) {
425
+ tokens.shift();
426
+ }
427
+ syntaxes.shift();
428
+ continue;
429
+ }
430
+ // @ts-ignore
431
+ if (token.val != null && specialValues.includes(token.val)) {
432
+ matched = true;
433
+ result = {
434
+ valid: ValidationLevel.Valid,
435
+ matches: [token],
436
+ node: null,
437
+ syntax,
438
+ error: '',
439
+ tokens
440
+ };
441
+ // @ts-ignore
442
+ matches.push(...result.matches);
443
+ }
444
+ else {
445
+ result = doValidateSyntax(syntax, token, tokens, root, options, context);
446
+ matched = result.valid == ValidationLevel.Valid && result.matches.length > 0;
447
+ if (matched) {
448
+ // splice(tokens, result.matches);
449
+ tokens = result.tokens;
450
+ // @ts-ignore
451
+ matches.push(...result.matches);
452
+ }
453
+ }
454
+ if (result.valid == ValidationLevel.Drop) {
455
+ // @ts-ignore
456
+ return { ...result, matches, tokens, node: result.valid == ValidationLevel.Valid ? null : token };
457
+ }
458
+ consumeSyntax(syntaxes);
459
+ if (tokens.length == 0) {
460
+ return result;
461
+ }
462
+ }
463
+ if (result?.valid == ValidationLevel.Valid) {
464
+ // splice(tokens, result.matches);
465
+ tokens = result.tokens;
466
+ // @ts-ignore
467
+ matches.push(...result.matches);
468
+ }
469
+ if ( /* result == null && */tokens.length == 0 && syntaxes.length > 0) {
470
+ validSyntax = isOptionalSyntax(syntaxes);
471
+ }
472
+ if (result == null) {
473
+ result = {
474
+ valid: validSyntax ? ValidationLevel.Valid : ValidationLevel.Drop,
475
+ matches,
476
+ node: validSyntax ? null : tokens[0] ?? null,
477
+ // @ts-ignore
478
+ syntax,
479
+ error: validSyntax ? '' : 'unexpected token',
480
+ tokens
481
+ };
482
+ }
483
+ if (token != null) {
484
+ if (!context.cache.has(token)) {
485
+ context.cache.set(token, new Map);
486
+ }
487
+ context.cache.get(token).set(syntax.text, result);
488
+ }
489
+ if (result != null) {
490
+ // @ts-ignore
491
+ return { ...result, matches: [...(new Set(matches))] };
492
+ }
493
+ return result;
494
+ }
495
+ function isOptionalSyntax(syntaxes) {
496
+ return syntaxes.length > 0 && syntaxes.every(t => t.typ == ValidationTokenEnum.Whitespace || t.isOptional || t.isRepeatable || (t.typ == ValidationTokenEnum.PropertyType && isOptionalSyntax(getParsedSyntax("syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */, t.val) ?? getParsedSyntax("declarations" /* ValidationSyntaxGroupEnum.Declarations */, t.val) ?? [])));
497
+ }
498
+ function doValidateSyntax(syntax, token, tokens, root, options, context) {
499
+ let valid = false;
500
+ let result;
501
+ let children;
502
+ let queue;
503
+ let matches;
504
+ let child;
505
+ let astNodes = new Set;
506
+ if (token.typ == EnumToken.NestingSelectorTokenType && syntax.typ == 2) {
507
+ valid = root != null && 'relative-selector' == syntax.val;
508
+ return {
509
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
510
+ matches: valid ? [token] : [],
511
+ node: valid ? null : token,
512
+ syntax,
513
+ error: valid ? '' : 'unexpected token',
514
+ tokens
515
+ };
516
+ }
517
+ switch (syntax.typ) {
518
+ case ValidationTokenEnum.Comma:
519
+ valid = token.typ === EnumToken.CommaTokenType;
520
+ // @ts-ignore
521
+ result = {
522
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
523
+ matches: valid ? [token] : [],
524
+ node: valid ? null : token,
525
+ syntax,
526
+ error: valid ? '' : 'unexpected token',
527
+ tokens
528
+ };
529
+ break;
530
+ case ValidationTokenEnum.AtRule:
531
+ if (token.typ != EnumToken.AtRuleNodeType) {
532
+ // @ts-ignore
533
+ return {
534
+ valid: ValidationLevel.Drop,
535
+ matches: [],
536
+ node: token,
537
+ syntax,
538
+ error: 'expecting at-rule',
539
+ tokens
540
+ };
541
+ }
542
+ if (token.nam != syntax.val) {
543
+ // @ts-ignore
544
+ return {
545
+ valid: ValidationLevel.Drop,
546
+ matches: [],
547
+ node: token,
548
+ syntax,
549
+ error: `expecting '@${syntax.val}' but found '@${token.nam}'`,
550
+ tokens
551
+ };
552
+ }
553
+ if (root == null) {
554
+ return {
555
+ valid: ValidationLevel.Valid,
556
+ matches: [token],
557
+ node: null,
558
+ syntax,
559
+ error: '',
560
+ tokens
561
+ };
562
+ }
563
+ if (root.typ != EnumToken.AtRuleNodeType) {
564
+ // @ts-ignore
565
+ return {
566
+ valid: ValidationLevel.Drop,
567
+ matches: [],
568
+ node: token,
569
+ syntax,
570
+ error: 'not allowed here',
571
+ tokens
572
+ };
573
+ }
574
+ if (!('chi' in token)) {
575
+ // @ts-ignore
576
+ return {
577
+ valid: ValidationLevel.Drop,
578
+ matches: [],
579
+ node: token,
580
+ syntax,
581
+ error: '@at-rule must have children',
582
+ tokens
583
+ };
584
+ }
585
+ // @ts-ignore
586
+ result = {
587
+ valid: ValidationLevel.Valid,
588
+ matches: [token],
589
+ node: null,
590
+ syntax,
591
+ error: '',
592
+ tokens
593
+ };
594
+ break;
595
+ case ValidationTokenEnum.AtRuleDefinition:
596
+ if (token.typ != EnumToken.AtRuleNodeType) {
597
+ // @ts-ignore
598
+ return {
599
+ valid: ValidationLevel.Drop,
600
+ matches: [],
601
+ node: token,
602
+ syntax,
603
+ error: 'expecting at-rule',
604
+ tokens
605
+ };
606
+ }
607
+ if ('chi' in syntax && !('chi' in token)) {
608
+ // @ts-ignore
609
+ return {
610
+ valid: ValidationLevel.Drop,
611
+ matches: [],
612
+ node: token,
613
+ syntax,
614
+ error: '@at-rule must have children',
615
+ tokens
616
+ };
617
+ }
618
+ if ('chi' in token && !('chi' in token)) {
619
+ // @ts-ignore
620
+ return {
621
+ valid: ValidationLevel.Drop,
622
+ matches: [],
623
+ node: token,
624
+ syntax,
625
+ error: 'children not allowed here',
626
+ tokens
627
+ };
628
+ }
629
+ const s = getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, '@' + token.nam);
630
+ if ('prelude' in syntax) {
631
+ if (!('tokens' in token)) {
632
+ // @ts-ignore
633
+ return {
634
+ valid: ValidationLevel.Drop,
635
+ matches: [],
636
+ node: token,
637
+ syntax,
638
+ error: 'expected at-rule prelude',
639
+ tokens
640
+ };
641
+ }
642
+ result = validateSyntax(s[0].prelude, token.tokens, root, options, {
643
+ ...context,
644
+ tokens: null,
645
+ level: context.level + 1
646
+ });
647
+ if (result.valid == ValidationLevel.Drop) {
648
+ return result;
649
+ }
650
+ }
651
+ const hasBody = 'chi' in s[0];
652
+ if ('chi' in token) {
653
+ if (!hasBody) {
654
+ // @ts-ignore
655
+ return {
656
+ valid: ValidationLevel.Drop,
657
+ matches: [],
658
+ node: token,
659
+ syntax,
660
+ error: 'unexpected at-rule body',
661
+ tokens
662
+ };
663
+ }
664
+ }
665
+ else if (hasBody) {
666
+ // @ts-ignore
667
+ return {
668
+ valid: ValidationLevel.Drop,
669
+ matches: [],
670
+ node: token,
671
+ syntax,
672
+ error: 'expecting at-rule body',
673
+ tokens
674
+ };
675
+ }
676
+ break;
677
+ case ValidationTokenEnum.DeclarationType:
678
+ // @ts-ignore
679
+ result = validateSyntax(getParsedSyntax("declarations" /* ValidationSyntaxGroupEnum.Declarations */, syntax.val), [token], root, options, context);
680
+ break;
681
+ case ValidationTokenEnum.Keyword:
682
+ valid = (token.typ == EnumToken.IdenTokenType && token.val.localeCompare(syntax.val, 'en', { sensitivity: 'base' }) == 0) ||
683
+ (token.typ == EnumToken.ColorTokenType && token.kin == 'lit' && syntax.val.localeCompare(token.val, 'en', { sensitivity: 'base' }) == 0);
684
+ result = {
685
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
686
+ matches: valid ? [token] : [],
687
+ node: valid ? null : token,
688
+ syntax,
689
+ error: valid ? '' : 'unexpected token',
690
+ tokens
691
+ };
692
+ break;
693
+ case ValidationTokenEnum.SemiColon:
694
+ valid = root == null || [EnumToken.RuleNodeType, EnumToken.AtRuleNodeType, EnumToken.StyleSheetNodeType].includes(root.typ);
695
+ result = {
696
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
697
+ matches: valid ? [token] : [],
698
+ node: valid ? null : token,
699
+ syntax,
700
+ error: valid ? '' : 'unexpected token',
701
+ tokens
702
+ };
703
+ break;
704
+ case ValidationTokenEnum.Separator:
705
+ valid = token.typ == EnumToken.LiteralTokenType && token.val != '/';
706
+ result = {
707
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
708
+ matches: valid ? [token] : [],
709
+ node: valid ? null : token,
710
+ syntax,
711
+ error: valid ? '' : 'unexpected token',
712
+ tokens
713
+ };
714
+ break;
715
+ case ValidationTokenEnum.PropertyType:
716
+ //
717
+ if ('image' == syntax.val) {
718
+ valid = token.typ == EnumToken.UrlFunctionTokenType || token.typ == EnumToken.ImageFunctionTokenType;
719
+ if (!valid) {
720
+ return {
721
+ valid: ValidationLevel.Drop,
722
+ matches: [],
723
+ node: token,
724
+ syntax,
725
+ error: 'unexpected <image>',
726
+ tokens
727
+ };
728
+ }
729
+ result = validateImage(token);
730
+ }
731
+ else if (['media-feature', 'mf-plain'].includes(syntax.val)) {
732
+ valid = token.typ == EnumToken.DeclarationNodeType;
733
+ result = {
734
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
735
+ matches: valid ? [token] : [],
736
+ node: valid ? null : token,
737
+ syntax,
738
+ error: valid ? '' : 'unexpected token',
739
+ tokens
740
+ };
741
+ }
742
+ else if (syntax.val == 'pseudo-page') {
743
+ valid = token.typ == EnumToken.PseudoClassTokenType && [':left', ':right', ':first', ':blank'].includes(token.val);
744
+ result = {
745
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
746
+ matches: valid ? [token] : [],
747
+ node: valid ? null : token,
748
+ syntax,
749
+ error: valid ? '' : 'unexpected token',
750
+ tokens
751
+ };
752
+ }
753
+ else if (syntax.val == 'page-body') {
754
+ if (token.typ == EnumToken.DeclarationNodeType) {
755
+ valid = true;
756
+ // @ts-ignore
757
+ result = {
758
+ valid: ValidationLevel.Valid,
759
+ matches: [token],
760
+ node: null,
761
+ syntax,
762
+ error: '',
763
+ tokens
764
+ };
765
+ while (tokens.length > 0 && [EnumToken.DeclarationNodeType].includes(tokens[0].typ)) {
766
+ // @ts-ignore
767
+ result.matches.push(tokens.shift());
768
+ }
769
+ }
770
+ else if (token.typ == EnumToken.AtRuleNodeType) {
771
+ result = validateSyntax(getParsedSyntax("syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */, 'page-margin-box-type'), [token], root, options, context);
772
+ }
773
+ }
774
+ else if (syntax.val == 'group-rule-body') {
775
+ valid = [EnumToken.AtRuleNodeType, EnumToken.RuleNodeType].includes(token.typ);
776
+ if (!valid && token.typ == EnumToken.DeclarationNodeType && root?.typ == EnumToken.AtRuleNodeType && root.nam == 'media') {
777
+ // allowed only if nested rule
778
+ let parent = root;
779
+ while (parent != null) {
780
+ if (parent.typ == EnumToken.RuleNodeType) {
781
+ valid = true;
782
+ break;
783
+ }
784
+ // @ts-ignore
785
+ parent = parent.parent;
786
+ }
787
+ }
788
+ // @ts-ignore
789
+ result = {
790
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
791
+ matches: [],
792
+ node: valid ? null : token,
793
+ syntax,
794
+ error: valid ? '' : 'token is not allowed as a child',
795
+ tokens
796
+ };
797
+ if (!valid) {
798
+ return result;
799
+ }
800
+ }
801
+ //
802
+ else if ('type-selector' == syntax.val) {
803
+ valid = (token.typ == EnumToken.UniversalSelectorTokenType) ||
804
+ token.typ == EnumToken.IdenTokenType || (token.typ == EnumToken.NameSpaceAttributeTokenType &&
805
+ (token.l == null || token.l.typ == EnumToken.IdenTokenType ||
806
+ (token.l.typ == EnumToken.LiteralTokenType && token.l.val == '*')) &&
807
+ token.r.typ == EnumToken.IdenTokenType);
808
+ result = {
809
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
810
+ matches: valid ? [token] : [],
811
+ node: token,
812
+ syntax,
813
+ error: valid ? '' : 'unexpected token',
814
+ tokens
815
+ };
816
+ }
817
+ else if ('wq-name' == syntax.val) {
818
+ valid = token.typ == EnumToken.IdenTokenType || (token.typ == EnumToken.NameSpaceAttributeTokenType &&
819
+ (token.l == null || token.l.typ == EnumToken.IdenTokenType || (token.l.typ == EnumToken.LiteralTokenType && token.l.val == '*')) &&
820
+ token.r.typ == EnumToken.IdenTokenType);
821
+ result = {
822
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
823
+ matches: valid ? [token] : [],
824
+ node: token,
825
+ syntax,
826
+ error: valid ? '' : 'unexpected token',
827
+ tokens
828
+ };
829
+ }
830
+ else if (EnumToken.UniversalSelectorTokenType == token.typ && 'subclass-selector' == syntax.val) {
831
+ valid = true;
832
+ result = {
833
+ valid: ValidationLevel.Valid,
834
+ matches: [token],
835
+ node: null,
836
+ syntax,
837
+ error: '',
838
+ tokens
839
+ };
840
+ }
841
+ else if ('attribute-selector' == syntax.val) {
842
+ valid = token.typ == EnumToken.AttrTokenType && token.chi.length > 0;
843
+ if (valid) {
844
+ const children = token.chi.filter(t => t.typ != EnumToken.WhitespaceTokenType && t.typ != EnumToken.CommaTokenType);
845
+ valid = children.length == 1 && [
846
+ EnumToken.IdenTokenType,
847
+ EnumToken.NameSpaceAttributeTokenType,
848
+ EnumToken.MatchExpressionTokenType
849
+ ].includes(children[0].typ);
850
+ if (valid && children[0].typ == EnumToken.MatchExpressionTokenType) {
851
+ const t = children[0];
852
+ valid = [
853
+ EnumToken.IdenTokenType,
854
+ EnumToken.NameSpaceAttributeTokenType
855
+ ].includes(t.l.typ) &&
856
+ (t.op == null || ([
857
+ EnumToken.DelimTokenType, EnumToken.DashMatchTokenType,
858
+ EnumToken.StartMatchTokenType, EnumToken.ContainMatchTokenType,
859
+ EnumToken.EndMatchTokenType, EnumToken.IncludeMatchTokenType
860
+ ].includes(t.op.typ) &&
861
+ t.r != null &&
862
+ [
863
+ EnumToken.StringTokenType,
864
+ EnumToken.IdenTokenType
865
+ ].includes(t.r.typ)));
866
+ if (valid && t.attr != null) {
867
+ const s = getParsedSyntax("syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */, 'attr-modifier')[0];
868
+ valid = s.chi.some((l) => l.some((r) => r.val == t.attr));
869
+ }
870
+ }
871
+ }
872
+ result = {
873
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
874
+ matches: valid ? [token] : [],
875
+ node: valid ? null : token,
876
+ syntax,
877
+ error: valid ? '' : 'unexpected token',
878
+ tokens
879
+ };
880
+ if (!valid) {
881
+ return result;
882
+ }
883
+ }
884
+ else if ('combinator' == syntax.val) {
885
+ valid = [
886
+ EnumToken.DescendantCombinatorTokenType,
887
+ EnumToken.SubsequentSiblingCombinatorTokenType,
888
+ EnumToken.NextSiblingCombinatorTokenType,
889
+ EnumToken.ChildCombinatorTokenType,
890
+ EnumToken.ColumnCombinatorTokenType
891
+ ].includes(token.typ);
892
+ if (valid) {
893
+ // @ts-ignore
894
+ const position = context.tokens.indexOf(token);
895
+ if (root == null) {
896
+ valid = position > 0 && context.tokens[position - 1]?.typ != EnumToken.CommaTokenType;
897
+ }
898
+ }
899
+ result = {
900
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
901
+ matches: valid ? [token] : [],
902
+ node: valid ? null : token,
903
+ syntax,
904
+ error: valid ? '' : 'unexpected token',
905
+ tokens
906
+ };
907
+ if (!valid) {
908
+ return result;
909
+ }
910
+ }
911
+ else if ('ident-token' == syntax.val) {
912
+ valid = token.typ == EnumToken.IdenTokenType;
913
+ result = {
914
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
915
+ matches: valid ? [token] : [],
916
+ node: valid ? null : token,
917
+ syntax,
918
+ error: valid ? '' : 'unexpected token',
919
+ tokens
920
+ };
921
+ }
922
+ else if ('hex-color' == syntax.val) {
923
+ valid = token.typ == EnumToken.ColorTokenType && token.kin == 'hex';
924
+ result = {
925
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
926
+ matches: valid ? [token] : [],
927
+ node: valid ? null : token,
928
+ syntax,
929
+ error: valid ? '' : 'unexpected token',
930
+ tokens
931
+ };
932
+ }
933
+ else if ('resolution' == syntax.val) {
934
+ valid = token.typ == EnumToken.ResolutionTokenType;
935
+ result = {
936
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
937
+ matches: valid ? [token] : [],
938
+ node: valid ? null : token,
939
+ syntax,
940
+ error: valid ? '' : 'unexpected token',
941
+ tokens
942
+ };
943
+ }
944
+ else if ('angle' == syntax.val) {
945
+ valid = token.typ == EnumToken.AngleTokenType || (token.typ == EnumToken.NumberTokenType && token.val == '0');
946
+ result = {
947
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
948
+ matches: valid ? [token] : [],
949
+ node: valid ? null : token,
950
+ syntax,
951
+ error: valid ? '' : 'unexpected token',
952
+ tokens
953
+ };
954
+ }
955
+ else if ('time' == syntax.val) {
956
+ valid = token.typ == EnumToken.TimingFunctionTokenType;
957
+ result = {
958
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
959
+ matches: valid ? [token] : [],
960
+ node: valid ? null : token,
961
+ syntax,
962
+ error: valid ? '' : 'unexpected token',
963
+ tokens
964
+ };
965
+ }
966
+ else if ('ident' == syntax.val) {
967
+ valid = token.typ == EnumToken.IdenTokenType;
968
+ result = {
969
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
970
+ matches: valid ? [token] : [],
971
+ node: valid ? null : token,
972
+ syntax,
973
+ error: valid ? '' : 'unexpected token',
974
+ tokens
975
+ };
976
+ }
977
+ else if (['id-selector', 'hash-token'].includes(syntax.val)) {
978
+ valid = token.typ == EnumToken.HashTokenType;
979
+ result = {
980
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
981
+ matches: valid ? [token] : [],
982
+ node: valid ? null : token,
983
+ syntax,
984
+ error: valid ? '' : 'unexpected token',
985
+ tokens
986
+ };
987
+ }
988
+ else if (['integer', 'number'].includes(syntax.val)) {
989
+ // valid = token.typ == EnumToken.NumberTokenType;
990
+ valid = token.typ == EnumToken.NumberTokenType && ('integer' != syntax.val || Number.isInteger(+token.val));
991
+ if (valid && 'range' in syntax) {
992
+ const value = Number(token.val);
993
+ const range = syntax.range;
994
+ valid = value >= range[0] && (range[1] == null || value <= range[1]);
995
+ }
996
+ result = {
997
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
998
+ matches: valid ? [token] : [],
999
+ node: valid ? null : token,
1000
+ syntax,
1001
+ error: valid ? '' : 'unexpected token',
1002
+ tokens
1003
+ };
1004
+ }
1005
+ else if ('length' == syntax.val) {
1006
+ valid = isLength(token) || (token.typ == EnumToken.NumberTokenType && token.val == '0');
1007
+ // @ts-ignore
1008
+ result = {
1009
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1010
+ matches: valid ? [token] : [],
1011
+ node: valid ? null : token,
1012
+ syntax,
1013
+ error: valid ? '' : 'unexpected token',
1014
+ tokens
1015
+ };
1016
+ }
1017
+ else if ('percentage' == syntax.val) {
1018
+ valid = token.typ == EnumToken.PercentageTokenType || (token.typ == EnumToken.NumberTokenType && token.val == '0');
1019
+ result = {
1020
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1021
+ matches: valid ? [token] : [],
1022
+ node: valid ? null : token,
1023
+ syntax,
1024
+ error: valid ? '' : 'unexpected token',
1025
+ tokens
1026
+ };
1027
+ }
1028
+ else if ('dashed-ident' == syntax.val) {
1029
+ valid = token.typ == EnumToken.DashedIdenTokenType;
1030
+ result = {
1031
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1032
+ matches: valid ? [token] : [],
1033
+ node: valid ? null : token,
1034
+ syntax,
1035
+ error: valid ? '' : 'unexpected token',
1036
+ tokens
1037
+ };
1038
+ }
1039
+ else if ('custom-ident' == syntax.val) {
1040
+ valid = token.typ == EnumToken.DashedIdenTokenType || token.typ == EnumToken.IdenTokenType;
1041
+ result = {
1042
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1043
+ matches: valid ? [token] : [],
1044
+ node: valid ? null : token,
1045
+ syntax,
1046
+ error: valid ? '' : 'unexpected token',
1047
+ tokens
1048
+ };
1049
+ }
1050
+ else if ('custom-property-name' == syntax.val) {
1051
+ valid = token.typ == EnumToken.DashedIdenTokenType;
1052
+ result = {
1053
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1054
+ matches: valid ? [token] : [],
1055
+ node: valid ? null : token,
1056
+ syntax,
1057
+ error: valid ? '' : 'unexpected token',
1058
+ tokens
1059
+ };
1060
+ }
1061
+ else if ('string' == syntax.val) {
1062
+ valid = token.typ == EnumToken.StringTokenType;
1063
+ result = {
1064
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1065
+ matches: valid ? [token] : [],
1066
+ node: valid ? null : token,
1067
+ syntax,
1068
+ error: valid ? '' : 'unexpected token',
1069
+ tokens
1070
+ };
1071
+ }
1072
+ else if ('declaration-value' == syntax.val) {
1073
+ valid = token.typ != EnumToken.LiteralTokenType;
1074
+ result = {
1075
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1076
+ matches: valid ? [token] : [],
1077
+ node: valid ? null : token,
1078
+ syntax,
1079
+ error: valid ? '' : 'unexpected token',
1080
+ tokens
1081
+ };
1082
+ }
1083
+ else if ('url' == syntax.val) {
1084
+ valid = token.typ == EnumToken.UrlFunctionTokenType || token.typ == EnumToken.StringTokenType;
1085
+ result = {
1086
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1087
+ matches: valid ? [token] : [],
1088
+ node: valid ? null : token,
1089
+ syntax,
1090
+ error: valid ? '' : 'unexpected token',
1091
+ tokens
1092
+ };
1093
+ }
1094
+ else if ('declaration' == syntax.val) {
1095
+ valid = token.typ == EnumToken.DeclarationNodeType && (token.nam.startsWith(('--')) || token.nam in config.declarations || token.nam in config.syntaxes);
1096
+ if (!valid) {
1097
+ // @ts-ignore
1098
+ result = {
1099
+ valid: ValidationLevel.Drop,
1100
+ matches: [],
1101
+ node: token,
1102
+ syntax,
1103
+ error: 'unexpected token',
1104
+ tokens
1105
+ };
1106
+ }
1107
+ else if (token.nam.startsWith(('--'))) {
1108
+ result = {
1109
+ valid: ValidationLevel.Valid,
1110
+ matches: [token],
1111
+ node: null,
1112
+ syntax,
1113
+ error: '',
1114
+ tokens
1115
+ };
1116
+ }
1117
+ else {
1118
+ result = validateSyntax(getParsedSyntax("declarations" /* ValidationSyntaxGroupEnum.Declarations */, token.nam) ?? getParsedSyntax("syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */, token.nam), token.val, token, options, {
1119
+ ...context,
1120
+ tokens: null,
1121
+ level: 0
1122
+ });
1123
+ if (result.valid == ValidationLevel.Valid && result.error.length == 0) {
1124
+ tokens = result.tokens;
1125
+ }
1126
+ }
1127
+ }
1128
+ else if ('class-selector' == syntax.val) {
1129
+ valid = EnumToken.ClassSelectorTokenType == token.typ || EnumToken.UniversalSelectorTokenType == token.typ;
1130
+ result = {
1131
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1132
+ matches: valid ? [token] : [],
1133
+ node: token,
1134
+ syntax,
1135
+ error: valid ? '' : 'unexpected token',
1136
+ tokens
1137
+ };
1138
+ }
1139
+ // else if ('complex-selector' == (syntaxes as ValidationPropertyToken).val) {
1140
+ //
1141
+ // result = validateSyntax(getParsedSyntax(ValidationSyntaxGroupEnum.Syntaxes, (syntaxes as ValidationPropertyToken).val) as ValidationToken[], tokens, root as AstNode, options, context);
1142
+ //
1143
+ // }
1144
+ else if (['pseudo-element-selector', 'pseudo-class-selector'].includes(syntax.val)) {
1145
+ valid = false;
1146
+ if (token.typ == EnumToken.PseudoClassTokenType) {
1147
+ let val = token.val;
1148
+ if (val == ':before' || val == ':after') {
1149
+ val = ':' + val;
1150
+ }
1151
+ valid = val in config.selectors;
1152
+ if (!valid && val.match(/^:?:-/) != null) {
1153
+ const match = token.val.match(/^(:?:)(-[^-]+-)(.*)$/);
1154
+ if (match != null) {
1155
+ valid = true;
1156
+ }
1157
+ }
1158
+ result = {
1159
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1160
+ matches: valid ? [token] : [],
1161
+ node: valid ? null : token,
1162
+ syntax,
1163
+ error: valid ? '' : 'invalid pseudo class',
1164
+ tokens
1165
+ };
1166
+ }
1167
+ else if (token.typ == EnumToken.PseudoClassFuncTokenType) {
1168
+ let key = token.val in config.selectors ? token.val : token.val + '()';
1169
+ valid = key in config.selectors;
1170
+ if (!valid && token.val.match(/^:?:-/)) {
1171
+ const match = token.val.match(/^(:?:)(-[^-]+-)(.*)$/);
1172
+ if (match != null) {
1173
+ key = match[1] + match[3] in config.selectors ? match[1] + match[3] : match[1] + match[3] + '()';
1174
+ valid = key in config.selectors;
1175
+ }
1176
+ }
1177
+ const s = getParsedSyntax("selectors" /* ValidationSyntaxGroupEnum.Selectors */, key);
1178
+ if (s != null) {
1179
+ const r = s[0];
1180
+ if (r.typ != ValidationTokenEnum.PseudoClassFunctionToken) {
1181
+ valid = false;
1182
+ }
1183
+ else {
1184
+ result = validateSyntax(s[0].chi, token.chi, root, options, {
1185
+ ...context,
1186
+ tokens: null,
1187
+ level: context.level + 1
1188
+ });
1189
+ break;
1190
+ }
1191
+ }
1192
+ }
1193
+ result = {
1194
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1195
+ matches: valid ? [token] : [],
1196
+ node: token,
1197
+ syntax,
1198
+ error: valid ? '' : 'unexpected token',
1199
+ tokens
1200
+ };
1201
+ }
1202
+ // <relative-selector-list>
1203
+ // <complex-selector-list>
1204
+ else if ('relative-selector' == syntax.val) {
1205
+ if (tokens.length == 1 && token.typ == EnumToken.NestingSelectorTokenType) {
1206
+ return {
1207
+ valid: ValidationLevel.Valid,
1208
+ matches: [token],
1209
+ node: token,
1210
+ syntax,
1211
+ error: '',
1212
+ tokens
1213
+ };
1214
+ }
1215
+ result = validateSyntax(getParsedSyntax("syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */, syntax.val), token.typ == EnumToken.NestingSelectorTokenType ? tokens.slice(1) : tokens, root, options, context);
1216
+ }
1217
+ // <relative-selector-list>
1218
+ // <complex-selector-list>
1219
+ else if (['forgiving-selector-list', 'forgiving-relative-selector-list'].includes(syntax.val)) {
1220
+ // @ts-ignore
1221
+ result = { tokens: tokens.slice(), ...validateSelector(tokens, options, root) };
1222
+ }
1223
+ // https://github.com/mdn/data/pull/186#issuecomment-369604537
1224
+ else if (syntax.val.endsWith('-token')) {
1225
+ const val = syntax.val;
1226
+ valid = true;
1227
+ switch (val) {
1228
+ case 'function-token':
1229
+ valid = token.typ != EnumToken.ParensTokenType && funcLike.includes(token.typ);
1230
+ break;
1231
+ case 'ident-token':
1232
+ valid = token.typ == EnumToken.DashedIdenTokenType || token.typ == EnumToken.IdenTokenType;
1233
+ break;
1234
+ case 'hash-token':
1235
+ valid = token.typ == EnumToken.HashTokenType;
1236
+ break;
1237
+ case 'string-token':
1238
+ valid = token.typ == EnumToken.StringTokenType;
1239
+ break;
1240
+ default:
1241
+ console.error(new Error(`unhandled syntax: '<${val}>'`));
1242
+ break;
1243
+ }
1244
+ result = {
1245
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1246
+ matches: valid ? [token] : [],
1247
+ node: valid ? null : token,
1248
+ syntax,
1249
+ error: valid ? '' : 'unexpected token',
1250
+ tokens
1251
+ };
1252
+ }
1253
+ else if ('wq-name' == syntax.val) {
1254
+ valid = token.typ == EnumToken.IdenTokenType || (token.typ == EnumToken.NameSpaceAttributeTokenType &&
1255
+ (token.l == null || token.l.typ == EnumToken.IdenTokenType || (token.l.typ == EnumToken.LiteralTokenType && token.l.val == '*')) &&
1256
+ token.r.typ == EnumToken.IdenTokenType);
1257
+ result = {
1258
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1259
+ matches: valid ? [token] : [],
1260
+ node: token,
1261
+ syntax,
1262
+ error: valid ? '' : 'unexpected token',
1263
+ tokens
1264
+ };
1265
+ }
1266
+ else {
1267
+ const val = syntax.val;
1268
+ // https://github.com/mdn/data/pull/186#issuecomment-369604537
1269
+ if (val == 'any-value') {
1270
+ return {
1271
+ valid: ValidationLevel.Valid,
1272
+ matches: [token],
1273
+ node: null,
1274
+ syntax,
1275
+ error: '',
1276
+ tokens
1277
+ };
1278
+ }
1279
+ else if (val in config.declarations || val in config.syntaxes) {
1280
+ result = validateSyntax(getParsedSyntax("syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */, val) ?? getParsedSyntax("declarations" /* ValidationSyntaxGroupEnum.Declarations */, val), tokens, root, options, context);
1281
+ }
1282
+ else {
1283
+ // @ts-ignore
1284
+ result = {
1285
+ valid: ValidationLevel.Drop,
1286
+ matches: [],
1287
+ node: token,
1288
+ syntax,
1289
+ error: 'unexpected token',
1290
+ tokens
1291
+ };
1292
+ }
1293
+ }
1294
+ break;
1295
+ case ValidationTokenEnum.Parens:
1296
+ case ValidationTokenEnum.Function:
1297
+ if (syntax.typ == ValidationTokenEnum.Parens) {
1298
+ valid = token.typ == EnumToken.ParensTokenType;
1299
+ }
1300
+ else {
1301
+ valid = 'chi' in token && 'val' in token &&
1302
+ token.val.localeCompare(syntax.val, 'en', { sensitivity: 'base' }) == 0;
1303
+ }
1304
+ result = !valid ?
1305
+ // @ts-ignore
1306
+ {
1307
+ valid: ValidationLevel.Drop,
1308
+ matches: [],
1309
+ node: token,
1310
+ syntax,
1311
+ error: 'unexpected token',
1312
+ tokens
1313
+ } : validateSyntax(syntax.chi, token.chi, root, options, {
1314
+ ...context,
1315
+ tokens: null,
1316
+ level: context.level + 1
1317
+ });
1318
+ break;
1319
+ case ValidationTokenEnum.ValidationFunctionDefinition:
1320
+ valid = 'val' in token && 'chi' in token;
1321
+ result = {
1322
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1323
+ matches: valid ? [token] : [],
1324
+ node: valid ? null : token,
1325
+ syntax,
1326
+ error: '',
1327
+ tokens
1328
+ };
1329
+ if (result.valid == ValidationLevel.Valid) {
1330
+ valid = token.val.localeCompare(syntax.val, 'en', { sensitivity: 'base' }) == 0;
1331
+ result = {
1332
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1333
+ matches: valid ? [token] : [],
1334
+ node: valid ? null : token,
1335
+ error: '',
1336
+ syntax,
1337
+ tokens
1338
+ };
1339
+ if (result.valid == ValidationLevel.Valid) {
1340
+ const s = getParsedSyntax("syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */, syntax.val + '()'); // config[ValidationSyntaxGroupEnum.Syntaxes][(syntaxes as ValidationFunctionDefinitionToken).val + '()'] as ValidationSyntaxNode;
1341
+ result = validateSyntax(s, tokens, root, options, context);
1342
+ }
1343
+ }
1344
+ break;
1345
+ case ValidationTokenEnum.Bracket:
1346
+ result = validateSyntax(syntax.chi, tokens, root, options, context);
1347
+ break;
1348
+ case ValidationTokenEnum.PipeToken:
1349
+ for (const lines of syntax.chi) {
1350
+ result = validateSyntax(lines, tokens, root, options, context);
1351
+ if (result.valid == ValidationLevel.Valid) {
1352
+ break;
1353
+ }
1354
+ }
1355
+ break;
1356
+ case ValidationTokenEnum.AmpersandToken:
1357
+ children = [...syntax.l.slice(), ...syntax.r.slice()];
1358
+ matches = [];
1359
+ queue = [];
1360
+ let m = [];
1361
+ for (let j = 0; j < children.length; j++) {
1362
+ const res = validateSyntax([children[j]], tokens, root, options, context);
1363
+ // @ts-ignore
1364
+ if (res.valid == ValidationLevel.Valid) {
1365
+ m.push(...res.matches);
1366
+ matches.push(...children.splice(j, 1));
1367
+ j = 0;
1368
+ // @ts-ignore
1369
+ astNodes.delete(token);
1370
+ consumeToken(tokens);
1371
+ token = tokens[0];
1372
+ if (token == null) {
1373
+ break;
1374
+ }
1375
+ // @ts-ignore
1376
+ astNodes.add(token);
1377
+ }
1378
+ }
1379
+ if (astNodes.size > 0) {
1380
+ // @ts-ignore
1381
+ tokens.unshift(...astNodes);
1382
+ astNodes = new Set();
1383
+ }
1384
+ valid = matches.length > 0;
1385
+ result = {
1386
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1387
+ matches: m,
1388
+ node: valid ? null : token,
1389
+ syntax,
1390
+ error: valid ? '' : 'expecting token',
1391
+ tokens
1392
+ };
1393
+ break;
1394
+ case ValidationTokenEnum.ColumnToken:
1395
+ children = [...syntax.l.slice(), ...syntax.r.slice()];
1396
+ matches = [];
1397
+ queue = [];
1398
+ while ((child = children.shift())) {
1399
+ const res = validateSyntax([child], tokens, root, options, context);
1400
+ if (res.valid == ValidationLevel.Valid) {
1401
+ matches.push(child);
1402
+ consumeToken(tokens);
1403
+ token = tokens[0];
1404
+ if (queue.length > 0) {
1405
+ children.unshift(...queue);
1406
+ queue = [];
1407
+ }
1408
+ if (token == null) {
1409
+ break;
1410
+ }
1411
+ }
1412
+ else {
1413
+ queue.push(child);
1414
+ }
1415
+ }
1416
+ valid = matches.length > 0;
1417
+ result = {
1418
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1419
+ matches: valid ? [token] : [],
1420
+ node: valid ? null : token,
1421
+ syntax,
1422
+ error: valid ? '' : 'expecting token',
1423
+ tokens
1424
+ };
1425
+ break;
1426
+ case ValidationTokenEnum.StringToken:
1427
+ valid = token.typ == EnumToken.StringTokenType && syntax.val.slice(1, -1) == token.val.slice(1, -1);
1428
+ return {
1429
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1430
+ matches: valid ? [token] : [],
1431
+ node: valid ? null : token,
1432
+ syntax,
1433
+ error: valid ? '' : 'expecting token',
1434
+ tokens
1435
+ };
1436
+ case ValidationTokenEnum.PseudoClassFunctionToken:
1437
+ valid = token.typ == EnumToken.PseudoClassFuncTokenType;
1438
+ if (valid) {
1439
+ let key = token.val in config.selectors ? token.val : token.val + '()';
1440
+ const s = getParsedSyntax("syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */, key);
1441
+ valid = s != null && validateSyntax(s, token.chi, root, options, {
1442
+ ...context,
1443
+ tokens: null,
1444
+ level: context.level + 1
1445
+ }).valid == ValidationLevel.Valid;
1446
+ }
1447
+ result = {
1448
+ valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
1449
+ matches: valid ? [token] : [],
1450
+ node: valid ? null : token,
1451
+ syntax,
1452
+ error: valid ? '' : 'invalid token',
1453
+ tokens
1454
+ };
1455
+ break;
1456
+ case ValidationTokenEnum.DeclarationDefinitionToken:
1457
+ if (token.typ != EnumToken.DeclarationNodeType || token.nam != syntax.nam) {
1458
+ return {
1459
+ valid: ValidationLevel.Drop,
1460
+ matches: [],
1461
+ node: token,
1462
+ syntax,
1463
+ error: '',
1464
+ tokens
1465
+ };
1466
+ }
1467
+ return validateSyntax([syntax.val], token.val, root, options, context);
1468
+ default:
1469
+ throw new Error('not implemented: ' + JSON.stringify({ syntax, token, tokens }, null, 1));
1470
+ }
1471
+ // @ts-ignore
1472
+ return result;
1473
+ }
1474
+
1475
+ export { validateSyntax };