@tbela99/css-parser 0.9.0 → 1.0.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 (70) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +22 -12
  3. package/dist/index-umd-web.js +2678 -2838
  4. package/dist/index.cjs +2468 -2628
  5. package/dist/index.d.ts +71 -26
  6. package/dist/lib/ast/expand.js +15 -2
  7. package/dist/lib/ast/features/calc.js +7 -10
  8. package/dist/lib/ast/features/index.js +1 -0
  9. package/dist/lib/ast/features/inlinecssvariables.js +0 -5
  10. package/dist/lib/ast/features/prefix.js +2 -7
  11. package/dist/lib/ast/features/shorthand.js +6 -9
  12. package/dist/lib/ast/features/transform.js +60 -0
  13. package/dist/lib/ast/math/expression.js +14 -10
  14. package/dist/lib/ast/math/math.js +14 -2
  15. package/dist/lib/ast/minify.js +47 -6
  16. package/dist/lib/ast/transform/compute.js +336 -0
  17. package/dist/lib/ast/transform/convert.js +33 -0
  18. package/dist/lib/ast/transform/matrix.js +111 -0
  19. package/dist/lib/ast/transform/minify.js +296 -0
  20. package/dist/lib/ast/transform/perspective.js +10 -0
  21. package/dist/lib/ast/transform/rotate.js +40 -0
  22. package/dist/lib/ast/transform/scale.js +32 -0
  23. package/dist/lib/ast/transform/skew.js +23 -0
  24. package/dist/lib/ast/transform/translate.js +32 -0
  25. package/dist/lib/ast/transform/utils.js +198 -0
  26. package/dist/lib/ast/types.js +2 -0
  27. package/dist/lib/ast/walk.js +23 -17
  28. package/dist/lib/parser/parse.js +174 -127
  29. package/dist/lib/parser/utils/declaration.js +1 -1
  30. package/dist/lib/renderer/color/{colormix.js → color-mix.js} +6 -0
  31. package/dist/lib/renderer/color/color.js +96 -20
  32. package/dist/lib/renderer/color/hex.js +17 -7
  33. package/dist/lib/renderer/color/hsl.js +7 -2
  34. package/dist/lib/renderer/color/lab.js +10 -1
  35. package/dist/lib/renderer/color/lch.js +8 -0
  36. package/dist/lib/renderer/color/oklab.js +8 -0
  37. package/dist/lib/renderer/color/oklch.js +8 -0
  38. package/dist/lib/renderer/color/prophotorgb.js +2 -2
  39. package/dist/lib/renderer/color/relativecolor.js +10 -21
  40. package/dist/lib/renderer/color/rgb.js +10 -7
  41. package/dist/lib/renderer/color/srgb.js +30 -6
  42. package/dist/lib/renderer/color/utils/components.js +13 -2
  43. package/dist/lib/renderer/color/xyz.js +2 -18
  44. package/dist/lib/renderer/color/xyzd50.js +20 -2
  45. package/dist/lib/renderer/render.js +70 -32
  46. package/dist/lib/renderer/sourcemap/sourcemap.js +1 -1
  47. package/dist/lib/syntax/syntax.js +75 -56
  48. package/dist/lib/validation/at-rules/container.js +6 -6
  49. package/dist/lib/validation/at-rules/document.js +40 -60
  50. package/dist/lib/validation/at-rules/import.js +61 -59
  51. package/dist/lib/validation/at-rules/keyframes.js +1 -1
  52. package/dist/lib/validation/at-rules/media.js +1 -1
  53. package/dist/lib/validation/at-rules/supports.js +40 -9
  54. package/dist/lib/validation/atrule.js +0 -4
  55. package/dist/lib/validation/config.json.js +83 -35
  56. package/dist/lib/validation/parser/parse.js +1 -95
  57. package/dist/lib/validation/parser/types.js +1 -2
  58. package/dist/lib/validation/selector.js +5 -2
  59. package/dist/lib/validation/syntaxes/compound-selector.js +2 -2
  60. package/dist/lib/validation/syntaxes/keyframe-block-list.js +2 -2
  61. package/dist/lib/validation/syntaxes/keyframe-selector.js +11 -90
  62. package/dist/lib/validation/syntaxes/layer-name.js +5 -16
  63. package/dist/lib/validation/syntaxes/relative-selector.js +15 -14
  64. package/dist/lib/validation/utils/list.js +18 -1
  65. package/dist/node/load.js +1 -1
  66. package/package.json +13 -12
  67. package/dist/lib/renderer/color/prophotoRgb.js +0 -56
  68. package/dist/lib/validation/declaration.js +0 -102
  69. package/dist/lib/validation/syntax.js +0 -1475
  70. package/dist/lib/validation/syntaxes/image.js +0 -29
@@ -0,0 +1,296 @@
1
+ import { multiply, identity, epsilon, decompose, round, toZero } from './utils.js';
2
+ import { EnumToken } from '../types.js';
3
+ import { computeMatrix } from './compute.js';
4
+ import { parseMatrix } from './matrix.js';
5
+
6
+ // translate → rotate → skew → scale
7
+ function minify(matrix) {
8
+ const decomposed = decompose(matrix);
9
+ if (decomposed == null) {
10
+ return null;
11
+ }
12
+ const transforms = new Set(['translate', 'scale', 'skew', 'perspective', 'rotate']);
13
+ const scales = new Set(['x', 'y', 'z']);
14
+ const skew = new Set(['x', 'y']);
15
+ let result = [];
16
+ // check identity
17
+ if (round(decomposed.translate[0]) == 0 && round(decomposed.translate[1]) == 0 && round(decomposed.translate[2]) == 0) {
18
+ transforms.delete('translate');
19
+ }
20
+ if (round(decomposed.scale[0]) == 1 && round(decomposed.scale[1]) == 1 && round(decomposed.scale[2]) == 1) {
21
+ transforms.delete('scale');
22
+ }
23
+ if (round(decomposed.skew[0]) == 0 && round(decomposed.skew[1]) == 0) {
24
+ transforms.delete('skew');
25
+ }
26
+ if (round(decomposed.perspective[2]) == 0) {
27
+ transforms.delete('perspective');
28
+ }
29
+ if (round(decomposed.rotate[3]) == 0) {
30
+ transforms.delete('rotate');
31
+ }
32
+ if (transforms.has('translate')) {
33
+ let coordinates = new Set(['x', 'y', 'z']);
34
+ for (let i = 0; i < 3; i++) {
35
+ if (round(decomposed.translate[i]) == 0) {
36
+ coordinates.delete(i == 0 ? 'x' : i == 1 ? 'y' : 'z');
37
+ }
38
+ }
39
+ if (coordinates.size == 3) {
40
+ result.push({
41
+ typ: EnumToken.FunctionTokenType,
42
+ val: 'translate3d',
43
+ chi: [
44
+ { typ: EnumToken.LengthTokenType, val: round(decomposed.translate[0]) + '', unit: 'px' },
45
+ { typ: EnumToken.CommaTokenType },
46
+ { typ: EnumToken.LengthTokenType, val: round(decomposed.translate[1]) + '', unit: 'px' },
47
+ { typ: EnumToken.CommaTokenType },
48
+ { typ: EnumToken.LengthTokenType, val: round(decomposed.translate[2]) + '', unit: 'px' }
49
+ ]
50
+ });
51
+ }
52
+ else if (coordinates.size == 1) {
53
+ if (coordinates.has('x')) {
54
+ result.push({
55
+ typ: EnumToken.FunctionTokenType,
56
+ val: 'translate',
57
+ chi: [{ typ: EnumToken.LengthTokenType, val: round(decomposed.translate[0]) + '', unit: 'px' }]
58
+ });
59
+ }
60
+ else {
61
+ let axis = coordinates.has('y') ? 'y' : 'z';
62
+ let index = axis == 'y' ? 1 : 2;
63
+ result.push({
64
+ typ: EnumToken.FunctionTokenType,
65
+ val: 'translate' + axis.toUpperCase(),
66
+ chi: [{ typ: EnumToken.LengthTokenType, val: round(decomposed.translate[index]) + '', unit: 'px' }]
67
+ });
68
+ }
69
+ }
70
+ else if (coordinates.has('z')) {
71
+ result.push({
72
+ typ: EnumToken.FunctionTokenType,
73
+ val: 'translate3d',
74
+ chi: [
75
+ decomposed.translate[0] == 0 ? {
76
+ typ: EnumToken.NumberTokenType,
77
+ 'val': '0'
78
+ } : { typ: EnumToken.LengthTokenType, val: round(decomposed.translate[0]) + '', unit: 'px' },
79
+ { typ: EnumToken.CommaTokenType },
80
+ decomposed.translate[1] == 0 ? {
81
+ typ: EnumToken.NumberTokenType,
82
+ 'val': '0'
83
+ } : { typ: EnumToken.LengthTokenType, val: round(decomposed.translate[1]) + '', unit: 'px' },
84
+ { typ: EnumToken.CommaTokenType },
85
+ { typ: EnumToken.LengthTokenType, val: round(decomposed.translate[2]) + '', unit: 'px' }
86
+ ]
87
+ });
88
+ }
89
+ else {
90
+ result.push({
91
+ typ: EnumToken.FunctionTokenType,
92
+ val: 'translate',
93
+ chi: [
94
+ decomposed.translate[0] == 0 ? {
95
+ typ: EnumToken.NumberTokenType,
96
+ 'val': '0'
97
+ } : { typ: EnumToken.LengthTokenType, val: round(decomposed.translate[0]) + '', unit: 'px' },
98
+ { typ: EnumToken.CommaTokenType },
99
+ decomposed.translate[1] == 0 ? {
100
+ typ: EnumToken.NumberTokenType,
101
+ 'val': '0'
102
+ } : { typ: EnumToken.LengthTokenType, val: round(decomposed.translate[1]) + '', unit: 'px' }
103
+ ]
104
+ });
105
+ }
106
+ }
107
+ if (transforms.has('rotate')) {
108
+ const [x, y, z, angle] = decomposed.rotate;
109
+ if (y == 0 && z == 0) {
110
+ result.push({
111
+ typ: EnumToken.FunctionTokenType,
112
+ val: 'rotateX',
113
+ chi: [
114
+ {
115
+ typ: EnumToken.AngleTokenType,
116
+ val: '' + round(angle),
117
+ unit: 'deg'
118
+ }
119
+ ]
120
+ });
121
+ }
122
+ else if (x == 0 && z == 0) {
123
+ result.push({
124
+ typ: EnumToken.FunctionTokenType,
125
+ val: 'rotateY',
126
+ chi: [
127
+ {
128
+ typ: EnumToken.AngleTokenType,
129
+ val: '' + round(angle),
130
+ unit: 'deg'
131
+ }
132
+ ]
133
+ });
134
+ }
135
+ else if (x == 0 && y == 0) {
136
+ result.push({
137
+ typ: EnumToken.FunctionTokenType,
138
+ val: 'rotate',
139
+ chi: [
140
+ {
141
+ typ: EnumToken.AngleTokenType,
142
+ val: '' + round(angle),
143
+ unit: 'deg'
144
+ }
145
+ ]
146
+ });
147
+ }
148
+ else {
149
+ result.push({
150
+ typ: EnumToken.FunctionTokenType,
151
+ val: 'rotate3d',
152
+ chi: [
153
+ {
154
+ typ: EnumToken.NumberTokenType,
155
+ val: '' + round(x)
156
+ },
157
+ { typ: EnumToken.CommaTokenType },
158
+ {
159
+ typ: EnumToken.NumberTokenType,
160
+ val: '' + round(y)
161
+ },
162
+ { typ: EnumToken.CommaTokenType },
163
+ {
164
+ typ: EnumToken.NumberTokenType,
165
+ val: '' + round(z)
166
+ },
167
+ { typ: EnumToken.CommaTokenType },
168
+ {
169
+ typ: EnumToken.AngleTokenType,
170
+ val: '' + round(angle),
171
+ unit: 'deg'
172
+ }
173
+ ]
174
+ });
175
+ }
176
+ }
177
+ if (transforms.has('skew')) {
178
+ if (round(decomposed.skew[0]) == 0) {
179
+ skew.delete('x');
180
+ }
181
+ if (round(decomposed.skew[1]) == 0) {
182
+ skew.delete('y');
183
+ }
184
+ for (let i = 0; i < 2; i++) {
185
+ decomposed.skew[i] = round(Math.atan(decomposed.skew[i]) * 180 / Math.PI);
186
+ }
187
+ if (skew.size == 1) {
188
+ result.push({
189
+ typ: EnumToken.FunctionTokenType,
190
+ val: 'skew' + (skew.has('x') ? '' : 'Y'),
191
+ chi: [
192
+ { typ: EnumToken.AngleTokenType, val: '' + round(decomposed.skew[0]), unit: 'deg' }
193
+ ]
194
+ });
195
+ }
196
+ else {
197
+ result.push({
198
+ typ: EnumToken.FunctionTokenType,
199
+ val: 'skew',
200
+ chi: [
201
+ { typ: EnumToken.AngleTokenType, val: '' + round(decomposed.skew[0]), unit: 'deg' },
202
+ { typ: EnumToken.CommaTokenType },
203
+ { typ: EnumToken.AngleTokenType, val: '' + round(decomposed.skew[1]), unit: 'deg' }
204
+ ]
205
+ });
206
+ }
207
+ }
208
+ if (transforms.has('scale')) {
209
+ const [sx, sy, sz] = toZero(decomposed.scale);
210
+ if (sz == 1) {
211
+ scales.delete('z');
212
+ }
213
+ if (sy == 1) {
214
+ scales.delete('y');
215
+ }
216
+ if (sx == 1) {
217
+ scales.delete('x');
218
+ }
219
+ if (scales.size == 1) {
220
+ let prefix = scales.has('x') ? '' : scales.has('y') ? 'Y' : 'Z';
221
+ result.push({
222
+ typ: EnumToken.FunctionTokenType,
223
+ val: 'scale' + prefix,
224
+ chi: [
225
+ { typ: EnumToken.NumberTokenType, val: '' + round(prefix == 'Z' ? sz : prefix == 'Y' ? sy : sx) }
226
+ ]
227
+ });
228
+ }
229
+ else if (!scales.has('z')) {
230
+ result.push({
231
+ typ: EnumToken.FunctionTokenType,
232
+ val: 'scale',
233
+ chi: [
234
+ { typ: EnumToken.NumberTokenType, val: '' + round(sx) },
235
+ { typ: EnumToken.CommaTokenType },
236
+ { typ: EnumToken.NumberTokenType, val: '' + round(sy) },
237
+ ]
238
+ });
239
+ }
240
+ else {
241
+ result.push({
242
+ typ: EnumToken.FunctionTokenType,
243
+ val: 'scale3d',
244
+ chi: [
245
+ { typ: EnumToken.NumberTokenType, val: '' + round(sx) },
246
+ { typ: EnumToken.CommaTokenType },
247
+ { typ: EnumToken.NumberTokenType, val: '' + round(sy) },
248
+ { typ: EnumToken.CommaTokenType },
249
+ { typ: EnumToken.NumberTokenType, val: '' + round(sz) }
250
+ ]
251
+ });
252
+ }
253
+ }
254
+ if (transforms.has('perspective')) {
255
+ result.push({
256
+ typ: EnumToken.FunctionTokenType,
257
+ val: 'perspective',
258
+ chi: [
259
+ { typ: EnumToken.Length, val: '' + round(1 / decomposed.perspective[2]), unit: 'px' },
260
+ ]
261
+ });
262
+ }
263
+ // identity
264
+ return result.length == 0 || (result.length == 1 && eqMatrix(identity(), result)) ? [
265
+ {
266
+ typ: EnumToken.IdenTokenType,
267
+ val: 'none'
268
+ }
269
+ ] : result;
270
+ }
271
+ function eqMatrix(a, b) {
272
+ let mat = identity();
273
+ let tmp = identity();
274
+ // @ts-ignore
275
+ const data = Array.isArray(a) ? a : parseMatrix(a);
276
+ for (const transform of b) {
277
+ tmp = computeMatrix([transform], identity());
278
+ if (tmp == null) {
279
+ return false;
280
+ }
281
+ mat = multiply(mat, tmp);
282
+ }
283
+ if (mat == null) {
284
+ return false;
285
+ }
286
+ for (let i = 0; i < 4; i++) {
287
+ for (let j = 0; j < 4; j++) {
288
+ if (Math.abs(mat[i][j] - data[i][j]) > epsilon) {
289
+ return false;
290
+ }
291
+ }
292
+ }
293
+ return true;
294
+ }
295
+
296
+ export { eqMatrix, minify };
@@ -0,0 +1,10 @@
1
+ import { identity, multiply } from './utils.js';
2
+
3
+ function perspective(x, from) {
4
+ const matrix = identity();
5
+ // @ts-ignore
6
+ matrix[2][3] = typeof x == 'object' && x.val == 'none' ? 0 : x == 0 ? Number.NEGATIVE_INFINITY : -1 / x;
7
+ return multiply(from, matrix);
8
+ }
9
+
10
+ export { perspective };
@@ -0,0 +1,40 @@
1
+ import { identity, multiply } from './utils.js';
2
+
3
+ /**
4
+ * angle in radian
5
+ * @param angle
6
+ * @param x
7
+ * @param y
8
+ * @param z
9
+ * @param from
10
+ */
11
+ function rotate3D(angle, x, y, z, from) {
12
+ const matrix = identity();
13
+ const sc = Math.sin(angle / 2) * Math.cos(angle / 2);
14
+ const sq = Math.sin(angle / 2) * Math.sin(angle / 2);
15
+ const norm = Math.sqrt(x * x + y * y + z * z);
16
+ const unit = norm === 0 ? 0 : 1 / norm;
17
+ x *= unit;
18
+ y *= unit;
19
+ z *= unit;
20
+ matrix[0][0] = 1 - 2 * (y * y + z * z) * sq;
21
+ matrix[0][1] = 2 * (x * y * sq + z * sc);
22
+ matrix[0][2] = 2 * (x * z * sq - y * sc);
23
+ matrix[1][0] = 2 * (x * y * sq - z * sc);
24
+ matrix[1][1] = 1 - 2 * (x * x + z * z) * sq;
25
+ matrix[1][2] = 2 * (y * z * sq + x * sc);
26
+ matrix[2][0] = 2 * (x * z * sq + y * sc);
27
+ matrix[2][1] = 2 * (y * z * sq - x * sc);
28
+ matrix[2][2] = 1 - 2 * (x * x + y * y) * sq;
29
+ return multiply(from, matrix);
30
+ }
31
+ function rotate(angle, from) {
32
+ const matrix = identity();
33
+ matrix[0][0] = Math.cos(angle);
34
+ matrix[0][1] = Math.sin(angle);
35
+ matrix[1][0] = -Math.sin(angle);
36
+ matrix[1][1] = Math.cos(angle);
37
+ return multiply(from, matrix);
38
+ }
39
+
40
+ export { rotate, rotate3D };
@@ -0,0 +1,32 @@
1
+ import { identity, multiply } from './utils.js';
2
+
3
+ function scaleX(x, from) {
4
+ const matrix = identity();
5
+ matrix[0][0] = x;
6
+ return multiply(from, matrix);
7
+ }
8
+ function scaleY(y, from) {
9
+ const matrix = identity();
10
+ matrix[1][1] = y;
11
+ return multiply(from, matrix);
12
+ }
13
+ function scaleZ(z, from) {
14
+ const matrix = identity();
15
+ matrix[2][2] = z;
16
+ return multiply(from, matrix);
17
+ }
18
+ function scale(x, y, from) {
19
+ const matrix = identity();
20
+ matrix[0][0] = x;
21
+ matrix[1][1] = y;
22
+ return multiply(from, matrix);
23
+ }
24
+ function scale3d(x, y, z, from) {
25
+ const matrix = identity();
26
+ matrix[0][0] = x;
27
+ matrix[1][1] = y;
28
+ matrix[2][2] = z;
29
+ return multiply(from, matrix);
30
+ }
31
+
32
+ export { scale, scale3d, scaleX, scaleY, scaleZ };
@@ -0,0 +1,23 @@
1
+ import { identity, multiply } from './utils.js';
2
+
3
+ function skewX(x, from) {
4
+ const matrix = identity();
5
+ matrix[1][0] = Math.tan(x);
6
+ return multiply(from, matrix);
7
+ }
8
+ function skewY(y, from) {
9
+ const matrix = identity();
10
+ matrix[0][1] = Math.tan(y);
11
+ return multiply(from, matrix);
12
+ }
13
+ // convert angle to radian
14
+ function skew(values, from) {
15
+ const matrix = identity();
16
+ matrix[1][0] = Math.tan(values[0]);
17
+ if (values.length > 1) {
18
+ matrix[0][1] = Math.tan(values[1]);
19
+ }
20
+ return multiply(from, matrix);
21
+ }
22
+
23
+ export { skew, skewX, skewY };
@@ -0,0 +1,32 @@
1
+ import { identity, multiply } from './utils.js';
2
+
3
+ function translateX(x, from) {
4
+ const matrix = identity();
5
+ matrix[3][0] = x;
6
+ return multiply(from, matrix);
7
+ }
8
+ function translateY(y, from) {
9
+ const matrix = identity();
10
+ matrix[3][1] = y;
11
+ return multiply(from, matrix);
12
+ }
13
+ function translateZ(z, from) {
14
+ const matrix = identity();
15
+ matrix[3][2] = z;
16
+ return multiply(from, matrix);
17
+ }
18
+ function translate(translate, from) {
19
+ const matrix = identity();
20
+ matrix[3][0] = translate[0];
21
+ matrix[3][1] = translate[1] ?? 0;
22
+ return multiply(from, matrix);
23
+ }
24
+ function translate3d(translate, from) {
25
+ const matrix = identity();
26
+ matrix[3][0] = translate[0];
27
+ matrix[3][1] = translate[1];
28
+ matrix[3][2] = translate[2];
29
+ return multiply(from, matrix);
30
+ }
31
+
32
+ export { translate, translate3d, translateX, translateY, translateZ };
@@ -0,0 +1,198 @@
1
+ const epsilon = 1e-5;
2
+ function identity() {
3
+ return [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]];
4
+ }
5
+ function pLength(point) {
6
+ // Calcul de la norme euclidienne
7
+ return Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
8
+ }
9
+ function normalize(point) {
10
+ const [x, y, z] = point;
11
+ const norm = Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
12
+ return norm === 0 ? [0, 0, 0] : [x / norm, y / norm, z / norm];
13
+ }
14
+ function dot(point1, point2) {
15
+ if (point1.length === 4 && point2.length === 4) {
16
+ return point1[0] * point2[0] + point1[1] * point2[1] + point1[2] * point2[2] + point1[3] * point2[3];
17
+ }
18
+ return point1[0] * point2[0] + point1[1] * point2[1] + point1[2] * point2[2];
19
+ }
20
+ function multiply(matrixA, matrixB) {
21
+ let result = Array(4).fill(0).map(() => Array(4).fill(0));
22
+ for (let i = 0; i < 4; i++) {
23
+ for (let j = 0; j < 4; j++) {
24
+ for (let k = 0; k < 4; k++) {
25
+ result[j][i] += matrixA[k][i] * matrixB[j][k];
26
+ }
27
+ }
28
+ }
29
+ return result;
30
+ }
31
+ function round(number) {
32
+ return Math.abs(number) < epsilon ? 0 : +number.toPrecision(6);
33
+ }
34
+ // translate3d(25.9808px, 0, 15px ) rotateY(60deg) skewX(49.9999deg) scale(1, 1.2)
35
+ // translate → rotate → skew → scale
36
+ function decompose(original) {
37
+ const matrix = original.flat();
38
+ // Normalize last row
39
+ if (matrix[15] === 0) {
40
+ return null;
41
+ }
42
+ for (let i = 0; i < 16; i++)
43
+ matrix[i] /= matrix[15];
44
+ // Perspective extraction
45
+ const perspective = [0, 0, 0, 1];
46
+ if (matrix[3] !== 0 || matrix[7] !== 0 || matrix[11] !== 0) {
47
+ const rightHandSide = [matrix[3], matrix[7], matrix[11], matrix[15]];
48
+ const perspectiveMatrix = matrix.slice();
49
+ perspectiveMatrix[3] = 0;
50
+ perspectiveMatrix[7] = 0;
51
+ perspectiveMatrix[11] = 0;
52
+ perspectiveMatrix[15] = 1;
53
+ const inverse = invertMatrix4(perspectiveMatrix);
54
+ if (!inverse) {
55
+ return null;
56
+ }
57
+ const transposedInverse = transposeMatrix4(inverse);
58
+ perspective[0] = dot(rightHandSide, transposedInverse.slice(0, 4));
59
+ perspective[1] = dot(rightHandSide, transposedInverse.slice(4, 8));
60
+ perspective[2] = dot(rightHandSide, transposedInverse.slice(8, 12));
61
+ perspective[3] = dot(rightHandSide, transposedInverse.slice(12, 16));
62
+ // Clear perspective from matrix
63
+ matrix[3] = 0;
64
+ matrix[7] = 0;
65
+ matrix[11] = 0;
66
+ matrix[15] = 1;
67
+ }
68
+ // Translation
69
+ const translate = [matrix[12], matrix[13], matrix[14]];
70
+ matrix[12] = matrix[13] = matrix[14] = 0;
71
+ // Build the 3x3 matrix
72
+ const row0 = [matrix[0], matrix[1], matrix[2]];
73
+ const row1 = [matrix[4], matrix[5], matrix[6]];
74
+ const row2 = [matrix[8], matrix[9], matrix[10]];
75
+ // Compute scale
76
+ const scaleX = pLength(row0);
77
+ const row0Norm = normalize(row0);
78
+ const skewXY = dot(row0Norm, row1);
79
+ const row1Proj = [
80
+ row1[0] - skewXY * row0Norm[0],
81
+ row1[1] - skewXY * row0Norm[1],
82
+ row1[2] - skewXY * row0Norm[2]
83
+ ];
84
+ const scaleY = pLength(row1Proj);
85
+ const row1Norm = normalize(row1Proj);
86
+ const skewXZ = dot(row0Norm, row2);
87
+ const skewYZ = dot(row1Norm, row2);
88
+ const row2Proj = [
89
+ row2[0] - skewXZ * row0Norm[0] - skewYZ * row1Norm[0],
90
+ row2[1] - skewXZ * row0Norm[1] - skewYZ * row1Norm[1],
91
+ row2[2] - skewXZ * row0Norm[2] - skewYZ * row1Norm[2]
92
+ ];
93
+ const scaleZ = pLength(row2Proj);
94
+ const row2Norm = normalize(row2Proj);
95
+ // Build rotation matrix from orthonormalized vectors
96
+ const r00 = row0Norm[0], r01 = row1Norm[0], r02 = row2Norm[0];
97
+ const r10 = row0Norm[1], r11 = row1Norm[1], r12 = row2Norm[1];
98
+ const r20 = row0Norm[2], r21 = row1Norm[2], r22 = row2Norm[2];
99
+ // Convert to quaternion
100
+ const trace = r00 + r11 + r22;
101
+ let qw, qx, qy, qz;
102
+ if (trace > 0) {
103
+ const s = 0.5 / Math.sqrt(trace + 1.0);
104
+ qw = 0.25 / s;
105
+ qx = (r21 - r12) * s;
106
+ qy = (r02 - r20) * s;
107
+ qz = (r10 - r01) * s;
108
+ }
109
+ else if (r00 > r11 && r00 > r22) {
110
+ const s = 2.0 * Math.sqrt(1.0 + r00 - r11 - r22);
111
+ qw = (r21 - r12) / s;
112
+ qx = 0.25 * s;
113
+ qy = (r01 + r10) / s;
114
+ qz = (r02 + r20) / s;
115
+ }
116
+ else if (r11 > r22) {
117
+ const s = 2.0 * Math.sqrt(1.0 + r11 - r00 - r22);
118
+ qw = (r02 - r20) / s;
119
+ qx = (r01 + r10) / s;
120
+ qy = 0.25 * s;
121
+ qz = (r12 + r21) / s;
122
+ }
123
+ else {
124
+ const s = 2.0 * Math.sqrt(1.0 + r22 - r00 - r11);
125
+ qw = (r10 - r01) / s;
126
+ qx = (r02 + r20) / s;
127
+ qy = (r12 + r21) / s;
128
+ qz = 0.25 * s;
129
+ }
130
+ [qx, qy, qz] = toZero([qx, qy, qz]);
131
+ // const q = gcd(qx, gcd(qy, qz));
132
+ let q = [Math.abs(qx), Math.abs(qy), Math.abs(qz)].reduce((acc, curr) => {
133
+ if (acc == 0 || (curr > 0 && curr < acc)) {
134
+ acc = curr;
135
+ }
136
+ return acc;
137
+ }, 0);
138
+ if (q > 0) {
139
+ qx /= q;
140
+ qy /= q;
141
+ qz /= q;
142
+ }
143
+ const rotate = [qx, qy, qz, Object.is(qw, 0) ? 0 : 2 * Math.acos(qw) * 180 / Math.PI];
144
+ const scale = [scaleX, scaleY, scaleZ];
145
+ const skew = [skewXY, skewXZ, skewYZ];
146
+ return {
147
+ translate,
148
+ scale,
149
+ rotate,
150
+ skew,
151
+ perspective
152
+ };
153
+ }
154
+ function transposeMatrix4(m) {
155
+ return [
156
+ m[0], m[4], m[8], m[12],
157
+ m[1], m[5], m[9], m[13],
158
+ m[2], m[6], m[10], m[14],
159
+ m[3], m[7], m[11], m[15],
160
+ ];
161
+ }
162
+ function invertMatrix4(m) {
163
+ new Array(16);
164
+ const det = m[0] * m[5] * m[10] * m[15] + m[0] * m[9] * m[14] * m[7] + m[0] * m[13] * m[6] * m[11]
165
+ - m[0] * m[13] * m[10] * m[7] - m[0] * m[9] * m[6] * m[15] - m[0] * m[5] * m[14] * m[11];
166
+ if (det === 0)
167
+ return null;
168
+ // For brevity, not implementing full inverse here — you'd normally use gl-matrix or similar.
169
+ // Just use a trusted library or expand this if needed.
170
+ return null; // placeholder
171
+ }
172
+ function toZero(v) {
173
+ for (let i = 0; i < v.length; i++) {
174
+ if (Math.abs(v[i]) <= epsilon) {
175
+ v[i] = 0;
176
+ }
177
+ else {
178
+ v[i] = +v[i].toPrecision(6);
179
+ }
180
+ }
181
+ return v;
182
+ }
183
+ // https://drafts.csswg.org/css-transforms-1/#2d-matrix
184
+ function is2DMatrix(matrix) {
185
+ // m13,m14, m23, m24, m31, m32, m34, m43 are all 0
186
+ return matrix[0][2] === 0 &&
187
+ matrix[0][3] === 0 &&
188
+ matrix[1][2] === 0 &&
189
+ matrix[1][3] === 0 &&
190
+ matrix[2][0] === 0 &&
191
+ matrix[2][1] === 0 &&
192
+ matrix[2][3] === 0 &&
193
+ matrix[3][2] === 0 &&
194
+ matrix[2][2] === 1 &&
195
+ matrix[3][3] === 1;
196
+ }
197
+
198
+ export { decompose, epsilon, identity, is2DMatrix, multiply, round, toZero };
@@ -101,6 +101,8 @@ var EnumToken;
101
101
  EnumToken[EnumToken["MediaFeatureAndTokenType"] = 89] = "MediaFeatureAndTokenType";
102
102
  EnumToken[EnumToken["MediaFeatureOrTokenType"] = 90] = "MediaFeatureOrTokenType";
103
103
  EnumToken[EnumToken["PseudoPageTokenType"] = 91] = "PseudoPageTokenType";
104
+ EnumToken[EnumToken["PseudoElementTokenType"] = 92] = "PseudoElementTokenType";
105
+ EnumToken[EnumToken["KeyframeAtRuleNodeType"] = 93] = "KeyframeAtRuleNodeType";
104
106
  /* aliases */
105
107
  EnumToken[EnumToken["Time"] = 25] = "Time";
106
108
  EnumToken[EnumToken["Iden"] = 7] = "Iden";