@tbela99/css-parser 1.3.3 → 1.3.4
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.
- package/CHANGELOG.md +7 -0
- package/README.md +20 -17
- package/dist/index-umd-web.js +1031 -571
- package/dist/index.cjs +1031 -566
- package/dist/index.d.ts +247 -171
- package/dist/lib/ast/expand.js +5 -10
- package/dist/lib/ast/features/calc.js +3 -2
- package/dist/lib/ast/features/inlinecssvariables.js +5 -3
- package/dist/lib/ast/features/prefix.js +1 -1
- package/dist/lib/ast/features/shorthand.js +1 -0
- package/dist/lib/ast/features/transform.js +13 -19
- package/dist/lib/ast/minify.js +5 -2
- package/dist/lib/ast/transform/compute.js +2 -4
- package/dist/lib/ast/transform/matrix.js +20 -20
- package/dist/lib/ast/transform/minify.js +105 -12
- package/dist/lib/ast/transform/rotate.js +11 -11
- package/dist/lib/ast/transform/scale.js +6 -6
- package/dist/lib/ast/transform/skew.js +4 -4
- package/dist/lib/ast/transform/translate.js +3 -3
- package/dist/lib/ast/transform/utils.js +30 -37
- package/dist/lib/ast/types.js +14 -2
- package/dist/lib/ast/walk.js +61 -49
- package/dist/lib/fs/resolve.js +6 -3
- package/dist/lib/parser/declaration/list.js +3 -1
- package/dist/lib/parser/parse.js +345 -305
- package/dist/lib/parser/tokenize.js +11 -13
- package/dist/lib/renderer/render.js +2 -2
- package/dist/lib/syntax/syntax.js +36 -18
- package/dist/lib/validation/at-rules/container.js +11 -0
- package/dist/lib/validation/at-rules/counter-style.js +11 -0
- package/dist/lib/validation/at-rules/font-feature-values.js +11 -0
- package/dist/lib/validation/at-rules/keyframes.js +11 -0
- package/dist/lib/validation/at-rules/layer.js +11 -0
- package/dist/lib/validation/at-rules/media.js +11 -0
- package/dist/lib/validation/at-rules/page-margin-box.js +11 -0
- package/dist/lib/validation/at-rules/page.js +11 -0
- package/dist/lib/validation/at-rules/supports.js +11 -0
- package/dist/lib/validation/at-rules/when.js +11 -0
- package/dist/lib/validation/config.js +0 -2
- package/dist/lib/validation/config.json.js +21 -1
- package/dist/lib/validation/parser/parse.js +53 -2
- package/dist/lib/validation/syntax.js +199 -36
- package/dist/node.js +17 -12
- package/dist/web.js +11 -11
- package/package.json +6 -3
- package/dist/lib/validation/parser/types.js +0 -54
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { ValidationTokenEnum } from './parser/
|
|
2
|
-
import {
|
|
3
|
-
import { EnumToken, SyntaxValidationResult, ColorType } from '../ast/types.js';
|
|
1
|
+
import { ValidationTokenEnum, renderSyntax } from './parser/parse.js';
|
|
2
|
+
import { SyntaxValidationResult, EnumToken, ColorType } from '../ast/types.js';
|
|
4
3
|
import '../ast/minify.js';
|
|
5
4
|
import '../ast/walk.js';
|
|
6
5
|
import '../parser/parse.js';
|
|
7
6
|
import '../parser/tokenize.js';
|
|
8
7
|
import '../parser/utils/config.js';
|
|
9
|
-
import { wildCardFuncs, isIdentColor, mathFuncs } from '../syntax/syntax.js';
|
|
8
|
+
import { wildCardFuncs, isIdentColor, mathFuncs, isColor } from '../syntax/syntax.js';
|
|
10
9
|
import { renderToken } from '../renderer/render.js';
|
|
11
10
|
import '../renderer/sourcemap/lib/encode.js';
|
|
12
11
|
import { getSyntaxConfig, getParsedSyntax, getSyntax } from './config.js';
|
|
@@ -17,6 +16,116 @@ import '../ast/features/type.js';
|
|
|
17
16
|
const config = getSyntaxConfig();
|
|
18
17
|
// @ts-ignore
|
|
19
18
|
const allValues = getSyntaxConfig()["declarations" /* ValidationSyntaxGroupEnum.Declarations */].all.syntax.trim().split(/[\s|]+/g);
|
|
19
|
+
/**
|
|
20
|
+
* Check if a node is allowed as child in a given context
|
|
21
|
+
* @param node
|
|
22
|
+
* @param context
|
|
23
|
+
*/
|
|
24
|
+
function isNodeAllowedInContext(node, context) {
|
|
25
|
+
if (node.typ == EnumToken.CommentNodeType || context == null) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
switch (context?.typ) {
|
|
29
|
+
case EnumToken.StyleSheetNodeType:
|
|
30
|
+
case EnumToken.RuleNodeType:
|
|
31
|
+
return node.typ == EnumToken.RuleNodeType ||
|
|
32
|
+
node.typ == EnumToken.AtRuleNodeType ||
|
|
33
|
+
node.typ == EnumToken.KeyframesAtRuleNodeType ||
|
|
34
|
+
(node.typ == EnumToken.DeclarationNodeType && context.typ == EnumToken.RuleNodeType) ||
|
|
35
|
+
(node.typ == EnumToken.CDOCOMMNodeType && context.typ == EnumToken.StyleSheetNodeType);
|
|
36
|
+
case EnumToken.KeyframesAtRuleNodeType:
|
|
37
|
+
return node.typ == EnumToken.KeyFramesRuleNodeType;
|
|
38
|
+
case EnumToken.KeyFramesRuleNodeType:
|
|
39
|
+
return node.typ == EnumToken.DeclarationNodeType;
|
|
40
|
+
case EnumToken.AtRuleNodeType:
|
|
41
|
+
// @ts-ignore
|
|
42
|
+
const syntax = getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, '@' + context.nam)?.[0].chi ?? null;
|
|
43
|
+
//
|
|
44
|
+
if (syntax == null) {
|
|
45
|
+
// console.error(`syntax: Not found ${ValidationSyntaxGroupEnum.AtRules}@${(context as AstAtRule).nam}`);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
const stack = syntax.slice();
|
|
49
|
+
for (const child of stack) {
|
|
50
|
+
if (Array.isArray(child)) {
|
|
51
|
+
stack.push(...child);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if ('chi' in child && Array.isArray(child.chi)) {
|
|
55
|
+
stack.push(...child.chi);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
// @ts-ignore
|
|
59
|
+
if (child.l != null) {
|
|
60
|
+
// @ts-ignore
|
|
61
|
+
stack.push(child.l);
|
|
62
|
+
// @ts-ignore
|
|
63
|
+
if (child.r != null) {
|
|
64
|
+
// @ts-ignore
|
|
65
|
+
stack.push(...(Array.isArray(child.r) ? child.r : [child.r]));
|
|
66
|
+
}
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (node.typ == EnumToken.DeclarationNodeType) {
|
|
70
|
+
if (child.typ == ValidationTokenEnum.DeclarationDefinitionToken) {
|
|
71
|
+
if (node.nam == child.nam) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (child.typ == ValidationTokenEnum.PropertyType) {
|
|
77
|
+
if (['group-rule-body', 'block-contents', 'rule-list', 'stylesheet'].includes(child.val)) {
|
|
78
|
+
if ((node.typ == EnumToken.RuleNodeType ||
|
|
79
|
+
node.typ == EnumToken.AtRuleNodeType ||
|
|
80
|
+
node.typ == EnumToken.KeyframesAtRuleNodeType)) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
if (node.typ == EnumToken.DeclarationNodeType) {
|
|
84
|
+
let parent = node.parent;
|
|
85
|
+
while (parent != null) {
|
|
86
|
+
if (parent.parent?.typ == EnumToken.RuleNodeType) {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
parent = parent.parent;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (['declaration-list', 'feature-value-declaration'].includes(child.val) && node.typ == EnumToken.DeclarationNodeType) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
if (child.val == 'page-body' && (node.typ == EnumToken.DeclarationNodeType || (node.typ == EnumToken.AtRuleNodeType && [
|
|
97
|
+
'top-left-corner', 'top-left', 'top-center', 'top-right', 'top-right-corner',
|
|
98
|
+
'bottom-left-corner', 'bottom-left', 'bottom-center', 'bottom-right', 'bottom-right-corner',
|
|
99
|
+
'left-top', 'left-middle', 'left-bottom', 'right-top', 'right-middle', 'right-bottom'
|
|
100
|
+
].includes(node.nam)))) {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
if (child.val == 'feature-value-block-list' &&
|
|
104
|
+
(node.typ == EnumToken.AtRuleNodeType && ['stylistic', 'historical-forms', 'styleset', 'character-variant', 'swash', 'ornaments', 'annotation'].includes(node.nam))) {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
if (['feature-value-declaration-list', 'feature-value-declaration'].includes(child.val) && node.typ == EnumToken.DeclarationNodeType) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
if (child.val == 'page-body') {
|
|
111
|
+
if (node.typ == EnumToken.DeclarationNodeType) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// console.error(`isNodeAllowedInContext: Not found ${(child as ValidationPropertyToken).val}`, {
|
|
116
|
+
// child,
|
|
117
|
+
// node
|
|
118
|
+
// });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Create a syntax validation context from a list of tokens
|
|
127
|
+
* @param input
|
|
128
|
+
*/
|
|
20
129
|
function createContext(input) {
|
|
21
130
|
const values = input.slice();
|
|
22
131
|
const result = values.filter(token => token.typ != EnumToken.CommentTokenType).slice();
|
|
@@ -77,7 +186,22 @@ function createContext(input) {
|
|
|
77
186
|
}
|
|
78
187
|
};
|
|
79
188
|
}
|
|
80
|
-
|
|
189
|
+
/**
|
|
190
|
+
* Evaluate the validity of the syntax of a node
|
|
191
|
+
* @param node
|
|
192
|
+
* @param parent
|
|
193
|
+
* @param options
|
|
194
|
+
*/
|
|
195
|
+
function evaluateSyntax(node, parent, options) {
|
|
196
|
+
if (node.validSyntax) {
|
|
197
|
+
return {
|
|
198
|
+
valid: SyntaxValidationResult.Valid,
|
|
199
|
+
node,
|
|
200
|
+
syntax: null,
|
|
201
|
+
error: '',
|
|
202
|
+
context: []
|
|
203
|
+
};
|
|
204
|
+
}
|
|
81
205
|
let ast;
|
|
82
206
|
let result;
|
|
83
207
|
switch (node.typ) {
|
|
@@ -85,25 +209,34 @@ function evaluateSyntax(node, options) {
|
|
|
85
209
|
if (node.nam.startsWith('--')) {
|
|
86
210
|
break;
|
|
87
211
|
}
|
|
212
|
+
let token = null;
|
|
213
|
+
let values = node.val.slice();
|
|
88
214
|
ast = getParsedSyntax("declarations" /* ValidationSyntaxGroupEnum.Declarations */, node.nam);
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
215
|
+
while (values.length > 0) {
|
|
216
|
+
token = values.at(-1);
|
|
217
|
+
if (token.typ == EnumToken.WhitespaceTokenType || token.typ == EnumToken.CommentTokenType) {
|
|
218
|
+
values.pop();
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
if (token.typ == EnumToken.ImportantTokenType) {
|
|
95
222
|
values.pop();
|
|
96
|
-
|
|
97
|
-
else {
|
|
98
|
-
if (token.typ == EnumToken.ImportantTokenType) {
|
|
223
|
+
if (values.at(-1)?.typ == EnumToken.WhitespaceTokenType) {
|
|
99
224
|
values.pop();
|
|
100
|
-
if (values.at(-1)?.typ == EnumToken.WhitespaceTokenType) {
|
|
101
|
-
values.pop();
|
|
102
|
-
}
|
|
103
225
|
}
|
|
104
|
-
|
|
226
|
+
}
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (ast == null) {
|
|
231
|
+
if (parent?.typ == EnumToken.AtRuleNodeType) {
|
|
232
|
+
ast = (getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, ['@' + parent.nam, 'descriptors', node.nam]));
|
|
233
|
+
if (ast == null) {
|
|
234
|
+
ast = (getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, ['@' + parent.nam, 'descriptors', node.nam]) ?? getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, '@' + parent.nam))?.[0]?.chi;
|
|
235
|
+
values = [{ ...node, val: values }];
|
|
105
236
|
}
|
|
106
237
|
}
|
|
238
|
+
}
|
|
239
|
+
if (ast != null) {
|
|
107
240
|
result = doEvaluateSyntax(ast, createContext(values), { ...options, visited: new WeakMap() });
|
|
108
241
|
if (result.valid == SyntaxValidationResult.Valid && !result.context.done()) {
|
|
109
242
|
let token = null;
|
|
@@ -195,7 +328,7 @@ function doEvaluateSyntax(syntaxes, context, options) {
|
|
|
195
328
|
continue;
|
|
196
329
|
}
|
|
197
330
|
}
|
|
198
|
-
else if (options.
|
|
331
|
+
else if (options.occurrence !== false && syntax.occurence != null) {
|
|
199
332
|
result = matchOccurence(syntax, context, options);
|
|
200
333
|
}
|
|
201
334
|
else if (options.atLeastOnce !== false && syntax.atLeastOnce) {
|
|
@@ -284,7 +417,7 @@ function matchList(syntax, context, options) {
|
|
|
284
417
|
result = doEvaluateSyntax([syntax], createContext(tokens), {
|
|
285
418
|
...options,
|
|
286
419
|
isList: false,
|
|
287
|
-
|
|
420
|
+
occurrence: false
|
|
288
421
|
});
|
|
289
422
|
if (result.valid == SyntaxValidationResult.Valid) {
|
|
290
423
|
context = con.clone();
|
|
@@ -319,7 +452,7 @@ function matchOccurence(syntax, context, options) {
|
|
|
319
452
|
let counter = 0;
|
|
320
453
|
let result;
|
|
321
454
|
do {
|
|
322
|
-
result = match(syntax, context.clone(), { ...options,
|
|
455
|
+
result = match(syntax, context.clone(), { ...options, occurrence: false });
|
|
323
456
|
if (result.valid == SyntaxValidationResult.Drop) {
|
|
324
457
|
break;
|
|
325
458
|
}
|
|
@@ -370,7 +503,7 @@ function match(syntax, context, options) {
|
|
|
370
503
|
...options,
|
|
371
504
|
isRepeatable: null,
|
|
372
505
|
isList: null,
|
|
373
|
-
|
|
506
|
+
occurrence: null,
|
|
374
507
|
atLeastOnce: null
|
|
375
508
|
});
|
|
376
509
|
if (result.valid == SyntaxValidationResult.Valid) {
|
|
@@ -382,7 +515,7 @@ function match(syntax, context, options) {
|
|
|
382
515
|
case ValidationTokenEnum.Keyword:
|
|
383
516
|
success = (token.typ == EnumToken.IdenTokenType || token.typ == EnumToken.DashedIdenTokenType || isIdentColor(token)) &&
|
|
384
517
|
(token.val == syntax.val ||
|
|
385
|
-
syntax.val === token.val?.toLowerCase?.() ||
|
|
518
|
+
syntax.val.toLowerCase() === token.val?.toLowerCase?.() ||
|
|
386
519
|
// config.declarations.all
|
|
387
520
|
allValues.includes(token.val.toLowerCase()));
|
|
388
521
|
if (success) {
|
|
@@ -421,7 +554,7 @@ function match(syntax, context, options) {
|
|
|
421
554
|
...options,
|
|
422
555
|
isRepeatable: null,
|
|
423
556
|
isList: null,
|
|
424
|
-
|
|
557
|
+
occurrence: null,
|
|
425
558
|
atLeastOnce: null
|
|
426
559
|
});
|
|
427
560
|
case ValidationTokenEnum.Comma:
|
|
@@ -456,7 +589,7 @@ function match(syntax, context, options) {
|
|
|
456
589
|
...options,
|
|
457
590
|
isRepeatable: null,
|
|
458
591
|
isList: null,
|
|
459
|
-
|
|
592
|
+
occurrence: null,
|
|
460
593
|
atLeastOnce: null
|
|
461
594
|
}).valid == SyntaxValidationResult.Valid;
|
|
462
595
|
if (success) {
|
|
@@ -479,18 +612,19 @@ function match(syntax, context, options) {
|
|
|
479
612
|
}
|
|
480
613
|
function matchPropertyType(syntax, context, options) {
|
|
481
614
|
if (![
|
|
482
|
-
'
|
|
615
|
+
'color',
|
|
483
616
|
'integer',
|
|
617
|
+
'bg-position',
|
|
484
618
|
'length-percentage', 'flex', 'calc-sum', 'color',
|
|
485
619
|
'color-base', 'system-color', 'deprecated-system-color',
|
|
486
|
-
'pseudo-class-selector', 'pseudo-element-selector'
|
|
620
|
+
'pseudo-class-selector', 'pseudo-element-selector', 'feature-value-declaration'
|
|
487
621
|
].includes(syntax.val)) {
|
|
488
622
|
if (syntax.val in config["syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */]) {
|
|
489
623
|
return doEvaluateSyntax(getParsedSyntax("syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */, syntax.val), context, {
|
|
490
624
|
...options,
|
|
491
625
|
isRepeatable: null,
|
|
492
626
|
isList: null,
|
|
493
|
-
|
|
627
|
+
occurrence: null,
|
|
494
628
|
atLeastOnce: null
|
|
495
629
|
});
|
|
496
630
|
}
|
|
@@ -502,7 +636,7 @@ function matchPropertyType(syntax, context, options) {
|
|
|
502
636
|
...options,
|
|
503
637
|
isRepeatable: null,
|
|
504
638
|
isList: null,
|
|
505
|
-
|
|
639
|
+
occurrence: null,
|
|
506
640
|
atLeastOnce: null
|
|
507
641
|
});
|
|
508
642
|
if (result.valid == SyntaxValidationResult.Valid) {
|
|
@@ -607,6 +741,14 @@ function matchPropertyType(syntax, context, options) {
|
|
|
607
741
|
(token.typ == EnumToken.IdenTokenType && typeof Math[token.val.toUpperCase()] == 'number') ||
|
|
608
742
|
[EnumToken.BinaryExpressionTokenType, EnumToken.NumberTokenType, EnumToken.PercentageTokenType, EnumToken.DimensionTokenType, EnumToken.LengthTokenType, EnumToken.AngleTokenType, EnumToken.TimeTokenType, EnumToken.ResolutionTokenType, EnumToken.FrequencyTokenType].includes(token.typ);
|
|
609
743
|
break;
|
|
744
|
+
case 'declaration':
|
|
745
|
+
{
|
|
746
|
+
success = token.typ == EnumToken.DeclarationNodeType;
|
|
747
|
+
if (success) {
|
|
748
|
+
success = evaluateSyntax(token, null, options).valid == SyntaxValidationResult.Valid;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
break;
|
|
610
752
|
case 'declaration-value':
|
|
611
753
|
while (!context.done()) {
|
|
612
754
|
context.next();
|
|
@@ -633,13 +775,17 @@ function matchPropertyType(syntax, context, options) {
|
|
|
633
775
|
break;
|
|
634
776
|
case 'color':
|
|
635
777
|
case 'color-base':
|
|
636
|
-
success = token.typ == EnumToken.ColorTokenType ||
|
|
778
|
+
success = token.typ == EnumToken.ColorTokenType ||
|
|
779
|
+
(token.typ == EnumToken.IdenTokenType && 'currentcolor' === token.val.toLowerCase()) ||
|
|
780
|
+
(token.typ == EnumToken.IdenTokenType && 'transparent' === token.val.toLowerCase()) ||
|
|
781
|
+
(token.typ == EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val) ||
|
|
782
|
+
isColor(token));
|
|
637
783
|
if (!success && token.typ == EnumToken.FunctionTokenType && colorsFunc.includes(token.val)) {
|
|
638
784
|
success = doEvaluateSyntax(getParsedSyntax("functions" /* ValidationSyntaxGroupEnum.Functions */, token.val)?.[0]?.chi, createContext(token.chi), {
|
|
639
785
|
...options,
|
|
640
786
|
isRepeatable: null,
|
|
641
787
|
isList: null,
|
|
642
|
-
|
|
788
|
+
occurrence: null,
|
|
643
789
|
atLeastOnce: null
|
|
644
790
|
}).valid == SyntaxValidationResult.Valid;
|
|
645
791
|
}
|
|
@@ -647,8 +793,26 @@ function matchPropertyType(syntax, context, options) {
|
|
|
647
793
|
case 'hex-color':
|
|
648
794
|
success = (token.typ == EnumToken.ColorTokenType && token.kin == ColorType.HEX) || (token.typ == EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val));
|
|
649
795
|
break;
|
|
796
|
+
case 'feature-value-declaration':
|
|
797
|
+
{
|
|
798
|
+
let hasNumber = false;
|
|
799
|
+
success = token.typ == EnumToken.DeclarationNodeType && token.val.length > 0 && token.val.every((val) => {
|
|
800
|
+
if (val.typ == EnumToken.WhitespaceTokenType || val.typ == EnumToken.CommentTokenType) {
|
|
801
|
+
return true;
|
|
802
|
+
}
|
|
803
|
+
const success = (val.typ == EnumToken.NumberTokenType && Number.isInteger(+val.val) && val.val > 0) || (val.typ == EnumToken.FunctionTokenType && mathFuncs.includes(val.val.toLowerCase()) || (val.typ == EnumToken.FunctionTokenType && wildCardFuncs.includes(val.val)));
|
|
804
|
+
if (success) {
|
|
805
|
+
hasNumber = true;
|
|
806
|
+
}
|
|
807
|
+
if ('range' in syntax) {
|
|
808
|
+
return success && +val.val >= +syntax.range[0] && +val.val <= +syntax.range[1];
|
|
809
|
+
}
|
|
810
|
+
return success;
|
|
811
|
+
}) && hasNumber;
|
|
812
|
+
}
|
|
813
|
+
break;
|
|
650
814
|
case 'integer':
|
|
651
|
-
success = (token.typ == EnumToken.NumberTokenType && Number.isInteger(+
|
|
815
|
+
success = (token.typ == EnumToken.NumberTokenType && Number.isInteger(+token.val) && token.val > 0) || (token.typ == EnumToken.FunctionTokenType && mathFuncs.includes(token.val.toLowerCase()) || (token.typ == EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val)));
|
|
652
816
|
if ('range' in syntax) {
|
|
653
817
|
success = success && +token.val >= +syntax.range[0] && +token.val <= +syntax.range[1];
|
|
654
818
|
}
|
|
@@ -712,7 +876,7 @@ function matchPropertyType(syntax, context, options) {
|
|
|
712
876
|
...options,
|
|
713
877
|
isRepeatable: null,
|
|
714
878
|
isList: null,
|
|
715
|
-
|
|
879
|
+
occurrence: null,
|
|
716
880
|
atLeastOnce: null
|
|
717
881
|
}).valid == SyntaxValidationResult.Valid;
|
|
718
882
|
}
|
|
@@ -728,7 +892,7 @@ function matchPropertyType(syntax, context, options) {
|
|
|
728
892
|
...options,
|
|
729
893
|
isRepeatable: null,
|
|
730
894
|
isList: null,
|
|
731
|
-
|
|
895
|
+
occurrence: null,
|
|
732
896
|
atLeastOnce: null
|
|
733
897
|
}).valid == SyntaxValidationResult.Valid;
|
|
734
898
|
}
|
|
@@ -875,7 +1039,6 @@ function allOf(syntax, context, options) {
|
|
|
875
1039
|
i = -1;
|
|
876
1040
|
}
|
|
877
1041
|
}
|
|
878
|
-
// console.error()
|
|
879
1042
|
const success = syntax.length == 0;
|
|
880
1043
|
return {
|
|
881
1044
|
valid: success ? SyntaxValidationResult.Valid : SyntaxValidationResult.Drop,
|
|
@@ -902,4 +1065,4 @@ function flatten(syntax) {
|
|
|
902
1065
|
return data;
|
|
903
1066
|
}
|
|
904
1067
|
|
|
905
|
-
export { createContext, doEvaluateSyntax, evaluateSyntax };
|
|
1068
|
+
export { createContext, doEvaluateSyntax, evaluateSyntax, isNodeAllowedInContext };
|
package/dist/node.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
2
|
export { ColorType, EnumToken, ValidationLevel } from './lib/ast/types.js';
|
|
3
3
|
export { minify } from './lib/ast/minify.js';
|
|
4
|
-
export {
|
|
4
|
+
export { WalkerEvent, WalkerOptionEnum, walk, walkValues } from './lib/ast/walk.js';
|
|
5
5
|
export { expand } from './lib/ast/expand.js';
|
|
6
6
|
import { doRender } from './lib/renderer/render.js';
|
|
7
7
|
export { renderToken } from './lib/renderer/render.js';
|
|
@@ -14,42 +14,45 @@ export { convertColor } from './lib/syntax/color/color.js';
|
|
|
14
14
|
import './lib/syntax/color/utils/constants.js';
|
|
15
15
|
export { isOkLabClose, okLabDistance } from './lib/syntax/color/utils/distance.js';
|
|
16
16
|
import './lib/validation/config.js';
|
|
17
|
-
import './lib/validation/parser/types.js';
|
|
18
17
|
import './lib/validation/parser/parse.js';
|
|
19
18
|
import './lib/validation/syntaxes/complex-selector.js';
|
|
20
19
|
import './lib/validation/syntax.js';
|
|
21
20
|
import { resolve, matchUrl, dirname } from './lib/fs/resolve.js';
|
|
22
21
|
import { Readable } from 'node:stream';
|
|
23
22
|
import { createReadStream } from 'node:fs';
|
|
24
|
-
import { lstat } from 'node:fs/promises';
|
|
23
|
+
import { readFile, lstat } from 'node:fs/promises';
|
|
25
24
|
export { FeatureWalkMode } from './lib/ast/features/type.js';
|
|
26
25
|
|
|
27
26
|
/**
|
|
28
27
|
* load file or url as stream
|
|
29
28
|
* @param url
|
|
30
29
|
* @param currentFile
|
|
30
|
+
* @param asStream
|
|
31
31
|
* @throws Error file not found
|
|
32
32
|
*
|
|
33
33
|
* @private
|
|
34
34
|
*/
|
|
35
|
-
async function load(url, currentFile = '.') {
|
|
35
|
+
async function load(url, currentFile = '.', asStream = false) {
|
|
36
36
|
const resolved = resolve(url, currentFile);
|
|
37
|
-
// @ts-ignore
|
|
38
37
|
if (matchUrl.test(resolved.absolute)) {
|
|
39
|
-
return fetch(resolved.absolute).then((response) => {
|
|
38
|
+
return fetch(resolved.absolute).then(async (response) => {
|
|
40
39
|
if (!response.ok) {
|
|
41
40
|
throw new Error(`${response.status} ${response.statusText} ${response.url}`);
|
|
42
41
|
}
|
|
43
|
-
return response.body;
|
|
42
|
+
return asStream ? response.body : await response.text();
|
|
44
43
|
});
|
|
45
44
|
}
|
|
46
45
|
try {
|
|
46
|
+
if (!asStream) {
|
|
47
|
+
return readFile(resolved.absolute, 'utf-8');
|
|
48
|
+
}
|
|
47
49
|
const stats = await lstat(resolved.absolute);
|
|
48
50
|
if (stats.isFile()) {
|
|
49
|
-
return Readable.toWeb(createReadStream(resolved.absolute));
|
|
51
|
+
return Readable.toWeb(createReadStream(resolved.absolute, { encoding: 'utf-8', highWaterMark: 64 * 1024 }));
|
|
50
52
|
}
|
|
51
53
|
}
|
|
52
54
|
catch (error) {
|
|
55
|
+
console.warn(error);
|
|
53
56
|
}
|
|
54
57
|
throw new Error(`File not found: '${resolved.absolute || url}'`);
|
|
55
58
|
}
|
|
@@ -88,6 +91,7 @@ function render(data, options = {}) {
|
|
|
88
91
|
* parse css file
|
|
89
92
|
* @param file url or path
|
|
90
93
|
* @param options
|
|
94
|
+
* @param asStream load file as stream
|
|
91
95
|
*
|
|
92
96
|
* @throws Error file not found
|
|
93
97
|
*
|
|
@@ -106,8 +110,8 @@ function render(data, options = {}) {
|
|
|
106
110
|
* console.log(result.ast);
|
|
107
111
|
* ```
|
|
108
112
|
*/
|
|
109
|
-
async function parseFile(file, options = {}) {
|
|
110
|
-
return load(file).then(stream => parse(stream, { src: file, ...options }));
|
|
113
|
+
async function parseFile(file, options = {}, asStream = false) {
|
|
114
|
+
return Promise.resolve((options.load ?? load)(file, '.', asStream)).then(stream => parse(stream, { src: file, ...options }));
|
|
111
115
|
}
|
|
112
116
|
/**
|
|
113
117
|
* parse css
|
|
@@ -164,6 +168,7 @@ async function parse(stream, options = {}) {
|
|
|
164
168
|
* transform css file
|
|
165
169
|
* @param file url or path
|
|
166
170
|
* @param options
|
|
171
|
+
* @param asStream load file as stream
|
|
167
172
|
*
|
|
168
173
|
* @throws Error file not found
|
|
169
174
|
*
|
|
@@ -182,8 +187,8 @@ async function parse(stream, options = {}) {
|
|
|
182
187
|
* console.log(result.code);
|
|
183
188
|
* ```
|
|
184
189
|
*/
|
|
185
|
-
async function transformFile(file, options = {}) {
|
|
186
|
-
return load(file).then(stream => transform(stream, { src: file, ...options }));
|
|
190
|
+
async function transformFile(file, options = {}, asStream = false) {
|
|
191
|
+
return Promise.resolve((options.load ?? load)(file, '.', asStream)).then(stream => transform(stream, { src: file, ...options }));
|
|
187
192
|
}
|
|
188
193
|
/**
|
|
189
194
|
* transform css
|
package/dist/web.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { ColorType, EnumToken, ValidationLevel } from './lib/ast/types.js';
|
|
2
2
|
export { minify } from './lib/ast/minify.js';
|
|
3
|
-
export {
|
|
3
|
+
export { WalkerEvent, WalkerOptionEnum, walk, walkValues } from './lib/ast/walk.js';
|
|
4
4
|
export { expand } from './lib/ast/expand.js';
|
|
5
5
|
import { doRender } from './lib/renderer/render.js';
|
|
6
6
|
export { renderToken } from './lib/renderer/render.js';
|
|
@@ -13,7 +13,6 @@ export { convertColor } from './lib/syntax/color/color.js';
|
|
|
13
13
|
import './lib/syntax/color/utils/constants.js';
|
|
14
14
|
export { isOkLabClose, okLabDistance } from './lib/syntax/color/utils/distance.js';
|
|
15
15
|
import './lib/validation/config.js';
|
|
16
|
-
import './lib/validation/parser/types.js';
|
|
17
16
|
import './lib/validation/parser/parse.js';
|
|
18
17
|
import './lib/validation/syntaxes/complex-selector.js';
|
|
19
18
|
import './lib/validation/syntax.js';
|
|
@@ -25,9 +24,10 @@ export { FeatureWalkMode } from './lib/ast/features/type.js';
|
|
|
25
24
|
* @param url
|
|
26
25
|
* @param currentFile
|
|
27
26
|
*
|
|
27
|
+
* @param asStream
|
|
28
28
|
* @private
|
|
29
29
|
*/
|
|
30
|
-
async function load(url, currentFile = '.') {
|
|
30
|
+
async function load(url, currentFile = '.', asStream = false) {
|
|
31
31
|
let t;
|
|
32
32
|
if (matchUrl.test(url)) {
|
|
33
33
|
t = new URL(url);
|
|
@@ -37,15 +37,13 @@ async function load(url, currentFile = '.') {
|
|
|
37
37
|
}
|
|
38
38
|
else {
|
|
39
39
|
const path = resolve(url, currentFile).absolute;
|
|
40
|
-
// @ts-ignore
|
|
41
40
|
t = new URL(path, self.origin);
|
|
42
41
|
}
|
|
43
|
-
|
|
44
|
-
return fetch(t, t.origin != self.origin ? { mode: 'cors' } : {}).then((response) => {
|
|
42
|
+
return fetch(t, t.origin != self.origin ? { mode: 'cors' } : {}).then(async (response) => {
|
|
45
43
|
if (!response.ok) {
|
|
46
44
|
throw new Error(`${response.status} ${response.statusText} ${response.url}`);
|
|
47
45
|
}
|
|
48
|
-
return response.body;
|
|
46
|
+
return asStream ? response.body : await response.text();
|
|
49
47
|
});
|
|
50
48
|
}
|
|
51
49
|
/**
|
|
@@ -87,6 +85,7 @@ function render(data, options = {}) {
|
|
|
87
85
|
* parse css file
|
|
88
86
|
* @param file url or path
|
|
89
87
|
* @param options
|
|
88
|
+
* @param asStream load file as stream
|
|
90
89
|
*
|
|
91
90
|
* @throws Error file not found
|
|
92
91
|
*
|
|
@@ -105,8 +104,8 @@ function render(data, options = {}) {
|
|
|
105
104
|
* console.log(result.ast);
|
|
106
105
|
* ```
|
|
107
106
|
*/
|
|
108
|
-
async function parseFile(file, options = {}) {
|
|
109
|
-
return load(file).then(stream => parse(stream, { src: file, ...options }));
|
|
107
|
+
async function parseFile(file, options = {}, asStream = false) {
|
|
108
|
+
return Promise.resolve((options.load ?? load)(file, '.', asStream)).then(stream => parse(stream, { src: file, ...options }));
|
|
110
109
|
}
|
|
111
110
|
/**
|
|
112
111
|
* parse css
|
|
@@ -153,6 +152,7 @@ async function parse(stream, options = {}) {
|
|
|
153
152
|
* transform css file
|
|
154
153
|
* @param file url or path
|
|
155
154
|
* @param options
|
|
155
|
+
* @param asStream load file as stream
|
|
156
156
|
*
|
|
157
157
|
* Example:
|
|
158
158
|
*
|
|
@@ -169,8 +169,8 @@ async function parse(stream, options = {}) {
|
|
|
169
169
|
* console.log(result.code);
|
|
170
170
|
* ```
|
|
171
171
|
*/
|
|
172
|
-
async function transformFile(file, options = {}) {
|
|
173
|
-
return load(file).then(stream => transform(stream, { src: file, ...options }));
|
|
172
|
+
async function transformFile(file, options = {}, asStream = false) {
|
|
173
|
+
return Promise.resolve((options.load ?? load)(file, '.', asStream)).then(stream => transform(stream, { src: file, ...options }));
|
|
174
174
|
}
|
|
175
175
|
/**
|
|
176
176
|
* transform css
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tbela99/css-parser",
|
|
3
3
|
"description": "CSS parser, minifier and validator for node and the browser",
|
|
4
|
-
"version": "v1.3.
|
|
4
|
+
"version": "v1.3.4",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dist/node.js",
|
|
7
7
|
"./node": "./dist/node.js",
|
|
@@ -42,7 +42,10 @@
|
|
|
42
42
|
"css-nesting",
|
|
43
43
|
"css-compiler",
|
|
44
44
|
"nested-css",
|
|
45
|
-
"walker"
|
|
45
|
+
"walker",
|
|
46
|
+
"stream",
|
|
47
|
+
"streaming",
|
|
48
|
+
"streaming-parser"
|
|
46
49
|
],
|
|
47
50
|
"author": "Thierry Bela",
|
|
48
51
|
"license": "MIT OR LGPL-3.0",
|
|
@@ -69,7 +72,7 @@
|
|
|
69
72
|
"rollup": "^4.48.0",
|
|
70
73
|
"rollup-plugin-dts": "^6.2.1",
|
|
71
74
|
"tslib": "^2.8.1",
|
|
72
|
-
"typedoc": "^0.28.
|
|
75
|
+
"typedoc": "^0.28.13",
|
|
73
76
|
"typedoc-material-theme": "^1.4.0"
|
|
74
77
|
}
|
|
75
78
|
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
var ValidationTokenEnum;
|
|
2
|
-
(function (ValidationTokenEnum) {
|
|
3
|
-
ValidationTokenEnum[ValidationTokenEnum["Root"] = 0] = "Root";
|
|
4
|
-
ValidationTokenEnum[ValidationTokenEnum["Keyword"] = 1] = "Keyword";
|
|
5
|
-
ValidationTokenEnum[ValidationTokenEnum["PropertyType"] = 2] = "PropertyType";
|
|
6
|
-
ValidationTokenEnum[ValidationTokenEnum["DeclarationType"] = 3] = "DeclarationType";
|
|
7
|
-
ValidationTokenEnum[ValidationTokenEnum["AtRule"] = 4] = "AtRule";
|
|
8
|
-
ValidationTokenEnum[ValidationTokenEnum["ValidationFunctionDefinition"] = 5] = "ValidationFunctionDefinition";
|
|
9
|
-
ValidationTokenEnum[ValidationTokenEnum["OpenBracket"] = 6] = "OpenBracket";
|
|
10
|
-
ValidationTokenEnum[ValidationTokenEnum["CloseBracket"] = 7] = "CloseBracket";
|
|
11
|
-
ValidationTokenEnum[ValidationTokenEnum["OpenParenthesis"] = 8] = "OpenParenthesis";
|
|
12
|
-
ValidationTokenEnum[ValidationTokenEnum["CloseParenthesis"] = 9] = "CloseParenthesis";
|
|
13
|
-
ValidationTokenEnum[ValidationTokenEnum["Comma"] = 10] = "Comma";
|
|
14
|
-
ValidationTokenEnum[ValidationTokenEnum["Pipe"] = 11] = "Pipe";
|
|
15
|
-
ValidationTokenEnum[ValidationTokenEnum["Column"] = 12] = "Column";
|
|
16
|
-
ValidationTokenEnum[ValidationTokenEnum["Star"] = 13] = "Star";
|
|
17
|
-
ValidationTokenEnum[ValidationTokenEnum["OpenCurlyBrace"] = 14] = "OpenCurlyBrace";
|
|
18
|
-
ValidationTokenEnum[ValidationTokenEnum["CloseCurlyBrace"] = 15] = "CloseCurlyBrace";
|
|
19
|
-
ValidationTokenEnum[ValidationTokenEnum["HashMark"] = 16] = "HashMark";
|
|
20
|
-
ValidationTokenEnum[ValidationTokenEnum["QuestionMark"] = 17] = "QuestionMark";
|
|
21
|
-
ValidationTokenEnum[ValidationTokenEnum["Function"] = 18] = "Function";
|
|
22
|
-
ValidationTokenEnum[ValidationTokenEnum["Number"] = 19] = "Number";
|
|
23
|
-
ValidationTokenEnum[ValidationTokenEnum["Whitespace"] = 20] = "Whitespace";
|
|
24
|
-
ValidationTokenEnum[ValidationTokenEnum["Parenthesis"] = 21] = "Parenthesis";
|
|
25
|
-
ValidationTokenEnum[ValidationTokenEnum["Bracket"] = 22] = "Bracket";
|
|
26
|
-
ValidationTokenEnum[ValidationTokenEnum["Block"] = 23] = "Block";
|
|
27
|
-
ValidationTokenEnum[ValidationTokenEnum["AtLeastOnce"] = 24] = "AtLeastOnce";
|
|
28
|
-
ValidationTokenEnum[ValidationTokenEnum["Separator"] = 25] = "Separator";
|
|
29
|
-
ValidationTokenEnum[ValidationTokenEnum["Exclamation"] = 26] = "Exclamation";
|
|
30
|
-
ValidationTokenEnum[ValidationTokenEnum["Ampersand"] = 27] = "Ampersand";
|
|
31
|
-
ValidationTokenEnum[ValidationTokenEnum["PipeToken"] = 28] = "PipeToken";
|
|
32
|
-
ValidationTokenEnum[ValidationTokenEnum["ColumnToken"] = 29] = "ColumnToken";
|
|
33
|
-
ValidationTokenEnum[ValidationTokenEnum["AmpersandToken"] = 30] = "AmpersandToken";
|
|
34
|
-
ValidationTokenEnum[ValidationTokenEnum["Parens"] = 31] = "Parens";
|
|
35
|
-
ValidationTokenEnum[ValidationTokenEnum["PseudoClassToken"] = 32] = "PseudoClassToken";
|
|
36
|
-
ValidationTokenEnum[ValidationTokenEnum["PseudoClassFunctionToken"] = 33] = "PseudoClassFunctionToken";
|
|
37
|
-
ValidationTokenEnum[ValidationTokenEnum["StringToken"] = 34] = "StringToken";
|
|
38
|
-
ValidationTokenEnum[ValidationTokenEnum["AtRuleDefinition"] = 35] = "AtRuleDefinition";
|
|
39
|
-
ValidationTokenEnum[ValidationTokenEnum["DeclarationNameToken"] = 36] = "DeclarationNameToken";
|
|
40
|
-
ValidationTokenEnum[ValidationTokenEnum["DeclarationDefinitionToken"] = 37] = "DeclarationDefinitionToken";
|
|
41
|
-
ValidationTokenEnum[ValidationTokenEnum["SemiColon"] = 38] = "SemiColon";
|
|
42
|
-
ValidationTokenEnum[ValidationTokenEnum["Character"] = 39] = "Character";
|
|
43
|
-
ValidationTokenEnum[ValidationTokenEnum["InfinityToken"] = 40] = "InfinityToken";
|
|
44
|
-
})(ValidationTokenEnum || (ValidationTokenEnum = {}));
|
|
45
|
-
var ValidationSyntaxGroupEnum;
|
|
46
|
-
(function (ValidationSyntaxGroupEnum) {
|
|
47
|
-
ValidationSyntaxGroupEnum["Declarations"] = "declarations";
|
|
48
|
-
ValidationSyntaxGroupEnum["Functions"] = "functions";
|
|
49
|
-
ValidationSyntaxGroupEnum["Syntaxes"] = "syntaxes";
|
|
50
|
-
ValidationSyntaxGroupEnum["Selectors"] = "selectors";
|
|
51
|
-
ValidationSyntaxGroupEnum["AtRules"] = "atRules";
|
|
52
|
-
})(ValidationSyntaxGroupEnum || (ValidationSyntaxGroupEnum = {}));
|
|
53
|
-
|
|
54
|
-
export { ValidationSyntaxGroupEnum, ValidationTokenEnum };
|