@tenphi/tasty 3.7.0 → 3.9.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.
- package/dist/{babel-DWCsafYw.d.ts → babel-Zs1Q03qt.d.ts} +2 -2
- package/dist/chunks/async-storage-CG5HnUT5.js +20 -0
- package/dist/chunks/async-storage-CG5HnUT5.js.map +1 -0
- package/dist/chunks/build-config-CUQVwdWF.js +42 -0
- package/dist/chunks/build-config-CUQVwdWF.js.map +1 -0
- package/dist/{collector-B3OsM252.js → chunks/collector-B0LTHw6Z.js} +6 -125
- package/dist/chunks/collector-B0LTHw6Z.js.map +1 -0
- package/dist/chunks/config-engine-C3pF9EK9.js +267 -0
- package/dist/chunks/config-engine-C3pF9EK9.js.map +1 -0
- package/dist/chunks/css-definitions-D_it4XZH.js +875 -0
- package/dist/chunks/css-definitions-D_it4XZH.js.map +1 -0
- package/dist/{css-resources-Cyl_axbI.js → chunks/css-resources-BN8apgxt.js} +1 -8
- package/dist/chunks/css-resources-BN8apgxt.js.map +1 -0
- package/dist/chunks/debug-C9LeNVoJ.js +501 -0
- package/dist/chunks/debug-C9LeNVoJ.js.map +1 -0
- package/dist/chunks/dsl-C5yuAn41.js +1373 -0
- package/dist/chunks/dsl-C5yuAn41.js.map +1 -0
- package/dist/chunks/hydration-TRcz5vnk.js +41 -0
- package/dist/chunks/hydration-TRcz5vnk.js.map +1 -0
- package/dist/chunks/react-runtime-O-OUrKLH.js +557 -0
- package/dist/chunks/react-runtime-O-OUrKLH.js.map +1 -0
- package/dist/chunks/runtime-engine-DvnE2g-E.js +2437 -0
- package/dist/chunks/runtime-engine-DvnE2g-E.js.map +1 -0
- package/dist/chunks/runtime-state-BTDqSYBk.js +127 -0
- package/dist/chunks/runtime-state-BTDqSYBk.js.map +1 -0
- package/dist/{merge-styles-DuoZEsm9.js → chunks/shared-utils-DWA4LjIa.js} +55 -54
- package/dist/chunks/shared-utils-DWA4LjIa.js.map +1 -0
- package/dist/chunks/style-engine-C1ECBZxR.js +5131 -0
- package/dist/chunks/style-engine-C1ECBZxR.js.map +1 -0
- package/dist/{css-writer-Bgowobbx.js → chunks/zero-engine-B6EnYcXY.js} +3 -120
- package/dist/chunks/zero-engine-B6EnYcXY.js.map +1 -0
- package/dist/{collector-BTVXj2hS.d.ts → collector-hl5KNH7k.d.ts} +6 -4
- package/dist/{config-LfIDmVHx.d.ts → config-DWL1ZYue.d.ts} +20 -25
- package/dist/core/index.d.ts +5 -5
- package/dist/core/index.js +9 -6
- package/dist/{index-Bm9ltvdH.d.ts → index-D9N9GV24.d.ts} +96 -82
- package/dist/index.d.ts +5 -5
- package/dist/index.js +11 -922
- package/dist/{merge-styles-BcLl1u_d.d.ts → merge-styles-C_oMoJVd.d.ts} +2 -2
- package/dist/ssr/astro-client.js +1 -14
- package/dist/ssr/astro-client.js.map +1 -1
- package/dist/ssr/astro-middleware-extract-static.js +1 -1
- package/dist/ssr/astro-middleware-extract.js +1 -1
- package/dist/ssr/astro-middleware-static.js +1 -12
- package/dist/ssr/astro-middleware-static.js.map +1 -1
- package/dist/ssr/astro-middleware.js +1 -13
- package/dist/ssr/astro-middleware.js.map +1 -1
- package/dist/ssr/astro.js +219 -1
- package/dist/ssr/astro.js.map +1 -0
- package/dist/ssr/index.d.ts +6 -6
- package/dist/ssr/index.js +4 -4
- package/dist/ssr/next-config.d.ts +1 -1
- package/dist/ssr/next-config.js +29 -20
- package/dist/ssr/next-config.js.map +1 -1
- package/dist/ssr/next.d.ts +1 -1
- package/dist/ssr/next.js +5 -37
- package/dist/ssr/next.js.map +1 -1
- package/dist/static/index.d.ts +2 -2
- package/dist/static/index.js +1 -19
- package/dist/static/index.js.map +1 -1
- package/dist/{index-BmogEzTo.d.ts → types-jKZNpias.d.ts} +845 -804
- package/dist/zero/babel.d.ts +1 -1
- package/dist/zero/babel.js +25 -96
- package/dist/zero/babel.js.map +1 -1
- package/dist/zero/index.d.ts +1 -1
- package/dist/zero/index.js +1 -1
- package/dist/zero/next.d.ts +1 -1
- package/dist/zero/next.js +0 -31
- package/dist/zero/next.js.map +1 -1
- package/docs/ai-agents.md +8 -3
- package/docs/debug.md +2 -5
- package/docs/methodology.md +3 -3
- package/docs/pipeline.md +3 -0
- package/docs/runtime-benchmarks.md +105 -68
- package/docs/styles.md +43 -11
- package/package.json +48 -5
- package/dist/astro-CeYENy2x.js +0 -301
- package/dist/astro-CeYENy2x.js.map +0 -1
- package/dist/async-storage-DKK-wTD4.js +0 -44
- package/dist/async-storage-DKK-wTD4.js.map +0 -1
- package/dist/collector-B3OsM252.js.map +0 -1
- package/dist/config-B3gPdCqd.js +0 -12421
- package/dist/config-B3gPdCqd.js.map +0 -1
- package/dist/context-CA8YKeMn.js +0 -24
- package/dist/context-CA8YKeMn.js.map +0 -1
- package/dist/core-DGm0CFHP.js +0 -1732
- package/dist/core-DGm0CFHP.js.map +0 -1
- package/dist/css-resources-Cyl_axbI.js.map +0 -1
- package/dist/css-writer-Bgowobbx.js.map +0 -1
- package/dist/format-global-rules-DklyaXv-.js +0 -22
- package/dist/format-global-rules-DklyaXv-.js.map +0 -1
- package/dist/format-rules-XRw9u7d4.js +0 -104
- package/dist/format-rules-XRw9u7d4.js.map +0 -1
- package/dist/hydrate-CNOmZprz.js +0 -37
- package/dist/hydrate-CNOmZprz.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/keyframes-DE-OE76F.js +0 -535
- package/dist/keyframes-DE-OE76F.js.map +0 -1
- package/dist/merge-styles-DuoZEsm9.js.map +0 -1
- package/dist/resolve-recipes-H9NqOQuP.js +0 -144
- package/dist/resolve-recipes-H9NqOQuP.js.map +0 -1
- package/dist/ssr-collector-ref-COs_ioWl.js +0 -29
- package/dist/ssr-collector-ref-COs_ioWl.js.map +0 -1
|
@@ -0,0 +1,1373 @@
|
|
|
1
|
+
import { a as warnOnceDev, o as isDevEnv } from "./shared-utils-DWA4LjIa.js";
|
|
2
|
+
//#region src/parser/const.ts
|
|
3
|
+
const VALUE_KEYWORDS = new Set([
|
|
4
|
+
"auto",
|
|
5
|
+
"max-content",
|
|
6
|
+
"min-content",
|
|
7
|
+
"fit-content",
|
|
8
|
+
"stretch",
|
|
9
|
+
"initial",
|
|
10
|
+
"inherit",
|
|
11
|
+
"revert",
|
|
12
|
+
"unset",
|
|
13
|
+
"revert-layer"
|
|
14
|
+
]);
|
|
15
|
+
const CSS_WIDE_KEYWORDS = new Set([
|
|
16
|
+
"initial",
|
|
17
|
+
"inherit",
|
|
18
|
+
"revert",
|
|
19
|
+
"unset",
|
|
20
|
+
"revert-layer"
|
|
21
|
+
]);
|
|
22
|
+
const DERIVED_COLOR_FUNCS_LIST = [
|
|
23
|
+
"color-mix",
|
|
24
|
+
"color-contrast",
|
|
25
|
+
"contrast-color",
|
|
26
|
+
"light-dark"
|
|
27
|
+
];
|
|
28
|
+
const DERIVED_COLOR_FUNCS = new Set(DERIVED_COLOR_FUNCS_LIST);
|
|
29
|
+
const COLOR_FUNCS = new Set([
|
|
30
|
+
"rgb",
|
|
31
|
+
"rgba",
|
|
32
|
+
"hsl",
|
|
33
|
+
"hsla",
|
|
34
|
+
"hwb",
|
|
35
|
+
"lab",
|
|
36
|
+
"lch",
|
|
37
|
+
"oklab",
|
|
38
|
+
"oklch",
|
|
39
|
+
"color",
|
|
40
|
+
"device-cmyk",
|
|
41
|
+
"gray",
|
|
42
|
+
...DERIVED_COLOR_FUNCS_LIST
|
|
43
|
+
]);
|
|
44
|
+
const RE_FUNC_CALL = /^([a-z][a-z0-9-]*)\((.+)\)$/i;
|
|
45
|
+
const RE_UNIT_NUM = /^[+-]?(?:\d*\.\d+|\d+)([a-z][a-z0-9]*)$/;
|
|
46
|
+
const RE_NUMBER = /^[+-]?(?:\d*\.\d+|\d+)$/;
|
|
47
|
+
const RE_HEX = /^(?:[0-9a-f]{3,4}|[0-9a-f]{6}(?:[0-9a-f]{2})?)$/;
|
|
48
|
+
const RE_RAW_UNIT = /^([+-]?(?:\d*\.\d+|\d+))([a-z%]+)$/;
|
|
49
|
+
const CANONICAL_FUNC_CASE = new Map([
|
|
50
|
+
["translatex", "translateX"],
|
|
51
|
+
["translatey", "translateY"],
|
|
52
|
+
["translatez", "translateZ"],
|
|
53
|
+
["scalex", "scaleX"],
|
|
54
|
+
["scaley", "scaleY"],
|
|
55
|
+
["scalez", "scaleZ"],
|
|
56
|
+
["rotatex", "rotateX"],
|
|
57
|
+
["rotatey", "rotateY"],
|
|
58
|
+
["rotatez", "rotateZ"],
|
|
59
|
+
["skewx", "skewX"],
|
|
60
|
+
["skewy", "skewY"]
|
|
61
|
+
]);
|
|
62
|
+
function canonicalFuncName(lowered) {
|
|
63
|
+
return CANONICAL_FUNC_CASE.get(lowered) ?? lowered;
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/utils/string.ts
|
|
67
|
+
function toSnakeCase(str) {
|
|
68
|
+
return str.replace(/[A-Z]/g, (s) => `-${s.toLowerCase()}`);
|
|
69
|
+
}
|
|
70
|
+
function normalizeDslName(name) {
|
|
71
|
+
if (!name) return name;
|
|
72
|
+
const first = name[0];
|
|
73
|
+
const lower = first.toLowerCase();
|
|
74
|
+
return lower === first ? name : lower + name.slice(1);
|
|
75
|
+
}
|
|
76
|
+
const RE_DSL_IDENTIFIER = /(\$\$?|##?)([a-zA-Z_][a-zA-Z0-9_-]*)/g;
|
|
77
|
+
function foldDslCase(src) {
|
|
78
|
+
const folded = src.toLowerCase();
|
|
79
|
+
if (folded === src || !src.includes("$") && !src.includes("#")) return folded;
|
|
80
|
+
RE_DSL_IDENTIFIER.lastIndex = 0;
|
|
81
|
+
let out = "";
|
|
82
|
+
let last = 0;
|
|
83
|
+
let match;
|
|
84
|
+
while (match = RE_DSL_IDENTIFIER.exec(src)) {
|
|
85
|
+
const [whole, prefix, body] = match;
|
|
86
|
+
out += src.slice(last, match.index).toLowerCase();
|
|
87
|
+
out += prefix + (prefix[0] === "#" && RE_HEX.test(body.toLowerCase()) ? body.toLowerCase() : normalizeDslName(body));
|
|
88
|
+
last = match.index + whole.length;
|
|
89
|
+
}
|
|
90
|
+
return out + src.slice(last).toLowerCase();
|
|
91
|
+
}
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region src/utils/color-math.ts
|
|
94
|
+
const OKLab_to_LMS_ab = [
|
|
95
|
+
[.3963377773761749, .2158037573099136],
|
|
96
|
+
[-.1055613458156586, -.0638541728258133],
|
|
97
|
+
[-.0894841775298119, -1.2914855480194092]
|
|
98
|
+
];
|
|
99
|
+
const LMS_to_linear_sRGB_M = [
|
|
100
|
+
[
|
|
101
|
+
4.076741636075959,
|
|
102
|
+
-3.307711539258062,
|
|
103
|
+
.2309699031821041
|
|
104
|
+
],
|
|
105
|
+
[
|
|
106
|
+
-1.2684379732850313,
|
|
107
|
+
2.6097573492876878,
|
|
108
|
+
-.3413193760026569
|
|
109
|
+
],
|
|
110
|
+
[
|
|
111
|
+
-.004196076138675526,
|
|
112
|
+
-.703418617935936,
|
|
113
|
+
1.7076146940746113
|
|
114
|
+
]
|
|
115
|
+
];
|
|
116
|
+
const OKLab_to_linear_sRGB_coefficients = [
|
|
117
|
+
[[-1.8817030993265873, -.8093650129914302], [
|
|
118
|
+
1.19086277,
|
|
119
|
+
1.76576728,
|
|
120
|
+
.59662641,
|
|
121
|
+
.75515197,
|
|
122
|
+
.56771245
|
|
123
|
+
]],
|
|
124
|
+
[[1.8144407988010998, -1.194452667805235], [
|
|
125
|
+
.73956515,
|
|
126
|
+
-.45954404,
|
|
127
|
+
.08285427,
|
|
128
|
+
.1254107,
|
|
129
|
+
.14503204
|
|
130
|
+
]],
|
|
131
|
+
[[.13110757611180954, 1.813339709266608], [
|
|
132
|
+
1.35733652,
|
|
133
|
+
-.00915799,
|
|
134
|
+
-1.1513021,
|
|
135
|
+
-.50559606,
|
|
136
|
+
.00692167
|
|
137
|
+
]]
|
|
138
|
+
];
|
|
139
|
+
const dotXY = (vector, x, y) => vector[0] * x + vector[1] * y;
|
|
140
|
+
const dotXYZ = (matrix, x, y, z) => matrix[0] * x + matrix[1] * y + matrix[2] * z;
|
|
141
|
+
const INV_GAMMA = 1 / 2.4;
|
|
142
|
+
function srgbLinearToGamma(val) {
|
|
143
|
+
const sign = val < 0 ? -1 : 1;
|
|
144
|
+
const abs = Math.abs(val);
|
|
145
|
+
return abs > .0031308 ? sign * (1.055 * abs ** INV_GAMMA - .055) : 12.92 * val;
|
|
146
|
+
}
|
|
147
|
+
const TAU = 2 * Math.PI;
|
|
148
|
+
const K1 = .206;
|
|
149
|
+
const K2 = .03;
|
|
150
|
+
const K3 = 1.206 / 1.03;
|
|
151
|
+
const clamp$1 = (value, min, max) => Math.max(Math.min(value, max), min);
|
|
152
|
+
const constrainAngle = (angle) => (angle % 360 + 360) % 360;
|
|
153
|
+
const toe = (x) => .5 * (K3 * x - K1 + Math.sqrt((K3 * x - K1) * (K3 * x - K1) + 4 * K2 * K3 * x));
|
|
154
|
+
const toeInv = (x) => (x ** 2 + K1 * x) / (K3 * (x + K2));
|
|
155
|
+
const OKHST_REF_EPS = .05;
|
|
156
|
+
function yToL(y) {
|
|
157
|
+
return toe(Math.cbrt(Math.max(0, y)));
|
|
158
|
+
}
|
|
159
|
+
function yFromTone(t, eps = OKHST_REF_EPS) {
|
|
160
|
+
const den = Math.log(1 + eps) - Math.log(eps);
|
|
161
|
+
return Math.exp(t / 100 * den + Math.log(eps)) - eps;
|
|
162
|
+
}
|
|
163
|
+
function fromTone(t, eps = OKHST_REF_EPS) {
|
|
164
|
+
return yToL(yFromTone(t, eps));
|
|
165
|
+
}
|
|
166
|
+
const oklabToLinearSrgb = (lab) => {
|
|
167
|
+
const L = lab[0];
|
|
168
|
+
const a = lab[1];
|
|
169
|
+
const b = lab[2];
|
|
170
|
+
const l_ = L + .3963377773761749 * a + .2158037573099136 * b;
|
|
171
|
+
const m_ = L - .1055613458156586 * a - .0638541728258133 * b;
|
|
172
|
+
const s_ = L - .0894841775298119 * a - 1.2914855480194092 * b;
|
|
173
|
+
const l = l_ * l_ * l_;
|
|
174
|
+
const m = m_ * m_ * m_;
|
|
175
|
+
const s = s_ * s_ * s_;
|
|
176
|
+
return [
|
|
177
|
+
4.076741636075959 * l - 3.307711539258062 * m + .2309699031821041 * s,
|
|
178
|
+
-1.2684379732850313 * l + 2.6097573492876878 * m - .3413193760026569 * s,
|
|
179
|
+
-.004196076138675526 * l - .703418617935936 * m + 1.7076146940746113 * s
|
|
180
|
+
];
|
|
181
|
+
};
|
|
182
|
+
const computeMaxSaturationOKLC = (a, b) => {
|
|
183
|
+
const okCoeff = OKLab_to_linear_sRGB_coefficients;
|
|
184
|
+
const lmsToRgb = LMS_to_linear_sRGB_M;
|
|
185
|
+
let chnlCoeff;
|
|
186
|
+
let chnlLMS;
|
|
187
|
+
if (dotXY(okCoeff[0][0], a, b) > 1) {
|
|
188
|
+
chnlCoeff = okCoeff[0][1];
|
|
189
|
+
chnlLMS = lmsToRgb[0];
|
|
190
|
+
} else if (dotXY(okCoeff[1][0], a, b) > 1) {
|
|
191
|
+
chnlCoeff = okCoeff[1][1];
|
|
192
|
+
chnlLMS = lmsToRgb[1];
|
|
193
|
+
} else {
|
|
194
|
+
chnlCoeff = okCoeff[2][1];
|
|
195
|
+
chnlLMS = lmsToRgb[2];
|
|
196
|
+
}
|
|
197
|
+
const [k0, k1, k2, k3, k4] = chnlCoeff;
|
|
198
|
+
const [wl, wm, ws] = chnlLMS;
|
|
199
|
+
let sat = k0 + k1 * a + k2 * b + k3 * (a * a) + k4 * a * b;
|
|
200
|
+
const kl = dotXY(OKLab_to_LMS_ab[0], a, b);
|
|
201
|
+
const km = dotXY(OKLab_to_LMS_ab[1], a, b);
|
|
202
|
+
const ks = dotXY(OKLab_to_LMS_ab[2], a, b);
|
|
203
|
+
const l_ = 1 + sat * kl;
|
|
204
|
+
const m_ = 1 + sat * km;
|
|
205
|
+
const s_ = 1 + sat * ks;
|
|
206
|
+
const l = l_ ** 3;
|
|
207
|
+
const m = m_ ** 3;
|
|
208
|
+
const s = s_ ** 3;
|
|
209
|
+
const lds = 3 * kl * (l_ * l_);
|
|
210
|
+
const mds = 3 * km * (m_ * m_);
|
|
211
|
+
const sds = 3 * ks * (s_ * s_);
|
|
212
|
+
const lds2 = 6 * (kl * kl) * l_;
|
|
213
|
+
const mds2 = 6 * (km * km) * m_;
|
|
214
|
+
const sds2 = 6 * (ks * ks) * s_;
|
|
215
|
+
const f = wl * l + wm * m + ws * s;
|
|
216
|
+
const f1 = wl * lds + wm * mds + ws * sds;
|
|
217
|
+
const f2 = wl * lds2 + wm * mds2 + ws * sds2;
|
|
218
|
+
sat = sat - f * f1 / (f1 * f1 - .5 * f * f2);
|
|
219
|
+
return sat;
|
|
220
|
+
};
|
|
221
|
+
const findCuspOKLCH = (a, b) => {
|
|
222
|
+
const S_cusp = computeMaxSaturationOKLC(a, b);
|
|
223
|
+
const rgb_at_max = oklabToLinearSrgb([
|
|
224
|
+
1,
|
|
225
|
+
S_cusp * a,
|
|
226
|
+
S_cusp * b
|
|
227
|
+
]);
|
|
228
|
+
const L_cusp = Math.cbrt(1 / Math.max(Math.max(rgb_at_max[0], rgb_at_max[1]), Math.max(rgb_at_max[2], 0)));
|
|
229
|
+
return [L_cusp, L_cusp * S_cusp];
|
|
230
|
+
};
|
|
231
|
+
const findGamutIntersectionOKLCH = (a, b, l1, c1, l0, cusp) => {
|
|
232
|
+
const lmsToRgb = LMS_to_linear_sRGB_M;
|
|
233
|
+
let t;
|
|
234
|
+
if ((l1 - l0) * cusp[1] - (cusp[0] - l0) * c1 <= 0) {
|
|
235
|
+
const denom = c1 * cusp[0] + cusp[1] * (l0 - l1);
|
|
236
|
+
t = denom === 0 ? 0 : cusp[1] * l0 / denom;
|
|
237
|
+
} else {
|
|
238
|
+
const denom = c1 * (cusp[0] - 1) + cusp[1] * (l0 - l1);
|
|
239
|
+
t = denom === 0 ? 0 : cusp[1] * (l0 - 1) / denom;
|
|
240
|
+
const dl = l1 - l0;
|
|
241
|
+
const dc = c1;
|
|
242
|
+
const kl = dotXY(OKLab_to_LMS_ab[0], a, b);
|
|
243
|
+
const km = dotXY(OKLab_to_LMS_ab[1], a, b);
|
|
244
|
+
const ks = dotXY(OKLab_to_LMS_ab[2], a, b);
|
|
245
|
+
const ldt_ = dl + dc * kl;
|
|
246
|
+
const mdt_ = dl + dc * km;
|
|
247
|
+
const sdt_ = dl + dc * ks;
|
|
248
|
+
const L = l0 * (1 - t) + t * l1;
|
|
249
|
+
const C = t * c1;
|
|
250
|
+
const l_ = L + C * kl;
|
|
251
|
+
const m_ = L + C * km;
|
|
252
|
+
const s_ = L + C * ks;
|
|
253
|
+
const l = l_ ** 3;
|
|
254
|
+
const m = m_ ** 3;
|
|
255
|
+
const s = s_ ** 3;
|
|
256
|
+
const ldt = 3 * ldt_ * l_ * l_;
|
|
257
|
+
const mdt = 3 * mdt_ * m_ * m_;
|
|
258
|
+
const sdt = 3 * sdt_ * s_ * s_;
|
|
259
|
+
const ldt2 = 6 * ldt_ * ldt_ * l_;
|
|
260
|
+
const mdt2 = 6 * mdt_ * mdt_ * m_;
|
|
261
|
+
const sdt2 = 6 * sdt_ * sdt_ * s_;
|
|
262
|
+
let correction = Number.MAX_VALUE;
|
|
263
|
+
for (const matrix of lmsToRgb) {
|
|
264
|
+
const value = dotXYZ(matrix, l, m, s) - 1;
|
|
265
|
+
const slope = dotXYZ(matrix, ldt, mdt, sdt);
|
|
266
|
+
const slope2 = dotXYZ(matrix, ldt2, mdt2, sdt2);
|
|
267
|
+
const u = slope / (slope * slope - .5 * value * slope2);
|
|
268
|
+
if (u >= 0) correction = Math.min(correction, -value * u);
|
|
269
|
+
}
|
|
270
|
+
t += correction;
|
|
271
|
+
}
|
|
272
|
+
return t;
|
|
273
|
+
};
|
|
274
|
+
const computeSt = (cusp) => [cusp[1] / cusp[0], cusp[1] / (1 - cusp[0])];
|
|
275
|
+
const computeStMid = (a, b) => [.11516993 + 1 / (7.4477897 + 4.1590124 * b + a * (-2.19557347 + 1.75198401 * b + a * (-2.13704948 - 10.02301043 * b + a * (-4.24894561 + 5.38770819 * b + 4.69891013 * a)))), .11239642 + 1 / (1.6132032 - .68124379 * b + a * (.40370612 + .90148123 * b + a * (-.27087943 + .6122399 * b + a * (.00299215 - .45399568 * b - .14661872 * a))))];
|
|
276
|
+
const getCs = (L, a, b, cusp) => {
|
|
277
|
+
const cMax = findGamutIntersectionOKLCH(a, b, L, 1, L, cusp);
|
|
278
|
+
const stMax = computeSt(cusp);
|
|
279
|
+
const k = cMax / Math.min(L * stMax[0], (1 - L) * stMax[1]);
|
|
280
|
+
const stMid = computeStMid(a, b);
|
|
281
|
+
let ca = L * stMid[0];
|
|
282
|
+
let cb = (1 - L) * stMid[1];
|
|
283
|
+
const cMid = .9 * k * Math.sqrt(Math.sqrt(1 / (1 / ca ** 4 + 1 / cb ** 4)));
|
|
284
|
+
ca = L * .4;
|
|
285
|
+
cb = (1 - L) * .8;
|
|
286
|
+
return [
|
|
287
|
+
Math.sqrt(1 / (1 / ca ** 2 + 1 / cb ** 2)),
|
|
288
|
+
cMid,
|
|
289
|
+
cMax
|
|
290
|
+
];
|
|
291
|
+
};
|
|
292
|
+
const okhslToOklab = (hsl) => {
|
|
293
|
+
let h = hsl[0];
|
|
294
|
+
const s = hsl[1];
|
|
295
|
+
const l = hsl[2];
|
|
296
|
+
const L = toeInv(l);
|
|
297
|
+
let a = 0;
|
|
298
|
+
let b = 0;
|
|
299
|
+
h = constrainAngle(h) / 360;
|
|
300
|
+
if (L !== 0 && L !== 1 && s !== 0) {
|
|
301
|
+
const a_ = Math.cos(TAU * h);
|
|
302
|
+
const b_ = Math.sin(TAU * h);
|
|
303
|
+
const [c0, cMid, cMax] = getCs(L, a_, b_, findCuspOKLCH(a_, b_));
|
|
304
|
+
const mid = .8;
|
|
305
|
+
const midInv = 1.25;
|
|
306
|
+
let t, k0, k1, k2;
|
|
307
|
+
if (s < mid) {
|
|
308
|
+
t = midInv * s;
|
|
309
|
+
k0 = 0;
|
|
310
|
+
k1 = mid * c0;
|
|
311
|
+
k2 = 1 - k1 / cMid;
|
|
312
|
+
} else {
|
|
313
|
+
t = 5 * (s - .8);
|
|
314
|
+
k0 = cMid;
|
|
315
|
+
k1 = .2 * cMid ** 2 * 1.25 ** 2 / c0;
|
|
316
|
+
k2 = 1 - k1 / (cMax - cMid);
|
|
317
|
+
}
|
|
318
|
+
const c = k0 + t * k1 / (1 - k2 * t);
|
|
319
|
+
a = c * a_;
|
|
320
|
+
b = c * b_;
|
|
321
|
+
}
|
|
322
|
+
return [
|
|
323
|
+
L,
|
|
324
|
+
a,
|
|
325
|
+
b
|
|
326
|
+
];
|
|
327
|
+
};
|
|
328
|
+
function hslToRgbValues(h, s, l) {
|
|
329
|
+
const a = s * Math.min(l, 1 - l);
|
|
330
|
+
const f = (n) => {
|
|
331
|
+
const k = (n + h / 30) % 12;
|
|
332
|
+
return l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1));
|
|
333
|
+
};
|
|
334
|
+
return [
|
|
335
|
+
f(0) * 255,
|
|
336
|
+
f(8) * 255,
|
|
337
|
+
f(4) * 255
|
|
338
|
+
];
|
|
339
|
+
}
|
|
340
|
+
function okhslToSrgb(h, s, l) {
|
|
341
|
+
const linearRGB = oklabToLinearSrgb(okhslToOklab([
|
|
342
|
+
h,
|
|
343
|
+
s,
|
|
344
|
+
l
|
|
345
|
+
]));
|
|
346
|
+
return [
|
|
347
|
+
clamp$1(srgbLinearToGamma(linearRGB[0]), 0, 1),
|
|
348
|
+
clamp$1(srgbLinearToGamma(linearRGB[1]), 0, 1),
|
|
349
|
+
clamp$1(srgbLinearToGamma(linearRGB[2]), 0, 1)
|
|
350
|
+
];
|
|
351
|
+
}
|
|
352
|
+
function okhstToSrgb(h, s, t) {
|
|
353
|
+
return okhslToSrgb(h, clamp$1(s, 0, 1), clamp$1(fromTone(t * 100), 0, 1));
|
|
354
|
+
}
|
|
355
|
+
function oklchToRgbValues(L, C, H) {
|
|
356
|
+
const hRad = H * Math.PI / 180;
|
|
357
|
+
const linear = oklabToLinearSrgb([
|
|
358
|
+
L,
|
|
359
|
+
C * Math.cos(hRad),
|
|
360
|
+
C * Math.sin(hRad)
|
|
361
|
+
]);
|
|
362
|
+
return [
|
|
363
|
+
clamp$1(srgbLinearToGamma(linear[0]), 0, 1) * 255,
|
|
364
|
+
clamp$1(srgbLinearToGamma(linear[1]), 0, 1) * 255,
|
|
365
|
+
clamp$1(srgbLinearToGamma(linear[2]), 0, 1) * 255
|
|
366
|
+
];
|
|
367
|
+
}
|
|
368
|
+
let _namedColorHex = null;
|
|
369
|
+
function getNamedColorHex() {
|
|
370
|
+
if (_namedColorHex) return _namedColorHex;
|
|
371
|
+
const names = "aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgreen darkgrey darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray darkslategrey darkturquoise darkviolet deeppink deepskyblue dimgray dimgrey dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray green greenyellow grey honeydew hotpink indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan lightgoldenrodyellow lightgray lightgreen lightgrey lightpink lightsalmon lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple rebeccapurple red rosybrown royalblue saddlebrown salmon sandybrown seagreen seashell sienna silver skyblue slateblue slategray slategrey snow springgreen steelblue tan teal thistle tomato turquoise violet wheat white whitesmoke yellow yellowgreen".split(" ");
|
|
372
|
+
const hex = "f0f8fffaebd700ffff7fffd4f0fffff5f5dcffe4c4000000ffebcd0000ff8a2be2a52a2adeb8875f9ea07fff00d2691eff7f506495edfff8dcdc143c00ffff00008b008b8bb8860ba9a9a9006400a9a9a9bdb76b8b008b556b2fff8c009932cc8b0000e9967a8fbc8f483d8b2f4f4f2f4f4f00ced19400d3ff149300bfff6969696969691e90ffb22222fffaf0228b22ff00ffdcdcdcf8f8ffffd700daa520808080008000adff2f808080f0fff0ff69b4cd5c5c4b0082fffff0f0e68ce6e6fafff0f57cfc00fffacdadd8e6f08080e0fffffafad2d3d3d390ee90d3d3d3ffb6c1ffa07a20b2aa87cefa778899778899b0c4deffffe000ff0032cd32faf0e6ff00ff80000066cdaa0000cdba55d39370db3cb3717b68ee00fa9a48d1ccc71585191970f5fffaffe4e1ffe4b5ffdead000080fdf5e68080006b8e23ffa500ff4500da70d6eee8aa98fb98afeeeedb7093ffefd5ffdab9cd853fffc0cbdda0ddb0e0e6800080663399ff0000bc8f8f4169e18b4513fa8072f4a4602e8b57fff5eea0522dc0c0c087ceeb6a5acd708090708090fffafa00ff7f4682b4d2b48c008080d8bfd8ff634740e0d0ee82eef5deb3fffffff5f5f5ffff009acd32";
|
|
373
|
+
const colors = /* @__PURE__ */ new Map();
|
|
374
|
+
for (let i = 0; i < names.length; i++) colors.set(names[i], `#${hex.slice(i * 6, i * 6 + 6)}`);
|
|
375
|
+
return _namedColorHex = colors;
|
|
376
|
+
}
|
|
377
|
+
function hexToRgb(hex) {
|
|
378
|
+
const matched = hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, (_m, r, g, b) => "#" + r + r + g + g + b + b).substring(1).match(/.{2}/g);
|
|
379
|
+
if (!matched) return null;
|
|
380
|
+
const rgba = matched.map((x, i) => parseInt(x, 16) * (i === 3 ? 1 / 255 : 1));
|
|
381
|
+
if (rgba.some((v) => Number.isNaN(v))) return null;
|
|
382
|
+
if (rgba.length >= 3) return `rgb(${rgba.slice(0, 3).join(" ")}${rgba.length > 3 ? ` / ${rgba[3]}` : ""})`;
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
function getRgbValuesFromRgbaString(str) {
|
|
386
|
+
const match = str.match(/rgba?\(([^)]+)\)/i);
|
|
387
|
+
if (!match) return [];
|
|
388
|
+
const [colorPart] = match[1].trim().split("/");
|
|
389
|
+
return colorPart.trim().split(/[,\s]+/).filter(Boolean).slice(0, 3).map((part) => {
|
|
390
|
+
part = part.trim();
|
|
391
|
+
if (part.endsWith("%")) return parseFloat(part) / 100 * 255;
|
|
392
|
+
return parseFloat(part);
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
function strToRgb(color, _ignoreAlpha = false) {
|
|
396
|
+
if (!color) return void 0;
|
|
397
|
+
if (color.startsWith("rgb")) return color;
|
|
398
|
+
if (color.startsWith("#")) return hexToRgb(color);
|
|
399
|
+
if (color.startsWith("oklch(")) return oklchStringToRgb(color);
|
|
400
|
+
if (color.startsWith("hsl")) return hslStringToRgb(color);
|
|
401
|
+
const namedHex = getNamedColorHex().get(color.toLowerCase());
|
|
402
|
+
if (namedHex) return hexToRgb(namedHex);
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
function hslStringToRgb(hslStr) {
|
|
406
|
+
const match = hslStr.match(/hsla?\(([^)]+)\)/i);
|
|
407
|
+
if (!match) return null;
|
|
408
|
+
const [colorPart, slashAlpha] = match[1].trim().split("/");
|
|
409
|
+
const parts = colorPart.trim().split(/[,\s]+/).filter(Boolean);
|
|
410
|
+
if (parts.length < 3) return null;
|
|
411
|
+
const alphaPart = slashAlpha?.trim() || (parts.length >= 4 ? parts[3] : null);
|
|
412
|
+
let h = parseFloat(parts[0]);
|
|
413
|
+
const hueStr = parts[0].toLowerCase();
|
|
414
|
+
if (hueStr.endsWith("turn")) h = parseFloat(hueStr) * 360;
|
|
415
|
+
else if (hueStr.endsWith("rad")) h = parseFloat(hueStr) * 180 / Math.PI;
|
|
416
|
+
h = (h % 360 + 360) % 360;
|
|
417
|
+
const parsePercent = (val) => {
|
|
418
|
+
const num = parseFloat(val);
|
|
419
|
+
return val.includes("%") ? num / 100 : num;
|
|
420
|
+
};
|
|
421
|
+
const s = Math.max(0, Math.min(1, parsePercent(parts[1])));
|
|
422
|
+
const l = Math.max(0, Math.min(1, parsePercent(parts[2])));
|
|
423
|
+
const [r, g, b] = hslToRgbValues(h, s, l);
|
|
424
|
+
if (alphaPart) {
|
|
425
|
+
const alpha = parseFloat(alphaPart.trim());
|
|
426
|
+
return `rgba(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)}, ${alpha})`;
|
|
427
|
+
}
|
|
428
|
+
return `rgb(${Math.round(r)} ${Math.round(g)} ${Math.round(b)})`;
|
|
429
|
+
}
|
|
430
|
+
function oklchStringToRgb(oklchStr) {
|
|
431
|
+
const match = oklchStr.match(/oklch\(([^)]+)\)/i);
|
|
432
|
+
if (!match) return null;
|
|
433
|
+
const [colorPart, alphaPart] = match[1].trim().split("/");
|
|
434
|
+
const parts = colorPart.trim().split(/[,\s]+/).filter(Boolean);
|
|
435
|
+
if (parts.length < 3) return null;
|
|
436
|
+
const parsePercent = (val) => {
|
|
437
|
+
const num = parseFloat(val);
|
|
438
|
+
return val.includes("%") ? num / 100 : num;
|
|
439
|
+
};
|
|
440
|
+
const L = Math.max(0, Math.min(1, parsePercent(parts[0])));
|
|
441
|
+
const C = Math.max(0, parseFloat(parts[1]));
|
|
442
|
+
let H = parseFloat(parts[2]);
|
|
443
|
+
const hueStr = parts[2].toLowerCase();
|
|
444
|
+
if (hueStr.endsWith("turn")) H = parseFloat(hueStr) * 360;
|
|
445
|
+
else if (hueStr.endsWith("rad")) H = parseFloat(hueStr) * 180 / Math.PI;
|
|
446
|
+
else if (hueStr.endsWith("deg")) H = parseFloat(hueStr);
|
|
447
|
+
const [r, g, b] = oklchToRgbValues(L, C, H);
|
|
448
|
+
if (alphaPart) {
|
|
449
|
+
const alpha = parseFloat(alphaPart.trim());
|
|
450
|
+
return `rgba(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)}, ${alpha})`;
|
|
451
|
+
}
|
|
452
|
+
return `rgb(${Math.round(r)} ${Math.round(g)} ${Math.round(b)})`;
|
|
453
|
+
}
|
|
454
|
+
//#endregion
|
|
455
|
+
//#region src/utils/color-space.ts
|
|
456
|
+
function overrideColorAlpha(color, alpha) {
|
|
457
|
+
return `oklch(from ${color} l c h / ${alpha})`;
|
|
458
|
+
}
|
|
459
|
+
function mixColorAlpha(color, percentage) {
|
|
460
|
+
return `color-mix(in oklab, ${color} ${percentage}, transparent)`;
|
|
461
|
+
}
|
|
462
|
+
const RE_ALPHA_OVERRIDE = /^oklch\(from (.+) l c h \/ (.+)\)$/;
|
|
463
|
+
function parseAlphaOverride(value) {
|
|
464
|
+
const match = value.match(RE_ALPHA_OVERRIDE);
|
|
465
|
+
return match ? {
|
|
466
|
+
color: match[1],
|
|
467
|
+
alpha: match[2]
|
|
468
|
+
} : null;
|
|
469
|
+
}
|
|
470
|
+
//#endregion
|
|
471
|
+
//#region src/parser/types.ts
|
|
472
|
+
const makeEmptyPart = () => ({
|
|
473
|
+
mods: [],
|
|
474
|
+
values: [],
|
|
475
|
+
colors: [],
|
|
476
|
+
all: [],
|
|
477
|
+
output: ""
|
|
478
|
+
});
|
|
479
|
+
const makeEmptyDetails = () => ({
|
|
480
|
+
input: "",
|
|
481
|
+
output: "",
|
|
482
|
+
mods: [],
|
|
483
|
+
values: [],
|
|
484
|
+
colors: [],
|
|
485
|
+
all: [],
|
|
486
|
+
parts: []
|
|
487
|
+
});
|
|
488
|
+
//#endregion
|
|
489
|
+
//#region src/parser/classify.ts
|
|
490
|
+
function alphaSuffixToAlpha(rawAlpha) {
|
|
491
|
+
if (rawAlpha.startsWith("$")) return `var(--${rawAlpha.slice(1)})`;
|
|
492
|
+
if (rawAlpha === "0") return "0";
|
|
493
|
+
return `.${rawAlpha}`;
|
|
494
|
+
}
|
|
495
|
+
function fadeColor(color, rawAlpha) {
|
|
496
|
+
return overrideColorAlpha(color, alphaSuffixToAlpha(rawAlpha));
|
|
497
|
+
}
|
|
498
|
+
function alphaSuffixToPercentage(rawAlpha) {
|
|
499
|
+
if (rawAlpha.startsWith("$")) return `calc(var(--${rawAlpha.slice(1)}) * 100%)`;
|
|
500
|
+
if (rawAlpha === "0") return "0%";
|
|
501
|
+
const digits = rawAlpha.length === 1 ? `${rawAlpha}0` : rawAlpha;
|
|
502
|
+
const whole = String(Number(digits.slice(0, 2)));
|
|
503
|
+
const fraction = digits.slice(2);
|
|
504
|
+
return `${fraction ? `${whole}.${fraction}` : whole}%`;
|
|
505
|
+
}
|
|
506
|
+
function fadeCurrentColor(rawAlpha) {
|
|
507
|
+
return mixColorAlpha("currentcolor", alphaSuffixToPercentage(rawAlpha));
|
|
508
|
+
}
|
|
509
|
+
function hasColorArgs(parsed) {
|
|
510
|
+
const namedColors = getNamedColorHex();
|
|
511
|
+
return parsed.groups.some((group) => group.colors.length > 0 || group.mods.some((mod) => namedColors.has(mod)));
|
|
512
|
+
}
|
|
513
|
+
function resolveUntilStable(value, opts, recurse, maxIterations = 10) {
|
|
514
|
+
let current = value;
|
|
515
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
516
|
+
const unitMatch = current.match(RE_UNIT_NUM);
|
|
517
|
+
if (!unitMatch) break;
|
|
518
|
+
const unitName = unitMatch[1];
|
|
519
|
+
if (!opts.units || !(unitName in opts.units)) break;
|
|
520
|
+
const result = recurse(current);
|
|
521
|
+
if (result.output === current) break;
|
|
522
|
+
current = result.output;
|
|
523
|
+
}
|
|
524
|
+
return current;
|
|
525
|
+
}
|
|
526
|
+
function classify(raw, opts, recurse) {
|
|
527
|
+
const token = raw.trim();
|
|
528
|
+
if (!token) return {
|
|
529
|
+
bucket: 2,
|
|
530
|
+
processed: ""
|
|
531
|
+
};
|
|
532
|
+
if (token.includes("(")) {
|
|
533
|
+
let depth = 0;
|
|
534
|
+
let inQuote = 0;
|
|
535
|
+
for (let i = 0; i < token.length; i++) {
|
|
536
|
+
const ch = token[i];
|
|
537
|
+
if (inQuote) {
|
|
538
|
+
if (ch === inQuote && token[i - 1] !== "\\") inQuote = 0;
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
if (ch === "\"" || ch === "'") {
|
|
542
|
+
inQuote = ch;
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
if (ch === "(") depth++;
|
|
546
|
+
else if (ch === ")" && depth) depth--;
|
|
547
|
+
}
|
|
548
|
+
if (depth !== 0) {
|
|
549
|
+
console.warn("[Tasty] skipped invalid function token with unmatched parentheses:", token);
|
|
550
|
+
return {
|
|
551
|
+
bucket: 2,
|
|
552
|
+
processed: ""
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
if (token.startsWith("\"") && token.endsWith("\"") || token.startsWith("'") && token.endsWith("'")) return {
|
|
557
|
+
bucket: 1,
|
|
558
|
+
processed: token
|
|
559
|
+
};
|
|
560
|
+
if (token.startsWith("$$")) {
|
|
561
|
+
const rest = token.slice(2);
|
|
562
|
+
const openIdx = rest.indexOf("(");
|
|
563
|
+
if (openIdx > 0 && rest.endsWith(")")) {
|
|
564
|
+
const fname = rest.slice(0, openIdx);
|
|
565
|
+
if (/^[a-z_][a-z0-9-_]*$/i.test(fname)) {
|
|
566
|
+
const inner = rest.slice(openIdx + 1, -1).trim();
|
|
567
|
+
const cssName = `--${fname}`;
|
|
568
|
+
if (opts.functions && cssName in opts.functions) {
|
|
569
|
+
const groups = inner ? new StyleParser(opts).process(inner).groups : [];
|
|
570
|
+
const funcResult = opts.functions[cssName](groups);
|
|
571
|
+
if (funcResult !== "") return classify(funcResult, {
|
|
572
|
+
...opts,
|
|
573
|
+
functions: void 0
|
|
574
|
+
}, recurse);
|
|
575
|
+
}
|
|
576
|
+
return {
|
|
577
|
+
bucket: 1,
|
|
578
|
+
processed: `--${fname}(${inner ? recurse(inner).output : ""})`
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
if (/^[a-z_][a-z0-9-_]*$/i.test(rest)) return {
|
|
583
|
+
bucket: 1,
|
|
584
|
+
processed: `--${rest}`
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
if (token.startsWith("##")) {
|
|
588
|
+
const rest = token.slice(2);
|
|
589
|
+
const openIdx = rest.indexOf("(");
|
|
590
|
+
if (openIdx > 0 && rest.endsWith(")")) {
|
|
591
|
+
const fname = rest.slice(0, openIdx);
|
|
592
|
+
if (/^[a-z_][a-z0-9-_]*$/i.test(fname)) {
|
|
593
|
+
const inner = rest.slice(openIdx + 1, -1).trim();
|
|
594
|
+
return {
|
|
595
|
+
bucket: 1,
|
|
596
|
+
processed: `--${fname}-color(${inner ? recurse(inner).output : ""})`
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
if (/^[a-z_][a-z0-9-_]*$/i.test(rest)) return {
|
|
601
|
+
bucket: 1,
|
|
602
|
+
processed: `--${rest}-color`
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
if (token === "#current") return {
|
|
606
|
+
bucket: 0,
|
|
607
|
+
processed: "currentcolor"
|
|
608
|
+
};
|
|
609
|
+
const currentAlphaMatch = token.match(/^#current\.(\$[a-z_][a-z0-9-_]*|[0-9]+)$/i);
|
|
610
|
+
if (currentAlphaMatch) return {
|
|
611
|
+
bucket: 0,
|
|
612
|
+
processed: fadeCurrentColor(currentAlphaMatch[1])
|
|
613
|
+
};
|
|
614
|
+
if (token[0] === "$" || token[0] === "#") {
|
|
615
|
+
const predefinedTokens = getGlobalPredefinedTokens();
|
|
616
|
+
if (predefinedTokens) {
|
|
617
|
+
const lookupKey = token.toLowerCase();
|
|
618
|
+
if (lookupKey in predefinedTokens) {
|
|
619
|
+
const tokenValue = predefinedTokens[lookupKey];
|
|
620
|
+
return classify(foldDslCase(tokenValue), opts, recurse);
|
|
621
|
+
}
|
|
622
|
+
if (token[0] === "#") {
|
|
623
|
+
const alphaMatch = token.match(/^(#[a-z0-9-]+)\.(\$[a-z_][a-z0-9-_]*|[0-9]+)$/i);
|
|
624
|
+
if (alphaMatch) {
|
|
625
|
+
const [, baseToken, rawAlpha] = alphaMatch;
|
|
626
|
+
const baseKey = baseToken.toLowerCase();
|
|
627
|
+
if (baseKey in predefinedTokens) {
|
|
628
|
+
const resolvedValue = predefinedTokens[baseKey];
|
|
629
|
+
if (resolvedValue.startsWith("#")) return classify(`${foldDslCase(resolvedValue)}.${rawAlpha}`, opts, recurse);
|
|
630
|
+
const funcMatch = resolvedValue.match(RE_FUNC_CALL);
|
|
631
|
+
if (funcMatch) {
|
|
632
|
+
const [, funcName, args] = funcMatch;
|
|
633
|
+
const lowerFunc = funcName.toLowerCase();
|
|
634
|
+
if (DERIVED_COLOR_FUNCS.has(lowerFunc)) return {
|
|
635
|
+
bucket: 0,
|
|
636
|
+
processed: fadeColor(classify(foldDslCase(resolvedValue), opts, recurse).processed, rawAlpha)
|
|
637
|
+
};
|
|
638
|
+
const isCustomFunc = !!(opts.functions && lowerFunc in opts.functions && !COLOR_FUNCS.has(lowerFunc) && !COLOR_FUNCS.has(funcName.replace(/a$/i, "").toLowerCase()));
|
|
639
|
+
const normalizedFunc = isCustomFunc ? lowerFunc : funcName.replace(/a$/i, "").toLowerCase();
|
|
640
|
+
if (!(COLOR_FUNCS.has(normalizedFunc) || COLOR_FUNCS.has(lowerFunc) || isCustomFunc)) return classify(`${resolvedValue}.${rawAlpha}`, opts, recurse);
|
|
641
|
+
let alpha;
|
|
642
|
+
if (rawAlpha.startsWith("$")) alpha = `var(--${rawAlpha.slice(1)})`;
|
|
643
|
+
else alpha = rawAlpha === "0" ? "0" : `.${rawAlpha}`;
|
|
644
|
+
const normalizeArgs = (a) => {
|
|
645
|
+
let result = "";
|
|
646
|
+
let depth = 0;
|
|
647
|
+
for (let i = 0; i < a.length; i++) {
|
|
648
|
+
const c = a[i];
|
|
649
|
+
if (c === "(") {
|
|
650
|
+
depth++;
|
|
651
|
+
result += c;
|
|
652
|
+
} else if (c === ")") {
|
|
653
|
+
depth = Math.max(0, depth - 1);
|
|
654
|
+
result += c;
|
|
655
|
+
} else if (c === "," && depth === 0) {
|
|
656
|
+
while (i + 1 < a.length && /\s/.test(a[i + 1])) i++;
|
|
657
|
+
result += " ";
|
|
658
|
+
} else result += c;
|
|
659
|
+
}
|
|
660
|
+
return result;
|
|
661
|
+
};
|
|
662
|
+
const findLastTopLevel = (str, ch) => {
|
|
663
|
+
let depth = 0;
|
|
664
|
+
for (let i = str.length - 1; i >= 0; i--) {
|
|
665
|
+
const c = str[i];
|
|
666
|
+
if (c === ")") depth++;
|
|
667
|
+
else if (c === "(") depth = Math.max(0, depth - 1);
|
|
668
|
+
else if (c === ch && depth === 0) return i;
|
|
669
|
+
}
|
|
670
|
+
return -1;
|
|
671
|
+
};
|
|
672
|
+
const slashIdx = findLastTopLevel(args, "/");
|
|
673
|
+
const hasModernAlpha = slashIdx !== -1;
|
|
674
|
+
let topLevelCommaCount = 0;
|
|
675
|
+
let lastTopLevelComma = -1;
|
|
676
|
+
{
|
|
677
|
+
let depth = 0;
|
|
678
|
+
for (let i = 0; i < args.length; i++) {
|
|
679
|
+
const c = args[i];
|
|
680
|
+
if (c === "(") depth++;
|
|
681
|
+
else if (c === ")") depth = Math.max(0, depth - 1);
|
|
682
|
+
else if (c === "," && depth === 0) {
|
|
683
|
+
topLevelCommaCount++;
|
|
684
|
+
lastTopLevelComma = i;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
const hasLegacyAlpha = !hasModernAlpha && /a$/i.test(funcName) && topLevelCommaCount === 3;
|
|
689
|
+
const constructed = `${normalizedFunc}(${hasModernAlpha || hasLegacyAlpha ? normalizeArgs(hasModernAlpha ? args.slice(0, slashIdx).trim() : args.slice(0, lastTopLevelComma).trim()) : normalizeArgs(args)} / ${alpha})`;
|
|
690
|
+
if (!COLOR_FUNCS.has(normalizedFunc) && opts.functions && normalizedFunc in opts.functions) return classify(constructed, opts, recurse);
|
|
691
|
+
return {
|
|
692
|
+
bucket: 0,
|
|
693
|
+
processed: constructed
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
return classify(`${resolvedValue}.${rawAlpha}`, opts, recurse);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
if (token.match(/^var\(--([a-zA-Z0-9-]+)-color\)$/)) return {
|
|
703
|
+
bucket: 0,
|
|
704
|
+
processed: token
|
|
705
|
+
};
|
|
706
|
+
if (token.startsWith("url(")) return {
|
|
707
|
+
bucket: 1,
|
|
708
|
+
processed: token
|
|
709
|
+
};
|
|
710
|
+
if (token[0] === "$") {
|
|
711
|
+
const identMatch = token.match(/^\$([a-z_][a-zA-Z0-9-_]*)$/);
|
|
712
|
+
if (identMatch) {
|
|
713
|
+
const name = identMatch[1];
|
|
714
|
+
const processed = `var(--${name})`;
|
|
715
|
+
return {
|
|
716
|
+
bucket: name.endsWith("-color") ? 3 : 1,
|
|
717
|
+
processed
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
if (token[0] === "#" && token.length > 1) {
|
|
722
|
+
const alphaMatch = token.match(/^#([a-z0-9-]+)\.(\$[a-z_][a-z0-9-_]*|[0-9]+)$/i);
|
|
723
|
+
if (alphaMatch) {
|
|
724
|
+
const [, base, rawAlpha] = alphaMatch;
|
|
725
|
+
return {
|
|
726
|
+
bucket: 0,
|
|
727
|
+
processed: fadeColor(`var(--${base}-color)`, rawAlpha)
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
const name = token.slice(1);
|
|
731
|
+
if (RE_HEX.test(name)) return {
|
|
732
|
+
bucket: 0,
|
|
733
|
+
processed: `var(--${name}-color, #${name})`
|
|
734
|
+
};
|
|
735
|
+
return {
|
|
736
|
+
bucket: 0,
|
|
737
|
+
processed: `var(--${name}-color)`
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
const openIdx = token.indexOf("(");
|
|
741
|
+
if (openIdx > 0 && token.endsWith(")")) {
|
|
742
|
+
const fname = token.slice(0, openIdx);
|
|
743
|
+
const inner = token.slice(openIdx + 1, -1);
|
|
744
|
+
if (COLOR_FUNCS.has(fname)) {
|
|
745
|
+
const parsedInner = recurse(inner);
|
|
746
|
+
const argProcessed = parsedInner.output.replace(/,\s+/g, ",");
|
|
747
|
+
const processed = `${canonicalFuncName(fname)}(${argProcessed})`;
|
|
748
|
+
return {
|
|
749
|
+
bucket: fname === "light-dark" && !hasColorArgs(parsedInner) ? 1 : 0,
|
|
750
|
+
processed
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
if (opts.functions && fname in opts.functions) {
|
|
754
|
+
const tmp = new StyleParser(opts).process(inner);
|
|
755
|
+
return classify(opts.functions[fname](tmp.groups), {
|
|
756
|
+
...opts,
|
|
757
|
+
functions: void 0
|
|
758
|
+
}, recurse);
|
|
759
|
+
}
|
|
760
|
+
const argProcessed = recurse(inner).output;
|
|
761
|
+
return {
|
|
762
|
+
bucket: 1,
|
|
763
|
+
processed: `${canonicalFuncName(fname)}(${argProcessed})`
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
if (token.startsWith("(") && token.endsWith(")")) {
|
|
767
|
+
const colorMatch = token.slice(1, -1).match(/^#([a-z0-9-]+)\s*,\s*(.*)$/i);
|
|
768
|
+
if (colorMatch) {
|
|
769
|
+
const [, name, fallback] = colorMatch;
|
|
770
|
+
return {
|
|
771
|
+
bucket: 0,
|
|
772
|
+
processed: `var(--${name}-color, ${recurse(fallback).output})`
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
if (token.startsWith("(") && token.endsWith(")")) {
|
|
777
|
+
const match = token.slice(1, -1).match(/^\$([a-z_][a-zA-Z0-9-_]*)\s*,\s*(.*)$/);
|
|
778
|
+
if (match) {
|
|
779
|
+
const [, name, fallback] = match;
|
|
780
|
+
const processedFallback = recurse(fallback).output;
|
|
781
|
+
return {
|
|
782
|
+
bucket: name.endsWith("-color") ? 3 : 1,
|
|
783
|
+
processed: `var(--${name}, ${processedFallback})`
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
if (token[0] === "(" && token[token.length - 1] === ")") return {
|
|
788
|
+
bucket: 1,
|
|
789
|
+
processed: `calc(${recurse(token.slice(1, -1)).output})`
|
|
790
|
+
};
|
|
791
|
+
const um = token.match(RE_UNIT_NUM);
|
|
792
|
+
if (um) {
|
|
793
|
+
const unit = um[1];
|
|
794
|
+
const numericPart = parseFloat(token.slice(0, -unit.length));
|
|
795
|
+
const handler = opts.units && opts.units[unit];
|
|
796
|
+
if (handler) if (typeof handler === "string") {
|
|
797
|
+
const rawMatch = handler.match(RE_RAW_UNIT);
|
|
798
|
+
if (rawMatch) {
|
|
799
|
+
const [, baseNum, cssUnit] = rawMatch;
|
|
800
|
+
return {
|
|
801
|
+
bucket: 1,
|
|
802
|
+
processed: resolveUntilStable(`${numericPart * parseFloat(baseNum)}${cssUnit}`, opts, recurse)
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
const base = handler;
|
|
806
|
+
if (numericPart === 1) return {
|
|
807
|
+
bucket: 1,
|
|
808
|
+
processed: base
|
|
809
|
+
};
|
|
810
|
+
return {
|
|
811
|
+
bucket: 1,
|
|
812
|
+
processed: `calc(${numericPart} * ${base})`
|
|
813
|
+
};
|
|
814
|
+
} else return {
|
|
815
|
+
bucket: 1,
|
|
816
|
+
processed: handler(numericPart)
|
|
817
|
+
};
|
|
818
|
+
}
|
|
819
|
+
if (/^[+-]?(?:\d*\.\d+|\d+)[a-z%]+$/.test(token)) return {
|
|
820
|
+
bucket: 1,
|
|
821
|
+
processed: token
|
|
822
|
+
};
|
|
823
|
+
if (RE_NUMBER.test(token)) return {
|
|
824
|
+
bucket: 1,
|
|
825
|
+
processed: token
|
|
826
|
+
};
|
|
827
|
+
if (VALUE_KEYWORDS.has(token)) return {
|
|
828
|
+
bucket: 1,
|
|
829
|
+
processed: token
|
|
830
|
+
};
|
|
831
|
+
if (token === "transparent" || token === "currentcolor") return {
|
|
832
|
+
bucket: 0,
|
|
833
|
+
processed: token
|
|
834
|
+
};
|
|
835
|
+
return {
|
|
836
|
+
bucket: 2,
|
|
837
|
+
processed: token
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
//#endregion
|
|
841
|
+
//#region src/parser/lru.ts
|
|
842
|
+
var Lru = class {
|
|
843
|
+
limit;
|
|
844
|
+
map = /* @__PURE__ */ new Map();
|
|
845
|
+
head = null;
|
|
846
|
+
tail = null;
|
|
847
|
+
onEvict;
|
|
848
|
+
constructor(limit = 1e3, onEvict) {
|
|
849
|
+
this.limit = limit;
|
|
850
|
+
let normalized = Number.isFinite(this.limit) ? Math.floor(this.limit) : 1e3;
|
|
851
|
+
if (normalized <= 0) normalized = 1e3;
|
|
852
|
+
this.limit = normalized;
|
|
853
|
+
this.onEvict = onEvict;
|
|
854
|
+
}
|
|
855
|
+
setOnEvict(fn) {
|
|
856
|
+
this.onEvict = fn;
|
|
857
|
+
}
|
|
858
|
+
get(key) {
|
|
859
|
+
const node = this.map.get(key);
|
|
860
|
+
if (node === void 0) return void 0;
|
|
861
|
+
if (this.head !== node) this.moveToHead(node);
|
|
862
|
+
return node.value;
|
|
863
|
+
}
|
|
864
|
+
set(key, value) {
|
|
865
|
+
const existing = this.map.get(key);
|
|
866
|
+
if (existing !== void 0) {
|
|
867
|
+
existing.value = value;
|
|
868
|
+
if (this.head !== existing) this.moveToHead(existing);
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
const node = {
|
|
872
|
+
key,
|
|
873
|
+
prev: null,
|
|
874
|
+
next: this.head,
|
|
875
|
+
value
|
|
876
|
+
};
|
|
877
|
+
if (this.head) this.head.prev = node;
|
|
878
|
+
this.head = node;
|
|
879
|
+
if (!this.tail) this.tail = node;
|
|
880
|
+
this.map.set(key, node);
|
|
881
|
+
if (this.map.size > this.limit) this.evict();
|
|
882
|
+
}
|
|
883
|
+
delete(key) {
|
|
884
|
+
const node = this.map.get(key);
|
|
885
|
+
if (node === void 0) return;
|
|
886
|
+
this.detach(node);
|
|
887
|
+
this.map.delete(key);
|
|
888
|
+
}
|
|
889
|
+
keys() {
|
|
890
|
+
return this.map.keys();
|
|
891
|
+
}
|
|
892
|
+
detach(node) {
|
|
893
|
+
if (node.prev) node.prev.next = node.next;
|
|
894
|
+
if (node.next) node.next.prev = node.prev;
|
|
895
|
+
if (this.head === node) this.head = node.next;
|
|
896
|
+
if (this.tail === node) this.tail = node.prev;
|
|
897
|
+
node.prev = null;
|
|
898
|
+
node.next = null;
|
|
899
|
+
}
|
|
900
|
+
moveToHead(node) {
|
|
901
|
+
this.detach(node);
|
|
902
|
+
node.next = this.head;
|
|
903
|
+
if (this.head) this.head.prev = node;
|
|
904
|
+
this.head = node;
|
|
905
|
+
if (!this.tail) this.tail = node;
|
|
906
|
+
}
|
|
907
|
+
evict() {
|
|
908
|
+
const node = this.tail;
|
|
909
|
+
if (!node) return;
|
|
910
|
+
this.detach(node);
|
|
911
|
+
this.map.delete(node.key);
|
|
912
|
+
if (this.onEvict) try {
|
|
913
|
+
this.onEvict(node.key, node.value);
|
|
914
|
+
} catch {}
|
|
915
|
+
}
|
|
916
|
+
clear() {
|
|
917
|
+
this.map.clear();
|
|
918
|
+
this.head = this.tail = null;
|
|
919
|
+
}
|
|
920
|
+
};
|
|
921
|
+
//#endregion
|
|
922
|
+
//#region src/parser/tokenizer.ts
|
|
923
|
+
const isWhitespace = (ch) => ch === " " || ch === "\n" || ch === " " || ch === "\r" || ch === "\f";
|
|
924
|
+
function scan(src, cb) {
|
|
925
|
+
let depth = 0;
|
|
926
|
+
let inQuote = 0;
|
|
927
|
+
let start = 0;
|
|
928
|
+
let i = 0;
|
|
929
|
+
let pendingSlash = false;
|
|
930
|
+
const flush = (isComma, isSlash) => {
|
|
931
|
+
const actualSlash = isSlash || pendingSlash;
|
|
932
|
+
pendingSlash = false;
|
|
933
|
+
if (start < i) cb(src.slice(start, i), isComma, actualSlash);
|
|
934
|
+
else if (isComma) cb("", true, false);
|
|
935
|
+
else if (actualSlash) cb("", false, true);
|
|
936
|
+
start = i + 1;
|
|
937
|
+
};
|
|
938
|
+
for (; i < src.length; i++) {
|
|
939
|
+
const ch = src[i];
|
|
940
|
+
if (inQuote) {
|
|
941
|
+
if (ch === inQuote && src[i - 1] !== "\\") inQuote = 0;
|
|
942
|
+
continue;
|
|
943
|
+
}
|
|
944
|
+
if (ch === "\"" || ch === "'") {
|
|
945
|
+
inQuote = ch;
|
|
946
|
+
continue;
|
|
947
|
+
}
|
|
948
|
+
if (ch === "(") {
|
|
949
|
+
depth++;
|
|
950
|
+
continue;
|
|
951
|
+
}
|
|
952
|
+
if (ch === ")") {
|
|
953
|
+
if (depth) depth--;
|
|
954
|
+
continue;
|
|
955
|
+
}
|
|
956
|
+
if (!depth) {
|
|
957
|
+
if (ch === ",") {
|
|
958
|
+
flush(true, false);
|
|
959
|
+
continue;
|
|
960
|
+
}
|
|
961
|
+
if (ch === "/") {
|
|
962
|
+
const prevIsWhitespace = isWhitespace(src[i - 1]);
|
|
963
|
+
const nextIsWhitespace = isWhitespace(src[i + 1]);
|
|
964
|
+
if (prevIsWhitespace && nextIsWhitespace) {
|
|
965
|
+
pendingSlash = true;
|
|
966
|
+
start = i + 1;
|
|
967
|
+
continue;
|
|
968
|
+
}
|
|
969
|
+
continue;
|
|
970
|
+
}
|
|
971
|
+
if (isWhitespace(ch)) {
|
|
972
|
+
flush(false, false);
|
|
973
|
+
continue;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
flush(false, false);
|
|
978
|
+
}
|
|
979
|
+
//#endregion
|
|
980
|
+
//#region src/parser/parser.ts
|
|
981
|
+
var StyleParser = class {
|
|
982
|
+
opts;
|
|
983
|
+
cache;
|
|
984
|
+
constructor(opts = {}) {
|
|
985
|
+
this.opts = opts;
|
|
986
|
+
this.cache = new Lru(this.opts.cacheSize ?? 1e3);
|
|
987
|
+
}
|
|
988
|
+
process(src) {
|
|
989
|
+
const key = String(src);
|
|
990
|
+
const hit = this.cache.get(key);
|
|
991
|
+
if (hit) return hit;
|
|
992
|
+
const stripped = foldDslCase(src.replace(/\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\//g, ""));
|
|
993
|
+
const groups = [];
|
|
994
|
+
let currentGroup = makeEmptyDetails();
|
|
995
|
+
let currentPart = makeEmptyPart();
|
|
996
|
+
let parts = [];
|
|
997
|
+
const pushToken = (bucket, processed) => {
|
|
998
|
+
if (!processed) return;
|
|
999
|
+
if (currentPart.values.length > 0 && currentPart.values[currentPart.values.length - 1].startsWith("url(")) {
|
|
1000
|
+
currentPart.values[currentPart.values.length - 1] += ` ${processed}`;
|
|
1001
|
+
currentPart.all[currentPart.all.length - 1] += ` ${processed}`;
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
switch (bucket) {
|
|
1005
|
+
case 0:
|
|
1006
|
+
currentPart.colors.push(processed);
|
|
1007
|
+
break;
|
|
1008
|
+
case 1:
|
|
1009
|
+
currentPart.values.push(processed);
|
|
1010
|
+
break;
|
|
1011
|
+
case 2:
|
|
1012
|
+
currentPart.mods.push(processed);
|
|
1013
|
+
break;
|
|
1014
|
+
case 3:
|
|
1015
|
+
currentPart.colors.push(processed);
|
|
1016
|
+
currentPart.values.push(processed);
|
|
1017
|
+
break;
|
|
1018
|
+
}
|
|
1019
|
+
currentPart.all.push(processed);
|
|
1020
|
+
};
|
|
1021
|
+
const endPart = (reset = true) => {
|
|
1022
|
+
if (currentPart.all.length > 0) {
|
|
1023
|
+
currentPart.output = currentPart.all.join(" ");
|
|
1024
|
+
parts.push(currentPart);
|
|
1025
|
+
}
|
|
1026
|
+
if (reset) currentPart = makeEmptyPart();
|
|
1027
|
+
};
|
|
1028
|
+
const endGroup = (reset = true) => {
|
|
1029
|
+
endPart(reset);
|
|
1030
|
+
if (parts.length === 0) parts.push(makeEmptyPart());
|
|
1031
|
+
currentGroup.parts = parts;
|
|
1032
|
+
for (const part of parts) {
|
|
1033
|
+
currentGroup.mods.push(...part.mods);
|
|
1034
|
+
currentGroup.values.push(...part.values);
|
|
1035
|
+
currentGroup.colors.push(...part.colors);
|
|
1036
|
+
currentGroup.all.push(...part.all);
|
|
1037
|
+
}
|
|
1038
|
+
currentGroup.output = parts.length === 1 ? parts[0].output : parts.map((part) => part.output).join(" / ");
|
|
1039
|
+
groups.push(currentGroup);
|
|
1040
|
+
if (reset) {
|
|
1041
|
+
currentGroup = makeEmptyDetails();
|
|
1042
|
+
parts = [];
|
|
1043
|
+
}
|
|
1044
|
+
};
|
|
1045
|
+
scan(stripped, (tok, isComma, isSlash) => {
|
|
1046
|
+
if (tok) {
|
|
1047
|
+
if (currentGroup.input) currentGroup.input += ` ${tok}`;
|
|
1048
|
+
else currentGroup.input = tok;
|
|
1049
|
+
const { bucket, processed } = classify(tok, this.opts, (sub) => this.process(sub));
|
|
1050
|
+
pushToken(bucket, processed);
|
|
1051
|
+
}
|
|
1052
|
+
if (isSlash) endPart();
|
|
1053
|
+
if (isComma) endGroup();
|
|
1054
|
+
});
|
|
1055
|
+
if (currentPart.all.length || parts.length || !groups.length) endGroup(false);
|
|
1056
|
+
const result = {
|
|
1057
|
+
output: groups.length === 1 ? groups[0].output : groups.map((group) => group.output).join(", "),
|
|
1058
|
+
groups
|
|
1059
|
+
};
|
|
1060
|
+
Object.freeze(result);
|
|
1061
|
+
this.cache.set(key, result);
|
|
1062
|
+
return result;
|
|
1063
|
+
}
|
|
1064
|
+
setFunctions(functions) {
|
|
1065
|
+
this.opts.functions = functions;
|
|
1066
|
+
this.cache.clear();
|
|
1067
|
+
}
|
|
1068
|
+
setUnits(units) {
|
|
1069
|
+
this.opts.units = units;
|
|
1070
|
+
this.cache.clear();
|
|
1071
|
+
}
|
|
1072
|
+
updateOptions(patch) {
|
|
1073
|
+
Object.assign(this.opts, patch);
|
|
1074
|
+
if (patch.cacheSize) this.cache = new Lru(patch.cacheSize);
|
|
1075
|
+
else this.cache.clear();
|
|
1076
|
+
}
|
|
1077
|
+
clearCache() {
|
|
1078
|
+
this.cache.clear();
|
|
1079
|
+
}
|
|
1080
|
+
getUnits() {
|
|
1081
|
+
return this.opts.units;
|
|
1082
|
+
}
|
|
1083
|
+
};
|
|
1084
|
+
//#endregion
|
|
1085
|
+
//#region src/plugins/color-func.ts
|
|
1086
|
+
const clamp = (value, min, max) => Math.max(Math.min(value, max), min);
|
|
1087
|
+
const parseAngle = (value) => {
|
|
1088
|
+
const match = value.match(/^([+-]?\d*\.?\d+)(deg|turn|rad)?$/);
|
|
1089
|
+
if (!match) return 0;
|
|
1090
|
+
const num = parseFloat(match[1]);
|
|
1091
|
+
switch (match[2]) {
|
|
1092
|
+
case "turn": return num * 360;
|
|
1093
|
+
case "rad": return num * 180 / Math.PI;
|
|
1094
|
+
default: return num;
|
|
1095
|
+
}
|
|
1096
|
+
};
|
|
1097
|
+
const parsePercentage = (value) => {
|
|
1098
|
+
const match = value.match(/^([+-]?\d*\.?\d+)%?$/);
|
|
1099
|
+
if (!match) return 0;
|
|
1100
|
+
const num = parseFloat(match[1]);
|
|
1101
|
+
return value.includes("%") ? num / 100 : num;
|
|
1102
|
+
};
|
|
1103
|
+
function createColorFunc(name, convert, label) {
|
|
1104
|
+
const conversionCache = new Lru(500);
|
|
1105
|
+
const expected = label ? ` (${label})` : "";
|
|
1106
|
+
return (groups) => {
|
|
1107
|
+
if (groups.length === 0 || groups[0].all.length < 3) {
|
|
1108
|
+
if (isDevEnv()) console.warn(`[Tasty] ${name}(): expected 3 values${expected}, got:`, groups);
|
|
1109
|
+
return "rgb(0% 0% 0%)";
|
|
1110
|
+
}
|
|
1111
|
+
const group = groups[0];
|
|
1112
|
+
const tokens = group.all;
|
|
1113
|
+
const alpha = group.parts.length > 1 && group.parts[1].all.length > 0 ? group.parts[1].output : void 0;
|
|
1114
|
+
const cacheKey = tokens.slice(0, 3).join(" ") + (alpha ? ` / ${alpha}` : "");
|
|
1115
|
+
const cached = conversionCache.get(cacheKey);
|
|
1116
|
+
if (cached) return cached;
|
|
1117
|
+
const h = parseAngle(tokens[0]);
|
|
1118
|
+
const c2 = parsePercentage(tokens[1]);
|
|
1119
|
+
const c3 = parsePercentage(tokens[2]);
|
|
1120
|
+
const misscaled = [tokens[1], tokens[2]].filter((raw, i) => !raw.includes("%") && (i === 0 ? c2 : c3) > 1);
|
|
1121
|
+
if (misscaled.length) warnOnceDev(`${name}:percent-scale`, `${name}(): channels are factors (0-1) or percentages, so ${misscaled.map((v) => `"${v}"`).join(" and ")} ${misscaled.length > 1 ? "clamp" : "clamps"} to 1 — add the missing '%', or write the value as a 0-1 number.`);
|
|
1122
|
+
const [r, g, b] = convert(h, clamp(c2, 0, 1), clamp(c3, 0, 1));
|
|
1123
|
+
const format = (n) => {
|
|
1124
|
+
const pct = n * 100;
|
|
1125
|
+
return parseFloat(pct.toFixed(1)).toString() + "%";
|
|
1126
|
+
};
|
|
1127
|
+
const result = alpha ? `rgb(${format(r)} ${format(g)} ${format(b)} / ${alpha})` : `rgb(${format(r)} ${format(g)} ${format(b)})`;
|
|
1128
|
+
conversionCache.set(cacheKey, result);
|
|
1129
|
+
return result;
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
1132
|
+
//#endregion
|
|
1133
|
+
//#region src/plugins/okhsl-plugin.ts
|
|
1134
|
+
const okhslFunction = createColorFunc("okhsl", okhslToSrgb, "H S L");
|
|
1135
|
+
const okhslPlugin = () => ({
|
|
1136
|
+
name: "okhsl",
|
|
1137
|
+
functions: { okhsl: okhslFunction }
|
|
1138
|
+
});
|
|
1139
|
+
//#endregion
|
|
1140
|
+
//#region src/plugins/okhst-plugin.ts
|
|
1141
|
+
const okhstFunction = createColorFunc("okhst", okhstToSrgb, "H S T");
|
|
1142
|
+
const okhstPlugin = () => ({
|
|
1143
|
+
name: "okhst",
|
|
1144
|
+
functions: { okhst: okhstFunction }
|
|
1145
|
+
});
|
|
1146
|
+
//#endregion
|
|
1147
|
+
//#region src/plugins/defaults.ts
|
|
1148
|
+
function registerDefaultFunctions() {
|
|
1149
|
+
customFunction("okhsl", okhslFunction);
|
|
1150
|
+
customFunction("okhst", okhstFunction);
|
|
1151
|
+
}
|
|
1152
|
+
//#endregion
|
|
1153
|
+
//#region src/utils/styles.ts
|
|
1154
|
+
function normalizeColorTokenValue(value) {
|
|
1155
|
+
if (value === true) return "transparent";
|
|
1156
|
+
if (value === false) return null;
|
|
1157
|
+
return value;
|
|
1158
|
+
}
|
|
1159
|
+
const COLOR_VAR_PATTERN = /^var\(--([a-z0-9-]+)-color[,)]/;
|
|
1160
|
+
const RGB_ALPHA_PATTERN = /\/\s*([0-9.]+)\)/;
|
|
1161
|
+
const RE_HEX_COLOR = /^#[0-9a-fA-F]{3,8}$/;
|
|
1162
|
+
const RE_VAR_COLOR = /^var\(--[a-z0-9-]+-color/;
|
|
1163
|
+
function isSimpleColorFast(val) {
|
|
1164
|
+
switch (val.charCodeAt(0)) {
|
|
1165
|
+
case 35: return RE_HEX_COLOR.test(val);
|
|
1166
|
+
case 114:
|
|
1167
|
+
if (val.charCodeAt(1) === 103 && val.charCodeAt(2) === 98) return true;
|
|
1168
|
+
break;
|
|
1169
|
+
case 104:
|
|
1170
|
+
if (val.charCodeAt(1) === 115 && val.charCodeAt(2) === 108) return true;
|
|
1171
|
+
break;
|
|
1172
|
+
case 108:
|
|
1173
|
+
if (val.charCodeAt(1) === 99 && val.charCodeAt(2) === 104) return true;
|
|
1174
|
+
break;
|
|
1175
|
+
case 111:
|
|
1176
|
+
if (val.startsWith("oklch(")) return true;
|
|
1177
|
+
break;
|
|
1178
|
+
case 118:
|
|
1179
|
+
if (RE_VAR_COLOR.test(val)) return true;
|
|
1180
|
+
break;
|
|
1181
|
+
case 99:
|
|
1182
|
+
if (val === "currentColor" || val === "currentcolor") return true;
|
|
1183
|
+
break;
|
|
1184
|
+
case 116:
|
|
1185
|
+
if (val === "transparent") return true;
|
|
1186
|
+
break;
|
|
1187
|
+
}
|
|
1188
|
+
return getNamedColorHex().has(val.toLowerCase());
|
|
1189
|
+
}
|
|
1190
|
+
let colorWarningCount = 0;
|
|
1191
|
+
const MAX_COLOR_WARNINGS = 10;
|
|
1192
|
+
const CUSTOM_UNITS = {
|
|
1193
|
+
r: "6px",
|
|
1194
|
+
cr: "10px",
|
|
1195
|
+
bw: "1px",
|
|
1196
|
+
ow: "3px",
|
|
1197
|
+
x: "8px",
|
|
1198
|
+
sf: function sf(num) {
|
|
1199
|
+
return `minmax(0, ${num}fr)`;
|
|
1200
|
+
}
|
|
1201
|
+
};
|
|
1202
|
+
const DIRECTIONS = [
|
|
1203
|
+
"top",
|
|
1204
|
+
"right",
|
|
1205
|
+
"bottom",
|
|
1206
|
+
"left"
|
|
1207
|
+
];
|
|
1208
|
+
let __tastyParser = null;
|
|
1209
|
+
function getOrCreateParser() {
|
|
1210
|
+
if (!__tastyParser) {
|
|
1211
|
+
__tastyParser = new StyleParser({ units: CUSTOM_UNITS });
|
|
1212
|
+
__tastyParser.setFunctions(__tastyParseFunctions);
|
|
1213
|
+
registerDefaultFunctions();
|
|
1214
|
+
}
|
|
1215
|
+
return __tastyParser;
|
|
1216
|
+
}
|
|
1217
|
+
const __tastyParseFunctions = {};
|
|
1218
|
+
function customFunction(name, fn) {
|
|
1219
|
+
__tastyParseFunctions[name] = fn;
|
|
1220
|
+
getOrCreateParser().setFunctions(__tastyParseFunctions);
|
|
1221
|
+
}
|
|
1222
|
+
function resetGlobalParseFunctions() {
|
|
1223
|
+
for (const key of Object.keys(__tastyParseFunctions)) delete __tastyParseFunctions[key];
|
|
1224
|
+
registerDefaultFunctions();
|
|
1225
|
+
getOrCreateParser().setFunctions(__tastyParseFunctions);
|
|
1226
|
+
}
|
|
1227
|
+
function getGlobalParser() {
|
|
1228
|
+
return getOrCreateParser();
|
|
1229
|
+
}
|
|
1230
|
+
function getGlobalParseFunctions() {
|
|
1231
|
+
return __tastyParseFunctions;
|
|
1232
|
+
}
|
|
1233
|
+
let __globalPredefinedTokens = null;
|
|
1234
|
+
function setGlobalPredefinedTokens(tokens) {
|
|
1235
|
+
const normalizedTokens = {};
|
|
1236
|
+
for (const [key, value] of Object.entries(tokens)) {
|
|
1237
|
+
const lowerKey = key.toLowerCase();
|
|
1238
|
+
const lowerValue = value.toLowerCase();
|
|
1239
|
+
if (lowerKey.startsWith("#") && lowerValue === "#current") {
|
|
1240
|
+
console.warn(`[Tasty] Using #current to define color token "${key}" is not supported. The #current token represents currentcolor which cannot be used as a base for other tokens.`);
|
|
1241
|
+
continue;
|
|
1242
|
+
}
|
|
1243
|
+
normalizedTokens[lowerKey] = value;
|
|
1244
|
+
}
|
|
1245
|
+
__globalPredefinedTokens = __globalPredefinedTokens ? {
|
|
1246
|
+
...__globalPredefinedTokens,
|
|
1247
|
+
...normalizedTokens
|
|
1248
|
+
} : normalizedTokens;
|
|
1249
|
+
getOrCreateParser().clearCache();
|
|
1250
|
+
}
|
|
1251
|
+
function getGlobalPredefinedTokens() {
|
|
1252
|
+
return __globalPredefinedTokens;
|
|
1253
|
+
}
|
|
1254
|
+
function resetGlobalPredefinedTokens() {
|
|
1255
|
+
__globalPredefinedTokens = null;
|
|
1256
|
+
getOrCreateParser().clearCache();
|
|
1257
|
+
}
|
|
1258
|
+
function parseStyle(value) {
|
|
1259
|
+
let str;
|
|
1260
|
+
if (typeof value === "string") str = value;
|
|
1261
|
+
else if (typeof value === "number") str = String(value);
|
|
1262
|
+
else str = "";
|
|
1263
|
+
return getOrCreateParser().process(str);
|
|
1264
|
+
}
|
|
1265
|
+
const RE_CUSTOM_PROPERTY_REF = /\$[a-zA-Z_$]/;
|
|
1266
|
+
function resolveCustomProperties(value) {
|
|
1267
|
+
if (!RE_CUSTOM_PROPERTY_REF.test(value)) return value;
|
|
1268
|
+
return parseStyle(value).output || value;
|
|
1269
|
+
}
|
|
1270
|
+
function parseColor(val, ignoreError = false) {
|
|
1271
|
+
if (typeof val !== "string") val = String(val ?? "");
|
|
1272
|
+
val = val.trim();
|
|
1273
|
+
if (!val) return {};
|
|
1274
|
+
const isSimpleColor = isSimpleColorFast(val);
|
|
1275
|
+
let firstColor;
|
|
1276
|
+
if (isSimpleColor) firstColor = val;
|
|
1277
|
+
else {
|
|
1278
|
+
const extractedColor = parseStyle(val).groups.find((g) => g.colors.length)?.colors[0];
|
|
1279
|
+
if (!extractedColor) {
|
|
1280
|
+
if (!ignoreError && colorWarningCount < MAX_COLOR_WARNINGS) {
|
|
1281
|
+
console.warn("[Tasty] unable to parse color:", val);
|
|
1282
|
+
colorWarningCount++;
|
|
1283
|
+
if (colorWarningCount === MAX_COLOR_WARNINGS) console.warn("[Tasty] color parsing warnings will be suppressed from now on");
|
|
1284
|
+
}
|
|
1285
|
+
return {};
|
|
1286
|
+
}
|
|
1287
|
+
firstColor = extractedColor;
|
|
1288
|
+
}
|
|
1289
|
+
const faded = parseAlphaOverride(firstColor);
|
|
1290
|
+
const baseColor = faded ? faded.color : firstColor;
|
|
1291
|
+
const nameMatch = baseColor.match(COLOR_VAR_PATTERN);
|
|
1292
|
+
let opacity;
|
|
1293
|
+
if (faded) {
|
|
1294
|
+
const { alpha } = faded;
|
|
1295
|
+
const v = parseFloat(alpha);
|
|
1296
|
+
if (!isNaN(v)) opacity = alpha.endsWith("%") ? v : v * 100;
|
|
1297
|
+
} else if (baseColor.startsWith("rgb") || baseColor.startsWith("hsl") || baseColor.startsWith("lch") || baseColor.startsWith("oklch")) {
|
|
1298
|
+
const alphaMatch = baseColor.match(RGB_ALPHA_PATTERN);
|
|
1299
|
+
if (alphaMatch) {
|
|
1300
|
+
const v = parseFloat(alphaMatch[1]);
|
|
1301
|
+
if (!isNaN(v)) opacity = v * 100;
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
return {
|
|
1305
|
+
color: firstColor,
|
|
1306
|
+
name: nameMatch ? nameMatch[1] : void 0,
|
|
1307
|
+
opacity
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
function filterMods(mods, allowedMods) {
|
|
1311
|
+
const filtered = [];
|
|
1312
|
+
for (const mod of mods) if (allowedMods.includes(mod)) filtered.push(mod);
|
|
1313
|
+
return filtered;
|
|
1314
|
+
}
|
|
1315
|
+
const _innerCache = /* @__PURE__ */ new WeakMap();
|
|
1316
|
+
const _topLevelCache = /* @__PURE__ */ new WeakMap();
|
|
1317
|
+
function stringifyStyles(styles) {
|
|
1318
|
+
if (styles == null || typeof styles !== "object") return "";
|
|
1319
|
+
const cached = _topLevelCache.get(styles);
|
|
1320
|
+
if (cached !== void 0) return cached;
|
|
1321
|
+
const obj = styles;
|
|
1322
|
+
const keys = Object.keys(obj).sort();
|
|
1323
|
+
const parts = [];
|
|
1324
|
+
for (const k of keys) {
|
|
1325
|
+
const v = obj[k];
|
|
1326
|
+
if (v === void 0 || typeof v === "function" || typeof v === "symbol") continue;
|
|
1327
|
+
const c0 = k.charCodeAt(0);
|
|
1328
|
+
const needsInnerSort = (c0 >= 65 && c0 <= 90 || c0 === 38) && v && typeof v === "object" && !Array.isArray(v);
|
|
1329
|
+
let sv;
|
|
1330
|
+
if (needsInnerSort) {
|
|
1331
|
+
sv = _innerCache.get(v);
|
|
1332
|
+
if (sv === void 0) {
|
|
1333
|
+
const innerObj = v;
|
|
1334
|
+
const innerKeys = Object.keys(innerObj).sort();
|
|
1335
|
+
const innerParts = [];
|
|
1336
|
+
for (const ik of innerKeys) {
|
|
1337
|
+
const ivs = JSON.stringify(innerObj[ik]);
|
|
1338
|
+
if (ivs !== void 0) innerParts.push(JSON.stringify(ik) + ":" + ivs);
|
|
1339
|
+
}
|
|
1340
|
+
sv = "{" + innerParts.join(",") + "}";
|
|
1341
|
+
_innerCache.set(v, sv);
|
|
1342
|
+
}
|
|
1343
|
+
} else sv = JSON.stringify(v);
|
|
1344
|
+
parts.push(JSON.stringify(k) + ":" + sv);
|
|
1345
|
+
}
|
|
1346
|
+
const result = "{" + parts.join(",") + "}";
|
|
1347
|
+
_topLevelCache.set(styles, result);
|
|
1348
|
+
return result;
|
|
1349
|
+
}
|
|
1350
|
+
//#endregion
|
|
1351
|
+
//#region src/utils/function-color.ts
|
|
1352
|
+
const RE_FUNC_NAME = /^([a-z][a-z0-9-]*)\s*\(/i;
|
|
1353
|
+
const RE_COLOR_OUT = /^(?:rgb|hsl|hwb|lab|lch|oklab|oklch|color)\(|^#|^var\(--/i;
|
|
1354
|
+
function resolveFunctionColor(str) {
|
|
1355
|
+
const m = RE_FUNC_NAME.exec(str);
|
|
1356
|
+
if (!m) return null;
|
|
1357
|
+
const name = m[1].toLowerCase();
|
|
1358
|
+
getGlobalParser();
|
|
1359
|
+
if (!(name in getGlobalParseFunctions())) return null;
|
|
1360
|
+
const out = getGlobalParser().process(str).output;
|
|
1361
|
+
if (!out || !RE_COLOR_OUT.test(out)) return null;
|
|
1362
|
+
return out;
|
|
1363
|
+
}
|
|
1364
|
+
//#endregion
|
|
1365
|
+
//#region src/utils/colors.ts
|
|
1366
|
+
function color(name, opacity = 1) {
|
|
1367
|
+
if (opacity !== 1) return overrideColorAlpha(`var(--${name}-color)`, String(opacity));
|
|
1368
|
+
return `var(--${name}-color)`;
|
|
1369
|
+
}
|
|
1370
|
+
//#endregion
|
|
1371
|
+
export { strToRgb as A, StyleParser as C, getRgbValuesFromRgbaString as D, getNamedColorHex as E, RE_RAW_UNIT as F, toSnakeCase as M, CSS_WIDE_KEYWORDS as N, hexToRgb as O, RE_NUMBER as P, createColorFunc as S, makeEmptyDetails as T, stringifyStyles as _, customFunction as a, okhslFunction as b, getGlobalParser as c, parseColor as d, parseStyle as f, setGlobalPredefinedTokens as g, resolveCustomProperties as h, DIRECTIONS as i, normalizeDslName as j, hslToRgbValues as k, getGlobalPredefinedTokens as l, resetGlobalPredefinedTokens as m, resolveFunctionColor as n, filterMods as o, resetGlobalParseFunctions as p, CUSTOM_UNITS as r, getGlobalParseFunctions as s, color as t, normalizeColorTokenValue as u, okhstFunction as v, Lru as w, okhslPlugin as x, okhstPlugin as y };
|
|
1372
|
+
|
|
1373
|
+
//# sourceMappingURL=dsl-C5yuAn41.js.map
|