@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
package/dist/index.cjs CHANGED
@@ -26,14 +26,26 @@ exports.ValidationLevel = void 0;
26
26
  * disable validation
27
27
  */
28
28
  ValidationLevel[ValidationLevel["None"] = 0] = "None";
29
+ /**
30
+ * validate selectors
31
+ */
32
+ ValidationLevel[ValidationLevel["Selector"] = 1] = "Selector";
33
+ /**
34
+ * validate at-rules
35
+ */
36
+ ValidationLevel[ValidationLevel["AtRule"] = 2] = "AtRule";
37
+ /**
38
+ * validate declarations
39
+ */
40
+ ValidationLevel[ValidationLevel["Declaration"] = 4] = "Declaration";
29
41
  /**
30
42
  * validate selectors and at-rules
31
43
  */
32
- ValidationLevel[ValidationLevel["Default"] = 1] = "Default";
44
+ ValidationLevel[ValidationLevel["Default"] = 3] = "Default";
33
45
  /**
34
46
  * validate selectors, at-rules and declarations
35
47
  */
36
- ValidationLevel[ValidationLevel["All"] = 2] = "All"; // selectors + at-rules + declarations
48
+ ValidationLevel[ValidationLevel["All"] = 7] = "All"; // selectors + at-rules + declarations
37
49
  })(exports.ValidationLevel || (exports.ValidationLevel = {}));
38
50
  /**
39
51
  * enum of all token types
@@ -4110,9 +4122,6 @@ const epsilon = 1e-5;
4110
4122
  function identity() {
4111
4123
  return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
4112
4124
  }
4113
- function pLength(point) {
4114
- return Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
4115
- }
4116
4125
  function normalize(point) {
4117
4126
  const [x, y, z] = point;
4118
4127
  const norm = Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
@@ -4140,8 +4149,14 @@ function multiply(matrixA, matrixB) {
4140
4149
  function inverse(matrix) {
4141
4150
  // Create augmented matrix [matrix | identity]
4142
4151
  let augmented = [
4143
- 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
4144
- 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
4152
+ ...matrix.slice(0, 4),
4153
+ 1, 0, 0, 0,
4154
+ ...matrix.slice(4, 8),
4155
+ 0, 1, 0, 0,
4156
+ ...matrix.slice(8, 12),
4157
+ 0, 0, 1, 0,
4158
+ ...matrix.slice(12, 16),
4159
+ 0, 0, 0, 1
4145
4160
  ];
4146
4161
  // Gaussian elimination with partial pivoting
4147
4162
  for (let col = 0; col < 4; col++) {
@@ -4181,24 +4196,9 @@ function inverse(matrix) {
4181
4196
  // Extract the inverse from the right side of the augmented matrix
4182
4197
  return augmented.slice(0, 16);
4183
4198
  }
4184
- // function transpose(matrix: Matrix): Matrix {
4185
- // // Crée une nouvelle matrice vide 4x4
4186
- // // @ts-ignore
4187
- // let transposed: Matrix = [[], [], [], []] as Matrix;
4188
- //
4189
- // // Parcourt chaque ligne et colonne pour transposer
4190
- // for (let i = 0; i < 4; i++) {
4191
- //
4192
- // for (let j = 0; j < 4; j++) {
4193
- //
4194
- // transposed[j][i] = matrix[i][j];
4195
- // }
4196
- // }
4197
- //
4198
- // return transposed;
4199
- // }
4200
4199
  function round(number) {
4201
- return Math.abs(number) < epsilon ? 0 : +number.toPrecision(6);
4200
+ const rounded = Math.round(number);
4201
+ return Math.abs(rounded - number) <= epsilon ? rounded : +number.toPrecision(6);
4202
4202
  }
4203
4203
  // translate3d(25.9808px, 0, 15px ) rotateY(60deg) skewX(49.9999deg) scale(1, 1.2)
4204
4204
  // translate → rotate → skew → scale
@@ -4221,7 +4221,7 @@ function decompose(original) {
4221
4221
  perspectiveMatrix[15] = 1;
4222
4222
  // @ts-ignore
4223
4223
  const inverted = inverse(original.slice());
4224
- if (!inverted) {
4224
+ if (inverted === null) {
4225
4225
  return null;
4226
4226
  }
4227
4227
  const transposedInverse = transposeMatrix4(inverted);
@@ -4242,8 +4242,13 @@ function decompose(original) {
4242
4242
  const row0 = [matrix[0], matrix[1], matrix[2]];
4243
4243
  const row1 = [matrix[4], matrix[5], matrix[6]];
4244
4244
  const row2 = [matrix[8], matrix[9], matrix[10]];
4245
+ const cross = [
4246
+ row1[1] * row2[2] - row1[2] * row2[1],
4247
+ row1[2] * row2[0] - row1[0] * row2[2],
4248
+ row1[0] * row2[1] - row1[1] * row2[0],
4249
+ ];
4245
4250
  // Compute scale
4246
- const scaleX = pLength(row0);
4251
+ const scaleX = Math.hypot(...row0);
4247
4252
  const row0Norm = normalize(row0);
4248
4253
  const skewXY = dot(row0Norm, row1);
4249
4254
  const row1Proj = [
@@ -4251,7 +4256,7 @@ function decompose(original) {
4251
4256
  row1[1] - skewXY * row0Norm[1],
4252
4257
  row1[2] - skewXY * row0Norm[2]
4253
4258
  ];
4254
- const scaleY = pLength(row1Proj);
4259
+ const scaleY = Math.hypot(...row1Proj);
4255
4260
  const row1Norm = normalize(row1Proj);
4256
4261
  const skewXZ = dot(row0Norm, row2);
4257
4262
  const skewYZ = dot(row1Norm, row2);
@@ -4260,8 +4265,9 @@ function decompose(original) {
4260
4265
  row2[1] - skewXZ * row0Norm[1] - skewYZ * row1Norm[1],
4261
4266
  row2[2] - skewXZ * row0Norm[2] - skewYZ * row1Norm[2]
4262
4267
  ];
4263
- const scaleZ = pLength(row2Proj);
4264
4268
  const row2Norm = normalize(row2Proj);
4269
+ const determinant = row0[0] * cross[0] + row0[1] * cross[1] + row0[2] * cross[2];
4270
+ const scaleZ = Math.hypot(...row2Proj) * (determinant < 0 ? -1 : 1);
4265
4271
  // Build rotation matrix from orthonormalized vectors
4266
4272
  const r00 = row0Norm[0], r01 = row1Norm[0], r02 = row2Norm[0];
4267
4273
  const r10 = row0Norm[1], r11 = row1Norm[1], r12 = row2Norm[1];
@@ -4298,7 +4304,6 @@ function decompose(original) {
4298
4304
  qz = 0.25 * s;
4299
4305
  }
4300
4306
  [qx, qy, qz] = toZero([qx, qy, qz]);
4301
- // const q = gcd(qx, gcd(qy, qz));
4302
4307
  let q = [Math.abs(qx), Math.abs(qy), Math.abs(qz)].reduce((acc, curr) => {
4303
4308
  if (acc == 0 || (curr > 0 && curr < acc)) {
4304
4309
  acc = curr;
@@ -4343,16 +4348,16 @@ function toZero(v) {
4343
4348
  // https://drafts.csswg.org/css-transforms-1/#2d-matrix
4344
4349
  function is2DMatrix(matrix) {
4345
4350
  // m13,m14, m23, m24, m31, m32, m34, m43 are all 0
4346
- return matrix[0 * 4 + 2] === 0 &&
4347
- matrix[0 * 4 + 3] === 0 &&
4348
- matrix[1 * 4 + 2] === 0 &&
4349
- matrix[1 * 4 + 3] === 0 &&
4350
- matrix[2 * 4 + 0] === 0 &&
4351
- matrix[2 * 4 + 1] === 0 &&
4352
- matrix[2 * 4 + 3] === 0 &&
4353
- matrix[3 * 4 + 2] === 0 &&
4354
- matrix[2 * 4 + 2] === 1 &&
4355
- matrix[3 * 4 + 3] === 1;
4351
+ return matrix[2] === 0 &&
4352
+ matrix[3] === 0 &&
4353
+ matrix[6] === 0 &&
4354
+ matrix[7] === 0 &&
4355
+ matrix[8] === 0 &&
4356
+ matrix[9] === 0 &&
4357
+ matrix[11] === 0 &&
4358
+ matrix[14] === 0 &&
4359
+ matrix[10] === 1 &&
4360
+ matrix[15] === 1;
4356
4361
  }
4357
4362
 
4358
4363
  /**
@@ -5454,7 +5459,7 @@ function isColor(token) {
5454
5459
  }
5455
5460
  if (token.typ == exports.EnumToken.IdenTokenType) {
5456
5461
  // named color
5457
- return token.val.toLowerCase() in COLORS_NAMES;
5462
+ return token.val.toLowerCase() in COLORS_NAMES || 'currentcolor' === token.val.toLowerCase() || 'transparent' === token.val.toLowerCase();
5458
5463
  }
5459
5464
  let isLegacySyntax = false;
5460
5465
  if (token.typ == exports.EnumToken.FunctionTokenType) {
@@ -5507,8 +5512,13 @@ function isColor(token) {
5507
5512
  return false;
5508
5513
  }
5509
5514
  }
5510
- if (children[i].typ == exports.EnumToken.FunctionTokenType && !mathFuncs.includes(children[i].val)) {
5511
- return false;
5515
+ if (children[i].typ == exports.EnumToken.FunctionTokenType) {
5516
+ if ('var' == children[i].val.toLowerCase()) {
5517
+ continue;
5518
+ }
5519
+ if (!mathFuncs.includes(children[i].val)) {
5520
+ return false;
5521
+ }
5512
5522
  }
5513
5523
  }
5514
5524
  if (children.length == 4 || (isRelative && children.length == 6)) {
@@ -5795,23 +5805,29 @@ function isNumber(name) {
5795
5805
  }
5796
5806
  return true;
5797
5807
  }
5798
- function isDimension(name) {
5799
- let index = name.length;
5800
- while (index--) {
5801
- if (isLetter(name.charCodeAt(index))) {
5802
- continue;
5803
- }
5804
- index++;
5805
- break;
5806
- }
5807
- const number = name.slice(0, index);
5808
- return number.length > 0 && isIdentStart(name.charCodeAt(index)) && isNumber(number);
5809
- }
5808
+ // export function isDimension(name: string) {
5809
+ //
5810
+ // let index: number = name.length;
5811
+ //
5812
+ // while (index--) {
5813
+ //
5814
+ // if (isLetter(<number>name.charCodeAt(index))) {
5815
+ //
5816
+ // continue
5817
+ // }
5818
+ //
5819
+ // index++;
5820
+ // break;
5821
+ // }
5822
+ //
5823
+ // const number: string = name.slice(0, index);
5824
+ // return number.length > 0 && isIdentStart(name.charCodeAt(index)) && isNumber(number);
5825
+ // }
5810
5826
  function isPercentage(name) {
5811
5827
  return name.endsWith('%') && isNumber(name.slice(0, -1));
5812
5828
  }
5813
- function isFlex(name) {
5814
- return name.endsWith('fr') && isNumber(name.slice(0, -2));
5829
+ function isFlex(dimension) {
5830
+ return 'unit' in dimension && 'fr' == dimension.unit.toLowerCase();
5815
5831
  }
5816
5832
  function parseDimension(name) {
5817
5833
  let index = name.length;
@@ -5827,6 +5843,9 @@ function parseDimension(name) {
5827
5843
  val: +name.slice(0, index),
5828
5844
  unit: name.slice(index)
5829
5845
  };
5846
+ if (index < 0 || Number.isNaN(dimension.val)) {
5847
+ return null;
5848
+ }
5830
5849
  if (isAngle(dimension)) {
5831
5850
  // @ts-ignore
5832
5851
  dimension.typ = exports.EnumToken.AngleTokenType;
@@ -5850,6 +5869,10 @@ function parseDimension(name) {
5850
5869
  // @ts-ignore
5851
5870
  dimension.typ = exports.EnumToken.FrequencyTokenType;
5852
5871
  }
5872
+ else if (isFlex(dimension)) {
5873
+ // @ts-ignore
5874
+ dimension.typ = exports.EnumToken.FlexTokenType;
5875
+ }
5853
5876
  return dimension;
5854
5877
  }
5855
5878
  function isHexColor(name) {
@@ -7690,7 +7713,7 @@ function doRender(data, options = {}) {
7690
7713
  const sourcemap = options.sourcemap ? new SourceMap : null;
7691
7714
  const cache = Object.create(null);
7692
7715
  const result = {
7693
- code: renderAstNode(options.expandNestingRules ? expand(data) : data, options, sourcemap, {
7716
+ code: renderAstNode(options.expandNestingRules && [exports.EnumToken.StyleSheetNodeType, exports.EnumToken.AtRuleNodeType, exports.EnumToken.RuleNodeType].includes(data.typ) && 'chi' in data ? expand(data) : data, options, sourcemap, {
7694
7717
  ind: 0,
7695
7718
  lin: 1,
7696
7719
  col: 1
@@ -7830,7 +7853,7 @@ function renderAstNode(data, options, sourcemap, position, errors, reducer, cach
7830
7853
  str = `${node.nam}:${options.indent}${(options.minify ? filterValues(node.val) : node.val).reduce(reducer, '').trimEnd()};`;
7831
7854
  }
7832
7855
  else if (node.typ == exports.EnumToken.AtRuleNodeType && !('chi' in node)) {
7833
- str = `${data.val === '' ? '' : options.indent || ' '}${data.val};`;
7856
+ str = `${node.val === '' ? '' : options.indent || ' '}${node.val};`;
7834
7857
  }
7835
7858
  else {
7836
7859
  str = renderAstNode(node, options, sourcemap, { ...position }, errors, reducer, cache, level + 1, indents);
@@ -8421,13 +8444,15 @@ function* tokenize$1(parseInfo, yieldEOFToken = true) {
8421
8444
  yield pushToken(buffer, parseInfo);
8422
8445
  buffer = '';
8423
8446
  }
8447
+ buffer += value;
8424
8448
  while (value = next(parseInfo)) {
8425
8449
  charCode = value.charCodeAt(0);
8426
8450
  if (!isWhiteSpace(charCode)) {
8427
8451
  break;
8428
8452
  }
8453
+ buffer += value;
8429
8454
  }
8430
- yield pushToken('', parseInfo, exports.EnumToken.WhitespaceTokenType);
8455
+ yield pushToken(buffer, parseInfo, exports.EnumToken.WhitespaceTokenType);
8431
8456
  buffer = '';
8432
8457
  }
8433
8458
  switch (charCode) {
@@ -8475,8 +8500,7 @@ function* tokenize$1(parseInfo, yieldEOFToken = true) {
8475
8500
  buffer = '';
8476
8501
  }
8477
8502
  if (match$1(parseInfo, '=')) {
8478
- yield pushToken('', parseInfo, exports.EnumToken.LteTokenType);
8479
- next(parseInfo);
8503
+ yield pushToken(value + next(parseInfo), parseInfo, exports.EnumToken.LteTokenType);
8480
8504
  break;
8481
8505
  }
8482
8506
  buffer += value;
@@ -8531,8 +8555,7 @@ function* tokenize$1(parseInfo, yieldEOFToken = true) {
8531
8555
  }
8532
8556
  if (charCode == 124 /* TokenMap.PIPE */) {
8533
8557
  if (match$1(parseInfo, '|')) {
8534
- next(parseInfo);
8535
- yield pushToken('', parseInfo, exports.EnumToken.ColumnCombinatorTokenType);
8558
+ yield pushToken(value + next(parseInfo), parseInfo, exports.EnumToken.ColumnCombinatorTokenType);
8536
8559
  }
8537
8560
  else if (match$1(parseInfo, '=')) {
8538
8561
  buffer += next(parseInfo);
@@ -8586,11 +8609,10 @@ function* tokenize$1(parseInfo, yieldEOFToken = true) {
8586
8609
  buffer = '';
8587
8610
  }
8588
8611
  if (match$1(parseInfo, '=')) {
8589
- yield pushToken('', parseInfo, exports.EnumToken.GteTokenType);
8590
- next(parseInfo);
8612
+ yield pushToken(value + next(parseInfo), parseInfo, exports.EnumToken.GteTokenType);
8591
8613
  }
8592
8614
  else {
8593
- yield pushToken('', parseInfo, exports.EnumToken.GtTokenType);
8615
+ yield pushToken(value, parseInfo, exports.EnumToken.GtTokenType);
8594
8616
  }
8595
8617
  consumeWhiteSpace(parseInfo);
8596
8618
  break;
@@ -8641,7 +8663,7 @@ function* tokenize$1(parseInfo, yieldEOFToken = true) {
8641
8663
  yield pushToken(buffer, parseInfo);
8642
8664
  buffer = '';
8643
8665
  }
8644
- yield pushToken('', parseInfo, exports.EnumToken.EndParensTokenType);
8666
+ yield pushToken(value, parseInfo, exports.EnumToken.EndParensTokenType);
8645
8667
  break;
8646
8668
  case 40 /* TokenMap.OPEN_PAREN */:
8647
8669
  if (buffer.length == 0) {
@@ -8707,7 +8729,7 @@ function* tokenize$1(parseInfo, yieldEOFToken = true) {
8707
8729
  // ')'
8708
8730
  if (charCode == 0x29) {
8709
8731
  yield pushToken(buffer, parseInfo, hasNewLine ? exports.EnumToken.BadStringTokenType : exports.EnumToken.StringTokenType);
8710
- yield pushToken('', parseInfo, exports.EnumToken.EndParensTokenType);
8732
+ yield pushToken(value, parseInfo, exports.EnumToken.EndParensTokenType);
8711
8733
  buffer = '';
8712
8734
  break;
8713
8735
  }
@@ -8731,7 +8753,7 @@ function* tokenize$1(parseInfo, yieldEOFToken = true) {
8731
8753
  charCode = value.charCodeAt(0);
8732
8754
  if (charCode == 0x29) { // ')'
8733
8755
  yield pushToken(buffer, parseInfo, exports.EnumToken.UrlTokenTokenType);
8734
- yield pushToken('', parseInfo, exports.EnumToken.EndParensTokenType);
8756
+ yield pushToken(value, parseInfo, exports.EnumToken.EndParensTokenType);
8735
8757
  buffer = '';
8736
8758
  break;
8737
8759
  }
@@ -8765,8 +8787,7 @@ function* tokenize$1(parseInfo, yieldEOFToken = true) {
8765
8787
  buffer = '';
8766
8788
  }
8767
8789
  if (match$1(parseInfo, 'important')) {
8768
- yield pushToken('', parseInfo, exports.EnumToken.ImportantTokenType);
8769
- next(parseInfo, 9);
8790
+ yield pushToken(value + next(parseInfo, 9), parseInfo, exports.EnumToken.ImportantTokenType);
8770
8791
  buffer = '';
8771
8792
  break;
8772
8793
  }
@@ -13018,7 +13039,27 @@ var atRules = {
13018
13039
  }
13019
13040
  },
13020
13041
  "@nest": {
13021
- syntax: "<complex-selector-list>"
13042
+ },
13043
+ "@stylistic": {
13044
+ syntax: " @stylistic { <feature-value-declaration-list> } "
13045
+ },
13046
+ "@historical-forms": {
13047
+ syntax: " @historical-forms { <feature-value-declaration-list> } "
13048
+ },
13049
+ "@styleset": {
13050
+ syntax: " @styleset { <feature-value-declaration-list> } "
13051
+ },
13052
+ "@character-variant": {
13053
+ syntax: " @character-variant { <feature-value-declaration-list> } "
13054
+ },
13055
+ "@swash": {
13056
+ syntax: " @swash { <feature-value-declaration-list> } "
13057
+ },
13058
+ "@ornaments": {
13059
+ syntax: " @ornaments { <feature-value-declaration-list> } "
13060
+ },
13061
+ "@annotation": {
13062
+ syntax: " @annotation { <feature-value-declaration-list> } "
13022
13063
  }
13023
13064
  };
13024
13065
  var config$3 = {
@@ -13081,7 +13122,6 @@ var ValidationSyntaxGroupEnum;
13081
13122
  ValidationSyntaxGroupEnum["Selectors"] = "selectors";
13082
13123
  ValidationSyntaxGroupEnum["AtRules"] = "atRules";
13083
13124
  })(ValidationSyntaxGroupEnum || (ValidationSyntaxGroupEnum = {}));
13084
-
13085
13125
  const skipped = [
13086
13126
  ValidationTokenEnum.Star,
13087
13127
  ValidationTokenEnum.HashMark,
@@ -14162,7 +14202,6 @@ function getParsedSyntax(group, key) {
14162
14202
  const index = group + '.' + keys.join('.');
14163
14203
  // @ts-ignore
14164
14204
  if (!parsedSyntaxes.has(index)) {
14165
- // @ts-ignore
14166
14205
  const syntax = parseSyntax(obj.syntax);
14167
14206
  // @ts-ignore
14168
14207
  parsedSyntaxes.set(index, syntax.chi);
@@ -14629,9 +14668,10 @@ function dirname(path) {
14629
14668
  if (chr == '/') {
14630
14669
  parts.push('');
14631
14670
  }
14632
- else if (chr == '?' || chr == '#') {
14633
- break;
14634
- }
14671
+ // else if (chr == '?' || chr == '#') {
14672
+ //
14673
+ // break;
14674
+ // }
14635
14675
  else {
14636
14676
  parts[parts.length - 1] += chr;
14637
14677
  }
@@ -14686,6 +14726,8 @@ function resolve(url, currentDirectory, cwd) {
14686
14726
  relative: url
14687
14727
  };
14688
14728
  }
14729
+ cwd ??= '';
14730
+ currentDirectory ??= '';
14689
14731
  if (matchUrl.test(currentDirectory)) {
14690
14732
  const path = new URL(url, currentDirectory).href;
14691
14733
  return {
@@ -14737,6 +14779,116 @@ exports.FeatureWalkMode = void 0;
14737
14779
  const config$2 = getSyntaxConfig();
14738
14780
  // @ts-ignore
14739
14781
  const allValues = getSyntaxConfig()["declarations" /* ValidationSyntaxGroupEnum.Declarations */].all.syntax.trim().split(/[\s|]+/g);
14782
+ /**
14783
+ * Check if a node is allowed as child in a given context
14784
+ * @param node
14785
+ * @param context
14786
+ */
14787
+ function isNodeAllowedInContext(node, context) {
14788
+ if (node.typ == exports.EnumToken.CommentNodeType || context == null) {
14789
+ return true;
14790
+ }
14791
+ switch (context?.typ) {
14792
+ case exports.EnumToken.StyleSheetNodeType:
14793
+ case exports.EnumToken.RuleNodeType:
14794
+ return node.typ == exports.EnumToken.RuleNodeType ||
14795
+ node.typ == exports.EnumToken.AtRuleNodeType ||
14796
+ node.typ == exports.EnumToken.KeyframesAtRuleNodeType ||
14797
+ (node.typ == exports.EnumToken.DeclarationNodeType && context.typ == exports.EnumToken.RuleNodeType) ||
14798
+ (node.typ == exports.EnumToken.CDOCOMMNodeType && context.typ == exports.EnumToken.StyleSheetNodeType);
14799
+ case exports.EnumToken.KeyframesAtRuleNodeType:
14800
+ return node.typ == exports.EnumToken.KeyFramesRuleNodeType;
14801
+ case exports.EnumToken.KeyFramesRuleNodeType:
14802
+ return node.typ == exports.EnumToken.DeclarationNodeType;
14803
+ case exports.EnumToken.AtRuleNodeType:
14804
+ // @ts-ignore
14805
+ const syntax = getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, '@' + context.nam)?.[0].chi ?? null;
14806
+ //
14807
+ if (syntax == null) {
14808
+ // console.error(`syntax: Not found ${ValidationSyntaxGroupEnum.AtRules}@${(context as AstAtRule).nam}`);
14809
+ return true;
14810
+ }
14811
+ const stack = syntax.slice();
14812
+ for (const child of stack) {
14813
+ if (Array.isArray(child)) {
14814
+ stack.push(...child);
14815
+ continue;
14816
+ }
14817
+ if ('chi' in child && Array.isArray(child.chi)) {
14818
+ stack.push(...child.chi);
14819
+ continue;
14820
+ }
14821
+ // @ts-ignore
14822
+ if (child.l != null) {
14823
+ // @ts-ignore
14824
+ stack.push(child.l);
14825
+ // @ts-ignore
14826
+ if (child.r != null) {
14827
+ // @ts-ignore
14828
+ stack.push(...(Array.isArray(child.r) ? child.r : [child.r]));
14829
+ }
14830
+ continue;
14831
+ }
14832
+ if (node.typ == exports.EnumToken.DeclarationNodeType) {
14833
+ if (child.typ == ValidationTokenEnum.DeclarationDefinitionToken) {
14834
+ if (node.nam == child.nam) {
14835
+ return true;
14836
+ }
14837
+ }
14838
+ }
14839
+ if (child.typ == ValidationTokenEnum.PropertyType) {
14840
+ if (['group-rule-body', 'block-contents', 'rule-list', 'stylesheet'].includes(child.val)) {
14841
+ if ((node.typ == exports.EnumToken.RuleNodeType ||
14842
+ node.typ == exports.EnumToken.AtRuleNodeType ||
14843
+ node.typ == exports.EnumToken.KeyframesAtRuleNodeType)) {
14844
+ return true;
14845
+ }
14846
+ if (node.typ == exports.EnumToken.DeclarationNodeType) {
14847
+ let parent = node.parent;
14848
+ while (parent != null) {
14849
+ if (parent.parent?.typ == exports.EnumToken.RuleNodeType) {
14850
+ return true;
14851
+ }
14852
+ parent = parent.parent;
14853
+ }
14854
+ }
14855
+ }
14856
+ if (['declaration-list', 'feature-value-declaration'].includes(child.val) && node.typ == exports.EnumToken.DeclarationNodeType) {
14857
+ return true;
14858
+ }
14859
+ if (child.val == 'page-body' && (node.typ == exports.EnumToken.DeclarationNodeType || (node.typ == exports.EnumToken.AtRuleNodeType && [
14860
+ 'top-left-corner', 'top-left', 'top-center', 'top-right', 'top-right-corner',
14861
+ 'bottom-left-corner', 'bottom-left', 'bottom-center', 'bottom-right', 'bottom-right-corner',
14862
+ 'left-top', 'left-middle', 'left-bottom', 'right-top', 'right-middle', 'right-bottom'
14863
+ ].includes(node.nam)))) {
14864
+ return true;
14865
+ }
14866
+ if (child.val == 'feature-value-block-list' &&
14867
+ (node.typ == exports.EnumToken.AtRuleNodeType && ['stylistic', 'historical-forms', 'styleset', 'character-variant', 'swash', 'ornaments', 'annotation'].includes(node.nam))) {
14868
+ return true;
14869
+ }
14870
+ if (['feature-value-declaration-list', 'feature-value-declaration'].includes(child.val) && node.typ == exports.EnumToken.DeclarationNodeType) {
14871
+ return true;
14872
+ }
14873
+ if (child.val == 'page-body') {
14874
+ if (node.typ == exports.EnumToken.DeclarationNodeType) {
14875
+ return true;
14876
+ }
14877
+ }
14878
+ // console.error(`isNodeAllowedInContext: Not found ${(child as ValidationPropertyToken).val}`, {
14879
+ // child,
14880
+ // node
14881
+ // });
14882
+ }
14883
+ }
14884
+ break;
14885
+ }
14886
+ return false;
14887
+ }
14888
+ /**
14889
+ * Create a syntax validation context from a list of tokens
14890
+ * @param input
14891
+ */
14740
14892
  function createContext(input) {
14741
14893
  const values = input.slice();
14742
14894
  const result = values.filter(token => token.typ != exports.EnumToken.CommentTokenType).slice();
@@ -14797,7 +14949,22 @@ function createContext(input) {
14797
14949
  }
14798
14950
  };
14799
14951
  }
14800
- function evaluateSyntax(node, options) {
14952
+ /**
14953
+ * Evaluate the validity of the syntax of a node
14954
+ * @param node
14955
+ * @param parent
14956
+ * @param options
14957
+ */
14958
+ function evaluateSyntax(node, parent, options) {
14959
+ if (node.validSyntax) {
14960
+ return {
14961
+ valid: SyntaxValidationResult.Valid,
14962
+ node,
14963
+ syntax: null,
14964
+ error: '',
14965
+ context: []
14966
+ };
14967
+ }
14801
14968
  let ast;
14802
14969
  let result;
14803
14970
  switch (node.typ) {
@@ -14805,25 +14972,34 @@ function evaluateSyntax(node, options) {
14805
14972
  if (node.nam.startsWith('--')) {
14806
14973
  break;
14807
14974
  }
14975
+ let token = null;
14976
+ let values = node.val.slice();
14808
14977
  ast = getParsedSyntax("declarations" /* ValidationSyntaxGroupEnum.Declarations */, node.nam);
14809
- if (ast != null) {
14810
- let token = null;
14811
- const values = node.val.slice();
14812
- while (values.length > 0) {
14813
- token = values.at(-1);
14814
- if (token.typ == exports.EnumToken.WhitespaceTokenType || token.typ == exports.EnumToken.CommentTokenType) {
14978
+ while (values.length > 0) {
14979
+ token = values.at(-1);
14980
+ if (token.typ == exports.EnumToken.WhitespaceTokenType || token.typ == exports.EnumToken.CommentTokenType) {
14981
+ values.pop();
14982
+ }
14983
+ else {
14984
+ if (token.typ == exports.EnumToken.ImportantTokenType) {
14815
14985
  values.pop();
14816
- }
14817
- else {
14818
- if (token.typ == exports.EnumToken.ImportantTokenType) {
14986
+ if (values.at(-1)?.typ == exports.EnumToken.WhitespaceTokenType) {
14819
14987
  values.pop();
14820
- if (values.at(-1)?.typ == exports.EnumToken.WhitespaceTokenType) {
14821
- values.pop();
14822
- }
14823
14988
  }
14824
- break;
14989
+ }
14990
+ break;
14991
+ }
14992
+ }
14993
+ if (ast == null) {
14994
+ if (parent?.typ == exports.EnumToken.AtRuleNodeType) {
14995
+ ast = (getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, ['@' + parent.nam, 'descriptors', node.nam]));
14996
+ if (ast == null) {
14997
+ ast = (getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, ['@' + parent.nam, 'descriptors', node.nam]) ?? getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, '@' + parent.nam))?.[0]?.chi;
14998
+ values = [{ ...node, val: values }];
14825
14999
  }
14826
15000
  }
15001
+ }
15002
+ if (ast != null) {
14827
15003
  result = doEvaluateSyntax(ast, createContext(values), { ...options, visited: new WeakMap() });
14828
15004
  if (result.valid == SyntaxValidationResult.Valid && !result.context.done()) {
14829
15005
  let token = null;
@@ -14915,7 +15091,7 @@ function doEvaluateSyntax(syntaxes, context, options) {
14915
15091
  continue;
14916
15092
  }
14917
15093
  }
14918
- else if (options.occurence !== false && syntax.occurence != null) {
15094
+ else if (options.occurrence !== false && syntax.occurence != null) {
14919
15095
  result = matchOccurence(syntax, context, options);
14920
15096
  }
14921
15097
  else if (options.atLeastOnce !== false && syntax.atLeastOnce) {
@@ -15004,7 +15180,7 @@ function matchList(syntax, context, options) {
15004
15180
  result = doEvaluateSyntax([syntax], createContext(tokens), {
15005
15181
  ...options,
15006
15182
  isList: false,
15007
- occurence: false
15183
+ occurrence: false
15008
15184
  });
15009
15185
  if (result.valid == SyntaxValidationResult.Valid) {
15010
15186
  context = con.clone();
@@ -15039,7 +15215,7 @@ function matchOccurence(syntax, context, options) {
15039
15215
  let counter = 0;
15040
15216
  let result;
15041
15217
  do {
15042
- result = match(syntax, context.clone(), { ...options, occurence: false });
15218
+ result = match(syntax, context.clone(), { ...options, occurrence: false });
15043
15219
  if (result.valid == SyntaxValidationResult.Drop) {
15044
15220
  break;
15045
15221
  }
@@ -15090,7 +15266,7 @@ function match(syntax, context, options) {
15090
15266
  ...options,
15091
15267
  isRepeatable: null,
15092
15268
  isList: null,
15093
- occurence: null,
15269
+ occurrence: null,
15094
15270
  atLeastOnce: null
15095
15271
  });
15096
15272
  if (result.valid == SyntaxValidationResult.Valid) {
@@ -15102,7 +15278,7 @@ function match(syntax, context, options) {
15102
15278
  case ValidationTokenEnum.Keyword:
15103
15279
  success = (token.typ == exports.EnumToken.IdenTokenType || token.typ == exports.EnumToken.DashedIdenTokenType || isIdentColor(token)) &&
15104
15280
  (token.val == syntax.val ||
15105
- syntax.val === token.val?.toLowerCase?.() ||
15281
+ syntax.val.toLowerCase() === token.val?.toLowerCase?.() ||
15106
15282
  // config.declarations.all
15107
15283
  allValues.includes(token.val.toLowerCase()));
15108
15284
  if (success) {
@@ -15141,7 +15317,7 @@ function match(syntax, context, options) {
15141
15317
  ...options,
15142
15318
  isRepeatable: null,
15143
15319
  isList: null,
15144
- occurence: null,
15320
+ occurrence: null,
15145
15321
  atLeastOnce: null
15146
15322
  });
15147
15323
  case ValidationTokenEnum.Comma:
@@ -15176,7 +15352,7 @@ function match(syntax, context, options) {
15176
15352
  ...options,
15177
15353
  isRepeatable: null,
15178
15354
  isList: null,
15179
- occurence: null,
15355
+ occurrence: null,
15180
15356
  atLeastOnce: null
15181
15357
  }).valid == SyntaxValidationResult.Valid;
15182
15358
  if (success) {
@@ -15199,18 +15375,19 @@ function match(syntax, context, options) {
15199
15375
  }
15200
15376
  function matchPropertyType(syntax, context, options) {
15201
15377
  if (![
15202
- 'bg-position',
15378
+ 'color',
15203
15379
  'integer',
15380
+ 'bg-position',
15204
15381
  'length-percentage', 'flex', 'calc-sum', 'color',
15205
15382
  'color-base', 'system-color', 'deprecated-system-color',
15206
- 'pseudo-class-selector', 'pseudo-element-selector'
15383
+ 'pseudo-class-selector', 'pseudo-element-selector', 'feature-value-declaration'
15207
15384
  ].includes(syntax.val)) {
15208
15385
  if (syntax.val in config$2["syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */]) {
15209
15386
  return doEvaluateSyntax(getParsedSyntax("syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */, syntax.val), context, {
15210
15387
  ...options,
15211
15388
  isRepeatable: null,
15212
15389
  isList: null,
15213
- occurence: null,
15390
+ occurrence: null,
15214
15391
  atLeastOnce: null
15215
15392
  });
15216
15393
  }
@@ -15222,7 +15399,7 @@ function matchPropertyType(syntax, context, options) {
15222
15399
  ...options,
15223
15400
  isRepeatable: null,
15224
15401
  isList: null,
15225
- occurence: null,
15402
+ occurrence: null,
15226
15403
  atLeastOnce: null
15227
15404
  });
15228
15405
  if (result.valid == SyntaxValidationResult.Valid) {
@@ -15327,6 +15504,14 @@ function matchPropertyType(syntax, context, options) {
15327
15504
  (token.typ == exports.EnumToken.IdenTokenType && typeof Math[token.val.toUpperCase()] == 'number') ||
15328
15505
  [exports.EnumToken.BinaryExpressionTokenType, exports.EnumToken.NumberTokenType, exports.EnumToken.PercentageTokenType, exports.EnumToken.DimensionTokenType, exports.EnumToken.LengthTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.TimeTokenType, exports.EnumToken.ResolutionTokenType, exports.EnumToken.FrequencyTokenType].includes(token.typ);
15329
15506
  break;
15507
+ case 'declaration':
15508
+ {
15509
+ success = token.typ == exports.EnumToken.DeclarationNodeType;
15510
+ if (success) {
15511
+ success = evaluateSyntax(token, null, options).valid == SyntaxValidationResult.Valid;
15512
+ }
15513
+ }
15514
+ break;
15330
15515
  case 'declaration-value':
15331
15516
  while (!context.done()) {
15332
15517
  context.next();
@@ -15353,13 +15538,17 @@ function matchPropertyType(syntax, context, options) {
15353
15538
  break;
15354
15539
  case 'color':
15355
15540
  case 'color-base':
15356
- success = token.typ == exports.EnumToken.ColorTokenType || (token.typ == exports.EnumToken.IdenTokenType && 'currentcolor' === token.val.toLowerCase()) || (token.typ == exports.EnumToken.IdenTokenType && 'transparent' === token.val.toLowerCase()) || (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val));
15541
+ success = token.typ == exports.EnumToken.ColorTokenType ||
15542
+ (token.typ == exports.EnumToken.IdenTokenType && 'currentcolor' === token.val.toLowerCase()) ||
15543
+ (token.typ == exports.EnumToken.IdenTokenType && 'transparent' === token.val.toLowerCase()) ||
15544
+ (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val) ||
15545
+ isColor(token));
15357
15546
  if (!success && token.typ == exports.EnumToken.FunctionTokenType && colorsFunc.includes(token.val)) {
15358
15547
  success = doEvaluateSyntax(getParsedSyntax("functions" /* ValidationSyntaxGroupEnum.Functions */, token.val)?.[0]?.chi, createContext(token.chi), {
15359
15548
  ...options,
15360
15549
  isRepeatable: null,
15361
15550
  isList: null,
15362
- occurence: null,
15551
+ occurrence: null,
15363
15552
  atLeastOnce: null
15364
15553
  }).valid == SyntaxValidationResult.Valid;
15365
15554
  }
@@ -15367,8 +15556,26 @@ function matchPropertyType(syntax, context, options) {
15367
15556
  case 'hex-color':
15368
15557
  success = (token.typ == exports.EnumToken.ColorTokenType && token.kin == exports.ColorType.HEX) || (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val));
15369
15558
  break;
15559
+ case 'feature-value-declaration':
15560
+ {
15561
+ let hasNumber = false;
15562
+ success = token.typ == exports.EnumToken.DeclarationNodeType && token.val.length > 0 && token.val.every((val) => {
15563
+ if (val.typ == exports.EnumToken.WhitespaceTokenType || val.typ == exports.EnumToken.CommentTokenType) {
15564
+ return true;
15565
+ }
15566
+ const success = (val.typ == exports.EnumToken.NumberTokenType && Number.isInteger(+val.val) && val.val > 0) || (val.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(val.val.toLowerCase()) || (val.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(val.val)));
15567
+ if (success) {
15568
+ hasNumber = true;
15569
+ }
15570
+ if ('range' in syntax) {
15571
+ return success && +val.val >= +syntax.range[0] && +val.val <= +syntax.range[1];
15572
+ }
15573
+ return success;
15574
+ }) && hasNumber;
15575
+ }
15576
+ break;
15370
15577
  case 'integer':
15371
- success = (token.typ == exports.EnumToken.NumberTokenType && Number.isInteger(+(token.val))) || (token.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(token.val.toLowerCase()) || (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val)));
15578
+ success = (token.typ == exports.EnumToken.NumberTokenType && Number.isInteger(+token.val) && token.val > 0) || (token.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(token.val.toLowerCase()) || (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val)));
15372
15579
  if ('range' in syntax) {
15373
15580
  success = success && +token.val >= +syntax.range[0] && +token.val <= +syntax.range[1];
15374
15581
  }
@@ -15432,7 +15639,7 @@ function matchPropertyType(syntax, context, options) {
15432
15639
  ...options,
15433
15640
  isRepeatable: null,
15434
15641
  isList: null,
15435
- occurence: null,
15642
+ occurrence: null,
15436
15643
  atLeastOnce: null
15437
15644
  }).valid == SyntaxValidationResult.Valid;
15438
15645
  }
@@ -15448,7 +15655,7 @@ function matchPropertyType(syntax, context, options) {
15448
15655
  ...options,
15449
15656
  isRepeatable: null,
15450
15657
  isList: null,
15451
- occurence: null,
15658
+ occurrence: null,
15452
15659
  atLeastOnce: null
15453
15660
  }).valid == SyntaxValidationResult.Valid;
15454
15661
  }
@@ -15595,7 +15802,6 @@ function allOf(syntax, context, options) {
15595
15802
  i = -1;
15596
15803
  }
15597
15804
  }
15598
- // console.error()
15599
15805
  const success = syntax.length == 0;
15600
15806
  return {
15601
15807
  valid: success ? SyntaxValidationResult.Valid : SyntaxValidationResult.Drop,
@@ -15675,6 +15881,17 @@ function validateSelector(selector, options, root) {
15675
15881
  }
15676
15882
 
15677
15883
  function validateAtRuleMedia(atRule, options, root) {
15884
+ if (!Array.isArray(atRule.chi)) {
15885
+ // @ts-ignore
15886
+ return {
15887
+ valid: SyntaxValidationResult.Drop,
15888
+ matches: [],
15889
+ node: atRule,
15890
+ syntax: '@' + atRule.nam,
15891
+ error: 'expected supports body',
15892
+ tokens: []
15893
+ };
15894
+ }
15678
15895
  // media-query-list
15679
15896
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
15680
15897
  // @ts-ignore
@@ -15907,6 +16124,17 @@ function validateMediaFeature(token) {
15907
16124
  }
15908
16125
 
15909
16126
  function validateAtRuleCounterStyle(atRule, options, root) {
16127
+ if (!Array.isArray(atRule.chi)) {
16128
+ // @ts-ignore
16129
+ return {
16130
+ valid: SyntaxValidationResult.Drop,
16131
+ matches: [],
16132
+ node: atRule,
16133
+ syntax: '@' + atRule.nam,
16134
+ error: 'expected supports body',
16135
+ tokens: []
16136
+ };
16137
+ }
15910
16138
  // media-query-list
15911
16139
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
15912
16140
  // @ts-ignore
@@ -15976,6 +16204,17 @@ function validateAtRuleCounterStyle(atRule, options, root) {
15976
16204
  }
15977
16205
 
15978
16206
  function validateAtRulePage(atRule, options, root) {
16207
+ if (!Array.isArray(atRule.chi)) {
16208
+ // @ts-ignore
16209
+ return {
16210
+ valid: SyntaxValidationResult.Drop,
16211
+ matches: [],
16212
+ node: atRule,
16213
+ syntax: '@' + atRule.nam,
16214
+ error: 'expected supports body',
16215
+ tokens: []
16216
+ };
16217
+ }
15979
16218
  // media-query-list
15980
16219
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
15981
16220
  // @ts-ignore
@@ -16054,6 +16293,17 @@ function validateAtRulePage(atRule, options, root) {
16054
16293
  }
16055
16294
 
16056
16295
  function validateAtRulePageMarginBox(atRule, options, root) {
16296
+ if (!Array.isArray(atRule.chi)) {
16297
+ // @ts-ignore
16298
+ return {
16299
+ valid: SyntaxValidationResult.Drop,
16300
+ matches: [],
16301
+ node: atRule,
16302
+ syntax: '@' + atRule.nam,
16303
+ error: 'expected supports body',
16304
+ tokens: []
16305
+ };
16306
+ }
16057
16307
  if (Array.isArray(atRule.tokens) && atRule.tokens.length > 0) {
16058
16308
  // @ts-ignore
16059
16309
  return {
@@ -16109,6 +16359,17 @@ function validateAtRuleSupports(atRule, options, root) {
16109
16359
  tokens: []
16110
16360
  };
16111
16361
  }
16362
+ if (!Array.isArray(atRule.chi)) {
16363
+ // @ts-ignore
16364
+ return {
16365
+ valid: SyntaxValidationResult.Drop,
16366
+ matches: [],
16367
+ node: atRule,
16368
+ syntax: '@' + atRule.nam,
16369
+ error: 'expected supports body',
16370
+ tokens: []
16371
+ };
16372
+ }
16112
16373
  const result = validateAtRuleSupportsConditions(atRule, atRule.tokens);
16113
16374
  if (result) {
16114
16375
  if (result.node == null) {
@@ -16501,6 +16762,17 @@ function validateAtRuleImport(atRule, options, root) {
16501
16762
  }
16502
16763
 
16503
16764
  function validateAtRuleLayer(atRule, options, root) {
16765
+ if (!Array.isArray(atRule.chi)) {
16766
+ // @ts-ignore
16767
+ return {
16768
+ valid: SyntaxValidationResult.Drop,
16769
+ matches: [],
16770
+ node: atRule,
16771
+ syntax: '@' + atRule.nam,
16772
+ error: 'expected supports body',
16773
+ tokens: []
16774
+ };
16775
+ }
16504
16776
  // media-query-list
16505
16777
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
16506
16778
  // @ts-ignore
@@ -16517,6 +16789,17 @@ function validateAtRuleLayer(atRule, options, root) {
16517
16789
  }
16518
16790
 
16519
16791
  function validateAtRuleFontFeatureValues(atRule, options, root) {
16792
+ if (!Array.isArray(atRule.chi)) {
16793
+ // @ts-ignore
16794
+ return {
16795
+ valid: SyntaxValidationResult.Drop,
16796
+ matches: [],
16797
+ node: atRule,
16798
+ syntax: '@' + atRule.nam,
16799
+ error: 'expected supports body',
16800
+ tokens: []
16801
+ };
16802
+ }
16520
16803
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
16521
16804
  // @ts-ignore
16522
16805
  return {
@@ -16700,6 +16983,17 @@ function validateAtRuleDocument(atRule, options, root) {
16700
16983
  }
16701
16984
 
16702
16985
  function validateAtRuleKeyframes(atRule, options, root) {
16986
+ if (!Array.isArray(atRule.chi)) {
16987
+ // @ts-ignore
16988
+ return {
16989
+ valid: SyntaxValidationResult.Drop,
16990
+ matches: [],
16991
+ node: atRule,
16992
+ syntax: '@' + atRule.nam,
16993
+ error: 'expected supports body',
16994
+ tokens: []
16995
+ };
16996
+ }
16703
16997
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
16704
16998
  // @ts-ignore
16705
16999
  return {
@@ -16745,6 +17039,17 @@ function validateAtRuleKeyframes(atRule, options, root) {
16745
17039
  }
16746
17040
 
16747
17041
  function validateAtRuleWhen(atRule, options, root) {
17042
+ if (!Array.isArray(atRule.chi)) {
17043
+ // @ts-ignore
17044
+ return {
17045
+ valid: SyntaxValidationResult.Drop,
17046
+ matches: [],
17047
+ node: atRule,
17048
+ syntax: '@' + atRule.nam,
17049
+ error: 'expected supports body',
17050
+ tokens: []
17051
+ };
17052
+ }
16748
17053
  const slice = Array.isArray(atRule.tokens) ? atRule.tokens.slice() : [];
16749
17054
  consumeWhitespace(slice);
16750
17055
  if (slice.length == 0) {
@@ -16908,6 +17213,17 @@ const validateAtRuleElse = validateAtRuleWhen;
16908
17213
 
16909
17214
  const validateContainerScrollStateFeature = validateContainerSizeFeature;
16910
17215
  function validateAtRuleContainer(atRule, options, root) {
17216
+ if (!Array.isArray(atRule.chi)) {
17217
+ // @ts-ignore
17218
+ return {
17219
+ valid: SyntaxValidationResult.Drop,
17220
+ matches: [],
17221
+ node: atRule,
17222
+ syntax: '@' + atRule.nam,
17223
+ error: 'expected supports body',
17224
+ tokens: []
17225
+ };
17226
+ }
16911
17227
  // media-query-list
16912
17228
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
16913
17229
  // @ts-ignore
@@ -17444,12 +17760,13 @@ function normalizeVisitorKeyName(keyName) {
17444
17760
  return keyName.replace(/-([a-z])/g, (all, one) => one.toUpperCase());
17445
17761
  }
17446
17762
  function replaceToken(parent, value, replacement) {
17447
- // @ts-ignore
17448
- if ('parent' in value && value.parent != replacement.parent) {
17449
- Object.defineProperty(replacement, 'parent', {
17450
- ...definedPropertySettings,
17451
- value: value.parent
17452
- });
17763
+ for (const node of (Array.isArray(replacement) ? replacement : [replacement])) {
17764
+ if ('parent' in value && value.parent != node.parent) {
17765
+ Object.defineProperty(node, 'parent', {
17766
+ ...definedPropertySettings,
17767
+ value: value.parent
17768
+ });
17769
+ }
17453
17770
  }
17454
17771
  if (parent.typ == exports.EnumToken.BinaryExpressionTokenType) {
17455
17772
  if (parent.l == value) {
@@ -17460,14 +17777,12 @@ function replaceToken(parent, value, replacement) {
17460
17777
  }
17461
17778
  }
17462
17779
  else {
17463
- // @ts-ignore
17464
17780
  const target = 'val' in parent && Array.isArray(parent.val) ? parent.val : parent.chi;
17465
17781
  // @ts-ignore
17466
17782
  const index = target.indexOf(value);
17467
17783
  if (index == -1) {
17468
17784
  return;
17469
17785
  }
17470
- // @ts-ignore
17471
17786
  target.splice(index, 1, ...(Array.isArray(replacement) ? replacement : [replacement]));
17472
17787
  }
17473
17788
  }
@@ -17520,6 +17835,8 @@ async function doParse(iter, options = {}) {
17520
17835
  const stats = {
17521
17836
  src: options.src ?? '',
17522
17837
  bytesIn: 0,
17838
+ nodesCount: 0,
17839
+ tokensCount: 0,
17523
17840
  importedBytesIn: 0,
17524
17841
  parse: `0ms`,
17525
17842
  minify: `0ms`,
@@ -17548,19 +17865,112 @@ async function doParse(iter, options = {}) {
17548
17865
  src: ''
17549
17866
  };
17550
17867
  }
17551
- let item;
17552
- let node;
17868
+ let valuesHandlers;
17869
+ let preValuesHandlers;
17870
+ let postValuesHandlers;
17871
+ let preVisitorsHandlersMap;
17872
+ let visitorsHandlersMap;
17873
+ let postVisitorsHandlersMap;
17553
17874
  const rawTokens = [];
17554
17875
  const imports = [];
17876
+ let item;
17877
+ let node;
17555
17878
  // @ts-ignore ignore error
17556
17879
  let isAsync = typeof iter[Symbol.asyncIterator] === 'function';
17557
- while (item = isAsync ? (await iter.next()).value : iter.next().value) {
17558
- stats.bytesIn = item.bytesIn;
17559
- rawTokens.push(item);
17560
- if (item.hint != null && BadTokensTypes.includes(item.hint)) {
17561
- const node = getTokenType(item.token, item.hint);
17562
- errors.push({
17563
- action: 'drop',
17880
+ if (options.visitor != null) {
17881
+ valuesHandlers = new Map;
17882
+ preValuesHandlers = new Map;
17883
+ postValuesHandlers = new Map;
17884
+ preVisitorsHandlersMap = new Map;
17885
+ visitorsHandlersMap = new Map;
17886
+ postVisitorsHandlersMap = new Map;
17887
+ const visitors = Object.entries(options.visitor);
17888
+ let key;
17889
+ let value;
17890
+ let i;
17891
+ for (i = 0; i < visitors.length; i++) {
17892
+ key = visitors[i][0];
17893
+ value = visitors[i][1];
17894
+ if (Number.isInteger(+key)) {
17895
+ visitors.splice(i + 1, 0, ...Object.entries(value));
17896
+ continue;
17897
+ }
17898
+ if (Array.isArray(value)) {
17899
+ // @ts-ignore
17900
+ visitors.splice(i + 1, 0, ...value.map((item) => [key, item]));
17901
+ continue;
17902
+ }
17903
+ if (key in exports.EnumToken) {
17904
+ if (typeof value == 'function') {
17905
+ if (!valuesHandlers.has(exports.EnumToken[key])) {
17906
+ valuesHandlers.set(exports.EnumToken[key], []);
17907
+ }
17908
+ valuesHandlers.get(exports.EnumToken[key]).push(value);
17909
+ }
17910
+ else if (typeof value == 'object' && 'type' in value && 'handler' in value && value.type in exports.WalkerEvent) {
17911
+ if (value.type == exports.WalkerEvent.Enter) {
17912
+ if (!preValuesHandlers.has(exports.EnumToken[key])) {
17913
+ preValuesHandlers.set(exports.EnumToken[key], []);
17914
+ }
17915
+ preValuesHandlers.get(exports.EnumToken[key]).push(value.handler);
17916
+ }
17917
+ else if (value.type == exports.WalkerEvent.Leave) {
17918
+ if (!postValuesHandlers.has(exports.EnumToken[key])) {
17919
+ postValuesHandlers.set(exports.EnumToken[key], []);
17920
+ }
17921
+ postValuesHandlers.get(exports.EnumToken[key]).push(value.handler);
17922
+ }
17923
+ }
17924
+ else {
17925
+ errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
17926
+ }
17927
+ }
17928
+ else if (['Declaration', 'Rule', 'AtRule', 'KeyframesRule', 'KeyframesAtRule'].includes(key)) {
17929
+ if (typeof value == 'function') {
17930
+ if (!visitorsHandlersMap.has(key)) {
17931
+ visitorsHandlersMap.set(key, []);
17932
+ }
17933
+ visitorsHandlersMap.get(key).push(value);
17934
+ }
17935
+ else if (typeof value == 'object') {
17936
+ if ('type' in value && 'handler' in value && value.type in exports.WalkerEvent) {
17937
+ if (value.type == exports.WalkerEvent.Enter) {
17938
+ if (!preVisitorsHandlersMap.has(key)) {
17939
+ preVisitorsHandlersMap.set(key, []);
17940
+ }
17941
+ preVisitorsHandlersMap.get(key).push(value.handler);
17942
+ }
17943
+ else if (value.type == exports.WalkerEvent.Leave) {
17944
+ if (!postVisitorsHandlersMap.has(key)) {
17945
+ postVisitorsHandlersMap.set(key, []);
17946
+ }
17947
+ postVisitorsHandlersMap.get(key).push(value.handler);
17948
+ }
17949
+ }
17950
+ else {
17951
+ if (!visitorsHandlersMap.has(key)) {
17952
+ visitorsHandlersMap.set(key, []);
17953
+ }
17954
+ visitorsHandlersMap.get(key).push(value);
17955
+ }
17956
+ }
17957
+ else {
17958
+ errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
17959
+ }
17960
+ }
17961
+ else {
17962
+ errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
17963
+ }
17964
+ }
17965
+ }
17966
+ while (item = isAsync ? (await iter.next()).value : iter.next().value) {
17967
+ stats.bytesIn = item.bytesIn;
17968
+ stats.tokensCount++;
17969
+ rawTokens.push(item);
17970
+ if (item.hint != null && BadTokensTypes.includes(item.hint)) {
17971
+ const node = getTokenType(item.token, item.hint);
17972
+ errors.push({
17973
+ action: 'drop',
17564
17974
  message: 'Bad token',
17565
17975
  syntax: null,
17566
17976
  node,
@@ -17583,7 +17993,7 @@ async function doParse(iter, options = {}) {
17583
17993
  ast.loc.end = item.end;
17584
17994
  }
17585
17995
  if (item.token == ';' || item.token == '{') {
17586
- node = parseNode(tokens, context, options, errors, src, map, rawTokens);
17996
+ node = parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
17587
17997
  rawTokens.length = 0;
17588
17998
  if (node != null) {
17589
17999
  if ('chi' in node) {
@@ -17627,7 +18037,7 @@ async function doParse(iter, options = {}) {
17627
18037
  map = new Map;
17628
18038
  }
17629
18039
  else if (item.token == '}') {
17630
- parseNode(tokens, context, options, errors, src, map, rawTokens);
18040
+ parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
17631
18041
  rawTokens.length = 0;
17632
18042
  if (context.loc != null) {
17633
18043
  context.loc.end = item.end;
@@ -17648,7 +18058,7 @@ async function doParse(iter, options = {}) {
17648
18058
  }
17649
18059
  }
17650
18060
  if (tokens.length > 0) {
17651
- node = parseNode(tokens, context, options, errors, src, map, rawTokens);
18061
+ node = parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
17652
18062
  rawTokens.length = 0;
17653
18063
  if (node != null) {
17654
18064
  if (node.typ == exports.EnumToken.AtRuleNodeType && node.nam == 'import') {
@@ -17711,228 +18121,153 @@ async function doParse(iter, options = {}) {
17711
18121
  if (options.expandNestingRules) {
17712
18122
  ast = expand(ast);
17713
18123
  }
17714
- const valuesHandlers = new Map;
17715
- const preValuesHandlers = new Map;
17716
- const postValuesHandlers = new Map;
17717
- const preVisitorsHandlersMap = new Map;
17718
- const visitorsHandlersMap = new Map;
17719
- const postVisitorsHandlersMap = new Map;
17720
- const allValuesHandlers = [];
18124
+ let replacement;
18125
+ let callable;
17721
18126
  if (options.visitor != null) {
17722
- for (const [key, value] of Object.entries(options.visitor)) {
17723
- if (key in exports.EnumToken) {
17724
- if (typeof value == 'function') {
17725
- valuesHandlers.set(exports.EnumToken[key], value);
17726
- }
17727
- else if (typeof value == 'object' && 'type' in value && 'handler' in value && value.type in exports.WalkerValueEvent) {
17728
- if (exports.WalkerValueEvent[value.type] == exports.WalkerValueEvent.Enter) {
17729
- preValuesHandlers.set(exports.EnumToken[key], value.handler);
18127
+ for (const result of walk(ast)) {
18128
+ if (valuesHandlers.size > 0 || preVisitorsHandlersMap.size > 0 || visitorsHandlersMap.size > 0 || postVisitorsHandlersMap.size > 0) {
18129
+ if ((result.node.typ == exports.EnumToken.DeclarationNodeType &&
18130
+ (preVisitorsHandlersMap.has('Declaration') || visitorsHandlersMap.has('Declaration') || postVisitorsHandlersMap.has('Declaration'))) ||
18131
+ (result.node.typ == exports.EnumToken.AtRuleNodeType && (preVisitorsHandlersMap.has('AtRule') || visitorsHandlersMap.has('AtRule') || postVisitorsHandlersMap.has('AtRule'))) ||
18132
+ (result.node.typ == exports.EnumToken.KeyframesAtRuleNodeType && (preVisitorsHandlersMap.has('KeyframesAtRule') || visitorsHandlersMap.has('KeyframesAtRule') || postVisitorsHandlersMap.has('KeyframesAtRule')))) {
18133
+ const handlers = [];
18134
+ const key = result.node.typ == exports.EnumToken.DeclarationNodeType ? 'Declaration' : result.node.typ == exports.EnumToken.AtRuleNodeType ? 'AtRule' : 'KeyframesAtRule';
18135
+ if (preVisitorsHandlersMap.has(key)) {
18136
+ // @ts-ignore
18137
+ handlers.push(...preVisitorsHandlersMap.get(key));
17730
18138
  }
17731
- else if (exports.WalkerValueEvent[value.type] == exports.WalkerValueEvent.Leave) {
17732
- postValuesHandlers.set(exports.EnumToken[key], value.handler);
18139
+ if (visitorsHandlersMap.has(key)) {
18140
+ // @ts-ignore
18141
+ handlers.push(...visitorsHandlersMap.get(key));
17733
18142
  }
17734
- }
17735
- else {
17736
- console.warn(`doParse: visitor.${key} is not a valid key name`);
17737
- }
17738
- }
17739
- else if (['Declaration', 'Rule', 'AtRule', 'KeyframesRule', 'KeyframesAtRule'].includes(key)) {
17740
- if (typeof value == 'function') {
17741
- visitorsHandlersMap.set(key, value);
17742
- }
17743
- else if (typeof value == 'object') {
17744
- if ('type' in value && 'handler' in value && value.type in exports.WalkerValueEvent) {
17745
- if (exports.WalkerValueEvent[value.type] == exports.WalkerValueEvent.Enter) {
17746
- preVisitorsHandlersMap.set(key, value.handler);
18143
+ if (postVisitorsHandlersMap.has(key)) {
18144
+ // @ts-ignore
18145
+ handlers.push(...postVisitorsHandlersMap.get(key));
18146
+ }
18147
+ let node = result.node;
18148
+ for (const handler of handlers) {
18149
+ callable = typeof handler == 'function' ? handler : handler[normalizeVisitorKeyName(node.typ == exports.EnumToken.DeclarationNodeType || node.typ == exports.EnumToken.AtRuleNodeType ? node.nam : node.val)];
18150
+ if (callable == null) {
18151
+ continue;
17747
18152
  }
17748
- else if (exports.WalkerValueEvent[value.type] == exports.WalkerValueEvent.Leave) {
17749
- postVisitorsHandlersMap.set(key, value.handler);
18153
+ replacement = callable(node, result.parent);
18154
+ if (replacement == null) {
18155
+ continue;
18156
+ }
18157
+ isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
18158
+ if (replacement) {
18159
+ replacement = await replacement;
18160
+ }
18161
+ if (replacement == null || replacement == node) {
18162
+ continue;
18163
+ }
18164
+ // @ts-ignore
18165
+ node = replacement;
18166
+ //
18167
+ if (Array.isArray(node)) {
18168
+ break;
17750
18169
  }
17751
18170
  }
17752
- else {
17753
- visitorsHandlersMap.set(key, value);
17754
- }
17755
- }
17756
- else {
17757
- console.warn(`doParse: visitor.${key} is not a valid key name`);
17758
- }
17759
- }
17760
- else {
17761
- console.warn(`doParse: visitor.${key} is not a valid key name`);
17762
- }
17763
- }
17764
- if (preValuesHandlers.size > 0) {
17765
- allValuesHandlers.push(preValuesHandlers);
17766
- }
17767
- if (valuesHandlers.size > 0) {
17768
- allValuesHandlers.push(valuesHandlers);
17769
- }
17770
- if (postValuesHandlers.size > 0) {
17771
- allValuesHandlers.push(postValuesHandlers);
17772
- }
17773
- }
17774
- for (const result of walk(ast)) {
17775
- // if (result.parent != null && !isNodeAllowedInContext(result.node, result.parent as AstNode)) {
17776
- //
17777
- // errors.push({
17778
- // action: 'drop',
17779
- // 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'` : ''}`,
17780
- // // @ts-ignore
17781
- // location: result.node.loc ?? map.get(result.node ) ?? null
17782
- // });
17783
- //
17784
- // // @ts-ignore
17785
- // removeNode(result.node, result.parent as AstNode);
17786
- // continue;
17787
- // }
17788
- if (allValuesHandlers.length > 0 || preVisitorsHandlersMap.size > 0 || visitorsHandlersMap.size > 0 || postVisitorsHandlersMap.size > 0) {
17789
- if ((result.node.typ == exports.EnumToken.DeclarationNodeType &&
17790
- (preVisitorsHandlersMap.has('Declaration') || visitorsHandlersMap.has('Declaration') || postVisitorsHandlersMap.has('Declaration'))) ||
17791
- (result.node.typ == exports.EnumToken.AtRuleNodeType && (preVisitorsHandlersMap.has('AtRule') || visitorsHandlersMap.has('AtRule') || postVisitorsHandlersMap.has('AtRule'))) ||
17792
- (result.node.typ == exports.EnumToken.KeyframesAtRuleNodeType && (preVisitorsHandlersMap.has('KeyframesAtRule') || visitorsHandlersMap.has('KeyframesAtRule') || postVisitorsHandlersMap.has('KeyframesAtRule')))) {
17793
- const handlers = [];
17794
- const key = result.node.typ == exports.EnumToken.DeclarationNodeType ? 'Declaration' : result.node.typ == exports.EnumToken.AtRuleNodeType ? 'AtRule' : 'KeyframesAtRule';
17795
- if (preVisitorsHandlersMap.has(key)) {
17796
- // @ts-ignore
17797
- handlers.push(preVisitorsHandlersMap.get(key));
17798
- }
17799
- if (visitorsHandlersMap.has(key)) {
17800
- // @ts-ignore
17801
- handlers.push(visitorsHandlersMap.get(key));
17802
- }
17803
- if (postVisitorsHandlersMap.has(key)) {
17804
- // @ts-ignore
17805
- handlers.push(postVisitorsHandlersMap.get(key));
17806
- }
17807
- let callable;
17808
- let node = result.node;
17809
- for (const handler of handlers) {
17810
- callable = typeof handler == 'function' ? handler : handler[normalizeVisitorKeyName(node.typ == exports.EnumToken.DeclarationNodeType || node.typ == exports.EnumToken.AtRuleNodeType ? node.nam : node.val)];
17811
- if (callable == null) {
17812
- continue;
17813
- }
17814
- let replacement = callable(node, result.parent);
17815
- if (replacement == null) {
17816
- continue;
17817
- }
17818
- isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
17819
- if (replacement) {
17820
- replacement = await replacement;
17821
- }
17822
- if (replacement == null || replacement == node) {
17823
- continue;
17824
- }
17825
- // @ts-ignore
17826
- node = replacement;
17827
- //
17828
- if (Array.isArray(node)) {
17829
- break;
18171
+ if (node != result.node) {
18172
+ // @ts-ignore
18173
+ replaceToken(result.parent, result.node, node);
17830
18174
  }
17831
18175
  }
17832
- if (node != result.node) {
17833
- // @ts-ignore
17834
- replaceToken(result.parent, result.node, node);
17835
- }
17836
- }
17837
- else if ((result.node.typ == exports.EnumToken.RuleNodeType && (preVisitorsHandlersMap.has('Rule') || visitorsHandlersMap.has('Rule') || postVisitorsHandlersMap.has('Rule'))) ||
17838
- (result.node.typ == exports.EnumToken.KeyFramesRuleNodeType && (preVisitorsHandlersMap.has('KeyframesRule') || visitorsHandlersMap.has('KeyframesRule') || postVisitorsHandlersMap.has('KeyframesRule')))) {
17839
- const handlers = [];
17840
- const key = result.node.typ == exports.EnumToken.RuleNodeType ? 'Rule' : 'KeyframesRule';
17841
- if (preVisitorsHandlersMap.has(key)) {
17842
- // @ts-ignore
17843
- handlers.push(preVisitorsHandlersMap.get(key));
17844
- }
17845
- if (visitorsHandlersMap.has(key)) {
17846
- // @ts-ignore
17847
- handlers.push(visitorsHandlersMap.get(key));
17848
- }
17849
- if (postVisitorsHandlersMap.has(key)) {
17850
- // @ts-ignore
17851
- handlers.push(postVisitorsHandlersMap.get(key));
17852
- }
17853
- let node = result.node;
17854
- for (const callable of handlers) {
17855
- // @ts-ignore
17856
- let replacement = callable(node, result.parent);
17857
- if (replacement == null) {
17858
- continue;
18176
+ else if ((result.node.typ == exports.EnumToken.RuleNodeType && (preVisitorsHandlersMap.has('Rule') || visitorsHandlersMap.has('Rule') || postVisitorsHandlersMap.has('Rule'))) ||
18177
+ (result.node.typ == exports.EnumToken.KeyFramesRuleNodeType && (preVisitorsHandlersMap.has('KeyframesRule') || visitorsHandlersMap.has('KeyframesRule') || postVisitorsHandlersMap.has('KeyframesRule')))) {
18178
+ const handlers = [];
18179
+ const key = result.node.typ == exports.EnumToken.RuleNodeType ? 'Rule' : 'KeyframesRule';
18180
+ if (preVisitorsHandlersMap.has(key)) {
18181
+ handlers.push(...preVisitorsHandlersMap.get(key));
17859
18182
  }
17860
- isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
17861
- if (replacement) {
17862
- replacement = await replacement;
18183
+ if (visitorsHandlersMap.has(key)) {
18184
+ handlers.push(...visitorsHandlersMap.get(key));
17863
18185
  }
17864
- if (replacement == null || replacement == node) {
17865
- continue;
17866
- }
17867
- // @ts-ignore
17868
- node = replacement;
17869
- //
17870
- if (Array.isArray(node)) {
17871
- break;
18186
+ if (postVisitorsHandlersMap.has(key)) {
18187
+ handlers.push(...postVisitorsHandlersMap.get(key));
17872
18188
  }
17873
- }
17874
- // @ts-ignore
17875
- if (node != result.node) {
17876
- // @ts-ignore
17877
- replaceToken(result.parent, result.node, node);
17878
- }
17879
- }
17880
- else if (allValuesHandlers.length > 0) {
17881
- let callable;
17882
- let node = null;
17883
- node = result.node;
17884
- for (const valueHandler of allValuesHandlers) {
17885
- if (valueHandler.has(node.typ)) {
17886
- callable = valueHandler.get(node.typ);
17887
- let replacement = callable(node, result.parent);
18189
+ let node = result.node;
18190
+ for (const callable of handlers) {
18191
+ replacement = callable(node, result.parent);
17888
18192
  if (replacement == null) {
17889
18193
  continue;
17890
18194
  }
17891
18195
  isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
17892
- if (isAsync) {
18196
+ if (replacement) {
17893
18197
  replacement = await replacement;
17894
18198
  }
17895
- if (replacement != null && replacement != node) {
17896
- node = replacement;
18199
+ if (replacement == null || replacement == node) {
18200
+ continue;
18201
+ }
18202
+ // @ts-ignore
18203
+ node = replacement;
18204
+ //
18205
+ if (Array.isArray(node)) {
18206
+ break;
17897
18207
  }
17898
18208
  }
17899
- }
17900
- if (node != result.node) {
17901
18209
  // @ts-ignore
17902
- replaceToken(result.parent, value, node);
17903
- }
17904
- const tokens = 'tokens' in result.node ? result.node.tokens : [];
17905
- if ('val' in result.node && Array.isArray(result.node.val)) {
17906
- tokens.push(...result.node.val);
17907
- }
17908
- if (tokens.length == 0) {
17909
- continue;
18210
+ if (node != result.node) {
18211
+ // @ts-ignore
18212
+ replaceToken(result.parent, result.node, node);
18213
+ }
17910
18214
  }
17911
- for (const { value, parent, root } of walkValues(tokens, result.node)) {
17912
- node = value;
17913
- for (const valueHandler of allValuesHandlers) {
17914
- if (valueHandler.has(node.typ)) {
17915
- callable = valueHandler.get(node.typ);
17916
- let result = callable(node, parent, root);
17917
- if (result == null) {
18215
+ else if (valuesHandlers.size > 0) {
18216
+ let node = null;
18217
+ node = result.node;
18218
+ if (valuesHandlers.has(node.typ)) {
18219
+ for (const valueHandler of valuesHandlers.get(node.typ)) {
18220
+ callable = valueHandler;
18221
+ replacement = callable(node, result.parent);
18222
+ if (replacement == null) {
17918
18223
  continue;
17919
18224
  }
17920
- isAsync = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction';
18225
+ isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
17921
18226
  if (isAsync) {
17922
- result = await result;
18227
+ replacement = await replacement;
17923
18228
  }
17924
- if (result != null && result != node) {
17925
- node = result;
17926
- }
17927
- //
17928
- if (Array.isArray(node)) {
17929
- break;
18229
+ if (replacement != null && replacement != node) {
18230
+ node = replacement;
17930
18231
  }
17931
18232
  }
17932
18233
  }
17933
- if (node != value) {
18234
+ if (node != result.node) {
17934
18235
  // @ts-ignore
17935
- replaceToken(parent, value, node);
18236
+ replaceToken(result.parent, value, node);
18237
+ }
18238
+ const tokens = 'tokens' in result.node ? result.node.tokens : [];
18239
+ if ('val' in result.node && Array.isArray(result.node.val)) {
18240
+ tokens.push(...result.node.val);
18241
+ }
18242
+ if (tokens.length == 0) {
18243
+ continue;
18244
+ }
18245
+ for (const { value, parent, root } of walkValues(tokens, result.node)) {
18246
+ node = value;
18247
+ if (valuesHandlers.has(node.typ)) {
18248
+ for (const valueHandler of valuesHandlers.get(node.typ)) {
18249
+ callable = valueHandler;
18250
+ let result = callable(node, parent, root);
18251
+ if (result == null) {
18252
+ continue;
18253
+ }
18254
+ isAsync = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction';
18255
+ if (isAsync) {
18256
+ result = await result;
18257
+ }
18258
+ if (result != null && result != node) {
18259
+ node = result;
18260
+ }
18261
+ //
18262
+ if (Array.isArray(node)) {
18263
+ break;
18264
+ }
18265
+ }
18266
+ }
18267
+ if (node != value) {
18268
+ // @ts-ignore
18269
+ replaceToken(parent, value, node);
18270
+ }
17936
18271
  }
17937
18272
  }
17938
18273
  }
@@ -17972,7 +18307,7 @@ function getLastNode(context) {
17972
18307
  }
17973
18308
  return null;
17974
18309
  }
17975
- function parseNode(results, context, options, errors, src, map, rawTokens) {
18310
+ function parseNode(results, context, options, errors, src, map, rawTokens, stats) {
17976
18311
  let tokens = [];
17977
18312
  for (const t of results) {
17978
18313
  const node = getTokenType(t.token, t.hint);
@@ -17995,9 +18330,12 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
17995
18330
  }
17996
18331
  loc = location;
17997
18332
  context.chi.push(tokens[i]);
17998
- if (options.sourcemap) {
17999
- tokens[i].loc = loc;
18000
- }
18333
+ stats.nodesCount++;
18334
+ Object.defineProperty(tokens[i], 'loc', {
18335
+ ...definedPropertySettings,
18336
+ value: loc,
18337
+ enumerable: options.sourcemap !== false
18338
+ });
18001
18339
  }
18002
18340
  else if (tokens[i].typ != exports.EnumToken.WhitespaceTokenType) {
18003
18341
  break;
@@ -18138,10 +18476,10 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
18138
18476
  }
18139
18477
  }
18140
18478
  const t = parseAtRulePrelude(parseTokens(tokens, { minify: options.minify }), atRule);
18141
- const raw = t.reduce((acc, curr) => {
18142
- acc.push(renderToken(curr, { removeComments: true, convertColor: false }));
18143
- return acc;
18144
- }, []);
18479
+ const raw = [];
18480
+ for (const curr of t) {
18481
+ raw.push(renderToken(curr, { removeComments: true, convertColor: false }));
18482
+ }
18145
18483
  const nam = renderToken(atRule, { removeComments: true });
18146
18484
  // @ts-ignore
18147
18485
  const node = {
@@ -18157,10 +18495,12 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
18157
18495
  node.chi = [];
18158
18496
  }
18159
18497
  loc = map.get(atRule);
18160
- if (options.sourcemap) {
18161
- node.loc = loc;
18162
- node.loc.end = { ...map.get(delim).end };
18163
- }
18498
+ Object.defineProperty(node, 'loc', {
18499
+ ...definedPropertySettings,
18500
+ value: loc,
18501
+ enumerable: options.sourcemap !== false
18502
+ });
18503
+ node.loc.end = { ...map.get(delim).end };
18164
18504
  let isValid = true;
18165
18505
  if (node.nam == 'else') {
18166
18506
  const prev = getLastNode(context);
@@ -18174,20 +18514,31 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
18174
18514
  }
18175
18515
  }
18176
18516
  // @ts-ignore
18177
- const valid = options.validation == exports.ValidationLevel.None ? {
18517
+ const skipValidate = (options.validation & exports.ValidationLevel.AtRule) == 0;
18518
+ const isAllowed = skipValidate || isNodeAllowedInContext(node, context);
18519
+ // @ts-ignore
18520
+ const valid = skipValidate ? {
18178
18521
  valid: SyntaxValidationResult.Valid,
18179
18522
  error: '',
18180
18523
  node,
18181
18524
  syntax: '@' + node.nam
18182
- } : isValid ? (node.typ == exports.EnumToken.KeyframesAtRuleNodeType ? validateAtRuleKeyframes(node) : validateAtRule(node, options, context)) : {
18525
+ } : !isAllowed ? {
18526
+ valid: SyntaxValidationResult.Drop,
18527
+ node,
18528
+ syntax: '@' + node.nam,
18529
+ error: `${exports.EnumToken[context.typ]}: child ${exports.EnumToken[node.typ]} not allowed in context${context.typ == exports.EnumToken.AtRuleNodeType ? ` '@${context.nam}'` : context.typ == exports.EnumToken.StyleSheetNodeType ? ` 'stylesheet'` : ''}`} : isValid ? (node.typ == exports.EnumToken.KeyframesAtRuleNodeType ? validateAtRuleKeyframes(node) : validateAtRule(node, options, context)) : {
18183
18530
  valid: SyntaxValidationResult.Drop,
18184
18531
  node,
18185
18532
  syntax: '@' + node.nam,
18186
18533
  error: '@' + node.nam + ' not allowed here'};
18187
18534
  if (valid.valid == SyntaxValidationResult.Drop) {
18535
+ let message = '';
18536
+ for (const token of tokens) {
18537
+ message += renderToken(token, { minify: false });
18538
+ }
18188
18539
  errors.push({
18189
18540
  action: 'drop',
18190
- message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
18541
+ message: valid.error + ' - "' + message + '"',
18191
18542
  node,
18192
18543
  // @ts-ignore
18193
18544
  location: { src, ...(map.get(valid.node) ?? location) }
@@ -18196,13 +18547,17 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
18196
18547
  node.typ = exports.EnumToken.InvalidAtRuleTokenType;
18197
18548
  }
18198
18549
  else {
18199
- node.val = node.tokens.reduce((acc, curr) => acc + renderToken(curr, {
18200
- minify: false,
18201
- convertColor: false,
18202
- removeComments: true
18203
- }), '');
18550
+ node.val = '';
18551
+ for (const token of node.tokens) {
18552
+ node.val += renderToken(token, {
18553
+ minify: false,
18554
+ convertColor: false,
18555
+ removeComments: true
18556
+ });
18557
+ }
18204
18558
  }
18205
18559
  context.chi.push(node);
18560
+ stats.nodesCount++;
18206
18561
  Object.defineProperties(node, {
18207
18562
  parent: { ...definedPropertySettings, value: context },
18208
18563
  validSyntax: { ...definedPropertySettings, value: valid.valid == SyntaxValidationResult.Valid }
@@ -18300,16 +18655,23 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
18300
18655
  value: tokens.slice()
18301
18656
  });
18302
18657
  loc = location;
18303
- if (options.sourcemap) {
18304
- node.loc = loc;
18305
- }
18306
- // @ts-ignore
18658
+ Object.defineProperty(node, 'loc', {
18659
+ ...definedPropertySettings,
18660
+ value: loc,
18661
+ enumerable: options.sourcemap !== false
18662
+ });
18307
18663
  context.chi.push(node);
18308
18664
  Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: context });
18309
18665
  // @ts-ignore
18310
- const valid = options.validation == exports.ValidationLevel.None ? {
18666
+ const skipValidate = (options.validation & exports.ValidationLevel.Selector) == 0;
18667
+ const isAllowed = skipValidate || isNodeAllowedInContext(node, context);
18668
+ // @ts-ignore
18669
+ const valid = skipValidate ? {
18311
18670
  valid: SyntaxValidationResult.Valid,
18312
18671
  error: null
18672
+ } : !isAllowed ? {
18673
+ valid: SyntaxValidationResult.Drop,
18674
+ error: `${exports.EnumToken[context.typ]}: child ${exports.EnumToken[node.typ]} not allowed in context${context.typ == exports.EnumToken.AtRuleNodeType ? ` '@${context.nam}'` : context.typ == exports.EnumToken.StyleSheetNodeType ? ` 'stylesheet'` : ''}`
18313
18675
  } : ruleType == exports.EnumToken.KeyFramesRuleNodeType ? validateKeyframeSelector(tokens) : validateSelector(tokens, options, context);
18314
18676
  if (valid.valid != SyntaxValidationResult.Valid) {
18315
18677
  // @ts-ignore
@@ -18419,11 +18781,13 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
18419
18781
  nam,
18420
18782
  val: []
18421
18783
  };
18422
- if (options.sourcemap) {
18423
- node.loc = location;
18424
- node.loc.end = { ...map.get(delim).end };
18425
- }
18784
+ Object.defineProperty(node, 'loc', {
18785
+ ...definedPropertySettings,
18786
+ value: location,
18787
+ enumerable: options.sourcemap !== false
18788
+ });
18426
18789
  context.chi.push(node);
18790
+ stats.nodesCount++;
18427
18791
  }
18428
18792
  return null;
18429
18793
  }
@@ -18447,22 +18811,31 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
18447
18811
  nam,
18448
18812
  val: value
18449
18813
  };
18450
- if (options.sourcemap) {
18451
- node.loc = location;
18452
- node.loc.end = { ...map.get(delim).end };
18453
- }
18814
+ Object.defineProperty(node, 'loc', {
18815
+ ...definedPropertySettings,
18816
+ value: location,
18817
+ enumerable: options.sourcemap !== false
18818
+ });
18819
+ node.loc.end = { ...map.get(delim).end };
18454
18820
  // do not allow declarations in style sheets
18455
18821
  if (context.typ == exports.EnumToken.StyleSheetNodeType && options.lenient) {
18456
- // @ts-ignore
18457
- node.typ = exports.EnumToken.InvalidDeclarationNodeType;
18822
+ Object.assign(node, { typ: exports.EnumToken.InvalidDeclarationNodeType });
18458
18823
  context.chi.push(node);
18824
+ stats.nodesCount++;
18459
18825
  return null;
18460
18826
  }
18461
18827
  const result = parseDeclarationNode(node, errors, location);
18462
18828
  Object.defineProperty(result, 'parent', { ...definedPropertySettings, value: context });
18463
18829
  if (result != null) {
18464
- if (options.validation == exports.ValidationLevel.All) {
18465
- const valid = evaluateSyntax(result, options);
18830
+ if (options.validation & exports.ValidationLevel.Declaration) {
18831
+ const isAllowed = isNodeAllowedInContext(node, context);
18832
+ // @ts-ignore
18833
+ const valid = !isAllowed ? {
18834
+ valid: SyntaxValidationResult.Drop,
18835
+ error: `${exports.EnumToken[node.typ]} not allowed in context${context.typ == exports.EnumToken.AtRuleNodeType ? ` '@${context.nam}'` : context.typ == exports.EnumToken.StyleSheetNodeType ? ` 'stylesheet'` : ''}`,
18836
+ node,
18837
+ syntax: null
18838
+ } : evaluateSyntax(result, context, options);
18466
18839
  Object.defineProperty(result, 'validSyntax', {
18467
18840
  ...definedPropertySettings,
18468
18841
  value: valid.valid == SyntaxValidationResult.Valid
@@ -18478,11 +18851,11 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
18478
18851
  if (!options.lenient) {
18479
18852
  return null;
18480
18853
  }
18481
- // @ts-ignore
18482
- node.typ = exports.EnumToken.InvalidDeclarationNodeType;
18854
+ Object.assign(node, { typ: exports.EnumToken.InvalidDeclarationNodeType });
18483
18855
  }
18484
18856
  }
18485
18857
  context.chi.push(result);
18858
+ stats.nodesCount++;
18486
18859
  }
18487
18860
  return null;
18488
18861
  }
@@ -18494,7 +18867,6 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
18494
18867
  * @param atRule
18495
18868
  */
18496
18869
  function parseAtRulePrelude(tokens, atRule) {
18497
- // @ts-ignore
18498
18870
  for (const { value, parent } of walkValues(tokens, null, null, true)) {
18499
18871
  if (value.typ == exports.EnumToken.CommentTokenType ||
18500
18872
  value.typ == exports.EnumToken.WhitespaceTokenType ||
@@ -18530,16 +18902,14 @@ function parseAtRulePrelude(tokens, atRule) {
18530
18902
  }
18531
18903
  if (atRule.val == 'page' && value.typ == exports.EnumToken.PseudoClassTokenType) {
18532
18904
  if ([':left', ':right', ':first', ':blank'].includes(value.val)) {
18533
- // @ts-ignore
18534
- value.typ = exports.EnumToken.PseudoPageTokenType;
18905
+ Object.assign(value, { typ: exports.EnumToken.PseudoPageTokenType });
18535
18906
  }
18536
18907
  }
18537
18908
  if (atRule.val == 'layer') {
18538
18909
  if (parent == null && value.typ == exports.EnumToken.LiteralTokenType) {
18539
18910
  if (value.val.charAt(0) == '.') {
18540
18911
  if (isIdent(value.val.slice(1))) {
18541
- // @ts-ignore
18542
- value.typ = exports.EnumToken.ClassSelectorTokenType;
18912
+ Object.assign(value, { typ: exports.EnumToken.ClassSelectorTokenType });
18543
18913
  }
18544
18914
  }
18545
18915
  }
@@ -18548,8 +18918,7 @@ function parseAtRulePrelude(tokens, atRule) {
18548
18918
  if (value.typ == exports.EnumToken.IdenTokenType) {
18549
18919
  if (parent == null && mediaTypes.some((t) => {
18550
18920
  if (val === t) {
18551
- // @ts-ignore
18552
- value.typ = exports.EnumToken.MediaFeatureTokenType;
18921
+ Object.assign(value, { typ: exports.EnumToken.MediaFeatureTokenType });
18553
18922
  return true;
18554
18923
  }
18555
18924
  return false;
@@ -18557,18 +18926,15 @@ function parseAtRulePrelude(tokens, atRule) {
18557
18926
  continue;
18558
18927
  }
18559
18928
  if (value.typ == exports.EnumToken.IdenTokenType && 'and' === val) {
18560
- // @ts-ignore
18561
- value.typ = exports.EnumToken.MediaFeatureAndTokenType;
18929
+ Object.assign(value, { typ: exports.EnumToken.MediaFeatureAndTokenType });
18562
18930
  continue;
18563
18931
  }
18564
18932
  if (value.typ == exports.EnumToken.IdenTokenType && 'or' === val) {
18565
- // @ts-ignore
18566
- value.typ = exports.EnumToken.MediaFeatureOrTokenType;
18933
+ Object.assign(value, { typ: exports.EnumToken.MediaFeatureOrTokenType });
18567
18934
  continue;
18568
18935
  }
18569
18936
  if (value.typ == exports.EnumToken.IdenTokenType &&
18570
18937
  ['not', 'only'].some((t) => val === t)) {
18571
- // @ts-ignore
18572
18938
  const array = parent?.chi ?? tokens;
18573
18939
  const startIndex = array.indexOf(value);
18574
18940
  let index = startIndex + 1;
@@ -18613,12 +18979,15 @@ function parseAtRulePrelude(tokens, atRule) {
18613
18979
  if (value.chi[i].typ == exports.EnumToken.CommentTokenType || value.chi[i].typ == exports.EnumToken.WhitespaceTokenType) {
18614
18980
  continue;
18615
18981
  }
18616
- if (value.chi[i].typ == exports.EnumToken.LiteralTokenType && value.chi[i].val.startsWith(':') && isDimension(value.chi[i].val.slice(1))) {
18617
- value.chi.splice(i, 1, {
18618
- typ: exports.EnumToken.ColonTokenType,
18619
- }, Object.assign(value.chi[i], parseDimension(value.chi[i].val.slice(1))));
18620
- i--;
18621
- continue;
18982
+ if (value.chi[i].typ == exports.EnumToken.LiteralTokenType && value.chi[i].val.startsWith(':')) {
18983
+ const dimension = parseDimension(value.chi[i].val.slice(1));
18984
+ if (dimension != null) {
18985
+ value.chi.splice(i, 1, {
18986
+ typ: exports.EnumToken.ColonTokenType,
18987
+ }, Object.assign(value.chi[i], dimension));
18988
+ i--;
18989
+ continue;
18990
+ }
18622
18991
  }
18623
18992
  if (nameIndex != -1 && value.chi[i].typ == exports.EnumToken.PseudoClassTokenType) {
18624
18993
  value.chi.splice(i, 1, {
@@ -18645,11 +19014,10 @@ function parseAtRulePrelude(tokens, atRule) {
18645
19014
  const val = value.chi.splice(valueIndex, 1)[0];
18646
19015
  const node = value.chi.splice(nameIndex, 1)[0];
18647
19016
  // 'background'
18648
- // @ts-ignore
18649
19017
  if (node.typ == exports.EnumToken.ColorTokenType && node.kin == exports.ColorType.DPSYS) {
19018
+ Object.assign(node, { typ: exports.EnumToken.IdenTokenType });
18650
19019
  // @ts-ignore
18651
19020
  delete node.kin;
18652
- node.typ = exports.EnumToken.IdenTokenType;
18653
19021
  }
18654
19022
  while (value.chi[0]?.typ == exports.EnumToken.WhitespaceTokenType) {
18655
19023
  value.chi.shift();
@@ -18704,43 +19072,35 @@ function parseSelector(tokens) {
18704
19072
  }
18705
19073
  if (parent == null) {
18706
19074
  if (value.typ == exports.EnumToken.GtTokenType) {
18707
- // @ts-ignore
18708
- value.typ = exports.EnumToken.ChildCombinatorTokenType;
19075
+ Object.assign(value, { typ: exports.EnumToken.ChildCombinatorTokenType });
18709
19076
  }
18710
19077
  else if (value.typ == exports.EnumToken.LiteralTokenType) {
18711
19078
  if (value.val.charAt(0) == '&') {
18712
- // @ts-ignore
18713
- value.typ = exports.EnumToken.NestingSelectorTokenType;
19079
+ Object.assign(value, { typ: exports.EnumToken.NestingSelectorTokenType });
18714
19080
  // @ts-ignore
18715
19081
  delete value.val;
18716
19082
  }
18717
19083
  else if (value.val.charAt(0) == '.') {
18718
19084
  if (!isIdent(value.val.slice(1))) {
18719
- // @ts-ignore
18720
- value.typ = exports.EnumToken.InvalidClassSelectorTokenType;
19085
+ Object.assign(value, { typ: exports.EnumToken.InvalidClassSelectorTokenType });
18721
19086
  }
18722
19087
  else {
18723
- // @ts-ignore
18724
- value.typ = exports.EnumToken.ClassSelectorTokenType;
19088
+ Object.assign(value, { typ: exports.EnumToken.ClassSelectorTokenType });
18725
19089
  }
18726
19090
  }
18727
19091
  if (['*', '>', '+', '~'].includes(value.val)) {
18728
19092
  switch (value.val) {
18729
19093
  case '*':
18730
- // @ts-ignore
18731
- value.typ = exports.EnumToken.UniversalSelectorTokenType;
19094
+ Object.assign(value, { typ: exports.EnumToken.UniversalSelectorTokenType });
18732
19095
  break;
18733
19096
  case '>':
18734
- // @ts-ignore
18735
- value.typ = exports.EnumToken.ChildCombinatorTokenType;
19097
+ Object.assign(value, { typ: exports.EnumToken.ChildCombinatorTokenType });
18736
19098
  break;
18737
19099
  case '+':
18738
- // @ts-ignore
18739
- value.typ = exports.EnumToken.NextSiblingCombinatorTokenType;
19100
+ Object.assign(value, { typ: exports.EnumToken.NextSiblingCombinatorTokenType });
18740
19101
  break;
18741
19102
  case '~':
18742
- // @ts-ignore
18743
- value.typ = exports.EnumToken.SubsequentSiblingCombinatorTokenType;
19103
+ Object.assign(value, { typ: exports.EnumToken.SubsequentSiblingCombinatorTokenType });
18744
19104
  break;
18745
19105
  }
18746
19106
  // @ts-ignore
@@ -18753,12 +19113,10 @@ function parseSelector(tokens) {
18753
19113
  if (!isIdent(value.val.slice(1))) {
18754
19114
  continue;
18755
19115
  }
18756
- // @ts-ignore
18757
- value.typ = exports.EnumToken.HashTokenType;
19116
+ Object.assign(value, { typ: exports.EnumToken.HashTokenType });
18758
19117
  }
18759
19118
  else {
18760
- // @ts-ignore
18761
- value.typ = exports.EnumToken.IdenTokenType;
19119
+ Object.assign(value, { typ: exports.EnumToken.IdenTokenType });
18762
19120
  }
18763
19121
  // @ts-ignore
18764
19122
  delete value.kin;
@@ -18821,15 +19179,17 @@ function parseString(src, options = { location: false }) {
18821
19179
  return acc;
18822
19180
  }
18823
19181
  const token = getTokenType(t.token, t.hint);
18824
- if (options.location) {
18825
- Object.assign(token, { loc: t.sta });
18826
- }
19182
+ Object.defineProperty(token, 'loc', {
19183
+ ...definedPropertySettings,
19184
+ value: { sta: t.sta },
19185
+ enumerable: options.location !== false
19186
+ });
18827
19187
  acc.push(token);
18828
19188
  return acc;
18829
19189
  }, []));
18830
19190
  }
18831
19191
  /**
18832
- * get token type from a string
19192
+ * get the token type from a string
18833
19193
  * @param val
18834
19194
  * @param hint
18835
19195
  */
@@ -18865,7 +19225,7 @@ function getTokenType(val, hint) {
18865
19225
  case '>':
18866
19226
  return { typ: exports.EnumToken.GtTokenType };
18867
19227
  }
18868
- if (isPseudo(val)) {
19228
+ if (val.charAt(0) == ':' && isPseudo(val)) {
18869
19229
  return val.endsWith('(') ? {
18870
19230
  typ: exports.EnumToken.PseudoClassFuncTokenType,
18871
19231
  val: val.slice(0, -1),
@@ -18882,13 +19242,13 @@ function getTokenType(val, hint) {
18882
19242
  val
18883
19243
  });
18884
19244
  }
18885
- if (isAtKeyword(val)) {
19245
+ if (val.charAt(0) == '@' && isAtKeyword(val)) {
18886
19246
  return {
18887
19247
  typ: exports.EnumToken.AtRuleTokenType,
18888
19248
  val: val.slice(1)
18889
19249
  };
18890
19250
  }
18891
- if (isFunction(val)) {
19251
+ if (val.endsWith('(') && isFunction(val)) {
18892
19252
  val = val.slice(0, -1);
18893
19253
  if (val == 'url') {
18894
19254
  return {
@@ -18936,15 +19296,12 @@ function getTokenType(val, hint) {
18936
19296
  val: +val.slice(0, -1)
18937
19297
  };
18938
19298
  }
18939
- if (isFlex(val)) {
18940
- return {
18941
- typ: exports.EnumToken.FlexTokenType,
18942
- val: +val.slice(0, -2)
18943
- };
18944
- }
18945
- if (isDimension(val)) {
18946
- return parseDimension(val);
19299
+ // if (isDimension(val)) {
19300
+ const dimension = parseDimension(val);
19301
+ if (dimension != null) {
19302
+ return dimension;
18947
19303
  }
19304
+ // }
18948
19305
  const v = val.toLowerCase();
18949
19306
  if (v == 'currentcolor' || v == 'transparent' || v in COLORS_NAMES) {
18950
19307
  return {
@@ -19353,28 +19710,28 @@ exports.WalkerOptionEnum = void 0;
19353
19710
  */
19354
19711
  WalkerOptionEnum[WalkerOptionEnum["Stop"] = 2] = "Stop";
19355
19712
  /**
19356
- * ignore node and process children
19713
+ * ignore the current node and process its children
19357
19714
  */
19358
19715
  WalkerOptionEnum[WalkerOptionEnum["Children"] = 4] = "Children";
19359
19716
  /**
19360
- * ignore children
19717
+ * ignore the current node children
19361
19718
  */
19362
19719
  WalkerOptionEnum[WalkerOptionEnum["IgnoreChildren"] = 8] = "IgnoreChildren";
19363
19720
  })(exports.WalkerOptionEnum || (exports.WalkerOptionEnum = {}));
19364
19721
  /**
19365
19722
  * event types for the walkValues function
19366
19723
  */
19367
- exports.WalkerValueEvent = void 0;
19368
- (function (WalkerValueEvent) {
19724
+ exports.WalkerEvent = void 0;
19725
+ (function (WalkerEvent) {
19369
19726
  /**
19370
19727
  * enter node
19371
19728
  */
19372
- WalkerValueEvent[WalkerValueEvent["Enter"] = 1] = "Enter";
19729
+ WalkerEvent[WalkerEvent["Enter"] = 1] = "Enter";
19373
19730
  /**
19374
19731
  * leave node
19375
19732
  */
19376
- WalkerValueEvent[WalkerValueEvent["Leave"] = 2] = "Leave";
19377
- })(exports.WalkerValueEvent || (exports.WalkerValueEvent = {}));
19733
+ WalkerEvent[WalkerEvent["Leave"] = 2] = "Leave";
19734
+ })(exports.WalkerEvent || (exports.WalkerEvent = {}));
19378
19735
  /**
19379
19736
  * walk ast nodes
19380
19737
  * @param node initial node
@@ -19405,11 +19762,10 @@ exports.WalkerValueEvent = void 0;
19405
19762
  * }
19406
19763
  * ```
19407
19764
  *
19408
- * Using a filter to control the walk process:
19765
+ * Using a {@link filter} function to control the ast traversal. the filter function returns a value of type {@link WalkerOption}.
19409
19766
  *
19410
19767
  * ```ts
19411
- *
19412
- * import {walk} from '@tbela99/css-parser';
19768
+ * import {EnumToken, transform, walk, WalkerOptionEnum} from '@tbela99/css-parser';
19413
19769
  *
19414
19770
  * const css = `
19415
19771
  * body { color: color(from var(--base-color) display-p3 r calc(g + 0.24) calc(b + 0.15)); }
@@ -19425,17 +19781,28 @@ exports.WalkerValueEvent = void 0;
19425
19781
  * }
19426
19782
  * `;
19427
19783
  *
19428
- * for (const {node, parent, root} of walk(ast, (node) => {
19784
+ * function filter(node) {
19429
19785
  *
19430
19786
  * if (node.typ == EnumToken.AstRule && node.sel.includes('html')) {
19431
19787
  *
19432
19788
  * // skip the children of the current node
19433
19789
  * return WalkerOptionEnum.IgnoreChildren;
19434
19790
  * }
19435
- * })) {
19791
+ * }
19436
19792
  *
19437
- * // do something with node
19793
+ * const result = await transform(css);
19794
+ * for (const {node} of walk(result.ast, filter)) {
19795
+ *
19796
+ * console.error([EnumToken[node.typ]]);
19438
19797
  * }
19798
+ *
19799
+ * // [ "StyleSheetNodeType" ]
19800
+ * // [ "RuleNodeType" ]
19801
+ * // [ "DeclarationNodeType" ]
19802
+ * // [ "RuleNodeType" ]
19803
+ * // [ "DeclarationNodeType" ]
19804
+ * // [ "RuleNodeType" ]
19805
+ * // [ "DeclarationNodeType" ]
19439
19806
  * ```
19440
19807
  */
19441
19808
  function* walk(node, filter, reverse) {
@@ -19443,7 +19810,8 @@ function* walk(node, filter, reverse) {
19443
19810
  const root = node;
19444
19811
  const map = new Map;
19445
19812
  let isNumeric = false;
19446
- while ((node = parents.shift())) {
19813
+ let i = 0;
19814
+ while ((node = parents[i++])) {
19447
19815
  let option = null;
19448
19816
  if (filter != null) {
19449
19817
  option = filter(node);
@@ -19462,8 +19830,8 @@ function* walk(node, filter, reverse) {
19462
19830
  yield { node, parent: map.get(node), root };
19463
19831
  }
19464
19832
  if ('chi' in node && (!isNumeric || ((option & exports.WalkerOptionEnum.IgnoreChildren) === 0))) {
19465
- parents.unshift(...node.chi[reverse ? 'reverse' : 'slice']());
19466
- for (const child of node.chi.slice()) {
19833
+ parents.splice(i, 0, ...node.chi[reverse ? 'reverse' : 'slice']());
19834
+ for (const child of node.chi) {
19467
19835
  map.set(child, node);
19468
19836
  }
19469
19837
  }
@@ -19480,27 +19848,41 @@ function* walk(node, filter, reverse) {
19480
19848
  *
19481
19849
  * ```ts
19482
19850
  *
19483
- * import {EnumToken, walk} from '@tbela99/css-parser';
19851
+ * import {AstDeclaration, EnumToken, transform, walkValues} from '@tbela99/css-parser';
19484
19852
  *
19485
19853
  * const css = `
19486
19854
  * body { color: color(from var(--base-color) display-p3 r calc(g + 0.24) calc(b + 0.15)); }
19487
- *
19488
- * html,
19489
- * body {
19490
- * line-height: 1.474;
19491
- * }
19492
- *
19493
- * .ruler {
19494
- *
19495
- * height: 10px;
19496
- * }
19497
19855
  * `;
19498
19856
  *
19499
- * for (const {value} of walkValues(result.ast.chi[0].chi[0].val, null, null,true)) {
19857
+ * const result = await transform(css);
19858
+ * const declaration = result.ast.chi[0].chi[0] as AstDeclaration;
19859
+ *
19860
+ * // walk the node attribute's tokens in reverse order
19861
+ * for (const {value} of walkValues(declaration.val, null, null,true)) {
19500
19862
  *
19501
19863
  * console.error([EnumToken[value.typ], value.val]);
19502
19864
  * }
19503
19865
  *
19866
+ * // [ "Color", "color" ]
19867
+ * // [ "FunctionTokenType", "calc" ]
19868
+ * // [ "Number", 0.15 ]
19869
+ * // [ "Add", undefined ]
19870
+ * // [ "Iden", "b" ]
19871
+ * // [ "Whitespace", undefined ]
19872
+ * // [ "FunctionTokenType", "calc" ]
19873
+ * // [ "Number", 0.24 ]
19874
+ * // [ "Add", undefined ]
19875
+ * // [ "Iden", "g" ]
19876
+ * // [ "Whitespace", undefined ]
19877
+ * // [ "Iden", "r" ]
19878
+ * // [ "Whitespace", undefined ]
19879
+ * // [ "Iden", "display-p3" ]
19880
+ * // [ "Whitespace", undefined ]
19881
+ * // [ "FunctionTokenType", "var" ]
19882
+ * // [ "DashedIden", "--base-color" ]
19883
+ * // [ "Whitespace", undefined ]
19884
+ * // [ "Iden", "from" ]
19885
+ * ```
19504
19886
  */
19505
19887
  function* walkValues(values, root = null, filter, reverse) {
19506
19888
  // const set = new Set<Token>();
@@ -19509,26 +19891,26 @@ function* walkValues(values, root = null, filter, reverse) {
19509
19891
  let previous = null;
19510
19892
  if (filter != null && typeof filter == 'function') {
19511
19893
  filter = {
19512
- event: exports.WalkerValueEvent.Enter,
19894
+ event: exports.WalkerEvent.Enter,
19513
19895
  fn: filter
19514
19896
  };
19515
19897
  }
19516
19898
  else if (filter == null) {
19517
19899
  filter = {
19518
- event: exports.WalkerValueEvent.Enter
19900
+ event: exports.WalkerEvent.Enter
19519
19901
  };
19520
19902
  }
19521
19903
  let isNumeric = false;
19522
- const eventType = filter.event ?? exports.WalkerValueEvent.Enter;
19904
+ const eventType = filter.event ?? exports.WalkerEvent.Enter;
19523
19905
  while (stack.length > 0) {
19524
19906
  let value = reverse ? stack.pop() : stack.shift();
19525
19907
  let option = null;
19526
- if (filter.fn != null && (eventType & exports.WalkerValueEvent.Enter)) {
19908
+ if (filter.fn != null && (eventType & exports.WalkerEvent.Enter)) {
19527
19909
  const isValid = filter.type == null || value.typ == filter.type ||
19528
19910
  (Array.isArray(filter.type) && filter.type.includes(value.typ)) ||
19529
19911
  (typeof filter.type == 'function' && filter.type(value));
19530
19912
  if (isValid) {
19531
- option = filter.fn(value, map.get(value) ?? root, exports.WalkerValueEvent.Enter);
19913
+ option = filter.fn(value, map.get(value) ?? root, exports.WalkerEvent.Enter);
19532
19914
  isNumeric = typeof option == 'number';
19533
19915
  if (isNumeric && (option & exports.WalkerOptionEnum.Stop)) {
19534
19916
  return;
@@ -19542,7 +19924,6 @@ function* walkValues(values, root = null, filter, reverse) {
19542
19924
  }
19543
19925
  }
19544
19926
  }
19545
- // if ((eventType & WalkerValueEvent.Enter) && (!isNumeric || ((option as number) & WalkerOptionEnum.Children) === 0)) {
19546
19927
  yield {
19547
19928
  value,
19548
19929
  parent: map.get(value) ?? root,
@@ -19551,7 +19932,6 @@ function* walkValues(values, root = null, filter, reverse) {
19551
19932
  // @ts-ignore
19552
19933
  root: root ?? null
19553
19934
  };
19554
- // }
19555
19935
  if ('chi' in value && (!isNumeric || (option & exports.WalkerOptionEnum.IgnoreChildren) === 0)) {
19556
19936
  const sliced = value.chi.slice();
19557
19937
  for (const child of sliced) {
@@ -19592,29 +19972,18 @@ function* walkValues(values, root = null, filter, reverse) {
19592
19972
  stack[reverse ? 'push' : 'unshift'](...values);
19593
19973
  }
19594
19974
  }
19595
- if ((eventType & exports.WalkerValueEvent.Leave) && filter.fn != null) {
19975
+ if ((eventType & exports.WalkerEvent.Leave) && filter.fn != null) {
19596
19976
  const isValid = filter.type == null || value.typ == filter.type ||
19597
19977
  (Array.isArray(filter.type) && filter.type.includes(value.typ)) ||
19598
19978
  (typeof filter.type == 'function' && filter.type(value));
19599
19979
  if (isValid) {
19600
- option = filter.fn(value, map.get(value), exports.WalkerValueEvent.Leave);
19980
+ option = filter.fn(value, map.get(value), exports.WalkerEvent.Leave);
19601
19981
  // @ts-ignore
19602
19982
  if (option != null && 'typ' in option) {
19603
19983
  map.set(option, map.get(value) ?? root);
19604
19984
  }
19605
19985
  }
19606
19986
  }
19607
- // if ((eventType & WalkerValueEvent.Leave) && (!isNumeric && ((option as number) & WalkerOptionEnum.Children) === 0)) {
19608
- //
19609
- // yield {
19610
- // value,
19611
- // parent: <FunctionToken | ParensToken>map.get(value) ?? root,
19612
- // previousValue: previous,
19613
- // nextValue: <Token>stack[0] ?? null,
19614
- // // @ts-ignore
19615
- // root: root ?? null
19616
- // };
19617
- // }
19618
19987
  previous = value;
19619
19988
  }
19620
19989
  }
@@ -19725,6 +20094,7 @@ class ComputePrefixFeature {
19725
20094
  }
19726
20095
  }
19727
20096
  }
20097
+ // @ts-ignore
19728
20098
  if (SyntaxValidationResult.Valid == evaluateSyntax({ ...node, val: nodes }, {}).valid) {
19729
20099
  node.val = nodes;
19730
20100
  }
@@ -19790,6 +20160,7 @@ function replace(node, variableScope) {
19790
20160
  }
19791
20161
  }
19792
20162
  class InlineCssVariablesFeature {
20163
+ accept = new Set([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType]);
19793
20164
  get ordering() {
19794
20165
  return 0;
19795
20166
  }
@@ -19803,9 +20174,10 @@ class InlineCssVariablesFeature {
19803
20174
  }
19804
20175
  }
19805
20176
  run(ast, options = {}, parent, context) {
19806
- if (!('chi' in ast)) {
19807
- return null;
19808
- }
20177
+ // if (!('chi' in ast)) {
20178
+ //
20179
+ // return null;
20180
+ // }
19809
20181
  if (!('variableScope' in context)) {
19810
20182
  context.variableScope = new Map;
19811
20183
  }
@@ -20687,7 +21059,9 @@ class PropertyList {
20687
21059
  }
20688
21060
  add(...declarations) {
20689
21061
  for (const declaration of declarations) {
20690
- if (declaration.typ != exports.EnumToken.DeclarationNodeType || (Array.isArray(this.options.removeDuplicateDeclarations) ? this.options.removeDuplicateDeclarations.includes(declaration.nam) : !this.options.removeDuplicateDeclarations)) {
21062
+ if (declaration.typ != exports.EnumToken.DeclarationNodeType ||
21063
+ (typeof this.options.removeDuplicateDeclarations === 'string' && this.options.removeDuplicateDeclarations === declaration.nam.toLowerCase()) ||
21064
+ (Array.isArray(this.options.removeDuplicateDeclarations) ? this.options.removeDuplicateDeclarations.includes(declaration.nam) : !this.options.removeDuplicateDeclarations)) {
20691
21065
  this.declarations.set(Number(Math.random().toString().slice(2)).toString(36), declaration);
20692
21066
  continue;
20693
21067
  }
@@ -20772,6 +21146,7 @@ class PropertyList {
20772
21146
  }
20773
21147
 
20774
21148
  class ComputeShorthandFeature {
21149
+ accept = new Set([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType, exports.EnumToken.KeyFramesRuleNodeType]);
20775
21150
  get ordering() {
20776
21151
  return 3;
20777
21152
  }
@@ -20824,6 +21199,7 @@ class ComputeShorthandFeature {
20824
21199
  }
20825
21200
 
20826
21201
  class ComputeCalcExpressionFeature {
21202
+ accept = new Set([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType]);
20827
21203
  get ordering() {
20828
21204
  return 1;
20829
21205
  }
@@ -20846,7 +21222,7 @@ class ComputeCalcExpressionFeature {
20846
21222
  }
20847
21223
  const set = new Set;
20848
21224
  for (const { value, parent } of walkValues(node.val, node, {
20849
- event: exports.WalkerValueEvent.Enter,
21225
+ event: exports.WalkerEvent.Enter,
20850
21226
  // @ts-ignore
20851
21227
  fn(node, parent) {
20852
21228
  if (parent != null &&
@@ -20923,7 +21299,7 @@ class ComputeCalcExpressionFeature {
20923
21299
 
20924
21300
  function translateX(x, from) {
20925
21301
  const matrix = identity();
20926
- matrix[3 * 4 + 0] = x;
21302
+ matrix[3 * 4] = x;
20927
21303
  return multiply(from, matrix);
20928
21304
  }
20929
21305
  function translateY(y, from) {
@@ -20938,13 +21314,13 @@ function translateZ(z, from) {
20938
21314
  }
20939
21315
  function translate(translate, from) {
20940
21316
  const matrix = identity();
20941
- matrix[3 * 4 + 0] = translate[0];
21317
+ matrix[3 * 4] = translate[0];
20942
21318
  matrix[3 * 4 + 1] = translate[1] ?? 0;
20943
21319
  return multiply(from, matrix);
20944
21320
  }
20945
21321
  function translate3d(translate, from) {
20946
21322
  const matrix = identity();
20947
- matrix[3 * 4 + 0] = translate[0];
21323
+ matrix[3 * 4] = translate[0];
20948
21324
  matrix[3 * 4 + 1] = translate[1];
20949
21325
  matrix[3 * 4 + 2] = translate[2];
20950
21326
  return multiply(from, matrix);
@@ -20967,34 +21343,34 @@ function rotate3D(angle, x, y, z, from) {
20967
21343
  x *= unit;
20968
21344
  y *= unit;
20969
21345
  z *= unit;
20970
- matrix[0 * 4 + 0] = 1 - 2 * (y * y + z * z) * sq;
20971
- matrix[0 * 4 + 1] = 2 * (x * y * sq + z * sc);
20972
- matrix[0 * 4 + 2] = 2 * (x * z * sq - y * sc);
20973
- matrix[1 * 4 + 0] = 2 * (x * y * sq - z * sc);
20974
- matrix[1 * 4 + 1] = 1 - 2 * (x * x + z * z) * sq;
20975
- matrix[1 * 4 + 2] = 2 * (y * z * sq + x * sc);
20976
- matrix[2 * 4 + 0] = 2 * (x * z * sq + y * sc);
21346
+ matrix[0] = 1 - 2 * (y * y + z * z) * sq;
21347
+ matrix[1] = 2 * (x * y * sq + z * sc);
21348
+ matrix[2] = 2 * (x * z * sq - y * sc);
21349
+ matrix[4] = 2 * (x * y * sq - z * sc);
21350
+ matrix[4 + 1] = 1 - 2 * (x * x + z * z) * sq;
21351
+ matrix[4 + 2] = 2 * (y * z * sq + x * sc);
21352
+ matrix[2 * 4] = 2 * (x * z * sq + y * sc);
20977
21353
  matrix[2 * 4 + 1] = 2 * (y * z * sq - x * sc);
20978
21354
  matrix[2 * 4 + 2] = 1 - 2 * (x * x + y * y) * sq;
20979
21355
  return multiply(from, matrix);
20980
21356
  }
20981
21357
  function rotate(angle, from) {
20982
21358
  const matrix = identity();
20983
- matrix[0 * 4 + 0] = Math.cos(angle);
20984
- matrix[0 * 4 + 1] = Math.sin(angle);
20985
- matrix[1 * 4 + 0] = -Math.sin(angle);
20986
- matrix[1 * 4 + 1] = Math.cos(angle);
21359
+ matrix[0] = Math.cos(angle);
21360
+ matrix[1] = Math.sin(angle);
21361
+ matrix[4] = -Math.sin(angle);
21362
+ matrix[4 + 1] = Math.cos(angle);
20987
21363
  return multiply(from, matrix);
20988
21364
  }
20989
21365
 
20990
21366
  function scaleX(x, from) {
20991
21367
  const matrix = identity();
20992
- matrix[0 * 4 + 0] = x;
21368
+ matrix[0] = x;
20993
21369
  return multiply(from, matrix);
20994
21370
  }
20995
21371
  function scaleY(y, from) {
20996
21372
  const matrix = identity();
20997
- matrix[1 * 4 + 1] = y;
21373
+ matrix[4 + 1] = y;
20998
21374
  return multiply(from, matrix);
20999
21375
  }
21000
21376
  function scaleZ(z, from) {
@@ -21004,14 +21380,14 @@ function scaleZ(z, from) {
21004
21380
  }
21005
21381
  function scale(x, y, from) {
21006
21382
  const matrix = identity();
21007
- matrix[0 * 4 + 0] = x;
21008
- matrix[1 * 4 + 1] = y;
21383
+ matrix[0] = x;
21384
+ matrix[4 + 1] = y;
21009
21385
  return multiply(from, matrix);
21010
21386
  }
21011
21387
  function scale3d(x, y, z, from) {
21012
21388
  const matrix = identity();
21013
- matrix[0 * 4 + 0] = x;
21014
- matrix[1 * 4 + 1] = y;
21389
+ matrix[0] = x;
21390
+ matrix[4 + 1] = y;
21015
21391
  matrix[2 * 4 + 2] = z;
21016
21392
  return multiply(from, matrix);
21017
21393
  }
@@ -21036,27 +21412,27 @@ function parseMatrix(mat) {
21036
21412
  function matrix(values) {
21037
21413
  const matrix = identity();
21038
21414
  if (values.length === 6) {
21039
- matrix[0 * 4 + 0] = values[0];
21040
- matrix[0 * 4 + 1] = values[1];
21041
- matrix[1 * 4 + 0] = values[2];
21042
- matrix[1 * 4 + 1] = values[3];
21043
- matrix[3 * 4 + 0] = values[4];
21415
+ matrix[0] = values[0];
21416
+ matrix[1] = values[1];
21417
+ matrix[4] = values[2];
21418
+ matrix[4 + 1] = values[3];
21419
+ matrix[3 * 4] = values[4];
21044
21420
  matrix[3 * 4 + 1] = values[5];
21045
21421
  }
21046
21422
  else if (values.length === 16) {
21047
- matrix[0 * 4 + 0] = values[0];
21048
- matrix[0 * 4 + 1] = values[1];
21049
- matrix[0 * 4 + 2] = values[2];
21050
- matrix[0 * 4 + 3] = values[3];
21051
- matrix[1 * 4 + 0] = values[4];
21052
- matrix[1 * 4 + 1] = values[5];
21053
- matrix[1 * 4 + 2] = values[6];
21054
- matrix[1 * 4 + 3] = values[7];
21055
- matrix[2 * 4 + 0] = values[8];
21423
+ matrix[0] = values[0];
21424
+ matrix[1] = values[1];
21425
+ matrix[2] = values[2];
21426
+ matrix[3] = values[3];
21427
+ matrix[4] = values[4];
21428
+ matrix[4 + 1] = values[5];
21429
+ matrix[4 + 2] = values[6];
21430
+ matrix[4 + 3] = values[7];
21431
+ matrix[2 * 4] = values[8];
21056
21432
  matrix[2 * 4 + 1] = values[9];
21057
21433
  matrix[2 * 4 + 2] = values[10];
21058
21434
  matrix[2 * 4 + 3] = values[11];
21059
- matrix[3 * 4 + 0] = values[12];
21435
+ matrix[3 * 4] = values[12];
21060
21436
  matrix[3 * 4 + 1] = values[13];
21061
21437
  matrix[3 * 4 + 2] = values[14];
21062
21438
  matrix[3 * 4 + 3] = values[15];
@@ -21081,11 +21457,11 @@ function serialize(matrix) {
21081
21457
  typ: exports.EnumToken.FunctionTokenType,
21082
21458
  val: 'matrix',
21083
21459
  chi: [
21084
- matrix[0 * 4 + 0],
21085
- matrix[0 * 4 + 1],
21086
- matrix[1 * 4 + 0],
21087
- matrix[1 * 4 + 1],
21088
- matrix[3 * 4 + 0],
21460
+ matrix[0],
21461
+ matrix[1],
21462
+ matrix[4],
21463
+ matrix[4 + 1],
21464
+ matrix[3 * 4],
21089
21465
  matrix[3 * 4 + 1]
21090
21466
  ].reduce((acc, t) => {
21091
21467
  if (acc.length > 0) {
@@ -21268,10 +21644,6 @@ function minify$1(matrix) {
21268
21644
  }
21269
21645
  }
21270
21646
  if (transforms.has('skew')) {
21271
- // if (round(decomposed.skew[0]) == 0) {
21272
- //
21273
- // skew.delete('x');
21274
- // }
21275
21647
  if (round(decomposed.skew[1]) == 0) {
21276
21648
  skew.delete('y');
21277
21649
  }
@@ -21311,7 +21683,7 @@ function minify$1(matrix) {
21311
21683
  scales.delete('x');
21312
21684
  }
21313
21685
  if (scales.size == 1) {
21314
- let prefix = scales.has('x') ? '' : scales.has('y') ? 'Y' : 'Z';
21686
+ let prefix = scales.has('x') ? 'X' : scales.has('y') ? 'Y' : 'Z';
21315
21687
  result.push({
21316
21688
  typ: exports.EnumToken.FunctionTokenType,
21317
21689
  val: 'scale' + prefix,
@@ -21354,13 +21726,9 @@ function minify$1(matrix) {
21354
21726
  ] : result;
21355
21727
  }
21356
21728
  function eqMatrix(a, b) {
21357
- // console.error(JSON.stringify({a, b}, null, 1));
21358
21729
  let mat = identity();
21359
21730
  let tmp = identity();
21360
- // @ts-ignore
21361
21731
  const data = (Array.isArray(a) ? a : parseMatrix(a));
21362
- // toZero(data);
21363
- // console.error({data});
21364
21732
  for (const transform of b) {
21365
21733
  tmp = computeMatrix([transform], identity());
21366
21734
  if (tmp == null) {
@@ -21368,8 +21736,6 @@ function eqMatrix(a, b) {
21368
21736
  }
21369
21737
  mat = multiply(mat, tmp);
21370
21738
  }
21371
- // toZero(mat);
21372
- // console.error({mat});
21373
21739
  if (mat == null) {
21374
21740
  return false;
21375
21741
  }
@@ -21382,23 +21748,126 @@ function eqMatrix(a, b) {
21382
21748
  }
21383
21749
  return true;
21384
21750
  }
21751
+ function minifyTransformFunctions(transform) {
21752
+ const name = transform.val.toLowerCase();
21753
+ if ('skewx' == name) {
21754
+ transform.val = 'skew';
21755
+ return transform;
21756
+ }
21757
+ if (!['translate', 'translate3d', 'scale', 'scale3d'].includes(name)) {
21758
+ return transform;
21759
+ }
21760
+ const values = [];
21761
+ for (const token of transform.chi) {
21762
+ if (token.typ == exports.EnumToken.CommentTokenType || token.typ == exports.EnumToken.WhitespaceTokenType || token.typ == exports.EnumToken.CommaTokenType) {
21763
+ continue;
21764
+ }
21765
+ if (![exports.EnumToken.NumberTokenType, exports.EnumToken.LengthTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.PercentageTokenType].includes(token.typ)) {
21766
+ return transform;
21767
+ }
21768
+ if (token.typ == exports.EnumToken.PercentageTokenType && typeof token.val == 'number' && name.startsWith('scale')) {
21769
+ Object.assign(token, { typ: exports.EnumToken.NumberTokenType, val: token.val / 100 });
21770
+ }
21771
+ values.push(token);
21772
+ }
21773
+ if ((name == 'translate' || name == 'scale') && values.length > 2) {
21774
+ return transform;
21775
+ }
21776
+ const ignoredValue = name.startsWith('scale') ? 1 : 0;
21777
+ const t = new Set(['x', 'y', 'z']);
21778
+ let i = 3;
21779
+ while (i--) {
21780
+ if (values.length <= i || values[i].val == ignoredValue) {
21781
+ t.delete(i == 0 ? 'x' : i == 1 ? 'y' : 'z');
21782
+ }
21783
+ }
21784
+ if (name == 'translate3d' || name == 'translate') {
21785
+ if (t.size == 0) {
21786
+ return {
21787
+ typ: exports.EnumToken.FunctionTokenType,
21788
+ val: 'translate',
21789
+ chi: [
21790
+ { typ: exports.EnumToken.NumberTokenType, val: 0 }
21791
+ ]
21792
+ };
21793
+ }
21794
+ if (t.size == 1) {
21795
+ return {
21796
+ typ: exports.EnumToken.FunctionTokenType,
21797
+ val: 'translate' + (t.has('x') ? '' : t.has('y') ? 'Y' : 'Z'),
21798
+ chi: [
21799
+ values[t.has('x') ? 0 : t.has('y') ? 1 : 2]
21800
+ ]
21801
+ };
21802
+ }
21803
+ if (t.size == 2) {
21804
+ if (t.has('z')) {
21805
+ return transform;
21806
+ }
21807
+ return {
21808
+ typ: exports.EnumToken.FunctionTokenType,
21809
+ val: 'translate',
21810
+ chi: [
21811
+ values[0],
21812
+ { typ: exports.EnumToken.CommaTokenType },
21813
+ values[1]
21814
+ ]
21815
+ };
21816
+ }
21817
+ }
21818
+ if (name == 'scale3d' || name == 'scale') {
21819
+ if (t.size == 0) {
21820
+ return {
21821
+ typ: exports.EnumToken.FunctionTokenType,
21822
+ val: 'scale',
21823
+ chi: [
21824
+ { typ: exports.EnumToken.NumberTokenType, val: 1 }
21825
+ ]
21826
+ };
21827
+ }
21828
+ if (t.size == 1) {
21829
+ return {
21830
+ typ: exports.EnumToken.FunctionTokenType,
21831
+ val: 'scale' + (t.has('x') ? 'X' : t.has('y') ? 'Y' : 'Z'),
21832
+ chi: [
21833
+ values[t.has('x') ? 0 : t.has('y') ? 1 : 2]
21834
+ ]
21835
+ };
21836
+ }
21837
+ if (t.size == 2) {
21838
+ if (t.has('z')) {
21839
+ return transform;
21840
+ }
21841
+ return {
21842
+ typ: exports.EnumToken.FunctionTokenType,
21843
+ val: 'scale',
21844
+ chi: [
21845
+ values[0],
21846
+ { typ: exports.EnumToken.CommaTokenType },
21847
+ values[1]
21848
+ ]
21849
+ };
21850
+ }
21851
+ }
21852
+ return transform;
21853
+ }
21385
21854
 
21386
21855
  function skewX(x, from) {
21387
21856
  const matrix = identity();
21388
- matrix[1 * 4 + 0] = Math.tan(x);
21857
+ matrix[4] = Math.tan(x);
21389
21858
  return multiply(from, matrix);
21390
21859
  }
21391
21860
  function skewY(y, from) {
21392
21861
  const matrix = identity();
21393
- matrix[0 * 4 + 1] = Math.tan(y);
21862
+ matrix[1] = Math.tan(y);
21394
21863
  return multiply(from, matrix);
21395
21864
  }
21396
21865
  // convert angle to radian
21397
21866
  function skew(values, from) {
21398
21867
  const matrix = identity();
21399
- matrix[1 * 4 + 0] = Math.tan(values[0]);
21868
+ matrix[4] = Math.tan(values[0]);
21400
21869
  if (values.length > 1) {
21401
- matrix[0 * 4 + 1] = Math.tan(values[1]);
21870
+ matrix[1] = Math.tan(values[1]);
21402
21871
  }
21403
21872
  return multiply(from, matrix);
21404
21873
  }
@@ -21437,8 +21906,6 @@ function compute(transformLists) {
21437
21906
  });
21438
21907
  }
21439
21908
  }
21440
- // console.error({matrix});
21441
- // matrix = toZero(matrix) as Matrix;
21442
21909
  return {
21443
21910
  matrix: serialize(toZero(matrix)),
21444
21911
  cumulative,
@@ -21462,7 +21929,7 @@ function computeMatrix(transformList, matrixVar) {
21462
21929
  {
21463
21930
  values.length = 0;
21464
21931
  const children = stripCommaToken(transformList[i].chi.slice());
21465
- const valCount = transformList[i].val == 'translate3d' || transformList[i].val == 'translate' ? 3 : 1;
21932
+ const valCount = transformList[i].val == 'translate3d' ? 3 : transformList[i].val == 'translate' ? 2 : 1;
21466
21933
  for (let j = 0; j < children.length; j++) {
21467
21934
  if (children[j].typ == exports.EnumToken.WhitespaceTokenType) {
21468
21935
  continue;
@@ -21549,7 +22016,7 @@ function computeMatrix(transformList, matrixVar) {
21549
22016
  const children = stripCommaToken(transformList[i].chi.slice());
21550
22017
  for (let k = 0; k < children.length; k++) {
21551
22018
  child = children[k];
21552
- if (child.typ != exports.EnumToken.NumberTokenType) {
22019
+ if (child.typ != exports.EnumToken.NumberTokenType && child.typ != exports.EnumToken.PercentageTokenType) {
21553
22020
  return null;
21554
22021
  }
21555
22022
  values.push(getNumber(child));
@@ -21703,6 +22170,7 @@ function splitTransformList(transformList) {
21703
22170
  }
21704
22171
 
21705
22172
  class TransformCssFeature {
22173
+ accept = new Set([exports.EnumToken.RuleNodeType, exports.EnumToken.KeyFramesRuleNodeType]);
21706
22174
  get ordering() {
21707
22175
  return 4;
21708
22176
  }
@@ -21729,28 +22197,21 @@ class TransformCssFeature {
21729
22197
  if (node.typ != exports.EnumToken.DeclarationNodeType || !node.nam.match(/^(-[a-z]+-)?transform$/)) {
21730
22198
  continue;
21731
22199
  }
21732
- const children = node.val.reduce((acc, curr) => {
21733
- if (curr.typ == exports.EnumToken.FunctionTokenType && 'skew' == curr.val.toLowerCase()) {
21734
- if (curr.chi.length == 3) {
21735
- if (curr.chi[2].val == 0) {
21736
- curr.chi.length = 1;
21737
- curr.val = 'skew';
21738
- }
21739
- else if (curr.chi[0].val == 0) {
21740
- curr.chi = [curr.chi[2]];
21741
- curr.val = 'skewY';
21742
- }
21743
- }
21744
- }
21745
- acc.push(curr);
21746
- return acc;
21747
- }, []);
22200
+ const children = [];
22201
+ for (const child of node.val) {
22202
+ children.push(child.typ == exports.EnumToken.FunctionTokenType ? minifyTransformFunctions(child) : child);
22203
+ }
21748
22204
  consumeWhitespace(children);
21749
- let { matrix, cumulative, minified } = compute(children) ?? {};
22205
+ let { matrix, cumulative, minified } = compute(children) ?? {
22206
+ matrix: null,
22207
+ cumulative: null,
22208
+ minified: null
22209
+ };
21750
22210
  if (matrix == null || cumulative == null || minified == null) {
22211
+ node.val = children;
21751
22212
  continue;
21752
22213
  }
21753
- let r = [filterValues(node.val.slice())];
22214
+ let r = [filterValues(children)];
21754
22215
  if (eqMatrix(matrix, cumulative)) {
21755
22216
  r.push(cumulative);
21756
22217
  }
@@ -21829,7 +22290,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
21829
22290
  }
21830
22291
  replacement = parent;
21831
22292
  for (const feature of options.features) {
21832
- if ((feature.processMode & exports.FeatureWalkMode.Pre) === 0) {
22293
+ if ((feature.processMode & exports.FeatureWalkMode.Pre) === 0 || (feature.accept != null && !feature.accept.has(parent.typ))) {
21833
22294
  continue;
21834
22295
  }
21835
22296
  const result = feature.run(replacement, options, parent.parent ?? ast, context, exports.FeatureWalkMode.Pre);
@@ -21868,7 +22329,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
21868
22329
  replacement = parent;
21869
22330
  if (postprocess) {
21870
22331
  for (const feature of options.features) {
21871
- if ((feature.processMode & exports.FeatureWalkMode.Post) === 0) {
22332
+ if ((feature.processMode & exports.FeatureWalkMode.Post) === 0 || (feature.accept != null && !feature.accept.has(parent.typ))) {
21872
22333
  continue;
21873
22334
  }
21874
22335
  const result = feature.run(replacement, options, parent.parent ?? ast, context, exports.FeatureWalkMode.Post);
@@ -21999,6 +22460,7 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
21999
22460
  continue;
22000
22461
  }
22001
22462
  if (previous?.typ == exports.EnumToken.AtRuleNodeType &&
22463
+ node.nam != 'font-face' &&
22002
22464
  previous.nam == node.nam &&
22003
22465
  previous.val == node.val) {
22004
22466
  if ('chi' in node) {
@@ -22147,7 +22609,9 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
22147
22609
  break;
22148
22610
  }
22149
22611
  if (shouldMerge) {
22612
+ // @ts-ignore
22150
22613
  if (((node.typ == exports.EnumToken.RuleNodeType || node.typ == exports.EnumToken.KeyFramesRuleNodeType) && node.sel == previous.sel) ||
22614
+ // @ts-ignore
22151
22615
  (node.typ == exports.EnumToken.AtRuleNodeType) && node.val != 'font-face' && node.val == previous.val) {
22152
22616
  // @ts-ignore
22153
22617
  node.chi.unshift(...previous.chi);
@@ -22815,14 +23279,11 @@ function reduceRuleSelector(node) {
22815
23279
  */
22816
23280
  function expand(ast) {
22817
23281
  const result = { ...ast, chi: [] };
22818
- // @ts-ignore
22819
23282
  for (let i = 0; i < ast.chi.length; i++) {
22820
- // @ts-ignore
22821
23283
  const node = ast.chi[i];
22822
23284
  if (node.typ == exports.EnumToken.RuleNodeType) {
22823
23285
  // @ts-ignore
22824
23286
  result.chi.push(...expandRule(node));
22825
- // i += expanded.length - 1;
22826
23287
  }
22827
23288
  else if (node.typ == exports.EnumToken.AtRuleNodeType && 'chi' in node) {
22828
23289
  let hasRule = false;
@@ -22837,6 +23298,10 @@ function expand(ast) {
22837
23298
  // @ts-ignore
22838
23299
  result.chi.push({ ...(hasRule ? expand(node) : node) });
22839
23300
  }
23301
+ else {
23302
+ // @ts-ignore
23303
+ result.chi.push(node);
23304
+ }
22840
23305
  }
22841
23306
  return result;
22842
23307
  }
@@ -23019,41 +23484,39 @@ function replaceCompoundLiteral(selector, replace) {
23019
23484
  return 1;
23020
23485
  }
23021
23486
  return b == '&' ? -1 : 0;
23022
- }).reduce((acc, curr) => {
23023
- // if (acc.length > 0 && curr == '&' && (replace.charAt(0) != '.' || replace.includes(' '))) {
23024
- //
23025
- // return acc + ':is(' + replace + ')';
23026
- // }
23027
- return acc + (curr == '&' ? replace : curr);
23028
- }, '');
23487
+ }).reduce((acc, curr) => acc + (curr == '&' ? replace : curr), '');
23029
23488
  }
23030
23489
 
23031
23490
  /**
23032
23491
  * load file or url as stream
23033
23492
  * @param url
23034
23493
  * @param currentFile
23494
+ * @param asStream
23035
23495
  * @throws Error file not found
23036
23496
  *
23037
23497
  * @private
23038
23498
  */
23039
- async function load(url, currentFile = '.') {
23499
+ async function load(url, currentFile = '.', asStream = false) {
23040
23500
  const resolved = resolve(url, currentFile);
23041
- // @ts-ignore
23042
23501
  if (matchUrl.test(resolved.absolute)) {
23043
- return fetch(resolved.absolute).then((response) => {
23502
+ return fetch(resolved.absolute).then(async (response) => {
23044
23503
  if (!response.ok) {
23045
23504
  throw new Error(`${response.status} ${response.statusText} ${response.url}`);
23046
23505
  }
23047
- return response.body;
23506
+ return asStream ? response.body : await response.text();
23048
23507
  });
23049
23508
  }
23050
23509
  try {
23510
+ if (!asStream) {
23511
+ return promises.readFile(resolved.absolute, 'utf-8');
23512
+ }
23051
23513
  const stats = await promises.lstat(resolved.absolute);
23052
23514
  if (stats.isFile()) {
23053
- return node_stream.Readable.toWeb(node_fs.createReadStream(resolved.absolute));
23515
+ return node_stream.Readable.toWeb(node_fs.createReadStream(resolved.absolute, { encoding: 'utf-8', highWaterMark: 64 * 1024 }));
23054
23516
  }
23055
23517
  }
23056
23518
  catch (error) {
23519
+ console.warn(error);
23057
23520
  }
23058
23521
  throw new Error(`File not found: '${resolved.absolute || url}'`);
23059
23522
  }
@@ -23092,6 +23555,7 @@ function render(data, options = {}) {
23092
23555
  * parse css file
23093
23556
  * @param file url or path
23094
23557
  * @param options
23558
+ * @param asStream load file as stream
23095
23559
  *
23096
23560
  * @throws Error file not found
23097
23561
  *
@@ -23110,8 +23574,8 @@ function render(data, options = {}) {
23110
23574
  * console.log(result.ast);
23111
23575
  * ```
23112
23576
  */
23113
- async function parseFile(file, options = {}) {
23114
- return load(file).then(stream => parse(stream, { src: file, ...options }));
23577
+ async function parseFile(file, options = {}, asStream = false) {
23578
+ return Promise.resolve((options.load ?? load)(file, '.', asStream)).then(stream => parse(stream, { src: file, ...options }));
23115
23579
  }
23116
23580
  /**
23117
23581
  * parse css
@@ -23168,6 +23632,7 @@ async function parse(stream, options = {}) {
23168
23632
  * transform css file
23169
23633
  * @param file url or path
23170
23634
  * @param options
23635
+ * @param asStream load file as stream
23171
23636
  *
23172
23637
  * @throws Error file not found
23173
23638
  *
@@ -23186,8 +23651,8 @@ async function parse(stream, options = {}) {
23186
23651
  * console.log(result.code);
23187
23652
  * ```
23188
23653
  */
23189
- async function transformFile(file, options = {}) {
23190
- return load(file).then(stream => transform(stream, { src: file, ...options }));
23654
+ async function transformFile(file, options = {}, asStream = false) {
23655
+ return Promise.resolve((options.load ?? load)(file, '.', asStream)).then(stream => transform(stream, { src: file, ...options }));
23191
23656
  }
23192
23657
  /**
23193
23658
  * transform css