@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
@@ -25,14 +25,26 @@
25
25
  * disable validation
26
26
  */
27
27
  ValidationLevel[ValidationLevel["None"] = 0] = "None";
28
+ /**
29
+ * validate selectors
30
+ */
31
+ ValidationLevel[ValidationLevel["Selector"] = 1] = "Selector";
32
+ /**
33
+ * validate at-rules
34
+ */
35
+ ValidationLevel[ValidationLevel["AtRule"] = 2] = "AtRule";
36
+ /**
37
+ * validate declarations
38
+ */
39
+ ValidationLevel[ValidationLevel["Declaration"] = 4] = "Declaration";
28
40
  /**
29
41
  * validate selectors and at-rules
30
42
  */
31
- ValidationLevel[ValidationLevel["Default"] = 1] = "Default";
43
+ ValidationLevel[ValidationLevel["Default"] = 3] = "Default";
32
44
  /**
33
45
  * validate selectors, at-rules and declarations
34
46
  */
35
- ValidationLevel[ValidationLevel["All"] = 2] = "All"; // selectors + at-rules + declarations
47
+ ValidationLevel[ValidationLevel["All"] = 7] = "All"; // selectors + at-rules + declarations
36
48
  })(exports.ValidationLevel || (exports.ValidationLevel = {}));
37
49
  /**
38
50
  * enum of all token types
@@ -4109,9 +4121,6 @@
4109
4121
  function identity() {
4110
4122
  return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
4111
4123
  }
4112
- function pLength(point) {
4113
- return Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
4114
- }
4115
4124
  function normalize(point) {
4116
4125
  const [x, y, z] = point;
4117
4126
  const norm = Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
@@ -4139,8 +4148,14 @@
4139
4148
  function inverse(matrix) {
4140
4149
  // Create augmented matrix [matrix | identity]
4141
4150
  let augmented = [
4142
- 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
4143
- 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
4151
+ ...matrix.slice(0, 4),
4152
+ 1, 0, 0, 0,
4153
+ ...matrix.slice(4, 8),
4154
+ 0, 1, 0, 0,
4155
+ ...matrix.slice(8, 12),
4156
+ 0, 0, 1, 0,
4157
+ ...matrix.slice(12, 16),
4158
+ 0, 0, 0, 1
4144
4159
  ];
4145
4160
  // Gaussian elimination with partial pivoting
4146
4161
  for (let col = 0; col < 4; col++) {
@@ -4180,24 +4195,9 @@
4180
4195
  // Extract the inverse from the right side of the augmented matrix
4181
4196
  return augmented.slice(0, 16);
4182
4197
  }
4183
- // function transpose(matrix: Matrix): Matrix {
4184
- // // Crée une nouvelle matrice vide 4x4
4185
- // // @ts-ignore
4186
- // let transposed: Matrix = [[], [], [], []] as Matrix;
4187
- //
4188
- // // Parcourt chaque ligne et colonne pour transposer
4189
- // for (let i = 0; i < 4; i++) {
4190
- //
4191
- // for (let j = 0; j < 4; j++) {
4192
- //
4193
- // transposed[j][i] = matrix[i][j];
4194
- // }
4195
- // }
4196
- //
4197
- // return transposed;
4198
- // }
4199
4198
  function round(number) {
4200
- return Math.abs(number) < epsilon ? 0 : +number.toPrecision(6);
4199
+ const rounded = Math.round(number);
4200
+ return Math.abs(rounded - number) <= epsilon ? rounded : +number.toPrecision(6);
4201
4201
  }
4202
4202
  // translate3d(25.9808px, 0, 15px ) rotateY(60deg) skewX(49.9999deg) scale(1, 1.2)
4203
4203
  // translate → rotate → skew → scale
@@ -4220,7 +4220,7 @@
4220
4220
  perspectiveMatrix[15] = 1;
4221
4221
  // @ts-ignore
4222
4222
  const inverted = inverse(original.slice());
4223
- if (!inverted) {
4223
+ if (inverted === null) {
4224
4224
  return null;
4225
4225
  }
4226
4226
  const transposedInverse = transposeMatrix4(inverted);
@@ -4241,8 +4241,13 @@
4241
4241
  const row0 = [matrix[0], matrix[1], matrix[2]];
4242
4242
  const row1 = [matrix[4], matrix[5], matrix[6]];
4243
4243
  const row2 = [matrix[8], matrix[9], matrix[10]];
4244
+ const cross = [
4245
+ row1[1] * row2[2] - row1[2] * row2[1],
4246
+ row1[2] * row2[0] - row1[0] * row2[2],
4247
+ row1[0] * row2[1] - row1[1] * row2[0],
4248
+ ];
4244
4249
  // Compute scale
4245
- const scaleX = pLength(row0);
4250
+ const scaleX = Math.hypot(...row0);
4246
4251
  const row0Norm = normalize(row0);
4247
4252
  const skewXY = dot(row0Norm, row1);
4248
4253
  const row1Proj = [
@@ -4250,7 +4255,7 @@
4250
4255
  row1[1] - skewXY * row0Norm[1],
4251
4256
  row1[2] - skewXY * row0Norm[2]
4252
4257
  ];
4253
- const scaleY = pLength(row1Proj);
4258
+ const scaleY = Math.hypot(...row1Proj);
4254
4259
  const row1Norm = normalize(row1Proj);
4255
4260
  const skewXZ = dot(row0Norm, row2);
4256
4261
  const skewYZ = dot(row1Norm, row2);
@@ -4259,8 +4264,9 @@
4259
4264
  row2[1] - skewXZ * row0Norm[1] - skewYZ * row1Norm[1],
4260
4265
  row2[2] - skewXZ * row0Norm[2] - skewYZ * row1Norm[2]
4261
4266
  ];
4262
- const scaleZ = pLength(row2Proj);
4263
4267
  const row2Norm = normalize(row2Proj);
4268
+ const determinant = row0[0] * cross[0] + row0[1] * cross[1] + row0[2] * cross[2];
4269
+ const scaleZ = Math.hypot(...row2Proj) * (determinant < 0 ? -1 : 1);
4264
4270
  // Build rotation matrix from orthonormalized vectors
4265
4271
  const r00 = row0Norm[0], r01 = row1Norm[0], r02 = row2Norm[0];
4266
4272
  const r10 = row0Norm[1], r11 = row1Norm[1], r12 = row2Norm[1];
@@ -4297,7 +4303,6 @@
4297
4303
  qz = 0.25 * s;
4298
4304
  }
4299
4305
  [qx, qy, qz] = toZero([qx, qy, qz]);
4300
- // const q = gcd(qx, gcd(qy, qz));
4301
4306
  let q = [Math.abs(qx), Math.abs(qy), Math.abs(qz)].reduce((acc, curr) => {
4302
4307
  if (acc == 0 || (curr > 0 && curr < acc)) {
4303
4308
  acc = curr;
@@ -4342,16 +4347,16 @@
4342
4347
  // https://drafts.csswg.org/css-transforms-1/#2d-matrix
4343
4348
  function is2DMatrix(matrix) {
4344
4349
  // m13,m14, m23, m24, m31, m32, m34, m43 are all 0
4345
- return matrix[0 * 4 + 2] === 0 &&
4346
- matrix[0 * 4 + 3] === 0 &&
4347
- matrix[1 * 4 + 2] === 0 &&
4348
- matrix[1 * 4 + 3] === 0 &&
4349
- matrix[2 * 4 + 0] === 0 &&
4350
- matrix[2 * 4 + 1] === 0 &&
4351
- matrix[2 * 4 + 3] === 0 &&
4352
- matrix[3 * 4 + 2] === 0 &&
4353
- matrix[2 * 4 + 2] === 1 &&
4354
- matrix[3 * 4 + 3] === 1;
4350
+ return matrix[2] === 0 &&
4351
+ matrix[3] === 0 &&
4352
+ matrix[6] === 0 &&
4353
+ matrix[7] === 0 &&
4354
+ matrix[8] === 0 &&
4355
+ matrix[9] === 0 &&
4356
+ matrix[11] === 0 &&
4357
+ matrix[14] === 0 &&
4358
+ matrix[10] === 1 &&
4359
+ matrix[15] === 1;
4355
4360
  }
4356
4361
 
4357
4362
  /**
@@ -5453,7 +5458,7 @@
5453
5458
  }
5454
5459
  if (token.typ == exports.EnumToken.IdenTokenType) {
5455
5460
  // named color
5456
- return token.val.toLowerCase() in COLORS_NAMES;
5461
+ return token.val.toLowerCase() in COLORS_NAMES || 'currentcolor' === token.val.toLowerCase() || 'transparent' === token.val.toLowerCase();
5457
5462
  }
5458
5463
  let isLegacySyntax = false;
5459
5464
  if (token.typ == exports.EnumToken.FunctionTokenType) {
@@ -5506,8 +5511,13 @@
5506
5511
  return false;
5507
5512
  }
5508
5513
  }
5509
- if (children[i].typ == exports.EnumToken.FunctionTokenType && !mathFuncs.includes(children[i].val)) {
5510
- return false;
5514
+ if (children[i].typ == exports.EnumToken.FunctionTokenType) {
5515
+ if ('var' == children[i].val.toLowerCase()) {
5516
+ continue;
5517
+ }
5518
+ if (!mathFuncs.includes(children[i].val)) {
5519
+ return false;
5520
+ }
5511
5521
  }
5512
5522
  }
5513
5523
  if (children.length == 4 || (isRelative && children.length == 6)) {
@@ -5794,23 +5804,29 @@
5794
5804
  }
5795
5805
  return true;
5796
5806
  }
5797
- function isDimension(name) {
5798
- let index = name.length;
5799
- while (index--) {
5800
- if (isLetter(name.charCodeAt(index))) {
5801
- continue;
5802
- }
5803
- index++;
5804
- break;
5805
- }
5806
- const number = name.slice(0, index);
5807
- return number.length > 0 && isIdentStart(name.charCodeAt(index)) && isNumber(number);
5808
- }
5807
+ // export function isDimension(name: string) {
5808
+ //
5809
+ // let index: number = name.length;
5810
+ //
5811
+ // while (index--) {
5812
+ //
5813
+ // if (isLetter(<number>name.charCodeAt(index))) {
5814
+ //
5815
+ // continue
5816
+ // }
5817
+ //
5818
+ // index++;
5819
+ // break;
5820
+ // }
5821
+ //
5822
+ // const number: string = name.slice(0, index);
5823
+ // return number.length > 0 && isIdentStart(name.charCodeAt(index)) && isNumber(number);
5824
+ // }
5809
5825
  function isPercentage(name) {
5810
5826
  return name.endsWith('%') && isNumber(name.slice(0, -1));
5811
5827
  }
5812
- function isFlex(name) {
5813
- return name.endsWith('fr') && isNumber(name.slice(0, -2));
5828
+ function isFlex(dimension) {
5829
+ return 'unit' in dimension && 'fr' == dimension.unit.toLowerCase();
5814
5830
  }
5815
5831
  function parseDimension(name) {
5816
5832
  let index = name.length;
@@ -5826,6 +5842,9 @@
5826
5842
  val: +name.slice(0, index),
5827
5843
  unit: name.slice(index)
5828
5844
  };
5845
+ if (index < 0 || Number.isNaN(dimension.val)) {
5846
+ return null;
5847
+ }
5829
5848
  if (isAngle(dimension)) {
5830
5849
  // @ts-ignore
5831
5850
  dimension.typ = exports.EnumToken.AngleTokenType;
@@ -5849,6 +5868,10 @@
5849
5868
  // @ts-ignore
5850
5869
  dimension.typ = exports.EnumToken.FrequencyTokenType;
5851
5870
  }
5871
+ else if (isFlex(dimension)) {
5872
+ // @ts-ignore
5873
+ dimension.typ = exports.EnumToken.FlexTokenType;
5874
+ }
5852
5875
  return dimension;
5853
5876
  }
5854
5877
  function isHexColor(name) {
@@ -7689,7 +7712,7 @@
7689
7712
  const sourcemap = options.sourcemap ? new SourceMap : null;
7690
7713
  const cache = Object.create(null);
7691
7714
  const result = {
7692
- code: renderAstNode(options.expandNestingRules ? expand(data) : data, options, sourcemap, {
7715
+ code: renderAstNode(options.expandNestingRules && [exports.EnumToken.StyleSheetNodeType, exports.EnumToken.AtRuleNodeType, exports.EnumToken.RuleNodeType].includes(data.typ) && 'chi' in data ? expand(data) : data, options, sourcemap, {
7693
7716
  ind: 0,
7694
7717
  lin: 1,
7695
7718
  col: 1
@@ -7829,7 +7852,7 @@
7829
7852
  str = `${node.nam}:${options.indent}${(options.minify ? filterValues(node.val) : node.val).reduce(reducer, '').trimEnd()};`;
7830
7853
  }
7831
7854
  else if (node.typ == exports.EnumToken.AtRuleNodeType && !('chi' in node)) {
7832
- str = `${data.val === '' ? '' : options.indent || ' '}${data.val};`;
7855
+ str = `${node.val === '' ? '' : options.indent || ' '}${node.val};`;
7833
7856
  }
7834
7857
  else {
7835
7858
  str = renderAstNode(node, options, sourcemap, { ...position }, errors, reducer, cache, level + 1, indents);
@@ -8420,13 +8443,15 @@
8420
8443
  yield pushToken(buffer, parseInfo);
8421
8444
  buffer = '';
8422
8445
  }
8446
+ buffer += value;
8423
8447
  while (value = next(parseInfo)) {
8424
8448
  charCode = value.charCodeAt(0);
8425
8449
  if (!isWhiteSpace(charCode)) {
8426
8450
  break;
8427
8451
  }
8452
+ buffer += value;
8428
8453
  }
8429
- yield pushToken('', parseInfo, exports.EnumToken.WhitespaceTokenType);
8454
+ yield pushToken(buffer, parseInfo, exports.EnumToken.WhitespaceTokenType);
8430
8455
  buffer = '';
8431
8456
  }
8432
8457
  switch (charCode) {
@@ -8474,8 +8499,7 @@
8474
8499
  buffer = '';
8475
8500
  }
8476
8501
  if (match$1(parseInfo, '=')) {
8477
- yield pushToken('', parseInfo, exports.EnumToken.LteTokenType);
8478
- next(parseInfo);
8502
+ yield pushToken(value + next(parseInfo), parseInfo, exports.EnumToken.LteTokenType);
8479
8503
  break;
8480
8504
  }
8481
8505
  buffer += value;
@@ -8530,8 +8554,7 @@
8530
8554
  }
8531
8555
  if (charCode == 124 /* TokenMap.PIPE */) {
8532
8556
  if (match$1(parseInfo, '|')) {
8533
- next(parseInfo);
8534
- yield pushToken('', parseInfo, exports.EnumToken.ColumnCombinatorTokenType);
8557
+ yield pushToken(value + next(parseInfo), parseInfo, exports.EnumToken.ColumnCombinatorTokenType);
8535
8558
  }
8536
8559
  else if (match$1(parseInfo, '=')) {
8537
8560
  buffer += next(parseInfo);
@@ -8585,11 +8608,10 @@
8585
8608
  buffer = '';
8586
8609
  }
8587
8610
  if (match$1(parseInfo, '=')) {
8588
- yield pushToken('', parseInfo, exports.EnumToken.GteTokenType);
8589
- next(parseInfo);
8611
+ yield pushToken(value + next(parseInfo), parseInfo, exports.EnumToken.GteTokenType);
8590
8612
  }
8591
8613
  else {
8592
- yield pushToken('', parseInfo, exports.EnumToken.GtTokenType);
8614
+ yield pushToken(value, parseInfo, exports.EnumToken.GtTokenType);
8593
8615
  }
8594
8616
  consumeWhiteSpace(parseInfo);
8595
8617
  break;
@@ -8640,7 +8662,7 @@
8640
8662
  yield pushToken(buffer, parseInfo);
8641
8663
  buffer = '';
8642
8664
  }
8643
- yield pushToken('', parseInfo, exports.EnumToken.EndParensTokenType);
8665
+ yield pushToken(value, parseInfo, exports.EnumToken.EndParensTokenType);
8644
8666
  break;
8645
8667
  case 40 /* TokenMap.OPEN_PAREN */:
8646
8668
  if (buffer.length == 0) {
@@ -8706,7 +8728,7 @@
8706
8728
  // ')'
8707
8729
  if (charCode == 0x29) {
8708
8730
  yield pushToken(buffer, parseInfo, hasNewLine ? exports.EnumToken.BadStringTokenType : exports.EnumToken.StringTokenType);
8709
- yield pushToken('', parseInfo, exports.EnumToken.EndParensTokenType);
8731
+ yield pushToken(value, parseInfo, exports.EnumToken.EndParensTokenType);
8710
8732
  buffer = '';
8711
8733
  break;
8712
8734
  }
@@ -8730,7 +8752,7 @@
8730
8752
  charCode = value.charCodeAt(0);
8731
8753
  if (charCode == 0x29) { // ')'
8732
8754
  yield pushToken(buffer, parseInfo, exports.EnumToken.UrlTokenTokenType);
8733
- yield pushToken('', parseInfo, exports.EnumToken.EndParensTokenType);
8755
+ yield pushToken(value, parseInfo, exports.EnumToken.EndParensTokenType);
8734
8756
  buffer = '';
8735
8757
  break;
8736
8758
  }
@@ -8764,8 +8786,7 @@
8764
8786
  buffer = '';
8765
8787
  }
8766
8788
  if (match$1(parseInfo, 'important')) {
8767
- yield pushToken('', parseInfo, exports.EnumToken.ImportantTokenType);
8768
- next(parseInfo, 9);
8789
+ yield pushToken(value + next(parseInfo, 9), parseInfo, exports.EnumToken.ImportantTokenType);
8769
8790
  buffer = '';
8770
8791
  break;
8771
8792
  }
@@ -13017,7 +13038,27 @@
13017
13038
  }
13018
13039
  },
13019
13040
  "@nest": {
13020
- syntax: "<complex-selector-list>"
13041
+ },
13042
+ "@stylistic": {
13043
+ syntax: " @stylistic { <feature-value-declaration-list> } "
13044
+ },
13045
+ "@historical-forms": {
13046
+ syntax: " @historical-forms { <feature-value-declaration-list> } "
13047
+ },
13048
+ "@styleset": {
13049
+ syntax: " @styleset { <feature-value-declaration-list> } "
13050
+ },
13051
+ "@character-variant": {
13052
+ syntax: " @character-variant { <feature-value-declaration-list> } "
13053
+ },
13054
+ "@swash": {
13055
+ syntax: " @swash { <feature-value-declaration-list> } "
13056
+ },
13057
+ "@ornaments": {
13058
+ syntax: " @ornaments { <feature-value-declaration-list> } "
13059
+ },
13060
+ "@annotation": {
13061
+ syntax: " @annotation { <feature-value-declaration-list> } "
13021
13062
  }
13022
13063
  };
13023
13064
  var config$3 = {
@@ -13080,7 +13121,6 @@
13080
13121
  ValidationSyntaxGroupEnum["Selectors"] = "selectors";
13081
13122
  ValidationSyntaxGroupEnum["AtRules"] = "atRules";
13082
13123
  })(ValidationSyntaxGroupEnum || (ValidationSyntaxGroupEnum = {}));
13083
-
13084
13124
  const skipped = [
13085
13125
  ValidationTokenEnum.Star,
13086
13126
  ValidationTokenEnum.HashMark,
@@ -14161,7 +14201,6 @@
14161
14201
  const index = group + '.' + keys.join('.');
14162
14202
  // @ts-ignore
14163
14203
  if (!parsedSyntaxes.has(index)) {
14164
- // @ts-ignore
14165
14204
  const syntax = parseSyntax(obj.syntax);
14166
14205
  // @ts-ignore
14167
14206
  parsedSyntaxes.set(index, syntax.chi);
@@ -14612,6 +14651,116 @@
14612
14651
  const config$2 = getSyntaxConfig();
14613
14652
  // @ts-ignore
14614
14653
  const allValues = getSyntaxConfig()["declarations" /* ValidationSyntaxGroupEnum.Declarations */].all.syntax.trim().split(/[\s|]+/g);
14654
+ /**
14655
+ * Check if a node is allowed as child in a given context
14656
+ * @param node
14657
+ * @param context
14658
+ */
14659
+ function isNodeAllowedInContext(node, context) {
14660
+ if (node.typ == exports.EnumToken.CommentNodeType || context == null) {
14661
+ return true;
14662
+ }
14663
+ switch (context?.typ) {
14664
+ case exports.EnumToken.StyleSheetNodeType:
14665
+ case exports.EnumToken.RuleNodeType:
14666
+ return node.typ == exports.EnumToken.RuleNodeType ||
14667
+ node.typ == exports.EnumToken.AtRuleNodeType ||
14668
+ node.typ == exports.EnumToken.KeyframesAtRuleNodeType ||
14669
+ (node.typ == exports.EnumToken.DeclarationNodeType && context.typ == exports.EnumToken.RuleNodeType) ||
14670
+ (node.typ == exports.EnumToken.CDOCOMMNodeType && context.typ == exports.EnumToken.StyleSheetNodeType);
14671
+ case exports.EnumToken.KeyframesAtRuleNodeType:
14672
+ return node.typ == exports.EnumToken.KeyFramesRuleNodeType;
14673
+ case exports.EnumToken.KeyFramesRuleNodeType:
14674
+ return node.typ == exports.EnumToken.DeclarationNodeType;
14675
+ case exports.EnumToken.AtRuleNodeType:
14676
+ // @ts-ignore
14677
+ const syntax = getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, '@' + context.nam)?.[0].chi ?? null;
14678
+ //
14679
+ if (syntax == null) {
14680
+ // console.error(`syntax: Not found ${ValidationSyntaxGroupEnum.AtRules}@${(context as AstAtRule).nam}`);
14681
+ return true;
14682
+ }
14683
+ const stack = syntax.slice();
14684
+ for (const child of stack) {
14685
+ if (Array.isArray(child)) {
14686
+ stack.push(...child);
14687
+ continue;
14688
+ }
14689
+ if ('chi' in child && Array.isArray(child.chi)) {
14690
+ stack.push(...child.chi);
14691
+ continue;
14692
+ }
14693
+ // @ts-ignore
14694
+ if (child.l != null) {
14695
+ // @ts-ignore
14696
+ stack.push(child.l);
14697
+ // @ts-ignore
14698
+ if (child.r != null) {
14699
+ // @ts-ignore
14700
+ stack.push(...(Array.isArray(child.r) ? child.r : [child.r]));
14701
+ }
14702
+ continue;
14703
+ }
14704
+ if (node.typ == exports.EnumToken.DeclarationNodeType) {
14705
+ if (child.typ == ValidationTokenEnum.DeclarationDefinitionToken) {
14706
+ if (node.nam == child.nam) {
14707
+ return true;
14708
+ }
14709
+ }
14710
+ }
14711
+ if (child.typ == ValidationTokenEnum.PropertyType) {
14712
+ if (['group-rule-body', 'block-contents', 'rule-list', 'stylesheet'].includes(child.val)) {
14713
+ if ((node.typ == exports.EnumToken.RuleNodeType ||
14714
+ node.typ == exports.EnumToken.AtRuleNodeType ||
14715
+ node.typ == exports.EnumToken.KeyframesAtRuleNodeType)) {
14716
+ return true;
14717
+ }
14718
+ if (node.typ == exports.EnumToken.DeclarationNodeType) {
14719
+ let parent = node.parent;
14720
+ while (parent != null) {
14721
+ if (parent.parent?.typ == exports.EnumToken.RuleNodeType) {
14722
+ return true;
14723
+ }
14724
+ parent = parent.parent;
14725
+ }
14726
+ }
14727
+ }
14728
+ if (['declaration-list', 'feature-value-declaration'].includes(child.val) && node.typ == exports.EnumToken.DeclarationNodeType) {
14729
+ return true;
14730
+ }
14731
+ if (child.val == 'page-body' && (node.typ == exports.EnumToken.DeclarationNodeType || (node.typ == exports.EnumToken.AtRuleNodeType && [
14732
+ 'top-left-corner', 'top-left', 'top-center', 'top-right', 'top-right-corner',
14733
+ 'bottom-left-corner', 'bottom-left', 'bottom-center', 'bottom-right', 'bottom-right-corner',
14734
+ 'left-top', 'left-middle', 'left-bottom', 'right-top', 'right-middle', 'right-bottom'
14735
+ ].includes(node.nam)))) {
14736
+ return true;
14737
+ }
14738
+ if (child.val == 'feature-value-block-list' &&
14739
+ (node.typ == exports.EnumToken.AtRuleNodeType && ['stylistic', 'historical-forms', 'styleset', 'character-variant', 'swash', 'ornaments', 'annotation'].includes(node.nam))) {
14740
+ return true;
14741
+ }
14742
+ if (['feature-value-declaration-list', 'feature-value-declaration'].includes(child.val) && node.typ == exports.EnumToken.DeclarationNodeType) {
14743
+ return true;
14744
+ }
14745
+ if (child.val == 'page-body') {
14746
+ if (node.typ == exports.EnumToken.DeclarationNodeType) {
14747
+ return true;
14748
+ }
14749
+ }
14750
+ // console.error(`isNodeAllowedInContext: Not found ${(child as ValidationPropertyToken).val}`, {
14751
+ // child,
14752
+ // node
14753
+ // });
14754
+ }
14755
+ }
14756
+ break;
14757
+ }
14758
+ return false;
14759
+ }
14760
+ /**
14761
+ * Create a syntax validation context from a list of tokens
14762
+ * @param input
14763
+ */
14615
14764
  function createContext(input) {
14616
14765
  const values = input.slice();
14617
14766
  const result = values.filter(token => token.typ != exports.EnumToken.CommentTokenType).slice();
@@ -14672,7 +14821,22 @@
14672
14821
  }
14673
14822
  };
14674
14823
  }
14675
- function evaluateSyntax(node, options) {
14824
+ /**
14825
+ * Evaluate the validity of the syntax of a node
14826
+ * @param node
14827
+ * @param parent
14828
+ * @param options
14829
+ */
14830
+ function evaluateSyntax(node, parent, options) {
14831
+ if (node.validSyntax) {
14832
+ return {
14833
+ valid: SyntaxValidationResult.Valid,
14834
+ node,
14835
+ syntax: null,
14836
+ error: '',
14837
+ context: []
14838
+ };
14839
+ }
14676
14840
  let ast;
14677
14841
  let result;
14678
14842
  switch (node.typ) {
@@ -14680,25 +14844,34 @@
14680
14844
  if (node.nam.startsWith('--')) {
14681
14845
  break;
14682
14846
  }
14847
+ let token = null;
14848
+ let values = node.val.slice();
14683
14849
  ast = getParsedSyntax("declarations" /* ValidationSyntaxGroupEnum.Declarations */, node.nam);
14684
- if (ast != null) {
14685
- let token = null;
14686
- const values = node.val.slice();
14687
- while (values.length > 0) {
14688
- token = values.at(-1);
14689
- if (token.typ == exports.EnumToken.WhitespaceTokenType || token.typ == exports.EnumToken.CommentTokenType) {
14850
+ while (values.length > 0) {
14851
+ token = values.at(-1);
14852
+ if (token.typ == exports.EnumToken.WhitespaceTokenType || token.typ == exports.EnumToken.CommentTokenType) {
14853
+ values.pop();
14854
+ }
14855
+ else {
14856
+ if (token.typ == exports.EnumToken.ImportantTokenType) {
14690
14857
  values.pop();
14691
- }
14692
- else {
14693
- if (token.typ == exports.EnumToken.ImportantTokenType) {
14858
+ if (values.at(-1)?.typ == exports.EnumToken.WhitespaceTokenType) {
14694
14859
  values.pop();
14695
- if (values.at(-1)?.typ == exports.EnumToken.WhitespaceTokenType) {
14696
- values.pop();
14697
- }
14698
14860
  }
14699
- break;
14861
+ }
14862
+ break;
14863
+ }
14864
+ }
14865
+ if (ast == null) {
14866
+ if (parent?.typ == exports.EnumToken.AtRuleNodeType) {
14867
+ ast = (getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, ['@' + parent.nam, 'descriptors', node.nam]));
14868
+ if (ast == null) {
14869
+ ast = (getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, ['@' + parent.nam, 'descriptors', node.nam]) ?? getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, '@' + parent.nam))?.[0]?.chi;
14870
+ values = [{ ...node, val: values }];
14700
14871
  }
14701
14872
  }
14873
+ }
14874
+ if (ast != null) {
14702
14875
  result = doEvaluateSyntax(ast, createContext(values), { ...options, visited: new WeakMap() });
14703
14876
  if (result.valid == SyntaxValidationResult.Valid && !result.context.done()) {
14704
14877
  let token = null;
@@ -14790,7 +14963,7 @@
14790
14963
  continue;
14791
14964
  }
14792
14965
  }
14793
- else if (options.occurence !== false && syntax.occurence != null) {
14966
+ else if (options.occurrence !== false && syntax.occurence != null) {
14794
14967
  result = matchOccurence(syntax, context, options);
14795
14968
  }
14796
14969
  else if (options.atLeastOnce !== false && syntax.atLeastOnce) {
@@ -14879,7 +15052,7 @@
14879
15052
  result = doEvaluateSyntax([syntax], createContext(tokens), {
14880
15053
  ...options,
14881
15054
  isList: false,
14882
- occurence: false
15055
+ occurrence: false
14883
15056
  });
14884
15057
  if (result.valid == SyntaxValidationResult.Valid) {
14885
15058
  context = con.clone();
@@ -14914,7 +15087,7 @@
14914
15087
  let counter = 0;
14915
15088
  let result;
14916
15089
  do {
14917
- result = match(syntax, context.clone(), { ...options, occurence: false });
15090
+ result = match(syntax, context.clone(), { ...options, occurrence: false });
14918
15091
  if (result.valid == SyntaxValidationResult.Drop) {
14919
15092
  break;
14920
15093
  }
@@ -14965,7 +15138,7 @@
14965
15138
  ...options,
14966
15139
  isRepeatable: null,
14967
15140
  isList: null,
14968
- occurence: null,
15141
+ occurrence: null,
14969
15142
  atLeastOnce: null
14970
15143
  });
14971
15144
  if (result.valid == SyntaxValidationResult.Valid) {
@@ -14977,7 +15150,7 @@
14977
15150
  case ValidationTokenEnum.Keyword:
14978
15151
  success = (token.typ == exports.EnumToken.IdenTokenType || token.typ == exports.EnumToken.DashedIdenTokenType || isIdentColor(token)) &&
14979
15152
  (token.val == syntax.val ||
14980
- syntax.val === token.val?.toLowerCase?.() ||
15153
+ syntax.val.toLowerCase() === token.val?.toLowerCase?.() ||
14981
15154
  // config.declarations.all
14982
15155
  allValues.includes(token.val.toLowerCase()));
14983
15156
  if (success) {
@@ -15016,7 +15189,7 @@
15016
15189
  ...options,
15017
15190
  isRepeatable: null,
15018
15191
  isList: null,
15019
- occurence: null,
15192
+ occurrence: null,
15020
15193
  atLeastOnce: null
15021
15194
  });
15022
15195
  case ValidationTokenEnum.Comma:
@@ -15051,7 +15224,7 @@
15051
15224
  ...options,
15052
15225
  isRepeatable: null,
15053
15226
  isList: null,
15054
- occurence: null,
15227
+ occurrence: null,
15055
15228
  atLeastOnce: null
15056
15229
  }).valid == SyntaxValidationResult.Valid;
15057
15230
  if (success) {
@@ -15074,18 +15247,19 @@
15074
15247
  }
15075
15248
  function matchPropertyType(syntax, context, options) {
15076
15249
  if (![
15077
- 'bg-position',
15250
+ 'color',
15078
15251
  'integer',
15252
+ 'bg-position',
15079
15253
  'length-percentage', 'flex', 'calc-sum', 'color',
15080
15254
  'color-base', 'system-color', 'deprecated-system-color',
15081
- 'pseudo-class-selector', 'pseudo-element-selector'
15255
+ 'pseudo-class-selector', 'pseudo-element-selector', 'feature-value-declaration'
15082
15256
  ].includes(syntax.val)) {
15083
15257
  if (syntax.val in config$2["syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */]) {
15084
15258
  return doEvaluateSyntax(getParsedSyntax("syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */, syntax.val), context, {
15085
15259
  ...options,
15086
15260
  isRepeatable: null,
15087
15261
  isList: null,
15088
- occurence: null,
15262
+ occurrence: null,
15089
15263
  atLeastOnce: null
15090
15264
  });
15091
15265
  }
@@ -15097,7 +15271,7 @@
15097
15271
  ...options,
15098
15272
  isRepeatable: null,
15099
15273
  isList: null,
15100
- occurence: null,
15274
+ occurrence: null,
15101
15275
  atLeastOnce: null
15102
15276
  });
15103
15277
  if (result.valid == SyntaxValidationResult.Valid) {
@@ -15202,6 +15376,14 @@
15202
15376
  (token.typ == exports.EnumToken.IdenTokenType && typeof Math[token.val.toUpperCase()] == 'number') ||
15203
15377
  [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);
15204
15378
  break;
15379
+ case 'declaration':
15380
+ {
15381
+ success = token.typ == exports.EnumToken.DeclarationNodeType;
15382
+ if (success) {
15383
+ success = evaluateSyntax(token, null, options).valid == SyntaxValidationResult.Valid;
15384
+ }
15385
+ }
15386
+ break;
15205
15387
  case 'declaration-value':
15206
15388
  while (!context.done()) {
15207
15389
  context.next();
@@ -15228,13 +15410,17 @@
15228
15410
  break;
15229
15411
  case 'color':
15230
15412
  case 'color-base':
15231
- 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));
15413
+ success = token.typ == exports.EnumToken.ColorTokenType ||
15414
+ (token.typ == exports.EnumToken.IdenTokenType && 'currentcolor' === token.val.toLowerCase()) ||
15415
+ (token.typ == exports.EnumToken.IdenTokenType && 'transparent' === token.val.toLowerCase()) ||
15416
+ (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val) ||
15417
+ isColor(token));
15232
15418
  if (!success && token.typ == exports.EnumToken.FunctionTokenType && colorsFunc.includes(token.val)) {
15233
15419
  success = doEvaluateSyntax(getParsedSyntax("functions" /* ValidationSyntaxGroupEnum.Functions */, token.val)?.[0]?.chi, createContext(token.chi), {
15234
15420
  ...options,
15235
15421
  isRepeatable: null,
15236
15422
  isList: null,
15237
- occurence: null,
15423
+ occurrence: null,
15238
15424
  atLeastOnce: null
15239
15425
  }).valid == SyntaxValidationResult.Valid;
15240
15426
  }
@@ -15242,8 +15428,26 @@
15242
15428
  case 'hex-color':
15243
15429
  success = (token.typ == exports.EnumToken.ColorTokenType && token.kin == exports.ColorType.HEX) || (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val));
15244
15430
  break;
15431
+ case 'feature-value-declaration':
15432
+ {
15433
+ let hasNumber = false;
15434
+ success = token.typ == exports.EnumToken.DeclarationNodeType && token.val.length > 0 && token.val.every((val) => {
15435
+ if (val.typ == exports.EnumToken.WhitespaceTokenType || val.typ == exports.EnumToken.CommentTokenType) {
15436
+ return true;
15437
+ }
15438
+ 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)));
15439
+ if (success) {
15440
+ hasNumber = true;
15441
+ }
15442
+ if ('range' in syntax) {
15443
+ return success && +val.val >= +syntax.range[0] && +val.val <= +syntax.range[1];
15444
+ }
15445
+ return success;
15446
+ }) && hasNumber;
15447
+ }
15448
+ break;
15245
15449
  case 'integer':
15246
- 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)));
15450
+ 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)));
15247
15451
  if ('range' in syntax) {
15248
15452
  success = success && +token.val >= +syntax.range[0] && +token.val <= +syntax.range[1];
15249
15453
  }
@@ -15307,7 +15511,7 @@
15307
15511
  ...options,
15308
15512
  isRepeatable: null,
15309
15513
  isList: null,
15310
- occurence: null,
15514
+ occurrence: null,
15311
15515
  atLeastOnce: null
15312
15516
  }).valid == SyntaxValidationResult.Valid;
15313
15517
  }
@@ -15323,7 +15527,7 @@
15323
15527
  ...options,
15324
15528
  isRepeatable: null,
15325
15529
  isList: null,
15326
- occurence: null,
15530
+ occurrence: null,
15327
15531
  atLeastOnce: null
15328
15532
  }).valid == SyntaxValidationResult.Valid;
15329
15533
  }
@@ -15470,7 +15674,6 @@
15470
15674
  i = -1;
15471
15675
  }
15472
15676
  }
15473
- // console.error()
15474
15677
  const success = syntax.length == 0;
15475
15678
  return {
15476
15679
  valid: success ? SyntaxValidationResult.Valid : SyntaxValidationResult.Drop,
@@ -15550,6 +15753,17 @@
15550
15753
  }
15551
15754
 
15552
15755
  function validateAtRuleMedia(atRule, options, root) {
15756
+ if (!Array.isArray(atRule.chi)) {
15757
+ // @ts-ignore
15758
+ return {
15759
+ valid: SyntaxValidationResult.Drop,
15760
+ matches: [],
15761
+ node: atRule,
15762
+ syntax: '@' + atRule.nam,
15763
+ error: 'expected supports body',
15764
+ tokens: []
15765
+ };
15766
+ }
15553
15767
  // media-query-list
15554
15768
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
15555
15769
  // @ts-ignore
@@ -15782,6 +15996,17 @@
15782
15996
  }
15783
15997
 
15784
15998
  function validateAtRuleCounterStyle(atRule, options, root) {
15999
+ if (!Array.isArray(atRule.chi)) {
16000
+ // @ts-ignore
16001
+ return {
16002
+ valid: SyntaxValidationResult.Drop,
16003
+ matches: [],
16004
+ node: atRule,
16005
+ syntax: '@' + atRule.nam,
16006
+ error: 'expected supports body',
16007
+ tokens: []
16008
+ };
16009
+ }
15785
16010
  // media-query-list
15786
16011
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
15787
16012
  // @ts-ignore
@@ -15851,6 +16076,17 @@
15851
16076
  }
15852
16077
 
15853
16078
  function validateAtRulePage(atRule, options, root) {
16079
+ if (!Array.isArray(atRule.chi)) {
16080
+ // @ts-ignore
16081
+ return {
16082
+ valid: SyntaxValidationResult.Drop,
16083
+ matches: [],
16084
+ node: atRule,
16085
+ syntax: '@' + atRule.nam,
16086
+ error: 'expected supports body',
16087
+ tokens: []
16088
+ };
16089
+ }
15854
16090
  // media-query-list
15855
16091
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
15856
16092
  // @ts-ignore
@@ -15929,6 +16165,17 @@
15929
16165
  }
15930
16166
 
15931
16167
  function validateAtRulePageMarginBox(atRule, options, root) {
16168
+ if (!Array.isArray(atRule.chi)) {
16169
+ // @ts-ignore
16170
+ return {
16171
+ valid: SyntaxValidationResult.Drop,
16172
+ matches: [],
16173
+ node: atRule,
16174
+ syntax: '@' + atRule.nam,
16175
+ error: 'expected supports body',
16176
+ tokens: []
16177
+ };
16178
+ }
15932
16179
  if (Array.isArray(atRule.tokens) && atRule.tokens.length > 0) {
15933
16180
  // @ts-ignore
15934
16181
  return {
@@ -15984,6 +16231,17 @@
15984
16231
  tokens: []
15985
16232
  };
15986
16233
  }
16234
+ if (!Array.isArray(atRule.chi)) {
16235
+ // @ts-ignore
16236
+ return {
16237
+ valid: SyntaxValidationResult.Drop,
16238
+ matches: [],
16239
+ node: atRule,
16240
+ syntax: '@' + atRule.nam,
16241
+ error: 'expected supports body',
16242
+ tokens: []
16243
+ };
16244
+ }
15987
16245
  const result = validateAtRuleSupportsConditions(atRule, atRule.tokens);
15988
16246
  if (result) {
15989
16247
  if (result.node == null) {
@@ -16376,6 +16634,17 @@
16376
16634
  }
16377
16635
 
16378
16636
  function validateAtRuleLayer(atRule, options, root) {
16637
+ if (!Array.isArray(atRule.chi)) {
16638
+ // @ts-ignore
16639
+ return {
16640
+ valid: SyntaxValidationResult.Drop,
16641
+ matches: [],
16642
+ node: atRule,
16643
+ syntax: '@' + atRule.nam,
16644
+ error: 'expected supports body',
16645
+ tokens: []
16646
+ };
16647
+ }
16379
16648
  // media-query-list
16380
16649
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
16381
16650
  // @ts-ignore
@@ -16392,6 +16661,17 @@
16392
16661
  }
16393
16662
 
16394
16663
  function validateAtRuleFontFeatureValues(atRule, options, root) {
16664
+ if (!Array.isArray(atRule.chi)) {
16665
+ // @ts-ignore
16666
+ return {
16667
+ valid: SyntaxValidationResult.Drop,
16668
+ matches: [],
16669
+ node: atRule,
16670
+ syntax: '@' + atRule.nam,
16671
+ error: 'expected supports body',
16672
+ tokens: []
16673
+ };
16674
+ }
16395
16675
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
16396
16676
  // @ts-ignore
16397
16677
  return {
@@ -16575,6 +16855,17 @@
16575
16855
  }
16576
16856
 
16577
16857
  function validateAtRuleKeyframes(atRule, options, root) {
16858
+ if (!Array.isArray(atRule.chi)) {
16859
+ // @ts-ignore
16860
+ return {
16861
+ valid: SyntaxValidationResult.Drop,
16862
+ matches: [],
16863
+ node: atRule,
16864
+ syntax: '@' + atRule.nam,
16865
+ error: 'expected supports body',
16866
+ tokens: []
16867
+ };
16868
+ }
16578
16869
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
16579
16870
  // @ts-ignore
16580
16871
  return {
@@ -16620,6 +16911,17 @@
16620
16911
  }
16621
16912
 
16622
16913
  function validateAtRuleWhen(atRule, options, root) {
16914
+ if (!Array.isArray(atRule.chi)) {
16915
+ // @ts-ignore
16916
+ return {
16917
+ valid: SyntaxValidationResult.Drop,
16918
+ matches: [],
16919
+ node: atRule,
16920
+ syntax: '@' + atRule.nam,
16921
+ error: 'expected supports body',
16922
+ tokens: []
16923
+ };
16924
+ }
16623
16925
  const slice = Array.isArray(atRule.tokens) ? atRule.tokens.slice() : [];
16624
16926
  consumeWhitespace(slice);
16625
16927
  if (slice.length == 0) {
@@ -16783,6 +17085,17 @@
16783
17085
 
16784
17086
  const validateContainerScrollStateFeature = validateContainerSizeFeature;
16785
17087
  function validateAtRuleContainer(atRule, options, root) {
17088
+ if (!Array.isArray(atRule.chi)) {
17089
+ // @ts-ignore
17090
+ return {
17091
+ valid: SyntaxValidationResult.Drop,
17092
+ matches: [],
17093
+ node: atRule,
17094
+ syntax: '@' + atRule.nam,
17095
+ error: 'expected supports body',
17096
+ tokens: []
17097
+ };
17098
+ }
16786
17099
  // media-query-list
16787
17100
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
16788
17101
  // @ts-ignore
@@ -17319,12 +17632,13 @@
17319
17632
  return keyName.replace(/-([a-z])/g, (all, one) => one.toUpperCase());
17320
17633
  }
17321
17634
  function replaceToken(parent, value, replacement) {
17322
- // @ts-ignore
17323
- if ('parent' in value && value.parent != replacement.parent) {
17324
- Object.defineProperty(replacement, 'parent', {
17325
- ...definedPropertySettings,
17326
- value: value.parent
17327
- });
17635
+ for (const node of (Array.isArray(replacement) ? replacement : [replacement])) {
17636
+ if ('parent' in value && value.parent != node.parent) {
17637
+ Object.defineProperty(node, 'parent', {
17638
+ ...definedPropertySettings,
17639
+ value: value.parent
17640
+ });
17641
+ }
17328
17642
  }
17329
17643
  if (parent.typ == exports.EnumToken.BinaryExpressionTokenType) {
17330
17644
  if (parent.l == value) {
@@ -17335,14 +17649,12 @@
17335
17649
  }
17336
17650
  }
17337
17651
  else {
17338
- // @ts-ignore
17339
17652
  const target = 'val' in parent && Array.isArray(parent.val) ? parent.val : parent.chi;
17340
17653
  // @ts-ignore
17341
17654
  const index = target.indexOf(value);
17342
17655
  if (index == -1) {
17343
17656
  return;
17344
17657
  }
17345
- // @ts-ignore
17346
17658
  target.splice(index, 1, ...(Array.isArray(replacement) ? replacement : [replacement]));
17347
17659
  }
17348
17660
  }
@@ -17395,6 +17707,8 @@
17395
17707
  const stats = {
17396
17708
  src: options.src ?? '',
17397
17709
  bytesIn: 0,
17710
+ nodesCount: 0,
17711
+ tokensCount: 0,
17398
17712
  importedBytesIn: 0,
17399
17713
  parse: `0ms`,
17400
17714
  minify: `0ms`,
@@ -17423,24 +17737,117 @@
17423
17737
  src: ''
17424
17738
  };
17425
17739
  }
17426
- let item;
17427
- let node;
17740
+ let valuesHandlers;
17741
+ let preValuesHandlers;
17742
+ let postValuesHandlers;
17743
+ let preVisitorsHandlersMap;
17744
+ let visitorsHandlersMap;
17745
+ let postVisitorsHandlersMap;
17428
17746
  const rawTokens = [];
17429
17747
  const imports = [];
17748
+ let item;
17749
+ let node;
17430
17750
  // @ts-ignore ignore error
17431
17751
  let isAsync = typeof iter[Symbol.asyncIterator] === 'function';
17432
- while (item = isAsync ? (await iter.next()).value : iter.next().value) {
17433
- stats.bytesIn = item.bytesIn;
17434
- rawTokens.push(item);
17435
- if (item.hint != null && BadTokensTypes.includes(item.hint)) {
17436
- const node = getTokenType(item.token, item.hint);
17437
- errors.push({
17438
- action: 'drop',
17439
- message: 'Bad token',
17440
- syntax: null,
17441
- node,
17442
- location: {
17443
- src,
17752
+ if (options.visitor != null) {
17753
+ valuesHandlers = new Map;
17754
+ preValuesHandlers = new Map;
17755
+ postValuesHandlers = new Map;
17756
+ preVisitorsHandlersMap = new Map;
17757
+ visitorsHandlersMap = new Map;
17758
+ postVisitorsHandlersMap = new Map;
17759
+ const visitors = Object.entries(options.visitor);
17760
+ let key;
17761
+ let value;
17762
+ let i;
17763
+ for (i = 0; i < visitors.length; i++) {
17764
+ key = visitors[i][0];
17765
+ value = visitors[i][1];
17766
+ if (Number.isInteger(+key)) {
17767
+ visitors.splice(i + 1, 0, ...Object.entries(value));
17768
+ continue;
17769
+ }
17770
+ if (Array.isArray(value)) {
17771
+ // @ts-ignore
17772
+ visitors.splice(i + 1, 0, ...value.map((item) => [key, item]));
17773
+ continue;
17774
+ }
17775
+ if (key in exports.EnumToken) {
17776
+ if (typeof value == 'function') {
17777
+ if (!valuesHandlers.has(exports.EnumToken[key])) {
17778
+ valuesHandlers.set(exports.EnumToken[key], []);
17779
+ }
17780
+ valuesHandlers.get(exports.EnumToken[key]).push(value);
17781
+ }
17782
+ else if (typeof value == 'object' && 'type' in value && 'handler' in value && value.type in exports.WalkerEvent) {
17783
+ if (value.type == exports.WalkerEvent.Enter) {
17784
+ if (!preValuesHandlers.has(exports.EnumToken[key])) {
17785
+ preValuesHandlers.set(exports.EnumToken[key], []);
17786
+ }
17787
+ preValuesHandlers.get(exports.EnumToken[key]).push(value.handler);
17788
+ }
17789
+ else if (value.type == exports.WalkerEvent.Leave) {
17790
+ if (!postValuesHandlers.has(exports.EnumToken[key])) {
17791
+ postValuesHandlers.set(exports.EnumToken[key], []);
17792
+ }
17793
+ postValuesHandlers.get(exports.EnumToken[key]).push(value.handler);
17794
+ }
17795
+ }
17796
+ else {
17797
+ errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
17798
+ }
17799
+ }
17800
+ else if (['Declaration', 'Rule', 'AtRule', 'KeyframesRule', 'KeyframesAtRule'].includes(key)) {
17801
+ if (typeof value == 'function') {
17802
+ if (!visitorsHandlersMap.has(key)) {
17803
+ visitorsHandlersMap.set(key, []);
17804
+ }
17805
+ visitorsHandlersMap.get(key).push(value);
17806
+ }
17807
+ else if (typeof value == 'object') {
17808
+ if ('type' in value && 'handler' in value && value.type in exports.WalkerEvent) {
17809
+ if (value.type == exports.WalkerEvent.Enter) {
17810
+ if (!preVisitorsHandlersMap.has(key)) {
17811
+ preVisitorsHandlersMap.set(key, []);
17812
+ }
17813
+ preVisitorsHandlersMap.get(key).push(value.handler);
17814
+ }
17815
+ else if (value.type == exports.WalkerEvent.Leave) {
17816
+ if (!postVisitorsHandlersMap.has(key)) {
17817
+ postVisitorsHandlersMap.set(key, []);
17818
+ }
17819
+ postVisitorsHandlersMap.get(key).push(value.handler);
17820
+ }
17821
+ }
17822
+ else {
17823
+ if (!visitorsHandlersMap.has(key)) {
17824
+ visitorsHandlersMap.set(key, []);
17825
+ }
17826
+ visitorsHandlersMap.get(key).push(value);
17827
+ }
17828
+ }
17829
+ else {
17830
+ errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
17831
+ }
17832
+ }
17833
+ else {
17834
+ errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
17835
+ }
17836
+ }
17837
+ }
17838
+ while (item = isAsync ? (await iter.next()).value : iter.next().value) {
17839
+ stats.bytesIn = item.bytesIn;
17840
+ stats.tokensCount++;
17841
+ rawTokens.push(item);
17842
+ if (item.hint != null && BadTokensTypes.includes(item.hint)) {
17843
+ const node = getTokenType(item.token, item.hint);
17844
+ errors.push({
17845
+ action: 'drop',
17846
+ message: 'Bad token',
17847
+ syntax: null,
17848
+ node,
17849
+ location: {
17850
+ src,
17444
17851
  sta: item.sta,
17445
17852
  end: item.end
17446
17853
  }
@@ -17458,7 +17865,7 @@
17458
17865
  ast.loc.end = item.end;
17459
17866
  }
17460
17867
  if (item.token == ';' || item.token == '{') {
17461
- node = parseNode(tokens, context, options, errors, src, map, rawTokens);
17868
+ node = parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
17462
17869
  rawTokens.length = 0;
17463
17870
  if (node != null) {
17464
17871
  if ('chi' in node) {
@@ -17502,7 +17909,7 @@
17502
17909
  map = new Map;
17503
17910
  }
17504
17911
  else if (item.token == '}') {
17505
- parseNode(tokens, context, options, errors, src, map, rawTokens);
17912
+ parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
17506
17913
  rawTokens.length = 0;
17507
17914
  if (context.loc != null) {
17508
17915
  context.loc.end = item.end;
@@ -17523,7 +17930,7 @@
17523
17930
  }
17524
17931
  }
17525
17932
  if (tokens.length > 0) {
17526
- node = parseNode(tokens, context, options, errors, src, map, rawTokens);
17933
+ node = parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
17527
17934
  rawTokens.length = 0;
17528
17935
  if (node != null) {
17529
17936
  if (node.typ == exports.EnumToken.AtRuleNodeType && node.nam == 'import') {
@@ -17586,228 +17993,153 @@
17586
17993
  if (options.expandNestingRules) {
17587
17994
  ast = expand(ast);
17588
17995
  }
17589
- const valuesHandlers = new Map;
17590
- const preValuesHandlers = new Map;
17591
- const postValuesHandlers = new Map;
17592
- const preVisitorsHandlersMap = new Map;
17593
- const visitorsHandlersMap = new Map;
17594
- const postVisitorsHandlersMap = new Map;
17595
- const allValuesHandlers = [];
17996
+ let replacement;
17997
+ let callable;
17596
17998
  if (options.visitor != null) {
17597
- for (const [key, value] of Object.entries(options.visitor)) {
17598
- if (key in exports.EnumToken) {
17599
- if (typeof value == 'function') {
17600
- valuesHandlers.set(exports.EnumToken[key], value);
17601
- }
17602
- else if (typeof value == 'object' && 'type' in value && 'handler' in value && value.type in exports.WalkerValueEvent) {
17603
- if (exports.WalkerValueEvent[value.type] == exports.WalkerValueEvent.Enter) {
17604
- preValuesHandlers.set(exports.EnumToken[key], value.handler);
17999
+ for (const result of walk(ast)) {
18000
+ if (valuesHandlers.size > 0 || preVisitorsHandlersMap.size > 0 || visitorsHandlersMap.size > 0 || postVisitorsHandlersMap.size > 0) {
18001
+ if ((result.node.typ == exports.EnumToken.DeclarationNodeType &&
18002
+ (preVisitorsHandlersMap.has('Declaration') || visitorsHandlersMap.has('Declaration') || postVisitorsHandlersMap.has('Declaration'))) ||
18003
+ (result.node.typ == exports.EnumToken.AtRuleNodeType && (preVisitorsHandlersMap.has('AtRule') || visitorsHandlersMap.has('AtRule') || postVisitorsHandlersMap.has('AtRule'))) ||
18004
+ (result.node.typ == exports.EnumToken.KeyframesAtRuleNodeType && (preVisitorsHandlersMap.has('KeyframesAtRule') || visitorsHandlersMap.has('KeyframesAtRule') || postVisitorsHandlersMap.has('KeyframesAtRule')))) {
18005
+ const handlers = [];
18006
+ const key = result.node.typ == exports.EnumToken.DeclarationNodeType ? 'Declaration' : result.node.typ == exports.EnumToken.AtRuleNodeType ? 'AtRule' : 'KeyframesAtRule';
18007
+ if (preVisitorsHandlersMap.has(key)) {
18008
+ // @ts-ignore
18009
+ handlers.push(...preVisitorsHandlersMap.get(key));
17605
18010
  }
17606
- else if (exports.WalkerValueEvent[value.type] == exports.WalkerValueEvent.Leave) {
17607
- postValuesHandlers.set(exports.EnumToken[key], value.handler);
18011
+ if (visitorsHandlersMap.has(key)) {
18012
+ // @ts-ignore
18013
+ handlers.push(...visitorsHandlersMap.get(key));
17608
18014
  }
17609
- }
17610
- else {
17611
- console.warn(`doParse: visitor.${key} is not a valid key name`);
17612
- }
17613
- }
17614
- else if (['Declaration', 'Rule', 'AtRule', 'KeyframesRule', 'KeyframesAtRule'].includes(key)) {
17615
- if (typeof value == 'function') {
17616
- visitorsHandlersMap.set(key, value);
17617
- }
17618
- else if (typeof value == 'object') {
17619
- if ('type' in value && 'handler' in value && value.type in exports.WalkerValueEvent) {
17620
- if (exports.WalkerValueEvent[value.type] == exports.WalkerValueEvent.Enter) {
17621
- preVisitorsHandlersMap.set(key, value.handler);
18015
+ if (postVisitorsHandlersMap.has(key)) {
18016
+ // @ts-ignore
18017
+ handlers.push(...postVisitorsHandlersMap.get(key));
18018
+ }
18019
+ let node = result.node;
18020
+ for (const handler of handlers) {
18021
+ callable = typeof handler == 'function' ? handler : handler[normalizeVisitorKeyName(node.typ == exports.EnumToken.DeclarationNodeType || node.typ == exports.EnumToken.AtRuleNodeType ? node.nam : node.val)];
18022
+ if (callable == null) {
18023
+ continue;
17622
18024
  }
17623
- else if (exports.WalkerValueEvent[value.type] == exports.WalkerValueEvent.Leave) {
17624
- postVisitorsHandlersMap.set(key, value.handler);
18025
+ replacement = callable(node, result.parent);
18026
+ if (replacement == null) {
18027
+ continue;
18028
+ }
18029
+ isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
18030
+ if (replacement) {
18031
+ replacement = await replacement;
18032
+ }
18033
+ if (replacement == null || replacement == node) {
18034
+ continue;
18035
+ }
18036
+ // @ts-ignore
18037
+ node = replacement;
18038
+ //
18039
+ if (Array.isArray(node)) {
18040
+ break;
17625
18041
  }
17626
18042
  }
17627
- else {
17628
- visitorsHandlersMap.set(key, value);
17629
- }
17630
- }
17631
- else {
17632
- console.warn(`doParse: visitor.${key} is not a valid key name`);
17633
- }
17634
- }
17635
- else {
17636
- console.warn(`doParse: visitor.${key} is not a valid key name`);
17637
- }
17638
- }
17639
- if (preValuesHandlers.size > 0) {
17640
- allValuesHandlers.push(preValuesHandlers);
17641
- }
17642
- if (valuesHandlers.size > 0) {
17643
- allValuesHandlers.push(valuesHandlers);
17644
- }
17645
- if (postValuesHandlers.size > 0) {
17646
- allValuesHandlers.push(postValuesHandlers);
17647
- }
17648
- }
17649
- for (const result of walk(ast)) {
17650
- // if (result.parent != null && !isNodeAllowedInContext(result.node, result.parent as AstNode)) {
17651
- //
17652
- // errors.push({
17653
- // action: 'drop',
17654
- // 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'` : ''}`,
17655
- // // @ts-ignore
17656
- // location: result.node.loc ?? map.get(result.node ) ?? null
17657
- // });
17658
- //
17659
- // // @ts-ignore
17660
- // removeNode(result.node, result.parent as AstNode);
17661
- // continue;
17662
- // }
17663
- if (allValuesHandlers.length > 0 || preVisitorsHandlersMap.size > 0 || visitorsHandlersMap.size > 0 || postVisitorsHandlersMap.size > 0) {
17664
- if ((result.node.typ == exports.EnumToken.DeclarationNodeType &&
17665
- (preVisitorsHandlersMap.has('Declaration') || visitorsHandlersMap.has('Declaration') || postVisitorsHandlersMap.has('Declaration'))) ||
17666
- (result.node.typ == exports.EnumToken.AtRuleNodeType && (preVisitorsHandlersMap.has('AtRule') || visitorsHandlersMap.has('AtRule') || postVisitorsHandlersMap.has('AtRule'))) ||
17667
- (result.node.typ == exports.EnumToken.KeyframesAtRuleNodeType && (preVisitorsHandlersMap.has('KeyframesAtRule') || visitorsHandlersMap.has('KeyframesAtRule') || postVisitorsHandlersMap.has('KeyframesAtRule')))) {
17668
- const handlers = [];
17669
- const key = result.node.typ == exports.EnumToken.DeclarationNodeType ? 'Declaration' : result.node.typ == exports.EnumToken.AtRuleNodeType ? 'AtRule' : 'KeyframesAtRule';
17670
- if (preVisitorsHandlersMap.has(key)) {
17671
- // @ts-ignore
17672
- handlers.push(preVisitorsHandlersMap.get(key));
17673
- }
17674
- if (visitorsHandlersMap.has(key)) {
17675
- // @ts-ignore
17676
- handlers.push(visitorsHandlersMap.get(key));
17677
- }
17678
- if (postVisitorsHandlersMap.has(key)) {
17679
- // @ts-ignore
17680
- handlers.push(postVisitorsHandlersMap.get(key));
17681
- }
17682
- let callable;
17683
- let node = result.node;
17684
- for (const handler of handlers) {
17685
- callable = typeof handler == 'function' ? handler : handler[normalizeVisitorKeyName(node.typ == exports.EnumToken.DeclarationNodeType || node.typ == exports.EnumToken.AtRuleNodeType ? node.nam : node.val)];
17686
- if (callable == null) {
17687
- continue;
17688
- }
17689
- let replacement = callable(node, result.parent);
17690
- if (replacement == null) {
17691
- continue;
17692
- }
17693
- isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
17694
- if (replacement) {
17695
- replacement = await replacement;
17696
- }
17697
- if (replacement == null || replacement == node) {
17698
- continue;
17699
- }
17700
- // @ts-ignore
17701
- node = replacement;
17702
- //
17703
- if (Array.isArray(node)) {
17704
- break;
18043
+ if (node != result.node) {
18044
+ // @ts-ignore
18045
+ replaceToken(result.parent, result.node, node);
17705
18046
  }
17706
18047
  }
17707
- if (node != result.node) {
17708
- // @ts-ignore
17709
- replaceToken(result.parent, result.node, node);
17710
- }
17711
- }
17712
- else if ((result.node.typ == exports.EnumToken.RuleNodeType && (preVisitorsHandlersMap.has('Rule') || visitorsHandlersMap.has('Rule') || postVisitorsHandlersMap.has('Rule'))) ||
17713
- (result.node.typ == exports.EnumToken.KeyFramesRuleNodeType && (preVisitorsHandlersMap.has('KeyframesRule') || visitorsHandlersMap.has('KeyframesRule') || postVisitorsHandlersMap.has('KeyframesRule')))) {
17714
- const handlers = [];
17715
- const key = result.node.typ == exports.EnumToken.RuleNodeType ? 'Rule' : 'KeyframesRule';
17716
- if (preVisitorsHandlersMap.has(key)) {
17717
- // @ts-ignore
17718
- handlers.push(preVisitorsHandlersMap.get(key));
17719
- }
17720
- if (visitorsHandlersMap.has(key)) {
17721
- // @ts-ignore
17722
- handlers.push(visitorsHandlersMap.get(key));
17723
- }
17724
- if (postVisitorsHandlersMap.has(key)) {
17725
- // @ts-ignore
17726
- handlers.push(postVisitorsHandlersMap.get(key));
17727
- }
17728
- let node = result.node;
17729
- for (const callable of handlers) {
17730
- // @ts-ignore
17731
- let replacement = callable(node, result.parent);
17732
- if (replacement == null) {
17733
- continue;
18048
+ else if ((result.node.typ == exports.EnumToken.RuleNodeType && (preVisitorsHandlersMap.has('Rule') || visitorsHandlersMap.has('Rule') || postVisitorsHandlersMap.has('Rule'))) ||
18049
+ (result.node.typ == exports.EnumToken.KeyFramesRuleNodeType && (preVisitorsHandlersMap.has('KeyframesRule') || visitorsHandlersMap.has('KeyframesRule') || postVisitorsHandlersMap.has('KeyframesRule')))) {
18050
+ const handlers = [];
18051
+ const key = result.node.typ == exports.EnumToken.RuleNodeType ? 'Rule' : 'KeyframesRule';
18052
+ if (preVisitorsHandlersMap.has(key)) {
18053
+ handlers.push(...preVisitorsHandlersMap.get(key));
17734
18054
  }
17735
- isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
17736
- if (replacement) {
17737
- replacement = await replacement;
18055
+ if (visitorsHandlersMap.has(key)) {
18056
+ handlers.push(...visitorsHandlersMap.get(key));
17738
18057
  }
17739
- if (replacement == null || replacement == node) {
17740
- continue;
17741
- }
17742
- // @ts-ignore
17743
- node = replacement;
17744
- //
17745
- if (Array.isArray(node)) {
17746
- break;
18058
+ if (postVisitorsHandlersMap.has(key)) {
18059
+ handlers.push(...postVisitorsHandlersMap.get(key));
17747
18060
  }
17748
- }
17749
- // @ts-ignore
17750
- if (node != result.node) {
17751
- // @ts-ignore
17752
- replaceToken(result.parent, result.node, node);
17753
- }
17754
- }
17755
- else if (allValuesHandlers.length > 0) {
17756
- let callable;
17757
- let node = null;
17758
- node = result.node;
17759
- for (const valueHandler of allValuesHandlers) {
17760
- if (valueHandler.has(node.typ)) {
17761
- callable = valueHandler.get(node.typ);
17762
- let replacement = callable(node, result.parent);
18061
+ let node = result.node;
18062
+ for (const callable of handlers) {
18063
+ replacement = callable(node, result.parent);
17763
18064
  if (replacement == null) {
17764
18065
  continue;
17765
18066
  }
17766
18067
  isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
17767
- if (isAsync) {
18068
+ if (replacement) {
17768
18069
  replacement = await replacement;
17769
18070
  }
17770
- if (replacement != null && replacement != node) {
17771
- node = replacement;
18071
+ if (replacement == null || replacement == node) {
18072
+ continue;
18073
+ }
18074
+ // @ts-ignore
18075
+ node = replacement;
18076
+ //
18077
+ if (Array.isArray(node)) {
18078
+ break;
17772
18079
  }
17773
18080
  }
17774
- }
17775
- if (node != result.node) {
17776
18081
  // @ts-ignore
17777
- replaceToken(result.parent, value, node);
17778
- }
17779
- const tokens = 'tokens' in result.node ? result.node.tokens : [];
17780
- if ('val' in result.node && Array.isArray(result.node.val)) {
17781
- tokens.push(...result.node.val);
17782
- }
17783
- if (tokens.length == 0) {
17784
- continue;
18082
+ if (node != result.node) {
18083
+ // @ts-ignore
18084
+ replaceToken(result.parent, result.node, node);
18085
+ }
17785
18086
  }
17786
- for (const { value, parent, root } of walkValues(tokens, result.node)) {
17787
- node = value;
17788
- for (const valueHandler of allValuesHandlers) {
17789
- if (valueHandler.has(node.typ)) {
17790
- callable = valueHandler.get(node.typ);
17791
- let result = callable(node, parent, root);
17792
- if (result == null) {
18087
+ else if (valuesHandlers.size > 0) {
18088
+ let node = null;
18089
+ node = result.node;
18090
+ if (valuesHandlers.has(node.typ)) {
18091
+ for (const valueHandler of valuesHandlers.get(node.typ)) {
18092
+ callable = valueHandler;
18093
+ replacement = callable(node, result.parent);
18094
+ if (replacement == null) {
17793
18095
  continue;
17794
18096
  }
17795
- isAsync = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction';
18097
+ isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
17796
18098
  if (isAsync) {
17797
- result = await result;
17798
- }
17799
- if (result != null && result != node) {
17800
- node = result;
18099
+ replacement = await replacement;
17801
18100
  }
17802
- //
17803
- if (Array.isArray(node)) {
17804
- break;
18101
+ if (replacement != null && replacement != node) {
18102
+ node = replacement;
17805
18103
  }
17806
18104
  }
17807
18105
  }
17808
- if (node != value) {
18106
+ if (node != result.node) {
17809
18107
  // @ts-ignore
17810
- replaceToken(parent, value, node);
18108
+ replaceToken(result.parent, value, node);
18109
+ }
18110
+ const tokens = 'tokens' in result.node ? result.node.tokens : [];
18111
+ if ('val' in result.node && Array.isArray(result.node.val)) {
18112
+ tokens.push(...result.node.val);
18113
+ }
18114
+ if (tokens.length == 0) {
18115
+ continue;
18116
+ }
18117
+ for (const { value, parent, root } of walkValues(tokens, result.node)) {
18118
+ node = value;
18119
+ if (valuesHandlers.has(node.typ)) {
18120
+ for (const valueHandler of valuesHandlers.get(node.typ)) {
18121
+ callable = valueHandler;
18122
+ let result = callable(node, parent, root);
18123
+ if (result == null) {
18124
+ continue;
18125
+ }
18126
+ isAsync = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction';
18127
+ if (isAsync) {
18128
+ result = await result;
18129
+ }
18130
+ if (result != null && result != node) {
18131
+ node = result;
18132
+ }
18133
+ //
18134
+ if (Array.isArray(node)) {
18135
+ break;
18136
+ }
18137
+ }
18138
+ }
18139
+ if (node != value) {
18140
+ // @ts-ignore
18141
+ replaceToken(parent, value, node);
18142
+ }
17811
18143
  }
17812
18144
  }
17813
18145
  }
@@ -17847,7 +18179,7 @@
17847
18179
  }
17848
18180
  return null;
17849
18181
  }
17850
- function parseNode(results, context, options, errors, src, map, rawTokens) {
18182
+ function parseNode(results, context, options, errors, src, map, rawTokens, stats) {
17851
18183
  let tokens = [];
17852
18184
  for (const t of results) {
17853
18185
  const node = getTokenType(t.token, t.hint);
@@ -17870,9 +18202,12 @@
17870
18202
  }
17871
18203
  loc = location;
17872
18204
  context.chi.push(tokens[i]);
17873
- if (options.sourcemap) {
17874
- tokens[i].loc = loc;
17875
- }
18205
+ stats.nodesCount++;
18206
+ Object.defineProperty(tokens[i], 'loc', {
18207
+ ...definedPropertySettings,
18208
+ value: loc,
18209
+ enumerable: options.sourcemap !== false
18210
+ });
17876
18211
  }
17877
18212
  else if (tokens[i].typ != exports.EnumToken.WhitespaceTokenType) {
17878
18213
  break;
@@ -18013,10 +18348,10 @@
18013
18348
  }
18014
18349
  }
18015
18350
  const t = parseAtRulePrelude(parseTokens(tokens, { minify: options.minify }), atRule);
18016
- const raw = t.reduce((acc, curr) => {
18017
- acc.push(renderToken(curr, { removeComments: true, convertColor: false }));
18018
- return acc;
18019
- }, []);
18351
+ const raw = [];
18352
+ for (const curr of t) {
18353
+ raw.push(renderToken(curr, { removeComments: true, convertColor: false }));
18354
+ }
18020
18355
  const nam = renderToken(atRule, { removeComments: true });
18021
18356
  // @ts-ignore
18022
18357
  const node = {
@@ -18032,10 +18367,12 @@
18032
18367
  node.chi = [];
18033
18368
  }
18034
18369
  loc = map.get(atRule);
18035
- if (options.sourcemap) {
18036
- node.loc = loc;
18037
- node.loc.end = { ...map.get(delim).end };
18038
- }
18370
+ Object.defineProperty(node, 'loc', {
18371
+ ...definedPropertySettings,
18372
+ value: loc,
18373
+ enumerable: options.sourcemap !== false
18374
+ });
18375
+ node.loc.end = { ...map.get(delim).end };
18039
18376
  let isValid = true;
18040
18377
  if (node.nam == 'else') {
18041
18378
  const prev = getLastNode(context);
@@ -18049,20 +18386,31 @@
18049
18386
  }
18050
18387
  }
18051
18388
  // @ts-ignore
18052
- const valid = options.validation == exports.ValidationLevel.None ? {
18389
+ const skipValidate = (options.validation & exports.ValidationLevel.AtRule) == 0;
18390
+ const isAllowed = skipValidate || isNodeAllowedInContext(node, context);
18391
+ // @ts-ignore
18392
+ const valid = skipValidate ? {
18053
18393
  valid: SyntaxValidationResult.Valid,
18054
18394
  error: '',
18055
18395
  node,
18056
18396
  syntax: '@' + node.nam
18057
- } : isValid ? (node.typ == exports.EnumToken.KeyframesAtRuleNodeType ? validateAtRuleKeyframes(node) : validateAtRule(node, options, context)) : {
18397
+ } : !isAllowed ? {
18398
+ valid: SyntaxValidationResult.Drop,
18399
+ node,
18400
+ syntax: '@' + node.nam,
18401
+ 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)) : {
18058
18402
  valid: SyntaxValidationResult.Drop,
18059
18403
  node,
18060
18404
  syntax: '@' + node.nam,
18061
18405
  error: '@' + node.nam + ' not allowed here'};
18062
18406
  if (valid.valid == SyntaxValidationResult.Drop) {
18407
+ let message = '';
18408
+ for (const token of tokens) {
18409
+ message += renderToken(token, { minify: false });
18410
+ }
18063
18411
  errors.push({
18064
18412
  action: 'drop',
18065
- message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
18413
+ message: valid.error + ' - "' + message + '"',
18066
18414
  node,
18067
18415
  // @ts-ignore
18068
18416
  location: { src, ...(map.get(valid.node) ?? location) }
@@ -18071,13 +18419,17 @@
18071
18419
  node.typ = exports.EnumToken.InvalidAtRuleTokenType;
18072
18420
  }
18073
18421
  else {
18074
- node.val = node.tokens.reduce((acc, curr) => acc + renderToken(curr, {
18075
- minify: false,
18076
- convertColor: false,
18077
- removeComments: true
18078
- }), '');
18422
+ node.val = '';
18423
+ for (const token of node.tokens) {
18424
+ node.val += renderToken(token, {
18425
+ minify: false,
18426
+ convertColor: false,
18427
+ removeComments: true
18428
+ });
18429
+ }
18079
18430
  }
18080
18431
  context.chi.push(node);
18432
+ stats.nodesCount++;
18081
18433
  Object.defineProperties(node, {
18082
18434
  parent: { ...definedPropertySettings, value: context },
18083
18435
  validSyntax: { ...definedPropertySettings, value: valid.valid == SyntaxValidationResult.Valid }
@@ -18175,16 +18527,23 @@
18175
18527
  value: tokens.slice()
18176
18528
  });
18177
18529
  loc = location;
18178
- if (options.sourcemap) {
18179
- node.loc = loc;
18180
- }
18181
- // @ts-ignore
18530
+ Object.defineProperty(node, 'loc', {
18531
+ ...definedPropertySettings,
18532
+ value: loc,
18533
+ enumerable: options.sourcemap !== false
18534
+ });
18182
18535
  context.chi.push(node);
18183
18536
  Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: context });
18184
18537
  // @ts-ignore
18185
- const valid = options.validation == exports.ValidationLevel.None ? {
18538
+ const skipValidate = (options.validation & exports.ValidationLevel.Selector) == 0;
18539
+ const isAllowed = skipValidate || isNodeAllowedInContext(node, context);
18540
+ // @ts-ignore
18541
+ const valid = skipValidate ? {
18186
18542
  valid: SyntaxValidationResult.Valid,
18187
18543
  error: null
18544
+ } : !isAllowed ? {
18545
+ valid: SyntaxValidationResult.Drop,
18546
+ 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'` : ''}`
18188
18547
  } : ruleType == exports.EnumToken.KeyFramesRuleNodeType ? validateKeyframeSelector(tokens) : validateSelector(tokens, options, context);
18189
18548
  if (valid.valid != SyntaxValidationResult.Valid) {
18190
18549
  // @ts-ignore
@@ -18294,11 +18653,13 @@
18294
18653
  nam,
18295
18654
  val: []
18296
18655
  };
18297
- if (options.sourcemap) {
18298
- node.loc = location;
18299
- node.loc.end = { ...map.get(delim).end };
18300
- }
18656
+ Object.defineProperty(node, 'loc', {
18657
+ ...definedPropertySettings,
18658
+ value: location,
18659
+ enumerable: options.sourcemap !== false
18660
+ });
18301
18661
  context.chi.push(node);
18662
+ stats.nodesCount++;
18302
18663
  }
18303
18664
  return null;
18304
18665
  }
@@ -18322,22 +18683,31 @@
18322
18683
  nam,
18323
18684
  val: value
18324
18685
  };
18325
- if (options.sourcemap) {
18326
- node.loc = location;
18327
- node.loc.end = { ...map.get(delim).end };
18328
- }
18686
+ Object.defineProperty(node, 'loc', {
18687
+ ...definedPropertySettings,
18688
+ value: location,
18689
+ enumerable: options.sourcemap !== false
18690
+ });
18691
+ node.loc.end = { ...map.get(delim).end };
18329
18692
  // do not allow declarations in style sheets
18330
18693
  if (context.typ == exports.EnumToken.StyleSheetNodeType && options.lenient) {
18331
- // @ts-ignore
18332
- node.typ = exports.EnumToken.InvalidDeclarationNodeType;
18694
+ Object.assign(node, { typ: exports.EnumToken.InvalidDeclarationNodeType });
18333
18695
  context.chi.push(node);
18696
+ stats.nodesCount++;
18334
18697
  return null;
18335
18698
  }
18336
18699
  const result = parseDeclarationNode(node, errors, location);
18337
18700
  Object.defineProperty(result, 'parent', { ...definedPropertySettings, value: context });
18338
18701
  if (result != null) {
18339
- if (options.validation == exports.ValidationLevel.All) {
18340
- const valid = evaluateSyntax(result, options);
18702
+ if (options.validation & exports.ValidationLevel.Declaration) {
18703
+ const isAllowed = isNodeAllowedInContext(node, context);
18704
+ // @ts-ignore
18705
+ const valid = !isAllowed ? {
18706
+ valid: SyntaxValidationResult.Drop,
18707
+ error: `${exports.EnumToken[node.typ]} not allowed in context${context.typ == exports.EnumToken.AtRuleNodeType ? ` '@${context.nam}'` : context.typ == exports.EnumToken.StyleSheetNodeType ? ` 'stylesheet'` : ''}`,
18708
+ node,
18709
+ syntax: null
18710
+ } : evaluateSyntax(result, context, options);
18341
18711
  Object.defineProperty(result, 'validSyntax', {
18342
18712
  ...definedPropertySettings,
18343
18713
  value: valid.valid == SyntaxValidationResult.Valid
@@ -18353,11 +18723,11 @@
18353
18723
  if (!options.lenient) {
18354
18724
  return null;
18355
18725
  }
18356
- // @ts-ignore
18357
- node.typ = exports.EnumToken.InvalidDeclarationNodeType;
18726
+ Object.assign(node, { typ: exports.EnumToken.InvalidDeclarationNodeType });
18358
18727
  }
18359
18728
  }
18360
18729
  context.chi.push(result);
18730
+ stats.nodesCount++;
18361
18731
  }
18362
18732
  return null;
18363
18733
  }
@@ -18369,7 +18739,6 @@
18369
18739
  * @param atRule
18370
18740
  */
18371
18741
  function parseAtRulePrelude(tokens, atRule) {
18372
- // @ts-ignore
18373
18742
  for (const { value, parent } of walkValues(tokens, null, null, true)) {
18374
18743
  if (value.typ == exports.EnumToken.CommentTokenType ||
18375
18744
  value.typ == exports.EnumToken.WhitespaceTokenType ||
@@ -18405,16 +18774,14 @@
18405
18774
  }
18406
18775
  if (atRule.val == 'page' && value.typ == exports.EnumToken.PseudoClassTokenType) {
18407
18776
  if ([':left', ':right', ':first', ':blank'].includes(value.val)) {
18408
- // @ts-ignore
18409
- value.typ = exports.EnumToken.PseudoPageTokenType;
18777
+ Object.assign(value, { typ: exports.EnumToken.PseudoPageTokenType });
18410
18778
  }
18411
18779
  }
18412
18780
  if (atRule.val == 'layer') {
18413
18781
  if (parent == null && value.typ == exports.EnumToken.LiteralTokenType) {
18414
18782
  if (value.val.charAt(0) == '.') {
18415
18783
  if (isIdent(value.val.slice(1))) {
18416
- // @ts-ignore
18417
- value.typ = exports.EnumToken.ClassSelectorTokenType;
18784
+ Object.assign(value, { typ: exports.EnumToken.ClassSelectorTokenType });
18418
18785
  }
18419
18786
  }
18420
18787
  }
@@ -18423,8 +18790,7 @@
18423
18790
  if (value.typ == exports.EnumToken.IdenTokenType) {
18424
18791
  if (parent == null && mediaTypes.some((t) => {
18425
18792
  if (val === t) {
18426
- // @ts-ignore
18427
- value.typ = exports.EnumToken.MediaFeatureTokenType;
18793
+ Object.assign(value, { typ: exports.EnumToken.MediaFeatureTokenType });
18428
18794
  return true;
18429
18795
  }
18430
18796
  return false;
@@ -18432,18 +18798,15 @@
18432
18798
  continue;
18433
18799
  }
18434
18800
  if (value.typ == exports.EnumToken.IdenTokenType && 'and' === val) {
18435
- // @ts-ignore
18436
- value.typ = exports.EnumToken.MediaFeatureAndTokenType;
18801
+ Object.assign(value, { typ: exports.EnumToken.MediaFeatureAndTokenType });
18437
18802
  continue;
18438
18803
  }
18439
18804
  if (value.typ == exports.EnumToken.IdenTokenType && 'or' === val) {
18440
- // @ts-ignore
18441
- value.typ = exports.EnumToken.MediaFeatureOrTokenType;
18805
+ Object.assign(value, { typ: exports.EnumToken.MediaFeatureOrTokenType });
18442
18806
  continue;
18443
18807
  }
18444
18808
  if (value.typ == exports.EnumToken.IdenTokenType &&
18445
18809
  ['not', 'only'].some((t) => val === t)) {
18446
- // @ts-ignore
18447
18810
  const array = parent?.chi ?? tokens;
18448
18811
  const startIndex = array.indexOf(value);
18449
18812
  let index = startIndex + 1;
@@ -18488,12 +18851,15 @@
18488
18851
  if (value.chi[i].typ == exports.EnumToken.CommentTokenType || value.chi[i].typ == exports.EnumToken.WhitespaceTokenType) {
18489
18852
  continue;
18490
18853
  }
18491
- if (value.chi[i].typ == exports.EnumToken.LiteralTokenType && value.chi[i].val.startsWith(':') && isDimension(value.chi[i].val.slice(1))) {
18492
- value.chi.splice(i, 1, {
18493
- typ: exports.EnumToken.ColonTokenType,
18494
- }, Object.assign(value.chi[i], parseDimension(value.chi[i].val.slice(1))));
18495
- i--;
18496
- continue;
18854
+ if (value.chi[i].typ == exports.EnumToken.LiteralTokenType && value.chi[i].val.startsWith(':')) {
18855
+ const dimension = parseDimension(value.chi[i].val.slice(1));
18856
+ if (dimension != null) {
18857
+ value.chi.splice(i, 1, {
18858
+ typ: exports.EnumToken.ColonTokenType,
18859
+ }, Object.assign(value.chi[i], dimension));
18860
+ i--;
18861
+ continue;
18862
+ }
18497
18863
  }
18498
18864
  if (nameIndex != -1 && value.chi[i].typ == exports.EnumToken.PseudoClassTokenType) {
18499
18865
  value.chi.splice(i, 1, {
@@ -18520,11 +18886,10 @@
18520
18886
  const val = value.chi.splice(valueIndex, 1)[0];
18521
18887
  const node = value.chi.splice(nameIndex, 1)[0];
18522
18888
  // 'background'
18523
- // @ts-ignore
18524
18889
  if (node.typ == exports.EnumToken.ColorTokenType && node.kin == exports.ColorType.DPSYS) {
18890
+ Object.assign(node, { typ: exports.EnumToken.IdenTokenType });
18525
18891
  // @ts-ignore
18526
18892
  delete node.kin;
18527
- node.typ = exports.EnumToken.IdenTokenType;
18528
18893
  }
18529
18894
  while (value.chi[0]?.typ == exports.EnumToken.WhitespaceTokenType) {
18530
18895
  value.chi.shift();
@@ -18579,43 +18944,35 @@
18579
18944
  }
18580
18945
  if (parent == null) {
18581
18946
  if (value.typ == exports.EnumToken.GtTokenType) {
18582
- // @ts-ignore
18583
- value.typ = exports.EnumToken.ChildCombinatorTokenType;
18947
+ Object.assign(value, { typ: exports.EnumToken.ChildCombinatorTokenType });
18584
18948
  }
18585
18949
  else if (value.typ == exports.EnumToken.LiteralTokenType) {
18586
18950
  if (value.val.charAt(0) == '&') {
18587
- // @ts-ignore
18588
- value.typ = exports.EnumToken.NestingSelectorTokenType;
18951
+ Object.assign(value, { typ: exports.EnumToken.NestingSelectorTokenType });
18589
18952
  // @ts-ignore
18590
18953
  delete value.val;
18591
18954
  }
18592
18955
  else if (value.val.charAt(0) == '.') {
18593
18956
  if (!isIdent(value.val.slice(1))) {
18594
- // @ts-ignore
18595
- value.typ = exports.EnumToken.InvalidClassSelectorTokenType;
18957
+ Object.assign(value, { typ: exports.EnumToken.InvalidClassSelectorTokenType });
18596
18958
  }
18597
18959
  else {
18598
- // @ts-ignore
18599
- value.typ = exports.EnumToken.ClassSelectorTokenType;
18960
+ Object.assign(value, { typ: exports.EnumToken.ClassSelectorTokenType });
18600
18961
  }
18601
18962
  }
18602
18963
  if (['*', '>', '+', '~'].includes(value.val)) {
18603
18964
  switch (value.val) {
18604
18965
  case '*':
18605
- // @ts-ignore
18606
- value.typ = exports.EnumToken.UniversalSelectorTokenType;
18966
+ Object.assign(value, { typ: exports.EnumToken.UniversalSelectorTokenType });
18607
18967
  break;
18608
18968
  case '>':
18609
- // @ts-ignore
18610
- value.typ = exports.EnumToken.ChildCombinatorTokenType;
18969
+ Object.assign(value, { typ: exports.EnumToken.ChildCombinatorTokenType });
18611
18970
  break;
18612
18971
  case '+':
18613
- // @ts-ignore
18614
- value.typ = exports.EnumToken.NextSiblingCombinatorTokenType;
18972
+ Object.assign(value, { typ: exports.EnumToken.NextSiblingCombinatorTokenType });
18615
18973
  break;
18616
18974
  case '~':
18617
- // @ts-ignore
18618
- value.typ = exports.EnumToken.SubsequentSiblingCombinatorTokenType;
18975
+ Object.assign(value, { typ: exports.EnumToken.SubsequentSiblingCombinatorTokenType });
18619
18976
  break;
18620
18977
  }
18621
18978
  // @ts-ignore
@@ -18628,12 +18985,10 @@
18628
18985
  if (!isIdent(value.val.slice(1))) {
18629
18986
  continue;
18630
18987
  }
18631
- // @ts-ignore
18632
- value.typ = exports.EnumToken.HashTokenType;
18988
+ Object.assign(value, { typ: exports.EnumToken.HashTokenType });
18633
18989
  }
18634
18990
  else {
18635
- // @ts-ignore
18636
- value.typ = exports.EnumToken.IdenTokenType;
18991
+ Object.assign(value, { typ: exports.EnumToken.IdenTokenType });
18637
18992
  }
18638
18993
  // @ts-ignore
18639
18994
  delete value.kin;
@@ -18696,15 +19051,17 @@
18696
19051
  return acc;
18697
19052
  }
18698
19053
  const token = getTokenType(t.token, t.hint);
18699
- if (options.location) {
18700
- Object.assign(token, { loc: t.sta });
18701
- }
19054
+ Object.defineProperty(token, 'loc', {
19055
+ ...definedPropertySettings,
19056
+ value: { sta: t.sta },
19057
+ enumerable: options.location !== false
19058
+ });
18702
19059
  acc.push(token);
18703
19060
  return acc;
18704
19061
  }, []));
18705
19062
  }
18706
19063
  /**
18707
- * get token type from a string
19064
+ * get the token type from a string
18708
19065
  * @param val
18709
19066
  * @param hint
18710
19067
  */
@@ -18740,7 +19097,7 @@
18740
19097
  case '>':
18741
19098
  return { typ: exports.EnumToken.GtTokenType };
18742
19099
  }
18743
- if (isPseudo(val)) {
19100
+ if (val.charAt(0) == ':' && isPseudo(val)) {
18744
19101
  return val.endsWith('(') ? {
18745
19102
  typ: exports.EnumToken.PseudoClassFuncTokenType,
18746
19103
  val: val.slice(0, -1),
@@ -18757,13 +19114,13 @@
18757
19114
  val
18758
19115
  });
18759
19116
  }
18760
- if (isAtKeyword(val)) {
19117
+ if (val.charAt(0) == '@' && isAtKeyword(val)) {
18761
19118
  return {
18762
19119
  typ: exports.EnumToken.AtRuleTokenType,
18763
19120
  val: val.slice(1)
18764
19121
  };
18765
19122
  }
18766
- if (isFunction(val)) {
19123
+ if (val.endsWith('(') && isFunction(val)) {
18767
19124
  val = val.slice(0, -1);
18768
19125
  if (val == 'url') {
18769
19126
  return {
@@ -18811,15 +19168,12 @@
18811
19168
  val: +val.slice(0, -1)
18812
19169
  };
18813
19170
  }
18814
- if (isFlex(val)) {
18815
- return {
18816
- typ: exports.EnumToken.FlexTokenType,
18817
- val: +val.slice(0, -2)
18818
- };
18819
- }
18820
- if (isDimension(val)) {
18821
- return parseDimension(val);
19171
+ // if (isDimension(val)) {
19172
+ const dimension = parseDimension(val);
19173
+ if (dimension != null) {
19174
+ return dimension;
18822
19175
  }
19176
+ // }
18823
19177
  const v = val.toLowerCase();
18824
19178
  if (v == 'currentcolor' || v == 'transparent' || v in COLORS_NAMES) {
18825
19179
  return {
@@ -19228,28 +19582,28 @@
19228
19582
  */
19229
19583
  WalkerOptionEnum[WalkerOptionEnum["Stop"] = 2] = "Stop";
19230
19584
  /**
19231
- * ignore node and process children
19585
+ * ignore the current node and process its children
19232
19586
  */
19233
19587
  WalkerOptionEnum[WalkerOptionEnum["Children"] = 4] = "Children";
19234
19588
  /**
19235
- * ignore children
19589
+ * ignore the current node children
19236
19590
  */
19237
19591
  WalkerOptionEnum[WalkerOptionEnum["IgnoreChildren"] = 8] = "IgnoreChildren";
19238
19592
  })(exports.WalkerOptionEnum || (exports.WalkerOptionEnum = {}));
19239
19593
  /**
19240
19594
  * event types for the walkValues function
19241
19595
  */
19242
- exports.WalkerValueEvent = void 0;
19243
- (function (WalkerValueEvent) {
19596
+ exports.WalkerEvent = void 0;
19597
+ (function (WalkerEvent) {
19244
19598
  /**
19245
19599
  * enter node
19246
19600
  */
19247
- WalkerValueEvent[WalkerValueEvent["Enter"] = 1] = "Enter";
19601
+ WalkerEvent[WalkerEvent["Enter"] = 1] = "Enter";
19248
19602
  /**
19249
19603
  * leave node
19250
19604
  */
19251
- WalkerValueEvent[WalkerValueEvent["Leave"] = 2] = "Leave";
19252
- })(exports.WalkerValueEvent || (exports.WalkerValueEvent = {}));
19605
+ WalkerEvent[WalkerEvent["Leave"] = 2] = "Leave";
19606
+ })(exports.WalkerEvent || (exports.WalkerEvent = {}));
19253
19607
  /**
19254
19608
  * walk ast nodes
19255
19609
  * @param node initial node
@@ -19280,11 +19634,10 @@
19280
19634
  * }
19281
19635
  * ```
19282
19636
  *
19283
- * Using a filter to control the walk process:
19637
+ * Using a {@link filter} function to control the ast traversal. the filter function returns a value of type {@link WalkerOption}.
19284
19638
  *
19285
19639
  * ```ts
19286
- *
19287
- * import {walk} from '@tbela99/css-parser';
19640
+ * import {EnumToken, transform, walk, WalkerOptionEnum} from '@tbela99/css-parser';
19288
19641
  *
19289
19642
  * const css = `
19290
19643
  * body { color: color(from var(--base-color) display-p3 r calc(g + 0.24) calc(b + 0.15)); }
@@ -19300,17 +19653,28 @@
19300
19653
  * }
19301
19654
  * `;
19302
19655
  *
19303
- * for (const {node, parent, root} of walk(ast, (node) => {
19656
+ * function filter(node) {
19304
19657
  *
19305
19658
  * if (node.typ == EnumToken.AstRule && node.sel.includes('html')) {
19306
19659
  *
19307
19660
  * // skip the children of the current node
19308
19661
  * return WalkerOptionEnum.IgnoreChildren;
19309
19662
  * }
19310
- * })) {
19663
+ * }
19311
19664
  *
19312
- * // do something with node
19665
+ * const result = await transform(css);
19666
+ * for (const {node} of walk(result.ast, filter)) {
19667
+ *
19668
+ * console.error([EnumToken[node.typ]]);
19313
19669
  * }
19670
+ *
19671
+ * // [ "StyleSheetNodeType" ]
19672
+ * // [ "RuleNodeType" ]
19673
+ * // [ "DeclarationNodeType" ]
19674
+ * // [ "RuleNodeType" ]
19675
+ * // [ "DeclarationNodeType" ]
19676
+ * // [ "RuleNodeType" ]
19677
+ * // [ "DeclarationNodeType" ]
19314
19678
  * ```
19315
19679
  */
19316
19680
  function* walk(node, filter, reverse) {
@@ -19318,7 +19682,8 @@
19318
19682
  const root = node;
19319
19683
  const map = new Map;
19320
19684
  let isNumeric = false;
19321
- while ((node = parents.shift())) {
19685
+ let i = 0;
19686
+ while ((node = parents[i++])) {
19322
19687
  let option = null;
19323
19688
  if (filter != null) {
19324
19689
  option = filter(node);
@@ -19337,8 +19702,8 @@
19337
19702
  yield { node, parent: map.get(node), root };
19338
19703
  }
19339
19704
  if ('chi' in node && (!isNumeric || ((option & exports.WalkerOptionEnum.IgnoreChildren) === 0))) {
19340
- parents.unshift(...node.chi[reverse ? 'reverse' : 'slice']());
19341
- for (const child of node.chi.slice()) {
19705
+ parents.splice(i, 0, ...node.chi[reverse ? 'reverse' : 'slice']());
19706
+ for (const child of node.chi) {
19342
19707
  map.set(child, node);
19343
19708
  }
19344
19709
  }
@@ -19355,27 +19720,41 @@
19355
19720
  *
19356
19721
  * ```ts
19357
19722
  *
19358
- * import {EnumToken, walk} from '@tbela99/css-parser';
19723
+ * import {AstDeclaration, EnumToken, transform, walkValues} from '@tbela99/css-parser';
19359
19724
  *
19360
19725
  * const css = `
19361
19726
  * body { color: color(from var(--base-color) display-p3 r calc(g + 0.24) calc(b + 0.15)); }
19362
- *
19363
- * html,
19364
- * body {
19365
- * line-height: 1.474;
19366
- * }
19367
- *
19368
- * .ruler {
19369
- *
19370
- * height: 10px;
19371
- * }
19372
19727
  * `;
19373
19728
  *
19374
- * for (const {value} of walkValues(result.ast.chi[0].chi[0].val, null, null,true)) {
19729
+ * const result = await transform(css);
19730
+ * const declaration = result.ast.chi[0].chi[0] as AstDeclaration;
19731
+ *
19732
+ * // walk the node attribute's tokens in reverse order
19733
+ * for (const {value} of walkValues(declaration.val, null, null,true)) {
19375
19734
  *
19376
19735
  * console.error([EnumToken[value.typ], value.val]);
19377
19736
  * }
19378
19737
  *
19738
+ * // [ "Color", "color" ]
19739
+ * // [ "FunctionTokenType", "calc" ]
19740
+ * // [ "Number", 0.15 ]
19741
+ * // [ "Add", undefined ]
19742
+ * // [ "Iden", "b" ]
19743
+ * // [ "Whitespace", undefined ]
19744
+ * // [ "FunctionTokenType", "calc" ]
19745
+ * // [ "Number", 0.24 ]
19746
+ * // [ "Add", undefined ]
19747
+ * // [ "Iden", "g" ]
19748
+ * // [ "Whitespace", undefined ]
19749
+ * // [ "Iden", "r" ]
19750
+ * // [ "Whitespace", undefined ]
19751
+ * // [ "Iden", "display-p3" ]
19752
+ * // [ "Whitespace", undefined ]
19753
+ * // [ "FunctionTokenType", "var" ]
19754
+ * // [ "DashedIden", "--base-color" ]
19755
+ * // [ "Whitespace", undefined ]
19756
+ * // [ "Iden", "from" ]
19757
+ * ```
19379
19758
  */
19380
19759
  function* walkValues(values, root = null, filter, reverse) {
19381
19760
  // const set = new Set<Token>();
@@ -19384,26 +19763,26 @@
19384
19763
  let previous = null;
19385
19764
  if (filter != null && typeof filter == 'function') {
19386
19765
  filter = {
19387
- event: exports.WalkerValueEvent.Enter,
19766
+ event: exports.WalkerEvent.Enter,
19388
19767
  fn: filter
19389
19768
  };
19390
19769
  }
19391
19770
  else if (filter == null) {
19392
19771
  filter = {
19393
- event: exports.WalkerValueEvent.Enter
19772
+ event: exports.WalkerEvent.Enter
19394
19773
  };
19395
19774
  }
19396
19775
  let isNumeric = false;
19397
- const eventType = filter.event ?? exports.WalkerValueEvent.Enter;
19776
+ const eventType = filter.event ?? exports.WalkerEvent.Enter;
19398
19777
  while (stack.length > 0) {
19399
19778
  let value = reverse ? stack.pop() : stack.shift();
19400
19779
  let option = null;
19401
- if (filter.fn != null && (eventType & exports.WalkerValueEvent.Enter)) {
19780
+ if (filter.fn != null && (eventType & exports.WalkerEvent.Enter)) {
19402
19781
  const isValid = filter.type == null || value.typ == filter.type ||
19403
19782
  (Array.isArray(filter.type) && filter.type.includes(value.typ)) ||
19404
19783
  (typeof filter.type == 'function' && filter.type(value));
19405
19784
  if (isValid) {
19406
- option = filter.fn(value, map.get(value) ?? root, exports.WalkerValueEvent.Enter);
19785
+ option = filter.fn(value, map.get(value) ?? root, exports.WalkerEvent.Enter);
19407
19786
  isNumeric = typeof option == 'number';
19408
19787
  if (isNumeric && (option & exports.WalkerOptionEnum.Stop)) {
19409
19788
  return;
@@ -19417,7 +19796,6 @@
19417
19796
  }
19418
19797
  }
19419
19798
  }
19420
- // if ((eventType & WalkerValueEvent.Enter) && (!isNumeric || ((option as number) & WalkerOptionEnum.Children) === 0)) {
19421
19799
  yield {
19422
19800
  value,
19423
19801
  parent: map.get(value) ?? root,
@@ -19426,7 +19804,6 @@
19426
19804
  // @ts-ignore
19427
19805
  root: root ?? null
19428
19806
  };
19429
- // }
19430
19807
  if ('chi' in value && (!isNumeric || (option & exports.WalkerOptionEnum.IgnoreChildren) === 0)) {
19431
19808
  const sliced = value.chi.slice();
19432
19809
  for (const child of sliced) {
@@ -19467,29 +19844,18 @@
19467
19844
  stack[reverse ? 'push' : 'unshift'](...values);
19468
19845
  }
19469
19846
  }
19470
- if ((eventType & exports.WalkerValueEvent.Leave) && filter.fn != null) {
19847
+ if ((eventType & exports.WalkerEvent.Leave) && filter.fn != null) {
19471
19848
  const isValid = filter.type == null || value.typ == filter.type ||
19472
19849
  (Array.isArray(filter.type) && filter.type.includes(value.typ)) ||
19473
19850
  (typeof filter.type == 'function' && filter.type(value));
19474
19851
  if (isValid) {
19475
- option = filter.fn(value, map.get(value), exports.WalkerValueEvent.Leave);
19852
+ option = filter.fn(value, map.get(value), exports.WalkerEvent.Leave);
19476
19853
  // @ts-ignore
19477
19854
  if (option != null && 'typ' in option) {
19478
19855
  map.set(option, map.get(value) ?? root);
19479
19856
  }
19480
19857
  }
19481
19858
  }
19482
- // if ((eventType & WalkerValueEvent.Leave) && (!isNumeric && ((option as number) & WalkerOptionEnum.Children) === 0)) {
19483
- //
19484
- // yield {
19485
- // value,
19486
- // parent: <FunctionToken | ParensToken>map.get(value) ?? root,
19487
- // previousValue: previous,
19488
- // nextValue: <Token>stack[0] ?? null,
19489
- // // @ts-ignore
19490
- // root: root ?? null
19491
- // };
19492
- // }
19493
19859
  previous = value;
19494
19860
  }
19495
19861
  }
@@ -19617,6 +19983,7 @@
19617
19983
  }
19618
19984
  }
19619
19985
  }
19986
+ // @ts-ignore
19620
19987
  if (SyntaxValidationResult.Valid == evaluateSyntax({ ...node, val: nodes }, {}).valid) {
19621
19988
  node.val = nodes;
19622
19989
  }
@@ -19682,6 +20049,7 @@
19682
20049
  }
19683
20050
  }
19684
20051
  class InlineCssVariablesFeature {
20052
+ accept = new Set([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType]);
19685
20053
  get ordering() {
19686
20054
  return 0;
19687
20055
  }
@@ -19695,9 +20063,10 @@
19695
20063
  }
19696
20064
  }
19697
20065
  run(ast, options = {}, parent, context) {
19698
- if (!('chi' in ast)) {
19699
- return null;
19700
- }
20066
+ // if (!('chi' in ast)) {
20067
+ //
20068
+ // return null;
20069
+ // }
19701
20070
  if (!('variableScope' in context)) {
19702
20071
  context.variableScope = new Map;
19703
20072
  }
@@ -20579,7 +20948,9 @@
20579
20948
  }
20580
20949
  add(...declarations) {
20581
20950
  for (const declaration of declarations) {
20582
- if (declaration.typ != exports.EnumToken.DeclarationNodeType || (Array.isArray(this.options.removeDuplicateDeclarations) ? this.options.removeDuplicateDeclarations.includes(declaration.nam) : !this.options.removeDuplicateDeclarations)) {
20951
+ if (declaration.typ != exports.EnumToken.DeclarationNodeType ||
20952
+ (typeof this.options.removeDuplicateDeclarations === 'string' && this.options.removeDuplicateDeclarations === declaration.nam.toLowerCase()) ||
20953
+ (Array.isArray(this.options.removeDuplicateDeclarations) ? this.options.removeDuplicateDeclarations.includes(declaration.nam) : !this.options.removeDuplicateDeclarations)) {
20583
20954
  this.declarations.set(Number(Math.random().toString().slice(2)).toString(36), declaration);
20584
20955
  continue;
20585
20956
  }
@@ -20664,6 +21035,7 @@
20664
21035
  }
20665
21036
 
20666
21037
  class ComputeShorthandFeature {
21038
+ accept = new Set([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType, exports.EnumToken.KeyFramesRuleNodeType]);
20667
21039
  get ordering() {
20668
21040
  return 3;
20669
21041
  }
@@ -20716,6 +21088,7 @@
20716
21088
  }
20717
21089
 
20718
21090
  class ComputeCalcExpressionFeature {
21091
+ accept = new Set([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType]);
20719
21092
  get ordering() {
20720
21093
  return 1;
20721
21094
  }
@@ -20738,7 +21111,7 @@
20738
21111
  }
20739
21112
  const set = new Set;
20740
21113
  for (const { value, parent } of walkValues(node.val, node, {
20741
- event: exports.WalkerValueEvent.Enter,
21114
+ event: exports.WalkerEvent.Enter,
20742
21115
  // @ts-ignore
20743
21116
  fn(node, parent) {
20744
21117
  if (parent != null &&
@@ -20815,7 +21188,7 @@
20815
21188
 
20816
21189
  function translateX(x, from) {
20817
21190
  const matrix = identity();
20818
- matrix[3 * 4 + 0] = x;
21191
+ matrix[3 * 4] = x;
20819
21192
  return multiply(from, matrix);
20820
21193
  }
20821
21194
  function translateY(y, from) {
@@ -20830,13 +21203,13 @@
20830
21203
  }
20831
21204
  function translate(translate, from) {
20832
21205
  const matrix = identity();
20833
- matrix[3 * 4 + 0] = translate[0];
21206
+ matrix[3 * 4] = translate[0];
20834
21207
  matrix[3 * 4 + 1] = translate[1] ?? 0;
20835
21208
  return multiply(from, matrix);
20836
21209
  }
20837
21210
  function translate3d(translate, from) {
20838
21211
  const matrix = identity();
20839
- matrix[3 * 4 + 0] = translate[0];
21212
+ matrix[3 * 4] = translate[0];
20840
21213
  matrix[3 * 4 + 1] = translate[1];
20841
21214
  matrix[3 * 4 + 2] = translate[2];
20842
21215
  return multiply(from, matrix);
@@ -20859,34 +21232,34 @@
20859
21232
  x *= unit;
20860
21233
  y *= unit;
20861
21234
  z *= unit;
20862
- matrix[0 * 4 + 0] = 1 - 2 * (y * y + z * z) * sq;
20863
- matrix[0 * 4 + 1] = 2 * (x * y * sq + z * sc);
20864
- matrix[0 * 4 + 2] = 2 * (x * z * sq - y * sc);
20865
- matrix[1 * 4 + 0] = 2 * (x * y * sq - z * sc);
20866
- matrix[1 * 4 + 1] = 1 - 2 * (x * x + z * z) * sq;
20867
- matrix[1 * 4 + 2] = 2 * (y * z * sq + x * sc);
20868
- matrix[2 * 4 + 0] = 2 * (x * z * sq + y * sc);
21235
+ matrix[0] = 1 - 2 * (y * y + z * z) * sq;
21236
+ matrix[1] = 2 * (x * y * sq + z * sc);
21237
+ matrix[2] = 2 * (x * z * sq - y * sc);
21238
+ matrix[4] = 2 * (x * y * sq - z * sc);
21239
+ matrix[4 + 1] = 1 - 2 * (x * x + z * z) * sq;
21240
+ matrix[4 + 2] = 2 * (y * z * sq + x * sc);
21241
+ matrix[2 * 4] = 2 * (x * z * sq + y * sc);
20869
21242
  matrix[2 * 4 + 1] = 2 * (y * z * sq - x * sc);
20870
21243
  matrix[2 * 4 + 2] = 1 - 2 * (x * x + y * y) * sq;
20871
21244
  return multiply(from, matrix);
20872
21245
  }
20873
21246
  function rotate(angle, from) {
20874
21247
  const matrix = identity();
20875
- matrix[0 * 4 + 0] = Math.cos(angle);
20876
- matrix[0 * 4 + 1] = Math.sin(angle);
20877
- matrix[1 * 4 + 0] = -Math.sin(angle);
20878
- matrix[1 * 4 + 1] = Math.cos(angle);
21248
+ matrix[0] = Math.cos(angle);
21249
+ matrix[1] = Math.sin(angle);
21250
+ matrix[4] = -Math.sin(angle);
21251
+ matrix[4 + 1] = Math.cos(angle);
20879
21252
  return multiply(from, matrix);
20880
21253
  }
20881
21254
 
20882
21255
  function scaleX(x, from) {
20883
21256
  const matrix = identity();
20884
- matrix[0 * 4 + 0] = x;
21257
+ matrix[0] = x;
20885
21258
  return multiply(from, matrix);
20886
21259
  }
20887
21260
  function scaleY(y, from) {
20888
21261
  const matrix = identity();
20889
- matrix[1 * 4 + 1] = y;
21262
+ matrix[4 + 1] = y;
20890
21263
  return multiply(from, matrix);
20891
21264
  }
20892
21265
  function scaleZ(z, from) {
@@ -20896,14 +21269,14 @@
20896
21269
  }
20897
21270
  function scale(x, y, from) {
20898
21271
  const matrix = identity();
20899
- matrix[0 * 4 + 0] = x;
20900
- matrix[1 * 4 + 1] = y;
21272
+ matrix[0] = x;
21273
+ matrix[4 + 1] = y;
20901
21274
  return multiply(from, matrix);
20902
21275
  }
20903
21276
  function scale3d(x, y, z, from) {
20904
21277
  const matrix = identity();
20905
- matrix[0 * 4 + 0] = x;
20906
- matrix[1 * 4 + 1] = y;
21278
+ matrix[0] = x;
21279
+ matrix[4 + 1] = y;
20907
21280
  matrix[2 * 4 + 2] = z;
20908
21281
  return multiply(from, matrix);
20909
21282
  }
@@ -20928,27 +21301,27 @@
20928
21301
  function matrix(values) {
20929
21302
  const matrix = identity();
20930
21303
  if (values.length === 6) {
20931
- matrix[0 * 4 + 0] = values[0];
20932
- matrix[0 * 4 + 1] = values[1];
20933
- matrix[1 * 4 + 0] = values[2];
20934
- matrix[1 * 4 + 1] = values[3];
20935
- matrix[3 * 4 + 0] = values[4];
21304
+ matrix[0] = values[0];
21305
+ matrix[1] = values[1];
21306
+ matrix[4] = values[2];
21307
+ matrix[4 + 1] = values[3];
21308
+ matrix[3 * 4] = values[4];
20936
21309
  matrix[3 * 4 + 1] = values[5];
20937
21310
  }
20938
21311
  else if (values.length === 16) {
20939
- matrix[0 * 4 + 0] = values[0];
20940
- matrix[0 * 4 + 1] = values[1];
20941
- matrix[0 * 4 + 2] = values[2];
20942
- matrix[0 * 4 + 3] = values[3];
20943
- matrix[1 * 4 + 0] = values[4];
20944
- matrix[1 * 4 + 1] = values[5];
20945
- matrix[1 * 4 + 2] = values[6];
20946
- matrix[1 * 4 + 3] = values[7];
20947
- matrix[2 * 4 + 0] = values[8];
21312
+ matrix[0] = values[0];
21313
+ matrix[1] = values[1];
21314
+ matrix[2] = values[2];
21315
+ matrix[3] = values[3];
21316
+ matrix[4] = values[4];
21317
+ matrix[4 + 1] = values[5];
21318
+ matrix[4 + 2] = values[6];
21319
+ matrix[4 + 3] = values[7];
21320
+ matrix[2 * 4] = values[8];
20948
21321
  matrix[2 * 4 + 1] = values[9];
20949
21322
  matrix[2 * 4 + 2] = values[10];
20950
21323
  matrix[2 * 4 + 3] = values[11];
20951
- matrix[3 * 4 + 0] = values[12];
21324
+ matrix[3 * 4] = values[12];
20952
21325
  matrix[3 * 4 + 1] = values[13];
20953
21326
  matrix[3 * 4 + 2] = values[14];
20954
21327
  matrix[3 * 4 + 3] = values[15];
@@ -20973,11 +21346,11 @@
20973
21346
  typ: exports.EnumToken.FunctionTokenType,
20974
21347
  val: 'matrix',
20975
21348
  chi: [
20976
- matrix[0 * 4 + 0],
20977
- matrix[0 * 4 + 1],
20978
- matrix[1 * 4 + 0],
20979
- matrix[1 * 4 + 1],
20980
- matrix[3 * 4 + 0],
21349
+ matrix[0],
21350
+ matrix[1],
21351
+ matrix[4],
21352
+ matrix[4 + 1],
21353
+ matrix[3 * 4],
20981
21354
  matrix[3 * 4 + 1]
20982
21355
  ].reduce((acc, t) => {
20983
21356
  if (acc.length > 0) {
@@ -21160,10 +21533,6 @@
21160
21533
  }
21161
21534
  }
21162
21535
  if (transforms.has('skew')) {
21163
- // if (round(decomposed.skew[0]) == 0) {
21164
- //
21165
- // skew.delete('x');
21166
- // }
21167
21536
  if (round(decomposed.skew[1]) == 0) {
21168
21537
  skew.delete('y');
21169
21538
  }
@@ -21203,7 +21572,7 @@
21203
21572
  scales.delete('x');
21204
21573
  }
21205
21574
  if (scales.size == 1) {
21206
- let prefix = scales.has('x') ? '' : scales.has('y') ? 'Y' : 'Z';
21575
+ let prefix = scales.has('x') ? 'X' : scales.has('y') ? 'Y' : 'Z';
21207
21576
  result.push({
21208
21577
  typ: exports.EnumToken.FunctionTokenType,
21209
21578
  val: 'scale' + prefix,
@@ -21246,13 +21615,9 @@
21246
21615
  ] : result;
21247
21616
  }
21248
21617
  function eqMatrix(a, b) {
21249
- // console.error(JSON.stringify({a, b}, null, 1));
21250
21618
  let mat = identity();
21251
21619
  let tmp = identity();
21252
- // @ts-ignore
21253
21620
  const data = (Array.isArray(a) ? a : parseMatrix(a));
21254
- // toZero(data);
21255
- // console.error({data});
21256
21621
  for (const transform of b) {
21257
21622
  tmp = computeMatrix([transform], identity());
21258
21623
  if (tmp == null) {
@@ -21260,8 +21625,6 @@
21260
21625
  }
21261
21626
  mat = multiply(mat, tmp);
21262
21627
  }
21263
- // toZero(mat);
21264
- // console.error({mat});
21265
21628
  if (mat == null) {
21266
21629
  return false;
21267
21630
  }
@@ -21274,23 +21637,126 @@
21274
21637
  }
21275
21638
  return true;
21276
21639
  }
21640
+ function minifyTransformFunctions(transform) {
21641
+ const name = transform.val.toLowerCase();
21642
+ if ('skewx' == name) {
21643
+ transform.val = 'skew';
21644
+ return transform;
21645
+ }
21646
+ if (!['translate', 'translate3d', 'scale', 'scale3d'].includes(name)) {
21647
+ return transform;
21648
+ }
21649
+ const values = [];
21650
+ for (const token of transform.chi) {
21651
+ if (token.typ == exports.EnumToken.CommentTokenType || token.typ == exports.EnumToken.WhitespaceTokenType || token.typ == exports.EnumToken.CommaTokenType) {
21652
+ continue;
21653
+ }
21654
+ if (![exports.EnumToken.NumberTokenType, exports.EnumToken.LengthTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.PercentageTokenType].includes(token.typ)) {
21655
+ return transform;
21656
+ }
21657
+ if (token.typ == exports.EnumToken.PercentageTokenType && typeof token.val == 'number' && name.startsWith('scale')) {
21658
+ Object.assign(token, { typ: exports.EnumToken.NumberTokenType, val: token.val / 100 });
21659
+ }
21660
+ values.push(token);
21661
+ }
21662
+ if ((name == 'translate' || name == 'scale') && values.length > 2) {
21663
+ return transform;
21664
+ }
21665
+ const ignoredValue = name.startsWith('scale') ? 1 : 0;
21666
+ const t = new Set(['x', 'y', 'z']);
21667
+ let i = 3;
21668
+ while (i--) {
21669
+ if (values.length <= i || values[i].val == ignoredValue) {
21670
+ t.delete(i == 0 ? 'x' : i == 1 ? 'y' : 'z');
21671
+ }
21672
+ }
21673
+ if (name == 'translate3d' || name == 'translate') {
21674
+ if (t.size == 0) {
21675
+ return {
21676
+ typ: exports.EnumToken.FunctionTokenType,
21677
+ val: 'translate',
21678
+ chi: [
21679
+ { typ: exports.EnumToken.NumberTokenType, val: 0 }
21680
+ ]
21681
+ };
21682
+ }
21683
+ if (t.size == 1) {
21684
+ return {
21685
+ typ: exports.EnumToken.FunctionTokenType,
21686
+ val: 'translate' + (t.has('x') ? '' : t.has('y') ? 'Y' : 'Z'),
21687
+ chi: [
21688
+ values[t.has('x') ? 0 : t.has('y') ? 1 : 2]
21689
+ ]
21690
+ };
21691
+ }
21692
+ if (t.size == 2) {
21693
+ if (t.has('z')) {
21694
+ return transform;
21695
+ }
21696
+ return {
21697
+ typ: exports.EnumToken.FunctionTokenType,
21698
+ val: 'translate',
21699
+ chi: [
21700
+ values[0],
21701
+ { typ: exports.EnumToken.CommaTokenType },
21702
+ values[1]
21703
+ ]
21704
+ };
21705
+ }
21706
+ }
21707
+ if (name == 'scale3d' || name == 'scale') {
21708
+ if (t.size == 0) {
21709
+ return {
21710
+ typ: exports.EnumToken.FunctionTokenType,
21711
+ val: 'scale',
21712
+ chi: [
21713
+ { typ: exports.EnumToken.NumberTokenType, val: 1 }
21714
+ ]
21715
+ };
21716
+ }
21717
+ if (t.size == 1) {
21718
+ return {
21719
+ typ: exports.EnumToken.FunctionTokenType,
21720
+ val: 'scale' + (t.has('x') ? 'X' : t.has('y') ? 'Y' : 'Z'),
21721
+ chi: [
21722
+ values[t.has('x') ? 0 : t.has('y') ? 1 : 2]
21723
+ ]
21724
+ };
21725
+ }
21726
+ if (t.size == 2) {
21727
+ if (t.has('z')) {
21728
+ return transform;
21729
+ }
21730
+ return {
21731
+ typ: exports.EnumToken.FunctionTokenType,
21732
+ val: 'scale',
21733
+ chi: [
21734
+ values[0],
21735
+ { typ: exports.EnumToken.CommaTokenType },
21736
+ values[1]
21737
+ ]
21738
+ };
21739
+ }
21740
+ }
21741
+ return transform;
21742
+ }
21277
21743
 
21278
21744
  function skewX(x, from) {
21279
21745
  const matrix = identity();
21280
- matrix[1 * 4 + 0] = Math.tan(x);
21746
+ matrix[4] = Math.tan(x);
21281
21747
  return multiply(from, matrix);
21282
21748
  }
21283
21749
  function skewY(y, from) {
21284
21750
  const matrix = identity();
21285
- matrix[0 * 4 + 1] = Math.tan(y);
21751
+ matrix[1] = Math.tan(y);
21286
21752
  return multiply(from, matrix);
21287
21753
  }
21288
21754
  // convert angle to radian
21289
21755
  function skew(values, from) {
21290
21756
  const matrix = identity();
21291
- matrix[1 * 4 + 0] = Math.tan(values[0]);
21757
+ matrix[4] = Math.tan(values[0]);
21292
21758
  if (values.length > 1) {
21293
- matrix[0 * 4 + 1] = Math.tan(values[1]);
21759
+ matrix[1] = Math.tan(values[1]);
21294
21760
  }
21295
21761
  return multiply(from, matrix);
21296
21762
  }
@@ -21329,8 +21795,6 @@
21329
21795
  });
21330
21796
  }
21331
21797
  }
21332
- // console.error({matrix});
21333
- // matrix = toZero(matrix) as Matrix;
21334
21798
  return {
21335
21799
  matrix: serialize(toZero(matrix)),
21336
21800
  cumulative,
@@ -21354,7 +21818,7 @@
21354
21818
  {
21355
21819
  values.length = 0;
21356
21820
  const children = stripCommaToken(transformList[i].chi.slice());
21357
- const valCount = transformList[i].val == 'translate3d' || transformList[i].val == 'translate' ? 3 : 1;
21821
+ const valCount = transformList[i].val == 'translate3d' ? 3 : transformList[i].val == 'translate' ? 2 : 1;
21358
21822
  for (let j = 0; j < children.length; j++) {
21359
21823
  if (children[j].typ == exports.EnumToken.WhitespaceTokenType) {
21360
21824
  continue;
@@ -21441,7 +21905,7 @@
21441
21905
  const children = stripCommaToken(transformList[i].chi.slice());
21442
21906
  for (let k = 0; k < children.length; k++) {
21443
21907
  child = children[k];
21444
- if (child.typ != exports.EnumToken.NumberTokenType) {
21908
+ if (child.typ != exports.EnumToken.NumberTokenType && child.typ != exports.EnumToken.PercentageTokenType) {
21445
21909
  return null;
21446
21910
  }
21447
21911
  values.push(getNumber(child));
@@ -21595,6 +22059,7 @@
21595
22059
  }
21596
22060
 
21597
22061
  class TransformCssFeature {
22062
+ accept = new Set([exports.EnumToken.RuleNodeType, exports.EnumToken.KeyFramesRuleNodeType]);
21598
22063
  get ordering() {
21599
22064
  return 4;
21600
22065
  }
@@ -21621,28 +22086,21 @@
21621
22086
  if (node.typ != exports.EnumToken.DeclarationNodeType || !node.nam.match(/^(-[a-z]+-)?transform$/)) {
21622
22087
  continue;
21623
22088
  }
21624
- const children = node.val.reduce((acc, curr) => {
21625
- if (curr.typ == exports.EnumToken.FunctionTokenType && 'skew' == curr.val.toLowerCase()) {
21626
- if (curr.chi.length == 3) {
21627
- if (curr.chi[2].val == 0) {
21628
- curr.chi.length = 1;
21629
- curr.val = 'skew';
21630
- }
21631
- else if (curr.chi[0].val == 0) {
21632
- curr.chi = [curr.chi[2]];
21633
- curr.val = 'skewY';
21634
- }
21635
- }
21636
- }
21637
- acc.push(curr);
21638
- return acc;
21639
- }, []);
22089
+ const children = [];
22090
+ for (const child of node.val) {
22091
+ children.push(child.typ == exports.EnumToken.FunctionTokenType ? minifyTransformFunctions(child) : child);
22092
+ }
21640
22093
  consumeWhitespace(children);
21641
- let { matrix, cumulative, minified } = compute(children) ?? {};
22094
+ let { matrix, cumulative, minified } = compute(children) ?? {
22095
+ matrix: null,
22096
+ cumulative: null,
22097
+ minified: null
22098
+ };
21642
22099
  if (matrix == null || cumulative == null || minified == null) {
22100
+ node.val = children;
21643
22101
  continue;
21644
22102
  }
21645
- let r = [filterValues(node.val.slice())];
22103
+ let r = [filterValues(children)];
21646
22104
  if (eqMatrix(matrix, cumulative)) {
21647
22105
  r.push(cumulative);
21648
22106
  }
@@ -21721,7 +22179,7 @@
21721
22179
  }
21722
22180
  replacement = parent;
21723
22181
  for (const feature of options.features) {
21724
- if ((feature.processMode & exports.FeatureWalkMode.Pre) === 0) {
22182
+ if ((feature.processMode & exports.FeatureWalkMode.Pre) === 0 || (feature.accept != null && !feature.accept.has(parent.typ))) {
21725
22183
  continue;
21726
22184
  }
21727
22185
  const result = feature.run(replacement, options, parent.parent ?? ast, context, exports.FeatureWalkMode.Pre);
@@ -21760,7 +22218,7 @@
21760
22218
  replacement = parent;
21761
22219
  if (postprocess) {
21762
22220
  for (const feature of options.features) {
21763
- if ((feature.processMode & exports.FeatureWalkMode.Post) === 0) {
22221
+ if ((feature.processMode & exports.FeatureWalkMode.Post) === 0 || (feature.accept != null && !feature.accept.has(parent.typ))) {
21764
22222
  continue;
21765
22223
  }
21766
22224
  const result = feature.run(replacement, options, parent.parent ?? ast, context, exports.FeatureWalkMode.Post);
@@ -21891,6 +22349,7 @@
21891
22349
  continue;
21892
22350
  }
21893
22351
  if (previous?.typ == exports.EnumToken.AtRuleNodeType &&
22352
+ node.nam != 'font-face' &&
21894
22353
  previous.nam == node.nam &&
21895
22354
  previous.val == node.val) {
21896
22355
  if ('chi' in node) {
@@ -22039,7 +22498,9 @@
22039
22498
  break;
22040
22499
  }
22041
22500
  if (shouldMerge) {
22501
+ // @ts-ignore
22042
22502
  if (((node.typ == exports.EnumToken.RuleNodeType || node.typ == exports.EnumToken.KeyFramesRuleNodeType) && node.sel == previous.sel) ||
22503
+ // @ts-ignore
22043
22504
  (node.typ == exports.EnumToken.AtRuleNodeType) && node.val != 'font-face' && node.val == previous.val) {
22044
22505
  // @ts-ignore
22045
22506
  node.chi.unshift(...previous.chi);
@@ -22707,14 +23168,11 @@
22707
23168
  */
22708
23169
  function expand(ast) {
22709
23170
  const result = { ...ast, chi: [] };
22710
- // @ts-ignore
22711
23171
  for (let i = 0; i < ast.chi.length; i++) {
22712
- // @ts-ignore
22713
23172
  const node = ast.chi[i];
22714
23173
  if (node.typ == exports.EnumToken.RuleNodeType) {
22715
23174
  // @ts-ignore
22716
23175
  result.chi.push(...expandRule(node));
22717
- // i += expanded.length - 1;
22718
23176
  }
22719
23177
  else if (node.typ == exports.EnumToken.AtRuleNodeType && 'chi' in node) {
22720
23178
  let hasRule = false;
@@ -22729,6 +23187,10 @@
22729
23187
  // @ts-ignore
22730
23188
  result.chi.push({ ...(hasRule ? expand(node) : node) });
22731
23189
  }
23190
+ else {
23191
+ // @ts-ignore
23192
+ result.chi.push(node);
23193
+ }
22732
23194
  }
22733
23195
  return result;
22734
23196
  }
@@ -22911,13 +23373,7 @@
22911
23373
  return 1;
22912
23374
  }
22913
23375
  return b == '&' ? -1 : 0;
22914
- }).reduce((acc, curr) => {
22915
- // if (acc.length > 0 && curr == '&' && (replace.charAt(0) != '.' || replace.includes(' '))) {
22916
- //
22917
- // return acc + ':is(' + replace + ')';
22918
- // }
22919
- return acc + (curr == '&' ? replace : curr);
22920
- }, '');
23376
+ }).reduce((acc, curr) => acc + (curr == '&' ? replace : curr), '');
22921
23377
  }
22922
23378
 
22923
23379
  const matchUrl = /^(https?:)?\/\//;
@@ -22939,9 +23395,10 @@
22939
23395
  if (chr == '/') {
22940
23396
  parts.push('');
22941
23397
  }
22942
- else if (chr == '?' || chr == '#') {
22943
- break;
22944
- }
23398
+ // else if (chr == '?' || chr == '#') {
23399
+ //
23400
+ // break;
23401
+ // }
22945
23402
  else {
22946
23403
  parts[parts.length - 1] += chr;
22947
23404
  }
@@ -22996,6 +23453,8 @@
22996
23453
  relative: url
22997
23454
  };
22998
23455
  }
23456
+ cwd ??= '';
23457
+ currentDirectory ??= '';
22999
23458
  if (matchUrl.test(currentDirectory)) {
23000
23459
  const path = new URL(url, currentDirectory).href;
23001
23460
  return {
@@ -23032,9 +23491,10 @@
23032
23491
  * @param url
23033
23492
  * @param currentFile
23034
23493
  *
23494
+ * @param asStream
23035
23495
  * @private
23036
23496
  */
23037
- async function load(url, currentFile = '.') {
23497
+ async function load(url, currentFile = '.', asStream = false) {
23038
23498
  let t;
23039
23499
  if (matchUrl.test(url)) {
23040
23500
  t = new URL(url);
@@ -23044,15 +23504,13 @@
23044
23504
  }
23045
23505
  else {
23046
23506
  const path = resolve(url, currentFile).absolute;
23047
- // @ts-ignore
23048
23507
  t = new URL(path, self.origin);
23049
23508
  }
23050
- // @ts-ignore
23051
- return fetch(t, t.origin != self.origin ? { mode: 'cors' } : {}).then((response) => {
23509
+ return fetch(t, t.origin != self.origin ? { mode: 'cors' } : {}).then(async (response) => {
23052
23510
  if (!response.ok) {
23053
23511
  throw new Error(`${response.status} ${response.statusText} ${response.url}`);
23054
23512
  }
23055
- return response.body;
23513
+ return asStream ? response.body : await response.text();
23056
23514
  });
23057
23515
  }
23058
23516
  /**
@@ -23094,6 +23552,7 @@
23094
23552
  * parse css file
23095
23553
  * @param file url or path
23096
23554
  * @param options
23555
+ * @param asStream load file as stream
23097
23556
  *
23098
23557
  * @throws Error file not found
23099
23558
  *
@@ -23112,8 +23571,8 @@
23112
23571
  * console.log(result.ast);
23113
23572
  * ```
23114
23573
  */
23115
- async function parseFile(file, options = {}) {
23116
- return load(file).then(stream => parse(stream, { src: file, ...options }));
23574
+ async function parseFile(file, options = {}, asStream = false) {
23575
+ return Promise.resolve((options.load ?? load)(file, '.', asStream)).then(stream => parse(stream, { src: file, ...options }));
23117
23576
  }
23118
23577
  /**
23119
23578
  * parse css
@@ -23160,6 +23619,7 @@
23160
23619
  * transform css file
23161
23620
  * @param file url or path
23162
23621
  * @param options
23622
+ * @param asStream load file as stream
23163
23623
  *
23164
23624
  * Example:
23165
23625
  *
@@ -23176,8 +23636,8 @@
23176
23636
  * console.log(result.code);
23177
23637
  * ```
23178
23638
  */
23179
- async function transformFile(file, options = {}) {
23180
- return load(file).then(stream => transform(stream, { src: file, ...options }));
23639
+ async function transformFile(file, options = {}, asStream = false) {
23640
+ return Promise.resolve((options.load ?? load)(file, '.', asStream)).then(stream => transform(stream, { src: file, ...options }));
23181
23641
  }
23182
23642
  /**
23183
23643
  * transform css