@tbela99/css-parser 0.8.0 → 0.9.1
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/.editorconfig +484 -0
- package/README.md +13 -8
- package/dist/index-umd-web.js +2451 -2554
- package/dist/index.cjs +2605 -2708
- package/dist/index.d.ts +73 -23
- package/dist/lib/ast/expand.js +29 -4
- package/dist/lib/ast/math/expression.js +1 -1
- package/dist/lib/ast/minify.js +31 -17
- package/dist/lib/ast/types.js +2 -0
- package/dist/lib/ast/walk.js +12 -0
- package/dist/lib/parser/declaration/map.js +59 -52
- package/dist/lib/parser/declaration/set.js +0 -12
- package/dist/lib/parser/parse.js +204 -139
- package/dist/lib/parser/tokenize.js +15 -3
- package/dist/lib/renderer/color/color.js +2 -2
- package/dist/lib/renderer/color/hex.js +1 -1
- package/dist/lib/renderer/color/hsl.js +1 -1
- package/dist/lib/renderer/color/hwb.js +2 -2
- package/dist/lib/renderer/color/lab.js +3 -2
- package/dist/lib/renderer/color/lch.js +1 -1
- package/dist/lib/renderer/color/oklab.js +2 -2
- package/dist/lib/renderer/color/oklch.js +1 -1
- package/dist/lib/renderer/color/p3.js +1 -1
- package/dist/lib/renderer/color/prophotoRgb.js +2 -2
- package/dist/lib/renderer/color/prophotorgb.js +2 -2
- package/dist/lib/renderer/color/rgb.js +1 -1
- package/dist/lib/renderer/color/srgb.js +2 -2
- package/dist/lib/renderer/color/utils/constants.js +1 -1
- package/dist/lib/renderer/color/xyz.js +2 -18
- package/dist/lib/renderer/color/xyzd50.js +20 -2
- package/dist/lib/renderer/render.js +37 -8
- package/dist/lib/renderer/sourcemap/sourcemap.js +1 -1
- package/dist/lib/syntax/syntax.js +337 -1
- package/dist/lib/validation/at-rules/container.js +353 -0
- package/dist/lib/validation/at-rules/counter-style.js +2 -2
- package/dist/lib/validation/at-rules/custom-media.js +52 -0
- package/dist/lib/validation/at-rules/document.js +40 -60
- package/dist/lib/validation/at-rules/else.js +5 -0
- package/dist/lib/validation/at-rules/font-feature-values.js +3 -0
- package/dist/lib/validation/at-rules/import.js +64 -59
- package/dist/lib/validation/at-rules/layer.js +3 -0
- package/dist/lib/validation/at-rules/media.js +118 -29
- package/dist/lib/validation/at-rules/supports.js +51 -20
- package/dist/lib/validation/at-rules/when.js +178 -0
- package/dist/lib/validation/atrule.js +25 -10
- package/dist/lib/validation/config.js +20 -15
- package/dist/lib/validation/config.json.js +242 -74
- package/dist/lib/validation/declaration.js +32 -10
- package/dist/lib/validation/parser/parse.js +87 -103
- package/dist/lib/validation/parser/types.js +2 -2
- package/dist/lib/validation/selector.js +6 -3
- package/dist/lib/validation/syntax.js +86 -6
- package/dist/lib/validation/syntaxes/complex-selector-list.js +16 -12
- package/dist/lib/validation/syntaxes/complex-selector.js +17 -247
- package/dist/lib/validation/syntaxes/compound-selector.js +226 -0
- package/dist/lib/validation/syntaxes/image.js +29 -0
- package/dist/lib/validation/syntaxes/keyframe-block-list.js +1 -1
- package/dist/lib/validation/syntaxes/keyframe-selector.js +1 -1
- package/dist/lib/validation/syntaxes/layer-name.js +5 -16
- package/dist/lib/validation/syntaxes/relative-selector-list.js +43 -13
- package/dist/lib/validation/utils/list.js +2 -2
- package/dist/node/index.js +1 -1
- package/dist/web/index.js +1 -1
- package/package.json +10 -9
|
@@ -5,7 +5,7 @@ import '../parser/parse.js';
|
|
|
5
5
|
import '../renderer/color/utils/constants.js';
|
|
6
6
|
import '../renderer/sourcemap/lib/encode.js';
|
|
7
7
|
import '../parser/utils/config.js';
|
|
8
|
-
import {
|
|
8
|
+
import { getSyntaxConfig, getParsedSyntax } from './config.js';
|
|
9
9
|
import { validateSyntax } from './syntax.js';
|
|
10
10
|
|
|
11
11
|
function validateDeclaration(declaration, options, root) {
|
|
@@ -21,6 +21,7 @@ function validateDeclaration(declaration, options, root) {
|
|
|
21
21
|
}
|
|
22
22
|
// root is at-rule - check if declaration allowed
|
|
23
23
|
if (root?.typ == EnumToken.AtRuleNodeType) {
|
|
24
|
+
//
|
|
24
25
|
const syntax = getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, '@' + root.nam)?.[0];
|
|
25
26
|
if (syntax != null) {
|
|
26
27
|
if (!('chi' in syntax)) {
|
|
@@ -39,15 +40,36 @@ function validateDeclaration(declaration, options, root) {
|
|
|
39
40
|
error: ''
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
// console.error({syntax});
|
|
44
|
+
const config = getSyntaxConfig();
|
|
45
|
+
// @ts-ignore
|
|
46
|
+
const obj = config["atRules" /* ValidationSyntaxGroupEnum.AtRules */]['@' + root.nam];
|
|
47
|
+
if ('descriptors' in obj) {
|
|
48
|
+
const descriptors = obj.descriptors;
|
|
49
|
+
if (!(name in descriptors)) {
|
|
50
|
+
return {
|
|
51
|
+
valid: ValidationLevel.Drop,
|
|
52
|
+
node: declaration,
|
|
53
|
+
syntax: `<${declaration.nam}>`,
|
|
54
|
+
error: `declaration <${declaration.nam}> is not allowed in <@${root.nam}>`
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const syntax = getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, ['@' + root.nam, 'descriptors', name]);
|
|
58
|
+
return validateSyntax(syntax, declaration.val, root, options);
|
|
49
59
|
}
|
|
50
|
-
|
|
60
|
+
// console.error({name});
|
|
61
|
+
// if (!(name in config.declarations) && !(name in config.syntaxes)) {
|
|
62
|
+
//
|
|
63
|
+
// return {
|
|
64
|
+
//
|
|
65
|
+
// valid: ValidationLevel.Drop,
|
|
66
|
+
// node: declaration,
|
|
67
|
+
// syntax: null,
|
|
68
|
+
// error: `unknown declaration "${declaration.nam}"`
|
|
69
|
+
// }
|
|
70
|
+
// }
|
|
71
|
+
//
|
|
72
|
+
// return validateSyntax((syntax as ValidationAtRuleDefinitionToken).chi as ValidationToken[], [declaration], root, options);
|
|
51
73
|
}
|
|
52
74
|
}
|
|
53
75
|
if (name.startsWith('--')) {
|
|
@@ -62,7 +84,7 @@ function validateDeclaration(declaration, options, root) {
|
|
|
62
84
|
return {
|
|
63
85
|
valid: ValidationLevel.Drop,
|
|
64
86
|
node: declaration,
|
|
65
|
-
syntax:
|
|
87
|
+
syntax: `<${declaration.nam}>`,
|
|
66
88
|
error: `unknown declaration "${declaration.nam}"`
|
|
67
89
|
};
|
|
68
90
|
}
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { ValidationTokenEnum } from './types.js';
|
|
2
2
|
import { isIdent, isPseudo } from '../../syntax/syntax.js';
|
|
3
3
|
|
|
4
|
+
var WalkValidationTokenEnum;
|
|
5
|
+
(function (WalkValidationTokenEnum) {
|
|
6
|
+
WalkValidationTokenEnum[WalkValidationTokenEnum["IgnoreChildren"] = 0] = "IgnoreChildren";
|
|
7
|
+
WalkValidationTokenEnum[WalkValidationTokenEnum["IgnoreNode"] = 1] = "IgnoreNode";
|
|
8
|
+
WalkValidationTokenEnum[WalkValidationTokenEnum["IgnoreAll"] = 2] = "IgnoreAll";
|
|
9
|
+
})(WalkValidationTokenEnum || (WalkValidationTokenEnum = {}));
|
|
10
|
+
var WalkValidationTokenKeyTypeEnum;
|
|
11
|
+
(function (WalkValidationTokenKeyTypeEnum) {
|
|
12
|
+
WalkValidationTokenKeyTypeEnum["Array"] = "array";
|
|
13
|
+
WalkValidationTokenKeyTypeEnum["Children"] = "chi";
|
|
14
|
+
WalkValidationTokenKeyTypeEnum["Left"] = "l";
|
|
15
|
+
WalkValidationTokenKeyTypeEnum["Right"] = "r";
|
|
16
|
+
WalkValidationTokenKeyTypeEnum["Prelude"] = "prelude";
|
|
17
|
+
})(WalkValidationTokenKeyTypeEnum || (WalkValidationTokenKeyTypeEnum = {}));
|
|
4
18
|
const skipped = [
|
|
5
19
|
ValidationTokenEnum.Star,
|
|
6
20
|
ValidationTokenEnum.HashMark,
|
|
@@ -167,13 +181,66 @@ function* tokenize(syntax, position = { ind: 0, lin: 1, col: 0 }, currentPositio
|
|
|
167
181
|
yield getTokenType(buffer, position, currentPosition);
|
|
168
182
|
}
|
|
169
183
|
}
|
|
184
|
+
function columnCallback(token, parent, key) {
|
|
185
|
+
if (key == WalkValidationTokenKeyTypeEnum.Prelude) {
|
|
186
|
+
return WalkValidationTokenEnum.IgnoreAll;
|
|
187
|
+
}
|
|
188
|
+
if (token.typ == ValidationTokenEnum.ColumnToken || token.typ == ValidationTokenEnum.Whitespace) {
|
|
189
|
+
return WalkValidationTokenEnum.IgnoreNode;
|
|
190
|
+
}
|
|
191
|
+
return WalkValidationTokenEnum.IgnoreChildren;
|
|
192
|
+
}
|
|
193
|
+
function toColumnArray(ast, parent) {
|
|
194
|
+
const result = new Map;
|
|
195
|
+
// @ts-ignore
|
|
196
|
+
for (const { token } of walkValidationToken(ast, null, columnCallback)) {
|
|
197
|
+
result.set(JSON.stringify(token), token);
|
|
198
|
+
}
|
|
199
|
+
const node = {
|
|
200
|
+
typ: ValidationTokenEnum.ColumnArrayToken,
|
|
201
|
+
chi: [...result.values()]
|
|
202
|
+
};
|
|
203
|
+
if (parent != null) {
|
|
204
|
+
replaceNode(parent, ast, node);
|
|
205
|
+
}
|
|
206
|
+
return node;
|
|
207
|
+
}
|
|
208
|
+
function replaceNode(parent, target, node) {
|
|
209
|
+
if ('l' in parent && parent.l == target) {
|
|
210
|
+
parent.l = node;
|
|
211
|
+
}
|
|
212
|
+
if ('r' in parent && parent.r == target) {
|
|
213
|
+
parent.r = node;
|
|
214
|
+
}
|
|
215
|
+
if ('chi' in parent) {
|
|
216
|
+
// @ts-ignore
|
|
217
|
+
for (let i = 0; i < parent.chi.length; i++) {
|
|
218
|
+
// @ts-ignore
|
|
219
|
+
if (parent.chi[i] == target) {
|
|
220
|
+
// @ts-ignore
|
|
221
|
+
parent.chi[i] = node;
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function transform(context) {
|
|
228
|
+
for (const { token, parent } of walkValidationToken(context)) {
|
|
229
|
+
switch (token.typ) {
|
|
230
|
+
case ValidationTokenEnum.ColumnToken:
|
|
231
|
+
toColumnArray(token, parent);
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return context;
|
|
236
|
+
}
|
|
170
237
|
function parseSyntax(syntax) {
|
|
171
238
|
const root = Object.defineProperty({
|
|
172
239
|
typ: ValidationTokenEnum.Root,
|
|
173
240
|
chi: []
|
|
174
241
|
}, 'pos', { ...objectProperties, value: { ind: 0, lin: 1, col: 0 } });
|
|
175
242
|
// return minify(doParseSyntax(syntaxes, tokenize(syntaxes), root)) as ValidationRootToken;
|
|
176
|
-
return minify(doParseSyntax(syntax, tokenize(syntax), root));
|
|
243
|
+
return minify(transform(doParseSyntax(syntax, tokenize(syntax), root)));
|
|
177
244
|
}
|
|
178
245
|
function matchParens(syntax, iterator) {
|
|
179
246
|
let item;
|
|
@@ -882,96 +949,6 @@ function move(position, chr) {
|
|
|
882
949
|
}
|
|
883
950
|
return position;
|
|
884
951
|
}
|
|
885
|
-
function renderSyntax(token, parent) {
|
|
886
|
-
let glue;
|
|
887
|
-
switch (token.typ) {
|
|
888
|
-
case ValidationTokenEnum.Root:
|
|
889
|
-
return token.chi.reduce((acc, curr) => acc + renderSyntax(curr), '');
|
|
890
|
-
case ValidationTokenEnum.Whitespace:
|
|
891
|
-
return ' ';
|
|
892
|
-
case ValidationTokenEnum.ValidationFunctionDefinition:
|
|
893
|
-
return '<' + token.val + '()>';
|
|
894
|
-
case ValidationTokenEnum.HashMark:
|
|
895
|
-
return '#';
|
|
896
|
-
case ValidationTokenEnum.Pipe:
|
|
897
|
-
return '|';
|
|
898
|
-
case ValidationTokenEnum.Column:
|
|
899
|
-
return '||';
|
|
900
|
-
case ValidationTokenEnum.PipeToken:
|
|
901
|
-
return token.chi.reduce((acc, curr) => acc + (acc.trim().length > 0 ? '|' : '') + curr.reduce((acc, curr) => acc + renderSyntax(curr), ''), '');
|
|
902
|
-
case ValidationTokenEnum.ColumnToken:
|
|
903
|
-
case ValidationTokenEnum.AmpersandToken:
|
|
904
|
-
glue = token.typ == ValidationTokenEnum.ColumnToken ? '||' : '&&';
|
|
905
|
-
return token.l.reduce((acc, curr) => acc + renderSyntax(curr), '') +
|
|
906
|
-
glue +
|
|
907
|
-
token.r.reduce((acc, curr) => acc + renderSyntax(curr), '');
|
|
908
|
-
case ValidationTokenEnum.Function:
|
|
909
|
-
case ValidationTokenEnum.PseudoClassFunctionToken:
|
|
910
|
-
case ValidationTokenEnum.Parens:
|
|
911
|
-
return token.val + '(' + token.chi.reduce((acc, curr) => acc + renderSyntax(curr), '') + ')' + renderAttributes(token);
|
|
912
|
-
case ValidationTokenEnum.Comma:
|
|
913
|
-
return ',';
|
|
914
|
-
case ValidationTokenEnum.Keyword:
|
|
915
|
-
return token.val + renderAttributes(token);
|
|
916
|
-
case ValidationTokenEnum.OpenBracket:
|
|
917
|
-
return '[';
|
|
918
|
-
case ValidationTokenEnum.Ampersand:
|
|
919
|
-
return '&&';
|
|
920
|
-
case ValidationTokenEnum.QuestionMark:
|
|
921
|
-
return '?';
|
|
922
|
-
case ValidationTokenEnum.Separator:
|
|
923
|
-
return '/';
|
|
924
|
-
case ValidationTokenEnum.Bracket:
|
|
925
|
-
return '[' + token.chi.reduce((acc, curr) => acc + renderSyntax(curr), '') + ']' + renderAttributes(token);
|
|
926
|
-
case ValidationTokenEnum.PropertyType:
|
|
927
|
-
return '<' + token.val + '>' + renderAttributes(token);
|
|
928
|
-
case ValidationTokenEnum.DeclarationType:
|
|
929
|
-
return "<'" + token.val + "'>" + renderAttributes(token);
|
|
930
|
-
case ValidationTokenEnum.Number:
|
|
931
|
-
case ValidationTokenEnum.PseudoClassToken:
|
|
932
|
-
case ValidationTokenEnum.StringToken:
|
|
933
|
-
return token.val + '';
|
|
934
|
-
case ValidationTokenEnum.SemiColon:
|
|
935
|
-
return ';';
|
|
936
|
-
case ValidationTokenEnum.AtRule:
|
|
937
|
-
return '@' + token.val;
|
|
938
|
-
case ValidationTokenEnum.AtRuleDefinition:
|
|
939
|
-
return '@' + token.val +
|
|
940
|
-
(token.prelude == null ? '' : ' ' + token.prelude.reduce((acc, curr) => acc + renderSyntax(curr), '')) +
|
|
941
|
-
(token.chi == null ? '' : ' {\n' + token.chi.reduce((acc, curr) => acc + renderSyntax(curr), '')).slice(1, -1) + '\n}';
|
|
942
|
-
case ValidationTokenEnum.Block:
|
|
943
|
-
return '{' + token.chi.reduce((acc, t) => acc + renderSyntax(t), '') + '}';
|
|
944
|
-
default:
|
|
945
|
-
throw new Error('Unhandled token: ' + JSON.stringify({ token }));
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
function renderAttributes(token) {
|
|
949
|
-
let result = '';
|
|
950
|
-
if (token.isList) {
|
|
951
|
-
result += '#';
|
|
952
|
-
}
|
|
953
|
-
if (token.isOptional) {
|
|
954
|
-
result += '?';
|
|
955
|
-
}
|
|
956
|
-
if (token.isRepeatableGroup) {
|
|
957
|
-
result += '!';
|
|
958
|
-
}
|
|
959
|
-
if (token.isRepeatable) {
|
|
960
|
-
result += '*';
|
|
961
|
-
}
|
|
962
|
-
if (token.atLeastOnce) {
|
|
963
|
-
result += '+';
|
|
964
|
-
}
|
|
965
|
-
if (token.occurence != null) {
|
|
966
|
-
if (token.occurence.max == 0 || token.occurence.max == token.occurence.min || Number.isNaN(token.occurence.max)) {
|
|
967
|
-
result += '{' + token.occurence.min + '}';
|
|
968
|
-
}
|
|
969
|
-
else {
|
|
970
|
-
result += '{' + token.occurence.min + ',' + token.occurence.max + '}';
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
return result;
|
|
974
|
-
}
|
|
975
952
|
function minify(ast) {
|
|
976
953
|
if (Array.isArray(ast)) {
|
|
977
954
|
// @ts-ignore
|
|
@@ -1032,37 +1009,44 @@ function minify(ast) {
|
|
|
1032
1009
|
}
|
|
1033
1010
|
return ast;
|
|
1034
1011
|
}
|
|
1035
|
-
function* walkValidationToken(token, parent, callback) {
|
|
1012
|
+
function* walkValidationToken(token, parent, callback, key) {
|
|
1036
1013
|
if (Array.isArray(token)) {
|
|
1037
1014
|
for (const child of token) {
|
|
1038
|
-
yield* walkValidationToken(child, parent);
|
|
1015
|
+
yield* walkValidationToken(child, parent, callback, WalkValidationTokenKeyTypeEnum.Array);
|
|
1039
1016
|
}
|
|
1040
1017
|
return;
|
|
1041
1018
|
}
|
|
1042
|
-
|
|
1043
|
-
if (
|
|
1019
|
+
let action = null;
|
|
1020
|
+
if (callback != null) {
|
|
1021
|
+
// @ts-ignore
|
|
1022
|
+
action = callback(token, parent, key);
|
|
1023
|
+
}
|
|
1024
|
+
if (action != WalkValidationTokenEnum.IgnoreNode && action != WalkValidationTokenEnum.IgnoreAll) {
|
|
1025
|
+
yield { token, parent };
|
|
1026
|
+
}
|
|
1027
|
+
if (action != WalkValidationTokenEnum.IgnoreChildren && action != WalkValidationTokenEnum.IgnoreAll && 'prelude' in token) {
|
|
1044
1028
|
for (const child of token.prelude) {
|
|
1045
|
-
yield* walkValidationToken(child, token);
|
|
1029
|
+
yield* walkValidationToken(child, token, callback, WalkValidationTokenKeyTypeEnum.Prelude);
|
|
1046
1030
|
}
|
|
1047
1031
|
}
|
|
1048
|
-
if ('chi' in token) {
|
|
1032
|
+
if (action != WalkValidationTokenEnum.IgnoreChildren && 'chi' in token) {
|
|
1049
1033
|
// @ts-ignore
|
|
1050
1034
|
for (const child of token.chi) {
|
|
1051
|
-
yield* walkValidationToken(child, token);
|
|
1035
|
+
yield* walkValidationToken(child, token, callback, WalkValidationTokenKeyTypeEnum.Children);
|
|
1052
1036
|
}
|
|
1053
1037
|
}
|
|
1054
|
-
if ('l' in token) {
|
|
1038
|
+
if (action != WalkValidationTokenEnum.IgnoreChildren && action != WalkValidationTokenEnum.IgnoreAll && 'l' in token) {
|
|
1055
1039
|
// @ts-ignore
|
|
1056
1040
|
for (const child of token.l) {
|
|
1057
|
-
yield* walkValidationToken(child, token);
|
|
1041
|
+
yield* walkValidationToken(child, token, callback, WalkValidationTokenKeyTypeEnum.Left);
|
|
1058
1042
|
}
|
|
1059
1043
|
}
|
|
1060
|
-
if ('r' in token) {
|
|
1044
|
+
if (action != WalkValidationTokenEnum.IgnoreChildren && action != WalkValidationTokenEnum.IgnoreAll && 'r' in token) {
|
|
1061
1045
|
// @ts-ignore
|
|
1062
1046
|
for (const child of token.r) {
|
|
1063
|
-
yield* walkValidationToken(child, token);
|
|
1047
|
+
yield* walkValidationToken(child, token, callback, WalkValidationTokenKeyTypeEnum.Right);
|
|
1064
1048
|
}
|
|
1065
1049
|
}
|
|
1066
1050
|
}
|
|
1067
1051
|
|
|
1068
|
-
export {
|
|
1052
|
+
export { WalkValidationTokenEnum, WalkValidationTokenKeyTypeEnum, parseSyntax, walkValidationToken };
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const specialValues = ['inherit', 'initial', 'unset', 'revert', 'revert-layer'];
|
|
2
1
|
var ValidationTokenEnum;
|
|
3
2
|
(function (ValidationTokenEnum) {
|
|
4
3
|
ValidationTokenEnum[ValidationTokenEnum["Root"] = 0] = "Root";
|
|
@@ -41,6 +40,7 @@ var ValidationTokenEnum;
|
|
|
41
40
|
ValidationTokenEnum[ValidationTokenEnum["DeclarationDefinitionToken"] = 37] = "DeclarationDefinitionToken";
|
|
42
41
|
ValidationTokenEnum[ValidationTokenEnum["SemiColon"] = 38] = "SemiColon";
|
|
43
42
|
ValidationTokenEnum[ValidationTokenEnum["Character"] = 39] = "Character";
|
|
43
|
+
ValidationTokenEnum[ValidationTokenEnum["ColumnArrayToken"] = 40] = "ColumnArrayToken";
|
|
44
44
|
})(ValidationTokenEnum || (ValidationTokenEnum = {}));
|
|
45
45
|
var ValidationSyntaxGroupEnum;
|
|
46
46
|
(function (ValidationSyntaxGroupEnum) {
|
|
@@ -51,4 +51,4 @@ var ValidationSyntaxGroupEnum;
|
|
|
51
51
|
ValidationSyntaxGroupEnum["AtRules"] = "atRules";
|
|
52
52
|
})(ValidationSyntaxGroupEnum || (ValidationSyntaxGroupEnum = {}));
|
|
53
53
|
|
|
54
|
-
export { ValidationSyntaxGroupEnum, ValidationTokenEnum
|
|
54
|
+
export { ValidationSyntaxGroupEnum, ValidationTokenEnum };
|
|
@@ -8,11 +8,14 @@ import '../parser/utils/config.js';
|
|
|
8
8
|
import { validateRelativeSelectorList } from './syntaxes/relative-selector-list.js';
|
|
9
9
|
import './syntaxes/complex-selector.js';
|
|
10
10
|
import { validateKeyframeBlockList } from './syntaxes/keyframe-block-list.js';
|
|
11
|
+
import './parser/types.js';
|
|
12
|
+
import './parser/parse.js';
|
|
13
|
+
import './config.js';
|
|
11
14
|
import { validateSelectorList } from './syntaxes/selector-list.js';
|
|
12
15
|
|
|
13
16
|
function validateSelector(selector, options, root) {
|
|
14
17
|
if (root == null) {
|
|
15
|
-
return
|
|
18
|
+
return validateSelectorList(selector, root, options);
|
|
16
19
|
}
|
|
17
20
|
// @ts-ignore
|
|
18
21
|
if (root.typ == EnumToken.AtRuleNodeType && root.nam.match(/^(-[a-z]+-)?keyframes$/)) {
|
|
@@ -25,14 +28,14 @@ function validateSelector(selector, options, root) {
|
|
|
25
28
|
isNested++;
|
|
26
29
|
if (isNested > 0) {
|
|
27
30
|
// @ts-ignore
|
|
28
|
-
return validateRelativeSelectorList(selector, root, { nestedSelector: true });
|
|
31
|
+
return validateRelativeSelectorList(selector, root, { ...(options ?? {}), nestedSelector: true });
|
|
29
32
|
}
|
|
30
33
|
}
|
|
31
34
|
currentRoot = currentRoot.parent;
|
|
32
35
|
}
|
|
33
36
|
const nestedSelector = isNested > 0;
|
|
34
37
|
// @ts-ignore
|
|
35
|
-
return nestedSelector ? validateRelativeSelectorList(selector, root, { nestedSelector }) : validateSelectorList(selector, root, { nestedSelector });
|
|
38
|
+
return nestedSelector ? validateRelativeSelectorList(selector, root, { ...(options ?? {}), nestedSelector }) : validateSelectorList(selector, root, { ...(options ?? {}), nestedSelector });
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
export { validateSelector };
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { ValidationTokenEnum, specialValues } from './parser/types.js';
|
|
2
|
-
import './parser/parse.js';
|
|
2
|
+
import { renderSyntax } from './parser/parse.js';
|
|
3
3
|
import { ValidationLevel, EnumToken, funcLike } from '../ast/types.js';
|
|
4
4
|
import '../ast/minify.js';
|
|
5
5
|
import '../ast/walk.js';
|
|
6
6
|
import '../parser/parse.js';
|
|
7
7
|
import { isLength } from '../syntax/syntax.js';
|
|
8
8
|
import '../parser/utils/config.js';
|
|
9
|
-
import '../renderer/
|
|
10
|
-
import '
|
|
11
|
-
import { getParsedSyntax, getSyntaxConfig } from './config.js';
|
|
9
|
+
import { renderToken } from '../renderer/render.js';
|
|
10
|
+
import { getSyntaxConfig, getParsedSyntax } from './config.js';
|
|
12
11
|
import { validateSelector } from './selector.js';
|
|
12
|
+
import './syntaxes/complex-selector.js';
|
|
13
|
+
import { validateImage } from './syntaxes/image.js';
|
|
13
14
|
|
|
14
15
|
const config = getSyntaxConfig();
|
|
15
16
|
function consumeToken(tokens) {
|
|
@@ -30,6 +31,12 @@ function splice(tokens, matches) {
|
|
|
30
31
|
return tokens;
|
|
31
32
|
}
|
|
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));
|
|
33
40
|
if (syntaxes == null) {
|
|
34
41
|
// @ts-ignore
|
|
35
42
|
return {
|
|
@@ -485,7 +492,7 @@ function validateSyntax(syntaxes, tokens, root, options, context = { level: 0 })
|
|
|
485
492
|
return result;
|
|
486
493
|
}
|
|
487
494
|
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))));
|
|
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) ?? [])));
|
|
489
496
|
}
|
|
490
497
|
function doValidateSyntax(syntax, token, tokens, root, options, context) {
|
|
491
498
|
let valid = false;
|
|
@@ -706,7 +713,21 @@ function doValidateSyntax(syntax, token, tokens, root, options, context) {
|
|
|
706
713
|
break;
|
|
707
714
|
case ValidationTokenEnum.PropertyType:
|
|
708
715
|
//
|
|
709
|
-
if (
|
|
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)) {
|
|
710
731
|
valid = token.typ == EnumToken.DeclarationNodeType;
|
|
711
732
|
result = {
|
|
712
733
|
valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
|
|
@@ -751,6 +772,18 @@ function doValidateSyntax(syntax, token, tokens, root, options, context) {
|
|
|
751
772
|
}
|
|
752
773
|
else if (syntax.val == 'group-rule-body') {
|
|
753
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
|
+
}
|
|
754
787
|
// @ts-ignore
|
|
755
788
|
result = {
|
|
756
789
|
valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
|
|
@@ -1357,6 +1390,41 @@ function doValidateSyntax(syntax, token, tokens, root, options, context) {
|
|
|
1357
1390
|
tokens
|
|
1358
1391
|
};
|
|
1359
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;
|
|
1360
1428
|
case ValidationTokenEnum.ColumnToken:
|
|
1361
1429
|
children = [...syntax.l.slice(), ...syntax.r.slice()];
|
|
1362
1430
|
matches = [];
|
|
@@ -1419,6 +1487,18 @@ function doValidateSyntax(syntax, token, tokens, root, options, context) {
|
|
|
1419
1487
|
tokens
|
|
1420
1488
|
};
|
|
1421
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);
|
|
1422
1502
|
default:
|
|
1423
1503
|
throw new Error('not implemented: ' + JSON.stringify({ syntax, token, tokens }, null, 1));
|
|
1424
1504
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ValidationLevel
|
|
1
|
+
import { ValidationLevel } from '../../ast/types.js';
|
|
2
2
|
import '../../ast/minify.js';
|
|
3
3
|
import '../../ast/walk.js';
|
|
4
4
|
import '../../parser/parse.js';
|
|
@@ -7,6 +7,7 @@ import '../../renderer/sourcemap/lib/encode.js';
|
|
|
7
7
|
import '../../parser/utils/config.js';
|
|
8
8
|
import { validateSelector } from './selector.js';
|
|
9
9
|
import { consumeWhitespace } from '../utils/whitespace.js';
|
|
10
|
+
import { splitTokenList } from '../utils/list.js';
|
|
10
11
|
|
|
11
12
|
function validateComplexSelectorList(tokens, root, options) {
|
|
12
13
|
tokens = tokens.slice();
|
|
@@ -22,20 +23,23 @@ function validateComplexSelectorList(tokens, root, options) {
|
|
|
22
23
|
tokens
|
|
23
24
|
};
|
|
24
25
|
}
|
|
25
|
-
let i = -1;
|
|
26
|
-
let j = 0;
|
|
27
26
|
let result = null;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return result;
|
|
33
|
-
}
|
|
34
|
-
j = i + 1;
|
|
35
|
-
i = j;
|
|
27
|
+
for (const t of splitTokenList(tokens)) {
|
|
28
|
+
result = validateSelector(t, root, options);
|
|
29
|
+
if (result.valid == ValidationLevel.Drop) {
|
|
30
|
+
return result;
|
|
36
31
|
}
|
|
37
32
|
}
|
|
38
|
-
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
return result ?? {
|
|
35
|
+
valid: ValidationLevel.Drop,
|
|
36
|
+
matches: [],
|
|
37
|
+
// @ts-ignore
|
|
38
|
+
node: root,
|
|
39
|
+
syntax: null,
|
|
40
|
+
error: 'expecting complex selector list',
|
|
41
|
+
tokens
|
|
42
|
+
};
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
export { validateComplexSelectorList };
|