@tbela99/css-parser 1.2.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +29 -11
  3. package/dist/index-umd-web.js +2041 -1967
  4. package/dist/index.cjs +2129 -1964
  5. package/dist/index.d.ts +1936 -77
  6. package/dist/lib/ast/expand.js +4 -65
  7. package/dist/lib/ast/features/calc.js +3 -27
  8. package/dist/lib/ast/features/inlinecssvariables.js +2 -21
  9. package/dist/lib/ast/features/prefix.js +2 -1
  10. package/dist/lib/ast/features/transform.js +4 -3
  11. package/dist/lib/ast/features/type.js +9 -0
  12. package/dist/lib/ast/math/expression.js +26 -149
  13. package/dist/lib/ast/math/math.js +9 -9
  14. package/dist/lib/ast/minify.js +82 -171
  15. package/dist/lib/ast/transform/compute.js +4 -37
  16. package/dist/lib/ast/transform/matrix.js +33 -34
  17. package/dist/lib/ast/transform/minify.js +32 -51
  18. package/dist/lib/ast/transform/perspective.js +1 -1
  19. package/dist/lib/ast/transform/rotate.js +13 -13
  20. package/dist/lib/ast/transform/scale.js +8 -8
  21. package/dist/lib/ast/transform/skew.js +4 -4
  22. package/dist/lib/ast/transform/translate.js +8 -8
  23. package/dist/lib/ast/transform/utils.js +31 -39
  24. package/dist/lib/ast/types.js +459 -5
  25. package/dist/lib/ast/walk.js +18 -0
  26. package/dist/lib/fs/resolve.js +11 -3
  27. package/dist/lib/parser/declaration/map.js +1 -0
  28. package/dist/lib/parser/declaration/set.js +2 -2
  29. package/dist/lib/parser/parse.js +139 -32
  30. package/dist/lib/parser/tokenize.js +41 -93
  31. package/dist/lib/parser/utils/type.js +1 -1
  32. package/dist/lib/renderer/render.js +61 -30
  33. package/dist/lib/renderer/sourcemap/sourcemap.js +34 -0
  34. package/dist/lib/syntax/color/cmyk.js +2 -2
  35. package/dist/lib/syntax/color/color-mix.js +11 -12
  36. package/dist/lib/syntax/color/color.js +14 -7
  37. package/dist/lib/syntax/color/hsl.js +4 -4
  38. package/dist/lib/syntax/color/hwb.js +27 -8
  39. package/dist/lib/syntax/color/lab.js +4 -4
  40. package/dist/lib/syntax/color/lch.js +4 -4
  41. package/dist/lib/syntax/color/oklab.js +4 -4
  42. package/dist/lib/syntax/color/oklch.js +4 -4
  43. package/dist/lib/syntax/color/relativecolor.js +1 -1
  44. package/dist/lib/syntax/color/rgb.js +4 -4
  45. package/dist/lib/syntax/color/utils/components.js +15 -3
  46. package/dist/lib/syntax/color/utils/distance.js +15 -1
  47. package/dist/lib/syntax/syntax.js +18 -17
  48. package/dist/lib/syntax/utils.js +1 -1
  49. package/dist/lib/validation/at-rules/document.js +1 -1
  50. package/dist/lib/validation/at-rules/import.js +4 -4
  51. package/dist/lib/validation/at-rules/keyframes.js +0 -11
  52. package/dist/lib/validation/at-rules/supports.js +6 -6
  53. package/dist/lib/validation/config.js +0 -4
  54. package/dist/lib/validation/config.json.js +33 -30
  55. package/dist/lib/validation/parser/parse.js +0 -8
  56. package/dist/lib/validation/selector.js +0 -9
  57. package/dist/lib/validation/syntax.js +17 -135
  58. package/dist/lib/validation/syntaxes/complex-selector-list.js +0 -11
  59. package/dist/lib/validation/syntaxes/family-name.js +0 -32
  60. package/dist/lib/validation/syntaxes/keyframe-selector.js +0 -11
  61. package/dist/lib/validation/syntaxes/relative-selector-list.js +0 -26
  62. package/dist/lib/validation/syntaxes/url.js +0 -33
  63. package/dist/lib/validation/utils/list.js +0 -8
  64. package/dist/node.js +229 -0
  65. package/dist/web.js +158 -0
  66. package/package.json +14 -11
  67. package/dist/node/index.js +0 -57
  68. package/dist/node/load.js +0 -20
  69. package/dist/web/index.js +0 -66
  70. package/dist/web/load.js +0 -31
@@ -8,6 +8,11 @@ import { isColor, pseudoElements, mathFuncs, isNewLine } from '../syntax/syntax.
8
8
  import { minifyNumber } from '../syntax/utils.js';
9
9
  import { SourceMap } from './sourcemap/sourcemap.js';
10
10
 
11
+ /**
12
+ * Update position
13
+ * @param position
14
+ * @param str
15
+ */
11
16
  function update(position, str) {
12
17
  let i = 0;
13
18
  for (; i < str.length; i++) {
@@ -24,6 +29,7 @@ function update(position, str) {
24
29
  * render ast
25
30
  * @param data
26
31
  * @param options
32
+ * @private
27
33
  */
28
34
  function doRender(data, options = {}) {
29
35
  const minify = options.minify ?? true;
@@ -91,6 +97,17 @@ function doRender(data, options = {}) {
91
97
  }
92
98
  return result;
93
99
  }
100
+ /**
101
+ * Update source map
102
+ * @param node
103
+ * @param options
104
+ * @param cache
105
+ * @param sourcemap
106
+ * @param position
107
+ * @param str
108
+ *
109
+ * @internal
110
+ */
94
111
  function updateSourceMap(node, options, cache, sourcemap, position, str) {
95
112
  if ([
96
113
  EnumToken.RuleNodeType, EnumToken.AtRuleNodeType,
@@ -126,6 +143,8 @@ function updateSourceMap(node, options, cache, sourcemap, position, str) {
126
143
  * @param cache
127
144
  * @param level
128
145
  * @param indents
146
+ *
147
+ * @internal
129
148
  */
130
149
  function renderAstNode(data, options, sourcemap, position, errors, reducer, cache, level = 0, indents = []) {
131
150
  if (indents.length < level + 1) {
@@ -224,9 +243,6 @@ function renderAstNode(data, options, sourcemap, position, errors, reducer, cach
224
243
  * render ast token
225
244
  * @param token
226
245
  * @param options
227
- * @param cache
228
- * @param reducer
229
- * @param errors
230
246
  */
231
247
  function renderToken(token, options = {}, cache = Object.create(null), reducer, errors) {
232
248
  if (reducer == null) {
@@ -325,7 +341,7 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
325
341
  if (Array.isArray(token.chi)) {
326
342
  const isLegacy = ['rgb', 'rgba', 'hsl', 'hsla'].includes(token.val.toLowerCase());
327
343
  const useAlpha = (['rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'oklab', 'oklch', 'lab', 'lch'].includes(token.val.toLowerCase()) && token.chi.length == 4) ||
328
- ('color'.localeCompare(token.val, undefined, { sensitivity: 'base' }) == 0 && token.chi.length == 5);
344
+ ('color' == token.val.toLowerCase() && token.chi.length == 5);
329
345
  return (token.val.endsWith('a') ? token.val.slice(0, -1) : token.val) + '(' + token.chi.reduce((acc, curr, index, array) => {
330
346
  if (/[,/]\s*$/.test(acc)) {
331
347
  if (curr.typ == EnumToken.WhitespaceTokenType) {
@@ -522,32 +538,41 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
522
538
  return token.val.slice(1);
523
539
  }
524
540
  case EnumToken.UrlTokenTokenType:
525
- if (token.typ == EnumToken.UrlTokenTokenType) {
526
- if (options.output != null) {
527
- if (!('original' in token)) {
528
- // do not modify original token
529
- token = { ...token };
530
- Object.defineProperty(token, 'original', {
531
- enumerable: false,
532
- writable: false,
533
- value: token.val
534
- });
535
- }
536
- // @ts-ignore
537
- if (!(token.original in cache)) {
538
- let output = options.output ?? '';
539
- const key = output + 'abs';
540
- if (!(key in cache)) {
541
- // @ts-ignore
542
- cache[key] = options.dirname(options.resolve(output, options.cwd).absolute);
543
- }
544
- // @ts-ignore
545
- cache[token.original] = options.resolve(token.original, cache[key]).relative;
546
- }
547
- // @ts-ignore
548
- token.val = cache[token.original];
549
- }
550
- }
541
+ // if (token.typ == EnumToken.UrlTokenTokenType) {
542
+ //
543
+ // if (options.output != null) {
544
+ //
545
+ // if (!('original' in token)) {
546
+ //
547
+ // // do not modify original token
548
+ // token = {...token};
549
+ // Object.defineProperty(token, 'original', {
550
+ // enumerable: false,
551
+ // writable: false,
552
+ // value: (token as UrlToken).val
553
+ // })
554
+ // }
555
+ //
556
+ // // @ts-ignore
557
+ // if (!(token.original in cache)) {
558
+ //
559
+ // let output: string = <string>options.output ?? '';
560
+ // const key = output + 'abs';
561
+ //
562
+ // if (!(key in cache)) {
563
+ //
564
+ // // @ts-ignore
565
+ // cache[key] = options.dirname(options.resolve(output, options.cwd).absolute);
566
+ // }
567
+ //
568
+ // // @ts-ignore
569
+ // cache[token.original] = options.resolve(token.original, cache[key]).relative;
570
+ // }
571
+ //
572
+ // // @ts-ignore
573
+ // token.val = cache[token.original];
574
+ // }
575
+ // }
551
576
  case EnumToken.HashTokenType:
552
577
  case EnumToken.IdenTokenType:
553
578
  case EnumToken.AtRuleTokenType:
@@ -581,6 +606,12 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
581
606
  errors?.push({ action: 'ignore', message: `render: unexpected token ${JSON.stringify(token, null, 1)}` });
582
607
  return '';
583
608
  }
609
+ /**
610
+ * Remove whitespace tokens that are not needed
611
+ * @param values
612
+ *
613
+ * @internal
614
+ */
584
615
  function filterValues(values) {
585
616
  let i = 0;
586
617
  for (; i < values.length; i++) {
@@ -1,11 +1,39 @@
1
1
  import { encode } from './lib/encode.js';
2
2
 
3
+ /**
4
+ * Source map class
5
+ * @internal
6
+ */
3
7
  class SourceMap {
8
+ /**
9
+ * Last location
10
+ */
4
11
  lastLocation = null;
12
+ /**
13
+ * Version
14
+ * @private
15
+ */
5
16
  #version = 3;
17
+ /**
18
+ * Sources
19
+ * @private
20
+ */
6
21
  #sources = [];
22
+ /**
23
+ * Map
24
+ * @private
25
+ */
7
26
  #map = new Map;
27
+ /**
28
+ * Line
29
+ * @private
30
+ */
8
31
  #line = -1;
32
+ /**
33
+ * Add a location
34
+ * @param source
35
+ * @param original
36
+ */
9
37
  add(source, original) {
10
38
  if (original.src !== '') {
11
39
  if (!this.#sources.includes(original.src)) {
@@ -32,10 +60,16 @@ class SourceMap {
32
60
  this.lastLocation = original;
33
61
  }
34
62
  }
63
+ /**
64
+ * Convert to URL encoded string
65
+ */
35
66
  toUrl() {
36
67
  // /*# sourceMappingURL = ${url} */
37
68
  return `data:application/json,${encodeURIComponent(JSON.stringify(this.toJSON()))}`;
38
69
  }
70
+ /**
71
+ * Convert to JSON object
72
+ */
39
73
  toJSON() {
40
74
  const mappings = [];
41
75
  let i = 0;
@@ -92,11 +92,11 @@ function cmyktoken(values) {
92
92
  chi: values.reduce((acc, curr, index) => index < 4 ? [...acc, {
93
93
  typ: EnumToken.PercentageTokenType,
94
94
  // @ts-ignore
95
- val: (curr * 100) + ''
95
+ val: curr * 100
96
96
  }] : [...acc, {
97
97
  typ: EnumToken.LiteralTokenType,
98
98
  val: '/'
99
- }, { typ: EnumToken.PercentageTokenType, val: (curr * 100).toFixed() }], []),
99
+ }, { typ: EnumToken.PercentageTokenType, val: curr * 100 }], []),
100
100
  kin: ColorType.DEVICE_CMYK
101
101
  };
102
102
  }
@@ -57,7 +57,7 @@ function interpolateHue(interpolationMethod, h1, h2) {
57
57
  return [h1, h2];
58
58
  }
59
59
  function colorMix(colorSpace, hueInterpolationMethod, color1, percentage1, color2, percentage2) {
60
- if (color1.val == 'currentcolor' || color2.val == 'currentcolor') {
60
+ if (color1.val.toLowerCase() == 'currentcolor' || color2.val == 'currentcolor'.toLowerCase()) {
61
61
  return null;
62
62
  }
63
63
  if (hueInterpolationMethod != null && isRectangularOrthogonalColorspace(colorSpace)) {
@@ -69,20 +69,19 @@ function colorMix(colorSpace, hueInterpolationMethod, color1, percentage1, color
69
69
  if (percentage1 == null) {
70
70
  if (percentage2 == null) {
71
71
  // @ts-ignore
72
- percentage1 = { typ: EnumToken.NumberTokenType, val: '.5' };
72
+ percentage1 = { typ: EnumToken.NumberTokenType, val: .5 };
73
73
  // @ts-ignore
74
- percentage2 = { typ: EnumToken.NumberTokenType, val: '.5' };
74
+ percentage2 = { typ: EnumToken.NumberTokenType, val: .5 };
75
75
  }
76
76
  else {
77
77
  if (+percentage2.val <= 0) {
78
78
  return null;
79
79
  }
80
80
  if (+percentage2.val >= 100) {
81
- // @ts-ignore
82
- percentage2 = { typ: EnumToken.NumberTokenType, val: '1' };
81
+ percentage2 = { typ: EnumToken.NumberTokenType, val: 1 };
83
82
  }
84
83
  // @ts-ignore
85
- percentage1 = { typ: EnumToken.NumberTokenType, val: String(1 - percentage2.val / 100) };
84
+ percentage1 = { typ: EnumToken.NumberTokenType, val: 1 - percentage2.val / 100 };
86
85
  }
87
86
  }
88
87
  else {
@@ -94,10 +93,10 @@ function colorMix(colorSpace, hueInterpolationMethod, color1, percentage1, color
94
93
  // @ts-ignore
95
94
  if (percentage1.val >= 100) {
96
95
  // @ts-ignore
97
- percentage1 = { typ: EnumToken.NumberTokenType, val: '1' };
96
+ percentage1 = { typ: EnumToken.NumberTokenType, val: 1 };
98
97
  }
99
98
  // @ts-ignore
100
- percentage2 = { typ: EnumToken.NumberTokenType, val: String(1 - percentage1.val / 100) };
99
+ percentage2 = { typ: EnumToken.NumberTokenType, val: 1 - percentage1.val / 100 };
101
100
  }
102
101
  else {
103
102
  // @ts-ignore
@@ -275,7 +274,7 @@ function colorMix(colorSpace, hueInterpolationMethod, color1, percentage1, color
275
274
  chi: values.map(v => {
276
275
  return {
277
276
  typ: EnumToken.NumberTokenType,
278
- val: String(v)
277
+ val: v
279
278
  };
280
279
  }),
281
280
  kin: ColorType.LCH
@@ -332,11 +331,11 @@ function colorMix(colorSpace, hueInterpolationMethod, color1, percentage1, color
332
331
  };
333
332
  if (colorSpace.val == 'hsl' || colorSpace.val == 'hwb') {
334
333
  // @ts-ignore
335
- result.chi[0] = { typ: EnumToken.AngleTokenType, val: String(result.chi[0].val * 360), unit: 'deg' };
334
+ result.chi[0] = { typ: EnumToken.AngleTokenType, val: result.chi[0].val * 360 };
336
335
  // @ts-ignore
337
- result.chi[1] = { typ: EnumToken.PercentageTokenType, val: String(result.chi[1].val * 100) };
336
+ result.chi[1] = { typ: EnumToken.PercentageTokenType, val: result.chi[1].val * 100 };
338
337
  // @ts-ignore
339
- result.chi[2] = { typ: EnumToken.PercentageTokenType, val: String(result.chi[2].val * 100) };
338
+ result.chi[2] = { typ: EnumToken.PercentageTokenType, val: result.chi[2].val * 100 };
340
339
  }
341
340
  return result;
342
341
  }
@@ -28,15 +28,22 @@ import { a98rgb2srgbvalues, srgb2a98values } from './a98rgb.js';
28
28
  import '../../renderer/sourcemap/lib/encode.js';
29
29
 
30
30
  /**
31
- * Converts a color token to another color space
31
+ * Converts a color to another color space
32
32
  * @param token
33
33
  * @param to
34
+ *
35
+ * <code>
36
+ *
37
+ * const token = {typ: EnumToken.ColorTokenType, kin: ColorType.HEX, val: '#F00'}
38
+ * const result = convertColor(token, ColorType.LCH);
39
+ *
40
+ * </code>
34
41
  */
35
42
  function convertColor(token, to) {
36
43
  if (token.kin == ColorType.SYS ||
37
44
  token.kin == ColorType.DPSYS ||
38
45
  (isIdentColor(token) &&
39
- ('currentcolor'.localeCompare(token.val, undefined, { sensitivity: 'base' }) == 0))) {
46
+ 'currentcolor' == token.val.toLowerCase())) {
40
47
  return token;
41
48
  }
42
49
  if (token.kin == ColorType.COLOR_MIX && to != ColorType.COLOR_MIX) {
@@ -505,14 +512,14 @@ function color2srgbvalues(token) {
505
512
  function values2colortoken(values, to) {
506
513
  values = srgb2srgbcolorspace(values, to);
507
514
  const chi = [
508
- { typ: EnumToken.NumberTokenType, val: String(values[0]) },
509
- { typ: EnumToken.NumberTokenType, val: String(values[1]) },
510
- { typ: EnumToken.NumberTokenType, val: String(values[2]) },
515
+ { typ: EnumToken.NumberTokenType, val: values[0] },
516
+ { typ: EnumToken.NumberTokenType, val: values[1] },
517
+ { typ: EnumToken.NumberTokenType, val: values[2] },
511
518
  ];
512
519
  if (values.length == 4) {
513
520
  chi.push({ typ: EnumToken.LiteralTokenType, val: "/" }, {
514
521
  typ: EnumToken.PercentageTokenType,
515
- val: (values[3] * 100).toFixed()
522
+ val: values[3] * 100
516
523
  });
517
524
  }
518
525
  const colorSpace = ColorType[to].toLowerCase().replaceAll('_', '-');
@@ -533,7 +540,7 @@ function getNumber(token) {
533
540
  return 0;
534
541
  }
535
542
  // @ts-ignore
536
- return token.typ == EnumToken.PercentageTokenType ? token.val / 100 : +token.val;
543
+ return token.typ == EnumToken.PercentageTokenType ? token.val / 100 : token.val;
537
544
  }
538
545
  /**
539
546
  * convert angle to turn
@@ -76,12 +76,12 @@ function color2HslToken(token) {
76
76
  function hslToken(values) {
77
77
  values[0] = toPrecisionAngle(values[0] * 360);
78
78
  const chi = [
79
- { typ: EnumToken.NumberTokenType, val: String(values[0]), uni: 'deg' },
80
- { typ: EnumToken.PercentageTokenType, val: String(values[1] * 100) },
81
- { typ: EnumToken.PercentageTokenType, val: String(values[2] * 100) },
79
+ { typ: EnumToken.NumberTokenType, val: values[0] },
80
+ { typ: EnumToken.PercentageTokenType, val: values[1] * 100 },
81
+ { typ: EnumToken.PercentageTokenType, val: values[2] * 100 },
82
82
  ];
83
83
  if (values.length == 4 && values[3] != 1) {
84
- chi.push({ typ: EnumToken.LiteralTokenType, val: '/' }, { typ: EnumToken.PercentageTokenType, val: (values[3] * 100).toFixed() });
84
+ chi.push({ typ: EnumToken.LiteralTokenType, val: '/' }, { typ: EnumToken.PercentageTokenType, val: values[3] * 100 });
85
85
  }
86
86
  return {
87
87
  typ: EnumToken.ColorTokenType,
@@ -70,12 +70,15 @@ function color2hwbToken(token) {
70
70
  function hwbToken(values) {
71
71
  values[0] = toPrecisionAngle(values[0] * 360);
72
72
  const chi = [
73
- { typ: EnumToken.NumberTokenType, val: String(values[0]) },
74
- { typ: EnumToken.PercentageTokenType, val: String(values[1] * 100) },
75
- { typ: EnumToken.PercentageTokenType, val: String(values[2] * 100) },
73
+ { typ: EnumToken.NumberTokenType, val: values[0] },
74
+ { typ: EnumToken.PercentageTokenType, val: values[1] * 100 },
75
+ { typ: EnumToken.PercentageTokenType, val: values[2] * 100 },
76
76
  ];
77
77
  if (values.length == 4) {
78
- chi.push({ typ: EnumToken.LiteralTokenType, val: '/' }, { typ: EnumToken.PercentageTokenType, val: String((values[3] * 100).toFixed()) });
78
+ chi.push({ typ: EnumToken.LiteralTokenType, val: '/' }, {
79
+ typ: EnumToken.PercentageTokenType,
80
+ val: values[3] * 100
81
+ });
79
82
  }
80
83
  return {
81
84
  typ: EnumToken.ColorTokenType,
@@ -110,16 +113,28 @@ function hsl2hwbvalues(token) {
110
113
  }));
111
114
  }
112
115
  function lab2hwbvalues(token) {
116
+ const values = lab2srgbvalues(token);
117
+ if (values == null) {
118
+ return null;
119
+ }
113
120
  // @ts-ignore
114
- return srgb2hwb(...lab2srgbvalues(token));
121
+ return srgb2hwb(...values);
115
122
  }
116
123
  function lch2hwbvalues(token) {
124
+ const values = lch2srgbvalues(token);
125
+ if (values == null) {
126
+ return null;
127
+ }
117
128
  // @ts-ignore
118
- return srgb2hwb(...lch2srgbvalues(token));
129
+ return srgb2hwb(...values);
119
130
  }
120
131
  function oklab2hwbvalues(token) {
132
+ const values = oklab2srgbvalues(token);
133
+ if (values == null) {
134
+ return null;
135
+ }
121
136
  // @ts-ignore
122
- return srgb2hwb(...oklab2srgbvalues(token));
137
+ return srgb2hwb(...values);
123
138
  }
124
139
  function oklch2hwbvalues(token) {
125
140
  const values = oklch2srgbvalues(token);
@@ -153,8 +168,12 @@ function rgb2whiteness(r, g, b) {
153
168
  return Math.min(r, g, b);
154
169
  }
155
170
  function color2hwbvalues(token) {
171
+ const values = color2srgbvalues(token);
172
+ if (values == null) {
173
+ return null;
174
+ }
156
175
  // @ts-ignore
157
- return srgb2hwb(...color2srgbvalues(token));
176
+ return srgb2hwb(...values);
158
177
  }
159
178
  function srgb2hwb(r, g, b, a = null, fallback = 0) {
160
179
  r *= 100;
@@ -76,14 +76,14 @@ function color2labToken(token) {
76
76
  }
77
77
  function labToken(values) {
78
78
  const chi = [
79
- { typ: EnumToken.NumberTokenType, val: String(values[0]) },
80
- { typ: EnumToken.NumberTokenType, val: String(values[1]) },
81
- { typ: EnumToken.NumberTokenType, val: String(values[2]) },
79
+ { typ: EnumToken.NumberTokenType, val: values[0] },
80
+ { typ: EnumToken.NumberTokenType, val: values[1] },
81
+ { typ: EnumToken.NumberTokenType, val: values[2] },
82
82
  ];
83
83
  if (values.length == 4) {
84
84
  chi.push({ typ: EnumToken.LiteralTokenType, val: '/' }, {
85
85
  typ: EnumToken.PercentageTokenType,
86
- val: (values[3] * 100).toFixed()
86
+ val: values[3] * 100
87
87
  });
88
88
  }
89
89
  return {
@@ -77,12 +77,12 @@ function color2lchToken(token) {
77
77
  function lchToken(values) {
78
78
  values[2] = toPrecisionAngle(values[2]);
79
79
  const chi = [
80
- { typ: EnumToken.NumberTokenType, val: String(values[0]) },
81
- { typ: EnumToken.NumberTokenType, val: String(values[1]) },
82
- { typ: EnumToken.NumberTokenType, val: String(values[2]) },
80
+ { typ: EnumToken.NumberTokenType, val: values[0] },
81
+ { typ: EnumToken.NumberTokenType, val: values[1] },
82
+ { typ: EnumToken.NumberTokenType, val: values[2] },
83
83
  ];
84
84
  if (values.length == 4) {
85
- chi.push({ typ: EnumToken.LiteralTokenType, val: '/' }, { typ: EnumToken.PercentageTokenType, val: (values[3] * 100).toFixed() });
85
+ chi.push({ typ: EnumToken.LiteralTokenType, val: '/' }, { typ: EnumToken.PercentageTokenType, val: values[3] * 100 });
86
86
  }
87
87
  return {
88
88
  typ: EnumToken.ColorTokenType,
@@ -78,14 +78,14 @@ function color2oklabToken(token) {
78
78
  }
79
79
  function oklabToken(values) {
80
80
  const chi = [
81
- { typ: EnumToken.NumberTokenType, val: String(values[0]) },
82
- { typ: EnumToken.NumberTokenType, val: String(values[1]) },
83
- { typ: EnumToken.NumberTokenType, val: String(values[2]) },
81
+ { typ: EnumToken.NumberTokenType, val: values[0] },
82
+ { typ: EnumToken.NumberTokenType, val: values[1] },
83
+ { typ: EnumToken.NumberTokenType, val: values[2] },
84
84
  ];
85
85
  if (values.length == 4) {
86
86
  chi.push({ typ: EnumToken.LiteralTokenType, val: '/' }, {
87
87
  typ: EnumToken.PercentageTokenType,
88
- val: (values[3] * 100).toFixed()
88
+ val: values[3] * 100
89
89
  });
90
90
  }
91
91
  return {
@@ -76,14 +76,14 @@ function color2oklchToken(token) {
76
76
  function oklchToken(values) {
77
77
  values[2] = toPrecisionAngle(values[2]);
78
78
  const chi = [
79
- { typ: EnumToken.NumberTokenType, val: String(values[0]) },
80
- { typ: EnumToken.NumberTokenType, val: String(values[1]) },
81
- { typ: EnumToken.NumberTokenType, val: String(values[2]) },
79
+ { typ: EnumToken.NumberTokenType, val: values[0] },
80
+ { typ: EnumToken.NumberTokenType, val: values[1] },
81
+ { typ: EnumToken.NumberTokenType, val: values[2] },
82
82
  ];
83
83
  if (values.length == 4) {
84
84
  chi.push({ typ: EnumToken.LiteralTokenType, val: '/' }, {
85
85
  typ: EnumToken.PercentageTokenType,
86
- val: (values[3] * 100).toFixed()
86
+ val: values[3] * 100
87
87
  });
88
88
  }
89
89
  return {
@@ -70,7 +70,7 @@ function getValue(t, converted, component) {
70
70
  }
71
71
  return {
72
72
  typ: EnumToken.NumberTokenType,
73
- val: String(value)
73
+ val: value
74
74
  };
75
75
  }
76
76
  return t;
@@ -74,12 +74,12 @@ function color2RgbToken(token) {
74
74
  }
75
75
  function rgb2RgbToken(values) {
76
76
  const chi = [
77
- { typ: EnumToken.NumberTokenType, val: String(values[0]) },
78
- { typ: EnumToken.NumberTokenType, val: String(values[1]) },
79
- { typ: EnumToken.NumberTokenType, val: String(values[2]) },
77
+ { typ: EnumToken.NumberTokenType, val: values[0] },
78
+ { typ: EnumToken.NumberTokenType, val: values[1] },
79
+ { typ: EnumToken.NumberTokenType, val: values[2] },
80
80
  ];
81
81
  if (values.length == 4) {
82
- chi.push({ typ: EnumToken.PercentageTokenType, val: (values[3] * 100).toFixed() });
82
+ chi.push({ typ: EnumToken.PercentageTokenType, val: values[3] * 100 });
83
83
  }
84
84
  return {
85
85
  typ: EnumToken.ColorTokenType,
@@ -1,6 +1,6 @@
1
1
  import { ColorType, EnumToken } from '../../../ast/types.js';
2
2
  import '../../../ast/minify.js';
3
- import '../../../ast/walk.js';
3
+ import { walkValues } from '../../../ast/walk.js';
4
4
  import '../../../parser/parse.js';
5
5
  import '../../../parser/tokenize.js';
6
6
  import '../../../parser/utils/config.js';
@@ -13,7 +13,7 @@ function getComponents(token) {
13
13
  const value = expandHexValue(token.kin == ColorType.LIT ? COLORS_NAMES[token.val.toLowerCase()] : token.val);
14
14
  // @ts-ignore
15
15
  return value.slice(1).match(/([a-fA-F0-9]{2})/g).map((t, index) => {
16
- return { typ: EnumToken.Number, val: (index < 3 ? parseInt(t, 16) : parseInt(t, 16) / 255).toString() };
16
+ return { typ: EnumToken.Number, val: index < 3 ? parseInt(t, 16) : parseInt(t, 16) / 255 };
17
17
  });
18
18
  }
19
19
  const result = [];
@@ -23,7 +23,19 @@ function getComponents(token) {
23
23
  ].includes(child.typ)) {
24
24
  continue;
25
25
  }
26
- if (child.typ == EnumToken.ColorTokenType && child.val.localeCompare('currentcolor', undefined, { sensitivity: 'base' }) == 0) {
26
+ if (child.typ == EnumToken.FunctionTokenType) {
27
+ if ('var' == child.val.toLowerCase()) {
28
+ return null;
29
+ }
30
+ else {
31
+ for (const { value } of walkValues(child.chi)) {
32
+ if (value.typ == EnumToken.FunctionTokenType && 'var' === value.val.toLowerCase()) {
33
+ return null;
34
+ }
35
+ }
36
+ }
37
+ }
38
+ if (child.typ == EnumToken.ColorTokenType && 'currentcolor' === child.val.toLowerCase()) {
27
39
  return null;
28
40
  }
29
41
  result.push(child);
@@ -9,13 +9,27 @@ import '../../../parser/utils/config.js';
9
9
  import './constants.js';
10
10
  import '../../../renderer/sourcemap/lib/encode.js';
11
11
 
12
+ /**
13
+ * Calculate the distance between two okLab colors.
14
+ * @param okLab1
15
+ * @param okLab2
16
+ *
17
+ * @private
18
+ */
12
19
  function okLabDistance(okLab1, okLab2) {
13
20
  return Math.sqrt(Math.pow(okLab1[0] - okLab2[0], 2) + Math.pow(okLab1[1] - okLab2[1], 2) + Math.pow(okLab1[2] - okLab2[2], 2));
14
21
  }
22
+ /**
23
+ * Check if two colors are close in okLab space.
24
+ * @param color1
25
+ * @param color2
26
+ * @param threshold
27
+ *
28
+ * @private
29
+ */
15
30
  function isOkLabClose(color1, color2, threshold = .01) {
16
31
  color1 = convertColor(color1, ColorType.OKLAB);
17
32
  color2 = convertColor(color2, ColorType.OKLAB);
18
- // console.error(JSON.stringify({color1, color2}, null, 1));
19
33
  if (color1 == null || color2 == null) {
20
34
  return false;
21
35
  }