@tbela99/css-parser 1.3.3 → 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.
Files changed (46) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +20 -17
  3. package/dist/index-umd-web.js +1031 -571
  4. package/dist/index.cjs +1031 -566
  5. package/dist/index.d.ts +247 -171
  6. package/dist/lib/ast/expand.js +5 -10
  7. package/dist/lib/ast/features/calc.js +3 -2
  8. package/dist/lib/ast/features/inlinecssvariables.js +5 -3
  9. package/dist/lib/ast/features/prefix.js +1 -1
  10. package/dist/lib/ast/features/shorthand.js +1 -0
  11. package/dist/lib/ast/features/transform.js +13 -19
  12. package/dist/lib/ast/minify.js +5 -2
  13. package/dist/lib/ast/transform/compute.js +2 -4
  14. package/dist/lib/ast/transform/matrix.js +20 -20
  15. package/dist/lib/ast/transform/minify.js +105 -12
  16. package/dist/lib/ast/transform/rotate.js +11 -11
  17. package/dist/lib/ast/transform/scale.js +6 -6
  18. package/dist/lib/ast/transform/skew.js +4 -4
  19. package/dist/lib/ast/transform/translate.js +3 -3
  20. package/dist/lib/ast/transform/utils.js +30 -37
  21. package/dist/lib/ast/types.js +14 -2
  22. package/dist/lib/ast/walk.js +61 -49
  23. package/dist/lib/fs/resolve.js +6 -3
  24. package/dist/lib/parser/declaration/list.js +3 -1
  25. package/dist/lib/parser/parse.js +345 -305
  26. package/dist/lib/parser/tokenize.js +11 -13
  27. package/dist/lib/renderer/render.js +2 -2
  28. package/dist/lib/syntax/syntax.js +36 -18
  29. package/dist/lib/validation/at-rules/container.js +11 -0
  30. package/dist/lib/validation/at-rules/counter-style.js +11 -0
  31. package/dist/lib/validation/at-rules/font-feature-values.js +11 -0
  32. package/dist/lib/validation/at-rules/keyframes.js +11 -0
  33. package/dist/lib/validation/at-rules/layer.js +11 -0
  34. package/dist/lib/validation/at-rules/media.js +11 -0
  35. package/dist/lib/validation/at-rules/page-margin-box.js +11 -0
  36. package/dist/lib/validation/at-rules/page.js +11 -0
  37. package/dist/lib/validation/at-rules/supports.js +11 -0
  38. package/dist/lib/validation/at-rules/when.js +11 -0
  39. package/dist/lib/validation/config.js +0 -2
  40. package/dist/lib/validation/config.json.js +21 -1
  41. package/dist/lib/validation/parser/parse.js +53 -2
  42. package/dist/lib/validation/syntax.js +199 -36
  43. package/dist/node.js +17 -12
  44. package/dist/web.js +11 -11
  45. package/package.json +6 -3
  46. package/dist/lib/validation/parser/types.js +0 -54
@@ -1,7 +1,7 @@
1
- import { isIdentStart, isIdent, isIdentColor, mathFuncs, isColor, parseColor, isPseudo, pseudoElements, isAtKeyword, isFunction, isNumber, isPercentage, isFlex, isDimension, parseDimension, isHexColor, isHash, mediaTypes } from '../syntax/syntax.js';
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 { minify, definedPropertySettings, combinators } from '../ast/minify.js';
4
- import { walkValues, WalkerValueEvent, 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)$/;
@@ -43,12 +42,13 @@ function normalizeVisitorKeyName(keyName) {
43
42
  return keyName.replace(/-([a-z])/g, (all, one) => one.toUpperCase());
44
43
  }
45
44
  function replaceToken(parent, value, replacement) {
46
- // @ts-ignore
47
- if ('parent' in value && value.parent != replacement.parent) {
48
- Object.defineProperty(replacement, 'parent', {
49
- ...definedPropertySettings,
50
- value: value.parent
51
- });
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
52
  }
53
53
  if (parent.typ == EnumToken.BinaryExpressionTokenType) {
54
54
  if (parent.l == value) {
@@ -59,14 +59,12 @@ function replaceToken(parent, value, replacement) {
59
59
  }
60
60
  }
61
61
  else {
62
- // @ts-ignore
63
62
  const target = 'val' in parent && Array.isArray(parent.val) ? parent.val : parent.chi;
64
63
  // @ts-ignore
65
64
  const index = target.indexOf(value);
66
65
  if (index == -1) {
67
66
  return;
68
67
  }
69
- // @ts-ignore
70
68
  target.splice(index, 1, ...(Array.isArray(replacement) ? replacement : [replacement]));
71
69
  }
72
70
  }
@@ -119,6 +117,8 @@ async function doParse(iter, options = {}) {
119
117
  const stats = {
120
118
  src: options.src ?? '',
121
119
  bytesIn: 0,
120
+ nodesCount: 0,
121
+ tokensCount: 0,
122
122
  importedBytesIn: 0,
123
123
  parse: `0ms`,
124
124
  minify: `0ms`,
@@ -147,14 +147,107 @@ async function doParse(iter, options = {}) {
147
147
  src: ''
148
148
  };
149
149
  }
150
- let item;
151
- let node;
150
+ let valuesHandlers;
151
+ let preValuesHandlers;
152
+ let postValuesHandlers;
153
+ let preVisitorsHandlersMap;
154
+ let visitorsHandlersMap;
155
+ let postVisitorsHandlersMap;
152
156
  const rawTokens = [];
153
157
  const imports = [];
158
+ let item;
159
+ let node;
154
160
  // @ts-ignore ignore error
155
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
+ }
156
248
  while (item = isAsync ? (await iter.next()).value : iter.next().value) {
157
249
  stats.bytesIn = item.bytesIn;
250
+ stats.tokensCount++;
158
251
  rawTokens.push(item);
159
252
  if (item.hint != null && BadTokensTypes.includes(item.hint)) {
160
253
  const node = getTokenType(item.token, item.hint);
@@ -182,7 +275,7 @@ async function doParse(iter, options = {}) {
182
275
  ast.loc.end = item.end;
183
276
  }
184
277
  if (item.token == ';' || item.token == '{') {
185
- node = parseNode(tokens, context, options, errors, src, map, rawTokens);
278
+ node = parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
186
279
  rawTokens.length = 0;
187
280
  if (node != null) {
188
281
  if ('chi' in node) {
@@ -226,7 +319,7 @@ async function doParse(iter, options = {}) {
226
319
  map = new Map;
227
320
  }
228
321
  else if (item.token == '}') {
229
- parseNode(tokens, context, options, errors, src, map, rawTokens);
322
+ parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
230
323
  rawTokens.length = 0;
231
324
  if (context.loc != null) {
232
325
  context.loc.end = item.end;
@@ -247,7 +340,7 @@ async function doParse(iter, options = {}) {
247
340
  }
248
341
  }
249
342
  if (tokens.length > 0) {
250
- node = parseNode(tokens, context, options, errors, src, map, rawTokens);
343
+ node = parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
251
344
  rawTokens.length = 0;
252
345
  if (node != null) {
253
346
  if (node.typ == EnumToken.AtRuleNodeType && node.nam == 'import') {
@@ -310,228 +403,153 @@ async function doParse(iter, options = {}) {
310
403
  if (options.expandNestingRules) {
311
404
  ast = expand(ast);
312
405
  }
313
- const valuesHandlers = new Map;
314
- const preValuesHandlers = new Map;
315
- const postValuesHandlers = new Map;
316
- const preVisitorsHandlersMap = new Map;
317
- const visitorsHandlersMap = new Map;
318
- const postVisitorsHandlersMap = new Map;
319
- const allValuesHandlers = [];
406
+ let replacement;
407
+ let callable;
320
408
  if (options.visitor != null) {
321
- for (const [key, value] of Object.entries(options.visitor)) {
322
- if (key in EnumToken) {
323
- if (typeof value == 'function') {
324
- valuesHandlers.set(EnumToken[key], value);
325
- }
326
- else if (typeof value == 'object' && 'type' in value && 'handler' in value && value.type in WalkerValueEvent) {
327
- if (WalkerValueEvent[value.type] == WalkerValueEvent.Enter) {
328
- preValuesHandlers.set(EnumToken[key], value.handler);
409
+ for (const result of walk(ast)) {
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));
329
420
  }
330
- else if (WalkerValueEvent[value.type] == WalkerValueEvent.Leave) {
331
- postValuesHandlers.set(EnumToken[key], value.handler);
421
+ if (visitorsHandlersMap.has(key)) {
422
+ // @ts-ignore
423
+ handlers.push(...visitorsHandlersMap.get(key));
332
424
  }
333
- }
334
- else {
335
- console.warn(`doParse: visitor.${key} is not a valid key name`);
336
- }
337
- }
338
- else if (['Declaration', 'Rule', 'AtRule', 'KeyframesRule', 'KeyframesAtRule'].includes(key)) {
339
- if (typeof value == 'function') {
340
- visitorsHandlersMap.set(key, value);
341
- }
342
- else if (typeof value == 'object') {
343
- if ('type' in value && 'handler' in value && value.type in WalkerValueEvent) {
344
- if (WalkerValueEvent[value.type] == WalkerValueEvent.Enter) {
345
- preVisitorsHandlersMap.set(key, value.handler);
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;
346
434
  }
347
- else if (WalkerValueEvent[value.type] == WalkerValueEvent.Leave) {
348
- postVisitorsHandlersMap.set(key, value.handler);
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;
349
451
  }
350
452
  }
351
- else {
352
- visitorsHandlersMap.set(key, value);
353
- }
354
- }
355
- else {
356
- console.warn(`doParse: visitor.${key} is not a valid key name`);
357
- }
358
- }
359
- else {
360
- console.warn(`doParse: visitor.${key} is not a valid key name`);
361
- }
362
- }
363
- if (preValuesHandlers.size > 0) {
364
- allValuesHandlers.push(preValuesHandlers);
365
- }
366
- if (valuesHandlers.size > 0) {
367
- allValuesHandlers.push(valuesHandlers);
368
- }
369
- if (postValuesHandlers.size > 0) {
370
- allValuesHandlers.push(postValuesHandlers);
371
- }
372
- }
373
- for (const result of walk(ast)) {
374
- // if (result.parent != null && !isNodeAllowedInContext(result.node, result.parent as AstNode)) {
375
- //
376
- // errors.push({
377
- // action: 'drop',
378
- // message: `${EnumToken[result.parent.typ]}: child ${EnumToken[result.node.typ]}${result.node.typ == EnumToken.DeclarationNodeType ? ` '${(result.node as AstDeclaration).nam}'` : result.node.typ == EnumToken.AtRuleNodeType || result.node.typ == EnumToken.KeyframesAtRuleNodeType ? ` '@${(result.node as AstAtRule).nam}'` : ''} not allowed in context${result.parent.typ == EnumToken.AtRuleNodeType ? ` '@${(result.parent as AstAtRule).nam}'` : result.parent.typ == EnumToken.StyleSheetNodeType ? ` 'stylesheet'` : ''}`,
379
- // // @ts-ignore
380
- // location: result.node.loc ?? map.get(result.node ) ?? null
381
- // });
382
- //
383
- // // @ts-ignore
384
- // removeNode(result.node, result.parent as AstNode);
385
- // continue;
386
- // }
387
- if (allValuesHandlers.length > 0 || preVisitorsHandlersMap.size > 0 || visitorsHandlersMap.size > 0 || postVisitorsHandlersMap.size > 0) {
388
- if ((result.node.typ == EnumToken.DeclarationNodeType &&
389
- (preVisitorsHandlersMap.has('Declaration') || visitorsHandlersMap.has('Declaration') || postVisitorsHandlersMap.has('Declaration'))) ||
390
- (result.node.typ == EnumToken.AtRuleNodeType && (preVisitorsHandlersMap.has('AtRule') || visitorsHandlersMap.has('AtRule') || postVisitorsHandlersMap.has('AtRule'))) ||
391
- (result.node.typ == EnumToken.KeyframesAtRuleNodeType && (preVisitorsHandlersMap.has('KeyframesAtRule') || visitorsHandlersMap.has('KeyframesAtRule') || postVisitorsHandlersMap.has('KeyframesAtRule')))) {
392
- const handlers = [];
393
- const key = result.node.typ == EnumToken.DeclarationNodeType ? 'Declaration' : result.node.typ == EnumToken.AtRuleNodeType ? 'AtRule' : 'KeyframesAtRule';
394
- if (preVisitorsHandlersMap.has(key)) {
395
- // @ts-ignore
396
- handlers.push(preVisitorsHandlersMap.get(key));
397
- }
398
- if (visitorsHandlersMap.has(key)) {
399
- // @ts-ignore
400
- handlers.push(visitorsHandlersMap.get(key));
401
- }
402
- if (postVisitorsHandlersMap.has(key)) {
403
- // @ts-ignore
404
- handlers.push(postVisitorsHandlersMap.get(key));
405
- }
406
- let callable;
407
- let node = result.node;
408
- for (const handler of handlers) {
409
- callable = typeof handler == 'function' ? handler : handler[normalizeVisitorKeyName(node.typ == EnumToken.DeclarationNodeType || node.typ == EnumToken.AtRuleNodeType ? node.nam : node.val)];
410
- if (callable == null) {
411
- continue;
412
- }
413
- let replacement = callable(node, result.parent);
414
- if (replacement == null) {
415
- continue;
416
- }
417
- isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
418
- if (replacement) {
419
- replacement = await replacement;
420
- }
421
- if (replacement == null || replacement == node) {
422
- continue;
423
- }
424
- // @ts-ignore
425
- node = replacement;
426
- //
427
- if (Array.isArray(node)) {
428
- break;
453
+ if (node != result.node) {
454
+ // @ts-ignore
455
+ replaceToken(result.parent, result.node, node);
429
456
  }
430
457
  }
431
- if (node != result.node) {
432
- // @ts-ignore
433
- replaceToken(result.parent, result.node, node);
434
- }
435
- }
436
- else if ((result.node.typ == EnumToken.RuleNodeType && (preVisitorsHandlersMap.has('Rule') || visitorsHandlersMap.has('Rule') || postVisitorsHandlersMap.has('Rule'))) ||
437
- (result.node.typ == EnumToken.KeyFramesRuleNodeType && (preVisitorsHandlersMap.has('KeyframesRule') || visitorsHandlersMap.has('KeyframesRule') || postVisitorsHandlersMap.has('KeyframesRule')))) {
438
- const handlers = [];
439
- const key = result.node.typ == EnumToken.RuleNodeType ? 'Rule' : 'KeyframesRule';
440
- if (preVisitorsHandlersMap.has(key)) {
441
- // @ts-ignore
442
- handlers.push(preVisitorsHandlersMap.get(key));
443
- }
444
- if (visitorsHandlersMap.has(key)) {
445
- // @ts-ignore
446
- handlers.push(visitorsHandlersMap.get(key));
447
- }
448
- if (postVisitorsHandlersMap.has(key)) {
449
- // @ts-ignore
450
- handlers.push(postVisitorsHandlersMap.get(key));
451
- }
452
- let node = result.node;
453
- for (const callable of handlers) {
454
- // @ts-ignore
455
- let replacement = callable(node, result.parent);
456
- if (replacement == null) {
457
- continue;
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));
458
464
  }
459
- isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
460
- if (replacement) {
461
- replacement = await replacement;
465
+ if (visitorsHandlersMap.has(key)) {
466
+ handlers.push(...visitorsHandlersMap.get(key));
462
467
  }
463
- if (replacement == null || replacement == node) {
464
- continue;
468
+ if (postVisitorsHandlersMap.has(key)) {
469
+ handlers.push(...postVisitorsHandlersMap.get(key));
465
470
  }
466
- // @ts-ignore
467
- node = replacement;
468
- //
469
- if (Array.isArray(node)) {
470
- break;
471
- }
472
- }
473
- // @ts-ignore
474
- if (node != result.node) {
475
- // @ts-ignore
476
- replaceToken(result.parent, result.node, node);
477
- }
478
- }
479
- else if (allValuesHandlers.length > 0) {
480
- let callable;
481
- let node = null;
482
- node = result.node;
483
- for (const valueHandler of allValuesHandlers) {
484
- if (valueHandler.has(node.typ)) {
485
- callable = valueHandler.get(node.typ);
486
- let replacement = callable(node, result.parent);
471
+ let node = result.node;
472
+ for (const callable of handlers) {
473
+ replacement = callable(node, result.parent);
487
474
  if (replacement == null) {
488
475
  continue;
489
476
  }
490
477
  isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
491
- if (isAsync) {
478
+ if (replacement) {
492
479
  replacement = await replacement;
493
480
  }
494
- if (replacement != null && replacement != node) {
495
- node = replacement;
481
+ if (replacement == null || replacement == node) {
482
+ continue;
483
+ }
484
+ // @ts-ignore
485
+ node = replacement;
486
+ //
487
+ if (Array.isArray(node)) {
488
+ break;
496
489
  }
497
490
  }
498
- }
499
- if (node != result.node) {
500
491
  // @ts-ignore
501
- replaceToken(result.parent, value, node);
502
- }
503
- const tokens = 'tokens' in result.node ? result.node.tokens : [];
504
- if ('val' in result.node && Array.isArray(result.node.val)) {
505
- tokens.push(...result.node.val);
506
- }
507
- if (tokens.length == 0) {
508
- continue;
492
+ if (node != result.node) {
493
+ // @ts-ignore
494
+ replaceToken(result.parent, result.node, node);
495
+ }
509
496
  }
510
- for (const { value, parent, root } of walkValues(tokens, result.node)) {
511
- node = value;
512
- for (const valueHandler of allValuesHandlers) {
513
- if (valueHandler.has(node.typ)) {
514
- callable = valueHandler.get(node.typ);
515
- let result = callable(node, parent, root);
516
- if (result == null) {
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) {
517
505
  continue;
518
506
  }
519
- isAsync = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction';
507
+ isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
520
508
  if (isAsync) {
521
- result = await result;
509
+ replacement = await replacement;
522
510
  }
523
- if (result != null && result != node) {
524
- node = result;
525
- }
526
- //
527
- if (Array.isArray(node)) {
528
- break;
511
+ if (replacement != null && replacement != node) {
512
+ node = replacement;
529
513
  }
530
514
  }
531
515
  }
532
- if (node != value) {
516
+ if (node != result.node) {
533
517
  // @ts-ignore
534
- replaceToken(parent, value, node);
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
+ }
535
553
  }
536
554
  }
537
555
  }
@@ -571,7 +589,7 @@ function getLastNode(context) {
571
589
  }
572
590
  return null;
573
591
  }
574
- function parseNode(results, context, options, errors, src, map, rawTokens) {
592
+ function parseNode(results, context, options, errors, src, map, rawTokens, stats) {
575
593
  let tokens = [];
576
594
  for (const t of results) {
577
595
  const node = getTokenType(t.token, t.hint);
@@ -594,9 +612,12 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
594
612
  }
595
613
  loc = location;
596
614
  context.chi.push(tokens[i]);
597
- if (options.sourcemap) {
598
- tokens[i].loc = loc;
599
- }
615
+ stats.nodesCount++;
616
+ Object.defineProperty(tokens[i], 'loc', {
617
+ ...definedPropertySettings,
618
+ value: loc,
619
+ enumerable: options.sourcemap !== false
620
+ });
600
621
  }
601
622
  else if (tokens[i].typ != EnumToken.WhitespaceTokenType) {
602
623
  break;
@@ -737,10 +758,10 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
737
758
  }
738
759
  }
739
760
  const t = parseAtRulePrelude(parseTokens(tokens, { minify: options.minify }), atRule);
740
- const raw = t.reduce((acc, curr) => {
741
- acc.push(renderToken(curr, { removeComments: true, convertColor: false }));
742
- return acc;
743
- }, []);
761
+ const raw = [];
762
+ for (const curr of t) {
763
+ raw.push(renderToken(curr, { removeComments: true, convertColor: false }));
764
+ }
744
765
  const nam = renderToken(atRule, { removeComments: true });
745
766
  // @ts-ignore
746
767
  const node = {
@@ -756,10 +777,12 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
756
777
  node.chi = [];
757
778
  }
758
779
  loc = map.get(atRule);
759
- if (options.sourcemap) {
760
- node.loc = loc;
761
- node.loc.end = { ...map.get(delim).end };
762
- }
780
+ Object.defineProperty(node, 'loc', {
781
+ ...definedPropertySettings,
782
+ value: loc,
783
+ enumerable: options.sourcemap !== false
784
+ });
785
+ node.loc.end = { ...map.get(delim).end };
763
786
  let isValid = true;
764
787
  if (node.nam == 'else') {
765
788
  const prev = getLastNode(context);
@@ -773,20 +796,31 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
773
796
  }
774
797
  }
775
798
  // @ts-ignore
776
- const valid = options.validation == ValidationLevel.None ? {
799
+ const skipValidate = (options.validation & ValidationLevel.AtRule) == 0;
800
+ const isAllowed = skipValidate || isNodeAllowedInContext(node, context);
801
+ // @ts-ignore
802
+ const valid = skipValidate ? {
777
803
  valid: SyntaxValidationResult.Valid,
778
804
  error: '',
779
805
  node,
780
806
  syntax: '@' + node.nam
781
- } : isValid ? (node.typ == EnumToken.KeyframesAtRuleNodeType ? validateAtRuleKeyframes(node) : validateAtRule(node, options, context)) : {
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)) : {
782
812
  valid: SyntaxValidationResult.Drop,
783
813
  node,
784
814
  syntax: '@' + node.nam,
785
815
  error: '@' + node.nam + ' not allowed here'};
786
816
  if (valid.valid == SyntaxValidationResult.Drop) {
817
+ let message = '';
818
+ for (const token of tokens) {
819
+ message += renderToken(token, { minify: false });
820
+ }
787
821
  errors.push({
788
822
  action: 'drop',
789
- message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
823
+ message: valid.error + ' - "' + message + '"',
790
824
  node,
791
825
  // @ts-ignore
792
826
  location: { src, ...(map.get(valid.node) ?? location) }
@@ -795,13 +829,17 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
795
829
  node.typ = EnumToken.InvalidAtRuleTokenType;
796
830
  }
797
831
  else {
798
- node.val = node.tokens.reduce((acc, curr) => acc + renderToken(curr, {
799
- minify: false,
800
- convertColor: false,
801
- removeComments: true
802
- }), '');
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
+ }
803
840
  }
804
841
  context.chi.push(node);
842
+ stats.nodesCount++;
805
843
  Object.defineProperties(node, {
806
844
  parent: { ...definedPropertySettings, value: context },
807
845
  validSyntax: { ...definedPropertySettings, value: valid.valid == SyntaxValidationResult.Valid }
@@ -899,16 +937,23 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
899
937
  value: tokens.slice()
900
938
  });
901
939
  loc = location;
902
- if (options.sourcemap) {
903
- node.loc = loc;
904
- }
905
- // @ts-ignore
940
+ Object.defineProperty(node, 'loc', {
941
+ ...definedPropertySettings,
942
+ value: loc,
943
+ enumerable: options.sourcemap !== false
944
+ });
906
945
  context.chi.push(node);
907
946
  Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: context });
908
947
  // @ts-ignore
909
- const valid = options.validation == ValidationLevel.None ? {
948
+ const skipValidate = (options.validation & ValidationLevel.Selector) == 0;
949
+ const isAllowed = skipValidate || isNodeAllowedInContext(node, context);
950
+ // @ts-ignore
951
+ const valid = skipValidate ? {
910
952
  valid: SyntaxValidationResult.Valid,
911
953
  error: null
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'` : ''}`
912
957
  } : ruleType == EnumToken.KeyFramesRuleNodeType ? validateKeyframeSelector(tokens) : validateSelector(tokens, options, context);
913
958
  if (valid.valid != SyntaxValidationResult.Valid) {
914
959
  // @ts-ignore
@@ -1018,11 +1063,13 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
1018
1063
  nam,
1019
1064
  val: []
1020
1065
  };
1021
- if (options.sourcemap) {
1022
- node.loc = location;
1023
- node.loc.end = { ...map.get(delim).end };
1024
- }
1066
+ Object.defineProperty(node, 'loc', {
1067
+ ...definedPropertySettings,
1068
+ value: location,
1069
+ enumerable: options.sourcemap !== false
1070
+ });
1025
1071
  context.chi.push(node);
1072
+ stats.nodesCount++;
1026
1073
  }
1027
1074
  return null;
1028
1075
  }
@@ -1046,22 +1093,31 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
1046
1093
  nam,
1047
1094
  val: value
1048
1095
  };
1049
- if (options.sourcemap) {
1050
- node.loc = location;
1051
- node.loc.end = { ...map.get(delim).end };
1052
- }
1096
+ Object.defineProperty(node, 'loc', {
1097
+ ...definedPropertySettings,
1098
+ value: location,
1099
+ enumerable: options.sourcemap !== false
1100
+ });
1101
+ node.loc.end = { ...map.get(delim).end };
1053
1102
  // do not allow declarations in style sheets
1054
1103
  if (context.typ == EnumToken.StyleSheetNodeType && options.lenient) {
1055
- // @ts-ignore
1056
- node.typ = EnumToken.InvalidDeclarationNodeType;
1104
+ Object.assign(node, { typ: EnumToken.InvalidDeclarationNodeType });
1057
1105
  context.chi.push(node);
1106
+ stats.nodesCount++;
1058
1107
  return null;
1059
1108
  }
1060
1109
  const result = parseDeclarationNode(node, errors, location);
1061
1110
  Object.defineProperty(result, 'parent', { ...definedPropertySettings, value: context });
1062
1111
  if (result != null) {
1063
- if (options.validation == ValidationLevel.All) {
1064
- const valid = evaluateSyntax(result, options);
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);
1065
1121
  Object.defineProperty(result, 'validSyntax', {
1066
1122
  ...definedPropertySettings,
1067
1123
  value: valid.valid == SyntaxValidationResult.Valid
@@ -1077,11 +1133,11 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
1077
1133
  if (!options.lenient) {
1078
1134
  return null;
1079
1135
  }
1080
- // @ts-ignore
1081
- node.typ = EnumToken.InvalidDeclarationNodeType;
1136
+ Object.assign(node, { typ: EnumToken.InvalidDeclarationNodeType });
1082
1137
  }
1083
1138
  }
1084
1139
  context.chi.push(result);
1140
+ stats.nodesCount++;
1085
1141
  }
1086
1142
  return null;
1087
1143
  }
@@ -1093,7 +1149,6 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
1093
1149
  * @param atRule
1094
1150
  */
1095
1151
  function parseAtRulePrelude(tokens, atRule) {
1096
- // @ts-ignore
1097
1152
  for (const { value, parent } of walkValues(tokens, null, null, true)) {
1098
1153
  if (value.typ == EnumToken.CommentTokenType ||
1099
1154
  value.typ == EnumToken.WhitespaceTokenType ||
@@ -1129,16 +1184,14 @@ function parseAtRulePrelude(tokens, atRule) {
1129
1184
  }
1130
1185
  if (atRule.val == 'page' && value.typ == EnumToken.PseudoClassTokenType) {
1131
1186
  if ([':left', ':right', ':first', ':blank'].includes(value.val)) {
1132
- // @ts-ignore
1133
- value.typ = EnumToken.PseudoPageTokenType;
1187
+ Object.assign(value, { typ: EnumToken.PseudoPageTokenType });
1134
1188
  }
1135
1189
  }
1136
1190
  if (atRule.val == 'layer') {
1137
1191
  if (parent == null && value.typ == EnumToken.LiteralTokenType) {
1138
1192
  if (value.val.charAt(0) == '.') {
1139
1193
  if (isIdent(value.val.slice(1))) {
1140
- // @ts-ignore
1141
- value.typ = EnumToken.ClassSelectorTokenType;
1194
+ Object.assign(value, { typ: EnumToken.ClassSelectorTokenType });
1142
1195
  }
1143
1196
  }
1144
1197
  }
@@ -1147,8 +1200,7 @@ function parseAtRulePrelude(tokens, atRule) {
1147
1200
  if (value.typ == EnumToken.IdenTokenType) {
1148
1201
  if (parent == null && mediaTypes.some((t) => {
1149
1202
  if (val === t) {
1150
- // @ts-ignore
1151
- value.typ = EnumToken.MediaFeatureTokenType;
1203
+ Object.assign(value, { typ: EnumToken.MediaFeatureTokenType });
1152
1204
  return true;
1153
1205
  }
1154
1206
  return false;
@@ -1156,18 +1208,15 @@ function parseAtRulePrelude(tokens, atRule) {
1156
1208
  continue;
1157
1209
  }
1158
1210
  if (value.typ == EnumToken.IdenTokenType && 'and' === val) {
1159
- // @ts-ignore
1160
- value.typ = EnumToken.MediaFeatureAndTokenType;
1211
+ Object.assign(value, { typ: EnumToken.MediaFeatureAndTokenType });
1161
1212
  continue;
1162
1213
  }
1163
1214
  if (value.typ == EnumToken.IdenTokenType && 'or' === val) {
1164
- // @ts-ignore
1165
- value.typ = EnumToken.MediaFeatureOrTokenType;
1215
+ Object.assign(value, { typ: EnumToken.MediaFeatureOrTokenType });
1166
1216
  continue;
1167
1217
  }
1168
1218
  if (value.typ == EnumToken.IdenTokenType &&
1169
1219
  ['not', 'only'].some((t) => val === t)) {
1170
- // @ts-ignore
1171
1220
  const array = parent?.chi ?? tokens;
1172
1221
  const startIndex = array.indexOf(value);
1173
1222
  let index = startIndex + 1;
@@ -1212,12 +1261,15 @@ function parseAtRulePrelude(tokens, atRule) {
1212
1261
  if (value.chi[i].typ == EnumToken.CommentTokenType || value.chi[i].typ == EnumToken.WhitespaceTokenType) {
1213
1262
  continue;
1214
1263
  }
1215
- if (value.chi[i].typ == EnumToken.LiteralTokenType && value.chi[i].val.startsWith(':') && isDimension(value.chi[i].val.slice(1))) {
1216
- value.chi.splice(i, 1, {
1217
- typ: EnumToken.ColonTokenType,
1218
- }, Object.assign(value.chi[i], parseDimension(value.chi[i].val.slice(1))));
1219
- i--;
1220
- continue;
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
+ }
1221
1273
  }
1222
1274
  if (nameIndex != -1 && value.chi[i].typ == EnumToken.PseudoClassTokenType) {
1223
1275
  value.chi.splice(i, 1, {
@@ -1244,11 +1296,10 @@ function parseAtRulePrelude(tokens, atRule) {
1244
1296
  const val = value.chi.splice(valueIndex, 1)[0];
1245
1297
  const node = value.chi.splice(nameIndex, 1)[0];
1246
1298
  // 'background'
1247
- // @ts-ignore
1248
1299
  if (node.typ == EnumToken.ColorTokenType && node.kin == ColorType.DPSYS) {
1300
+ Object.assign(node, { typ: EnumToken.IdenTokenType });
1249
1301
  // @ts-ignore
1250
1302
  delete node.kin;
1251
- node.typ = EnumToken.IdenTokenType;
1252
1303
  }
1253
1304
  while (value.chi[0]?.typ == EnumToken.WhitespaceTokenType) {
1254
1305
  value.chi.shift();
@@ -1303,43 +1354,35 @@ function parseSelector(tokens) {
1303
1354
  }
1304
1355
  if (parent == null) {
1305
1356
  if (value.typ == EnumToken.GtTokenType) {
1306
- // @ts-ignore
1307
- value.typ = EnumToken.ChildCombinatorTokenType;
1357
+ Object.assign(value, { typ: EnumToken.ChildCombinatorTokenType });
1308
1358
  }
1309
1359
  else if (value.typ == EnumToken.LiteralTokenType) {
1310
1360
  if (value.val.charAt(0) == '&') {
1311
- // @ts-ignore
1312
- value.typ = EnumToken.NestingSelectorTokenType;
1361
+ Object.assign(value, { typ: EnumToken.NestingSelectorTokenType });
1313
1362
  // @ts-ignore
1314
1363
  delete value.val;
1315
1364
  }
1316
1365
  else if (value.val.charAt(0) == '.') {
1317
1366
  if (!isIdent(value.val.slice(1))) {
1318
- // @ts-ignore
1319
- value.typ = EnumToken.InvalidClassSelectorTokenType;
1367
+ Object.assign(value, { typ: EnumToken.InvalidClassSelectorTokenType });
1320
1368
  }
1321
1369
  else {
1322
- // @ts-ignore
1323
- value.typ = EnumToken.ClassSelectorTokenType;
1370
+ Object.assign(value, { typ: EnumToken.ClassSelectorTokenType });
1324
1371
  }
1325
1372
  }
1326
1373
  if (['*', '>', '+', '~'].includes(value.val)) {
1327
1374
  switch (value.val) {
1328
1375
  case '*':
1329
- // @ts-ignore
1330
- value.typ = EnumToken.UniversalSelectorTokenType;
1376
+ Object.assign(value, { typ: EnumToken.UniversalSelectorTokenType });
1331
1377
  break;
1332
1378
  case '>':
1333
- // @ts-ignore
1334
- value.typ = EnumToken.ChildCombinatorTokenType;
1379
+ Object.assign(value, { typ: EnumToken.ChildCombinatorTokenType });
1335
1380
  break;
1336
1381
  case '+':
1337
- // @ts-ignore
1338
- value.typ = EnumToken.NextSiblingCombinatorTokenType;
1382
+ Object.assign(value, { typ: EnumToken.NextSiblingCombinatorTokenType });
1339
1383
  break;
1340
1384
  case '~':
1341
- // @ts-ignore
1342
- value.typ = EnumToken.SubsequentSiblingCombinatorTokenType;
1385
+ Object.assign(value, { typ: EnumToken.SubsequentSiblingCombinatorTokenType });
1343
1386
  break;
1344
1387
  }
1345
1388
  // @ts-ignore
@@ -1352,12 +1395,10 @@ function parseSelector(tokens) {
1352
1395
  if (!isIdent(value.val.slice(1))) {
1353
1396
  continue;
1354
1397
  }
1355
- // @ts-ignore
1356
- value.typ = EnumToken.HashTokenType;
1398
+ Object.assign(value, { typ: EnumToken.HashTokenType });
1357
1399
  }
1358
1400
  else {
1359
- // @ts-ignore
1360
- value.typ = EnumToken.IdenTokenType;
1401
+ Object.assign(value, { typ: EnumToken.IdenTokenType });
1361
1402
  }
1362
1403
  // @ts-ignore
1363
1404
  delete value.kin;
@@ -1420,15 +1461,17 @@ function parseString(src, options = { location: false }) {
1420
1461
  return acc;
1421
1462
  }
1422
1463
  const token = getTokenType(t.token, t.hint);
1423
- if (options.location) {
1424
- Object.assign(token, { loc: t.sta });
1425
- }
1464
+ Object.defineProperty(token, 'loc', {
1465
+ ...definedPropertySettings,
1466
+ value: { sta: t.sta },
1467
+ enumerable: options.location !== false
1468
+ });
1426
1469
  acc.push(token);
1427
1470
  return acc;
1428
1471
  }, []));
1429
1472
  }
1430
1473
  /**
1431
- * get token type from a string
1474
+ * get the token type from a string
1432
1475
  * @param val
1433
1476
  * @param hint
1434
1477
  */
@@ -1464,7 +1507,7 @@ function getTokenType(val, hint) {
1464
1507
  case '>':
1465
1508
  return { typ: EnumToken.GtTokenType };
1466
1509
  }
1467
- if (isPseudo(val)) {
1510
+ if (val.charAt(0) == ':' && isPseudo(val)) {
1468
1511
  return val.endsWith('(') ? {
1469
1512
  typ: EnumToken.PseudoClassFuncTokenType,
1470
1513
  val: val.slice(0, -1),
@@ -1481,13 +1524,13 @@ function getTokenType(val, hint) {
1481
1524
  val
1482
1525
  });
1483
1526
  }
1484
- if (isAtKeyword(val)) {
1527
+ if (val.charAt(0) == '@' && isAtKeyword(val)) {
1485
1528
  return {
1486
1529
  typ: EnumToken.AtRuleTokenType,
1487
1530
  val: val.slice(1)
1488
1531
  };
1489
1532
  }
1490
- if (isFunction(val)) {
1533
+ if (val.endsWith('(') && isFunction(val)) {
1491
1534
  val = val.slice(0, -1);
1492
1535
  if (val == 'url') {
1493
1536
  return {
@@ -1535,15 +1578,12 @@ function getTokenType(val, hint) {
1535
1578
  val: +val.slice(0, -1)
1536
1579
  };
1537
1580
  }
1538
- if (isFlex(val)) {
1539
- return {
1540
- typ: EnumToken.FlexTokenType,
1541
- val: +val.slice(0, -2)
1542
- };
1543
- }
1544
- if (isDimension(val)) {
1545
- return parseDimension(val);
1581
+ // if (isDimension(val)) {
1582
+ const dimension = parseDimension(val);
1583
+ if (dimension != null) {
1584
+ return dimension;
1546
1585
  }
1586
+ // }
1547
1587
  const v = val.toLowerCase();
1548
1588
  if (v == 'currentcolor' || v == 'transparent' || v in COLORS_NAMES) {
1549
1589
  return {