@tbela99/css-parser 1.3.2 → 1.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +59 -20
  3. package/dist/index-umd-web.js +1846 -1075
  4. package/dist/index.cjs +1941 -1202
  5. package/dist/index.d.ts +914 -181
  6. package/dist/lib/ast/expand.js +5 -10
  7. package/dist/lib/ast/features/calc.js +8 -8
  8. package/dist/lib/ast/features/inlinecssvariables.js +9 -8
  9. package/dist/lib/ast/features/prefix.js +5 -15
  10. package/dist/lib/ast/features/shorthand.js +5 -6
  11. package/dist/lib/ast/features/transform.js +18 -25
  12. package/dist/lib/ast/features/type.js +4 -2
  13. package/dist/lib/ast/minify.js +56 -112
  14. package/dist/lib/ast/transform/compute.js +2 -4
  15. package/dist/lib/ast/transform/matrix.js +20 -20
  16. package/dist/lib/ast/transform/minify.js +105 -12
  17. package/dist/lib/ast/transform/rotate.js +11 -11
  18. package/dist/lib/ast/transform/scale.js +6 -6
  19. package/dist/lib/ast/transform/skew.js +4 -4
  20. package/dist/lib/ast/transform/translate.js +3 -3
  21. package/dist/lib/ast/transform/utils.js +30 -37
  22. package/dist/lib/ast/types.js +16 -4
  23. package/dist/lib/ast/walk.js +172 -70
  24. package/dist/lib/fs/resolve.js +12 -7
  25. package/dist/lib/parser/declaration/list.js +3 -1
  26. package/dist/lib/parser/parse.js +441 -161
  27. package/dist/lib/parser/tokenize.js +12 -14
  28. package/dist/lib/renderer/render.js +7 -7
  29. package/dist/lib/syntax/color/cmyk.js +6 -3
  30. package/dist/lib/syntax/color/color-mix.js +2 -3
  31. package/dist/lib/syntax/color/color.js +28 -6
  32. package/dist/lib/syntax/color/hex.js +3 -0
  33. package/dist/lib/syntax/color/hsl.js +18 -7
  34. package/dist/lib/syntax/color/hwb.js +3 -3
  35. package/dist/lib/syntax/color/lab.js +4 -4
  36. package/dist/lib/syntax/color/lch.js +7 -4
  37. package/dist/lib/syntax/color/oklab.js +4 -4
  38. package/dist/lib/syntax/color/oklch.js +18 -6
  39. package/dist/lib/syntax/color/relativecolor.js +9 -56
  40. package/dist/lib/syntax/color/srgb.js +1 -1
  41. package/dist/lib/syntax/syntax.js +36 -18
  42. package/dist/lib/validation/at-rules/container.js +11 -0
  43. package/dist/lib/validation/at-rules/counter-style.js +11 -0
  44. package/dist/lib/validation/at-rules/font-feature-values.js +11 -0
  45. package/dist/lib/validation/at-rules/keyframes.js +11 -0
  46. package/dist/lib/validation/at-rules/layer.js +11 -0
  47. package/dist/lib/validation/at-rules/media.js +11 -0
  48. package/dist/lib/validation/at-rules/page-margin-box.js +11 -0
  49. package/dist/lib/validation/at-rules/page.js +11 -0
  50. package/dist/lib/validation/at-rules/supports.js +11 -0
  51. package/dist/lib/validation/at-rules/when.js +11 -0
  52. package/dist/lib/validation/config.js +0 -2
  53. package/dist/lib/validation/config.json.js +21 -9
  54. package/dist/lib/validation/parser/parse.js +53 -2
  55. package/dist/lib/validation/syntax.js +199 -36
  56. package/dist/node.js +63 -36
  57. package/dist/web.js +84 -25
  58. package/package.json +7 -5
  59. 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
@@ -336,7 +348,7 @@
336
348
  /**
337
349
  * keyframe rule node type
338
350
  */
339
- EnumToken[EnumToken["KeyFrameRuleNodeType"] = 73] = "KeyFrameRuleNodeType";
351
+ EnumToken[EnumToken["KeyFramesRuleNodeType"] = 73] = "KeyFramesRuleNodeType";
340
352
  /**
341
353
  * class selector token type
342
354
  */
@@ -416,7 +428,7 @@
416
428
  /**
417
429
  * keyframe at rule node type
418
430
  */
419
- EnumToken[EnumToken["KeyframeAtRuleNodeType"] = 93] = "KeyframeAtRuleNodeType";
431
+ EnumToken[EnumToken["KeyframesAtRuleNodeType"] = 93] = "KeyframesAtRuleNodeType";
420
432
  /**
421
433
  * invalid declaration node type
422
434
  */
@@ -951,12 +963,15 @@
951
963
  function lchToken(values) {
952
964
  values[2] = toPrecisionAngle(values[2]);
953
965
  const chi = [
954
- { typ: exports.EnumToken.NumberTokenType, val: values[0] },
955
- { typ: exports.EnumToken.NumberTokenType, val: values[1] },
966
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[0]) },
967
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[1]) },
956
968
  { typ: exports.EnumToken.NumberTokenType, val: values[2] },
957
969
  ];
958
970
  if (values.length == 4) {
959
- chi.push({ typ: exports.EnumToken.LiteralTokenType, val: '/' }, { typ: exports.EnumToken.PercentageTokenType, val: values[3] * 100 });
971
+ chi.push({ typ: exports.EnumToken.LiteralTokenType, val: '/' }, {
972
+ typ: exports.EnumToken.PercentageTokenType,
973
+ val: values[3] * 100
974
+ });
960
975
  }
961
976
  return {
962
977
  typ: exports.EnumToken.ColorTokenType,
@@ -1219,8 +1234,8 @@
1219
1234
  function oklchToken(values) {
1220
1235
  values[2] = toPrecisionAngle(values[2]);
1221
1236
  const chi = [
1222
- { typ: exports.EnumToken.NumberTokenType, val: values[0] },
1223
- { typ: exports.EnumToken.NumberTokenType, val: values[1] },
1237
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[0]) },
1238
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[1]) },
1224
1239
  { typ: exports.EnumToken.NumberTokenType, val: values[2] },
1225
1240
  ];
1226
1241
  if (values.length == 4) {
@@ -1262,16 +1277,28 @@
1262
1277
  return values == null ? null : srgb2oklch(...values);
1263
1278
  }
1264
1279
  function lab2oklchvalues(token) {
1280
+ const values = lab2oklabvalues(token);
1281
+ if (values == null) {
1282
+ return null;
1283
+ }
1265
1284
  // @ts-ignore
1266
- return labvalues2lchvalues(...lab2oklabvalues(token));
1285
+ return labvalues2lchvalues(...values);
1267
1286
  }
1268
1287
  function lch2oklchvalues(token) {
1288
+ const values = lch2oklabvalues(token);
1289
+ if (values == null) {
1290
+ return null;
1291
+ }
1269
1292
  // @ts-ignore
1270
- return labvalues2lchvalues(...lch2oklabvalues(token));
1293
+ return labvalues2lchvalues(...values);
1271
1294
  }
1272
1295
  function oklab2oklchvalues(token) {
1296
+ const values = getOKLABComponents(token);
1297
+ if (values == null) {
1298
+ return null;
1299
+ }
1273
1300
  // @ts-ignore
1274
- return labvalues2lchvalues(...getOKLABComponents(token));
1301
+ return labvalues2lchvalues(...values);
1275
1302
  }
1276
1303
  function srgb2oklch(r, g, blue, alpha) {
1277
1304
  // @ts-ignore
@@ -1371,9 +1398,9 @@
1371
1398
  }
1372
1399
  function oklabToken(values) {
1373
1400
  const chi = [
1374
- { typ: exports.EnumToken.NumberTokenType, val: values[0] },
1375
- { typ: exports.EnumToken.NumberTokenType, val: values[1] },
1376
- { typ: exports.EnumToken.NumberTokenType, val: values[2] },
1401
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[0]) },
1402
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[1]) },
1403
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[2]) },
1377
1404
  ];
1378
1405
  if (values.length == 4) {
1379
1406
  chi.push({ typ: exports.EnumToken.LiteralTokenType, val: '/' }, {
@@ -1589,9 +1616,9 @@
1589
1616
  }
1590
1617
  function labToken(values) {
1591
1618
  const chi = [
1592
- { typ: exports.EnumToken.NumberTokenType, val: values[0] },
1593
- { typ: exports.EnumToken.NumberTokenType, val: values[1] },
1594
- { typ: exports.EnumToken.NumberTokenType, val: values[2] },
1619
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[0]) },
1620
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[1]) },
1621
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[2]) },
1595
1622
  ];
1596
1623
  if (values.length == 4) {
1597
1624
  chi.push({ typ: exports.EnumToken.LiteralTokenType, val: '/' }, {
@@ -1992,7 +2019,7 @@
1992
2019
  return null;
1993
2020
  }
1994
2021
  const rgb = Lab_to_sRGB(l, a, b);
1995
- if (alpha != null && alpha != 1) {
2022
+ if (alpha != null && alpha < 1) {
1996
2023
  rgb.push(alpha);
1997
2024
  }
1998
2025
  return rgb;
@@ -2072,6 +2099,9 @@
2072
2099
  value[7] == value[8]) {
2073
2100
  value = `#${value[1]}${value[3]}${value[5]}${value[7] == 'f' ? '' : value[7]}`;
2074
2101
  }
2102
+ if (value.endsWith('ff')) {
2103
+ value = value.slice(0, -2);
2104
+ }
2075
2105
  }
2076
2106
  return named_color != null && named_color.length <= value.length ? named_color : value;
2077
2107
  }
@@ -2492,12 +2522,15 @@
2492
2522
  function hslToken(values) {
2493
2523
  values[0] = toPrecisionAngle(values[0] * 360);
2494
2524
  const chi = [
2495
- { typ: exports.EnumToken.NumberTokenType, val: values[0] },
2496
- { typ: exports.EnumToken.PercentageTokenType, val: values[1] * 100 },
2497
- { typ: exports.EnumToken.PercentageTokenType, val: values[2] * 100 },
2525
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[0]) },
2526
+ { typ: exports.EnumToken.PercentageTokenType, val: toPrecisionValue(values[1]) * 100 },
2527
+ { typ: exports.EnumToken.PercentageTokenType, val: toPrecisionValue(values[2]) * 100 },
2498
2528
  ];
2499
2529
  if (values.length == 4 && values[3] != 1) {
2500
- chi.push({ typ: exports.EnumToken.LiteralTokenType, val: '/' }, { typ: exports.EnumToken.PercentageTokenType, val: values[3] * 100 });
2530
+ chi.push({ typ: exports.EnumToken.LiteralTokenType, val: '/' }, {
2531
+ typ: exports.EnumToken.PercentageTokenType,
2532
+ val: values[3] * 100
2533
+ });
2501
2534
  }
2502
2535
  return {
2503
2536
  typ: exports.EnumToken.ColorTokenType,
@@ -2563,12 +2596,20 @@
2563
2596
  return hsv2hsl(...hwb2hsv(...Object.values(hslvalues(token))));
2564
2597
  }
2565
2598
  function lab2hslvalues(token) {
2599
+ const values = lab2rgbvalues(token);
2600
+ if (values == null) {
2601
+ return null;
2602
+ }
2566
2603
  // @ts-ignore
2567
- return rgbvalues2hslvalues(...lab2rgbvalues(token));
2604
+ return rgbvalues2hslvalues(...values);
2568
2605
  }
2569
2606
  function lch2hslvalues(token) {
2607
+ const values = lch2rgbvalues(token);
2608
+ if (values == null) {
2609
+ return null;
2610
+ }
2570
2611
  // @ts-ignore
2571
- return rgbvalues2hslvalues(...lch2rgbvalues(token));
2612
+ return rgbvalues2hslvalues(...values);
2572
2613
  }
2573
2614
  function oklab2hslvalues(token) {
2574
2615
  const t = oklab2srgbvalues(token);
@@ -2674,8 +2715,8 @@
2674
2715
  values[0] = toPrecisionAngle(values[0] * 360);
2675
2716
  const chi = [
2676
2717
  { typ: exports.EnumToken.NumberTokenType, val: values[0] },
2677
- { typ: exports.EnumToken.PercentageTokenType, val: values[1] * 100 },
2678
- { typ: exports.EnumToken.PercentageTokenType, val: values[2] * 100 },
2718
+ { typ: exports.EnumToken.PercentageTokenType, val: toPrecisionValue(values[1]) * 100 },
2719
+ { typ: exports.EnumToken.PercentageTokenType, val: toPrecisionValue(values[2]) * 100 },
2679
2720
  ];
2680
2721
  if (values.length == 4) {
2681
2722
  chi.push({ typ: exports.EnumToken.LiteralTokenType, val: '/' }, {
@@ -3069,11 +3110,10 @@
3069
3110
  // @ts-ignore
3070
3111
  const calculate = () => [colorSpace].concat(values1.map((v1, i) => {
3071
3112
  return {
3072
- // @ts-ignore
3073
- typ: exports.EnumToken.NumberTokenType, val: String((mul1 * v1 * p1 + mul2 * values2[i] * p2) / mul)
3113
+ typ: exports.EnumToken.NumberTokenType, val: (mul1 * v1 * p1 + mul2 * values2[i] * p2) / mul
3074
3114
  };
3075
3115
  }).concat(mul == 1 ? [] : [{
3076
- typ: exports.EnumToken.NumberTokenType, val: String(mul)
3116
+ typ: exports.EnumToken.NumberTokenType, val: mul
3077
3117
  }]));
3078
3118
  switch (colorSpace.val) {
3079
3119
  case 'srgb':
@@ -3816,7 +3856,7 @@
3816
3856
  let keys = {};
3817
3857
  let values = {};
3818
3858
  // colorFuncColorSpace x,y,z or r,g,b
3819
- const names = relativeKeys.startsWith('xyz') ? 'xyz' : relativeKeys.slice(-3);
3859
+ const names = relativeKeys.startsWith('xyz') ? 'xyz' : ['srgb', 'srgb-linear', 'display-p3', 'a98-rgb', 'prophoto-rgb', 'rec2020', 'rgb'].includes(relativeKeys.toLowerCase()) ? 'rgb' : relativeKeys.slice(-3);
3820
3860
  const converted = convertColor(original, exports.ColorType[relativeKeys.toUpperCase().replaceAll('-', '_')]);
3821
3861
  if (converted == null) {
3822
3862
  return null;
@@ -3830,13 +3870,13 @@
3830
3870
  // @ts-ignore
3831
3871
  alpha: alpha == null ? {
3832
3872
  typ: exports.EnumToken.NumberTokenType,
3833
- val: '1'
3873
+ val: 1
3834
3874
  } : (alpha.typ == exports.EnumToken.IdenTokenType && alpha.val == 'none') ? {
3835
3875
  typ: exports.EnumToken.NumberTokenType,
3836
- val: '0'
3876
+ val: 0
3837
3877
  } : (alpha.typ == exports.EnumToken.PercentageTokenType ? {
3838
3878
  typ: exports.EnumToken.NumberTokenType,
3839
- val: String(getNumber(alpha))
3879
+ val: getNumber(alpha)
3840
3880
  } : alpha)
3841
3881
  };
3842
3882
  keys = {
@@ -3846,19 +3886,15 @@
3846
3886
  // @ts-ignore
3847
3887
  alpha: getValue(aExp == null ? {
3848
3888
  typ: exports.EnumToken.NumberTokenType,
3849
- val: '1'
3889
+ val: 1
3850
3890
  } : (aExp.typ == exports.EnumToken.IdenTokenType && aExp.val == 'none') ? {
3851
3891
  typ: exports.EnumToken.NumberTokenType,
3852
- val: '0'
3892
+ val: 0
3853
3893
  } : aExp)
3854
3894
  };
3855
3895
  return computeComponentValue(keys, converted, values);
3856
3896
  }
3857
3897
  function getValue(t, converted, component) {
3858
- // if (t == null) {
3859
- //
3860
- // return t;
3861
- // }
3862
3898
  if (t.typ == exports.EnumToken.PercentageTokenType) {
3863
3899
  let value = getNumber(t);
3864
3900
  let colorSpace = exports.ColorType[converted.kin].toLowerCase().replaceAll('-', '_');
@@ -3888,55 +3924,13 @@
3888
3924
  }
3889
3925
  }
3890
3926
  for (const [key, exp] of Object.entries(expr)) {
3891
- /*
3892
- if (exp == null) {
3893
-
3894
- if (key in values) {
3895
-
3896
- if (typeof values[<RelativeColorTypes>key] == 'number') {
3897
-
3898
- expr[<RelativeColorTypes>key] = {
3899
- typ: EnumToken.NumberTokenType,
3900
- val: reduceNumber(<number>values[<RelativeColorTypes>key])
3901
- };
3902
- } else {
3903
-
3904
- expr[<RelativeColorTypes>key] = <Token>values[<RelativeColorTypes>key];
3905
- }
3906
- }
3907
-
3908
- } else
3909
- */
3910
3927
  if ([exports.EnumToken.NumberTokenType, exports.EnumToken.PercentageTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.LengthTokenType].includes(exp.typ)) ;
3911
3928
  else if (exp.typ == exports.EnumToken.IdenTokenType && exp.val in values) {
3912
- // if (typeof values[<RelativeColorTypes>exp.val] == 'number') {
3913
- //
3914
- // expr[<RelativeColorTypes>key] = {
3915
- // typ: EnumToken.NumberTokenType,
3916
- // val: reduceNumber(<number>values[<RelativeColorTypes>exp.val])
3917
- // };
3918
- // } else {
3919
3929
  expr[key] = values[exp.val];
3920
- // }
3921
3930
  }
3922
3931
  else if (exp.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(exp.val)) {
3923
3932
  for (let { value, parent } of walkValues(exp.chi, exp)) {
3924
- // if (parent == null) {
3925
- //
3926
- // parent = exp;
3927
- // }
3928
- /*
3929
- if (value.typ == EnumToken.PercentageTokenType) {
3930
-
3931
- replaceValue(parent as BinaryExpressionToken | FunctionToken | ParensToken, value, getValue(value, converted, <RelativeColorTypes>key));
3932
- } else
3933
- */
3934
3933
  if (value.typ == exports.EnumToken.IdenTokenType) {
3935
- // @ts-ignore
3936
- // if (!(value.val in values || typeof Math[(value as IdentToken).val.toUpperCase()] == 'number')) {
3937
- //
3938
- // return null;
3939
- // }
3940
3934
  // @ts-ignore
3941
3935
  replaceValue(parent, value, values[value.val] ?? {
3942
3936
  typ: exports.EnumToken.NumberTokenType,
@@ -3950,10 +3944,6 @@
3950
3944
  if (result.length == 1 && result[0].typ != exports.EnumToken.BinaryExpressionTokenType) {
3951
3945
  expr[key] = result[0];
3952
3946
  }
3953
- // else {
3954
- //
3955
- // return null;
3956
- // }
3957
3947
  }
3958
3948
  }
3959
3949
  return expr;
@@ -3964,13 +3954,16 @@
3964
3954
  if (pr.typ == exports.EnumToken.BinaryExpressionTokenType) {
3965
3955
  if (pr.l == val) {
3966
3956
  pr.l = newValue;
3957
+ return;
3967
3958
  }
3968
3959
  else {
3969
3960
  pr.r = newValue;
3961
+ return;
3970
3962
  }
3971
3963
  }
3972
3964
  else {
3973
3965
  pr.chi.splice(pr.chi.indexOf(val), 1, newValue);
3966
+ return;
3974
3967
  }
3975
3968
  }
3976
3969
  }
@@ -4058,11 +4051,14 @@
4058
4051
  chi: values.reduce((acc, curr, index) => index < 4 ? [...acc, {
4059
4052
  typ: exports.EnumToken.PercentageTokenType,
4060
4053
  // @ts-ignore
4061
- val: curr * 100
4054
+ val: toPrecisionValue(curr) * 100
4062
4055
  }] : [...acc, {
4063
4056
  typ: exports.EnumToken.LiteralTokenType,
4064
4057
  val: '/'
4065
- }, { typ: exports.EnumToken.PercentageTokenType, val: curr * 100 }], []),
4058
+ }, {
4059
+ typ: exports.EnumToken.PercentageTokenType,
4060
+ val: toPrecisionValue(curr) * 100
4061
+ }], []),
4066
4062
  kin: exports.ColorType.DEVICE_CMYK
4067
4063
  };
4068
4064
  }
@@ -4121,145 +4117,395 @@
4121
4117
  return multiplyMatrices(M, [x, y, z]).concat(a == null || a == 1 ? [] : [a]);
4122
4118
  }
4123
4119
 
4124
- /**
4125
- * Converts a color to another color space
4126
- * @param token
4127
- * @param to
4128
- *
4129
- * <code>
4130
- *
4131
- * const token = {typ: EnumToken.ColorTokenType, kin: ColorType.HEX, val: '#F00'}
4132
- * const result = convertColor(token, ColorType.LCH);
4133
- *
4134
- * </code>
4135
- */
4136
- function convertColor(token, to) {
4137
- if (token.kin == exports.ColorType.SYS ||
4138
- token.kin == exports.ColorType.DPSYS ||
4139
- (isIdentColor(token) &&
4140
- 'currentcolor' == token.val.toLowerCase())) {
4141
- return token;
4120
+ const epsilon = 1e-5;
4121
+ function identity() {
4122
+ return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
4123
+ }
4124
+ function normalize(point) {
4125
+ const [x, y, z] = point;
4126
+ const norm = Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
4127
+ return norm === 0 ? [0, 0, 0] : [x / norm, y / norm, z / norm];
4128
+ }
4129
+ function dot(point1, point2) {
4130
+ if (point1.length === 4 && point2.length === 4) {
4131
+ return point1[0] * point2[0] + point1[1] * point2[1] + point1[2] * point2[2] + point1[3] * point2[3];
4142
4132
  }
4143
- if (token.kin == exports.ColorType.COLOR_MIX && to != exports.ColorType.COLOR_MIX) {
4144
- const children = token.chi.reduce((acc, t) => {
4145
- if (t.typ == exports.EnumToken.ColorTokenType) {
4146
- acc.push([t]);
4147
- }
4148
- else {
4149
- if (![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType, exports.EnumToken.CommaTokenType].includes(t.typ)) {
4150
- acc[acc.length - 1].push(t);
4151
- }
4133
+ return point1[0] * point2[0] + point1[1] * point2[1] + point1[2] * point2[2];
4134
+ }
4135
+ function multiply(matrixA, matrixB) {
4136
+ let result = new Array(16).fill(0);
4137
+ for (let i = 0; i < 4; i++) {
4138
+ for (let j = 0; j < 4; j++) {
4139
+ for (let k = 0; k < 4; k++) {
4140
+ // Utiliser l'indexation linéaire pour accéder aux éléments
4141
+ // Pour une matrice 4x4, l'index est (row * 4 + col)
4142
+ result[j * 4 + i] += matrixA[k * 4 + i] * matrixB[j * 4 + k];
4152
4143
  }
4153
- return acc;
4154
- }, [[]]);
4155
- token = colorMix(children[0][1], children[0][2], children[1][0], children[1][1], children[2][0], children[2][1]);
4156
- if (token == null) {
4157
- return null;
4158
4144
  }
4159
4145
  }
4160
- if (token.cal == 'rel' && ['rgb', 'hsl', 'hwb', 'lab', 'lch', 'oklab', 'oklch', 'color'].includes(token.val.toLowerCase())) {
4161
- const chi = getComponents(token);
4162
- const offset = token.val == 'color' ? 2 : 1;
4163
- if (chi != null) {
4164
- // @ts-ignore
4165
- const color = chi[1];
4166
- const components = parseRelativeColor(token.val.toLowerCase() == 'color' ? chi[offset].val : token.val, color, chi[offset + 1], chi[offset + 2], chi[offset + 3], chi[offset + 4]);
4167
- if (components != null) {
4168
- token = {
4169
- ...token,
4170
- chi: [...(token.val == 'color' ? [chi[offset]] : []), ...Object.values(components)]
4171
- };
4172
- delete token.cal;
4146
+ return result;
4147
+ }
4148
+ function inverse(matrix) {
4149
+ // Create augmented matrix [matrix | identity]
4150
+ let augmented = [
4151
+ ...matrix.slice(0, 4),
4152
+ 1, 0, 0, 0,
4153
+ ...matrix.slice(4, 8),
4154
+ 0, 1, 0, 0,
4155
+ ...matrix.slice(8, 12),
4156
+ 0, 0, 1, 0,
4157
+ ...matrix.slice(12, 16),
4158
+ 0, 0, 0, 1
4159
+ ];
4160
+ // Gaussian elimination with partial pivoting
4161
+ for (let col = 0; col < 4; col++) {
4162
+ // Find pivot row with maximum absolute value
4163
+ let maxRow = col;
4164
+ let maxVal = Math.abs(augmented[col * 4 + col]);
4165
+ for (let row = col + 1; row < 4; row++) {
4166
+ let val = Math.abs(augmented[row * 4 + col]);
4167
+ if (val > maxVal) {
4168
+ maxVal = val;
4169
+ maxRow = row;
4173
4170
  }
4174
4171
  }
4175
- }
4176
- if (token.kin == to) {
4177
- if (token.kin == exports.ColorType.HEX || token.kin == exports.ColorType.LIT) {
4178
- token.val = reduceHexValue(token.val);
4179
- token.kin = token.val[0] == '#' ? exports.ColorType.HEX : exports.ColorType.LIT;
4172
+ // Check for singularity
4173
+ if (maxVal < 1e-5) {
4174
+ return null;
4180
4175
  }
4181
- return token;
4182
- }
4183
- if (token.kin == exports.ColorType.COLOR) {
4184
- const colorSpace = token.chi.find(t => ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(t.typ));
4185
- if (colorSpace.val == exports.ColorType[to].toLowerCase().replaceAll('_', '-')) {
4186
- return token;
4176
+ // Swap rows if necessary
4177
+ if (maxRow !== col) {
4178
+ [augmented[col], augmented[maxRow]] = [augmented[maxRow], augmented[col]];
4187
4179
  }
4188
- }
4189
- if (to == exports.ColorType.HSL) {
4190
- switch (token.kin) {
4191
- case exports.ColorType.RGB:
4192
- case exports.ColorType.RGBA:
4193
- return rgb2HslToken(token);
4194
- case exports.ColorType.HEX:
4195
- case exports.ColorType.LIT:
4196
- return hex2HslToken(token);
4197
- case exports.ColorType.HWB:
4198
- return hwb2HslToken(token);
4199
- case exports.ColorType.DEVICE_CMYK:
4200
- return cmyk2HslToken(token);
4201
- case exports.ColorType.OKLAB:
4202
- return oklab2HslToken(token);
4203
- case exports.ColorType.OKLCH:
4204
- return oklch2HslToken(token);
4205
- case exports.ColorType.LAB:
4206
- return lab2HslToken(token);
4207
- case exports.ColorType.LCH:
4208
- return lch2HslToken(token);
4209
- case exports.ColorType.COLOR:
4210
- return color2HslToken(token);
4180
+ // Scale pivot row to make pivot element 1
4181
+ let pivot = augmented[col * 4 + col];
4182
+ for (let j = 0; j < 8; j++) {
4183
+ augmented[col * 4 + j] /= pivot;
4211
4184
  }
4212
- }
4213
- else if (to == exports.ColorType.HWB) {
4214
- switch (token.kin) {
4215
- case exports.ColorType.RGB:
4216
- case exports.ColorType.RGBA:
4217
- return rgb2hwbToken(token);
4218
- case exports.ColorType.HEX:
4219
- case exports.ColorType.LIT:
4220
- return rgb2hwbToken(token);
4221
- case exports.ColorType.HSL:
4222
- case exports.ColorType.HSLA:
4223
- return hsl2hwbToken(token);
4224
- case exports.ColorType.OKLAB:
4225
- return oklab2hwbToken(token);
4226
- case exports.ColorType.OKLCH:
4227
- return oklch2hwbToken(token);
4228
- case exports.ColorType.LAB:
4229
- return lab2hwbToken(token);
4230
- case exports.ColorType.LCH:
4231
- return lch2hwbToken(token);
4232
- case exports.ColorType.DEVICE_CMYK:
4233
- return cmyk2hwbToken(token);
4234
- case exports.ColorType.COLOR:
4235
- return color2hwbToken(token);
4185
+ // Eliminate column in other rows
4186
+ for (let row = 0; row < 4; row++) {
4187
+ if (row !== col) {
4188
+ let factor = augmented[row * 4 + col];
4189
+ for (let j = 0; j < 8; j++) {
4190
+ augmented[row * 4 + j] -= factor * augmented[col * 4 + j];
4191
+ }
4192
+ }
4236
4193
  }
4237
4194
  }
4238
- else if (to == exports.ColorType.DEVICE_CMYK) {
4239
- switch (token.kin) {
4240
- case exports.ColorType.RGB:
4241
- case exports.ColorType.RGBA:
4242
- return rgb2cmykToken(token);
4243
- case exports.ColorType.HEX:
4244
- case exports.ColorType.LIT:
4245
- return rgb2cmykToken(token);
4246
- case exports.ColorType.HSL:
4247
- case exports.ColorType.HSLA:
4248
- return hsl2cmykToken(token);
4249
- case exports.ColorType.HWB:
4250
- return hwb2cmykToken(token);
4251
- case exports.ColorType.OKLAB:
4252
- return oklab2cmyk(token);
4253
- case exports.ColorType.OKLCH:
4254
- return oklch2cmykToken(token);
4255
- case exports.ColorType.LAB:
4256
- return lab2cmykToken(token);
4257
- //
4258
- case exports.ColorType.LCH:
4259
- return lch2cmykToken(token);
4260
- case exports.ColorType.COLOR:
4261
- return color2cmykToken(token);
4262
- }
4195
+ // Extract the inverse from the right side of the augmented matrix
4196
+ return augmented.slice(0, 16);
4197
+ }
4198
+ function round(number) {
4199
+ const rounded = Math.round(number);
4200
+ return Math.abs(rounded - number) <= epsilon ? rounded : +number.toPrecision(6);
4201
+ }
4202
+ // translate3d(25.9808px, 0, 15px ) rotateY(60deg) skewX(49.9999deg) scale(1, 1.2)
4203
+ // translate → rotate → skew → scale
4204
+ function decompose(original) {
4205
+ const matrix = original.slice();
4206
+ // Normalize last row
4207
+ if (matrix[15] === 0) {
4208
+ return null;
4209
+ }
4210
+ for (let i = 0; i < 16; i++)
4211
+ matrix[i] /= matrix[15];
4212
+ // Perspective extraction
4213
+ const perspective = [0, 0, 0, 1];
4214
+ if (matrix[3] !== 0 || matrix[7] !== 0 || matrix[11] !== 0) {
4215
+ const rightHandSide = [matrix[3], matrix[7], matrix[11], matrix[15]];
4216
+ const perspectiveMatrix = matrix.slice();
4217
+ perspectiveMatrix[3] = 0;
4218
+ perspectiveMatrix[7] = 0;
4219
+ perspectiveMatrix[11] = 0;
4220
+ perspectiveMatrix[15] = 1;
4221
+ // @ts-ignore
4222
+ const inverted = inverse(original.slice());
4223
+ if (inverted === null) {
4224
+ return null;
4225
+ }
4226
+ const transposedInverse = transposeMatrix4(inverted);
4227
+ perspective[0] = dot(rightHandSide, transposedInverse.slice(0, 4));
4228
+ perspective[1] = dot(rightHandSide, transposedInverse.slice(4, 8));
4229
+ perspective[2] = dot(rightHandSide, transposedInverse.slice(8, 12));
4230
+ perspective[3] = dot(rightHandSide, transposedInverse.slice(12, 16));
4231
+ // Clear perspective from matrix
4232
+ matrix[3] = 0;
4233
+ matrix[7] = 0;
4234
+ matrix[11] = 0;
4235
+ matrix[15] = 1;
4236
+ }
4237
+ // Translation
4238
+ const translate = [matrix[12], matrix[13], matrix[14]];
4239
+ matrix[12] = matrix[13] = matrix[14] = 0;
4240
+ // Build the 3x3 matrix
4241
+ const row0 = [matrix[0], matrix[1], matrix[2]];
4242
+ const row1 = [matrix[4], matrix[5], matrix[6]];
4243
+ const row2 = [matrix[8], matrix[9], matrix[10]];
4244
+ const cross = [
4245
+ row1[1] * row2[2] - row1[2] * row2[1],
4246
+ row1[2] * row2[0] - row1[0] * row2[2],
4247
+ row1[0] * row2[1] - row1[1] * row2[0],
4248
+ ];
4249
+ // Compute scale
4250
+ const scaleX = Math.hypot(...row0);
4251
+ const row0Norm = normalize(row0);
4252
+ const skewXY = dot(row0Norm, row1);
4253
+ const row1Proj = [
4254
+ row1[0] - skewXY * row0Norm[0],
4255
+ row1[1] - skewXY * row0Norm[1],
4256
+ row1[2] - skewXY * row0Norm[2]
4257
+ ];
4258
+ const scaleY = Math.hypot(...row1Proj);
4259
+ const row1Norm = normalize(row1Proj);
4260
+ const skewXZ = dot(row0Norm, row2);
4261
+ const skewYZ = dot(row1Norm, row2);
4262
+ const row2Proj = [
4263
+ row2[0] - skewXZ * row0Norm[0] - skewYZ * row1Norm[0],
4264
+ row2[1] - skewXZ * row0Norm[1] - skewYZ * row1Norm[1],
4265
+ row2[2] - skewXZ * row0Norm[2] - skewYZ * row1Norm[2]
4266
+ ];
4267
+ const row2Norm = normalize(row2Proj);
4268
+ const determinant = row0[0] * cross[0] + row0[1] * cross[1] + row0[2] * cross[2];
4269
+ const scaleZ = Math.hypot(...row2Proj) * (determinant < 0 ? -1 : 1);
4270
+ // Build rotation matrix from orthonormalized vectors
4271
+ const r00 = row0Norm[0], r01 = row1Norm[0], r02 = row2Norm[0];
4272
+ const r10 = row0Norm[1], r11 = row1Norm[1], r12 = row2Norm[1];
4273
+ const r20 = row0Norm[2], r21 = row1Norm[2], r22 = row2Norm[2];
4274
+ // Convert to quaternion
4275
+ const trace = r00 + r11 + r22;
4276
+ let qw, qx, qy, qz;
4277
+ if (trace > 0) {
4278
+ const s = 0.5 / Math.sqrt(trace + 1.0);
4279
+ qw = 0.25 / s;
4280
+ qx = (r21 - r12) * s;
4281
+ qy = (r02 - r20) * s;
4282
+ qz = (r10 - r01) * s;
4283
+ }
4284
+ else if (r00 > r11 && r00 > r22) {
4285
+ const s = 2.0 * Math.sqrt(1.0 + r00 - r11 - r22);
4286
+ qw = (r21 - r12) / s;
4287
+ qx = 0.25 * s;
4288
+ qy = (r01 + r10) / s;
4289
+ qz = (r02 + r20) / s;
4290
+ }
4291
+ else if (r11 > r22) {
4292
+ const s = 2.0 * Math.sqrt(1.0 + r11 - r00 - r22);
4293
+ qw = (r02 - r20) / s;
4294
+ qx = (r01 + r10) / s;
4295
+ qy = 0.25 * s;
4296
+ qz = (r12 + r21) / s;
4297
+ }
4298
+ else {
4299
+ const s = 2.0 * Math.sqrt(1.0 + r22 - r00 - r11);
4300
+ qw = (r10 - r01) / s;
4301
+ qx = (r02 + r20) / s;
4302
+ qy = (r12 + r21) / s;
4303
+ qz = 0.25 * s;
4304
+ }
4305
+ [qx, qy, qz] = toZero([qx, qy, qz]);
4306
+ let q = [Math.abs(qx), Math.abs(qy), Math.abs(qz)].reduce((acc, curr) => {
4307
+ if (acc == 0 || (curr > 0 && curr < acc)) {
4308
+ acc = curr;
4309
+ }
4310
+ return acc;
4311
+ }, 0);
4312
+ if (q > 0) {
4313
+ qx /= q;
4314
+ qy /= q;
4315
+ qz /= q;
4316
+ }
4317
+ const rotate = [qx, qy, qz, Object.is(qw, 0) ? 0 : 2 * Math.acos(qw) * 180 / Math.PI];
4318
+ const scale = [scaleX, scaleY, scaleZ];
4319
+ const skew = [skewXY, skewXZ, skewYZ];
4320
+ return {
4321
+ translate,
4322
+ scale,
4323
+ rotate,
4324
+ skew,
4325
+ perspective
4326
+ };
4327
+ }
4328
+ function transposeMatrix4(m) {
4329
+ return [
4330
+ m[0], m[4], m[8], m[12],
4331
+ m[1], m[5], m[9], m[13],
4332
+ m[2], m[6], m[10], m[14],
4333
+ m[3], m[7], m[11], m[15],
4334
+ ];
4335
+ }
4336
+ function toZero(v) {
4337
+ for (let i = 0; i < v.length; i++) {
4338
+ if (Math.abs(v[i]) <= epsilon) {
4339
+ v[i] = 0;
4340
+ }
4341
+ else {
4342
+ v[i] = +v[i].toPrecision(6);
4343
+ }
4344
+ }
4345
+ return v;
4346
+ }
4347
+ // https://drafts.csswg.org/css-transforms-1/#2d-matrix
4348
+ function is2DMatrix(matrix) {
4349
+ // m13,m14, m23, m24, m31, m32, m34, m43 are all 0
4350
+ return matrix[2] === 0 &&
4351
+ matrix[3] === 0 &&
4352
+ matrix[6] === 0 &&
4353
+ matrix[7] === 0 &&
4354
+ matrix[8] === 0 &&
4355
+ matrix[9] === 0 &&
4356
+ matrix[11] === 0 &&
4357
+ matrix[14] === 0 &&
4358
+ matrix[10] === 1 &&
4359
+ matrix[15] === 1;
4360
+ }
4361
+
4362
+ /**
4363
+ * Converts a color to another color space
4364
+ * @param token
4365
+ * @param to
4366
+ *
4367
+ * @private
4368
+ *
4369
+ * <code>
4370
+ *
4371
+ * const token = {typ: EnumToken.ColorTokenType, kin: ColorType.HEX, val: '#F00'}
4372
+ * const result = convertColor(token, ColorType.LCH);
4373
+ *
4374
+ * </code>
4375
+ */
4376
+ function convertColor(token, to) {
4377
+ if (token.kin == exports.ColorType.SYS ||
4378
+ token.kin == exports.ColorType.DPSYS ||
4379
+ (isIdentColor(token) &&
4380
+ 'currentcolor' == token.val.toLowerCase())) {
4381
+ return token;
4382
+ }
4383
+ if (token.kin == exports.ColorType.COLOR_MIX && to != exports.ColorType.COLOR_MIX) {
4384
+ const children = token.chi.reduce((acc, t) => {
4385
+ if (t.typ == exports.EnumToken.ColorTokenType) {
4386
+ acc.push([t]);
4387
+ }
4388
+ else {
4389
+ if (![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType, exports.EnumToken.CommaTokenType].includes(t.typ)) {
4390
+ acc[acc.length - 1].push(t);
4391
+ }
4392
+ }
4393
+ return acc;
4394
+ }, [[]]);
4395
+ token = colorMix(children[0][1], children[0][2], children[1][0], children[1][1], children[2][0], children[2][1]);
4396
+ if (token == null) {
4397
+ return null;
4398
+ }
4399
+ }
4400
+ if (token.cal == 'rel' && ['rgb', 'hsl', 'hwb', 'lab', 'lch', 'oklab', 'oklch', 'color'].includes(token.val.toLowerCase())) {
4401
+ const chi = getComponents(token);
4402
+ const offset = token.val == 'color' ? 2 : 1;
4403
+ if (chi != null) {
4404
+ // @ts-ignore
4405
+ const color = chi[1];
4406
+ const components = parseRelativeColor(token.val.toLowerCase() == 'color' ? chi[offset].val : token.val, color, chi[offset + 1], chi[offset + 2], chi[offset + 3], chi[offset + 4]);
4407
+ if (components != null) {
4408
+ token = {
4409
+ ...token,
4410
+ chi: [...(token.val == 'color' ? [chi[offset]] : []), ...Object.values(components)],
4411
+ kin: exports.ColorType[token.val.toUpperCase().replaceAll('-', '_')]
4412
+ };
4413
+ delete token.cal;
4414
+ }
4415
+ }
4416
+ }
4417
+ if (token.kin == to) {
4418
+ if (token.kin == exports.ColorType.HEX || token.kin == exports.ColorType.LIT) {
4419
+ token.val = reduceHexValue(token.val);
4420
+ token.kin = token.val[0] == '#' ? exports.ColorType.HEX : exports.ColorType.LIT;
4421
+ }
4422
+ return token;
4423
+ }
4424
+ if (token.kin == exports.ColorType.COLOR) {
4425
+ const colorSpace = token.chi.find(t => ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(t.typ));
4426
+ if (colorSpace.val == exports.ColorType[to].toLowerCase().replaceAll('_', '-')) {
4427
+ for (const chi of token.chi) {
4428
+ if (chi.typ == exports.EnumToken.NumberTokenType && typeof chi.val == 'number') {
4429
+ chi.val = toPrecisionValue(getNumber(chi));
4430
+ }
4431
+ }
4432
+ return token;
4433
+ }
4434
+ }
4435
+ if (to == exports.ColorType.HSL) {
4436
+ switch (token.kin) {
4437
+ case exports.ColorType.RGB:
4438
+ case exports.ColorType.RGBA:
4439
+ return rgb2HslToken(token);
4440
+ case exports.ColorType.HEX:
4441
+ case exports.ColorType.LIT:
4442
+ return hex2HslToken(token);
4443
+ case exports.ColorType.HWB:
4444
+ return hwb2HslToken(token);
4445
+ case exports.ColorType.DEVICE_CMYK:
4446
+ return cmyk2HslToken(token);
4447
+ case exports.ColorType.OKLAB:
4448
+ return oklab2HslToken(token);
4449
+ case exports.ColorType.OKLCH:
4450
+ return oklch2HslToken(token);
4451
+ case exports.ColorType.LAB:
4452
+ return lab2HslToken(token);
4453
+ case exports.ColorType.LCH:
4454
+ return lch2HslToken(token);
4455
+ case exports.ColorType.COLOR:
4456
+ return color2HslToken(token);
4457
+ }
4458
+ }
4459
+ else if (to == exports.ColorType.HWB) {
4460
+ switch (token.kin) {
4461
+ case exports.ColorType.RGB:
4462
+ case exports.ColorType.RGBA:
4463
+ return rgb2hwbToken(token);
4464
+ case exports.ColorType.HEX:
4465
+ case exports.ColorType.LIT:
4466
+ return rgb2hwbToken(token);
4467
+ case exports.ColorType.HSL:
4468
+ case exports.ColorType.HSLA:
4469
+ return hsl2hwbToken(token);
4470
+ case exports.ColorType.OKLAB:
4471
+ return oklab2hwbToken(token);
4472
+ case exports.ColorType.OKLCH:
4473
+ return oklch2hwbToken(token);
4474
+ case exports.ColorType.LAB:
4475
+ return lab2hwbToken(token);
4476
+ case exports.ColorType.LCH:
4477
+ return lch2hwbToken(token);
4478
+ case exports.ColorType.DEVICE_CMYK:
4479
+ return cmyk2hwbToken(token);
4480
+ case exports.ColorType.COLOR:
4481
+ return color2hwbToken(token);
4482
+ }
4483
+ }
4484
+ else if (to == exports.ColorType.DEVICE_CMYK) {
4485
+ switch (token.kin) {
4486
+ case exports.ColorType.RGB:
4487
+ case exports.ColorType.RGBA:
4488
+ return rgb2cmykToken(token);
4489
+ case exports.ColorType.HEX:
4490
+ case exports.ColorType.LIT:
4491
+ return rgb2cmykToken(token);
4492
+ case exports.ColorType.HSL:
4493
+ case exports.ColorType.HSLA:
4494
+ return hsl2cmykToken(token);
4495
+ case exports.ColorType.HWB:
4496
+ return hwb2cmykToken(token);
4497
+ case exports.ColorType.OKLAB:
4498
+ return oklab2cmyk(token);
4499
+ case exports.ColorType.OKLCH:
4500
+ return oklch2cmykToken(token);
4501
+ case exports.ColorType.LAB:
4502
+ return lab2cmykToken(token);
4503
+ //
4504
+ case exports.ColorType.LCH:
4505
+ return lch2cmykToken(token);
4506
+ case exports.ColorType.COLOR:
4507
+ return color2cmykToken(token);
4508
+ }
4263
4509
  }
4264
4510
  else if (to == exports.ColorType.HEX || to == exports.ColorType.LIT) {
4265
4511
  switch (token.kin) {
@@ -4606,9 +4852,9 @@
4606
4852
  function values2colortoken(values, to) {
4607
4853
  values = srgb2srgbcolorspace(values, to);
4608
4854
  const chi = [
4609
- { typ: exports.EnumToken.NumberTokenType, val: values[0] },
4610
- { typ: exports.EnumToken.NumberTokenType, val: values[1] },
4611
- { typ: exports.EnumToken.NumberTokenType, val: values[2] },
4855
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[0]) },
4856
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[1]) },
4857
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[2]) },
4612
4858
  ];
4613
4859
  if (values.length == 4) {
4614
4860
  chi.push({ typ: exports.EnumToken.LiteralTokenType, val: "/" }, {
@@ -4633,8 +4879,17 @@
4633
4879
  if (token.typ == exports.EnumToken.IdenTokenType && token.val == 'none') {
4634
4880
  return 0;
4635
4881
  }
4882
+ let val;
4883
+ // @ts-ignore
4884
+ if (typeof token.val != 'number' && token.val?.typ == exports.EnumToken.FractionTokenType) {
4885
+ // @ts-ignore
4886
+ val = token.val.l.val / token.val.r.val;
4887
+ }
4888
+ else {
4889
+ val = token.val;
4890
+ }
4636
4891
  // @ts-ignore
4637
- return token.typ == exports.EnumToken.PercentageTokenType ? token.val / 100 : token.val;
4892
+ return token.typ == exports.EnumToken.PercentageTokenType ? val / 100 : val;
4638
4893
  }
4639
4894
  /**
4640
4895
  * convert angle to turn
@@ -4665,6 +4920,10 @@
4665
4920
  // @ts-ignore
4666
4921
  return token.val / 360;
4667
4922
  }
4923
+ function toPrecisionValue(value) {
4924
+ value = +value.toFixed(colorPrecision);
4925
+ return Math.abs(value) < epsilon ? 0 : value;
4926
+ }
4668
4927
  function toPrecisionAngle(angle) {
4669
4928
  angle = +angle.toPrecision(colorPrecision);
4670
4929
  if (Math.abs(angle) >= 360) {
@@ -5199,7 +5458,7 @@
5199
5458
  }
5200
5459
  if (token.typ == exports.EnumToken.IdenTokenType) {
5201
5460
  // named color
5202
- return token.val.toLowerCase() in COLORS_NAMES;
5461
+ return token.val.toLowerCase() in COLORS_NAMES || 'currentcolor' === token.val.toLowerCase() || 'transparent' === token.val.toLowerCase();
5203
5462
  }
5204
5463
  let isLegacySyntax = false;
5205
5464
  if (token.typ == exports.EnumToken.FunctionTokenType) {
@@ -5252,8 +5511,13 @@
5252
5511
  return false;
5253
5512
  }
5254
5513
  }
5255
- if (children[i].typ == exports.EnumToken.FunctionTokenType && !mathFuncs.includes(children[i].val)) {
5256
- return false;
5514
+ if (children[i].typ == exports.EnumToken.FunctionTokenType) {
5515
+ if ('var' == children[i].val.toLowerCase()) {
5516
+ continue;
5517
+ }
5518
+ if (!mathFuncs.includes(children[i].val)) {
5519
+ return false;
5520
+ }
5257
5521
  }
5258
5522
  }
5259
5523
  if (children.length == 4 || (isRelative && children.length == 6)) {
@@ -5540,23 +5804,29 @@
5540
5804
  }
5541
5805
  return true;
5542
5806
  }
5543
- function isDimension(name) {
5544
- let index = name.length;
5545
- while (index--) {
5546
- if (isLetter(name.charCodeAt(index))) {
5547
- continue;
5548
- }
5549
- index++;
5550
- break;
5551
- }
5552
- const number = name.slice(0, index);
5553
- return number.length > 0 && isIdentStart(name.charCodeAt(index)) && isNumber(number);
5554
- }
5807
+ // export function isDimension(name: string) {
5808
+ //
5809
+ // let index: number = name.length;
5810
+ //
5811
+ // while (index--) {
5812
+ //
5813
+ // if (isLetter(<number>name.charCodeAt(index))) {
5814
+ //
5815
+ // continue
5816
+ // }
5817
+ //
5818
+ // index++;
5819
+ // break;
5820
+ // }
5821
+ //
5822
+ // const number: string = name.slice(0, index);
5823
+ // return number.length > 0 && isIdentStart(name.charCodeAt(index)) && isNumber(number);
5824
+ // }
5555
5825
  function isPercentage(name) {
5556
5826
  return name.endsWith('%') && isNumber(name.slice(0, -1));
5557
5827
  }
5558
- function isFlex(name) {
5559
- return name.endsWith('fr') && isNumber(name.slice(0, -2));
5828
+ function isFlex(dimension) {
5829
+ return 'unit' in dimension && 'fr' == dimension.unit.toLowerCase();
5560
5830
  }
5561
5831
  function parseDimension(name) {
5562
5832
  let index = name.length;
@@ -5572,6 +5842,9 @@
5572
5842
  val: +name.slice(0, index),
5573
5843
  unit: name.slice(index)
5574
5844
  };
5845
+ if (index < 0 || Number.isNaN(dimension.val)) {
5846
+ return null;
5847
+ }
5575
5848
  if (isAngle(dimension)) {
5576
5849
  // @ts-ignore
5577
5850
  dimension.typ = exports.EnumToken.AngleTokenType;
@@ -5595,6 +5868,10 @@
5595
5868
  // @ts-ignore
5596
5869
  dimension.typ = exports.EnumToken.FrequencyTokenType;
5597
5870
  }
5871
+ else if (isFlex(dimension)) {
5872
+ // @ts-ignore
5873
+ dimension.typ = exports.EnumToken.FlexTokenType;
5874
+ }
5598
5875
  return dimension;
5599
5876
  }
5600
5877
  function isHexColor(name) {
@@ -7435,7 +7712,7 @@
7435
7712
  const sourcemap = options.sourcemap ? new SourceMap : null;
7436
7713
  const cache = Object.create(null);
7437
7714
  const result = {
7438
- code: renderAstNode(options.expandNestingRules ? expand(data) : data, options, sourcemap, {
7715
+ code: renderAstNode(options.expandNestingRules && [exports.EnumToken.StyleSheetNodeType, exports.EnumToken.AtRuleNodeType, exports.EnumToken.RuleNodeType].includes(data.typ) && 'chi' in data ? expand(data) : data, options, sourcemap, {
7439
7716
  ind: 0,
7440
7717
  lin: 1,
7441
7718
  col: 1
@@ -7477,7 +7754,7 @@
7477
7754
  function updateSourceMap(node, options, cache, sourcemap, position, str) {
7478
7755
  if ([
7479
7756
  exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType,
7480
- exports.EnumToken.KeyFrameRuleNodeType, exports.EnumToken.KeyframeAtRuleNodeType
7757
+ exports.EnumToken.KeyFramesRuleNodeType, exports.EnumToken.KeyframesAtRuleNodeType
7481
7758
  ].includes(node.typ)) {
7482
7759
  let src = node.loc?.src ?? '';
7483
7760
  let output = options.output ?? '';
@@ -7551,9 +7828,9 @@
7551
7828
  }, '');
7552
7829
  case exports.EnumToken.AtRuleNodeType:
7553
7830
  case exports.EnumToken.RuleNodeType:
7554
- case exports.EnumToken.KeyFrameRuleNodeType:
7555
- case exports.EnumToken.KeyframeAtRuleNodeType:
7556
- if ([exports.EnumToken.AtRuleNodeType, exports.EnumToken.KeyframeAtRuleNodeType].includes(data.typ) && !('chi' in data)) {
7831
+ case exports.EnumToken.KeyFramesRuleNodeType:
7832
+ case exports.EnumToken.KeyframesAtRuleNodeType:
7833
+ if ([exports.EnumToken.AtRuleNodeType, exports.EnumToken.KeyframesAtRuleNodeType].includes(data.typ) && !('chi' in data)) {
7557
7834
  return `${indent}@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val};`;
7558
7835
  }
7559
7836
  // @ts-ignore
@@ -7575,7 +7852,7 @@
7575
7852
  str = `${node.nam}:${options.indent}${(options.minify ? filterValues(node.val) : node.val).reduce(reducer, '').trimEnd()};`;
7576
7853
  }
7577
7854
  else if (node.typ == exports.EnumToken.AtRuleNodeType && !('chi' in node)) {
7578
- str = `${data.val === '' ? '' : options.indent || ' '}${data.val};`;
7855
+ str = `${node.val === '' ? '' : options.indent || ' '}${node.val};`;
7579
7856
  }
7580
7857
  else {
7581
7858
  str = renderAstNode(node, options, sourcemap, { ...position }, errors, reducer, cache, level + 1, indents);
@@ -7594,7 +7871,7 @@
7594
7871
  if (children.endsWith(';')) {
7595
7872
  children = children.slice(0, -1);
7596
7873
  }
7597
- if ([exports.EnumToken.AtRuleNodeType, exports.EnumToken.KeyframeAtRuleNodeType].includes(data.typ)) {
7874
+ if ([exports.EnumToken.AtRuleNodeType, exports.EnumToken.KeyframesAtRuleNodeType].includes(data.typ)) {
7598
7875
  return `@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val}${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
7599
7876
  }
7600
7877
  return data.sel + `${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
@@ -8166,13 +8443,15 @@
8166
8443
  yield pushToken(buffer, parseInfo);
8167
8444
  buffer = '';
8168
8445
  }
8446
+ buffer += value;
8169
8447
  while (value = next(parseInfo)) {
8170
8448
  charCode = value.charCodeAt(0);
8171
8449
  if (!isWhiteSpace(charCode)) {
8172
8450
  break;
8173
8451
  }
8452
+ buffer += value;
8174
8453
  }
8175
- yield pushToken('', parseInfo, exports.EnumToken.WhitespaceTokenType);
8454
+ yield pushToken(buffer, parseInfo, exports.EnumToken.WhitespaceTokenType);
8176
8455
  buffer = '';
8177
8456
  }
8178
8457
  switch (charCode) {
@@ -8220,8 +8499,7 @@
8220
8499
  buffer = '';
8221
8500
  }
8222
8501
  if (match$1(parseInfo, '=')) {
8223
- yield pushToken('', parseInfo, exports.EnumToken.LteTokenType);
8224
- next(parseInfo);
8502
+ yield pushToken(value + next(parseInfo), parseInfo, exports.EnumToken.LteTokenType);
8225
8503
  break;
8226
8504
  }
8227
8505
  buffer += value;
@@ -8276,8 +8554,7 @@
8276
8554
  }
8277
8555
  if (charCode == 124 /* TokenMap.PIPE */) {
8278
8556
  if (match$1(parseInfo, '|')) {
8279
- next(parseInfo);
8280
- yield pushToken('', parseInfo, exports.EnumToken.ColumnCombinatorTokenType);
8557
+ yield pushToken(value + next(parseInfo), parseInfo, exports.EnumToken.ColumnCombinatorTokenType);
8281
8558
  }
8282
8559
  else if (match$1(parseInfo, '=')) {
8283
8560
  buffer += next(parseInfo);
@@ -8331,11 +8608,10 @@
8331
8608
  buffer = '';
8332
8609
  }
8333
8610
  if (match$1(parseInfo, '=')) {
8334
- yield pushToken('', parseInfo, exports.EnumToken.GteTokenType);
8335
- next(parseInfo);
8611
+ yield pushToken(value + next(parseInfo), parseInfo, exports.EnumToken.GteTokenType);
8336
8612
  }
8337
8613
  else {
8338
- yield pushToken('', parseInfo, exports.EnumToken.GtTokenType);
8614
+ yield pushToken(value, parseInfo, exports.EnumToken.GtTokenType);
8339
8615
  }
8340
8616
  consumeWhiteSpace(parseInfo);
8341
8617
  break;
@@ -8386,7 +8662,7 @@
8386
8662
  yield pushToken(buffer, parseInfo);
8387
8663
  buffer = '';
8388
8664
  }
8389
- yield pushToken('', parseInfo, exports.EnumToken.EndParensTokenType);
8665
+ yield pushToken(value, parseInfo, exports.EnumToken.EndParensTokenType);
8390
8666
  break;
8391
8667
  case 40 /* TokenMap.OPEN_PAREN */:
8392
8668
  if (buffer.length == 0) {
@@ -8452,7 +8728,7 @@
8452
8728
  // ')'
8453
8729
  if (charCode == 0x29) {
8454
8730
  yield pushToken(buffer, parseInfo, hasNewLine ? exports.EnumToken.BadStringTokenType : exports.EnumToken.StringTokenType);
8455
- yield pushToken('', parseInfo, exports.EnumToken.EndParensTokenType);
8731
+ yield pushToken(value, parseInfo, exports.EnumToken.EndParensTokenType);
8456
8732
  buffer = '';
8457
8733
  break;
8458
8734
  }
@@ -8476,7 +8752,7 @@
8476
8752
  charCode = value.charCodeAt(0);
8477
8753
  if (charCode == 0x29) { // ')'
8478
8754
  yield pushToken(buffer, parseInfo, exports.EnumToken.UrlTokenTokenType);
8479
- yield pushToken('', parseInfo, exports.EnumToken.EndParensTokenType);
8755
+ yield pushToken(value, parseInfo, exports.EnumToken.EndParensTokenType);
8480
8756
  buffer = '';
8481
8757
  break;
8482
8758
  }
@@ -8510,8 +8786,7 @@
8510
8786
  buffer = '';
8511
8787
  }
8512
8788
  if (match$1(parseInfo, 'important')) {
8513
- yield pushToken('', parseInfo, exports.EnumToken.ImportantTokenType);
8514
- next(parseInfo, 9);
8789
+ yield pushToken(value + next(parseInfo, 9), parseInfo, exports.EnumToken.ImportantTokenType);
8515
8790
  buffer = '';
8516
8791
  break;
8517
8792
  }
@@ -8563,7 +8838,7 @@
8563
8838
  const reader = input.getReader();
8564
8839
  while (true) {
8565
8840
  const { done, value } = await reader.read();
8566
- parseInfo.stream += decoder.decode(value, { stream: true });
8841
+ parseInfo.stream += ArrayBuffer.isView(value) ? decoder.decode(value, { stream: true }) : value;
8567
8842
  yield* tokenize$1(parseInfo, done);
8568
8843
  if (done) {
8569
8844
  break;
@@ -10192,6 +10467,9 @@
10192
10467
  "text-anchor": {
10193
10468
  syntax: "start | middle | end"
10194
10469
  },
10470
+ "text-autospace": {
10471
+ syntax: "normal | <autospace> | auto"
10472
+ },
10195
10473
  "text-box": {
10196
10474
  syntax: "normal | <'text-box-trim'> || <'text-box-edge'>"
10197
10475
  },
@@ -12759,19 +13037,28 @@
12759
13037
  }
12760
13038
  }
12761
13039
  },
12762
- charset: {
12763
- syntax: "<string>"
13040
+ "@nest": {
12764
13041
  },
12765
- container: {
12766
- syntax: "[ <container-name> ]? <container-condition>"
13042
+ "@stylistic": {
13043
+ syntax: " @stylistic { <feature-value-declaration-list> } "
12767
13044
  },
12768
- nest: {
12769
- syntax: "<complex-selector-list>"
13045
+ "@historical-forms": {
13046
+ syntax: " @historical-forms { <feature-value-declaration-list> } "
12770
13047
  },
12771
- scope: {
12772
- syntax: "[ ( <scope-start> ) ]? [ to ( <scope-end> ) ]?"
13048
+ "@styleset": {
13049
+ syntax: " @styleset { <feature-value-declaration-list> } "
12773
13050
  },
12774
- "position-try": {
13051
+ "@character-variant": {
13052
+ syntax: " @character-variant { <feature-value-declaration-list> } "
13053
+ },
13054
+ "@swash": {
13055
+ syntax: " @swash { <feature-value-declaration-list> } "
13056
+ },
13057
+ "@ornaments": {
13058
+ syntax: " @ornaments { <feature-value-declaration-list> } "
13059
+ },
13060
+ "@annotation": {
13061
+ syntax: " @annotation { <feature-value-declaration-list> } "
12775
13062
  }
12776
13063
  };
12777
13064
  var config$3 = {
@@ -12834,7 +13121,6 @@
12834
13121
  ValidationSyntaxGroupEnum["Selectors"] = "selectors";
12835
13122
  ValidationSyntaxGroupEnum["AtRules"] = "atRules";
12836
13123
  })(ValidationSyntaxGroupEnum || (ValidationSyntaxGroupEnum = {}));
12837
-
12838
13124
  const skipped = [
12839
13125
  ValidationTokenEnum.Star,
12840
13126
  ValidationTokenEnum.HashMark,
@@ -13915,7 +14201,6 @@
13915
14201
  const index = group + '.' + keys.join('.');
13916
14202
  // @ts-ignore
13917
14203
  if (!parsedSyntaxes.has(index)) {
13918
- // @ts-ignore
13919
14204
  const syntax = parseSyntax(obj.syntax);
13920
14205
  // @ts-ignore
13921
14206
  parsedSyntaxes.set(index, syntax.chi);
@@ -14366,6 +14651,116 @@
14366
14651
  const config$2 = getSyntaxConfig();
14367
14652
  // @ts-ignore
14368
14653
  const allValues = getSyntaxConfig()["declarations" /* ValidationSyntaxGroupEnum.Declarations */].all.syntax.trim().split(/[\s|]+/g);
14654
+ /**
14655
+ * Check if a node is allowed as child in a given context
14656
+ * @param node
14657
+ * @param context
14658
+ */
14659
+ function isNodeAllowedInContext(node, context) {
14660
+ if (node.typ == exports.EnumToken.CommentNodeType || context == null) {
14661
+ return true;
14662
+ }
14663
+ switch (context?.typ) {
14664
+ case exports.EnumToken.StyleSheetNodeType:
14665
+ case exports.EnumToken.RuleNodeType:
14666
+ return node.typ == exports.EnumToken.RuleNodeType ||
14667
+ node.typ == exports.EnumToken.AtRuleNodeType ||
14668
+ node.typ == exports.EnumToken.KeyframesAtRuleNodeType ||
14669
+ (node.typ == exports.EnumToken.DeclarationNodeType && context.typ == exports.EnumToken.RuleNodeType) ||
14670
+ (node.typ == exports.EnumToken.CDOCOMMNodeType && context.typ == exports.EnumToken.StyleSheetNodeType);
14671
+ case exports.EnumToken.KeyframesAtRuleNodeType:
14672
+ return node.typ == exports.EnumToken.KeyFramesRuleNodeType;
14673
+ case exports.EnumToken.KeyFramesRuleNodeType:
14674
+ return node.typ == exports.EnumToken.DeclarationNodeType;
14675
+ case exports.EnumToken.AtRuleNodeType:
14676
+ // @ts-ignore
14677
+ const syntax = getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, '@' + context.nam)?.[0].chi ?? null;
14678
+ //
14679
+ if (syntax == null) {
14680
+ // console.error(`syntax: Not found ${ValidationSyntaxGroupEnum.AtRules}@${(context as AstAtRule).nam}`);
14681
+ return true;
14682
+ }
14683
+ const stack = syntax.slice();
14684
+ for (const child of stack) {
14685
+ if (Array.isArray(child)) {
14686
+ stack.push(...child);
14687
+ continue;
14688
+ }
14689
+ if ('chi' in child && Array.isArray(child.chi)) {
14690
+ stack.push(...child.chi);
14691
+ continue;
14692
+ }
14693
+ // @ts-ignore
14694
+ if (child.l != null) {
14695
+ // @ts-ignore
14696
+ stack.push(child.l);
14697
+ // @ts-ignore
14698
+ if (child.r != null) {
14699
+ // @ts-ignore
14700
+ stack.push(...(Array.isArray(child.r) ? child.r : [child.r]));
14701
+ }
14702
+ continue;
14703
+ }
14704
+ if (node.typ == exports.EnumToken.DeclarationNodeType) {
14705
+ if (child.typ == ValidationTokenEnum.DeclarationDefinitionToken) {
14706
+ if (node.nam == child.nam) {
14707
+ return true;
14708
+ }
14709
+ }
14710
+ }
14711
+ if (child.typ == ValidationTokenEnum.PropertyType) {
14712
+ if (['group-rule-body', 'block-contents', 'rule-list', 'stylesheet'].includes(child.val)) {
14713
+ if ((node.typ == exports.EnumToken.RuleNodeType ||
14714
+ node.typ == exports.EnumToken.AtRuleNodeType ||
14715
+ node.typ == exports.EnumToken.KeyframesAtRuleNodeType)) {
14716
+ return true;
14717
+ }
14718
+ if (node.typ == exports.EnumToken.DeclarationNodeType) {
14719
+ let parent = node.parent;
14720
+ while (parent != null) {
14721
+ if (parent.parent?.typ == exports.EnumToken.RuleNodeType) {
14722
+ return true;
14723
+ }
14724
+ parent = parent.parent;
14725
+ }
14726
+ }
14727
+ }
14728
+ if (['declaration-list', 'feature-value-declaration'].includes(child.val) && node.typ == exports.EnumToken.DeclarationNodeType) {
14729
+ return true;
14730
+ }
14731
+ if (child.val == 'page-body' && (node.typ == exports.EnumToken.DeclarationNodeType || (node.typ == exports.EnumToken.AtRuleNodeType && [
14732
+ 'top-left-corner', 'top-left', 'top-center', 'top-right', 'top-right-corner',
14733
+ 'bottom-left-corner', 'bottom-left', 'bottom-center', 'bottom-right', 'bottom-right-corner',
14734
+ 'left-top', 'left-middle', 'left-bottom', 'right-top', 'right-middle', 'right-bottom'
14735
+ ].includes(node.nam)))) {
14736
+ return true;
14737
+ }
14738
+ if (child.val == 'feature-value-block-list' &&
14739
+ (node.typ == exports.EnumToken.AtRuleNodeType && ['stylistic', 'historical-forms', 'styleset', 'character-variant', 'swash', 'ornaments', 'annotation'].includes(node.nam))) {
14740
+ return true;
14741
+ }
14742
+ if (['feature-value-declaration-list', 'feature-value-declaration'].includes(child.val) && node.typ == exports.EnumToken.DeclarationNodeType) {
14743
+ return true;
14744
+ }
14745
+ if (child.val == 'page-body') {
14746
+ if (node.typ == exports.EnumToken.DeclarationNodeType) {
14747
+ return true;
14748
+ }
14749
+ }
14750
+ // console.error(`isNodeAllowedInContext: Not found ${(child as ValidationPropertyToken).val}`, {
14751
+ // child,
14752
+ // node
14753
+ // });
14754
+ }
14755
+ }
14756
+ break;
14757
+ }
14758
+ return false;
14759
+ }
14760
+ /**
14761
+ * Create a syntax validation context from a list of tokens
14762
+ * @param input
14763
+ */
14369
14764
  function createContext(input) {
14370
14765
  const values = input.slice();
14371
14766
  const result = values.filter(token => token.typ != exports.EnumToken.CommentTokenType).slice();
@@ -14426,7 +14821,22 @@
14426
14821
  }
14427
14822
  };
14428
14823
  }
14429
- function evaluateSyntax(node, options) {
14824
+ /**
14825
+ * Evaluate the validity of the syntax of a node
14826
+ * @param node
14827
+ * @param parent
14828
+ * @param options
14829
+ */
14830
+ function evaluateSyntax(node, parent, options) {
14831
+ if (node.validSyntax) {
14832
+ return {
14833
+ valid: SyntaxValidationResult.Valid,
14834
+ node,
14835
+ syntax: null,
14836
+ error: '',
14837
+ context: []
14838
+ };
14839
+ }
14430
14840
  let ast;
14431
14841
  let result;
14432
14842
  switch (node.typ) {
@@ -14434,25 +14844,34 @@
14434
14844
  if (node.nam.startsWith('--')) {
14435
14845
  break;
14436
14846
  }
14847
+ let token = null;
14848
+ let values = node.val.slice();
14437
14849
  ast = getParsedSyntax("declarations" /* ValidationSyntaxGroupEnum.Declarations */, node.nam);
14438
- if (ast != null) {
14439
- let token = null;
14440
- const values = node.val.slice();
14441
- while (values.length > 0) {
14442
- token = values.at(-1);
14443
- if (token.typ == exports.EnumToken.WhitespaceTokenType || token.typ == exports.EnumToken.CommentTokenType) {
14850
+ while (values.length > 0) {
14851
+ token = values.at(-1);
14852
+ if (token.typ == exports.EnumToken.WhitespaceTokenType || token.typ == exports.EnumToken.CommentTokenType) {
14853
+ values.pop();
14854
+ }
14855
+ else {
14856
+ if (token.typ == exports.EnumToken.ImportantTokenType) {
14444
14857
  values.pop();
14445
- }
14446
- else {
14447
- if (token.typ == exports.EnumToken.ImportantTokenType) {
14858
+ if (values.at(-1)?.typ == exports.EnumToken.WhitespaceTokenType) {
14448
14859
  values.pop();
14449
- if (values.at(-1)?.typ == exports.EnumToken.WhitespaceTokenType) {
14450
- values.pop();
14451
- }
14452
14860
  }
14453
- break;
14861
+ }
14862
+ break;
14863
+ }
14864
+ }
14865
+ if (ast == null) {
14866
+ if (parent?.typ == exports.EnumToken.AtRuleNodeType) {
14867
+ ast = (getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, ['@' + parent.nam, 'descriptors', node.nam]));
14868
+ if (ast == null) {
14869
+ ast = (getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, ['@' + parent.nam, 'descriptors', node.nam]) ?? getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, '@' + parent.nam))?.[0]?.chi;
14870
+ values = [{ ...node, val: values }];
14454
14871
  }
14455
14872
  }
14873
+ }
14874
+ if (ast != null) {
14456
14875
  result = doEvaluateSyntax(ast, createContext(values), { ...options, visited: new WeakMap() });
14457
14876
  if (result.valid == SyntaxValidationResult.Valid && !result.context.done()) {
14458
14877
  let token = null;
@@ -14544,7 +14963,7 @@
14544
14963
  continue;
14545
14964
  }
14546
14965
  }
14547
- else if (options.occurence !== false && syntax.occurence != null) {
14966
+ else if (options.occurrence !== false && syntax.occurence != null) {
14548
14967
  result = matchOccurence(syntax, context, options);
14549
14968
  }
14550
14969
  else if (options.atLeastOnce !== false && syntax.atLeastOnce) {
@@ -14633,7 +15052,7 @@
14633
15052
  result = doEvaluateSyntax([syntax], createContext(tokens), {
14634
15053
  ...options,
14635
15054
  isList: false,
14636
- occurence: false
15055
+ occurrence: false
14637
15056
  });
14638
15057
  if (result.valid == SyntaxValidationResult.Valid) {
14639
15058
  context = con.clone();
@@ -14668,7 +15087,7 @@
14668
15087
  let counter = 0;
14669
15088
  let result;
14670
15089
  do {
14671
- result = match(syntax, context.clone(), { ...options, occurence: false });
15090
+ result = match(syntax, context.clone(), { ...options, occurrence: false });
14672
15091
  if (result.valid == SyntaxValidationResult.Drop) {
14673
15092
  break;
14674
15093
  }
@@ -14719,7 +15138,7 @@
14719
15138
  ...options,
14720
15139
  isRepeatable: null,
14721
15140
  isList: null,
14722
- occurence: null,
15141
+ occurrence: null,
14723
15142
  atLeastOnce: null
14724
15143
  });
14725
15144
  if (result.valid == SyntaxValidationResult.Valid) {
@@ -14731,7 +15150,7 @@
14731
15150
  case ValidationTokenEnum.Keyword:
14732
15151
  success = (token.typ == exports.EnumToken.IdenTokenType || token.typ == exports.EnumToken.DashedIdenTokenType || isIdentColor(token)) &&
14733
15152
  (token.val == syntax.val ||
14734
- syntax.val === token.val?.toLowerCase?.() ||
15153
+ syntax.val.toLowerCase() === token.val?.toLowerCase?.() ||
14735
15154
  // config.declarations.all
14736
15155
  allValues.includes(token.val.toLowerCase()));
14737
15156
  if (success) {
@@ -14770,7 +15189,7 @@
14770
15189
  ...options,
14771
15190
  isRepeatable: null,
14772
15191
  isList: null,
14773
- occurence: null,
15192
+ occurrence: null,
14774
15193
  atLeastOnce: null
14775
15194
  });
14776
15195
  case ValidationTokenEnum.Comma:
@@ -14805,7 +15224,7 @@
14805
15224
  ...options,
14806
15225
  isRepeatable: null,
14807
15226
  isList: null,
14808
- occurence: null,
15227
+ occurrence: null,
14809
15228
  atLeastOnce: null
14810
15229
  }).valid == SyntaxValidationResult.Valid;
14811
15230
  if (success) {
@@ -14828,18 +15247,19 @@
14828
15247
  }
14829
15248
  function matchPropertyType(syntax, context, options) {
14830
15249
  if (![
14831
- 'bg-position',
15250
+ 'color',
14832
15251
  'integer',
15252
+ 'bg-position',
14833
15253
  'length-percentage', 'flex', 'calc-sum', 'color',
14834
15254
  'color-base', 'system-color', 'deprecated-system-color',
14835
- 'pseudo-class-selector', 'pseudo-element-selector'
15255
+ 'pseudo-class-selector', 'pseudo-element-selector', 'feature-value-declaration'
14836
15256
  ].includes(syntax.val)) {
14837
15257
  if (syntax.val in config$2["syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */]) {
14838
15258
  return doEvaluateSyntax(getParsedSyntax("syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */, syntax.val), context, {
14839
15259
  ...options,
14840
15260
  isRepeatable: null,
14841
15261
  isList: null,
14842
- occurence: null,
15262
+ occurrence: null,
14843
15263
  atLeastOnce: null
14844
15264
  });
14845
15265
  }
@@ -14851,7 +15271,7 @@
14851
15271
  ...options,
14852
15272
  isRepeatable: null,
14853
15273
  isList: null,
14854
- occurence: null,
15274
+ occurrence: null,
14855
15275
  atLeastOnce: null
14856
15276
  });
14857
15277
  if (result.valid == SyntaxValidationResult.Valid) {
@@ -14956,6 +15376,14 @@
14956
15376
  (token.typ == exports.EnumToken.IdenTokenType && typeof Math[token.val.toUpperCase()] == 'number') ||
14957
15377
  [exports.EnumToken.BinaryExpressionTokenType, exports.EnumToken.NumberTokenType, exports.EnumToken.PercentageTokenType, exports.EnumToken.DimensionTokenType, exports.EnumToken.LengthTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.TimeTokenType, exports.EnumToken.ResolutionTokenType, exports.EnumToken.FrequencyTokenType].includes(token.typ);
14958
15378
  break;
15379
+ case 'declaration':
15380
+ {
15381
+ success = token.typ == exports.EnumToken.DeclarationNodeType;
15382
+ if (success) {
15383
+ success = evaluateSyntax(token, null, options).valid == SyntaxValidationResult.Valid;
15384
+ }
15385
+ }
15386
+ break;
14959
15387
  case 'declaration-value':
14960
15388
  while (!context.done()) {
14961
15389
  context.next();
@@ -14982,13 +15410,17 @@
14982
15410
  break;
14983
15411
  case 'color':
14984
15412
  case 'color-base':
14985
- success = token.typ == exports.EnumToken.ColorTokenType || (token.typ == exports.EnumToken.IdenTokenType && 'currentcolor' === token.val.toLowerCase()) || (token.typ == exports.EnumToken.IdenTokenType && 'transparent' === token.val.toLowerCase()) || (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val));
15413
+ success = token.typ == exports.EnumToken.ColorTokenType ||
15414
+ (token.typ == exports.EnumToken.IdenTokenType && 'currentcolor' === token.val.toLowerCase()) ||
15415
+ (token.typ == exports.EnumToken.IdenTokenType && 'transparent' === token.val.toLowerCase()) ||
15416
+ (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val) ||
15417
+ isColor(token));
14986
15418
  if (!success && token.typ == exports.EnumToken.FunctionTokenType && colorsFunc.includes(token.val)) {
14987
15419
  success = doEvaluateSyntax(getParsedSyntax("functions" /* ValidationSyntaxGroupEnum.Functions */, token.val)?.[0]?.chi, createContext(token.chi), {
14988
15420
  ...options,
14989
15421
  isRepeatable: null,
14990
15422
  isList: null,
14991
- occurence: null,
15423
+ occurrence: null,
14992
15424
  atLeastOnce: null
14993
15425
  }).valid == SyntaxValidationResult.Valid;
14994
15426
  }
@@ -14996,8 +15428,26 @@
14996
15428
  case 'hex-color':
14997
15429
  success = (token.typ == exports.EnumToken.ColorTokenType && token.kin == exports.ColorType.HEX) || (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val));
14998
15430
  break;
15431
+ case 'feature-value-declaration':
15432
+ {
15433
+ let hasNumber = false;
15434
+ success = token.typ == exports.EnumToken.DeclarationNodeType && token.val.length > 0 && token.val.every((val) => {
15435
+ if (val.typ == exports.EnumToken.WhitespaceTokenType || val.typ == exports.EnumToken.CommentTokenType) {
15436
+ return true;
15437
+ }
15438
+ const success = (val.typ == exports.EnumToken.NumberTokenType && Number.isInteger(+val.val) && val.val > 0) || (val.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(val.val.toLowerCase()) || (val.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(val.val)));
15439
+ if (success) {
15440
+ hasNumber = true;
15441
+ }
15442
+ if ('range' in syntax) {
15443
+ return success && +val.val >= +syntax.range[0] && +val.val <= +syntax.range[1];
15444
+ }
15445
+ return success;
15446
+ }) && hasNumber;
15447
+ }
15448
+ break;
14999
15449
  case 'integer':
15000
- success = (token.typ == exports.EnumToken.NumberTokenType && Number.isInteger(+(token.val))) || (token.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(token.val.toLowerCase()) || (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val)));
15450
+ success = (token.typ == exports.EnumToken.NumberTokenType && Number.isInteger(+token.val) && token.val > 0) || (token.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(token.val.toLowerCase()) || (token.typ == exports.EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val)));
15001
15451
  if ('range' in syntax) {
15002
15452
  success = success && +token.val >= +syntax.range[0] && +token.val <= +syntax.range[1];
15003
15453
  }
@@ -15061,7 +15511,7 @@
15061
15511
  ...options,
15062
15512
  isRepeatable: null,
15063
15513
  isList: null,
15064
- occurence: null,
15514
+ occurrence: null,
15065
15515
  atLeastOnce: null
15066
15516
  }).valid == SyntaxValidationResult.Valid;
15067
15517
  }
@@ -15077,7 +15527,7 @@
15077
15527
  ...options,
15078
15528
  isRepeatable: null,
15079
15529
  isList: null,
15080
- occurence: null,
15530
+ occurrence: null,
15081
15531
  atLeastOnce: null
15082
15532
  }).valid == SyntaxValidationResult.Valid;
15083
15533
  }
@@ -15224,7 +15674,6 @@
15224
15674
  i = -1;
15225
15675
  }
15226
15676
  }
15227
- // console.error()
15228
15677
  const success = syntax.length == 0;
15229
15678
  return {
15230
15679
  valid: success ? SyntaxValidationResult.Valid : SyntaxValidationResult.Drop,
@@ -15304,6 +15753,17 @@
15304
15753
  }
15305
15754
 
15306
15755
  function validateAtRuleMedia(atRule, options, root) {
15756
+ if (!Array.isArray(atRule.chi)) {
15757
+ // @ts-ignore
15758
+ return {
15759
+ valid: SyntaxValidationResult.Drop,
15760
+ matches: [],
15761
+ node: atRule,
15762
+ syntax: '@' + atRule.nam,
15763
+ error: 'expected supports body',
15764
+ tokens: []
15765
+ };
15766
+ }
15307
15767
  // media-query-list
15308
15768
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
15309
15769
  // @ts-ignore
@@ -15536,6 +15996,17 @@
15536
15996
  }
15537
15997
 
15538
15998
  function validateAtRuleCounterStyle(atRule, options, root) {
15999
+ if (!Array.isArray(atRule.chi)) {
16000
+ // @ts-ignore
16001
+ return {
16002
+ valid: SyntaxValidationResult.Drop,
16003
+ matches: [],
16004
+ node: atRule,
16005
+ syntax: '@' + atRule.nam,
16006
+ error: 'expected supports body',
16007
+ tokens: []
16008
+ };
16009
+ }
15539
16010
  // media-query-list
15540
16011
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
15541
16012
  // @ts-ignore
@@ -15605,6 +16076,17 @@
15605
16076
  }
15606
16077
 
15607
16078
  function validateAtRulePage(atRule, options, root) {
16079
+ if (!Array.isArray(atRule.chi)) {
16080
+ // @ts-ignore
16081
+ return {
16082
+ valid: SyntaxValidationResult.Drop,
16083
+ matches: [],
16084
+ node: atRule,
16085
+ syntax: '@' + atRule.nam,
16086
+ error: 'expected supports body',
16087
+ tokens: []
16088
+ };
16089
+ }
15608
16090
  // media-query-list
15609
16091
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
15610
16092
  // @ts-ignore
@@ -15683,6 +16165,17 @@
15683
16165
  }
15684
16166
 
15685
16167
  function validateAtRulePageMarginBox(atRule, options, root) {
16168
+ if (!Array.isArray(atRule.chi)) {
16169
+ // @ts-ignore
16170
+ return {
16171
+ valid: SyntaxValidationResult.Drop,
16172
+ matches: [],
16173
+ node: atRule,
16174
+ syntax: '@' + atRule.nam,
16175
+ error: 'expected supports body',
16176
+ tokens: []
16177
+ };
16178
+ }
15686
16179
  if (Array.isArray(atRule.tokens) && atRule.tokens.length > 0) {
15687
16180
  // @ts-ignore
15688
16181
  return {
@@ -15738,6 +16231,17 @@
15738
16231
  tokens: []
15739
16232
  };
15740
16233
  }
16234
+ if (!Array.isArray(atRule.chi)) {
16235
+ // @ts-ignore
16236
+ return {
16237
+ valid: SyntaxValidationResult.Drop,
16238
+ matches: [],
16239
+ node: atRule,
16240
+ syntax: '@' + atRule.nam,
16241
+ error: 'expected supports body',
16242
+ tokens: []
16243
+ };
16244
+ }
15741
16245
  const result = validateAtRuleSupportsConditions(atRule, atRule.tokens);
15742
16246
  if (result) {
15743
16247
  if (result.node == null) {
@@ -16130,6 +16634,17 @@
16130
16634
  }
16131
16635
 
16132
16636
  function validateAtRuleLayer(atRule, options, root) {
16637
+ if (!Array.isArray(atRule.chi)) {
16638
+ // @ts-ignore
16639
+ return {
16640
+ valid: SyntaxValidationResult.Drop,
16641
+ matches: [],
16642
+ node: atRule,
16643
+ syntax: '@' + atRule.nam,
16644
+ error: 'expected supports body',
16645
+ tokens: []
16646
+ };
16647
+ }
16133
16648
  // media-query-list
16134
16649
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
16135
16650
  // @ts-ignore
@@ -16146,6 +16661,17 @@
16146
16661
  }
16147
16662
 
16148
16663
  function validateAtRuleFontFeatureValues(atRule, options, root) {
16664
+ if (!Array.isArray(atRule.chi)) {
16665
+ // @ts-ignore
16666
+ return {
16667
+ valid: SyntaxValidationResult.Drop,
16668
+ matches: [],
16669
+ node: atRule,
16670
+ syntax: '@' + atRule.nam,
16671
+ error: 'expected supports body',
16672
+ tokens: []
16673
+ };
16674
+ }
16149
16675
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
16150
16676
  // @ts-ignore
16151
16677
  return {
@@ -16329,6 +16855,17 @@
16329
16855
  }
16330
16856
 
16331
16857
  function validateAtRuleKeyframes(atRule, options, root) {
16858
+ if (!Array.isArray(atRule.chi)) {
16859
+ // @ts-ignore
16860
+ return {
16861
+ valid: SyntaxValidationResult.Drop,
16862
+ matches: [],
16863
+ node: atRule,
16864
+ syntax: '@' + atRule.nam,
16865
+ error: 'expected supports body',
16866
+ tokens: []
16867
+ };
16868
+ }
16332
16869
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
16333
16870
  // @ts-ignore
16334
16871
  return {
@@ -16374,6 +16911,17 @@
16374
16911
  }
16375
16912
 
16376
16913
  function validateAtRuleWhen(atRule, options, root) {
16914
+ if (!Array.isArray(atRule.chi)) {
16915
+ // @ts-ignore
16916
+ return {
16917
+ valid: SyntaxValidationResult.Drop,
16918
+ matches: [],
16919
+ node: atRule,
16920
+ syntax: '@' + atRule.nam,
16921
+ error: 'expected supports body',
16922
+ tokens: []
16923
+ };
16924
+ }
16377
16925
  const slice = Array.isArray(atRule.tokens) ? atRule.tokens.slice() : [];
16378
16926
  consumeWhitespace(slice);
16379
16927
  if (slice.length == 0) {
@@ -16537,6 +17085,17 @@
16537
17085
 
16538
17086
  const validateContainerScrollStateFeature = validateContainerSizeFeature;
16539
17087
  function validateAtRuleContainer(atRule, options, root) {
17088
+ if (!Array.isArray(atRule.chi)) {
17089
+ // @ts-ignore
17090
+ return {
17091
+ valid: SyntaxValidationResult.Drop,
17092
+ matches: [],
17093
+ node: atRule,
17094
+ syntax: '@' + atRule.nam,
17095
+ error: 'expected supports body',
17096
+ tokens: []
17097
+ };
17098
+ }
16540
17099
  // media-query-list
16541
17100
  if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
16542
17101
  // @ts-ignore
@@ -17069,6 +17628,36 @@
17069
17628
  function reject(reason) {
17070
17629
  throw new Error(reason ?? 'Parsing aborted');
17071
17630
  }
17631
+ function normalizeVisitorKeyName(keyName) {
17632
+ return keyName.replace(/-([a-z])/g, (all, one) => one.toUpperCase());
17633
+ }
17634
+ function replaceToken(parent, value, replacement) {
17635
+ for (const node of (Array.isArray(replacement) ? replacement : [replacement])) {
17636
+ if ('parent' in value && value.parent != node.parent) {
17637
+ Object.defineProperty(node, 'parent', {
17638
+ ...definedPropertySettings,
17639
+ value: value.parent
17640
+ });
17641
+ }
17642
+ }
17643
+ if (parent.typ == exports.EnumToken.BinaryExpressionTokenType) {
17644
+ if (parent.l == value) {
17645
+ parent.l = replacement;
17646
+ }
17647
+ else {
17648
+ parent.r = replacement;
17649
+ }
17650
+ }
17651
+ else {
17652
+ const target = 'val' in parent && Array.isArray(parent.val) ? parent.val : parent.chi;
17653
+ // @ts-ignore
17654
+ const index = target.indexOf(value);
17655
+ if (index == -1) {
17656
+ return;
17657
+ }
17658
+ target.splice(index, 1, ...(Array.isArray(replacement) ? replacement : [replacement]));
17659
+ }
17660
+ }
17072
17661
  /**
17073
17662
  * parse css string
17074
17663
  * @param iter
@@ -17118,6 +17707,8 @@
17118
17707
  const stats = {
17119
17708
  src: options.src ?? '',
17120
17709
  bytesIn: 0,
17710
+ nodesCount: 0,
17711
+ tokensCount: 0,
17121
17712
  importedBytesIn: 0,
17122
17713
  parse: `0ms`,
17123
17714
  minify: `0ms`,
@@ -17146,14 +17737,107 @@
17146
17737
  src: ''
17147
17738
  };
17148
17739
  }
17149
- let item;
17150
- let node;
17740
+ let valuesHandlers;
17741
+ let preValuesHandlers;
17742
+ let postValuesHandlers;
17743
+ let preVisitorsHandlersMap;
17744
+ let visitorsHandlersMap;
17745
+ let postVisitorsHandlersMap;
17151
17746
  const rawTokens = [];
17152
17747
  const imports = [];
17748
+ let item;
17749
+ let node;
17153
17750
  // @ts-ignore ignore error
17154
- const isAsync = typeof iter[Symbol.asyncIterator] === 'function';
17751
+ let isAsync = typeof iter[Symbol.asyncIterator] === 'function';
17752
+ if (options.visitor != null) {
17753
+ valuesHandlers = new Map;
17754
+ preValuesHandlers = new Map;
17755
+ postValuesHandlers = new Map;
17756
+ preVisitorsHandlersMap = new Map;
17757
+ visitorsHandlersMap = new Map;
17758
+ postVisitorsHandlersMap = new Map;
17759
+ const visitors = Object.entries(options.visitor);
17760
+ let key;
17761
+ let value;
17762
+ let i;
17763
+ for (i = 0; i < visitors.length; i++) {
17764
+ key = visitors[i][0];
17765
+ value = visitors[i][1];
17766
+ if (Number.isInteger(+key)) {
17767
+ visitors.splice(i + 1, 0, ...Object.entries(value));
17768
+ continue;
17769
+ }
17770
+ if (Array.isArray(value)) {
17771
+ // @ts-ignore
17772
+ visitors.splice(i + 1, 0, ...value.map((item) => [key, item]));
17773
+ continue;
17774
+ }
17775
+ if (key in exports.EnumToken) {
17776
+ if (typeof value == 'function') {
17777
+ if (!valuesHandlers.has(exports.EnumToken[key])) {
17778
+ valuesHandlers.set(exports.EnumToken[key], []);
17779
+ }
17780
+ valuesHandlers.get(exports.EnumToken[key]).push(value);
17781
+ }
17782
+ else if (typeof value == 'object' && 'type' in value && 'handler' in value && value.type in exports.WalkerEvent) {
17783
+ if (value.type == exports.WalkerEvent.Enter) {
17784
+ if (!preValuesHandlers.has(exports.EnumToken[key])) {
17785
+ preValuesHandlers.set(exports.EnumToken[key], []);
17786
+ }
17787
+ preValuesHandlers.get(exports.EnumToken[key]).push(value.handler);
17788
+ }
17789
+ else if (value.type == exports.WalkerEvent.Leave) {
17790
+ if (!postValuesHandlers.has(exports.EnumToken[key])) {
17791
+ postValuesHandlers.set(exports.EnumToken[key], []);
17792
+ }
17793
+ postValuesHandlers.get(exports.EnumToken[key]).push(value.handler);
17794
+ }
17795
+ }
17796
+ else {
17797
+ errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
17798
+ }
17799
+ }
17800
+ else if (['Declaration', 'Rule', 'AtRule', 'KeyframesRule', 'KeyframesAtRule'].includes(key)) {
17801
+ if (typeof value == 'function') {
17802
+ if (!visitorsHandlersMap.has(key)) {
17803
+ visitorsHandlersMap.set(key, []);
17804
+ }
17805
+ visitorsHandlersMap.get(key).push(value);
17806
+ }
17807
+ else if (typeof value == 'object') {
17808
+ if ('type' in value && 'handler' in value && value.type in exports.WalkerEvent) {
17809
+ if (value.type == exports.WalkerEvent.Enter) {
17810
+ if (!preVisitorsHandlersMap.has(key)) {
17811
+ preVisitorsHandlersMap.set(key, []);
17812
+ }
17813
+ preVisitorsHandlersMap.get(key).push(value.handler);
17814
+ }
17815
+ else if (value.type == exports.WalkerEvent.Leave) {
17816
+ if (!postVisitorsHandlersMap.has(key)) {
17817
+ postVisitorsHandlersMap.set(key, []);
17818
+ }
17819
+ postVisitorsHandlersMap.get(key).push(value.handler);
17820
+ }
17821
+ }
17822
+ else {
17823
+ if (!visitorsHandlersMap.has(key)) {
17824
+ visitorsHandlersMap.set(key, []);
17825
+ }
17826
+ visitorsHandlersMap.get(key).push(value);
17827
+ }
17828
+ }
17829
+ else {
17830
+ errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
17831
+ }
17832
+ }
17833
+ else {
17834
+ errors.push({ action: 'ignore', message: `doParse: visitor.${key} is not a valid key name` });
17835
+ }
17836
+ }
17837
+ }
17155
17838
  while (item = isAsync ? (await iter.next()).value : iter.next().value) {
17156
17839
  stats.bytesIn = item.bytesIn;
17840
+ stats.tokensCount++;
17157
17841
  rawTokens.push(item);
17158
17842
  if (item.hint != null && BadTokensTypes.includes(item.hint)) {
17159
17843
  const node = getTokenType(item.token, item.hint);
@@ -17181,7 +17865,7 @@
17181
17865
  ast.loc.end = item.end;
17182
17866
  }
17183
17867
  if (item.token == ';' || item.token == '{') {
17184
- node = parseNode(tokens, context, options, errors, src, map, rawTokens);
17868
+ node = parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
17185
17869
  rawTokens.length = 0;
17186
17870
  if (node != null) {
17187
17871
  if ('chi' in node) {
@@ -17225,7 +17909,7 @@
17225
17909
  map = new Map;
17226
17910
  }
17227
17911
  else if (item.token == '}') {
17228
- parseNode(tokens, context, options, errors, src, map, rawTokens);
17912
+ parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
17229
17913
  rawTokens.length = 0;
17230
17914
  if (context.loc != null) {
17231
17915
  context.loc.end = item.end;
@@ -17246,7 +17930,7 @@
17246
17930
  }
17247
17931
  }
17248
17932
  if (tokens.length > 0) {
17249
- node = parseNode(tokens, context, options, errors, src, map, rawTokens);
17933
+ node = parseNode(tokens, context, options, errors, src, map, rawTokens, stats);
17250
17934
  rawTokens.length = 0;
17251
17935
  if (node != null) {
17252
17936
  if (node.typ == exports.EnumToken.AtRuleNodeType && node.nam == 'import') {
@@ -17270,21 +17954,18 @@
17270
17954
  const token = node.tokens[0];
17271
17955
  const url = token.typ == exports.EnumToken.StringTokenType ? token.val.slice(1, -1) : token.val;
17272
17956
  try {
17273
- const root = await options.getStream(url, options.src).then(async (stream) => {
17274
- return doParse(tokenizeStream(stream), Object.assign({}, options, {
17275
- minify: false,
17276
- setParent: false,
17277
- src: options.resolve(url, options.src).absolute
17278
- })); // )
17279
- });
17280
- // const root: ParseResult = await options.load!(url, <string>options.src).then((src: string) => {
17281
- //
17282
- // return doParse(src, Object.assign({}, options, {
17283
- // minify: false,
17284
- // setParent: false,
17285
- // src: options.resolve!(url, options.src as string).absolute
17286
- // }))
17287
- // });
17957
+ const result = options.load(url, options.src);
17958
+ const stream = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction' ? await result : result;
17959
+ const root = await doParse(stream instanceof ReadableStream ? tokenizeStream(stream) : tokenize$1({
17960
+ stream,
17961
+ buffer: '',
17962
+ position: { ind: 0, lin: 1, col: 1 },
17963
+ currentPosition: { ind: -1, lin: 1, col: 0 }
17964
+ }), Object.assign({}, options, {
17965
+ minify: false,
17966
+ setParent: false,
17967
+ src: options.resolve(url, options.src).absolute
17968
+ }));
17288
17969
  stats.importedBytesIn += root.stats.bytesIn;
17289
17970
  stats.imports.push(root.stats);
17290
17971
  node.parent.chi.splice(node.parent.chi.indexOf(node), 1, ...root.ast.chi);
@@ -17312,39 +17993,155 @@
17312
17993
  if (options.expandNestingRules) {
17313
17994
  ast = expand(ast);
17314
17995
  }
17996
+ let replacement;
17997
+ let callable;
17315
17998
  if (options.visitor != null) {
17316
17999
  for (const result of walk(ast)) {
17317
- if (result.node.typ == exports.EnumToken.DeclarationNodeType &&
17318
- (typeof options.visitor.Declaration == 'function' || options.visitor.Declaration?.[result.node.nam] != null)) {
17319
- const callable = typeof options.visitor.Declaration == 'function' ? options.visitor.Declaration : options.visitor.Declaration[result.node.nam];
17320
- const isAsync = Object.getPrototypeOf(callable).constructor.name == 'AsyncFunction';
17321
- const results = isAsync ? await callable(result.node) : callable(result.node);
17322
- if (results == null || (Array.isArray(results) && results.length == 0)) {
17323
- continue;
18000
+ if (valuesHandlers.size > 0 || preVisitorsHandlersMap.size > 0 || visitorsHandlersMap.size > 0 || postVisitorsHandlersMap.size > 0) {
18001
+ if ((result.node.typ == exports.EnumToken.DeclarationNodeType &&
18002
+ (preVisitorsHandlersMap.has('Declaration') || visitorsHandlersMap.has('Declaration') || postVisitorsHandlersMap.has('Declaration'))) ||
18003
+ (result.node.typ == exports.EnumToken.AtRuleNodeType && (preVisitorsHandlersMap.has('AtRule') || visitorsHandlersMap.has('AtRule') || postVisitorsHandlersMap.has('AtRule'))) ||
18004
+ (result.node.typ == exports.EnumToken.KeyframesAtRuleNodeType && (preVisitorsHandlersMap.has('KeyframesAtRule') || visitorsHandlersMap.has('KeyframesAtRule') || postVisitorsHandlersMap.has('KeyframesAtRule')))) {
18005
+ const handlers = [];
18006
+ const key = result.node.typ == exports.EnumToken.DeclarationNodeType ? 'Declaration' : result.node.typ == exports.EnumToken.AtRuleNodeType ? 'AtRule' : 'KeyframesAtRule';
18007
+ if (preVisitorsHandlersMap.has(key)) {
18008
+ // @ts-ignore
18009
+ handlers.push(...preVisitorsHandlersMap.get(key));
18010
+ }
18011
+ if (visitorsHandlersMap.has(key)) {
18012
+ // @ts-ignore
18013
+ handlers.push(...visitorsHandlersMap.get(key));
18014
+ }
18015
+ if (postVisitorsHandlersMap.has(key)) {
18016
+ // @ts-ignore
18017
+ handlers.push(...postVisitorsHandlersMap.get(key));
18018
+ }
18019
+ let node = result.node;
18020
+ for (const handler of handlers) {
18021
+ callable = typeof handler == 'function' ? handler : handler[normalizeVisitorKeyName(node.typ == exports.EnumToken.DeclarationNodeType || node.typ == exports.EnumToken.AtRuleNodeType ? node.nam : node.val)];
18022
+ if (callable == null) {
18023
+ continue;
18024
+ }
18025
+ replacement = callable(node, result.parent);
18026
+ if (replacement == null) {
18027
+ continue;
18028
+ }
18029
+ isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
18030
+ if (replacement) {
18031
+ replacement = await replacement;
18032
+ }
18033
+ if (replacement == null || replacement == node) {
18034
+ continue;
18035
+ }
18036
+ // @ts-ignore
18037
+ node = replacement;
18038
+ //
18039
+ if (Array.isArray(node)) {
18040
+ break;
18041
+ }
18042
+ }
18043
+ if (node != result.node) {
18044
+ // @ts-ignore
18045
+ replaceToken(result.parent, result.node, node);
18046
+ }
17324
18047
  }
17325
- // @ts-ignore
17326
- result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
17327
- }
17328
- else if (options.visitor.Rule != null && result.node.typ == exports.EnumToken.RuleNodeType) {
17329
- const isAsync = Object.getPrototypeOf(options.visitor.Rule).constructor.name == 'AsyncFunction';
17330
- const results = isAsync ? await options.visitor.Rule(result.node) : options.visitor.Rule(result.node);
17331
- if (results == null || (Array.isArray(results) && results.length == 0)) {
17332
- continue;
18048
+ else if ((result.node.typ == exports.EnumToken.RuleNodeType && (preVisitorsHandlersMap.has('Rule') || visitorsHandlersMap.has('Rule') || postVisitorsHandlersMap.has('Rule'))) ||
18049
+ (result.node.typ == exports.EnumToken.KeyFramesRuleNodeType && (preVisitorsHandlersMap.has('KeyframesRule') || visitorsHandlersMap.has('KeyframesRule') || postVisitorsHandlersMap.has('KeyframesRule')))) {
18050
+ const handlers = [];
18051
+ const key = result.node.typ == exports.EnumToken.RuleNodeType ? 'Rule' : 'KeyframesRule';
18052
+ if (preVisitorsHandlersMap.has(key)) {
18053
+ handlers.push(...preVisitorsHandlersMap.get(key));
18054
+ }
18055
+ if (visitorsHandlersMap.has(key)) {
18056
+ handlers.push(...visitorsHandlersMap.get(key));
18057
+ }
18058
+ if (postVisitorsHandlersMap.has(key)) {
18059
+ handlers.push(...postVisitorsHandlersMap.get(key));
18060
+ }
18061
+ let node = result.node;
18062
+ for (const callable of handlers) {
18063
+ replacement = callable(node, result.parent);
18064
+ if (replacement == null) {
18065
+ continue;
18066
+ }
18067
+ isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
18068
+ if (replacement) {
18069
+ replacement = await replacement;
18070
+ }
18071
+ if (replacement == null || replacement == node) {
18072
+ continue;
18073
+ }
18074
+ // @ts-ignore
18075
+ node = replacement;
18076
+ //
18077
+ if (Array.isArray(node)) {
18078
+ break;
18079
+ }
18080
+ }
18081
+ // @ts-ignore
18082
+ if (node != result.node) {
18083
+ // @ts-ignore
18084
+ replaceToken(result.parent, result.node, node);
18085
+ }
17333
18086
  }
17334
- // @ts-ignore
17335
- result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
17336
- }
17337
- else if (options.visitor.AtRule != null &&
17338
- result.node.typ == exports.EnumToken.AtRuleNodeType &&
17339
- (typeof options.visitor.AtRule == 'function' || options.visitor.AtRule?.[result.node.nam] != null)) {
17340
- const callable = typeof options.visitor.AtRule == 'function' ? options.visitor.AtRule : options.visitor.AtRule[result.node.nam];
17341
- const isAsync = Object.getPrototypeOf(callable).constructor.name == 'AsyncFunction';
17342
- const results = isAsync ? await callable(result.node) : callable(result.node);
17343
- if (results == null || (Array.isArray(results) && results.length == 0)) {
17344
- continue;
18087
+ else if (valuesHandlers.size > 0) {
18088
+ let node = null;
18089
+ node = result.node;
18090
+ if (valuesHandlers.has(node.typ)) {
18091
+ for (const valueHandler of valuesHandlers.get(node.typ)) {
18092
+ callable = valueHandler;
18093
+ replacement = callable(node, result.parent);
18094
+ if (replacement == null) {
18095
+ continue;
18096
+ }
18097
+ isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
18098
+ if (isAsync) {
18099
+ replacement = await replacement;
18100
+ }
18101
+ if (replacement != null && replacement != node) {
18102
+ node = replacement;
18103
+ }
18104
+ }
18105
+ }
18106
+ if (node != result.node) {
18107
+ // @ts-ignore
18108
+ replaceToken(result.parent, value, node);
18109
+ }
18110
+ const tokens = 'tokens' in result.node ? result.node.tokens : [];
18111
+ if ('val' in result.node && Array.isArray(result.node.val)) {
18112
+ tokens.push(...result.node.val);
18113
+ }
18114
+ if (tokens.length == 0) {
18115
+ continue;
18116
+ }
18117
+ for (const { value, parent, root } of walkValues(tokens, result.node)) {
18118
+ node = value;
18119
+ if (valuesHandlers.has(node.typ)) {
18120
+ for (const valueHandler of valuesHandlers.get(node.typ)) {
18121
+ callable = valueHandler;
18122
+ let result = callable(node, parent, root);
18123
+ if (result == null) {
18124
+ continue;
18125
+ }
18126
+ isAsync = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction';
18127
+ if (isAsync) {
18128
+ result = await result;
18129
+ }
18130
+ if (result != null && result != node) {
18131
+ node = result;
18132
+ }
18133
+ //
18134
+ if (Array.isArray(node)) {
18135
+ break;
18136
+ }
18137
+ }
18138
+ }
18139
+ if (node != value) {
18140
+ // @ts-ignore
18141
+ replaceToken(parent, value, node);
18142
+ }
18143
+ }
17345
18144
  }
17346
- // @ts-ignore
17347
- result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
17348
18145
  }
17349
18146
  }
17350
18147
  }
@@ -17382,7 +18179,7 @@
17382
18179
  }
17383
18180
  return null;
17384
18181
  }
17385
- function parseNode(results, context, options, errors, src, map, rawTokens) {
18182
+ function parseNode(results, context, options, errors, src, map, rawTokens, stats) {
17386
18183
  let tokens = [];
17387
18184
  for (const t of results) {
17388
18185
  const node = getTokenType(t.token, t.hint);
@@ -17404,11 +18201,13 @@
17404
18201
  continue;
17405
18202
  }
17406
18203
  loc = location;
17407
- // @ts-ignore
17408
18204
  context.chi.push(tokens[i]);
17409
- if (options.sourcemap) {
17410
- tokens[i].loc = loc;
17411
- }
18205
+ stats.nodesCount++;
18206
+ Object.defineProperty(tokens[i], 'loc', {
18207
+ ...definedPropertySettings,
18208
+ value: loc,
18209
+ enumerable: options.sourcemap !== false
18210
+ });
17412
18211
  }
17413
18212
  else if (tokens[i].typ != exports.EnumToken.WhitespaceTokenType) {
17414
18213
  break;
@@ -17438,9 +18237,7 @@
17438
18237
  rawTokens.shift();
17439
18238
  if (atRule.val == 'import') {
17440
18239
  // only @charset and @layer are accepted before @import
17441
- // @ts-ignore
17442
18240
  if (context.chi.length > 0) {
17443
- // @ts-ignore
17444
18241
  let i = context.chi.length;
17445
18242
  while (i--) {
17446
18243
  // @ts-ignore
@@ -17449,11 +18246,8 @@
17449
18246
  continue;
17450
18247
  }
17451
18248
  if (type != exports.EnumToken.AtRuleNodeType) {
17452
- // @ts-ignore
17453
18249
  if (!(type == exports.EnumToken.InvalidAtRuleTokenType &&
17454
- // @ts-ignore
17455
18250
  ['charset', 'layer', 'import'].includes(context.chi[i].nam))) {
17456
- // @ts-ignore
17457
18251
  errors.push({
17458
18252
  action: 'drop',
17459
18253
  message: 'invalid @import',
@@ -17464,7 +18258,6 @@
17464
18258
  return null;
17465
18259
  }
17466
18260
  }
17467
- // @ts-ignore
17468
18261
  const name = context.chi[i].nam;
17469
18262
  if (name != 'charset' && name != 'import' && name != 'layer') {
17470
18263
  errors.push({ action: 'drop', message: 'invalid @import', location });
@@ -17555,14 +18348,14 @@
17555
18348
  }
17556
18349
  }
17557
18350
  const t = parseAtRulePrelude(parseTokens(tokens, { minify: options.minify }), atRule);
17558
- const raw = t.reduce((acc, curr) => {
17559
- acc.push(renderToken(curr, { removeComments: true, convertColor: false }));
17560
- return acc;
17561
- }, []);
18351
+ const raw = [];
18352
+ for (const curr of t) {
18353
+ raw.push(renderToken(curr, { removeComments: true, convertColor: false }));
18354
+ }
17562
18355
  const nam = renderToken(atRule, { removeComments: true });
17563
18356
  // @ts-ignore
17564
18357
  const node = {
17565
- typ: /^(-[a-z]+-)?keyframes$/.test(nam) ? exports.EnumToken.KeyframeAtRuleNodeType : exports.EnumToken.AtRuleNodeType,
18358
+ typ: /^(-[a-z]+-)?keyframes$/.test(nam) ? exports.EnumToken.KeyframesAtRuleNodeType : exports.EnumToken.AtRuleNodeType,
17566
18359
  nam,
17567
18360
  val: raw.join('')
17568
18361
  };
@@ -17574,10 +18367,12 @@
17574
18367
  node.chi = [];
17575
18368
  }
17576
18369
  loc = map.get(atRule);
17577
- if (options.sourcemap) {
17578
- node.loc = loc;
17579
- node.loc.end = { ...map.get(delim).end };
17580
- }
18370
+ Object.defineProperty(node, 'loc', {
18371
+ ...definedPropertySettings,
18372
+ value: loc,
18373
+ enumerable: options.sourcemap !== false
18374
+ });
18375
+ node.loc.end = { ...map.get(delim).end };
17581
18376
  let isValid = true;
17582
18377
  if (node.nam == 'else') {
17583
18378
  const prev = getLastNode(context);
@@ -17591,20 +18386,31 @@
17591
18386
  }
17592
18387
  }
17593
18388
  // @ts-ignore
17594
- const valid = options.validation == exports.ValidationLevel.None ? {
18389
+ const skipValidate = (options.validation & exports.ValidationLevel.AtRule) == 0;
18390
+ const isAllowed = skipValidate || isNodeAllowedInContext(node, context);
18391
+ // @ts-ignore
18392
+ const valid = skipValidate ? {
17595
18393
  valid: SyntaxValidationResult.Valid,
17596
18394
  error: '',
17597
18395
  node,
17598
18396
  syntax: '@' + node.nam
17599
- } : isValid ? (node.typ == exports.EnumToken.KeyframeAtRuleNodeType ? validateAtRuleKeyframes(node) : validateAtRule(node, options, context)) : {
18397
+ } : !isAllowed ? {
18398
+ valid: SyntaxValidationResult.Drop,
18399
+ node,
18400
+ syntax: '@' + node.nam,
18401
+ error: `${exports.EnumToken[context.typ]}: child ${exports.EnumToken[node.typ]} not allowed in context${context.typ == exports.EnumToken.AtRuleNodeType ? ` '@${context.nam}'` : context.typ == exports.EnumToken.StyleSheetNodeType ? ` 'stylesheet'` : ''}`} : isValid ? (node.typ == exports.EnumToken.KeyframesAtRuleNodeType ? validateAtRuleKeyframes(node) : validateAtRule(node, options, context)) : {
17600
18402
  valid: SyntaxValidationResult.Drop,
17601
18403
  node,
17602
18404
  syntax: '@' + node.nam,
17603
18405
  error: '@' + node.nam + ' not allowed here'};
17604
18406
  if (valid.valid == SyntaxValidationResult.Drop) {
18407
+ let message = '';
18408
+ for (const token of tokens) {
18409
+ message += renderToken(token, { minify: false });
18410
+ }
17605
18411
  errors.push({
17606
18412
  action: 'drop',
17607
- message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
18413
+ message: valid.error + ' - "' + message + '"',
17608
18414
  node,
17609
18415
  // @ts-ignore
17610
18416
  location: { src, ...(map.get(valid.node) ?? location) }
@@ -17613,13 +18419,17 @@
17613
18419
  node.typ = exports.EnumToken.InvalidAtRuleTokenType;
17614
18420
  }
17615
18421
  else {
17616
- node.val = node.tokens.reduce((acc, curr) => acc + renderToken(curr, {
17617
- minify: false,
17618
- convertColor: false,
17619
- removeComments: true
17620
- }), '');
18422
+ node.val = '';
18423
+ for (const token of node.tokens) {
18424
+ node.val += renderToken(token, {
18425
+ minify: false,
18426
+ convertColor: false,
18427
+ removeComments: true
18428
+ });
18429
+ }
17621
18430
  }
17622
18431
  context.chi.push(node);
18432
+ stats.nodesCount++;
17623
18433
  Object.defineProperties(node, {
17624
18434
  parent: { ...definedPropertySettings, value: context },
17625
18435
  validSyntax: { ...definedPropertySettings, value: valid.valid == SyntaxValidationResult.Valid }
@@ -17632,7 +18442,7 @@
17632
18442
  const location = map.get(tokens[0]);
17633
18443
  const uniq = new Map;
17634
18444
  parseTokens(tokens, { minify: true });
17635
- const ruleType = context.typ == exports.EnumToken.KeyframeAtRuleNodeType ? exports.EnumToken.KeyFrameRuleNodeType : exports.EnumToken.RuleNodeType;
18445
+ const ruleType = context.typ == exports.EnumToken.KeyframesAtRuleNodeType ? exports.EnumToken.KeyFramesRuleNodeType : exports.EnumToken.RuleNodeType;
17636
18446
  if (ruleType == exports.EnumToken.RuleNodeType) {
17637
18447
  parseSelector(tokens);
17638
18448
  }
@@ -17642,6 +18452,34 @@
17642
18452
  if (curr.typ == exports.EnumToken.CommentTokenType) {
17643
18453
  return acc;
17644
18454
  }
18455
+ if (options.minify) {
18456
+ if (curr.typ == exports.EnumToken.PseudoClassFuncTokenType && curr.val == ':nth-child') {
18457
+ let i = 0;
18458
+ for (; i < curr.chi.length; i++) {
18459
+ if (curr.chi[i].typ == exports.EnumToken.IdenTokenType && curr.chi[i].val == 'even') {
18460
+ Object.assign(curr.chi[i], {
18461
+ typ: exports.EnumToken.Dimension,
18462
+ val: 2,
18463
+ unit: 'n'
18464
+ });
18465
+ }
18466
+ else if (curr.chi[i].typ == exports.EnumToken.Dimension &&
18467
+ curr.chi[i].val == 2 &&
18468
+ curr.chi[i].unit == 'n' &&
18469
+ curr.chi[i + 1]?.typ == exports.EnumToken.WhitespaceTokenType &&
18470
+ curr.chi[i + 2]?.typ == exports.EnumToken.LiteralTokenType &&
18471
+ curr.chi[i + 2].val == '+' &&
18472
+ curr.chi[i + 3]?.typ == exports.EnumToken.WhitespaceTokenType &&
18473
+ curr.chi[i + 4]?.typ == exports.EnumToken.NumberTokenType &&
18474
+ curr.chi[i + 4].val == 1) {
18475
+ curr.chi.splice(i, 5, Object.assign(curr.chi[i], {
18476
+ typ: exports.EnumToken.IdenTokenType,
18477
+ val: 'odd'
18478
+ }));
18479
+ }
18480
+ }
18481
+ }
18482
+ }
17645
18483
  if (curr.typ == exports.EnumToken.WhitespaceTokenType) {
17646
18484
  if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
17647
18485
  trimWhiteSpace.includes(array[index + 1]?.typ) ||
@@ -17650,7 +18488,7 @@
17650
18488
  return acc;
17651
18489
  }
17652
18490
  }
17653
- if (ruleType == exports.EnumToken.KeyFrameRuleNodeType) {
18491
+ if (ruleType == exports.EnumToken.KeyFramesRuleNodeType && options.minify) {
17654
18492
  if (curr.typ == exports.EnumToken.IdenTokenType && curr.val == 'from') {
17655
18493
  Object.assign(curr, { typ: exports.EnumToken.PercentageTokenType, val: '0' });
17656
18494
  }
@@ -17689,17 +18527,24 @@
17689
18527
  value: tokens.slice()
17690
18528
  });
17691
18529
  loc = location;
17692
- if (options.sourcemap) {
17693
- node.loc = loc;
17694
- }
17695
- // @ts-ignore
18530
+ Object.defineProperty(node, 'loc', {
18531
+ ...definedPropertySettings,
18532
+ value: loc,
18533
+ enumerable: options.sourcemap !== false
18534
+ });
17696
18535
  context.chi.push(node);
17697
18536
  Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: context });
17698
18537
  // @ts-ignore
17699
- const valid = options.validation == exports.ValidationLevel.None ? {
18538
+ const skipValidate = (options.validation & exports.ValidationLevel.Selector) == 0;
18539
+ const isAllowed = skipValidate || isNodeAllowedInContext(node, context);
18540
+ // @ts-ignore
18541
+ const valid = skipValidate ? {
17700
18542
  valid: SyntaxValidationResult.Valid,
17701
18543
  error: null
17702
- } : ruleType == exports.EnumToken.KeyFrameRuleNodeType ? validateKeyframeSelector(tokens) : validateSelector(tokens, options, context);
18544
+ } : !isAllowed ? {
18545
+ valid: SyntaxValidationResult.Drop,
18546
+ error: `${exports.EnumToken[context.typ]}: child ${exports.EnumToken[node.typ]} not allowed in context${context.typ == exports.EnumToken.AtRuleNodeType ? ` '@${context.nam}'` : context.typ == exports.EnumToken.StyleSheetNodeType ? ` 'stylesheet'` : ''}`
18547
+ } : ruleType == exports.EnumToken.KeyFramesRuleNodeType ? validateKeyframeSelector(tokens) : validateSelector(tokens, options, context);
17703
18548
  if (valid.valid != SyntaxValidationResult.Valid) {
17704
18549
  // @ts-ignore
17705
18550
  node.typ = exports.EnumToken.InvalidRuleTokenType;
@@ -17808,11 +18653,13 @@
17808
18653
  nam,
17809
18654
  val: []
17810
18655
  };
17811
- if (options.sourcemap) {
17812
- node.loc = location;
17813
- node.loc.end = { ...map.get(delim).end };
17814
- }
18656
+ Object.defineProperty(node, 'loc', {
18657
+ ...definedPropertySettings,
18658
+ value: location,
18659
+ enumerable: options.sourcemap !== false
18660
+ });
17815
18661
  context.chi.push(node);
18662
+ stats.nodesCount++;
17816
18663
  }
17817
18664
  return null;
17818
18665
  }
@@ -17836,22 +18683,31 @@
17836
18683
  nam,
17837
18684
  val: value
17838
18685
  };
17839
- if (options.sourcemap) {
17840
- node.loc = location;
17841
- node.loc.end = { ...map.get(delim).end };
17842
- }
18686
+ Object.defineProperty(node, 'loc', {
18687
+ ...definedPropertySettings,
18688
+ value: location,
18689
+ enumerable: options.sourcemap !== false
18690
+ });
18691
+ node.loc.end = { ...map.get(delim).end };
17843
18692
  // do not allow declarations in style sheets
17844
18693
  if (context.typ == exports.EnumToken.StyleSheetNodeType && options.lenient) {
17845
- // @ts-ignore
17846
- node.typ = exports.EnumToken.InvalidDeclarationNodeType;
18694
+ Object.assign(node, { typ: exports.EnumToken.InvalidDeclarationNodeType });
17847
18695
  context.chi.push(node);
18696
+ stats.nodesCount++;
17848
18697
  return null;
17849
18698
  }
17850
18699
  const result = parseDeclarationNode(node, errors, location);
17851
18700
  Object.defineProperty(result, 'parent', { ...definedPropertySettings, value: context });
17852
18701
  if (result != null) {
17853
- if (options.validation == exports.ValidationLevel.All) {
17854
- const valid = evaluateSyntax(result, options);
18702
+ if (options.validation & exports.ValidationLevel.Declaration) {
18703
+ const isAllowed = isNodeAllowedInContext(node, context);
18704
+ // @ts-ignore
18705
+ const valid = !isAllowed ? {
18706
+ valid: SyntaxValidationResult.Drop,
18707
+ error: `${exports.EnumToken[node.typ]} not allowed in context${context.typ == exports.EnumToken.AtRuleNodeType ? ` '@${context.nam}'` : context.typ == exports.EnumToken.StyleSheetNodeType ? ` 'stylesheet'` : ''}`,
18708
+ node,
18709
+ syntax: null
18710
+ } : evaluateSyntax(result, context, options);
17855
18711
  Object.defineProperty(result, 'validSyntax', {
17856
18712
  ...definedPropertySettings,
17857
18713
  value: valid.valid == SyntaxValidationResult.Valid
@@ -17867,11 +18723,11 @@
17867
18723
  if (!options.lenient) {
17868
18724
  return null;
17869
18725
  }
17870
- // @ts-ignore
17871
- node.typ = exports.EnumToken.InvalidDeclarationNodeType;
18726
+ Object.assign(node, { typ: exports.EnumToken.InvalidDeclarationNodeType });
17872
18727
  }
17873
18728
  }
17874
18729
  context.chi.push(result);
18730
+ stats.nodesCount++;
17875
18731
  }
17876
18732
  return null;
17877
18733
  }
@@ -17883,7 +18739,6 @@
17883
18739
  * @param atRule
17884
18740
  */
17885
18741
  function parseAtRulePrelude(tokens, atRule) {
17886
- // @ts-ignore
17887
18742
  for (const { value, parent } of walkValues(tokens, null, null, true)) {
17888
18743
  if (value.typ == exports.EnumToken.CommentTokenType ||
17889
18744
  value.typ == exports.EnumToken.WhitespaceTokenType ||
@@ -17919,16 +18774,14 @@
17919
18774
  }
17920
18775
  if (atRule.val == 'page' && value.typ == exports.EnumToken.PseudoClassTokenType) {
17921
18776
  if ([':left', ':right', ':first', ':blank'].includes(value.val)) {
17922
- // @ts-ignore
17923
- value.typ = exports.EnumToken.PseudoPageTokenType;
18777
+ Object.assign(value, { typ: exports.EnumToken.PseudoPageTokenType });
17924
18778
  }
17925
18779
  }
17926
18780
  if (atRule.val == 'layer') {
17927
18781
  if (parent == null && value.typ == exports.EnumToken.LiteralTokenType) {
17928
18782
  if (value.val.charAt(0) == '.') {
17929
18783
  if (isIdent(value.val.slice(1))) {
17930
- // @ts-ignore
17931
- value.typ = exports.EnumToken.ClassSelectorTokenType;
18784
+ Object.assign(value, { typ: exports.EnumToken.ClassSelectorTokenType });
17932
18785
  }
17933
18786
  }
17934
18787
  }
@@ -17937,8 +18790,7 @@
17937
18790
  if (value.typ == exports.EnumToken.IdenTokenType) {
17938
18791
  if (parent == null && mediaTypes.some((t) => {
17939
18792
  if (val === t) {
17940
- // @ts-ignore
17941
- value.typ = exports.EnumToken.MediaFeatureTokenType;
18793
+ Object.assign(value, { typ: exports.EnumToken.MediaFeatureTokenType });
17942
18794
  return true;
17943
18795
  }
17944
18796
  return false;
@@ -17946,18 +18798,15 @@
17946
18798
  continue;
17947
18799
  }
17948
18800
  if (value.typ == exports.EnumToken.IdenTokenType && 'and' === val) {
17949
- // @ts-ignore
17950
- value.typ = exports.EnumToken.MediaFeatureAndTokenType;
18801
+ Object.assign(value, { typ: exports.EnumToken.MediaFeatureAndTokenType });
17951
18802
  continue;
17952
18803
  }
17953
18804
  if (value.typ == exports.EnumToken.IdenTokenType && 'or' === val) {
17954
- // @ts-ignore
17955
- value.typ = exports.EnumToken.MediaFeatureOrTokenType;
18805
+ Object.assign(value, { typ: exports.EnumToken.MediaFeatureOrTokenType });
17956
18806
  continue;
17957
18807
  }
17958
18808
  if (value.typ == exports.EnumToken.IdenTokenType &&
17959
18809
  ['not', 'only'].some((t) => val === t)) {
17960
- // @ts-ignore
17961
18810
  const array = parent?.chi ?? tokens;
17962
18811
  const startIndex = array.indexOf(value);
17963
18812
  let index = startIndex + 1;
@@ -18002,12 +18851,15 @@
18002
18851
  if (value.chi[i].typ == exports.EnumToken.CommentTokenType || value.chi[i].typ == exports.EnumToken.WhitespaceTokenType) {
18003
18852
  continue;
18004
18853
  }
18005
- if (value.chi[i].typ == exports.EnumToken.LiteralTokenType && value.chi[i].val.startsWith(':') && isDimension(value.chi[i].val.slice(1))) {
18006
- value.chi.splice(i, 1, {
18007
- typ: exports.EnumToken.ColonTokenType,
18008
- }, Object.assign(value.chi[i], parseDimension(value.chi[i].val.slice(1))));
18009
- i--;
18010
- continue;
18854
+ if (value.chi[i].typ == exports.EnumToken.LiteralTokenType && value.chi[i].val.startsWith(':')) {
18855
+ const dimension = parseDimension(value.chi[i].val.slice(1));
18856
+ if (dimension != null) {
18857
+ value.chi.splice(i, 1, {
18858
+ typ: exports.EnumToken.ColonTokenType,
18859
+ }, Object.assign(value.chi[i], dimension));
18860
+ i--;
18861
+ continue;
18862
+ }
18011
18863
  }
18012
18864
  if (nameIndex != -1 && value.chi[i].typ == exports.EnumToken.PseudoClassTokenType) {
18013
18865
  value.chi.splice(i, 1, {
@@ -18034,11 +18886,10 @@
18034
18886
  const val = value.chi.splice(valueIndex, 1)[0];
18035
18887
  const node = value.chi.splice(nameIndex, 1)[0];
18036
18888
  // 'background'
18037
- // @ts-ignore
18038
18889
  if (node.typ == exports.EnumToken.ColorTokenType && node.kin == exports.ColorType.DPSYS) {
18890
+ Object.assign(node, { typ: exports.EnumToken.IdenTokenType });
18039
18891
  // @ts-ignore
18040
18892
  delete node.kin;
18041
- node.typ = exports.EnumToken.IdenTokenType;
18042
18893
  }
18043
18894
  while (value.chi[0]?.typ == exports.EnumToken.WhitespaceTokenType) {
18044
18895
  value.chi.shift();
@@ -18075,7 +18926,7 @@
18075
18926
  position: { ind: 0, lin: 1, col: 1 },
18076
18927
  currentPosition: { ind: -1, lin: 1, col: 0 }
18077
18928
  }), { setParent: false, minify: false, validation: false }).then(result => {
18078
- return result.ast.chi[0].chi.filter(t => t.typ == exports.EnumToken.DeclarationNodeType);
18929
+ return result.ast.chi[0].chi.filter(t => t.typ == exports.EnumToken.DeclarationNodeType || t.typ == exports.EnumToken.CommentNodeType);
18079
18930
  });
18080
18931
  }
18081
18932
  /**
@@ -18093,43 +18944,35 @@
18093
18944
  }
18094
18945
  if (parent == null) {
18095
18946
  if (value.typ == exports.EnumToken.GtTokenType) {
18096
- // @ts-ignore
18097
- value.typ = exports.EnumToken.ChildCombinatorTokenType;
18947
+ Object.assign(value, { typ: exports.EnumToken.ChildCombinatorTokenType });
18098
18948
  }
18099
18949
  else if (value.typ == exports.EnumToken.LiteralTokenType) {
18100
18950
  if (value.val.charAt(0) == '&') {
18101
- // @ts-ignore
18102
- value.typ = exports.EnumToken.NestingSelectorTokenType;
18951
+ Object.assign(value, { typ: exports.EnumToken.NestingSelectorTokenType });
18103
18952
  // @ts-ignore
18104
18953
  delete value.val;
18105
18954
  }
18106
18955
  else if (value.val.charAt(0) == '.') {
18107
18956
  if (!isIdent(value.val.slice(1))) {
18108
- // @ts-ignore
18109
- value.typ = exports.EnumToken.InvalidClassSelectorTokenType;
18957
+ Object.assign(value, { typ: exports.EnumToken.InvalidClassSelectorTokenType });
18110
18958
  }
18111
18959
  else {
18112
- // @ts-ignore
18113
- value.typ = exports.EnumToken.ClassSelectorTokenType;
18960
+ Object.assign(value, { typ: exports.EnumToken.ClassSelectorTokenType });
18114
18961
  }
18115
18962
  }
18116
18963
  if (['*', '>', '+', '~'].includes(value.val)) {
18117
18964
  switch (value.val) {
18118
18965
  case '*':
18119
- // @ts-ignore
18120
- value.typ = exports.EnumToken.UniversalSelectorTokenType;
18966
+ Object.assign(value, { typ: exports.EnumToken.UniversalSelectorTokenType });
18121
18967
  break;
18122
18968
  case '>':
18123
- // @ts-ignore
18124
- value.typ = exports.EnumToken.ChildCombinatorTokenType;
18969
+ Object.assign(value, { typ: exports.EnumToken.ChildCombinatorTokenType });
18125
18970
  break;
18126
18971
  case '+':
18127
- // @ts-ignore
18128
- value.typ = exports.EnumToken.NextSiblingCombinatorTokenType;
18972
+ Object.assign(value, { typ: exports.EnumToken.NextSiblingCombinatorTokenType });
18129
18973
  break;
18130
18974
  case '~':
18131
- // @ts-ignore
18132
- value.typ = exports.EnumToken.SubsequentSiblingCombinatorTokenType;
18975
+ Object.assign(value, { typ: exports.EnumToken.SubsequentSiblingCombinatorTokenType });
18133
18976
  break;
18134
18977
  }
18135
18978
  // @ts-ignore
@@ -18142,12 +18985,10 @@
18142
18985
  if (!isIdent(value.val.slice(1))) {
18143
18986
  continue;
18144
18987
  }
18145
- // @ts-ignore
18146
- value.typ = exports.EnumToken.HashTokenType;
18988
+ Object.assign(value, { typ: exports.EnumToken.HashTokenType });
18147
18989
  }
18148
18990
  else {
18149
- // @ts-ignore
18150
- value.typ = exports.EnumToken.IdenTokenType;
18991
+ Object.assign(value, { typ: exports.EnumToken.IdenTokenType });
18151
18992
  }
18152
18993
  // @ts-ignore
18153
18994
  delete value.kin;
@@ -18210,15 +19051,17 @@
18210
19051
  return acc;
18211
19052
  }
18212
19053
  const token = getTokenType(t.token, t.hint);
18213
- if (options.location) {
18214
- Object.assign(token, { loc: t.sta });
18215
- }
19054
+ Object.defineProperty(token, 'loc', {
19055
+ ...definedPropertySettings,
19056
+ value: { sta: t.sta },
19057
+ enumerable: options.location !== false
19058
+ });
18216
19059
  acc.push(token);
18217
19060
  return acc;
18218
19061
  }, []));
18219
19062
  }
18220
19063
  /**
18221
- * get token type from a string
19064
+ * get the token type from a string
18222
19065
  * @param val
18223
19066
  * @param hint
18224
19067
  */
@@ -18254,7 +19097,7 @@
18254
19097
  case '>':
18255
19098
  return { typ: exports.EnumToken.GtTokenType };
18256
19099
  }
18257
- if (isPseudo(val)) {
19100
+ if (val.charAt(0) == ':' && isPseudo(val)) {
18258
19101
  return val.endsWith('(') ? {
18259
19102
  typ: exports.EnumToken.PseudoClassFuncTokenType,
18260
19103
  val: val.slice(0, -1),
@@ -18271,13 +19114,13 @@
18271
19114
  val
18272
19115
  });
18273
19116
  }
18274
- if (isAtKeyword(val)) {
19117
+ if (val.charAt(0) == '@' && isAtKeyword(val)) {
18275
19118
  return {
18276
19119
  typ: exports.EnumToken.AtRuleTokenType,
18277
19120
  val: val.slice(1)
18278
19121
  };
18279
19122
  }
18280
- if (isFunction(val)) {
19123
+ if (val.endsWith('(') && isFunction(val)) {
18281
19124
  val = val.slice(0, -1);
18282
19125
  if (val == 'url') {
18283
19126
  return {
@@ -18325,15 +19168,12 @@
18325
19168
  val: +val.slice(0, -1)
18326
19169
  };
18327
19170
  }
18328
- if (isFlex(val)) {
18329
- return {
18330
- typ: exports.EnumToken.FlexTokenType,
18331
- val: +val.slice(0, -2)
18332
- };
18333
- }
18334
- if (isDimension(val)) {
18335
- return parseDimension(val);
19171
+ // if (isDimension(val)) {
19172
+ const dimension = parseDimension(val);
19173
+ if (dimension != null) {
19174
+ return dimension;
18336
19175
  }
19176
+ // }
18337
19177
  const v = val.toLowerCase();
18338
19178
  if (v == 'currentcolor' || v == 'transparent' || v in COLORS_NAMES) {
18339
19179
  return {
@@ -18728,64 +19568,142 @@
18728
19568
  return true;
18729
19569
  }
18730
19570
 
19571
+ /**
19572
+ * options for the walk function
19573
+ */
18731
19574
  exports.WalkerOptionEnum = void 0;
18732
19575
  (function (WalkerOptionEnum) {
18733
19576
  /**
18734
19577
  * ignore the current node and its children
18735
19578
  */
18736
- WalkerOptionEnum[WalkerOptionEnum["Ignore"] = 0] = "Ignore";
19579
+ WalkerOptionEnum[WalkerOptionEnum["Ignore"] = 1] = "Ignore";
18737
19580
  /**
18738
19581
  * stop walking the tree
18739
19582
  */
18740
- WalkerOptionEnum[WalkerOptionEnum["Stop"] = 1] = "Stop";
19583
+ WalkerOptionEnum[WalkerOptionEnum["Stop"] = 2] = "Stop";
18741
19584
  /**
18742
- * ignore node and process children
19585
+ * ignore the current node and process its children
18743
19586
  */
18744
- WalkerOptionEnum[WalkerOptionEnum["Children"] = 2] = "Children";
19587
+ WalkerOptionEnum[WalkerOptionEnum["Children"] = 4] = "Children";
18745
19588
  /**
18746
- * ignore children
19589
+ * ignore the current node children
18747
19590
  */
18748
- WalkerOptionEnum[WalkerOptionEnum["IgnoreChildren"] = 3] = "IgnoreChildren";
19591
+ WalkerOptionEnum[WalkerOptionEnum["IgnoreChildren"] = 8] = "IgnoreChildren";
18749
19592
  })(exports.WalkerOptionEnum || (exports.WalkerOptionEnum = {}));
18750
- exports.WalkerValueEvent = void 0;
18751
- (function (WalkerValueEvent) {
19593
+ /**
19594
+ * event types for the walkValues function
19595
+ */
19596
+ exports.WalkerEvent = void 0;
19597
+ (function (WalkerEvent) {
18752
19598
  /**
18753
19599
  * enter node
18754
19600
  */
18755
- WalkerValueEvent[WalkerValueEvent["Enter"] = 0] = "Enter";
19601
+ WalkerEvent[WalkerEvent["Enter"] = 1] = "Enter";
18756
19602
  /**
18757
19603
  * leave node
18758
19604
  */
18759
- WalkerValueEvent[WalkerValueEvent["Leave"] = 1] = "Leave";
18760
- })(exports.WalkerValueEvent || (exports.WalkerValueEvent = {}));
19605
+ WalkerEvent[WalkerEvent["Leave"] = 2] = "Leave";
19606
+ })(exports.WalkerEvent || (exports.WalkerEvent = {}));
18761
19607
  /**
18762
19608
  * walk ast nodes
18763
- * @param node
18764
- * @param filter
19609
+ * @param node initial node
19610
+ * @param filter control the walk process
19611
+ * @param reverse walk in reverse order
19612
+ *
19613
+ * ```ts
19614
+ *
19615
+ * import {walk} from '@tbela99/css-parser';
19616
+ *
19617
+ * const css = `
19618
+ * body { color: color(from var(--base-color) display-p3 r calc(g + 0.24) calc(b + 0.15)); }
19619
+ *
19620
+ * html,
19621
+ * body {
19622
+ * line-height: 1.474;
19623
+ * }
19624
+ *
19625
+ * .ruler {
19626
+ *
19627
+ * height: 10px;
19628
+ * }
19629
+ * `;
19630
+ *
19631
+ * for (const {node, parent, root} of walk(ast)) {
19632
+ *
19633
+ * // do something with node
19634
+ * }
19635
+ * ```
19636
+ *
19637
+ * Using a {@link filter} function to control the ast traversal. the filter function returns a value of type {@link WalkerOption}.
19638
+ *
19639
+ * ```ts
19640
+ * import {EnumToken, transform, walk, WalkerOptionEnum} from '@tbela99/css-parser';
19641
+ *
19642
+ * const css = `
19643
+ * body { color: color(from var(--base-color) display-p3 r calc(g + 0.24) calc(b + 0.15)); }
19644
+ *
19645
+ * html,
19646
+ * body {
19647
+ * line-height: 1.474;
19648
+ * }
19649
+ *
19650
+ * .ruler {
19651
+ *
19652
+ * height: 10px;
19653
+ * }
19654
+ * `;
19655
+ *
19656
+ * function filter(node) {
19657
+ *
19658
+ * if (node.typ == EnumToken.AstRule && node.sel.includes('html')) {
19659
+ *
19660
+ * // skip the children of the current node
19661
+ * return WalkerOptionEnum.IgnoreChildren;
19662
+ * }
19663
+ * }
19664
+ *
19665
+ * const result = await transform(css);
19666
+ * for (const {node} of walk(result.ast, filter)) {
19667
+ *
19668
+ * console.error([EnumToken[node.typ]]);
19669
+ * }
19670
+ *
19671
+ * // [ "StyleSheetNodeType" ]
19672
+ * // [ "RuleNodeType" ]
19673
+ * // [ "DeclarationNodeType" ]
19674
+ * // [ "RuleNodeType" ]
19675
+ * // [ "DeclarationNodeType" ]
19676
+ * // [ "RuleNodeType" ]
19677
+ * // [ "DeclarationNodeType" ]
19678
+ * ```
18765
19679
  */
18766
- function* walk(node, filter) {
19680
+ function* walk(node, filter, reverse) {
18767
19681
  const parents = [node];
18768
19682
  const root = node;
18769
19683
  const map = new Map;
18770
- while ((node = parents.shift())) {
19684
+ let isNumeric = false;
19685
+ let i = 0;
19686
+ while ((node = parents[i++])) {
18771
19687
  let option = null;
18772
19688
  if (filter != null) {
18773
19689
  option = filter(node);
18774
- if (option === exports.WalkerOptionEnum.Ignore) {
18775
- continue;
18776
- }
18777
- if (option === exports.WalkerOptionEnum.Stop) {
18778
- break;
19690
+ isNumeric = typeof option == 'number';
19691
+ if (isNumeric) {
19692
+ if ((option & exports.WalkerOptionEnum.Ignore)) {
19693
+ continue;
19694
+ }
19695
+ if ((option & exports.WalkerOptionEnum.Stop)) {
19696
+ break;
19697
+ }
18779
19698
  }
18780
19699
  }
18781
- // @ts-ignore
18782
- if (option !== 'children') {
19700
+ if (!isNumeric || (option & exports.WalkerOptionEnum.Children) === 0) {
18783
19701
  // @ts-ignore
18784
19702
  yield { node, parent: map.get(node), root };
18785
19703
  }
18786
- if (option !== exports.WalkerOptionEnum.IgnoreChildren && 'chi' in node) {
18787
- parents.unshift(...node.chi);
18788
- for (const child of node.chi.slice()) {
19704
+ if ('chi' in node && (!isNumeric || ((option & exports.WalkerOptionEnum.IgnoreChildren) === 0))) {
19705
+ parents.splice(i, 0, ...node.chi[reverse ? 'reverse' : 'slice']());
19706
+ for (const child of node.chi) {
18789
19707
  map.set(child, node);
18790
19708
  }
18791
19709
  }
@@ -18797,39 +19715,80 @@
18797
19715
  * @param root
18798
19716
  * @param filter
18799
19717
  * @param reverse
19718
+ *
19719
+ * Example:
19720
+ *
19721
+ * ```ts
19722
+ *
19723
+ * import {AstDeclaration, EnumToken, transform, walkValues} from '@tbela99/css-parser';
19724
+ *
19725
+ * const css = `
19726
+ * body { color: color(from var(--base-color) display-p3 r calc(g + 0.24) calc(b + 0.15)); }
19727
+ * `;
19728
+ *
19729
+ * const result = await transform(css);
19730
+ * const declaration = result.ast.chi[0].chi[0] as AstDeclaration;
19731
+ *
19732
+ * // walk the node attribute's tokens in reverse order
19733
+ * for (const {value} of walkValues(declaration.val, null, null,true)) {
19734
+ *
19735
+ * console.error([EnumToken[value.typ], value.val]);
19736
+ * }
19737
+ *
19738
+ * // [ "Color", "color" ]
19739
+ * // [ "FunctionTokenType", "calc" ]
19740
+ * // [ "Number", 0.15 ]
19741
+ * // [ "Add", undefined ]
19742
+ * // [ "Iden", "b" ]
19743
+ * // [ "Whitespace", undefined ]
19744
+ * // [ "FunctionTokenType", "calc" ]
19745
+ * // [ "Number", 0.24 ]
19746
+ * // [ "Add", undefined ]
19747
+ * // [ "Iden", "g" ]
19748
+ * // [ "Whitespace", undefined ]
19749
+ * // [ "Iden", "r" ]
19750
+ * // [ "Whitespace", undefined ]
19751
+ * // [ "Iden", "display-p3" ]
19752
+ * // [ "Whitespace", undefined ]
19753
+ * // [ "FunctionTokenType", "var" ]
19754
+ * // [ "DashedIden", "--base-color" ]
19755
+ * // [ "Whitespace", undefined ]
19756
+ * // [ "Iden", "from" ]
19757
+ * ```
18800
19758
  */
18801
19759
  function* walkValues(values, root = null, filter, reverse) {
18802
19760
  // const set = new Set<Token>();
18803
19761
  const stack = values.slice();
18804
19762
  const map = new Map;
18805
19763
  let previous = null;
18806
- // let parent: FunctionToken | ParensToken | BinaryExpressionToken | null = null;
18807
19764
  if (filter != null && typeof filter == 'function') {
18808
19765
  filter = {
18809
- event: exports.WalkerValueEvent.Enter,
19766
+ event: exports.WalkerEvent.Enter,
18810
19767
  fn: filter
18811
19768
  };
18812
19769
  }
18813
19770
  else if (filter == null) {
18814
19771
  filter = {
18815
- event: exports.WalkerValueEvent.Enter
19772
+ event: exports.WalkerEvent.Enter
18816
19773
  };
18817
19774
  }
18818
- const eventType = filter.event ?? exports.WalkerValueEvent.Enter;
19775
+ let isNumeric = false;
19776
+ const eventType = filter.event ?? exports.WalkerEvent.Enter;
18819
19777
  while (stack.length > 0) {
18820
19778
  let value = reverse ? stack.pop() : stack.shift();
18821
19779
  let option = null;
18822
- if (filter.fn != null && eventType == exports.WalkerValueEvent.Enter) {
19780
+ if (filter.fn != null && (eventType & exports.WalkerEvent.Enter)) {
18823
19781
  const isValid = filter.type == null || value.typ == filter.type ||
18824
19782
  (Array.isArray(filter.type) && filter.type.includes(value.typ)) ||
18825
19783
  (typeof filter.type == 'function' && filter.type(value));
18826
19784
  if (isValid) {
18827
- option = filter.fn(value, map.get(value) ?? root);
18828
- if (option === exports.WalkerOptionEnum.Ignore) {
18829
- continue;
19785
+ option = filter.fn(value, map.get(value) ?? root, exports.WalkerEvent.Enter);
19786
+ isNumeric = typeof option == 'number';
19787
+ if (isNumeric && (option & exports.WalkerOptionEnum.Stop)) {
19788
+ return;
18830
19789
  }
18831
- if (option === exports.WalkerOptionEnum.Stop) {
18832
- break;
19790
+ if (isNumeric && (option & exports.WalkerOptionEnum.Ignore)) {
19791
+ continue;
18833
19792
  }
18834
19793
  // @ts-ignore
18835
19794
  if (option != null && typeof option == 'object' && 'typ' in option) {
@@ -18837,38 +19796,31 @@
18837
19796
  }
18838
19797
  }
18839
19798
  }
18840
- if (eventType == exports.WalkerValueEvent.Enter && option !== exports.WalkerOptionEnum.Children) {
18841
- yield {
18842
- value,
18843
- parent: map.get(value) ?? root,
18844
- previousValue: previous,
18845
- nextValue: stack[0] ?? null,
18846
- // @ts-ignore
18847
- root: root ?? null
18848
- };
18849
- }
18850
- if (option !== exports.WalkerOptionEnum.IgnoreChildren && 'chi' in value) {
19799
+ yield {
19800
+ value,
19801
+ parent: map.get(value) ?? root,
19802
+ previousValue: previous,
19803
+ nextValue: stack[0] ?? null,
19804
+ // @ts-ignore
19805
+ root: root ?? null
19806
+ };
19807
+ if ('chi' in value && (!isNumeric || (option & exports.WalkerOptionEnum.IgnoreChildren) === 0)) {
18851
19808
  const sliced = value.chi.slice();
18852
19809
  for (const child of sliced) {
18853
19810
  map.set(child, value);
18854
19811
  }
18855
- if (reverse) {
18856
- stack.push(...sliced);
18857
- }
18858
- else {
18859
- stack.unshift(...sliced);
18860
- }
19812
+ stack[reverse ? 'push' : 'unshift'](...sliced);
18861
19813
  }
18862
19814
  else {
18863
19815
  const values = [];
18864
19816
  if ('l' in value && value.l != null) {
18865
19817
  // @ts-ignore
18866
- values.push(value.l);
19818
+ values[reverse ? 'push' : 'unshift'](value.l);
18867
19819
  // @ts-ignore
18868
19820
  map.set(value.l, value);
18869
19821
  }
18870
19822
  if ('op' in value && typeof value.op == 'object') {
18871
- values.push(value.op);
19823
+ values[reverse ? 'push' : 'unshift'](value.op);
18872
19824
  // @ts-ignore
18873
19825
  map.set(value.op, value);
18874
19826
  }
@@ -18876,48 +19828,55 @@
18876
19828
  if (Array.isArray(value.r)) {
18877
19829
  for (const r of value.r) {
18878
19830
  // @ts-ignore
18879
- values.push(r);
19831
+ values[reverse ? 'push' : 'unshift'](r);
18880
19832
  // @ts-ignore
18881
19833
  map.set(r, value);
18882
19834
  }
18883
19835
  }
18884
19836
  else {
18885
19837
  // @ts-ignore
18886
- values.push(value.r);
19838
+ values[reverse ? 'push' : 'unshift'](value.r);
18887
19839
  // @ts-ignore
18888
19840
  map.set(value.r, value);
18889
19841
  }
18890
19842
  }
18891
19843
  if (values.length > 0) {
18892
- stack.unshift(...values);
19844
+ stack[reverse ? 'push' : 'unshift'](...values);
18893
19845
  }
18894
19846
  }
18895
- if (eventType == exports.WalkerValueEvent.Leave && filter.fn != null) {
19847
+ if ((eventType & exports.WalkerEvent.Leave) && filter.fn != null) {
18896
19848
  const isValid = filter.type == null || value.typ == filter.type ||
18897
19849
  (Array.isArray(filter.type) && filter.type.includes(value.typ)) ||
18898
19850
  (typeof filter.type == 'function' && filter.type(value));
18899
19851
  if (isValid) {
18900
- option = filter.fn(value, map.get(value));
19852
+ option = filter.fn(value, map.get(value), exports.WalkerEvent.Leave);
18901
19853
  // @ts-ignore
18902
19854
  if (option != null && 'typ' in option) {
18903
19855
  map.set(option, map.get(value) ?? root);
18904
19856
  }
18905
19857
  }
18906
19858
  }
18907
- if (eventType == exports.WalkerValueEvent.Leave && option !== exports.WalkerOptionEnum.Children) {
18908
- yield {
18909
- value,
18910
- parent: map.get(value) ?? root,
18911
- previousValue: previous,
18912
- nextValue: stack[0] ?? null,
18913
- // @ts-ignore
18914
- root: root ?? null
18915
- };
18916
- }
18917
19859
  previous = value;
18918
19860
  }
18919
19861
  }
18920
19862
 
19863
+ /**
19864
+ * feature walk mode
19865
+ *
19866
+ * @internal
19867
+ */
19868
+ exports.FeatureWalkMode = void 0;
19869
+ (function (FeatureWalkMode) {
19870
+ /**
19871
+ * pre process
19872
+ */
19873
+ FeatureWalkMode[FeatureWalkMode["Pre"] = 1] = "Pre";
19874
+ /**
19875
+ * post process
19876
+ */
19877
+ FeatureWalkMode[FeatureWalkMode["Post"] = 2] = "Post";
19878
+ })(exports.FeatureWalkMode || (exports.FeatureWalkMode = {}));
19879
+
18921
19880
  const config$1 = getSyntaxConfig();
18922
19881
  function replacePseudo(tokens) {
18923
19882
  return tokens.map((raw) => raw.map(r => {
@@ -18963,11 +19922,8 @@
18963
19922
  get ordering() {
18964
19923
  return 2;
18965
19924
  }
18966
- get preProcess() {
18967
- return true;
18968
- }
18969
- get postProcess() {
18970
- return false;
19925
+ get processMode() {
19926
+ return exports.FeatureWalkMode.Pre;
18971
19927
  }
18972
19928
  static register(options) {
18973
19929
  if (options.removePrefix) {
@@ -19027,12 +19983,13 @@
19027
19983
  }
19028
19984
  }
19029
19985
  }
19986
+ // @ts-ignore
19030
19987
  if (SyntaxValidationResult.Valid == evaluateSyntax({ ...node, val: nodes }, {}).valid) {
19031
19988
  node.val = nodes;
19032
19989
  }
19033
19990
  }
19034
19991
  }
19035
- else if (node.typ == exports.EnumToken.AtRuleNodeType || node.typ == exports.EnumToken.KeyframeAtRuleNodeType) {
19992
+ else if (node.typ == exports.EnumToken.AtRuleNodeType || node.typ == exports.EnumToken.KeyframesAtRuleNodeType) {
19036
19993
  if (node.nam.startsWith('-')) {
19037
19994
  const match = node.nam.match(/^-([^-]+)-(.+)$/);
19038
19995
  if (match != null && '@' + match[2] in config$1.atRules) {
@@ -19040,14 +19997,6 @@
19040
19997
  }
19041
19998
  }
19042
19999
  if (node.typ == exports.EnumToken.AtRuleNodeType && node.val !== '') {
19043
- // if ((node as AstAtRule).tokens == null) {
19044
- //
19045
- // Object.defineProperty(node, 'tokens', {
19046
- // // @ts-ignore
19047
- // ...definedPropertySettings,
19048
- // value: parseAtRulePrelude(parseString((node as AstAtRule).val), node as AstAtRule),
19049
- // })
19050
- // }
19051
20000
  if (replaceAstNodes(node.tokens)) {
19052
20001
  node.val = node.tokens.reduce((acc, curr) => acc + renderToken(curr), '');
19053
20002
  }
@@ -19100,14 +20049,12 @@
19100
20049
  }
19101
20050
  }
19102
20051
  class InlineCssVariablesFeature {
20052
+ accept = new Set([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType]);
19103
20053
  get ordering() {
19104
20054
  return 0;
19105
20055
  }
19106
- get preProcess() {
19107
- return true;
19108
- }
19109
- get postProcess() {
19110
- return false;
20056
+ get processMode() {
20057
+ return exports.FeatureWalkMode.Pre;
19111
20058
  }
19112
20059
  static register(options) {
19113
20060
  if (options.inlineCssVariables) {
@@ -19116,9 +20063,10 @@
19116
20063
  }
19117
20064
  }
19118
20065
  run(ast, options = {}, parent, context) {
19119
- if (!('chi' in ast)) {
19120
- return;
19121
- }
20066
+ // if (!('chi' in ast)) {
20067
+ //
20068
+ // return null;
20069
+ // }
19122
20070
  if (!('variableScope' in context)) {
19123
20071
  context.variableScope = new Map;
19124
20072
  }
@@ -19160,6 +20108,7 @@
19160
20108
  replace(node, variableScope);
19161
20109
  }
19162
20110
  }
20111
+ return null;
19163
20112
  }
19164
20113
  cleanup(ast, options = {}, context) {
19165
20114
  const variableScope = context.variableScope;
@@ -19999,7 +20948,9 @@
19999
20948
  }
20000
20949
  add(...declarations) {
20001
20950
  for (const declaration of declarations) {
20002
- if (declaration.typ != exports.EnumToken.DeclarationNodeType || !this.options.removeDuplicateDeclarations) {
20951
+ if (declaration.typ != exports.EnumToken.DeclarationNodeType ||
20952
+ (typeof this.options.removeDuplicateDeclarations === 'string' && this.options.removeDuplicateDeclarations === declaration.nam.toLowerCase()) ||
20953
+ (Array.isArray(this.options.removeDuplicateDeclarations) ? this.options.removeDuplicateDeclarations.includes(declaration.nam) : !this.options.removeDuplicateDeclarations)) {
20003
20954
  this.declarations.set(Number(Math.random().toString().slice(2)).toString(36), declaration);
20004
20955
  continue;
20005
20956
  }
@@ -20084,14 +21035,12 @@
20084
21035
  }
20085
21036
 
20086
21037
  class ComputeShorthandFeature {
21038
+ accept = new Set([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType, exports.EnumToken.KeyFramesRuleNodeType]);
20087
21039
  get ordering() {
20088
21040
  return 3;
20089
21041
  }
20090
- get preProcess() {
20091
- return false;
20092
- }
20093
- get postProcess() {
20094
- return true;
21042
+ get processMode() {
21043
+ return exports.FeatureWalkMode.Post;
20095
21044
  }
20096
21045
  static register(options) {
20097
21046
  if (options.computeShorthand) {
@@ -20101,7 +21050,7 @@
20101
21050
  }
20102
21051
  run(ast, options = {}, parent, context) {
20103
21052
  if (!('chi' in ast)) {
20104
- return ast;
21053
+ return null;
20105
21054
  }
20106
21055
  // @ts-ignore
20107
21056
  const j = ast.chi.length;
@@ -20139,14 +21088,12 @@
20139
21088
  }
20140
21089
 
20141
21090
  class ComputeCalcExpressionFeature {
21091
+ accept = new Set([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType]);
20142
21092
  get ordering() {
20143
21093
  return 1;
20144
21094
  }
20145
- get preProcess() {
20146
- return false;
20147
- }
20148
- get postProcess() {
20149
- return true;
21095
+ get processMode() {
21096
+ return exports.FeatureWalkMode.Post;
20150
21097
  }
20151
21098
  static register(options) {
20152
21099
  if (options.computeCalcExpression) {
@@ -20156,7 +21103,7 @@
20156
21103
  }
20157
21104
  run(ast) {
20158
21105
  if (!('chi' in ast)) {
20159
- return;
21106
+ return null;
20160
21107
  }
20161
21108
  for (const node of ast.chi) {
20162
21109
  if (node.typ != exports.EnumToken.DeclarationNodeType) {
@@ -20164,7 +21111,7 @@
20164
21111
  }
20165
21112
  const set = new Set;
20166
21113
  for (const { value, parent } of walkValues(node.val, node, {
20167
- event: exports.WalkerValueEvent.Enter,
21114
+ event: exports.WalkerEvent.Enter,
20168
21115
  // @ts-ignore
20169
21116
  fn(node, parent) {
20170
21117
  if (parent != null &&
@@ -20217,279 +21164,31 @@
20217
21164
  break;
20218
21165
  }
20219
21166
  }
20220
- }
20221
- else {
20222
- for (let i = 0; i < children.length; i++) {
20223
- if (children[i] == value) {
20224
- children.splice(i, 1, {
20225
- typ: exports.EnumToken.FunctionTokenType,
20226
- val: 'calc',
20227
- chi: values
20228
- });
20229
- break;
20230
- }
20231
- }
20232
- }
20233
- }
20234
- }
20235
- }
20236
- }
20237
- }
20238
- }
20239
- }
20240
-
20241
- const epsilon = 1e-5;
20242
- function identity() {
20243
- return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
20244
- }
20245
- function pLength(point) {
20246
- return Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
20247
- }
20248
- function normalize(point) {
20249
- const [x, y, z] = point;
20250
- const norm = Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
20251
- return norm === 0 ? [0, 0, 0] : [x / norm, y / norm, z / norm];
20252
- }
20253
- function dot(point1, point2) {
20254
- if (point1.length === 4 && point2.length === 4) {
20255
- return point1[0] * point2[0] + point1[1] * point2[1] + point1[2] * point2[2] + point1[3] * point2[3];
20256
- }
20257
- return point1[0] * point2[0] + point1[1] * point2[1] + point1[2] * point2[2];
20258
- }
20259
- function multiply(matrixA, matrixB) {
20260
- let result = new Array(16).fill(0);
20261
- for (let i = 0; i < 4; i++) {
20262
- for (let j = 0; j < 4; j++) {
20263
- for (let k = 0; k < 4; k++) {
20264
- // Utiliser l'indexation linéaire pour accéder aux éléments
20265
- // Pour une matrice 4x4, l'index est (row * 4 + col)
20266
- result[j * 4 + i] += matrixA[k * 4 + i] * matrixB[j * 4 + k];
20267
- }
20268
- }
20269
- }
20270
- return result;
20271
- }
20272
- function inverse(matrix) {
20273
- // Create augmented matrix [matrix | identity]
20274
- let augmented = [
20275
- 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
20276
- 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
20277
- ];
20278
- // Gaussian elimination with partial pivoting
20279
- for (let col = 0; col < 4; col++) {
20280
- // Find pivot row with maximum absolute value
20281
- let maxRow = col;
20282
- let maxVal = Math.abs(augmented[col * 4 + col]);
20283
- for (let row = col + 1; row < 4; row++) {
20284
- let val = Math.abs(augmented[row * 4 + col]);
20285
- if (val > maxVal) {
20286
- maxVal = val;
20287
- maxRow = row;
20288
- }
20289
- }
20290
- // Check for singularity
20291
- if (maxVal < 1e-5) {
20292
- return null;
20293
- }
20294
- // Swap rows if necessary
20295
- if (maxRow !== col) {
20296
- [augmented[col], augmented[maxRow]] = [augmented[maxRow], augmented[col]];
20297
- }
20298
- // Scale pivot row to make pivot element 1
20299
- let pivot = augmented[col * 4 + col];
20300
- for (let j = 0; j < 8; j++) {
20301
- augmented[col * 4 + j] /= pivot;
20302
- }
20303
- // Eliminate column in other rows
20304
- for (let row = 0; row < 4; row++) {
20305
- if (row !== col) {
20306
- let factor = augmented[row * 4 + col];
20307
- for (let j = 0; j < 8; j++) {
20308
- augmented[row * 4 + j] -= factor * augmented[col * 4 + j];
20309
- }
20310
- }
20311
- }
20312
- }
20313
- // Extract the inverse from the right side of the augmented matrix
20314
- return augmented.slice(0, 16);
20315
- }
20316
- // function transpose(matrix: Matrix): Matrix {
20317
- // // Crée une nouvelle matrice vide 4x4
20318
- // // @ts-ignore
20319
- // let transposed: Matrix = [[], [], [], []] as Matrix;
20320
- //
20321
- // // Parcourt chaque ligne et colonne pour transposer
20322
- // for (let i = 0; i < 4; i++) {
20323
- //
20324
- // for (let j = 0; j < 4; j++) {
20325
- //
20326
- // transposed[j][i] = matrix[i][j];
20327
- // }
20328
- // }
20329
- //
20330
- // return transposed;
20331
- // }
20332
- function round(number) {
20333
- return Math.abs(number) < epsilon ? 0 : +number.toPrecision(6);
20334
- }
20335
- // translate3d(25.9808px, 0, 15px ) rotateY(60deg) skewX(49.9999deg) scale(1, 1.2)
20336
- // translate → rotate → skew → scale
20337
- function decompose(original) {
20338
- const matrix = original.slice();
20339
- // Normalize last row
20340
- if (matrix[15] === 0) {
20341
- return null;
20342
- }
20343
- for (let i = 0; i < 16; i++)
20344
- matrix[i] /= matrix[15];
20345
- // Perspective extraction
20346
- const perspective = [0, 0, 0, 1];
20347
- if (matrix[3] !== 0 || matrix[7] !== 0 || matrix[11] !== 0) {
20348
- const rightHandSide = [matrix[3], matrix[7], matrix[11], matrix[15]];
20349
- const perspectiveMatrix = matrix.slice();
20350
- perspectiveMatrix[3] = 0;
20351
- perspectiveMatrix[7] = 0;
20352
- perspectiveMatrix[11] = 0;
20353
- perspectiveMatrix[15] = 1;
20354
- // @ts-ignore
20355
- const inverted = inverse(original.slice());
20356
- if (!inverted) {
20357
- return null;
20358
- }
20359
- const transposedInverse = transposeMatrix4(inverted);
20360
- perspective[0] = dot(rightHandSide, transposedInverse.slice(0, 4));
20361
- perspective[1] = dot(rightHandSide, transposedInverse.slice(4, 8));
20362
- perspective[2] = dot(rightHandSide, transposedInverse.slice(8, 12));
20363
- perspective[3] = dot(rightHandSide, transposedInverse.slice(12, 16));
20364
- // Clear perspective from matrix
20365
- matrix[3] = 0;
20366
- matrix[7] = 0;
20367
- matrix[11] = 0;
20368
- matrix[15] = 1;
20369
- }
20370
- // Translation
20371
- const translate = [matrix[12], matrix[13], matrix[14]];
20372
- matrix[12] = matrix[13] = matrix[14] = 0;
20373
- // Build the 3x3 matrix
20374
- const row0 = [matrix[0], matrix[1], matrix[2]];
20375
- const row1 = [matrix[4], matrix[5], matrix[6]];
20376
- const row2 = [matrix[8], matrix[9], matrix[10]];
20377
- // Compute scale
20378
- const scaleX = pLength(row0);
20379
- const row0Norm = normalize(row0);
20380
- const skewXY = dot(row0Norm, row1);
20381
- const row1Proj = [
20382
- row1[0] - skewXY * row0Norm[0],
20383
- row1[1] - skewXY * row0Norm[1],
20384
- row1[2] - skewXY * row0Norm[2]
20385
- ];
20386
- const scaleY = pLength(row1Proj);
20387
- const row1Norm = normalize(row1Proj);
20388
- const skewXZ = dot(row0Norm, row2);
20389
- const skewYZ = dot(row1Norm, row2);
20390
- const row2Proj = [
20391
- row2[0] - skewXZ * row0Norm[0] - skewYZ * row1Norm[0],
20392
- row2[1] - skewXZ * row0Norm[1] - skewYZ * row1Norm[1],
20393
- row2[2] - skewXZ * row0Norm[2] - skewYZ * row1Norm[2]
20394
- ];
20395
- const scaleZ = pLength(row2Proj);
20396
- const row2Norm = normalize(row2Proj);
20397
- // Build rotation matrix from orthonormalized vectors
20398
- const r00 = row0Norm[0], r01 = row1Norm[0], r02 = row2Norm[0];
20399
- const r10 = row0Norm[1], r11 = row1Norm[1], r12 = row2Norm[1];
20400
- const r20 = row0Norm[2], r21 = row1Norm[2], r22 = row2Norm[2];
20401
- // Convert to quaternion
20402
- const trace = r00 + r11 + r22;
20403
- let qw, qx, qy, qz;
20404
- if (trace > 0) {
20405
- const s = 0.5 / Math.sqrt(trace + 1.0);
20406
- qw = 0.25 / s;
20407
- qx = (r21 - r12) * s;
20408
- qy = (r02 - r20) * s;
20409
- qz = (r10 - r01) * s;
20410
- }
20411
- else if (r00 > r11 && r00 > r22) {
20412
- const s = 2.0 * Math.sqrt(1.0 + r00 - r11 - r22);
20413
- qw = (r21 - r12) / s;
20414
- qx = 0.25 * s;
20415
- qy = (r01 + r10) / s;
20416
- qz = (r02 + r20) / s;
20417
- }
20418
- else if (r11 > r22) {
20419
- const s = 2.0 * Math.sqrt(1.0 + r11 - r00 - r22);
20420
- qw = (r02 - r20) / s;
20421
- qx = (r01 + r10) / s;
20422
- qy = 0.25 * s;
20423
- qz = (r12 + r21) / s;
20424
- }
20425
- else {
20426
- const s = 2.0 * Math.sqrt(1.0 + r22 - r00 - r11);
20427
- qw = (r10 - r01) / s;
20428
- qx = (r02 + r20) / s;
20429
- qy = (r12 + r21) / s;
20430
- qz = 0.25 * s;
20431
- }
20432
- [qx, qy, qz] = toZero([qx, qy, qz]);
20433
- // const q = gcd(qx, gcd(qy, qz));
20434
- let q = [Math.abs(qx), Math.abs(qy), Math.abs(qz)].reduce((acc, curr) => {
20435
- if (acc == 0 || (curr > 0 && curr < acc)) {
20436
- acc = curr;
20437
- }
20438
- return acc;
20439
- }, 0);
20440
- if (q > 0) {
20441
- qx /= q;
20442
- qy /= q;
20443
- qz /= q;
20444
- }
20445
- const rotate = [qx, qy, qz, Object.is(qw, 0) ? 0 : 2 * Math.acos(qw) * 180 / Math.PI];
20446
- const scale = [scaleX, scaleY, scaleZ];
20447
- const skew = [skewXY, skewXZ, skewYZ];
20448
- return {
20449
- translate,
20450
- scale,
20451
- rotate,
20452
- skew,
20453
- perspective
20454
- };
20455
- }
20456
- function transposeMatrix4(m) {
20457
- return [
20458
- m[0], m[4], m[8], m[12],
20459
- m[1], m[5], m[9], m[13],
20460
- m[2], m[6], m[10], m[14],
20461
- m[3], m[7], m[11], m[15],
20462
- ];
20463
- }
20464
- function toZero(v) {
20465
- for (let i = 0; i < v.length; i++) {
20466
- if (Math.abs(v[i]) <= epsilon) {
20467
- v[i] = 0;
20468
- }
20469
- else {
20470
- v[i] = +v[i].toPrecision(6);
21167
+ }
21168
+ else {
21169
+ for (let i = 0; i < children.length; i++) {
21170
+ if (children[i] == value) {
21171
+ children.splice(i, 1, {
21172
+ typ: exports.EnumToken.FunctionTokenType,
21173
+ val: 'calc',
21174
+ chi: values
21175
+ });
21176
+ break;
21177
+ }
21178
+ }
21179
+ }
21180
+ }
21181
+ }
21182
+ }
21183
+ }
20471
21184
  }
21185
+ return null;
20472
21186
  }
20473
- return v;
20474
- }
20475
- // https://drafts.csswg.org/css-transforms-1/#2d-matrix
20476
- function is2DMatrix(matrix) {
20477
- // m13,m14, m23, m24, m31, m32, m34, m43 are all 0
20478
- return matrix[0 * 4 + 2] === 0 &&
20479
- matrix[0 * 4 + 3] === 0 &&
20480
- matrix[1 * 4 + 2] === 0 &&
20481
- matrix[1 * 4 + 3] === 0 &&
20482
- matrix[2 * 4 + 0] === 0 &&
20483
- matrix[2 * 4 + 1] === 0 &&
20484
- matrix[2 * 4 + 3] === 0 &&
20485
- matrix[3 * 4 + 2] === 0 &&
20486
- matrix[2 * 4 + 2] === 1 &&
20487
- matrix[3 * 4 + 3] === 1;
20488
21187
  }
20489
21188
 
20490
21189
  function translateX(x, from) {
20491
21190
  const matrix = identity();
20492
- matrix[3 * 4 + 0] = x;
21191
+ matrix[3 * 4] = x;
20493
21192
  return multiply(from, matrix);
20494
21193
  }
20495
21194
  function translateY(y, from) {
@@ -20504,13 +21203,13 @@
20504
21203
  }
20505
21204
  function translate(translate, from) {
20506
21205
  const matrix = identity();
20507
- matrix[3 * 4 + 0] = translate[0];
21206
+ matrix[3 * 4] = translate[0];
20508
21207
  matrix[3 * 4 + 1] = translate[1] ?? 0;
20509
21208
  return multiply(from, matrix);
20510
21209
  }
20511
21210
  function translate3d(translate, from) {
20512
21211
  const matrix = identity();
20513
- matrix[3 * 4 + 0] = translate[0];
21212
+ matrix[3 * 4] = translate[0];
20514
21213
  matrix[3 * 4 + 1] = translate[1];
20515
21214
  matrix[3 * 4 + 2] = translate[2];
20516
21215
  return multiply(from, matrix);
@@ -20533,34 +21232,34 @@
20533
21232
  x *= unit;
20534
21233
  y *= unit;
20535
21234
  z *= unit;
20536
- matrix[0 * 4 + 0] = 1 - 2 * (y * y + z * z) * sq;
20537
- matrix[0 * 4 + 1] = 2 * (x * y * sq + z * sc);
20538
- matrix[0 * 4 + 2] = 2 * (x * z * sq - y * sc);
20539
- matrix[1 * 4 + 0] = 2 * (x * y * sq - z * sc);
20540
- matrix[1 * 4 + 1] = 1 - 2 * (x * x + z * z) * sq;
20541
- matrix[1 * 4 + 2] = 2 * (y * z * sq + x * sc);
20542
- matrix[2 * 4 + 0] = 2 * (x * z * sq + y * sc);
21235
+ matrix[0] = 1 - 2 * (y * y + z * z) * sq;
21236
+ matrix[1] = 2 * (x * y * sq + z * sc);
21237
+ matrix[2] = 2 * (x * z * sq - y * sc);
21238
+ matrix[4] = 2 * (x * y * sq - z * sc);
21239
+ matrix[4 + 1] = 1 - 2 * (x * x + z * z) * sq;
21240
+ matrix[4 + 2] = 2 * (y * z * sq + x * sc);
21241
+ matrix[2 * 4] = 2 * (x * z * sq + y * sc);
20543
21242
  matrix[2 * 4 + 1] = 2 * (y * z * sq - x * sc);
20544
21243
  matrix[2 * 4 + 2] = 1 - 2 * (x * x + y * y) * sq;
20545
21244
  return multiply(from, matrix);
20546
21245
  }
20547
21246
  function rotate(angle, from) {
20548
21247
  const matrix = identity();
20549
- matrix[0 * 4 + 0] = Math.cos(angle);
20550
- matrix[0 * 4 + 1] = Math.sin(angle);
20551
- matrix[1 * 4 + 0] = -Math.sin(angle);
20552
- matrix[1 * 4 + 1] = Math.cos(angle);
21248
+ matrix[0] = Math.cos(angle);
21249
+ matrix[1] = Math.sin(angle);
21250
+ matrix[4] = -Math.sin(angle);
21251
+ matrix[4 + 1] = Math.cos(angle);
20553
21252
  return multiply(from, matrix);
20554
21253
  }
20555
21254
 
20556
21255
  function scaleX(x, from) {
20557
21256
  const matrix = identity();
20558
- matrix[0 * 4 + 0] = x;
21257
+ matrix[0] = x;
20559
21258
  return multiply(from, matrix);
20560
21259
  }
20561
21260
  function scaleY(y, from) {
20562
21261
  const matrix = identity();
20563
- matrix[1 * 4 + 1] = y;
21262
+ matrix[4 + 1] = y;
20564
21263
  return multiply(from, matrix);
20565
21264
  }
20566
21265
  function scaleZ(z, from) {
@@ -20570,14 +21269,14 @@
20570
21269
  }
20571
21270
  function scale(x, y, from) {
20572
21271
  const matrix = identity();
20573
- matrix[0 * 4 + 0] = x;
20574
- matrix[1 * 4 + 1] = y;
21272
+ matrix[0] = x;
21273
+ matrix[4 + 1] = y;
20575
21274
  return multiply(from, matrix);
20576
21275
  }
20577
21276
  function scale3d(x, y, z, from) {
20578
21277
  const matrix = identity();
20579
- matrix[0 * 4 + 0] = x;
20580
- matrix[1 * 4 + 1] = y;
21278
+ matrix[0] = x;
21279
+ matrix[4 + 1] = y;
20581
21280
  matrix[2 * 4 + 2] = z;
20582
21281
  return multiply(from, matrix);
20583
21282
  }
@@ -20602,27 +21301,27 @@
20602
21301
  function matrix(values) {
20603
21302
  const matrix = identity();
20604
21303
  if (values.length === 6) {
20605
- matrix[0 * 4 + 0] = values[0];
20606
- matrix[0 * 4 + 1] = values[1];
20607
- matrix[1 * 4 + 0] = values[2];
20608
- matrix[1 * 4 + 1] = values[3];
20609
- matrix[3 * 4 + 0] = values[4];
21304
+ matrix[0] = values[0];
21305
+ matrix[1] = values[1];
21306
+ matrix[4] = values[2];
21307
+ matrix[4 + 1] = values[3];
21308
+ matrix[3 * 4] = values[4];
20610
21309
  matrix[3 * 4 + 1] = values[5];
20611
21310
  }
20612
21311
  else if (values.length === 16) {
20613
- matrix[0 * 4 + 0] = values[0];
20614
- matrix[0 * 4 + 1] = values[1];
20615
- matrix[0 * 4 + 2] = values[2];
20616
- matrix[0 * 4 + 3] = values[3];
20617
- matrix[1 * 4 + 0] = values[4];
20618
- matrix[1 * 4 + 1] = values[5];
20619
- matrix[1 * 4 + 2] = values[6];
20620
- matrix[1 * 4 + 3] = values[7];
20621
- matrix[2 * 4 + 0] = values[8];
21312
+ matrix[0] = values[0];
21313
+ matrix[1] = values[1];
21314
+ matrix[2] = values[2];
21315
+ matrix[3] = values[3];
21316
+ matrix[4] = values[4];
21317
+ matrix[4 + 1] = values[5];
21318
+ matrix[4 + 2] = values[6];
21319
+ matrix[4 + 3] = values[7];
21320
+ matrix[2 * 4] = values[8];
20622
21321
  matrix[2 * 4 + 1] = values[9];
20623
21322
  matrix[2 * 4 + 2] = values[10];
20624
21323
  matrix[2 * 4 + 3] = values[11];
20625
- matrix[3 * 4 + 0] = values[12];
21324
+ matrix[3 * 4] = values[12];
20626
21325
  matrix[3 * 4 + 1] = values[13];
20627
21326
  matrix[3 * 4 + 2] = values[14];
20628
21327
  matrix[3 * 4 + 3] = values[15];
@@ -20647,11 +21346,11 @@
20647
21346
  typ: exports.EnumToken.FunctionTokenType,
20648
21347
  val: 'matrix',
20649
21348
  chi: [
20650
- matrix[0 * 4 + 0],
20651
- matrix[0 * 4 + 1],
20652
- matrix[1 * 4 + 0],
20653
- matrix[1 * 4 + 1],
20654
- matrix[3 * 4 + 0],
21349
+ matrix[0],
21350
+ matrix[1],
21351
+ matrix[4],
21352
+ matrix[4 + 1],
21353
+ matrix[3 * 4],
20655
21354
  matrix[3 * 4 + 1]
20656
21355
  ].reduce((acc, t) => {
20657
21356
  if (acc.length > 0) {
@@ -20834,10 +21533,6 @@
20834
21533
  }
20835
21534
  }
20836
21535
  if (transforms.has('skew')) {
20837
- // if (round(decomposed.skew[0]) == 0) {
20838
- //
20839
- // skew.delete('x');
20840
- // }
20841
21536
  if (round(decomposed.skew[1]) == 0) {
20842
21537
  skew.delete('y');
20843
21538
  }
@@ -20877,7 +21572,7 @@
20877
21572
  scales.delete('x');
20878
21573
  }
20879
21574
  if (scales.size == 1) {
20880
- let prefix = scales.has('x') ? '' : scales.has('y') ? 'Y' : 'Z';
21575
+ let prefix = scales.has('x') ? 'X' : scales.has('y') ? 'Y' : 'Z';
20881
21576
  result.push({
20882
21577
  typ: exports.EnumToken.FunctionTokenType,
20883
21578
  val: 'scale' + prefix,
@@ -20920,13 +21615,9 @@
20920
21615
  ] : result;
20921
21616
  }
20922
21617
  function eqMatrix(a, b) {
20923
- // console.error(JSON.stringify({a, b}, null, 1));
20924
21618
  let mat = identity();
20925
21619
  let tmp = identity();
20926
- // @ts-ignore
20927
21620
  const data = (Array.isArray(a) ? a : parseMatrix(a));
20928
- // toZero(data);
20929
- // console.error({data});
20930
21621
  for (const transform of b) {
20931
21622
  tmp = computeMatrix([transform], identity());
20932
21623
  if (tmp == null) {
@@ -20934,8 +21625,6 @@
20934
21625
  }
20935
21626
  mat = multiply(mat, tmp);
20936
21627
  }
20937
- // toZero(mat);
20938
- // console.error({mat});
20939
21628
  if (mat == null) {
20940
21629
  return false;
20941
21630
  }
@@ -20948,23 +21637,126 @@
20948
21637
  }
20949
21638
  return true;
20950
21639
  }
21640
+ function minifyTransformFunctions(transform) {
21641
+ const name = transform.val.toLowerCase();
21642
+ if ('skewx' == name) {
21643
+ transform.val = 'skew';
21644
+ return transform;
21645
+ }
21646
+ if (!['translate', 'translate3d', 'scale', 'scale3d'].includes(name)) {
21647
+ return transform;
21648
+ }
21649
+ const values = [];
21650
+ for (const token of transform.chi) {
21651
+ if (token.typ == exports.EnumToken.CommentTokenType || token.typ == exports.EnumToken.WhitespaceTokenType || token.typ == exports.EnumToken.CommaTokenType) {
21652
+ continue;
21653
+ }
21654
+ if (![exports.EnumToken.NumberTokenType, exports.EnumToken.LengthTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.PercentageTokenType].includes(token.typ)) {
21655
+ return transform;
21656
+ }
21657
+ if (token.typ == exports.EnumToken.PercentageTokenType && typeof token.val == 'number' && name.startsWith('scale')) {
21658
+ Object.assign(token, { typ: exports.EnumToken.NumberTokenType, val: token.val / 100 });
21659
+ }
21660
+ values.push(token);
21661
+ }
21662
+ if ((name == 'translate' || name == 'scale') && values.length > 2) {
21663
+ return transform;
21664
+ }
21665
+ const ignoredValue = name.startsWith('scale') ? 1 : 0;
21666
+ const t = new Set(['x', 'y', 'z']);
21667
+ let i = 3;
21668
+ while (i--) {
21669
+ if (values.length <= i || values[i].val == ignoredValue) {
21670
+ t.delete(i == 0 ? 'x' : i == 1 ? 'y' : 'z');
21671
+ }
21672
+ }
21673
+ if (name == 'translate3d' || name == 'translate') {
21674
+ if (t.size == 0) {
21675
+ return {
21676
+ typ: exports.EnumToken.FunctionTokenType,
21677
+ val: 'translate',
21678
+ chi: [
21679
+ { typ: exports.EnumToken.NumberTokenType, val: 0 }
21680
+ ]
21681
+ };
21682
+ }
21683
+ if (t.size == 1) {
21684
+ return {
21685
+ typ: exports.EnumToken.FunctionTokenType,
21686
+ val: 'translate' + (t.has('x') ? '' : t.has('y') ? 'Y' : 'Z'),
21687
+ chi: [
21688
+ values[t.has('x') ? 0 : t.has('y') ? 1 : 2]
21689
+ ]
21690
+ };
21691
+ }
21692
+ if (t.size == 2) {
21693
+ if (t.has('z')) {
21694
+ return transform;
21695
+ }
21696
+ return {
21697
+ typ: exports.EnumToken.FunctionTokenType,
21698
+ val: 'translate',
21699
+ chi: [
21700
+ values[0],
21701
+ { typ: exports.EnumToken.CommaTokenType },
21702
+ values[1]
21703
+ ]
21704
+ };
21705
+ }
21706
+ }
21707
+ if (name == 'scale3d' || name == 'scale') {
21708
+ if (t.size == 0) {
21709
+ return {
21710
+ typ: exports.EnumToken.FunctionTokenType,
21711
+ val: 'scale',
21712
+ chi: [
21713
+ { typ: exports.EnumToken.NumberTokenType, val: 1 }
21714
+ ]
21715
+ };
21716
+ }
21717
+ if (t.size == 1) {
21718
+ return {
21719
+ typ: exports.EnumToken.FunctionTokenType,
21720
+ val: 'scale' + (t.has('x') ? 'X' : t.has('y') ? 'Y' : 'Z'),
21721
+ chi: [
21722
+ values[t.has('x') ? 0 : t.has('y') ? 1 : 2]
21723
+ ]
21724
+ };
21725
+ }
21726
+ if (t.size == 2) {
21727
+ if (t.has('z')) {
21728
+ return transform;
21729
+ }
21730
+ return {
21731
+ typ: exports.EnumToken.FunctionTokenType,
21732
+ val: 'scale',
21733
+ chi: [
21734
+ values[0],
21735
+ { typ: exports.EnumToken.CommaTokenType },
21736
+ values[1]
21737
+ ]
21738
+ };
21739
+ }
21740
+ }
21741
+ return transform;
21742
+ }
20951
21743
 
20952
21744
  function skewX(x, from) {
20953
21745
  const matrix = identity();
20954
- matrix[1 * 4 + 0] = Math.tan(x);
21746
+ matrix[4] = Math.tan(x);
20955
21747
  return multiply(from, matrix);
20956
21748
  }
20957
21749
  function skewY(y, from) {
20958
21750
  const matrix = identity();
20959
- matrix[0 * 4 + 1] = Math.tan(y);
21751
+ matrix[1] = Math.tan(y);
20960
21752
  return multiply(from, matrix);
20961
21753
  }
20962
21754
  // convert angle to radian
20963
21755
  function skew(values, from) {
20964
21756
  const matrix = identity();
20965
- matrix[1 * 4 + 0] = Math.tan(values[0]);
21757
+ matrix[4] = Math.tan(values[0]);
20966
21758
  if (values.length > 1) {
20967
- matrix[0 * 4 + 1] = Math.tan(values[1]);
21759
+ matrix[1] = Math.tan(values[1]);
20968
21760
  }
20969
21761
  return multiply(from, matrix);
20970
21762
  }
@@ -21003,8 +21795,6 @@
21003
21795
  });
21004
21796
  }
21005
21797
  }
21006
- // console.error({matrix});
21007
- // matrix = toZero(matrix) as Matrix;
21008
21798
  return {
21009
21799
  matrix: serialize(toZero(matrix)),
21010
21800
  cumulative,
@@ -21028,7 +21818,7 @@
21028
21818
  {
21029
21819
  values.length = 0;
21030
21820
  const children = stripCommaToken(transformList[i].chi.slice());
21031
- const valCount = transformList[i].val == 'translate3d' || transformList[i].val == 'translate' ? 3 : 1;
21821
+ const valCount = transformList[i].val == 'translate3d' ? 3 : transformList[i].val == 'translate' ? 2 : 1;
21032
21822
  for (let j = 0; j < children.length; j++) {
21033
21823
  if (children[j].typ == exports.EnumToken.WhitespaceTokenType) {
21034
21824
  continue;
@@ -21115,7 +21905,7 @@
21115
21905
  const children = stripCommaToken(transformList[i].chi.slice());
21116
21906
  for (let k = 0; k < children.length; k++) {
21117
21907
  child = children[k];
21118
- if (child.typ != exports.EnumToken.NumberTokenType) {
21908
+ if (child.typ != exports.EnumToken.NumberTokenType && child.typ != exports.EnumToken.PercentageTokenType) {
21119
21909
  return null;
21120
21910
  }
21121
21911
  values.push(getNumber(child));
@@ -21269,14 +22059,12 @@
21269
22059
  }
21270
22060
 
21271
22061
  class TransformCssFeature {
22062
+ accept = new Set([exports.EnumToken.RuleNodeType, exports.EnumToken.KeyFramesRuleNodeType]);
21272
22063
  get ordering() {
21273
22064
  return 4;
21274
22065
  }
21275
- get preProcess() {
21276
- return false;
21277
- }
21278
- get postProcess() {
21279
- return true;
22066
+ get processMode() {
22067
+ return exports.FeatureWalkMode.Post;
21280
22068
  }
21281
22069
  static register(options) {
21282
22070
  // @ts-ignore
@@ -21287,7 +22075,7 @@
21287
22075
  }
21288
22076
  run(ast) {
21289
22077
  if (!('chi' in ast)) {
21290
- return;
22078
+ return null;
21291
22079
  }
21292
22080
  let i = 0;
21293
22081
  let node;
@@ -21298,28 +22086,21 @@
21298
22086
  if (node.typ != exports.EnumToken.DeclarationNodeType || !node.nam.match(/^(-[a-z]+-)?transform$/)) {
21299
22087
  continue;
21300
22088
  }
21301
- const children = node.val.reduce((acc, curr) => {
21302
- if (curr.typ == exports.EnumToken.FunctionTokenType && 'skew' == curr.val.toLowerCase()) {
21303
- if (curr.chi.length == 3) {
21304
- if (curr.chi[2].val == 0) {
21305
- curr.chi.length = 1;
21306
- curr.val = 'skew';
21307
- }
21308
- else if (curr.chi[0].val == 0) {
21309
- curr.chi = [curr.chi[2]];
21310
- curr.val = 'skewY';
21311
- }
21312
- }
21313
- }
21314
- acc.push(curr);
21315
- return acc;
21316
- }, []);
22089
+ const children = [];
22090
+ for (const child of node.val) {
22091
+ children.push(child.typ == exports.EnumToken.FunctionTokenType ? minifyTransformFunctions(child) : child);
22092
+ }
21317
22093
  consumeWhitespace(children);
21318
- let { matrix, cumulative, minified } = compute(children) ?? {};
22094
+ let { matrix, cumulative, minified } = compute(children) ?? {
22095
+ matrix: null,
22096
+ cumulative: null,
22097
+ minified: null
22098
+ };
21319
22099
  if (matrix == null || cumulative == null || minified == null) {
22100
+ node.val = children;
21320
22101
  continue;
21321
22102
  }
21322
- let r = [filterValues(node.val.slice())];
22103
+ let r = [filterValues(children)];
21323
22104
  if (eqMatrix(matrix, cumulative)) {
21324
22105
  r.push(cumulative);
21325
22106
  }
@@ -21334,6 +22115,7 @@
21334
22115
  return acc;
21335
22116
  }, [matrix]);
21336
22117
  }
22118
+ return null;
21337
22119
  }
21338
22120
  }
21339
22121
 
@@ -21346,21 +22128,6 @@
21346
22128
  TransformCssFeature: TransformCssFeature
21347
22129
  });
21348
22130
 
21349
- /**
21350
- * feature walk mode
21351
- */
21352
- exports.FeatureWalkMode = void 0;
21353
- (function (FeatureWalkMode) {
21354
- /**
21355
- * pre process
21356
- */
21357
- FeatureWalkMode[FeatureWalkMode["Pre"] = 0] = "Pre";
21358
- /**
21359
- * post process
21360
- */
21361
- FeatureWalkMode[FeatureWalkMode["Post"] = 1] = "Post";
21362
- })(exports.FeatureWalkMode || (exports.FeatureWalkMode = {}));
21363
-
21364
22131
  const combinators = ['+', '>', '~', '||', '|'];
21365
22132
  const definedPropertySettings = { configurable: true, enumerable: false, writable: true };
21366
22133
  const notEndingWith = ['(', '['].concat(combinators);
@@ -21380,6 +22147,7 @@
21380
22147
  let preprocess = false;
21381
22148
  let postprocess = false;
21382
22149
  let parents;
22150
+ let replacement;
21383
22151
  if (!('features' in options)) {
21384
22152
  // @ts-ignore
21385
22153
  options = {
@@ -21389,82 +22157,92 @@
21389
22157
  removePrefix: false,
21390
22158
  features: [], ...options
21391
22159
  };
21392
- // @ts-ignore
21393
22160
  for (const feature of features) {
21394
22161
  feature.register(options);
21395
22162
  }
21396
22163
  options.features.sort((a, b) => a.ordering - b.ordering);
21397
22164
  }
21398
22165
  for (const feature of options.features) {
21399
- if (feature.preProcess) {
22166
+ if (feature.processMode & exports.FeatureWalkMode.Pre) {
21400
22167
  preprocess = true;
21401
22168
  }
21402
- if (feature.postProcess) {
22169
+ if (feature.processMode & exports.FeatureWalkMode.Post) {
21403
22170
  postprocess = true;
21404
22171
  }
21405
22172
  }
21406
22173
  if (preprocess) {
21407
- parents = [ast];
22174
+ parents = new Set([ast]);
21408
22175
  for (const parent of parents) {
21409
22176
  if (parent.typ == exports.EnumToken.CommentTokenType ||
21410
22177
  parent.typ == exports.EnumToken.CDOCOMMTokenType) {
21411
- Object.defineProperty(parent, 'parent', {
21412
- ...definedPropertySettings,
21413
- value: parent
21414
- });
21415
22178
  continue;
21416
22179
  }
22180
+ replacement = parent;
21417
22181
  for (const feature of options.features) {
21418
- if (!feature.preProcess) {
22182
+ if ((feature.processMode & exports.FeatureWalkMode.Pre) === 0 || (feature.accept != null && !feature.accept.has(parent.typ))) {
21419
22183
  continue;
21420
22184
  }
21421
- feature.run(parent, options, parent.parent ?? ast, context, exports.FeatureWalkMode.Pre);
22185
+ const result = feature.run(replacement, options, parent.parent ?? ast, context, exports.FeatureWalkMode.Pre);
22186
+ if (result != null) {
22187
+ replacement = result;
22188
+ }
21422
22189
  }
21423
- if (('chi' in parent)) {
22190
+ if (replacement != parent && parent.parent != null) {
21424
22191
  // @ts-ignore
21425
- for (const node of parent.chi) {
21426
- parents.push(Object.defineProperty(node, 'parent', {
22192
+ replaceToken(parent.parent, parent, replacement);
22193
+ }
22194
+ if (('chi' in replacement)) {
22195
+ // @ts-ignore
22196
+ for (const node of replacement.chi) {
22197
+ parents.add(Object.defineProperty(node, 'parent', {
21427
22198
  ...definedPropertySettings,
21428
- value: parent
22199
+ value: replacement
21429
22200
  }));
21430
22201
  }
21431
22202
  }
21432
22203
  }
21433
22204
  for (const feature of options.features) {
21434
- if (feature.preProcess && 'cleanup' in feature) {
22205
+ if ((feature.processMode & exports.FeatureWalkMode.Pre) && 'cleanup' in feature) {
21435
22206
  // @ts-ignore
21436
22207
  feature.cleanup(ast, options, context, exports.FeatureWalkMode.Pre);
21437
22208
  }
21438
22209
  }
21439
22210
  }
21440
22211
  doMinify(ast, options, recursive, errors, nestingContent, context);
21441
- parents = [ast];
22212
+ parents = new Set([ast]);
21442
22213
  for (const parent of parents) {
21443
22214
  if (parent.typ == exports.EnumToken.CommentTokenType ||
21444
22215
  parent.typ == exports.EnumToken.CDOCOMMTokenType) {
21445
22216
  continue;
21446
22217
  }
22218
+ replacement = parent;
21447
22219
  if (postprocess) {
21448
22220
  for (const feature of options.features) {
21449
- if (!feature.postProcess) {
22221
+ if ((feature.processMode & exports.FeatureWalkMode.Post) === 0 || (feature.accept != null && !feature.accept.has(parent.typ))) {
21450
22222
  continue;
21451
22223
  }
21452
- feature.run(parent, options, parent.parent ?? ast, context, exports.FeatureWalkMode.Post);
22224
+ const result = feature.run(replacement, options, parent.parent ?? ast, context, exports.FeatureWalkMode.Post);
22225
+ if (result != null) {
22226
+ replacement = result;
22227
+ }
21453
22228
  }
21454
22229
  }
21455
- if (('chi' in parent)) {
22230
+ if (replacement != null && replacement != parent && parent.parent != null) {
21456
22231
  // @ts-ignore
21457
- for (const node of parent.chi) {
21458
- parents.push(Object.defineProperty(node, 'parent', {
22232
+ replaceToken(parent.parent, parent, replacement);
22233
+ }
22234
+ if (('chi' in replacement)) {
22235
+ for (const node of replacement.chi) {
22236
+ parents.add(Object.defineProperty(node, 'parent', {
21459
22237
  ...definedPropertySettings,
21460
- value: parent
22238
+ value: replacement
21461
22239
  }));
21462
22240
  }
21463
22241
  }
21464
22242
  }
21465
22243
  if (postprocess) {
21466
22244
  for (const feature of options.features) {
21467
- if (feature.postProcess && 'cleanup' in feature) {
22245
+ if (feature.processMode & exports.FeatureWalkMode.Post && 'cleanup' in feature) {
21468
22246
  // @ts-ignore
21469
22247
  feature.cleanup(ast, options, context, exports.FeatureWalkMode.Post);
21470
22248
  }
@@ -21476,12 +22254,10 @@
21476
22254
  * reduce selectors
21477
22255
  * @param acc
21478
22256
  * @param curr
21479
- * @param index
21480
- * @param array
21481
22257
  *
21482
22258
  * @private
21483
22259
  */
21484
- function reduce(acc, curr, index, array) {
22260
+ function reduce(acc, curr) {
21485
22261
  // trim :is()
21486
22262
  // if (array.length == 1 && array[0][0] == ':is(' && array[0].at(-1) == ')') {
21487
22263
  //
@@ -21522,21 +22298,18 @@
21522
22298
  }
21523
22299
  let i = 0;
21524
22300
  let previous = null;
21525
- let node;
22301
+ let node = null;
21526
22302
  let nodeIndex = -1;
21527
- // @ts-ignore
21528
22303
  for (; i < ast.chi.length; i++) {
21529
- // @ts-ignore
21530
22304
  if (ast.chi[i].typ == exports.EnumToken.CommentNodeType) {
21531
22305
  continue;
21532
22306
  }
21533
- // @ts-ignore
21534
22307
  node = ast.chi[i];
21535
22308
  if (node.typ == exports.EnumToken.AtRuleNodeType && node.nam == 'font-face') {
21536
22309
  continue;
21537
22310
  }
21538
- if (node.typ == exports.EnumToken.KeyframeAtRuleNodeType) {
21539
- if (previous?.typ == exports.EnumToken.KeyframeAtRuleNodeType &&
22311
+ if (node.typ == exports.EnumToken.KeyframesAtRuleNodeType) {
22312
+ if (previous?.typ == exports.EnumToken.KeyframesAtRuleNodeType &&
21540
22313
  node.nam == previous.nam &&
21541
22314
  node.val == previous.val) {
21542
22315
  ast.chi?.splice(nodeIndex--, 1);
@@ -21544,15 +22317,11 @@
21544
22317
  i = nodeIndex;
21545
22318
  continue;
21546
22319
  }
21547
- if (node.chi.length > 0) {
21548
- doMinify(node, options, true, errors, nestingContent, context);
21549
- }
21550
22320
  }
21551
- else if (node.typ == exports.EnumToken.KeyFrameRuleNodeType) {
21552
- if (previous?.typ == exports.EnumToken.KeyFrameRuleNodeType &&
22321
+ else if (node.typ == exports.EnumToken.KeyFramesRuleNodeType) {
22322
+ if (previous?.typ == exports.EnumToken.KeyFramesRuleNodeType &&
21553
22323
  node.sel == previous.sel) {
21554
22324
  previous.chi.push(...node.chi);
21555
- // @ts-ignore
21556
22325
  ast.chi.splice(i--, 1);
21557
22326
  continue;
21558
22327
  }
@@ -21574,25 +22343,26 @@
21574
22343
  }
21575
22344
  }
21576
22345
  else if (node.typ == exports.EnumToken.AtRuleNodeType) {
21577
- // @ts-ignore
21578
22346
  if (node.nam == 'media' && ['all', '', null].includes(node.val)) {
21579
- // @ts-ignore
21580
22347
  ast.chi?.splice(i, 1, ...node.chi);
21581
22348
  i--;
21582
22349
  continue;
21583
22350
  }
21584
- // @ts-ignore
21585
22351
  if (previous?.typ == exports.EnumToken.AtRuleNodeType &&
22352
+ node.nam != 'font-face' &&
21586
22353
  previous.nam == node.nam &&
21587
22354
  previous.val == node.val) {
21588
22355
  if ('chi' in node) {
21589
22356
  // @ts-ignore
21590
22357
  previous.chi.push(...node.chi);
22358
+ if (!hasDeclaration(previous)) {
22359
+ context.nodes.delete(previous);
22360
+ doMinify(previous, options, recursive, errors, nestingContent, context);
22361
+ }
21591
22362
  }
21592
22363
  ast?.chi?.splice(i--, 1);
21593
22364
  continue;
21594
22365
  }
21595
- // @ts-ignore
21596
22366
  if (!hasDeclaration(node)) {
21597
22367
  doMinify(node, options, recursive, errors, nestingContent, context);
21598
22368
  }
@@ -21603,47 +22373,33 @@
21603
22373
  // @ts-ignore
21604
22374
  else if (node.typ == exports.EnumToken.RuleNodeType) {
21605
22375
  reduceRuleSelector(node);
21606
- let wrapper;
22376
+ let wrapper = null;
21607
22377
  let match;
21608
- // @ts-ignore
21609
22378
  if (options.nestingRules) {
21610
- // @ts-ignore
21611
22379
  if (previous?.typ == exports.EnumToken.RuleNodeType) {
21612
- // @ts-ignore
21613
22380
  reduceRuleSelector(previous);
21614
22381
  // @ts-ignore
21615
22382
  match = matchSelectors(previous.raw, node.raw, ast.typ);
21616
- // @ts-ignore
21617
22383
  if (match != null) {
21618
- // @ts-ignore
21619
22384
  wrapper = wrapNodes(previous, node, match, ast, reducer, i, nodeIndex);
21620
22385
  nodeIndex = i - 1;
21621
- // @ts-ignore
21622
22386
  previous = ast.chi[nodeIndex];
21623
22387
  }
21624
22388
  }
21625
- // @ts-ignore
21626
22389
  if (wrapper != null) {
21627
- // @ts-ignore
21628
22390
  while (i < ast.chi.length) {
21629
- // @ts-ignore
21630
22391
  const nextNode = ast.chi[i];
21631
- // @ts-ignore
21632
22392
  if (nextNode.typ != exports.EnumToken.RuleNodeType) {
21633
22393
  break;
21634
22394
  }
21635
22395
  reduceRuleSelector(nextNode);
21636
- // @ts-ignore
21637
- match = matchSelectors(wrapper.raw, nextNode.raw, ast.typ);
21638
- // @ts-ignore
22396
+ match = matchSelectors(wrapper.raw, nextNode.raw);
21639
22397
  if (match == null) {
21640
22398
  break;
21641
22399
  }
21642
- // @ts-ignore
21643
22400
  wrapper = wrapNodes(wrapper, nextNode, match, ast, reducer, i, nodeIndex);
21644
22401
  }
21645
22402
  nodeIndex = --i;
21646
- // @ts-ignore
21647
22403
  previous = ast.chi[nodeIndex];
21648
22404
  doMinify(wrapper, options, recursive, errors, nestingContent, context);
21649
22405
  continue;
@@ -21690,7 +22446,6 @@
21690
22446
  curr.unshift('&');
21691
22447
  wrap = false;
21692
22448
  }
21693
- // @ts-ignore
21694
22449
  acc.push(curr);
21695
22450
  return acc;
21696
22451
  }, []);
@@ -21716,82 +22471,67 @@
21716
22471
  }
21717
22472
  }
21718
22473
  if (rule == null) {
21719
- rule = selector.map(s => {
22474
+ rule = selector.map((s) => {
21720
22475
  if (s[0] == '&') {
21721
22476
  s.splice(0, 1, ...node.optimized.optimized);
21722
22477
  }
21723
22478
  return s.join('');
21724
22479
  }).join(',');
21725
22480
  }
21726
- // @ts-ignore
21727
22481
  let sel = wrap ? node.optimized.optimized.join('') + `:is(${rule})` : rule;
21728
22482
  if (sel.length < node.sel.length) {
21729
22483
  node.sel = sel;
21730
22484
  }
21731
22485
  }
22486
+ doMinify(node, options, recursive, errors, nestingContent, context);
21732
22487
  }
21733
- // @ts-ignore
21734
22488
  if (previous != null) {
21735
- // @ts-ignore
21736
22489
  if ('chi' in previous && ('chi' in node)) {
21737
- // @ts-ignore
21738
22490
  if (previous.typ == node.typ) {
21739
22491
  let shouldMerge = true;
21740
- // @ts-ignore
21741
22492
  let k = previous.chi.length;
21742
22493
  while (k-- > 0) {
21743
- // @ts-ignore
21744
22494
  if (previous.chi[k].typ == exports.EnumToken.CommentNodeType) {
21745
22495
  continue;
21746
22496
  }
21747
- // @ts-ignore
21748
22497
  shouldMerge = previous.chi[k].typ == exports.EnumToken.DeclarationNodeType;
21749
22498
  break;
21750
22499
  }
21751
22500
  if (shouldMerge) {
21752
22501
  // @ts-ignore
21753
- if (((node.typ == exports.EnumToken.RuleNodeType || node.typ == exports.EnumToken.KeyFrameRuleNodeType) && node.sel == previous.sel) ||
22502
+ if (((node.typ == exports.EnumToken.RuleNodeType || node.typ == exports.EnumToken.KeyFramesRuleNodeType) && node.sel == previous.sel) ||
21754
22503
  // @ts-ignore
21755
22504
  (node.typ == exports.EnumToken.AtRuleNodeType) && node.val != 'font-face' && node.val == previous.val) {
21756
22505
  // @ts-ignore
21757
22506
  node.chi.unshift(...previous.chi);
21758
- // @ts-ignore
22507
+ doMinify(node, options, recursive, errors, nestingContent, context);
21759
22508
  ast.chi.splice(nodeIndex, 1);
21760
- i--;
21761
- previous = node;
22509
+ previous = ast.chi[--i];
21762
22510
  nodeIndex = i;
21763
22511
  continue;
21764
22512
  }
21765
- else if (node.typ == previous?.typ && [exports.EnumToken.KeyFrameRuleNodeType, exports.EnumToken.RuleNodeType].includes(node.typ)) {
22513
+ else if (node.typ == previous?.typ && [exports.EnumToken.KeyFramesRuleNodeType, exports.EnumToken.RuleNodeType].includes(node.typ)) {
21766
22514
  const intersect = diff(previous, node, reducer, options);
21767
22515
  if (intersect != null) {
21768
22516
  if (intersect.node1.chi.length == 0) {
21769
- // @ts-ignore
21770
22517
  ast.chi.splice(i--, 1);
21771
22518
  }
21772
22519
  else {
21773
- // @ts-ignore
21774
22520
  ast.chi.splice(i--, 1, intersect.node1);
21775
22521
  }
21776
22522
  if (intersect.node2.chi.length == 0) {
21777
- // @ts-ignore
21778
22523
  ast.chi.splice(nodeIndex, 1, intersect.result);
21779
22524
  i--;
21780
- // @ts-ignore
21781
22525
  if (nodeIndex == i) {
21782
22526
  nodeIndex = i;
21783
22527
  }
21784
22528
  }
21785
22529
  else {
21786
- // @ts-ignore
21787
22530
  ast.chi.splice(nodeIndex, 1, intersect.result, intersect.node2);
21788
- // @ts-ignore
21789
22531
  i = (nodeIndex ?? 0) + 1;
21790
22532
  }
21791
22533
  reduceRuleSelector(intersect.result);
21792
- // @ts-ignore
21793
22534
  if (node != ast.chi[i]) {
21794
- // @ts-ignore
21795
22535
  node = ast.chi[i];
21796
22536
  }
21797
22537
  previous = intersect.result;
@@ -21800,9 +22540,7 @@
21800
22540
  }
21801
22541
  }
21802
22542
  }
21803
- // @ts-ignore
21804
22543
  if (recursive && previous != node) {
21805
- // @ts-ignore
21806
22544
  if (!hasDeclaration(previous)) {
21807
22545
  doMinify(previous, options, recursive, errors, nestingContent, context);
21808
22546
  }
@@ -21810,9 +22548,7 @@
21810
22548
  }
21811
22549
  }
21812
22550
  if (!nestingContent &&
21813
- // @ts-ignore
21814
22551
  previous != null &&
21815
- // previous.optimized != null &&
21816
22552
  previous.typ == exports.EnumToken.RuleNodeType &&
21817
22553
  previous.sel.includes('&')) {
21818
22554
  fixSelector(previous);
@@ -21820,20 +22556,15 @@
21820
22556
  previous = node;
21821
22557
  nodeIndex = i;
21822
22558
  }
21823
- // @ts-ignore
21824
22559
  if (recursive && node != null && ('chi' in node)) {
21825
- // @ts-ignore
21826
- if (node.typ == exports.EnumToken.KeyframeAtRuleNodeType || !node.chi.some(n => n.typ == exports.EnumToken.DeclarationNodeType)) {
21827
- // @ts-ignore
22560
+ if (node.typ == exports.EnumToken.KeyframesAtRuleNodeType || !node.chi.some(n => n.typ == exports.EnumToken.DeclarationNodeType)) {
21828
22561
  if (!(node.typ == exports.EnumToken.AtRuleNodeType && node.nam != 'font-face')) {
21829
22562
  doMinify(node, options, recursive, errors, nestingContent, context);
21830
22563
  }
21831
22564
  }
21832
22565
  }
21833
22566
  if (!nestingContent &&
21834
- // @ts-ignore
21835
22567
  node != null &&
21836
- // previous.optimized != null &&
21837
22568
  node.typ == exports.EnumToken.RuleNodeType &&
21838
22569
  node.sel.includes('&')) {
21839
22570
  fixSelector(node);
@@ -21984,7 +22715,6 @@
21984
22715
  }
21985
22716
  if (chr == ',') {
21986
22717
  if (str !== '') {
21987
- // @ts-ignore
21988
22718
  result.at(-1).push(str);
21989
22719
  str = '';
21990
22720
  }
@@ -21993,7 +22723,6 @@
21993
22723
  }
21994
22724
  if (chr == '.') {
21995
22725
  if (str !== '') {
21996
- // @ts-ignore
21997
22726
  result.at(-1).push(str);
21998
22727
  str = '';
21999
22728
  }
@@ -22002,20 +22731,17 @@
22002
22731
  }
22003
22732
  if (combinators.includes(chr)) {
22004
22733
  if (str !== '') {
22005
- // @ts-ignore
22006
22734
  result.at(-1).push(str);
22007
22735
  str = '';
22008
22736
  }
22009
22737
  if (chr == '|' && buffer.charAt(i + 1) == '|') {
22010
22738
  chr += buffer.charAt(++i);
22011
22739
  }
22012
- // @ts-ignore
22013
22740
  result.at(-1).push(chr);
22014
22741
  continue;
22015
22742
  }
22016
22743
  if (chr == ':') {
22017
22744
  if (str !== '') {
22018
- // @ts-ignore
22019
22745
  result.at(-1).push(str);
22020
22746
  str = '';
22021
22747
  }
@@ -22057,7 +22783,6 @@
22057
22783
  }
22058
22784
  }
22059
22785
  if (str !== '') {
22060
- // @ts-ignore
22061
22786
  result.at(-1).push(str);
22062
22787
  }
22063
22788
  return result;
@@ -22122,7 +22847,7 @@
22122
22847
  *
22123
22848
  * @private
22124
22849
  */
22125
- function matchSelectors(selector1, selector2 /*, parentType: EnumToken, errors: ErrorDescription[] */) {
22850
+ function matchSelectors(selector1, selector2) {
22126
22851
  let match = [[]];
22127
22852
  const j = Math.min(selector1.reduce((acc, curr) => Math.min(acc, curr.length), selector1.length > 0 ? selector1[0].length : 0), selector2.reduce((acc, curr) => Math.min(acc, curr.length), selector2.length > 0 ? selector2[0].length : 0));
22128
22853
  let i = 0;
@@ -22197,7 +22922,6 @@
22197
22922
  * @private
22198
22923
  */
22199
22924
  function fixSelector(node) {
22200
- // @ts-ignore
22201
22925
  if (node.sel.includes('&')) {
22202
22926
  const attributes = parseString(node.sel);
22203
22927
  for (const attr of walkValues(attributes)) {
@@ -22232,40 +22956,27 @@
22232
22956
  let nSel = match.selector2.reduce(reducer, []).join(',');
22233
22957
  // @ts-ignore
22234
22958
  const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(',') };
22235
- // @ts-ignore
22236
22959
  Object.defineProperty(wrapper, 'raw', {
22237
22960
  ...definedPropertySettings,
22238
- // @ts-ignore
22239
22961
  value: match.match.map(t => t.slice())
22240
22962
  });
22241
22963
  if (pSel == '&' || pSel === '') {
22242
- // @ts-ignore
22243
22964
  wrapper.chi.push(...previous.chi);
22244
- // @ts-ignore
22245
22965
  if ((nSel == '&' || nSel === '')) {
22246
- // @ts-ignore
22247
22966
  wrapper.chi.push(...node.chi);
22248
22967
  }
22249
22968
  else {
22250
- // @ts-ignore
22251
22969
  wrapper.chi.push(node);
22252
22970
  }
22253
22971
  }
22254
22972
  else {
22255
- // @ts-ignore
22256
22973
  wrapper.chi.push(previous, node);
22257
22974
  }
22258
- // @ts-ignore
22259
22975
  ast.chi.splice(i, 1, wrapper);
22260
- // @ts-ignore
22261
22976
  ast.chi.splice(nodeIndex, 1);
22262
- // @ts-ignore
22263
22977
  previous.sel = pSel;
22264
- // @ts-ignore
22265
22978
  previous.raw = match.selector1;
22266
- // @ts-ignore
22267
22979
  node.sel = nSel;
22268
- // @ts-ignore
22269
22980
  node.raw = match.selector2;
22270
22981
  reduceRuleSelector(wrapper);
22271
22982
  return wrapper;
@@ -22457,14 +23168,11 @@
22457
23168
  */
22458
23169
  function expand(ast) {
22459
23170
  const result = { ...ast, chi: [] };
22460
- // @ts-ignore
22461
23171
  for (let i = 0; i < ast.chi.length; i++) {
22462
- // @ts-ignore
22463
23172
  const node = ast.chi[i];
22464
23173
  if (node.typ == exports.EnumToken.RuleNodeType) {
22465
23174
  // @ts-ignore
22466
23175
  result.chi.push(...expandRule(node));
22467
- // i += expanded.length - 1;
22468
23176
  }
22469
23177
  else if (node.typ == exports.EnumToken.AtRuleNodeType && 'chi' in node) {
22470
23178
  let hasRule = false;
@@ -22479,6 +23187,10 @@
22479
23187
  // @ts-ignore
22480
23188
  result.chi.push({ ...(hasRule ? expand(node) : node) });
22481
23189
  }
23190
+ else {
23191
+ // @ts-ignore
23192
+ result.chi.push(node);
23193
+ }
22482
23194
  }
22483
23195
  return result;
22484
23196
  }
@@ -22661,25 +23373,21 @@
22661
23373
  return 1;
22662
23374
  }
22663
23375
  return b == '&' ? -1 : 0;
22664
- }).reduce((acc, curr) => {
22665
- // if (acc.length > 0 && curr == '&' && (replace.charAt(0) != '.' || replace.includes(' '))) {
22666
- //
22667
- // return acc + ':is(' + replace + ')';
22668
- // }
22669
- return acc + (curr == '&' ? replace : curr);
22670
- }, '');
23376
+ }).reduce((acc, curr) => acc + (curr == '&' ? replace : curr), '');
22671
23377
  }
22672
23378
 
22673
23379
  const matchUrl = /^(https?:)?\/\//;
22674
23380
  /**
22675
23381
  * return the directory name of a path
22676
23382
  * @param path
22677
- * @internal
23383
+ *
23384
+ * @private
22678
23385
  */
22679
23386
  function dirname(path) {
22680
- if (path == '/' || path === '') {
22681
- return path;
22682
- }
23387
+ // if (path == '/' || path === '') {
23388
+ //
23389
+ // return path;
23390
+ // }
22683
23391
  let i = 0;
22684
23392
  let parts = [''];
22685
23393
  for (; i < path.length; i++) {
@@ -22687,9 +23395,10 @@
22687
23395
  if (chr == '/') {
22688
23396
  parts.push('');
22689
23397
  }
22690
- else if (chr == '?' || chr == '#') {
22691
- break;
22692
- }
23398
+ // else if (chr == '?' || chr == '#') {
23399
+ //
23400
+ // break;
23401
+ // }
22693
23402
  else {
22694
23403
  parts[parts.length - 1] += chr;
22695
23404
  }
@@ -22744,6 +23453,8 @@
22744
23453
  relative: url
22745
23454
  };
22746
23455
  }
23456
+ cwd ??= '';
23457
+ currentDirectory ??= '';
22747
23458
  if (matchUrl.test(currentDirectory)) {
22748
23459
  const path = new URL(url, currentDirectory).href;
22749
23460
  return {
@@ -22776,17 +23487,14 @@
22776
23487
  }
22777
23488
 
22778
23489
  /**
22779
- * web module entry point
22780
- * @module web
22781
- */
22782
- /**
22783
- * load file or url as stream
23490
+ * default file or url loader
22784
23491
  * @param url
22785
23492
  * @param currentFile
22786
23493
  *
23494
+ * @param asStream
22787
23495
  * @private
22788
23496
  */
22789
- async function getStream(url, currentFile = '.') {
23497
+ async function load(url, currentFile = '.', asStream = false) {
22790
23498
  let t;
22791
23499
  if (matchUrl.test(url)) {
22792
23500
  t = new URL(url);
@@ -22796,25 +23504,45 @@
22796
23504
  }
22797
23505
  else {
22798
23506
  const path = resolve(url, currentFile).absolute;
22799
- // @ts-ignore
22800
23507
  t = new URL(path, self.origin);
22801
23508
  }
22802
- // @ts-ignore
22803
- return fetch(t, t.origin != self.origin ? { mode: 'cors' } : {}).then((response) => {
23509
+ return fetch(t, t.origin != self.origin ? { mode: 'cors' } : {}).then(async (response) => {
22804
23510
  if (!response.ok) {
22805
23511
  throw new Error(`${response.status} ${response.statusText} ${response.url}`);
22806
23512
  }
22807
- return response.body;
23513
+ return asStream ? response.body : await response.text();
22808
23514
  });
22809
23515
  }
22810
23516
  /**
22811
- * render ast node
23517
+ * render the ast tree
22812
23518
  * @param data
22813
23519
  * @param options
23520
+ *
23521
+ * Example:
23522
+ *
23523
+ * ```ts
23524
+ *
23525
+ * import {render, ColorType} from '@tbela99/css-parser';
23526
+ *
23527
+ * const css = 'body { color: color(from hsl(0 100% 50%) xyz x y z); }';
23528
+ * const parseResult = await parse(css);
23529
+ *
23530
+ * let renderResult = render(parseResult.ast);
23531
+ * console.log(result.code);
23532
+ *
23533
+ * // body{color:red}
23534
+ *
23535
+ *
23536
+ * renderResult = render(parseResult.ast, {beautify: true, convertColor: ColorType.SRGB});
23537
+ * console.log(renderResult.code);
23538
+ *
23539
+ * // body {
23540
+ * // color: color(srgb 1 0 0)
23541
+ * // }
23542
+ * ```
22814
23543
  */
22815
23544
  function render(data, options = {}) {
22816
23545
  return doRender(data, Object.assign(options, {
22817
- getStream,
22818
23546
  resolve,
22819
23547
  dirname,
22820
23548
  cwd: options.cwd ?? self.location.pathname.endsWith('/') ? self.location.pathname : dirname(self.location.pathname)
@@ -22824,32 +23552,74 @@
22824
23552
  * parse css file
22825
23553
  * @param file url or path
22826
23554
  * @param options
23555
+ * @param asStream load file as stream
23556
+ *
23557
+ * @throws Error file not found
23558
+ *
23559
+ * Example:
23560
+ *
23561
+ * ```ts
23562
+ *
23563
+ * import {parseFile} from '@tbela99/css-parser/web';
23564
+ *
23565
+ * // remote file
23566
+ * let result = await parseFile('https://docs.deno.com/styles.css');
23567
+ * console.log(result.ast);
23568
+ *
23569
+ * // local file
23570
+ * result = await parseFile('./css/styles.css');
23571
+ * console.log(result.ast);
23572
+ * ```
22827
23573
  */
22828
- async function parseFile(file, options = {}) {
22829
- return getStream(file).then(stream => parse(stream, { src: file, ...options }));
23574
+ async function parseFile(file, options = {}, asStream = false) {
23575
+ return Promise.resolve((options.load ?? load)(file, '.', asStream)).then(stream => parse(stream, { src: file, ...options }));
22830
23576
  }
22831
23577
  /**
22832
23578
  * parse css
22833
23579
  * @param stream
22834
- * @param opt
23580
+ * @param options
23581
+ *
23582
+ * Example:
23583
+ *
23584
+ * ```ts
23585
+ *
23586
+ * import {parse} from '@tbela99/css-parser/web';
23587
+ *
23588
+ * // css string
23589
+ * const result = await parse(css);
23590
+ * console.log(result.ast);
23591
+ * ```
23592
+ *
23593
+ * Example using fetch and readable stream
23594
+ *
23595
+ * ```ts
23596
+ *
23597
+ * import {parse} from '@tbela99/css-parser/web';
23598
+ *
23599
+ * const response = await fetch('https://docs.deno.com/styles.css');
23600
+ * const result = await parse(response.body, {beautify: true});
23601
+ *
23602
+ * console.log(result.ast);
23603
+ * ```
22835
23604
  */
22836
- async function parse(stream, opt = {}) {
23605
+ async function parse(stream, options = {}) {
22837
23606
  return doParse(stream instanceof ReadableStream ? tokenizeStream(stream) : tokenize$1({
22838
23607
  stream,
22839
23608
  buffer: '',
22840
23609
  position: { ind: 0, lin: 1, col: 1 },
22841
23610
  currentPosition: { ind: -1, lin: 1, col: 0 }
22842
- }), Object.assign(opt, {
22843
- getStream,
23611
+ }), Object.assign(options, {
23612
+ load,
22844
23613
  resolve,
22845
23614
  dirname,
22846
- cwd: opt.cwd ?? self.location.pathname.endsWith('/') ? self.location.pathname : dirname(self.location.pathname)
23615
+ cwd: options.cwd ?? self.location.pathname.endsWith('/') ? self.location.pathname : dirname(self.location.pathname)
22847
23616
  }));
22848
23617
  }
22849
23618
  /**
22850
23619
  * transform css file
22851
23620
  * @param file url or path
22852
23621
  * @param options
23622
+ * @param asStream load file as stream
22853
23623
  *
22854
23624
  * Example:
22855
23625
  *
@@ -22866,8 +23636,8 @@
22866
23636
  * console.log(result.code);
22867
23637
  * ```
22868
23638
  */
22869
- async function transformFile(file, options = {}) {
22870
- return getStream(file).then(stream => transform(stream, { src: file, ...options }));
23639
+ async function transformFile(file, options = {}, asStream = false) {
23640
+ return Promise.resolve((options.load ?? load)(file, '.', asStream)).then(stream => transform(stream, { src: file, ...options }));
22871
23641
  }
22872
23642
  /**
22873
23643
  * transform css
@@ -22895,7 +23665,8 @@
22895
23665
  options = { minify: true, removeEmpty: true, removeCharset: true, ...options };
22896
23666
  const startTime = performance.now();
22897
23667
  return parse(css, options).then((parseResult) => {
22898
- const rendered = render(parseResult.ast, options);
23668
+ // ast already expanded by parse
23669
+ const rendered = render(parseResult.ast, { ...options, expandNestingRules: false });
22899
23670
  return {
22900
23671
  ...parseResult,
22901
23672
  ...rendered,
@@ -22914,8 +23685,8 @@
22914
23685
  exports.convertColor = convertColor;
22915
23686
  exports.dirname = dirname;
22916
23687
  exports.expand = expand;
22917
- exports.getStream = getStream;
22918
23688
  exports.isOkLabClose = isOkLabClose;
23689
+ exports.load = load;
22919
23690
  exports.minify = minify;
22920
23691
  exports.okLabDistance = okLabDistance;
22921
23692
  exports.parse = parse;