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