@tbela99/css-parser 1.3.2 → 1.3.3

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.
package/dist/index.cjs CHANGED
@@ -3,6 +3,7 @@
3
3
  var process = require('node:process');
4
4
  var node_stream = require('node:stream');
5
5
  var node_fs = require('node:fs');
6
+ var promises = require('node:fs/promises');
6
7
 
7
8
  /**
8
9
  * syntax validation enum
@@ -336,7 +337,7 @@ exports.EnumToken = void 0;
336
337
  /**
337
338
  * keyframe rule node type
338
339
  */
339
- EnumToken[EnumToken["KeyFrameRuleNodeType"] = 73] = "KeyFrameRuleNodeType";
340
+ EnumToken[EnumToken["KeyFramesRuleNodeType"] = 73] = "KeyFramesRuleNodeType";
340
341
  /**
341
342
  * class selector token type
342
343
  */
@@ -416,7 +417,7 @@ exports.EnumToken = void 0;
416
417
  /**
417
418
  * keyframe at rule node type
418
419
  */
419
- EnumToken[EnumToken["KeyframeAtRuleNodeType"] = 93] = "KeyframeAtRuleNodeType";
420
+ EnumToken[EnumToken["KeyframesAtRuleNodeType"] = 93] = "KeyframesAtRuleNodeType";
420
421
  /**
421
422
  * invalid declaration node type
422
423
  */
@@ -951,12 +952,15 @@ function color2lchToken(token) {
951
952
  function lchToken(values) {
952
953
  values[2] = toPrecisionAngle(values[2]);
953
954
  const chi = [
954
- { typ: exports.EnumToken.NumberTokenType, val: values[0] },
955
- { typ: exports.EnumToken.NumberTokenType, val: values[1] },
955
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[0]) },
956
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[1]) },
956
957
  { typ: exports.EnumToken.NumberTokenType, val: values[2] },
957
958
  ];
958
959
  if (values.length == 4) {
959
- chi.push({ typ: exports.EnumToken.LiteralTokenType, val: '/' }, { typ: exports.EnumToken.PercentageTokenType, val: values[3] * 100 });
960
+ chi.push({ typ: exports.EnumToken.LiteralTokenType, val: '/' }, {
961
+ typ: exports.EnumToken.PercentageTokenType,
962
+ val: values[3] * 100
963
+ });
960
964
  }
961
965
  return {
962
966
  typ: exports.EnumToken.ColorTokenType,
@@ -1219,8 +1223,8 @@ function color2oklchToken(token) {
1219
1223
  function oklchToken(values) {
1220
1224
  values[2] = toPrecisionAngle(values[2]);
1221
1225
  const chi = [
1222
- { typ: exports.EnumToken.NumberTokenType, val: values[0] },
1223
- { typ: exports.EnumToken.NumberTokenType, val: values[1] },
1226
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[0]) },
1227
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[1]) },
1224
1228
  { typ: exports.EnumToken.NumberTokenType, val: values[2] },
1225
1229
  ];
1226
1230
  if (values.length == 4) {
@@ -1262,16 +1266,28 @@ function cmyk2oklchvalues(token) {
1262
1266
  return values == null ? null : srgb2oklch(...values);
1263
1267
  }
1264
1268
  function lab2oklchvalues(token) {
1269
+ const values = lab2oklabvalues(token);
1270
+ if (values == null) {
1271
+ return null;
1272
+ }
1265
1273
  // @ts-ignore
1266
- return labvalues2lchvalues(...lab2oklabvalues(token));
1274
+ return labvalues2lchvalues(...values);
1267
1275
  }
1268
1276
  function lch2oklchvalues(token) {
1277
+ const values = lch2oklabvalues(token);
1278
+ if (values == null) {
1279
+ return null;
1280
+ }
1269
1281
  // @ts-ignore
1270
- return labvalues2lchvalues(...lch2oklabvalues(token));
1282
+ return labvalues2lchvalues(...values);
1271
1283
  }
1272
1284
  function oklab2oklchvalues(token) {
1285
+ const values = getOKLABComponents(token);
1286
+ if (values == null) {
1287
+ return null;
1288
+ }
1273
1289
  // @ts-ignore
1274
- return labvalues2lchvalues(...getOKLABComponents(token));
1290
+ return labvalues2lchvalues(...values);
1275
1291
  }
1276
1292
  function srgb2oklch(r, g, blue, alpha) {
1277
1293
  // @ts-ignore
@@ -1371,9 +1387,9 @@ function color2oklabToken(token) {
1371
1387
  }
1372
1388
  function oklabToken(values) {
1373
1389
  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] },
1390
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[0]) },
1391
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[1]) },
1392
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[2]) },
1377
1393
  ];
1378
1394
  if (values.length == 4) {
1379
1395
  chi.push({ typ: exports.EnumToken.LiteralTokenType, val: '/' }, {
@@ -1589,9 +1605,9 @@ function color2labToken(token) {
1589
1605
  }
1590
1606
  function labToken(values) {
1591
1607
  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] },
1608
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[0]) },
1609
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[1]) },
1610
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[2]) },
1595
1611
  ];
1596
1612
  if (values.length == 4) {
1597
1613
  chi.push({ typ: exports.EnumToken.LiteralTokenType, val: '/' }, {
@@ -1992,7 +2008,7 @@ function lab2srgbvalues(token) {
1992
2008
  return null;
1993
2009
  }
1994
2010
  const rgb = Lab_to_sRGB(l, a, b);
1995
- if (alpha != null && alpha != 1) {
2011
+ if (alpha != null && alpha < 1) {
1996
2012
  rgb.push(alpha);
1997
2013
  }
1998
2014
  return rgb;
@@ -2072,6 +2088,9 @@ function reduceHexValue(value) {
2072
2088
  value[7] == value[8]) {
2073
2089
  value = `#${value[1]}${value[3]}${value[5]}${value[7] == 'f' ? '' : value[7]}`;
2074
2090
  }
2091
+ if (value.endsWith('ff')) {
2092
+ value = value.slice(0, -2);
2093
+ }
2075
2094
  }
2076
2095
  return named_color != null && named_color.length <= value.length ? named_color : value;
2077
2096
  }
@@ -2492,12 +2511,15 @@ function color2HslToken(token) {
2492
2511
  function hslToken(values) {
2493
2512
  values[0] = toPrecisionAngle(values[0] * 360);
2494
2513
  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 },
2514
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[0]) },
2515
+ { typ: exports.EnumToken.PercentageTokenType, val: toPrecisionValue(values[1]) * 100 },
2516
+ { typ: exports.EnumToken.PercentageTokenType, val: toPrecisionValue(values[2]) * 100 },
2498
2517
  ];
2499
2518
  if (values.length == 4 && values[3] != 1) {
2500
- chi.push({ typ: exports.EnumToken.LiteralTokenType, val: '/' }, { typ: exports.EnumToken.PercentageTokenType, val: values[3] * 100 });
2519
+ chi.push({ typ: exports.EnumToken.LiteralTokenType, val: '/' }, {
2520
+ typ: exports.EnumToken.PercentageTokenType,
2521
+ val: values[3] * 100
2522
+ });
2501
2523
  }
2502
2524
  return {
2503
2525
  typ: exports.EnumToken.ColorTokenType,
@@ -2563,12 +2585,20 @@ function hwb2hslvalues(token) {
2563
2585
  return hsv2hsl(...hwb2hsv(...Object.values(hslvalues(token))));
2564
2586
  }
2565
2587
  function lab2hslvalues(token) {
2588
+ const values = lab2rgbvalues(token);
2589
+ if (values == null) {
2590
+ return null;
2591
+ }
2566
2592
  // @ts-ignore
2567
- return rgbvalues2hslvalues(...lab2rgbvalues(token));
2593
+ return rgbvalues2hslvalues(...values);
2568
2594
  }
2569
2595
  function lch2hslvalues(token) {
2596
+ const values = lch2rgbvalues(token);
2597
+ if (values == null) {
2598
+ return null;
2599
+ }
2570
2600
  // @ts-ignore
2571
- return rgbvalues2hslvalues(...lch2rgbvalues(token));
2601
+ return rgbvalues2hslvalues(...values);
2572
2602
  }
2573
2603
  function oklab2hslvalues(token) {
2574
2604
  const t = oklab2srgbvalues(token);
@@ -2674,8 +2704,8 @@ function hwbToken(values) {
2674
2704
  values[0] = toPrecisionAngle(values[0] * 360);
2675
2705
  const chi = [
2676
2706
  { 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 },
2707
+ { typ: exports.EnumToken.PercentageTokenType, val: toPrecisionValue(values[1]) * 100 },
2708
+ { typ: exports.EnumToken.PercentageTokenType, val: toPrecisionValue(values[2]) * 100 },
2679
2709
  ];
2680
2710
  if (values.length == 4) {
2681
2711
  chi.push({ typ: exports.EnumToken.LiteralTokenType, val: '/' }, {
@@ -3069,11 +3099,10 @@ function colorMix(colorSpace, hueInterpolationMethod, color1, percentage1, color
3069
3099
  // @ts-ignore
3070
3100
  const calculate = () => [colorSpace].concat(values1.map((v1, i) => {
3071
3101
  return {
3072
- // @ts-ignore
3073
- typ: exports.EnumToken.NumberTokenType, val: String((mul1 * v1 * p1 + mul2 * values2[i] * p2) / mul)
3102
+ typ: exports.EnumToken.NumberTokenType, val: (mul1 * v1 * p1 + mul2 * values2[i] * p2) / mul
3074
3103
  };
3075
3104
  }).concat(mul == 1 ? [] : [{
3076
- typ: exports.EnumToken.NumberTokenType, val: String(mul)
3105
+ typ: exports.EnumToken.NumberTokenType, val: mul
3077
3106
  }]));
3078
3107
  switch (colorSpace.val) {
3079
3108
  case 'srgb':
@@ -3816,7 +3845,7 @@ function parseRelativeColor(relativeKeys, original, rExp, gExp, bExp, aExp) {
3816
3845
  let keys = {};
3817
3846
  let values = {};
3818
3847
  // colorFuncColorSpace x,y,z or r,g,b
3819
- const names = relativeKeys.startsWith('xyz') ? 'xyz' : relativeKeys.slice(-3);
3848
+ 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
3849
  const converted = convertColor(original, exports.ColorType[relativeKeys.toUpperCase().replaceAll('-', '_')]);
3821
3850
  if (converted == null) {
3822
3851
  return null;
@@ -3830,13 +3859,13 @@ function parseRelativeColor(relativeKeys, original, rExp, gExp, bExp, aExp) {
3830
3859
  // @ts-ignore
3831
3860
  alpha: alpha == null ? {
3832
3861
  typ: exports.EnumToken.NumberTokenType,
3833
- val: '1'
3862
+ val: 1
3834
3863
  } : (alpha.typ == exports.EnumToken.IdenTokenType && alpha.val == 'none') ? {
3835
3864
  typ: exports.EnumToken.NumberTokenType,
3836
- val: '0'
3865
+ val: 0
3837
3866
  } : (alpha.typ == exports.EnumToken.PercentageTokenType ? {
3838
3867
  typ: exports.EnumToken.NumberTokenType,
3839
- val: String(getNumber(alpha))
3868
+ val: getNumber(alpha)
3840
3869
  } : alpha)
3841
3870
  };
3842
3871
  keys = {
@@ -3846,19 +3875,15 @@ function parseRelativeColor(relativeKeys, original, rExp, gExp, bExp, aExp) {
3846
3875
  // @ts-ignore
3847
3876
  alpha: getValue(aExp == null ? {
3848
3877
  typ: exports.EnumToken.NumberTokenType,
3849
- val: '1'
3878
+ val: 1
3850
3879
  } : (aExp.typ == exports.EnumToken.IdenTokenType && aExp.val == 'none') ? {
3851
3880
  typ: exports.EnumToken.NumberTokenType,
3852
- val: '0'
3881
+ val: 0
3853
3882
  } : aExp)
3854
3883
  };
3855
3884
  return computeComponentValue(keys, converted, values);
3856
3885
  }
3857
3886
  function getValue(t, converted, component) {
3858
- // if (t == null) {
3859
- //
3860
- // return t;
3861
- // }
3862
3887
  if (t.typ == exports.EnumToken.PercentageTokenType) {
3863
3888
  let value = getNumber(t);
3864
3889
  let colorSpace = exports.ColorType[converted.kin].toLowerCase().replaceAll('-', '_');
@@ -3888,55 +3913,13 @@ function computeComponentValue(expr, converted, values) {
3888
3913
  }
3889
3914
  }
3890
3915
  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
3916
  if ([exports.EnumToken.NumberTokenType, exports.EnumToken.PercentageTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.LengthTokenType].includes(exp.typ)) ;
3911
3917
  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
3918
  expr[key] = values[exp.val];
3920
- // }
3921
3919
  }
3922
3920
  else if (exp.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(exp.val)) {
3923
3921
  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
3922
  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
3923
  // @ts-ignore
3941
3924
  replaceValue(parent, value, values[value.val] ?? {
3942
3925
  typ: exports.EnumToken.NumberTokenType,
@@ -3950,10 +3933,6 @@ function computeComponentValue(expr, converted, values) {
3950
3933
  if (result.length == 1 && result[0].typ != exports.EnumToken.BinaryExpressionTokenType) {
3951
3934
  expr[key] = result[0];
3952
3935
  }
3953
- // else {
3954
- //
3955
- // return null;
3956
- // }
3957
3936
  }
3958
3937
  }
3959
3938
  return expr;
@@ -3964,13 +3943,16 @@ function replaceValue(parent, value, newValue) {
3964
3943
  if (pr.typ == exports.EnumToken.BinaryExpressionTokenType) {
3965
3944
  if (pr.l == val) {
3966
3945
  pr.l = newValue;
3946
+ return;
3967
3947
  }
3968
3948
  else {
3969
3949
  pr.r = newValue;
3950
+ return;
3970
3951
  }
3971
3952
  }
3972
3953
  else {
3973
3954
  pr.chi.splice(pr.chi.indexOf(val), 1, newValue);
3955
+ return;
3974
3956
  }
3975
3957
  }
3976
3958
  }
@@ -4058,11 +4040,14 @@ function cmyktoken(values) {
4058
4040
  chi: values.reduce((acc, curr, index) => index < 4 ? [...acc, {
4059
4041
  typ: exports.EnumToken.PercentageTokenType,
4060
4042
  // @ts-ignore
4061
- val: curr * 100
4043
+ val: toPrecisionValue(curr) * 100
4062
4044
  }] : [...acc, {
4063
4045
  typ: exports.EnumToken.LiteralTokenType,
4064
4046
  val: '/'
4065
- }, { typ: exports.EnumToken.PercentageTokenType, val: curr * 100 }], []),
4047
+ }, {
4048
+ typ: exports.EnumToken.PercentageTokenType,
4049
+ val: toPrecisionValue(curr) * 100
4050
+ }], []),
4066
4051
  kin: exports.ColorType.DEVICE_CMYK
4067
4052
  };
4068
4053
  }
@@ -4121,144 +4106,401 @@ function xyz2la98rgb(x, y, z, a = null) {
4121
4106
  return multiplyMatrices(M, [x, y, z]).concat(a == null || a == 1 ? [] : [a]);
4122
4107
  }
4123
4108
 
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;
4109
+ const epsilon = 1e-5;
4110
+ function identity() {
4111
+ return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
4112
+ }
4113
+ function pLength(point) {
4114
+ return Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
4115
+ }
4116
+ function normalize(point) {
4117
+ const [x, y, z] = point;
4118
+ const norm = Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
4119
+ return norm === 0 ? [0, 0, 0] : [x / norm, y / norm, z / norm];
4120
+ }
4121
+ function dot(point1, point2) {
4122
+ if (point1.length === 4 && point2.length === 4) {
4123
+ return point1[0] * point2[0] + point1[1] * point2[1] + point1[2] * point2[2] + point1[3] * point2[3];
4142
4124
  }
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
- }
4125
+ return point1[0] * point2[0] + point1[1] * point2[1] + point1[2] * point2[2];
4126
+ }
4127
+ function multiply(matrixA, matrixB) {
4128
+ let result = new Array(16).fill(0);
4129
+ for (let i = 0; i < 4; i++) {
4130
+ for (let j = 0; j < 4; j++) {
4131
+ for (let k = 0; k < 4; k++) {
4132
+ // Utiliser l'indexation linéaire pour accéder aux éléments
4133
+ // Pour une matrice 4x4, l'index est (row * 4 + col)
4134
+ result[j * 4 + i] += matrixA[k * 4 + i] * matrixB[j * 4 + k];
4152
4135
  }
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
4136
  }
4159
4137
  }
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;
4138
+ return result;
4139
+ }
4140
+ function inverse(matrix) {
4141
+ // Create augmented matrix [matrix | identity]
4142
+ let augmented = [
4143
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
4144
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
4145
+ ];
4146
+ // Gaussian elimination with partial pivoting
4147
+ for (let col = 0; col < 4; col++) {
4148
+ // Find pivot row with maximum absolute value
4149
+ let maxRow = col;
4150
+ let maxVal = Math.abs(augmented[col * 4 + col]);
4151
+ for (let row = col + 1; row < 4; row++) {
4152
+ let val = Math.abs(augmented[row * 4 + col]);
4153
+ if (val > maxVal) {
4154
+ maxVal = val;
4155
+ maxRow = row;
4173
4156
  }
4174
4157
  }
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;
4180
- }
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;
4158
+ // Check for singularity
4159
+ if (maxVal < 1e-5) {
4160
+ return null;
4187
4161
  }
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);
4162
+ // Swap rows if necessary
4163
+ if (maxRow !== col) {
4164
+ [augmented[col], augmented[maxRow]] = [augmented[maxRow], augmented[col]];
4211
4165
  }
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);
4166
+ // Scale pivot row to make pivot element 1
4167
+ let pivot = augmented[col * 4 + col];
4168
+ for (let j = 0; j < 8; j++) {
4169
+ augmented[col * 4 + j] /= pivot;
4236
4170
  }
4237
- }
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);
4171
+ // Eliminate column in other rows
4172
+ for (let row = 0; row < 4; row++) {
4173
+ if (row !== col) {
4174
+ let factor = augmented[row * 4 + col];
4175
+ for (let j = 0; j < 8; j++) {
4176
+ augmented[row * 4 + j] -= factor * augmented[col * 4 + j];
4177
+ }
4178
+ }
4179
+ }
4180
+ }
4181
+ // Extract the inverse from the right side of the augmented matrix
4182
+ return augmented.slice(0, 16);
4183
+ }
4184
+ // function transpose(matrix: Matrix): Matrix {
4185
+ // // Crée une nouvelle matrice vide 4x4
4186
+ // // @ts-ignore
4187
+ // let transposed: Matrix = [[], [], [], []] as Matrix;
4188
+ //
4189
+ // // Parcourt chaque ligne et colonne pour transposer
4190
+ // for (let i = 0; i < 4; i++) {
4191
+ //
4192
+ // for (let j = 0; j < 4; j++) {
4193
+ //
4194
+ // transposed[j][i] = matrix[i][j];
4195
+ // }
4196
+ // }
4197
+ //
4198
+ // return transposed;
4199
+ // }
4200
+ function round(number) {
4201
+ return Math.abs(number) < epsilon ? 0 : +number.toPrecision(6);
4202
+ }
4203
+ // translate3d(25.9808px, 0, 15px ) rotateY(60deg) skewX(49.9999deg) scale(1, 1.2)
4204
+ // translate → rotate → skew → scale
4205
+ function decompose(original) {
4206
+ const matrix = original.slice();
4207
+ // Normalize last row
4208
+ if (matrix[15] === 0) {
4209
+ return null;
4210
+ }
4211
+ for (let i = 0; i < 16; i++)
4212
+ matrix[i] /= matrix[15];
4213
+ // Perspective extraction
4214
+ const perspective = [0, 0, 0, 1];
4215
+ if (matrix[3] !== 0 || matrix[7] !== 0 || matrix[11] !== 0) {
4216
+ const rightHandSide = [matrix[3], matrix[7], matrix[11], matrix[15]];
4217
+ const perspectiveMatrix = matrix.slice();
4218
+ perspectiveMatrix[3] = 0;
4219
+ perspectiveMatrix[7] = 0;
4220
+ perspectiveMatrix[11] = 0;
4221
+ perspectiveMatrix[15] = 1;
4222
+ // @ts-ignore
4223
+ const inverted = inverse(original.slice());
4224
+ if (!inverted) {
4225
+ return null;
4226
+ }
4227
+ const transposedInverse = transposeMatrix4(inverted);
4228
+ perspective[0] = dot(rightHandSide, transposedInverse.slice(0, 4));
4229
+ perspective[1] = dot(rightHandSide, transposedInverse.slice(4, 8));
4230
+ perspective[2] = dot(rightHandSide, transposedInverse.slice(8, 12));
4231
+ perspective[3] = dot(rightHandSide, transposedInverse.slice(12, 16));
4232
+ // Clear perspective from matrix
4233
+ matrix[3] = 0;
4234
+ matrix[7] = 0;
4235
+ matrix[11] = 0;
4236
+ matrix[15] = 1;
4237
+ }
4238
+ // Translation
4239
+ const translate = [matrix[12], matrix[13], matrix[14]];
4240
+ matrix[12] = matrix[13] = matrix[14] = 0;
4241
+ // Build the 3x3 matrix
4242
+ const row0 = [matrix[0], matrix[1], matrix[2]];
4243
+ const row1 = [matrix[4], matrix[5], matrix[6]];
4244
+ const row2 = [matrix[8], matrix[9], matrix[10]];
4245
+ // Compute scale
4246
+ const scaleX = pLength(row0);
4247
+ const row0Norm = normalize(row0);
4248
+ const skewXY = dot(row0Norm, row1);
4249
+ const row1Proj = [
4250
+ row1[0] - skewXY * row0Norm[0],
4251
+ row1[1] - skewXY * row0Norm[1],
4252
+ row1[2] - skewXY * row0Norm[2]
4253
+ ];
4254
+ const scaleY = pLength(row1Proj);
4255
+ const row1Norm = normalize(row1Proj);
4256
+ const skewXZ = dot(row0Norm, row2);
4257
+ const skewYZ = dot(row1Norm, row2);
4258
+ const row2Proj = [
4259
+ row2[0] - skewXZ * row0Norm[0] - skewYZ * row1Norm[0],
4260
+ row2[1] - skewXZ * row0Norm[1] - skewYZ * row1Norm[1],
4261
+ row2[2] - skewXZ * row0Norm[2] - skewYZ * row1Norm[2]
4262
+ ];
4263
+ const scaleZ = pLength(row2Proj);
4264
+ const row2Norm = normalize(row2Proj);
4265
+ // Build rotation matrix from orthonormalized vectors
4266
+ const r00 = row0Norm[0], r01 = row1Norm[0], r02 = row2Norm[0];
4267
+ const r10 = row0Norm[1], r11 = row1Norm[1], r12 = row2Norm[1];
4268
+ const r20 = row0Norm[2], r21 = row1Norm[2], r22 = row2Norm[2];
4269
+ // Convert to quaternion
4270
+ const trace = r00 + r11 + r22;
4271
+ let qw, qx, qy, qz;
4272
+ if (trace > 0) {
4273
+ const s = 0.5 / Math.sqrt(trace + 1.0);
4274
+ qw = 0.25 / s;
4275
+ qx = (r21 - r12) * s;
4276
+ qy = (r02 - r20) * s;
4277
+ qz = (r10 - r01) * s;
4278
+ }
4279
+ else if (r00 > r11 && r00 > r22) {
4280
+ const s = 2.0 * Math.sqrt(1.0 + r00 - r11 - r22);
4281
+ qw = (r21 - r12) / s;
4282
+ qx = 0.25 * s;
4283
+ qy = (r01 + r10) / s;
4284
+ qz = (r02 + r20) / s;
4285
+ }
4286
+ else if (r11 > r22) {
4287
+ const s = 2.0 * Math.sqrt(1.0 + r11 - r00 - r22);
4288
+ qw = (r02 - r20) / s;
4289
+ qx = (r01 + r10) / s;
4290
+ qy = 0.25 * s;
4291
+ qz = (r12 + r21) / s;
4292
+ }
4293
+ else {
4294
+ const s = 2.0 * Math.sqrt(1.0 + r22 - r00 - r11);
4295
+ qw = (r10 - r01) / s;
4296
+ qx = (r02 + r20) / s;
4297
+ qy = (r12 + r21) / s;
4298
+ qz = 0.25 * s;
4299
+ }
4300
+ [qx, qy, qz] = toZero([qx, qy, qz]);
4301
+ // const q = gcd(qx, gcd(qy, qz));
4302
+ let q = [Math.abs(qx), Math.abs(qy), Math.abs(qz)].reduce((acc, curr) => {
4303
+ if (acc == 0 || (curr > 0 && curr < acc)) {
4304
+ acc = curr;
4305
+ }
4306
+ return acc;
4307
+ }, 0);
4308
+ if (q > 0) {
4309
+ qx /= q;
4310
+ qy /= q;
4311
+ qz /= q;
4312
+ }
4313
+ const rotate = [qx, qy, qz, Object.is(qw, 0) ? 0 : 2 * Math.acos(qw) * 180 / Math.PI];
4314
+ const scale = [scaleX, scaleY, scaleZ];
4315
+ const skew = [skewXY, skewXZ, skewYZ];
4316
+ return {
4317
+ translate,
4318
+ scale,
4319
+ rotate,
4320
+ skew,
4321
+ perspective
4322
+ };
4323
+ }
4324
+ function transposeMatrix4(m) {
4325
+ return [
4326
+ m[0], m[4], m[8], m[12],
4327
+ m[1], m[5], m[9], m[13],
4328
+ m[2], m[6], m[10], m[14],
4329
+ m[3], m[7], m[11], m[15],
4330
+ ];
4331
+ }
4332
+ function toZero(v) {
4333
+ for (let i = 0; i < v.length; i++) {
4334
+ if (Math.abs(v[i]) <= epsilon) {
4335
+ v[i] = 0;
4336
+ }
4337
+ else {
4338
+ v[i] = +v[i].toPrecision(6);
4339
+ }
4340
+ }
4341
+ return v;
4342
+ }
4343
+ // https://drafts.csswg.org/css-transforms-1/#2d-matrix
4344
+ function is2DMatrix(matrix) {
4345
+ // m13,m14, m23, m24, m31, m32, m34, m43 are all 0
4346
+ return matrix[0 * 4 + 2] === 0 &&
4347
+ matrix[0 * 4 + 3] === 0 &&
4348
+ matrix[1 * 4 + 2] === 0 &&
4349
+ matrix[1 * 4 + 3] === 0 &&
4350
+ matrix[2 * 4 + 0] === 0 &&
4351
+ matrix[2 * 4 + 1] === 0 &&
4352
+ matrix[2 * 4 + 3] === 0 &&
4353
+ matrix[3 * 4 + 2] === 0 &&
4354
+ matrix[2 * 4 + 2] === 1 &&
4355
+ matrix[3 * 4 + 3] === 1;
4356
+ }
4357
+
4358
+ /**
4359
+ * Converts a color to another color space
4360
+ * @param token
4361
+ * @param to
4362
+ *
4363
+ * @private
4364
+ *
4365
+ * <code>
4366
+ *
4367
+ * const token = {typ: EnumToken.ColorTokenType, kin: ColorType.HEX, val: '#F00'}
4368
+ * const result = convertColor(token, ColorType.LCH);
4369
+ *
4370
+ * </code>
4371
+ */
4372
+ function convertColor(token, to) {
4373
+ if (token.kin == exports.ColorType.SYS ||
4374
+ token.kin == exports.ColorType.DPSYS ||
4375
+ (isIdentColor(token) &&
4376
+ 'currentcolor' == token.val.toLowerCase())) {
4377
+ return token;
4378
+ }
4379
+ if (token.kin == exports.ColorType.COLOR_MIX && to != exports.ColorType.COLOR_MIX) {
4380
+ const children = token.chi.reduce((acc, t) => {
4381
+ if (t.typ == exports.EnumToken.ColorTokenType) {
4382
+ acc.push([t]);
4383
+ }
4384
+ else {
4385
+ if (![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType, exports.EnumToken.CommaTokenType].includes(t.typ)) {
4386
+ acc[acc.length - 1].push(t);
4387
+ }
4388
+ }
4389
+ return acc;
4390
+ }, [[]]);
4391
+ token = colorMix(children[0][1], children[0][2], children[1][0], children[1][1], children[2][0], children[2][1]);
4392
+ if (token == null) {
4393
+ return null;
4394
+ }
4395
+ }
4396
+ if (token.cal == 'rel' && ['rgb', 'hsl', 'hwb', 'lab', 'lch', 'oklab', 'oklch', 'color'].includes(token.val.toLowerCase())) {
4397
+ const chi = getComponents(token);
4398
+ const offset = token.val == 'color' ? 2 : 1;
4399
+ if (chi != null) {
4400
+ // @ts-ignore
4401
+ const color = chi[1];
4402
+ 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]);
4403
+ if (components != null) {
4404
+ token = {
4405
+ ...token,
4406
+ chi: [...(token.val == 'color' ? [chi[offset]] : []), ...Object.values(components)],
4407
+ kin: exports.ColorType[token.val.toUpperCase().replaceAll('-', '_')]
4408
+ };
4409
+ delete token.cal;
4410
+ }
4411
+ }
4412
+ }
4413
+ if (token.kin == to) {
4414
+ if (token.kin == exports.ColorType.HEX || token.kin == exports.ColorType.LIT) {
4415
+ token.val = reduceHexValue(token.val);
4416
+ token.kin = token.val[0] == '#' ? exports.ColorType.HEX : exports.ColorType.LIT;
4417
+ }
4418
+ return token;
4419
+ }
4420
+ if (token.kin == exports.ColorType.COLOR) {
4421
+ const colorSpace = token.chi.find(t => ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(t.typ));
4422
+ if (colorSpace.val == exports.ColorType[to].toLowerCase().replaceAll('_', '-')) {
4423
+ for (const chi of token.chi) {
4424
+ if (chi.typ == exports.EnumToken.NumberTokenType && typeof chi.val == 'number') {
4425
+ chi.val = toPrecisionValue(getNumber(chi));
4426
+ }
4427
+ }
4428
+ return token;
4429
+ }
4430
+ }
4431
+ if (to == exports.ColorType.HSL) {
4432
+ switch (token.kin) {
4433
+ case exports.ColorType.RGB:
4434
+ case exports.ColorType.RGBA:
4435
+ return rgb2HslToken(token);
4436
+ case exports.ColorType.HEX:
4437
+ case exports.ColorType.LIT:
4438
+ return hex2HslToken(token);
4439
+ case exports.ColorType.HWB:
4440
+ return hwb2HslToken(token);
4441
+ case exports.ColorType.DEVICE_CMYK:
4442
+ return cmyk2HslToken(token);
4443
+ case exports.ColorType.OKLAB:
4444
+ return oklab2HslToken(token);
4445
+ case exports.ColorType.OKLCH:
4446
+ return oklch2HslToken(token);
4447
+ case exports.ColorType.LAB:
4448
+ return lab2HslToken(token);
4449
+ case exports.ColorType.LCH:
4450
+ return lch2HslToken(token);
4451
+ case exports.ColorType.COLOR:
4452
+ return color2HslToken(token);
4453
+ }
4454
+ }
4455
+ else if (to == exports.ColorType.HWB) {
4456
+ switch (token.kin) {
4457
+ case exports.ColorType.RGB:
4458
+ case exports.ColorType.RGBA:
4459
+ return rgb2hwbToken(token);
4460
+ case exports.ColorType.HEX:
4461
+ case exports.ColorType.LIT:
4462
+ return rgb2hwbToken(token);
4463
+ case exports.ColorType.HSL:
4464
+ case exports.ColorType.HSLA:
4465
+ return hsl2hwbToken(token);
4466
+ case exports.ColorType.OKLAB:
4467
+ return oklab2hwbToken(token);
4468
+ case exports.ColorType.OKLCH:
4469
+ return oklch2hwbToken(token);
4470
+ case exports.ColorType.LAB:
4471
+ return lab2hwbToken(token);
4472
+ case exports.ColorType.LCH:
4473
+ return lch2hwbToken(token);
4474
+ case exports.ColorType.DEVICE_CMYK:
4475
+ return cmyk2hwbToken(token);
4476
+ case exports.ColorType.COLOR:
4477
+ return color2hwbToken(token);
4478
+ }
4479
+ }
4480
+ else if (to == exports.ColorType.DEVICE_CMYK) {
4481
+ switch (token.kin) {
4482
+ case exports.ColorType.RGB:
4483
+ case exports.ColorType.RGBA:
4484
+ return rgb2cmykToken(token);
4485
+ case exports.ColorType.HEX:
4486
+ case exports.ColorType.LIT:
4487
+ return rgb2cmykToken(token);
4488
+ case exports.ColorType.HSL:
4489
+ case exports.ColorType.HSLA:
4490
+ return hsl2cmykToken(token);
4491
+ case exports.ColorType.HWB:
4492
+ return hwb2cmykToken(token);
4493
+ case exports.ColorType.OKLAB:
4494
+ return oklab2cmyk(token);
4495
+ case exports.ColorType.OKLCH:
4496
+ return oklch2cmykToken(token);
4497
+ case exports.ColorType.LAB:
4498
+ return lab2cmykToken(token);
4499
+ //
4500
+ case exports.ColorType.LCH:
4501
+ return lch2cmykToken(token);
4502
+ case exports.ColorType.COLOR:
4503
+ return color2cmykToken(token);
4262
4504
  }
4263
4505
  }
4264
4506
  else if (to == exports.ColorType.HEX || to == exports.ColorType.LIT) {
@@ -4606,9 +4848,9 @@ function color2srgbvalues(token) {
4606
4848
  function values2colortoken(values, to) {
4607
4849
  values = srgb2srgbcolorspace(values, to);
4608
4850
  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] },
4851
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[0]) },
4852
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[1]) },
4853
+ { typ: exports.EnumToken.NumberTokenType, val: toPrecisionValue(values[2]) },
4612
4854
  ];
4613
4855
  if (values.length == 4) {
4614
4856
  chi.push({ typ: exports.EnumToken.LiteralTokenType, val: "/" }, {
@@ -4633,8 +4875,17 @@ function getNumber(token) {
4633
4875
  if (token.typ == exports.EnumToken.IdenTokenType && token.val == 'none') {
4634
4876
  return 0;
4635
4877
  }
4878
+ let val;
4636
4879
  // @ts-ignore
4637
- return token.typ == exports.EnumToken.PercentageTokenType ? token.val / 100 : token.val;
4880
+ if (typeof token.val != 'number' && token.val?.typ == exports.EnumToken.FractionTokenType) {
4881
+ // @ts-ignore
4882
+ val = token.val.l.val / token.val.r.val;
4883
+ }
4884
+ else {
4885
+ val = token.val;
4886
+ }
4887
+ // @ts-ignore
4888
+ return token.typ == exports.EnumToken.PercentageTokenType ? val / 100 : val;
4638
4889
  }
4639
4890
  /**
4640
4891
  * convert angle to turn
@@ -4665,6 +4916,10 @@ function getAngle(token) {
4665
4916
  // @ts-ignore
4666
4917
  return token.val / 360;
4667
4918
  }
4919
+ function toPrecisionValue(value) {
4920
+ value = +value.toFixed(colorPrecision);
4921
+ return Math.abs(value) < epsilon ? 0 : value;
4922
+ }
4668
4923
  function toPrecisionAngle(angle) {
4669
4924
  angle = +angle.toPrecision(colorPrecision);
4670
4925
  if (Math.abs(angle) >= 360) {
@@ -7477,7 +7732,7 @@ function doRender(data, options = {}) {
7477
7732
  function updateSourceMap(node, options, cache, sourcemap, position, str) {
7478
7733
  if ([
7479
7734
  exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType,
7480
- exports.EnumToken.KeyFrameRuleNodeType, exports.EnumToken.KeyframeAtRuleNodeType
7735
+ exports.EnumToken.KeyFramesRuleNodeType, exports.EnumToken.KeyframesAtRuleNodeType
7481
7736
  ].includes(node.typ)) {
7482
7737
  let src = node.loc?.src ?? '';
7483
7738
  let output = options.output ?? '';
@@ -7551,9 +7806,9 @@ function renderAstNode(data, options, sourcemap, position, errors, reducer, cach
7551
7806
  }, '');
7552
7807
  case exports.EnumToken.AtRuleNodeType:
7553
7808
  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)) {
7809
+ case exports.EnumToken.KeyFramesRuleNodeType:
7810
+ case exports.EnumToken.KeyframesAtRuleNodeType:
7811
+ if ([exports.EnumToken.AtRuleNodeType, exports.EnumToken.KeyframesAtRuleNodeType].includes(data.typ) && !('chi' in data)) {
7557
7812
  return `${indent}@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val};`;
7558
7813
  }
7559
7814
  // @ts-ignore
@@ -7594,7 +7849,7 @@ function renderAstNode(data, options, sourcemap, position, errors, reducer, cach
7594
7849
  if (children.endsWith(';')) {
7595
7850
  children = children.slice(0, -1);
7596
7851
  }
7597
- if ([exports.EnumToken.AtRuleNodeType, exports.EnumToken.KeyframeAtRuleNodeType].includes(data.typ)) {
7852
+ if ([exports.EnumToken.AtRuleNodeType, exports.EnumToken.KeyframesAtRuleNodeType].includes(data.typ)) {
7598
7853
  return `@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val}${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
7599
7854
  }
7600
7855
  return data.sel + `${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
@@ -8563,7 +8818,7 @@ async function* tokenizeStream(input) {
8563
8818
  const reader = input.getReader();
8564
8819
  while (true) {
8565
8820
  const { done, value } = await reader.read();
8566
- parseInfo.stream += decoder.decode(value, { stream: true });
8821
+ parseInfo.stream += ArrayBuffer.isView(value) ? decoder.decode(value, { stream: true }) : value;
8567
8822
  yield* tokenize$1(parseInfo, done);
8568
8823
  if (done) {
8569
8824
  break;
@@ -10192,6 +10447,9 @@ var declarations = {
10192
10447
  "text-anchor": {
10193
10448
  syntax: "start | middle | end"
10194
10449
  },
10450
+ "text-autospace": {
10451
+ syntax: "normal | <autospace> | auto"
10452
+ },
10195
10453
  "text-box": {
10196
10454
  syntax: "normal | <'text-box-trim'> || <'text-box-edge'>"
10197
10455
  },
@@ -12759,19 +13017,8 @@ var atRules = {
12759
13017
  }
12760
13018
  }
12761
13019
  },
12762
- charset: {
12763
- syntax: "<string>"
12764
- },
12765
- container: {
12766
- syntax: "[ <container-name> ]? <container-condition>"
12767
- },
12768
- nest: {
13020
+ "@nest": {
12769
13021
  syntax: "<complex-selector-list>"
12770
- },
12771
- scope: {
12772
- syntax: "[ ( <scope-start> ) ]? [ to ( <scope-end> ) ]?"
12773
- },
12774
- "position-try": {
12775
13022
  }
12776
13023
  };
12777
13024
  var config$3 = {
@@ -14367,12 +14614,14 @@ const matchUrl = /^(https?:)?\/\//;
14367
14614
  /**
14368
14615
  * return the directory name of a path
14369
14616
  * @param path
14370
- * @internal
14617
+ *
14618
+ * @private
14371
14619
  */
14372
14620
  function dirname(path) {
14373
- if (path == '/' || path === '') {
14374
- return path;
14375
- }
14621
+ // if (path == '/' || path === '') {
14622
+ //
14623
+ // return path;
14624
+ // }
14376
14625
  let i = 0;
14377
14626
  let parts = [''];
14378
14627
  for (; i < path.length; i++) {
@@ -14470,17 +14719,19 @@ function resolve(url, currentDirectory, cwd) {
14470
14719
 
14471
14720
  /**
14472
14721
  * feature walk mode
14722
+ *
14723
+ * @internal
14473
14724
  */
14474
14725
  exports.FeatureWalkMode = void 0;
14475
14726
  (function (FeatureWalkMode) {
14476
14727
  /**
14477
14728
  * pre process
14478
14729
  */
14479
- FeatureWalkMode[FeatureWalkMode["Pre"] = 0] = "Pre";
14730
+ FeatureWalkMode[FeatureWalkMode["Pre"] = 1] = "Pre";
14480
14731
  /**
14481
14732
  * post process
14482
14733
  */
14483
- FeatureWalkMode[FeatureWalkMode["Post"] = 1] = "Post";
14734
+ FeatureWalkMode[FeatureWalkMode["Post"] = 2] = "Post";
14484
14735
  })(exports.FeatureWalkMode || (exports.FeatureWalkMode = {}));
14485
14736
 
14486
14737
  const config$2 = getSyntaxConfig();
@@ -17189,6 +17440,37 @@ const enumTokenHints = new Set([
17189
17440
  function reject(reason) {
17190
17441
  throw new Error(reason ?? 'Parsing aborted');
17191
17442
  }
17443
+ function normalizeVisitorKeyName(keyName) {
17444
+ return keyName.replace(/-([a-z])/g, (all, one) => one.toUpperCase());
17445
+ }
17446
+ function replaceToken(parent, value, replacement) {
17447
+ // @ts-ignore
17448
+ if ('parent' in value && value.parent != replacement.parent) {
17449
+ Object.defineProperty(replacement, 'parent', {
17450
+ ...definedPropertySettings,
17451
+ value: value.parent
17452
+ });
17453
+ }
17454
+ if (parent.typ == exports.EnumToken.BinaryExpressionTokenType) {
17455
+ if (parent.l == value) {
17456
+ parent.l = replacement;
17457
+ }
17458
+ else {
17459
+ parent.r = replacement;
17460
+ }
17461
+ }
17462
+ else {
17463
+ // @ts-ignore
17464
+ const target = 'val' in parent && Array.isArray(parent.val) ? parent.val : parent.chi;
17465
+ // @ts-ignore
17466
+ const index = target.indexOf(value);
17467
+ if (index == -1) {
17468
+ return;
17469
+ }
17470
+ // @ts-ignore
17471
+ target.splice(index, 1, ...(Array.isArray(replacement) ? replacement : [replacement]));
17472
+ }
17473
+ }
17192
17474
  /**
17193
17475
  * parse css string
17194
17476
  * @param iter
@@ -17271,7 +17553,7 @@ async function doParse(iter, options = {}) {
17271
17553
  const rawTokens = [];
17272
17554
  const imports = [];
17273
17555
  // @ts-ignore ignore error
17274
- const isAsync = typeof iter[Symbol.asyncIterator] === 'function';
17556
+ let isAsync = typeof iter[Symbol.asyncIterator] === 'function';
17275
17557
  while (item = isAsync ? (await iter.next()).value : iter.next().value) {
17276
17558
  stats.bytesIn = item.bytesIn;
17277
17559
  rawTokens.push(item);
@@ -17390,21 +17672,18 @@ async function doParse(iter, options = {}) {
17390
17672
  const token = node.tokens[0];
17391
17673
  const url = token.typ == exports.EnumToken.StringTokenType ? token.val.slice(1, -1) : token.val;
17392
17674
  try {
17393
- const root = await options.getStream(url, options.src).then(async (stream) => {
17394
- return doParse(tokenizeStream(stream), Object.assign({}, options, {
17395
- minify: false,
17396
- setParent: false,
17397
- src: options.resolve(url, options.src).absolute
17398
- })); // )
17399
- });
17400
- // const root: ParseResult = await options.load!(url, <string>options.src).then((src: string) => {
17401
- //
17402
- // return doParse(src, Object.assign({}, options, {
17403
- // minify: false,
17404
- // setParent: false,
17405
- // src: options.resolve!(url, options.src as string).absolute
17406
- // }))
17407
- // });
17675
+ const result = options.load(url, options.src);
17676
+ const stream = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction' ? await result : result;
17677
+ const root = await doParse(stream instanceof ReadableStream ? tokenizeStream(stream) : tokenize$1({
17678
+ stream,
17679
+ buffer: '',
17680
+ position: { ind: 0, lin: 1, col: 1 },
17681
+ currentPosition: { ind: -1, lin: 1, col: 0 }
17682
+ }), Object.assign({}, options, {
17683
+ minify: false,
17684
+ setParent: false,
17685
+ src: options.resolve(url, options.src).absolute
17686
+ }));
17408
17687
  stats.importedBytesIn += root.stats.bytesIn;
17409
17688
  stats.imports.push(root.stats);
17410
17689
  node.parent.chi.splice(node.parent.chi.indexOf(node), 1, ...root.ast.chi);
@@ -17432,39 +17711,230 @@ async function doParse(iter, options = {}) {
17432
17711
  if (options.expandNestingRules) {
17433
17712
  ast = expand(ast);
17434
17713
  }
17714
+ const valuesHandlers = new Map;
17715
+ const preValuesHandlers = new Map;
17716
+ const postValuesHandlers = new Map;
17717
+ const preVisitorsHandlersMap = new Map;
17718
+ const visitorsHandlersMap = new Map;
17719
+ const postVisitorsHandlersMap = new Map;
17720
+ const allValuesHandlers = [];
17435
17721
  if (options.visitor != null) {
17436
- for (const result of walk(ast)) {
17437
- if (result.node.typ == exports.EnumToken.DeclarationNodeType &&
17438
- (typeof options.visitor.Declaration == 'function' || options.visitor.Declaration?.[result.node.nam] != null)) {
17439
- const callable = typeof options.visitor.Declaration == 'function' ? options.visitor.Declaration : options.visitor.Declaration[result.node.nam];
17440
- const isAsync = Object.getPrototypeOf(callable).constructor.name == 'AsyncFunction';
17441
- const results = isAsync ? await callable(result.node) : callable(result.node);
17442
- if (results == null || (Array.isArray(results) && results.length == 0)) {
17443
- continue;
17722
+ for (const [key, value] of Object.entries(options.visitor)) {
17723
+ if (key in exports.EnumToken) {
17724
+ if (typeof value == 'function') {
17725
+ valuesHandlers.set(exports.EnumToken[key], value);
17726
+ }
17727
+ else if (typeof value == 'object' && 'type' in value && 'handler' in value && value.type in exports.WalkerValueEvent) {
17728
+ if (exports.WalkerValueEvent[value.type] == exports.WalkerValueEvent.Enter) {
17729
+ preValuesHandlers.set(exports.EnumToken[key], value.handler);
17730
+ }
17731
+ else if (exports.WalkerValueEvent[value.type] == exports.WalkerValueEvent.Leave) {
17732
+ postValuesHandlers.set(exports.EnumToken[key], value.handler);
17733
+ }
17734
+ }
17735
+ else {
17736
+ console.warn(`doParse: visitor.${key} is not a valid key name`);
17737
+ }
17738
+ }
17739
+ else if (['Declaration', 'Rule', 'AtRule', 'KeyframesRule', 'KeyframesAtRule'].includes(key)) {
17740
+ if (typeof value == 'function') {
17741
+ visitorsHandlersMap.set(key, value);
17742
+ }
17743
+ else if (typeof value == 'object') {
17744
+ if ('type' in value && 'handler' in value && value.type in exports.WalkerValueEvent) {
17745
+ if (exports.WalkerValueEvent[value.type] == exports.WalkerValueEvent.Enter) {
17746
+ preVisitorsHandlersMap.set(key, value.handler);
17747
+ }
17748
+ else if (exports.WalkerValueEvent[value.type] == exports.WalkerValueEvent.Leave) {
17749
+ postVisitorsHandlersMap.set(key, value.handler);
17750
+ }
17751
+ }
17752
+ else {
17753
+ visitorsHandlersMap.set(key, value);
17754
+ }
17755
+ }
17756
+ else {
17757
+ console.warn(`doParse: visitor.${key} is not a valid key name`);
17758
+ }
17759
+ }
17760
+ else {
17761
+ console.warn(`doParse: visitor.${key} is not a valid key name`);
17762
+ }
17763
+ }
17764
+ if (preValuesHandlers.size > 0) {
17765
+ allValuesHandlers.push(preValuesHandlers);
17766
+ }
17767
+ if (valuesHandlers.size > 0) {
17768
+ allValuesHandlers.push(valuesHandlers);
17769
+ }
17770
+ if (postValuesHandlers.size > 0) {
17771
+ allValuesHandlers.push(postValuesHandlers);
17772
+ }
17773
+ }
17774
+ for (const result of walk(ast)) {
17775
+ // if (result.parent != null && !isNodeAllowedInContext(result.node, result.parent as AstNode)) {
17776
+ //
17777
+ // errors.push({
17778
+ // action: 'drop',
17779
+ // message: `${EnumToken[result.parent.typ]}: child ${EnumToken[result.node.typ]}${result.node.typ == EnumToken.DeclarationNodeType ? ` '${(result.node as AstDeclaration).nam}'` : result.node.typ == EnumToken.AtRuleNodeType || result.node.typ == EnumToken.KeyframesAtRuleNodeType ? ` '@${(result.node as AstAtRule).nam}'` : ''} not allowed in context${result.parent.typ == EnumToken.AtRuleNodeType ? ` '@${(result.parent as AstAtRule).nam}'` : result.parent.typ == EnumToken.StyleSheetNodeType ? ` 'stylesheet'` : ''}`,
17780
+ // // @ts-ignore
17781
+ // location: result.node.loc ?? map.get(result.node ) ?? null
17782
+ // });
17783
+ //
17784
+ // // @ts-ignore
17785
+ // removeNode(result.node, result.parent as AstNode);
17786
+ // continue;
17787
+ // }
17788
+ if (allValuesHandlers.length > 0 || preVisitorsHandlersMap.size > 0 || visitorsHandlersMap.size > 0 || postVisitorsHandlersMap.size > 0) {
17789
+ if ((result.node.typ == exports.EnumToken.DeclarationNodeType &&
17790
+ (preVisitorsHandlersMap.has('Declaration') || visitorsHandlersMap.has('Declaration') || postVisitorsHandlersMap.has('Declaration'))) ||
17791
+ (result.node.typ == exports.EnumToken.AtRuleNodeType && (preVisitorsHandlersMap.has('AtRule') || visitorsHandlersMap.has('AtRule') || postVisitorsHandlersMap.has('AtRule'))) ||
17792
+ (result.node.typ == exports.EnumToken.KeyframesAtRuleNodeType && (preVisitorsHandlersMap.has('KeyframesAtRule') || visitorsHandlersMap.has('KeyframesAtRule') || postVisitorsHandlersMap.has('KeyframesAtRule')))) {
17793
+ const handlers = [];
17794
+ const key = result.node.typ == exports.EnumToken.DeclarationNodeType ? 'Declaration' : result.node.typ == exports.EnumToken.AtRuleNodeType ? 'AtRule' : 'KeyframesAtRule';
17795
+ if (preVisitorsHandlersMap.has(key)) {
17796
+ // @ts-ignore
17797
+ handlers.push(preVisitorsHandlersMap.get(key));
17798
+ }
17799
+ if (visitorsHandlersMap.has(key)) {
17800
+ // @ts-ignore
17801
+ handlers.push(visitorsHandlersMap.get(key));
17802
+ }
17803
+ if (postVisitorsHandlersMap.has(key)) {
17804
+ // @ts-ignore
17805
+ handlers.push(postVisitorsHandlersMap.get(key));
17806
+ }
17807
+ let callable;
17808
+ let node = result.node;
17809
+ for (const handler of handlers) {
17810
+ callable = typeof handler == 'function' ? handler : handler[normalizeVisitorKeyName(node.typ == exports.EnumToken.DeclarationNodeType || node.typ == exports.EnumToken.AtRuleNodeType ? node.nam : node.val)];
17811
+ if (callable == null) {
17812
+ continue;
17813
+ }
17814
+ let replacement = callable(node, result.parent);
17815
+ if (replacement == null) {
17816
+ continue;
17817
+ }
17818
+ isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
17819
+ if (replacement) {
17820
+ replacement = await replacement;
17821
+ }
17822
+ if (replacement == null || replacement == node) {
17823
+ continue;
17824
+ }
17825
+ // @ts-ignore
17826
+ node = replacement;
17827
+ //
17828
+ if (Array.isArray(node)) {
17829
+ break;
17830
+ }
17831
+ }
17832
+ if (node != result.node) {
17833
+ // @ts-ignore
17834
+ replaceToken(result.parent, result.node, node);
17444
17835
  }
17445
- // @ts-ignore
17446
- result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
17447
17836
  }
17448
- else if (options.visitor.Rule != null && result.node.typ == exports.EnumToken.RuleNodeType) {
17449
- const isAsync = Object.getPrototypeOf(options.visitor.Rule).constructor.name == 'AsyncFunction';
17450
- const results = isAsync ? await options.visitor.Rule(result.node) : options.visitor.Rule(result.node);
17451
- if (results == null || (Array.isArray(results) && results.length == 0)) {
17452
- continue;
17837
+ else if ((result.node.typ == exports.EnumToken.RuleNodeType && (preVisitorsHandlersMap.has('Rule') || visitorsHandlersMap.has('Rule') || postVisitorsHandlersMap.has('Rule'))) ||
17838
+ (result.node.typ == exports.EnumToken.KeyFramesRuleNodeType && (preVisitorsHandlersMap.has('KeyframesRule') || visitorsHandlersMap.has('KeyframesRule') || postVisitorsHandlersMap.has('KeyframesRule')))) {
17839
+ const handlers = [];
17840
+ const key = result.node.typ == exports.EnumToken.RuleNodeType ? 'Rule' : 'KeyframesRule';
17841
+ if (preVisitorsHandlersMap.has(key)) {
17842
+ // @ts-ignore
17843
+ handlers.push(preVisitorsHandlersMap.get(key));
17844
+ }
17845
+ if (visitorsHandlersMap.has(key)) {
17846
+ // @ts-ignore
17847
+ handlers.push(visitorsHandlersMap.get(key));
17848
+ }
17849
+ if (postVisitorsHandlersMap.has(key)) {
17850
+ // @ts-ignore
17851
+ handlers.push(postVisitorsHandlersMap.get(key));
17852
+ }
17853
+ let node = result.node;
17854
+ for (const callable of handlers) {
17855
+ // @ts-ignore
17856
+ let replacement = callable(node, result.parent);
17857
+ if (replacement == null) {
17858
+ continue;
17859
+ }
17860
+ isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
17861
+ if (replacement) {
17862
+ replacement = await replacement;
17863
+ }
17864
+ if (replacement == null || replacement == node) {
17865
+ continue;
17866
+ }
17867
+ // @ts-ignore
17868
+ node = replacement;
17869
+ //
17870
+ if (Array.isArray(node)) {
17871
+ break;
17872
+ }
17453
17873
  }
17454
17874
  // @ts-ignore
17455
- result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
17456
- }
17457
- else if (options.visitor.AtRule != null &&
17458
- result.node.typ == exports.EnumToken.AtRuleNodeType &&
17459
- (typeof options.visitor.AtRule == 'function' || options.visitor.AtRule?.[result.node.nam] != null)) {
17460
- const callable = typeof options.visitor.AtRule == 'function' ? options.visitor.AtRule : options.visitor.AtRule[result.node.nam];
17461
- const isAsync = Object.getPrototypeOf(callable).constructor.name == 'AsyncFunction';
17462
- const results = isAsync ? await callable(result.node) : callable(result.node);
17463
- if (results == null || (Array.isArray(results) && results.length == 0)) {
17875
+ if (node != result.node) {
17876
+ // @ts-ignore
17877
+ replaceToken(result.parent, result.node, node);
17878
+ }
17879
+ }
17880
+ else if (allValuesHandlers.length > 0) {
17881
+ let callable;
17882
+ let node = null;
17883
+ node = result.node;
17884
+ for (const valueHandler of allValuesHandlers) {
17885
+ if (valueHandler.has(node.typ)) {
17886
+ callable = valueHandler.get(node.typ);
17887
+ let replacement = callable(node, result.parent);
17888
+ if (replacement == null) {
17889
+ continue;
17890
+ }
17891
+ isAsync = replacement instanceof Promise || Object.getPrototypeOf(replacement).constructor.name == 'AsyncFunction';
17892
+ if (isAsync) {
17893
+ replacement = await replacement;
17894
+ }
17895
+ if (replacement != null && replacement != node) {
17896
+ node = replacement;
17897
+ }
17898
+ }
17899
+ }
17900
+ if (node != result.node) {
17901
+ // @ts-ignore
17902
+ replaceToken(result.parent, value, node);
17903
+ }
17904
+ const tokens = 'tokens' in result.node ? result.node.tokens : [];
17905
+ if ('val' in result.node && Array.isArray(result.node.val)) {
17906
+ tokens.push(...result.node.val);
17907
+ }
17908
+ if (tokens.length == 0) {
17464
17909
  continue;
17465
17910
  }
17466
- // @ts-ignore
17467
- result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
17911
+ for (const { value, parent, root } of walkValues(tokens, result.node)) {
17912
+ node = value;
17913
+ for (const valueHandler of allValuesHandlers) {
17914
+ if (valueHandler.has(node.typ)) {
17915
+ callable = valueHandler.get(node.typ);
17916
+ let result = callable(node, parent, root);
17917
+ if (result == null) {
17918
+ continue;
17919
+ }
17920
+ isAsync = result instanceof Promise || Object.getPrototypeOf(result).constructor.name == 'AsyncFunction';
17921
+ if (isAsync) {
17922
+ result = await result;
17923
+ }
17924
+ if (result != null && result != node) {
17925
+ node = result;
17926
+ }
17927
+ //
17928
+ if (Array.isArray(node)) {
17929
+ break;
17930
+ }
17931
+ }
17932
+ }
17933
+ if (node != value) {
17934
+ // @ts-ignore
17935
+ replaceToken(parent, value, node);
17936
+ }
17937
+ }
17468
17938
  }
17469
17939
  }
17470
17940
  }
@@ -17524,7 +17994,6 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
17524
17994
  continue;
17525
17995
  }
17526
17996
  loc = location;
17527
- // @ts-ignore
17528
17997
  context.chi.push(tokens[i]);
17529
17998
  if (options.sourcemap) {
17530
17999
  tokens[i].loc = loc;
@@ -17558,9 +18027,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
17558
18027
  rawTokens.shift();
17559
18028
  if (atRule.val == 'import') {
17560
18029
  // only @charset and @layer are accepted before @import
17561
- // @ts-ignore
17562
18030
  if (context.chi.length > 0) {
17563
- // @ts-ignore
17564
18031
  let i = context.chi.length;
17565
18032
  while (i--) {
17566
18033
  // @ts-ignore
@@ -17569,11 +18036,8 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
17569
18036
  continue;
17570
18037
  }
17571
18038
  if (type != exports.EnumToken.AtRuleNodeType) {
17572
- // @ts-ignore
17573
18039
  if (!(type == exports.EnumToken.InvalidAtRuleTokenType &&
17574
- // @ts-ignore
17575
18040
  ['charset', 'layer', 'import'].includes(context.chi[i].nam))) {
17576
- // @ts-ignore
17577
18041
  errors.push({
17578
18042
  action: 'drop',
17579
18043
  message: 'invalid @import',
@@ -17584,7 +18048,6 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
17584
18048
  return null;
17585
18049
  }
17586
18050
  }
17587
- // @ts-ignore
17588
18051
  const name = context.chi[i].nam;
17589
18052
  if (name != 'charset' && name != 'import' && name != 'layer') {
17590
18053
  errors.push({ action: 'drop', message: 'invalid @import', location });
@@ -17682,7 +18145,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
17682
18145
  const nam = renderToken(atRule, { removeComments: true });
17683
18146
  // @ts-ignore
17684
18147
  const node = {
17685
- typ: /^(-[a-z]+-)?keyframes$/.test(nam) ? exports.EnumToken.KeyframeAtRuleNodeType : exports.EnumToken.AtRuleNodeType,
18148
+ typ: /^(-[a-z]+-)?keyframes$/.test(nam) ? exports.EnumToken.KeyframesAtRuleNodeType : exports.EnumToken.AtRuleNodeType,
17686
18149
  nam,
17687
18150
  val: raw.join('')
17688
18151
  };
@@ -17716,7 +18179,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
17716
18179
  error: '',
17717
18180
  node,
17718
18181
  syntax: '@' + node.nam
17719
- } : isValid ? (node.typ == exports.EnumToken.KeyframeAtRuleNodeType ? validateAtRuleKeyframes(node) : validateAtRule(node, options, context)) : {
18182
+ } : isValid ? (node.typ == exports.EnumToken.KeyframesAtRuleNodeType ? validateAtRuleKeyframes(node) : validateAtRule(node, options, context)) : {
17720
18183
  valid: SyntaxValidationResult.Drop,
17721
18184
  node,
17722
18185
  syntax: '@' + node.nam,
@@ -17752,7 +18215,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
17752
18215
  const location = map.get(tokens[0]);
17753
18216
  const uniq = new Map;
17754
18217
  parseTokens(tokens, { minify: true });
17755
- const ruleType = context.typ == exports.EnumToken.KeyframeAtRuleNodeType ? exports.EnumToken.KeyFrameRuleNodeType : exports.EnumToken.RuleNodeType;
18218
+ const ruleType = context.typ == exports.EnumToken.KeyframesAtRuleNodeType ? exports.EnumToken.KeyFramesRuleNodeType : exports.EnumToken.RuleNodeType;
17756
18219
  if (ruleType == exports.EnumToken.RuleNodeType) {
17757
18220
  parseSelector(tokens);
17758
18221
  }
@@ -17762,6 +18225,34 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
17762
18225
  if (curr.typ == exports.EnumToken.CommentTokenType) {
17763
18226
  return acc;
17764
18227
  }
18228
+ if (options.minify) {
18229
+ if (curr.typ == exports.EnumToken.PseudoClassFuncTokenType && curr.val == ':nth-child') {
18230
+ let i = 0;
18231
+ for (; i < curr.chi.length; i++) {
18232
+ if (curr.chi[i].typ == exports.EnumToken.IdenTokenType && curr.chi[i].val == 'even') {
18233
+ Object.assign(curr.chi[i], {
18234
+ typ: exports.EnumToken.Dimension,
18235
+ val: 2,
18236
+ unit: 'n'
18237
+ });
18238
+ }
18239
+ else if (curr.chi[i].typ == exports.EnumToken.Dimension &&
18240
+ curr.chi[i].val == 2 &&
18241
+ curr.chi[i].unit == 'n' &&
18242
+ curr.chi[i + 1]?.typ == exports.EnumToken.WhitespaceTokenType &&
18243
+ curr.chi[i + 2]?.typ == exports.EnumToken.LiteralTokenType &&
18244
+ curr.chi[i + 2].val == '+' &&
18245
+ curr.chi[i + 3]?.typ == exports.EnumToken.WhitespaceTokenType &&
18246
+ curr.chi[i + 4]?.typ == exports.EnumToken.NumberTokenType &&
18247
+ curr.chi[i + 4].val == 1) {
18248
+ curr.chi.splice(i, 5, Object.assign(curr.chi[i], {
18249
+ typ: exports.EnumToken.IdenTokenType,
18250
+ val: 'odd'
18251
+ }));
18252
+ }
18253
+ }
18254
+ }
18255
+ }
17765
18256
  if (curr.typ == exports.EnumToken.WhitespaceTokenType) {
17766
18257
  if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
17767
18258
  trimWhiteSpace.includes(array[index + 1]?.typ) ||
@@ -17770,7 +18261,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
17770
18261
  return acc;
17771
18262
  }
17772
18263
  }
17773
- if (ruleType == exports.EnumToken.KeyFrameRuleNodeType) {
18264
+ if (ruleType == exports.EnumToken.KeyFramesRuleNodeType && options.minify) {
17774
18265
  if (curr.typ == exports.EnumToken.IdenTokenType && curr.val == 'from') {
17775
18266
  Object.assign(curr, { typ: exports.EnumToken.PercentageTokenType, val: '0' });
17776
18267
  }
@@ -17819,7 +18310,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
17819
18310
  const valid = options.validation == exports.ValidationLevel.None ? {
17820
18311
  valid: SyntaxValidationResult.Valid,
17821
18312
  error: null
17822
- } : ruleType == exports.EnumToken.KeyFrameRuleNodeType ? validateKeyframeSelector(tokens) : validateSelector(tokens, options, context);
18313
+ } : ruleType == exports.EnumToken.KeyFramesRuleNodeType ? validateKeyframeSelector(tokens) : validateSelector(tokens, options, context);
17823
18314
  if (valid.valid != SyntaxValidationResult.Valid) {
17824
18315
  // @ts-ignore
17825
18316
  node.typ = exports.EnumToken.InvalidRuleTokenType;
@@ -18195,7 +18686,7 @@ async function parseDeclarations(declaration) {
18195
18686
  position: { ind: 0, lin: 1, col: 1 },
18196
18687
  currentPosition: { ind: -1, lin: 1, col: 0 }
18197
18688
  }), { setParent: false, minify: false, validation: false }).then(result => {
18198
- return result.ast.chi[0].chi.filter(t => t.typ == exports.EnumToken.DeclarationNodeType);
18689
+ return result.ast.chi[0].chi.filter(t => t.typ == exports.EnumToken.DeclarationNodeType || t.typ == exports.EnumToken.CommentNodeType);
18199
18690
  });
18200
18691
  }
18201
18692
  /**
@@ -18848,63 +19339,130 @@ function eq(a, b) {
18848
19339
  return true;
18849
19340
  }
18850
19341
 
19342
+ /**
19343
+ * options for the walk function
19344
+ */
18851
19345
  exports.WalkerOptionEnum = void 0;
18852
19346
  (function (WalkerOptionEnum) {
18853
19347
  /**
18854
19348
  * ignore the current node and its children
18855
19349
  */
18856
- WalkerOptionEnum[WalkerOptionEnum["Ignore"] = 0] = "Ignore";
19350
+ WalkerOptionEnum[WalkerOptionEnum["Ignore"] = 1] = "Ignore";
18857
19351
  /**
18858
19352
  * stop walking the tree
18859
19353
  */
18860
- WalkerOptionEnum[WalkerOptionEnum["Stop"] = 1] = "Stop";
19354
+ WalkerOptionEnum[WalkerOptionEnum["Stop"] = 2] = "Stop";
18861
19355
  /**
18862
19356
  * ignore node and process children
18863
19357
  */
18864
- WalkerOptionEnum[WalkerOptionEnum["Children"] = 2] = "Children";
19358
+ WalkerOptionEnum[WalkerOptionEnum["Children"] = 4] = "Children";
18865
19359
  /**
18866
19360
  * ignore children
18867
19361
  */
18868
- WalkerOptionEnum[WalkerOptionEnum["IgnoreChildren"] = 3] = "IgnoreChildren";
19362
+ WalkerOptionEnum[WalkerOptionEnum["IgnoreChildren"] = 8] = "IgnoreChildren";
18869
19363
  })(exports.WalkerOptionEnum || (exports.WalkerOptionEnum = {}));
19364
+ /**
19365
+ * event types for the walkValues function
19366
+ */
18870
19367
  exports.WalkerValueEvent = void 0;
18871
19368
  (function (WalkerValueEvent) {
18872
19369
  /**
18873
19370
  * enter node
18874
19371
  */
18875
- WalkerValueEvent[WalkerValueEvent["Enter"] = 0] = "Enter";
19372
+ WalkerValueEvent[WalkerValueEvent["Enter"] = 1] = "Enter";
18876
19373
  /**
18877
19374
  * leave node
18878
19375
  */
18879
- WalkerValueEvent[WalkerValueEvent["Leave"] = 1] = "Leave";
19376
+ WalkerValueEvent[WalkerValueEvent["Leave"] = 2] = "Leave";
18880
19377
  })(exports.WalkerValueEvent || (exports.WalkerValueEvent = {}));
18881
19378
  /**
18882
19379
  * walk ast nodes
18883
- * @param node
18884
- * @param filter
19380
+ * @param node initial node
19381
+ * @param filter control the walk process
19382
+ * @param reverse walk in reverse order
19383
+ *
19384
+ * ```ts
19385
+ *
19386
+ * import {walk} from '@tbela99/css-parser';
19387
+ *
19388
+ * const css = `
19389
+ * body { color: color(from var(--base-color) display-p3 r calc(g + 0.24) calc(b + 0.15)); }
19390
+ *
19391
+ * html,
19392
+ * body {
19393
+ * line-height: 1.474;
19394
+ * }
19395
+ *
19396
+ * .ruler {
19397
+ *
19398
+ * height: 10px;
19399
+ * }
19400
+ * `;
19401
+ *
19402
+ * for (const {node, parent, root} of walk(ast)) {
19403
+ *
19404
+ * // do something with node
19405
+ * }
19406
+ * ```
19407
+ *
19408
+ * Using a filter to control the walk process:
19409
+ *
19410
+ * ```ts
19411
+ *
19412
+ * import {walk} from '@tbela99/css-parser';
19413
+ *
19414
+ * const css = `
19415
+ * body { color: color(from var(--base-color) display-p3 r calc(g + 0.24) calc(b + 0.15)); }
19416
+ *
19417
+ * html,
19418
+ * body {
19419
+ * line-height: 1.474;
19420
+ * }
19421
+ *
19422
+ * .ruler {
19423
+ *
19424
+ * height: 10px;
19425
+ * }
19426
+ * `;
19427
+ *
19428
+ * for (const {node, parent, root} of walk(ast, (node) => {
19429
+ *
19430
+ * if (node.typ == EnumToken.AstRule && node.sel.includes('html')) {
19431
+ *
19432
+ * // skip the children of the current node
19433
+ * return WalkerOptionEnum.IgnoreChildren;
19434
+ * }
19435
+ * })) {
19436
+ *
19437
+ * // do something with node
19438
+ * }
19439
+ * ```
18885
19440
  */
18886
- function* walk(node, filter) {
19441
+ function* walk(node, filter, reverse) {
18887
19442
  const parents = [node];
18888
19443
  const root = node;
18889
19444
  const map = new Map;
19445
+ let isNumeric = false;
18890
19446
  while ((node = parents.shift())) {
18891
19447
  let option = null;
18892
19448
  if (filter != null) {
18893
19449
  option = filter(node);
18894
- if (option === exports.WalkerOptionEnum.Ignore) {
18895
- continue;
18896
- }
18897
- if (option === exports.WalkerOptionEnum.Stop) {
18898
- break;
19450
+ isNumeric = typeof option == 'number';
19451
+ if (isNumeric) {
19452
+ if ((option & exports.WalkerOptionEnum.Ignore)) {
19453
+ continue;
19454
+ }
19455
+ if ((option & exports.WalkerOptionEnum.Stop)) {
19456
+ break;
19457
+ }
18899
19458
  }
18900
19459
  }
18901
- // @ts-ignore
18902
- if (option !== 'children') {
19460
+ if (!isNumeric || (option & exports.WalkerOptionEnum.Children) === 0) {
18903
19461
  // @ts-ignore
18904
19462
  yield { node, parent: map.get(node), root };
18905
19463
  }
18906
- if (option !== exports.WalkerOptionEnum.IgnoreChildren && 'chi' in node) {
18907
- parents.unshift(...node.chi);
19464
+ if ('chi' in node && (!isNumeric || ((option & exports.WalkerOptionEnum.IgnoreChildren) === 0))) {
19465
+ parents.unshift(...node.chi[reverse ? 'reverse' : 'slice']());
18908
19466
  for (const child of node.chi.slice()) {
18909
19467
  map.set(child, node);
18910
19468
  }
@@ -18917,13 +19475,38 @@ function* walk(node, filter) {
18917
19475
  * @param root
18918
19476
  * @param filter
18919
19477
  * @param reverse
19478
+ *
19479
+ * Example:
19480
+ *
19481
+ * ```ts
19482
+ *
19483
+ * import {EnumToken, walk} from '@tbela99/css-parser';
19484
+ *
19485
+ * const css = `
19486
+ * body { color: color(from var(--base-color) display-p3 r calc(g + 0.24) calc(b + 0.15)); }
19487
+ *
19488
+ * html,
19489
+ * body {
19490
+ * line-height: 1.474;
19491
+ * }
19492
+ *
19493
+ * .ruler {
19494
+ *
19495
+ * height: 10px;
19496
+ * }
19497
+ * `;
19498
+ *
19499
+ * for (const {value} of walkValues(result.ast.chi[0].chi[0].val, null, null,true)) {
19500
+ *
19501
+ * console.error([EnumToken[value.typ], value.val]);
19502
+ * }
19503
+ *
18920
19504
  */
18921
19505
  function* walkValues(values, root = null, filter, reverse) {
18922
19506
  // const set = new Set<Token>();
18923
19507
  const stack = values.slice();
18924
19508
  const map = new Map;
18925
19509
  let previous = null;
18926
- // let parent: FunctionToken | ParensToken | BinaryExpressionToken | null = null;
18927
19510
  if (filter != null && typeof filter == 'function') {
18928
19511
  filter = {
18929
19512
  event: exports.WalkerValueEvent.Enter,
@@ -18935,21 +19518,23 @@ function* walkValues(values, root = null, filter, reverse) {
18935
19518
  event: exports.WalkerValueEvent.Enter
18936
19519
  };
18937
19520
  }
19521
+ let isNumeric = false;
18938
19522
  const eventType = filter.event ?? exports.WalkerValueEvent.Enter;
18939
19523
  while (stack.length > 0) {
18940
19524
  let value = reverse ? stack.pop() : stack.shift();
18941
19525
  let option = null;
18942
- if (filter.fn != null && eventType == exports.WalkerValueEvent.Enter) {
19526
+ if (filter.fn != null && (eventType & exports.WalkerValueEvent.Enter)) {
18943
19527
  const isValid = filter.type == null || value.typ == filter.type ||
18944
19528
  (Array.isArray(filter.type) && filter.type.includes(value.typ)) ||
18945
19529
  (typeof filter.type == 'function' && filter.type(value));
18946
19530
  if (isValid) {
18947
- option = filter.fn(value, map.get(value) ?? root);
18948
- if (option === exports.WalkerOptionEnum.Ignore) {
18949
- continue;
19531
+ option = filter.fn(value, map.get(value) ?? root, exports.WalkerValueEvent.Enter);
19532
+ isNumeric = typeof option == 'number';
19533
+ if (isNumeric && (option & exports.WalkerOptionEnum.Stop)) {
19534
+ return;
18950
19535
  }
18951
- if (option === exports.WalkerOptionEnum.Stop) {
18952
- break;
19536
+ if (isNumeric && (option & exports.WalkerOptionEnum.Ignore)) {
19537
+ continue;
18953
19538
  }
18954
19539
  // @ts-ignore
18955
19540
  if (option != null && typeof option == 'object' && 'typ' in option) {
@@ -18957,38 +19542,33 @@ function* walkValues(values, root = null, filter, reverse) {
18957
19542
  }
18958
19543
  }
18959
19544
  }
18960
- if (eventType == exports.WalkerValueEvent.Enter && option !== exports.WalkerOptionEnum.Children) {
18961
- yield {
18962
- value,
18963
- parent: map.get(value) ?? root,
18964
- previousValue: previous,
18965
- nextValue: stack[0] ?? null,
18966
- // @ts-ignore
18967
- root: root ?? null
18968
- };
18969
- }
18970
- if (option !== exports.WalkerOptionEnum.IgnoreChildren && 'chi' in value) {
19545
+ // if ((eventType & WalkerValueEvent.Enter) && (!isNumeric || ((option as number) & WalkerOptionEnum.Children) === 0)) {
19546
+ yield {
19547
+ value,
19548
+ parent: map.get(value) ?? root,
19549
+ previousValue: previous,
19550
+ nextValue: stack[0] ?? null,
19551
+ // @ts-ignore
19552
+ root: root ?? null
19553
+ };
19554
+ // }
19555
+ if ('chi' in value && (!isNumeric || (option & exports.WalkerOptionEnum.IgnoreChildren) === 0)) {
18971
19556
  const sliced = value.chi.slice();
18972
19557
  for (const child of sliced) {
18973
19558
  map.set(child, value);
18974
19559
  }
18975
- if (reverse) {
18976
- stack.push(...sliced);
18977
- }
18978
- else {
18979
- stack.unshift(...sliced);
18980
- }
19560
+ stack[reverse ? 'push' : 'unshift'](...sliced);
18981
19561
  }
18982
19562
  else {
18983
19563
  const values = [];
18984
19564
  if ('l' in value && value.l != null) {
18985
19565
  // @ts-ignore
18986
- values.push(value.l);
19566
+ values[reverse ? 'push' : 'unshift'](value.l);
18987
19567
  // @ts-ignore
18988
19568
  map.set(value.l, value);
18989
19569
  }
18990
19570
  if ('op' in value && typeof value.op == 'object') {
18991
- values.push(value.op);
19571
+ values[reverse ? 'push' : 'unshift'](value.op);
18992
19572
  // @ts-ignore
18993
19573
  map.set(value.op, value);
18994
19574
  }
@@ -18996,44 +19576,45 @@ function* walkValues(values, root = null, filter, reverse) {
18996
19576
  if (Array.isArray(value.r)) {
18997
19577
  for (const r of value.r) {
18998
19578
  // @ts-ignore
18999
- values.push(r);
19579
+ values[reverse ? 'push' : 'unshift'](r);
19000
19580
  // @ts-ignore
19001
19581
  map.set(r, value);
19002
19582
  }
19003
19583
  }
19004
19584
  else {
19005
19585
  // @ts-ignore
19006
- values.push(value.r);
19586
+ values[reverse ? 'push' : 'unshift'](value.r);
19007
19587
  // @ts-ignore
19008
19588
  map.set(value.r, value);
19009
19589
  }
19010
19590
  }
19011
19591
  if (values.length > 0) {
19012
- stack.unshift(...values);
19592
+ stack[reverse ? 'push' : 'unshift'](...values);
19013
19593
  }
19014
19594
  }
19015
- if (eventType == exports.WalkerValueEvent.Leave && filter.fn != null) {
19595
+ if ((eventType & exports.WalkerValueEvent.Leave) && filter.fn != null) {
19016
19596
  const isValid = filter.type == null || value.typ == filter.type ||
19017
19597
  (Array.isArray(filter.type) && filter.type.includes(value.typ)) ||
19018
19598
  (typeof filter.type == 'function' && filter.type(value));
19019
19599
  if (isValid) {
19020
- option = filter.fn(value, map.get(value));
19600
+ option = filter.fn(value, map.get(value), exports.WalkerValueEvent.Leave);
19021
19601
  // @ts-ignore
19022
19602
  if (option != null && 'typ' in option) {
19023
19603
  map.set(option, map.get(value) ?? root);
19024
19604
  }
19025
19605
  }
19026
19606
  }
19027
- if (eventType == exports.WalkerValueEvent.Leave && option !== exports.WalkerOptionEnum.Children) {
19028
- yield {
19029
- value,
19030
- parent: map.get(value) ?? root,
19031
- previousValue: previous,
19032
- nextValue: stack[0] ?? null,
19033
- // @ts-ignore
19034
- root: root ?? null
19035
- };
19036
- }
19607
+ // if ((eventType & WalkerValueEvent.Leave) && (!isNumeric && ((option as number) & WalkerOptionEnum.Children) === 0)) {
19608
+ //
19609
+ // yield {
19610
+ // value,
19611
+ // parent: <FunctionToken | ParensToken>map.get(value) ?? root,
19612
+ // previousValue: previous,
19613
+ // nextValue: <Token>stack[0] ?? null,
19614
+ // // @ts-ignore
19615
+ // root: root ?? null
19616
+ // };
19617
+ // }
19037
19618
  previous = value;
19038
19619
  }
19039
19620
  }
@@ -19083,11 +19664,8 @@ class ComputePrefixFeature {
19083
19664
  get ordering() {
19084
19665
  return 2;
19085
19666
  }
19086
- get preProcess() {
19087
- return true;
19088
- }
19089
- get postProcess() {
19090
- return false;
19667
+ get processMode() {
19668
+ return exports.FeatureWalkMode.Pre;
19091
19669
  }
19092
19670
  static register(options) {
19093
19671
  if (options.removePrefix) {
@@ -19152,7 +19730,7 @@ class ComputePrefixFeature {
19152
19730
  }
19153
19731
  }
19154
19732
  }
19155
- else if (node.typ == exports.EnumToken.AtRuleNodeType || node.typ == exports.EnumToken.KeyframeAtRuleNodeType) {
19733
+ else if (node.typ == exports.EnumToken.AtRuleNodeType || node.typ == exports.EnumToken.KeyframesAtRuleNodeType) {
19156
19734
  if (node.nam.startsWith('-')) {
19157
19735
  const match = node.nam.match(/^-([^-]+)-(.+)$/);
19158
19736
  if (match != null && '@' + match[2] in config$1.atRules) {
@@ -19160,14 +19738,6 @@ class ComputePrefixFeature {
19160
19738
  }
19161
19739
  }
19162
19740
  if (node.typ == exports.EnumToken.AtRuleNodeType && node.val !== '') {
19163
- // if ((node as AstAtRule).tokens == null) {
19164
- //
19165
- // Object.defineProperty(node, 'tokens', {
19166
- // // @ts-ignore
19167
- // ...definedPropertySettings,
19168
- // value: parseAtRulePrelude(parseString((node as AstAtRule).val), node as AstAtRule),
19169
- // })
19170
- // }
19171
19741
  if (replaceAstNodes(node.tokens)) {
19172
19742
  node.val = node.tokens.reduce((acc, curr) => acc + renderToken(curr), '');
19173
19743
  }
@@ -19223,11 +19793,8 @@ class InlineCssVariablesFeature {
19223
19793
  get ordering() {
19224
19794
  return 0;
19225
19795
  }
19226
- get preProcess() {
19227
- return true;
19228
- }
19229
- get postProcess() {
19230
- return false;
19796
+ get processMode() {
19797
+ return exports.FeatureWalkMode.Pre;
19231
19798
  }
19232
19799
  static register(options) {
19233
19800
  if (options.inlineCssVariables) {
@@ -19237,7 +19804,7 @@ class InlineCssVariablesFeature {
19237
19804
  }
19238
19805
  run(ast, options = {}, parent, context) {
19239
19806
  if (!('chi' in ast)) {
19240
- return;
19807
+ return null;
19241
19808
  }
19242
19809
  if (!('variableScope' in context)) {
19243
19810
  context.variableScope = new Map;
@@ -19280,6 +19847,7 @@ class InlineCssVariablesFeature {
19280
19847
  replace(node, variableScope);
19281
19848
  }
19282
19849
  }
19850
+ return null;
19283
19851
  }
19284
19852
  cleanup(ast, options = {}, context) {
19285
19853
  const variableScope = context.variableScope;
@@ -20119,7 +20687,7 @@ class PropertyList {
20119
20687
  }
20120
20688
  add(...declarations) {
20121
20689
  for (const declaration of declarations) {
20122
- if (declaration.typ != exports.EnumToken.DeclarationNodeType || !this.options.removeDuplicateDeclarations) {
20690
+ if (declaration.typ != exports.EnumToken.DeclarationNodeType || (Array.isArray(this.options.removeDuplicateDeclarations) ? this.options.removeDuplicateDeclarations.includes(declaration.nam) : !this.options.removeDuplicateDeclarations)) {
20123
20691
  this.declarations.set(Number(Math.random().toString().slice(2)).toString(36), declaration);
20124
20692
  continue;
20125
20693
  }
@@ -20189,422 +20757,168 @@ class PropertyList {
20189
20757
  if (value.value instanceof PropertySet || value.value instanceof PropertyMap) {
20190
20758
  iterators.unshift(iterator);
20191
20759
  // @ts-ignore
20192
- iterator = value.value[Symbol.iterator]();
20193
- value = iterator.next();
20194
- }
20195
- if (value.done && iterators.length > 0) {
20196
- iterator = iterators.shift();
20197
- value = iterator.next();
20198
- }
20199
- }
20200
- return value;
20201
- }
20202
- };
20203
- }
20204
- }
20205
-
20206
- class ComputeShorthandFeature {
20207
- get ordering() {
20208
- return 3;
20209
- }
20210
- get preProcess() {
20211
- return false;
20212
- }
20213
- get postProcess() {
20214
- return true;
20215
- }
20216
- static register(options) {
20217
- if (options.computeShorthand) {
20218
- // @ts-ignore
20219
- options.features.push(new ComputeShorthandFeature(options));
20220
- }
20221
- }
20222
- run(ast, options = {}, parent, context) {
20223
- if (!('chi' in ast)) {
20224
- return ast;
20225
- }
20226
- // @ts-ignore
20227
- const j = ast.chi.length;
20228
- let k = 0;
20229
- let l;
20230
- let properties = new PropertyList(options);
20231
- const rules = [];
20232
- // @ts-ignore
20233
- for (; k < j; k++) {
20234
- l = k;
20235
- // capture comments with the next token
20236
- while (l + 1 < j) {
20237
- // @ts-ignore
20238
- const node = ast.chi[l];
20239
- if (node.typ == exports.EnumToken.CommentNodeType) {
20240
- l++;
20241
- continue;
20242
- }
20243
- break;
20244
- }
20245
- // @ts-ignore
20246
- const node = ast.chi[l];
20247
- if (node.typ == exports.EnumToken.DeclarationNodeType) {
20248
- properties.add(...ast.chi.slice(k, l + 1));
20249
- }
20250
- else {
20251
- rules.push(...ast.chi.slice(k, l + 1));
20252
- }
20253
- k = l;
20254
- }
20255
- // @ts-ignore
20256
- ast.chi = [...properties, ...rules];
20257
- return ast;
20258
- }
20259
- }
20260
-
20261
- class ComputeCalcExpressionFeature {
20262
- get ordering() {
20263
- return 1;
20264
- }
20265
- get preProcess() {
20266
- return false;
20267
- }
20268
- get postProcess() {
20269
- return true;
20270
- }
20271
- static register(options) {
20272
- if (options.computeCalcExpression) {
20273
- // @ts-ignore
20274
- options.features.push(new ComputeCalcExpressionFeature());
20275
- }
20276
- }
20277
- run(ast) {
20278
- if (!('chi' in ast)) {
20279
- return;
20280
- }
20281
- for (const node of ast.chi) {
20282
- if (node.typ != exports.EnumToken.DeclarationNodeType) {
20283
- continue;
20284
- }
20285
- const set = new Set;
20286
- for (const { value, parent } of walkValues(node.val, node, {
20287
- event: exports.WalkerValueEvent.Enter,
20288
- // @ts-ignore
20289
- fn(node, parent) {
20290
- if (parent != null &&
20291
- // @ts-ignore
20292
- parent.typ == exports.EnumToken.DeclarationNodeType &&
20293
- // @ts-ignore
20294
- parent.val.length == 1 &&
20295
- node.typ == exports.EnumToken.FunctionTokenType &&
20296
- mathFuncs.includes(node.val) &&
20297
- node.chi.length == 1 &&
20298
- node.chi[0].typ == exports.EnumToken.IdenTokenType) {
20299
- return exports.WalkerOptionEnum.Ignore;
20300
- }
20301
- if ((node.typ == exports.EnumToken.FunctionTokenType && node.val == 'var') || (!mathFuncs.includes(parent.val) && [exports.EnumToken.ColorTokenType, exports.EnumToken.DeclarationNodeType, exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType, exports.EnumToken.StyleSheetNodeType].includes(parent?.typ))) {
20302
- return null;
20303
- }
20304
- // @ts-ignore
20305
- const slice = (node.typ == exports.EnumToken.FunctionTokenType ? node.chi : (node.typ == exports.EnumToken.DeclarationNodeType ? node.val : node.chi))?.slice();
20306
- if (slice != null && node.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(node.val)) {
20307
- // @ts-ignore
20308
- const key = 'chi' in node ? 'chi' : 'val';
20309
- const str1 = renderToken({ ...node, [key]: slice });
20310
- const str2 = renderToken(node); // values.reduce((acc: string, curr: Token): string => acc + renderToken(curr), '');
20311
- if (str1.length <= str2.length) {
20312
- // @ts-ignore
20313
- node[key] = slice;
20314
- }
20315
- return exports.WalkerOptionEnum.Ignore;
20760
+ iterator = value.value[Symbol.iterator]();
20761
+ value = iterator.next();
20316
20762
  }
20317
- return null;
20318
- }
20319
- })) {
20320
- if (value != null && value.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(value.val)) {
20321
- if (!set.has(value)) {
20322
- set.add(value);
20323
- if (parent != null) {
20324
- // @ts-ignore
20325
- const cp = value.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(value.val) && value.val != 'calc' ? [value] : (value.typ == exports.EnumToken.DeclarationNodeType ? value.val : value.chi);
20326
- const values = evaluate(cp);
20327
- // @ts-ignore
20328
- const children = parent.typ == exports.EnumToken.DeclarationNodeType ? parent.val : parent.chi;
20329
- if (values.length == 1 && values[0].typ != exports.EnumToken.BinaryExpressionTokenType) {
20330
- for (let i = 0; i < children.length; i++) {
20331
- if (children[i] == value) {
20332
- children.splice(i, 1, !(parent.typ == exports.EnumToken.FunctionTokenType && parent.val == 'calc') && (typeof values[0].val != 'number' && !(values[0].typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(values[0].val))) ? {
20333
- typ: exports.EnumToken.FunctionTokenType,
20334
- val: 'calc',
20335
- chi: values
20336
- } : values[0]);
20337
- break;
20338
- }
20339
- }
20340
- }
20341
- else {
20342
- for (let i = 0; i < children.length; i++) {
20343
- if (children[i] == value) {
20344
- children.splice(i, 1, {
20345
- typ: exports.EnumToken.FunctionTokenType,
20346
- val: 'calc',
20347
- chi: values
20348
- });
20349
- break;
20350
- }
20351
- }
20352
- }
20353
- }
20763
+ if (value.done && iterators.length > 0) {
20764
+ iterator = iterators.shift();
20765
+ value = iterator.next();
20354
20766
  }
20355
20767
  }
20768
+ return value;
20356
20769
  }
20357
- }
20770
+ };
20358
20771
  }
20359
20772
  }
20360
20773
 
20361
- const epsilon = 1e-5;
20362
- function identity() {
20363
- return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
20364
- }
20365
- function pLength(point) {
20366
- return Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
20367
- }
20368
- function normalize(point) {
20369
- const [x, y, z] = point;
20370
- const norm = Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
20371
- return norm === 0 ? [0, 0, 0] : [x / norm, y / norm, z / norm];
20372
- }
20373
- function dot(point1, point2) {
20374
- if (point1.length === 4 && point2.length === 4) {
20375
- return point1[0] * point2[0] + point1[1] * point2[1] + point1[2] * point2[2] + point1[3] * point2[3];
20774
+ class ComputeShorthandFeature {
20775
+ get ordering() {
20776
+ return 3;
20376
20777
  }
20377
- return point1[0] * point2[0] + point1[1] * point2[1] + point1[2] * point2[2];
20378
- }
20379
- function multiply(matrixA, matrixB) {
20380
- let result = new Array(16).fill(0);
20381
- for (let i = 0; i < 4; i++) {
20382
- for (let j = 0; j < 4; j++) {
20383
- for (let k = 0; k < 4; k++) {
20384
- // Utiliser l'indexation linéaire pour accéder aux éléments
20385
- // Pour une matrice 4x4, l'index est (row * 4 + col)
20386
- result[j * 4 + i] += matrixA[k * 4 + i] * matrixB[j * 4 + k];
20387
- }
20388
- }
20778
+ get processMode() {
20779
+ return exports.FeatureWalkMode.Post;
20389
20780
  }
20390
- return result;
20391
- }
20392
- function inverse(matrix) {
20393
- // Create augmented matrix [matrix | identity]
20394
- let augmented = [
20395
- 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
20396
- 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
20397
- ];
20398
- // Gaussian elimination with partial pivoting
20399
- for (let col = 0; col < 4; col++) {
20400
- // Find pivot row with maximum absolute value
20401
- let maxRow = col;
20402
- let maxVal = Math.abs(augmented[col * 4 + col]);
20403
- for (let row = col + 1; row < 4; row++) {
20404
- let val = Math.abs(augmented[row * 4 + col]);
20405
- if (val > maxVal) {
20406
- maxVal = val;
20407
- maxRow = row;
20408
- }
20781
+ static register(options) {
20782
+ if (options.computeShorthand) {
20783
+ // @ts-ignore
20784
+ options.features.push(new ComputeShorthandFeature(options));
20409
20785
  }
20410
- // Check for singularity
20411
- if (maxVal < 1e-5) {
20786
+ }
20787
+ run(ast, options = {}, parent, context) {
20788
+ if (!('chi' in ast)) {
20412
20789
  return null;
20413
20790
  }
20414
- // Swap rows if necessary
20415
- if (maxRow !== col) {
20416
- [augmented[col], augmented[maxRow]] = [augmented[maxRow], augmented[col]];
20417
- }
20418
- // Scale pivot row to make pivot element 1
20419
- let pivot = augmented[col * 4 + col];
20420
- for (let j = 0; j < 8; j++) {
20421
- augmented[col * 4 + j] /= pivot;
20422
- }
20423
- // Eliminate column in other rows
20424
- for (let row = 0; row < 4; row++) {
20425
- if (row !== col) {
20426
- let factor = augmented[row * 4 + col];
20427
- for (let j = 0; j < 8; j++) {
20428
- augmented[row * 4 + j] -= factor * augmented[col * 4 + j];
20791
+ // @ts-ignore
20792
+ const j = ast.chi.length;
20793
+ let k = 0;
20794
+ let l;
20795
+ let properties = new PropertyList(options);
20796
+ const rules = [];
20797
+ // @ts-ignore
20798
+ for (; k < j; k++) {
20799
+ l = k;
20800
+ // capture comments with the next token
20801
+ while (l + 1 < j) {
20802
+ // @ts-ignore
20803
+ const node = ast.chi[l];
20804
+ if (node.typ == exports.EnumToken.CommentNodeType) {
20805
+ l++;
20806
+ continue;
20429
20807
  }
20808
+ break;
20809
+ }
20810
+ // @ts-ignore
20811
+ const node = ast.chi[l];
20812
+ if (node.typ == exports.EnumToken.DeclarationNodeType) {
20813
+ properties.add(...ast.chi.slice(k, l + 1));
20430
20814
  }
20815
+ else {
20816
+ rules.push(...ast.chi.slice(k, l + 1));
20817
+ }
20818
+ k = l;
20431
20819
  }
20432
- }
20433
- // Extract the inverse from the right side of the augmented matrix
20434
- return augmented.slice(0, 16);
20435
- }
20436
- // function transpose(matrix: Matrix): Matrix {
20437
- // // Crée une nouvelle matrice vide 4x4
20438
- // // @ts-ignore
20439
- // let transposed: Matrix = [[], [], [], []] as Matrix;
20440
- //
20441
- // // Parcourt chaque ligne et colonne pour transposer
20442
- // for (let i = 0; i < 4; i++) {
20443
- //
20444
- // for (let j = 0; j < 4; j++) {
20445
- //
20446
- // transposed[j][i] = matrix[i][j];
20447
- // }
20448
- // }
20449
- //
20450
- // return transposed;
20451
- // }
20452
- function round(number) {
20453
- return Math.abs(number) < epsilon ? 0 : +number.toPrecision(6);
20454
- }
20455
- // translate3d(25.9808px, 0, 15px ) rotateY(60deg) skewX(49.9999deg) scale(1, 1.2)
20456
- // translate → rotate → skew → scale
20457
- function decompose(original) {
20458
- const matrix = original.slice();
20459
- // Normalize last row
20460
- if (matrix[15] === 0) {
20461
- return null;
20462
- }
20463
- for (let i = 0; i < 16; i++)
20464
- matrix[i] /= matrix[15];
20465
- // Perspective extraction
20466
- const perspective = [0, 0, 0, 1];
20467
- if (matrix[3] !== 0 || matrix[7] !== 0 || matrix[11] !== 0) {
20468
- const rightHandSide = [matrix[3], matrix[7], matrix[11], matrix[15]];
20469
- const perspectiveMatrix = matrix.slice();
20470
- perspectiveMatrix[3] = 0;
20471
- perspectiveMatrix[7] = 0;
20472
- perspectiveMatrix[11] = 0;
20473
- perspectiveMatrix[15] = 1;
20474
20820
  // @ts-ignore
20475
- const inverted = inverse(original.slice());
20476
- if (!inverted) {
20477
- return null;
20478
- }
20479
- const transposedInverse = transposeMatrix4(inverted);
20480
- perspective[0] = dot(rightHandSide, transposedInverse.slice(0, 4));
20481
- perspective[1] = dot(rightHandSide, transposedInverse.slice(4, 8));
20482
- perspective[2] = dot(rightHandSide, transposedInverse.slice(8, 12));
20483
- perspective[3] = dot(rightHandSide, transposedInverse.slice(12, 16));
20484
- // Clear perspective from matrix
20485
- matrix[3] = 0;
20486
- matrix[7] = 0;
20487
- matrix[11] = 0;
20488
- matrix[15] = 1;
20489
- }
20490
- // Translation
20491
- const translate = [matrix[12], matrix[13], matrix[14]];
20492
- matrix[12] = matrix[13] = matrix[14] = 0;
20493
- // Build the 3x3 matrix
20494
- const row0 = [matrix[0], matrix[1], matrix[2]];
20495
- const row1 = [matrix[4], matrix[5], matrix[6]];
20496
- const row2 = [matrix[8], matrix[9], matrix[10]];
20497
- // Compute scale
20498
- const scaleX = pLength(row0);
20499
- const row0Norm = normalize(row0);
20500
- const skewXY = dot(row0Norm, row1);
20501
- const row1Proj = [
20502
- row1[0] - skewXY * row0Norm[0],
20503
- row1[1] - skewXY * row0Norm[1],
20504
- row1[2] - skewXY * row0Norm[2]
20505
- ];
20506
- const scaleY = pLength(row1Proj);
20507
- const row1Norm = normalize(row1Proj);
20508
- const skewXZ = dot(row0Norm, row2);
20509
- const skewYZ = dot(row1Norm, row2);
20510
- const row2Proj = [
20511
- row2[0] - skewXZ * row0Norm[0] - skewYZ * row1Norm[0],
20512
- row2[1] - skewXZ * row0Norm[1] - skewYZ * row1Norm[1],
20513
- row2[2] - skewXZ * row0Norm[2] - skewYZ * row1Norm[2]
20514
- ];
20515
- const scaleZ = pLength(row2Proj);
20516
- const row2Norm = normalize(row2Proj);
20517
- // Build rotation matrix from orthonormalized vectors
20518
- const r00 = row0Norm[0], r01 = row1Norm[0], r02 = row2Norm[0];
20519
- const r10 = row0Norm[1], r11 = row1Norm[1], r12 = row2Norm[1];
20520
- const r20 = row0Norm[2], r21 = row1Norm[2], r22 = row2Norm[2];
20521
- // Convert to quaternion
20522
- const trace = r00 + r11 + r22;
20523
- let qw, qx, qy, qz;
20524
- if (trace > 0) {
20525
- const s = 0.5 / Math.sqrt(trace + 1.0);
20526
- qw = 0.25 / s;
20527
- qx = (r21 - r12) * s;
20528
- qy = (r02 - r20) * s;
20529
- qz = (r10 - r01) * s;
20530
- }
20531
- else if (r00 > r11 && r00 > r22) {
20532
- const s = 2.0 * Math.sqrt(1.0 + r00 - r11 - r22);
20533
- qw = (r21 - r12) / s;
20534
- qx = 0.25 * s;
20535
- qy = (r01 + r10) / s;
20536
- qz = (r02 + r20) / s;
20821
+ ast.chi = [...properties, ...rules];
20822
+ return ast;
20537
20823
  }
20538
- else if (r11 > r22) {
20539
- const s = 2.0 * Math.sqrt(1.0 + r11 - r00 - r22);
20540
- qw = (r02 - r20) / s;
20541
- qx = (r01 + r10) / s;
20542
- qy = 0.25 * s;
20543
- qz = (r12 + r21) / s;
20824
+ }
20825
+
20826
+ class ComputeCalcExpressionFeature {
20827
+ get ordering() {
20828
+ return 1;
20544
20829
  }
20545
- else {
20546
- const s = 2.0 * Math.sqrt(1.0 + r22 - r00 - r11);
20547
- qw = (r10 - r01) / s;
20548
- qx = (r02 + r20) / s;
20549
- qy = (r12 + r21) / s;
20550
- qz = 0.25 * s;
20830
+ get processMode() {
20831
+ return exports.FeatureWalkMode.Post;
20551
20832
  }
20552
- [qx, qy, qz] = toZero([qx, qy, qz]);
20553
- // const q = gcd(qx, gcd(qy, qz));
20554
- let q = [Math.abs(qx), Math.abs(qy), Math.abs(qz)].reduce((acc, curr) => {
20555
- if (acc == 0 || (curr > 0 && curr < acc)) {
20556
- acc = curr;
20833
+ static register(options) {
20834
+ if (options.computeCalcExpression) {
20835
+ // @ts-ignore
20836
+ options.features.push(new ComputeCalcExpressionFeature());
20557
20837
  }
20558
- return acc;
20559
- }, 0);
20560
- if (q > 0) {
20561
- qx /= q;
20562
- qy /= q;
20563
- qz /= q;
20564
20838
  }
20565
- const rotate = [qx, qy, qz, Object.is(qw, 0) ? 0 : 2 * Math.acos(qw) * 180 / Math.PI];
20566
- const scale = [scaleX, scaleY, scaleZ];
20567
- const skew = [skewXY, skewXZ, skewYZ];
20568
- return {
20569
- translate,
20570
- scale,
20571
- rotate,
20572
- skew,
20573
- perspective
20574
- };
20575
- }
20576
- function transposeMatrix4(m) {
20577
- return [
20578
- m[0], m[4], m[8], m[12],
20579
- m[1], m[5], m[9], m[13],
20580
- m[2], m[6], m[10], m[14],
20581
- m[3], m[7], m[11], m[15],
20582
- ];
20583
- }
20584
- function toZero(v) {
20585
- for (let i = 0; i < v.length; i++) {
20586
- if (Math.abs(v[i]) <= epsilon) {
20587
- v[i] = 0;
20839
+ run(ast) {
20840
+ if (!('chi' in ast)) {
20841
+ return null;
20588
20842
  }
20589
- else {
20590
- v[i] = +v[i].toPrecision(6);
20843
+ for (const node of ast.chi) {
20844
+ if (node.typ != exports.EnumToken.DeclarationNodeType) {
20845
+ continue;
20846
+ }
20847
+ const set = new Set;
20848
+ for (const { value, parent } of walkValues(node.val, node, {
20849
+ event: exports.WalkerValueEvent.Enter,
20850
+ // @ts-ignore
20851
+ fn(node, parent) {
20852
+ if (parent != null &&
20853
+ // @ts-ignore
20854
+ parent.typ == exports.EnumToken.DeclarationNodeType &&
20855
+ // @ts-ignore
20856
+ parent.val.length == 1 &&
20857
+ node.typ == exports.EnumToken.FunctionTokenType &&
20858
+ mathFuncs.includes(node.val) &&
20859
+ node.chi.length == 1 &&
20860
+ node.chi[0].typ == exports.EnumToken.IdenTokenType) {
20861
+ return exports.WalkerOptionEnum.Ignore;
20862
+ }
20863
+ if ((node.typ == exports.EnumToken.FunctionTokenType && node.val == 'var') || (!mathFuncs.includes(parent.val) && [exports.EnumToken.ColorTokenType, exports.EnumToken.DeclarationNodeType, exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType, exports.EnumToken.StyleSheetNodeType].includes(parent?.typ))) {
20864
+ return null;
20865
+ }
20866
+ // @ts-ignore
20867
+ const slice = (node.typ == exports.EnumToken.FunctionTokenType ? node.chi : (node.typ == exports.EnumToken.DeclarationNodeType ? node.val : node.chi))?.slice();
20868
+ if (slice != null && node.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(node.val)) {
20869
+ // @ts-ignore
20870
+ const key = 'chi' in node ? 'chi' : 'val';
20871
+ const str1 = renderToken({ ...node, [key]: slice });
20872
+ const str2 = renderToken(node); // values.reduce((acc: string, curr: Token): string => acc + renderToken(curr), '');
20873
+ if (str1.length <= str2.length) {
20874
+ // @ts-ignore
20875
+ node[key] = slice;
20876
+ }
20877
+ return exports.WalkerOptionEnum.Ignore;
20878
+ }
20879
+ return null;
20880
+ }
20881
+ })) {
20882
+ if (value != null && value.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(value.val)) {
20883
+ if (!set.has(value)) {
20884
+ set.add(value);
20885
+ if (parent != null) {
20886
+ // @ts-ignore
20887
+ const cp = value.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(value.val) && value.val != 'calc' ? [value] : (value.typ == exports.EnumToken.DeclarationNodeType ? value.val : value.chi);
20888
+ const values = evaluate(cp);
20889
+ // @ts-ignore
20890
+ const children = parent.typ == exports.EnumToken.DeclarationNodeType ? parent.val : parent.chi;
20891
+ if (values.length == 1 && values[0].typ != exports.EnumToken.BinaryExpressionTokenType) {
20892
+ for (let i = 0; i < children.length; i++) {
20893
+ if (children[i] == value) {
20894
+ children.splice(i, 1, !(parent.typ == exports.EnumToken.FunctionTokenType && parent.val == 'calc') && (typeof values[0].val != 'number' && !(values[0].typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(values[0].val))) ? {
20895
+ typ: exports.EnumToken.FunctionTokenType,
20896
+ val: 'calc',
20897
+ chi: values
20898
+ } : values[0]);
20899
+ break;
20900
+ }
20901
+ }
20902
+ }
20903
+ else {
20904
+ for (let i = 0; i < children.length; i++) {
20905
+ if (children[i] == value) {
20906
+ children.splice(i, 1, {
20907
+ typ: exports.EnumToken.FunctionTokenType,
20908
+ val: 'calc',
20909
+ chi: values
20910
+ });
20911
+ break;
20912
+ }
20913
+ }
20914
+ }
20915
+ }
20916
+ }
20917
+ }
20918
+ }
20591
20919
  }
20920
+ return null;
20592
20921
  }
20593
- return v;
20594
- }
20595
- // https://drafts.csswg.org/css-transforms-1/#2d-matrix
20596
- function is2DMatrix(matrix) {
20597
- // m13,m14, m23, m24, m31, m32, m34, m43 are all 0
20598
- return matrix[0 * 4 + 2] === 0 &&
20599
- matrix[0 * 4 + 3] === 0 &&
20600
- matrix[1 * 4 + 2] === 0 &&
20601
- matrix[1 * 4 + 3] === 0 &&
20602
- matrix[2 * 4 + 0] === 0 &&
20603
- matrix[2 * 4 + 1] === 0 &&
20604
- matrix[2 * 4 + 3] === 0 &&
20605
- matrix[3 * 4 + 2] === 0 &&
20606
- matrix[2 * 4 + 2] === 1 &&
20607
- matrix[3 * 4 + 3] === 1;
20608
20922
  }
20609
20923
 
20610
20924
  function translateX(x, from) {
@@ -21392,11 +21706,8 @@ class TransformCssFeature {
21392
21706
  get ordering() {
21393
21707
  return 4;
21394
21708
  }
21395
- get preProcess() {
21396
- return false;
21397
- }
21398
- get postProcess() {
21399
- return true;
21709
+ get processMode() {
21710
+ return exports.FeatureWalkMode.Post;
21400
21711
  }
21401
21712
  static register(options) {
21402
21713
  // @ts-ignore
@@ -21407,7 +21718,7 @@ class TransformCssFeature {
21407
21718
  }
21408
21719
  run(ast) {
21409
21720
  if (!('chi' in ast)) {
21410
- return;
21721
+ return null;
21411
21722
  }
21412
21723
  let i = 0;
21413
21724
  let node;
@@ -21454,6 +21765,7 @@ class TransformCssFeature {
21454
21765
  return acc;
21455
21766
  }, [matrix]);
21456
21767
  }
21768
+ return null;
21457
21769
  }
21458
21770
  }
21459
21771
 
@@ -21485,6 +21797,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
21485
21797
  let preprocess = false;
21486
21798
  let postprocess = false;
21487
21799
  let parents;
21800
+ let replacement;
21488
21801
  if (!('features' in options)) {
21489
21802
  // @ts-ignore
21490
21803
  options = {
@@ -21494,82 +21807,92 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
21494
21807
  removePrefix: false,
21495
21808
  features: [], ...options
21496
21809
  };
21497
- // @ts-ignore
21498
21810
  for (const feature of features) {
21499
21811
  feature.register(options);
21500
21812
  }
21501
21813
  options.features.sort((a, b) => a.ordering - b.ordering);
21502
21814
  }
21503
21815
  for (const feature of options.features) {
21504
- if (feature.preProcess) {
21816
+ if (feature.processMode & exports.FeatureWalkMode.Pre) {
21505
21817
  preprocess = true;
21506
21818
  }
21507
- if (feature.postProcess) {
21819
+ if (feature.processMode & exports.FeatureWalkMode.Post) {
21508
21820
  postprocess = true;
21509
21821
  }
21510
21822
  }
21511
21823
  if (preprocess) {
21512
- parents = [ast];
21824
+ parents = new Set([ast]);
21513
21825
  for (const parent of parents) {
21514
21826
  if (parent.typ == exports.EnumToken.CommentTokenType ||
21515
21827
  parent.typ == exports.EnumToken.CDOCOMMTokenType) {
21516
- Object.defineProperty(parent, 'parent', {
21517
- ...definedPropertySettings,
21518
- value: parent
21519
- });
21520
21828
  continue;
21521
21829
  }
21830
+ replacement = parent;
21522
21831
  for (const feature of options.features) {
21523
- if (!feature.preProcess) {
21832
+ if ((feature.processMode & exports.FeatureWalkMode.Pre) === 0) {
21524
21833
  continue;
21525
21834
  }
21526
- feature.run(parent, options, parent.parent ?? ast, context, exports.FeatureWalkMode.Pre);
21835
+ const result = feature.run(replacement, options, parent.parent ?? ast, context, exports.FeatureWalkMode.Pre);
21836
+ if (result != null) {
21837
+ replacement = result;
21838
+ }
21527
21839
  }
21528
- if (('chi' in parent)) {
21840
+ if (replacement != parent && parent.parent != null) {
21529
21841
  // @ts-ignore
21530
- for (const node of parent.chi) {
21531
- parents.push(Object.defineProperty(node, 'parent', {
21842
+ replaceToken(parent.parent, parent, replacement);
21843
+ }
21844
+ if (('chi' in replacement)) {
21845
+ // @ts-ignore
21846
+ for (const node of replacement.chi) {
21847
+ parents.add(Object.defineProperty(node, 'parent', {
21532
21848
  ...definedPropertySettings,
21533
- value: parent
21849
+ value: replacement
21534
21850
  }));
21535
21851
  }
21536
21852
  }
21537
21853
  }
21538
21854
  for (const feature of options.features) {
21539
- if (feature.preProcess && 'cleanup' in feature) {
21855
+ if ((feature.processMode & exports.FeatureWalkMode.Pre) && 'cleanup' in feature) {
21540
21856
  // @ts-ignore
21541
21857
  feature.cleanup(ast, options, context, exports.FeatureWalkMode.Pre);
21542
21858
  }
21543
21859
  }
21544
21860
  }
21545
21861
  doMinify(ast, options, recursive, errors, nestingContent, context);
21546
- parents = [ast];
21862
+ parents = new Set([ast]);
21547
21863
  for (const parent of parents) {
21548
21864
  if (parent.typ == exports.EnumToken.CommentTokenType ||
21549
21865
  parent.typ == exports.EnumToken.CDOCOMMTokenType) {
21550
21866
  continue;
21551
21867
  }
21868
+ replacement = parent;
21552
21869
  if (postprocess) {
21553
21870
  for (const feature of options.features) {
21554
- if (!feature.postProcess) {
21871
+ if ((feature.processMode & exports.FeatureWalkMode.Post) === 0) {
21555
21872
  continue;
21556
21873
  }
21557
- feature.run(parent, options, parent.parent ?? ast, context, exports.FeatureWalkMode.Post);
21874
+ const result = feature.run(replacement, options, parent.parent ?? ast, context, exports.FeatureWalkMode.Post);
21875
+ if (result != null) {
21876
+ replacement = result;
21877
+ }
21558
21878
  }
21559
21879
  }
21560
- if (('chi' in parent)) {
21880
+ if (replacement != null && replacement != parent && parent.parent != null) {
21561
21881
  // @ts-ignore
21562
- for (const node of parent.chi) {
21563
- parents.push(Object.defineProperty(node, 'parent', {
21882
+ replaceToken(parent.parent, parent, replacement);
21883
+ }
21884
+ if (('chi' in replacement)) {
21885
+ for (const node of replacement.chi) {
21886
+ parents.add(Object.defineProperty(node, 'parent', {
21564
21887
  ...definedPropertySettings,
21565
- value: parent
21888
+ value: replacement
21566
21889
  }));
21567
21890
  }
21568
21891
  }
21569
21892
  }
21570
21893
  if (postprocess) {
21571
21894
  for (const feature of options.features) {
21572
- if (feature.postProcess && 'cleanup' in feature) {
21895
+ if (feature.processMode & exports.FeatureWalkMode.Post && 'cleanup' in feature) {
21573
21896
  // @ts-ignore
21574
21897
  feature.cleanup(ast, options, context, exports.FeatureWalkMode.Post);
21575
21898
  }
@@ -21581,12 +21904,10 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
21581
21904
  * reduce selectors
21582
21905
  * @param acc
21583
21906
  * @param curr
21584
- * @param index
21585
- * @param array
21586
21907
  *
21587
21908
  * @private
21588
21909
  */
21589
- function reduce(acc, curr, index, array) {
21910
+ function reduce(acc, curr) {
21590
21911
  // trim :is()
21591
21912
  // if (array.length == 1 && array[0][0] == ':is(' && array[0].at(-1) == ')') {
21592
21913
  //
@@ -21627,21 +21948,18 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
21627
21948
  }
21628
21949
  let i = 0;
21629
21950
  let previous = null;
21630
- let node;
21951
+ let node = null;
21631
21952
  let nodeIndex = -1;
21632
- // @ts-ignore
21633
21953
  for (; i < ast.chi.length; i++) {
21634
- // @ts-ignore
21635
21954
  if (ast.chi[i].typ == exports.EnumToken.CommentNodeType) {
21636
21955
  continue;
21637
21956
  }
21638
- // @ts-ignore
21639
21957
  node = ast.chi[i];
21640
21958
  if (node.typ == exports.EnumToken.AtRuleNodeType && node.nam == 'font-face') {
21641
21959
  continue;
21642
21960
  }
21643
- if (node.typ == exports.EnumToken.KeyframeAtRuleNodeType) {
21644
- if (previous?.typ == exports.EnumToken.KeyframeAtRuleNodeType &&
21961
+ if (node.typ == exports.EnumToken.KeyframesAtRuleNodeType) {
21962
+ if (previous?.typ == exports.EnumToken.KeyframesAtRuleNodeType &&
21645
21963
  node.nam == previous.nam &&
21646
21964
  node.val == previous.val) {
21647
21965
  ast.chi?.splice(nodeIndex--, 1);
@@ -21649,15 +21967,11 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
21649
21967
  i = nodeIndex;
21650
21968
  continue;
21651
21969
  }
21652
- if (node.chi.length > 0) {
21653
- doMinify(node, options, true, errors, nestingContent, context);
21654
- }
21655
21970
  }
21656
- else if (node.typ == exports.EnumToken.KeyFrameRuleNodeType) {
21657
- if (previous?.typ == exports.EnumToken.KeyFrameRuleNodeType &&
21971
+ else if (node.typ == exports.EnumToken.KeyFramesRuleNodeType) {
21972
+ if (previous?.typ == exports.EnumToken.KeyFramesRuleNodeType &&
21658
21973
  node.sel == previous.sel) {
21659
21974
  previous.chi.push(...node.chi);
21660
- // @ts-ignore
21661
21975
  ast.chi.splice(i--, 1);
21662
21976
  continue;
21663
21977
  }
@@ -21679,25 +21993,25 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
21679
21993
  }
21680
21994
  }
21681
21995
  else if (node.typ == exports.EnumToken.AtRuleNodeType) {
21682
- // @ts-ignore
21683
21996
  if (node.nam == 'media' && ['all', '', null].includes(node.val)) {
21684
- // @ts-ignore
21685
21997
  ast.chi?.splice(i, 1, ...node.chi);
21686
21998
  i--;
21687
21999
  continue;
21688
22000
  }
21689
- // @ts-ignore
21690
22001
  if (previous?.typ == exports.EnumToken.AtRuleNodeType &&
21691
22002
  previous.nam == node.nam &&
21692
22003
  previous.val == node.val) {
21693
22004
  if ('chi' in node) {
21694
22005
  // @ts-ignore
21695
22006
  previous.chi.push(...node.chi);
22007
+ if (!hasDeclaration(previous)) {
22008
+ context.nodes.delete(previous);
22009
+ doMinify(previous, options, recursive, errors, nestingContent, context);
22010
+ }
21696
22011
  }
21697
22012
  ast?.chi?.splice(i--, 1);
21698
22013
  continue;
21699
22014
  }
21700
- // @ts-ignore
21701
22015
  if (!hasDeclaration(node)) {
21702
22016
  doMinify(node, options, recursive, errors, nestingContent, context);
21703
22017
  }
@@ -21708,47 +22022,33 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
21708
22022
  // @ts-ignore
21709
22023
  else if (node.typ == exports.EnumToken.RuleNodeType) {
21710
22024
  reduceRuleSelector(node);
21711
- let wrapper;
22025
+ let wrapper = null;
21712
22026
  let match;
21713
- // @ts-ignore
21714
22027
  if (options.nestingRules) {
21715
- // @ts-ignore
21716
22028
  if (previous?.typ == exports.EnumToken.RuleNodeType) {
21717
- // @ts-ignore
21718
22029
  reduceRuleSelector(previous);
21719
22030
  // @ts-ignore
21720
22031
  match = matchSelectors(previous.raw, node.raw, ast.typ);
21721
- // @ts-ignore
21722
22032
  if (match != null) {
21723
- // @ts-ignore
21724
22033
  wrapper = wrapNodes(previous, node, match, ast, reducer, i, nodeIndex);
21725
22034
  nodeIndex = i - 1;
21726
- // @ts-ignore
21727
22035
  previous = ast.chi[nodeIndex];
21728
22036
  }
21729
22037
  }
21730
- // @ts-ignore
21731
22038
  if (wrapper != null) {
21732
- // @ts-ignore
21733
22039
  while (i < ast.chi.length) {
21734
- // @ts-ignore
21735
22040
  const nextNode = ast.chi[i];
21736
- // @ts-ignore
21737
22041
  if (nextNode.typ != exports.EnumToken.RuleNodeType) {
21738
22042
  break;
21739
22043
  }
21740
22044
  reduceRuleSelector(nextNode);
21741
- // @ts-ignore
21742
- match = matchSelectors(wrapper.raw, nextNode.raw, ast.typ);
21743
- // @ts-ignore
22045
+ match = matchSelectors(wrapper.raw, nextNode.raw);
21744
22046
  if (match == null) {
21745
22047
  break;
21746
22048
  }
21747
- // @ts-ignore
21748
22049
  wrapper = wrapNodes(wrapper, nextNode, match, ast, reducer, i, nodeIndex);
21749
22050
  }
21750
22051
  nodeIndex = --i;
21751
- // @ts-ignore
21752
22052
  previous = ast.chi[nodeIndex];
21753
22053
  doMinify(wrapper, options, recursive, errors, nestingContent, context);
21754
22054
  continue;
@@ -21795,7 +22095,6 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
21795
22095
  curr.unshift('&');
21796
22096
  wrap = false;
21797
22097
  }
21798
- // @ts-ignore
21799
22098
  acc.push(curr);
21800
22099
  return acc;
21801
22100
  }, []);
@@ -21821,82 +22120,65 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
21821
22120
  }
21822
22121
  }
21823
22122
  if (rule == null) {
21824
- rule = selector.map(s => {
22123
+ rule = selector.map((s) => {
21825
22124
  if (s[0] == '&') {
21826
22125
  s.splice(0, 1, ...node.optimized.optimized);
21827
22126
  }
21828
22127
  return s.join('');
21829
22128
  }).join(',');
21830
22129
  }
21831
- // @ts-ignore
21832
22130
  let sel = wrap ? node.optimized.optimized.join('') + `:is(${rule})` : rule;
21833
22131
  if (sel.length < node.sel.length) {
21834
22132
  node.sel = sel;
21835
22133
  }
21836
22134
  }
22135
+ doMinify(node, options, recursive, errors, nestingContent, context);
21837
22136
  }
21838
- // @ts-ignore
21839
22137
  if (previous != null) {
21840
- // @ts-ignore
21841
22138
  if ('chi' in previous && ('chi' in node)) {
21842
- // @ts-ignore
21843
22139
  if (previous.typ == node.typ) {
21844
22140
  let shouldMerge = true;
21845
- // @ts-ignore
21846
22141
  let k = previous.chi.length;
21847
22142
  while (k-- > 0) {
21848
- // @ts-ignore
21849
22143
  if (previous.chi[k].typ == exports.EnumToken.CommentNodeType) {
21850
22144
  continue;
21851
22145
  }
21852
- // @ts-ignore
21853
22146
  shouldMerge = previous.chi[k].typ == exports.EnumToken.DeclarationNodeType;
21854
22147
  break;
21855
22148
  }
21856
22149
  if (shouldMerge) {
21857
- // @ts-ignore
21858
- if (((node.typ == exports.EnumToken.RuleNodeType || node.typ == exports.EnumToken.KeyFrameRuleNodeType) && node.sel == previous.sel) ||
21859
- // @ts-ignore
22150
+ if (((node.typ == exports.EnumToken.RuleNodeType || node.typ == exports.EnumToken.KeyFramesRuleNodeType) && node.sel == previous.sel) ||
21860
22151
  (node.typ == exports.EnumToken.AtRuleNodeType) && node.val != 'font-face' && node.val == previous.val) {
21861
22152
  // @ts-ignore
21862
22153
  node.chi.unshift(...previous.chi);
21863
- // @ts-ignore
22154
+ doMinify(node, options, recursive, errors, nestingContent, context);
21864
22155
  ast.chi.splice(nodeIndex, 1);
21865
- i--;
21866
- previous = node;
22156
+ previous = ast.chi[--i];
21867
22157
  nodeIndex = i;
21868
22158
  continue;
21869
22159
  }
21870
- else if (node.typ == previous?.typ && [exports.EnumToken.KeyFrameRuleNodeType, exports.EnumToken.RuleNodeType].includes(node.typ)) {
22160
+ else if (node.typ == previous?.typ && [exports.EnumToken.KeyFramesRuleNodeType, exports.EnumToken.RuleNodeType].includes(node.typ)) {
21871
22161
  const intersect = diff(previous, node, reducer, options);
21872
22162
  if (intersect != null) {
21873
22163
  if (intersect.node1.chi.length == 0) {
21874
- // @ts-ignore
21875
22164
  ast.chi.splice(i--, 1);
21876
22165
  }
21877
22166
  else {
21878
- // @ts-ignore
21879
22167
  ast.chi.splice(i--, 1, intersect.node1);
21880
22168
  }
21881
22169
  if (intersect.node2.chi.length == 0) {
21882
- // @ts-ignore
21883
22170
  ast.chi.splice(nodeIndex, 1, intersect.result);
21884
22171
  i--;
21885
- // @ts-ignore
21886
22172
  if (nodeIndex == i) {
21887
22173
  nodeIndex = i;
21888
22174
  }
21889
22175
  }
21890
22176
  else {
21891
- // @ts-ignore
21892
22177
  ast.chi.splice(nodeIndex, 1, intersect.result, intersect.node2);
21893
- // @ts-ignore
21894
22178
  i = (nodeIndex ?? 0) + 1;
21895
22179
  }
21896
22180
  reduceRuleSelector(intersect.result);
21897
- // @ts-ignore
21898
22181
  if (node != ast.chi[i]) {
21899
- // @ts-ignore
21900
22182
  node = ast.chi[i];
21901
22183
  }
21902
22184
  previous = intersect.result;
@@ -21905,9 +22187,7 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
21905
22187
  }
21906
22188
  }
21907
22189
  }
21908
- // @ts-ignore
21909
22190
  if (recursive && previous != node) {
21910
- // @ts-ignore
21911
22191
  if (!hasDeclaration(previous)) {
21912
22192
  doMinify(previous, options, recursive, errors, nestingContent, context);
21913
22193
  }
@@ -21915,9 +22195,7 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
21915
22195
  }
21916
22196
  }
21917
22197
  if (!nestingContent &&
21918
- // @ts-ignore
21919
22198
  previous != null &&
21920
- // previous.optimized != null &&
21921
22199
  previous.typ == exports.EnumToken.RuleNodeType &&
21922
22200
  previous.sel.includes('&')) {
21923
22201
  fixSelector(previous);
@@ -21925,20 +22203,15 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
21925
22203
  previous = node;
21926
22204
  nodeIndex = i;
21927
22205
  }
21928
- // @ts-ignore
21929
22206
  if (recursive && node != null && ('chi' in node)) {
21930
- // @ts-ignore
21931
- if (node.typ == exports.EnumToken.KeyframeAtRuleNodeType || !node.chi.some(n => n.typ == exports.EnumToken.DeclarationNodeType)) {
21932
- // @ts-ignore
22207
+ if (node.typ == exports.EnumToken.KeyframesAtRuleNodeType || !node.chi.some(n => n.typ == exports.EnumToken.DeclarationNodeType)) {
21933
22208
  if (!(node.typ == exports.EnumToken.AtRuleNodeType && node.nam != 'font-face')) {
21934
22209
  doMinify(node, options, recursive, errors, nestingContent, context);
21935
22210
  }
21936
22211
  }
21937
22212
  }
21938
22213
  if (!nestingContent &&
21939
- // @ts-ignore
21940
22214
  node != null &&
21941
- // previous.optimized != null &&
21942
22215
  node.typ == exports.EnumToken.RuleNodeType &&
21943
22216
  node.sel.includes('&')) {
21944
22217
  fixSelector(node);
@@ -22089,7 +22362,6 @@ function splitRule(buffer) {
22089
22362
  }
22090
22363
  if (chr == ',') {
22091
22364
  if (str !== '') {
22092
- // @ts-ignore
22093
22365
  result.at(-1).push(str);
22094
22366
  str = '';
22095
22367
  }
@@ -22098,7 +22370,6 @@ function splitRule(buffer) {
22098
22370
  }
22099
22371
  if (chr == '.') {
22100
22372
  if (str !== '') {
22101
- // @ts-ignore
22102
22373
  result.at(-1).push(str);
22103
22374
  str = '';
22104
22375
  }
@@ -22107,20 +22378,17 @@ function splitRule(buffer) {
22107
22378
  }
22108
22379
  if (combinators.includes(chr)) {
22109
22380
  if (str !== '') {
22110
- // @ts-ignore
22111
22381
  result.at(-1).push(str);
22112
22382
  str = '';
22113
22383
  }
22114
22384
  if (chr == '|' && buffer.charAt(i + 1) == '|') {
22115
22385
  chr += buffer.charAt(++i);
22116
22386
  }
22117
- // @ts-ignore
22118
22387
  result.at(-1).push(chr);
22119
22388
  continue;
22120
22389
  }
22121
22390
  if (chr == ':') {
22122
22391
  if (str !== '') {
22123
- // @ts-ignore
22124
22392
  result.at(-1).push(str);
22125
22393
  str = '';
22126
22394
  }
@@ -22162,7 +22430,6 @@ function splitRule(buffer) {
22162
22430
  }
22163
22431
  }
22164
22432
  if (str !== '') {
22165
- // @ts-ignore
22166
22433
  result.at(-1).push(str);
22167
22434
  }
22168
22435
  return result;
@@ -22227,7 +22494,7 @@ function reduceSelector(acc, curr) {
22227
22494
  *
22228
22495
  * @private
22229
22496
  */
22230
- function matchSelectors(selector1, selector2 /*, parentType: EnumToken, errors: ErrorDescription[] */) {
22497
+ function matchSelectors(selector1, selector2) {
22231
22498
  let match = [[]];
22232
22499
  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));
22233
22500
  let i = 0;
@@ -22302,7 +22569,6 @@ function matchSelectors(selector1, selector2 /*, parentType: EnumToken, errors:
22302
22569
  * @private
22303
22570
  */
22304
22571
  function fixSelector(node) {
22305
- // @ts-ignore
22306
22572
  if (node.sel.includes('&')) {
22307
22573
  const attributes = parseString(node.sel);
22308
22574
  for (const attr of walkValues(attributes)) {
@@ -22337,40 +22603,27 @@ function wrapNodes(previous, node, match, ast, reducer, i, nodeIndex) {
22337
22603
  let nSel = match.selector2.reduce(reducer, []).join(',');
22338
22604
  // @ts-ignore
22339
22605
  const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(',') };
22340
- // @ts-ignore
22341
22606
  Object.defineProperty(wrapper, 'raw', {
22342
22607
  ...definedPropertySettings,
22343
- // @ts-ignore
22344
22608
  value: match.match.map(t => t.slice())
22345
22609
  });
22346
22610
  if (pSel == '&' || pSel === '') {
22347
- // @ts-ignore
22348
22611
  wrapper.chi.push(...previous.chi);
22349
- // @ts-ignore
22350
22612
  if ((nSel == '&' || nSel === '')) {
22351
- // @ts-ignore
22352
22613
  wrapper.chi.push(...node.chi);
22353
22614
  }
22354
22615
  else {
22355
- // @ts-ignore
22356
22616
  wrapper.chi.push(node);
22357
22617
  }
22358
22618
  }
22359
22619
  else {
22360
- // @ts-ignore
22361
22620
  wrapper.chi.push(previous, node);
22362
22621
  }
22363
- // @ts-ignore
22364
22622
  ast.chi.splice(i, 1, wrapper);
22365
- // @ts-ignore
22366
22623
  ast.chi.splice(nodeIndex, 1);
22367
- // @ts-ignore
22368
22624
  previous.sel = pSel;
22369
- // @ts-ignore
22370
22625
  previous.raw = match.selector1;
22371
- // @ts-ignore
22372
22626
  node.sel = nSel;
22373
- // @ts-ignore
22374
22627
  node.raw = match.selector2;
22375
22628
  reduceRuleSelector(wrapper);
22376
22629
  return wrapper;
@@ -22775,29 +23028,37 @@ function replaceCompoundLiteral(selector, replace) {
22775
23028
  }, '');
22776
23029
  }
22777
23030
 
22778
- /**
22779
- * node module entry point
22780
- * @module node
22781
- */
22782
23031
  /**
22783
23032
  * load file or url as stream
22784
23033
  * @param url
22785
23034
  * @param currentFile
23035
+ * @throws Error file not found
22786
23036
  *
22787
23037
  * @private
22788
23038
  */
22789
- async function getStream(url, currentFile = '.') {
23039
+ async function load(url, currentFile = '.') {
22790
23040
  const resolved = resolve(url, currentFile);
22791
23041
  // @ts-ignore
22792
- return matchUrl.test(resolved.absolute) ? fetch(resolved.absolute).then((response) => {
22793
- if (!response.ok) {
22794
- throw new Error(`${response.status} ${response.statusText} ${response.url}`);
23042
+ if (matchUrl.test(resolved.absolute)) {
23043
+ return fetch(resolved.absolute).then((response) => {
23044
+ if (!response.ok) {
23045
+ throw new Error(`${response.status} ${response.statusText} ${response.url}`);
23046
+ }
23047
+ return response.body;
23048
+ });
23049
+ }
23050
+ try {
23051
+ const stats = await promises.lstat(resolved.absolute);
23052
+ if (stats.isFile()) {
23053
+ return node_stream.Readable.toWeb(node_fs.createReadStream(resolved.absolute));
22795
23054
  }
22796
- return response.body;
22797
- }) : node_stream.Readable.toWeb(node_fs.createReadStream(resolved.absolute));
23055
+ }
23056
+ catch (error) {
23057
+ }
23058
+ throw new Error(`File not found: '${resolved.absolute || url}'`);
22798
23059
  }
22799
23060
  /**
22800
- * render ast tree
23061
+ * render the ast tree
22801
23062
  * @param data
22802
23063
  * @param options
22803
23064
  *
@@ -22807,23 +23068,33 @@ async function getStream(url, currentFile = '.') {
22807
23068
  *
22808
23069
  * import {render, ColorType} from '@tbela99/css-parser';
22809
23070
  *
22810
- * // remote file
22811
- * let result = render(ast);
22812
- * console.log(result.code);
23071
+ * const css = 'body { color: color(from hsl(0 100% 50%) xyz x y z); }';
23072
+ * const parseResult = await parse(css);
22813
23073
  *
22814
- * // local file
22815
- * result = await parseFile(ast, {beatify: true, convertColor: ColorType.SRGB});
23074
+ * let renderResult = render(parseResult.ast);
22816
23075
  * console.log(result.code);
23076
+ *
23077
+ * // body{color:red}
23078
+ *
23079
+ *
23080
+ * renderResult = render(parseResult.ast, {beautify: true, convertColor: ColorType.SRGB});
23081
+ * console.log(renderResult.code);
23082
+ *
23083
+ * // body {
23084
+ * // color: color(srgb 1 0 0)
23085
+ * // }
22817
23086
  * ```
22818
23087
  */
22819
23088
  function render(data, options = {}) {
22820
- return doRender(data, Object.assign(options, { getStream, resolve, dirname, cwd: options.cwd ?? process.cwd() }));
23089
+ return doRender(data, Object.assign(options, { resolve, dirname, cwd: options.cwd ?? process.cwd() }));
22821
23090
  }
22822
23091
  /**
22823
23092
  * parse css file
22824
23093
  * @param file url or path
22825
23094
  * @param options
22826
23095
  *
23096
+ * @throws Error file not found
23097
+ *
22827
23098
  * Example:
22828
23099
  *
22829
23100
  * ```ts
@@ -22840,22 +23111,22 @@ function render(data, options = {}) {
22840
23111
  * ```
22841
23112
  */
22842
23113
  async function parseFile(file, options = {}) {
22843
- return getStream(file).then(stream => parse(stream, { src: file, ...options }));
23114
+ return load(file).then(stream => parse(stream, { src: file, ...options }));
22844
23115
  }
22845
23116
  /**
22846
23117
  * parse css
22847
23118
  * @param stream
22848
- * @param opt
23119
+ * @param options
22849
23120
  *
22850
23121
  * Example:
22851
23122
  *
22852
23123
  * ```ts
22853
23124
  *
22854
- * import {transform} from '@tbela99/css-parser';
23125
+ * import {parse} from '@tbela99/css-parser';
22855
23126
  *
22856
23127
  * // css string
22857
- * let result = await transform(css);
22858
- * console.log(result.code);
23128
+ * let result = await parse(css);
23129
+ * console.log(result.ast);
22859
23130
  * ```
22860
23131
  *
22861
23132
  * Example using stream
@@ -22868,36 +23139,38 @@ async function parseFile(file, options = {}) {
22868
23139
  * // usage: node index.ts < styles.css or cat styles.css | node index.ts
22869
23140
  *
22870
23141
  * const readableStream = Readable.toWeb(process.stdin);
22871
- * const result = await parse(readableStream, {beautify: true});
23142
+ * let result = await parse(readableStream, {beautify: true});
22872
23143
  *
22873
23144
  * console.log(result.ast);
22874
23145
  * ```
22875
23146
  *
22876
- * Example using fetch
23147
+ * Example using fetch and readable stream
22877
23148
  *
22878
23149
  * ```ts
22879
23150
  *
22880
23151
  * import {parse} from '@tbela99/css-parser';
22881
23152
  *
22882
23153
  * const response = await fetch('https://docs.deno.com/styles.css');
22883
- * result = await parse(response.body, {beautify: true});
23154
+ * const result = await parse(response.body, {beautify: true});
22884
23155
  *
22885
23156
  * console.log(result.ast);
22886
23157
  * ```
22887
23158
  */
22888
- async function parse(stream, opt = {}) {
23159
+ async function parse(stream, options = {}) {
22889
23160
  return doParse(stream instanceof ReadableStream ? tokenizeStream(stream) : tokenize$1({
22890
23161
  stream,
22891
23162
  buffer: '',
22892
23163
  position: { ind: 0, lin: 1, col: 1 },
22893
23164
  currentPosition: { ind: -1, lin: 1, col: 0 }
22894
- }), Object.assign(opt, { getStream, resolve, dirname, cwd: opt.cwd ?? process.cwd() }));
23165
+ }), Object.assign(options, { load, resolve, dirname, cwd: options.cwd ?? process.cwd() }));
22895
23166
  }
22896
23167
  /**
22897
23168
  * transform css file
22898
23169
  * @param file url or path
22899
23170
  * @param options
22900
23171
  *
23172
+ * @throws Error file not found
23173
+ *
22901
23174
  * Example:
22902
23175
  *
22903
23176
  * ```ts
@@ -22914,7 +23187,7 @@ async function parse(stream, opt = {}) {
22914
23187
  * ```
22915
23188
  */
22916
23189
  async function transformFile(file, options = {}) {
22917
- return getStream(file).then(stream => transform(stream, { src: file, ...options }));
23190
+ return load(file).then(stream => transform(stream, { src: file, ...options }));
22918
23191
  }
22919
23192
  /**
22920
23193
  * transform css
@@ -22928,7 +23201,7 @@ async function transformFile(file, options = {}) {
22928
23201
  * import {transform} from '@tbela99/css-parser';
22929
23202
  *
22930
23203
  * // css string
22931
- * let result = await transform(css);
23204
+ * const result = await transform(css);
22932
23205
  * console.log(result.code);
22933
23206
  * ```
22934
23207
  *
@@ -22963,7 +23236,8 @@ async function transform(css, options = {}) {
22963
23236
  options = { minify: true, removeEmpty: true, removeCharset: true, ...options };
22964
23237
  const startTime = performance.now();
22965
23238
  return parse(css, options).then((parseResult) => {
22966
- const rendered = render(parseResult.ast, options);
23239
+ // ast already expanded by parse
23240
+ const rendered = render(parseResult.ast, { ...options, expandNestingRules: false });
22967
23241
  return {
22968
23242
  ...parseResult,
22969
23243
  ...rendered,
@@ -22982,8 +23256,8 @@ exports.SourceMap = SourceMap;
22982
23256
  exports.convertColor = convertColor;
22983
23257
  exports.dirname = dirname;
22984
23258
  exports.expand = expand;
22985
- exports.getStream = getStream;
22986
23259
  exports.isOkLabClose = isOkLabClose;
23260
+ exports.load = load;
22987
23261
  exports.minify = minify;
22988
23262
  exports.okLabDistance = okLabDistance;
22989
23263
  exports.parse = parse;