@tbela99/css-parser 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +267 -2
  2. package/dist/config.json.js +611 -4
  3. package/dist/index-umd-web.js +2898 -1223
  4. package/dist/index.cjs +2898 -1223
  5. package/dist/lib/ast/expand.js +11 -11
  6. package/dist/lib/ast/features/calc.js +33 -224
  7. package/dist/lib/ast/features/index.js +3 -3
  8. package/dist/lib/ast/features/inlinecssvariables.js +46 -31
  9. package/dist/lib/ast/features/shorthand.js +7 -7
  10. package/dist/lib/ast/features/utils/math.js +95 -0
  11. package/dist/lib/ast/math/expression.js +185 -0
  12. package/dist/lib/ast/math/math.js +95 -0
  13. package/dist/lib/ast/minify.js +34 -29
  14. package/dist/lib/ast/types.js +108 -78
  15. package/dist/lib/ast/walk.js +42 -9
  16. package/dist/lib/fs/resolve.js +4 -3
  17. package/dist/lib/iterable/set.js +48 -0
  18. package/dist/lib/iterable/weakmap.js +53 -0
  19. package/dist/lib/iterable/weakset.js +48 -0
  20. package/dist/lib/parser/declaration/list.js +7 -3
  21. package/dist/lib/parser/declaration/map.js +86 -7
  22. package/dist/lib/parser/declaration/set.js +43 -23
  23. package/dist/lib/parser/parse.js +561 -387
  24. package/dist/lib/parser/tokenize.js +42 -13
  25. package/dist/lib/parser/utils/declaration.js +67 -0
  26. package/dist/lib/parser/utils/syntax.js +32 -2
  27. package/dist/lib/parser/utils/type.js +7 -2
  28. package/dist/lib/renderer/render.js +163 -47
  29. package/dist/lib/renderer/utils/calccolor.js +238 -0
  30. package/dist/lib/renderer/utils/color.js +36 -164
  31. package/dist/lib/renderer/utils/hex.js +124 -0
  32. package/dist/lib/renderer/utils/hsl.js +49 -0
  33. package/dist/lib/renderer/utils/hsv.js +15 -0
  34. package/dist/lib/renderer/utils/hwb.js +50 -0
  35. package/dist/lib/renderer/utils/rgb.js +66 -0
  36. package/dist/node/index.js +8 -12
  37. package/dist/web/index.js +8 -12
  38. package/package.json +9 -7
  39. package/dist/index.d.ts +0 -1056
  40. /package/dist/lib/ast/{utiles → utils}/minifyfeature.js +0 -0
@@ -0,0 +1,238 @@
1
+ import { COLORS_NAMES, getNumber, getAngle } from './color.js';
2
+ import { EnumToken } from '../../ast/types.js';
3
+ import '../../ast/minify.js';
4
+ import { walkValues } from '../../ast/walk.js';
5
+ import '../../parser/parse.js';
6
+ import { reduceNumber } from '../render.js';
7
+ import { hwb2rgb, hsl2rgb } from './rgb.js';
8
+ import { rgb2hwb, hsl2hwb } from './hwb.js';
9
+ import { rgb2hsl, hwb2hsl } from './hsl.js';
10
+ import { evaluate } from '../../ast/math/expression.js';
11
+
12
+ function parseRelativeColor(relativeKeys, original, rExp, gExp, bExp, aExp) {
13
+ const type = relativeKeys.join('');
14
+ let r;
15
+ let g;
16
+ let b;
17
+ let alpha = null;
18
+ let keys = {};
19
+ let values = {};
20
+ let children;
21
+ switch (original.kin) {
22
+ case 'lit':
23
+ case 'hex':
24
+ let value = original.val.toLowerCase();
25
+ if (original.kin == 'lit') {
26
+ if (original.val.toLowerCase() in COLORS_NAMES) {
27
+ value = COLORS_NAMES[original.val.toLowerCase()];
28
+ }
29
+ else {
30
+ return null;
31
+ }
32
+ }
33
+ if (value.length == 4) {
34
+ value = '#' + value[1] + value[1] + value[2] + value[2] + value[3] + value[3];
35
+ }
36
+ else if (value.length == 5) {
37
+ value = '#' + value[1] + value[1] + value[2] + value[2] + value[3] + value[3] + value[4] + value[4];
38
+ }
39
+ r = parseInt(value.slice(1, 3), 16);
40
+ g = parseInt(value.slice(3, 5), 16);
41
+ b = parseInt(value.slice(5, 7), 16);
42
+ alpha = value.length == 9 ? parseInt(value.slice(7, 9), 16) : null;
43
+ break;
44
+ case 'rgb':
45
+ case 'rgba':
46
+ children = original.chi.filter((t) => t.typ == EnumToken.NumberTokenType || t.typ == EnumToken.IdenTokenType || t.typ == EnumToken.PercentageTokenType);
47
+ if (children.every((t) => (t.typ == EnumToken.IdenTokenType && t.val == 'none') || t.typ == EnumToken.NumberTokenType)) {
48
+ r = children[0].typ == EnumToken.IdenTokenType && children[0].val == 'none' ? 0 : +children[0].val;
49
+ g = children[1].typ == EnumToken.IdenTokenType && children[1].val == 'none' ? 0 : +children[1].val;
50
+ b = children[2].typ == EnumToken.IdenTokenType && children[2].val == 'none' ? 0 : +children[2].val;
51
+ alpha = children.length < 4 ? null : children[3].typ == EnumToken.IdenTokenType && children[3].val == 'none' ? 0 : +children[3].val;
52
+ }
53
+ else if (children.every((t) => t.typ == EnumToken.PercentageTokenType || (t.typ == EnumToken.IdenTokenType && t.val == 'none') || (t.typ == EnumToken.NumberTokenType && t.val == '0'))) {
54
+ // @ts-ignore
55
+ r = children[0].typ == EnumToken.IdenTokenType && children[0].val == 'none' ? 0 : children[0].val * 255 / 100;
56
+ // @ts-ignore
57
+ g = children[1].typ == EnumToken.IdenTokenType && children[1].val == 'none' ? 0 : children[1].val * 255 / 100;
58
+ // @ts-ignore
59
+ b = children[2].typ == EnumToken.IdenTokenType && children[2].val == 'none' ? 0 : children[2].val * 255 / 100;
60
+ alpha = children.length < 4 ? null : children[3].typ == EnumToken.IdenTokenType && children[3].val == 'none' ? 0 : +children[3].val / 100;
61
+ }
62
+ else {
63
+ return null;
64
+ }
65
+ break;
66
+ case 'hsl':
67
+ case 'hsla':
68
+ case 'hwb':
69
+ children = original.chi.filter((t) => t.typ == EnumToken.AngleTokenType || t.typ == EnumToken.NumberTokenType || t.typ == EnumToken.IdenTokenType || t.typ == EnumToken.PercentageTokenType);
70
+ if (children.length == 3 || children.length == 4) {
71
+ [r, g, b, alpha] = children;
72
+ }
73
+ else {
74
+ return null;
75
+ }
76
+ break;
77
+ default:
78
+ return null;
79
+ }
80
+ const from = ['rgb', 'rgba', 'hex', 'lit'].includes(original.kin) ? 'rgb' : original.kin;
81
+ if (from != type) {
82
+ if (type == 'hsl' || type == 'hwb') {
83
+ if (from == 'rgb') {
84
+ [r, g, b] = (type == 'hwb' ? rgb2hwb : rgb2hsl)(r, g, b);
85
+ // @ts-ignore
86
+ r *= 360;
87
+ // @ts-ignore
88
+ g *= 100;
89
+ // @ts-ignore
90
+ b *= 100;
91
+ values = {
92
+ [relativeKeys[0]]: { typ: EnumToken.AngleTokenType, val: r, unit: 'deg' },
93
+ [relativeKeys[1]]: { typ: EnumToken.PercentageTokenType, val: g },
94
+ [relativeKeys[2]]: { typ: EnumToken.PercentageTokenType, val: b }
95
+ };
96
+ }
97
+ else if (from == 'hwb' || from == 'hsl') {
98
+ if (type == 'hsl') {
99
+ if (from == 'hwb') {
100
+ [r, g, b] = hwb2hsl(getAngle(r), getNumber(g), getNumber(b));
101
+ // @ts-ignore
102
+ r *= 360;
103
+ // @ts-ignore
104
+ g *= 100;
105
+ // @ts-ignore
106
+ b *= 100;
107
+ // @ts-ignore
108
+ values = {
109
+ [relativeKeys[0]]: { typ: EnumToken.AngleTokenType, val: r, unit: 'deg' },
110
+ [relativeKeys[1]]: { typ: EnumToken.PercentageTokenType, val: g },
111
+ [relativeKeys[2]]: { typ: EnumToken.PercentageTokenType, val: b }
112
+ };
113
+ }
114
+ }
115
+ else if (type == 'hwb') {
116
+ if (from == 'hsl') {
117
+ [r, g, b] = hsl2hwb(getAngle(r), getNumber(g), getNumber(b));
118
+ // @ts-ignore
119
+ r *= 360;
120
+ // @ts-ignore
121
+ g *= 100;
122
+ // @ts-ignore
123
+ b *= 100;
124
+ // @ts-ignore
125
+ values = {
126
+ [relativeKeys[0]]: { typ: EnumToken.AngleTokenType, val: r, unit: 'deg' },
127
+ [relativeKeys[1]]: { typ: EnumToken.PercentageTokenType, val: g },
128
+ [relativeKeys[2]]: { typ: EnumToken.PercentageTokenType, val: b }
129
+ };
130
+ }
131
+ }
132
+ }
133
+ else {
134
+ return null;
135
+ }
136
+ }
137
+ else if (type == 'rgb') {
138
+ if (from == 'hsl' || from == 'hwb') {
139
+ [r, g, b] = (from == 'hwb' ? hwb2rgb : hsl2rgb)(getAngle(r), getNumber(g), getNumber(b));
140
+ // @ts-ignore
141
+ values = {
142
+ [relativeKeys[0]]: { typ: EnumToken.NumberTokenType, val: r },
143
+ [relativeKeys[1]]: { typ: EnumToken.NumberTokenType, val: g },
144
+ [relativeKeys[2]]: { typ: EnumToken.NumberTokenType, val: b }
145
+ };
146
+ }
147
+ else {
148
+ return null;
149
+ }
150
+ }
151
+ }
152
+ else {
153
+ values = {
154
+ [relativeKeys[0]]: r,
155
+ [relativeKeys[1]]: g,
156
+ [relativeKeys[2]]: b
157
+ };
158
+ }
159
+ if (aExp != null && aExp.typ == EnumToken.IdenTokenType && aExp.val == 'none') {
160
+ aExp = null;
161
+ }
162
+ keys = {
163
+ [relativeKeys[0]]: rExp,
164
+ [relativeKeys[1]]: gExp,
165
+ [relativeKeys[2]]: bExp,
166
+ alpha: aExp ?? { typ: EnumToken.IdenTokenType, val: 'alpha' }
167
+ };
168
+ // @ts-ignore
169
+ values.alpha = alpha != null && typeof alpha == 'object' ? alpha : b.typ == EnumToken.PercentageTokenType ? { typ: EnumToken.PercentageTokenType, val: String(alpha ?? 100) } : { typ: EnumToken.NumberTokenType, val: String(alpha ?? 1) };
170
+ return computeComponentValue(keys, values);
171
+ }
172
+ function computeComponentValue(expr, values) {
173
+ for (const [key, exp] of Object.entries(expr)) {
174
+ if (exp == null) {
175
+ if (key in values) {
176
+ if (typeof values[key] == 'number') {
177
+ expr[key] = {
178
+ typ: EnumToken.NumberTokenType,
179
+ val: reduceNumber(values[key])
180
+ };
181
+ }
182
+ else {
183
+ expr[key] = values[key];
184
+ }
185
+ }
186
+ }
187
+ else if ([EnumToken.NumberTokenType, EnumToken.PercentageTokenType, EnumToken.AngleTokenType, EnumToken.LengthTokenType].includes(exp.typ)) ;
188
+ else if (exp.typ == EnumToken.IdenTokenType && exp.val in values) {
189
+ if (typeof values[exp.val] == 'number') {
190
+ expr[key] = {
191
+ typ: EnumToken.NumberTokenType,
192
+ val: reduceNumber(values[exp.val])
193
+ };
194
+ }
195
+ else {
196
+ expr[key] = values[exp.val];
197
+ }
198
+ }
199
+ else if (exp.typ == EnumToken.FunctionTokenType && exp.val == 'calc') {
200
+ for (let { value, parent } of walkValues(exp.chi)) {
201
+ if (value.typ == EnumToken.IdenTokenType) {
202
+ if (!(value.val in values)) {
203
+ return null;
204
+ }
205
+ if (parent == null) {
206
+ parent = exp;
207
+ }
208
+ if (parent.typ == EnumToken.BinaryExpressionTokenType) {
209
+ if (parent.l == value) {
210
+ parent.l = values[value.val];
211
+ }
212
+ else {
213
+ parent.r = values[value.val];
214
+ }
215
+ }
216
+ else {
217
+ for (let i = 0; i < parent.chi.length; i++) {
218
+ if (parent.chi[i] == value) {
219
+ parent.chi.splice(i, 1, values[value.val]);
220
+ break;
221
+ }
222
+ }
223
+ }
224
+ }
225
+ }
226
+ const result = evaluate(exp.chi);
227
+ if (result.length == 1 && result[0].typ != EnumToken.BinaryExpressionTokenType) {
228
+ expr[key] = result[0];
229
+ }
230
+ else {
231
+ return null;
232
+ }
233
+ }
234
+ }
235
+ return expr;
236
+ }
237
+
238
+ export { parseRelativeColor };
@@ -307,122 +307,47 @@ const NAMES_COLORS = Object.seal({
307
307
  '#663399': 'rebeccapurple',
308
308
  '#00000000': 'transparent'
309
309
  });
310
- function rgb2Hex(token) {
311
- let value = '#';
312
- let t;
313
- // @ts-ignore
314
- for (let i = 0; i < 6; i += 2) {
315
- // @ts-ignore
316
- t = token.chi[i];
317
- // @ts-ignore
318
- value += Math.round(t.typ == EnumToken.PercentageTokenType ? 255 * t.val / 100 : t.val).toString(16).padStart(2, '0');
310
+ /**
311
+ * clamp color values
312
+ * @param token
313
+ */
314
+ function clamp(token) {
315
+ if (token.kin == 'rgb' || token.kin == 'rgba') {
316
+ token.chi.filter((token) => ![EnumToken.LiteralTokenType, EnumToken.CommaTokenType, EnumToken.WhitespaceTokenType].includes(token.typ)).
317
+ forEach((token, index) => {
318
+ if (index <= 2) {
319
+ if (token.typ == EnumToken.NumberTokenType) {
320
+ token.val = String(Math.min(255, Math.max(0, +token.val)));
321
+ }
322
+ else if (token.typ == EnumToken.PercentageTokenType) {
323
+ token.val = String(Math.min(100, Math.max(0, +token.val)));
324
+ }
325
+ }
326
+ else {
327
+ if (token.typ == EnumToken.NumberTokenType) {
328
+ token.val = String(Math.min(1, Math.max(0, +token.val)));
329
+ }
330
+ else if (token.typ == EnumToken.PercentageTokenType) {
331
+ token.val = String(Math.min(100, Math.max(0, +token.val)));
332
+ }
333
+ }
334
+ });
319
335
  }
320
- // @ts-ignore
321
- if (token.chi.length == 7) {
322
- // @ts-ignore
323
- t = token.chi[6];
324
- // @ts-ignore
325
- if ((t.typ == EnumToken.NumberTokenType && t.val < 1) ||
326
- // @ts-ignore
327
- (t.typ == EnumToken.PercentageTokenType && t.val < 100)) {
328
- // @ts-ignore
329
- value += Math.round(255 * (t.typ == EnumToken.PercentageTokenType ? t.val / 100 : t.val)).toString(16).padStart(2, '0');
330
- }
331
- }
332
- return value;
336
+ return token;
333
337
  }
334
- function hsl2Hex(token) {
335
- let t;
336
- // @ts-ignore
337
- let h = getAngle(token.chi[0]);
338
- // @ts-ignore
339
- t = token.chi[2];
340
- // @ts-ignore
341
- let s = t.typ == EnumToken.PercentageTokenType ? t.val / 100 : t.val;
342
- // @ts-ignore
343
- t = token.chi[4];
344
- // @ts-ignore
345
- let l = t.typ == EnumToken.PercentageTokenType ? t.val / 100 : t.val;
346
- let a = null;
347
- if (token.chi?.length == 7) {
348
- // @ts-ignore
349
- t = token.chi[6];
350
- // @ts-ignore
351
- if ((t.typ == EnumToken.PercentageTokenType && t.val < 100) ||
352
- // @ts-ignore
353
- (t.typ == EnumToken.NumberTokenType && t.val < 1)) {
354
- // @ts-ignore
355
- a = (t.typ == EnumToken.PercentageTokenType ? t.val / 100 : t.val);
356
- }
338
+ function getNumber(token) {
339
+ if (token.typ == EnumToken.IdenTokenType && token.val == 'none') {
340
+ return 0;
357
341
  }
358
- return `#${hsl2rgb(h, s, l, a).reduce((acc, curr) => acc + curr.toString(16).padStart(2, '0'), '')}`;
359
- }
360
- function hwb2hex(token) {
361
- let t;
362
- // @ts-ignore
363
- let h = getAngle(token.chi[0]);
364
- // @ts-ignore
365
- t = token.chi[2];
366
- // @ts-ignore
367
- let white = t.typ == EnumToken.PercentageTokenType ? t.val / 100 : t.val;
368
342
  // @ts-ignore
369
- t = token.chi[4];
370
- // @ts-ignore
371
- let black = t.typ == EnumToken.PercentageTokenType ? t.val / 100 : t.val;
372
- let a = null;
373
- if (token.chi?.length == 7) {
374
- // @ts-ignore
375
- t = token.chi[6];
376
- // @ts-ignore
377
- if ((t.typ == EnumToken.PercentageTokenType && t.val < 100) ||
378
- // @ts-ignore
379
- (t.typ == EnumToken.NumberTokenType && t.val < 1)) {
380
- // @ts-ignore
381
- a = (t.typ == EnumToken.PercentageTokenType ? t.val / 100 : t.val);
382
- }
383
- }
384
- const rgb = hsl2rgb(h, 1, .5, a);
385
- let value;
386
- for (let i = 0; i < 3; i++) {
387
- value = rgb[i] / 255;
388
- value *= (1 - white - black);
389
- value += white;
390
- rgb[i] = Math.round(value * 255);
391
- }
392
- return `#${rgb.reduce((acc, curr) => acc + curr.toString(16).padStart(2, '0'), '')}`;
393
- }
394
- function cmyk2hex(token) {
395
- // @ts-ignore
396
- let t = token.chi[0];
397
- // @ts-ignore
398
- const c = t.typ == EnumToken.PercentageTokenType ? t.val / 100 : t.val;
399
- // @ts-ignore
400
- t = token.chi[2];
401
- // @ts-ignore
402
- const m = t.typ == EnumToken.PercentageTokenType ? t.val / 100 : t.val;
403
- // @ts-ignore
404
- t = token.chi[4];
405
- // @ts-ignore
406
- const y = t.typ == EnumToken.PercentageTokenType ? t.val / 100 : t.val;
407
- // @ts-ignore
408
- t = token.chi[6];
409
- // @ts-ignore
410
- const k = t.typ == EnumToken.PercentageTokenType ? t.val / 100 : t.val;
411
- const rgb = [
412
- Math.round(255 * (1 - Math.min(1, c * (1 - k) + k))),
413
- Math.round(255 * (1 - Math.min(1, m * (1 - k) + k))),
414
- Math.round(255 * (1 - Math.min(1, y * (1 - k) + k)))
415
- ];
416
- // @ts-ignore
417
- if (token.chi.length >= 9) {
418
- // @ts-ignore
419
- t = token.chi[8];
420
- // @ts-ignore
421
- rgb.push(Math.round(255 * (t.typ == EnumToken.PercentageTokenType ? t.val / 100 : t.val)));
422
- }
423
- return `#${rgb.reduce((acc, curr) => acc + curr.toString(16).padStart(2, '0'), '')}`;
343
+ return token.typ == EnumToken.PercentageTokenType ? token.val / 100 : +token.val;
424
344
  }
425
345
  function getAngle(token) {
346
+ if (token.typ == EnumToken.IdenTokenType) {
347
+ if (token.val == 'none') {
348
+ return 0;
349
+ }
350
+ }
426
351
  if (token.typ == EnumToken.AngleTokenType) {
427
352
  switch (token.unit) {
428
353
  case 'deg':
@@ -442,58 +367,5 @@ function getAngle(token) {
442
367
  // @ts-ignore
443
368
  return token.val / 360;
444
369
  }
445
- function hsl2rgb(h, s, l, a = null) {
446
- let v = l <= .5 ? l * (1.0 + s) : l + s - l * s;
447
- let r = l;
448
- let g = l;
449
- let b = l;
450
- if (v > 0) {
451
- let m = l + l - v;
452
- let sv = (v - m) / v;
453
- h *= 6.0;
454
- let sextant = Math.floor(h);
455
- let fract = h - sextant;
456
- let vsf = v * sv * fract;
457
- let mid1 = m + vsf;
458
- let mid2 = v - vsf;
459
- switch (sextant) {
460
- case 0:
461
- r = v;
462
- g = mid1;
463
- b = m;
464
- break;
465
- case 1:
466
- r = mid2;
467
- g = v;
468
- b = m;
469
- break;
470
- case 2:
471
- r = m;
472
- g = v;
473
- b = mid1;
474
- break;
475
- case 3:
476
- r = m;
477
- g = mid2;
478
- b = v;
479
- break;
480
- case 4:
481
- r = mid1;
482
- g = m;
483
- b = v;
484
- break;
485
- case 5:
486
- r = v;
487
- g = m;
488
- b = mid2;
489
- break;
490
- }
491
- }
492
- const values = [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
493
- if (a != null && a != 1) {
494
- values.push(Math.round(a * 255));
495
- }
496
- return values;
497
- }
498
370
 
499
- export { COLORS_NAMES, NAMES_COLORS, cmyk2hex, getAngle, hsl2Hex, hwb2hex, rgb2Hex };
371
+ export { COLORS_NAMES, NAMES_COLORS, clamp, getAngle, getNumber };
@@ -0,0 +1,124 @@
1
+ import { EnumToken } from '../../ast/types.js';
2
+ import '../../ast/minify.js';
3
+ import '../../parser/parse.js';
4
+ import { getNumber, getAngle } from './color.js';
5
+ import { hsl2rgb } from './rgb.js';
6
+ import '../sourcemap/lib/encode.js';
7
+
8
+ function rgb2Hex(token) {
9
+ let value = '#';
10
+ let t;
11
+ // @ts-ignore
12
+ for (let i = 0; i < 3; i++) {
13
+ // @ts-ignore
14
+ t = token.chi[i];
15
+ // @ts-ignore
16
+ value += (t.val == 'none' ? '0' : Math.round(t.typ == EnumToken.PercentageTokenType ? 255 * t.val / 100 : t.val)).toString(16).padStart(2, '0');
17
+ }
18
+ // @ts-ignore
19
+ if (token.chi.length == 4) {
20
+ // @ts-ignore
21
+ t = token.chi[3];
22
+ // @ts-ignore
23
+ if ((t.typ == EnumToken.IdenTokenType && t.val == 'none') ||
24
+ (t.typ == EnumToken.NumberTokenType && +t.val < 1) ||
25
+ (t.typ == EnumToken.PercentageTokenType && +t.val < 100)) {
26
+ // @ts-ignore
27
+ value += Math.round(255 * getNumber(t)).toString(16).padStart(2, '0');
28
+ }
29
+ }
30
+ return value;
31
+ }
32
+ function hsl2Hex(token) {
33
+ let t;
34
+ // @ts-ignore
35
+ let h = getAngle(token.chi[0]);
36
+ // @ts-ignore
37
+ t = token.chi[1];
38
+ // @ts-ignore
39
+ let s = getNumber(t);
40
+ // @ts-ignore
41
+ t = token.chi[2];
42
+ // @ts-ignore
43
+ let l = getNumber(t);
44
+ let a = null;
45
+ if (token.chi?.length == 4) {
46
+ // @ts-ignore
47
+ t = token.chi[3];
48
+ // @ts-ignore
49
+ if ((t.typ == EnumToken.IdenTokenType && t.val == 'none') || (t.typ == EnumToken.PercentageTokenType && +t.val < 100) ||
50
+ // @ts-ignore
51
+ (t.typ == EnumToken.NumberTokenType && t.val < 1)) {
52
+ // @ts-ignore
53
+ a = getNumber(t);
54
+ }
55
+ }
56
+ return `#${hsl2rgb(h, s, l, a).reduce((acc, curr) => acc + curr.toString(16).padStart(2, '0'), '')}`;
57
+ }
58
+ function hwb2hex(token) {
59
+ let t;
60
+ // @ts-ignore
61
+ let h = getAngle(token.chi[0]);
62
+ // @ts-ignore
63
+ t = token.chi[1];
64
+ // @ts-ignore
65
+ let white = getNumber(t);
66
+ // @ts-ignore
67
+ t = token.chi[2];
68
+ // @ts-ignore
69
+ let black = getNumber(t);
70
+ let a = null;
71
+ if (token.chi?.length == 4) {
72
+ // @ts-ignore
73
+ t = token.chi[3];
74
+ // @ts-ignore
75
+ if ((t.typ == EnumToken.IdenTokenType && t.val == 'none') ||
76
+ (t.typ == EnumToken.PercentageTokenType && +t.val < 100) ||
77
+ (t.typ == EnumToken.NumberTokenType && +t.val < 1)) {
78
+ // @ts-ignore
79
+ a = getNumber(t);
80
+ }
81
+ }
82
+ const rgb = hsl2rgb(h, 1, .5, a);
83
+ let value;
84
+ for (let i = 0; i < 3; i++) {
85
+ value = rgb[i] / 255;
86
+ value *= (1 - white - black);
87
+ value += white;
88
+ rgb[i] = Math.round(value * 255);
89
+ }
90
+ return `#${rgb.reduce((acc, curr) => acc + curr.toString(16).padStart(2, '0'), '')}`;
91
+ }
92
+ function cmyk2hex(token) {
93
+ // @ts-ignore
94
+ let t = token.chi[0];
95
+ // @ts-ignore
96
+ const c = getNumber(t);
97
+ // @ts-ignore
98
+ t = token.chi[1];
99
+ // @ts-ignore
100
+ const m = getNumber(t);
101
+ // @ts-ignore
102
+ t = token.chi[2];
103
+ // @ts-ignore
104
+ const y = getNumber(t);
105
+ // @ts-ignore
106
+ t = token.chi[3];
107
+ // @ts-ignore
108
+ const k = getNumber(t);
109
+ const rgb = [
110
+ Math.round(255 * (1 - Math.min(1, c * (1 - k) + k))),
111
+ Math.round(255 * (1 - Math.min(1, m * (1 - k) + k))),
112
+ Math.round(255 * (1 - Math.min(1, y * (1 - k) + k)))
113
+ ];
114
+ // @ts-ignore
115
+ if (token.chi.length >= 9) {
116
+ // @ts-ignore
117
+ t = token.chi[8];
118
+ // @ts-ignore
119
+ rgb.push(Math.round(255 * getNumber(t)));
120
+ }
121
+ return `#${rgb.reduce((acc, curr) => acc + curr.toString(16).padStart(2, '0'), '')}`;
122
+ }
123
+
124
+ export { cmyk2hex, hsl2Hex, hwb2hex, rgb2Hex };
@@ -0,0 +1,49 @@
1
+ import { hwb2hsv } from './hsv.js';
2
+
3
+ function rgb2hsl(r, g, b, a) {
4
+ r /= 255;
5
+ g /= 255;
6
+ b /= 255;
7
+ let max = Math.max(r, g, b);
8
+ let min = Math.min(r, g, b);
9
+ let h = 0;
10
+ let s = 0;
11
+ let l = (max + min) / 2;
12
+ if (max != min) {
13
+ let d = max - min;
14
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
15
+ switch (max) {
16
+ case r:
17
+ h = (g - b) / d + (g < b ? 6 : 0);
18
+ break;
19
+ case g:
20
+ h = (b - r) / d + 2;
21
+ break;
22
+ case b:
23
+ h = (r - g) / d + 4;
24
+ break;
25
+ }
26
+ h /= 6;
27
+ }
28
+ return [h, s, l, a == 1 ? null : a ?? null];
29
+ }
30
+ // https://gist.github.com/defims/0ca2ef8832833186ed396a2f8a204117#file-annotated-js
31
+ function hsv2hsl(h, s, v) {
32
+ return [
33
+ //[hue, saturation, lightness]
34
+ //Range should be between 0 - 1
35
+ h,
36
+ //Saturation is very different between the two color spaces
37
+ //If (2-sat)*val < 1 set it to sat*val/((2-sat)*val)
38
+ //Otherwise sat*val/(2-(2-sat)*val)
39
+ //Conditional is not operating with hue, it is reassigned!
40
+ s * v / ((h = (2 - s) * v) < 1 ? h : 2 - h),
41
+ h / 2 //Lightness is (2-sat)*val/2
42
+ //See reassignment of hue above
43
+ ];
44
+ }
45
+ function hwb2hsl(h, w, b) {
46
+ return hsv2hsl(...hwb2hsv(h, w, b));
47
+ }
48
+
49
+ export { hsv2hsl, hwb2hsl, rgb2hsl };
@@ -0,0 +1,15 @@
1
+ function hwb2hsv(h, w, b) {
2
+ return [h, 1 - w / (1 - b), 1 - b];
3
+ }
4
+ // https://gist.github.com/defims/0ca2ef8832833186ed396a2f8a204117#file-annotated-js
5
+ function hsl2hsv(h, s, l) {
6
+ s *= l < .5 ? l : 1 - l;
7
+ return [
8
+ //Range should be between 0 - 1
9
+ h,
10
+ 2 * s / (l + s),
11
+ l + s //Value
12
+ ];
13
+ }
14
+
15
+ export { hsl2hsv, hwb2hsv };
@@ -0,0 +1,50 @@
1
+ import { hsl2hsv } from './hsv.js';
2
+
3
+ function rgb2hue(r, g, b, fallback = 0) {
4
+ let value = rgb2value(r, g, b);
5
+ let whiteness = rgb2whiteness(r, g, b);
6
+ let delta = value - whiteness;
7
+ if (delta > 0) {
8
+ // calculate segment
9
+ let segment = value === r ? (g - b) / delta : (value === g
10
+ ? (b - r) / delta
11
+ : (r - g) / delta);
12
+ // calculate shift
13
+ let shift = value === r ? segment < 0
14
+ ? 360 / 60
15
+ : 0 / 60 : (value === g
16
+ ? 120 / 60
17
+ : 240 / 60);
18
+ // calculate hue
19
+ return (segment + shift) * 60;
20
+ }
21
+ return fallback;
22
+ }
23
+ function rgb2value(r, g, b) {
24
+ return Math.max(r, g, b);
25
+ }
26
+ function rgb2whiteness(r, g, b) {
27
+ return Math.min(r, g, b);
28
+ }
29
+ function rgb2hwb(r, g, b, a = null, fallback = 0) {
30
+ r *= 100 / 255;
31
+ g *= 100 / 255;
32
+ b *= 100 / 255;
33
+ let hue = rgb2hue(r, g, b, fallback);
34
+ let whiteness = rgb2whiteness(r, g, b);
35
+ let value = Math.round(rgb2value(r, g, b));
36
+ let blackness = 100 - value;
37
+ const result = [hue / 360, whiteness / 100, blackness / 100];
38
+ if (a != null) {
39
+ result.push(a);
40
+ }
41
+ return result;
42
+ }
43
+ function hsv2hwb(h, s, v) {
44
+ return [h, (1 - s) * v, 1 - v];
45
+ }
46
+ function hsl2hwb(h, s, l) {
47
+ return hsv2hwb(...hsl2hsv(h, s, l));
48
+ }
49
+
50
+ export { hsl2hwb, hsv2hwb, rgb2hwb };