@colorye/react-native-css 0.3.1 → 0.3.2
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.
- package/crates/transformer/index.js +1 -0
- package/crates/transformer/transformer.darwin-arm64.node +0 -0
- package/crates/transformer/transformer.darwin-x64.node +0 -0
- package/crates/transformer/transformer.linux-x64-gnu.node +0 -0
- package/crates/transformer/transformer.node +0 -0
- package/crates/transformer/transformer.win32-x64-msvc.node +0 -0
- package/dist/babel.js +68 -159
- package/dist/index.d.ts +22 -8
- package/dist/interop.js +17 -5
- package/dist/metro.js +55 -0
- package/dist/transformer-runtime.js +170 -18
- package/dist/transformer.js +73 -20
- package/package.json +3 -1
- package/src/babel.js +71 -224
- package/src/index.d.ts +22 -8
- package/src/interop.js +13 -1
- package/src/metro.js +42 -0
- package/src/transformer-runtime.js +169 -15
- package/src/transformer.js +75 -15
- package/dist/features/build-transform.js +0 -575
- package/dist/features/css-calc.js +0 -539
- package/dist/features/css-media.js +0 -77
- package/dist/features/css-transform.js +0 -426
- package/dist/features/css-vars.js +0 -153
- package/dist/features/stylesheet.js +0 -45
- package/dist/utils/babel.js +0 -363
- package/dist/utils/css.js +0 -263
- package/dist/utils/helper.js +0 -11
- package/src/features/build-transform.js +0 -536
- package/src/features/css-calc.js +0 -490
- package/src/features/css-media.js +0 -78
- package/src/features/css-transform.js +0 -446
- package/src/features/css-vars.js +0 -138
- package/src/features/stylesheet.js +0 -29
- package/src/utils/babel.js +0 -425
- package/src/utils/css.js +0 -221
- package/src/utils/helper.js +0 -3
package/src/features/css-calc.js
DELETED
|
@@ -1,490 +0,0 @@
|
|
|
1
|
-
const calcRe = /calc\(([^)]+)\)/g;
|
|
2
|
-
|
|
3
|
-
const colorRe1 = /rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d+)\s*)?\)/g;
|
|
4
|
-
const colorRe2 = /rgba?\(\s*(\d+)\s+(\d+)\s+(\d+)\s*\/\s*([\d.]+)\s*\)/g;
|
|
5
|
-
|
|
6
|
-
const itohex = (component) => {
|
|
7
|
-
const hex = Number(component).toString(16);
|
|
8
|
-
return hex.length === 1 ? `0${hex}` : hex;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
function splitTopLevelCommas(str) {
|
|
12
|
-
const parts = [];
|
|
13
|
-
let current = "";
|
|
14
|
-
let depth = 0;
|
|
15
|
-
for (let i = 0; i < str.length; i++) {
|
|
16
|
-
const char = str[i];
|
|
17
|
-
if (char === "(") {
|
|
18
|
-
depth++;
|
|
19
|
-
current += char;
|
|
20
|
-
} else if (char === ")") {
|
|
21
|
-
depth--;
|
|
22
|
-
current += char;
|
|
23
|
-
} else if (char === "," && depth === 0) {
|
|
24
|
-
parts.push(current.trim());
|
|
25
|
-
current = "";
|
|
26
|
-
} else {
|
|
27
|
-
current += char;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
if (current) {
|
|
31
|
-
parts.push(current.trim());
|
|
32
|
-
}
|
|
33
|
-
return parts;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function parseColorMixArg(arg) {
|
|
37
|
-
arg = arg.trim();
|
|
38
|
-
// Check if there is a percentage at the end
|
|
39
|
-
const percentEndMatch = arg.match(/\s+([\d.]+)%$/i);
|
|
40
|
-
if (percentEndMatch) {
|
|
41
|
-
const percentage = parseFloat(percentEndMatch[1]);
|
|
42
|
-
const colorStr = arg.substring(0, arg.length - percentEndMatch[0].length).trim();
|
|
43
|
-
return { colorStr, percentage };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Check if there is a percentage at the beginning
|
|
47
|
-
const percentStartMatch = arg.match(/^([\d.]+)%\s+/i);
|
|
48
|
-
if (percentStartMatch) {
|
|
49
|
-
const percentage = parseFloat(percentStartMatch[1]);
|
|
50
|
-
const colorStr = arg.substring(percentStartMatch[0].length).trim();
|
|
51
|
-
return { colorStr, percentage };
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return { colorStr: arg, percentage: null };
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function hslToRgb(h, s, l) {
|
|
58
|
-
h = h / 360;
|
|
59
|
-
s = s / 100;
|
|
60
|
-
l = l / 100;
|
|
61
|
-
let r, g, b;
|
|
62
|
-
if (s === 0) {
|
|
63
|
-
r = g = b = l; // achromatic
|
|
64
|
-
} else {
|
|
65
|
-
const hue2rgb = (p, q, t) => {
|
|
66
|
-
if (t < 0) t += 1;
|
|
67
|
-
if (t > 1) t -= 1;
|
|
68
|
-
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
|
69
|
-
if (t < 1 / 2) return q;
|
|
70
|
-
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
|
71
|
-
return p;
|
|
72
|
-
};
|
|
73
|
-
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
74
|
-
const p = 2 * l - q;
|
|
75
|
-
r = hue2rgb(p, q, h + 1 / 3);
|
|
76
|
-
g = hue2rgb(p, q, h);
|
|
77
|
-
b = hue2rgb(p, q, h - 1 / 3);
|
|
78
|
-
}
|
|
79
|
-
return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255) };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function parseColor(colorStr) {
|
|
83
|
-
if (!colorStr) return null;
|
|
84
|
-
colorStr = colorStr.trim().toLowerCase();
|
|
85
|
-
|
|
86
|
-
if (colorStr === "transparent") {
|
|
87
|
-
return { r: 0, g: 0, b: 0, a: 0 };
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Hex
|
|
91
|
-
if (colorStr.startsWith("#")) {
|
|
92
|
-
const hex = colorStr.substring(1);
|
|
93
|
-
if (hex.length === 3 || hex.length === 4) {
|
|
94
|
-
const r = parseInt(hex[0] + hex[0], 16);
|
|
95
|
-
const g = parseInt(hex[1] + hex[1], 16);
|
|
96
|
-
const b = parseInt(hex[2] + hex[2], 16);
|
|
97
|
-
const a = hex.length === 4 ? parseInt(hex[3] + hex[3], 16) / 255 : 1;
|
|
98
|
-
return { r, g, b, a };
|
|
99
|
-
}
|
|
100
|
-
if (hex.length === 6 || hex.length === 8) {
|
|
101
|
-
const r = parseInt(hex.substring(0, 2), 16);
|
|
102
|
-
const g = parseInt(hex.substring(2, 4), 16);
|
|
103
|
-
const b = parseInt(hex.substring(4, 6), 16);
|
|
104
|
-
const a = hex.length === 8 ? parseInt(hex.substring(6, 8), 16) / 255 : 1;
|
|
105
|
-
return { r, g, b, a };
|
|
106
|
-
}
|
|
107
|
-
return null;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// rgb / rgba
|
|
111
|
-
const rgbMatch = colorStr.match(/rgba?\(\s*([\d.]+)(%?)\s*[\s,]\s*([\d.]+)(%?)\s*[\s,]\s*([\d.]+)(%?)(?:\s*[\s,/]\s*([\d.]+)(%?))?\s*\)/);
|
|
112
|
-
if (rgbMatch) {
|
|
113
|
-
let r = parseFloat(rgbMatch[1]);
|
|
114
|
-
if (rgbMatch[2] === "%") r = (r / 100) * 255;
|
|
115
|
-
let g = parseFloat(rgbMatch[3]);
|
|
116
|
-
if (rgbMatch[4] === "%") g = (g / 100) * 255;
|
|
117
|
-
let b = parseFloat(rgbMatch[5]);
|
|
118
|
-
if (rgbMatch[6] === "%") b = (b / 100) * 255;
|
|
119
|
-
|
|
120
|
-
let a = 1;
|
|
121
|
-
if (rgbMatch[7] !== undefined) {
|
|
122
|
-
a = parseFloat(rgbMatch[7]);
|
|
123
|
-
if (rgbMatch[8] === "%") a = a / 100;
|
|
124
|
-
}
|
|
125
|
-
return { r: Math.round(r), g: Math.round(g), b: Math.round(b), a };
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// hsl / hsla
|
|
129
|
-
const hslMatch = colorStr.match(/hsla?\(\s*([\d.]+)(?:deg)?\s*[\s,]\s*([\d.]+)%\s*[\s,]\s*([\d.]+)%\s*(?:\s*[\s,/]\s*([\d.]+)(%?))?\s*\)/);
|
|
130
|
-
if (hslMatch) {
|
|
131
|
-
const h = parseFloat(hslMatch[1]);
|
|
132
|
-
const s = parseFloat(hslMatch[2]);
|
|
133
|
-
const l = parseFloat(hslMatch[3]);
|
|
134
|
-
let a = 1;
|
|
135
|
-
if (hslMatch[4] !== undefined) {
|
|
136
|
-
a = parseFloat(hslMatch[4]);
|
|
137
|
-
if (hslMatch[5] === "%") a = a / 100;
|
|
138
|
-
}
|
|
139
|
-
const rgb = hslToRgb(h, s, l);
|
|
140
|
-
return { ...rgb, a };
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// oklch(L C H [/ A])
|
|
144
|
-
const oklchMatch = colorStr.match(/oklch\(\s*([\d.]+)(%?)\s+([\d.]+)\s+([\d.]+)(?:deg)?(?:\s*\/\s*([\d.]+)(%?))?\s*\)/);
|
|
145
|
-
if (oklchMatch) {
|
|
146
|
-
let L = parseFloat(oklchMatch[1]);
|
|
147
|
-
if (oklchMatch[2] === "%" || L > 1) L = L / 100;
|
|
148
|
-
const C = parseFloat(oklchMatch[3]);
|
|
149
|
-
const H = parseFloat(oklchMatch[4]);
|
|
150
|
-
let a = 1;
|
|
151
|
-
if (oklchMatch[5] !== undefined) {
|
|
152
|
-
a = parseFloat(oklchMatch[5]);
|
|
153
|
-
if (oklchMatch[6] === "%") a = a / 100;
|
|
154
|
-
}
|
|
155
|
-
const hRad = (H * Math.PI) / 180;
|
|
156
|
-
const okA = C * Math.cos(hRad);
|
|
157
|
-
const okB = C * Math.sin(hRad);
|
|
158
|
-
const l_ = L + 0.3963377774 * okA + 0.2158037573 * okB;
|
|
159
|
-
const m_ = L - 0.1055613458 * okA - 0.0638541728 * okB;
|
|
160
|
-
const s_ = L - 0.0894841775 * okA - 1.291485548 * okB;
|
|
161
|
-
const l = l_ * l_ * l_;
|
|
162
|
-
const m = m_ * m_ * m_;
|
|
163
|
-
const s = s_ * s_ * s_;
|
|
164
|
-
const r = +4.0767439362 * l - 3.3077115913 * m + 0.2309699292 * s;
|
|
165
|
-
const g = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s;
|
|
166
|
-
const bl = -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s;
|
|
167
|
-
const gamma = (c) => (c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(Math.max(0, c), 1 / 2.4) - 0.055);
|
|
168
|
-
return {
|
|
169
|
-
r: Math.max(0, Math.min(255, Math.round(gamma(r) * 255))),
|
|
170
|
-
g: Math.max(0, Math.min(255, Math.round(gamma(g) * 255))),
|
|
171
|
-
b: Math.max(0, Math.min(255, Math.round(gamma(bl) * 255))),
|
|
172
|
-
a,
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// lab(L a b [/ A])
|
|
177
|
-
const labMatch = colorStr.match(/lab\(\s*([\d.]+)(%?)\s+([+-]?[\d.]+)\s+([+-]?[\d.]+)(?:\s*\/\s*([\d.]+)(%?))?\s*\)/);
|
|
178
|
-
if (labMatch) {
|
|
179
|
-
let L = parseFloat(labMatch[1]);
|
|
180
|
-
const labA = parseFloat(labMatch[3]);
|
|
181
|
-
const labB = parseFloat(labMatch[4]);
|
|
182
|
-
let a = 1;
|
|
183
|
-
if (labMatch[5] !== undefined) {
|
|
184
|
-
a = parseFloat(labMatch[5]);
|
|
185
|
-
if (labMatch[6] === "%") a = a / 100;
|
|
186
|
-
}
|
|
187
|
-
let y = (L + 16) / 116;
|
|
188
|
-
let x = labA / 500 + y;
|
|
189
|
-
let z = y - labB / 200;
|
|
190
|
-
const fInv = (t) => (t > 6 / 29 ? t * t * t : 3 * (6 / 29) * (6 / 29) * (t - 4 / 29));
|
|
191
|
-
x = 0.95047 * fInv(x);
|
|
192
|
-
y = 1.0 * fInv(y);
|
|
193
|
-
z = 1.08883 * fInv(z);
|
|
194
|
-
let r = 3.2406 * x - 1.5372 * y - 0.4986 * z;
|
|
195
|
-
let g = -0.9689 * x + 1.8758 * y + 0.0415 * z;
|
|
196
|
-
let bl = 0.0557 * x - 0.204 * y + 1.057 * z;
|
|
197
|
-
const gamma = (c) => (c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(Math.max(0, c), 1 / 2.4) - 0.055);
|
|
198
|
-
return {
|
|
199
|
-
r: Math.max(0, Math.min(255, Math.round(gamma(r) * 255))),
|
|
200
|
-
g: Math.max(0, Math.min(255, Math.round(gamma(g) * 255))),
|
|
201
|
-
b: Math.max(0, Math.min(255, Math.round(gamma(bl) * 255))),
|
|
202
|
-
a,
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// Basic named colors fallback
|
|
207
|
-
const basicColors = {
|
|
208
|
-
white: { r: 255, g: 255, b: 255, a: 1 },
|
|
209
|
-
black: { r: 0, g: 0, b: 0, a: 1 },
|
|
210
|
-
red: { r: 255, g: 0, b: 0, a: 1 },
|
|
211
|
-
green: { r: 0, g: 128, b: 0, a: 1 },
|
|
212
|
-
blue: { r: 0, g: 0, b: 255, a: 1 },
|
|
213
|
-
yellow: { r: 255, g: 255, b: 0, a: 1 },
|
|
214
|
-
magenta: { r: 255, g: 0, b: 255, a: 1 },
|
|
215
|
-
cyan: { r: 0, g: 255, b: 255, a: 1 },
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
if (basicColors[colorStr]) {
|
|
219
|
-
return basicColors[colorStr];
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return null;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function resolveColorMix(value) {
|
|
226
|
-
if (typeof value !== "string") return value;
|
|
227
|
-
|
|
228
|
-
let index;
|
|
229
|
-
while ((index = value.toLowerCase().indexOf("color-mix(")) !== -1) {
|
|
230
|
-
// Find matching closing parenthesis
|
|
231
|
-
let depth = 1;
|
|
232
|
-
let j = index + "color-mix(".length;
|
|
233
|
-
while (j < value.length && depth > 0) {
|
|
234
|
-
if (value[j] === "(") {
|
|
235
|
-
depth++;
|
|
236
|
-
} else if (value[j] === ")") {
|
|
237
|
-
depth--;
|
|
238
|
-
}
|
|
239
|
-
j++;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
if (depth > 0) {
|
|
243
|
-
// Unmatched parenthesis, break to avoid infinite loop
|
|
244
|
-
break;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const innerContent = value.substring(index + "color-mix(".length, j - 1);
|
|
248
|
-
|
|
249
|
-
// Parse innerContent: "in <color-space>, <args>"
|
|
250
|
-
const commaIndex = innerContent.indexOf(",");
|
|
251
|
-
if (commaIndex === -1) {
|
|
252
|
-
// Invalid syntax, skip this one by replacing "color-mix(" with a placeholder temporarily
|
|
253
|
-
value = value.substring(0, index) + "COLOR_MIX_TEMP(" + value.substring(index + "color-mix(".length);
|
|
254
|
-
continue;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
const argsPart = innerContent.substring(commaIndex + 1).trim();
|
|
258
|
-
|
|
259
|
-
// Check if argsPart contains another color-mix. If so, resolve the inner one first.
|
|
260
|
-
if (argsPart.toLowerCase().includes("color-mix(")) {
|
|
261
|
-
const resolvedArgsPart = resolveColorMix(argsPart);
|
|
262
|
-
value = value.substring(0, index + "color-mix(".length + commaIndex + 1) + " " + resolvedArgsPart + value.substring(j - 1);
|
|
263
|
-
continue;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// Now we can resolve this color-mix
|
|
267
|
-
const args = splitTopLevelCommas(argsPart);
|
|
268
|
-
if (args.length !== 2) {
|
|
269
|
-
// Invalid syntax
|
|
270
|
-
value = value.substring(0, index) + "COLOR_MIX_TEMP(" + value.substring(index + "color-mix(".length);
|
|
271
|
-
continue;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
const arg1 = parseColorMixArg(args[0]);
|
|
275
|
-
const arg2 = parseColorMixArg(args[1]);
|
|
276
|
-
|
|
277
|
-
const c1 = parseColor(arg1.colorStr);
|
|
278
|
-
const c2 = parseColor(arg2.colorStr);
|
|
279
|
-
|
|
280
|
-
if (!c1 || !c2) {
|
|
281
|
-
// Parsing failed, skip
|
|
282
|
-
value = value.substring(0, index) + "COLOR_MIX_TEMP(" + value.substring(index + "color-mix(".length);
|
|
283
|
-
continue;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
const p1 = arg1.percentage;
|
|
287
|
-
const p2 = arg2.percentage;
|
|
288
|
-
|
|
289
|
-
let w1, w2;
|
|
290
|
-
if (p1 !== null && p2 !== null) {
|
|
291
|
-
const sum = p1 + p2;
|
|
292
|
-
if (sum > 100) {
|
|
293
|
-
w1 = (p1 / sum) * 100;
|
|
294
|
-
w2 = (p2 / sum) * 100;
|
|
295
|
-
} else {
|
|
296
|
-
w1 = p1;
|
|
297
|
-
w2 = p2;
|
|
298
|
-
}
|
|
299
|
-
} else if (p1 !== null) {
|
|
300
|
-
w1 = p1;
|
|
301
|
-
w2 = 100 - p1;
|
|
302
|
-
} else if (p2 !== null) {
|
|
303
|
-
w2 = p2;
|
|
304
|
-
w1 = 100 - p2;
|
|
305
|
-
} else {
|
|
306
|
-
w1 = 50;
|
|
307
|
-
w2 = 50;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
const a1 = c1.a;
|
|
311
|
-
const a2 = c2.a;
|
|
312
|
-
|
|
313
|
-
const totalWeight = w1 + w2;
|
|
314
|
-
let resolvedColor;
|
|
315
|
-
if (totalWeight === 0) {
|
|
316
|
-
resolvedColor = "transparent";
|
|
317
|
-
} else {
|
|
318
|
-
const f1 = w1 / totalWeight;
|
|
319
|
-
const f2 = w2 / totalWeight;
|
|
320
|
-
|
|
321
|
-
const mixedA = a1 * f1 + a2 * f2;
|
|
322
|
-
|
|
323
|
-
let mixedR, mixedG, mixedB;
|
|
324
|
-
if (mixedA === 0) {
|
|
325
|
-
mixedR = 0;
|
|
326
|
-
mixedG = 0;
|
|
327
|
-
mixedB = 0;
|
|
328
|
-
} else {
|
|
329
|
-
mixedR = Math.round((c1.r * a1 * f1 + c2.r * a2 * f2) / mixedA);
|
|
330
|
-
mixedG = Math.round((c1.g * a1 * f1 + c2.g * a2 * f2) / mixedA);
|
|
331
|
-
mixedB = Math.round((c1.b * a1 * f1 + c2.b * a2 * f2) / mixedA);
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
const finalA = totalWeight < 100 ? mixedA * (totalWeight / 100) : mixedA;
|
|
335
|
-
const roundedA = Math.round(finalA * 10000) / 10000;
|
|
336
|
-
|
|
337
|
-
resolvedColor = `rgba(${mixedR}, ${mixedG}, ${mixedB}, ${roundedA})`;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
value = value.substring(0, index) + resolvedColor + value.substring(j);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// Restore placeholders
|
|
344
|
-
value = value.replace(/COLOR_MIX_TEMP\(/gi, "color-mix(");
|
|
345
|
-
|
|
346
|
-
return value;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
function safeEvalMath(expr) {
|
|
350
|
-
if (!expr || typeof expr !== "string") return 0;
|
|
351
|
-
|
|
352
|
-
// Clean rem and px units if present
|
|
353
|
-
const sanitized = expr
|
|
354
|
-
.replace(/([\d.]+)rem/g, (_, n) => `${parseFloat(n) * 16}`)
|
|
355
|
-
.replace(/([\d.]+)px/g, "$1");
|
|
356
|
-
|
|
357
|
-
let pos = 0;
|
|
358
|
-
const len = sanitized.length;
|
|
359
|
-
|
|
360
|
-
function peek() {
|
|
361
|
-
while (pos < len && sanitized.charCodeAt(pos) <= 32) pos++;
|
|
362
|
-
return pos < len ? sanitized[pos] : "";
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
function get() {
|
|
366
|
-
const ch = peek();
|
|
367
|
-
pos++;
|
|
368
|
-
return ch;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
function parseFactor() {
|
|
372
|
-
const ch = peek();
|
|
373
|
-
if (ch === "+") {
|
|
374
|
-
get();
|
|
375
|
-
return parseFactor();
|
|
376
|
-
}
|
|
377
|
-
if (ch === "-") {
|
|
378
|
-
get();
|
|
379
|
-
return -parseFactor();
|
|
380
|
-
}
|
|
381
|
-
if (ch === "(") {
|
|
382
|
-
get();
|
|
383
|
-
const val = parseExpression();
|
|
384
|
-
if (peek() === ")") get();
|
|
385
|
-
return val;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
// Parse number
|
|
389
|
-
const start = pos;
|
|
390
|
-
let hasDot = false;
|
|
391
|
-
while (pos < len) {
|
|
392
|
-
const c = sanitized[pos];
|
|
393
|
-
if (c >= "0" && c <= "9") {
|
|
394
|
-
pos++;
|
|
395
|
-
} else if (c === "." && !hasDot) {
|
|
396
|
-
hasDot = true;
|
|
397
|
-
pos++;
|
|
398
|
-
} else {
|
|
399
|
-
break;
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
if (start === pos) return 0;
|
|
404
|
-
const numStr = sanitized.slice(start, pos);
|
|
405
|
-
const num = parseFloat(numStr);
|
|
406
|
-
return isNaN(num) ? 0 : num;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
function parseTerm() {
|
|
410
|
-
let result = parseFactor();
|
|
411
|
-
while (true) {
|
|
412
|
-
const op = peek();
|
|
413
|
-
if (op === "*" || op === "/") {
|
|
414
|
-
get();
|
|
415
|
-
const factor = parseFactor();
|
|
416
|
-
result = op === "*" ? result * factor : (factor !== 0 ? result / factor : 0);
|
|
417
|
-
} else {
|
|
418
|
-
break;
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
return result;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
function parseExpression() {
|
|
425
|
-
let result = parseTerm();
|
|
426
|
-
while (true) {
|
|
427
|
-
const op = peek();
|
|
428
|
-
if (op === "+" || op === "-") {
|
|
429
|
-
get();
|
|
430
|
-
const term = parseTerm();
|
|
431
|
-
result = op === "+" ? result + term : result - term;
|
|
432
|
-
} else {
|
|
433
|
-
break;
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
return result;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
try {
|
|
440
|
-
const val = parseExpression();
|
|
441
|
-
return isNaN(val) ? 0 : val;
|
|
442
|
-
} catch {
|
|
443
|
-
return 0;
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
export default function CssCalc() {
|
|
448
|
-
this.calc = (value) => {
|
|
449
|
-
if (value === undefined || typeof value !== "string") return value;
|
|
450
|
-
|
|
451
|
-
return value.replace(calcRe, (_, calc) => {
|
|
452
|
-
return safeEvalMath(calc);
|
|
453
|
-
});
|
|
454
|
-
};
|
|
455
|
-
|
|
456
|
-
this.calcColor = (value) => {
|
|
457
|
-
if (value === undefined || typeof value !== "string") return value;
|
|
458
|
-
|
|
459
|
-
value = resolveColorMix(value);
|
|
460
|
-
|
|
461
|
-
// If the entire value is a single color (hex, rgb, hsl, oklch, lab), normalize to hex/rgba
|
|
462
|
-
const parsed = parseColor(value);
|
|
463
|
-
if (parsed) {
|
|
464
|
-
if (parsed.a === 1) {
|
|
465
|
-
return `#${itohex(parsed.r)}${itohex(parsed.g)}${itohex(parsed.b)}`;
|
|
466
|
-
}
|
|
467
|
-
const a = Math.round(parsed.a * 255);
|
|
468
|
-
return `#${itohex(parsed.r)}${itohex(parsed.g)}${itohex(parsed.b)}${itohex(a)}`;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
value = value.replace(colorRe1, (_, r, g, b, a) => {
|
|
472
|
-
a = parseFloat(a);
|
|
473
|
-
if (isNaN(a) || a >= 1) return `#${itohex(r)}${itohex(g)}${itohex(b)}`;
|
|
474
|
-
|
|
475
|
-
a = Math.round(a * 255);
|
|
476
|
-
return `#${itohex(r)}${itohex(g)}${itohex(b)}${itohex(a)}`;
|
|
477
|
-
});
|
|
478
|
-
value = value.replace(colorRe2, (_, r, g, b, a) => {
|
|
479
|
-
a = parseFloat(a);
|
|
480
|
-
if (isNaN(a) || a >= 1) return `#${itohex(r)}${itohex(g)}${itohex(b)}`;
|
|
481
|
-
|
|
482
|
-
a = Math.round(a * 255);
|
|
483
|
-
return `#${itohex(r)}${itohex(g)}${itohex(b)}${itohex(a)}`;
|
|
484
|
-
});
|
|
485
|
-
|
|
486
|
-
return value;
|
|
487
|
-
};
|
|
488
|
-
|
|
489
|
-
return this;
|
|
490
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { camelize } from "../utils/helper";
|
|
2
|
-
import CssTransform from "./css-transform";
|
|
3
|
-
|
|
4
|
-
const SUPPORTED_MEDIA_TYPE = [
|
|
5
|
-
"min-width",
|
|
6
|
-
"min-height",
|
|
7
|
-
"max-width",
|
|
8
|
-
"max-height",
|
|
9
|
-
"prefers-color-scheme",
|
|
10
|
-
];
|
|
11
|
-
|
|
12
|
-
export default function CssMedia() {
|
|
13
|
-
const transform = new CssTransform();
|
|
14
|
-
|
|
15
|
-
this.match = (media, { width, height, colorScheme } = {}) => {
|
|
16
|
-
const isMedia = media.startsWith("@media");
|
|
17
|
-
if (!isMedia) return [false];
|
|
18
|
-
|
|
19
|
-
let isValidMedia = true;
|
|
20
|
-
const widthRange = [Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY];
|
|
21
|
-
const heightRange = [Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY];
|
|
22
|
-
|
|
23
|
-
const mediaGroupsRe = /\([^)]*\)/g;
|
|
24
|
-
const mediaGroups = media.match(mediaGroupsRe)?.map((rawGroup) => {
|
|
25
|
-
const mediaGroupRe = /\(\s*([^:)\s]+)\s*:\s*([^:)\s]+)\s*\)/g;
|
|
26
|
-
let [, mediaType, mediaValue] = mediaGroupRe.exec(rawGroup) || [];
|
|
27
|
-
|
|
28
|
-
if (!SUPPORTED_MEDIA_TYPE.includes(mediaType)) {
|
|
29
|
-
isValidMedia = false;
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
mediaType = camelize(mediaType);
|
|
34
|
-
|
|
35
|
-
mediaValue = transform.transformUnsupportedUnit(mediaValue);
|
|
36
|
-
mediaValue = transform.transformViewportUnit(mediaValue, { width, height });
|
|
37
|
-
mediaValue = transform.removeUnit(mediaValue);
|
|
38
|
-
|
|
39
|
-
if (mediaType === "minWidth") {
|
|
40
|
-
widthRange[0] = mediaValue;
|
|
41
|
-
} else if (mediaType === "minHeight") {
|
|
42
|
-
heightRange[0] = mediaValue;
|
|
43
|
-
} else if (mediaType === "maxWidth") {
|
|
44
|
-
widthRange[1] = mediaValue;
|
|
45
|
-
} else if (mediaType === "maxHeight") {
|
|
46
|
-
heightRange[1] = mediaValue;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return [mediaType, mediaValue];
|
|
50
|
-
});
|
|
51
|
-
if (!Array.isArray(mediaGroups) || mediaGroups.length === 0) {
|
|
52
|
-
isValidMedia = false;
|
|
53
|
-
}
|
|
54
|
-
if (!isValidMedia) return [true, false];
|
|
55
|
-
|
|
56
|
-
if (mediaGroups[0][0] === "prefersColorScheme" && mediaGroups[0][1] === "dark") {
|
|
57
|
-
if (colorScheme === "dark") {
|
|
58
|
-
return [true, true];
|
|
59
|
-
} else {
|
|
60
|
-
return [true, false];
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const isValidRange = widthRange[0] <= widthRange[1] && heightRange[0] <= heightRange[1];
|
|
65
|
-
if (!isValidRange) return [true, false];
|
|
66
|
-
|
|
67
|
-
const isMatchedMedia =
|
|
68
|
-
widthRange[0] <= width &&
|
|
69
|
-
width <= widthRange[1] &&
|
|
70
|
-
heightRange[0] <= height &&
|
|
71
|
-
height <= heightRange[1];
|
|
72
|
-
if (!isMatchedMedia) return [true, false];
|
|
73
|
-
|
|
74
|
-
return [true, true];
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
return this;
|
|
78
|
-
}
|