@tbela99/css-parser 1.0.0 → 1.1.1-alpha4
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 +269 -0
- package/README.md +16 -11
- package/dist/index-umd-web.js +3805 -1894
- package/dist/index.cjs +3806 -1895
- package/dist/index.d.ts +184 -57
- package/dist/lib/ast/expand.js +2 -1
- package/dist/lib/ast/features/calc.js +12 -1
- package/dist/lib/ast/features/inlinecssvariables.js +47 -24
- package/dist/lib/ast/features/prefix.js +117 -86
- package/dist/lib/ast/features/shorthand.js +29 -6
- package/dist/lib/ast/features/transform.js +10 -3
- package/dist/lib/ast/features/type.js +7 -0
- package/dist/lib/ast/math/expression.js +7 -1
- package/dist/lib/ast/math/math.js +6 -0
- package/dist/lib/ast/minify.js +165 -77
- package/dist/lib/ast/transform/compute.js +1 -0
- package/dist/lib/ast/transform/matrix.js +1 -0
- package/dist/lib/ast/types.js +26 -15
- package/dist/lib/ast/utils/utils.js +104 -0
- package/dist/lib/ast/walk.js +33 -7
- package/dist/lib/fs/resolve.js +10 -0
- package/dist/lib/parser/declaration/list.js +48 -45
- package/dist/lib/parser/declaration/map.js +1 -0
- package/dist/lib/parser/declaration/set.js +2 -1
- package/dist/lib/parser/parse.js +350 -279
- package/dist/lib/parser/tokenize.js +147 -72
- package/dist/lib/parser/utils/declaration.js +4 -3
- package/dist/lib/parser/utils/type.js +2 -1
- package/dist/lib/renderer/color/a98rgb.js +2 -1
- package/dist/lib/renderer/color/color-mix.js +10 -7
- package/dist/lib/renderer/color/color.js +171 -153
- package/dist/lib/renderer/color/hex.js +2 -1
- package/dist/lib/renderer/color/hsl.js +2 -1
- package/dist/lib/renderer/color/hwb.js +2 -1
- package/dist/lib/renderer/color/lab.js +2 -1
- package/dist/lib/renderer/color/lch.js +2 -1
- package/dist/lib/renderer/color/oklab.js +2 -1
- package/dist/lib/renderer/color/oklch.js +2 -1
- package/dist/lib/renderer/color/p3.js +2 -1
- package/dist/lib/renderer/color/rec2020.js +2 -1
- package/dist/lib/renderer/color/relativecolor.js +17 -11
- package/dist/lib/renderer/color/rgb.js +4 -3
- package/dist/lib/renderer/color/srgb.js +18 -17
- package/dist/lib/renderer/color/utils/components.js +6 -5
- package/dist/lib/renderer/color/utils/constants.js +47 -3
- package/dist/lib/renderer/color/xyz.js +2 -1
- package/dist/lib/renderer/color/xyzd50.js +2 -1
- package/dist/lib/renderer/render.js +48 -20
- package/dist/lib/syntax/syntax.js +257 -140
- package/dist/lib/validation/at-rules/container.js +75 -97
- package/dist/lib/validation/at-rules/counter-style.js +9 -8
- package/dist/lib/validation/at-rules/custom-media.js +13 -15
- package/dist/lib/validation/at-rules/document.js +22 -27
- package/dist/lib/validation/at-rules/font-feature-values.js +8 -8
- package/dist/lib/validation/at-rules/import.js +30 -81
- package/dist/lib/validation/at-rules/keyframes.js +18 -22
- package/dist/lib/validation/at-rules/layer.js +5 -5
- package/dist/lib/validation/at-rules/media.js +42 -52
- package/dist/lib/validation/at-rules/namespace.js +19 -23
- package/dist/lib/validation/at-rules/page-margin-box.js +15 -18
- package/dist/lib/validation/at-rules/page.js +8 -7
- package/dist/lib/validation/at-rules/supports.js +73 -82
- package/dist/lib/validation/at-rules/when.js +32 -36
- package/dist/lib/validation/atrule.js +15 -14
- package/dist/lib/validation/config.js +24 -1
- package/dist/lib/validation/config.json.js +611 -111
- package/dist/lib/validation/parser/parse.js +206 -212
- package/dist/lib/validation/parser/types.js +1 -1
- package/dist/lib/validation/selector.js +3 -3
- package/dist/lib/validation/syntax.js +984 -0
- package/dist/lib/validation/syntaxes/complex-selector-list.js +10 -11
- package/dist/lib/validation/syntaxes/complex-selector.js +10 -11
- package/dist/lib/validation/syntaxes/compound-selector.js +40 -50
- package/dist/lib/validation/syntaxes/family-name.js +9 -8
- package/dist/lib/validation/syntaxes/keyframe-block-list.js +4 -3
- package/dist/lib/validation/syntaxes/keyframe-selector.js +15 -18
- package/dist/lib/validation/syntaxes/layer-name.js +6 -5
- package/dist/lib/validation/syntaxes/relative-selector-list.js +7 -6
- package/dist/lib/validation/syntaxes/relative-selector.js +2 -1
- package/dist/lib/validation/syntaxes/url.js +18 -22
- package/dist/lib/validation/utils/list.js +2 -1
- package/dist/lib/validation/utils/whitespace.js +2 -1
- package/dist/node/index.js +4 -2
- package/dist/node/load.js +5 -0
- package/dist/web/index.js +4 -2
- package/dist/web/load.js +5 -0
- package/package.json +14 -13
package/dist/lib/parser/parse.js
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isColor, parseColor, isIdent, mediaTypes, isDimension, parseDimension, isPseudo, pseudoElements, isAtKeyword, isFunction, isNumber, isPercentage, isFlex, isHexColor, isHash, isIdentStart, isIdentColor, mathFuncs } from '../syntax/syntax.js';
|
|
2
2
|
import './utils/config.js';
|
|
3
|
-
import { EnumToken,
|
|
3
|
+
import { EnumToken, ValidationLevel, SyntaxValidationResult } from '../ast/types.js';
|
|
4
4
|
import { minify, definedPropertySettings, combinators } from '../ast/minify.js';
|
|
5
5
|
import { walkValues, walk, WalkerOptionEnum } from '../ast/walk.js';
|
|
6
6
|
import { expand } from '../ast/expand.js';
|
|
7
7
|
import { parseDeclarationNode } from './utils/declaration.js';
|
|
8
8
|
import { renderToken } from '../renderer/render.js';
|
|
9
|
-
import { COLORS_NAMES, systemColors, deprecatedSystemColors } from '../renderer/color/utils/constants.js';
|
|
9
|
+
import { funcLike, ColorKind, COLORS_NAMES, systemColors, deprecatedSystemColors, colorsFunc } from '../renderer/color/utils/constants.js';
|
|
10
|
+
import { buildExpression } from '../ast/math/expression.js';
|
|
10
11
|
import { tokenize } from './tokenize.js';
|
|
11
12
|
import '../validation/config.js';
|
|
12
13
|
import '../validation/parser/types.js';
|
|
13
14
|
import '../validation/parser/parse.js';
|
|
14
15
|
import { validateSelector } from '../validation/selector.js';
|
|
15
16
|
import { validateAtRule } from '../validation/atrule.js';
|
|
17
|
+
import { splitTokenList } from '../validation/utils/list.js';
|
|
16
18
|
import '../validation/syntaxes/complex-selector.js';
|
|
17
19
|
import { validateKeyframeSelector } from '../validation/syntaxes/keyframe-selector.js';
|
|
20
|
+
import { evaluateSyntax } from '../validation/syntax.js';
|
|
18
21
|
import { validateAtRuleKeyframes } from '../validation/at-rules/keyframes.js';
|
|
19
22
|
|
|
20
23
|
const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
|
|
@@ -62,10 +65,13 @@ async function doParse(iterator, options = {}) {
|
|
|
62
65
|
inlineCssVariables: false,
|
|
63
66
|
setParent: true,
|
|
64
67
|
removePrefix: false,
|
|
65
|
-
validation:
|
|
68
|
+
validation: ValidationLevel.Default,
|
|
66
69
|
lenient: true,
|
|
67
70
|
...options
|
|
68
71
|
};
|
|
72
|
+
if (typeof options.validation == 'boolean') {
|
|
73
|
+
options.validation = options.validation ? ValidationLevel.All : ValidationLevel.None;
|
|
74
|
+
}
|
|
69
75
|
if (options.expandNestingRules) {
|
|
70
76
|
options.nestingRules = false;
|
|
71
77
|
}
|
|
@@ -77,11 +83,13 @@ async function doParse(iterator, options = {}) {
|
|
|
77
83
|
const src = options.src;
|
|
78
84
|
const stack = [];
|
|
79
85
|
const stats = {
|
|
86
|
+
src: options.src ?? '',
|
|
80
87
|
bytesIn: 0,
|
|
81
88
|
importedBytesIn: 0,
|
|
82
89
|
parse: `0ms`,
|
|
83
90
|
minify: `0ms`,
|
|
84
|
-
total: `0ms
|
|
91
|
+
total: `0ms`,
|
|
92
|
+
imports: []
|
|
85
93
|
};
|
|
86
94
|
let ast = {
|
|
87
95
|
typ: EnumToken.StyleSheetNodeType,
|
|
@@ -97,16 +105,22 @@ async function doParse(iterator, options = {}) {
|
|
|
97
105
|
lin: 1,
|
|
98
106
|
col: 1
|
|
99
107
|
},
|
|
108
|
+
end: {
|
|
109
|
+
ind: 0,
|
|
110
|
+
lin: 1,
|
|
111
|
+
col: 1
|
|
112
|
+
},
|
|
100
113
|
src: ''
|
|
101
114
|
};
|
|
102
115
|
}
|
|
103
116
|
const iter = tokenize(iterator);
|
|
104
117
|
let item;
|
|
118
|
+
let node;
|
|
105
119
|
const rawTokens = [];
|
|
120
|
+
const imports = [];
|
|
106
121
|
while (item = iter.next().value) {
|
|
107
122
|
stats.bytesIn = item.bytesIn;
|
|
108
123
|
rawTokens.push(item);
|
|
109
|
-
// doParse error
|
|
110
124
|
if (item.hint != null && BadTokensTypes.includes(item.hint)) {
|
|
111
125
|
// bad token
|
|
112
126
|
continue;
|
|
@@ -114,14 +128,23 @@ async function doParse(iterator, options = {}) {
|
|
|
114
128
|
if (item.hint != EnumToken.EOFTokenType) {
|
|
115
129
|
tokens.push(item);
|
|
116
130
|
}
|
|
131
|
+
else if (ast.loc != null) {
|
|
132
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
133
|
+
stack[i].loc.end = { ...item.end };
|
|
134
|
+
}
|
|
135
|
+
ast.loc.end = item.end;
|
|
136
|
+
}
|
|
117
137
|
if (item.token == ';' || item.token == '{') {
|
|
118
|
-
|
|
138
|
+
node = parseNode(tokens, context, options, errors, src, map, rawTokens);
|
|
119
139
|
rawTokens.length = 0;
|
|
120
140
|
if (node != null) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
141
|
+
if ('chi' in node) {
|
|
142
|
+
stack.push(node);
|
|
143
|
+
context = node;
|
|
144
|
+
}
|
|
145
|
+
else if (node.typ == EnumToken.AtRuleNodeType && node.nam == 'import') {
|
|
146
|
+
imports.push(node);
|
|
147
|
+
}
|
|
125
148
|
}
|
|
126
149
|
else if (item.token == '{') {
|
|
127
150
|
let inBlock = 1;
|
|
@@ -151,23 +174,20 @@ async function doParse(iterator, options = {}) {
|
|
|
151
174
|
map = new Map;
|
|
152
175
|
}
|
|
153
176
|
else if (item.token == '}') {
|
|
154
|
-
|
|
177
|
+
parseNode(tokens, context, options, errors, src, map, rawTokens);
|
|
155
178
|
rawTokens.length = 0;
|
|
179
|
+
if (context.loc != null) {
|
|
180
|
+
context.loc.end = item.end;
|
|
181
|
+
}
|
|
156
182
|
const previousNode = stack.pop();
|
|
157
|
-
|
|
158
|
-
context = stack[stack.length - 1] ?? ast;
|
|
159
|
-
// @ts-ignore
|
|
183
|
+
context = (stack[stack.length - 1] ?? ast);
|
|
160
184
|
if (previousNode != null && previousNode.typ == EnumToken.InvalidRuleTokenType) {
|
|
161
|
-
// @ts-ignore
|
|
162
185
|
const index = context.chi.findIndex(node => node == previousNode);
|
|
163
186
|
if (index > -1) {
|
|
164
|
-
// @ts-ignore
|
|
165
187
|
context.chi.splice(index, 1);
|
|
166
188
|
}
|
|
167
189
|
}
|
|
168
|
-
// @ts-ignore
|
|
169
190
|
if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
|
|
170
|
-
// @ts-ignore
|
|
171
191
|
context.chi.pop();
|
|
172
192
|
}
|
|
173
193
|
tokens = [];
|
|
@@ -175,8 +195,17 @@ async function doParse(iterator, options = {}) {
|
|
|
175
195
|
}
|
|
176
196
|
}
|
|
177
197
|
if (tokens.length > 0) {
|
|
178
|
-
|
|
198
|
+
node = parseNode(tokens, context, options, errors, src, map, rawTokens);
|
|
179
199
|
rawTokens.length = 0;
|
|
200
|
+
if (node != null) {
|
|
201
|
+
if (node.typ == EnumToken.AtRuleNodeType && node.nam == 'import') {
|
|
202
|
+
imports.push(node);
|
|
203
|
+
}
|
|
204
|
+
else if ('chi' in node && node.typ != EnumToken.InvalidRuleTokenType) {
|
|
205
|
+
stack.push(node);
|
|
206
|
+
context = node;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
180
209
|
if (context != null && context.typ == EnumToken.InvalidRuleTokenType) {
|
|
181
210
|
// @ts-ignore
|
|
182
211
|
const index = context.chi.findIndex((node) => node == context);
|
|
@@ -185,14 +214,37 @@ async function doParse(iterator, options = {}) {
|
|
|
185
214
|
}
|
|
186
215
|
}
|
|
187
216
|
}
|
|
217
|
+
if (imports.length > 0 && options.resolveImport) {
|
|
218
|
+
await Promise.all(imports.map(async (node) => {
|
|
219
|
+
const token = node.tokens[0];
|
|
220
|
+
const url = token.typ == EnumToken.StringTokenType ? token.val.slice(1, -1) : token.val;
|
|
221
|
+
try {
|
|
222
|
+
const root = await options.load(url, options.src).then((src) => {
|
|
223
|
+
return doParse(src, Object.assign({}, options, {
|
|
224
|
+
minify: false,
|
|
225
|
+
setParent: false,
|
|
226
|
+
src: options.resolve(url, options.src).absolute
|
|
227
|
+
}));
|
|
228
|
+
});
|
|
229
|
+
stats.importedBytesIn += root.stats.bytesIn;
|
|
230
|
+
stats.imports.push(root.stats);
|
|
231
|
+
node.parent.chi.splice(node.parent.chi.indexOf(node), 1, ...root.ast.chi);
|
|
232
|
+
if (root.errors.length > 0) {
|
|
233
|
+
errors.push(...root.errors);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
// console.error(error);
|
|
238
|
+
// @ts-ignore
|
|
239
|
+
errors.push({ action: 'ignore', message: 'doParse: ' + error.message, error });
|
|
240
|
+
}
|
|
241
|
+
}));
|
|
242
|
+
}
|
|
188
243
|
while (stack.length > 0 && context != ast) {
|
|
189
244
|
const previousNode = stack.pop();
|
|
190
|
-
|
|
191
|
-
context = stack[stack.length - 1] ?? ast;
|
|
245
|
+
context = (stack[stack.length - 1] ?? ast);
|
|
192
246
|
// remove empty nodes
|
|
193
|
-
// @ts-ignore
|
|
194
247
|
if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
|
|
195
|
-
// @ts-ignore
|
|
196
248
|
context.chi.pop();
|
|
197
249
|
continue;
|
|
198
250
|
}
|
|
@@ -205,14 +257,12 @@ async function doParse(iterator, options = {}) {
|
|
|
205
257
|
if (options.visitor != null) {
|
|
206
258
|
for (const result of walk(ast)) {
|
|
207
259
|
if (result.node.typ == EnumToken.DeclarationNodeType &&
|
|
208
|
-
// @ts-ignore
|
|
209
260
|
(typeof options.visitor.Declaration == 'function' || options.visitor.Declaration?.[result.node.nam] != null)) {
|
|
210
261
|
const callable = typeof options.visitor.Declaration == 'function' ? options.visitor.Declaration : options.visitor.Declaration[result.node.nam];
|
|
211
262
|
const results = await callable(result.node);
|
|
212
263
|
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
213
264
|
continue;
|
|
214
265
|
}
|
|
215
|
-
// @ts-ignore
|
|
216
266
|
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
217
267
|
}
|
|
218
268
|
else if (options.visitor.Rule != null && result.node.typ == EnumToken.RuleNodeType) {
|
|
@@ -220,7 +270,6 @@ async function doParse(iterator, options = {}) {
|
|
|
220
270
|
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
221
271
|
continue;
|
|
222
272
|
}
|
|
223
|
-
// @ts-ignore
|
|
224
273
|
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
225
274
|
}
|
|
226
275
|
else if (options.visitor.AtRule != null &&
|
|
@@ -232,7 +281,6 @@ async function doParse(iterator, options = {}) {
|
|
|
232
281
|
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
233
282
|
continue;
|
|
234
283
|
}
|
|
235
|
-
// @ts-ignore
|
|
236
284
|
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
237
285
|
}
|
|
238
286
|
}
|
|
@@ -271,30 +319,27 @@ function getLastNode(context) {
|
|
|
271
319
|
}
|
|
272
320
|
return null;
|
|
273
321
|
}
|
|
274
|
-
|
|
322
|
+
function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
275
323
|
let tokens = [];
|
|
276
324
|
for (const t of results) {
|
|
277
325
|
const node = getTokenType(t.token, t.hint);
|
|
278
|
-
map.set(node, t.
|
|
326
|
+
map.set(node, { sta: t.sta, end: t.end, src });
|
|
279
327
|
tokens.push(node);
|
|
280
328
|
}
|
|
281
329
|
let i;
|
|
282
330
|
let loc;
|
|
283
331
|
for (i = 0; i < tokens.length; i++) {
|
|
284
332
|
if (tokens[i].typ == EnumToken.CommentTokenType || tokens[i].typ == EnumToken.CDOCOMMTokenType) {
|
|
285
|
-
const
|
|
333
|
+
const location = map.get(tokens[i]);
|
|
286
334
|
if (tokens[i].typ == EnumToken.CDOCOMMTokenType && context.typ != EnumToken.StyleSheetNodeType) {
|
|
287
335
|
errors.push({
|
|
288
336
|
action: 'drop',
|
|
289
337
|
message: `CDOCOMM not allowed here ${JSON.stringify(tokens[i], null, 1)}`,
|
|
290
|
-
location
|
|
338
|
+
location
|
|
291
339
|
});
|
|
292
340
|
continue;
|
|
293
341
|
}
|
|
294
|
-
loc =
|
|
295
|
-
sta: position,
|
|
296
|
-
src
|
|
297
|
-
};
|
|
342
|
+
loc = location;
|
|
298
343
|
// @ts-ignore
|
|
299
344
|
context.chi.push(tokens[i]);
|
|
300
345
|
if (options.sourcemap) {
|
|
@@ -313,10 +358,6 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
313
358
|
if (delim.typ == EnumToken.SemiColonTokenType || delim.typ == EnumToken.BlockStartTokenType || delim.typ == EnumToken.BlockEndTokenType) {
|
|
314
359
|
tokens.pop();
|
|
315
360
|
}
|
|
316
|
-
else {
|
|
317
|
-
delim = { typ: EnumToken.SemiColonTokenType };
|
|
318
|
-
}
|
|
319
|
-
// @ts-ignore
|
|
320
361
|
while ([EnumToken.WhitespaceTokenType, EnumToken.BadStringTokenType, EnumToken.BadCommentTokenType].includes(tokens.at(-1)?.typ)) {
|
|
321
362
|
tokens.pop();
|
|
322
363
|
}
|
|
@@ -325,11 +366,12 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
325
366
|
}
|
|
326
367
|
if (tokens[0]?.typ == EnumToken.AtRuleTokenType) {
|
|
327
368
|
const atRule = tokens.shift();
|
|
328
|
-
const
|
|
369
|
+
const location = map.get(atRule);
|
|
329
370
|
// @ts-ignore
|
|
330
371
|
while ([EnumToken.WhitespaceTokenType].includes(tokens[0]?.typ)) {
|
|
331
372
|
tokens.shift();
|
|
332
373
|
}
|
|
374
|
+
rawTokens.shift();
|
|
333
375
|
if (atRule.val == 'import') {
|
|
334
376
|
// only @charset and @layer are accepted before @import
|
|
335
377
|
// @ts-ignore
|
|
@@ -347,14 +389,14 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
347
389
|
if (!(type == EnumToken.InvalidAtRuleTokenType &&
|
|
348
390
|
// @ts-ignore
|
|
349
391
|
['charset', 'layer', 'import'].includes(context.chi[i].nam))) {
|
|
350
|
-
errors.push({ action: 'drop', message: 'invalid @import', location
|
|
392
|
+
errors.push({ action: 'drop', message: 'invalid @import', location });
|
|
351
393
|
return null;
|
|
352
394
|
}
|
|
353
395
|
}
|
|
354
396
|
// @ts-ignore
|
|
355
397
|
const name = context.chi[i].nam;
|
|
356
398
|
if (name != 'charset' && name != 'import' && name != 'layer') {
|
|
357
|
-
errors.push({ action: 'drop', message: 'invalid @import', location
|
|
399
|
+
errors.push({ action: 'drop', message: 'invalid @import', location });
|
|
358
400
|
return null;
|
|
359
401
|
}
|
|
360
402
|
break;
|
|
@@ -365,7 +407,7 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
365
407
|
errors.push({
|
|
366
408
|
action: 'drop',
|
|
367
409
|
message: 'doParse: invalid @import',
|
|
368
|
-
location
|
|
410
|
+
location
|
|
369
411
|
});
|
|
370
412
|
return null;
|
|
371
413
|
}
|
|
@@ -374,7 +416,7 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
374
416
|
errors.push({
|
|
375
417
|
action: 'drop',
|
|
376
418
|
message: 'doParse: invalid @import',
|
|
377
|
-
location
|
|
419
|
+
location
|
|
378
420
|
});
|
|
379
421
|
return null;
|
|
380
422
|
}
|
|
@@ -400,37 +442,6 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
400
442
|
}
|
|
401
443
|
}
|
|
402
444
|
}
|
|
403
|
-
// @ts-ignore
|
|
404
|
-
if (tokens[0].typ == EnumToken.StringTokenType) {
|
|
405
|
-
if (options.resolveImport) {
|
|
406
|
-
const url = tokens[0].val.slice(1, -1);
|
|
407
|
-
try {
|
|
408
|
-
// @ts-ignore
|
|
409
|
-
const root = await options.load(url, options.src).then((src) => {
|
|
410
|
-
return doParse(src, Object.assign({}, options, {
|
|
411
|
-
minify: false,
|
|
412
|
-
setParent: false,
|
|
413
|
-
// @ts-ignore
|
|
414
|
-
src: options.resolve(url, options.src).absolute
|
|
415
|
-
}));
|
|
416
|
-
});
|
|
417
|
-
stats.importedBytesIn += root.stats.bytesIn;
|
|
418
|
-
if (root.ast.chi.length > 0) {
|
|
419
|
-
// @todo - filter charset, layer and scope
|
|
420
|
-
// @ts-ignore
|
|
421
|
-
context.chi.push(...root.ast.chi);
|
|
422
|
-
}
|
|
423
|
-
if (root.errors.length > 0) {
|
|
424
|
-
errors.push(...root.errors);
|
|
425
|
-
}
|
|
426
|
-
return null;
|
|
427
|
-
}
|
|
428
|
-
catch (error) {
|
|
429
|
-
// @ts-ignore
|
|
430
|
-
errors.push({ action: 'ignore', message: 'doParse: ' + error.message, error });
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
445
|
}
|
|
435
446
|
// https://www.w3.org/TR/css-nesting-1/#conditionals
|
|
436
447
|
// allowed nesting at-rules
|
|
@@ -438,7 +449,7 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
438
449
|
if (atRule.val == 'charset') {
|
|
439
450
|
let spaces = 0;
|
|
440
451
|
// https://developer.mozilla.org/en-US/docs/Web/CSS/@charset
|
|
441
|
-
for (let k =
|
|
452
|
+
for (let k = 0; k < rawTokens.length; k++) {
|
|
442
453
|
if (rawTokens[k].hint == EnumToken.WhitespaceTokenType) {
|
|
443
454
|
spaces += rawTokens[k].len;
|
|
444
455
|
continue;
|
|
@@ -454,7 +465,7 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
454
465
|
action: 'drop',
|
|
455
466
|
message: '@charset must have only one space',
|
|
456
467
|
// @ts-ignore
|
|
457
|
-
location
|
|
468
|
+
location
|
|
458
469
|
});
|
|
459
470
|
return null;
|
|
460
471
|
}
|
|
@@ -462,8 +473,7 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
462
473
|
errors.push({
|
|
463
474
|
action: 'drop',
|
|
464
475
|
message: '@charset expects a "<charset>"',
|
|
465
|
-
|
|
466
|
-
location: { src, ...(map.get(atRule) ?? position) }
|
|
476
|
+
location
|
|
467
477
|
});
|
|
468
478
|
return null;
|
|
469
479
|
}
|
|
@@ -483,94 +493,77 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
483
493
|
const node = {
|
|
484
494
|
typ: /^(-[a-z]+-)?keyframes$/.test(nam) ? EnumToken.KeyframeAtRuleNodeType : EnumToken.AtRuleNodeType,
|
|
485
495
|
nam,
|
|
486
|
-
// tokens: t,
|
|
487
496
|
val: raw.join('')
|
|
488
497
|
};
|
|
489
498
|
Object.defineProperties(node, {
|
|
490
|
-
tokens: { ...definedPropertySettings, enumerable: false, value:
|
|
499
|
+
tokens: { ...definedPropertySettings, enumerable: false, value: t.slice() },
|
|
491
500
|
raw: { ...definedPropertySettings, value: raw }
|
|
492
501
|
});
|
|
493
502
|
if (delim.typ == EnumToken.BlockStartTokenType) {
|
|
494
503
|
node.chi = [];
|
|
495
504
|
}
|
|
496
|
-
loc =
|
|
497
|
-
sta: position,
|
|
498
|
-
src
|
|
499
|
-
};
|
|
505
|
+
loc = map.get(atRule);
|
|
500
506
|
if (options.sourcemap) {
|
|
501
507
|
node.loc = loc;
|
|
508
|
+
node.loc.end = { ...map.get(delim).end };
|
|
502
509
|
}
|
|
503
|
-
if (options.validation) {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
else {
|
|
513
|
-
isValid = false;
|
|
510
|
+
// if (options.validation) {
|
|
511
|
+
let isValid = true;
|
|
512
|
+
if (node.nam == 'else') {
|
|
513
|
+
const prev = getLastNode(context);
|
|
514
|
+
if (prev != null && prev.typ == EnumToken.AtRuleNodeType && ['when', 'else'].includes(prev.nam)) {
|
|
515
|
+
if (prev.nam == 'else') {
|
|
516
|
+
isValid = Array.isArray(prev.tokens) && prev.tokens.length > 0;
|
|
514
517
|
}
|
|
515
518
|
}
|
|
516
|
-
const valid = isValid ? (node.typ == EnumToken.KeyframeAtRuleNodeType ? validateAtRuleKeyframes(node) : validateAtRule(node, options, context)) : {
|
|
517
|
-
valid: ValidationLevel.Drop,
|
|
518
|
-
node,
|
|
519
|
-
syntax: '@' + node.nam,
|
|
520
|
-
error: '@' + node.nam + ' not allowed here'};
|
|
521
|
-
if (valid.valid == ValidationLevel.Drop) {
|
|
522
|
-
errors.push({
|
|
523
|
-
action: 'drop',
|
|
524
|
-
message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
|
|
525
|
-
// @ts-ignore
|
|
526
|
-
location: { src, ...(map.get(valid.node) ?? position) }
|
|
527
|
-
});
|
|
528
|
-
// @ts-ignore
|
|
529
|
-
node.typ = EnumToken.InvalidAtRuleTokenType;
|
|
530
|
-
}
|
|
531
519
|
else {
|
|
532
|
-
|
|
533
|
-
minify: false,
|
|
534
|
-
removeComments: true
|
|
535
|
-
}), '');
|
|
520
|
+
isValid = false;
|
|
536
521
|
}
|
|
537
522
|
}
|
|
538
523
|
// @ts-ignore
|
|
524
|
+
const valid = options.validation == ValidationLevel.None ? {
|
|
525
|
+
valid: SyntaxValidationResult.Valid,
|
|
526
|
+
error: '',
|
|
527
|
+
node,
|
|
528
|
+
syntax: '@' + node.nam
|
|
529
|
+
} : isValid ? (node.typ == EnumToken.KeyframeAtRuleNodeType ? validateAtRuleKeyframes(node) : validateAtRule(node, options, context)) : {
|
|
530
|
+
valid: SyntaxValidationResult.Drop,
|
|
531
|
+
node,
|
|
532
|
+
syntax: '@' + node.nam,
|
|
533
|
+
error: '@' + node.nam + ' not allowed here'};
|
|
534
|
+
if (valid.valid == SyntaxValidationResult.Drop) {
|
|
535
|
+
errors.push({
|
|
536
|
+
action: 'drop',
|
|
537
|
+
message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
|
|
538
|
+
// @ts-ignore
|
|
539
|
+
location: { src, ...(map.get(valid.node) ?? location) }
|
|
540
|
+
});
|
|
541
|
+
// @ts-ignore
|
|
542
|
+
node.typ = EnumToken.InvalidAtRuleTokenType;
|
|
543
|
+
}
|
|
544
|
+
else {
|
|
545
|
+
node.val = node.tokens.reduce((acc, curr) => acc + renderToken(curr, {
|
|
546
|
+
minify: false,
|
|
547
|
+
removeComments: true
|
|
548
|
+
}), '');
|
|
549
|
+
}
|
|
539
550
|
context.chi.push(node);
|
|
540
|
-
Object.
|
|
541
|
-
|
|
551
|
+
Object.defineProperties(node, {
|
|
552
|
+
parent: { ...definedPropertySettings, value: context },
|
|
553
|
+
validSyntax: { ...definedPropertySettings, value: valid.valid == SyntaxValidationResult.Valid }
|
|
554
|
+
});
|
|
555
|
+
return node;
|
|
542
556
|
}
|
|
543
557
|
else {
|
|
544
558
|
// rule
|
|
545
559
|
if (delim.typ == EnumToken.BlockStartTokenType) {
|
|
546
|
-
const
|
|
560
|
+
const location = map.get(tokens[0]);
|
|
547
561
|
const uniq = new Map;
|
|
548
562
|
parseTokens(tokens, { minify: true });
|
|
549
563
|
const ruleType = context.typ == EnumToken.KeyframeAtRuleNodeType ? EnumToken.KeyFrameRuleNodeType : EnumToken.RuleNodeType;
|
|
550
564
|
if (ruleType == EnumToken.RuleNodeType) {
|
|
551
565
|
parseSelector(tokens);
|
|
552
566
|
}
|
|
553
|
-
if (options.validation) {
|
|
554
|
-
// @ts-ignore
|
|
555
|
-
const valid = ruleType == EnumToken.KeyFrameRuleNodeType ? validateKeyframeSelector(tokens) : validateSelector(tokens, options, context);
|
|
556
|
-
if (valid.valid != ValidationLevel.Valid) {
|
|
557
|
-
const node = {
|
|
558
|
-
typ: EnumToken.InvalidRuleTokenType,
|
|
559
|
-
sel: tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), ''),
|
|
560
|
-
chi: []
|
|
561
|
-
};
|
|
562
|
-
errors.push({
|
|
563
|
-
action: 'drop',
|
|
564
|
-
message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
|
|
565
|
-
// @ts-ignore
|
|
566
|
-
location: { src, ...(map.get(valid.node) ?? position) }
|
|
567
|
-
});
|
|
568
|
-
// @ts-ignore
|
|
569
|
-
context.chi.push(node);
|
|
570
|
-
Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: context });
|
|
571
|
-
return node;
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
567
|
const node = {
|
|
575
568
|
typ: ruleType,
|
|
576
569
|
sel: [...tokens.reduce((acc, curr, index, array) => {
|
|
@@ -596,11 +589,9 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
596
589
|
let t = renderToken(curr, { minify: false });
|
|
597
590
|
if (t == ',') {
|
|
598
591
|
acc.push([]);
|
|
599
|
-
// uniqTokens.push([]);
|
|
600
592
|
}
|
|
601
593
|
else {
|
|
602
594
|
acc[acc.length - 1].push(t);
|
|
603
|
-
// uniqTokens[uniqTokens.length - 1].push(curr);
|
|
604
595
|
}
|
|
605
596
|
return acc;
|
|
606
597
|
}, [[]]).reduce((acc, curr) => {
|
|
@@ -625,78 +616,107 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
625
616
|
enumerable: false,
|
|
626
617
|
value: tokens.slice()
|
|
627
618
|
});
|
|
628
|
-
|
|
629
|
-
Object.defineProperty(node, 'raw', {
|
|
630
|
-
enumerable: false,
|
|
631
|
-
configurable: true,
|
|
632
|
-
writable: true,
|
|
633
|
-
value: raw
|
|
634
|
-
});
|
|
635
|
-
loc = {
|
|
636
|
-
sta: position,
|
|
637
|
-
src
|
|
638
|
-
};
|
|
619
|
+
loc = location;
|
|
639
620
|
if (options.sourcemap) {
|
|
640
621
|
node.loc = loc;
|
|
641
622
|
}
|
|
642
623
|
// @ts-ignore
|
|
643
624
|
context.chi.push(node);
|
|
644
625
|
Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: context });
|
|
626
|
+
// @ts-ignore
|
|
627
|
+
const valid = options.validation == ValidationLevel.None ? {
|
|
628
|
+
valid: SyntaxValidationResult.Valid,
|
|
629
|
+
error: null
|
|
630
|
+
} : ruleType == EnumToken.KeyFrameRuleNodeType ? validateKeyframeSelector(tokens) : validateSelector(tokens, options, context);
|
|
631
|
+
if (valid.valid != SyntaxValidationResult.Valid) {
|
|
632
|
+
// @ts-ignore
|
|
633
|
+
node.typ = EnumToken.InvalidRuleTokenType;
|
|
634
|
+
node.sel = tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '');
|
|
635
|
+
errors.push({
|
|
636
|
+
action: 'drop',
|
|
637
|
+
message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
|
|
638
|
+
// @ts-ignore
|
|
639
|
+
location
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
Object.defineProperty(node, 'validSyntax', {
|
|
643
|
+
...definedPropertySettings,
|
|
644
|
+
value: valid.valid == SyntaxValidationResult.Valid
|
|
645
|
+
});
|
|
645
646
|
return node;
|
|
646
647
|
}
|
|
647
648
|
else {
|
|
648
649
|
let name = null;
|
|
649
650
|
let value = null;
|
|
650
|
-
|
|
651
|
+
let i = 0;
|
|
652
|
+
for (; i < tokens.length; i++) {
|
|
653
|
+
if (tokens[i].typ == EnumToken.LiteralTokenType && tokens[i].val.length > 1) {
|
|
654
|
+
const start = tokens[i].val.charAt(0);
|
|
655
|
+
const val = tokens[i].val.slice(1);
|
|
656
|
+
if (['/', '*'].includes(start) && isNumber(val)) {
|
|
657
|
+
tokens.splice(i, 1, {
|
|
658
|
+
typ: EnumToken.LiteralTokenType,
|
|
659
|
+
val: tokens[i].val.charAt(0)
|
|
660
|
+
}, {
|
|
661
|
+
typ: EnumToken.NumberTokenType,
|
|
662
|
+
val: tokens[i].val.slice(1)
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
else if (start == '/' && isFunction(val)) {
|
|
666
|
+
tokens.splice(i, 1, { typ: EnumToken.LiteralTokenType, val: '/' }, getTokenType(val));
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
parseTokens(tokens, { ...options, parseColor: true });
|
|
671
|
+
for (i = 0; i < tokens.length; i++) {
|
|
651
672
|
if (tokens[i].typ == EnumToken.CommentTokenType) {
|
|
652
673
|
continue;
|
|
653
674
|
}
|
|
654
675
|
if (name == null && [EnumToken.IdenTokenType, EnumToken.DashedIdenTokenType].includes(tokens[i].typ)) {
|
|
655
676
|
name = tokens.slice(0, i + 1);
|
|
656
677
|
}
|
|
678
|
+
else if (name == null && tokens[i].typ == EnumToken.ColorTokenType && [ColorKind.SYS, ColorKind.DPSYS].includes(tokens[i].kin)) {
|
|
679
|
+
name = tokens.slice(0, i + 1);
|
|
680
|
+
tokens[i].typ = EnumToken.IdenTokenType;
|
|
681
|
+
}
|
|
657
682
|
else if (name != null && funcLike.concat([
|
|
658
683
|
EnumToken.LiteralTokenType,
|
|
659
684
|
EnumToken.IdenTokenType, EnumToken.DashedIdenTokenType,
|
|
660
685
|
EnumToken.PseudoClassTokenType, EnumToken.PseudoClassFuncTokenType
|
|
661
686
|
]).includes(tokens[i].typ)) {
|
|
662
|
-
if (tokens[i].val
|
|
687
|
+
if (tokens[i].val?.charAt?.(0) == ':') {
|
|
663
688
|
Object.assign(tokens[i], getTokenType(tokens[i].val.slice(1)));
|
|
689
|
+
if ('chi' in tokens[i]) {
|
|
690
|
+
tokens[i].typ = EnumToken.FunctionTokenType;
|
|
691
|
+
if (colorsFunc.includes(tokens[i].val) && isColor(tokens[i])) {
|
|
692
|
+
parseColor(tokens[i]);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
tokens.splice(i--, 0, { typ: EnumToken.ColonTokenType });
|
|
696
|
+
continue;
|
|
664
697
|
}
|
|
665
698
|
if ('chi' in tokens[i]) {
|
|
666
699
|
tokens[i].typ = EnumToken.FunctionTokenType;
|
|
667
700
|
}
|
|
668
|
-
value =
|
|
669
|
-
parseColor: options.parseColor,
|
|
670
|
-
src: options.src,
|
|
671
|
-
resolveUrls: options.resolveUrls,
|
|
672
|
-
resolve: options.resolve,
|
|
673
|
-
cwd: options.cwd
|
|
674
|
-
});
|
|
675
|
-
break;
|
|
701
|
+
value = tokens.slice(i);
|
|
676
702
|
}
|
|
677
703
|
if (tokens[i].typ == EnumToken.ColonTokenType) {
|
|
678
704
|
name = tokens.slice(0, i);
|
|
679
|
-
value =
|
|
680
|
-
parseColor: options.parseColor,
|
|
681
|
-
src: options.src,
|
|
682
|
-
resolveUrls: options.resolveUrls,
|
|
683
|
-
resolve: options.resolve,
|
|
684
|
-
cwd: options.cwd
|
|
685
|
-
});
|
|
705
|
+
value = tokens.slice(i + 1);
|
|
686
706
|
break;
|
|
687
707
|
}
|
|
688
708
|
}
|
|
689
709
|
if (name == null) {
|
|
690
710
|
name = tokens;
|
|
691
711
|
}
|
|
692
|
-
const
|
|
712
|
+
const location = map.get(name[0]);
|
|
693
713
|
if (name.length > 0) {
|
|
694
714
|
for (let i = 1; i < name.length; i++) {
|
|
695
715
|
if (name[i].typ != EnumToken.WhitespaceTokenType && name[i].typ != EnumToken.CommentTokenType) {
|
|
696
716
|
errors.push({
|
|
697
717
|
action: 'drop',
|
|
698
718
|
message: 'doParse: invalid declaration',
|
|
699
|
-
location
|
|
719
|
+
location
|
|
700
720
|
});
|
|
701
721
|
return null;
|
|
702
722
|
}
|
|
@@ -707,8 +727,20 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
707
727
|
errors.push({
|
|
708
728
|
action: 'drop',
|
|
709
729
|
message: 'doParse: invalid declaration',
|
|
710
|
-
location
|
|
730
|
+
location
|
|
711
731
|
});
|
|
732
|
+
if (options.lenient) {
|
|
733
|
+
const node = {
|
|
734
|
+
typ: EnumToken.InvalidDeclarationNodeType,
|
|
735
|
+
nam,
|
|
736
|
+
val: []
|
|
737
|
+
};
|
|
738
|
+
if (options.sourcemap) {
|
|
739
|
+
node.loc = location;
|
|
740
|
+
node.loc.end = { ...map.get(delim).end };
|
|
741
|
+
}
|
|
742
|
+
context.chi.push(node);
|
|
743
|
+
}
|
|
712
744
|
return null;
|
|
713
745
|
}
|
|
714
746
|
for (const { value: token } of walkValues(value, null, {
|
|
@@ -728,16 +760,46 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
728
760
|
}
|
|
729
761
|
const node = {
|
|
730
762
|
typ: EnumToken.DeclarationNodeType,
|
|
731
|
-
// @ts-ignore
|
|
732
763
|
nam,
|
|
733
|
-
// @ts-ignore
|
|
734
764
|
val: value
|
|
735
765
|
};
|
|
736
|
-
|
|
737
|
-
|
|
766
|
+
if (options.sourcemap) {
|
|
767
|
+
node.loc = location;
|
|
768
|
+
node.loc.end = { ...map.get(delim).end };
|
|
769
|
+
}
|
|
770
|
+
// do not allow declarations in style sheets
|
|
771
|
+
if (context.typ == EnumToken.StyleSheetNodeType && options.lenient) {
|
|
738
772
|
// @ts-ignore
|
|
773
|
+
node.typ = EnumToken.InvalidDeclarationNodeType;
|
|
774
|
+
context.chi.push(node);
|
|
775
|
+
return null;
|
|
776
|
+
}
|
|
777
|
+
const result = parseDeclarationNode(node, errors, location);
|
|
778
|
+
Object.defineProperty(result, 'parent', { ...definedPropertySettings, value: context });
|
|
779
|
+
if (result != null) {
|
|
780
|
+
if (options.validation == ValidationLevel.All) {
|
|
781
|
+
const valid = evaluateSyntax(result, options);
|
|
782
|
+
Object.defineProperty(result, 'validSyntax', {
|
|
783
|
+
...definedPropertySettings,
|
|
784
|
+
value: valid.valid == SyntaxValidationResult.Valid
|
|
785
|
+
});
|
|
786
|
+
if (valid.valid == SyntaxValidationResult.Drop) {
|
|
787
|
+
// console.error({result, valid});
|
|
788
|
+
// console.error(JSON.stringify({result, options, valid}, null, 1));
|
|
789
|
+
errors.push({
|
|
790
|
+
action: 'drop',
|
|
791
|
+
message: valid.error,
|
|
792
|
+
syntax: valid.syntax,
|
|
793
|
+
location: map.get(valid.node) ?? valid.node?.loc ?? result.loc ?? location
|
|
794
|
+
});
|
|
795
|
+
if (!options.lenient) {
|
|
796
|
+
return null;
|
|
797
|
+
}
|
|
798
|
+
// @ts-ignore
|
|
799
|
+
node.typ = EnumToken.InvalidDeclarationNodeType;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
739
802
|
context.chi.push(result);
|
|
740
|
-
Object.defineProperty(result, 'parent', { ...definedPropertySettings, value: context });
|
|
741
803
|
}
|
|
742
804
|
return null;
|
|
743
805
|
}
|
|
@@ -756,6 +818,33 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
756
818
|
value.typ == EnumToken.CommaTokenType) {
|
|
757
819
|
continue;
|
|
758
820
|
}
|
|
821
|
+
if (value.typ == EnumToken.PseudoClassFuncTokenType || value.typ == EnumToken.PseudoClassTokenType) {
|
|
822
|
+
if (parent?.typ == EnumToken.ParensTokenType) {
|
|
823
|
+
const index = parent.chi.indexOf(value);
|
|
824
|
+
let i = index;
|
|
825
|
+
while (i--) {
|
|
826
|
+
if (parent.chi[i].typ == EnumToken.IdenTokenType || parent.chi[i].typ == EnumToken.DashedIdenTokenType) {
|
|
827
|
+
break;
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
if (i >= 0) {
|
|
831
|
+
const token = getTokenType(parent.chi[index].val.slice(1) + (funcLike.includes(parent.chi[index].typ) ? '(' : ''));
|
|
832
|
+
parent.chi[index].val = token.val;
|
|
833
|
+
parent.chi[index].typ = token.typ;
|
|
834
|
+
if (parent.chi[index].typ == EnumToken.FunctionTokenType && isColor(parent.chi[index])) {
|
|
835
|
+
parseColor(parent.chi[index]);
|
|
836
|
+
}
|
|
837
|
+
parent.chi.splice(i, index - i + 1, {
|
|
838
|
+
typ: EnumToken.MediaQueryConditionTokenType,
|
|
839
|
+
l: parent.chi[i],
|
|
840
|
+
r: parent.chi.slice(index),
|
|
841
|
+
op: {
|
|
842
|
+
typ: EnumToken.ColonTokenType
|
|
843
|
+
}
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
}
|
|
759
848
|
if (atRule.val == 'page' && value.typ == EnumToken.PseudoClassTokenType) {
|
|
760
849
|
if ([':left', ':right', ':first', ':blank'].includes(value.val)) {
|
|
761
850
|
// @ts-ignore
|
|
@@ -816,6 +905,9 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
816
905
|
continue;
|
|
817
906
|
}
|
|
818
907
|
}
|
|
908
|
+
if (value.typ == EnumToken.FunctionTokenType && value.val == 'selector') {
|
|
909
|
+
parseSelector(value.chi);
|
|
910
|
+
}
|
|
819
911
|
if (value.typ == EnumToken.ParensTokenType || (value.typ == EnumToken.FunctionTokenType && ['media', 'supports', 'style', 'scroll-state'].includes(value.val))) {
|
|
820
912
|
let i;
|
|
821
913
|
let nameIndex = -1;
|
|
@@ -837,6 +929,23 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
837
929
|
if (value.chi[i].typ == EnumToken.CommentTokenType || value.chi[i].typ == EnumToken.WhitespaceTokenType) {
|
|
838
930
|
continue;
|
|
839
931
|
}
|
|
932
|
+
if (value.chi[i].typ == EnumToken.LiteralTokenType && value.chi[i].val.startsWith(':') && isDimension(value.chi[i].val.slice(1))) {
|
|
933
|
+
value.chi.splice(i, 1, {
|
|
934
|
+
typ: EnumToken.ColonTokenType,
|
|
935
|
+
}, Object.assign(value.chi[i], parseDimension(value.chi[i].val.slice(1))));
|
|
936
|
+
i--;
|
|
937
|
+
continue;
|
|
938
|
+
}
|
|
939
|
+
if (nameIndex != -1 && value.chi[i].typ == EnumToken.PseudoClassTokenType) {
|
|
940
|
+
value.chi.splice(i, 1, {
|
|
941
|
+
typ: EnumToken.ColonTokenType,
|
|
942
|
+
}, Object.assign(value.chi[i], {
|
|
943
|
+
typ: EnumToken.IdenTokenType,
|
|
944
|
+
val: value.chi[i].val.slice(1)
|
|
945
|
+
}));
|
|
946
|
+
i--;
|
|
947
|
+
continue;
|
|
948
|
+
}
|
|
840
949
|
valueIndex = i;
|
|
841
950
|
break;
|
|
842
951
|
}
|
|
@@ -856,7 +965,7 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
856
965
|
const node = value.chi.splice(nameIndex, 1)[0];
|
|
857
966
|
// 'background'
|
|
858
967
|
// @ts-ignore
|
|
859
|
-
if (node.typ == EnumToken.ColorTokenType && node.kin ==
|
|
968
|
+
if (node.typ == EnumToken.ColorTokenType && node.kin == ColorKind.DPSYS) {
|
|
860
969
|
// @ts-ignore
|
|
861
970
|
delete node.kin;
|
|
862
971
|
node.typ = EnumToken.IdenTokenType;
|
|
@@ -980,8 +1089,8 @@ function parseSelector(tokens) {
|
|
|
980
1089
|
}
|
|
981
1090
|
}
|
|
982
1091
|
else if (value.typ == EnumToken.ColorTokenType) {
|
|
983
|
-
if (value.kin ==
|
|
984
|
-
if (value.kin ==
|
|
1092
|
+
if (value.kin == ColorKind.LIT || value.kin == ColorKind.HEX || value.kin == ColorKind.SYS || value.kin == ColorKind.DPSYS) {
|
|
1093
|
+
if (value.kin == ColorKind.HEX) {
|
|
985
1094
|
if (!isIdent(value.val.slice(1))) {
|
|
986
1095
|
continue;
|
|
987
1096
|
}
|
|
@@ -1026,64 +1135,54 @@ function parseSelector(tokens) {
|
|
|
1026
1135
|
// return doParse(`.x{${src}`, options).then((result: ParseResult) => <AstDeclaration[]>(<AstRule>result.ast.chi[0]).chi.filter(t => t.typ == EnumToken.DeclarationNodeType));
|
|
1027
1136
|
// }
|
|
1028
1137
|
/**
|
|
1029
|
-
* parse string
|
|
1138
|
+
* parse css string
|
|
1030
1139
|
* @param src
|
|
1031
1140
|
* @param options
|
|
1032
1141
|
*/
|
|
1033
1142
|
function parseString(src, options = { location: false }) {
|
|
1034
|
-
return parseTokens([...tokenize(src)].
|
|
1143
|
+
return parseTokens([...tokenize(src)].reduce((acc, t) => {
|
|
1144
|
+
if (t.hint == EnumToken.EOFTokenType) {
|
|
1145
|
+
return acc;
|
|
1146
|
+
}
|
|
1035
1147
|
const token = getTokenType(t.token, t.hint);
|
|
1036
1148
|
if (options.location) {
|
|
1037
|
-
Object.assign(token, { loc: t.
|
|
1149
|
+
Object.assign(token, { loc: t.sta });
|
|
1038
1150
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1151
|
+
acc.push(token);
|
|
1152
|
+
return acc;
|
|
1153
|
+
}, []));
|
|
1041
1154
|
}
|
|
1042
1155
|
function getTokenType(val, hint) {
|
|
1043
1156
|
if (hint != null) {
|
|
1044
1157
|
return enumTokenHints.has(hint) ? { typ: hint } : { typ: hint, val };
|
|
1045
1158
|
}
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
if (val == '=') {
|
|
1074
|
-
return { typ: EnumToken.DelimTokenType };
|
|
1075
|
-
}
|
|
1076
|
-
if (val == ';') {
|
|
1077
|
-
return { typ: EnumToken.SemiColonTokenType };
|
|
1078
|
-
}
|
|
1079
|
-
if (val == ',') {
|
|
1080
|
-
return { typ: EnumToken.CommaTokenType };
|
|
1081
|
-
}
|
|
1082
|
-
if (val == '<') {
|
|
1083
|
-
return { typ: EnumToken.LtTokenType };
|
|
1084
|
-
}
|
|
1085
|
-
if (val == '>') {
|
|
1086
|
-
return { typ: EnumToken.GtTokenType };
|
|
1159
|
+
switch (val) {
|
|
1160
|
+
case ' ':
|
|
1161
|
+
return { typ: EnumToken.WhitespaceTokenType };
|
|
1162
|
+
case ';':
|
|
1163
|
+
return { typ: EnumToken.SemiColonTokenType };
|
|
1164
|
+
case '{':
|
|
1165
|
+
return { typ: EnumToken.BlockStartTokenType };
|
|
1166
|
+
case '}':
|
|
1167
|
+
return { typ: EnumToken.BlockEndTokenType };
|
|
1168
|
+
case '[':
|
|
1169
|
+
return { typ: EnumToken.AttrStartTokenType };
|
|
1170
|
+
case ']':
|
|
1171
|
+
return { typ: EnumToken.AttrEndTokenType };
|
|
1172
|
+
case ':':
|
|
1173
|
+
return { typ: EnumToken.ColonTokenType };
|
|
1174
|
+
case ')':
|
|
1175
|
+
return { typ: EnumToken.EndParensTokenType };
|
|
1176
|
+
case '(':
|
|
1177
|
+
return { typ: EnumToken.StartParensTokenType };
|
|
1178
|
+
case '=':
|
|
1179
|
+
return { typ: EnumToken.DelimTokenType };
|
|
1180
|
+
case ',':
|
|
1181
|
+
return { typ: EnumToken.CommaTokenType };
|
|
1182
|
+
case '<':
|
|
1183
|
+
return { typ: EnumToken.LtTokenType };
|
|
1184
|
+
case '>':
|
|
1185
|
+
return { typ: EnumToken.GtTokenType };
|
|
1087
1186
|
}
|
|
1088
1187
|
if (isPseudo(val)) {
|
|
1089
1188
|
return val.endsWith('(') ? {
|
|
@@ -1170,22 +1269,22 @@ function getTokenType(val, hint) {
|
|
|
1170
1269
|
return {
|
|
1171
1270
|
typ: EnumToken.ColorTokenType,
|
|
1172
1271
|
val: v,
|
|
1173
|
-
kin:
|
|
1272
|
+
kin: ColorKind.LIT
|
|
1174
1273
|
};
|
|
1175
1274
|
}
|
|
1176
1275
|
if (isIdent(val)) {
|
|
1177
|
-
if (systemColors.has(
|
|
1276
|
+
if (systemColors.has(v)) {
|
|
1178
1277
|
return {
|
|
1179
1278
|
typ: EnumToken.ColorTokenType,
|
|
1180
1279
|
val,
|
|
1181
|
-
kin:
|
|
1280
|
+
kin: ColorKind.SYS
|
|
1182
1281
|
};
|
|
1183
1282
|
}
|
|
1184
|
-
if (deprecatedSystemColors.has(
|
|
1283
|
+
if (deprecatedSystemColors.has(v)) {
|
|
1185
1284
|
return {
|
|
1186
1285
|
typ: EnumToken.ColorTokenType,
|
|
1187
1286
|
val,
|
|
1188
|
-
kin:
|
|
1287
|
+
kin: ColorKind.DPSYS
|
|
1189
1288
|
};
|
|
1190
1289
|
}
|
|
1191
1290
|
return {
|
|
@@ -1197,7 +1296,7 @@ function getTokenType(val, hint) {
|
|
|
1197
1296
|
return {
|
|
1198
1297
|
typ: EnumToken.ColorTokenType,
|
|
1199
1298
|
val,
|
|
1200
|
-
kin:
|
|
1299
|
+
kin: ColorKind.HEX
|
|
1201
1300
|
};
|
|
1202
1301
|
}
|
|
1203
1302
|
if (val.charAt(0) == '#' && isHash(val)) {
|
|
@@ -1218,23 +1317,13 @@ function getTokenType(val, hint) {
|
|
|
1218
1317
|
};
|
|
1219
1318
|
}
|
|
1220
1319
|
/**
|
|
1221
|
-
* parse token
|
|
1320
|
+
* parse token array into a tree structure
|
|
1222
1321
|
* @param tokens
|
|
1223
1322
|
* @param options
|
|
1224
1323
|
*/
|
|
1225
1324
|
function parseTokens(tokens, options = {}) {
|
|
1226
1325
|
for (let i = 0; i < tokens.length; i++) {
|
|
1227
1326
|
const t = tokens[i];
|
|
1228
|
-
if (t.typ == EnumToken.PseudoClassFuncTokenType) {
|
|
1229
|
-
if (t.val.slice(1) in webkitPseudoAliasMap) {
|
|
1230
|
-
t.val = ':' + webkitPseudoAliasMap[t.val.slice(1)];
|
|
1231
|
-
}
|
|
1232
|
-
}
|
|
1233
|
-
else if (t.typ == EnumToken.PseudoClassTokenType) {
|
|
1234
|
-
if (t.val.slice(1) in webkitPseudoAliasMap) {
|
|
1235
|
-
t.val = ':' + webkitPseudoAliasMap[t.val.slice(1)];
|
|
1236
|
-
}
|
|
1237
|
-
}
|
|
1238
1327
|
if (t.typ == EnumToken.WhitespaceTokenType && ((i == 0 ||
|
|
1239
1328
|
i + 1 == tokens.length ||
|
|
1240
1329
|
[EnumToken.CommaTokenType, EnumToken.GteTokenType, EnumToken.LteTokenType, EnumToken.ColumnCombinatorTokenType].includes(tokens[i + 1].typ)) ||
|
|
@@ -1246,13 +1335,9 @@ function parseTokens(tokens, options = {}) {
|
|
|
1246
1335
|
const typ = tokens[i + 1]?.typ;
|
|
1247
1336
|
if (typ != null) {
|
|
1248
1337
|
if (typ == EnumToken.FunctionTokenType) {
|
|
1249
|
-
tokens[i + 1].val = ':' + (tokens[i + 1].val in webkitPseudoAliasMap ? webkitPseudoAliasMap[tokens[i + 1].val] : tokens[i + 1].val);
|
|
1250
1338
|
tokens[i + 1].typ = EnumToken.PseudoClassFuncTokenType;
|
|
1251
1339
|
}
|
|
1252
1340
|
else if (typ == EnumToken.IdenTokenType) {
|
|
1253
|
-
if (tokens[i + 1].val in webkitPseudoAliasMap) {
|
|
1254
|
-
tokens[i + 1].val = webkitPseudoAliasMap[tokens[i + 1].val];
|
|
1255
|
-
}
|
|
1256
1341
|
tokens[i + 1].val = ':' + tokens[i + 1].val;
|
|
1257
1342
|
tokens[i + 1].typ = EnumToken.PseudoClassTokenType;
|
|
1258
1343
|
}
|
|
@@ -1372,6 +1457,12 @@ function parseTokens(tokens, options = {}) {
|
|
|
1372
1457
|
l: t.chi[lower],
|
|
1373
1458
|
r: t.chi[upper]
|
|
1374
1459
|
};
|
|
1460
|
+
if (isIdentColor(t.chi[m].l)) {
|
|
1461
|
+
t.chi[m].l.typ = EnumToken.IdenTokenType;
|
|
1462
|
+
}
|
|
1463
|
+
if (isIdentColor(t.chi[m].r)) {
|
|
1464
|
+
t.chi[m].r.typ = EnumToken.IdenTokenType;
|
|
1465
|
+
}
|
|
1375
1466
|
t.chi.splice(upper, 1);
|
|
1376
1467
|
t.chi.splice(lower, 1);
|
|
1377
1468
|
upper = m;
|
|
@@ -1458,6 +1549,13 @@ function parseTokens(tokens, options = {}) {
|
|
|
1458
1549
|
delete value.val;
|
|
1459
1550
|
}
|
|
1460
1551
|
}
|
|
1552
|
+
t.chi = splitTokenList(t.chi).reduce((acc, t) => {
|
|
1553
|
+
if (acc.length > 0) {
|
|
1554
|
+
acc.push({ typ: EnumToken.CommaTokenType });
|
|
1555
|
+
}
|
|
1556
|
+
acc.push(buildExpression(t));
|
|
1557
|
+
return acc;
|
|
1558
|
+
}, []);
|
|
1461
1559
|
}
|
|
1462
1560
|
else if (t.typ == EnumToken.FunctionTokenType && ['minmax', 'fit-content', 'repeat'].includes(t.val)) {
|
|
1463
1561
|
// @ts-ignore
|
|
@@ -1469,34 +1567,7 @@ function parseTokens(tokens, options = {}) {
|
|
|
1469
1567
|
}
|
|
1470
1568
|
// @ts-ignore
|
|
1471
1569
|
if (options.parseColor && t.typ == EnumToken.FunctionTokenType && isColor(t)) {
|
|
1472
|
-
|
|
1473
|
-
t.typ = EnumToken.ColorTokenType;
|
|
1474
|
-
// @ts-ignore
|
|
1475
|
-
t.kin = t.val;
|
|
1476
|
-
// @ts-ignore
|
|
1477
|
-
if (t.chi[0].typ == EnumToken.IdenTokenType) {
|
|
1478
|
-
// @ts-ignore
|
|
1479
|
-
if (t.chi[0].val == 'from') {
|
|
1480
|
-
// @ts-ignore
|
|
1481
|
-
t.cal = 'rel';
|
|
1482
|
-
}
|
|
1483
|
-
// @ts-ignore
|
|
1484
|
-
else if (t.val == 'color-mix' && t.chi[0].val == 'in') {
|
|
1485
|
-
// @ts-ignore
|
|
1486
|
-
t.cal = 'mix';
|
|
1487
|
-
}
|
|
1488
|
-
else { // @ts-ignore
|
|
1489
|
-
if (t.val == 'color') {
|
|
1490
|
-
// @ts-ignore
|
|
1491
|
-
t.cal = 'col';
|
|
1492
|
-
}
|
|
1493
|
-
}
|
|
1494
|
-
}
|
|
1495
|
-
const filter = [EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType];
|
|
1496
|
-
if (t.val != 'light-dark') {
|
|
1497
|
-
filter.push(EnumToken.CommaTokenType);
|
|
1498
|
-
}
|
|
1499
|
-
t.chi = t.chi.filter((t) => !filter.includes(t.typ));
|
|
1570
|
+
parseColor(t);
|
|
1500
1571
|
continue;
|
|
1501
1572
|
}
|
|
1502
1573
|
if (t.typ == EnumToken.UrlFunctionTokenType) {
|
|
@@ -1543,7 +1614,7 @@ function parseTokens(tokens, options = {}) {
|
|
|
1543
1614
|
Object.assign(t, {
|
|
1544
1615
|
typ: EnumToken.ColorTokenType,
|
|
1545
1616
|
val: COLORS_NAMES[value].length < value.length ? COLORS_NAMES[value] : value,
|
|
1546
|
-
kin:
|
|
1617
|
+
kin: ColorKind.HEX
|
|
1547
1618
|
});
|
|
1548
1619
|
}
|
|
1549
1620
|
continue;
|
|
@@ -1553,11 +1624,11 @@ function parseTokens(tokens, options = {}) {
|
|
|
1553
1624
|
// @ts-ignore
|
|
1554
1625
|
t.typ = EnumToken.ColorTokenType;
|
|
1555
1626
|
// @ts-ignore
|
|
1556
|
-
t.kin =
|
|
1627
|
+
t.kin = ColorKind.HEX;
|
|
1557
1628
|
}
|
|
1558
1629
|
}
|
|
1559
1630
|
}
|
|
1560
1631
|
return tokens;
|
|
1561
1632
|
}
|
|
1562
1633
|
|
|
1563
|
-
export { doParse, parseSelector, parseString, parseTokens, urlTokenMatcher };
|
|
1634
|
+
export { doParse, getTokenType, parseAtRulePrelude, parseSelector, parseString, parseTokens, urlTokenMatcher };
|