@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
|
@@ -15,7 +15,7 @@ function validateAtRuleCounterStyle(atRule, options, root) {
|
|
|
15
15
|
matches: [],
|
|
16
16
|
node: atRule,
|
|
17
17
|
syntax: '@counter-style',
|
|
18
|
-
error: 'expected
|
|
18
|
+
error: 'expected counter style name',
|
|
19
19
|
tokens: []
|
|
20
20
|
};
|
|
21
21
|
}
|
|
@@ -23,7 +23,7 @@ function validateAtRuleCounterStyle(atRule, options, root) {
|
|
|
23
23
|
if (tokens.length == 0) {
|
|
24
24
|
// @ts-ignore
|
|
25
25
|
return {
|
|
26
|
-
valid: ValidationLevel.
|
|
26
|
+
valid: ValidationLevel.Drop,
|
|
27
27
|
matches: [],
|
|
28
28
|
node: atRule,
|
|
29
29
|
syntax: '@counter-style',
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ValidationLevel, EnumToken } from '../../ast/types.js';
|
|
2
|
+
import '../../ast/minify.js';
|
|
3
|
+
import '../../ast/walk.js';
|
|
4
|
+
import '../../parser/parse.js';
|
|
5
|
+
import '../../renderer/color/utils/constants.js';
|
|
6
|
+
import '../../renderer/sourcemap/lib/encode.js';
|
|
7
|
+
import '../../parser/utils/config.js';
|
|
8
|
+
import { consumeWhitespace } from '../utils/whitespace.js';
|
|
9
|
+
import { validateAtRuleMediaQueryList } from './media.js';
|
|
10
|
+
|
|
11
|
+
function validateAtRuleCustomMedia(atRule, options, root) {
|
|
12
|
+
// media-query-list
|
|
13
|
+
if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
return {
|
|
16
|
+
valid: ValidationLevel.Valid,
|
|
17
|
+
matches: [],
|
|
18
|
+
node: null,
|
|
19
|
+
syntax: null,
|
|
20
|
+
error: '',
|
|
21
|
+
tokens: []
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const queries = atRule.tokens.slice();
|
|
25
|
+
consumeWhitespace(queries);
|
|
26
|
+
if (queries.length == 0 || queries[0].typ != EnumToken.DashedIdenTokenType) {
|
|
27
|
+
return {
|
|
28
|
+
valid: ValidationLevel.Drop,
|
|
29
|
+
matches: [],
|
|
30
|
+
node: atRule,
|
|
31
|
+
syntax: '@custom-media',
|
|
32
|
+
error: 'expecting dashed identifier',
|
|
33
|
+
tokens: []
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
queries.shift();
|
|
37
|
+
const result = validateAtRuleMediaQueryList(queries, atRule);
|
|
38
|
+
if (result.valid == ValidationLevel.Drop) {
|
|
39
|
+
atRule.tokens = [];
|
|
40
|
+
return {
|
|
41
|
+
valid: ValidationLevel.Valid,
|
|
42
|
+
matches: [],
|
|
43
|
+
node: atRule,
|
|
44
|
+
syntax: '@custom-media',
|
|
45
|
+
error: '',
|
|
46
|
+
tokens: []
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { validateAtRuleCustomMedia };
|
|
@@ -6,6 +6,7 @@ import '../../renderer/color/utils/constants.js';
|
|
|
6
6
|
import '../../renderer/sourcemap/lib/encode.js';
|
|
7
7
|
import '../../parser/utils/config.js';
|
|
8
8
|
import { consumeWhitespace } from '../utils/whitespace.js';
|
|
9
|
+
import { splitTokenList } from '../utils/list.js';
|
|
9
10
|
import { validateURL } from '../syntaxes/url.js';
|
|
10
11
|
|
|
11
12
|
function validateAtRuleDocument(atRule, options, root) {
|
|
@@ -34,71 +35,50 @@ function validateAtRuleDocument(atRule, options, root) {
|
|
|
34
35
|
tokens
|
|
35
36
|
};
|
|
36
37
|
}
|
|
37
|
-
|
|
38
|
+
for (const t of splitTokenList(tokens)) {
|
|
39
|
+
if (t.length != 1) {
|
|
40
|
+
return {
|
|
41
|
+
valid: ValidationLevel.Drop,
|
|
42
|
+
matches: [],
|
|
43
|
+
node: t[0] ?? atRule,
|
|
44
|
+
syntax: '@document',
|
|
45
|
+
error: 'unexpected token',
|
|
46
|
+
tokens
|
|
47
|
+
};
|
|
48
|
+
}
|
|
38
49
|
// @ts-ignore
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
while (tokens.length > 0) {
|
|
49
|
-
if (tokens[0].typ == EnumToken.CommentTokenType) {
|
|
50
|
-
tokens.shift();
|
|
51
|
-
consumeWhitespace(tokens);
|
|
50
|
+
if ((t[0].typ != EnumToken.FunctionTokenType && t[0].typ != EnumToken.UrlFunctionTokenType) || !['url', 'url-prefix', 'domain', 'media-document', 'regexp'].some((f) => f.localeCompare(t[0].val, undefined, { sensitivity: 'base' }) == 0)) {
|
|
51
|
+
return {
|
|
52
|
+
valid: ValidationLevel.Drop,
|
|
53
|
+
matches: [],
|
|
54
|
+
node: t[0] ?? atRule,
|
|
55
|
+
syntax: '@document',
|
|
56
|
+
error: 'expecting any of url-prefix(), domain(), media-document(), regexp() but found ' + t[0].val,
|
|
57
|
+
tokens
|
|
58
|
+
};
|
|
52
59
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
if (t[0].typ == EnumToken.UrlFunctionTokenType) {
|
|
61
|
+
result = validateURL(t[0]);
|
|
62
|
+
if (result.valid == ValidationLevel.Drop) {
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
57
65
|
continue;
|
|
58
66
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
const children = tokens[0].chi.slice();
|
|
72
|
-
consumeWhitespace(children);
|
|
73
|
-
if (children.length == 0) {
|
|
74
|
-
// @ts-ignore
|
|
75
|
-
return {
|
|
76
|
-
valid: ValidationLevel.Drop,
|
|
77
|
-
matches: [],
|
|
78
|
-
node: tokens[0],
|
|
79
|
-
syntax: '@document',
|
|
80
|
-
error: 'expecting string argument',
|
|
81
|
-
tokens
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
if (children[0].typ == EnumToken.StringTokenType) {
|
|
85
|
-
children.shift();
|
|
86
|
-
consumeWhitespace(children);
|
|
87
|
-
}
|
|
88
|
-
if (children.length > 0) {
|
|
89
|
-
// @ts-ignore
|
|
90
|
-
return {
|
|
91
|
-
valid: ValidationLevel.Drop,
|
|
92
|
-
matches: [],
|
|
93
|
-
node: children[0],
|
|
94
|
-
syntax: '@document',
|
|
95
|
-
error: 'unexpected token',
|
|
96
|
-
tokens
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
tokens.shift();
|
|
100
|
-
consumeWhitespace(tokens);
|
|
67
|
+
const children = t[0].chi.slice();
|
|
68
|
+
consumeWhitespace(children);
|
|
69
|
+
if (children.length != 1 || (children[0].typ != EnumToken.StringTokenType && children[0].typ != EnumToken.UrlTokenTokenType)) {
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
return {
|
|
72
|
+
valid: ValidationLevel.Drop,
|
|
73
|
+
matches: [],
|
|
74
|
+
node: tokens[0],
|
|
75
|
+
syntax: '@document',
|
|
76
|
+
error: 'expecting string argument',
|
|
77
|
+
tokens
|
|
78
|
+
};
|
|
101
79
|
}
|
|
80
|
+
tokens.shift();
|
|
81
|
+
consumeWhitespace(tokens);
|
|
102
82
|
}
|
|
103
83
|
// @ts-ignore
|
|
104
84
|
return {
|
|
@@ -7,6 +7,9 @@ import '../../renderer/sourcemap/lib/encode.js';
|
|
|
7
7
|
import '../../parser/utils/config.js';
|
|
8
8
|
import { validateFamilyName } from '../syntaxes/family-name.js';
|
|
9
9
|
import '../syntaxes/complex-selector.js';
|
|
10
|
+
import '../parser/types.js';
|
|
11
|
+
import '../parser/parse.js';
|
|
12
|
+
import '../config.js';
|
|
10
13
|
|
|
11
14
|
function validateAtRuleFontFeatureValues(atRule, options, root) {
|
|
12
15
|
if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
|
|
@@ -5,11 +5,14 @@ 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 { validateAtRuleSupports } from './supports.js';
|
|
9
8
|
import { validateAtRuleMediaQueryList } from './media.js';
|
|
10
9
|
import { consumeWhitespace } from '../utils/whitespace.js';
|
|
11
10
|
import { validateLayerName } from '../syntaxes/layer-name.js';
|
|
12
11
|
import '../syntaxes/complex-selector.js';
|
|
12
|
+
import '../parser/types.js';
|
|
13
|
+
import '../parser/parse.js';
|
|
14
|
+
import '../config.js';
|
|
15
|
+
import { validateAtRuleSupportsConditions } from './supports.js';
|
|
13
16
|
|
|
14
17
|
function validateAtRuleImport(atRule, options, root) {
|
|
15
18
|
if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
|
|
@@ -79,6 +82,9 @@ function validateAtRuleImport(atRule, options, root) {
|
|
|
79
82
|
};
|
|
80
83
|
}
|
|
81
84
|
}
|
|
85
|
+
tokens.shift();
|
|
86
|
+
// @ts-ignore
|
|
87
|
+
consumeWhitespace(tokens);
|
|
82
88
|
}
|
|
83
89
|
else {
|
|
84
90
|
// @ts-ignore
|
|
@@ -114,71 +120,70 @@ function validateAtRuleImport(atRule, options, root) {
|
|
|
114
120
|
// @ts-ignore
|
|
115
121
|
else if (tokens[0].typ == EnumToken.FunctionTokenType) {
|
|
116
122
|
// @ts-ignore
|
|
117
|
-
if ('layer'.localeCompare(tokens[0].val, undefined, { sensitivity: 'base' })
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
syntax: '@' + atRule.nam,
|
|
124
|
-
error: 'expecting layer()',
|
|
125
|
-
tokens
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
// @ts-ignore
|
|
129
|
-
const result = validateLayerName(tokens[0].chi);
|
|
130
|
-
if (result.valid == ValidationLevel.Drop) {
|
|
131
|
-
return result;
|
|
132
|
-
}
|
|
133
|
-
tokens.shift();
|
|
134
|
-
// @ts-ignore
|
|
135
|
-
if (!consumeWhitespace(tokens)) {
|
|
136
|
-
// @ts-ignore
|
|
137
|
-
return {
|
|
138
|
-
valid: ValidationLevel.Drop,
|
|
139
|
-
matches: [],
|
|
140
|
-
node: tokens[0],
|
|
141
|
-
syntax: '@' + atRule.nam,
|
|
142
|
-
error: 'expecting whitespace',
|
|
143
|
-
tokens
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
if (tokens.length > 0) {
|
|
149
|
-
// @ts-ignore
|
|
150
|
-
if (tokens[0].typ == EnumToken.AtRuleTokenType) {
|
|
151
|
-
if (tokens[0].nam != 'supports') {
|
|
123
|
+
if ('layer'.localeCompare(tokens[0].val, undefined, { sensitivity: 'base' }) == 0) {
|
|
124
|
+
const result = validateLayerName(tokens[0].chi);
|
|
125
|
+
if (result.valid == ValidationLevel.Drop) {
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
tokens.shift();
|
|
152
129
|
// @ts-ignore
|
|
153
|
-
|
|
154
|
-
valid: ValidationLevel.Drop,
|
|
155
|
-
matches: [],
|
|
156
|
-
node: tokens[0],
|
|
157
|
-
syntax: '@' + atRule.nam,
|
|
158
|
-
error: 'expecting @supports or media query list',
|
|
159
|
-
tokens
|
|
160
|
-
};
|
|
130
|
+
consumeWhitespace(tokens);
|
|
161
131
|
}
|
|
162
132
|
// @ts-ignore
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
if (!consumeWhitespace(tokens)) {
|
|
133
|
+
if ('supports'.localeCompare(tokens[0]?.val, undefined, { sensitivity: 'base' }) == 0) {
|
|
134
|
+
const result = validateAtRuleSupportsConditions(atRule, tokens[0].chi);
|
|
135
|
+
if (result.valid == ValidationLevel.Drop) {
|
|
136
|
+
return result;
|
|
137
|
+
}
|
|
138
|
+
tokens.shift();
|
|
170
139
|
// @ts-ignore
|
|
171
|
-
|
|
172
|
-
valid: ValidationLevel.Drop,
|
|
173
|
-
matches: [],
|
|
174
|
-
node: tokens[0],
|
|
175
|
-
syntax: '@' + atRule.nam,
|
|
176
|
-
error: 'expecting whitespace',
|
|
177
|
-
tokens
|
|
178
|
-
};
|
|
140
|
+
consumeWhitespace(tokens);
|
|
179
141
|
}
|
|
180
142
|
}
|
|
181
143
|
}
|
|
144
|
+
// if (tokens.length > 0) {
|
|
145
|
+
//
|
|
146
|
+
// // @ts-ignore
|
|
147
|
+
// if (tokens[0].typ == EnumToken.AtRuleTokenType) {
|
|
148
|
+
//
|
|
149
|
+
// if ((tokens[0] as AstAtRule).nam != 'supports') {
|
|
150
|
+
//
|
|
151
|
+
// // @ts-ignore
|
|
152
|
+
// return {
|
|
153
|
+
// valid: ValidationLevel.Drop,
|
|
154
|
+
// matches: [],
|
|
155
|
+
// node: tokens[0],
|
|
156
|
+
// syntax: '@' + atRule.nam,
|
|
157
|
+
// error: 'expecting @supports or media query list',
|
|
158
|
+
// tokens
|
|
159
|
+
// }
|
|
160
|
+
// }
|
|
161
|
+
//
|
|
162
|
+
// // @ts-ignore
|
|
163
|
+
// const result: ValidationSyntaxResult = validateAtRuleSupports(tokens[0] as AstAtRule, options, atRule);
|
|
164
|
+
//
|
|
165
|
+
// if (result.valid == ValidationLevel.Drop) {
|
|
166
|
+
//
|
|
167
|
+
// return result;
|
|
168
|
+
// }
|
|
169
|
+
//
|
|
170
|
+
// tokens.shift();
|
|
171
|
+
//
|
|
172
|
+
// // @ts-ignore
|
|
173
|
+
// if (!consumeWhitespace(tokens)) {
|
|
174
|
+
//
|
|
175
|
+
// // @ts-ignore
|
|
176
|
+
// return {
|
|
177
|
+
// valid: ValidationLevel.Drop,
|
|
178
|
+
// matches: [],
|
|
179
|
+
// node: tokens[0],
|
|
180
|
+
// syntax: '@' + atRule.nam,
|
|
181
|
+
// error: 'expecting whitespace',
|
|
182
|
+
// tokens
|
|
183
|
+
// }
|
|
184
|
+
// }
|
|
185
|
+
// }
|
|
186
|
+
// }
|
|
182
187
|
if (tokens.length > 0) {
|
|
183
188
|
return validateAtRuleMediaQueryList(tokens, atRule);
|
|
184
189
|
}
|
|
@@ -7,6 +7,9 @@ import '../../renderer/sourcemap/lib/encode.js';
|
|
|
7
7
|
import '../../parser/utils/config.js';
|
|
8
8
|
import { validateLayerName } from '../syntaxes/layer-name.js';
|
|
9
9
|
import '../syntaxes/complex-selector.js';
|
|
10
|
+
import '../parser/types.js';
|
|
11
|
+
import '../parser/parse.js';
|
|
12
|
+
import '../config.js';
|
|
10
13
|
|
|
11
14
|
function validateAtRuleLayer(atRule, options, root) {
|
|
12
15
|
// media-query-list
|
|
@@ -13,15 +13,28 @@ function validateAtRuleMedia(atRule, options, root) {
|
|
|
13
13
|
if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
|
|
14
14
|
// @ts-ignore
|
|
15
15
|
return {
|
|
16
|
-
valid: ValidationLevel.
|
|
16
|
+
valid: ValidationLevel.Valid,
|
|
17
|
+
matches: [],
|
|
18
|
+
node: null,
|
|
19
|
+
syntax: null,
|
|
20
|
+
error: '',
|
|
21
|
+
tokens: []
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
let result = null;
|
|
25
|
+
const slice = atRule.tokens.slice();
|
|
26
|
+
consumeWhitespace(slice);
|
|
27
|
+
if (slice.length == 0) {
|
|
28
|
+
return {
|
|
29
|
+
valid: ValidationLevel.Valid,
|
|
17
30
|
matches: [],
|
|
18
31
|
node: atRule,
|
|
19
32
|
syntax: '@media',
|
|
20
|
-
error: '
|
|
33
|
+
error: '',
|
|
21
34
|
tokens: []
|
|
22
35
|
};
|
|
23
36
|
}
|
|
24
|
-
|
|
37
|
+
result = validateAtRuleMediaQueryList(atRule.tokens, atRule);
|
|
25
38
|
if (result.valid == ValidationLevel.Drop) {
|
|
26
39
|
return result;
|
|
27
40
|
}
|
|
@@ -47,10 +60,20 @@ function validateAtRuleMedia(atRule, options, root) {
|
|
|
47
60
|
};
|
|
48
61
|
}
|
|
49
62
|
function validateAtRuleMediaQueryList(tokenList, atRule) {
|
|
50
|
-
|
|
63
|
+
const split = splitTokenList(tokenList);
|
|
64
|
+
const matched = [];
|
|
65
|
+
let result = null;
|
|
66
|
+
let previousToken;
|
|
67
|
+
let mediaFeatureType;
|
|
68
|
+
for (let i = 0; i < split.length; i++) {
|
|
69
|
+
const tokens = split[i].slice();
|
|
70
|
+
const match = [];
|
|
71
|
+
result = null;
|
|
72
|
+
mediaFeatureType = null;
|
|
73
|
+
previousToken = null;
|
|
51
74
|
if (tokens.length == 0) {
|
|
52
75
|
// @ts-ignore
|
|
53
|
-
|
|
76
|
+
result = {
|
|
54
77
|
valid: ValidationLevel.Drop,
|
|
55
78
|
matches: [],
|
|
56
79
|
node: tokens[0] ?? atRule,
|
|
@@ -58,26 +81,38 @@ function validateAtRuleMediaQueryList(tokenList, atRule) {
|
|
|
58
81
|
error: 'unexpected token',
|
|
59
82
|
tokens: []
|
|
60
83
|
};
|
|
84
|
+
continue;
|
|
61
85
|
}
|
|
62
|
-
let previousToken = null;
|
|
63
86
|
while (tokens.length > 0) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
tokens.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
87
|
+
previousToken = tokens[0];
|
|
88
|
+
// media-condition | media-type | custom-media
|
|
89
|
+
if (!(validateMediaCondition(tokens[0], atRule) || validateMediaFeature(tokens[0]) || validateCustomMediaCondition(tokens[0], atRule))) {
|
|
90
|
+
if (tokens[0].typ == EnumToken.ParensTokenType) {
|
|
91
|
+
result = validateAtRuleMediaQueryList(tokens[0].chi, atRule);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
result = {
|
|
95
|
+
valid: ValidationLevel.Drop,
|
|
96
|
+
matches: [],
|
|
97
|
+
node: tokens[0] ?? atRule,
|
|
98
|
+
syntax: '@media',
|
|
99
|
+
error: 'expecting media feature or media condition',
|
|
100
|
+
tokens: []
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (result.valid == ValidationLevel.Drop) {
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
result = null;
|
|
73
107
|
}
|
|
108
|
+
match.push(tokens.shift());
|
|
74
109
|
if (tokens.length == 0) {
|
|
75
110
|
break;
|
|
76
111
|
}
|
|
77
112
|
if (!consumeWhitespace(tokens)) {
|
|
78
113
|
if (previousToken?.typ != EnumToken.ParensTokenType) {
|
|
79
114
|
// @ts-ignore
|
|
80
|
-
|
|
115
|
+
result = {
|
|
81
116
|
valid: ValidationLevel.Drop,
|
|
82
117
|
matches: [],
|
|
83
118
|
node: tokens[0] ?? atRule,
|
|
@@ -85,11 +120,12 @@ function validateAtRuleMediaQueryList(tokenList, atRule) {
|
|
|
85
120
|
error: 'expected media query list',
|
|
86
121
|
tokens: []
|
|
87
122
|
};
|
|
123
|
+
break;
|
|
88
124
|
}
|
|
89
125
|
}
|
|
90
|
-
if (![EnumToken.MediaFeatureOrTokenType, EnumToken.MediaFeatureAndTokenType].includes(tokens[0].typ)) {
|
|
126
|
+
else if (![EnumToken.MediaFeatureOrTokenType, EnumToken.MediaFeatureAndTokenType].includes(tokens[0].typ)) {
|
|
91
127
|
// @ts-ignore
|
|
92
|
-
|
|
128
|
+
result = {
|
|
93
129
|
valid: ValidationLevel.Drop,
|
|
94
130
|
matches: [],
|
|
95
131
|
node: tokens[0] ?? atRule,
|
|
@@ -97,31 +133,70 @@ function validateAtRuleMediaQueryList(tokenList, atRule) {
|
|
|
97
133
|
error: 'expected and/or',
|
|
98
134
|
tokens: []
|
|
99
135
|
};
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
if (mediaFeatureType == null) {
|
|
139
|
+
mediaFeatureType = tokens[0];
|
|
100
140
|
}
|
|
101
|
-
if (
|
|
141
|
+
if (mediaFeatureType.typ != tokens[0].typ) {
|
|
102
142
|
// @ts-ignore
|
|
103
|
-
|
|
143
|
+
result = {
|
|
104
144
|
valid: ValidationLevel.Drop,
|
|
105
145
|
matches: [],
|
|
106
146
|
node: tokens[0] ?? atRule,
|
|
107
147
|
syntax: '@media',
|
|
108
|
-
error: '
|
|
148
|
+
error: 'mixing and/or not allowed at the same level',
|
|
109
149
|
tokens: []
|
|
110
150
|
};
|
|
151
|
+
break;
|
|
111
152
|
}
|
|
112
|
-
tokens.shift();
|
|
113
|
-
|
|
153
|
+
match.push({ typ: EnumToken.WhitespaceTokenType }, tokens.shift());
|
|
154
|
+
consumeWhitespace(tokens);
|
|
155
|
+
if (tokens.length == 0) {
|
|
114
156
|
// @ts-ignore
|
|
115
|
-
|
|
157
|
+
result = {
|
|
116
158
|
valid: ValidationLevel.Drop,
|
|
117
159
|
matches: [],
|
|
118
160
|
node: tokens[0] ?? atRule,
|
|
119
161
|
syntax: '@media',
|
|
120
|
-
error: 'expected
|
|
162
|
+
error: 'expected media-condition',
|
|
121
163
|
tokens: []
|
|
122
164
|
};
|
|
165
|
+
break;
|
|
123
166
|
}
|
|
167
|
+
match.push({ typ: EnumToken.WhitespaceTokenType });
|
|
124
168
|
}
|
|
169
|
+
if (result == null && match.length > 0) {
|
|
170
|
+
matched.push(match);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (result != null) {
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
if (matched.length == 0) {
|
|
177
|
+
return {
|
|
178
|
+
valid: ValidationLevel.Drop,
|
|
179
|
+
matches: [],
|
|
180
|
+
node: atRule,
|
|
181
|
+
syntax: '@media',
|
|
182
|
+
error: 'expected media query list',
|
|
183
|
+
tokens: []
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
tokenList.length = 0;
|
|
187
|
+
let hasAll = false;
|
|
188
|
+
for (let i = 0; i < matched.length; i++) {
|
|
189
|
+
if (tokenList.length > 0) {
|
|
190
|
+
tokenList.push({ typ: EnumToken.CommaTokenType });
|
|
191
|
+
}
|
|
192
|
+
if (matched[i].length == 1 && matched.length > 1 && matched[i][0].typ == EnumToken.MediaFeatureTokenType && matched[i][0].val == 'all') {
|
|
193
|
+
hasAll = true;
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
tokenList.push(...matched[i]);
|
|
197
|
+
}
|
|
198
|
+
if (hasAll && tokenList.length == 0) {
|
|
199
|
+
tokenList.push({ typ: EnumToken.MediaFeatureTokenType, val: 'all' });
|
|
125
200
|
}
|
|
126
201
|
// @ts-ignore
|
|
127
202
|
return {
|
|
@@ -133,9 +208,9 @@ function validateAtRuleMediaQueryList(tokenList, atRule) {
|
|
|
133
208
|
tokens: []
|
|
134
209
|
};
|
|
135
210
|
}
|
|
136
|
-
function
|
|
211
|
+
function validateCustomMediaCondition(token, atRule) {
|
|
137
212
|
if (token.typ == EnumToken.MediaFeatureNotTokenType) {
|
|
138
|
-
return validateMediaCondition(token.val);
|
|
213
|
+
return validateMediaCondition(token.val, atRule);
|
|
139
214
|
}
|
|
140
215
|
if (token.typ != EnumToken.ParensTokenType) {
|
|
141
216
|
return false;
|
|
@@ -144,15 +219,29 @@ function validateMediaCondition(token) {
|
|
|
144
219
|
if (chi.length != 1) {
|
|
145
220
|
return false;
|
|
146
221
|
}
|
|
222
|
+
return chi[0].typ == EnumToken.DashedIdenTokenType;
|
|
223
|
+
}
|
|
224
|
+
function validateMediaCondition(token, atRule) {
|
|
225
|
+
if (token.typ == EnumToken.MediaFeatureNotTokenType) {
|
|
226
|
+
return validateMediaCondition(token.val, atRule);
|
|
227
|
+
}
|
|
228
|
+
if (token.typ != EnumToken.ParensTokenType && !(['when', 'else', 'import'].includes(atRule.nam) && token.typ == EnumToken.FunctionTokenType && ['media', 'supports', 'selector'].includes(token.val))) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
const chi = token.chi.filter((t) => t.typ != EnumToken.CommentTokenType && t.typ != EnumToken.WhitespaceTokenType);
|
|
232
|
+
if (chi.length != 1) {
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
147
235
|
if (chi[0].typ == EnumToken.IdenTokenType) {
|
|
148
236
|
return true;
|
|
149
237
|
}
|
|
150
238
|
if (chi[0].typ == EnumToken.MediaFeatureNotTokenType) {
|
|
151
|
-
return validateMediaCondition(chi[0].val);
|
|
239
|
+
return validateMediaCondition(chi[0].val, atRule);
|
|
152
240
|
}
|
|
153
241
|
if (chi[0].typ == EnumToken.MediaQueryConditionTokenType) {
|
|
154
242
|
return chi[0].l.typ == EnumToken.IdenTokenType;
|
|
155
243
|
}
|
|
244
|
+
console.error(chi[0].parent);
|
|
156
245
|
return false;
|
|
157
246
|
}
|
|
158
247
|
function validateMediaFeature(token) {
|
|
@@ -163,4 +252,4 @@ function validateMediaFeature(token) {
|
|
|
163
252
|
return val.typ == EnumToken.MediaFeatureTokenType;
|
|
164
253
|
}
|
|
165
254
|
|
|
166
|
-
export { validateAtRuleMedia, validateAtRuleMediaQueryList };
|
|
255
|
+
export { validateAtRuleMedia, validateAtRuleMediaQueryList, validateMediaCondition, validateMediaFeature };
|