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