@tbela99/css-parser 1.3.3 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +64 -48
  3. package/dist/config.json.js +3 -0
  4. package/dist/index-umd-web.js +2266 -631
  5. package/dist/index.cjs +2271 -620
  6. package/dist/index.d.ts +522 -181
  7. package/dist/lib/ast/expand.js +5 -10
  8. package/dist/lib/ast/features/calc.js +3 -2
  9. package/dist/lib/ast/features/inlinecssvariables.js +5 -3
  10. package/dist/lib/ast/features/prefix.js +1 -1
  11. package/dist/lib/ast/features/shorthand.js +1 -0
  12. package/dist/lib/ast/features/transform.js +13 -19
  13. package/dist/lib/ast/features/type.js +1 -1
  14. package/dist/lib/ast/minify.js +6 -3
  15. package/dist/lib/ast/transform/compute.js +2 -4
  16. package/dist/lib/ast/transform/matrix.js +20 -20
  17. package/dist/lib/ast/transform/minify.js +105 -12
  18. package/dist/lib/ast/transform/rotate.js +11 -11
  19. package/dist/lib/ast/transform/scale.js +6 -6
  20. package/dist/lib/ast/transform/skew.js +4 -4
  21. package/dist/lib/ast/transform/translate.js +3 -3
  22. package/dist/lib/ast/transform/utils.js +30 -37
  23. package/dist/lib/ast/types.js +76 -5
  24. package/dist/lib/ast/walk.js +77 -58
  25. package/dist/lib/fs/resolve.js +69 -10
  26. package/dist/lib/parser/declaration/list.js +6 -1
  27. package/dist/lib/parser/parse.js +1169 -312
  28. package/dist/lib/parser/tokenize.js +33 -20
  29. package/dist/lib/parser/utils/declaration.js +54 -0
  30. package/dist/lib/parser/utils/hash.js +86 -0
  31. package/dist/lib/parser/utils/text.js +8 -0
  32. package/dist/lib/renderer/render.js +26 -7
  33. package/dist/lib/syntax/color/relativecolor.js +0 -3
  34. package/dist/lib/syntax/syntax.js +36 -18
  35. package/dist/lib/validation/at-rules/container.js +11 -0
  36. package/dist/lib/validation/at-rules/counter-style.js +11 -0
  37. package/dist/lib/validation/at-rules/font-feature-values.js +11 -0
  38. package/dist/lib/validation/at-rules/keyframes.js +11 -0
  39. package/dist/lib/validation/at-rules/layer.js +11 -0
  40. package/dist/lib/validation/at-rules/media.js +11 -0
  41. package/dist/lib/validation/at-rules/page-margin-box.js +11 -0
  42. package/dist/lib/validation/at-rules/page.js +11 -0
  43. package/dist/lib/validation/at-rules/supports.js +11 -0
  44. package/dist/lib/validation/at-rules/when.js +11 -0
  45. package/dist/lib/validation/config.js +0 -2
  46. package/dist/lib/validation/config.json.js +36 -4
  47. package/dist/lib/validation/parser/parse.js +53 -2
  48. package/dist/lib/validation/syntax.js +204 -36
  49. package/dist/lib/validation/syntaxes/compound-selector.js +1 -2
  50. package/dist/lib/validation/syntaxes/relative-selector-list.js +2 -5
  51. package/dist/node.js +60 -18
  52. package/dist/types.d.ts +17 -0
  53. package/dist/types.js +20 -0
  54. package/dist/web.js +43 -17
  55. package/package.json +20 -17
  56. 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
@@ -421,6 +433,23 @@
421
433
  * invalid declaration node type
422
434
  */
423
435
  EnumToken[EnumToken["InvalidDeclarationNodeType"] = 94] = "InvalidDeclarationNodeType";
436
+ /* css module nodes */
437
+ /**
438
+ * composes token node type
439
+ */
440
+ EnumToken[EnumToken["ComposesSelectorNodeType"] = 95] = "ComposesSelectorNodeType";
441
+ /**
442
+ * css variable token type
443
+ */
444
+ EnumToken[EnumToken["CssVariableTokenType"] = 96] = "CssVariableTokenType";
445
+ /**
446
+ * css variable import token type
447
+ */
448
+ EnumToken[EnumToken["CssVariableImportTokenType"] = 97] = "CssVariableImportTokenType";
449
+ /**
450
+ * css variable declaration map token type
451
+ */
452
+ EnumToken[EnumToken["CssVariableDeclarationMapTokenType"] = 98] = "CssVariableDeclarationMapTokenType";
424
453
  /* aliases */
425
454
  /**
426
455
  * alias for time token type
@@ -537,7 +566,7 @@
537
566
  exports.ColorType = void 0;
538
567
  (function (ColorType) {
539
568
  /**
540
- * system colors
569
+ * deprecated system colors
541
570
  */
542
571
  ColorType[ColorType["SYS"] = 0] = "SYS";
543
572
  /**
@@ -545,7 +574,7 @@
545
574
  */
546
575
  ColorType[ColorType["DPSYS"] = 1] = "DPSYS";
547
576
  /**
548
- * colors as literals
577
+ * named colors
549
578
  */
550
579
  ColorType[ColorType["LIT"] = 2] = "LIT";
551
580
  /**
@@ -645,6 +674,48 @@
645
674
  */
646
675
  ColorType[ColorType["DEVICE_CMYK"] = 7] = "DEVICE_CMYK";
647
676
  })(exports.ColorType || (exports.ColorType = {}));
677
+ exports.ModuleCaseTransformEnum = void 0;
678
+ (function (ModuleCaseTransformEnum) {
679
+ /**
680
+ * export class names as-is
681
+ */
682
+ ModuleCaseTransformEnum[ModuleCaseTransformEnum["IgnoreCase"] = 1] = "IgnoreCase";
683
+ /**
684
+ * transform mapping key name to camel case
685
+ */
686
+ ModuleCaseTransformEnum[ModuleCaseTransformEnum["CamelCase"] = 2] = "CamelCase";
687
+ /**
688
+ * transform class names and mapping key name to camel case
689
+ */
690
+ ModuleCaseTransformEnum[ModuleCaseTransformEnum["CamelCaseOnly"] = 4] = "CamelCaseOnly";
691
+ /**
692
+ * transform mapping key name to dash case
693
+ */
694
+ ModuleCaseTransformEnum[ModuleCaseTransformEnum["DashCase"] = 8] = "DashCase";
695
+ /**
696
+ * transform class names and mapping key name to dash case
697
+ */
698
+ ModuleCaseTransformEnum[ModuleCaseTransformEnum["DashCaseOnly"] = 16] = "DashCaseOnly";
699
+ })(exports.ModuleCaseTransformEnum || (exports.ModuleCaseTransformEnum = {}));
700
+ exports.ModuleScopeEnumOptions = void 0;
701
+ (function (ModuleScopeEnumOptions) {
702
+ /**
703
+ * use the global scope
704
+ */
705
+ ModuleScopeEnumOptions[ModuleScopeEnumOptions["Global"] = 32] = "Global";
706
+ /**
707
+ * use the local scope
708
+ */
709
+ ModuleScopeEnumOptions[ModuleScopeEnumOptions["Local"] = 64] = "Local";
710
+ /**
711
+ * do not allow selector without an id or class
712
+ */
713
+ ModuleScopeEnumOptions[ModuleScopeEnumOptions["Pure"] = 128] = "Pure";
714
+ /**
715
+ * export using ICSS module format
716
+ */
717
+ ModuleScopeEnumOptions[ModuleScopeEnumOptions["ICSS"] = 256] = "ICSS";
718
+ })(exports.ModuleScopeEnumOptions || (exports.ModuleScopeEnumOptions = {}));
648
719
 
649
720
  // from https://www.w3.org/TR/css-color-4/multiply-matrices.js
650
721
  /**
@@ -3903,10 +3974,7 @@
3903
3974
  // normalize hue
3904
3975
  for (const k of walkValues([object.h])) {
3905
3976
  if (k.value.typ == exports.EnumToken.AngleTokenType && k.value.unit == 'deg') {
3906
- // @ts-ignore
3907
3977
  k.value.typ = exports.EnumToken.NumberTokenType;
3908
- // @ts-ignore
3909
- delete k.value.unit;
3910
3978
  }
3911
3979
  }
3912
3980
  }
@@ -4109,10 +4177,7 @@
4109
4177
  function identity() {
4110
4178
  return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
4111
4179
  }
4112
- function pLength(point) {
4113
- return Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
4114
- }
4115
- function normalize(point) {
4180
+ function normalize$1(point) {
4116
4181
  const [x, y, z] = point;
4117
4182
  const norm = Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
4118
4183
  return norm === 0 ? [0, 0, 0] : [x / norm, y / norm, z / norm];
@@ -4139,8 +4204,14 @@
4139
4204
  function inverse(matrix) {
4140
4205
  // Create augmented matrix [matrix | identity]
4141
4206
  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
4207
+ ...matrix.slice(0, 4),
4208
+ 1, 0, 0, 0,
4209
+ ...matrix.slice(4, 8),
4210
+ 0, 1, 0, 0,
4211
+ ...matrix.slice(8, 12),
4212
+ 0, 0, 1, 0,
4213
+ ...matrix.slice(12, 16),
4214
+ 0, 0, 0, 1
4144
4215
  ];
4145
4216
  // Gaussian elimination with partial pivoting
4146
4217
  for (let col = 0; col < 4; col++) {
@@ -4180,24 +4251,9 @@
4180
4251
  // Extract the inverse from the right side of the augmented matrix
4181
4252
  return augmented.slice(0, 16);
4182
4253
  }
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
4254
  function round(number) {
4200
- return Math.abs(number) < epsilon ? 0 : +number.toPrecision(6);
4255
+ const rounded = Math.round(number);
4256
+ return Math.abs(rounded - number) <= epsilon ? rounded : +number.toPrecision(6);
4201
4257
  }
4202
4258
  // translate3d(25.9808px, 0, 15px ) rotateY(60deg) skewX(49.9999deg) scale(1, 1.2)
4203
4259
  // translate → rotate → skew → scale
@@ -4220,7 +4276,7 @@
4220
4276
  perspectiveMatrix[15] = 1;
4221
4277
  // @ts-ignore
4222
4278
  const inverted = inverse(original.slice());
4223
- if (!inverted) {
4279
+ if (inverted === null) {
4224
4280
  return null;
4225
4281
  }
4226
4282
  const transposedInverse = transposeMatrix4(inverted);
@@ -4241,17 +4297,22 @@
4241
4297
  const row0 = [matrix[0], matrix[1], matrix[2]];
4242
4298
  const row1 = [matrix[4], matrix[5], matrix[6]];
4243
4299
  const row2 = [matrix[8], matrix[9], matrix[10]];
4300
+ const cross = [
4301
+ row1[1] * row2[2] - row1[2] * row2[1],
4302
+ row1[2] * row2[0] - row1[0] * row2[2],
4303
+ row1[0] * row2[1] - row1[1] * row2[0],
4304
+ ];
4244
4305
  // Compute scale
4245
- const scaleX = pLength(row0);
4246
- const row0Norm = normalize(row0);
4306
+ const scaleX = Math.hypot(...row0);
4307
+ const row0Norm = normalize$1(row0);
4247
4308
  const skewXY = dot(row0Norm, row1);
4248
4309
  const row1Proj = [
4249
4310
  row1[0] - skewXY * row0Norm[0],
4250
4311
  row1[1] - skewXY * row0Norm[1],
4251
4312
  row1[2] - skewXY * row0Norm[2]
4252
4313
  ];
4253
- const scaleY = pLength(row1Proj);
4254
- const row1Norm = normalize(row1Proj);
4314
+ const scaleY = Math.hypot(...row1Proj);
4315
+ const row1Norm = normalize$1(row1Proj);
4255
4316
  const skewXZ = dot(row0Norm, row2);
4256
4317
  const skewYZ = dot(row1Norm, row2);
4257
4318
  const row2Proj = [
@@ -4259,8 +4320,9 @@
4259
4320
  row2[1] - skewXZ * row0Norm[1] - skewYZ * row1Norm[1],
4260
4321
  row2[2] - skewXZ * row0Norm[2] - skewYZ * row1Norm[2]
4261
4322
  ];
4262
- const scaleZ = pLength(row2Proj);
4263
- const row2Norm = normalize(row2Proj);
4323
+ const row2Norm = normalize$1(row2Proj);
4324
+ const determinant = row0[0] * cross[0] + row0[1] * cross[1] + row0[2] * cross[2];
4325
+ const scaleZ = Math.hypot(...row2Proj) * (determinant < 0 ? -1 : 1);
4264
4326
  // Build rotation matrix from orthonormalized vectors
4265
4327
  const r00 = row0Norm[0], r01 = row1Norm[0], r02 = row2Norm[0];
4266
4328
  const r10 = row0Norm[1], r11 = row1Norm[1], r12 = row2Norm[1];
@@ -4297,7 +4359,6 @@
4297
4359
  qz = 0.25 * s;
4298
4360
  }
4299
4361
  [qx, qy, qz] = toZero([qx, qy, qz]);
4300
- // const q = gcd(qx, gcd(qy, qz));
4301
4362
  let q = [Math.abs(qx), Math.abs(qy), Math.abs(qz)].reduce((acc, curr) => {
4302
4363
  if (acc == 0 || (curr > 0 && curr < acc)) {
4303
4364
  acc = curr;
@@ -4342,16 +4403,16 @@
4342
4403
  // https://drafts.csswg.org/css-transforms-1/#2d-matrix
4343
4404
  function is2DMatrix(matrix) {
4344
4405
  // 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;
4406
+ return matrix[2] === 0 &&
4407
+ matrix[3] === 0 &&
4408
+ matrix[6] === 0 &&
4409
+ matrix[7] === 0 &&
4410
+ matrix[8] === 0 &&
4411
+ matrix[9] === 0 &&
4412
+ matrix[11] === 0 &&
4413
+ matrix[14] === 0 &&
4414
+ matrix[10] === 1 &&
4415
+ matrix[15] === 1;
4355
4416
  }
4356
4417
 
4357
4418
  /**
@@ -5453,7 +5514,7 @@
5453
5514
  }
5454
5515
  if (token.typ == exports.EnumToken.IdenTokenType) {
5455
5516
  // named color
5456
- return token.val.toLowerCase() in COLORS_NAMES;
5517
+ return token.val.toLowerCase() in COLORS_NAMES || 'currentcolor' === token.val.toLowerCase() || 'transparent' === token.val.toLowerCase();
5457
5518
  }
5458
5519
  let isLegacySyntax = false;
5459
5520
  if (token.typ == exports.EnumToken.FunctionTokenType) {
@@ -5506,8 +5567,13 @@
5506
5567
  return false;
5507
5568
  }
5508
5569
  }
5509
- if (children[i].typ == exports.EnumToken.FunctionTokenType && !mathFuncs.includes(children[i].val)) {
5510
- return false;
5570
+ if (children[i].typ == exports.EnumToken.FunctionTokenType) {
5571
+ if ('var' == children[i].val.toLowerCase()) {
5572
+ continue;
5573
+ }
5574
+ if (!mathFuncs.includes(children[i].val)) {
5575
+ return false;
5576
+ }
5511
5577
  }
5512
5578
  }
5513
5579
  if (children.length == 4 || (isRelative && children.length == 6)) {
@@ -5794,23 +5860,29 @@
5794
5860
  }
5795
5861
  return true;
5796
5862
  }
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
- }
5863
+ // export function isDimension(name: string) {
5864
+ //
5865
+ // let index: number = name.length;
5866
+ //
5867
+ // while (index--) {
5868
+ //
5869
+ // if (isLetter(<number>name.charCodeAt(index))) {
5870
+ //
5871
+ // continue
5872
+ // }
5873
+ //
5874
+ // index++;
5875
+ // break;
5876
+ // }
5877
+ //
5878
+ // const number: string = name.slice(0, index);
5879
+ // return number.length > 0 && isIdentStart(name.charCodeAt(index)) && isNumber(number);
5880
+ // }
5809
5881
  function isPercentage(name) {
5810
5882
  return name.endsWith('%') && isNumber(name.slice(0, -1));
5811
5883
  }
5812
- function isFlex(name) {
5813
- return name.endsWith('fr') && isNumber(name.slice(0, -2));
5884
+ function isFlex(dimension) {
5885
+ return 'unit' in dimension && 'fr' == dimension.unit.toLowerCase();
5814
5886
  }
5815
5887
  function parseDimension(name) {
5816
5888
  let index = name.length;
@@ -5826,6 +5898,9 @@
5826
5898
  val: +name.slice(0, index),
5827
5899
  unit: name.slice(index)
5828
5900
  };
5901
+ if (index < 0 || Number.isNaN(dimension.val)) {
5902
+ return null;
5903
+ }
5829
5904
  if (isAngle(dimension)) {
5830
5905
  // @ts-ignore
5831
5906
  dimension.typ = exports.EnumToken.AngleTokenType;
@@ -5849,6 +5924,10 @@
5849
5924
  // @ts-ignore
5850
5925
  dimension.typ = exports.EnumToken.FrequencyTokenType;
5851
5926
  }
5927
+ else if (isFlex(dimension)) {
5928
+ // @ts-ignore
5929
+ dimension.typ = exports.EnumToken.FlexTokenType;
5930
+ }
5852
5931
  return dimension;
5853
5932
  }
5854
5933
  function isHexColor(name) {
@@ -6507,6 +6586,9 @@
6507
6586
  },
6508
6587
  animation: {
6509
6588
  shorthand: "animation",
6589
+ separator: {
6590
+ typ: "Comma"
6591
+ },
6510
6592
  pattern: "animation-name animation-duration animation-timing-function animation-delay animation-iteration-count animation-direction animation-fill-mode animation-play-state animation-timeline",
6511
6593
  "default": [
6512
6594
  "1",
@@ -7457,6 +7539,60 @@
7457
7539
  });
7458
7540
  return null;
7459
7541
  }
7542
+ if ('composes' == node.nam.toLowerCase()) {
7543
+ let left = [];
7544
+ let right = [];
7545
+ let current = 0;
7546
+ let hasFrom = 0;
7547
+ for (; current < node.val.length; current++) {
7548
+ if (exports.EnumToken.WhitespaceTokenType == node.val[current].typ || exports.EnumToken.CommentTokenType == node.val[current].typ) {
7549
+ if (!hasFrom) {
7550
+ left.push(node.val[current]);
7551
+ }
7552
+ else {
7553
+ right.push(node.val[current]);
7554
+ }
7555
+ continue;
7556
+ }
7557
+ if (exports.EnumToken.IdenTokenType == node.val[current].typ || exports.EnumToken.DashedIdenTokenType == node.val[current].typ || exports.EnumToken.StringTokenType == node.val[current].typ) {
7558
+ if (exports.EnumToken.IdenTokenType == node.val[current].typ) {
7559
+ if ('from' == node.val[current].val) {
7560
+ if (hasFrom) {
7561
+ return null;
7562
+ }
7563
+ hasFrom++;
7564
+ continue;
7565
+ }
7566
+ }
7567
+ if (hasFrom) {
7568
+ right.push(node.val[current]);
7569
+ }
7570
+ else {
7571
+ left.push(node.val[current]);
7572
+ }
7573
+ continue;
7574
+ }
7575
+ break;
7576
+ }
7577
+ if (hasFrom <= 1 && current > 0) {
7578
+ if (hasFrom == 0) {
7579
+ node.val.splice(0, left.length, {
7580
+ typ: exports.EnumToken.ComposesSelectorNodeType,
7581
+ l: left,
7582
+ r: null
7583
+ });
7584
+ }
7585
+ else {
7586
+ node.val.splice(0, current, {
7587
+ typ: exports.EnumToken.ComposesSelectorNodeType,
7588
+ l: left,
7589
+ r: right.reduce((a, b) => {
7590
+ return a == null ? b : b.typ == exports.EnumToken.WhitespaceTokenType || b.typ == exports.EnumToken.CommentTokenType ? a : b;
7591
+ }, null)
7592
+ });
7593
+ }
7594
+ }
7595
+ }
7460
7596
  for (const { value: val, parent } of walkValues(node.val, node)) {
7461
7597
  if (val.typ == exports.EnumToken.AttrTokenType && val.chi.every((t) => [exports.EnumToken.IdenTokenType, exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(t.typ))) {
7462
7598
  // @ts-ignore
@@ -7503,6 +7639,13 @@
7503
7639
  return buffer.length > 0 ? result + buffer : result;
7504
7640
  }
7505
7641
 
7642
+ function dasherize(value) {
7643
+ return value.replace(/([A-Z])/g, (all, one) => `-${one.toLowerCase()}`);
7644
+ }
7645
+ function camelize(value) {
7646
+ return value.replace(/-([a-z])/g, (all, one) => one.toUpperCase());
7647
+ }
7648
+
7506
7649
  // from https://github.com/Rich-Harris/vlq/tree/master
7507
7650
  // credit: Rich Harris
7508
7651
  const integer_to_char = {};
@@ -7649,9 +7792,10 @@
7649
7792
  * render ast
7650
7793
  * @param data
7651
7794
  * @param options
7795
+ * @param mapping
7652
7796
  * @private
7653
7797
  */
7654
- function doRender(data, options = {}) {
7798
+ function doRender(data, options = {}, mapping) {
7655
7799
  const minify = options.minify ?? true;
7656
7800
  const beautify = options.beautify ?? !minify;
7657
7801
  options = {
@@ -7688,12 +7832,23 @@
7688
7832
  const errors = [];
7689
7833
  const sourcemap = options.sourcemap ? new SourceMap : null;
7690
7834
  const cache = Object.create(null);
7835
+ const position = {
7836
+ ind: 0,
7837
+ lin: 1,
7838
+ col: 1
7839
+ };
7840
+ let code = '';
7841
+ if (mapping != null) {
7842
+ if (mapping.importMapping != null) {
7843
+ for (const [key, value] of Object.entries(mapping.importMapping)) {
7844
+ code += `:import("${key}")${options.indent}{${options.newLine}${Object.entries(value).reduce((acc, [k, v]) => acc + (acc.length > 0 ? options.newLine : '') + `${options.indent}${v}:${options.indent}${k};`, '')}${options.newLine}}${options.newLine}`;
7845
+ }
7846
+ }
7847
+ code += `:export${options.indent}{${options.newLine}${Object.entries(mapping.mapping).reduce((acc, [k, v]) => acc + (acc.length > 0 ? options.newLine : '') + `${options.indent}${k}:${options.indent}${v};`, '')}${options.newLine}}${options.newLine}`;
7848
+ update(position, code);
7849
+ }
7691
7850
  const result = {
7692
- code: renderAstNode(options.expandNestingRules ? expand(data) : data, options, sourcemap, {
7693
- ind: 0,
7694
- lin: 1,
7695
- col: 1
7696
- }, errors, function reducer(acc, curr) {
7851
+ code: code + renderAstNode(options.expandNestingRules && [exports.EnumToken.StyleSheetNodeType, exports.EnumToken.AtRuleNodeType, exports.EnumToken.RuleNodeType].includes(data.typ) && 'chi' in data ? expand(data) : data, options, sourcemap, position, errors, function reducer(acc, curr) {
7697
7852
  if (curr.typ == exports.EnumToken.CommentTokenType && options.removeComments) {
7698
7853
  if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
7699
7854
  return acc;
@@ -7829,7 +7984,7 @@
7829
7984
  str = `${node.nam}:${options.indent}${(options.minify ? filterValues(node.val) : node.val).reduce(reducer, '').trimEnd()};`;
7830
7985
  }
7831
7986
  else if (node.typ == exports.EnumToken.AtRuleNodeType && !('chi' in node)) {
7832
- str = `${data.val === '' ? '' : options.indent || ' '}${data.val};`;
7987
+ str = `${node.val === '' ? '' : options.indent || ' '}${node.val};`;
7833
7988
  }
7834
7989
  else {
7835
7990
  str = renderAstNode(node, options, sourcemap, { ...position }, errors, reducer, cache, level + 1, indents);
@@ -7852,6 +8007,11 @@
7852
8007
  return `@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val}${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
7853
8008
  }
7854
8009
  return data.sel + `${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
8010
+ case exports.EnumToken.CssVariableTokenType:
8011
+ case exports.EnumToken.CssVariableImportTokenType:
8012
+ return `@value ${data.nam}:${options.indent}${filterValues((options.minify ? data.val : data.val)).reduce(reducer, '').trim()};`;
8013
+ case exports.EnumToken.CssVariableDeclarationMapTokenType:
8014
+ return `@value ${filterValues(data.vars).reduce((acc, curr) => acc + renderToken(curr), '').trim()} from ${filterValues(data.from).reduce((acc, curr) => acc + renderToken(curr), '').trim()};`;
7855
8015
  case exports.EnumToken.InvalidDeclarationNodeType:
7856
8016
  case exports.EnumToken.InvalidRuleTokenType:
7857
8017
  case exports.EnumToken.InvalidAtRuleTokenType:
@@ -8006,6 +8166,8 @@
8006
8166
  case exports.EnumToken.NameSpaceAttributeTokenType:
8007
8167
  return (token.l == null ? '' : renderToken(token.l, options, cache, reducer, errors)) + '|' +
8008
8168
  renderToken(token.r, options, cache, reducer, errors);
8169
+ case exports.EnumToken.ComposesSelectorNodeType:
8170
+ return token.l.reduce((acc, curr) => acc + renderToken(curr, options, cache), '') + (token.r == null ? '' : ' from ' + renderToken(token.r, options, cache, reducer, errors));
8009
8171
  case exports.EnumToken.BlockStartTokenType:
8010
8172
  return '{';
8011
8173
  case exports.EnumToken.BlockEndTokenType:
@@ -8376,23 +8538,27 @@
8376
8538
  }
8377
8539
  }
8378
8540
  function match$1(parseInfo, input) {
8379
- return parseInfo.stream.slice(parseInfo.currentPosition.ind + 1, parseInfo.currentPosition.ind + input.length + 1) == input;
8541
+ const position = parseInfo.currentPosition.ind - parseInfo.offset;
8542
+ return parseInfo.stream.slice(position + 1, position + input.length + 1) == input;
8380
8543
  }
8381
8544
  function peek(parseInfo, count = 1) {
8382
8545
  if (count == 1) {
8383
- return parseInfo.stream.charAt(parseInfo.currentPosition.ind + 1);
8546
+ return parseInfo.stream.charAt(parseInfo.currentPosition.ind - parseInfo.offset + 1);
8384
8547
  }
8385
- return parseInfo.stream.slice(parseInfo.currentPosition.ind + 1, parseInfo.currentPosition.ind + count + 1);
8548
+ const position = parseInfo.currentPosition.ind - parseInfo.offset;
8549
+ return parseInfo.stream.slice(position + 1, position + count + 1);
8386
8550
  }
8387
8551
  function prev(parseInfo) {
8388
- return parseInfo.stream.charAt(parseInfo.currentPosition.ind - 1);
8552
+ return parseInfo.offset == parseInfo.currentPosition.ind ? parseInfo.buffer.slice(-1) : parseInfo.stream.charAt(parseInfo.currentPosition.ind - parseInfo.offset - 1);
8389
8553
  }
8390
8554
  function next(parseInfo, count = 1) {
8391
8555
  let char = '';
8392
8556
  let chr = '';
8393
- while (count-- && (chr = parseInfo.stream.charAt(parseInfo.currentPosition.ind + 1))) {
8557
+ let position = parseInfo.currentPosition.ind - parseInfo.offset;
8558
+ while (count-- && (chr = parseInfo.stream.charAt(position + 1))) {
8394
8559
  char += chr;
8395
- const codepoint = parseInfo.stream.charCodeAt(++parseInfo.currentPosition.ind);
8560
+ const codepoint = parseInfo.stream.charCodeAt(++position);
8561
+ ++parseInfo.currentPosition.ind;
8396
8562
  if (isNewLine(codepoint)) {
8397
8563
  parseInfo.currentPosition.lin++;
8398
8564
  parseInfo.currentPosition.col = 0;
@@ -8420,13 +8586,15 @@
8420
8586
  yield pushToken(buffer, parseInfo);
8421
8587
  buffer = '';
8422
8588
  }
8589
+ buffer += value;
8423
8590
  while (value = next(parseInfo)) {
8424
8591
  charCode = value.charCodeAt(0);
8425
8592
  if (!isWhiteSpace(charCode)) {
8426
8593
  break;
8427
8594
  }
8595
+ buffer += value;
8428
8596
  }
8429
- yield pushToken('', parseInfo, exports.EnumToken.WhitespaceTokenType);
8597
+ yield pushToken(buffer, parseInfo, exports.EnumToken.WhitespaceTokenType);
8430
8598
  buffer = '';
8431
8599
  }
8432
8600
  switch (charCode) {
@@ -8474,8 +8642,7 @@
8474
8642
  buffer = '';
8475
8643
  }
8476
8644
  if (match$1(parseInfo, '=')) {
8477
- yield pushToken('', parseInfo, exports.EnumToken.LteTokenType);
8478
- next(parseInfo);
8645
+ yield pushToken(value + next(parseInfo), parseInfo, exports.EnumToken.LteTokenType);
8479
8646
  break;
8480
8647
  }
8481
8648
  buffer += value;
@@ -8530,8 +8697,7 @@
8530
8697
  }
8531
8698
  if (charCode == 124 /* TokenMap.PIPE */) {
8532
8699
  if (match$1(parseInfo, '|')) {
8533
- next(parseInfo);
8534
- yield pushToken('', parseInfo, exports.EnumToken.ColumnCombinatorTokenType);
8700
+ yield pushToken(value + next(parseInfo), parseInfo, exports.EnumToken.ColumnCombinatorTokenType);
8535
8701
  }
8536
8702
  else if (match$1(parseInfo, '=')) {
8537
8703
  buffer += next(parseInfo);
@@ -8585,11 +8751,10 @@
8585
8751
  buffer = '';
8586
8752
  }
8587
8753
  if (match$1(parseInfo, '=')) {
8588
- yield pushToken('', parseInfo, exports.EnumToken.GteTokenType);
8589
- next(parseInfo);
8754
+ yield pushToken(value + next(parseInfo), parseInfo, exports.EnumToken.GteTokenType);
8590
8755
  }
8591
8756
  else {
8592
- yield pushToken('', parseInfo, exports.EnumToken.GtTokenType);
8757
+ yield pushToken(value, parseInfo, exports.EnumToken.GtTokenType);
8593
8758
  }
8594
8759
  consumeWhiteSpace(parseInfo);
8595
8760
  break;
@@ -8640,7 +8805,7 @@
8640
8805
  yield pushToken(buffer, parseInfo);
8641
8806
  buffer = '';
8642
8807
  }
8643
- yield pushToken('', parseInfo, exports.EnumToken.EndParensTokenType);
8808
+ yield pushToken(value, parseInfo, exports.EnumToken.EndParensTokenType);
8644
8809
  break;
8645
8810
  case 40 /* TokenMap.OPEN_PAREN */:
8646
8811
  if (buffer.length == 0) {
@@ -8706,7 +8871,7 @@
8706
8871
  // ')'
8707
8872
  if (charCode == 0x29) {
8708
8873
  yield pushToken(buffer, parseInfo, hasNewLine ? exports.EnumToken.BadStringTokenType : exports.EnumToken.StringTokenType);
8709
- yield pushToken('', parseInfo, exports.EnumToken.EndParensTokenType);
8874
+ yield pushToken(value, parseInfo, exports.EnumToken.EndParensTokenType);
8710
8875
  buffer = '';
8711
8876
  break;
8712
8877
  }
@@ -8730,7 +8895,7 @@
8730
8895
  charCode = value.charCodeAt(0);
8731
8896
  if (charCode == 0x29) { // ')'
8732
8897
  yield pushToken(buffer, parseInfo, exports.EnumToken.UrlTokenTokenType);
8733
- yield pushToken('', parseInfo, exports.EnumToken.EndParensTokenType);
8898
+ yield pushToken(value, parseInfo, exports.EnumToken.EndParensTokenType);
8734
8899
  buffer = '';
8735
8900
  break;
8736
8901
  }
@@ -8764,8 +8929,7 @@
8764
8929
  buffer = '';
8765
8930
  }
8766
8931
  if (match$1(parseInfo, 'important')) {
8767
- yield pushToken('', parseInfo, exports.EnumToken.ImportantTokenType);
8768
- next(parseInfo, 9);
8932
+ yield pushToken(value + next(parseInfo, 9), parseInfo, exports.EnumToken.ImportantTokenType);
8769
8933
  buffer = '';
8770
8934
  break;
8771
8935
  }
@@ -8810,6 +8974,7 @@
8810
8974
  const parseInfo = {
8811
8975
  stream: '',
8812
8976
  buffer: '',
8977
+ offset: 0,
8813
8978
  position: { ind: 0, lin: 1, col: 1 },
8814
8979
  currentPosition: { ind: -1, lin: 1, col: 0 }
8815
8980
  };
@@ -8817,7 +8982,17 @@
8817
8982
  const reader = input.getReader();
8818
8983
  while (true) {
8819
8984
  const { done, value } = await reader.read();
8820
- parseInfo.stream += ArrayBuffer.isView(value) ? decoder.decode(value, { stream: true }) : value;
8985
+ const stream = ArrayBuffer.isView(value) ? decoder.decode(value, { stream: true }) : value;
8986
+ if (!done) {
8987
+ if (parseInfo.stream.length > 2) {
8988
+ parseInfo.stream = parseInfo.stream.slice(-2) + stream;
8989
+ parseInfo.offset = parseInfo.currentPosition.ind - 1;
8990
+ }
8991
+ else {
8992
+ parseInfo.stream = stream;
8993
+ parseInfo.offset = Math.max(0, parseInfo.currentPosition.ind);
8994
+ }
8995
+ }
8821
8996
  yield* tokenize$1(parseInfo, done);
8822
8997
  if (done) {
8823
8998
  break;
@@ -9580,7 +9755,7 @@
9580
9755
  syntax: "[ <counter-name> <integer>? ]+ | none"
9581
9756
  },
9582
9757
  cursor: {
9583
- syntax: "[ [ <url> [ <x> <y> ]? , ]* [ auto | default | none | context-menu | help | pointer | progress | wait | cell | crosshair | text | vertical-text | alias | copy | move | no-drop | not-allowed | e-resize | n-resize | ne-resize | nw-resize | s-resize | se-resize | sw-resize | w-resize | ew-resize | ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | all-scroll | zoom-in | zoom-out | grab | grabbing ] ] [ [ <url> [ <x> <y> ]? , ]* [ auto | default | none | context-menu | help | pointer | progress | wait | cell | crosshair | text | vertical-text | alias | copy | move | no-drop | not-allowed | e-resize | n-resize | ne-resize | nw-resize | s-resize | se-resize | sw-resize | w-resize | ew-resize | ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | all-scroll | zoom-in | zoom-out | grab | grabbing | hand | -webkit-grab | -webkit-grabbing | -webkit-zoom-in | -webkit-zoom-out | -moz-grab | -moz-grabbing | -moz-zoom-in | -moz-zoom-out ] ]"
9758
+ syntax: "[ [ <url> [ <x> <y> ]? , ]* <cursor-predefined> ] [ [ <url> [ <x> <y> ]? , ]* [ auto | default | none | context-menu | help | pointer | progress | wait | cell | crosshair | text | vertical-text | alias | copy | move | no-drop | not-allowed | e-resize | n-resize | ne-resize | nw-resize | s-resize | se-resize | sw-resize | w-resize | ew-resize | ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | all-scroll | zoom-in | zoom-out | grab | grabbing | hand | -webkit-grab | -webkit-grabbing | -webkit-zoom-in | -webkit-zoom-out | -moz-grab | -moz-grabbing | -moz-zoom-in | -moz-zoom-out ] ]"
9584
9759
  },
9585
9760
  cx: {
9586
9761
  syntax: "<length> | <percentage>"
@@ -10808,6 +10983,12 @@
10808
10983
  },
10809
10984
  "white-space-trim": {
10810
10985
  syntax: "none | discard-before || discard-after || discard-inner"
10986
+ },
10987
+ composes: {
10988
+ syntax: "<composes-selector>#"
10989
+ },
10990
+ "composes-selector": {
10991
+ syntax: "<ident>+ [from [global&&<string>]]?"
10811
10992
  }
10812
10993
  };
10813
10994
  var functions = {
@@ -10833,7 +11014,7 @@
10833
11014
  syntax: "atan2( <calc-sum>, <calc-sum> )"
10834
11015
  },
10835
11016
  attr: {
10836
- syntax: "attr( <attr-name> <type-or-unit>? [, <attr-fallback> ]? )"
11017
+ syntax: "attr( <attr-name> <attr-type>? , <declaration-value>? )"
10837
11018
  },
10838
11019
  blur: {
10839
11020
  syntax: "blur( <length>? )"
@@ -11186,7 +11367,7 @@
11186
11367
  syntax: "scroll | fixed | local"
11187
11368
  },
11188
11369
  "attr()": {
11189
- syntax: "attr( <attr-name> <type-or-unit>? [, <attr-fallback> ]? )"
11370
+ syntax: "attr( <attr-name> <attr-type>? , <declaration-value>? )"
11190
11371
  },
11191
11372
  "attr-matcher": {
11192
11373
  syntax: "[ '~' | '|' | '^' | '$' | '*' ]? '='"
@@ -11194,6 +11375,9 @@
11194
11375
  "attr-modifier": {
11195
11376
  syntax: "i | s"
11196
11377
  },
11378
+ "attr-type": {
11379
+ syntax: "type( <syntax> ) | raw-string | number | <attr-unit>"
11380
+ },
11197
11381
  "attribute-selector": {
11198
11382
  syntax: "'[' <wq-name> ']' | '[' <wq-name> <attr-matcher> [ <string-token> | <ident-token> ] <attr-modifier>? ']'"
11199
11383
  },
@@ -11407,6 +11591,9 @@
11407
11591
  "cubic-bezier-easing-function": {
11408
11592
  syntax: "ease | ease-in | ease-out | ease-in-out | cubic-bezier( <number [0,1]> , <number> , <number [0,1]> , <number> )"
11409
11593
  },
11594
+ "cursor-predefined": {
11595
+ syntax: "auto | default | none | context-menu | help | pointer | progress | wait | cell | crosshair | text | vertical-text | alias | copy | move | no-drop | not-allowed | e-resize | n-resize | ne-resize | nw-resize | s-resize | se-resize | sw-resize | w-resize | ew-resize | ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | all-scroll | zoom-in | zoom-out | grab | grabbing"
11596
+ },
11410
11597
  "custom-color-space": {
11411
11598
  syntax: "<dashed-ident>"
11412
11599
  },
@@ -13017,7 +13204,27 @@
13017
13204
  }
13018
13205
  },
13019
13206
  "@nest": {
13020
- syntax: "<complex-selector-list>"
13207
+ },
13208
+ "@stylistic": {
13209
+ syntax: " @stylistic { <feature-value-declaration-list> } "
13210
+ },
13211
+ "@historical-forms": {
13212
+ syntax: " @historical-forms { <feature-value-declaration-list> } "
13213
+ },
13214
+ "@styleset": {
13215
+ syntax: " @styleset { <feature-value-declaration-list> } "
13216
+ },
13217
+ "@character-variant": {
13218
+ syntax: " @character-variant { <feature-value-declaration-list> } "
13219
+ },
13220
+ "@swash": {
13221
+ syntax: " @swash { <feature-value-declaration-list> } "
13222
+ },
13223
+ "@ornaments": {
13224
+ syntax: " @ornaments { <feature-value-declaration-list> } "
13225
+ },
13226
+ "@annotation": {
13227
+ syntax: " @annotation { <feature-value-declaration-list> } "
13021
13228
  }
13022
13229
  };
13023
13230
  var config$3 = {
@@ -13080,7 +13287,6 @@
13080
13287
  ValidationSyntaxGroupEnum["Selectors"] = "selectors";
13081
13288
  ValidationSyntaxGroupEnum["AtRules"] = "atRules";
13082
13289
  })(ValidationSyntaxGroupEnum || (ValidationSyntaxGroupEnum = {}));
13083
-
13084
13290
  const skipped = [
13085
13291
  ValidationTokenEnum.Star,
13086
13292
  ValidationTokenEnum.HashMark,
@@ -14161,7 +14367,6 @@
14161
14367
  const index = group + '.' + keys.join('.');
14162
14368
  // @ts-ignore
14163
14369
  if (!parsedSyntaxes.has(index)) {
14164
- // @ts-ignore
14165
14370
  const syntax = parseSyntax(obj.syntax);
14166
14371
  // @ts-ignore
14167
14372
  parsedSyntaxes.set(index, syntax.chi);
@@ -14310,8 +14515,7 @@
14310
14515
  node: root,
14311
14516
  // @ts-ignore
14312
14517
  syntax: null,
14313
- error: 'expected selector',
14314
- tokens
14518
+ error: 'expected selector'
14315
14519
  };
14316
14520
  }
14317
14521
  tokens = tokens.slice();
@@ -14559,15 +14763,12 @@
14559
14763
  return result;
14560
14764
  }
14561
14765
  }
14766
+ // @ts-ignore
14562
14767
  return {
14563
14768
  valid: SyntaxValidationResult.Valid,
14564
- matches: [],
14565
- // @ts-ignore
14566
14769
  node: root,
14567
- // @ts-ignore
14568
14770
  syntax: null,
14569
- error: '',
14570
- tokens
14771
+ error: ''
14571
14772
  };
14572
14773
  }
14573
14774
 
@@ -14612,6 +14813,116 @@
14612
14813
  const config$2 = getSyntaxConfig();
14613
14814
  // @ts-ignore
14614
14815
  const allValues = getSyntaxConfig()["declarations" /* ValidationSyntaxGroupEnum.Declarations */].all.syntax.trim().split(/[\s|]+/g);
14816
+ /**
14817
+ * Check if a node is allowed as child in a given context
14818
+ * @param node
14819
+ * @param context
14820
+ */
14821
+ function isNodeAllowedInContext(node, context) {
14822
+ if (node.typ == exports.EnumToken.CommentNodeType || context == null) {
14823
+ return true;
14824
+ }
14825
+ switch (context?.typ) {
14826
+ case exports.EnumToken.StyleSheetNodeType:
14827
+ case exports.EnumToken.RuleNodeType:
14828
+ return node.typ == exports.EnumToken.RuleNodeType ||
14829
+ node.typ == exports.EnumToken.AtRuleNodeType ||
14830
+ node.typ == exports.EnumToken.KeyframesAtRuleNodeType ||
14831
+ (node.typ == exports.EnumToken.DeclarationNodeType && context.typ == exports.EnumToken.RuleNodeType) ||
14832
+ (node.typ == exports.EnumToken.CDOCOMMNodeType && context.typ == exports.EnumToken.StyleSheetNodeType);
14833
+ case exports.EnumToken.KeyframesAtRuleNodeType:
14834
+ return node.typ == exports.EnumToken.KeyFramesRuleNodeType;
14835
+ case exports.EnumToken.KeyFramesRuleNodeType:
14836
+ return node.typ == exports.EnumToken.DeclarationNodeType;
14837
+ case exports.EnumToken.AtRuleNodeType:
14838
+ // @ts-ignore
14839
+ const syntax = getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, '@' + context.nam)?.[0].chi ?? null;
14840
+ //
14841
+ if (syntax == null) {
14842
+ // console.error(`syntax: Not found ${ValidationSyntaxGroupEnum.AtRules}@${(context as AstAtRule).nam}`);
14843
+ return true;
14844
+ }
14845
+ const stack = syntax.slice();
14846
+ for (const child of stack) {
14847
+ if (Array.isArray(child)) {
14848
+ stack.push(...child);
14849
+ continue;
14850
+ }
14851
+ if ('chi' in child && Array.isArray(child.chi)) {
14852
+ stack.push(...child.chi);
14853
+ continue;
14854
+ }
14855
+ // @ts-ignore
14856
+ if (child.l != null) {
14857
+ // @ts-ignore
14858
+ stack.push(child.l);
14859
+ // @ts-ignore
14860
+ if (child.r != null) {
14861
+ // @ts-ignore
14862
+ stack.push(...(Array.isArray(child.r) ? child.r : [child.r]));
14863
+ }
14864
+ continue;
14865
+ }
14866
+ if (node.typ == exports.EnumToken.DeclarationNodeType) {
14867
+ if (child.typ == ValidationTokenEnum.DeclarationDefinitionToken) {
14868
+ if (node.nam == child.nam) {
14869
+ return true;
14870
+ }
14871
+ }
14872
+ }
14873
+ if (child.typ == ValidationTokenEnum.PropertyType) {
14874
+ if (['group-rule-body', 'block-contents', 'rule-list', 'stylesheet'].includes(child.val)) {
14875
+ if ((node.typ == exports.EnumToken.RuleNodeType ||
14876
+ node.typ == exports.EnumToken.AtRuleNodeType ||
14877
+ node.typ == exports.EnumToken.KeyframesAtRuleNodeType)) {
14878
+ return true;
14879
+ }
14880
+ if (node.typ == exports.EnumToken.DeclarationNodeType) {
14881
+ let parent = node.parent;
14882
+ while (parent != null) {
14883
+ if (parent.parent?.typ == exports.EnumToken.RuleNodeType) {
14884
+ return true;
14885
+ }
14886
+ parent = parent.parent;
14887
+ }
14888
+ }
14889
+ }
14890
+ if (['declaration-list', 'feature-value-declaration'].includes(child.val) && node.typ == exports.EnumToken.DeclarationNodeType) {
14891
+ return true;
14892
+ }
14893
+ if (child.val == 'page-body' && (node.typ == exports.EnumToken.DeclarationNodeType || (node.typ == exports.EnumToken.AtRuleNodeType && [
14894
+ 'top-left-corner', 'top-left', 'top-center', 'top-right', 'top-right-corner',
14895
+ 'bottom-left-corner', 'bottom-left', 'bottom-center', 'bottom-right', 'bottom-right-corner',
14896
+ 'left-top', 'left-middle', 'left-bottom', 'right-top', 'right-middle', 'right-bottom'
14897
+ ].includes(node.nam)))) {
14898
+ return true;
14899
+ }
14900
+ if (child.val == 'feature-value-block-list' &&
14901
+ (node.typ == exports.EnumToken.AtRuleNodeType && ['stylistic', 'historical-forms', 'styleset', 'character-variant', 'swash', 'ornaments', 'annotation'].includes(node.nam))) {
14902
+ return true;
14903
+ }
14904
+ if (['feature-value-declaration-list', 'feature-value-declaration'].includes(child.val) && node.typ == exports.EnumToken.DeclarationNodeType) {
14905
+ return true;
14906
+ }
14907
+ if (child.val == 'page-body') {
14908
+ if (node.typ == exports.EnumToken.DeclarationNodeType) {
14909
+ return true;
14910
+ }
14911
+ }
14912
+ // console.error(`isNodeAllowedInContext: Not found ${(child as ValidationPropertyToken).val}`, {
14913
+ // child,
14914
+ // node
14915
+ // });
14916
+ }
14917
+ }
14918
+ break;
14919
+ }
14920
+ return false;
14921
+ }
14922
+ /**
14923
+ * Create a syntax validation context from a list of tokens
14924
+ * @param input
14925
+ */
14615
14926
  function createContext(input) {
14616
14927
  const values = input.slice();
14617
14928
  const result = values.filter(token => token.typ != exports.EnumToken.CommentTokenType).slice();
@@ -14672,7 +14983,22 @@
14672
14983
  }
14673
14984
  };
14674
14985
  }
14675
- function evaluateSyntax(node, options) {
14986
+ /**
14987
+ * Evaluate the validity of the syntax of a node
14988
+ * @param node
14989
+ * @param parent
14990
+ * @param options
14991
+ */
14992
+ function evaluateSyntax(node, parent, options) {
14993
+ if (node.validSyntax) {
14994
+ return {
14995
+ valid: SyntaxValidationResult.Valid,
14996
+ node,
14997
+ syntax: null,
14998
+ error: '',
14999
+ context: []
15000
+ };
15001
+ }
14676
15002
  let ast;
14677
15003
  let result;
14678
15004
  switch (node.typ) {
@@ -14680,25 +15006,34 @@
14680
15006
  if (node.nam.startsWith('--')) {
14681
15007
  break;
14682
15008
  }
15009
+ let token = null;
15010
+ let values = node.val.slice();
14683
15011
  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) {
15012
+ while (values.length > 0) {
15013
+ token = values.at(-1);
15014
+ if (token.typ == exports.EnumToken.WhitespaceTokenType || token.typ == exports.EnumToken.CommentTokenType) {
15015
+ values.pop();
15016
+ }
15017
+ else {
15018
+ if (token.typ == exports.EnumToken.ImportantTokenType) {
14690
15019
  values.pop();
14691
- }
14692
- else {
14693
- if (token.typ == exports.EnumToken.ImportantTokenType) {
15020
+ if (values.at(-1)?.typ == exports.EnumToken.WhitespaceTokenType) {
14694
15021
  values.pop();
14695
- if (values.at(-1)?.typ == exports.EnumToken.WhitespaceTokenType) {
14696
- values.pop();
14697
- }
14698
15022
  }
14699
- break;
15023
+ }
15024
+ break;
15025
+ }
15026
+ }
15027
+ if (ast == null) {
15028
+ if (parent?.typ == exports.EnumToken.AtRuleNodeType) {
15029
+ ast = (getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, ['@' + parent.nam, 'descriptors', node.nam]));
15030
+ if (ast == null) {
15031
+ ast = (getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, ['@' + parent.nam, 'descriptors', node.nam]) ?? getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, '@' + parent.nam))?.[0]?.chi;
15032
+ values = [{ ...node, val: values }];
14700
15033
  }
14701
15034
  }
15035
+ }
15036
+ if (ast != null) {
14702
15037
  result = doEvaluateSyntax(ast, createContext(values), { ...options, visited: new WeakMap() });
14703
15038
  if (result.valid == SyntaxValidationResult.Valid && !result.context.done()) {
14704
15039
  let token = null;
@@ -14790,7 +15125,7 @@
14790
15125
  continue;
14791
15126
  }
14792
15127
  }
14793
- else if (options.occurence !== false && syntax.occurence != null) {
15128
+ else if (options.occurrence !== false && syntax.occurence != null) {
14794
15129
  result = matchOccurence(syntax, context, options);
14795
15130
  }
14796
15131
  else if (options.atLeastOnce !== false && syntax.atLeastOnce) {
@@ -14879,7 +15214,7 @@
14879
15214
  result = doEvaluateSyntax([syntax], createContext(tokens), {
14880
15215
  ...options,
14881
15216
  isList: false,
14882
- occurence: false
15217
+ occurrence: false
14883
15218
  });
14884
15219
  if (result.valid == SyntaxValidationResult.Valid) {
14885
15220
  context = con.clone();
@@ -14914,7 +15249,7 @@
14914
15249
  let counter = 0;
14915
15250
  let result;
14916
15251
  do {
14917
- result = match(syntax, context.clone(), { ...options, occurence: false });
15252
+ result = match(syntax, context.clone(), { ...options, occurrence: false });
14918
15253
  if (result.valid == SyntaxValidationResult.Drop) {
14919
15254
  break;
14920
15255
  }
@@ -14965,7 +15300,7 @@
14965
15300
  ...options,
14966
15301
  isRepeatable: null,
14967
15302
  isList: null,
14968
- occurence: null,
15303
+ occurrence: null,
14969
15304
  atLeastOnce: null
14970
15305
  });
14971
15306
  if (result.valid == SyntaxValidationResult.Valid) {
@@ -14977,7 +15312,7 @@
14977
15312
  case ValidationTokenEnum.Keyword:
14978
15313
  success = (token.typ == exports.EnumToken.IdenTokenType || token.typ == exports.EnumToken.DashedIdenTokenType || isIdentColor(token)) &&
14979
15314
  (token.val == syntax.val ||
14980
- syntax.val === token.val?.toLowerCase?.() ||
15315
+ syntax.val.toLowerCase() === token.val?.toLowerCase?.() ||
14981
15316
  // config.declarations.all
14982
15317
  allValues.includes(token.val.toLowerCase()));
14983
15318
  if (success) {
@@ -15016,7 +15351,7 @@
15016
15351
  ...options,
15017
15352
  isRepeatable: null,
15018
15353
  isList: null,
15019
- occurence: null,
15354
+ occurrence: null,
15020
15355
  atLeastOnce: null
15021
15356
  });
15022
15357
  case ValidationTokenEnum.Comma:
@@ -15051,7 +15386,7 @@
15051
15386
  ...options,
15052
15387
  isRepeatable: null,
15053
15388
  isList: null,
15054
- occurence: null,
15389
+ occurrence: null,
15055
15390
  atLeastOnce: null
15056
15391
  }).valid == SyntaxValidationResult.Valid;
15057
15392
  if (success) {
@@ -15074,18 +15409,20 @@
15074
15409
  }
15075
15410
  function matchPropertyType(syntax, context, options) {
15076
15411
  if (![
15077
- 'bg-position',
15412
+ 'color',
15078
15413
  'integer',
15414
+ 'bg-position',
15415
+ 'composes-selector',
15079
15416
  'length-percentage', 'flex', 'calc-sum', 'color',
15080
15417
  'color-base', 'system-color', 'deprecated-system-color',
15081
- 'pseudo-class-selector', 'pseudo-element-selector'
15418
+ 'pseudo-class-selector', 'pseudo-element-selector', 'feature-value-declaration'
15082
15419
  ].includes(syntax.val)) {
15083
15420
  if (syntax.val in config$2["syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */]) {
15084
15421
  return doEvaluateSyntax(getParsedSyntax("syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */, syntax.val), context, {
15085
15422
  ...options,
15086
15423
  isRepeatable: null,
15087
15424
  isList: null,
15088
- occurence: null,
15425
+ occurrence: null,
15089
15426
  atLeastOnce: null
15090
15427
  });
15091
15428
  }
@@ -15097,7 +15434,7 @@
15097
15434
  ...options,
15098
15435
  isRepeatable: null,
15099
15436
  isList: null,
15100
- occurence: null,
15437
+ occurrence: null,
15101
15438
  atLeastOnce: null
15102
15439
  });
15103
15440
  if (result.valid == SyntaxValidationResult.Valid) {
@@ -15106,6 +15443,9 @@
15106
15443
  return { ...result, context };
15107
15444
  }
15108
15445
  switch (syntax.val) {
15446
+ case 'composes-selector':
15447
+ success = token.typ == exports.EnumToken.ComposesSelectorNodeType;
15448
+ break;
15109
15449
  case 'bg-position': {
15110
15450
  let val;
15111
15451
  let keyworkMatchCount = 0;
@@ -15202,6 +15542,14 @@
15202
15542
  (token.typ == exports.EnumToken.IdenTokenType && typeof Math[token.val.toUpperCase()] == 'number') ||
15203
15543
  [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
15544
  break;
15545
+ case 'declaration':
15546
+ {
15547
+ success = token.typ == exports.EnumToken.DeclarationNodeType;
15548
+ if (success) {
15549
+ success = evaluateSyntax(token, null, options).valid == SyntaxValidationResult.Valid;
15550
+ }
15551
+ }
15552
+ break;
15205
15553
  case 'declaration-value':
15206
15554
  while (!context.done()) {
15207
15555
  context.next();
@@ -15228,13 +15576,17 @@
15228
15576
  break;
15229
15577
  case 'color':
15230
15578
  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));
15579
+ success = token.typ == exports.EnumToken.ColorTokenType ||
15580
+ (token.typ == exports.EnumToken.IdenTokenType && 'currentcolor' === token.val.toLowerCase()) ||
15581
+ (token.typ == exports.EnumToken.IdenTokenType && 'transparent' === token.val.toLowerCase()) ||
15582
+ (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val) ||
15583
+ isColor(token));
15232
15584
  if (!success && token.typ == exports.EnumToken.FunctionTokenType && colorsFunc.includes(token.val)) {
15233
15585
  success = doEvaluateSyntax(getParsedSyntax("functions" /* ValidationSyntaxGroupEnum.Functions */, token.val)?.[0]?.chi, createContext(token.chi), {
15234
15586
  ...options,
15235
15587
  isRepeatable: null,
15236
15588
  isList: null,
15237
- occurence: null,
15589
+ occurrence: null,
15238
15590
  atLeastOnce: null
15239
15591
  }).valid == SyntaxValidationResult.Valid;
15240
15592
  }
@@ -15242,8 +15594,26 @@
15242
15594
  case 'hex-color':
15243
15595
  success = (token.typ == exports.EnumToken.ColorTokenType && token.kin == exports.ColorType.HEX) || (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val));
15244
15596
  break;
15597
+ case 'feature-value-declaration':
15598
+ {
15599
+ let hasNumber = false;
15600
+ success = token.typ == exports.EnumToken.DeclarationNodeType && token.val.length > 0 && token.val.every((val) => {
15601
+ if (val.typ == exports.EnumToken.WhitespaceTokenType || val.typ == exports.EnumToken.CommentTokenType) {
15602
+ return true;
15603
+ }
15604
+ 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)));
15605
+ if (success) {
15606
+ hasNumber = true;
15607
+ }
15608
+ if ('range' in syntax) {
15609
+ return success && +val.val >= +syntax.range[0] && +val.val <= +syntax.range[1];
15610
+ }
15611
+ return success;
15612
+ }) && hasNumber;
15613
+ }
15614
+ break;
15245
15615
  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)));
15616
+ success = (token.typ == exports.EnumToken.NumberTokenType && /^[+-]?\d+$/.test(token.val.toString())) || (token.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(token.val.toLowerCase()) || (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val)));
15247
15617
  if ('range' in syntax) {
15248
15618
  success = success && +token.val >= +syntax.range[0] && +token.val <= +syntax.range[1];
15249
15619
  }
@@ -15307,7 +15677,7 @@
15307
15677
  ...options,
15308
15678
  isRepeatable: null,
15309
15679
  isList: null,
15310
- occurence: null,
15680
+ occurrence: null,
15311
15681
  atLeastOnce: null
15312
15682
  }).valid == SyntaxValidationResult.Valid;
15313
15683
  }
@@ -15323,7 +15693,7 @@
15323
15693
  ...options,
15324
15694
  isRepeatable: null,
15325
15695
  isList: null,
15326
- occurence: null,
15696
+ occurrence: null,
15327
15697
  atLeastOnce: null
15328
15698
  }).valid == SyntaxValidationResult.Valid;
15329
15699
  }
@@ -15470,7 +15840,6 @@
15470
15840
  i = -1;
15471
15841
  }
15472
15842
  }
15473
- // console.error()
15474
15843
  const success = syntax.length == 0;
15475
15844
  return {
15476
15845
  valid: success ? SyntaxValidationResult.Valid : SyntaxValidationResult.Drop,
@@ -15550,6 +15919,17 @@
15550
15919
  }
15551
15920
 
15552
15921
  function validateAtRuleMedia(atRule, options, root) {
15922
+ if (!Array.isArray(atRule.chi)) {
15923
+ // @ts-ignore
15924
+ return {
15925
+ valid: SyntaxValidationResult.Drop,
15926
+ matches: [],
15927
+ node: atRule,
15928
+ syntax: '@' + atRule.nam,
15929
+ error: 'expected supports body',
15930
+ tokens: []
15931
+ };
15932
+ }
15553
15933
  // media-query-list
15554
15934
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
15555
15935
  // @ts-ignore
@@ -15782,6 +16162,17 @@
15782
16162
  }
15783
16163
 
15784
16164
  function validateAtRuleCounterStyle(atRule, options, root) {
16165
+ if (!Array.isArray(atRule.chi)) {
16166
+ // @ts-ignore
16167
+ return {
16168
+ valid: SyntaxValidationResult.Drop,
16169
+ matches: [],
16170
+ node: atRule,
16171
+ syntax: '@' + atRule.nam,
16172
+ error: 'expected supports body',
16173
+ tokens: []
16174
+ };
16175
+ }
15785
16176
  // media-query-list
15786
16177
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
15787
16178
  // @ts-ignore
@@ -15851,6 +16242,17 @@
15851
16242
  }
15852
16243
 
15853
16244
  function validateAtRulePage(atRule, options, root) {
16245
+ if (!Array.isArray(atRule.chi)) {
16246
+ // @ts-ignore
16247
+ return {
16248
+ valid: SyntaxValidationResult.Drop,
16249
+ matches: [],
16250
+ node: atRule,
16251
+ syntax: '@' + atRule.nam,
16252
+ error: 'expected supports body',
16253
+ tokens: []
16254
+ };
16255
+ }
15854
16256
  // media-query-list
15855
16257
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
15856
16258
  // @ts-ignore
@@ -15929,14 +16331,25 @@
15929
16331
  }
15930
16332
 
15931
16333
  function validateAtRulePageMarginBox(atRule, options, root) {
15932
- if (Array.isArray(atRule.tokens) && atRule.tokens.length > 0) {
16334
+ if (!Array.isArray(atRule.chi)) {
15933
16335
  // @ts-ignore
15934
16336
  return {
15935
- valid: SyntaxValidationResult.Valid,
15936
- context: [],
15937
- node: null,
15938
- syntax: '@' + atRule.nam,
15939
- error: ''
16337
+ valid: SyntaxValidationResult.Drop,
16338
+ matches: [],
16339
+ node: atRule,
16340
+ syntax: '@' + atRule.nam,
16341
+ error: 'expected supports body',
16342
+ tokens: []
16343
+ };
16344
+ }
16345
+ if (Array.isArray(atRule.tokens) && atRule.tokens.length > 0) {
16346
+ // @ts-ignore
16347
+ return {
16348
+ valid: SyntaxValidationResult.Valid,
16349
+ context: [],
16350
+ node: null,
16351
+ syntax: '@' + atRule.nam,
16352
+ error: ''
15940
16353
  };
15941
16354
  }
15942
16355
  if (!('chi' in atRule)) {
@@ -15984,6 +16397,17 @@
15984
16397
  tokens: []
15985
16398
  };
15986
16399
  }
16400
+ if (!Array.isArray(atRule.chi)) {
16401
+ // @ts-ignore
16402
+ return {
16403
+ valid: SyntaxValidationResult.Drop,
16404
+ matches: [],
16405
+ node: atRule,
16406
+ syntax: '@' + atRule.nam,
16407
+ error: 'expected supports body',
16408
+ tokens: []
16409
+ };
16410
+ }
15987
16411
  const result = validateAtRuleSupportsConditions(atRule, atRule.tokens);
15988
16412
  if (result) {
15989
16413
  if (result.node == null) {
@@ -16376,6 +16800,17 @@
16376
16800
  }
16377
16801
 
16378
16802
  function validateAtRuleLayer(atRule, options, root) {
16803
+ if (!Array.isArray(atRule.chi)) {
16804
+ // @ts-ignore
16805
+ return {
16806
+ valid: SyntaxValidationResult.Drop,
16807
+ matches: [],
16808
+ node: atRule,
16809
+ syntax: '@' + atRule.nam,
16810
+ error: 'expected supports body',
16811
+ tokens: []
16812
+ };
16813
+ }
16379
16814
  // media-query-list
16380
16815
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
16381
16816
  // @ts-ignore
@@ -16392,6 +16827,17 @@
16392
16827
  }
16393
16828
 
16394
16829
  function validateAtRuleFontFeatureValues(atRule, options, root) {
16830
+ if (!Array.isArray(atRule.chi)) {
16831
+ // @ts-ignore
16832
+ return {
16833
+ valid: SyntaxValidationResult.Drop,
16834
+ matches: [],
16835
+ node: atRule,
16836
+ syntax: '@' + atRule.nam,
16837
+ error: 'expected supports body',
16838
+ tokens: []
16839
+ };
16840
+ }
16395
16841
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
16396
16842
  // @ts-ignore
16397
16843
  return {
@@ -16575,6 +17021,17 @@
16575
17021
  }
16576
17022
 
16577
17023
  function validateAtRuleKeyframes(atRule, options, root) {
17024
+ if (!Array.isArray(atRule.chi)) {
17025
+ // @ts-ignore
17026
+ return {
17027
+ valid: SyntaxValidationResult.Drop,
17028
+ matches: [],
17029
+ node: atRule,
17030
+ syntax: '@' + atRule.nam,
17031
+ error: 'expected supports body',
17032
+ tokens: []
17033
+ };
17034
+ }
16578
17035
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
16579
17036
  // @ts-ignore
16580
17037
  return {
@@ -16620,6 +17077,17 @@
16620
17077
  }
16621
17078
 
16622
17079
  function validateAtRuleWhen(atRule, options, root) {
17080
+ if (!Array.isArray(atRule.chi)) {
17081
+ // @ts-ignore
17082
+ return {
17083
+ valid: SyntaxValidationResult.Drop,
17084
+ matches: [],
17085
+ node: atRule,
17086
+ syntax: '@' + atRule.nam,
17087
+ error: 'expected supports body',
17088
+ tokens: []
17089
+ };
17090
+ }
16623
17091
  const slice = Array.isArray(atRule.tokens) ? atRule.tokens.slice() : [];
16624
17092
  consumeWhitespace(slice);
16625
17093
  if (slice.length == 0) {
@@ -16783,6 +17251,17 @@
16783
17251
 
16784
17252
  const validateContainerScrollStateFeature = validateContainerSizeFeature;
16785
17253
  function validateAtRuleContainer(atRule, options, root) {
17254
+ if (!Array.isArray(atRule.chi)) {
17255
+ // @ts-ignore
17256
+ return {
17257
+ valid: SyntaxValidationResult.Drop,
17258
+ matches: [],
17259
+ node: atRule,
17260
+ syntax: '@' + atRule.nam,
17261
+ error: 'expected supports body',
17262
+ tokens: []
17263
+ };
17264
+ }
16786
17265
  // media-query-list
16787
17266
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
16788
17267
  // @ts-ignore
@@ -17297,6 +17776,91 @@
17297
17776
  };
17298
17777
  }
17299
17778
 
17779
+ // Alphabet: a-z, A-Z, 0-9, _, -
17780
+ const LOWER = "abcdefghijklmnopqrstuvwxyz";
17781
+ const DIGITS = "0123456789";
17782
+ const FULL_ALPHABET = (LOWER + DIGITS).split(""); // 64 chars
17783
+ const FIRST_ALPHABET = (LOWER).split(""); // 54 chars (no digits)
17784
+ /**
17785
+ * supported hash algorithms
17786
+ */
17787
+ const hashAlgorithms = ['hex', 'base64', 'base64url', 'sha1', 'sha256', 'sha384', 'sha512'];
17788
+ // simple deterministic hash → number
17789
+ function hashCode(str) {
17790
+ let hash = 0;
17791
+ let l = str.length;
17792
+ let i = 0;
17793
+ while (i < l) {
17794
+ hash = (hash * 31 + str.charCodeAt(i++)) >>> 0;
17795
+ }
17796
+ return hash;
17797
+ }
17798
+ /**
17799
+ * generate a hash id
17800
+ * @param input
17801
+ * @param length
17802
+ */
17803
+ function hashId(input, length = 6) {
17804
+ let n = hashCode(input);
17805
+ const chars = [];
17806
+ // First character: must not be a digit
17807
+ chars.push(FIRST_ALPHABET[n % FIRST_ALPHABET.length]);
17808
+ // Remaining characters
17809
+ for (let i = 1; i < length; i++) {
17810
+ n = (n + chars.length + i) % FULL_ALPHABET.length;
17811
+ chars.push(FULL_ALPHABET[n]);
17812
+ }
17813
+ return chars.join("");
17814
+ }
17815
+ /**
17816
+ * convert input to hex
17817
+ * @param input
17818
+ */
17819
+ function toHex(input) {
17820
+ let result = '';
17821
+ if (input instanceof ArrayBuffer || ArrayBuffer.isView(input)) {
17822
+ for (const byte of Array.from(new Uint8Array(input))) {
17823
+ result += byte.toString(16).padStart(2, '0');
17824
+ }
17825
+ }
17826
+ else {
17827
+ for (const char of String(input)) {
17828
+ result += char.charCodeAt(0).toString(16).padStart(2, '0');
17829
+ }
17830
+ }
17831
+ return result;
17832
+ }
17833
+ /**
17834
+ * generate a hash
17835
+ * @param input
17836
+ * @param length
17837
+ * @param algo
17838
+ */
17839
+ async function hash(input, length = 6, algo) {
17840
+ let result;
17841
+ if (algo != null) {
17842
+ switch (algo) {
17843
+ case 'hex':
17844
+ return toHex(input).slice(0, length);
17845
+ case 'base64':
17846
+ case 'base64url':
17847
+ result = btoa(input);
17848
+ if (algo == 'base64url') {
17849
+ result = result.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
17850
+ }
17851
+ return result.slice(0, length);
17852
+ case 'sha1':
17853
+ case 'sha256':
17854
+ case 'sha384':
17855
+ case 'sha512':
17856
+ return toHex(await crypto.subtle.digest(algo.replace('sha', 'SHA-'), new TextEncoder().encode(input))).slice(0, length);
17857
+ default:
17858
+ throw new Error(`Unsupported hash algorithm: ${algo}`);
17859
+ }
17860
+ }
17861
+ return hashId(input, length);
17862
+ }
17863
+
17300
17864
  const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
17301
17865
  const trimWhiteSpace = [exports.EnumToken.CommentTokenType, exports.EnumToken.GtTokenType, exports.EnumToken.GteTokenType, exports.EnumToken.LtTokenType, exports.EnumToken.LteTokenType, exports.EnumToken.ColumnCombinatorTokenType];
17302
17866
  const BadTokensTypes = [
@@ -17315,16 +17879,20 @@
17315
17879
  function reject(reason) {
17316
17880
  throw new Error(reason ?? 'Parsing aborted');
17317
17881
  }
17318
- function normalizeVisitorKeyName(keyName) {
17319
- return keyName.replace(/-([a-z])/g, (all, one) => one.toUpperCase());
17320
- }
17882
+ /**
17883
+ * replace token in its parent node
17884
+ * @param parent
17885
+ * @param value
17886
+ * @param replacement
17887
+ */
17321
17888
  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
- });
17889
+ for (const node of (Array.isArray(replacement) ? replacement : [replacement])) {
17890
+ if ('parent' in value && value.parent != node.parent) {
17891
+ Object.defineProperty(node, 'parent', {
17892
+ ...definedPropertySettings,
17893
+ value: value.parent
17894
+ });
17895
+ }
17328
17896
  }
17329
17897
  if (parent.typ == exports.EnumToken.BinaryExpressionTokenType) {
17330
17898
  if (parent.l == value) {
@@ -17335,22 +17903,138 @@
17335
17903
  }
17336
17904
  }
17337
17905
  else {
17338
- // @ts-ignore
17339
17906
  const target = 'val' in parent && Array.isArray(parent.val) ? parent.val : parent.chi;
17340
17907
  // @ts-ignore
17341
17908
  const index = target.indexOf(value);
17342
17909
  if (index == -1) {
17343
17910
  return;
17344
17911
  }
17345
- // @ts-ignore
17346
17912
  target.splice(index, 1, ...(Array.isArray(replacement) ? replacement : [replacement]));
17347
17913
  }
17348
17914
  }
17915
+ /**
17916
+ * transform case of key name
17917
+ * @param key
17918
+ * @param how
17919
+ *
17920
+ * @throws Error
17921
+ * @private
17922
+ */
17923
+ function getKeyName(key, how) {
17924
+ switch (how) {
17925
+ case exports.ModuleCaseTransformEnum.CamelCase:
17926
+ case exports.ModuleCaseTransformEnum.CamelCaseOnly:
17927
+ return camelize(key);
17928
+ case exports.ModuleCaseTransformEnum.DashCase:
17929
+ case exports.ModuleCaseTransformEnum.DashCaseOnly:
17930
+ return dasherize(key);
17931
+ }
17932
+ return key;
17933
+ }
17934
+ /**
17935
+ * generate scoped name
17936
+ * @param localName
17937
+ * @param filePath
17938
+ * @param pattern
17939
+ * @param hashLength
17940
+ *
17941
+ * @throws Error
17942
+ * @private
17943
+ */
17944
+ async function generateScopedName(localName, filePath, pattern, hashLength = 5) {
17945
+ if (localName.startsWith('--')) {
17946
+ localName = localName.slice(2);
17947
+ }
17948
+ const matches = /.*?(([^/]+)\/)?([^/\\]*?)(\.([^?/]+))?([?].*)?$/.exec(filePath);
17949
+ const folder = matches?.[2]?.replace?.(/[^A-Za-z0-9_-]/g, "_") ?? '';
17950
+ const fileBase = matches?.[3] ?? '';
17951
+ const ext = matches?.[5] ?? '';
17952
+ const path = filePath.replace(/[^A-Za-z0-9_-]/g, "_");
17953
+ // sanitize localName for safe char set (replace spaces/illegal chars)
17954
+ const safeLocal = localName.replace(/[^A-Za-z0-9_-]/g, "_");
17955
+ const hashString = `${localName}::${filePath}`;
17956
+ let result = '';
17957
+ let inParens = 0;
17958
+ let key = '';
17959
+ let position = 0;
17960
+ // Compose final scoped name. Ensure the entire class doesn't start with digit:
17961
+ for (const char of pattern) {
17962
+ position += char.length;
17963
+ if (char == '[') {
17964
+ inParens++;
17965
+ if (inParens != 1) {
17966
+ throw new Error(`Unexpected character: '${char} at position ${position - 1}' in pattern '${pattern}'`);
17967
+ }
17968
+ continue;
17969
+ }
17970
+ if (char == ']') {
17971
+ inParens--;
17972
+ if (inParens != 0) {
17973
+ throw new Error(`Unexpected character: '${char}:${position - 1}'`);
17974
+ }
17975
+ let hashAlgo = null;
17976
+ let length = null;
17977
+ if (key.includes(':')) {
17978
+ const parts = key.split(':');
17979
+ if (parts.length == 2) {
17980
+ // @ts-ignore
17981
+ [key, length] = parts;
17982
+ // @ts-ignore
17983
+ if (key == 'hash' && hashAlgorithms.includes(length)) {
17984
+ // @ts-ignore
17985
+ hashAlgo = length;
17986
+ length = null;
17987
+ }
17988
+ }
17989
+ if (parts.length == 3) {
17990
+ // @ts-ignore
17991
+ [key, hashAlgo, length] = parts;
17992
+ }
17993
+ if (length != null && !Number.isInteger(+length)) {
17994
+ throw new Error(`Unsupported hash length: '${length}'. expecting format [hash:length] or [hash:hash-algo:length]`);
17995
+ }
17996
+ }
17997
+ switch (key) {
17998
+ case 'hash':
17999
+ result += await hash(hashString, length ?? hashLength, hashAlgo);
18000
+ break;
18001
+ case 'name':
18002
+ result += length != null ? fileBase.slice(0, +length) : fileBase;
18003
+ break;
18004
+ case 'local':
18005
+ result += length != null ? safeLocal.slice(0, +length) : localName;
18006
+ break;
18007
+ case 'ext':
18008
+ result += length != null ? ext.slice(0, +length) : ext;
18009
+ break;
18010
+ case 'path':
18011
+ result += length != null ? path.slice(0, +length) : path;
18012
+ break;
18013
+ case 'folder':
18014
+ result += length != null ? folder.slice(0, +length) : folder;
18015
+ break;
18016
+ default:
18017
+ throw new Error(`Unsupported key: '${key}'`);
18018
+ }
18019
+ key = '';
18020
+ continue;
18021
+ }
18022
+ if (inParens > 0) {
18023
+ key += char;
18024
+ }
18025
+ else {
18026
+ result += char;
18027
+ }
18028
+ }
18029
+ // if leading char is digit, prefix underscore (very rare)
18030
+ return (/^[0-9]/.test(result) ? '_' : '') + result;
18031
+ }
17349
18032
  /**
17350
18033
  * parse css string
17351
18034
  * @param iter
17352
18035
  * @param options
17353
18036
  *
18037
+ * @throws Error
17354
18038
  * @private
17355
18039
  */
17356
18040
  async function doParse(iter, options = {}) {
@@ -17382,6 +18066,9 @@
17382
18066
  if (typeof options.validation == 'boolean') {
17383
18067
  options.validation = options.validation ? exports.ValidationLevel.All : exports.ValidationLevel.None;
17384
18068
  }
18069
+ if (options.module) {
18070
+ options.expandNestingRules = true;
18071
+ }
17385
18072
  if (options.expandNestingRules) {
17386
18073
  options.nestingRules = false;
17387
18074
  }
@@ -17395,6 +18082,8 @@
17395
18082
  const stats = {
17396
18083
  src: options.src ?? '',
17397
18084
  bytesIn: 0,
18085
+ nodesCount: 0,
18086
+ tokensCount: 0,
17398
18087
  importedBytesIn: 0,
17399
18088
  parse: `0ms`,
17400
18089
  minify: `0ms`,
@@ -17423,14 +18112,107 @@
17423
18112
  src: ''
17424
18113
  };
17425
18114
  }
17426
- let item;
17427
- let node;
18115
+ let valuesHandlers;
18116
+ let preValuesHandlers;
18117
+ let postValuesHandlers;
18118
+ let preVisitorsHandlersMap;
18119
+ let visitorsHandlersMap;
18120
+ let postVisitorsHandlersMap;
17428
18121
  const rawTokens = [];
17429
18122
  const imports = [];
18123
+ let item;
18124
+ let node;
17430
18125
  // @ts-ignore ignore error
17431
18126
  let isAsync = typeof iter[Symbol.asyncIterator] === 'function';
18127
+ if (options.visitor != null) {
18128
+ valuesHandlers = new Map;
18129
+ preValuesHandlers = new Map;
18130
+ postValuesHandlers = new Map;
18131
+ preVisitorsHandlersMap = new Map;
18132
+ visitorsHandlersMap = new Map;
18133
+ postVisitorsHandlersMap = new Map;
18134
+ const visitors = Object.entries(options.visitor);
18135
+ let key;
18136
+ let value;
18137
+ let i;
18138
+ for (i = 0; i < visitors.length; i++) {
18139
+ key = visitors[i][0];
18140
+ value = visitors[i][1];
18141
+ if (Number.isInteger(+key)) {
18142
+ visitors.splice(i + 1, 0, ...Object.entries(value));
18143
+ continue;
18144
+ }
18145
+ if (Array.isArray(value)) {
18146
+ // @ts-ignore
18147
+ visitors.splice(i + 1, 0, ...value.map((item) => [key, item]));
18148
+ continue;
18149
+ }
18150
+ if (key in exports.EnumToken) {
18151
+ if (typeof value == 'function') {
18152
+ if (!valuesHandlers.has(exports.EnumToken[key])) {
18153
+ valuesHandlers.set(exports.EnumToken[key], []);
18154
+ }
18155
+ valuesHandlers.get(exports.EnumToken[key]).push(value);
18156
+ }
18157
+ else if (typeof value == 'object' && 'type' in value && 'handler' in value && value.type in exports.WalkerEvent) {
18158
+ if (value.type == exports.WalkerEvent.Enter) {
18159
+ if (!preValuesHandlers.has(exports.EnumToken[key])) {
18160
+ preValuesHandlers.set(exports.EnumToken[key], []);
18161
+ }
18162
+ preValuesHandlers.get(exports.EnumToken[key]).push(value.handler);
18163
+ }
18164
+ else if (value.type == exports.WalkerEvent.Leave) {
18165
+ if (!postValuesHandlers.has(exports.EnumToken[key])) {
18166
+ postValuesHandlers.set(exports.EnumToken[key], []);
18167
+ }
18168
+ postValuesHandlers.get(exports.EnumToken[key]).push(value.handler);
18169
+ }
18170
+ }
18171
+ else {
18172
+ errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
18173
+ }
18174
+ }
18175
+ else if (['Declaration', 'Rule', 'AtRule', 'KeyframesRule', 'KeyframesAtRule'].includes(key)) {
18176
+ if (typeof value == 'function') {
18177
+ if (!visitorsHandlersMap.has(key)) {
18178
+ visitorsHandlersMap.set(key, []);
18179
+ }
18180
+ visitorsHandlersMap.get(key).push(value);
18181
+ }
18182
+ else if (typeof value == 'object') {
18183
+ if ('type' in value && 'handler' in value && value.type in exports.WalkerEvent) {
18184
+ if (value.type == exports.WalkerEvent.Enter) {
18185
+ if (!preVisitorsHandlersMap.has(key)) {
18186
+ preVisitorsHandlersMap.set(key, []);
18187
+ }
18188
+ preVisitorsHandlersMap.get(key).push(value.handler);
18189
+ }
18190
+ else if (value.type == exports.WalkerEvent.Leave) {
18191
+ if (!postVisitorsHandlersMap.has(key)) {
18192
+ postVisitorsHandlersMap.set(key, []);
18193
+ }
18194
+ postVisitorsHandlersMap.get(key).push(value.handler);
18195
+ }
18196
+ }
18197
+ else {
18198
+ if (!visitorsHandlersMap.has(key)) {
18199
+ visitorsHandlersMap.set(key, []);
18200
+ }
18201
+ visitorsHandlersMap.get(key).push(value);
18202
+ }
18203
+ }
18204
+ else {
18205
+ errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
18206
+ }
18207
+ }
18208
+ else {
18209
+ errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
18210
+ }
18211
+ }
18212
+ }
17432
18213
  while (item = isAsync ? (await iter.next()).value : iter.next().value) {
17433
18214
  stats.bytesIn = item.bytesIn;
18215
+ stats.tokensCount++;
17434
18216
  rawTokens.push(item);
17435
18217
  if (item.hint != null && BadTokensTypes.includes(item.hint)) {
17436
18218
  const node = getTokenType(item.token, item.hint);
@@ -17458,7 +18240,7 @@
17458
18240
  ast.loc.end = item.end;
17459
18241
  }
17460
18242
  if (item.token == ';' || item.token == '{') {
17461
- node = parseNode(tokens, context, options, errors, src, map, rawTokens);
18243
+ node = parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
17462
18244
  rawTokens.length = 0;
17463
18245
  if (node != null) {
17464
18246
  if ('chi' in node) {
@@ -17502,7 +18284,7 @@
17502
18284
  map = new Map;
17503
18285
  }
17504
18286
  else if (item.token == '}') {
17505
- parseNode(tokens, context, options, errors, src, map, rawTokens);
18287
+ parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
17506
18288
  rawTokens.length = 0;
17507
18289
  if (context.loc != null) {
17508
18290
  context.loc.end = item.end;
@@ -17523,7 +18305,7 @@
17523
18305
  }
17524
18306
  }
17525
18307
  if (tokens.length > 0) {
17526
- node = parseNode(tokens, context, options, errors, src, map, rawTokens);
18308
+ node = parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
17527
18309
  rawTokens.length = 0;
17528
18310
  if (node != null) {
17529
18311
  if (node.typ == exports.EnumToken.AtRuleNodeType && node.nam == 'import') {
@@ -17552,6 +18334,7 @@
17552
18334
  const root = await doParse(stream instanceof ReadableStream ? tokenizeStream(stream) : tokenize$1({
17553
18335
  stream,
17554
18336
  buffer: '',
18337
+ offset: 0,
17555
18338
  position: { ind: 0, lin: 1, col: 1 },
17556
18339
  currentPosition: { ind: -1, lin: 1, col: 0 }
17557
18340
  }), Object.assign({}, options, {
@@ -17586,256 +18369,675 @@
17586
18369
  if (options.expandNestingRules) {
17587
18370
  ast = expand(ast);
17588
18371
  }
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 = [];
18372
+ let replacement;
18373
+ let callable;
17596
18374
  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);
18375
+ for (const result of walk(ast)) {
18376
+ if (valuesHandlers.size > 0 || preVisitorsHandlersMap.size > 0 || visitorsHandlersMap.size > 0 || postVisitorsHandlersMap.size > 0) {
18377
+ if ((result.node.typ == exports.EnumToken.DeclarationNodeType &&
18378
+ (preVisitorsHandlersMap.has('Declaration') || visitorsHandlersMap.has('Declaration') || postVisitorsHandlersMap.has('Declaration'))) ||
18379
+ (result.node.typ == exports.EnumToken.AtRuleNodeType && (preVisitorsHandlersMap.has('AtRule') || visitorsHandlersMap.has('AtRule') || postVisitorsHandlersMap.has('AtRule'))) ||
18380
+ (result.node.typ == exports.EnumToken.KeyframesAtRuleNodeType && (preVisitorsHandlersMap.has('KeyframesAtRule') || visitorsHandlersMap.has('KeyframesAtRule') || postVisitorsHandlersMap.has('KeyframesAtRule')))) {
18381
+ const handlers = [];
18382
+ const key = result.node.typ == exports.EnumToken.DeclarationNodeType ? 'Declaration' : result.node.typ == exports.EnumToken.AtRuleNodeType ? 'AtRule' : 'KeyframesAtRule';
18383
+ if (preVisitorsHandlersMap.has(key)) {
18384
+ // @ts-ignore
18385
+ handlers.push(...preVisitorsHandlersMap.get(key));
17605
18386
  }
17606
- else if (exports.WalkerValueEvent[value.type] == exports.WalkerValueEvent.Leave) {
17607
- postValuesHandlers.set(exports.EnumToken[key], value.handler);
18387
+ if (visitorsHandlersMap.has(key)) {
18388
+ // @ts-ignore
18389
+ handlers.push(...visitorsHandlersMap.get(key));
17608
18390
  }
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);
18391
+ if (postVisitorsHandlersMap.has(key)) {
18392
+ // @ts-ignore
18393
+ handlers.push(...postVisitorsHandlersMap.get(key));
18394
+ }
18395
+ let node = result.node;
18396
+ for (const handler of handlers) {
18397
+ callable = typeof handler == 'function' ? handler : handler[camelize(node.typ == exports.EnumToken.DeclarationNodeType || node.typ == exports.EnumToken.AtRuleNodeType ? node.nam : node.val)];
18398
+ if (callable == null) {
18399
+ continue;
18400
+ }
18401
+ replacement = callable(node, result.parent);
18402
+ if (replacement == null) {
18403
+ continue;
18404
+ }
18405
+ isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
18406
+ if (replacement) {
18407
+ replacement = await replacement;
18408
+ }
18409
+ if (replacement == null || replacement == node) {
18410
+ continue;
17622
18411
  }
17623
- else if (exports.WalkerValueEvent[value.type] == exports.WalkerValueEvent.Leave) {
17624
- postVisitorsHandlersMap.set(key, value.handler);
18412
+ // @ts-ignore
18413
+ node = replacement;
18414
+ //
18415
+ if (Array.isArray(node)) {
18416
+ break;
17625
18417
  }
17626
18418
  }
17627
- else {
17628
- visitorsHandlersMap.set(key, value);
18419
+ if (node != result.node) {
18420
+ // @ts-ignore
18421
+ replaceToken(result.parent, result.node, node);
17629
18422
  }
17630
18423
  }
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;
18424
+ else if ((result.node.typ == exports.EnumToken.RuleNodeType && (preVisitorsHandlersMap.has('Rule') || visitorsHandlersMap.has('Rule') || postVisitorsHandlersMap.has('Rule'))) ||
18425
+ (result.node.typ == exports.EnumToken.KeyFramesRuleNodeType && (preVisitorsHandlersMap.has('KeyframesRule') || visitorsHandlersMap.has('KeyframesRule') || postVisitorsHandlersMap.has('KeyframesRule')))) {
18426
+ const handlers = [];
18427
+ const key = result.node.typ == exports.EnumToken.RuleNodeType ? 'Rule' : 'KeyframesRule';
18428
+ if (preVisitorsHandlersMap.has(key)) {
18429
+ handlers.push(...preVisitorsHandlersMap.get(key));
17688
18430
  }
17689
- let replacement = callable(node, result.parent);
17690
- if (replacement == null) {
17691
- continue;
18431
+ if (visitorsHandlersMap.has(key)) {
18432
+ handlers.push(...visitorsHandlersMap.get(key));
17692
18433
  }
17693
- isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
17694
- if (replacement) {
17695
- replacement = await replacement;
18434
+ if (postVisitorsHandlersMap.has(key)) {
18435
+ handlers.push(...postVisitorsHandlersMap.get(key));
17696
18436
  }
17697
- if (replacement == null || replacement == node) {
17698
- continue;
18437
+ let node = result.node;
18438
+ for (const callable of handlers) {
18439
+ replacement = callable(node, result.parent);
18440
+ if (replacement == null) {
18441
+ continue;
18442
+ }
18443
+ isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
18444
+ if (replacement) {
18445
+ replacement = await replacement;
18446
+ }
18447
+ if (replacement == null || replacement == node) {
18448
+ continue;
18449
+ }
18450
+ // @ts-ignore
18451
+ node = replacement;
18452
+ //
18453
+ if (Array.isArray(node)) {
18454
+ break;
18455
+ }
17699
18456
  }
17700
18457
  // @ts-ignore
17701
- node = replacement;
17702
- //
17703
- if (Array.isArray(node)) {
17704
- break;
18458
+ if (node != result.node) {
18459
+ // @ts-ignore
18460
+ replaceToken(result.parent, result.node, node);
17705
18461
  }
17706
18462
  }
17707
- if (node != result.node) {
17708
- // @ts-ignore
17709
- replaceToken(result.parent, result.node, node);
18463
+ else if (valuesHandlers.size > 0) {
18464
+ let node = null;
18465
+ node = result.node;
18466
+ if (valuesHandlers.has(node.typ)) {
18467
+ for (const valueHandler of valuesHandlers.get(node.typ)) {
18468
+ callable = valueHandler;
18469
+ replacement = callable(node, result.parent);
18470
+ if (replacement == null) {
18471
+ continue;
18472
+ }
18473
+ isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
18474
+ if (isAsync) {
18475
+ replacement = await replacement;
18476
+ }
18477
+ if (replacement != null && replacement != node) {
18478
+ node = replacement;
18479
+ }
18480
+ }
18481
+ }
18482
+ if (node != result.node) {
18483
+ // @ts-ignore
18484
+ replaceToken(result.parent, value, node);
18485
+ }
18486
+ const tokens = 'tokens' in result.node ? result.node.tokens : [];
18487
+ if ('val' in result.node && Array.isArray(result.node.val)) {
18488
+ tokens.push(...result.node.val);
18489
+ }
18490
+ if (tokens.length == 0) {
18491
+ continue;
18492
+ }
18493
+ for (const { value, parent, root } of walkValues(tokens, result.node)) {
18494
+ node = value;
18495
+ if (valuesHandlers.has(node.typ)) {
18496
+ for (const valueHandler of valuesHandlers.get(node.typ)) {
18497
+ callable = valueHandler;
18498
+ let result = callable(node, parent, root);
18499
+ if (result == null) {
18500
+ continue;
18501
+ }
18502
+ isAsync = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction';
18503
+ if (isAsync) {
18504
+ result = await result;
18505
+ }
18506
+ if (result != null && result != node) {
18507
+ node = result;
18508
+ }
18509
+ //
18510
+ if (Array.isArray(node)) {
18511
+ break;
18512
+ }
18513
+ }
18514
+ }
18515
+ if (node != value) {
18516
+ // @ts-ignore
18517
+ replaceToken(parent, value, node);
18518
+ }
18519
+ }
17710
18520
  }
17711
18521
  }
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));
18522
+ }
18523
+ }
18524
+ if (options.minify) {
18525
+ if (ast.chi.length > 0) {
18526
+ let passes = options.pass ?? 1;
18527
+ while (passes--) {
18528
+ minify(ast, options, true, errors, false);
18529
+ }
18530
+ }
18531
+ }
18532
+ stats.bytesIn += stats.importedBytesIn;
18533
+ let endTime = performance.now();
18534
+ const result = {
18535
+ ast,
18536
+ errors,
18537
+ stats: {
18538
+ ...stats,
18539
+ parse: `${(endParseTime - startTime).toFixed(2)}ms`,
18540
+ minify: `${(endTime - endParseTime).toFixed(2)}ms`,
18541
+ total: `${(endTime - startTime).toFixed(2)}ms`
18542
+ }
18543
+ };
18544
+ if (options.module) {
18545
+ const moduleSettings = {
18546
+ hashLength: 5,
18547
+ filePath: '',
18548
+ scoped: exports.ModuleScopeEnumOptions.Local,
18549
+ naming: exports.ModuleCaseTransformEnum.IgnoreCase,
18550
+ pattern: '',
18551
+ generateScopedName,
18552
+ ...(typeof options.module != 'object' ? {} : options.module)
18553
+ };
18554
+ const parseModuleTime = performance.now();
18555
+ const namesMapping = {};
18556
+ const global = new Set;
18557
+ const processed = new Set;
18558
+ const pattern = typeof options.module == 'boolean' ? null : moduleSettings.pattern;
18559
+ const importMapping = {};
18560
+ const cssVariablesMap = {};
18561
+ const importedCssVariables = {};
18562
+ let mapping = {};
18563
+ let revMapping = {};
18564
+ let filePath = typeof options.module == 'boolean' ? options.src : (moduleSettings.filePath ?? options.src);
18565
+ filePath = filePath === '' ? options.src : options.resolve(filePath, options.dirname(options.src), options.cwd).relative;
18566
+ if (typeof options.module == 'number') {
18567
+ if (options.module & exports.ModuleCaseTransformEnum.CamelCase) {
18568
+ moduleSettings.naming = exports.ModuleCaseTransformEnum.CamelCase;
18569
+ }
18570
+ else if (options.module & exports.ModuleCaseTransformEnum.CamelCaseOnly) {
18571
+ moduleSettings.naming = exports.ModuleCaseTransformEnum.CamelCaseOnly;
18572
+ }
18573
+ else if (options.module & exports.ModuleCaseTransformEnum.DashCase) {
18574
+ moduleSettings.naming = exports.ModuleCaseTransformEnum.DashCase;
18575
+ }
18576
+ else if (options.module & exports.ModuleCaseTransformEnum.DashCaseOnly) {
18577
+ moduleSettings.naming = exports.ModuleCaseTransformEnum.DashCaseOnly;
18578
+ }
18579
+ if (options.module & exports.ModuleScopeEnumOptions.Global) {
18580
+ moduleSettings.scoped = exports.ModuleScopeEnumOptions.Global;
18581
+ }
18582
+ if (options.module & exports.ModuleScopeEnumOptions.Pure) {
18583
+ // @ts-ignore
18584
+ moduleSettings.scoped |= exports.ModuleScopeEnumOptions.Pure;
18585
+ }
18586
+ if (options.module & exports.ModuleScopeEnumOptions.ICSS) {
18587
+ // @ts-ignore
18588
+ moduleSettings.scoped |= exports.ModuleScopeEnumOptions.ICSS;
18589
+ }
18590
+ }
18591
+ if (typeof moduleSettings.scoped == 'boolean') {
18592
+ moduleSettings.scoped = moduleSettings.scoped ? exports.ModuleScopeEnumOptions.Local : exports.ModuleScopeEnumOptions.Global;
18593
+ }
18594
+ moduleSettings.filePath = filePath;
18595
+ moduleSettings.pattern = pattern != null && pattern !== '' ? pattern : (filePath === '' ? `[local]_[hash]` : `[local]_[hash]_[name]`);
18596
+ for (const { node, parent } of walk(ast)) {
18597
+ if (node.typ == exports.EnumToken.CssVariableImportTokenType) {
18598
+ const url = node.val.find(t => t.typ == exports.EnumToken.StringTokenType).val.slice(1, -1);
18599
+ const src = options.resolve(url, options.dirname(options.src), options.cwd);
18600
+ const result = options.load(url, options.src);
18601
+ const stream = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction' ? await result : result;
18602
+ const root = await doParse(stream instanceof ReadableStream ? tokenizeStream(stream) : tokenize$1({
18603
+ stream,
18604
+ buffer: '',
18605
+ offset: 0,
18606
+ position: { ind: 0, lin: 1, col: 1 },
18607
+ currentPosition: { ind: -1, lin: 1, col: 0 }
18608
+ }), Object.assign({}, options, {
18609
+ minify: false,
18610
+ setParent: false,
18611
+ src: src.relative
18612
+ }));
18613
+ cssVariablesMap[node.nam] = root.cssModuleVariables;
18614
+ parent.chi.splice(parent.chi.indexOf(node), 1);
18615
+ continue;
18616
+ }
18617
+ if (node.typ == exports.EnumToken.CssVariableDeclarationMapTokenType) {
18618
+ const from = node.from.find(t => t.typ == exports.EnumToken.IdenTokenType || isIdentColor(t));
18619
+ if (!(from.val in cssVariablesMap)) {
18620
+ errors.push({
18621
+ node,
18622
+ message: `could not resolve @value import from '${from.val}'`,
18623
+ action: 'drop'
18624
+ });
17719
18625
  }
17720
- if (visitorsHandlersMap.has(key)) {
17721
- // @ts-ignore
17722
- handlers.push(visitorsHandlersMap.get(key));
18626
+ else {
18627
+ for (const token of node.vars) {
18628
+ if (token.typ == exports.EnumToken.IdenTokenType || isIdentColor(token)) {
18629
+ if (!(token.val in cssVariablesMap[from.val])) {
18630
+ errors.push({
18631
+ node,
18632
+ message: `value '${token.val}' is not exported from '${from.val}'`,
18633
+ action: 'drop'
18634
+ });
18635
+ continue;
18636
+ }
18637
+ result.cssModuleVariables ??= {};
18638
+ result.cssModuleVariables[token.val] = importedCssVariables[token.val] = cssVariablesMap[from.val][token.val];
18639
+ }
18640
+ }
17723
18641
  }
17724
- if (postVisitorsHandlersMap.has(key)) {
17725
- // @ts-ignore
17726
- handlers.push(postVisitorsHandlersMap.get(key));
18642
+ parent.chi.splice(parent.chi.indexOf(node), 1);
18643
+ continue;
18644
+ }
18645
+ if (node.typ == exports.EnumToken.CssVariableTokenType) {
18646
+ if (parent?.typ == exports.EnumToken.StyleSheetNodeType) {
18647
+ if (result.cssModuleVariables == null) {
18648
+ result.cssModuleVariables = {};
18649
+ }
18650
+ result.cssModuleVariables[node.nam] = node;
17727
18651
  }
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;
18652
+ parent.chi.splice(parent.chi.indexOf(node), 1);
18653
+ continue;
18654
+ }
18655
+ if (node.typ == exports.EnumToken.DeclarationNodeType) {
18656
+ if (node.nam.startsWith('--')) {
18657
+ if (!(node.nam in namesMapping)) {
18658
+ let result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? node.nam : moduleSettings.generateScopedName(node.nam, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
18659
+ let value = result instanceof Promise ? await result : result;
18660
+ mapping[node.nam] = '--' + (moduleSettings.naming & exports.ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & exports.ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(value, moduleSettings.naming) : value);
18661
+ revMapping[node.nam] = node.nam;
18662
+ }
18663
+ node.nam = mapping[node.nam];
18664
+ }
18665
+ if ('composes' == node.nam.toLowerCase()) {
18666
+ const tokens = [];
18667
+ let isValid = true;
18668
+ for (const token of node.val) {
18669
+ if (token.typ == exports.EnumToken.ComposesSelectorNodeType) {
18670
+ if (!(token.r == null || token.r.typ == exports.EnumToken.StringTokenType || token.r.typ == exports.EnumToken.IdenTokenType)) {
18671
+ errors.push({
18672
+ action: 'drop',
18673
+ message: `composes '${exports.EnumToken[token.r.typ]}' is not supported`,
18674
+ node
18675
+ });
18676
+ isValid = false;
18677
+ break;
18678
+ }
18679
+ tokens.push(token);
18680
+ }
17734
18681
  }
17735
- isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
17736
- if (replacement) {
17737
- replacement = await replacement;
18682
+ // find parent rule
18683
+ let parentRule = node.parent;
18684
+ while (parentRule != null && parentRule.typ != exports.EnumToken.RuleNodeType) {
18685
+ parentRule = parentRule.parent;
17738
18686
  }
17739
- if (replacement == null || replacement == node) {
18687
+ if (!isValid || tokens.length == 0) {
18688
+ if (tokens.length == 0) {
18689
+ errors.push({
18690
+ action: 'drop',
18691
+ message: `composes is empty`,
18692
+ node
18693
+ });
18694
+ }
18695
+ parentRule.chi.splice(parentRule.chi.indexOf(node), 1);
17740
18696
  continue;
17741
18697
  }
17742
- // @ts-ignore
17743
- node = replacement;
17744
- //
17745
- if (Array.isArray(node)) {
17746
- break;
18698
+ for (const token of tokens) {
18699
+ // composes: a b c;
18700
+ if (token.r == null) {
18701
+ for (const rule of token.l) {
18702
+ if (rule.typ == exports.EnumToken.WhitespaceTokenType || rule.typ == exports.EnumToken.CommentTokenType) {
18703
+ continue;
18704
+ }
18705
+ if (!(rule.val in mapping)) {
18706
+ let result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? rule.val : moduleSettings.generateScopedName(rule.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
18707
+ let value = result instanceof Promise ? await result : result;
18708
+ mapping[rule.val] = (rule.typ == exports.EnumToken.DashedIdenTokenType ? '--' : '') + (moduleSettings.naming & exports.ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & exports.ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(value, moduleSettings.naming) : value);
18709
+ revMapping[mapping[rule.val]] = rule.val;
18710
+ }
18711
+ if (parentRule != null) {
18712
+ for (const tk of parentRule.tokens) {
18713
+ if (tk.typ == exports.EnumToken.ClassSelectorTokenType) {
18714
+ const val = tk.val.slice(1);
18715
+ if (val in revMapping) {
18716
+ const key = revMapping[val];
18717
+ mapping[key] = [...new Set([...mapping[key].split(' '), mapping[rule.val]])].join(' ');
18718
+ }
18719
+ }
18720
+ }
18721
+ }
18722
+ }
18723
+ }
18724
+ // composes: a b c from 'file.css';
18725
+ else if (token.r.typ == exports.EnumToken.String) {
18726
+ const url = token.r.val.slice(1, -1);
18727
+ const src = options.resolve(url, options.dirname(options.src), options.cwd);
18728
+ const result = options.load(url, options.src);
18729
+ const stream = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction' ? await result : result;
18730
+ const root = await doParse(stream instanceof ReadableStream ? tokenizeStream(stream) : tokenize$1({
18731
+ stream,
18732
+ buffer: '',
18733
+ offset: 0,
18734
+ position: { ind: 0, lin: 1, col: 1 },
18735
+ currentPosition: { ind: -1, lin: 1, col: 0 }
18736
+ }), Object.assign({}, options, {
18737
+ minify: false,
18738
+ setParent: false,
18739
+ src: src.relative
18740
+ }));
18741
+ const srcIndex = (src.relative.startsWith('/') || src.relative.startsWith('../') ? '' : './') + src.relative;
18742
+ if (Object.keys(root.mapping).length > 0) {
18743
+ importMapping[srcIndex] = {};
18744
+ }
18745
+ if (parentRule != null) {
18746
+ for (const tk of parentRule.tokens) {
18747
+ if (tk.typ == exports.EnumToken.ClassSelectorTokenType) {
18748
+ const val = tk.val.slice(1);
18749
+ if (val in revMapping) {
18750
+ const key = revMapping[val];
18751
+ const values = [];
18752
+ for (const iden of token.l) {
18753
+ if (iden.typ != exports.EnumToken.IdenTokenType && iden.typ != exports.EnumToken.DashedIdenTokenType) {
18754
+ continue;
18755
+ }
18756
+ if (!(iden.val in root.mapping)) {
18757
+ const result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? iden.val : moduleSettings.generateScopedName(iden.val, srcIndex, moduleSettings.pattern, moduleSettings.hashLength);
18758
+ let value = result instanceof Promise ? await result : result;
18759
+ root.mapping[iden.val] = (moduleSettings.naming & exports.ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & exports.ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(value, moduleSettings.naming) : value);
18760
+ root.revMapping[root.mapping[iden.val]] = iden.val;
18761
+ }
18762
+ importMapping[srcIndex][iden.val] = root.mapping[iden.val];
18763
+ values.push(root.mapping[iden.val]);
18764
+ }
18765
+ mapping[key] = [...new Set([...mapping[key].split(' '), ...values])].join(' ');
18766
+ }
18767
+ }
18768
+ }
18769
+ }
18770
+ }
18771
+ // composes: a b c from global;
18772
+ else if (token.r.typ == exports.EnumToken.IdenTokenType) {
18773
+ // global
18774
+ if (parentRule != null) {
18775
+ if ('global' == token.r.val.toLowerCase()) {
18776
+ for (const tk of parentRule.tokens) {
18777
+ if (tk.typ == exports.EnumToken.ClassSelectorTokenType) {
18778
+ const val = tk.val.slice(1);
18779
+ if (val in revMapping) {
18780
+ const key = revMapping[val];
18781
+ mapping[key] = [...new Set([...mapping[key].split(' '), ...(token.l.reduce((acc, curr) => {
18782
+ if (curr.typ == exports.EnumToken.IdenTokenType) {
18783
+ acc.push(curr.val);
18784
+ }
18785
+ return acc;
18786
+ }, []))])].join(' ');
18787
+ }
18788
+ }
18789
+ }
18790
+ }
18791
+ else {
18792
+ errors.push({
18793
+ action: 'drop',
18794
+ message: `composes '${token.r.val}' is not supported`,
18795
+ node
18796
+ });
18797
+ }
18798
+ }
18799
+ }
17747
18800
  }
18801
+ parentRule.chi.splice(parentRule.chi.indexOf(node), 1);
17748
18802
  }
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);
17763
- if (replacement == null) {
18803
+ if (node.typ == exports.EnumToken.DeclarationNodeType && ['grid-column', 'grid-column-start', 'grid-column-end', 'grid-row', 'grid-row-start', 'grid-row-end', 'grid-template', 'grid-template-columns', 'grid-template-rows'].includes(node.nam)) {
18804
+ for (const { value } of walkValues(node.val, node)) {
18805
+ if (value.typ != exports.EnumToken.IdenTokenType) {
17764
18806
  continue;
17765
18807
  }
17766
- isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
17767
- if (isAsync) {
17768
- replacement = await replacement;
18808
+ let idenToken = value.val;
18809
+ let suffix = '';
18810
+ if (idenToken.endsWith('-start')) {
18811
+ suffix = '-start';
18812
+ idenToken = idenToken.slice(0, -6);
18813
+ }
18814
+ else if (idenToken.endsWith('-end')) {
18815
+ suffix = '-end';
18816
+ idenToken = idenToken.slice(0, -4);
17769
18817
  }
17770
- if (replacement != null && replacement != node) {
17771
- node = replacement;
18818
+ if (!(idenToken in mapping)) {
18819
+ let result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? idenToken : moduleSettings.generateScopedName(idenToken, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
18820
+ if (result instanceof Promise) {
18821
+ result = await result;
18822
+ }
18823
+ mapping[idenToken] = result;
18824
+ revMapping[result] = idenToken;
18825
+ if (suffix !== '') {
18826
+ idenToken += suffix;
18827
+ if (!(idenToken in mapping)) {
18828
+ mapping[idenToken] = result + suffix;
18829
+ revMapping[result + suffix] = idenToken;
18830
+ }
18831
+ }
17772
18832
  }
18833
+ value.val = mapping[idenToken];
17773
18834
  }
17774
18835
  }
17775
- if (node != result.node) {
17776
- // @ts-ignore
17777
- replaceToken(result.parent, value, node);
18836
+ else if (node.nam == 'grid-template-areas' || node.nam == 'grid-template') {
18837
+ for (let i = 0; i < node.val.length; i++) {
18838
+ if (node.val[i].typ == exports.EnumToken.String) {
18839
+ const tokens = parseString(node.val[i].val.slice(1, -1), { location: true });
18840
+ for (const { value } of walkValues(tokens)) {
18841
+ if (value.typ == exports.EnumToken.IdenTokenType || value.typ == exports.EnumToken.DashedIdenTokenType) {
18842
+ if (value.val in mapping) {
18843
+ value.val = mapping[value.val];
18844
+ }
18845
+ else {
18846
+ let result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? value.val : moduleSettings.generateScopedName(value.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
18847
+ if (result instanceof Promise) {
18848
+ result = await result;
18849
+ }
18850
+ mapping[value.val] = result;
18851
+ revMapping[result] = value.val;
18852
+ value.val = result;
18853
+ }
18854
+ }
18855
+ }
18856
+ node.val[i].val = node.val[i].val.charAt(0) + tokens.reduce((acc, curr) => acc + renderToken(curr), '') + node.val[i].val.charAt(node.val[i].val.length - 1);
18857
+ }
18858
+ }
17778
18859
  }
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);
18860
+ else if (node.nam == 'animation' || node.nam == 'animation-name') {
18861
+ for (const { value } of walkValues(node.val, node)) {
18862
+ if (value.typ == exports.EnumToken.IdenTokenType && ![
18863
+ 'none', 'infinite', 'normal', 'reverse', 'alternate',
18864
+ 'alternate-reverse', 'forwards', 'backwards', 'both',
18865
+ 'running', 'paused', 'linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out',
18866
+ 'step-start', 'step-end', 'jump-start', 'jump-end',
18867
+ 'jump-none', 'jump-both', 'start', 'end',
18868
+ 'inherit', 'initial', 'unset'
18869
+ ].includes(value.val)) {
18870
+ if (!(value.val in mapping)) {
18871
+ const result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? value.val : moduleSettings.generateScopedName(value.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
18872
+ mapping[value.val] = result instanceof Promise ? await result : result;
18873
+ revMapping[mapping[value.val]] = value.val;
18874
+ }
18875
+ value.val = mapping[value.val];
18876
+ }
18877
+ }
17782
18878
  }
17783
- if (tokens.length == 0) {
17784
- continue;
18879
+ for (const { value, parent } of walkValues(node.val, node)) {
18880
+ if (value.typ == exports.EnumToken.DashedIdenTokenType) {
18881
+ if (!(value.val in mapping)) {
18882
+ const result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? value.val : moduleSettings.generateScopedName(value.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
18883
+ let val = result instanceof Promise ? await result : result;
18884
+ mapping[value.val] = '--' + (moduleSettings.naming & exports.ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & exports.ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(val, moduleSettings.naming) : val);
18885
+ revMapping[mapping[value.val]] = value.val;
18886
+ }
18887
+ value.val = mapping[value.val];
18888
+ }
18889
+ else if ((value.typ == exports.EnumToken.IdenTokenType || isIdentColor(value)) && value.val in importedCssVariables) {
18890
+ replaceToken(parent, value, importedCssVariables[value.val].val);
18891
+ }
17785
18892
  }
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) {
17793
- continue;
17794
- }
17795
- isAsync = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction';
17796
- if (isAsync) {
17797
- result = await result;
17798
- }
17799
- if (result != null && result != node) {
17800
- node = result;
17801
- }
17802
- //
17803
- if (Array.isArray(node)) {
18893
+ }
18894
+ else if (node.typ == exports.EnumToken.RuleNodeType) {
18895
+ if (node.tokens == null) {
18896
+ Object.defineProperty(node, 'tokens', {
18897
+ ...definedPropertySettings,
18898
+ value: parseSelector(parseString(node.sel, { location: true }))
18899
+ });
18900
+ }
18901
+ let hasIdOrClass = false;
18902
+ for (const { value } of walkValues(node.tokens, node,
18903
+ // @ts-ignore
18904
+ (value, parent) => {
18905
+ if (value.typ == exports.EnumToken.PseudoClassTokenType) {
18906
+ const val = value.val.toLowerCase();
18907
+ switch (val) {
18908
+ case ':local':
18909
+ case ':global':
18910
+ {
18911
+ let index = parent.tokens.indexOf(value);
18912
+ parent.tokens.splice(index, 1);
18913
+ if (parent.tokens[index]?.typ == exports.EnumToken.WhitespaceTokenType || parent.tokens[index]?.typ == exports.EnumToken.DescendantCombinatorTokenType) {
18914
+ parent.tokens.splice(index, 1);
18915
+ }
18916
+ if (val == ':global') {
18917
+ for (; index < parent.tokens.length; index++) {
18918
+ if (parent.tokens[index].typ == exports.EnumToken.CommaTokenType ||
18919
+ ([exports.EnumToken.PseudoClassFuncTokenType, exports.EnumToken.PseudoClassTokenType].includes(parent.tokens[index].typ) &&
18920
+ [':global', ':local'].includes(parent.tokens[index].val.toLowerCase()))) {
18921
+ break;
18922
+ }
18923
+ global.add(parent.tokens[index]);
18924
+ }
18925
+ }
18926
+ }
18927
+ break;
18928
+ }
18929
+ }
18930
+ else if (value.typ == exports.EnumToken.PseudoClassFuncTokenType) {
18931
+ switch (value.val.toLowerCase()) {
18932
+ case ':global':
18933
+ for (const token of value.chi) {
18934
+ global.add(token);
18935
+ }
18936
+ parent.tokens.splice(parent.tokens.indexOf(value), 1, ...value.chi);
18937
+ break;
18938
+ case ':local':
18939
+ parent.tokens.splice(parent.tokens.indexOf(value), 1, ...value.chi);
17804
18940
  break;
18941
+ }
18942
+ }
18943
+ })) {
18944
+ if (value.typ == exports.EnumToken.HashTokenType || value.typ == exports.EnumToken.ClassSelectorTokenType) {
18945
+ hasIdOrClass = true;
18946
+ }
18947
+ if (processed.has(value)) {
18948
+ continue;
18949
+ }
18950
+ processed.add(value);
18951
+ if (value.typ == exports.EnumToken.PseudoClassTokenType) ;
18952
+ else if (value.typ == exports.EnumToken.PseudoClassFuncTokenType) ;
18953
+ else {
18954
+ if (global.has(value)) {
18955
+ continue;
18956
+ }
18957
+ if (value.typ == exports.EnumToken.ClassSelectorTokenType) {
18958
+ const val = value.val.slice(1);
18959
+ if (!(val in mapping)) {
18960
+ const result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? val : moduleSettings.generateScopedName(val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
18961
+ let value = result instanceof Promise ? await result : result;
18962
+ mapping[val] = (moduleSettings.naming & exports.ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & exports.ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(value, moduleSettings.naming) : value);
18963
+ revMapping[mapping[val]] = val;
17805
18964
  }
18965
+ value.val = '.' + mapping[val];
17806
18966
  }
17807
18967
  }
17808
- if (node != value) {
18968
+ }
18969
+ if (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Pure) {
18970
+ if (!hasIdOrClass) {
18971
+ throw new Error(`pure module: No id or class found in selector '${node.sel}' at '${node.loc?.src ?? ''}':${node.loc?.sta?.lin ?? ''}:${node.loc?.sta?.col ?? ''}`);
18972
+ }
18973
+ }
18974
+ node.sel = '';
18975
+ for (const token of node.tokens) {
18976
+ node.sel += renderToken(token);
18977
+ }
18978
+ }
18979
+ else if (node.typ == exports.EnumToken.AtRuleNodeType || node.typ == exports.EnumToken.KeyframesAtRuleNodeType) {
18980
+ const val = node.nam.toLowerCase();
18981
+ if (node.tokens == null) {
18982
+ Object.defineProperty(node, 'tokens', {
18983
+ ...definedPropertySettings,
17809
18984
  // @ts-ignore
17810
- replaceToken(parent, value, node);
18985
+ value: parseAtRulePrelude(parseString(node.val), node)
18986
+ });
18987
+ }
18988
+ if (val == 'property' || val == 'keyframes') {
18989
+ const prefix = val == 'property' ? '--' : '';
18990
+ for (const value of node.tokens) {
18991
+ if ((prefix == '--' && value.typ == exports.EnumToken.DashedIdenTokenType) || (prefix == '' && value.typ == exports.EnumToken.IdenTokenType)) {
18992
+ if (!(value.val in mapping)) {
18993
+ const result = (moduleSettings.scoped & exports.ModuleScopeEnumOptions.Global) ? value.val : moduleSettings.generateScopedName(value.val, moduleSettings.filePath, moduleSettings.pattern, moduleSettings.hashLength);
18994
+ let val = result instanceof Promise ? await result : result;
18995
+ mapping[value.val] = prefix + (moduleSettings.naming & exports.ModuleCaseTransformEnum.DashCaseOnly || moduleSettings.naming & exports.ModuleCaseTransformEnum.CamelCaseOnly ? getKeyName(val, moduleSettings.naming) : val);
18996
+ revMapping[mapping[value.val]] = value.val;
18997
+ }
18998
+ value.val = mapping[value.val];
18999
+ }
19000
+ }
19001
+ node.val = node.tokens.reduce((a, b) => a + renderToken(b), '');
19002
+ }
19003
+ else {
19004
+ let isReplaced = false;
19005
+ for (const { value, parent } of walkValues(node.tokens, node)) {
19006
+ if (exports.EnumToken.MediaQueryConditionTokenType == parent.typ && value != parent.l) {
19007
+ if ((value.typ == exports.EnumToken.IdenTokenType || isIdentColor(value)) && value.val in importedCssVariables) {
19008
+ isReplaced = true;
19009
+ parent.r.splice(parent.r.indexOf(value), 1, ...importedCssVariables[value.val].val);
19010
+ }
19011
+ }
19012
+ }
19013
+ if (isReplaced) {
19014
+ node.val = node.tokens.reduce((a, b) => a + renderToken(b), '');
17811
19015
  }
17812
19016
  }
17813
19017
  }
17814
19018
  }
17815
- }
17816
- if (options.minify) {
17817
- if (ast.chi.length > 0) {
17818
- let passes = options.pass ?? 1;
17819
- while (passes--) {
17820
- minify(ast, options, true, errors, false);
17821
- }
19019
+ if (moduleSettings.naming != exports.ModuleCaseTransformEnum.IgnoreCase) {
19020
+ revMapping = {};
19021
+ mapping = Object.entries(mapping).reduce((acc, [key, value]) => {
19022
+ const keyName = getKeyName(key, moduleSettings.naming);
19023
+ acc[keyName] = value;
19024
+ revMapping[value] = keyName;
19025
+ return acc;
19026
+ }, {});
17822
19027
  }
19028
+ result.mapping = mapping;
19029
+ result.revMapping = revMapping;
19030
+ if ((moduleSettings.scoped & exports.ModuleScopeEnumOptions.ICSS) && Object.keys(importMapping).length > 0) {
19031
+ result.importMapping = importMapping;
19032
+ }
19033
+ endTime = performance.now();
19034
+ result.stats.module = `${(endTime - parseModuleTime).toFixed(2)}ms`;
19035
+ result.stats.total = `${(endTime - startTime).toFixed(2)}ms`;
17823
19036
  }
17824
- const endTime = performance.now();
17825
19037
  if (options.signal != null) {
17826
19038
  options.signal.removeEventListener('abort', reject);
17827
19039
  }
17828
- stats.bytesIn += stats.importedBytesIn;
17829
- return {
17830
- ast,
17831
- errors,
17832
- stats: {
17833
- ...stats,
17834
- parse: `${(endParseTime - startTime).toFixed(2)}ms`,
17835
- minify: `${(endTime - endParseTime).toFixed(2)}ms`,
17836
- total: `${(endTime - startTime).toFixed(2)}ms`
17837
- }
17838
- };
19040
+ return result;
17839
19041
  }
17840
19042
  function getLastNode(context) {
17841
19043
  let i = context.chi.length;
@@ -17847,7 +19049,7 @@
17847
19049
  }
17848
19050
  return null;
17849
19051
  }
17850
- function parseNode(results, context, options, errors, src, map, rawTokens) {
19052
+ function parseNode(results, context, options, errors, src, map, rawTokens, stats) {
17851
19053
  let tokens = [];
17852
19054
  for (const t of results) {
17853
19055
  const node = getTokenType(t.token, t.hint);
@@ -17870,9 +19072,12 @@
17870
19072
  }
17871
19073
  loc = location;
17872
19074
  context.chi.push(tokens[i]);
17873
- if (options.sourcemap) {
17874
- tokens[i].loc = loc;
17875
- }
19075
+ stats.nodesCount++;
19076
+ Object.defineProperty(tokens[i], 'loc', {
19077
+ ...definedPropertySettings,
19078
+ value: loc,
19079
+ enumerable: options.sourcemap !== false
19080
+ });
17876
19081
  }
17877
19082
  else if (tokens[i].typ != exports.EnumToken.WhitespaceTokenType) {
17878
19083
  break;
@@ -18013,10 +19218,10 @@
18013
19218
  }
18014
19219
  }
18015
19220
  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
- }, []);
19221
+ const raw = [];
19222
+ for (const curr of t) {
19223
+ raw.push(renderToken(curr, { removeComments: true, convertColor: false }));
19224
+ }
18020
19225
  const nam = renderToken(atRule, { removeComments: true });
18021
19226
  // @ts-ignore
18022
19227
  const node = {
@@ -18032,10 +19237,12 @@
18032
19237
  node.chi = [];
18033
19238
  }
18034
19239
  loc = map.get(atRule);
18035
- if (options.sourcemap) {
18036
- node.loc = loc;
18037
- node.loc.end = { ...map.get(delim).end };
18038
- }
19240
+ Object.defineProperty(node, 'loc', {
19241
+ ...definedPropertySettings,
19242
+ value: loc,
19243
+ enumerable: options.sourcemap !== false
19244
+ });
19245
+ node.loc.end = { ...map.get(delim).end };
18039
19246
  let isValid = true;
18040
19247
  if (node.nam == 'else') {
18041
19248
  const prev = getLastNode(context);
@@ -18048,21 +19255,173 @@
18048
19255
  isValid = false;
18049
19256
  }
18050
19257
  }
19258
+ if (node.nam == 'value') {
19259
+ let i = 0;
19260
+ while (i < tokens.length) {
19261
+ if (tokens[i].typ == exports.EnumToken.WhitespaceTokenType || tokens[i].typ == exports.EnumToken.CommentTokenType) {
19262
+ i++;
19263
+ continue;
19264
+ }
19265
+ break;
19266
+ }
19267
+ if (i < tokens.length) {
19268
+ if (tokens[i].typ == exports.EnumToken.IdenTokenType || isIdentColor(tokens[i])) {
19269
+ let k = i + 1;
19270
+ while (k < tokens.length) {
19271
+ if (tokens[k].typ == exports.EnumToken.WhitespaceTokenType || tokens[k].typ == exports.EnumToken.CommentTokenType) {
19272
+ k++;
19273
+ continue;
19274
+ }
19275
+ // var or import
19276
+ if (tokens[k].typ == exports.EnumToken.ColonTokenType) {
19277
+ let j = k;
19278
+ while (++j < tokens.length) {
19279
+ if (tokens[j].typ != exports.EnumToken.WhitespaceTokenType && tokens[j].typ != exports.EnumToken.CommentTokenType) {
19280
+ break;
19281
+ }
19282
+ }
19283
+ let offset = k + 1;
19284
+ while (offset < tokens.length && tokens[offset].typ == exports.EnumToken.WhitespaceTokenType) {
19285
+ offset++;
19286
+ }
19287
+ if (tokens[j].typ == exports.EnumToken.StringTokenType) {
19288
+ Object.assign(node, {
19289
+ typ: exports.EnumToken.CssVariableImportTokenType,
19290
+ nam: tokens[i].val,
19291
+ val: tokens.slice(offset)
19292
+ });
19293
+ delete node.tokens;
19294
+ // @ts-ignore
19295
+ delete node.raw;
19296
+ context.chi.push(node);
19297
+ return null;
19298
+ }
19299
+ Object.assign(node, {
19300
+ typ: exports.EnumToken.CssVariableTokenType,
19301
+ nam: tokens[i].val,
19302
+ val: tokens.slice(offset)
19303
+ });
19304
+ context.chi.push(node);
19305
+ return null;
19306
+ }
19307
+ if (tokens[k].typ == exports.EnumToken.PseudoClassTokenType) {
19308
+ Object.assign(tokens[k], {
19309
+ typ: exports.EnumToken.IdenTokenType,
19310
+ val: tokens[k].val.slice(1)
19311
+ });
19312
+ Object.assign(node, {
19313
+ typ: exports.EnumToken.CssVariableTokenType,
19314
+ nam: tokens[i].val,
19315
+ val: tokens.slice(k)
19316
+ });
19317
+ context.chi.push(node);
19318
+ return null;
19319
+ }
19320
+ if (tokens[k].typ == exports.EnumToken.CommaTokenType) {
19321
+ let j = i;
19322
+ while (++j < tokens.length) {
19323
+ if (tokens[j].typ == exports.EnumToken.IdenTokenType && tokens[j].val.toLowerCase() == 'from') {
19324
+ const vars = tokens.slice(i, j);
19325
+ const from = tokens.slice(j + 1);
19326
+ let l = 0;
19327
+ let expect = exports.EnumToken.IdenTokenType;
19328
+ for (; l < vars.length; l++) {
19329
+ if (vars[l].typ == exports.EnumToken.WhitespaceTokenType || vars[l].typ == exports.EnumToken.CommentTokenType) {
19330
+ continue;
19331
+ }
19332
+ if (expect == vars[l].typ || (expect == exports.EnumToken.IdenTokenType && isIdentColor(vars[l]))) {
19333
+ expect = expect == exports.EnumToken.CommaTokenType ? exports.EnumToken.IdenTokenType : exports.EnumToken.CommaTokenType;
19334
+ continue;
19335
+ }
19336
+ errors.push({
19337
+ action: 'drop',
19338
+ node: node,
19339
+ location: map.get(vars[l]) ?? location,
19340
+ message: `expecting '${exports.EnumToken[expect]}' but found ${renderToken(vars[l])}`
19341
+ });
19342
+ return null;
19343
+ }
19344
+ l = 0;
19345
+ expect = exports.EnumToken.IdenTokenType;
19346
+ for (; l < from.length; l++) {
19347
+ if (from[l].typ == exports.EnumToken.WhitespaceTokenType || from[l].typ == exports.EnumToken.CommentTokenType) {
19348
+ continue;
19349
+ }
19350
+ if (expect == from[l].typ || isIdentColor(from[l])) {
19351
+ while (++l < from.length) {
19352
+ if (from[l].typ == exports.EnumToken.WhitespaceTokenType || from[l].typ == exports.EnumToken.CommentTokenType) {
19353
+ continue;
19354
+ }
19355
+ errors.push({
19356
+ action: 'drop',
19357
+ node: node,
19358
+ location: map.get(from[l]) ?? location,
19359
+ message: `unexpected '${renderToken(from[l])}'`
19360
+ });
19361
+ return null;
19362
+ }
19363
+ break;
19364
+ }
19365
+ errors.push({
19366
+ action: 'drop',
19367
+ node: node,
19368
+ location: map.get(from[l]) ?? location,
19369
+ message: `expecting <string> but found ${renderToken(from[l])}`
19370
+ });
19371
+ return null;
19372
+ }
19373
+ // @ts-ignore
19374
+ delete node.nam;
19375
+ // @ts-ignore
19376
+ delete node.val;
19377
+ Object.assign(node, {
19378
+ typ: exports.EnumToken.CssVariableDeclarationMapTokenType,
19379
+ vars,
19380
+ from
19381
+ });
19382
+ context.chi.push(node);
19383
+ return null;
19384
+ }
19385
+ }
19386
+ }
19387
+ k++;
19388
+ }
19389
+ Object.assign(node, {
19390
+ typ: exports.EnumToken.CssVariableTokenType,
19391
+ nam: tokens[i].val,
19392
+ val: tokens.slice(k)
19393
+ });
19394
+ context.chi.push(node);
19395
+ return null;
19396
+ }
19397
+ }
19398
+ }
19399
+ // @ts-ignore
19400
+ const skipValidate = (options.validation & exports.ValidationLevel.AtRule) == 0;
19401
+ const isAllowed = skipValidate || isNodeAllowedInContext(node, context);
18051
19402
  // @ts-ignore
18052
- const valid = options.validation == exports.ValidationLevel.None ? {
19403
+ const valid = skipValidate ? {
18053
19404
  valid: SyntaxValidationResult.Valid,
18054
19405
  error: '',
18055
19406
  node,
18056
19407
  syntax: '@' + node.nam
18057
- } : isValid ? (node.typ == exports.EnumToken.KeyframesAtRuleNodeType ? validateAtRuleKeyframes(node) : validateAtRule(node, options, context)) : {
19408
+ } : !isAllowed ? {
19409
+ valid: SyntaxValidationResult.Drop,
19410
+ node,
19411
+ syntax: '@' + node.nam,
19412
+ 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
19413
  valid: SyntaxValidationResult.Drop,
18059
19414
  node,
18060
19415
  syntax: '@' + node.nam,
18061
19416
  error: '@' + node.nam + ' not allowed here'};
18062
19417
  if (valid.valid == SyntaxValidationResult.Drop) {
19418
+ let message = '';
19419
+ for (const token of tokens) {
19420
+ message += renderToken(token, { minify: false });
19421
+ }
18063
19422
  errors.push({
18064
19423
  action: 'drop',
18065
- message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
19424
+ message: valid.error + ' - "' + message + '"',
18066
19425
  node,
18067
19426
  // @ts-ignore
18068
19427
  location: { src, ...(map.get(valid.node) ?? location) }
@@ -18071,13 +19430,17 @@
18071
19430
  node.typ = exports.EnumToken.InvalidAtRuleTokenType;
18072
19431
  }
18073
19432
  else {
18074
- node.val = node.tokens.reduce((acc, curr) => acc + renderToken(curr, {
18075
- minify: false,
18076
- convertColor: false,
18077
- removeComments: true
18078
- }), '');
19433
+ node.val = '';
19434
+ for (const token of node.tokens) {
19435
+ node.val += renderToken(token, {
19436
+ minify: false,
19437
+ convertColor: false,
19438
+ removeComments: true
19439
+ });
19440
+ }
18079
19441
  }
18080
19442
  context.chi.push(node);
19443
+ stats.nodesCount++;
18081
19444
  Object.defineProperties(node, {
18082
19445
  parent: { ...definedPropertySettings, value: context },
18083
19446
  validSyntax: { ...definedPropertySettings, value: valid.valid == SyntaxValidationResult.Valid }
@@ -18175,16 +19538,23 @@
18175
19538
  value: tokens.slice()
18176
19539
  });
18177
19540
  loc = location;
18178
- if (options.sourcemap) {
18179
- node.loc = loc;
18180
- }
18181
- // @ts-ignore
19541
+ Object.defineProperty(node, 'loc', {
19542
+ ...definedPropertySettings,
19543
+ value: loc,
19544
+ enumerable: options.sourcemap !== false
19545
+ });
18182
19546
  context.chi.push(node);
18183
19547
  Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: context });
18184
19548
  // @ts-ignore
18185
- const valid = options.validation == exports.ValidationLevel.None ? {
19549
+ const skipValidate = (options.validation & exports.ValidationLevel.Selector) == 0;
19550
+ const isAllowed = skipValidate || isNodeAllowedInContext(node, context);
19551
+ // @ts-ignore
19552
+ const valid = skipValidate ? {
18186
19553
  valid: SyntaxValidationResult.Valid,
18187
19554
  error: null
19555
+ } : !isAllowed ? {
19556
+ valid: SyntaxValidationResult.Drop,
19557
+ 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
19558
  } : ruleType == exports.EnumToken.KeyFramesRuleNodeType ? validateKeyframeSelector(tokens) : validateSelector(tokens, options, context);
18189
19559
  if (valid.valid != SyntaxValidationResult.Valid) {
18190
19560
  // @ts-ignore
@@ -18294,11 +19664,13 @@
18294
19664
  nam,
18295
19665
  val: []
18296
19666
  };
18297
- if (options.sourcemap) {
18298
- node.loc = location;
18299
- node.loc.end = { ...map.get(delim).end };
18300
- }
19667
+ Object.defineProperty(node, 'loc', {
19668
+ ...definedPropertySettings,
19669
+ value: location,
19670
+ enumerable: options.sourcemap !== false
19671
+ });
18301
19672
  context.chi.push(node);
19673
+ stats.nodesCount++;
18302
19674
  }
18303
19675
  return null;
18304
19676
  }
@@ -18322,22 +19694,31 @@
18322
19694
  nam,
18323
19695
  val: value
18324
19696
  };
18325
- if (options.sourcemap) {
18326
- node.loc = location;
18327
- node.loc.end = { ...map.get(delim).end };
18328
- }
19697
+ Object.defineProperty(node, 'loc', {
19698
+ ...definedPropertySettings,
19699
+ value: location,
19700
+ enumerable: options.sourcemap !== false
19701
+ });
19702
+ node.loc.end = { ...map.get(delim).end };
18329
19703
  // do not allow declarations in style sheets
18330
19704
  if (context.typ == exports.EnumToken.StyleSheetNodeType && options.lenient) {
18331
- // @ts-ignore
18332
- node.typ = exports.EnumToken.InvalidDeclarationNodeType;
19705
+ Object.assign(node, { typ: exports.EnumToken.InvalidDeclarationNodeType });
18333
19706
  context.chi.push(node);
19707
+ stats.nodesCount++;
18334
19708
  return null;
18335
19709
  }
18336
19710
  const result = parseDeclarationNode(node, errors, location);
18337
19711
  Object.defineProperty(result, 'parent', { ...definedPropertySettings, value: context });
18338
19712
  if (result != null) {
18339
- if (options.validation == exports.ValidationLevel.All) {
18340
- const valid = evaluateSyntax(result, options);
19713
+ if (options.validation & exports.ValidationLevel.Declaration) {
19714
+ const isAllowed = isNodeAllowedInContext(node, context);
19715
+ // @ts-ignore
19716
+ const valid = !isAllowed ? {
19717
+ valid: SyntaxValidationResult.Drop,
19718
+ error: `${exports.EnumToken[node.typ]} not allowed in context${context.typ == exports.EnumToken.AtRuleNodeType ? ` '@${context.nam}'` : context.typ == exports.EnumToken.StyleSheetNodeType ? ` 'stylesheet'` : ''}`,
19719
+ node,
19720
+ syntax: null
19721
+ } : evaluateSyntax(result, context, options);
18341
19722
  Object.defineProperty(result, 'validSyntax', {
18342
19723
  ...definedPropertySettings,
18343
19724
  value: valid.valid == SyntaxValidationResult.Valid
@@ -18353,11 +19734,11 @@
18353
19734
  if (!options.lenient) {
18354
19735
  return null;
18355
19736
  }
18356
- // @ts-ignore
18357
- node.typ = exports.EnumToken.InvalidDeclarationNodeType;
19737
+ Object.assign(node, { typ: exports.EnumToken.InvalidDeclarationNodeType });
18358
19738
  }
18359
19739
  }
18360
19740
  context.chi.push(result);
19741
+ stats.nodesCount++;
18361
19742
  }
18362
19743
  return null;
18363
19744
  }
@@ -18369,7 +19750,6 @@
18369
19750
  * @param atRule
18370
19751
  */
18371
19752
  function parseAtRulePrelude(tokens, atRule) {
18372
- // @ts-ignore
18373
19753
  for (const { value, parent } of walkValues(tokens, null, null, true)) {
18374
19754
  if (value.typ == exports.EnumToken.CommentTokenType ||
18375
19755
  value.typ == exports.EnumToken.WhitespaceTokenType ||
@@ -18405,16 +19785,14 @@
18405
19785
  }
18406
19786
  if (atRule.val == 'page' && value.typ == exports.EnumToken.PseudoClassTokenType) {
18407
19787
  if ([':left', ':right', ':first', ':blank'].includes(value.val)) {
18408
- // @ts-ignore
18409
- value.typ = exports.EnumToken.PseudoPageTokenType;
19788
+ Object.assign(value, { typ: exports.EnumToken.PseudoPageTokenType });
18410
19789
  }
18411
19790
  }
18412
19791
  if (atRule.val == 'layer') {
18413
19792
  if (parent == null && value.typ == exports.EnumToken.LiteralTokenType) {
18414
19793
  if (value.val.charAt(0) == '.') {
18415
19794
  if (isIdent(value.val.slice(1))) {
18416
- // @ts-ignore
18417
- value.typ = exports.EnumToken.ClassSelectorTokenType;
19795
+ Object.assign(value, { typ: exports.EnumToken.ClassSelectorTokenType });
18418
19796
  }
18419
19797
  }
18420
19798
  }
@@ -18423,8 +19801,7 @@
18423
19801
  if (value.typ == exports.EnumToken.IdenTokenType) {
18424
19802
  if (parent == null && mediaTypes.some((t) => {
18425
19803
  if (val === t) {
18426
- // @ts-ignore
18427
- value.typ = exports.EnumToken.MediaFeatureTokenType;
19804
+ Object.assign(value, { typ: exports.EnumToken.MediaFeatureTokenType });
18428
19805
  return true;
18429
19806
  }
18430
19807
  return false;
@@ -18432,18 +19809,15 @@
18432
19809
  continue;
18433
19810
  }
18434
19811
  if (value.typ == exports.EnumToken.IdenTokenType && 'and' === val) {
18435
- // @ts-ignore
18436
- value.typ = exports.EnumToken.MediaFeatureAndTokenType;
19812
+ Object.assign(value, { typ: exports.EnumToken.MediaFeatureAndTokenType });
18437
19813
  continue;
18438
19814
  }
18439
19815
  if (value.typ == exports.EnumToken.IdenTokenType && 'or' === val) {
18440
- // @ts-ignore
18441
- value.typ = exports.EnumToken.MediaFeatureOrTokenType;
19816
+ Object.assign(value, { typ: exports.EnumToken.MediaFeatureOrTokenType });
18442
19817
  continue;
18443
19818
  }
18444
19819
  if (value.typ == exports.EnumToken.IdenTokenType &&
18445
19820
  ['not', 'only'].some((t) => val === t)) {
18446
- // @ts-ignore
18447
19821
  const array = parent?.chi ?? tokens;
18448
19822
  const startIndex = array.indexOf(value);
18449
19823
  let index = startIndex + 1;
@@ -18488,12 +19862,15 @@
18488
19862
  if (value.chi[i].typ == exports.EnumToken.CommentTokenType || value.chi[i].typ == exports.EnumToken.WhitespaceTokenType) {
18489
19863
  continue;
18490
19864
  }
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;
19865
+ if (value.chi[i].typ == exports.EnumToken.LiteralTokenType && value.chi[i].val.startsWith(':')) {
19866
+ const dimension = parseDimension(value.chi[i].val.slice(1));
19867
+ if (dimension != null) {
19868
+ value.chi.splice(i, 1, {
19869
+ typ: exports.EnumToken.ColonTokenType,
19870
+ }, Object.assign(value.chi[i], dimension));
19871
+ i--;
19872
+ continue;
19873
+ }
18497
19874
  }
18498
19875
  if (nameIndex != -1 && value.chi[i].typ == exports.EnumToken.PseudoClassTokenType) {
18499
19876
  value.chi.splice(i, 1, {
@@ -18520,11 +19897,10 @@
18520
19897
  const val = value.chi.splice(valueIndex, 1)[0];
18521
19898
  const node = value.chi.splice(nameIndex, 1)[0];
18522
19899
  // 'background'
18523
- // @ts-ignore
18524
19900
  if (node.typ == exports.EnumToken.ColorTokenType && node.kin == exports.ColorType.DPSYS) {
19901
+ Object.assign(node, { typ: exports.EnumToken.IdenTokenType });
18525
19902
  // @ts-ignore
18526
19903
  delete node.kin;
18527
- node.typ = exports.EnumToken.IdenTokenType;
18528
19904
  }
18529
19905
  while (value.chi[0]?.typ == exports.EnumToken.WhitespaceTokenType) {
18530
19906
  value.chi.shift();
@@ -18558,6 +19934,7 @@
18558
19934
  return doParse(tokenize$1({
18559
19935
  stream: `.x{${declaration}}`,
18560
19936
  buffer: '',
19937
+ offset: 0,
18561
19938
  position: { ind: 0, lin: 1, col: 1 },
18562
19939
  currentPosition: { ind: -1, lin: 1, col: 0 }
18563
19940
  }), { setParent: false, minify: false, validation: false }).then(result => {
@@ -18579,43 +19956,35 @@
18579
19956
  }
18580
19957
  if (parent == null) {
18581
19958
  if (value.typ == exports.EnumToken.GtTokenType) {
18582
- // @ts-ignore
18583
- value.typ = exports.EnumToken.ChildCombinatorTokenType;
19959
+ Object.assign(value, { typ: exports.EnumToken.ChildCombinatorTokenType });
18584
19960
  }
18585
19961
  else if (value.typ == exports.EnumToken.LiteralTokenType) {
18586
19962
  if (value.val.charAt(0) == '&') {
18587
- // @ts-ignore
18588
- value.typ = exports.EnumToken.NestingSelectorTokenType;
19963
+ Object.assign(value, { typ: exports.EnumToken.NestingSelectorTokenType });
18589
19964
  // @ts-ignore
18590
19965
  delete value.val;
18591
19966
  }
18592
19967
  else if (value.val.charAt(0) == '.') {
18593
19968
  if (!isIdent(value.val.slice(1))) {
18594
- // @ts-ignore
18595
- value.typ = exports.EnumToken.InvalidClassSelectorTokenType;
19969
+ Object.assign(value, { typ: exports.EnumToken.InvalidClassSelectorTokenType });
18596
19970
  }
18597
19971
  else {
18598
- // @ts-ignore
18599
- value.typ = exports.EnumToken.ClassSelectorTokenType;
19972
+ Object.assign(value, { typ: exports.EnumToken.ClassSelectorTokenType });
18600
19973
  }
18601
19974
  }
18602
19975
  if (['*', '>', '+', '~'].includes(value.val)) {
18603
19976
  switch (value.val) {
18604
19977
  case '*':
18605
- // @ts-ignore
18606
- value.typ = exports.EnumToken.UniversalSelectorTokenType;
19978
+ Object.assign(value, { typ: exports.EnumToken.UniversalSelectorTokenType });
18607
19979
  break;
18608
19980
  case '>':
18609
- // @ts-ignore
18610
- value.typ = exports.EnumToken.ChildCombinatorTokenType;
19981
+ Object.assign(value, { typ: exports.EnumToken.ChildCombinatorTokenType });
18611
19982
  break;
18612
19983
  case '+':
18613
- // @ts-ignore
18614
- value.typ = exports.EnumToken.NextSiblingCombinatorTokenType;
19984
+ Object.assign(value, { typ: exports.EnumToken.NextSiblingCombinatorTokenType });
18615
19985
  break;
18616
19986
  case '~':
18617
- // @ts-ignore
18618
- value.typ = exports.EnumToken.SubsequentSiblingCombinatorTokenType;
19987
+ Object.assign(value, { typ: exports.EnumToken.SubsequentSiblingCombinatorTokenType });
18619
19988
  break;
18620
19989
  }
18621
19990
  // @ts-ignore
@@ -18628,12 +19997,10 @@
18628
19997
  if (!isIdent(value.val.slice(1))) {
18629
19998
  continue;
18630
19999
  }
18631
- // @ts-ignore
18632
- value.typ = exports.EnumToken.HashTokenType;
20000
+ Object.assign(value, { typ: exports.EnumToken.HashTokenType });
18633
20001
  }
18634
20002
  else {
18635
- // @ts-ignore
18636
- value.typ = exports.EnumToken.IdenTokenType;
20003
+ Object.assign(value, { typ: exports.EnumToken.IdenTokenType });
18637
20004
  }
18638
20005
  // @ts-ignore
18639
20006
  delete value.kin;
@@ -18688,6 +20055,7 @@
18688
20055
  const parseInfo = {
18689
20056
  stream: src,
18690
20057
  buffer: '',
20058
+ offset: 0,
18691
20059
  position: { ind: 0, lin: 1, col: 1 },
18692
20060
  currentPosition: { ind: -1, lin: 1, col: 0 }
18693
20061
  };
@@ -18696,15 +20064,17 @@
18696
20064
  return acc;
18697
20065
  }
18698
20066
  const token = getTokenType(t.token, t.hint);
18699
- if (options.location) {
18700
- Object.assign(token, { loc: t.sta });
18701
- }
20067
+ Object.defineProperty(token, 'loc', {
20068
+ ...definedPropertySettings,
20069
+ value: { sta: t.sta },
20070
+ enumerable: options.location !== false
20071
+ });
18702
20072
  acc.push(token);
18703
20073
  return acc;
18704
20074
  }, []));
18705
20075
  }
18706
20076
  /**
18707
- * get token type from a string
20077
+ * get the token type from a string
18708
20078
  * @param val
18709
20079
  * @param hint
18710
20080
  */
@@ -18740,7 +20110,7 @@
18740
20110
  case '>':
18741
20111
  return { typ: exports.EnumToken.GtTokenType };
18742
20112
  }
18743
- if (isPseudo(val)) {
20113
+ if (val.charAt(0) == ':' && isPseudo(val)) {
18744
20114
  return val.endsWith('(') ? {
18745
20115
  typ: exports.EnumToken.PseudoClassFuncTokenType,
18746
20116
  val: val.slice(0, -1),
@@ -18757,13 +20127,13 @@
18757
20127
  val
18758
20128
  });
18759
20129
  }
18760
- if (isAtKeyword(val)) {
20130
+ if (val.charAt(0) == '@' && isAtKeyword(val)) {
18761
20131
  return {
18762
20132
  typ: exports.EnumToken.AtRuleTokenType,
18763
20133
  val: val.slice(1)
18764
20134
  };
18765
20135
  }
18766
- if (isFunction(val)) {
20136
+ if (val.endsWith('(') && isFunction(val)) {
18767
20137
  val = val.slice(0, -1);
18768
20138
  if (val == 'url') {
18769
20139
  return {
@@ -18811,14 +20181,9 @@
18811
20181
  val: +val.slice(0, -1)
18812
20182
  };
18813
20183
  }
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);
20184
+ const dimension = parseDimension(val);
20185
+ if (dimension != null) {
20186
+ return dimension;
18822
20187
  }
18823
20188
  const v = val.toLowerCase();
18824
20189
  if (v == 'currentcolor' || v == 'transparent' || v in COLORS_NAMES) {
@@ -18848,6 +20213,12 @@
18848
20213
  val
18849
20214
  };
18850
20215
  }
20216
+ if (val.charAt(0) == '.' && isIdent(val.slice(1))) {
20217
+ return {
20218
+ typ: exports.EnumToken.ClassSelectorTokenType,
20219
+ val
20220
+ };
20221
+ }
18851
20222
  if (val.charAt(0) == '#' && isHexColor(val)) {
18852
20223
  return {
18853
20224
  typ: exports.EnumToken.ColorTokenType,
@@ -18895,6 +20266,55 @@
18895
20266
  function parseTokens(tokens, options = {}) {
18896
20267
  for (let i = 0; i < tokens.length; i++) {
18897
20268
  const t = tokens[i];
20269
+ if (t.typ == exports.EnumToken.IdenTokenType && t.val == 'from' && i > 0) {
20270
+ const left = [];
20271
+ const right = [];
20272
+ let foundLeft = 0;
20273
+ let foundRight = 0;
20274
+ let k = i;
20275
+ let l = i;
20276
+ while (k > 0) {
20277
+ if (tokens[k - 1].typ == exports.EnumToken.CommentTokenType || tokens[k - 1].typ == exports.EnumToken.WhitespaceTokenType) {
20278
+ left.push(tokens[--k]);
20279
+ continue;
20280
+ }
20281
+ if (tokens[k - 1].typ == exports.EnumToken.IdenTokenType || tokens[k - 1].typ == exports.EnumToken.DashedIdenTokenType) {
20282
+ foundLeft++;
20283
+ left.push(tokens[--k]);
20284
+ continue;
20285
+ }
20286
+ break;
20287
+ }
20288
+ while (++l < tokens.length) {
20289
+ if (tokens[l].typ == exports.EnumToken.CommentTokenType || tokens[l].typ == exports.EnumToken.WhitespaceTokenType) {
20290
+ right.push(tokens[l]);
20291
+ continue;
20292
+ }
20293
+ if (tokens[l].typ == exports.EnumToken.IdenTokenType || tokens[l].typ == exports.EnumToken.StringTokenType) {
20294
+ foundRight++;
20295
+ right.push(tokens[l]);
20296
+ continue;
20297
+ }
20298
+ break;
20299
+ }
20300
+ if (foundLeft > 0 && foundRight == 1) {
20301
+ while (left?.[0].typ == exports.EnumToken.WhitespaceTokenType) {
20302
+ left.shift();
20303
+ }
20304
+ while (left.at(-1)?.typ == exports.EnumToken.WhitespaceTokenType) {
20305
+ left.pop();
20306
+ }
20307
+ tokens.splice(k, l - k + 1, {
20308
+ typ: exports.EnumToken.ComposesSelectorNodeType,
20309
+ l: left,
20310
+ r: right.reduce((a, b) => {
20311
+ return a == null ? b : b.typ == exports.EnumToken.IdenTokenType || b.typ == exports.EnumToken.StringTokenType ? b : a;
20312
+ }, null)
20313
+ });
20314
+ i = k;
20315
+ continue;
20316
+ }
20317
+ }
18898
20318
  if (t.typ == exports.EnumToken.WhitespaceTokenType && ((i == 0 ||
18899
20319
  i + 1 == tokens.length ||
18900
20320
  [exports.EnumToken.CommaTokenType, exports.EnumToken.GteTokenType, exports.EnumToken.LteTokenType, exports.EnumToken.ColumnCombinatorTokenType].includes(tokens[i + 1].typ)) ||
@@ -19228,28 +20648,28 @@
19228
20648
  */
19229
20649
  WalkerOptionEnum[WalkerOptionEnum["Stop"] = 2] = "Stop";
19230
20650
  /**
19231
- * ignore node and process children
20651
+ * ignore the current node and process its children
19232
20652
  */
19233
20653
  WalkerOptionEnum[WalkerOptionEnum["Children"] = 4] = "Children";
19234
20654
  /**
19235
- * ignore children
20655
+ * ignore the current node children
19236
20656
  */
19237
20657
  WalkerOptionEnum[WalkerOptionEnum["IgnoreChildren"] = 8] = "IgnoreChildren";
19238
20658
  })(exports.WalkerOptionEnum || (exports.WalkerOptionEnum = {}));
19239
20659
  /**
19240
20660
  * event types for the walkValues function
19241
20661
  */
19242
- exports.WalkerValueEvent = void 0;
19243
- (function (WalkerValueEvent) {
20662
+ exports.WalkerEvent = void 0;
20663
+ (function (WalkerEvent) {
19244
20664
  /**
19245
20665
  * enter node
19246
20666
  */
19247
- WalkerValueEvent[WalkerValueEvent["Enter"] = 1] = "Enter";
20667
+ WalkerEvent[WalkerEvent["Enter"] = 1] = "Enter";
19248
20668
  /**
19249
20669
  * leave node
19250
20670
  */
19251
- WalkerValueEvent[WalkerValueEvent["Leave"] = 2] = "Leave";
19252
- })(exports.WalkerValueEvent || (exports.WalkerValueEvent = {}));
20671
+ WalkerEvent[WalkerEvent["Leave"] = 2] = "Leave";
20672
+ })(exports.WalkerEvent || (exports.WalkerEvent = {}));
19253
20673
  /**
19254
20674
  * walk ast nodes
19255
20675
  * @param node initial node
@@ -19280,11 +20700,10 @@
19280
20700
  * }
19281
20701
  * ```
19282
20702
  *
19283
- * Using a filter to control the walk process:
20703
+ * Using a {@link filter} function to control the ast traversal. the filter function returns a value of type {@link WalkerOption}.
19284
20704
  *
19285
20705
  * ```ts
19286
- *
19287
- * import {walk} from '@tbela99/css-parser';
20706
+ * import {EnumToken, transform, walk, WalkerOptionEnum} from '@tbela99/css-parser';
19288
20707
  *
19289
20708
  * const css = `
19290
20709
  * body { color: color(from var(--base-color) display-p3 r calc(g + 0.24) calc(b + 0.15)); }
@@ -19300,17 +20719,28 @@
19300
20719
  * }
19301
20720
  * `;
19302
20721
  *
19303
- * for (const {node, parent, root} of walk(ast, (node) => {
20722
+ * function filter(node) {
19304
20723
  *
19305
20724
  * if (node.typ == EnumToken.AstRule && node.sel.includes('html')) {
19306
20725
  *
19307
20726
  * // skip the children of the current node
19308
20727
  * return WalkerOptionEnum.IgnoreChildren;
19309
20728
  * }
19310
- * })) {
20729
+ * }
19311
20730
  *
19312
- * // do something with node
20731
+ * const result = await transform(css);
20732
+ * for (const {node} of walk(result.ast, filter)) {
20733
+ *
20734
+ * console.error([EnumToken[node.typ]]);
19313
20735
  * }
20736
+ *
20737
+ * // [ "StyleSheetNodeType" ]
20738
+ * // [ "RuleNodeType" ]
20739
+ * // [ "DeclarationNodeType" ]
20740
+ * // [ "RuleNodeType" ]
20741
+ * // [ "DeclarationNodeType" ]
20742
+ * // [ "RuleNodeType" ]
20743
+ * // [ "DeclarationNodeType" ]
19314
20744
  * ```
19315
20745
  */
19316
20746
  function* walk(node, filter, reverse) {
@@ -19318,7 +20748,8 @@
19318
20748
  const root = node;
19319
20749
  const map = new Map;
19320
20750
  let isNumeric = false;
19321
- while ((node = parents.shift())) {
20751
+ let i = 0;
20752
+ while ((node = parents[i++])) {
19322
20753
  let option = null;
19323
20754
  if (filter != null) {
19324
20755
  option = filter(node);
@@ -19337,8 +20768,8 @@
19337
20768
  yield { node, parent: map.get(node), root };
19338
20769
  }
19339
20770
  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()) {
20771
+ parents.splice(i, 0, ...node.chi[reverse ? 'reverse' : 'slice']());
20772
+ for (const child of node.chi) {
19342
20773
  map.set(child, node);
19343
20774
  }
19344
20775
  }
@@ -19355,55 +20786,68 @@
19355
20786
  *
19356
20787
  * ```ts
19357
20788
  *
19358
- * import {EnumToken, walk} from '@tbela99/css-parser';
20789
+ * import {AstDeclaration, EnumToken, transform, walkValues} from '@tbela99/css-parser';
19359
20790
  *
19360
20791
  * const css = `
19361
20792
  * 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
20793
  * `;
19373
20794
  *
19374
- * for (const {value} of walkValues(result.ast.chi[0].chi[0].val, null, null,true)) {
20795
+ * const result = await transform(css);
20796
+ * const declaration = result.ast.chi[0].chi[0] as AstDeclaration;
20797
+ *
20798
+ * // walk the node attribute's tokens in reverse order
20799
+ * for (const {value} of walkValues(declaration.val, null, null,true)) {
19375
20800
  *
19376
20801
  * console.error([EnumToken[value.typ], value.val]);
19377
20802
  * }
19378
20803
  *
20804
+ * // [ "Color", "color" ]
20805
+ * // [ "FunctionTokenType", "calc" ]
20806
+ * // [ "Number", 0.15 ]
20807
+ * // [ "Add", undefined ]
20808
+ * // [ "Iden", "b" ]
20809
+ * // [ "Whitespace", undefined ]
20810
+ * // [ "FunctionTokenType", "calc" ]
20811
+ * // [ "Number", 0.24 ]
20812
+ * // [ "Add", undefined ]
20813
+ * // [ "Iden", "g" ]
20814
+ * // [ "Whitespace", undefined ]
20815
+ * // [ "Iden", "r" ]
20816
+ * // [ "Whitespace", undefined ]
20817
+ * // [ "Iden", "display-p3" ]
20818
+ * // [ "Whitespace", undefined ]
20819
+ * // [ "FunctionTokenType", "var" ]
20820
+ * // [ "DashedIden", "--base-color" ]
20821
+ * // [ "Whitespace", undefined ]
20822
+ * // [ "Iden", "from" ]
20823
+ * ```
19379
20824
  */
19380
20825
  function* walkValues(values, root = null, filter, reverse) {
19381
- // const set = new Set<Token>();
19382
20826
  const stack = values.slice();
19383
20827
  const map = new Map;
19384
20828
  let previous = null;
19385
20829
  if (filter != null && typeof filter == 'function') {
19386
20830
  filter = {
19387
- event: exports.WalkerValueEvent.Enter,
20831
+ event: exports.WalkerEvent.Enter,
19388
20832
  fn: filter
19389
20833
  };
19390
20834
  }
19391
20835
  else if (filter == null) {
19392
20836
  filter = {
19393
- event: exports.WalkerValueEvent.Enter
20837
+ event: exports.WalkerEvent.Enter
19394
20838
  };
19395
20839
  }
19396
20840
  let isNumeric = false;
19397
- const eventType = filter.event ?? exports.WalkerValueEvent.Enter;
20841
+ const eventType = filter.event ?? exports.WalkerEvent.Enter;
19398
20842
  while (stack.length > 0) {
19399
20843
  let value = reverse ? stack.pop() : stack.shift();
19400
20844
  let option = null;
19401
- if (filter.fn != null && (eventType & exports.WalkerValueEvent.Enter)) {
20845
+ if (filter.fn != null && (eventType & exports.WalkerEvent.Enter)) {
19402
20846
  const isValid = filter.type == null || value.typ == filter.type ||
19403
20847
  (Array.isArray(filter.type) && filter.type.includes(value.typ)) ||
19404
20848
  (typeof filter.type == 'function' && filter.type(value));
19405
20849
  if (isValid) {
19406
- option = filter.fn(value, map.get(value) ?? root, exports.WalkerValueEvent.Enter);
20850
+ option = filter.fn(value, map.get(value) ?? root, exports.WalkerEvent.Enter);
19407
20851
  isNumeric = typeof option == 'number';
19408
20852
  if (isNumeric && (option & exports.WalkerOptionEnum.Stop)) {
19409
20853
  return;
@@ -19412,12 +20856,15 @@
19412
20856
  continue;
19413
20857
  }
19414
20858
  // @ts-ignore
19415
- if (option != null && typeof option == 'object' && 'typ' in option) {
19416
- map.set(option, map.get(value) ?? root);
20859
+ if (option != null && typeof option == 'object' && ('typ' in option || Array.isArray(option))) {
20860
+ const op = Array.isArray(option) ? option : [option];
20861
+ for (const o of op) {
20862
+ map.set(o, map.get(value) ?? root);
20863
+ }
20864
+ stack[reverse ? 'push' : 'unshift'](...op);
19417
20865
  }
19418
20866
  }
19419
20867
  }
19420
- // if ((eventType & WalkerValueEvent.Enter) && (!isNumeric || ((option as number) & WalkerOptionEnum.Children) === 0)) {
19421
20868
  yield {
19422
20869
  value,
19423
20870
  parent: map.get(value) ?? root,
@@ -19426,7 +20873,6 @@
19426
20873
  // @ts-ignore
19427
20874
  root: root ?? null
19428
20875
  };
19429
- // }
19430
20876
  if ('chi' in value && (!isNumeric || (option & exports.WalkerOptionEnum.IgnoreChildren) === 0)) {
19431
20877
  const sliced = value.chi.slice();
19432
20878
  for (const child of sliced) {
@@ -19438,12 +20884,12 @@
19438
20884
  const values = [];
19439
20885
  if ('l' in value && value.l != null) {
19440
20886
  // @ts-ignore
19441
- values[reverse ? 'push' : 'unshift'](value.l);
20887
+ values.push(value.l);
19442
20888
  // @ts-ignore
19443
20889
  map.set(value.l, value);
19444
20890
  }
19445
20891
  if ('op' in value && typeof value.op == 'object') {
19446
- values[reverse ? 'push' : 'unshift'](value.op);
20892
+ values.push(value.op);
19447
20893
  // @ts-ignore
19448
20894
  map.set(value.op, value);
19449
20895
  }
@@ -19451,14 +20897,14 @@
19451
20897
  if (Array.isArray(value.r)) {
19452
20898
  for (const r of value.r) {
19453
20899
  // @ts-ignore
19454
- values[reverse ? 'push' : 'unshift'](r);
20900
+ values.push(r);
19455
20901
  // @ts-ignore
19456
20902
  map.set(r, value);
19457
20903
  }
19458
20904
  }
19459
20905
  else {
19460
20906
  // @ts-ignore
19461
- values[reverse ? 'push' : 'unshift'](value.r);
20907
+ values.push(value.r);
19462
20908
  // @ts-ignore
19463
20909
  map.set(value.r, value);
19464
20910
  }
@@ -19467,29 +20913,22 @@
19467
20913
  stack[reverse ? 'push' : 'unshift'](...values);
19468
20914
  }
19469
20915
  }
19470
- if ((eventType & exports.WalkerValueEvent.Leave) && filter.fn != null) {
20916
+ if ((eventType & exports.WalkerEvent.Leave) && filter.fn != null) {
19471
20917
  const isValid = filter.type == null || value.typ == filter.type ||
19472
20918
  (Array.isArray(filter.type) && filter.type.includes(value.typ)) ||
19473
20919
  (typeof filter.type == 'function' && filter.type(value));
19474
20920
  if (isValid) {
19475
- option = filter.fn(value, map.get(value), exports.WalkerValueEvent.Leave);
20921
+ option = filter.fn(value, map.get(value), exports.WalkerEvent.Leave);
19476
20922
  // @ts-ignore
19477
- if (option != null && 'typ' in option) {
19478
- map.set(option, map.get(value) ?? root);
20923
+ if (option != null && ('typ' in option || Array.isArray(option))) {
20924
+ const op = Array.isArray(option) ? option : [option];
20925
+ for (const o of op) {
20926
+ map.set(o, map.get(value) ?? root);
20927
+ }
20928
+ stack[reverse ? 'push' : 'unshift'](...op);
19479
20929
  }
19480
20930
  }
19481
20931
  }
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
20932
  previous = value;
19494
20933
  }
19495
20934
  }
@@ -19497,7 +20936,7 @@
19497
20936
  /**
19498
20937
  * feature walk mode
19499
20938
  *
19500
- * @internal
20939
+ * @private
19501
20940
  */
19502
20941
  exports.FeatureWalkMode = void 0;
19503
20942
  (function (FeatureWalkMode) {
@@ -19617,6 +21056,7 @@
19617
21056
  }
19618
21057
  }
19619
21058
  }
21059
+ // @ts-ignore
19620
21060
  if (SyntaxValidationResult.Valid == evaluateSyntax({ ...node, val: nodes }, {}).valid) {
19621
21061
  node.val = nodes;
19622
21062
  }
@@ -19682,6 +21122,7 @@
19682
21122
  }
19683
21123
  }
19684
21124
  class InlineCssVariablesFeature {
21125
+ accept = new Set([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType]);
19685
21126
  get ordering() {
19686
21127
  return 0;
19687
21128
  }
@@ -19695,9 +21136,10 @@
19695
21136
  }
19696
21137
  }
19697
21138
  run(ast, options = {}, parent, context) {
19698
- if (!('chi' in ast)) {
19699
- return null;
19700
- }
21139
+ // if (!('chi' in ast)) {
21140
+ //
21141
+ // return null;
21142
+ // }
19701
21143
  if (!('variableScope' in context)) {
19702
21144
  context.variableScope = new Map;
19703
21145
  }
@@ -20578,8 +22020,13 @@
20578
22020
  });
20579
22021
  }
20580
22022
  add(...declarations) {
22023
+ let name;
20581
22024
  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)) {
22025
+ name = declaration.typ != exports.EnumToken.DeclarationNodeType ? null : declaration.nam.toLowerCase();
22026
+ if (declaration.typ != exports.EnumToken.DeclarationNodeType ||
22027
+ 'composes' === name ||
22028
+ (typeof this.options.removeDuplicateDeclarations === 'string' && this.options.removeDuplicateDeclarations === name) ||
22029
+ (Array.isArray(this.options.removeDuplicateDeclarations) ? this.options.removeDuplicateDeclarations.includes(declaration.nam) : !this.options.removeDuplicateDeclarations)) {
20583
22030
  this.declarations.set(Number(Math.random().toString().slice(2)).toString(36), declaration);
20584
22031
  continue;
20585
22032
  }
@@ -20664,6 +22111,7 @@
20664
22111
  }
20665
22112
 
20666
22113
  class ComputeShorthandFeature {
22114
+ accept = new Set([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType, exports.EnumToken.KeyFramesRuleNodeType]);
20667
22115
  get ordering() {
20668
22116
  return 3;
20669
22117
  }
@@ -20716,6 +22164,7 @@
20716
22164
  }
20717
22165
 
20718
22166
  class ComputeCalcExpressionFeature {
22167
+ accept = new Set([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType]);
20719
22168
  get ordering() {
20720
22169
  return 1;
20721
22170
  }
@@ -20738,7 +22187,7 @@
20738
22187
  }
20739
22188
  const set = new Set;
20740
22189
  for (const { value, parent } of walkValues(node.val, node, {
20741
- event: exports.WalkerValueEvent.Enter,
22190
+ event: exports.WalkerEvent.Enter,
20742
22191
  // @ts-ignore
20743
22192
  fn(node, parent) {
20744
22193
  if (parent != null &&
@@ -20815,7 +22264,7 @@
20815
22264
 
20816
22265
  function translateX(x, from) {
20817
22266
  const matrix = identity();
20818
- matrix[3 * 4 + 0] = x;
22267
+ matrix[3 * 4] = x;
20819
22268
  return multiply(from, matrix);
20820
22269
  }
20821
22270
  function translateY(y, from) {
@@ -20830,13 +22279,13 @@
20830
22279
  }
20831
22280
  function translate(translate, from) {
20832
22281
  const matrix = identity();
20833
- matrix[3 * 4 + 0] = translate[0];
22282
+ matrix[3 * 4] = translate[0];
20834
22283
  matrix[3 * 4 + 1] = translate[1] ?? 0;
20835
22284
  return multiply(from, matrix);
20836
22285
  }
20837
22286
  function translate3d(translate, from) {
20838
22287
  const matrix = identity();
20839
- matrix[3 * 4 + 0] = translate[0];
22288
+ matrix[3 * 4] = translate[0];
20840
22289
  matrix[3 * 4 + 1] = translate[1];
20841
22290
  matrix[3 * 4 + 2] = translate[2];
20842
22291
  return multiply(from, matrix);
@@ -20859,34 +22308,34 @@
20859
22308
  x *= unit;
20860
22309
  y *= unit;
20861
22310
  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);
22311
+ matrix[0] = 1 - 2 * (y * y + z * z) * sq;
22312
+ matrix[1] = 2 * (x * y * sq + z * sc);
22313
+ matrix[2] = 2 * (x * z * sq - y * sc);
22314
+ matrix[4] = 2 * (x * y * sq - z * sc);
22315
+ matrix[4 + 1] = 1 - 2 * (x * x + z * z) * sq;
22316
+ matrix[4 + 2] = 2 * (y * z * sq + x * sc);
22317
+ matrix[2 * 4] = 2 * (x * z * sq + y * sc);
20869
22318
  matrix[2 * 4 + 1] = 2 * (y * z * sq - x * sc);
20870
22319
  matrix[2 * 4 + 2] = 1 - 2 * (x * x + y * y) * sq;
20871
22320
  return multiply(from, matrix);
20872
22321
  }
20873
22322
  function rotate(angle, from) {
20874
22323
  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);
22324
+ matrix[0] = Math.cos(angle);
22325
+ matrix[1] = Math.sin(angle);
22326
+ matrix[4] = -Math.sin(angle);
22327
+ matrix[4 + 1] = Math.cos(angle);
20879
22328
  return multiply(from, matrix);
20880
22329
  }
20881
22330
 
20882
22331
  function scaleX(x, from) {
20883
22332
  const matrix = identity();
20884
- matrix[0 * 4 + 0] = x;
22333
+ matrix[0] = x;
20885
22334
  return multiply(from, matrix);
20886
22335
  }
20887
22336
  function scaleY(y, from) {
20888
22337
  const matrix = identity();
20889
- matrix[1 * 4 + 1] = y;
22338
+ matrix[4 + 1] = y;
20890
22339
  return multiply(from, matrix);
20891
22340
  }
20892
22341
  function scaleZ(z, from) {
@@ -20896,14 +22345,14 @@
20896
22345
  }
20897
22346
  function scale(x, y, from) {
20898
22347
  const matrix = identity();
20899
- matrix[0 * 4 + 0] = x;
20900
- matrix[1 * 4 + 1] = y;
22348
+ matrix[0] = x;
22349
+ matrix[4 + 1] = y;
20901
22350
  return multiply(from, matrix);
20902
22351
  }
20903
22352
  function scale3d(x, y, z, from) {
20904
22353
  const matrix = identity();
20905
- matrix[0 * 4 + 0] = x;
20906
- matrix[1 * 4 + 1] = y;
22354
+ matrix[0] = x;
22355
+ matrix[4 + 1] = y;
20907
22356
  matrix[2 * 4 + 2] = z;
20908
22357
  return multiply(from, matrix);
20909
22358
  }
@@ -20928,27 +22377,27 @@
20928
22377
  function matrix(values) {
20929
22378
  const matrix = identity();
20930
22379
  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];
22380
+ matrix[0] = values[0];
22381
+ matrix[1] = values[1];
22382
+ matrix[4] = values[2];
22383
+ matrix[4 + 1] = values[3];
22384
+ matrix[3 * 4] = values[4];
20936
22385
  matrix[3 * 4 + 1] = values[5];
20937
22386
  }
20938
22387
  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];
22388
+ matrix[0] = values[0];
22389
+ matrix[1] = values[1];
22390
+ matrix[2] = values[2];
22391
+ matrix[3] = values[3];
22392
+ matrix[4] = values[4];
22393
+ matrix[4 + 1] = values[5];
22394
+ matrix[4 + 2] = values[6];
22395
+ matrix[4 + 3] = values[7];
22396
+ matrix[2 * 4] = values[8];
20948
22397
  matrix[2 * 4 + 1] = values[9];
20949
22398
  matrix[2 * 4 + 2] = values[10];
20950
22399
  matrix[2 * 4 + 3] = values[11];
20951
- matrix[3 * 4 + 0] = values[12];
22400
+ matrix[3 * 4] = values[12];
20952
22401
  matrix[3 * 4 + 1] = values[13];
20953
22402
  matrix[3 * 4 + 2] = values[14];
20954
22403
  matrix[3 * 4 + 3] = values[15];
@@ -20973,11 +22422,11 @@
20973
22422
  typ: exports.EnumToken.FunctionTokenType,
20974
22423
  val: 'matrix',
20975
22424
  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],
22425
+ matrix[0],
22426
+ matrix[1],
22427
+ matrix[4],
22428
+ matrix[4 + 1],
22429
+ matrix[3 * 4],
20981
22430
  matrix[3 * 4 + 1]
20982
22431
  ].reduce((acc, t) => {
20983
22432
  if (acc.length > 0) {
@@ -21160,10 +22609,6 @@
21160
22609
  }
21161
22610
  }
21162
22611
  if (transforms.has('skew')) {
21163
- // if (round(decomposed.skew[0]) == 0) {
21164
- //
21165
- // skew.delete('x');
21166
- // }
21167
22612
  if (round(decomposed.skew[1]) == 0) {
21168
22613
  skew.delete('y');
21169
22614
  }
@@ -21203,7 +22648,7 @@
21203
22648
  scales.delete('x');
21204
22649
  }
21205
22650
  if (scales.size == 1) {
21206
- let prefix = scales.has('x') ? '' : scales.has('y') ? 'Y' : 'Z';
22651
+ let prefix = scales.has('x') ? 'X' : scales.has('y') ? 'Y' : 'Z';
21207
22652
  result.push({
21208
22653
  typ: exports.EnumToken.FunctionTokenType,
21209
22654
  val: 'scale' + prefix,
@@ -21246,13 +22691,9 @@
21246
22691
  ] : result;
21247
22692
  }
21248
22693
  function eqMatrix(a, b) {
21249
- // console.error(JSON.stringify({a, b}, null, 1));
21250
22694
  let mat = identity();
21251
22695
  let tmp = identity();
21252
- // @ts-ignore
21253
22696
  const data = (Array.isArray(a) ? a : parseMatrix(a));
21254
- // toZero(data);
21255
- // console.error({data});
21256
22697
  for (const transform of b) {
21257
22698
  tmp = computeMatrix([transform], identity());
21258
22699
  if (tmp == null) {
@@ -21260,8 +22701,6 @@
21260
22701
  }
21261
22702
  mat = multiply(mat, tmp);
21262
22703
  }
21263
- // toZero(mat);
21264
- // console.error({mat});
21265
22704
  if (mat == null) {
21266
22705
  return false;
21267
22706
  }
@@ -21274,23 +22713,126 @@
21274
22713
  }
21275
22714
  return true;
21276
22715
  }
22716
+ function minifyTransformFunctions(transform) {
22717
+ const name = transform.val.toLowerCase();
22718
+ if ('skewx' == name) {
22719
+ transform.val = 'skew';
22720
+ return transform;
22721
+ }
22722
+ if (!['translate', 'translate3d', 'scale', 'scale3d'].includes(name)) {
22723
+ return transform;
22724
+ }
22725
+ const values = [];
22726
+ for (const token of transform.chi) {
22727
+ if (token.typ == exports.EnumToken.CommentTokenType || token.typ == exports.EnumToken.WhitespaceTokenType || token.typ == exports.EnumToken.CommaTokenType) {
22728
+ continue;
22729
+ }
22730
+ if (![exports.EnumToken.NumberTokenType, exports.EnumToken.LengthTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.PercentageTokenType].includes(token.typ)) {
22731
+ return transform;
22732
+ }
22733
+ if (token.typ == exports.EnumToken.PercentageTokenType && typeof token.val == 'number' && name.startsWith('scale')) {
22734
+ Object.assign(token, { typ: exports.EnumToken.NumberTokenType, val: token.val / 100 });
22735
+ }
22736
+ values.push(token);
22737
+ }
22738
+ if ((name == 'translate' || name == 'scale') && values.length > 2) {
22739
+ return transform;
22740
+ }
22741
+ const ignoredValue = name.startsWith('scale') ? 1 : 0;
22742
+ const t = new Set(['x', 'y', 'z']);
22743
+ let i = 3;
22744
+ while (i--) {
22745
+ if (values.length <= i || values[i].val == ignoredValue) {
22746
+ t.delete(i == 0 ? 'x' : i == 1 ? 'y' : 'z');
22747
+ }
22748
+ }
22749
+ if (name == 'translate3d' || name == 'translate') {
22750
+ if (t.size == 0) {
22751
+ return {
22752
+ typ: exports.EnumToken.FunctionTokenType,
22753
+ val: 'translate',
22754
+ chi: [
22755
+ { typ: exports.EnumToken.NumberTokenType, val: 0 }
22756
+ ]
22757
+ };
22758
+ }
22759
+ if (t.size == 1) {
22760
+ return {
22761
+ typ: exports.EnumToken.FunctionTokenType,
22762
+ val: 'translate' + (t.has('x') ? '' : t.has('y') ? 'Y' : 'Z'),
22763
+ chi: [
22764
+ values[t.has('x') ? 0 : t.has('y') ? 1 : 2]
22765
+ ]
22766
+ };
22767
+ }
22768
+ if (t.size == 2) {
22769
+ if (t.has('z')) {
22770
+ return transform;
22771
+ }
22772
+ return {
22773
+ typ: exports.EnumToken.FunctionTokenType,
22774
+ val: 'translate',
22775
+ chi: [
22776
+ values[0],
22777
+ { typ: exports.EnumToken.CommaTokenType },
22778
+ values[1]
22779
+ ]
22780
+ };
22781
+ }
22782
+ }
22783
+ if (name == 'scale3d' || name == 'scale') {
22784
+ if (t.size == 0) {
22785
+ return {
22786
+ typ: exports.EnumToken.FunctionTokenType,
22787
+ val: 'scale',
22788
+ chi: [
22789
+ { typ: exports.EnumToken.NumberTokenType, val: 1 }
22790
+ ]
22791
+ };
22792
+ }
22793
+ if (t.size == 1) {
22794
+ return {
22795
+ typ: exports.EnumToken.FunctionTokenType,
22796
+ val: 'scale' + (t.has('x') ? 'X' : t.has('y') ? 'Y' : 'Z'),
22797
+ chi: [
22798
+ values[t.has('x') ? 0 : t.has('y') ? 1 : 2]
22799
+ ]
22800
+ };
22801
+ }
22802
+ if (t.size == 2) {
22803
+ if (t.has('z')) {
22804
+ return transform;
22805
+ }
22806
+ return {
22807
+ typ: exports.EnumToken.FunctionTokenType,
22808
+ val: 'scale',
22809
+ chi: [
22810
+ values[0],
22811
+ { typ: exports.EnumToken.CommaTokenType },
22812
+ values[1]
22813
+ ]
22814
+ };
22815
+ }
22816
+ }
22817
+ return transform;
22818
+ }
21277
22819
 
21278
22820
  function skewX(x, from) {
21279
22821
  const matrix = identity();
21280
- matrix[1 * 4 + 0] = Math.tan(x);
22822
+ matrix[4] = Math.tan(x);
21281
22823
  return multiply(from, matrix);
21282
22824
  }
21283
22825
  function skewY(y, from) {
21284
22826
  const matrix = identity();
21285
- matrix[0 * 4 + 1] = Math.tan(y);
22827
+ matrix[1] = Math.tan(y);
21286
22828
  return multiply(from, matrix);
21287
22829
  }
21288
22830
  // convert angle to radian
21289
22831
  function skew(values, from) {
21290
22832
  const matrix = identity();
21291
- matrix[1 * 4 + 0] = Math.tan(values[0]);
22833
+ matrix[4] = Math.tan(values[0]);
21292
22834
  if (values.length > 1) {
21293
- matrix[0 * 4 + 1] = Math.tan(values[1]);
22835
+ matrix[1] = Math.tan(values[1]);
21294
22836
  }
21295
22837
  return multiply(from, matrix);
21296
22838
  }
@@ -21329,8 +22871,6 @@
21329
22871
  });
21330
22872
  }
21331
22873
  }
21332
- // console.error({matrix});
21333
- // matrix = toZero(matrix) as Matrix;
21334
22874
  return {
21335
22875
  matrix: serialize(toZero(matrix)),
21336
22876
  cumulative,
@@ -21354,7 +22894,7 @@
21354
22894
  {
21355
22895
  values.length = 0;
21356
22896
  const children = stripCommaToken(transformList[i].chi.slice());
21357
- const valCount = transformList[i].val == 'translate3d' || transformList[i].val == 'translate' ? 3 : 1;
22897
+ const valCount = transformList[i].val == 'translate3d' ? 3 : transformList[i].val == 'translate' ? 2 : 1;
21358
22898
  for (let j = 0; j < children.length; j++) {
21359
22899
  if (children[j].typ == exports.EnumToken.WhitespaceTokenType) {
21360
22900
  continue;
@@ -21441,7 +22981,7 @@
21441
22981
  const children = stripCommaToken(transformList[i].chi.slice());
21442
22982
  for (let k = 0; k < children.length; k++) {
21443
22983
  child = children[k];
21444
- if (child.typ != exports.EnumToken.NumberTokenType) {
22984
+ if (child.typ != exports.EnumToken.NumberTokenType && child.typ != exports.EnumToken.PercentageTokenType) {
21445
22985
  return null;
21446
22986
  }
21447
22987
  values.push(getNumber(child));
@@ -21595,6 +23135,7 @@
21595
23135
  }
21596
23136
 
21597
23137
  class TransformCssFeature {
23138
+ accept = new Set([exports.EnumToken.RuleNodeType, exports.EnumToken.KeyFramesRuleNodeType]);
21598
23139
  get ordering() {
21599
23140
  return 4;
21600
23141
  }
@@ -21621,28 +23162,21 @@
21621
23162
  if (node.typ != exports.EnumToken.DeclarationNodeType || !node.nam.match(/^(-[a-z]+-)?transform$/)) {
21622
23163
  continue;
21623
23164
  }
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
- }, []);
23165
+ const children = [];
23166
+ for (const child of node.val) {
23167
+ children.push(child.typ == exports.EnumToken.FunctionTokenType ? minifyTransformFunctions(child) : child);
23168
+ }
21640
23169
  consumeWhitespace(children);
21641
- let { matrix, cumulative, minified } = compute(children) ?? {};
23170
+ let { matrix, cumulative, minified } = compute(children) ?? {
23171
+ matrix: null,
23172
+ cumulative: null,
23173
+ minified: null
23174
+ };
21642
23175
  if (matrix == null || cumulative == null || minified == null) {
23176
+ node.val = children;
21643
23177
  continue;
21644
23178
  }
21645
- let r = [filterValues(node.val.slice())];
23179
+ let r = [filterValues(children)];
21646
23180
  if (eqMatrix(matrix, cumulative)) {
21647
23181
  r.push(cumulative);
21648
23182
  }
@@ -21721,7 +23255,7 @@
21721
23255
  }
21722
23256
  replacement = parent;
21723
23257
  for (const feature of options.features) {
21724
- if ((feature.processMode & exports.FeatureWalkMode.Pre) === 0) {
23258
+ if ((feature.processMode & exports.FeatureWalkMode.Pre) === 0 || (feature.accept != null && !feature.accept.has(parent.typ))) {
21725
23259
  continue;
21726
23260
  }
21727
23261
  const result = feature.run(replacement, options, parent.parent ?? ast, context, exports.FeatureWalkMode.Pre);
@@ -21760,7 +23294,7 @@
21760
23294
  replacement = parent;
21761
23295
  if (postprocess) {
21762
23296
  for (const feature of options.features) {
21763
- if ((feature.processMode & exports.FeatureWalkMode.Post) === 0) {
23297
+ if ((feature.processMode & exports.FeatureWalkMode.Post) === 0 || (feature.accept != null && !feature.accept.has(parent.typ))) {
21764
23298
  continue;
21765
23299
  }
21766
23300
  const result = feature.run(replacement, options, parent.parent ?? ast, context, exports.FeatureWalkMode.Post);
@@ -21891,6 +23425,7 @@
21891
23425
  continue;
21892
23426
  }
21893
23427
  if (previous?.typ == exports.EnumToken.AtRuleNodeType &&
23428
+ node.nam != 'font-face' &&
21894
23429
  previous.nam == node.nam &&
21895
23430
  previous.val == node.val) {
21896
23431
  if ('chi' in node) {
@@ -22039,7 +23574,9 @@
22039
23574
  break;
22040
23575
  }
22041
23576
  if (shouldMerge) {
23577
+ // @ts-ignore
22042
23578
  if (((node.typ == exports.EnumToken.RuleNodeType || node.typ == exports.EnumToken.KeyFramesRuleNodeType) && node.sel == previous.sel) ||
23579
+ // @ts-ignore
22043
23580
  (node.typ == exports.EnumToken.AtRuleNodeType) && node.val != 'font-face' && node.val == previous.val) {
22044
23581
  // @ts-ignore
22045
23582
  node.chi.unshift(...previous.chi);
@@ -22050,7 +23587,7 @@
22050
23587
  continue;
22051
23588
  }
22052
23589
  else if (node.typ == previous?.typ && [exports.EnumToken.KeyFramesRuleNodeType, exports.EnumToken.RuleNodeType].includes(node.typ)) {
22053
- const intersect = diff(previous, node, reducer, options);
23590
+ const intersect = diff$1(previous, node, reducer, options);
22054
23591
  if (intersect != null) {
22055
23592
  if (intersect.node1.chi.length == 0) {
22056
23593
  ast.chi.splice(i--, 1);
@@ -22096,7 +23633,7 @@
22096
23633
  nodeIndex = i;
22097
23634
  }
22098
23635
  if (recursive && node != null && ('chi' in node)) {
22099
- if (node.typ == exports.EnumToken.KeyframesAtRuleNodeType || !node.chi.some(n => n.typ == exports.EnumToken.DeclarationNodeType)) {
23636
+ if (node.typ == exports.EnumToken.KeyframesAtRuleNodeType || !node.chi.some((n) => n.typ == exports.EnumToken.DeclarationNodeType)) {
22100
23637
  if (!(node.typ == exports.EnumToken.AtRuleNodeType && node.nam != 'font-face')) {
22101
23638
  doMinify(node, options, recursive, errors, nestingContent, context);
22102
23639
  }
@@ -22529,7 +24066,7 @@
22529
24066
  *
22530
24067
  * @private
22531
24068
  */
22532
- function diff(n1, n2, reducer, options = {}) {
24069
+ function diff$1(n1, n2, reducer, options = {}) {
22533
24070
  if (!('cache' in options)) {
22534
24071
  options.cache = new WeakMap();
22535
24072
  }
@@ -22707,14 +24244,11 @@
22707
24244
  */
22708
24245
  function expand(ast) {
22709
24246
  const result = { ...ast, chi: [] };
22710
- // @ts-ignore
22711
24247
  for (let i = 0; i < ast.chi.length; i++) {
22712
- // @ts-ignore
22713
24248
  const node = ast.chi[i];
22714
24249
  if (node.typ == exports.EnumToken.RuleNodeType) {
22715
24250
  // @ts-ignore
22716
24251
  result.chi.push(...expandRule(node));
22717
- // i += expanded.length - 1;
22718
24252
  }
22719
24253
  else if (node.typ == exports.EnumToken.AtRuleNodeType && 'chi' in node) {
22720
24254
  let hasRule = false;
@@ -22729,6 +24263,10 @@
22729
24263
  // @ts-ignore
22730
24264
  result.chi.push({ ...(hasRule ? expand(node) : node) });
22731
24265
  }
24266
+ else {
24267
+ // @ts-ignore
24268
+ result.chi.push(node);
24269
+ }
22732
24270
  }
22733
24271
  return result;
22734
24272
  }
@@ -22911,13 +24449,7 @@
22911
24449
  return 1;
22912
24450
  }
22913
24451
  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
- }, '');
24452
+ }).reduce((acc, curr) => acc + (curr == '&' ? replace : curr), '');
22921
24453
  }
22922
24454
 
22923
24455
  const matchUrl = /^(https?:)?\/\//;
@@ -22932,6 +24464,9 @@
22932
24464
  //
22933
24465
  // return path;
22934
24466
  // }
24467
+ if (path === '') {
24468
+ return '';
24469
+ }
22935
24470
  let i = 0;
22936
24471
  let parts = [''];
22937
24472
  for (; i < path.length; i++) {
@@ -22939,9 +24474,10 @@
22939
24474
  if (chr == '/') {
22940
24475
  parts.push('');
22941
24476
  }
22942
- else if (chr == '?' || chr == '#') {
22943
- break;
22944
- }
24477
+ // else if (chr == '?' || chr == '#') {
24478
+ //
24479
+ // break;
24480
+ // }
22945
24481
  else {
22946
24482
  parts[parts.length - 1] += chr;
22947
24483
  }
@@ -22955,6 +24491,12 @@
22955
24491
  * @private
22956
24492
  */
22957
24493
  function splitPath(result) {
24494
+ if (result.length == 0) {
24495
+ return { parts: [], i: 0 };
24496
+ }
24497
+ if (result === '/') {
24498
+ return { parts: ['/'], i: 0 };
24499
+ }
22958
24500
  const parts = [''];
22959
24501
  let i = 0;
22960
24502
  for (; i < result.length; i++) {
@@ -22996,6 +24538,23 @@
22996
24538
  relative: url
22997
24539
  };
22998
24540
  }
24541
+ cwd ??= '';
24542
+ currentDirectory ??= '';
24543
+ if (currentDirectory !== '' && url.startsWith(currentDirectory + '/')) {
24544
+ return {
24545
+ absolute: url,
24546
+ relative: url.slice(currentDirectory.length + 1)
24547
+ };
24548
+ }
24549
+ if (currentDirectory === '' && cwd !== '' && url.startsWith(cwd == '/' ? cwd : cwd + '/')) {
24550
+ cwd = normalize(cwd);
24551
+ const absolute = normalize(url);
24552
+ const prefix = cwd == '/' ? cwd : cwd + '/';
24553
+ return {
24554
+ absolute,
24555
+ relative: absolute.startsWith(prefix) ? absolute.slice(prefix.length) : diff(absolute, cwd)
24556
+ };
24557
+ }
22999
24558
  if (matchUrl.test(currentDirectory)) {
23000
24559
  const path = new URL(url, currentDirectory).href;
23001
24560
  return {
@@ -23010,9 +24569,15 @@
23010
24569
  else if (currentDirectory.charAt(0) == '/') {
23011
24570
  result = dirname(currentDirectory) + '/' + url;
23012
24571
  }
23013
- let { parts, i } = splitPath(result);
23014
- const absolute = parts.join('/');
23015
- const { parts: dirs } = splitPath(cwd ?? currentDirectory);
24572
+ const absolute = normalize(result);
24573
+ return {
24574
+ absolute,
24575
+ relative: absolute === '' ? '' : diff(absolute, cwd ?? currentDirectory),
24576
+ };
24577
+ }
24578
+ function diff(path1, path2) {
24579
+ let { parts } = splitPath(path1);
24580
+ const { parts: dirs } = splitPath(path2);
23016
24581
  for (const p of dirs) {
23017
24582
  if (parts[0] == p) {
23018
24583
  parts.shift();
@@ -23021,20 +24586,69 @@
23021
24586
  parts.unshift('..');
23022
24587
  }
23023
24588
  }
23024
- return {
23025
- absolute,
23026
- relative: parts.join('/') + (i < result.length ? result.slice(i) : '')
23027
- };
24589
+ return parts.join('/');
24590
+ }
24591
+ function normalize(path) {
24592
+ let parts = [];
24593
+ let i = 0;
24594
+ for (; i < path.length; i++) {
24595
+ const chr = path.charAt(i);
24596
+ if (chr == '/') {
24597
+ if (parts.length == 0 || parts[parts.length - 1] !== '') {
24598
+ parts.push('');
24599
+ }
24600
+ }
24601
+ else if (chr == '?' || chr == '#') {
24602
+ break;
24603
+ }
24604
+ else {
24605
+ parts[parts.length - 1] += chr;
24606
+ }
24607
+ }
24608
+ let k = -1;
24609
+ while (++k < parts.length) {
24610
+ if (parts[k] == '.') {
24611
+ parts.splice(k--, 1);
24612
+ }
24613
+ else if (parts[k] == '..') {
24614
+ parts.splice(k - 1, 2);
24615
+ k -= 2;
24616
+ }
24617
+ }
24618
+ return (path.charAt(0) == '/' ? '/' : '') + parts.join('/');
23028
24619
  }
23029
24620
 
24621
+ /**
24622
+ * response type
24623
+ */
24624
+ exports.ResponseType = void 0;
24625
+ (function (ResponseType) {
24626
+ /**
24627
+ * return text
24628
+ */
24629
+ ResponseType[ResponseType["Text"] = 0] = "Text";
24630
+ /**
24631
+ * return a readable stream
24632
+ */
24633
+ ResponseType[ResponseType["ReadableStream"] = 1] = "ReadableStream";
24634
+ /**
24635
+ * return an arraybuffer
24636
+ */
24637
+ ResponseType[ResponseType["ArrayBuffer"] = 2] = "ArrayBuffer";
24638
+ })(exports.ResponseType || (exports.ResponseType = {}));
24639
+
23030
24640
  /**
23031
24641
  * default file or url loader
23032
24642
  * @param url
23033
24643
  * @param currentFile
23034
24644
  *
24645
+ * @param responseType
23035
24646
  * @private
23036
24647
  */
23037
- async function load(url, currentFile = '.') {
24648
+ async function load(url, currentFile = '.', responseType = false) {
24649
+ if (typeof responseType == 'boolean') {
24650
+ responseType = responseType ? exports.ResponseType.ReadableStream : exports.ResponseType.Text;
24651
+ }
23038
24652
  let t;
23039
24653
  if (matchUrl.test(url)) {
23040
24654
  t = new URL(url);
@@ -23044,21 +24658,23 @@
23044
24658
  }
23045
24659
  else {
23046
24660
  const path = resolve(url, currentFile).absolute;
23047
- // @ts-ignore
23048
24661
  t = new URL(path, self.origin);
23049
24662
  }
23050
- // @ts-ignore
23051
- return fetch(t, t.origin != self.origin ? { mode: 'cors' } : {}).then((response) => {
24663
+ return fetch(t, t.origin != self.origin ? { mode: 'cors' } : {}).then(async (response) => {
23052
24664
  if (!response.ok) {
23053
24665
  throw new Error(`${response.status} ${response.statusText} ${response.url}`);
23054
24666
  }
23055
- return response.body;
24667
+ if (responseType == exports.ResponseType.ArrayBuffer) {
24668
+ return response.arrayBuffer();
24669
+ }
24670
+ return responseType == exports.ResponseType.ReadableStream ? response.body : await response.text();
23056
24671
  });
23057
24672
  }
23058
24673
  /**
23059
24674
  * render the ast tree
23060
24675
  * @param data
23061
24676
  * @param options
24677
+ * @param mapping
23062
24678
  *
23063
24679
  * Example:
23064
24680
  *
@@ -23083,17 +24699,18 @@
23083
24699
  * // }
23084
24700
  * ```
23085
24701
  */
23086
- function render(data, options = {}) {
24702
+ function render(data, options = {}, mapping) {
23087
24703
  return doRender(data, Object.assign(options, {
23088
24704
  resolve,
23089
24705
  dirname,
23090
24706
  cwd: options.cwd ?? self.location.pathname.endsWith('/') ? self.location.pathname : dirname(self.location.pathname)
23091
- }));
24707
+ }), mapping);
23092
24708
  }
23093
24709
  /**
23094
24710
  * parse css file
23095
24711
  * @param file url or path
23096
24712
  * @param options
24713
+ * @param asStream load file as stream
23097
24714
  *
23098
24715
  * @throws Error file not found
23099
24716
  *
@@ -23112,8 +24729,8 @@
23112
24729
  * console.log(result.ast);
23113
24730
  * ```
23114
24731
  */
23115
- async function parseFile(file, options = {}) {
23116
- return load(file).then(stream => parse(stream, { src: file, ...options }));
24732
+ async function parseFile(file, options = {}, asStream = false) {
24733
+ return Promise.resolve((options.load ?? load)(file, '.', asStream)).then(stream => parse(stream, { src: file, ...options }));
23117
24734
  }
23118
24735
  /**
23119
24736
  * parse css
@@ -23147,6 +24764,7 @@
23147
24764
  return doParse(stream instanceof ReadableStream ? tokenizeStream(stream) : tokenize$1({
23148
24765
  stream,
23149
24766
  buffer: '',
24767
+ offset: 0,
23150
24768
  position: { ind: 0, lin: 1, col: 1 },
23151
24769
  currentPosition: { ind: -1, lin: 1, col: 0 }
23152
24770
  }), Object.assign(options, {
@@ -23154,12 +24772,16 @@
23154
24772
  resolve,
23155
24773
  dirname,
23156
24774
  cwd: options.cwd ?? self.location.pathname.endsWith('/') ? self.location.pathname : dirname(self.location.pathname)
23157
- }));
24775
+ })).then(result => {
24776
+ const { revMapping, ...res } = result;
24777
+ return res;
24778
+ });
23158
24779
  }
23159
24780
  /**
23160
24781
  * transform css file
23161
24782
  * @param file url or path
23162
24783
  * @param options
24784
+ * @param asStream load file as stream
23163
24785
  *
23164
24786
  * Example:
23165
24787
  *
@@ -23176,8 +24798,8 @@
23176
24798
  * console.log(result.code);
23177
24799
  * ```
23178
24800
  */
23179
- async function transformFile(file, options = {}) {
23180
- return load(file).then(stream => transform(stream, { src: file, ...options }));
24801
+ async function transformFile(file, options = {}, asStream = false) {
24802
+ return Promise.resolve((options.load ?? load)(file, '.', asStream)).then(stream => transform(stream, { src: file, ...options }));
23181
24803
  }
23182
24804
  /**
23183
24805
  * transform css
@@ -23205,8 +24827,21 @@
23205
24827
  options = { minify: true, removeEmpty: true, removeCharset: true, ...options };
23206
24828
  const startTime = performance.now();
23207
24829
  return parse(css, options).then((parseResult) => {
24830
+ let mapping = null;
24831
+ let importMapping = null;
24832
+ if (typeof options.module == 'number' && (options.module & exports.ModuleScopeEnumOptions.ICSS)) {
24833
+ mapping = parseResult.mapping;
24834
+ importMapping = parseResult.importMapping;
24835
+ }
24836
+ else if (typeof options.module == 'object' && typeof options.module.scoped == 'number' && (options.module.scoped & exports.ModuleScopeEnumOptions.ICSS)) {
24837
+ mapping = parseResult.mapping;
24838
+ importMapping = parseResult.importMapping;
24839
+ }
23208
24840
  // ast already expanded by parse
23209
- const rendered = render(parseResult.ast, { ...options, expandNestingRules: false });
24841
+ const rendered = render(parseResult.ast, {
24842
+ ...options,
24843
+ expandNestingRules: false
24844
+ }, mapping != null ? { mapping, importMapping } : null);
23210
24845
  return {
23211
24846
  ...parseResult,
23212
24847
  ...rendered,