@tbela99/css-parser 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +265 -0
- package/README.md +16 -11
- package/dist/index-umd-web.js +3613 -1829
- package/dist/index.cjs +3611 -1827
- package/dist/index.d.ts +160 -50
- 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 +17 -15
- 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 +364 -276
- 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 +253 -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 +563 -63
- package/dist/lib/validation/parser/parse.js +196 -185
- package/dist/lib/validation/parser/types.js +1 -1
- package/dist/lib/validation/selector.js +3 -3
- package/dist/lib/validation/syntax.js +828 -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 +12 -11
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
|
}
|
|
@@ -97,16 +103,22 @@ async function doParse(iterator, options = {}) {
|
|
|
97
103
|
lin: 1,
|
|
98
104
|
col: 1
|
|
99
105
|
},
|
|
106
|
+
end: {
|
|
107
|
+
ind: 0,
|
|
108
|
+
lin: 1,
|
|
109
|
+
col: 1
|
|
110
|
+
},
|
|
100
111
|
src: ''
|
|
101
112
|
};
|
|
102
113
|
}
|
|
103
114
|
const iter = tokenize(iterator);
|
|
104
115
|
let item;
|
|
116
|
+
let node;
|
|
105
117
|
const rawTokens = [];
|
|
118
|
+
const imports = [];
|
|
106
119
|
while (item = iter.next().value) {
|
|
107
120
|
stats.bytesIn = item.bytesIn;
|
|
108
121
|
rawTokens.push(item);
|
|
109
|
-
// doParse error
|
|
110
122
|
if (item.hint != null && BadTokensTypes.includes(item.hint)) {
|
|
111
123
|
// bad token
|
|
112
124
|
continue;
|
|
@@ -114,14 +126,23 @@ async function doParse(iterator, options = {}) {
|
|
|
114
126
|
if (item.hint != EnumToken.EOFTokenType) {
|
|
115
127
|
tokens.push(item);
|
|
116
128
|
}
|
|
129
|
+
else if (ast.loc != null) {
|
|
130
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
131
|
+
stack[i].loc.end = { ...item.end };
|
|
132
|
+
}
|
|
133
|
+
ast.loc.end = item.end;
|
|
134
|
+
}
|
|
117
135
|
if (item.token == ';' || item.token == '{') {
|
|
118
|
-
|
|
136
|
+
node = parseNode(tokens, context, stats, options, errors, src, map, rawTokens);
|
|
119
137
|
rawTokens.length = 0;
|
|
120
138
|
if (node != null) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
139
|
+
if ('chi' in node) {
|
|
140
|
+
stack.push(node);
|
|
141
|
+
context = node;
|
|
142
|
+
}
|
|
143
|
+
else if (node.typ == EnumToken.AtRuleNodeType && node.nam == 'import') {
|
|
144
|
+
imports.push(node);
|
|
145
|
+
}
|
|
125
146
|
}
|
|
126
147
|
else if (item.token == '{') {
|
|
127
148
|
let inBlock = 1;
|
|
@@ -151,23 +172,20 @@ async function doParse(iterator, options = {}) {
|
|
|
151
172
|
map = new Map;
|
|
152
173
|
}
|
|
153
174
|
else if (item.token == '}') {
|
|
154
|
-
|
|
175
|
+
parseNode(tokens, context, stats, options, errors, src, map, rawTokens);
|
|
155
176
|
rawTokens.length = 0;
|
|
177
|
+
if (context.loc != null) {
|
|
178
|
+
context.loc.end = item.end;
|
|
179
|
+
}
|
|
156
180
|
const previousNode = stack.pop();
|
|
157
|
-
|
|
158
|
-
context = stack[stack.length - 1] ?? ast;
|
|
159
|
-
// @ts-ignore
|
|
181
|
+
context = (stack[stack.length - 1] ?? ast);
|
|
160
182
|
if (previousNode != null && previousNode.typ == EnumToken.InvalidRuleTokenType) {
|
|
161
|
-
// @ts-ignore
|
|
162
183
|
const index = context.chi.findIndex(node => node == previousNode);
|
|
163
184
|
if (index > -1) {
|
|
164
|
-
// @ts-ignore
|
|
165
185
|
context.chi.splice(index, 1);
|
|
166
186
|
}
|
|
167
187
|
}
|
|
168
|
-
// @ts-ignore
|
|
169
188
|
if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
|
|
170
|
-
// @ts-ignore
|
|
171
189
|
context.chi.pop();
|
|
172
190
|
}
|
|
173
191
|
tokens = [];
|
|
@@ -175,8 +193,17 @@ async function doParse(iterator, options = {}) {
|
|
|
175
193
|
}
|
|
176
194
|
}
|
|
177
195
|
if (tokens.length > 0) {
|
|
178
|
-
|
|
196
|
+
node = parseNode(tokens, context, stats, options, errors, src, map, rawTokens);
|
|
179
197
|
rawTokens.length = 0;
|
|
198
|
+
if (node != null) {
|
|
199
|
+
if (node.typ == EnumToken.AtRuleNodeType && node.nam == 'import') {
|
|
200
|
+
imports.push(node);
|
|
201
|
+
}
|
|
202
|
+
else if ('chi' in node && node.typ != EnumToken.InvalidRuleTokenType) {
|
|
203
|
+
stack.push(node);
|
|
204
|
+
context = node;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
180
207
|
if (context != null && context.typ == EnumToken.InvalidRuleTokenType) {
|
|
181
208
|
// @ts-ignore
|
|
182
209
|
const index = context.chi.findIndex((node) => node == context);
|
|
@@ -185,14 +212,37 @@ async function doParse(iterator, options = {}) {
|
|
|
185
212
|
}
|
|
186
213
|
}
|
|
187
214
|
}
|
|
215
|
+
if (imports.length > 0 && options.resolveImport) {
|
|
216
|
+
await Promise.all(imports.map(async (node) => {
|
|
217
|
+
const token = node.tokens[0];
|
|
218
|
+
const url = token.typ == EnumToken.StringTokenType ? token.val.slice(1, -1) : token.val;
|
|
219
|
+
try {
|
|
220
|
+
const root = await options.load(url, options.src).then((src) => {
|
|
221
|
+
// console.error({url, src: options.src, resolved: options.resolve!(url, options.src as string)})
|
|
222
|
+
return doParse(src, Object.assign({}, options, {
|
|
223
|
+
minify: false,
|
|
224
|
+
setParent: false,
|
|
225
|
+
src: options.resolve(url, options.src).absolute
|
|
226
|
+
}));
|
|
227
|
+
});
|
|
228
|
+
stats.importedBytesIn += root.stats.bytesIn;
|
|
229
|
+
node.parent.chi.splice(node.parent.chi.indexOf(node), 1, ...root.ast.chi);
|
|
230
|
+
if (root.errors.length > 0) {
|
|
231
|
+
errors.push(...root.errors);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
// console.error(error);
|
|
236
|
+
// @ts-ignore
|
|
237
|
+
errors.push({ action: 'ignore', message: 'doParse: ' + error.message, error });
|
|
238
|
+
}
|
|
239
|
+
}));
|
|
240
|
+
}
|
|
188
241
|
while (stack.length > 0 && context != ast) {
|
|
189
242
|
const previousNode = stack.pop();
|
|
190
|
-
|
|
191
|
-
context = stack[stack.length - 1] ?? ast;
|
|
243
|
+
context = (stack[stack.length - 1] ?? ast);
|
|
192
244
|
// remove empty nodes
|
|
193
|
-
// @ts-ignore
|
|
194
245
|
if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
|
|
195
|
-
// @ts-ignore
|
|
196
246
|
context.chi.pop();
|
|
197
247
|
continue;
|
|
198
248
|
}
|
|
@@ -205,14 +255,12 @@ async function doParse(iterator, options = {}) {
|
|
|
205
255
|
if (options.visitor != null) {
|
|
206
256
|
for (const result of walk(ast)) {
|
|
207
257
|
if (result.node.typ == EnumToken.DeclarationNodeType &&
|
|
208
|
-
// @ts-ignore
|
|
209
258
|
(typeof options.visitor.Declaration == 'function' || options.visitor.Declaration?.[result.node.nam] != null)) {
|
|
210
259
|
const callable = typeof options.visitor.Declaration == 'function' ? options.visitor.Declaration : options.visitor.Declaration[result.node.nam];
|
|
211
260
|
const results = await callable(result.node);
|
|
212
261
|
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
213
262
|
continue;
|
|
214
263
|
}
|
|
215
|
-
// @ts-ignore
|
|
216
264
|
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
217
265
|
}
|
|
218
266
|
else if (options.visitor.Rule != null && result.node.typ == EnumToken.RuleNodeType) {
|
|
@@ -220,7 +268,6 @@ async function doParse(iterator, options = {}) {
|
|
|
220
268
|
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
221
269
|
continue;
|
|
222
270
|
}
|
|
223
|
-
// @ts-ignore
|
|
224
271
|
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
225
272
|
}
|
|
226
273
|
else if (options.visitor.AtRule != null &&
|
|
@@ -232,7 +279,6 @@ async function doParse(iterator, options = {}) {
|
|
|
232
279
|
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
233
280
|
continue;
|
|
234
281
|
}
|
|
235
|
-
// @ts-ignore
|
|
236
282
|
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
237
283
|
}
|
|
238
284
|
}
|
|
@@ -271,30 +317,27 @@ function getLastNode(context) {
|
|
|
271
317
|
}
|
|
272
318
|
return null;
|
|
273
319
|
}
|
|
274
|
-
|
|
320
|
+
function parseNode(results, context, stats, options, errors, src, map, rawTokens) {
|
|
275
321
|
let tokens = [];
|
|
276
322
|
for (const t of results) {
|
|
277
323
|
const node = getTokenType(t.token, t.hint);
|
|
278
|
-
map.set(node, t.
|
|
324
|
+
map.set(node, { sta: t.sta, end: t.end, src });
|
|
279
325
|
tokens.push(node);
|
|
280
326
|
}
|
|
281
327
|
let i;
|
|
282
328
|
let loc;
|
|
283
329
|
for (i = 0; i < tokens.length; i++) {
|
|
284
330
|
if (tokens[i].typ == EnumToken.CommentTokenType || tokens[i].typ == EnumToken.CDOCOMMTokenType) {
|
|
285
|
-
const
|
|
331
|
+
const location = map.get(tokens[i]);
|
|
286
332
|
if (tokens[i].typ == EnumToken.CDOCOMMTokenType && context.typ != EnumToken.StyleSheetNodeType) {
|
|
287
333
|
errors.push({
|
|
288
334
|
action: 'drop',
|
|
289
335
|
message: `CDOCOMM not allowed here ${JSON.stringify(tokens[i], null, 1)}`,
|
|
290
|
-
location
|
|
336
|
+
location
|
|
291
337
|
});
|
|
292
338
|
continue;
|
|
293
339
|
}
|
|
294
|
-
loc =
|
|
295
|
-
sta: position,
|
|
296
|
-
src
|
|
297
|
-
};
|
|
340
|
+
loc = location;
|
|
298
341
|
// @ts-ignore
|
|
299
342
|
context.chi.push(tokens[i]);
|
|
300
343
|
if (options.sourcemap) {
|
|
@@ -313,10 +356,6 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
313
356
|
if (delim.typ == EnumToken.SemiColonTokenType || delim.typ == EnumToken.BlockStartTokenType || delim.typ == EnumToken.BlockEndTokenType) {
|
|
314
357
|
tokens.pop();
|
|
315
358
|
}
|
|
316
|
-
else {
|
|
317
|
-
delim = { typ: EnumToken.SemiColonTokenType };
|
|
318
|
-
}
|
|
319
|
-
// @ts-ignore
|
|
320
359
|
while ([EnumToken.WhitespaceTokenType, EnumToken.BadStringTokenType, EnumToken.BadCommentTokenType].includes(tokens.at(-1)?.typ)) {
|
|
321
360
|
tokens.pop();
|
|
322
361
|
}
|
|
@@ -325,11 +364,12 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
325
364
|
}
|
|
326
365
|
if (tokens[0]?.typ == EnumToken.AtRuleTokenType) {
|
|
327
366
|
const atRule = tokens.shift();
|
|
328
|
-
const
|
|
367
|
+
const location = map.get(atRule);
|
|
329
368
|
// @ts-ignore
|
|
330
369
|
while ([EnumToken.WhitespaceTokenType].includes(tokens[0]?.typ)) {
|
|
331
370
|
tokens.shift();
|
|
332
371
|
}
|
|
372
|
+
rawTokens.shift();
|
|
333
373
|
if (atRule.val == 'import') {
|
|
334
374
|
// only @charset and @layer are accepted before @import
|
|
335
375
|
// @ts-ignore
|
|
@@ -347,14 +387,14 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
347
387
|
if (!(type == EnumToken.InvalidAtRuleTokenType &&
|
|
348
388
|
// @ts-ignore
|
|
349
389
|
['charset', 'layer', 'import'].includes(context.chi[i].nam))) {
|
|
350
|
-
errors.push({ action: 'drop', message: 'invalid @import', location
|
|
390
|
+
errors.push({ action: 'drop', message: 'invalid @import', location });
|
|
351
391
|
return null;
|
|
352
392
|
}
|
|
353
393
|
}
|
|
354
394
|
// @ts-ignore
|
|
355
395
|
const name = context.chi[i].nam;
|
|
356
396
|
if (name != 'charset' && name != 'import' && name != 'layer') {
|
|
357
|
-
errors.push({ action: 'drop', message: 'invalid @import', location
|
|
397
|
+
errors.push({ action: 'drop', message: 'invalid @import', location });
|
|
358
398
|
return null;
|
|
359
399
|
}
|
|
360
400
|
break;
|
|
@@ -365,7 +405,7 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
365
405
|
errors.push({
|
|
366
406
|
action: 'drop',
|
|
367
407
|
message: 'doParse: invalid @import',
|
|
368
|
-
location
|
|
408
|
+
location
|
|
369
409
|
});
|
|
370
410
|
return null;
|
|
371
411
|
}
|
|
@@ -374,7 +414,7 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
374
414
|
errors.push({
|
|
375
415
|
action: 'drop',
|
|
376
416
|
message: 'doParse: invalid @import',
|
|
377
|
-
location
|
|
417
|
+
location
|
|
378
418
|
});
|
|
379
419
|
return null;
|
|
380
420
|
}
|
|
@@ -400,37 +440,6 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
400
440
|
}
|
|
401
441
|
}
|
|
402
442
|
}
|
|
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
443
|
}
|
|
435
444
|
// https://www.w3.org/TR/css-nesting-1/#conditionals
|
|
436
445
|
// allowed nesting at-rules
|
|
@@ -438,7 +447,7 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
438
447
|
if (atRule.val == 'charset') {
|
|
439
448
|
let spaces = 0;
|
|
440
449
|
// https://developer.mozilla.org/en-US/docs/Web/CSS/@charset
|
|
441
|
-
for (let k =
|
|
450
|
+
for (let k = 0; k < rawTokens.length; k++) {
|
|
442
451
|
if (rawTokens[k].hint == EnumToken.WhitespaceTokenType) {
|
|
443
452
|
spaces += rawTokens[k].len;
|
|
444
453
|
continue;
|
|
@@ -454,7 +463,7 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
454
463
|
action: 'drop',
|
|
455
464
|
message: '@charset must have only one space',
|
|
456
465
|
// @ts-ignore
|
|
457
|
-
location
|
|
466
|
+
location
|
|
458
467
|
});
|
|
459
468
|
return null;
|
|
460
469
|
}
|
|
@@ -462,8 +471,7 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
462
471
|
errors.push({
|
|
463
472
|
action: 'drop',
|
|
464
473
|
message: '@charset expects a "<charset>"',
|
|
465
|
-
|
|
466
|
-
location: { src, ...(map.get(atRule) ?? position) }
|
|
474
|
+
location
|
|
467
475
|
});
|
|
468
476
|
return null;
|
|
469
477
|
}
|
|
@@ -483,94 +491,75 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
483
491
|
const node = {
|
|
484
492
|
typ: /^(-[a-z]+-)?keyframes$/.test(nam) ? EnumToken.KeyframeAtRuleNodeType : EnumToken.AtRuleNodeType,
|
|
485
493
|
nam,
|
|
486
|
-
// tokens: t,
|
|
487
494
|
val: raw.join('')
|
|
488
495
|
};
|
|
489
496
|
Object.defineProperties(node, {
|
|
490
|
-
tokens: { ...definedPropertySettings, enumerable: false, value:
|
|
497
|
+
tokens: { ...definedPropertySettings, enumerable: false, value: t.slice() },
|
|
491
498
|
raw: { ...definedPropertySettings, value: raw }
|
|
492
499
|
});
|
|
493
500
|
if (delim.typ == EnumToken.BlockStartTokenType) {
|
|
494
501
|
node.chi = [];
|
|
495
502
|
}
|
|
496
|
-
loc =
|
|
497
|
-
sta: position,
|
|
498
|
-
src
|
|
499
|
-
};
|
|
503
|
+
loc = map.get(atRule);
|
|
500
504
|
if (options.sourcemap) {
|
|
501
505
|
node.loc = loc;
|
|
506
|
+
node.loc.end = { ...map.get(delim).end };
|
|
502
507
|
}
|
|
503
|
-
if (options.validation) {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
else {
|
|
513
|
-
isValid = false;
|
|
508
|
+
// if (options.validation) {
|
|
509
|
+
let isValid = true;
|
|
510
|
+
if (node.nam == 'else') {
|
|
511
|
+
const prev = getLastNode(context);
|
|
512
|
+
if (prev != null && prev.typ == EnumToken.AtRuleNodeType && ['when', 'else'].includes(prev.nam)) {
|
|
513
|
+
if (prev.nam == 'else') {
|
|
514
|
+
isValid = Array.isArray(prev.tokens) && prev.tokens.length > 0;
|
|
514
515
|
}
|
|
515
516
|
}
|
|
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
517
|
else {
|
|
532
|
-
|
|
533
|
-
minify: false,
|
|
534
|
-
removeComments: true
|
|
535
|
-
}), '');
|
|
518
|
+
isValid = false;
|
|
536
519
|
}
|
|
537
520
|
}
|
|
538
521
|
// @ts-ignore
|
|
522
|
+
const valid = options.validation == ValidationLevel.None ? {
|
|
523
|
+
valid: SyntaxValidationResult.Valid,
|
|
524
|
+
error: '',
|
|
525
|
+
node,
|
|
526
|
+
syntax: '@' + node.nam
|
|
527
|
+
} : isValid ? (node.typ == EnumToken.KeyframeAtRuleNodeType ? validateAtRuleKeyframes(node) : validateAtRule(node, options, context)) : {
|
|
528
|
+
valid: SyntaxValidationResult.Drop,
|
|
529
|
+
node,
|
|
530
|
+
syntax: '@' + node.nam,
|
|
531
|
+
error: '@' + node.nam + ' not allowed here'};
|
|
532
|
+
if (valid.valid == SyntaxValidationResult.Drop) {
|
|
533
|
+
errors.push({
|
|
534
|
+
action: 'drop',
|
|
535
|
+
message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
|
|
536
|
+
// @ts-ignore
|
|
537
|
+
location: { src, ...(map.get(valid.node) ?? location) }
|
|
538
|
+
});
|
|
539
|
+
// @ts-ignore
|
|
540
|
+
node.typ = EnumToken.InvalidAtRuleTokenType;
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
node.val = node.tokens.reduce((acc, curr) => acc + renderToken(curr, {
|
|
544
|
+
minify: false,
|
|
545
|
+
removeComments: true
|
|
546
|
+
}), '');
|
|
547
|
+
}
|
|
548
|
+
// }
|
|
539
549
|
context.chi.push(node);
|
|
540
|
-
Object.
|
|
541
|
-
return
|
|
550
|
+
Object.defineProperties(node, { parent: { ...definedPropertySettings, value: context }, validSyntax: { ...definedPropertySettings, value: valid.valid == SyntaxValidationResult.Valid } });
|
|
551
|
+
return node;
|
|
542
552
|
}
|
|
543
553
|
else {
|
|
544
554
|
// rule
|
|
545
555
|
if (delim.typ == EnumToken.BlockStartTokenType) {
|
|
546
|
-
const
|
|
556
|
+
const location = map.get(tokens[0]);
|
|
547
557
|
const uniq = new Map;
|
|
548
558
|
parseTokens(tokens, { minify: true });
|
|
549
559
|
const ruleType = context.typ == EnumToken.KeyframeAtRuleNodeType ? EnumToken.KeyFrameRuleNodeType : EnumToken.RuleNodeType;
|
|
550
560
|
if (ruleType == EnumToken.RuleNodeType) {
|
|
551
561
|
parseSelector(tokens);
|
|
552
562
|
}
|
|
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
563
|
const node = {
|
|
575
564
|
typ: ruleType,
|
|
576
565
|
sel: [...tokens.reduce((acc, curr, index, array) => {
|
|
@@ -625,78 +614,124 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
625
614
|
enumerable: false,
|
|
626
615
|
value: tokens.slice()
|
|
627
616
|
});
|
|
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
|
-
};
|
|
617
|
+
loc = location;
|
|
639
618
|
if (options.sourcemap) {
|
|
640
619
|
node.loc = loc;
|
|
641
620
|
}
|
|
642
621
|
// @ts-ignore
|
|
643
622
|
context.chi.push(node);
|
|
644
623
|
Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: context });
|
|
624
|
+
// if (options.validation) {
|
|
625
|
+
// @ts-ignore
|
|
626
|
+
const valid = options.validation == ValidationLevel.None ? {
|
|
627
|
+
valid: SyntaxValidationResult.Valid,
|
|
628
|
+
error: null
|
|
629
|
+
} : ruleType == EnumToken.KeyFrameRuleNodeType ? validateKeyframeSelector(tokens) : validateSelector(tokens, options, context);
|
|
630
|
+
if (valid.valid != SyntaxValidationResult.Valid) {
|
|
631
|
+
// @ts-ignore
|
|
632
|
+
node.typ = EnumToken.InvalidRuleTokenType;
|
|
633
|
+
node.sel = tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '');
|
|
634
|
+
errors.push({
|
|
635
|
+
action: 'drop',
|
|
636
|
+
message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
|
|
637
|
+
// @ts-ignore
|
|
638
|
+
location
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
// } else {
|
|
642
|
+
//
|
|
643
|
+
// Object.defineProperty(node, 'tokens', {
|
|
644
|
+
// ...definedPropertySettings,
|
|
645
|
+
// enumerable: false,
|
|
646
|
+
// value: tokens.slice()
|
|
647
|
+
// });
|
|
648
|
+
//
|
|
649
|
+
// let raw: string[][] = [...uniq.values()];
|
|
650
|
+
//
|
|
651
|
+
// Object.defineProperty(node, 'raw', {
|
|
652
|
+
// enumerable: false,
|
|
653
|
+
// configurable: true,
|
|
654
|
+
// writable: true,
|
|
655
|
+
// value: raw
|
|
656
|
+
// });
|
|
657
|
+
// }
|
|
658
|
+
Object.defineProperty(node, 'validSyntax', { ...definedPropertySettings, value: valid.valid == SyntaxValidationResult.Valid });
|
|
645
659
|
return node;
|
|
646
660
|
}
|
|
647
661
|
else {
|
|
648
662
|
let name = null;
|
|
649
663
|
let value = null;
|
|
650
|
-
|
|
664
|
+
let i = 0;
|
|
665
|
+
for (; i < tokens.length; i++) {
|
|
666
|
+
if (tokens[i].typ == EnumToken.LiteralTokenType && tokens[i].val.length > 1) {
|
|
667
|
+
const start = tokens[i].val.charAt(0);
|
|
668
|
+
const val = tokens[i].val.slice(1);
|
|
669
|
+
if (['/', '*'].includes(start) && isNumber(val)) {
|
|
670
|
+
tokens.splice(i, 1, {
|
|
671
|
+
typ: EnumToken.LiteralTokenType,
|
|
672
|
+
val: tokens[i].val.charAt(0)
|
|
673
|
+
}, {
|
|
674
|
+
typ: EnumToken.NumberTokenType,
|
|
675
|
+
val: tokens[i].val.slice(1)
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
else if (start == '/' && isFunction(val)) {
|
|
679
|
+
tokens.splice(i, 1, { typ: EnumToken.LiteralTokenType, val: '/' }, getTokenType(val));
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
parseTokens(tokens, { ...options, parseColor: true });
|
|
684
|
+
for (i = 0; i < tokens.length; i++) {
|
|
651
685
|
if (tokens[i].typ == EnumToken.CommentTokenType) {
|
|
652
686
|
continue;
|
|
653
687
|
}
|
|
654
688
|
if (name == null && [EnumToken.IdenTokenType, EnumToken.DashedIdenTokenType].includes(tokens[i].typ)) {
|
|
655
689
|
name = tokens.slice(0, i + 1);
|
|
656
690
|
}
|
|
691
|
+
else if (name == null && tokens[i].typ == EnumToken.ColorTokenType && [ColorKind.SYS, ColorKind.DPSYS].includes(tokens[i].kin)) {
|
|
692
|
+
name = tokens.slice(0, i + 1);
|
|
693
|
+
tokens[i].typ = EnumToken.IdenTokenType;
|
|
694
|
+
}
|
|
657
695
|
else if (name != null && funcLike.concat([
|
|
658
696
|
EnumToken.LiteralTokenType,
|
|
659
697
|
EnumToken.IdenTokenType, EnumToken.DashedIdenTokenType,
|
|
660
698
|
EnumToken.PseudoClassTokenType, EnumToken.PseudoClassFuncTokenType
|
|
661
699
|
]).includes(tokens[i].typ)) {
|
|
662
|
-
if (tokens[i].val
|
|
700
|
+
if (tokens[i].val?.charAt?.(0) == ':') {
|
|
663
701
|
Object.assign(tokens[i], getTokenType(tokens[i].val.slice(1)));
|
|
702
|
+
if ('chi' in tokens[i]) {
|
|
703
|
+
tokens[i].typ = EnumToken.FunctionTokenType;
|
|
704
|
+
if (colorsFunc.includes(tokens[i].val) && isColor(tokens[i])) {
|
|
705
|
+
parseColor(tokens[i]);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
tokens.splice(i, 0, { typ: EnumToken.ColonTokenType });
|
|
709
|
+
// i++;
|
|
710
|
+
i--;
|
|
711
|
+
continue;
|
|
664
712
|
}
|
|
665
713
|
if ('chi' in tokens[i]) {
|
|
666
714
|
tokens[i].typ = EnumToken.FunctionTokenType;
|
|
667
715
|
}
|
|
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;
|
|
716
|
+
value = tokens.slice(i);
|
|
676
717
|
}
|
|
677
718
|
if (tokens[i].typ == EnumToken.ColonTokenType) {
|
|
678
719
|
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
|
-
});
|
|
720
|
+
value = tokens.slice(i + 1);
|
|
686
721
|
break;
|
|
687
722
|
}
|
|
688
723
|
}
|
|
689
724
|
if (name == null) {
|
|
690
725
|
name = tokens;
|
|
691
726
|
}
|
|
692
|
-
const
|
|
727
|
+
const location = map.get(name[0]);
|
|
693
728
|
if (name.length > 0) {
|
|
694
729
|
for (let i = 1; i < name.length; i++) {
|
|
695
730
|
if (name[i].typ != EnumToken.WhitespaceTokenType && name[i].typ != EnumToken.CommentTokenType) {
|
|
696
731
|
errors.push({
|
|
697
732
|
action: 'drop',
|
|
698
733
|
message: 'doParse: invalid declaration',
|
|
699
|
-
location
|
|
734
|
+
location
|
|
700
735
|
});
|
|
701
736
|
return null;
|
|
702
737
|
}
|
|
@@ -707,8 +742,20 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
707
742
|
errors.push({
|
|
708
743
|
action: 'drop',
|
|
709
744
|
message: 'doParse: invalid declaration',
|
|
710
|
-
location
|
|
745
|
+
location
|
|
711
746
|
});
|
|
747
|
+
if (options.lenient) {
|
|
748
|
+
const node = {
|
|
749
|
+
typ: EnumToken.InvalidDeclarationNodeType,
|
|
750
|
+
nam,
|
|
751
|
+
val: []
|
|
752
|
+
};
|
|
753
|
+
if (options.sourcemap) {
|
|
754
|
+
node.loc = location;
|
|
755
|
+
node.loc.end = { ...map.get(delim).end };
|
|
756
|
+
}
|
|
757
|
+
context.chi.push(node);
|
|
758
|
+
}
|
|
712
759
|
return null;
|
|
713
760
|
}
|
|
714
761
|
for (const { value: token } of walkValues(value, null, {
|
|
@@ -728,16 +775,42 @@ async function parseNode(results, context, stats, options, errors, src, map, raw
|
|
|
728
775
|
}
|
|
729
776
|
const node = {
|
|
730
777
|
typ: EnumToken.DeclarationNodeType,
|
|
731
|
-
// @ts-ignore
|
|
732
778
|
nam,
|
|
733
|
-
// @ts-ignore
|
|
734
779
|
val: value
|
|
735
780
|
};
|
|
736
|
-
|
|
737
|
-
|
|
781
|
+
if (options.sourcemap) {
|
|
782
|
+
node.loc = location;
|
|
783
|
+
node.loc.end = { ...map.get(delim).end };
|
|
784
|
+
}
|
|
785
|
+
// do not allow declarations in style sheets
|
|
786
|
+
if (context.typ == EnumToken.StyleSheetNodeType && options.lenient) {
|
|
738
787
|
// @ts-ignore
|
|
788
|
+
node.typ = EnumToken.InvalidDeclarationNodeType;
|
|
789
|
+
context.chi.push(node);
|
|
790
|
+
return null;
|
|
791
|
+
}
|
|
792
|
+
const result = parseDeclarationNode(node, errors, location);
|
|
793
|
+
Object.defineProperty(result, 'parent', { ...definedPropertySettings, value: context });
|
|
794
|
+
if (result != null) {
|
|
795
|
+
// console.error(doRender(result), result.val, location);
|
|
796
|
+
if (options.validation == ValidationLevel.All) {
|
|
797
|
+
const valid = evaluateSyntax(result, options);
|
|
798
|
+
Object.defineProperty(result, 'validSyntax', { ...definedPropertySettings, value: valid.valid == SyntaxValidationResult.Valid });
|
|
799
|
+
if (valid.valid == SyntaxValidationResult.Drop) {
|
|
800
|
+
errors.push({
|
|
801
|
+
action: 'drop',
|
|
802
|
+
message: valid.error,
|
|
803
|
+
syntax: valid.syntax,
|
|
804
|
+
location: map.get(valid.node) ?? valid.node?.loc ?? result.loc ?? location
|
|
805
|
+
});
|
|
806
|
+
if (!options.lenient) {
|
|
807
|
+
return null;
|
|
808
|
+
}
|
|
809
|
+
// @ts-ignore
|
|
810
|
+
node.typ = EnumToken.InvalidDeclarationNodeType;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
739
813
|
context.chi.push(result);
|
|
740
|
-
Object.defineProperty(result, 'parent', { ...definedPropertySettings, value: context });
|
|
741
814
|
}
|
|
742
815
|
return null;
|
|
743
816
|
}
|
|
@@ -756,6 +829,33 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
756
829
|
value.typ == EnumToken.CommaTokenType) {
|
|
757
830
|
continue;
|
|
758
831
|
}
|
|
832
|
+
if (value.typ == EnumToken.PseudoClassFuncTokenType || value.typ == EnumToken.PseudoClassTokenType) {
|
|
833
|
+
if (parent?.typ == EnumToken.ParensTokenType) {
|
|
834
|
+
const index = parent.chi.indexOf(value);
|
|
835
|
+
let i = index;
|
|
836
|
+
while (i--) {
|
|
837
|
+
if (parent.chi[i].typ == EnumToken.IdenTokenType || parent.chi[i].typ == EnumToken.DashedIdenTokenType) {
|
|
838
|
+
break;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
if (i >= 0) {
|
|
842
|
+
const token = getTokenType(parent.chi[index].val.slice(1) + (funcLike.includes(parent.chi[index].typ) ? '(' : ''));
|
|
843
|
+
parent.chi[index].val = token.val;
|
|
844
|
+
parent.chi[index].typ = token.typ;
|
|
845
|
+
if (parent.chi[index].typ == EnumToken.FunctionTokenType && isColor(parent.chi[index])) {
|
|
846
|
+
parseColor(parent.chi[index]);
|
|
847
|
+
}
|
|
848
|
+
parent.chi.splice(i, index - i + 1, {
|
|
849
|
+
typ: EnumToken.MediaQueryConditionTokenType,
|
|
850
|
+
l: parent.chi[i],
|
|
851
|
+
r: parent.chi.slice(index),
|
|
852
|
+
op: {
|
|
853
|
+
typ: EnumToken.ColonTokenType
|
|
854
|
+
}
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
}
|
|
759
859
|
if (atRule.val == 'page' && value.typ == EnumToken.PseudoClassTokenType) {
|
|
760
860
|
if ([':left', ':right', ':first', ':blank'].includes(value.val)) {
|
|
761
861
|
// @ts-ignore
|
|
@@ -816,6 +916,9 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
816
916
|
continue;
|
|
817
917
|
}
|
|
818
918
|
}
|
|
919
|
+
if (value.typ == EnumToken.FunctionTokenType && value.val == 'selector') {
|
|
920
|
+
parseSelector(value.chi);
|
|
921
|
+
}
|
|
819
922
|
if (value.typ == EnumToken.ParensTokenType || (value.typ == EnumToken.FunctionTokenType && ['media', 'supports', 'style', 'scroll-state'].includes(value.val))) {
|
|
820
923
|
let i;
|
|
821
924
|
let nameIndex = -1;
|
|
@@ -837,6 +940,23 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
837
940
|
if (value.chi[i].typ == EnumToken.CommentTokenType || value.chi[i].typ == EnumToken.WhitespaceTokenType) {
|
|
838
941
|
continue;
|
|
839
942
|
}
|
|
943
|
+
if (value.chi[i].typ == EnumToken.LiteralTokenType && value.chi[i].val.startsWith(':') && isDimension(value.chi[i].val.slice(1))) {
|
|
944
|
+
value.chi.splice(i, 1, {
|
|
945
|
+
typ: EnumToken.ColonTokenType,
|
|
946
|
+
}, Object.assign(value.chi[i], parseDimension(value.chi[i].val.slice(1))));
|
|
947
|
+
i--;
|
|
948
|
+
continue;
|
|
949
|
+
}
|
|
950
|
+
if (nameIndex != -1 && value.chi[i].typ == EnumToken.PseudoClassTokenType) {
|
|
951
|
+
value.chi.splice(i, 1, {
|
|
952
|
+
typ: EnumToken.ColonTokenType,
|
|
953
|
+
}, Object.assign(value.chi[i], {
|
|
954
|
+
typ: EnumToken.IdenTokenType,
|
|
955
|
+
val: value.chi[i].val.slice(1)
|
|
956
|
+
}));
|
|
957
|
+
i--;
|
|
958
|
+
continue;
|
|
959
|
+
}
|
|
840
960
|
valueIndex = i;
|
|
841
961
|
break;
|
|
842
962
|
}
|
|
@@ -856,7 +976,7 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
856
976
|
const node = value.chi.splice(nameIndex, 1)[0];
|
|
857
977
|
// 'background'
|
|
858
978
|
// @ts-ignore
|
|
859
|
-
if (node.typ == EnumToken.ColorTokenType && node.kin ==
|
|
979
|
+
if (node.typ == EnumToken.ColorTokenType && node.kin == ColorKind.DPSYS) {
|
|
860
980
|
// @ts-ignore
|
|
861
981
|
delete node.kin;
|
|
862
982
|
node.typ = EnumToken.IdenTokenType;
|
|
@@ -980,8 +1100,8 @@ function parseSelector(tokens) {
|
|
|
980
1100
|
}
|
|
981
1101
|
}
|
|
982
1102
|
else if (value.typ == EnumToken.ColorTokenType) {
|
|
983
|
-
if (value.kin ==
|
|
984
|
-
if (value.kin ==
|
|
1103
|
+
if (value.kin == ColorKind.LIT || value.kin == ColorKind.HEX || value.kin == ColorKind.SYS || value.kin == ColorKind.DPSYS) {
|
|
1104
|
+
if (value.kin == ColorKind.HEX) {
|
|
985
1105
|
if (!isIdent(value.val.slice(1))) {
|
|
986
1106
|
continue;
|
|
987
1107
|
}
|
|
@@ -1026,64 +1146,54 @@ function parseSelector(tokens) {
|
|
|
1026
1146
|
// return doParse(`.x{${src}`, options).then((result: ParseResult) => <AstDeclaration[]>(<AstRule>result.ast.chi[0]).chi.filter(t => t.typ == EnumToken.DeclarationNodeType));
|
|
1027
1147
|
// }
|
|
1028
1148
|
/**
|
|
1029
|
-
* parse string
|
|
1149
|
+
* parse css string
|
|
1030
1150
|
* @param src
|
|
1031
1151
|
* @param options
|
|
1032
1152
|
*/
|
|
1033
1153
|
function parseString(src, options = { location: false }) {
|
|
1034
|
-
return parseTokens([...tokenize(src)].
|
|
1154
|
+
return parseTokens([...tokenize(src)].reduce((acc, t) => {
|
|
1155
|
+
if (t.hint == EnumToken.EOFTokenType) {
|
|
1156
|
+
return acc;
|
|
1157
|
+
}
|
|
1035
1158
|
const token = getTokenType(t.token, t.hint);
|
|
1036
1159
|
if (options.location) {
|
|
1037
|
-
Object.assign(token, { loc: t.
|
|
1160
|
+
Object.assign(token, { loc: t.sta });
|
|
1038
1161
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1162
|
+
acc.push(token);
|
|
1163
|
+
return acc;
|
|
1164
|
+
}, []));
|
|
1041
1165
|
}
|
|
1042
1166
|
function getTokenType(val, hint) {
|
|
1043
1167
|
if (hint != null) {
|
|
1044
1168
|
return enumTokenHints.has(hint) ? { typ: hint } : { typ: hint, val };
|
|
1045
1169
|
}
|
|
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 };
|
|
1170
|
+
switch (val) {
|
|
1171
|
+
case ' ':
|
|
1172
|
+
return { typ: EnumToken.WhitespaceTokenType };
|
|
1173
|
+
case ';':
|
|
1174
|
+
return { typ: EnumToken.SemiColonTokenType };
|
|
1175
|
+
case '{':
|
|
1176
|
+
return { typ: EnumToken.BlockStartTokenType };
|
|
1177
|
+
case '}':
|
|
1178
|
+
return { typ: EnumToken.BlockEndTokenType };
|
|
1179
|
+
case '[':
|
|
1180
|
+
return { typ: EnumToken.AttrStartTokenType };
|
|
1181
|
+
case ']':
|
|
1182
|
+
return { typ: EnumToken.AttrEndTokenType };
|
|
1183
|
+
case ':':
|
|
1184
|
+
return { typ: EnumToken.ColonTokenType };
|
|
1185
|
+
case ')':
|
|
1186
|
+
return { typ: EnumToken.EndParensTokenType };
|
|
1187
|
+
case '(':
|
|
1188
|
+
return { typ: EnumToken.StartParensTokenType };
|
|
1189
|
+
case '=':
|
|
1190
|
+
return { typ: EnumToken.DelimTokenType };
|
|
1191
|
+
case ',':
|
|
1192
|
+
return { typ: EnumToken.CommaTokenType };
|
|
1193
|
+
case '<':
|
|
1194
|
+
return { typ: EnumToken.LtTokenType };
|
|
1195
|
+
case '>':
|
|
1196
|
+
return { typ: EnumToken.GtTokenType };
|
|
1087
1197
|
}
|
|
1088
1198
|
if (isPseudo(val)) {
|
|
1089
1199
|
return val.endsWith('(') ? {
|
|
@@ -1170,22 +1280,22 @@ function getTokenType(val, hint) {
|
|
|
1170
1280
|
return {
|
|
1171
1281
|
typ: EnumToken.ColorTokenType,
|
|
1172
1282
|
val: v,
|
|
1173
|
-
kin:
|
|
1283
|
+
kin: ColorKind.LIT
|
|
1174
1284
|
};
|
|
1175
1285
|
}
|
|
1176
1286
|
if (isIdent(val)) {
|
|
1177
|
-
if (systemColors.has(
|
|
1287
|
+
if (systemColors.has(v)) {
|
|
1178
1288
|
return {
|
|
1179
1289
|
typ: EnumToken.ColorTokenType,
|
|
1180
1290
|
val,
|
|
1181
|
-
kin:
|
|
1291
|
+
kin: ColorKind.SYS
|
|
1182
1292
|
};
|
|
1183
1293
|
}
|
|
1184
|
-
if (deprecatedSystemColors.has(
|
|
1294
|
+
if (deprecatedSystemColors.has(v)) {
|
|
1185
1295
|
return {
|
|
1186
1296
|
typ: EnumToken.ColorTokenType,
|
|
1187
1297
|
val,
|
|
1188
|
-
kin:
|
|
1298
|
+
kin: ColorKind.DPSYS
|
|
1189
1299
|
};
|
|
1190
1300
|
}
|
|
1191
1301
|
return {
|
|
@@ -1197,7 +1307,7 @@ function getTokenType(val, hint) {
|
|
|
1197
1307
|
return {
|
|
1198
1308
|
typ: EnumToken.ColorTokenType,
|
|
1199
1309
|
val,
|
|
1200
|
-
kin:
|
|
1310
|
+
kin: ColorKind.HEX
|
|
1201
1311
|
};
|
|
1202
1312
|
}
|
|
1203
1313
|
if (val.charAt(0) == '#' && isHash(val)) {
|
|
@@ -1218,23 +1328,13 @@ function getTokenType(val, hint) {
|
|
|
1218
1328
|
};
|
|
1219
1329
|
}
|
|
1220
1330
|
/**
|
|
1221
|
-
* parse token
|
|
1331
|
+
* parse token array into a tree structure
|
|
1222
1332
|
* @param tokens
|
|
1223
1333
|
* @param options
|
|
1224
1334
|
*/
|
|
1225
1335
|
function parseTokens(tokens, options = {}) {
|
|
1226
1336
|
for (let i = 0; i < tokens.length; i++) {
|
|
1227
1337
|
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
1338
|
if (t.typ == EnumToken.WhitespaceTokenType && ((i == 0 ||
|
|
1239
1339
|
i + 1 == tokens.length ||
|
|
1240
1340
|
[EnumToken.CommaTokenType, EnumToken.GteTokenType, EnumToken.LteTokenType, EnumToken.ColumnCombinatorTokenType].includes(tokens[i + 1].typ)) ||
|
|
@@ -1246,13 +1346,9 @@ function parseTokens(tokens, options = {}) {
|
|
|
1246
1346
|
const typ = tokens[i + 1]?.typ;
|
|
1247
1347
|
if (typ != null) {
|
|
1248
1348
|
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
1349
|
tokens[i + 1].typ = EnumToken.PseudoClassFuncTokenType;
|
|
1251
1350
|
}
|
|
1252
1351
|
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
1352
|
tokens[i + 1].val = ':' + tokens[i + 1].val;
|
|
1257
1353
|
tokens[i + 1].typ = EnumToken.PseudoClassTokenType;
|
|
1258
1354
|
}
|
|
@@ -1372,6 +1468,12 @@ function parseTokens(tokens, options = {}) {
|
|
|
1372
1468
|
l: t.chi[lower],
|
|
1373
1469
|
r: t.chi[upper]
|
|
1374
1470
|
};
|
|
1471
|
+
if (isIdentColor(t.chi[m].l)) {
|
|
1472
|
+
t.chi[m].l.typ = EnumToken.IdenTokenType;
|
|
1473
|
+
}
|
|
1474
|
+
if (isIdentColor(t.chi[m].r)) {
|
|
1475
|
+
t.chi[m].r.typ = EnumToken.IdenTokenType;
|
|
1476
|
+
}
|
|
1375
1477
|
t.chi.splice(upper, 1);
|
|
1376
1478
|
t.chi.splice(lower, 1);
|
|
1377
1479
|
upper = m;
|
|
@@ -1458,6 +1560,13 @@ function parseTokens(tokens, options = {}) {
|
|
|
1458
1560
|
delete value.val;
|
|
1459
1561
|
}
|
|
1460
1562
|
}
|
|
1563
|
+
t.chi = splitTokenList(t.chi).reduce((acc, t) => {
|
|
1564
|
+
if (acc.length > 0) {
|
|
1565
|
+
acc.push({ typ: EnumToken.CommaTokenType });
|
|
1566
|
+
}
|
|
1567
|
+
acc.push(buildExpression(t));
|
|
1568
|
+
return acc;
|
|
1569
|
+
}, []);
|
|
1461
1570
|
}
|
|
1462
1571
|
else if (t.typ == EnumToken.FunctionTokenType && ['minmax', 'fit-content', 'repeat'].includes(t.val)) {
|
|
1463
1572
|
// @ts-ignore
|
|
@@ -1469,34 +1578,7 @@ function parseTokens(tokens, options = {}) {
|
|
|
1469
1578
|
}
|
|
1470
1579
|
// @ts-ignore
|
|
1471
1580
|
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));
|
|
1581
|
+
parseColor(t);
|
|
1500
1582
|
continue;
|
|
1501
1583
|
}
|
|
1502
1584
|
if (t.typ == EnumToken.UrlFunctionTokenType) {
|
|
@@ -1508,6 +1590,12 @@ function parseTokens(tokens, options = {}) {
|
|
|
1508
1590
|
if (t.chi[0].val.slice(1, 5) != 'data:' && urlTokenMatcher.test(value)) {
|
|
1509
1591
|
// @ts-ignore
|
|
1510
1592
|
t.chi[0].typ = EnumToken.UrlTokenTokenType;
|
|
1593
|
+
// console.error({t, v: t.chi[0], value,
|
|
1594
|
+
// src: options.src,
|
|
1595
|
+
// resolved: options.src !== '' && options.resolveUrls ? options.resolve(value, options.src).absolute : null,
|
|
1596
|
+
// val2: options.src !== '' && options.resolveUrls ? options.resolve(value, options.src).absolute : value});
|
|
1597
|
+
//
|
|
1598
|
+
// console.error(new Error('resolved'));
|
|
1511
1599
|
// @ts-ignore
|
|
1512
1600
|
t.chi[0].val = options.src !== '' && options.resolveUrls ? options.resolve(value, options.src).absolute : value;
|
|
1513
1601
|
}
|
|
@@ -1543,7 +1631,7 @@ function parseTokens(tokens, options = {}) {
|
|
|
1543
1631
|
Object.assign(t, {
|
|
1544
1632
|
typ: EnumToken.ColorTokenType,
|
|
1545
1633
|
val: COLORS_NAMES[value].length < value.length ? COLORS_NAMES[value] : value,
|
|
1546
|
-
kin:
|
|
1634
|
+
kin: ColorKind.HEX
|
|
1547
1635
|
});
|
|
1548
1636
|
}
|
|
1549
1637
|
continue;
|
|
@@ -1553,11 +1641,11 @@ function parseTokens(tokens, options = {}) {
|
|
|
1553
1641
|
// @ts-ignore
|
|
1554
1642
|
t.typ = EnumToken.ColorTokenType;
|
|
1555
1643
|
// @ts-ignore
|
|
1556
|
-
t.kin =
|
|
1644
|
+
t.kin = ColorKind.HEX;
|
|
1557
1645
|
}
|
|
1558
1646
|
}
|
|
1559
1647
|
}
|
|
1560
1648
|
return tokens;
|
|
1561
1649
|
}
|
|
1562
1650
|
|
|
1563
|
-
export { doParse, parseSelector, parseString, parseTokens, urlTokenMatcher };
|
|
1651
|
+
export { doParse, parseAtRulePrelude, parseSelector, parseString, parseTokens, urlTokenMatcher };
|