@kbach/react 1.0.0-beta.0 → 1.0.0-beta.10
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/README.md +216 -73
- package/dist/chunk-4Y2QXNJY.mjs +115 -0
- package/dist/{chunk-AFY36PRX.mjs → chunk-EOSN5CYG.mjs} +69 -10
- package/dist/chunk-J2M6QWJW.mjs +1385 -0
- package/dist/{chunk-VBPQAIZL.mjs → chunk-L6B4DTLD.mjs} +1 -1
- package/dist/{chunk-G3RJJNSY.mjs → chunk-ROKZPEHA.mjs} +1 -1
- package/dist/config-BQ_b-qxF.d.mts +105 -0
- package/dist/config-BQ_b-qxF.d.ts +105 -0
- package/dist/index.d.mts +65 -34
- package/dist/index.d.ts +65 -34
- package/dist/index.js +260 -44
- package/dist/index.mjs +90 -33
- package/dist/jsx-dev-runtime.js +69 -10
- package/dist/jsx-dev-runtime.mjs +3 -3
- package/dist/jsx-runtime.js +69 -10
- package/dist/jsx-runtime.mjs +3 -3
- package/dist/postcss-plugin.d.mts +36 -0
- package/dist/postcss-plugin.d.ts +36 -0
- package/dist/postcss-plugin.js +1152 -0
- package/dist/postcss-plugin.mjs +79 -0
- package/dist/vite-plugin.d.mts +108 -6
- package/dist/vite-plugin.d.ts +108 -6
- package/dist/vite-plugin.js +545 -226
- package/dist/vite-plugin.mjs +15 -1181
- package/package.json +13 -2
- package/dist/theme-BKAb78KP.d.mts +0 -20
- package/dist/theme-BKAb78KP.d.ts +0 -20
|
@@ -0,0 +1,1385 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveKbachConfig
|
|
3
|
+
} from "./chunk-4Y2QXNJY.mjs";
|
|
4
|
+
import {
|
|
5
|
+
buildResetCSS,
|
|
6
|
+
defaultTheme
|
|
7
|
+
} from "./chunk-EOSN5CYG.mjs";
|
|
8
|
+
|
|
9
|
+
// src/vite-plugin/index.ts
|
|
10
|
+
import { readFileSync as readFileSync3, writeFileSync, mkdirSync, existsSync, statSync as statSync2 } from "fs";
|
|
11
|
+
import { join as join4, dirname } from "path";
|
|
12
|
+
import { pathToFileURL } from "url";
|
|
13
|
+
import { createRequire } from "module";
|
|
14
|
+
|
|
15
|
+
// src/vite-plugin/cssVars.ts
|
|
16
|
+
function hexToRgbTriplet(hex) {
|
|
17
|
+
const h = hex.replace("#", "");
|
|
18
|
+
const expand = (s) => s.length === 3 ? s.split("").map((c) => c + c).join("") : s;
|
|
19
|
+
const full = expand(h);
|
|
20
|
+
if (full.length !== 6) return null;
|
|
21
|
+
const r = parseInt(full.slice(0, 2), 16);
|
|
22
|
+
const g = parseInt(full.slice(2, 4), 16);
|
|
23
|
+
const b = parseInt(full.slice(4, 6), 16);
|
|
24
|
+
if ([r, g, b].some((n) => Number.isNaN(n))) return null;
|
|
25
|
+
return `${r},${g},${b}`;
|
|
26
|
+
}
|
|
27
|
+
function buildColorVarMap(theme, cssText) {
|
|
28
|
+
const replacements = /* @__PURE__ */ new Map();
|
|
29
|
+
const declarations = /* @__PURE__ */ new Map();
|
|
30
|
+
for (const [name, value] of Object.entries(theme.colors)) {
|
|
31
|
+
if (typeof value !== "string") continue;
|
|
32
|
+
const varName = `--color-${name}`;
|
|
33
|
+
if (cssText.includes(value)) {
|
|
34
|
+
replacements.set(value, `var(${varName})`);
|
|
35
|
+
declarations.set(varName, value);
|
|
36
|
+
}
|
|
37
|
+
const triplet = hexToRgbTriplet(value);
|
|
38
|
+
if (!triplet) continue;
|
|
39
|
+
const rgbaPrefix = `rgba(${triplet},`;
|
|
40
|
+
if (cssText.includes(rgbaPrefix)) {
|
|
41
|
+
const rgbVarName = `--color-${name}-rgb`;
|
|
42
|
+
replacements.set(rgbaPrefix, `rgba(var(${rgbVarName}),`);
|
|
43
|
+
declarations.set(rgbVarName, triplet);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { replacements, declarations };
|
|
47
|
+
}
|
|
48
|
+
var SPACING_PROPS = /* @__PURE__ */ new Set([
|
|
49
|
+
"padding",
|
|
50
|
+
"padding-top",
|
|
51
|
+
"padding-right",
|
|
52
|
+
"padding-bottom",
|
|
53
|
+
"padding-left",
|
|
54
|
+
"margin",
|
|
55
|
+
"margin-top",
|
|
56
|
+
"margin-right",
|
|
57
|
+
"margin-bottom",
|
|
58
|
+
"margin-left",
|
|
59
|
+
"gap",
|
|
60
|
+
"column-gap",
|
|
61
|
+
"row-gap",
|
|
62
|
+
"width",
|
|
63
|
+
"height",
|
|
64
|
+
"min-width",
|
|
65
|
+
"min-height",
|
|
66
|
+
"max-width",
|
|
67
|
+
"max-height",
|
|
68
|
+
"top",
|
|
69
|
+
"right",
|
|
70
|
+
"bottom",
|
|
71
|
+
"left"
|
|
72
|
+
]);
|
|
73
|
+
function buildSpacingVarMap(theme, cssText) {
|
|
74
|
+
const replacements = /* @__PURE__ */ new Map();
|
|
75
|
+
const declarations = /* @__PURE__ */ new Map();
|
|
76
|
+
const pxToKey = /* @__PURE__ */ new Map();
|
|
77
|
+
for (const [key, val] of Object.entries(theme.spacing)) {
|
|
78
|
+
if (!pxToKey.has(val)) pxToKey.set(val, key);
|
|
79
|
+
}
|
|
80
|
+
const varNameFor = (key) => `--spacing-${key.replace(/\./g, "_")}`;
|
|
81
|
+
const declRe = /([a-z-]+): (\d+(?:\.\d+)?)px/g;
|
|
82
|
+
let m;
|
|
83
|
+
while ((m = declRe.exec(cssText)) !== null) {
|
|
84
|
+
const [, prop, numStr] = m;
|
|
85
|
+
if (!SPACING_PROPS.has(prop)) continue;
|
|
86
|
+
const key = pxToKey.get(parseFloat(numStr));
|
|
87
|
+
if (key === void 0) continue;
|
|
88
|
+
const varName = varNameFor(key);
|
|
89
|
+
replacements.set(`${prop}: ${numStr}px`, `${prop}: var(${varName})`);
|
|
90
|
+
declarations.set(varName, `${numStr}px`);
|
|
91
|
+
}
|
|
92
|
+
return { replacements, declarations };
|
|
93
|
+
}
|
|
94
|
+
function applyVarMap(cssText, ...maps) {
|
|
95
|
+
const replacements = /* @__PURE__ */ new Map();
|
|
96
|
+
const declarations = /* @__PURE__ */ new Map();
|
|
97
|
+
for (const map of maps) {
|
|
98
|
+
for (const [k, v] of map.replacements) replacements.set(k, v);
|
|
99
|
+
for (const [k, v] of map.declarations) declarations.set(k, v);
|
|
100
|
+
}
|
|
101
|
+
const sorted = [...replacements].sort(([a], [b]) => b.length - a.length);
|
|
102
|
+
const escapeRegex = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
103
|
+
const patterns = sorted.map(([pattern, replacement]) => [new RegExp(escapeRegex(pattern), "g"), replacement]);
|
|
104
|
+
const text = cssText.replace(/\{([^{}]*)\}/g, (_whole, inner) => {
|
|
105
|
+
let replaced = inner;
|
|
106
|
+
for (const [re, replacement] of patterns) {
|
|
107
|
+
replaced = replaced.replace(re, () => replacement);
|
|
108
|
+
}
|
|
109
|
+
return `{${replaced}}`;
|
|
110
|
+
});
|
|
111
|
+
return { text, declarations };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// src/vite-plugin/mediaMerge.ts
|
|
115
|
+
var RESPONSIVE_MEDIA_RE = /^@media \(min-width: (\d+)px\) \{ (.+) \}$/;
|
|
116
|
+
function mergeResponsiveMediaBlocks(rules) {
|
|
117
|
+
const byWidth = /* @__PURE__ */ new Map();
|
|
118
|
+
const widthOrder = [];
|
|
119
|
+
const unwrapped = [];
|
|
120
|
+
for (const rule of rules) {
|
|
121
|
+
const m = RESPONSIVE_MEDIA_RE.exec(rule);
|
|
122
|
+
if (!m) {
|
|
123
|
+
unwrapped.push(rule);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const width = Number(m[1]);
|
|
127
|
+
if (!byWidth.has(width)) {
|
|
128
|
+
byWidth.set(width, []);
|
|
129
|
+
widthOrder.push(width);
|
|
130
|
+
}
|
|
131
|
+
byWidth.get(width).push(m[2]);
|
|
132
|
+
}
|
|
133
|
+
widthOrder.sort((a, b) => a - b);
|
|
134
|
+
const merged = widthOrder.map((w) => `@media (min-width: ${w}px) { ${byWidth.get(w).join(" ")} }`);
|
|
135
|
+
return [...unwrapped, ...merged];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// src/vite-plugin/prettify.ts
|
|
139
|
+
function prettifyCSS(css) {
|
|
140
|
+
const out = [];
|
|
141
|
+
let depth = 0;
|
|
142
|
+
let current = "";
|
|
143
|
+
for (const ch of css) {
|
|
144
|
+
if (ch === "{") {
|
|
145
|
+
const selector = current.trim();
|
|
146
|
+
if (selector) out.push(`${" ".repeat(depth)}${selector} {`);
|
|
147
|
+
depth++;
|
|
148
|
+
current = "";
|
|
149
|
+
} else if (ch === "}") {
|
|
150
|
+
const decl = current.trim();
|
|
151
|
+
if (decl) out.push(`${" ".repeat(depth)}${decl};`);
|
|
152
|
+
depth = Math.max(0, depth - 1);
|
|
153
|
+
out.push(`${" ".repeat(depth)}}`);
|
|
154
|
+
current = "";
|
|
155
|
+
} else if (ch === ";") {
|
|
156
|
+
const decl = current.trim();
|
|
157
|
+
if (decl) out.push(`${" ".repeat(depth)}${decl};`);
|
|
158
|
+
current = "";
|
|
159
|
+
} else {
|
|
160
|
+
current += ch;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const trailing = current.trim();
|
|
164
|
+
if (trailing) out.push(trailing);
|
|
165
|
+
return out.join("\n");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// src/vite-plugin/format.ts
|
|
169
|
+
var KBACH_START = "/* kbach:start */";
|
|
170
|
+
var KBACH_END = "/* kbach:end */";
|
|
171
|
+
function formatKbachCSS(tokenRules, theme, usedTags) {
|
|
172
|
+
const allEntries = [];
|
|
173
|
+
for (const rules of tokenRules.values()) {
|
|
174
|
+
for (const entry of rules) allEntries.push(entry);
|
|
175
|
+
}
|
|
176
|
+
allEntries.sort((a, b) => a.order - b.order);
|
|
177
|
+
const allRules = allEntries.map((e) => e.rule);
|
|
178
|
+
const merged = mergeResponsiveMediaBlocks(allRules);
|
|
179
|
+
const compact = merged.join("\n");
|
|
180
|
+
const colorMap = buildColorVarMap(theme, compact);
|
|
181
|
+
const spacingMap = buildSpacingVarMap(theme, compact);
|
|
182
|
+
const { text, declarations } = applyVarMap(compact, colorMap, spacingMap);
|
|
183
|
+
const lines = ["/* Generated by Kbach \u2014 do not edit */", "", buildResetCSS(usedTags)];
|
|
184
|
+
if (declarations.size > 0) {
|
|
185
|
+
lines.push("", ":root {");
|
|
186
|
+
for (const [varName, val] of declarations) lines.push(` ${varName}: ${val};`);
|
|
187
|
+
lines.push("}");
|
|
188
|
+
}
|
|
189
|
+
lines.push("", prettifyCSS(text));
|
|
190
|
+
return lines.join("\n");
|
|
191
|
+
}
|
|
192
|
+
function writeKbachToFile(filePath, css, readFile, writeFile) {
|
|
193
|
+
let existing = "";
|
|
194
|
+
try {
|
|
195
|
+
existing = readFile(filePath);
|
|
196
|
+
} catch {
|
|
197
|
+
}
|
|
198
|
+
const block = `${KBACH_START}
|
|
199
|
+
${css}
|
|
200
|
+
${KBACH_END}`;
|
|
201
|
+
const start = existing.indexOf(KBACH_START);
|
|
202
|
+
const end = existing.indexOf(KBACH_END);
|
|
203
|
+
const next = start !== -1 && end !== -1 && end > start ? existing.slice(0, start) + block + existing.slice(end + KBACH_END.length) : existing ? `${existing}
|
|
204
|
+
|
|
205
|
+
${block}` : block;
|
|
206
|
+
if (next === existing) return false;
|
|
207
|
+
writeFile(filePath, next);
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// src/vite-plugin/classNameHints.ts
|
|
212
|
+
var STRUCTURAL_TOKENS = [
|
|
213
|
+
// layout.rs
|
|
214
|
+
"flex",
|
|
215
|
+
"flex-row",
|
|
216
|
+
"flex-col",
|
|
217
|
+
"flex-row-reverse",
|
|
218
|
+
"flex-col-reverse",
|
|
219
|
+
"flex-wrap",
|
|
220
|
+
"flex-wrap-reverse",
|
|
221
|
+
"flex-nowrap",
|
|
222
|
+
"flex-1",
|
|
223
|
+
"flex-auto",
|
|
224
|
+
"flex-initial",
|
|
225
|
+
"flex-none",
|
|
226
|
+
"flex-grow",
|
|
227
|
+
"flex-grow-0",
|
|
228
|
+
"flex-shrink",
|
|
229
|
+
"flex-shrink-0",
|
|
230
|
+
"grow",
|
|
231
|
+
"grow-0",
|
|
232
|
+
"shrink",
|
|
233
|
+
"shrink-0",
|
|
234
|
+
"grid",
|
|
235
|
+
"block",
|
|
236
|
+
"inline-block",
|
|
237
|
+
"inline",
|
|
238
|
+
"inline-flex",
|
|
239
|
+
"inline-grid",
|
|
240
|
+
"contents",
|
|
241
|
+
"flow-root",
|
|
242
|
+
"hidden",
|
|
243
|
+
"items-center",
|
|
244
|
+
"items-start",
|
|
245
|
+
"items-end",
|
|
246
|
+
"items-baseline",
|
|
247
|
+
"items-stretch",
|
|
248
|
+
"justify-center",
|
|
249
|
+
"justify-start",
|
|
250
|
+
"justify-end",
|
|
251
|
+
"justify-between",
|
|
252
|
+
"justify-around",
|
|
253
|
+
"justify-evenly",
|
|
254
|
+
"content-start",
|
|
255
|
+
"content-end",
|
|
256
|
+
"content-center",
|
|
257
|
+
"content-between",
|
|
258
|
+
"content-around",
|
|
259
|
+
"content-evenly",
|
|
260
|
+
"content-stretch",
|
|
261
|
+
"self-auto",
|
|
262
|
+
"self-center",
|
|
263
|
+
"self-start",
|
|
264
|
+
"self-end",
|
|
265
|
+
"self-stretch",
|
|
266
|
+
"self-baseline",
|
|
267
|
+
"overflow-hidden",
|
|
268
|
+
"overflow-auto",
|
|
269
|
+
"overflow-scroll",
|
|
270
|
+
"overflow-visible",
|
|
271
|
+
"static",
|
|
272
|
+
"relative",
|
|
273
|
+
"absolute",
|
|
274
|
+
"fixed",
|
|
275
|
+
"sticky",
|
|
276
|
+
"aspect-square",
|
|
277
|
+
"aspect-video",
|
|
278
|
+
"w-full",
|
|
279
|
+
"h-full",
|
|
280
|
+
"min-w-full",
|
|
281
|
+
"max-w-full",
|
|
282
|
+
"min-h-full",
|
|
283
|
+
"max-h-full",
|
|
284
|
+
"w-screen",
|
|
285
|
+
"h-screen",
|
|
286
|
+
"min-w-screen",
|
|
287
|
+
"max-w-screen",
|
|
288
|
+
"min-h-screen",
|
|
289
|
+
"max-h-screen",
|
|
290
|
+
"w-auto",
|
|
291
|
+
"h-auto",
|
|
292
|
+
"m-auto",
|
|
293
|
+
"mx-auto",
|
|
294
|
+
"my-auto",
|
|
295
|
+
// grid.rs — web-only (see the module's own doc comment for why)
|
|
296
|
+
"grid-cols-none",
|
|
297
|
+
"grid-rows-none",
|
|
298
|
+
"grid-flow-row",
|
|
299
|
+
"grid-flow-col",
|
|
300
|
+
"grid-flow-dense",
|
|
301
|
+
"grid-flow-row-dense",
|
|
302
|
+
"grid-flow-col-dense",
|
|
303
|
+
"auto-cols-auto",
|
|
304
|
+
"auto-cols-min",
|
|
305
|
+
"auto-cols-max",
|
|
306
|
+
"auto-cols-fr",
|
|
307
|
+
"auto-rows-auto",
|
|
308
|
+
"auto-rows-min",
|
|
309
|
+
"auto-rows-max",
|
|
310
|
+
"auto-rows-fr",
|
|
311
|
+
"col-span-full",
|
|
312
|
+
"row-span-full",
|
|
313
|
+
"col-start-auto",
|
|
314
|
+
"col-end-auto",
|
|
315
|
+
"row-start-auto",
|
|
316
|
+
"row-end-auto",
|
|
317
|
+
"col",
|
|
318
|
+
"col-auto",
|
|
319
|
+
"row",
|
|
320
|
+
"row-auto",
|
|
321
|
+
"place-items-start",
|
|
322
|
+
"place-items-end",
|
|
323
|
+
"place-items-center",
|
|
324
|
+
"place-items-stretch",
|
|
325
|
+
"place-items-baseline",
|
|
326
|
+
"place-content-start",
|
|
327
|
+
"place-content-end",
|
|
328
|
+
"place-content-center",
|
|
329
|
+
"place-content-stretch",
|
|
330
|
+
"place-content-between",
|
|
331
|
+
"place-content-around",
|
|
332
|
+
"place-content-evenly",
|
|
333
|
+
"place-content-baseline",
|
|
334
|
+
"place-self-auto",
|
|
335
|
+
"place-self-start",
|
|
336
|
+
"place-self-end",
|
|
337
|
+
"place-self-center",
|
|
338
|
+
"place-self-stretch",
|
|
339
|
+
"justify-items-start",
|
|
340
|
+
"justify-items-end",
|
|
341
|
+
"justify-items-center",
|
|
342
|
+
"justify-items-stretch",
|
|
343
|
+
"justify-self-auto",
|
|
344
|
+
"justify-self-start",
|
|
345
|
+
"justify-self-end",
|
|
346
|
+
"justify-self-center",
|
|
347
|
+
"justify-self-stretch",
|
|
348
|
+
// transform.rs — web-only (see the module's own doc comment for why)
|
|
349
|
+
"transform-none",
|
|
350
|
+
"origin-center",
|
|
351
|
+
"origin-top",
|
|
352
|
+
"origin-top-right",
|
|
353
|
+
"origin-right",
|
|
354
|
+
"origin-bottom-right",
|
|
355
|
+
"origin-bottom",
|
|
356
|
+
"origin-bottom-left",
|
|
357
|
+
"origin-left",
|
|
358
|
+
"origin-top-left",
|
|
359
|
+
// filters.rs — web-only (see the module's own doc comment for why)
|
|
360
|
+
"blur",
|
|
361
|
+
"blur-sm",
|
|
362
|
+
"blur-md",
|
|
363
|
+
"blur-lg",
|
|
364
|
+
"blur-xl",
|
|
365
|
+
"blur-2xl",
|
|
366
|
+
"blur-3xl",
|
|
367
|
+
"blur-none",
|
|
368
|
+
"grayscale",
|
|
369
|
+
"grayscale-0",
|
|
370
|
+
"invert",
|
|
371
|
+
"invert-0",
|
|
372
|
+
"sepia",
|
|
373
|
+
"sepia-0",
|
|
374
|
+
"drop-shadow",
|
|
375
|
+
"drop-shadow-sm",
|
|
376
|
+
"drop-shadow-md",
|
|
377
|
+
"drop-shadow-lg",
|
|
378
|
+
"drop-shadow-xl",
|
|
379
|
+
"drop-shadow-2xl",
|
|
380
|
+
"drop-shadow-none",
|
|
381
|
+
"filter-none",
|
|
382
|
+
"backdrop-filter-none",
|
|
383
|
+
"backdrop-blur",
|
|
384
|
+
"backdrop-blur-sm",
|
|
385
|
+
"backdrop-blur-md",
|
|
386
|
+
"backdrop-blur-lg",
|
|
387
|
+
"backdrop-blur-xl",
|
|
388
|
+
"backdrop-blur-2xl",
|
|
389
|
+
"backdrop-blur-3xl",
|
|
390
|
+
"backdrop-blur-none",
|
|
391
|
+
"backdrop-grayscale",
|
|
392
|
+
"backdrop-grayscale-0",
|
|
393
|
+
"backdrop-invert",
|
|
394
|
+
"backdrop-invert-0",
|
|
395
|
+
"backdrop-sepia",
|
|
396
|
+
"backdrop-sepia-0",
|
|
397
|
+
// border.rs
|
|
398
|
+
"border",
|
|
399
|
+
"border-t",
|
|
400
|
+
"border-r",
|
|
401
|
+
"border-b",
|
|
402
|
+
"border-l",
|
|
403
|
+
"rounded",
|
|
404
|
+
"rounded-none",
|
|
405
|
+
"rounded-sm",
|
|
406
|
+
"rounded-md",
|
|
407
|
+
"rounded-lg",
|
|
408
|
+
"rounded-xl",
|
|
409
|
+
"rounded-2xl",
|
|
410
|
+
"rounded-3xl",
|
|
411
|
+
"rounded-full",
|
|
412
|
+
"ring",
|
|
413
|
+
"ring-0",
|
|
414
|
+
"ring-1",
|
|
415
|
+
"ring-2",
|
|
416
|
+
"ring-4",
|
|
417
|
+
"ring-8",
|
|
418
|
+
"ring-inset",
|
|
419
|
+
"ring-offset-0",
|
|
420
|
+
"ring-offset-1",
|
|
421
|
+
"ring-offset-2",
|
|
422
|
+
"ring-offset-4",
|
|
423
|
+
"ring-offset-8",
|
|
424
|
+
"outline",
|
|
425
|
+
"outline-none",
|
|
426
|
+
"border-solid",
|
|
427
|
+
"border-dashed",
|
|
428
|
+
"border-dotted",
|
|
429
|
+
"border-none",
|
|
430
|
+
// typography.rs
|
|
431
|
+
"font-thin",
|
|
432
|
+
"font-normal",
|
|
433
|
+
"font-medium",
|
|
434
|
+
"font-semibold",
|
|
435
|
+
"font-bold",
|
|
436
|
+
"font-extrabold",
|
|
437
|
+
"uppercase",
|
|
438
|
+
"lowercase",
|
|
439
|
+
"capitalize",
|
|
440
|
+
"underline",
|
|
441
|
+
"line-through",
|
|
442
|
+
"no-underline",
|
|
443
|
+
"truncate",
|
|
444
|
+
"text-xs",
|
|
445
|
+
"text-sm",
|
|
446
|
+
"text-base",
|
|
447
|
+
"text-lg",
|
|
448
|
+
"text-xl",
|
|
449
|
+
"text-2xl",
|
|
450
|
+
"text-3xl",
|
|
451
|
+
"text-4xl",
|
|
452
|
+
"text-left",
|
|
453
|
+
"text-center",
|
|
454
|
+
"text-right",
|
|
455
|
+
"text-justify",
|
|
456
|
+
// typography.rs — Phase 20 (typography completeness)
|
|
457
|
+
"italic",
|
|
458
|
+
"not-italic",
|
|
459
|
+
"leading-none",
|
|
460
|
+
"leading-tight",
|
|
461
|
+
"leading-snug",
|
|
462
|
+
"leading-normal",
|
|
463
|
+
"leading-relaxed",
|
|
464
|
+
"leading-loose",
|
|
465
|
+
"tracking-tighter",
|
|
466
|
+
"tracking-tight",
|
|
467
|
+
"tracking-normal",
|
|
468
|
+
"tracking-wide",
|
|
469
|
+
"tracking-wider",
|
|
470
|
+
"tracking-widest",
|
|
471
|
+
"decoration-auto",
|
|
472
|
+
"decoration-from-font",
|
|
473
|
+
"decoration-solid",
|
|
474
|
+
"decoration-dashed",
|
|
475
|
+
"decoration-dotted",
|
|
476
|
+
"decoration-double",
|
|
477
|
+
"decoration-wavy",
|
|
478
|
+
"underline-offset-auto",
|
|
479
|
+
"underline-offset-0",
|
|
480
|
+
"underline-offset-1",
|
|
481
|
+
"underline-offset-2",
|
|
482
|
+
"underline-offset-4",
|
|
483
|
+
"underline-offset-8",
|
|
484
|
+
"text-wrap",
|
|
485
|
+
"text-nowrap",
|
|
486
|
+
"text-balance",
|
|
487
|
+
"text-pretty",
|
|
488
|
+
"whitespace-normal",
|
|
489
|
+
"whitespace-nowrap",
|
|
490
|
+
"whitespace-pre",
|
|
491
|
+
"whitespace-pre-wrap",
|
|
492
|
+
"whitespace-pre-line",
|
|
493
|
+
"break-normal",
|
|
494
|
+
"break-words",
|
|
495
|
+
"break-all",
|
|
496
|
+
"align-baseline",
|
|
497
|
+
"align-top",
|
|
498
|
+
"align-middle",
|
|
499
|
+
"align-bottom",
|
|
500
|
+
"align-text-top",
|
|
501
|
+
"align-text-bottom",
|
|
502
|
+
"align-sub",
|
|
503
|
+
"align-super",
|
|
504
|
+
"list-none",
|
|
505
|
+
"list-disc",
|
|
506
|
+
"list-decimal",
|
|
507
|
+
"list-inside",
|
|
508
|
+
"list-outside",
|
|
509
|
+
"hyphens-none",
|
|
510
|
+
"hyphens-manual",
|
|
511
|
+
"hyphens-auto",
|
|
512
|
+
// effects.rs
|
|
513
|
+
"shadow",
|
|
514
|
+
"shadow-sm",
|
|
515
|
+
"shadow-md",
|
|
516
|
+
"shadow-lg",
|
|
517
|
+
"shadow-xl",
|
|
518
|
+
"shadow-2xl",
|
|
519
|
+
"shadow-inner",
|
|
520
|
+
"shadow-none",
|
|
521
|
+
"transition",
|
|
522
|
+
"transition-none",
|
|
523
|
+
"ease-linear",
|
|
524
|
+
"ease-in",
|
|
525
|
+
"ease-out",
|
|
526
|
+
"ease-in-out",
|
|
527
|
+
"cursor-pointer",
|
|
528
|
+
"cursor-default",
|
|
529
|
+
"cursor-not-allowed",
|
|
530
|
+
"cursor-wait",
|
|
531
|
+
"select-none",
|
|
532
|
+
"select-text",
|
|
533
|
+
"select-all",
|
|
534
|
+
"pointer-events-none",
|
|
535
|
+
"pointer-events-auto",
|
|
536
|
+
// effects.rs — Phase 22 (effects completeness)
|
|
537
|
+
"text-shadow",
|
|
538
|
+
"text-shadow-sm",
|
|
539
|
+
"text-shadow-lg",
|
|
540
|
+
"text-shadow-none",
|
|
541
|
+
"mix-blend-normal",
|
|
542
|
+
"mix-blend-multiply",
|
|
543
|
+
"mix-blend-screen",
|
|
544
|
+
"mix-blend-overlay",
|
|
545
|
+
"mix-blend-darken",
|
|
546
|
+
"mix-blend-lighten",
|
|
547
|
+
"mix-blend-color-dodge",
|
|
548
|
+
"mix-blend-color-burn",
|
|
549
|
+
"mix-blend-hard-light",
|
|
550
|
+
"mix-blend-soft-light",
|
|
551
|
+
"mix-blend-difference",
|
|
552
|
+
"mix-blend-exclusion",
|
|
553
|
+
"mix-blend-hue",
|
|
554
|
+
"mix-blend-saturation",
|
|
555
|
+
"mix-blend-color",
|
|
556
|
+
"mix-blend-luminosity",
|
|
557
|
+
"mix-blend-plus-lighter",
|
|
558
|
+
"bg-blend-normal",
|
|
559
|
+
"bg-blend-multiply",
|
|
560
|
+
"bg-blend-screen",
|
|
561
|
+
"bg-blend-overlay",
|
|
562
|
+
"bg-blend-darken",
|
|
563
|
+
"bg-blend-lighten",
|
|
564
|
+
"bg-blend-color-dodge",
|
|
565
|
+
"bg-blend-color-burn",
|
|
566
|
+
"bg-blend-hard-light",
|
|
567
|
+
"bg-blend-soft-light",
|
|
568
|
+
"bg-blend-difference",
|
|
569
|
+
"bg-blend-exclusion",
|
|
570
|
+
"bg-blend-hue",
|
|
571
|
+
"bg-blend-saturation",
|
|
572
|
+
"bg-blend-color",
|
|
573
|
+
"bg-blend-luminosity",
|
|
574
|
+
"bg-blend-plus-lighter",
|
|
575
|
+
"animate-spin",
|
|
576
|
+
"animate-ping",
|
|
577
|
+
"animate-pulse",
|
|
578
|
+
"animate-bounce",
|
|
579
|
+
"animate-none",
|
|
580
|
+
// interactivity.rs — Phase 23 (interactivity & sizing rest)
|
|
581
|
+
"resize",
|
|
582
|
+
"resize-none",
|
|
583
|
+
"resize-y",
|
|
584
|
+
"resize-x",
|
|
585
|
+
"touch-auto",
|
|
586
|
+
"touch-none",
|
|
587
|
+
"touch-pan-x",
|
|
588
|
+
"touch-pan-left",
|
|
589
|
+
"touch-pan-right",
|
|
590
|
+
"touch-pan-y",
|
|
591
|
+
"touch-pan-up",
|
|
592
|
+
"touch-pan-down",
|
|
593
|
+
"touch-pinch-zoom",
|
|
594
|
+
"touch-manipulation",
|
|
595
|
+
"will-change-auto",
|
|
596
|
+
"will-change-scroll",
|
|
597
|
+
"will-change-contents",
|
|
598
|
+
"will-change-transform",
|
|
599
|
+
"sr-only",
|
|
600
|
+
"not-sr-only",
|
|
601
|
+
"border-collapse",
|
|
602
|
+
"border-separate",
|
|
603
|
+
"table-auto",
|
|
604
|
+
"table-fixed",
|
|
605
|
+
"caption-top",
|
|
606
|
+
"caption-bottom",
|
|
607
|
+
"stroke-width-0",
|
|
608
|
+
"stroke-width-1",
|
|
609
|
+
"stroke-width-2",
|
|
610
|
+
// spacing.rs — Phase 23 (size-* shorthand + fraction-based width/height)
|
|
611
|
+
"size-full",
|
|
612
|
+
"size-auto",
|
|
613
|
+
"size-px",
|
|
614
|
+
"w-1/2",
|
|
615
|
+
"w-1/3",
|
|
616
|
+
"w-2/3",
|
|
617
|
+
"w-1/4",
|
|
618
|
+
"w-2/4",
|
|
619
|
+
"w-3/4",
|
|
620
|
+
"w-1/5",
|
|
621
|
+
"w-2/5",
|
|
622
|
+
"w-3/5",
|
|
623
|
+
"w-4/5",
|
|
624
|
+
"w-1/6",
|
|
625
|
+
"w-5/6",
|
|
626
|
+
"w-1/12",
|
|
627
|
+
"w-5/12",
|
|
628
|
+
"w-7/12",
|
|
629
|
+
"w-11/12",
|
|
630
|
+
"h-1/2",
|
|
631
|
+
"h-1/3",
|
|
632
|
+
"h-2/3",
|
|
633
|
+
"h-1/4",
|
|
634
|
+
"h-2/4",
|
|
635
|
+
"h-3/4",
|
|
636
|
+
"h-1/5",
|
|
637
|
+
"h-2/5",
|
|
638
|
+
"h-3/5",
|
|
639
|
+
"h-4/5",
|
|
640
|
+
"h-1/6",
|
|
641
|
+
"h-5/6",
|
|
642
|
+
// scroll.rs — Phase 23 (scroll-behavior/-margin/-padding, scroll-snap)
|
|
643
|
+
"scroll-auto",
|
|
644
|
+
"scroll-smooth",
|
|
645
|
+
"snap-start",
|
|
646
|
+
"snap-end",
|
|
647
|
+
"snap-center",
|
|
648
|
+
"snap-align-none",
|
|
649
|
+
"snap-normal",
|
|
650
|
+
"snap-always",
|
|
651
|
+
"snap-none",
|
|
652
|
+
"snap-x",
|
|
653
|
+
"snap-y",
|
|
654
|
+
"snap-both",
|
|
655
|
+
"snap-mandatory",
|
|
656
|
+
"snap-proximity",
|
|
657
|
+
// divide.rs
|
|
658
|
+
"divide-x",
|
|
659
|
+
"divide-y",
|
|
660
|
+
// background.rs — web-only (see the module's own doc comment for why)
|
|
661
|
+
"bg-top",
|
|
662
|
+
"bg-bottom",
|
|
663
|
+
"bg-left",
|
|
664
|
+
"bg-right",
|
|
665
|
+
"bg-center",
|
|
666
|
+
"bg-left-top",
|
|
667
|
+
"bg-left-bottom",
|
|
668
|
+
"bg-right-top",
|
|
669
|
+
"bg-right-bottom",
|
|
670
|
+
"bg-auto",
|
|
671
|
+
"bg-cover",
|
|
672
|
+
"bg-contain",
|
|
673
|
+
"bg-repeat",
|
|
674
|
+
"bg-no-repeat",
|
|
675
|
+
"bg-repeat-x",
|
|
676
|
+
"bg-repeat-y",
|
|
677
|
+
"bg-repeat-round",
|
|
678
|
+
"bg-repeat-space",
|
|
679
|
+
"bg-fixed",
|
|
680
|
+
"bg-local",
|
|
681
|
+
"bg-scroll",
|
|
682
|
+
"bg-clip-border",
|
|
683
|
+
"bg-clip-padding",
|
|
684
|
+
"bg-clip-content",
|
|
685
|
+
"bg-clip-text",
|
|
686
|
+
"bg-origin-border",
|
|
687
|
+
"bg-origin-padding",
|
|
688
|
+
"bg-origin-content",
|
|
689
|
+
"bg-none",
|
|
690
|
+
"bg-linear-to-t",
|
|
691
|
+
"bg-linear-to-tr",
|
|
692
|
+
"bg-linear-to-r",
|
|
693
|
+
"bg-linear-to-br",
|
|
694
|
+
"bg-linear-to-b",
|
|
695
|
+
"bg-linear-to-bl",
|
|
696
|
+
"bg-linear-to-l",
|
|
697
|
+
"bg-linear-to-tl",
|
|
698
|
+
"bg-radial",
|
|
699
|
+
"bg-conic",
|
|
700
|
+
// Ancestor/sibling-state marker classes — carry no styles of their own,
|
|
701
|
+
// just a selector target for group-hover:/peer-hover:/etc. below (see
|
|
702
|
+
// unknownClassWarnings.ts's MARKER_CLASSES for why they need special
|
|
703
|
+
// handling there too).
|
|
704
|
+
"group",
|
|
705
|
+
"peer",
|
|
706
|
+
// registry.rs modifiers — bare tokens only, not composed with a
|
|
707
|
+
// following utility (see this module's doc header / the Phase 15 plan).
|
|
708
|
+
"hover:",
|
|
709
|
+
"focus:",
|
|
710
|
+
"focus-visible:",
|
|
711
|
+
"focus-within:",
|
|
712
|
+
"active:",
|
|
713
|
+
"visited:",
|
|
714
|
+
"disabled:",
|
|
715
|
+
"checked:",
|
|
716
|
+
"group-hover:",
|
|
717
|
+
"group-focus:",
|
|
718
|
+
"peer-hover:",
|
|
719
|
+
"peer-focus:",
|
|
720
|
+
"peer-checked:",
|
|
721
|
+
"dark:",
|
|
722
|
+
"motion-safe:",
|
|
723
|
+
"motion-reduce:",
|
|
724
|
+
"print:",
|
|
725
|
+
"sm:",
|
|
726
|
+
"md:",
|
|
727
|
+
"lg:",
|
|
728
|
+
"xl:",
|
|
729
|
+
"2xl:",
|
|
730
|
+
// registry.rs modifiers — Phase 24 (expanded variant system), the
|
|
731
|
+
// FIXED/static additions only. Deliberately excluded: every genuinely
|
|
732
|
+
// parameterized modifier (has-[...]/group-has-[...]/peer-has-[...]/
|
|
733
|
+
// data-[...]/aria-[...]/not-[...]/min-[...]/max-[...], and the
|
|
734
|
+
// generalized group-<pseudo>/peer-<pseudo> beyond the five hardcoded
|
|
735
|
+
// combos above) — these have no finite enumerable set (their whole point
|
|
736
|
+
// is arbitrary user-supplied content), so there's nothing meaningful to
|
|
737
|
+
// suggest beyond the bare prefix, same reasoning as every other
|
|
738
|
+
// arbitrary-value exclusion in this file. `not-hover:`/`not-disabled:`/
|
|
739
|
+
// etc. (wrapping a KNOWN static modifier) are excluded for the same
|
|
740
|
+
// reason — enumerable in principle, but a full cross-product with every
|
|
741
|
+
// modifier above would be more noise than signal for an editor hint list.
|
|
742
|
+
"first:",
|
|
743
|
+
"last:",
|
|
744
|
+
"only:",
|
|
745
|
+
"odd:",
|
|
746
|
+
"even:",
|
|
747
|
+
"open:",
|
|
748
|
+
"inert:",
|
|
749
|
+
"aria-checked:",
|
|
750
|
+
"aria-disabled:",
|
|
751
|
+
"aria-expanded:",
|
|
752
|
+
"aria-hidden:",
|
|
753
|
+
"aria-pressed:",
|
|
754
|
+
"aria-readonly:",
|
|
755
|
+
"aria-required:",
|
|
756
|
+
"aria-selected:",
|
|
757
|
+
"aria-busy:",
|
|
758
|
+
// registry.rs modifiers, added later — same "fixed/static, finite" bar
|
|
759
|
+
// as the Phase 24 block above. Structural -of-type/empty, form-state and
|
|
760
|
+
// validation pseudo-classes, other native pseudo-classes with no aria-*
|
|
761
|
+
// counterpart, a pseudo-element, pointer media variants, and the
|
|
762
|
+
// direct-children/all-descendants variants. "supports-[...]:"/"in-*:" are
|
|
763
|
+
// deliberately excluded here for the same "no finite enumerable set"
|
|
764
|
+
// reason as has-[...]:/group-<pseudo>: above.
|
|
765
|
+
"first-of-type:",
|
|
766
|
+
"last-of-type:",
|
|
767
|
+
"only-of-type:",
|
|
768
|
+
"empty:",
|
|
769
|
+
"enabled:",
|
|
770
|
+
"read-only:",
|
|
771
|
+
"required:",
|
|
772
|
+
"optional:",
|
|
773
|
+
"valid:",
|
|
774
|
+
"invalid:",
|
|
775
|
+
"in-range:",
|
|
776
|
+
"out-of-range:",
|
|
777
|
+
"default:",
|
|
778
|
+
"indeterminate:",
|
|
779
|
+
"placeholder-shown:",
|
|
780
|
+
"autofill:",
|
|
781
|
+
"user-valid:",
|
|
782
|
+
"user-invalid:",
|
|
783
|
+
"target:",
|
|
784
|
+
"fullscreen:",
|
|
785
|
+
"popover-open:",
|
|
786
|
+
"details-content:",
|
|
787
|
+
"pointer-coarse:",
|
|
788
|
+
"pointer-fine:",
|
|
789
|
+
"any-pointer-coarse:",
|
|
790
|
+
"any-pointer-fine:",
|
|
791
|
+
"*:",
|
|
792
|
+
"**:",
|
|
793
|
+
// Phase 25 (container queries & arbitrary properties). "@container" is a
|
|
794
|
+
// real UTILITY (container-type: inline-size), not a modifier — included
|
|
795
|
+
// as a bare token like "flex"/"hidden" above, not with the trailing ":"
|
|
796
|
+
// the modifier tokens below get. "@sm:"/"@md:"/"@lg:"/"@xl:"/"@2xl:" are
|
|
797
|
+
// container-responsive modifiers (registry.rs's `is_container_responsive`),
|
|
798
|
+
// and "starting:" wraps in @starting-style. Deliberately excluded, same
|
|
799
|
+
// "no finite enumerable set" reasoning as Phase 24's exclusions:
|
|
800
|
+
// "@min-[...]:"/"@max-[...]:" (arbitrary container breakpoints) and every
|
|
801
|
+
// `[property:value]` arbitrary property — both are open-ended by design.
|
|
802
|
+
"@container",
|
|
803
|
+
"@sm:",
|
|
804
|
+
"@md:",
|
|
805
|
+
"@lg:",
|
|
806
|
+
"@xl:",
|
|
807
|
+
"@2xl:",
|
|
808
|
+
"starting:"
|
|
809
|
+
];
|
|
810
|
+
var COLOR_PREFIXES = [
|
|
811
|
+
"bg-",
|
|
812
|
+
"text-",
|
|
813
|
+
"border-",
|
|
814
|
+
"divide-",
|
|
815
|
+
"decoration-",
|
|
816
|
+
"from-",
|
|
817
|
+
"via-",
|
|
818
|
+
"to-",
|
|
819
|
+
"text-shadow-",
|
|
820
|
+
"ring-",
|
|
821
|
+
"ring-offset-",
|
|
822
|
+
"caret-",
|
|
823
|
+
"accent-",
|
|
824
|
+
"fill-",
|
|
825
|
+
"stroke-"
|
|
826
|
+
];
|
|
827
|
+
var SPACING_PREFIXES = [
|
|
828
|
+
"p-",
|
|
829
|
+
"px-",
|
|
830
|
+
"py-",
|
|
831
|
+
"pt-",
|
|
832
|
+
"pr-",
|
|
833
|
+
"pb-",
|
|
834
|
+
"pl-",
|
|
835
|
+
"m-",
|
|
836
|
+
"mx-",
|
|
837
|
+
"my-",
|
|
838
|
+
"mt-",
|
|
839
|
+
"mr-",
|
|
840
|
+
"mb-",
|
|
841
|
+
"ml-",
|
|
842
|
+
"gap-",
|
|
843
|
+
"gap-x-",
|
|
844
|
+
"gap-y-",
|
|
845
|
+
"w-",
|
|
846
|
+
"h-",
|
|
847
|
+
"min-w-",
|
|
848
|
+
"max-w-",
|
|
849
|
+
"min-h-",
|
|
850
|
+
"max-h-",
|
|
851
|
+
"size-",
|
|
852
|
+
"top-",
|
|
853
|
+
"right-",
|
|
854
|
+
"bottom-",
|
|
855
|
+
"left-",
|
|
856
|
+
"inset-",
|
|
857
|
+
"space-x-",
|
|
858
|
+
"space-y-",
|
|
859
|
+
"indent-",
|
|
860
|
+
"scroll-m-",
|
|
861
|
+
"scroll-mx-",
|
|
862
|
+
"scroll-my-",
|
|
863
|
+
"scroll-mt-",
|
|
864
|
+
"scroll-mr-",
|
|
865
|
+
"scroll-mb-",
|
|
866
|
+
"scroll-ml-",
|
|
867
|
+
"scroll-p-",
|
|
868
|
+
"scroll-px-",
|
|
869
|
+
"scroll-py-",
|
|
870
|
+
"scroll-pt-",
|
|
871
|
+
"scroll-pr-",
|
|
872
|
+
"scroll-pb-",
|
|
873
|
+
"scroll-pl-"
|
|
874
|
+
];
|
|
875
|
+
var SIZE_PREFIXES = ["w-", "h-", "min-w-", "max-w-", "min-h-", "max-h-", "size-"];
|
|
876
|
+
var NAMED_SIZES = ["sm", "md", "lg", "xl", "2xl", "3xl", "4xl", "5xl", "6xl", "7xl", "8xl", "9xl"];
|
|
877
|
+
function buildClassTokens(theme) {
|
|
878
|
+
const tokens = new Set(STRUCTURAL_TOKENS);
|
|
879
|
+
for (const colorKey of Object.keys(theme.colors)) {
|
|
880
|
+
for (const prefix of COLOR_PREFIXES) tokens.add(`${prefix}${colorKey}`);
|
|
881
|
+
}
|
|
882
|
+
for (const spacingKey of Object.keys(theme.spacing)) {
|
|
883
|
+
for (const prefix of SPACING_PREFIXES) tokens.add(`${prefix}${spacingKey}`);
|
|
884
|
+
}
|
|
885
|
+
for (const size of NAMED_SIZES) {
|
|
886
|
+
for (const prefix of SIZE_PREFIXES) tokens.add(`${prefix}${size}`);
|
|
887
|
+
}
|
|
888
|
+
return Array.from(tokens).sort();
|
|
889
|
+
}
|
|
890
|
+
function buildClassNameHintsDts(tokens) {
|
|
891
|
+
const literals = tokens.map((t) => ` | '${t}'`).join("\n");
|
|
892
|
+
return [
|
|
893
|
+
"// Generated by Kbach \u2014 do not edit",
|
|
894
|
+
"// Editor autocomplete for className \u2014 see packages/react/src/vite-plugin/classNameHints.ts",
|
|
895
|
+
"",
|
|
896
|
+
"type KbachClassToken =",
|
|
897
|
+
literals,
|
|
898
|
+
";",
|
|
899
|
+
"",
|
|
900
|
+
"export type KbachClassName = KbachClassToken | `${string} ${KbachClassToken}` | (string & {});",
|
|
901
|
+
"",
|
|
902
|
+
"declare module 'react' {",
|
|
903
|
+
" interface HTMLAttributes<T> {",
|
|
904
|
+
" className?: KbachClassName | undefined;",
|
|
905
|
+
" }",
|
|
906
|
+
" interface SVGAttributes<T> {",
|
|
907
|
+
" className?: KbachClassName | undefined;",
|
|
908
|
+
" }",
|
|
909
|
+
"}",
|
|
910
|
+
""
|
|
911
|
+
].join("\n");
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
// src/staticCss/engine.ts
|
|
915
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
916
|
+
import { join as join3 } from "path";
|
|
917
|
+
|
|
918
|
+
// src/vite-plugin/wasmNode.ts
|
|
919
|
+
import { generate_css } from "@kbach/core-engine/node";
|
|
920
|
+
function generateCssForToken(token, themeJson) {
|
|
921
|
+
return JSON.parse(generate_css(token, themeJson));
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
// src/vite-plugin/scan.ts
|
|
925
|
+
import { readdirSync, readFileSync, statSync } from "fs";
|
|
926
|
+
import { join } from "path";
|
|
927
|
+
function stripComments(code) {
|
|
928
|
+
let out = "";
|
|
929
|
+
let i = 0;
|
|
930
|
+
const n = code.length;
|
|
931
|
+
while (i < n) {
|
|
932
|
+
const two = code[i] + (code[i + 1] ?? "");
|
|
933
|
+
if (two === "//") {
|
|
934
|
+
i += 2;
|
|
935
|
+
while (i < n && code[i] !== "\n") i++;
|
|
936
|
+
continue;
|
|
937
|
+
}
|
|
938
|
+
if (two === "/*") {
|
|
939
|
+
i += 2;
|
|
940
|
+
while (i < n && code[i] + (code[i + 1] ?? "") !== "*/") i++;
|
|
941
|
+
i += 2;
|
|
942
|
+
continue;
|
|
943
|
+
}
|
|
944
|
+
const ch = code[i];
|
|
945
|
+
if (ch === '"' || ch === "'") {
|
|
946
|
+
out += ch;
|
|
947
|
+
i++;
|
|
948
|
+
while (i < n && code[i] !== ch) {
|
|
949
|
+
if (code[i] === "\\") {
|
|
950
|
+
out += code[i] + (code[i + 1] ?? "");
|
|
951
|
+
i += 2;
|
|
952
|
+
continue;
|
|
953
|
+
}
|
|
954
|
+
out += code[i];
|
|
955
|
+
i++;
|
|
956
|
+
}
|
|
957
|
+
out += code[i] ?? "";
|
|
958
|
+
i++;
|
|
959
|
+
continue;
|
|
960
|
+
}
|
|
961
|
+
if (ch === "`") {
|
|
962
|
+
out += ch;
|
|
963
|
+
i++;
|
|
964
|
+
let interpolationDepth = 0;
|
|
965
|
+
while (i < n) {
|
|
966
|
+
if (interpolationDepth === 0 && code[i] === "`") {
|
|
967
|
+
out += code[i];
|
|
968
|
+
i++;
|
|
969
|
+
break;
|
|
970
|
+
}
|
|
971
|
+
if (interpolationDepth === 0 && code[i] === "\\") {
|
|
972
|
+
out += code[i] + (code[i + 1] ?? "");
|
|
973
|
+
i += 2;
|
|
974
|
+
continue;
|
|
975
|
+
}
|
|
976
|
+
if (interpolationDepth === 0 && code[i] + (code[i + 1] ?? "") === "${") {
|
|
977
|
+
out += "${";
|
|
978
|
+
i += 2;
|
|
979
|
+
interpolationDepth = 1;
|
|
980
|
+
continue;
|
|
981
|
+
}
|
|
982
|
+
if (interpolationDepth > 0) {
|
|
983
|
+
if (code[i] === "{") interpolationDepth++;
|
|
984
|
+
else if (code[i] === "}") {
|
|
985
|
+
interpolationDepth--;
|
|
986
|
+
if (interpolationDepth === 0) {
|
|
987
|
+
out += "}";
|
|
988
|
+
i++;
|
|
989
|
+
continue;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
out += code[i];
|
|
994
|
+
i++;
|
|
995
|
+
}
|
|
996
|
+
continue;
|
|
997
|
+
}
|
|
998
|
+
out += ch;
|
|
999
|
+
i++;
|
|
1000
|
+
}
|
|
1001
|
+
return out;
|
|
1002
|
+
}
|
|
1003
|
+
function splitClassTokens(str) {
|
|
1004
|
+
return str.split(/\s+/).filter(Boolean);
|
|
1005
|
+
}
|
|
1006
|
+
var NOT_A_CLASS_NAME_RE = /[${}]|-$|^[?:&|!"'=<>]+$/;
|
|
1007
|
+
function pushTokens(str, into) {
|
|
1008
|
+
for (const tok of splitClassTokens(str)) {
|
|
1009
|
+
if (tok && !NOT_A_CLASS_NAME_RE.test(tok)) into.add(tok);
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
function pushTemplateLiteralBody(body, into) {
|
|
1013
|
+
const interpolationRe = /\$\{(?:[^{}]|\{[^{}]*\})*\}/g;
|
|
1014
|
+
let im;
|
|
1015
|
+
while ((im = interpolationRe.exec(body)) !== null) {
|
|
1016
|
+
pushClassLikeStrings(im[0], into);
|
|
1017
|
+
}
|
|
1018
|
+
pushTokens(body.replace(/\$\{(?:[^{}]|\{[^{}]*\})*\}/g, () => "$"), into);
|
|
1019
|
+
}
|
|
1020
|
+
function pushClassLikeStrings(text, into) {
|
|
1021
|
+
const quotedStringRe = /(["'`])((?:(?!\1).)*)\1/g;
|
|
1022
|
+
let qm;
|
|
1023
|
+
while ((qm = quotedStringRe.exec(text)) !== null) {
|
|
1024
|
+
const [, quote, content] = qm;
|
|
1025
|
+
if (quote === "`") pushTemplateLiteralBody(content, into);
|
|
1026
|
+
else pushTokens(content, into);
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
var JSX_TAG_RE = /<([a-z][a-zA-Z0-9]*)[\s/>]/g;
|
|
1030
|
+
function scanUsedTags(code) {
|
|
1031
|
+
const cleaned = stripComments(code);
|
|
1032
|
+
const tags = /* @__PURE__ */ new Set();
|
|
1033
|
+
let m;
|
|
1034
|
+
JSX_TAG_RE.lastIndex = 0;
|
|
1035
|
+
while ((m = JSX_TAG_RE.exec(cleaned)) !== null) tags.add(m[1]);
|
|
1036
|
+
return tags;
|
|
1037
|
+
}
|
|
1038
|
+
function extractClassStrings(rawCode) {
|
|
1039
|
+
const code = stripComments(rawCode);
|
|
1040
|
+
const found = /* @__PURE__ */ new Set();
|
|
1041
|
+
const simpleRe = /(?:className|kb)=(["'])((?:(?!\1).)*)\1/g;
|
|
1042
|
+
let m;
|
|
1043
|
+
while ((m = simpleRe.exec(code)) !== null) pushTokens(m[2], found);
|
|
1044
|
+
const jsxExprRe = /(?:className|kb)=\{/g;
|
|
1045
|
+
while ((m = jsxExprRe.exec(code)) !== null) {
|
|
1046
|
+
let depth = 1;
|
|
1047
|
+
let i = m.index + m[0].length;
|
|
1048
|
+
let block = "";
|
|
1049
|
+
while (i < code.length && depth > 0) {
|
|
1050
|
+
const ch = code[i];
|
|
1051
|
+
if (ch === "{") depth++;
|
|
1052
|
+
else if (ch === "}") {
|
|
1053
|
+
if (--depth === 0) break;
|
|
1054
|
+
}
|
|
1055
|
+
block += ch;
|
|
1056
|
+
i++;
|
|
1057
|
+
}
|
|
1058
|
+
jsxExprRe.lastIndex = i + 1;
|
|
1059
|
+
pushClassLikeStrings(block, found);
|
|
1060
|
+
}
|
|
1061
|
+
const classComposerCallRe = /(?:clsx|cn|classnames|cx|kb)\(/g;
|
|
1062
|
+
while ((m = classComposerCallRe.exec(code)) !== null) {
|
|
1063
|
+
let depth = 1;
|
|
1064
|
+
let i = m.index + m[0].length;
|
|
1065
|
+
let block = "";
|
|
1066
|
+
while (i < code.length && depth > 0) {
|
|
1067
|
+
const ch = code[i];
|
|
1068
|
+
if (ch === "(") depth++;
|
|
1069
|
+
else if (ch === ")") {
|
|
1070
|
+
if (--depth === 0) break;
|
|
1071
|
+
}
|
|
1072
|
+
block += ch;
|
|
1073
|
+
i++;
|
|
1074
|
+
}
|
|
1075
|
+
classComposerCallRe.lastIndex = i + 1;
|
|
1076
|
+
pushClassLikeStrings(block, found);
|
|
1077
|
+
}
|
|
1078
|
+
const templateRe = /`([^`]{1,2000})`/g;
|
|
1079
|
+
while ((m = templateRe.exec(code)) !== null) pushTemplateLiteralBody(m[1], found);
|
|
1080
|
+
return [...found];
|
|
1081
|
+
}
|
|
1082
|
+
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "dist", "build", "out", ".next", ".output", ".git", ".svn", ".cache", "coverage"]);
|
|
1083
|
+
var MAX_SCAN_DEPTH = 10;
|
|
1084
|
+
var DEFAULT_FILE_MATCH = /\.(tsx?|jsx?)$/;
|
|
1085
|
+
function scanDir(dir, onFile, depth = 0, fileMatch = DEFAULT_FILE_MATCH) {
|
|
1086
|
+
if (depth > MAX_SCAN_DEPTH) return;
|
|
1087
|
+
let entries;
|
|
1088
|
+
try {
|
|
1089
|
+
entries = readdirSync(dir);
|
|
1090
|
+
} catch {
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
for (const entry of entries) {
|
|
1094
|
+
if (entry.startsWith(".") || SKIP_DIRS.has(entry)) continue;
|
|
1095
|
+
const full = join(dir, entry);
|
|
1096
|
+
try {
|
|
1097
|
+
const st = statSync(full);
|
|
1098
|
+
if (st.isDirectory()) scanDir(full, onFile, depth + 1, fileMatch);
|
|
1099
|
+
else if (fileMatch.test(entry)) onFile(full, readFileSync(full, "utf-8"));
|
|
1100
|
+
} catch {
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
// src/vite-plugin/unknownClassWarnings.ts
|
|
1106
|
+
import { join as join2 } from "path";
|
|
1107
|
+
var CSS_CLASS_SELECTOR_RE = /\.(-?[a-zA-Z_][a-zA-Z0-9_-]*)/g;
|
|
1108
|
+
var CSS_FILE_RE = /\.(css|scss|sass|less)$/;
|
|
1109
|
+
var useColor = !!process.stdout?.isTTY && !process.env.NO_COLOR;
|
|
1110
|
+
var paint = (code, s) => useColor ? `\x1B[${code}m${s}\x1B[0m` : s;
|
|
1111
|
+
var green = (s) => paint("32", s);
|
|
1112
|
+
var blue = (s) => paint("34", s);
|
|
1113
|
+
var white = (s) => paint("97", s);
|
|
1114
|
+
var gray = (s) => paint("90", s);
|
|
1115
|
+
var bold = (s) => paint("1", s);
|
|
1116
|
+
var ARROW = () => green("\u2192");
|
|
1117
|
+
var TAG = () => bold(green("[kbach]"));
|
|
1118
|
+
var highlight = (s) => bold(white(s));
|
|
1119
|
+
function findLineCol(code, needle) {
|
|
1120
|
+
const index = code.indexOf(needle);
|
|
1121
|
+
if (index === -1) return null;
|
|
1122
|
+
let line = 1;
|
|
1123
|
+
let lastNewline = -1;
|
|
1124
|
+
for (let i = 0; i < index; i++) {
|
|
1125
|
+
if (code.charCodeAt(i) === 10) {
|
|
1126
|
+
line++;
|
|
1127
|
+
lastNewline = i;
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
return { line, column: index - lastNewline };
|
|
1131
|
+
}
|
|
1132
|
+
function scanCssFileInto(code, into) {
|
|
1133
|
+
const re = new RegExp(CSS_CLASS_SELECTOR_RE.source, "g");
|
|
1134
|
+
let m;
|
|
1135
|
+
while ((m = re.exec(code)) !== null) into.add(m[1]);
|
|
1136
|
+
}
|
|
1137
|
+
function scanProjectCssSelectors(root, includeDirs) {
|
|
1138
|
+
const projectCssClasses = /* @__PURE__ */ new Set();
|
|
1139
|
+
for (const dir of includeDirs) {
|
|
1140
|
+
scanDir(join2(root, dir), (_filePath, code) => scanCssFileInto(code, projectCssClasses), 0, CSS_FILE_RE);
|
|
1141
|
+
}
|
|
1142
|
+
return projectCssClasses;
|
|
1143
|
+
}
|
|
1144
|
+
function stripModifierPrefix(token) {
|
|
1145
|
+
return token.replace(/^(?:[a-zA-Z0-9_/-]+:)+/, "");
|
|
1146
|
+
}
|
|
1147
|
+
var MARKER_CLASSES = /* @__PURE__ */ new Set(["group", "peer"]);
|
|
1148
|
+
function warnIfUnknownClass(token, filePath, code, isResolvable, projectCssClasses, warnedTokens) {
|
|
1149
|
+
if (isResolvable || warnedTokens.has(token)) return;
|
|
1150
|
+
const base = stripModifierPrefix(token);
|
|
1151
|
+
if (!base || projectCssClasses.has(base) || MARKER_CLASSES.has(base)) return;
|
|
1152
|
+
warnedTokens.add(token);
|
|
1153
|
+
const pos = findLineCol(code, token);
|
|
1154
|
+
const location = pos ? `${blue(filePath)}${green(`:${pos.line}:${pos.column}`)}` : blue(filePath);
|
|
1155
|
+
console.warn(
|
|
1156
|
+
`${ARROW()} ${TAG()} ${gray("Unknown class")} ${highlight(token)} ${gray("\u2014 no Kbach utility or project CSS rule matches it. Typo?")}
|
|
1157
|
+
${bold("at")} ${location}`
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
// src/staticCss/engine.ts
|
|
1162
|
+
function normPath(p) {
|
|
1163
|
+
const fwd = p.replace(/\\/g, "/");
|
|
1164
|
+
return process.platform === "win32" ? fwd.toLowerCase() : fwd;
|
|
1165
|
+
}
|
|
1166
|
+
var SAFELIST_KEY = "\0kbach-safelist";
|
|
1167
|
+
function createKbachStaticCssEngine(options) {
|
|
1168
|
+
const { root, theme, themeJson, includeDirs, safelist } = options;
|
|
1169
|
+
const fileTokens = /* @__PURE__ */ new Map();
|
|
1170
|
+
const tokenRules = /* @__PURE__ */ new Map();
|
|
1171
|
+
const fileTags = /* @__PURE__ */ new Map();
|
|
1172
|
+
let projectCssClasses = /* @__PURE__ */ new Set();
|
|
1173
|
+
const warnedTokens = /* @__PURE__ */ new Set();
|
|
1174
|
+
function resolveToken(tok) {
|
|
1175
|
+
if (!tokenRules.has(tok)) {
|
|
1176
|
+
tokenRules.set(tok, generateCssForToken(tok, themeJson).rules);
|
|
1177
|
+
}
|
|
1178
|
+
return tokenRules.get(tok);
|
|
1179
|
+
}
|
|
1180
|
+
function processFile(filePath, code) {
|
|
1181
|
+
const tokens = /* @__PURE__ */ new Set();
|
|
1182
|
+
for (const tok of extractClassStrings(code)) {
|
|
1183
|
+
tokens.add(tok);
|
|
1184
|
+
const rules = resolveToken(tok);
|
|
1185
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1186
|
+
warnIfUnknownClass(tok, filePath, code, rules.length > 0, projectCssClasses, warnedTokens);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
fileTokens.set(normPath(filePath), tokens);
|
|
1190
|
+
fileTags.set(normPath(filePath), scanUsedTags(code));
|
|
1191
|
+
}
|
|
1192
|
+
function removeFile(filePath) {
|
|
1193
|
+
fileTokens.delete(normPath(filePath));
|
|
1194
|
+
fileTags.delete(normPath(filePath));
|
|
1195
|
+
}
|
|
1196
|
+
function processSafelist() {
|
|
1197
|
+
if (safelist.length === 0) return;
|
|
1198
|
+
const tokens = new Set(safelist);
|
|
1199
|
+
for (const tok of tokens) resolveToken(tok);
|
|
1200
|
+
fileTokens.set(SAFELIST_KEY, tokens);
|
|
1201
|
+
}
|
|
1202
|
+
function activeTokens() {
|
|
1203
|
+
const active = /* @__PURE__ */ new Set();
|
|
1204
|
+
for (const tokens of fileTokens.values()) for (const t of tokens) active.add(t);
|
|
1205
|
+
return active;
|
|
1206
|
+
}
|
|
1207
|
+
function activeTags() {
|
|
1208
|
+
const active = /* @__PURE__ */ new Set();
|
|
1209
|
+
for (const tags of fileTags.values()) for (const t of tags) active.add(t);
|
|
1210
|
+
return active;
|
|
1211
|
+
}
|
|
1212
|
+
function generateCSS() {
|
|
1213
|
+
const active = activeTokens();
|
|
1214
|
+
const view = /* @__PURE__ */ new Map();
|
|
1215
|
+
for (const tok of active) {
|
|
1216
|
+
const rules = tokenRules.get(tok);
|
|
1217
|
+
if (rules) view.set(tok, rules);
|
|
1218
|
+
}
|
|
1219
|
+
for (const tok of tokenRules.keys()) {
|
|
1220
|
+
if (!active.has(tok)) tokenRules.delete(tok);
|
|
1221
|
+
}
|
|
1222
|
+
return formatKbachCSS(view, theme, activeTags());
|
|
1223
|
+
}
|
|
1224
|
+
function initialScan() {
|
|
1225
|
+
for (const dir of includeDirs) {
|
|
1226
|
+
scanDir(join3(root, dir), processFile);
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
function scanProjectCssSelectorsOnce() {
|
|
1230
|
+
projectCssClasses = scanProjectCssSelectors(root, includeDirs);
|
|
1231
|
+
}
|
|
1232
|
+
return { processFile, removeFile, initialScan, processSafelist, generateCSS, scanProjectCssSelectorsOnce };
|
|
1233
|
+
}
|
|
1234
|
+
function readSourceFile(path) {
|
|
1235
|
+
return readFileSync2(path, "utf-8");
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
// src/vite-plugin/index.ts
|
|
1239
|
+
function findMainCSSFile(root, includeDirs, explicitCssFile) {
|
|
1240
|
+
if (explicitCssFile) return join4(root, explicitCssFile);
|
|
1241
|
+
const searchDirs = [...includeDirs, "."];
|
|
1242
|
+
for (const dir of searchDirs) {
|
|
1243
|
+
const candidate = join4(root, dir, "kbach.css");
|
|
1244
|
+
if (!existsSync(candidate)) continue;
|
|
1245
|
+
try {
|
|
1246
|
+
const content = readFileSync3(candidate, "utf-8");
|
|
1247
|
+
if (content.includes(KBACH_START) && content.includes(KBACH_END)) return candidate;
|
|
1248
|
+
} catch {
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
for (const dir of includeDirs) {
|
|
1252
|
+
const full = join4(root, dir);
|
|
1253
|
+
try {
|
|
1254
|
+
if (statSync2(full).isDirectory()) return join4(full, "kbach.css");
|
|
1255
|
+
} catch {
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
return join4(root, includeDirs[0] ?? "src", "kbach.css");
|
|
1259
|
+
}
|
|
1260
|
+
var DEFAULT_SCAN_DIRS = ["src", "app", "pages", "components"];
|
|
1261
|
+
var CSS_SYNC_DEBOUNCE_MS = 50;
|
|
1262
|
+
function writeFileEnsuringDir(path, content) {
|
|
1263
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
1264
|
+
writeFileSync(path, content, "utf-8");
|
|
1265
|
+
}
|
|
1266
|
+
function isEsmRequireFailure(err) {
|
|
1267
|
+
if (!(err instanceof Error)) return false;
|
|
1268
|
+
return err.code === "ERR_REQUIRE_ESM" || /is not defined in ES module scope/.test(err.message);
|
|
1269
|
+
}
|
|
1270
|
+
async function importConfigModule(path) {
|
|
1271
|
+
const mod = await import(pathToFileURL(path).href);
|
|
1272
|
+
return mod.default ?? mod;
|
|
1273
|
+
}
|
|
1274
|
+
function requireConfigModule(root, path) {
|
|
1275
|
+
const mod = createRequire(root)(path);
|
|
1276
|
+
return mod.default ?? mod;
|
|
1277
|
+
}
|
|
1278
|
+
async function loadConfigFile(root) {
|
|
1279
|
+
const cjsPath = join4(root, "kbach.config.cjs");
|
|
1280
|
+
if (existsSync(cjsPath)) return requireConfigModule(root, cjsPath);
|
|
1281
|
+
const mjsPath = join4(root, "kbach.config.mjs");
|
|
1282
|
+
if (existsSync(mjsPath)) return importConfigModule(mjsPath);
|
|
1283
|
+
const jsPath = join4(root, "kbach.config.js");
|
|
1284
|
+
if (!existsSync(jsPath)) return void 0;
|
|
1285
|
+
try {
|
|
1286
|
+
return requireConfigModule(root, jsPath);
|
|
1287
|
+
} catch (err) {
|
|
1288
|
+
if (!isEsmRequireFailure(err)) throw err;
|
|
1289
|
+
return importConfigModule(jsPath);
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
async function resolveEffectiveTheme(root, options) {
|
|
1293
|
+
if (options.theme) return options.theme;
|
|
1294
|
+
if (options.config) return resolveKbachConfig(options.config);
|
|
1295
|
+
const discovered = await loadConfigFile(root);
|
|
1296
|
+
return discovered ? resolveKbachConfig(discovered) : defaultTheme;
|
|
1297
|
+
}
|
|
1298
|
+
function kbach(options = {}) {
|
|
1299
|
+
const includeDirs = options.include ?? DEFAULT_SCAN_DIRS;
|
|
1300
|
+
const safelist = options.safelist ?? [];
|
|
1301
|
+
let root = process.cwd();
|
|
1302
|
+
let theme = defaultTheme;
|
|
1303
|
+
let engine = createKbachStaticCssEngine({ root, theme, themeJson: JSON.stringify(theme), includeDirs, safelist });
|
|
1304
|
+
let mainCSSFilePath = join4(root, "src", "kbach.css");
|
|
1305
|
+
function mainCSSFile() {
|
|
1306
|
+
return mainCSSFilePath;
|
|
1307
|
+
}
|
|
1308
|
+
function classNameHintsFile() {
|
|
1309
|
+
return join4(root, ".kbach", "kbach-classnames.d.ts");
|
|
1310
|
+
}
|
|
1311
|
+
function writeClassNameHints() {
|
|
1312
|
+
const dts = buildClassNameHintsDts(buildClassTokens(theme));
|
|
1313
|
+
writeFileEnsuringDir(classNameHintsFile(), dts);
|
|
1314
|
+
}
|
|
1315
|
+
function syncMainCSSFile(server) {
|
|
1316
|
+
const changed = writeKbachToFile(mainCSSFile(), engine.generateCSS(), readSourceFile, writeFileEnsuringDir);
|
|
1317
|
+
if (changed && server) server.watcher.emit("change", mainCSSFile());
|
|
1318
|
+
}
|
|
1319
|
+
let syncTimer = null;
|
|
1320
|
+
function scheduleSync(server) {
|
|
1321
|
+
if (syncTimer) clearTimeout(syncTimer);
|
|
1322
|
+
syncTimer = setTimeout(() => {
|
|
1323
|
+
syncTimer = null;
|
|
1324
|
+
syncMainCSSFile(server);
|
|
1325
|
+
}, CSS_SYNC_DEBOUNCE_MS);
|
|
1326
|
+
}
|
|
1327
|
+
return {
|
|
1328
|
+
name: "kbach",
|
|
1329
|
+
enforce: "pre",
|
|
1330
|
+
async configResolved(resolved) {
|
|
1331
|
+
root = resolved.root;
|
|
1332
|
+
theme = await resolveEffectiveTheme(root, options);
|
|
1333
|
+
engine = createKbachStaticCssEngine({ root, theme, themeJson: JSON.stringify(theme), includeDirs, safelist });
|
|
1334
|
+
mainCSSFilePath = findMainCSSFile(root, includeDirs, options.cssFile);
|
|
1335
|
+
},
|
|
1336
|
+
buildStart() {
|
|
1337
|
+
engine.scanProjectCssSelectorsOnce();
|
|
1338
|
+
engine.initialScan();
|
|
1339
|
+
engine.processSafelist();
|
|
1340
|
+
writeKbachToFile(mainCSSFile(), engine.generateCSS(), readSourceFile, writeFileEnsuringDir);
|
|
1341
|
+
writeClassNameHints();
|
|
1342
|
+
},
|
|
1343
|
+
// handleHotUpdate covers edits; add/unlink (create/delete) land on the
|
|
1344
|
+
// raw watcher instead — Vite's handleHotUpdate hook only fires for
|
|
1345
|
+
// type === "update".
|
|
1346
|
+
configureServer(server) {
|
|
1347
|
+
const onAddOrUnlink = (file, isUnlink) => {
|
|
1348
|
+
if (file.includes("node_modules")) return;
|
|
1349
|
+
if (!/\.(tsx?|jsx?)$/.test(file)) return;
|
|
1350
|
+
if (isUnlink) {
|
|
1351
|
+
engine.removeFile(file);
|
|
1352
|
+
} else {
|
|
1353
|
+
try {
|
|
1354
|
+
engine.processFile(file, readSourceFile(file));
|
|
1355
|
+
} catch {
|
|
1356
|
+
engine.removeFile(file);
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
scheduleSync(server);
|
|
1360
|
+
};
|
|
1361
|
+
server.watcher.on("add", (file) => onAddOrUnlink(file, false));
|
|
1362
|
+
server.watcher.on("unlink", (file) => onAddOrUnlink(file, true));
|
|
1363
|
+
},
|
|
1364
|
+
handleHotUpdate({ file, server }) {
|
|
1365
|
+
if (file.includes("node_modules")) return;
|
|
1366
|
+
if (!/\.(tsx?|jsx?)$/.test(file)) return;
|
|
1367
|
+
try {
|
|
1368
|
+
engine.processFile(file, readSourceFile(file));
|
|
1369
|
+
} catch {
|
|
1370
|
+
engine.removeFile(file);
|
|
1371
|
+
}
|
|
1372
|
+
scheduleSync(server);
|
|
1373
|
+
}
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
export {
|
|
1378
|
+
createKbachStaticCssEngine,
|
|
1379
|
+
findMainCSSFile,
|
|
1380
|
+
DEFAULT_SCAN_DIRS,
|
|
1381
|
+
CSS_SYNC_DEBOUNCE_MS,
|
|
1382
|
+
loadConfigFile,
|
|
1383
|
+
resolveEffectiveTheme,
|
|
1384
|
+
kbach
|
|
1385
|
+
};
|