@tbela99/css-parser 0.9.1 → 1.1.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 (99) hide show
  1. package/CHANGELOG.md +265 -0
  2. package/LICENSE.md +1 -1
  3. package/README.md +29 -17
  4. package/dist/index-umd-web.js +7461 -4360
  5. package/dist/index.cjs +8608 -5507
  6. package/dist/index.d.ts +203 -61
  7. package/dist/lib/ast/expand.js +2 -1
  8. package/dist/lib/ast/features/calc.js +19 -11
  9. package/dist/lib/ast/features/index.js +1 -0
  10. package/dist/lib/ast/features/inlinecssvariables.js +47 -29
  11. package/dist/lib/ast/features/prefix.js +117 -91
  12. package/dist/lib/ast/features/shorthand.js +34 -14
  13. package/dist/lib/ast/features/transform.js +67 -0
  14. package/dist/lib/ast/features/type.js +7 -0
  15. package/dist/lib/ast/math/expression.js +20 -10
  16. package/dist/lib/ast/math/math.js +20 -2
  17. package/dist/lib/ast/minify.js +209 -80
  18. package/dist/lib/ast/transform/compute.js +337 -0
  19. package/dist/lib/ast/transform/convert.js +33 -0
  20. package/dist/lib/ast/transform/matrix.js +112 -0
  21. package/dist/lib/ast/transform/minify.js +296 -0
  22. package/dist/lib/ast/transform/perspective.js +10 -0
  23. package/dist/lib/ast/transform/rotate.js +40 -0
  24. package/dist/lib/ast/transform/scale.js +32 -0
  25. package/dist/lib/ast/transform/skew.js +23 -0
  26. package/dist/lib/ast/transform/translate.js +32 -0
  27. package/dist/lib/ast/transform/utils.js +198 -0
  28. package/dist/lib/ast/types.js +18 -15
  29. package/dist/lib/ast/walk.js +54 -22
  30. package/dist/lib/fs/resolve.js +10 -0
  31. package/dist/lib/parser/declaration/list.js +48 -45
  32. package/dist/lib/parser/declaration/map.js +1 -0
  33. package/dist/lib/parser/declaration/set.js +2 -1
  34. package/dist/lib/parser/parse.js +449 -340
  35. package/dist/lib/parser/tokenize.js +147 -72
  36. package/dist/lib/parser/utils/declaration.js +5 -4
  37. package/dist/lib/parser/utils/type.js +2 -1
  38. package/dist/lib/renderer/color/a98rgb.js +2 -1
  39. package/dist/lib/renderer/color/{colormix.js → color-mix.js} +16 -7
  40. package/dist/lib/renderer/color/color.js +264 -170
  41. package/dist/lib/renderer/color/hex.js +19 -8
  42. package/dist/lib/renderer/color/hsl.js +9 -3
  43. package/dist/lib/renderer/color/hwb.js +2 -1
  44. package/dist/lib/renderer/color/lab.js +10 -1
  45. package/dist/lib/renderer/color/lch.js +10 -1
  46. package/dist/lib/renderer/color/oklab.js +10 -1
  47. package/dist/lib/renderer/color/oklch.js +10 -1
  48. package/dist/lib/renderer/color/p3.js +2 -1
  49. package/dist/lib/renderer/color/rec2020.js +2 -1
  50. package/dist/lib/renderer/color/relativecolor.js +27 -32
  51. package/dist/lib/renderer/color/rgb.js +14 -10
  52. package/dist/lib/renderer/color/srgb.js +48 -23
  53. package/dist/lib/renderer/color/utils/components.js +18 -6
  54. package/dist/lib/renderer/color/utils/constants.js +47 -3
  55. package/dist/lib/renderer/color/xyz.js +2 -1
  56. package/dist/lib/renderer/color/xyzd50.js +2 -1
  57. package/dist/lib/renderer/render.js +108 -43
  58. package/dist/lib/syntax/syntax.js +267 -136
  59. package/dist/lib/validation/at-rules/container.js +81 -103
  60. package/dist/lib/validation/at-rules/counter-style.js +9 -8
  61. package/dist/lib/validation/at-rules/custom-media.js +13 -15
  62. package/dist/lib/validation/at-rules/document.js +22 -27
  63. package/dist/lib/validation/at-rules/font-feature-values.js +8 -8
  64. package/dist/lib/validation/at-rules/import.js +30 -81
  65. package/dist/lib/validation/at-rules/keyframes.js +19 -23
  66. package/dist/lib/validation/at-rules/layer.js +5 -5
  67. package/dist/lib/validation/at-rules/media.js +42 -53
  68. package/dist/lib/validation/at-rules/namespace.js +19 -23
  69. package/dist/lib/validation/at-rules/page-margin-box.js +15 -18
  70. package/dist/lib/validation/at-rules/page.js +8 -7
  71. package/dist/lib/validation/at-rules/supports.js +73 -82
  72. package/dist/lib/validation/at-rules/when.js +32 -36
  73. package/dist/lib/validation/atrule.js +15 -18
  74. package/dist/lib/validation/config.js +24 -1
  75. package/dist/lib/validation/config.json.js +563 -63
  76. package/dist/lib/validation/parser/parse.js +196 -185
  77. package/dist/lib/validation/parser/types.js +1 -1
  78. package/dist/lib/validation/selector.js +8 -5
  79. package/dist/lib/validation/syntax.js +724 -1405
  80. package/dist/lib/validation/syntaxes/complex-selector-list.js +10 -11
  81. package/dist/lib/validation/syntaxes/complex-selector.js +10 -11
  82. package/dist/lib/validation/syntaxes/compound-selector.js +40 -50
  83. package/dist/lib/validation/syntaxes/family-name.js +9 -8
  84. package/dist/lib/validation/syntaxes/keyframe-block-list.js +6 -5
  85. package/dist/lib/validation/syntaxes/keyframe-selector.js +23 -105
  86. package/dist/lib/validation/syntaxes/layer-name.js +6 -5
  87. package/dist/lib/validation/syntaxes/relative-selector-list.js +7 -6
  88. package/dist/lib/validation/syntaxes/relative-selector.js +17 -15
  89. package/dist/lib/validation/syntaxes/url.js +18 -22
  90. package/dist/lib/validation/utils/list.js +20 -2
  91. package/dist/lib/validation/utils/whitespace.js +2 -1
  92. package/dist/node/index.js +4 -2
  93. package/dist/node/load.js +6 -1
  94. package/dist/web/index.js +4 -2
  95. package/dist/web/load.js +5 -0
  96. package/package.json +16 -15
  97. package/dist/lib/renderer/color/prophotoRgb.js +0 -56
  98. package/dist/lib/validation/declaration.js +0 -94
  99. package/dist/lib/validation/syntaxes/image.js +0 -29
@@ -0,0 +1,337 @@
1
+ import { multiply, identity } from './utils.js';
2
+ import { EnumToken } from '../types.js';
3
+ import { length2Px } from './convert.js';
4
+ import { transformFunctions } from '../../syntax/syntax.js';
5
+ import '../minify.js';
6
+ import '../walk.js';
7
+ import '../../parser/parse.js';
8
+ import '../../parser/tokenize.js';
9
+ import '../../parser/utils/config.js';
10
+ import { getNumber, getAngle } from '../../renderer/color/color.js';
11
+ import '../../renderer/color/utils/constants.js';
12
+ import '../../renderer/sourcemap/lib/encode.js';
13
+ import { stripCommaToken } from '../../validation/utils/list.js';
14
+ import { translateX, translateY, translateZ, translate, translate3d } from './translate.js';
15
+ import { rotate, rotate3D } from './rotate.js';
16
+ import { scale3d, scale, scaleX, scaleY, scaleZ } from './scale.js';
17
+ import { minify } from './minify.js';
18
+ import { skew, skewX, skewY } from './skew.js';
19
+ import { serialize, matrix } from './matrix.js';
20
+ import { perspective } from './perspective.js';
21
+
22
+ function compute(transformLists) {
23
+ transformLists = transformLists.slice();
24
+ stripCommaToken(transformLists);
25
+ if (transformLists.length == 0) {
26
+ return null;
27
+ }
28
+ let matrix = identity();
29
+ let mat;
30
+ const cumulative = [];
31
+ for (const transformList of splitTransformList(transformLists)) {
32
+ mat = computeMatrix(transformList, identity());
33
+ if (mat == null) {
34
+ return null;
35
+ }
36
+ matrix = multiply(matrix, mat);
37
+ cumulative.push(...(minify(mat) ?? transformList));
38
+ }
39
+ const serialized = serialize(matrix);
40
+ if (cumulative.length > 0) {
41
+ for (let i = 0; i < cumulative.length; i++) {
42
+ if (cumulative[i].typ == EnumToken.IdenTokenType && cumulative[i].val == 'none') {
43
+ cumulative.splice(i--, 1);
44
+ }
45
+ }
46
+ if (cumulative.length == 0) {
47
+ cumulative.push({
48
+ typ: EnumToken.IdenTokenType, val: 'none'
49
+ });
50
+ }
51
+ }
52
+ return {
53
+ matrix: serialize(matrix),
54
+ cumulative,
55
+ minified: minify(matrix) ?? [serialized]
56
+ };
57
+ }
58
+ function computeMatrix(transformList, matrixVar) {
59
+ let values = [];
60
+ let val;
61
+ let i = 0;
62
+ for (; i < transformList.length; i++) {
63
+ if (transformList[i].typ == EnumToken.WhitespaceTokenType) {
64
+ continue;
65
+ }
66
+ if (transformList[i].typ != EnumToken.FunctionTokenType || !transformFunctions.includes(transformList[i].val)) {
67
+ return null;
68
+ }
69
+ switch (transformList[i].val) {
70
+ case 'translate':
71
+ case 'translateX':
72
+ case 'translateY':
73
+ case 'translateZ':
74
+ case 'translate3d':
75
+ {
76
+ values.length = 0;
77
+ const children = stripCommaToken(transformList[i].chi.slice());
78
+ if (children == null || children.length == 0) {
79
+ return null;
80
+ }
81
+ const valCount = transformList[i].val == 'translate3d' || transformList[i].val == 'translate' ? 3 : 1;
82
+ if (children.length == 1 && children[0].typ == EnumToken.IdenTokenType && children[0].val == 'none') {
83
+ values.fill(0, 0, valCount);
84
+ }
85
+ else {
86
+ for (let j = 0; j < children.length; j++) {
87
+ if (children[j].typ == EnumToken.WhitespaceTokenType) {
88
+ continue;
89
+ }
90
+ val = length2Px(children[j]);
91
+ if (typeof val != 'number' || Number.isNaN(val)) {
92
+ return null;
93
+ }
94
+ values.push(val);
95
+ }
96
+ }
97
+ if (values.length == 0 || values.length > valCount) {
98
+ return null;
99
+ }
100
+ if (transformList[i].val == 'translateX') {
101
+ matrixVar = translateX(values[0], matrixVar);
102
+ }
103
+ else if (transformList[i].val == 'translateY') {
104
+ matrixVar = translateY(values[0], matrixVar);
105
+ }
106
+ else if (transformList[i].val == 'translateZ') {
107
+ matrixVar = translateZ(values[0], matrixVar);
108
+ }
109
+ else if (transformList[i].val == 'translate') {
110
+ matrixVar = translate(values, matrixVar);
111
+ }
112
+ else {
113
+ // @ts-ignore
114
+ matrixVar = translate3d(values, matrixVar);
115
+ }
116
+ }
117
+ break;
118
+ case 'rotate':
119
+ case 'rotateX':
120
+ case 'rotateY':
121
+ case 'rotateZ':
122
+ case 'rotate3d':
123
+ {
124
+ let x = 0;
125
+ let y = 0;
126
+ let z = 0;
127
+ let angle;
128
+ let values = [];
129
+ let valuesCount = transformList[i].val == 'rotate3d' ? 4 : 1;
130
+ for (const child of stripCommaToken(transformList[i].chi.slice())) {
131
+ if (child.typ == EnumToken.WhitespaceTokenType) {
132
+ continue;
133
+ }
134
+ values.push(child);
135
+ if (transformList[i].val == 'rotateX') {
136
+ x = 1;
137
+ }
138
+ else if (transformList[i].val == 'rotateY') {
139
+ y = 1;
140
+ }
141
+ else if (transformList[i].val == 'rotate' || transformList[i].val == 'rotateZ') {
142
+ z = 1;
143
+ }
144
+ }
145
+ if (values.length != valuesCount) {
146
+ return null;
147
+ }
148
+ if (transformList[i].val == 'rotate3d') {
149
+ x = getNumber(values[0]);
150
+ y = getNumber(values[1]);
151
+ z = getNumber(values[2]);
152
+ }
153
+ angle = getAngle(values.at(-1));
154
+ if ([x, y, z, angle].some(t => typeof t != 'number' || Number.isNaN(+t))) {
155
+ return null;
156
+ }
157
+ if (transformList[i].val == 'rotate' || transformList[i].val == 'rotateZ') {
158
+ matrixVar = rotate(angle * 2 * Math.PI, matrixVar);
159
+ }
160
+ else {
161
+ matrixVar = rotate3D(angle * 2 * Math.PI, x, y, z, matrixVar);
162
+ }
163
+ }
164
+ break;
165
+ case 'scale':
166
+ case 'scaleX':
167
+ case 'scaleY':
168
+ case 'scaleZ':
169
+ case 'scale3d':
170
+ {
171
+ values.length = 0;
172
+ let child;
173
+ const children = stripCommaToken(transformList[i].chi.slice());
174
+ for (let k = 0; k < children.length; k++) {
175
+ child = children[k];
176
+ if (child.typ == EnumToken.CommentTokenType || child.typ == EnumToken.WhitespaceTokenType) {
177
+ continue;
178
+ }
179
+ if (child.typ != EnumToken.NumberTokenType) {
180
+ return null;
181
+ }
182
+ values.push(getNumber(child));
183
+ }
184
+ if (values.length == 0) {
185
+ return null;
186
+ }
187
+ if (transformList[i].val == 'scale3d') {
188
+ if (values.length != 3) {
189
+ return null;
190
+ }
191
+ matrixVar = scale3d(...values, matrixVar);
192
+ break;
193
+ }
194
+ if (transformList[i].val == 'scale') {
195
+ if (values.length != 1 && values.length != 2) {
196
+ return null;
197
+ }
198
+ matrixVar = scale(values[0], values[1] ?? values[0], matrixVar);
199
+ break;
200
+ }
201
+ if (values.length != 1) {
202
+ return null;
203
+ }
204
+ else if (transformList[i].val == 'scaleX') {
205
+ matrixVar = scaleX(values[0], matrixVar);
206
+ }
207
+ else if (transformList[i].val == 'scaleY') {
208
+ matrixVar = scaleY(values[0], matrixVar);
209
+ }
210
+ else if (transformList[i].val == 'scaleZ') {
211
+ matrixVar = scaleZ(values[0], matrixVar);
212
+ }
213
+ }
214
+ break;
215
+ case 'skew':
216
+ case 'skewX':
217
+ case 'skewY':
218
+ {
219
+ values.length = 0;
220
+ let child;
221
+ let value;
222
+ for (let k = 0; k < transformList[i].chi.length; k++) {
223
+ child = transformList[i].chi[k];
224
+ if (child.typ == EnumToken.CommentTokenType || child.typ == EnumToken.WhitespaceTokenType) {
225
+ continue;
226
+ }
227
+ value = getAngle(child);
228
+ if (value == null) {
229
+ return null;
230
+ }
231
+ values.push(value * 2 * Math.PI);
232
+ }
233
+ if (values.length == 0 || (values.length > (transformList[i].val == 'skew' ? 2 : 1))) {
234
+ return null;
235
+ }
236
+ if (transformList[i].val == 'skew') {
237
+ matrixVar = skew(values, matrixVar);
238
+ }
239
+ else {
240
+ matrixVar = transformList[i].val == 'skewX' ? skewX(values[0], matrixVar) : skewY(values[0], matrixVar);
241
+ }
242
+ }
243
+ break;
244
+ case 'perspective':
245
+ {
246
+ const values = [];
247
+ let child;
248
+ let value;
249
+ for (let k = 0; k < transformList[i].chi.length; k++) {
250
+ child = transformList[i].chi[k];
251
+ if (child.typ == EnumToken.CommentTokenType || child.typ == EnumToken.WhitespaceTokenType) {
252
+ continue;
253
+ }
254
+ if (child.typ == EnumToken.IdenTokenType && child.val == 'none') {
255
+ values.push(child);
256
+ continue;
257
+ }
258
+ value = length2Px(child);
259
+ if (value == null) {
260
+ return null;
261
+ }
262
+ values.push(value);
263
+ }
264
+ if (values.length != 1) {
265
+ return null;
266
+ }
267
+ matrixVar = perspective(values[0], matrixVar);
268
+ }
269
+ break;
270
+ case 'matrix3d':
271
+ // return null;
272
+ case 'matrix':
273
+ {
274
+ const values = [];
275
+ let value;
276
+ for (const token of transformList[i].chi) {
277
+ if ([EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType, EnumToken.CommaTokenType].includes(token.typ)) {
278
+ continue;
279
+ }
280
+ value = getNumber(token);
281
+ if (value == null) {
282
+ return null;
283
+ }
284
+ values.push(value);
285
+ }
286
+ if (transformList[i].val == 'matrix') {
287
+ if (values.length != 6) {
288
+ return null;
289
+ }
290
+ }
291
+ else if (values.length != 16) {
292
+ return null;
293
+ }
294
+ matrixVar = multiply(matrixVar, matrix(values));
295
+ }
296
+ break;
297
+ default:
298
+ return null;
299
+ }
300
+ }
301
+ return matrixVar;
302
+ }
303
+ function splitTransformList(transformList) {
304
+ let pattern = null;
305
+ const tokens = [];
306
+ for (let i = 0; i < transformList.length; i++) {
307
+ if (transformList[i].typ == EnumToken.CommentTokenType || transformList[i].typ == EnumToken.WhitespaceTokenType) {
308
+ continue;
309
+ }
310
+ if (pattern == null || (transformList[i].typ == EnumToken.FunctionTokenType && !transformList[i].val.startsWith(pattern))) {
311
+ if (transformList[i].typ == EnumToken.FunctionTokenType) {
312
+ if (transformList[i].val.startsWith('scale')) {
313
+ pattern = 'scale';
314
+ }
315
+ else if (transformList[i].val.startsWith('rotate')) {
316
+ pattern = 'rotate';
317
+ }
318
+ else if (transformList[i].val.startsWith('translate')) {
319
+ pattern = 'translate';
320
+ }
321
+ else {
322
+ pattern = null;
323
+ }
324
+ tokens.push([transformList[i]]);
325
+ continue;
326
+ }
327
+ }
328
+ if (pattern != null && transformList[i].typ == EnumToken.FunctionTokenType && transformList[i].val.startsWith(pattern)) {
329
+ tokens[tokens.length - 1].push(transformList[i]);
330
+ continue;
331
+ }
332
+ tokens.push([transformList[i]]);
333
+ }
334
+ return tokens;
335
+ }
336
+
337
+ export { compute, computeMatrix };
@@ -0,0 +1,33 @@
1
+ import { EnumToken } from '../types.js';
2
+
3
+ // https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Values_and_units#absolute_length_units
4
+ function length2Px(value) {
5
+ if (value.typ == EnumToken.NumberTokenType) {
6
+ return +value.val;
7
+ }
8
+ switch (value.unit) {
9
+ case 'cm':
10
+ // @ts-ignore
11
+ return value.val * 37.8;
12
+ case 'mm':
13
+ // @ts-ignore
14
+ return value.val * 3.78;
15
+ case 'Q':
16
+ // @ts-ignore
17
+ return value.val * 37.8 / 40;
18
+ case 'in':
19
+ // @ts-ignore
20
+ return value.val / 96;
21
+ case 'pc':
22
+ // @ts-ignore
23
+ return value.val / 16;
24
+ case 'pt':
25
+ // @ts-ignore
26
+ return value.val * 4 / 3;
27
+ case 'px':
28
+ return +value.val;
29
+ }
30
+ return null;
31
+ }
32
+
33
+ export { length2Px };
@@ -0,0 +1,112 @@
1
+ import { toZero, is2DMatrix, identity } from './utils.js';
2
+ import { EnumToken } from '../types.js';
3
+ import { reduceNumber } from '../../renderer/render.js';
4
+ import { eq } from '../../parser/utils/eq.js';
5
+ import { getNumber } from '../../renderer/color/color.js';
6
+ import '../../renderer/color/utils/constants.js';
7
+ import '../minify.js';
8
+ import '../walk.js';
9
+ import '../../parser/parse.js';
10
+ import '../../parser/tokenize.js';
11
+ import '../../parser/utils/config.js';
12
+
13
+ function parseMatrix(mat) {
14
+ if (mat.typ == EnumToken.IdenTokenType) {
15
+ return mat.val == 'none' ? identity() : null;
16
+ }
17
+ const children = mat.chi.filter((t) => t.typ == EnumToken.NumberTokenType || t.typ == EnumToken.IdenTokenType);
18
+ const values = [];
19
+ for (const child of children) {
20
+ if (child.typ != EnumToken.NumberTokenType) {
21
+ return null;
22
+ }
23
+ // @ts-ignore
24
+ values.push(getNumber(child));
25
+ }
26
+ // @ts-ignore
27
+ return matrix(values);
28
+ }
29
+ // use column-major order
30
+ function matrix(values) {
31
+ const matrix = identity();
32
+ if (values.length === 6) {
33
+ matrix[0][0] = values[0];
34
+ matrix[0][1] = values[1];
35
+ matrix[1][0] = values[2];
36
+ matrix[1][1] = values[3];
37
+ matrix[3][0] = values[4];
38
+ matrix[3][1] = values[5];
39
+ }
40
+ else if (values.length === 16) {
41
+ matrix[0][0] = values[0];
42
+ matrix[0][1] = values[1];
43
+ matrix[0][2] = values[2];
44
+ matrix[0][3] = values[3];
45
+ matrix[1][0] = values[4];
46
+ matrix[1][1] = values[5];
47
+ matrix[1][2] = values[6];
48
+ matrix[1][3] = values[7];
49
+ matrix[2][0] = values[8];
50
+ matrix[2][1] = values[9];
51
+ matrix[2][2] = values[10];
52
+ matrix[2][3] = values[11];
53
+ matrix[3][0] = values[12];
54
+ matrix[3][1] = values[13];
55
+ matrix[3][2] = values[14];
56
+ matrix[3][3] = values[15];
57
+ }
58
+ else {
59
+ return null;
60
+ }
61
+ return matrix;
62
+ }
63
+ function serialize(matrix) {
64
+ matrix = matrix.map(t => toZero(t.slice()));
65
+ // @ts-ignore
66
+ if (eq(matrix, identity())) {
67
+ return {
68
+ typ: EnumToken.IdenTokenType,
69
+ val: 'none'
70
+ };
71
+ }
72
+ if (is2DMatrix(matrix)) {
73
+ // https://drafts.csswg.org/css-transforms-2/#two-dimensional-subset
74
+ return {
75
+ typ: EnumToken.FunctionTokenType,
76
+ val: 'matrix',
77
+ chi: [
78
+ matrix[0][0],
79
+ matrix[0][1],
80
+ matrix[1][0],
81
+ matrix[1][1],
82
+ matrix[3][0],
83
+ matrix[3][1]
84
+ ].reduce((acc, t) => {
85
+ if (acc.length > 0) {
86
+ acc.push({ typ: EnumToken.CommaTokenType });
87
+ }
88
+ acc.push({
89
+ typ: EnumToken.NumberTokenType,
90
+ val: reduceNumber(t)
91
+ });
92
+ return acc;
93
+ }, [])
94
+ };
95
+ }
96
+ return {
97
+ typ: EnumToken.FunctionTokenType,
98
+ val: 'matrix3d',
99
+ chi: matrix.flat().reduce((acc, curr) => {
100
+ if (acc.length > 0) {
101
+ acc.push({ typ: EnumToken.CommaTokenType });
102
+ }
103
+ acc.push({
104
+ typ: EnumToken.NumberTokenType,
105
+ val: reduceNumber(curr)
106
+ });
107
+ return acc;
108
+ }, [])
109
+ };
110
+ }
111
+
112
+ export { matrix, parseMatrix, serialize };