@tbela99/css-parser 1.3.2 → 1.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +59 -20
- package/dist/index-umd-web.js +1846 -1075
- package/dist/index.cjs +1941 -1202
- package/dist/index.d.ts +914 -181
- package/dist/lib/ast/expand.js +5 -10
- package/dist/lib/ast/features/calc.js +8 -8
- package/dist/lib/ast/features/inlinecssvariables.js +9 -8
- package/dist/lib/ast/features/prefix.js +5 -15
- package/dist/lib/ast/features/shorthand.js +5 -6
- package/dist/lib/ast/features/transform.js +18 -25
- package/dist/lib/ast/features/type.js +4 -2
- package/dist/lib/ast/minify.js +56 -112
- package/dist/lib/ast/transform/compute.js +2 -4
- package/dist/lib/ast/transform/matrix.js +20 -20
- package/dist/lib/ast/transform/minify.js +105 -12
- package/dist/lib/ast/transform/rotate.js +11 -11
- package/dist/lib/ast/transform/scale.js +6 -6
- package/dist/lib/ast/transform/skew.js +4 -4
- package/dist/lib/ast/transform/translate.js +3 -3
- package/dist/lib/ast/transform/utils.js +30 -37
- package/dist/lib/ast/types.js +16 -4
- package/dist/lib/ast/walk.js +172 -70
- package/dist/lib/fs/resolve.js +12 -7
- package/dist/lib/parser/declaration/list.js +3 -1
- package/dist/lib/parser/parse.js +441 -161
- package/dist/lib/parser/tokenize.js +12 -14
- package/dist/lib/renderer/render.js +7 -7
- package/dist/lib/syntax/color/cmyk.js +6 -3
- package/dist/lib/syntax/color/color-mix.js +2 -3
- package/dist/lib/syntax/color/color.js +28 -6
- package/dist/lib/syntax/color/hex.js +3 -0
- package/dist/lib/syntax/color/hsl.js +18 -7
- package/dist/lib/syntax/color/hwb.js +3 -3
- package/dist/lib/syntax/color/lab.js +4 -4
- package/dist/lib/syntax/color/lch.js +7 -4
- package/dist/lib/syntax/color/oklab.js +4 -4
- package/dist/lib/syntax/color/oklch.js +18 -6
- package/dist/lib/syntax/color/relativecolor.js +9 -56
- package/dist/lib/syntax/color/srgb.js +1 -1
- package/dist/lib/syntax/syntax.js +36 -18
- package/dist/lib/validation/at-rules/container.js +11 -0
- package/dist/lib/validation/at-rules/counter-style.js +11 -0
- package/dist/lib/validation/at-rules/font-feature-values.js +11 -0
- package/dist/lib/validation/at-rules/keyframes.js +11 -0
- package/dist/lib/validation/at-rules/layer.js +11 -0
- package/dist/lib/validation/at-rules/media.js +11 -0
- package/dist/lib/validation/at-rules/page-margin-box.js +11 -0
- package/dist/lib/validation/at-rules/page.js +11 -0
- package/dist/lib/validation/at-rules/supports.js +11 -0
- package/dist/lib/validation/at-rules/when.js +11 -0
- package/dist/lib/validation/config.js +0 -2
- package/dist/lib/validation/config.json.js +21 -9
- package/dist/lib/validation/parser/parse.js +53 -2
- package/dist/lib/validation/syntax.js +199 -36
- package/dist/node.js +63 -36
- package/dist/web.js +84 -25
- package/package.json +7 -5
- package/dist/lib/validation/parser/types.js +0 -54
package/dist/lib/parser/parse.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { isIdentStart, isIdent, isIdentColor, mathFuncs, isColor, parseColor, isPseudo, pseudoElements, isAtKeyword, isFunction, isNumber, isPercentage,
|
|
1
|
+
import { isIdentStart, isIdent, isIdentColor, mathFuncs, isColor, parseColor, isPseudo, pseudoElements, isAtKeyword, isFunction, isNumber, isPercentage, parseDimension, isHexColor, isHash, mediaTypes } from '../syntax/syntax.js';
|
|
2
2
|
import { EnumToken, ColorType, ValidationLevel, SyntaxValidationResult } from '../ast/types.js';
|
|
3
|
-
import {
|
|
4
|
-
import { walkValues, walk, WalkerOptionEnum } from '../ast/walk.js';
|
|
3
|
+
import { definedPropertySettings, minify, combinators } from '../ast/minify.js';
|
|
4
|
+
import { walkValues, WalkerEvent, walk, WalkerOptionEnum } from '../ast/walk.js';
|
|
5
5
|
import { expand } from '../ast/expand.js';
|
|
6
6
|
import './utils/config.js';
|
|
7
7
|
import { parseDeclarationNode } from './utils/declaration.js';
|
|
@@ -11,14 +11,13 @@ import { funcLike, timingFunc, timelineFunc, COLORS_NAMES, systemColors, depreca
|
|
|
11
11
|
import { buildExpression } from '../ast/math/expression.js';
|
|
12
12
|
import { tokenize, tokenizeStream } from './tokenize.js';
|
|
13
13
|
import '../validation/config.js';
|
|
14
|
-
import '../validation/parser/types.js';
|
|
15
14
|
import '../validation/parser/parse.js';
|
|
16
15
|
import { validateSelector } from '../validation/selector.js';
|
|
17
16
|
import { validateAtRule } from '../validation/atrule.js';
|
|
18
17
|
import { splitTokenList } from '../validation/utils/list.js';
|
|
19
18
|
import '../validation/syntaxes/complex-selector.js';
|
|
20
19
|
import { validateKeyframeSelector } from '../validation/syntaxes/keyframe-selector.js';
|
|
21
|
-
import { evaluateSyntax } from '../validation/syntax.js';
|
|
20
|
+
import { isNodeAllowedInContext, evaluateSyntax } from '../validation/syntax.js';
|
|
22
21
|
import { validateAtRuleKeyframes } from '../validation/at-rules/keyframes.js';
|
|
23
22
|
|
|
24
23
|
const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
|
|
@@ -39,6 +38,36 @@ const enumTokenHints = new Set([
|
|
|
39
38
|
function reject(reason) {
|
|
40
39
|
throw new Error(reason ?? 'Parsing aborted');
|
|
41
40
|
}
|
|
41
|
+
function normalizeVisitorKeyName(keyName) {
|
|
42
|
+
return keyName.replace(/-([a-z])/g, (all, one) => one.toUpperCase());
|
|
43
|
+
}
|
|
44
|
+
function replaceToken(parent, value, replacement) {
|
|
45
|
+
for (const node of (Array.isArray(replacement) ? replacement : [replacement])) {
|
|
46
|
+
if ('parent' in value && value.parent != node.parent) {
|
|
47
|
+
Object.defineProperty(node, 'parent', {
|
|
48
|
+
...definedPropertySettings,
|
|
49
|
+
value: value.parent
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (parent.typ == EnumToken.BinaryExpressionTokenType) {
|
|
54
|
+
if (parent.l == value) {
|
|
55
|
+
parent.l = replacement;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
parent.r = replacement;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
const target = 'val' in parent && Array.isArray(parent.val) ? parent.val : parent.chi;
|
|
63
|
+
// @ts-ignore
|
|
64
|
+
const index = target.indexOf(value);
|
|
65
|
+
if (index == -1) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
target.splice(index, 1, ...(Array.isArray(replacement) ? replacement : [replacement]));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
42
71
|
/**
|
|
43
72
|
* parse css string
|
|
44
73
|
* @param iter
|
|
@@ -88,6 +117,8 @@ async function doParse(iter, options = {}) {
|
|
|
88
117
|
const stats = {
|
|
89
118
|
src: options.src ?? '',
|
|
90
119
|
bytesIn: 0,
|
|
120
|
+
nodesCount: 0,
|
|
121
|
+
tokensCount: 0,
|
|
91
122
|
importedBytesIn: 0,
|
|
92
123
|
parse: `0ms`,
|
|
93
124
|
minify: `0ms`,
|
|
@@ -116,14 +147,107 @@ async function doParse(iter, options = {}) {
|
|
|
116
147
|
src: ''
|
|
117
148
|
};
|
|
118
149
|
}
|
|
119
|
-
let
|
|
120
|
-
let
|
|
150
|
+
let valuesHandlers;
|
|
151
|
+
let preValuesHandlers;
|
|
152
|
+
let postValuesHandlers;
|
|
153
|
+
let preVisitorsHandlersMap;
|
|
154
|
+
let visitorsHandlersMap;
|
|
155
|
+
let postVisitorsHandlersMap;
|
|
121
156
|
const rawTokens = [];
|
|
122
157
|
const imports = [];
|
|
158
|
+
let item;
|
|
159
|
+
let node;
|
|
123
160
|
// @ts-ignore ignore error
|
|
124
|
-
|
|
161
|
+
let isAsync = typeof iter[Symbol.asyncIterator] === 'function';
|
|
162
|
+
if (options.visitor != null) {
|
|
163
|
+
valuesHandlers = new Map;
|
|
164
|
+
preValuesHandlers = new Map;
|
|
165
|
+
postValuesHandlers = new Map;
|
|
166
|
+
preVisitorsHandlersMap = new Map;
|
|
167
|
+
visitorsHandlersMap = new Map;
|
|
168
|
+
postVisitorsHandlersMap = new Map;
|
|
169
|
+
const visitors = Object.entries(options.visitor);
|
|
170
|
+
let key;
|
|
171
|
+
let value;
|
|
172
|
+
let i;
|
|
173
|
+
for (i = 0; i < visitors.length; i++) {
|
|
174
|
+
key = visitors[i][0];
|
|
175
|
+
value = visitors[i][1];
|
|
176
|
+
if (Number.isInteger(+key)) {
|
|
177
|
+
visitors.splice(i + 1, 0, ...Object.entries(value));
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (Array.isArray(value)) {
|
|
181
|
+
// @ts-ignore
|
|
182
|
+
visitors.splice(i + 1, 0, ...value.map((item) => [key, item]));
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (key in EnumToken) {
|
|
186
|
+
if (typeof value == 'function') {
|
|
187
|
+
if (!valuesHandlers.has(EnumToken[key])) {
|
|
188
|
+
valuesHandlers.set(EnumToken[key], []);
|
|
189
|
+
}
|
|
190
|
+
valuesHandlers.get(EnumToken[key]).push(value);
|
|
191
|
+
}
|
|
192
|
+
else if (typeof value == 'object' && 'type' in value && 'handler' in value && value.type in WalkerEvent) {
|
|
193
|
+
if (value.type == WalkerEvent.Enter) {
|
|
194
|
+
if (!preValuesHandlers.has(EnumToken[key])) {
|
|
195
|
+
preValuesHandlers.set(EnumToken[key], []);
|
|
196
|
+
}
|
|
197
|
+
preValuesHandlers.get(EnumToken[key]).push(value.handler);
|
|
198
|
+
}
|
|
199
|
+
else if (value.type == WalkerEvent.Leave) {
|
|
200
|
+
if (!postValuesHandlers.has(EnumToken[key])) {
|
|
201
|
+
postValuesHandlers.set(EnumToken[key], []);
|
|
202
|
+
}
|
|
203
|
+
postValuesHandlers.get(EnumToken[key]).push(value.handler);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
else if (['Declaration', 'Rule', 'AtRule', 'KeyframesRule', 'KeyframesAtRule'].includes(key)) {
|
|
211
|
+
if (typeof value == 'function') {
|
|
212
|
+
if (!visitorsHandlersMap.has(key)) {
|
|
213
|
+
visitorsHandlersMap.set(key, []);
|
|
214
|
+
}
|
|
215
|
+
visitorsHandlersMap.get(key).push(value);
|
|
216
|
+
}
|
|
217
|
+
else if (typeof value == 'object') {
|
|
218
|
+
if ('type' in value && 'handler' in value && value.type in WalkerEvent) {
|
|
219
|
+
if (value.type == WalkerEvent.Enter) {
|
|
220
|
+
if (!preVisitorsHandlersMap.has(key)) {
|
|
221
|
+
preVisitorsHandlersMap.set(key, []);
|
|
222
|
+
}
|
|
223
|
+
preVisitorsHandlersMap.get(key).push(value.handler);
|
|
224
|
+
}
|
|
225
|
+
else if (value.type == WalkerEvent.Leave) {
|
|
226
|
+
if (!postVisitorsHandlersMap.has(key)) {
|
|
227
|
+
postVisitorsHandlersMap.set(key, []);
|
|
228
|
+
}
|
|
229
|
+
postVisitorsHandlersMap.get(key).push(value.handler);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
if (!visitorsHandlersMap.has(key)) {
|
|
234
|
+
visitorsHandlersMap.set(key, []);
|
|
235
|
+
}
|
|
236
|
+
visitorsHandlersMap.get(key).push(value);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
125
248
|
while (item = isAsync ? (await iter.next()).value : iter.next().value) {
|
|
126
249
|
stats.bytesIn = item.bytesIn;
|
|
250
|
+
stats.tokensCount++;
|
|
127
251
|
rawTokens.push(item);
|
|
128
252
|
if (item.hint != null && BadTokensTypes.includes(item.hint)) {
|
|
129
253
|
const node = getTokenType(item.token, item.hint);
|
|
@@ -151,7 +275,7 @@ async function doParse(iter, options = {}) {
|
|
|
151
275
|
ast.loc.end = item.end;
|
|
152
276
|
}
|
|
153
277
|
if (item.token == ';' || item.token == '{') {
|
|
154
|
-
node = parseNode(tokens, context, options, errors, src, map, rawTokens);
|
|
278
|
+
node = parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
|
|
155
279
|
rawTokens.length = 0;
|
|
156
280
|
if (node != null) {
|
|
157
281
|
if ('chi' in node) {
|
|
@@ -195,7 +319,7 @@ async function doParse(iter, options = {}) {
|
|
|
195
319
|
map = new Map;
|
|
196
320
|
}
|
|
197
321
|
else if (item.token == '}') {
|
|
198
|
-
parseNode(tokens, context, options, errors, src, map, rawTokens);
|
|
322
|
+
parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
|
|
199
323
|
rawTokens.length = 0;
|
|
200
324
|
if (context.loc != null) {
|
|
201
325
|
context.loc.end = item.end;
|
|
@@ -216,7 +340,7 @@ async function doParse(iter, options = {}) {
|
|
|
216
340
|
}
|
|
217
341
|
}
|
|
218
342
|
if (tokens.length > 0) {
|
|
219
|
-
node = parseNode(tokens, context, options, errors, src, map, rawTokens);
|
|
343
|
+
node = parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
|
|
220
344
|
rawTokens.length = 0;
|
|
221
345
|
if (node != null) {
|
|
222
346
|
if (node.typ == EnumToken.AtRuleNodeType && node.nam == 'import') {
|
|
@@ -240,21 +364,18 @@ async function doParse(iter, options = {}) {
|
|
|
240
364
|
const token = node.tokens[0];
|
|
241
365
|
const url = token.typ == EnumToken.StringTokenType ? token.val.slice(1, -1) : token.val;
|
|
242
366
|
try {
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
// src: options.resolve!(url, options.src as string).absolute
|
|
256
|
-
// }))
|
|
257
|
-
// });
|
|
367
|
+
const result = options.load(url, options.src);
|
|
368
|
+
const stream = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction' ? await result : result;
|
|
369
|
+
const root = await doParse(stream instanceof ReadableStream ? tokenizeStream(stream) : tokenize({
|
|
370
|
+
stream,
|
|
371
|
+
buffer: '',
|
|
372
|
+
position: { ind: 0, lin: 1, col: 1 },
|
|
373
|
+
currentPosition: { ind: -1, lin: 1, col: 0 }
|
|
374
|
+
}), Object.assign({}, options, {
|
|
375
|
+
minify: false,
|
|
376
|
+
setParent: false,
|
|
377
|
+
src: options.resolve(url, options.src).absolute
|
|
378
|
+
}));
|
|
258
379
|
stats.importedBytesIn += root.stats.bytesIn;
|
|
259
380
|
stats.imports.push(root.stats);
|
|
260
381
|
node.parent.chi.splice(node.parent.chi.indexOf(node), 1, ...root.ast.chi);
|
|
@@ -282,39 +403,155 @@ async function doParse(iter, options = {}) {
|
|
|
282
403
|
if (options.expandNestingRules) {
|
|
283
404
|
ast = expand(ast);
|
|
284
405
|
}
|
|
406
|
+
let replacement;
|
|
407
|
+
let callable;
|
|
285
408
|
if (options.visitor != null) {
|
|
286
409
|
for (const result of walk(ast)) {
|
|
287
|
-
if (
|
|
288
|
-
(
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
410
|
+
if (valuesHandlers.size > 0 || preVisitorsHandlersMap.size > 0 || visitorsHandlersMap.size > 0 || postVisitorsHandlersMap.size > 0) {
|
|
411
|
+
if ((result.node.typ == EnumToken.DeclarationNodeType &&
|
|
412
|
+
(preVisitorsHandlersMap.has('Declaration') || visitorsHandlersMap.has('Declaration') || postVisitorsHandlersMap.has('Declaration'))) ||
|
|
413
|
+
(result.node.typ == EnumToken.AtRuleNodeType && (preVisitorsHandlersMap.has('AtRule') || visitorsHandlersMap.has('AtRule') || postVisitorsHandlersMap.has('AtRule'))) ||
|
|
414
|
+
(result.node.typ == EnumToken.KeyframesAtRuleNodeType && (preVisitorsHandlersMap.has('KeyframesAtRule') || visitorsHandlersMap.has('KeyframesAtRule') || postVisitorsHandlersMap.has('KeyframesAtRule')))) {
|
|
415
|
+
const handlers = [];
|
|
416
|
+
const key = result.node.typ == EnumToken.DeclarationNodeType ? 'Declaration' : result.node.typ == EnumToken.AtRuleNodeType ? 'AtRule' : 'KeyframesAtRule';
|
|
417
|
+
if (preVisitorsHandlersMap.has(key)) {
|
|
418
|
+
// @ts-ignore
|
|
419
|
+
handlers.push(...preVisitorsHandlersMap.get(key));
|
|
420
|
+
}
|
|
421
|
+
if (visitorsHandlersMap.has(key)) {
|
|
422
|
+
// @ts-ignore
|
|
423
|
+
handlers.push(...visitorsHandlersMap.get(key));
|
|
424
|
+
}
|
|
425
|
+
if (postVisitorsHandlersMap.has(key)) {
|
|
426
|
+
// @ts-ignore
|
|
427
|
+
handlers.push(...postVisitorsHandlersMap.get(key));
|
|
428
|
+
}
|
|
429
|
+
let node = result.node;
|
|
430
|
+
for (const handler of handlers) {
|
|
431
|
+
callable = typeof handler == 'function' ? handler : handler[normalizeVisitorKeyName(node.typ == EnumToken.DeclarationNodeType || node.typ == EnumToken.AtRuleNodeType ? node.nam : node.val)];
|
|
432
|
+
if (callable == null) {
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
replacement = callable(node, result.parent);
|
|
436
|
+
if (replacement == null) {
|
|
437
|
+
continue;
|
|
438
|
+
}
|
|
439
|
+
isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
|
|
440
|
+
if (replacement) {
|
|
441
|
+
replacement = await replacement;
|
|
442
|
+
}
|
|
443
|
+
if (replacement == null || replacement == node) {
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
// @ts-ignore
|
|
447
|
+
node = replacement;
|
|
448
|
+
//
|
|
449
|
+
if (Array.isArray(node)) {
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
if (node != result.node) {
|
|
454
|
+
// @ts-ignore
|
|
455
|
+
replaceToken(result.parent, result.node, node);
|
|
456
|
+
}
|
|
294
457
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
458
|
+
else if ((result.node.typ == EnumToken.RuleNodeType && (preVisitorsHandlersMap.has('Rule') || visitorsHandlersMap.has('Rule') || postVisitorsHandlersMap.has('Rule'))) ||
|
|
459
|
+
(result.node.typ == EnumToken.KeyFramesRuleNodeType && (preVisitorsHandlersMap.has('KeyframesRule') || visitorsHandlersMap.has('KeyframesRule') || postVisitorsHandlersMap.has('KeyframesRule')))) {
|
|
460
|
+
const handlers = [];
|
|
461
|
+
const key = result.node.typ == EnumToken.RuleNodeType ? 'Rule' : 'KeyframesRule';
|
|
462
|
+
if (preVisitorsHandlersMap.has(key)) {
|
|
463
|
+
handlers.push(...preVisitorsHandlersMap.get(key));
|
|
464
|
+
}
|
|
465
|
+
if (visitorsHandlersMap.has(key)) {
|
|
466
|
+
handlers.push(...visitorsHandlersMap.get(key));
|
|
467
|
+
}
|
|
468
|
+
if (postVisitorsHandlersMap.has(key)) {
|
|
469
|
+
handlers.push(...postVisitorsHandlersMap.get(key));
|
|
470
|
+
}
|
|
471
|
+
let node = result.node;
|
|
472
|
+
for (const callable of handlers) {
|
|
473
|
+
replacement = callable(node, result.parent);
|
|
474
|
+
if (replacement == null) {
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
477
|
+
isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
|
|
478
|
+
if (replacement) {
|
|
479
|
+
replacement = await replacement;
|
|
480
|
+
}
|
|
481
|
+
if (replacement == null || replacement == node) {
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
// @ts-ignore
|
|
485
|
+
node = replacement;
|
|
486
|
+
//
|
|
487
|
+
if (Array.isArray(node)) {
|
|
488
|
+
break;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
// @ts-ignore
|
|
492
|
+
if (node != result.node) {
|
|
493
|
+
// @ts-ignore
|
|
494
|
+
replaceToken(result.parent, result.node, node);
|
|
495
|
+
}
|
|
303
496
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
497
|
+
else if (valuesHandlers.size > 0) {
|
|
498
|
+
let node = null;
|
|
499
|
+
node = result.node;
|
|
500
|
+
if (valuesHandlers.has(node.typ)) {
|
|
501
|
+
for (const valueHandler of valuesHandlers.get(node.typ)) {
|
|
502
|
+
callable = valueHandler;
|
|
503
|
+
replacement = callable(node, result.parent);
|
|
504
|
+
if (replacement == null) {
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
|
|
508
|
+
if (isAsync) {
|
|
509
|
+
replacement = await replacement;
|
|
510
|
+
}
|
|
511
|
+
if (replacement != null && replacement != node) {
|
|
512
|
+
node = replacement;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
if (node != result.node) {
|
|
517
|
+
// @ts-ignore
|
|
518
|
+
replaceToken(result.parent, value, node);
|
|
519
|
+
}
|
|
520
|
+
const tokens = 'tokens' in result.node ? result.node.tokens : [];
|
|
521
|
+
if ('val' in result.node && Array.isArray(result.node.val)) {
|
|
522
|
+
tokens.push(...result.node.val);
|
|
523
|
+
}
|
|
524
|
+
if (tokens.length == 0) {
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
for (const { value, parent, root } of walkValues(tokens, result.node)) {
|
|
528
|
+
node = value;
|
|
529
|
+
if (valuesHandlers.has(node.typ)) {
|
|
530
|
+
for (const valueHandler of valuesHandlers.get(node.typ)) {
|
|
531
|
+
callable = valueHandler;
|
|
532
|
+
let result = callable(node, parent, root);
|
|
533
|
+
if (result == null) {
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
536
|
+
isAsync = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction';
|
|
537
|
+
if (isAsync) {
|
|
538
|
+
result = await result;
|
|
539
|
+
}
|
|
540
|
+
if (result != null && result != node) {
|
|
541
|
+
node = result;
|
|
542
|
+
}
|
|
543
|
+
//
|
|
544
|
+
if (Array.isArray(node)) {
|
|
545
|
+
break;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
if (node != value) {
|
|
550
|
+
// @ts-ignore
|
|
551
|
+
replaceToken(parent, value, node);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
315
554
|
}
|
|
316
|
-
// @ts-ignore
|
|
317
|
-
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
318
555
|
}
|
|
319
556
|
}
|
|
320
557
|
}
|
|
@@ -352,7 +589,7 @@ function getLastNode(context) {
|
|
|
352
589
|
}
|
|
353
590
|
return null;
|
|
354
591
|
}
|
|
355
|
-
function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
592
|
+
function parseNode(results, context, options, errors, src, map, rawTokens, stats) {
|
|
356
593
|
let tokens = [];
|
|
357
594
|
for (const t of results) {
|
|
358
595
|
const node = getTokenType(t.token, t.hint);
|
|
@@ -374,11 +611,13 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
374
611
|
continue;
|
|
375
612
|
}
|
|
376
613
|
loc = location;
|
|
377
|
-
// @ts-ignore
|
|
378
614
|
context.chi.push(tokens[i]);
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
615
|
+
stats.nodesCount++;
|
|
616
|
+
Object.defineProperty(tokens[i], 'loc', {
|
|
617
|
+
...definedPropertySettings,
|
|
618
|
+
value: loc,
|
|
619
|
+
enumerable: options.sourcemap !== false
|
|
620
|
+
});
|
|
382
621
|
}
|
|
383
622
|
else if (tokens[i].typ != EnumToken.WhitespaceTokenType) {
|
|
384
623
|
break;
|
|
@@ -408,9 +647,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
408
647
|
rawTokens.shift();
|
|
409
648
|
if (atRule.val == 'import') {
|
|
410
649
|
// only @charset and @layer are accepted before @import
|
|
411
|
-
// @ts-ignore
|
|
412
650
|
if (context.chi.length > 0) {
|
|
413
|
-
// @ts-ignore
|
|
414
651
|
let i = context.chi.length;
|
|
415
652
|
while (i--) {
|
|
416
653
|
// @ts-ignore
|
|
@@ -419,11 +656,8 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
419
656
|
continue;
|
|
420
657
|
}
|
|
421
658
|
if (type != EnumToken.AtRuleNodeType) {
|
|
422
|
-
// @ts-ignore
|
|
423
659
|
if (!(type == EnumToken.InvalidAtRuleTokenType &&
|
|
424
|
-
// @ts-ignore
|
|
425
660
|
['charset', 'layer', 'import'].includes(context.chi[i].nam))) {
|
|
426
|
-
// @ts-ignore
|
|
427
661
|
errors.push({
|
|
428
662
|
action: 'drop',
|
|
429
663
|
message: 'invalid @import',
|
|
@@ -434,7 +668,6 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
434
668
|
return null;
|
|
435
669
|
}
|
|
436
670
|
}
|
|
437
|
-
// @ts-ignore
|
|
438
671
|
const name = context.chi[i].nam;
|
|
439
672
|
if (name != 'charset' && name != 'import' && name != 'layer') {
|
|
440
673
|
errors.push({ action: 'drop', message: 'invalid @import', location });
|
|
@@ -525,14 +758,14 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
525
758
|
}
|
|
526
759
|
}
|
|
527
760
|
const t = parseAtRulePrelude(parseTokens(tokens, { minify: options.minify }), atRule);
|
|
528
|
-
const raw =
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
}
|
|
761
|
+
const raw = [];
|
|
762
|
+
for (const curr of t) {
|
|
763
|
+
raw.push(renderToken(curr, { removeComments: true, convertColor: false }));
|
|
764
|
+
}
|
|
532
765
|
const nam = renderToken(atRule, { removeComments: true });
|
|
533
766
|
// @ts-ignore
|
|
534
767
|
const node = {
|
|
535
|
-
typ: /^(-[a-z]+-)?keyframes$/.test(nam) ? EnumToken.
|
|
768
|
+
typ: /^(-[a-z]+-)?keyframes$/.test(nam) ? EnumToken.KeyframesAtRuleNodeType : EnumToken.AtRuleNodeType,
|
|
536
769
|
nam,
|
|
537
770
|
val: raw.join('')
|
|
538
771
|
};
|
|
@@ -544,10 +777,12 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
544
777
|
node.chi = [];
|
|
545
778
|
}
|
|
546
779
|
loc = map.get(atRule);
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
780
|
+
Object.defineProperty(node, 'loc', {
|
|
781
|
+
...definedPropertySettings,
|
|
782
|
+
value: loc,
|
|
783
|
+
enumerable: options.sourcemap !== false
|
|
784
|
+
});
|
|
785
|
+
node.loc.end = { ...map.get(delim).end };
|
|
551
786
|
let isValid = true;
|
|
552
787
|
if (node.nam == 'else') {
|
|
553
788
|
const prev = getLastNode(context);
|
|
@@ -561,20 +796,31 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
561
796
|
}
|
|
562
797
|
}
|
|
563
798
|
// @ts-ignore
|
|
564
|
-
const
|
|
799
|
+
const skipValidate = (options.validation & ValidationLevel.AtRule) == 0;
|
|
800
|
+
const isAllowed = skipValidate || isNodeAllowedInContext(node, context);
|
|
801
|
+
// @ts-ignore
|
|
802
|
+
const valid = skipValidate ? {
|
|
565
803
|
valid: SyntaxValidationResult.Valid,
|
|
566
804
|
error: '',
|
|
567
805
|
node,
|
|
568
806
|
syntax: '@' + node.nam
|
|
569
|
-
} :
|
|
807
|
+
} : !isAllowed ? {
|
|
808
|
+
valid: SyntaxValidationResult.Drop,
|
|
809
|
+
node,
|
|
810
|
+
syntax: '@' + node.nam,
|
|
811
|
+
error: `${EnumToken[context.typ]}: child ${EnumToken[node.typ]} not allowed in context${context.typ == EnumToken.AtRuleNodeType ? ` '@${context.nam}'` : context.typ == EnumToken.StyleSheetNodeType ? ` 'stylesheet'` : ''}`} : isValid ? (node.typ == EnumToken.KeyframesAtRuleNodeType ? validateAtRuleKeyframes(node) : validateAtRule(node, options, context)) : {
|
|
570
812
|
valid: SyntaxValidationResult.Drop,
|
|
571
813
|
node,
|
|
572
814
|
syntax: '@' + node.nam,
|
|
573
815
|
error: '@' + node.nam + ' not allowed here'};
|
|
574
816
|
if (valid.valid == SyntaxValidationResult.Drop) {
|
|
817
|
+
let message = '';
|
|
818
|
+
for (const token of tokens) {
|
|
819
|
+
message += renderToken(token, { minify: false });
|
|
820
|
+
}
|
|
575
821
|
errors.push({
|
|
576
822
|
action: 'drop',
|
|
577
|
-
message: valid.error + ' - "' +
|
|
823
|
+
message: valid.error + ' - "' + message + '"',
|
|
578
824
|
node,
|
|
579
825
|
// @ts-ignore
|
|
580
826
|
location: { src, ...(map.get(valid.node) ?? location) }
|
|
@@ -583,13 +829,17 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
583
829
|
node.typ = EnumToken.InvalidAtRuleTokenType;
|
|
584
830
|
}
|
|
585
831
|
else {
|
|
586
|
-
node.val =
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
832
|
+
node.val = '';
|
|
833
|
+
for (const token of node.tokens) {
|
|
834
|
+
node.val += renderToken(token, {
|
|
835
|
+
minify: false,
|
|
836
|
+
convertColor: false,
|
|
837
|
+
removeComments: true
|
|
838
|
+
});
|
|
839
|
+
}
|
|
591
840
|
}
|
|
592
841
|
context.chi.push(node);
|
|
842
|
+
stats.nodesCount++;
|
|
593
843
|
Object.defineProperties(node, {
|
|
594
844
|
parent: { ...definedPropertySettings, value: context },
|
|
595
845
|
validSyntax: { ...definedPropertySettings, value: valid.valid == SyntaxValidationResult.Valid }
|
|
@@ -602,7 +852,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
602
852
|
const location = map.get(tokens[0]);
|
|
603
853
|
const uniq = new Map;
|
|
604
854
|
parseTokens(tokens, { minify: true });
|
|
605
|
-
const ruleType = context.typ == EnumToken.
|
|
855
|
+
const ruleType = context.typ == EnumToken.KeyframesAtRuleNodeType ? EnumToken.KeyFramesRuleNodeType : EnumToken.RuleNodeType;
|
|
606
856
|
if (ruleType == EnumToken.RuleNodeType) {
|
|
607
857
|
parseSelector(tokens);
|
|
608
858
|
}
|
|
@@ -612,6 +862,34 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
612
862
|
if (curr.typ == EnumToken.CommentTokenType) {
|
|
613
863
|
return acc;
|
|
614
864
|
}
|
|
865
|
+
if (options.minify) {
|
|
866
|
+
if (curr.typ == EnumToken.PseudoClassFuncTokenType && curr.val == ':nth-child') {
|
|
867
|
+
let i = 0;
|
|
868
|
+
for (; i < curr.chi.length; i++) {
|
|
869
|
+
if (curr.chi[i].typ == EnumToken.IdenTokenType && curr.chi[i].val == 'even') {
|
|
870
|
+
Object.assign(curr.chi[i], {
|
|
871
|
+
typ: EnumToken.Dimension,
|
|
872
|
+
val: 2,
|
|
873
|
+
unit: 'n'
|
|
874
|
+
});
|
|
875
|
+
}
|
|
876
|
+
else if (curr.chi[i].typ == EnumToken.Dimension &&
|
|
877
|
+
curr.chi[i].val == 2 &&
|
|
878
|
+
curr.chi[i].unit == 'n' &&
|
|
879
|
+
curr.chi[i + 1]?.typ == EnumToken.WhitespaceTokenType &&
|
|
880
|
+
curr.chi[i + 2]?.typ == EnumToken.LiteralTokenType &&
|
|
881
|
+
curr.chi[i + 2].val == '+' &&
|
|
882
|
+
curr.chi[i + 3]?.typ == EnumToken.WhitespaceTokenType &&
|
|
883
|
+
curr.chi[i + 4]?.typ == EnumToken.NumberTokenType &&
|
|
884
|
+
curr.chi[i + 4].val == 1) {
|
|
885
|
+
curr.chi.splice(i, 5, Object.assign(curr.chi[i], {
|
|
886
|
+
typ: EnumToken.IdenTokenType,
|
|
887
|
+
val: 'odd'
|
|
888
|
+
}));
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
}
|
|
615
893
|
if (curr.typ == EnumToken.WhitespaceTokenType) {
|
|
616
894
|
if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
|
|
617
895
|
trimWhiteSpace.includes(array[index + 1]?.typ) ||
|
|
@@ -620,7 +898,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
620
898
|
return acc;
|
|
621
899
|
}
|
|
622
900
|
}
|
|
623
|
-
if (ruleType == EnumToken.
|
|
901
|
+
if (ruleType == EnumToken.KeyFramesRuleNodeType && options.minify) {
|
|
624
902
|
if (curr.typ == EnumToken.IdenTokenType && curr.val == 'from') {
|
|
625
903
|
Object.assign(curr, { typ: EnumToken.PercentageTokenType, val: '0' });
|
|
626
904
|
}
|
|
@@ -659,17 +937,24 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
659
937
|
value: tokens.slice()
|
|
660
938
|
});
|
|
661
939
|
loc = location;
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
940
|
+
Object.defineProperty(node, 'loc', {
|
|
941
|
+
...definedPropertySettings,
|
|
942
|
+
value: loc,
|
|
943
|
+
enumerable: options.sourcemap !== false
|
|
944
|
+
});
|
|
666
945
|
context.chi.push(node);
|
|
667
946
|
Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: context });
|
|
668
947
|
// @ts-ignore
|
|
669
|
-
const
|
|
948
|
+
const skipValidate = (options.validation & ValidationLevel.Selector) == 0;
|
|
949
|
+
const isAllowed = skipValidate || isNodeAllowedInContext(node, context);
|
|
950
|
+
// @ts-ignore
|
|
951
|
+
const valid = skipValidate ? {
|
|
670
952
|
valid: SyntaxValidationResult.Valid,
|
|
671
953
|
error: null
|
|
672
|
-
} :
|
|
954
|
+
} : !isAllowed ? {
|
|
955
|
+
valid: SyntaxValidationResult.Drop,
|
|
956
|
+
error: `${EnumToken[context.typ]}: child ${EnumToken[node.typ]} not allowed in context${context.typ == EnumToken.AtRuleNodeType ? ` '@${context.nam}'` : context.typ == EnumToken.StyleSheetNodeType ? ` 'stylesheet'` : ''}`
|
|
957
|
+
} : ruleType == EnumToken.KeyFramesRuleNodeType ? validateKeyframeSelector(tokens) : validateSelector(tokens, options, context);
|
|
673
958
|
if (valid.valid != SyntaxValidationResult.Valid) {
|
|
674
959
|
// @ts-ignore
|
|
675
960
|
node.typ = EnumToken.InvalidRuleTokenType;
|
|
@@ -778,11 +1063,13 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
778
1063
|
nam,
|
|
779
1064
|
val: []
|
|
780
1065
|
};
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
1066
|
+
Object.defineProperty(node, 'loc', {
|
|
1067
|
+
...definedPropertySettings,
|
|
1068
|
+
value: location,
|
|
1069
|
+
enumerable: options.sourcemap !== false
|
|
1070
|
+
});
|
|
785
1071
|
context.chi.push(node);
|
|
1072
|
+
stats.nodesCount++;
|
|
786
1073
|
}
|
|
787
1074
|
return null;
|
|
788
1075
|
}
|
|
@@ -806,22 +1093,31 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
806
1093
|
nam,
|
|
807
1094
|
val: value
|
|
808
1095
|
};
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
1096
|
+
Object.defineProperty(node, 'loc', {
|
|
1097
|
+
...definedPropertySettings,
|
|
1098
|
+
value: location,
|
|
1099
|
+
enumerable: options.sourcemap !== false
|
|
1100
|
+
});
|
|
1101
|
+
node.loc.end = { ...map.get(delim).end };
|
|
813
1102
|
// do not allow declarations in style sheets
|
|
814
1103
|
if (context.typ == EnumToken.StyleSheetNodeType && options.lenient) {
|
|
815
|
-
|
|
816
|
-
node.typ = EnumToken.InvalidDeclarationNodeType;
|
|
1104
|
+
Object.assign(node, { typ: EnumToken.InvalidDeclarationNodeType });
|
|
817
1105
|
context.chi.push(node);
|
|
1106
|
+
stats.nodesCount++;
|
|
818
1107
|
return null;
|
|
819
1108
|
}
|
|
820
1109
|
const result = parseDeclarationNode(node, errors, location);
|
|
821
1110
|
Object.defineProperty(result, 'parent', { ...definedPropertySettings, value: context });
|
|
822
1111
|
if (result != null) {
|
|
823
|
-
if (options.validation
|
|
824
|
-
const
|
|
1112
|
+
if (options.validation & ValidationLevel.Declaration) {
|
|
1113
|
+
const isAllowed = isNodeAllowedInContext(node, context);
|
|
1114
|
+
// @ts-ignore
|
|
1115
|
+
const valid = !isAllowed ? {
|
|
1116
|
+
valid: SyntaxValidationResult.Drop,
|
|
1117
|
+
error: `${EnumToken[node.typ]} not allowed in context${context.typ == EnumToken.AtRuleNodeType ? ` '@${context.nam}'` : context.typ == EnumToken.StyleSheetNodeType ? ` 'stylesheet'` : ''}`,
|
|
1118
|
+
node,
|
|
1119
|
+
syntax: null
|
|
1120
|
+
} : evaluateSyntax(result, context, options);
|
|
825
1121
|
Object.defineProperty(result, 'validSyntax', {
|
|
826
1122
|
...definedPropertySettings,
|
|
827
1123
|
value: valid.valid == SyntaxValidationResult.Valid
|
|
@@ -837,11 +1133,11 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
837
1133
|
if (!options.lenient) {
|
|
838
1134
|
return null;
|
|
839
1135
|
}
|
|
840
|
-
|
|
841
|
-
node.typ = EnumToken.InvalidDeclarationNodeType;
|
|
1136
|
+
Object.assign(node, { typ: EnumToken.InvalidDeclarationNodeType });
|
|
842
1137
|
}
|
|
843
1138
|
}
|
|
844
1139
|
context.chi.push(result);
|
|
1140
|
+
stats.nodesCount++;
|
|
845
1141
|
}
|
|
846
1142
|
return null;
|
|
847
1143
|
}
|
|
@@ -853,7 +1149,6 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
853
1149
|
* @param atRule
|
|
854
1150
|
*/
|
|
855
1151
|
function parseAtRulePrelude(tokens, atRule) {
|
|
856
|
-
// @ts-ignore
|
|
857
1152
|
for (const { value, parent } of walkValues(tokens, null, null, true)) {
|
|
858
1153
|
if (value.typ == EnumToken.CommentTokenType ||
|
|
859
1154
|
value.typ == EnumToken.WhitespaceTokenType ||
|
|
@@ -889,16 +1184,14 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
889
1184
|
}
|
|
890
1185
|
if (atRule.val == 'page' && value.typ == EnumToken.PseudoClassTokenType) {
|
|
891
1186
|
if ([':left', ':right', ':first', ':blank'].includes(value.val)) {
|
|
892
|
-
|
|
893
|
-
value.typ = EnumToken.PseudoPageTokenType;
|
|
1187
|
+
Object.assign(value, { typ: EnumToken.PseudoPageTokenType });
|
|
894
1188
|
}
|
|
895
1189
|
}
|
|
896
1190
|
if (atRule.val == 'layer') {
|
|
897
1191
|
if (parent == null && value.typ == EnumToken.LiteralTokenType) {
|
|
898
1192
|
if (value.val.charAt(0) == '.') {
|
|
899
1193
|
if (isIdent(value.val.slice(1))) {
|
|
900
|
-
|
|
901
|
-
value.typ = EnumToken.ClassSelectorTokenType;
|
|
1194
|
+
Object.assign(value, { typ: EnumToken.ClassSelectorTokenType });
|
|
902
1195
|
}
|
|
903
1196
|
}
|
|
904
1197
|
}
|
|
@@ -907,8 +1200,7 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
907
1200
|
if (value.typ == EnumToken.IdenTokenType) {
|
|
908
1201
|
if (parent == null && mediaTypes.some((t) => {
|
|
909
1202
|
if (val === t) {
|
|
910
|
-
|
|
911
|
-
value.typ = EnumToken.MediaFeatureTokenType;
|
|
1203
|
+
Object.assign(value, { typ: EnumToken.MediaFeatureTokenType });
|
|
912
1204
|
return true;
|
|
913
1205
|
}
|
|
914
1206
|
return false;
|
|
@@ -916,18 +1208,15 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
916
1208
|
continue;
|
|
917
1209
|
}
|
|
918
1210
|
if (value.typ == EnumToken.IdenTokenType && 'and' === val) {
|
|
919
|
-
|
|
920
|
-
value.typ = EnumToken.MediaFeatureAndTokenType;
|
|
1211
|
+
Object.assign(value, { typ: EnumToken.MediaFeatureAndTokenType });
|
|
921
1212
|
continue;
|
|
922
1213
|
}
|
|
923
1214
|
if (value.typ == EnumToken.IdenTokenType && 'or' === val) {
|
|
924
|
-
|
|
925
|
-
value.typ = EnumToken.MediaFeatureOrTokenType;
|
|
1215
|
+
Object.assign(value, { typ: EnumToken.MediaFeatureOrTokenType });
|
|
926
1216
|
continue;
|
|
927
1217
|
}
|
|
928
1218
|
if (value.typ == EnumToken.IdenTokenType &&
|
|
929
1219
|
['not', 'only'].some((t) => val === t)) {
|
|
930
|
-
// @ts-ignore
|
|
931
1220
|
const array = parent?.chi ?? tokens;
|
|
932
1221
|
const startIndex = array.indexOf(value);
|
|
933
1222
|
let index = startIndex + 1;
|
|
@@ -972,12 +1261,15 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
972
1261
|
if (value.chi[i].typ == EnumToken.CommentTokenType || value.chi[i].typ == EnumToken.WhitespaceTokenType) {
|
|
973
1262
|
continue;
|
|
974
1263
|
}
|
|
975
|
-
if (value.chi[i].typ == EnumToken.LiteralTokenType && value.chi[i].val.startsWith(':')
|
|
976
|
-
value.chi.
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1264
|
+
if (value.chi[i].typ == EnumToken.LiteralTokenType && value.chi[i].val.startsWith(':')) {
|
|
1265
|
+
const dimension = parseDimension(value.chi[i].val.slice(1));
|
|
1266
|
+
if (dimension != null) {
|
|
1267
|
+
value.chi.splice(i, 1, {
|
|
1268
|
+
typ: EnumToken.ColonTokenType,
|
|
1269
|
+
}, Object.assign(value.chi[i], dimension));
|
|
1270
|
+
i--;
|
|
1271
|
+
continue;
|
|
1272
|
+
}
|
|
981
1273
|
}
|
|
982
1274
|
if (nameIndex != -1 && value.chi[i].typ == EnumToken.PseudoClassTokenType) {
|
|
983
1275
|
value.chi.splice(i, 1, {
|
|
@@ -1004,11 +1296,10 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
1004
1296
|
const val = value.chi.splice(valueIndex, 1)[0];
|
|
1005
1297
|
const node = value.chi.splice(nameIndex, 1)[0];
|
|
1006
1298
|
// 'background'
|
|
1007
|
-
// @ts-ignore
|
|
1008
1299
|
if (node.typ == EnumToken.ColorTokenType && node.kin == ColorType.DPSYS) {
|
|
1300
|
+
Object.assign(node, { typ: EnumToken.IdenTokenType });
|
|
1009
1301
|
// @ts-ignore
|
|
1010
1302
|
delete node.kin;
|
|
1011
|
-
node.typ = EnumToken.IdenTokenType;
|
|
1012
1303
|
}
|
|
1013
1304
|
while (value.chi[0]?.typ == EnumToken.WhitespaceTokenType) {
|
|
1014
1305
|
value.chi.shift();
|
|
@@ -1045,7 +1336,7 @@ async function parseDeclarations(declaration) {
|
|
|
1045
1336
|
position: { ind: 0, lin: 1, col: 1 },
|
|
1046
1337
|
currentPosition: { ind: -1, lin: 1, col: 0 }
|
|
1047
1338
|
}), { setParent: false, minify: false, validation: false }).then(result => {
|
|
1048
|
-
return result.ast.chi[0].chi.filter(t => t.typ == EnumToken.DeclarationNodeType);
|
|
1339
|
+
return result.ast.chi[0].chi.filter(t => t.typ == EnumToken.DeclarationNodeType || t.typ == EnumToken.CommentNodeType);
|
|
1049
1340
|
});
|
|
1050
1341
|
}
|
|
1051
1342
|
/**
|
|
@@ -1063,43 +1354,35 @@ function parseSelector(tokens) {
|
|
|
1063
1354
|
}
|
|
1064
1355
|
if (parent == null) {
|
|
1065
1356
|
if (value.typ == EnumToken.GtTokenType) {
|
|
1066
|
-
|
|
1067
|
-
value.typ = EnumToken.ChildCombinatorTokenType;
|
|
1357
|
+
Object.assign(value, { typ: EnumToken.ChildCombinatorTokenType });
|
|
1068
1358
|
}
|
|
1069
1359
|
else if (value.typ == EnumToken.LiteralTokenType) {
|
|
1070
1360
|
if (value.val.charAt(0) == '&') {
|
|
1071
|
-
|
|
1072
|
-
value.typ = EnumToken.NestingSelectorTokenType;
|
|
1361
|
+
Object.assign(value, { typ: EnumToken.NestingSelectorTokenType });
|
|
1073
1362
|
// @ts-ignore
|
|
1074
1363
|
delete value.val;
|
|
1075
1364
|
}
|
|
1076
1365
|
else if (value.val.charAt(0) == '.') {
|
|
1077
1366
|
if (!isIdent(value.val.slice(1))) {
|
|
1078
|
-
|
|
1079
|
-
value.typ = EnumToken.InvalidClassSelectorTokenType;
|
|
1367
|
+
Object.assign(value, { typ: EnumToken.InvalidClassSelectorTokenType });
|
|
1080
1368
|
}
|
|
1081
1369
|
else {
|
|
1082
|
-
|
|
1083
|
-
value.typ = EnumToken.ClassSelectorTokenType;
|
|
1370
|
+
Object.assign(value, { typ: EnumToken.ClassSelectorTokenType });
|
|
1084
1371
|
}
|
|
1085
1372
|
}
|
|
1086
1373
|
if (['*', '>', '+', '~'].includes(value.val)) {
|
|
1087
1374
|
switch (value.val) {
|
|
1088
1375
|
case '*':
|
|
1089
|
-
|
|
1090
|
-
value.typ = EnumToken.UniversalSelectorTokenType;
|
|
1376
|
+
Object.assign(value, { typ: EnumToken.UniversalSelectorTokenType });
|
|
1091
1377
|
break;
|
|
1092
1378
|
case '>':
|
|
1093
|
-
|
|
1094
|
-
value.typ = EnumToken.ChildCombinatorTokenType;
|
|
1379
|
+
Object.assign(value, { typ: EnumToken.ChildCombinatorTokenType });
|
|
1095
1380
|
break;
|
|
1096
1381
|
case '+':
|
|
1097
|
-
|
|
1098
|
-
value.typ = EnumToken.NextSiblingCombinatorTokenType;
|
|
1382
|
+
Object.assign(value, { typ: EnumToken.NextSiblingCombinatorTokenType });
|
|
1099
1383
|
break;
|
|
1100
1384
|
case '~':
|
|
1101
|
-
|
|
1102
|
-
value.typ = EnumToken.SubsequentSiblingCombinatorTokenType;
|
|
1385
|
+
Object.assign(value, { typ: EnumToken.SubsequentSiblingCombinatorTokenType });
|
|
1103
1386
|
break;
|
|
1104
1387
|
}
|
|
1105
1388
|
// @ts-ignore
|
|
@@ -1112,12 +1395,10 @@ function parseSelector(tokens) {
|
|
|
1112
1395
|
if (!isIdent(value.val.slice(1))) {
|
|
1113
1396
|
continue;
|
|
1114
1397
|
}
|
|
1115
|
-
|
|
1116
|
-
value.typ = EnumToken.HashTokenType;
|
|
1398
|
+
Object.assign(value, { typ: EnumToken.HashTokenType });
|
|
1117
1399
|
}
|
|
1118
1400
|
else {
|
|
1119
|
-
|
|
1120
|
-
value.typ = EnumToken.IdenTokenType;
|
|
1401
|
+
Object.assign(value, { typ: EnumToken.IdenTokenType });
|
|
1121
1402
|
}
|
|
1122
1403
|
// @ts-ignore
|
|
1123
1404
|
delete value.kin;
|
|
@@ -1180,15 +1461,17 @@ function parseString(src, options = { location: false }) {
|
|
|
1180
1461
|
return acc;
|
|
1181
1462
|
}
|
|
1182
1463
|
const token = getTokenType(t.token, t.hint);
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1464
|
+
Object.defineProperty(token, 'loc', {
|
|
1465
|
+
...definedPropertySettings,
|
|
1466
|
+
value: { sta: t.sta },
|
|
1467
|
+
enumerable: options.location !== false
|
|
1468
|
+
});
|
|
1186
1469
|
acc.push(token);
|
|
1187
1470
|
return acc;
|
|
1188
1471
|
}, []));
|
|
1189
1472
|
}
|
|
1190
1473
|
/**
|
|
1191
|
-
* get token type from a string
|
|
1474
|
+
* get the token type from a string
|
|
1192
1475
|
* @param val
|
|
1193
1476
|
* @param hint
|
|
1194
1477
|
*/
|
|
@@ -1224,7 +1507,7 @@ function getTokenType(val, hint) {
|
|
|
1224
1507
|
case '>':
|
|
1225
1508
|
return { typ: EnumToken.GtTokenType };
|
|
1226
1509
|
}
|
|
1227
|
-
if (isPseudo(val)) {
|
|
1510
|
+
if (val.charAt(0) == ':' && isPseudo(val)) {
|
|
1228
1511
|
return val.endsWith('(') ? {
|
|
1229
1512
|
typ: EnumToken.PseudoClassFuncTokenType,
|
|
1230
1513
|
val: val.slice(0, -1),
|
|
@@ -1241,13 +1524,13 @@ function getTokenType(val, hint) {
|
|
|
1241
1524
|
val
|
|
1242
1525
|
});
|
|
1243
1526
|
}
|
|
1244
|
-
if (isAtKeyword(val)) {
|
|
1527
|
+
if (val.charAt(0) == '@' && isAtKeyword(val)) {
|
|
1245
1528
|
return {
|
|
1246
1529
|
typ: EnumToken.AtRuleTokenType,
|
|
1247
1530
|
val: val.slice(1)
|
|
1248
1531
|
};
|
|
1249
1532
|
}
|
|
1250
|
-
if (isFunction(val)) {
|
|
1533
|
+
if (val.endsWith('(') && isFunction(val)) {
|
|
1251
1534
|
val = val.slice(0, -1);
|
|
1252
1535
|
if (val == 'url') {
|
|
1253
1536
|
return {
|
|
@@ -1295,15 +1578,12 @@ function getTokenType(val, hint) {
|
|
|
1295
1578
|
val: +val.slice(0, -1)
|
|
1296
1579
|
};
|
|
1297
1580
|
}
|
|
1298
|
-
if (
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
};
|
|
1303
|
-
}
|
|
1304
|
-
if (isDimension(val)) {
|
|
1305
|
-
return parseDimension(val);
|
|
1581
|
+
// if (isDimension(val)) {
|
|
1582
|
+
const dimension = parseDimension(val);
|
|
1583
|
+
if (dimension != null) {
|
|
1584
|
+
return dimension;
|
|
1306
1585
|
}
|
|
1586
|
+
// }
|
|
1307
1587
|
const v = val.toLowerCase();
|
|
1308
1588
|
if (v == 'currentcolor' || v == 'transparent' || v in COLORS_NAMES) {
|
|
1309
1589
|
return {
|
|
@@ -1662,4 +1942,4 @@ function parseTokens(tokens, options = {}) {
|
|
|
1662
1942
|
return tokens;
|
|
1663
1943
|
}
|
|
1664
1944
|
|
|
1665
|
-
export { doParse, getTokenType, parseAtRulePrelude, parseDeclarations, parseSelector, parseString, parseTokens, urlTokenMatcher };
|
|
1945
|
+
export { doParse, getTokenType, parseAtRulePrelude, parseDeclarations, parseSelector, parseString, parseTokens, replaceToken, urlTokenMatcher };
|