rainbowindex 0.6.0 → 0.7.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/CHANGELOG.md +543 -0
- package/LICENSE +16 -17
- package/NOTICE.md +106 -0
- package/README.md +219 -65
- package/dist/browser.d.ts +4 -2
- package/dist/browser.mjs +12 -4
- package/dist/chunk-2T7V5XLK.mjs +912 -0
- package/dist/chunk-6OORICWF.mjs +16 -0
- package/dist/{chunk-KSNYSR3C.mjs → chunk-FJOZJIKB.mjs} +2499 -329
- package/dist/chunk-L56IRO7A.mjs +491 -0
- package/dist/chunk-PZDVDEZJ.mjs +196 -0
- package/dist/{chunk-3LWJTLOJ.mjs → chunk-RC6DDE4L.mjs} +23 -15
- package/dist/chunk-TQJYVQPE.mjs +217 -0
- package/dist/chunk-W756NVYI.mjs +33 -0
- package/dist/chunk-WBESS2ZD.mjs +598 -0
- package/dist/{chunk-3HRMFZGE.mjs → chunk-X66Z2YHT.mjs} +2 -1
- package/dist/{chunk-6U4IOFOS.mjs → chunk-XQGSG2HK.mjs} +199 -555
- package/dist/cli.mjs +1077 -123
- package/dist/{index-DSgpB6bS.d.ts → context-DcBtnnan.d.ts} +47 -103
- package/dist/editor.d.ts +71 -433
- package/dist/editor.mjs +51 -368
- package/dist/eslint.d.ts +16 -0
- package/dist/eslint.mjs +32 -0
- package/dist/{index-4Kyaq3IZ.d.ts → imports-C9esHd5Q.d.ts} +78 -84
- package/dist/index-CNqdL5U0.d.ts +56 -0
- package/dist/index-Czx-EUwh.d.ts +138 -0
- package/dist/index-DW8YSxTz.d.ts +104 -0
- package/dist/index.d.ts +46 -5
- package/dist/index.mjs +33 -9
- package/dist/oxlint.d.ts +21 -3
- package/dist/oxlint.mjs +19 -1
- package/dist/recipe.d.ts +111 -0
- package/dist/recipe.mjs +71 -0
- package/dist/safelist-CH3_PywB.d.ts +43 -0
- package/dist/session-CMaskdB7.d.ts +543 -0
- package/dist/tailwind.css +644 -0
- package/dist/theme-CIZiGlce.d.ts +115 -0
- package/dist/vite.d.ts +10 -1
- package/dist/vite.mjs +266 -118
- package/package.json +27 -5
- package/dist/chunk-WK6S4HTC.mjs +0 -1921
- package/dist/chunk-ZR7XJMUN.mjs +0 -251
- package/dist/safelist-CGCtF-Fr.d.ts +0 -96
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ANIMATION_STATIC_NAMES,
|
|
3
|
+
BACKGROUND_STATIC_NAMES,
|
|
4
|
+
BORDER_STATIC_NAMES,
|
|
5
|
+
EFFECTS_STATIC_NAMES,
|
|
6
|
+
LAYOUT_STATIC_NAMES,
|
|
7
|
+
PREFIX_DISPATCH,
|
|
8
|
+
ROOT_GROUPS,
|
|
9
|
+
ROUNDED_CORNER_NAMES,
|
|
10
|
+
ROUNDED_SIDE_NAMES,
|
|
11
|
+
SPACING_SAMPLES,
|
|
12
|
+
STATIC_UTILITIES,
|
|
13
|
+
SVG_STATIC_NAMES,
|
|
14
|
+
TYPOGRAPHY_STATIC_NAMES,
|
|
15
|
+
buildBreakpointWeights,
|
|
16
|
+
codepointCompare,
|
|
17
|
+
compileUtility,
|
|
18
|
+
createEmptyCompilationResult,
|
|
19
|
+
escapeSelector,
|
|
20
|
+
findClosest,
|
|
21
|
+
listVariants,
|
|
22
|
+
parseUtility,
|
|
23
|
+
resolveUtilityDeclarations
|
|
24
|
+
} from "./chunk-FJOZJIKB.mjs";
|
|
25
|
+
import {
|
|
26
|
+
computeDarkStop,
|
|
27
|
+
formatOklch,
|
|
28
|
+
generateStop,
|
|
29
|
+
linearToSrgb,
|
|
30
|
+
oklabToLinearSrgb,
|
|
31
|
+
oklchToOklab
|
|
32
|
+
} from "./chunk-L56IRO7A.mjs";
|
|
33
|
+
import {
|
|
34
|
+
SPECIAL_COLORS
|
|
35
|
+
} from "./chunk-XQGSG2HK.mjs";
|
|
36
|
+
|
|
37
|
+
// src/project/css-entry.ts
|
|
38
|
+
var CSS_ENTRY_CANDIDATES = Object.freeze([
|
|
39
|
+
"src/index.css",
|
|
40
|
+
"src/style.css",
|
|
41
|
+
"src/styles.css",
|
|
42
|
+
"src/app.css",
|
|
43
|
+
"src/global.css",
|
|
44
|
+
"index.css",
|
|
45
|
+
"style.css",
|
|
46
|
+
"styles.css",
|
|
47
|
+
"app.css",
|
|
48
|
+
"global.css"
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
// src/theme/swatch.ts
|
|
52
|
+
var CANONICAL_COLOR_STOPS = Object.freeze([
|
|
53
|
+
50,
|
|
54
|
+
100,
|
|
55
|
+
150,
|
|
56
|
+
200,
|
|
57
|
+
250,
|
|
58
|
+
300,
|
|
59
|
+
350,
|
|
60
|
+
400,
|
|
61
|
+
450,
|
|
62
|
+
500,
|
|
63
|
+
550,
|
|
64
|
+
600,
|
|
65
|
+
650,
|
|
66
|
+
700,
|
|
67
|
+
750,
|
|
68
|
+
800,
|
|
69
|
+
850,
|
|
70
|
+
900,
|
|
71
|
+
950
|
|
72
|
+
]);
|
|
73
|
+
function channelHex(value) {
|
|
74
|
+
return Math.round(Math.min(1, Math.max(0, value)) * 255).toString(16).padStart(2, "0");
|
|
75
|
+
}
|
|
76
|
+
function oklchToHex(l, c, h) {
|
|
77
|
+
const [labL, labA, labB] = oklchToOklab(l, c, h);
|
|
78
|
+
const [r, g, b] = oklabToLinearSrgb(labL, labA, labB);
|
|
79
|
+
return `#${channelHex(linearToSrgb(r))}${channelHex(linearToSrgb(g))}${channelHex(linearToSrgb(b))}`;
|
|
80
|
+
}
|
|
81
|
+
var OKLCH_TEXT_RE = /^oklch\(\s*([\d.]+%?)\s+([\d.]+)\s+([\d.-]+)\s*(?:\/\s*[\d.]+%?\s*)?\)$/i;
|
|
82
|
+
var HEX_TEXT_RE = /^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
|
|
83
|
+
function cssColorToHex(css) {
|
|
84
|
+
const text = css.trim();
|
|
85
|
+
if (HEX_TEXT_RE.test(text)) {
|
|
86
|
+
if (text.length === 4 || text.length === 5) {
|
|
87
|
+
return `#${text[1]}${text[1]}${text[2]}${text[2]}${text[3]}${text[3]}`.toLowerCase();
|
|
88
|
+
}
|
|
89
|
+
return text.slice(0, 7).toLowerCase();
|
|
90
|
+
}
|
|
91
|
+
const match = OKLCH_TEXT_RE.exec(text);
|
|
92
|
+
if (match) {
|
|
93
|
+
const rawL = match[1];
|
|
94
|
+
const l = rawL.endsWith("%") ? Number.parseFloat(rawL) / 100 : Number.parseFloat(rawL);
|
|
95
|
+
const c = Number.parseFloat(match[2]);
|
|
96
|
+
const h = Number.parseFloat(match[3]);
|
|
97
|
+
if (Number.isFinite(l) && Number.isFinite(c) && Number.isFinite(h)) {
|
|
98
|
+
return oklchToHex(l, c, h);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
var MAX_ALIAS_HOPS = 8;
|
|
104
|
+
var SEMANTIC_SWATCHES = Object.freeze({
|
|
105
|
+
paper: {
|
|
106
|
+
light: { css: "oklch(1 0 0)", hex: "#ffffff" },
|
|
107
|
+
dark: { css: "oklch(0 0 0)", hex: "#000000" }
|
|
108
|
+
},
|
|
109
|
+
ink: {
|
|
110
|
+
light: { css: "oklch(0 0 0)", hex: "#000000" },
|
|
111
|
+
dark: { css: "oklch(1 0 0)", hex: "#ffffff" }
|
|
112
|
+
},
|
|
113
|
+
white: {
|
|
114
|
+
light: { css: "oklch(1 0 0)", hex: "#ffffff" },
|
|
115
|
+
dark: null
|
|
116
|
+
},
|
|
117
|
+
black: {
|
|
118
|
+
light: { css: "oklch(0 0 0)", hex: "#000000" },
|
|
119
|
+
dark: null
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
function swatchFromCss(css) {
|
|
123
|
+
return { css, hex: cssColorToHex(css) };
|
|
124
|
+
}
|
|
125
|
+
function resolveColorSwatch(theme, name, stop = 500) {
|
|
126
|
+
let def = theme.colors[name];
|
|
127
|
+
for (let hop = 0; def && def.type === "alias" && hop < MAX_ALIAS_HOPS; hop++) {
|
|
128
|
+
def = theme.colors[def.source];
|
|
129
|
+
}
|
|
130
|
+
if (!def || def.type === "alias") {
|
|
131
|
+
return SEMANTIC_SWATCHES[name] ?? null;
|
|
132
|
+
}
|
|
133
|
+
switch (def.type) {
|
|
134
|
+
case "generative": {
|
|
135
|
+
const light = generateStop(def, stop);
|
|
136
|
+
const lightSwatch = {
|
|
137
|
+
css: formatOklch(light.l, light.c, light.h),
|
|
138
|
+
hex: oklchToHex(light.l, light.c, light.h)
|
|
139
|
+
};
|
|
140
|
+
if (theme.darkConfig.mode === "off" || def.dark?.strategy === "fixed") {
|
|
141
|
+
return { light: lightSwatch, dark: null };
|
|
142
|
+
}
|
|
143
|
+
const dark = computeDarkStop(def, stop, theme.darkConfig, def.dark);
|
|
144
|
+
return {
|
|
145
|
+
light: lightSwatch,
|
|
146
|
+
dark: {
|
|
147
|
+
css: formatOklch(dark.l, dark.c, dark.h),
|
|
148
|
+
hex: oklchToHex(dark.l, dark.c, dark.h)
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
case "explicit":
|
|
153
|
+
return { light: swatchFromCss(def.value), dark: null };
|
|
154
|
+
case "pair":
|
|
155
|
+
return {
|
|
156
|
+
light: swatchFromCss(def.light),
|
|
157
|
+
dark: theme.darkConfig.mode === "off" ? null : swatchFromCss(def.dark)
|
|
158
|
+
};
|
|
159
|
+
case "keyword":
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function listThemeTokens(theme) {
|
|
164
|
+
return {
|
|
165
|
+
colors: Object.entries(theme.colors).map(([name, def]) => ({ name, kind: def.type })),
|
|
166
|
+
colorStops: CANONICAL_COLOR_STOPS,
|
|
167
|
+
spacingBase: theme.spacing.base,
|
|
168
|
+
textSizes: Object.entries(theme.text).map(([name, def]) => ({
|
|
169
|
+
name,
|
|
170
|
+
fontSize: def.fontSize,
|
|
171
|
+
lineHeight: def.lineHeight
|
|
172
|
+
})),
|
|
173
|
+
breakpoints: { ...theme.breakpoints },
|
|
174
|
+
shadows: { ...theme.shadows },
|
|
175
|
+
weights: { ...theme.weights },
|
|
176
|
+
easing: { ...theme.easing },
|
|
177
|
+
blur: { ...theme.blur },
|
|
178
|
+
z: { ...theme.z },
|
|
179
|
+
leading: { ...theme.leading },
|
|
180
|
+
tracking: { ...theme.tracking },
|
|
181
|
+
opacity: { ...theme.opacity },
|
|
182
|
+
duration: { ...theme.duration },
|
|
183
|
+
radii: { ...theme.radii },
|
|
184
|
+
fluidRanges: Object.fromEntries(
|
|
185
|
+
Object.entries(theme.fluidRanges).map(([name, range]) => [
|
|
186
|
+
name,
|
|
187
|
+
{ min: range.min, max: range.max }
|
|
188
|
+
])
|
|
189
|
+
),
|
|
190
|
+
fonts: theme.fonts.map((slot) => ({ slot: slot.slot, family: slot.family })),
|
|
191
|
+
animations: Object.keys(theme.animations)
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// src/utilities/enumerate.ts
|
|
196
|
+
var COLOR_STOPS = Object.freeze([
|
|
197
|
+
"50",
|
|
198
|
+
"100",
|
|
199
|
+
"150",
|
|
200
|
+
"200",
|
|
201
|
+
"250",
|
|
202
|
+
"300",
|
|
203
|
+
"350",
|
|
204
|
+
"400",
|
|
205
|
+
"450",
|
|
206
|
+
"500",
|
|
207
|
+
"550",
|
|
208
|
+
"600",
|
|
209
|
+
"650",
|
|
210
|
+
"700",
|
|
211
|
+
"750",
|
|
212
|
+
"800",
|
|
213
|
+
"850",
|
|
214
|
+
"900",
|
|
215
|
+
"950"
|
|
216
|
+
]);
|
|
217
|
+
var FRACTION_SAMPLES = Object.freeze([
|
|
218
|
+
"1/2",
|
|
219
|
+
"1/3",
|
|
220
|
+
"2/3",
|
|
221
|
+
"1/4",
|
|
222
|
+
"3/4",
|
|
223
|
+
"1/5",
|
|
224
|
+
"2/5",
|
|
225
|
+
"3/5",
|
|
226
|
+
"4/5",
|
|
227
|
+
"1/6",
|
|
228
|
+
"5/6"
|
|
229
|
+
]);
|
|
230
|
+
var INT_SAMPLES = Object.freeze(["0", "1", "2", "3", "4", "6", "8", "10", "12"]);
|
|
231
|
+
var INT_RE = /^\d+$/;
|
|
232
|
+
var WEIGHT_STEPS = Object.freeze(["100", "200", "300", "400", "500", "600", "700", "800", "900"]);
|
|
233
|
+
var PERCENT_SAMPLES = Object.freeze([
|
|
234
|
+
"0",
|
|
235
|
+
"5",
|
|
236
|
+
"10",
|
|
237
|
+
"15",
|
|
238
|
+
"20",
|
|
239
|
+
"25",
|
|
240
|
+
"30",
|
|
241
|
+
"40",
|
|
242
|
+
"50",
|
|
243
|
+
"60",
|
|
244
|
+
"70",
|
|
245
|
+
"75",
|
|
246
|
+
"80",
|
|
247
|
+
"90",
|
|
248
|
+
"95",
|
|
249
|
+
"100"
|
|
250
|
+
]);
|
|
251
|
+
var BUILTIN_FONT_SLOTS = Object.freeze(["sans", "serif", "mono"]);
|
|
252
|
+
var DURATION_SAMPLES = Object.freeze(["75", "100", "150", "200", "300", "500", "700", "1000"]);
|
|
253
|
+
var ROUNDED_SIDES = Object.freeze([
|
|
254
|
+
...ROUNDED_SIDE_NAMES,
|
|
255
|
+
...ROUNDED_CORNER_NAMES
|
|
256
|
+
]);
|
|
257
|
+
var RADIUS_SAMPLES = Object.freeze([...SPACING_SAMPLES, "none", "full"]);
|
|
258
|
+
function buildValueSpaces() {
|
|
259
|
+
const table = /* @__PURE__ */ new Map();
|
|
260
|
+
for (const { roots, spec } of ROOT_GROUPS) {
|
|
261
|
+
for (const root of roots) {
|
|
262
|
+
let entry = table.get(root);
|
|
263
|
+
if (!entry) {
|
|
264
|
+
entry = { kinds: /* @__PURE__ */ new Set(), keywords: /* @__PURE__ */ new Set() };
|
|
265
|
+
table.set(root, entry);
|
|
266
|
+
}
|
|
267
|
+
for (const kind of spec.kinds) entry.kinds.add(kind);
|
|
268
|
+
for (const kw of spec.keywords ?? []) entry.keywords.add(kw);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const out = /* @__PURE__ */ new Map();
|
|
272
|
+
for (const [root, entry] of table) {
|
|
273
|
+
out.set(root, {
|
|
274
|
+
kinds: Object.freeze([...entry.kinds]),
|
|
275
|
+
keywords: entry.keywords.size > 0 ? Object.freeze([...entry.keywords]) : void 0
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
return out;
|
|
279
|
+
}
|
|
280
|
+
var UTILITY_VALUE_SPACES = buildValueSpaces();
|
|
281
|
+
function candidateValues(kind, theme) {
|
|
282
|
+
switch (kind) {
|
|
283
|
+
case "color": {
|
|
284
|
+
const out = [];
|
|
285
|
+
for (const name of Object.keys(theme.colors)) {
|
|
286
|
+
for (const stop of COLOR_STOPS) out.push(`${name}-${stop}`);
|
|
287
|
+
}
|
|
288
|
+
return out;
|
|
289
|
+
}
|
|
290
|
+
case "special-color":
|
|
291
|
+
return Object.keys(SPECIAL_COLORS);
|
|
292
|
+
case "spacing":
|
|
293
|
+
return [...SPACING_SAMPLES];
|
|
294
|
+
case "fraction":
|
|
295
|
+
return [...FRACTION_SAMPLES];
|
|
296
|
+
case "text-size":
|
|
297
|
+
return Object.keys(theme.text);
|
|
298
|
+
case "fluid-text-size":
|
|
299
|
+
return Object.keys(theme.text).map((size) => `fluid-${size}`);
|
|
300
|
+
case "fluid-range":
|
|
301
|
+
return Object.keys(theme.fluidRanges);
|
|
302
|
+
case "font-slot":
|
|
303
|
+
return [.../* @__PURE__ */ new Set([...BUILTIN_FONT_SLOTS, ...theme.fonts.map((slot) => slot.slot)])];
|
|
304
|
+
case "weight":
|
|
305
|
+
return [...Object.keys(theme.weights), ...WEIGHT_STEPS];
|
|
306
|
+
// Named @rounded radii plus the spacing multiples, the way @weight pairs
|
|
307
|
+
// its tokens with the numeric steps. Without the names, `rounded-roof`
|
|
308
|
+
// compiles but is offered by neither completions nor generated types.
|
|
309
|
+
case "rounded":
|
|
310
|
+
return [...Object.keys(theme.radii), ...RADIUS_SAMPLES];
|
|
311
|
+
case "rounded-side": {
|
|
312
|
+
const out = [];
|
|
313
|
+
const sizes = [...Object.keys(theme.radii), ...RADIUS_SAMPLES];
|
|
314
|
+
for (const side of ROUNDED_SIDES) {
|
|
315
|
+
for (const size of sizes) out.push(`${side}-${size}`);
|
|
316
|
+
}
|
|
317
|
+
return out;
|
|
318
|
+
}
|
|
319
|
+
case "shadow":
|
|
320
|
+
return Object.keys(theme.shadows);
|
|
321
|
+
case "z":
|
|
322
|
+
return Object.keys(theme.z);
|
|
323
|
+
case "ease":
|
|
324
|
+
return Object.keys(theme.easing);
|
|
325
|
+
case "blur":
|
|
326
|
+
return Object.keys(theme.blur);
|
|
327
|
+
case "animation":
|
|
328
|
+
return Object.keys(theme.animations);
|
|
329
|
+
case "leading":
|
|
330
|
+
return Object.keys(theme.leading);
|
|
331
|
+
case "tracking":
|
|
332
|
+
return Object.keys(theme.tracking);
|
|
333
|
+
case "opacity":
|
|
334
|
+
return Object.keys(theme.opacity);
|
|
335
|
+
case "duration":
|
|
336
|
+
return [.../* @__PURE__ */ new Set([...Object.keys(theme.duration), ...DURATION_SAMPLES])];
|
|
337
|
+
case "breakpoint":
|
|
338
|
+
return Object.keys(theme.breakpoints);
|
|
339
|
+
case "int":
|
|
340
|
+
return [...INT_SAMPLES];
|
|
341
|
+
case "percent":
|
|
342
|
+
return [...PERCENT_SAMPLES];
|
|
343
|
+
case "keywords":
|
|
344
|
+
return [];
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
function enumerateClassNames(theme) {
|
|
348
|
+
const seen = /* @__PURE__ */ new Set();
|
|
349
|
+
const classes = [];
|
|
350
|
+
const templates = [];
|
|
351
|
+
const probeWarnings = [];
|
|
352
|
+
const resolves = (name) => resolveUtilityDeclarations(parseUtility(name), theme, probeWarnings) !== null;
|
|
353
|
+
const emit = (name, kind, root) => {
|
|
354
|
+
if (seen.has(name)) return;
|
|
355
|
+
if (!resolves(name)) return;
|
|
356
|
+
seen.add(name);
|
|
357
|
+
classes.push({ name, kind, root });
|
|
358
|
+
};
|
|
359
|
+
for (const name of STATIC_UTILITIES) emit(name, "static", null);
|
|
360
|
+
for (const names of [
|
|
361
|
+
ANIMATION_STATIC_NAMES,
|
|
362
|
+
BORDER_STATIC_NAMES,
|
|
363
|
+
BACKGROUND_STATIC_NAMES,
|
|
364
|
+
EFFECTS_STATIC_NAMES,
|
|
365
|
+
LAYOUT_STATIC_NAMES,
|
|
366
|
+
SVG_STATIC_NAMES,
|
|
367
|
+
TYPOGRAPHY_STATIC_NAMES
|
|
368
|
+
]) {
|
|
369
|
+
for (const name of names) emit(name, "static", null);
|
|
370
|
+
}
|
|
371
|
+
for (const custom of theme.customUtilities) {
|
|
372
|
+
if (custom.functional) {
|
|
373
|
+
templates.push({ root: custom.name, kind: "custom", example: `${custom.name}-value` });
|
|
374
|
+
} else {
|
|
375
|
+
emit(custom.name, "custom", null);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
for (const root of PREFIX_DISPATCH.keys()) {
|
|
379
|
+
const spec = UTILITY_VALUE_SPACES.get(root);
|
|
380
|
+
if (!spec) continue;
|
|
381
|
+
let spacingHit = false;
|
|
382
|
+
let intHit = false;
|
|
383
|
+
for (const kind of spec.kinds) {
|
|
384
|
+
for (const value of candidateValues(kind, theme)) {
|
|
385
|
+
const name = `${root}-${value}`;
|
|
386
|
+
if (seen.has(name)) continue;
|
|
387
|
+
if (!resolves(name)) continue;
|
|
388
|
+
seen.add(name);
|
|
389
|
+
classes.push({ name, kind, root });
|
|
390
|
+
if (kind === "spacing") spacingHit = true;
|
|
391
|
+
if (kind === "int" || kind === "weight" && INT_RE.test(value)) intHit = true;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
for (const keyword of spec.keywords ?? []) {
|
|
395
|
+
emit(`${root}-${keyword}`, "keywords", root);
|
|
396
|
+
}
|
|
397
|
+
if (spacingHit) templates.push({ root, kind: "spacing", example: `${root}-4` });
|
|
398
|
+
else if (intHit) templates.push({ root, kind: "number", example: `${root}-2` });
|
|
399
|
+
}
|
|
400
|
+
classes.sort((a, b) => codepointCompare(a.name, b.name));
|
|
401
|
+
templates.sort((a, b) => codepointCompare(a.root, b.root));
|
|
402
|
+
return { classes, templates };
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// src/engine/inspector.ts
|
|
406
|
+
var RESOLUTION_CACHE_CAP = 1e4;
|
|
407
|
+
var OK = Object.freeze({ ok: true });
|
|
408
|
+
function createClassInspector(theme) {
|
|
409
|
+
const customVariantMap = new Map(theme.customVariants.map((cv) => [cv.name, cv]));
|
|
410
|
+
const breakpointWeights = buildBreakpointWeights(theme.breakpoints);
|
|
411
|
+
const variantMemo = /* @__PURE__ */ new Map();
|
|
412
|
+
const scratch = createEmptyCompilationResult();
|
|
413
|
+
const warnSeen = /* @__PURE__ */ new Set();
|
|
414
|
+
const detail = { reason: null, variant: null, declarations: null };
|
|
415
|
+
const cache = /* @__PURE__ */ new Map();
|
|
416
|
+
let variantList = null;
|
|
417
|
+
let variantNames = null;
|
|
418
|
+
let utilityCorpus = null;
|
|
419
|
+
function variants() {
|
|
420
|
+
if (!variantList) variantList = Object.freeze(listVariants(theme));
|
|
421
|
+
return variantList;
|
|
422
|
+
}
|
|
423
|
+
function variantSuggestionCorpus() {
|
|
424
|
+
if (!variantNames) {
|
|
425
|
+
const names = [];
|
|
426
|
+
for (const v of variants()) {
|
|
427
|
+
if (v.kind !== "pattern") names.push(v.name);
|
|
428
|
+
}
|
|
429
|
+
variantNames = names;
|
|
430
|
+
}
|
|
431
|
+
return variantNames;
|
|
432
|
+
}
|
|
433
|
+
function utilitySuggestionCorpus() {
|
|
434
|
+
if (!utilityCorpus) {
|
|
435
|
+
const names = new Set(STATIC_UTILITIES);
|
|
436
|
+
for (const custom of theme.customUtilities) {
|
|
437
|
+
if (!custom.functional) names.add(custom.name);
|
|
438
|
+
}
|
|
439
|
+
for (const entry of enumerateClassNames(theme).classes) names.add(entry.name);
|
|
440
|
+
utilityCorpus = [...names];
|
|
441
|
+
}
|
|
442
|
+
return utilityCorpus;
|
|
443
|
+
}
|
|
444
|
+
function baseName(raw, parsed) {
|
|
445
|
+
let base = raw;
|
|
446
|
+
if (parsed.variants.length > 0) {
|
|
447
|
+
const prefix = `${parsed.variants.join(":")}:`;
|
|
448
|
+
if (base.startsWith(prefix)) base = base.slice(prefix.length);
|
|
449
|
+
}
|
|
450
|
+
if (parsed.important && base.endsWith("!")) base = base.slice(0, -1);
|
|
451
|
+
return base;
|
|
452
|
+
}
|
|
453
|
+
function resolve(className) {
|
|
454
|
+
const cached = cache.get(className);
|
|
455
|
+
if (cached) return cached;
|
|
456
|
+
if (cache.size >= RESOLUTION_CACHE_CAP) {
|
|
457
|
+
cache.clear();
|
|
458
|
+
variantMemo.clear();
|
|
459
|
+
}
|
|
460
|
+
scratch.warnings.length = 0;
|
|
461
|
+
warnSeen.clear();
|
|
462
|
+
const parsed = parseUtility(className);
|
|
463
|
+
const rule = compileUtility(
|
|
464
|
+
parsed,
|
|
465
|
+
theme,
|
|
466
|
+
scratch,
|
|
467
|
+
customVariantMap,
|
|
468
|
+
warnSeen,
|
|
469
|
+
breakpointWeights,
|
|
470
|
+
variantMemo,
|
|
471
|
+
detail
|
|
472
|
+
);
|
|
473
|
+
let entry;
|
|
474
|
+
if (rule) {
|
|
475
|
+
entry = {
|
|
476
|
+
validation: OK,
|
|
477
|
+
explanation: {
|
|
478
|
+
parsed,
|
|
479
|
+
declarations: detail.declarations ? [...detail.declarations] : [],
|
|
480
|
+
selector: rule.selector,
|
|
481
|
+
css: rule.css,
|
|
482
|
+
sortKey: rule.sortKey
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
} else if (detail.reason === "marker") {
|
|
486
|
+
entry = {
|
|
487
|
+
validation: OK,
|
|
488
|
+
explanation: {
|
|
489
|
+
parsed,
|
|
490
|
+
declarations: [],
|
|
491
|
+
selector: `.${escapeSelector(parsed.utility)}`,
|
|
492
|
+
css: "",
|
|
493
|
+
sortKey: 0,
|
|
494
|
+
marker: true
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
} else if (detail.reason === "unknown-variant" && detail.variant !== null) {
|
|
498
|
+
const suggestion = findClosest(detail.variant, variantSuggestionCorpus());
|
|
499
|
+
entry = {
|
|
500
|
+
validation: {
|
|
501
|
+
ok: false,
|
|
502
|
+
reason: "unknown-variant",
|
|
503
|
+
offender: detail.variant,
|
|
504
|
+
...suggestion ? { suggestion } : {}
|
|
505
|
+
},
|
|
506
|
+
explanation: null
|
|
507
|
+
};
|
|
508
|
+
} else {
|
|
509
|
+
const base = baseName(className, parsed);
|
|
510
|
+
if (parsed.arbitrary || parsed.arbitraryProperty !== null) {
|
|
511
|
+
entry = {
|
|
512
|
+
validation: { ok: false, reason: "invalid-arbitrary", offender: base },
|
|
513
|
+
explanation: null
|
|
514
|
+
};
|
|
515
|
+
} else {
|
|
516
|
+
const suggestion = findClosest(base, utilitySuggestionCorpus());
|
|
517
|
+
entry = {
|
|
518
|
+
validation: {
|
|
519
|
+
ok: false,
|
|
520
|
+
reason: "unknown-utility",
|
|
521
|
+
offender: base,
|
|
522
|
+
...suggestion ? { suggestion } : {}
|
|
523
|
+
},
|
|
524
|
+
explanation: null
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
cache.set(className, entry);
|
|
529
|
+
return entry;
|
|
530
|
+
}
|
|
531
|
+
return {
|
|
532
|
+
theme,
|
|
533
|
+
validate: (className) => resolve(className).validation,
|
|
534
|
+
explain: (className) => resolve(className).explanation,
|
|
535
|
+
variants
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// src/editor/candidates.ts
|
|
540
|
+
function lastIndexWithStart(starts, value, inclusive) {
|
|
541
|
+
let low = 0;
|
|
542
|
+
let high = starts.length - 1;
|
|
543
|
+
let found = -1;
|
|
544
|
+
while (low <= high) {
|
|
545
|
+
const mid = low + high >> 1;
|
|
546
|
+
if (inclusive ? starts[mid] <= value : starts[mid] < value) {
|
|
547
|
+
found = mid;
|
|
548
|
+
low = mid + 1;
|
|
549
|
+
} else {
|
|
550
|
+
high = mid - 1;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return found;
|
|
554
|
+
}
|
|
555
|
+
function outermostCandidates(candidates) {
|
|
556
|
+
if (candidates.length < 2) return [...candidates];
|
|
557
|
+
const spans = [];
|
|
558
|
+
for (const candidate of candidates) {
|
|
559
|
+
spans.push({ start: candidate.start, end: candidate.end });
|
|
560
|
+
if (candidate.groupPrefix) spans.push(candidate.groupPrefix);
|
|
561
|
+
}
|
|
562
|
+
spans.sort((a, b) => a.start - b.start || a.end - b.end);
|
|
563
|
+
const starts = spans.map((span) => span.start);
|
|
564
|
+
const prefixMaxEnd = new Array(spans.length);
|
|
565
|
+
let running = Number.NEGATIVE_INFINITY;
|
|
566
|
+
for (let i = 0; i < spans.length; i++) {
|
|
567
|
+
running = Math.max(running, spans[i].end);
|
|
568
|
+
prefixMaxEnd[i] = running;
|
|
569
|
+
}
|
|
570
|
+
const seenSpans = /* @__PURE__ */ new Set();
|
|
571
|
+
const kept = [];
|
|
572
|
+
for (const candidate of candidates) {
|
|
573
|
+
const atOrBefore = lastIndexWithStart(starts, candidate.start, true);
|
|
574
|
+
const before = lastIndexWithStart(starts, candidate.start, false);
|
|
575
|
+
const reachAtOrBefore = atOrBefore === -1 ? Number.NEGATIVE_INFINITY : prefixMaxEnd[atOrBefore];
|
|
576
|
+
const reachBefore = before === -1 ? Number.NEGATIVE_INFINITY : prefixMaxEnd[before];
|
|
577
|
+
if (reachAtOrBefore > candidate.end || reachBefore >= candidate.end) continue;
|
|
578
|
+
const key = `${candidate.start}:${candidate.end}`;
|
|
579
|
+
if (seenSpans.has(key)) continue;
|
|
580
|
+
seenSpans.add(key);
|
|
581
|
+
kept.push(candidate);
|
|
582
|
+
}
|
|
583
|
+
kept.sort((a, b) => a.start - b.start);
|
|
584
|
+
return kept;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
export {
|
|
588
|
+
CSS_ENTRY_CANDIDATES,
|
|
589
|
+
CANONICAL_COLOR_STOPS,
|
|
590
|
+
oklchToHex,
|
|
591
|
+
cssColorToHex,
|
|
592
|
+
resolveColorSwatch,
|
|
593
|
+
listThemeTokens,
|
|
594
|
+
UTILITY_VALUE_SPACES,
|
|
595
|
+
enumerateClassNames,
|
|
596
|
+
createClassInspector,
|
|
597
|
+
outermostCandidates
|
|
598
|
+
};
|