@tbela99/css-parser 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/{LICENSE → LICENSE.md} +1 -1
  2. package/README.md +250 -77
  3. package/dist/config.json.js +245 -1
  4. package/dist/index-umd-web.js +4241 -1583
  5. package/dist/index.cjs +4242 -1584
  6. package/dist/index.d.ts +71 -23
  7. package/dist/lib/ast/expand.js +1 -1
  8. package/dist/lib/ast/features/calc.js +31 -192
  9. package/dist/lib/ast/features/index.js +3 -3
  10. package/dist/lib/ast/features/inlinecssvariables.js +6 -6
  11. package/dist/lib/ast/features/shorthand.js +5 -6
  12. package/dist/lib/ast/math/expression.js +220 -0
  13. package/dist/lib/ast/{features/utils → math}/math.js +4 -4
  14. package/dist/lib/ast/minify.js +0 -1
  15. package/dist/lib/ast/types.js +31 -13
  16. package/dist/lib/ast/utils/minifyfeature.js +4 -3
  17. package/dist/lib/ast/walk.js +24 -4
  18. package/dist/lib/fs/resolve.js +4 -3
  19. package/dist/lib/parser/declaration/list.js +6 -2
  20. package/dist/lib/parser/declaration/map.js +158 -24
  21. package/dist/lib/parser/declaration/set.js +42 -22
  22. package/dist/lib/parser/parse.js +345 -349
  23. package/dist/lib/parser/tokenize.js +220 -223
  24. package/dist/lib/parser/utils/declaration.js +67 -0
  25. package/dist/lib/parser/utils/syntax.js +172 -6
  26. package/dist/lib/parser/utils/type.js +2 -2
  27. package/dist/lib/renderer/color/a98rgb.js +64 -0
  28. package/dist/lib/renderer/color/color.js +521 -0
  29. package/dist/lib/renderer/color/colormix.js +337 -0
  30. package/dist/lib/renderer/color/hex.js +92 -0
  31. package/dist/lib/renderer/color/hsl.js +118 -0
  32. package/dist/lib/renderer/color/hsv.js +20 -0
  33. package/dist/lib/renderer/color/hwb.js +101 -0
  34. package/dist/lib/renderer/color/lab.js +136 -0
  35. package/dist/lib/renderer/color/lch.js +79 -0
  36. package/dist/lib/renderer/color/oklab.js +121 -0
  37. package/dist/lib/renderer/color/oklch.js +65 -0
  38. package/dist/lib/renderer/color/p3.js +57 -0
  39. package/dist/lib/renderer/color/prophotorgb.js +56 -0
  40. package/dist/lib/renderer/color/rec2020.js +70 -0
  41. package/dist/lib/renderer/color/relativecolor.js +152 -0
  42. package/dist/lib/renderer/color/rgb.js +44 -0
  43. package/dist/lib/renderer/color/srgb.js +261 -0
  44. package/dist/lib/renderer/color/utils/components.js +20 -0
  45. package/dist/lib/renderer/color/utils/constants.js +191 -0
  46. package/dist/lib/renderer/color/utils/matrix.js +35 -0
  47. package/dist/lib/renderer/color/xyz.js +64 -0
  48. package/dist/lib/renderer/color/xyzd50.js +33 -0
  49. package/dist/lib/renderer/render.js +128 -30
  50. package/dist/node/index.js +1 -1
  51. package/dist/node/load.js +1 -1
  52. package/dist/web/index.js +1 -1
  53. package/package.json +19 -18
  54. package/quickjs.sh +1 -0
  55. package/dist/lib/iterable/weakmap.js +0 -53
  56. package/dist/lib/renderer/utils/color.js +0 -499
  57. /package/dist/lib/iterable/{set.js → weakset.js} +0 -0
@@ -0,0 +1,67 @@
1
+ import { EnumToken } from '../../ast/types.js';
2
+ import '../../ast/minify.js';
3
+ import { walkValues } from '../../ast/walk.js';
4
+ import '../parse.js';
5
+ import { isWhiteSpace } from './syntax.js';
6
+ import '../../renderer/color/utils/constants.js';
7
+ import '../../renderer/sourcemap/lib/encode.js';
8
+
9
+ function parseDeclaration(node, errors, src, position) {
10
+ while (node.val[0]?.typ == EnumToken.WhitespaceTokenType) {
11
+ node.val.shift();
12
+ }
13
+ if (node.val.filter((t) => ![EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType].includes(t.typ)).length == 0) {
14
+ errors.push({
15
+ action: 'drop',
16
+ message: 'doParse: invalid declaration',
17
+ location: { src, ...position }
18
+ });
19
+ return null;
20
+ }
21
+ for (const { value: val, parent } of walkValues(node.val, node)) {
22
+ if (val.typ == EnumToken.AttrTokenType && val.chi.every((t) => [EnumToken.IdenTokenType, EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType].includes(t.typ))) {
23
+ // @ts-ignore
24
+ val.typ = EnumToken.IdenListTokenType;
25
+ }
26
+ else if (val.typ == EnumToken.StringTokenType && (node.nam == 'grid' || node.nam == 'grid-template-areas' || node.nam == 'grid-template-rows' || node.nam == 'grid-template-columns')) {
27
+ val.val = val.val.at(0) + parseGridTemplate(val.val.slice(1, -1)) + val.val.at(-1);
28
+ // @ts-ignore
29
+ const array = parent?.chi ?? node.val;
30
+ const index = array.indexOf(val);
31
+ if (index > 0 && array[index - 1].typ == EnumToken.WhitespaceTokenType) {
32
+ array.splice(index - 1, 1);
33
+ }
34
+ }
35
+ }
36
+ return node;
37
+ }
38
+ function parseGridTemplate(template) {
39
+ let result = '';
40
+ let buffer = '';
41
+ for (let i = 0; i < template.length; i++) {
42
+ const char = template[i];
43
+ if (isWhiteSpace(char.codePointAt(0))) {
44
+ while (i + 1 < template.length && isWhiteSpace(template[i + 1].codePointAt(0))) {
45
+ i++;
46
+ }
47
+ result += buffer + ' ';
48
+ buffer = '';
49
+ }
50
+ else if (char == '.') {
51
+ while (i + 1 < template.length && template[i + 1] == '.') {
52
+ i++;
53
+ }
54
+ if (isWhiteSpace((result.at(-1)?.codePointAt(0)))) {
55
+ result = result.slice(0, -1);
56
+ }
57
+ result += buffer + char;
58
+ buffer = '';
59
+ }
60
+ else {
61
+ buffer += char;
62
+ }
63
+ }
64
+ return buffer.length > 0 ? result + buffer : result;
65
+ }
66
+
67
+ export { parseDeclaration };
@@ -1,8 +1,8 @@
1
1
  import { colorsFunc } from '../../renderer/render.js';
2
- import { COLORS_NAMES } from '../../renderer/utils/color.js';
3
2
  import { EnumToken } from '../../ast/types.js';
4
3
  import '../../ast/minify.js';
5
4
  import '../parse.js';
5
+ import { COLORS_NAMES } from '../../renderer/color/utils/constants.js';
6
6
 
7
7
  // https://www.w3.org/TR/CSS21/syndata.html#syntax
8
8
  // https://www.w3.org/TR/2021/CRD-css-syntax-3-20211224/#typedef-ident-token
@@ -29,6 +29,30 @@ function isTime(dimension) {
29
29
  function isFrequency(dimension) {
30
30
  return 'unit' in dimension && ['hz', 'khz'].includes(dimension.unit.toLowerCase());
31
31
  }
32
+ function isColorspace(token) {
33
+ if (token.typ != EnumToken.IdenTokenType) {
34
+ return false;
35
+ }
36
+ return ['srgb', 'srgb-linear', 'lab', 'oklab', 'lch', 'oklch', 'xyz', 'xyz-d50', 'xyz-d65', 'display-p3', 'a98-rgb', 'prophoto-rgb', 'rec2020', 'rgb', 'hsl', 'hwb'].includes(token.val.toLowerCase());
37
+ }
38
+ function isRectangularOrthogonalColorspace(token) {
39
+ if (token.typ != EnumToken.IdenTokenType) {
40
+ return false;
41
+ }
42
+ return ['srgb', 'srgb-linear', 'display-p3', 'a98-rgb', 'prophoto-rgb', 'rec2020', 'lab', 'oklab', 'xyz', 'xyz-d50', 'xyz-d65'].includes(token.val.toLowerCase());
43
+ }
44
+ function isPolarColorspace(token) {
45
+ if (token.typ != EnumToken.IdenTokenType) {
46
+ return false;
47
+ }
48
+ return ['hsl', 'hwb', 'lch', 'oklch'].includes(token.val);
49
+ }
50
+ function isHueInterpolationMethod(token) {
51
+ if (token.typ != EnumToken.IdenTokenType) {
52
+ return false;
53
+ }
54
+ return ['shorter', 'longer', 'increasing', 'decreasing'].includes(token.val);
55
+ }
32
56
  function isColor(token) {
33
57
  if (token.typ == EnumToken.ColorTokenType) {
34
58
  return true;
@@ -37,12 +61,122 @@ function isColor(token) {
37
61
  // named color
38
62
  return token.val.toLowerCase() in COLORS_NAMES;
39
63
  }
64
+ let isLegacySyntax = false;
40
65
  if (token.typ == EnumToken.FunctionTokenType && token.chi.length > 0 && colorsFunc.includes(token.val)) {
41
- // @ts-ignore
42
- for (const v of token.chi) {
43
- if (![EnumToken.NumberTokenType, EnumToken.AngleTokenType, EnumToken.PercentageTokenType, EnumToken.CommaTokenType, EnumToken.WhitespaceTokenType, EnumToken.LiteralTokenType].includes(v.typ)) {
66
+ if (token.val == 'color') {
67
+ const children = token.chi.filter((t) => [EnumToken.IdenTokenType, EnumToken.NumberTokenType, EnumToken.LiteralTokenType, EnumToken.ColorTokenType, EnumToken.FunctionTokenType, EnumToken.PercentageTokenType].includes(t.typ));
68
+ const isRelative = children[0].typ == EnumToken.IdenTokenType && children[0].val == 'from';
69
+ if (children.length < 4 || children.length > 8) {
44
70
  return false;
45
71
  }
72
+ if (!isRelative && !isColorspace(children[0])) {
73
+ return false;
74
+ }
75
+ for (let i = 1; i < children.length - 2; i++) {
76
+ if (children[i].typ == EnumToken.IdenTokenType) {
77
+ if (children[i].val != 'none' &&
78
+ !(isRelative && ['alpha', 'r', 'g', 'b'].includes(children[i].val) || isColorspace(children[i]))) {
79
+ return false;
80
+ }
81
+ }
82
+ if (children[i].typ == EnumToken.FunctionTokenType && !['calc'].includes(children[i].val)) {
83
+ return false;
84
+ }
85
+ }
86
+ if (children.length == 8 || children.length == 6) {
87
+ const sep = children.at(-2);
88
+ const alpha = children.at(-1);
89
+ if (sep.typ != EnumToken.LiteralTokenType || sep.val != '/') {
90
+ return false;
91
+ }
92
+ if (alpha.typ == EnumToken.IdenTokenType && alpha.val != 'none') {
93
+ return false;
94
+ }
95
+ else {
96
+ // @ts-ignore
97
+ if (alpha.typ == EnumToken.PercentageTokenType) {
98
+ if (+alpha.val < 0 || +alpha.val > 100) {
99
+ return false;
100
+ }
101
+ }
102
+ else if (alpha.typ == EnumToken.NumberTokenType) {
103
+ if (+alpha.val < 0 || +alpha.val > 1) {
104
+ return false;
105
+ }
106
+ }
107
+ }
108
+ }
109
+ return true;
110
+ }
111
+ else if (token.val == 'color-mix') {
112
+ const children = token.chi.reduce((acc, t) => {
113
+ if (t.typ == EnumToken.CommaTokenType) {
114
+ acc.push([]);
115
+ }
116
+ else {
117
+ if (![EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType].includes(t.typ)) {
118
+ acc[acc.length - 1].push(t);
119
+ }
120
+ }
121
+ return acc;
122
+ }, [[]]);
123
+ if (children.length == 3) {
124
+ if (children[0].length > 3 ||
125
+ children[0][0].typ != EnumToken.IdenTokenType ||
126
+ children[0][0].val != 'in' ||
127
+ !isColorspace(children[0][1]) ||
128
+ (children[0].length == 3 && !isHueInterpolationMethod(children[0][2])) ||
129
+ children[1].length > 2 ||
130
+ children[1][0].typ != EnumToken.ColorTokenType ||
131
+ children[2].length > 2 ||
132
+ children[2][0].typ != EnumToken.ColorTokenType) {
133
+ return false;
134
+ }
135
+ if (children[1].length == 2) {
136
+ if (!(children[1][1].typ == EnumToken.PercentageTokenType || (children[1][1].typ == EnumToken.NumberTokenType && children[1][1].val == '0'))) {
137
+ return false;
138
+ }
139
+ }
140
+ if (children[2].length == 2) {
141
+ if (!(children[2][1].typ == EnumToken.PercentageTokenType || (children[2][1].typ == EnumToken.NumberTokenType && children[2][1].val == '0'))) {
142
+ return false;
143
+ }
144
+ }
145
+ return true;
146
+ }
147
+ return false;
148
+ }
149
+ else {
150
+ const keywords = ['from', 'none'];
151
+ if (['rgb', 'hsl', 'hwb', 'lab', 'lch', 'oklab', 'oklch'].includes(token.val)) {
152
+ keywords.push('alpha', ...token.val.slice(-3).split(''));
153
+ }
154
+ // @ts-ignore
155
+ for (const v of token.chi) {
156
+ if (v.typ == EnumToken.CommaTokenType) {
157
+ isLegacySyntax = true;
158
+ }
159
+ if (v.typ == EnumToken.IdenTokenType) {
160
+ if (!(keywords.includes(v.val) || v.val.toLowerCase() in COLORS_NAMES)) {
161
+ return false;
162
+ }
163
+ if (keywords.includes(v.val)) {
164
+ if (isLegacySyntax) {
165
+ return false;
166
+ }
167
+ if (v.val == 'from' && ['rgba', 'hsla'].includes(token.val)) {
168
+ return false;
169
+ }
170
+ }
171
+ continue;
172
+ }
173
+ if (v.typ == EnumToken.FunctionTokenType && (v.val == 'calc' || v.val == 'var' || colorsFunc.includes(v.val))) {
174
+ continue;
175
+ }
176
+ if (![EnumToken.ColorTokenType, EnumToken.IdenTokenType, EnumToken.NumberTokenType, EnumToken.AngleTokenType, EnumToken.PercentageTokenType, EnumToken.CommaTokenType, EnumToken.WhitespaceTokenType, EnumToken.LiteralTokenType].includes(v.typ)) {
177
+ return false;
178
+ }
179
+ }
46
180
  }
47
181
  return true;
48
182
  }
@@ -200,6 +334,9 @@ function isDimension(name) {
200
334
  function isPercentage(name) {
201
335
  return name.endsWith('%') && isNumber(name.slice(0, -1));
202
336
  }
337
+ function isFlex(name) {
338
+ return name.endsWith('fr') && isNumber(name.slice(0, -2));
339
+ }
203
340
  function parseDimension(name) {
204
341
  let index = name.length;
205
342
  while (index--) {
@@ -209,7 +346,11 @@ function parseDimension(name) {
209
346
  index++;
210
347
  break;
211
348
  }
212
- const dimension = { typ: EnumToken.DimensionTokenType, val: name.slice(0, index), unit: name.slice(index) };
349
+ const dimension = {
350
+ typ: EnumToken.DimensionTokenType,
351
+ val: name.slice(0, index),
352
+ unit: name.slice(index)
353
+ };
213
354
  if (isAngle(dimension)) {
214
355
  // @ts-ignore
215
356
  dimension.typ = EnumToken.AngleTokenType;
@@ -251,6 +392,31 @@ function isHexColor(name) {
251
392
  }
252
393
  return true;
253
394
  }
395
+ /*
396
+ export function isHexDigit(name: string): boolean {
397
+
398
+ if (name.length || name.length > 6) {
399
+
400
+ return false;
401
+ }
402
+
403
+ for (let chr of name) {
404
+
405
+ let codepoint = <number>chr.charCodeAt(0);
406
+
407
+ if (!isDigit(codepoint) &&
408
+ // A F
409
+ !(codepoint >= 0x41 && codepoint <= 0x46) &&
410
+ // a f
411
+ !(codepoint >= 0x61 && codepoint <= 0x66)) {
412
+
413
+ return false;
414
+ }
415
+ }
416
+
417
+ return true;
418
+ }
419
+ */
254
420
  function isFunction(name) {
255
421
  return name.endsWith('(') && isIdent(name.slice(0, -1));
256
422
  }
@@ -267,4 +433,4 @@ function isWhiteSpace(codepoint) {
267
433
  codepoint == 0xa || codepoint == 0xc || codepoint == 0xd;
268
434
  }
269
435
 
270
- export { isAngle, isAtKeyword, isColor, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNonPrintable, isNumber, isPercentage, isPseudo, isResolution, isTime, isWhiteSpace, parseDimension };
436
+ export { isAngle, isAtKeyword, isColor, isColorspace, isDigit, isDimension, isFlex, isFrequency, isFunction, isHash, isHexColor, isHueInterpolationMethod, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNonPrintable, isNumber, isPercentage, isPolarColorspace, isPseudo, isRectangularOrthogonalColorspace, isResolution, isTime, isWhiteSpace, parseDimension };
@@ -1,7 +1,7 @@
1
1
  import { EnumToken } from '../../ast/types.js';
2
2
  import '../../ast/minify.js';
3
3
  import '../parse.js';
4
- import '../../renderer/utils/color.js';
4
+ import '../../renderer/color/utils/constants.js';
5
5
  import '../../renderer/sourcemap/lib/encode.js';
6
6
 
7
7
  // https://www.w3.org/TR/css-values-4/#math-function
@@ -22,7 +22,7 @@ function matchType(val, properties) {
22
22
  }
23
23
  if (val.typ == EnumToken.FunctionTokenType) {
24
24
  if (funcList.includes(val.val)) {
25
- return val.chi.every((t => [EnumToken.LiteralTokenType, EnumToken.CommaTokenType, EnumToken.WhitespaceTokenType, EnumToken.StartParensTokenType, EnumToken.EndParensTokenType].includes(t.typ) || matchType(t, properties)));
25
+ return val.chi.every(((t) => [EnumToken.LiteralTokenType, EnumToken.CommaTokenType, EnumToken.WhitespaceTokenType, EnumToken.StartParensTokenType, EnumToken.EndParensTokenType].includes(t.typ) || matchType(t, properties)));
26
26
  }
27
27
  // match type defined like function 'symbols()', 'url()', 'attr()' etc.
28
28
  // return properties.types.includes((<FunctionToken>val).val + '()')
@@ -0,0 +1,64 @@
1
+ import { xyz2srgb } from './srgb.js';
2
+ import { multiplyMatrices } from './utils/matrix.js';
3
+ import './utils/constants.js';
4
+ import '../../ast/types.js';
5
+ import '../../ast/minify.js';
6
+ import '../../parser/parse.js';
7
+ import { srgb2xyz } from './xyz.js';
8
+ import '../sourcemap/lib/encode.js';
9
+
10
+ function a98rgb2srgbvalues(r, g, b, a = null) {
11
+ // @ts-ignore
12
+ return xyz2srgb(...la98rgb2xyz(...a98rgb2la98(r, g, b, a)));
13
+ }
14
+ function srgb2a98values(r, g, b, a = null) {
15
+ // @ts-ignore
16
+ return la98rgb2a98rgb(xyz2la98rgb(...srgb2xyz(r, g, b, a)));
17
+ }
18
+ // a98-rgb functions
19
+ function a98rgb2la98(r, g, b, a = null) {
20
+ // convert an array of a98-rgb values in the range 0.0 - 1.0
21
+ // to linear light (un-companded) form.
22
+ // negative values are also now accepted
23
+ return [r, g, b].map(function (val) {
24
+ let sign = val < 0 ? -1 : 1;
25
+ let abs = Math.abs(val);
26
+ return sign * Math.pow(abs, 563 / 256);
27
+ }).concat(a == null || a == 1 ? [] : [a]);
28
+ }
29
+ function la98rgb2a98rgb(r, g, b, a = null) {
30
+ // convert an array of linear-light a98-rgb in the range 0.0-1.0
31
+ // to gamma corrected form
32
+ // negative values are also now accepted
33
+ return [r, b, g].map(function (val) {
34
+ let sign = val < 0 ? -1 : 1;
35
+ let abs = Math.abs(val);
36
+ return sign * Math.pow(abs, 256 / 563);
37
+ }).concat(a == null || a == 1 ? [] : [a]);
38
+ }
39
+ function la98rgb2xyz(r, g, b, a = null) {
40
+ // convert an array of linear-light a98-rgb values to CIE XYZ
41
+ // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
42
+ // has greater numerical precision than section 4.3.5.3 of
43
+ // https://www.adobe.com/digitalimag/pdfs/AdobeRGB1998.pdf
44
+ // but the values below were calculated from first principles
45
+ // from the chromaticity coordinates of R G B W
46
+ // see matrixmaker.html
47
+ var M = [
48
+ [573536 / 994567, 263643 / 1420810, 187206 / 994567],
49
+ [591459 / 1989134, 6239551 / 9945670, 374412 / 4972835],
50
+ [53769 / 1989134, 351524 / 4972835, 4929758 / 4972835],
51
+ ];
52
+ return multiplyMatrices(M, [r, g, b]).concat(a == null || a == 1 ? [] : [a]);
53
+ }
54
+ function xyz2la98rgb(x, y, z, a = null) {
55
+ // convert XYZ to linear-light a98-rgb
56
+ var M = [
57
+ [1829569 / 896150, -506331 / 896150, -308931 / 896150],
58
+ [-851781 / 878810, 1648619 / 878810, 36519 / 878810],
59
+ [16779 / 1248040, -147721 / 1248040, 1266979 / 1248040],
60
+ ];
61
+ return multiplyMatrices(M, [x, y, z]).concat(a == null || a == 1 ? [] : [a]);
62
+ }
63
+
64
+ export { a98rgb2srgbvalues, srgb2a98values };