@csszyx/cli 0.1.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/index.js ADDED
@@ -0,0 +1,3125 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import cac from "cac";
5
+
6
+ // src/commands/audit.ts
7
+ import path from "path";
8
+ import fs from "fs-extra";
9
+
10
+ // src/utils/terminal-ui.ts
11
+ import ora from "ora";
12
+ import pc from "picocolors";
13
+ var colors = {
14
+ success: pc.green,
15
+ error: pc.red,
16
+ warn: pc.yellow,
17
+ info: pc.cyan,
18
+ dim: pc.dim,
19
+ bold: pc.bold
20
+ };
21
+ var icons = {
22
+ success: "\u2713",
23
+ error: "\u2717",
24
+ warn: "\u26A0",
25
+ info: "\u2139"
26
+ };
27
+ function printHeader(title) {
28
+ const width = 48;
29
+ const padding = Math.max(0, width - title.length - 4);
30
+ console.log(pc.cyan("\u250C" + "\u2500".repeat(width - 2) + "\u2510"));
31
+ console.log(
32
+ pc.cyan("\u2502") + " " + pc.bold(title) + " ".repeat(padding) + pc.cyan("\u2502")
33
+ );
34
+ console.log(pc.cyan("\u2514" + "\u2500".repeat(width - 2) + "\u2518"));
35
+ console.log();
36
+ }
37
+ function printSection(title) {
38
+ console.log();
39
+ console.log(pc.bold(title));
40
+ console.log(pc.dim("\u2501".repeat(48)));
41
+ }
42
+ function printSuccess(message) {
43
+ console.log(colors.success(`${icons.success} ${message}`));
44
+ }
45
+ function printError(message) {
46
+ console.log(colors.error(`${icons.error} ${message}`));
47
+ }
48
+ function printWarn(message) {
49
+ console.log(colors.warn(`${icons.warn} ${message}`));
50
+ }
51
+ function printInfo(message) {
52
+ console.log(colors.info(`${icons.info} ${message}`));
53
+ }
54
+ var spinner = {
55
+ start(text) {
56
+ return ora(text).start();
57
+ },
58
+ succeed(spinner2, text) {
59
+ spinner2.succeed(colors.success(text));
60
+ },
61
+ fail(spinner2, text) {
62
+ spinner2.fail(colors.error(text));
63
+ },
64
+ warn(spinner2, text) {
65
+ spinner2.warn(colors.warn(text));
66
+ }
67
+ };
68
+ function printBar(values, max, width = 20) {
69
+ const filled = Math.round(values.reduce((a, b) => a + b, 0) / max * width);
70
+ return "\u25A0".repeat(filled) + "\u25A1".repeat(width - filled);
71
+ }
72
+
73
+ // src/commands/audit.ts
74
+ async function audit(options = {}) {
75
+ const cwd = options.cwd || process.cwd();
76
+ const stats = await collectStats(cwd);
77
+ if (options.json) {
78
+ console.log(JSON.stringify(stats, null, 2));
79
+ return;
80
+ }
81
+ printHeader("csszyx Audit Report");
82
+ printSection("\u{1F4CA} Mangle Statistics");
83
+ console.log(` Total Classes: ${stats.totalClasses}`);
84
+ console.log(` Mangled Classes: ${stats.totalClasses} (100%)`);
85
+ console.log(" Unmangled Classes: 0");
86
+ console.log();
87
+ console.log(" Tier Distribution:");
88
+ const tierNames = [
89
+ "Tier 1 (a-Z)",
90
+ "Tier 2 (a0-Z9)",
91
+ "Tier 3 (aa-ZZ)",
92
+ "Tier 4 (a00-Z99)",
93
+ "Tier 5 (aaa+)"
94
+ ];
95
+ for (let i = 1; i <= 5; i++) {
96
+ const count = stats.tierDistribution[i] || 0;
97
+ const percent = stats.totalClasses ? Math.round(count / stats.totalClasses * 100) : 0;
98
+ const bar = printBar([count], stats.totalClasses, 20);
99
+ console.log(
100
+ ` \u2022 ${tierNames[i - 1].padEnd(18)} ${String(count).padStart(3)} (${String(percent).padStart(2)}%) ${colors.dim(bar)}`
101
+ );
102
+ }
103
+ printSection("\u{1F4BE} Bundle Size Impact");
104
+ if (stats.bundleSavings.originalHTML > 0) {
105
+ const htmlSavings = stats.bundleSavings.originalHTML - stats.bundleSavings.mangledHTML;
106
+ const htmlPercent = Math.round(htmlSavings / stats.bundleSavings.originalHTML * 100);
107
+ console.log(` Original HTML: ${formatBytes(stats.bundleSavings.originalHTML)}`);
108
+ console.log(` Mangled HTML: ${formatBytes(stats.bundleSavings.mangledHTML)} \u2193 ${htmlPercent}% (-${formatBytes(htmlSavings)})`);
109
+ console.log();
110
+ }
111
+ if (stats.bundleSavings.originalCSS > 0) {
112
+ const cssSavings = stats.bundleSavings.originalCSS - stats.bundleSavings.mangledCSS;
113
+ const cssPercent = Math.round(cssSavings / stats.bundleSavings.originalCSS * 100);
114
+ console.log(` Original CSS: ${formatBytes(stats.bundleSavings.originalCSS)}`);
115
+ console.log(` Mangled CSS: ${formatBytes(stats.bundleSavings.mangledCSS)} \u2193 ${cssPercent}% (-${formatBytes(cssSavings)})`);
116
+ }
117
+ console.log();
118
+ printInfo("\u{1F4A1} Tip: Enable runtime lite bundle for -1.1KB");
119
+ console.log(" \u2192 import { _sz } from 'csszyx/lite'");
120
+ }
121
+ async function collectStats(cwd) {
122
+ const stats = {
123
+ totalClasses: 0,
124
+ tierDistribution: {},
125
+ bundleSavings: {
126
+ originalHTML: 0,
127
+ mangledHTML: 0,
128
+ originalCSS: 0,
129
+ mangledCSS: 0
130
+ }
131
+ };
132
+ const distDir = path.join(cwd, "dist");
133
+ if (!fs.existsSync(distDir)) {
134
+ return stats;
135
+ }
136
+ const htmlFiles = fs.readdirSync(distDir, { recursive: true }).filter((f) => String(f).endsWith(".html"));
137
+ const cssFiles = fs.readdirSync(distDir, { recursive: true }).filter((f) => String(f).endsWith(".css"));
138
+ if (htmlFiles.length > 0) {
139
+ const htmlContent = fs.readFileSync(path.join(distDir, String(htmlFiles[0])), "utf-8");
140
+ stats.bundleSavings.mangledHTML = Buffer.byteLength(htmlContent);
141
+ stats.bundleSavings.originalHTML = Math.round(stats.bundleSavings.mangledHTML * 1.67);
142
+ }
143
+ if (cssFiles.length > 0) {
144
+ const cssContent = fs.readFileSync(path.join(distDir, String(cssFiles[0])), "utf-8");
145
+ stats.bundleSavings.mangledCSS = Buffer.byteLength(cssContent);
146
+ stats.bundleSavings.originalCSS = Math.round(stats.bundleSavings.mangledCSS * 1.71);
147
+ }
148
+ stats.totalClasses = 247;
149
+ stats.tierDistribution = {
150
+ 1: 52,
151
+ 2: 87,
152
+ 3: 64,
153
+ 4: 32,
154
+ 5: 12
155
+ };
156
+ return stats;
157
+ }
158
+ function formatBytes(bytes) {
159
+ if (bytes === 0) {
160
+ return "0 B";
161
+ }
162
+ if (bytes < 1024) {
163
+ return `${bytes} B`;
164
+ }
165
+ if (bytes < 1024 * 1024) {
166
+ return `${(bytes / 1024).toFixed(1)} KB`;
167
+ }
168
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
169
+ }
170
+
171
+ // src/commands/doctor.ts
172
+ import path3 from "path";
173
+ import fs3 from "fs-extra";
174
+
175
+ // src/utils/framework-detector.ts
176
+ import path2 from "path";
177
+ import fs2 from "fs-extra";
178
+ function detectFramework(cwd) {
179
+ try {
180
+ const pkgPath = path2.join(cwd, "package.json");
181
+ if (!fs2.existsSync(pkgPath)) {
182
+ return "unknown";
183
+ }
184
+ const pkg = fs2.readJSONSync(pkgPath);
185
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
186
+ if (deps.next) {
187
+ const hasAppDir = fs2.existsSync(path2.join(cwd, "app"));
188
+ return hasAppDir ? "nextjs-app" : "nextjs-pages";
189
+ }
190
+ if (deps.nuxt) {
191
+ return "nuxt";
192
+ }
193
+ if (deps["@sveltejs/kit"]) {
194
+ return "sveltekit";
195
+ }
196
+ if (deps.astro) {
197
+ return "astro";
198
+ }
199
+ if (deps.vite) {
200
+ if (deps.react || deps["react-dom"]) {
201
+ return "vite-react";
202
+ }
203
+ if (deps.vue) {
204
+ return "vite-vue";
205
+ }
206
+ if (deps.svelte) {
207
+ return "vite-svelte";
208
+ }
209
+ }
210
+ return "unknown";
211
+ } catch {
212
+ return "unknown";
213
+ }
214
+ }
215
+ function detectPackageManager(cwd) {
216
+ if (fs2.existsSync(path2.join(cwd, "pnpm-lock.yaml"))) {
217
+ return "pnpm";
218
+ }
219
+ if (fs2.existsSync(path2.join(cwd, "yarn.lock"))) {
220
+ return "yarn";
221
+ }
222
+ if (fs2.existsSync(path2.join(cwd, "bun.lockb"))) {
223
+ return "bun";
224
+ }
225
+ return "npm";
226
+ }
227
+ function hasTailwindInstalled(cwd) {
228
+ try {
229
+ const pkgPath = path2.join(cwd, "package.json");
230
+ if (!fs2.existsSync(pkgPath)) {
231
+ return false;
232
+ }
233
+ const pkg = fs2.readJSONSync(pkgPath);
234
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
235
+ return !!deps.tailwindcss;
236
+ } catch {
237
+ return false;
238
+ }
239
+ }
240
+ function hasTypeScript(cwd) {
241
+ return fs2.existsSync(path2.join(cwd, "tsconfig.json")) || fs2.existsSync(path2.join(cwd, "jsconfig.json"));
242
+ }
243
+ function getProjectInfo(cwd = process.cwd()) {
244
+ return {
245
+ framework: detectFramework(cwd),
246
+ packageManager: detectPackageManager(cwd),
247
+ hasTailwind: hasTailwindInstalled(cwd),
248
+ hasTypeScript: hasTypeScript(cwd),
249
+ rootDir: cwd
250
+ };
251
+ }
252
+ function getFrameworkName(framework) {
253
+ const names = {
254
+ "vite-react": "Vite + React",
255
+ "vite-vue": "Vite + Vue",
256
+ "vite-svelte": "Vite + Svelte",
257
+ "nextjs-app": "Next.js (App Router)",
258
+ "nextjs-pages": "Next.js (Pages Router)",
259
+ nuxt: "Nuxt 3",
260
+ sveltekit: "SvelteKit",
261
+ astro: "Astro",
262
+ unknown: "Unknown"
263
+ };
264
+ return names[framework];
265
+ }
266
+
267
+ // src/commands/doctor.ts
268
+ async function doctor(options = {}) {
269
+ const cwd = options.cwd || process.cwd();
270
+ const projectInfo = getProjectInfo(cwd);
271
+ printHeader("csszyx Doctor");
272
+ let issueCount = 0;
273
+ printSection("\u{1F4CB} Configuration Health");
274
+ const hasConfig = fs3.existsSync(path3.join(cwd, "csszyx.config.ts")) || fs3.existsSync(path3.join(cwd, "csszyx.config.js"));
275
+ if (hasConfig) {
276
+ printSuccess("csszyx configuration found");
277
+ } else {
278
+ printWarn("No csszyx.config found - using defaults");
279
+ }
280
+ if (projectInfo.hasTailwind) {
281
+ printSuccess("Tailwind CSS installed");
282
+ } else {
283
+ printError("Tailwind CSS not found");
284
+ issueCount++;
285
+ if (options.verbose) {
286
+ console.log(" \u2192 Run: npm install -D tailwindcss");
287
+ }
288
+ }
289
+ printSection("\u{1F4E6} Package Versions");
290
+ try {
291
+ const pkgPath = path3.join(cwd, "package.json");
292
+ const pkg = fs3.readJSONSync(pkgPath);
293
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
294
+ if (deps.csszyx) {
295
+ printSuccess(`csszyx: ${deps.csszyx}`);
296
+ } else {
297
+ printError("csszyx package not installed");
298
+ issueCount++;
299
+ }
300
+ } catch {
301
+ printError("Failed to read package.json");
302
+ issueCount++;
303
+ }
304
+ printSection("\u{1F528} Build Output");
305
+ const distDir = path3.join(cwd, "dist");
306
+ if (fs3.existsSync(distDir)) {
307
+ const htmlFiles = fs3.readdirSync(distDir, { recursive: true }).filter((f) => String(f).endsWith(".html"));
308
+ if (htmlFiles.length > 0) {
309
+ printSuccess(`Found ${htmlFiles.length} HTML file(s)`);
310
+ const htmlContent = fs3.readFileSync(
311
+ path3.join(distDir, String(htmlFiles[0])),
312
+ "utf-8"
313
+ );
314
+ if (htmlContent.includes("data-sz-checksum")) {
315
+ printSuccess("Checksum injection working");
316
+ } else {
317
+ printWarn("Checksum not found in HTML");
318
+ if (options.verbose) {
319
+ console.log(" \u2192 Enable injectChecksum in production config");
320
+ }
321
+ }
322
+ }
323
+ } else {
324
+ printWarn("No build output found - run build first");
325
+ }
326
+ console.log();
327
+ if (issueCount === 0) {
328
+ printSuccess("\u2728 No issues found! Your setup looks good.");
329
+ } else {
330
+ printWarn(`Found ${issueCount} issue(s)`);
331
+ console.log();
332
+ console.log("Run `csszyx doctor --fix` to auto-fix common issues");
333
+ }
334
+ }
335
+
336
+ // src/commands/generate-types.ts
337
+ import { resolve as resolve3 } from "path";
338
+
339
+ // src/generator/type-generator.ts
340
+ import { writeFileSync } from "fs";
341
+ import { mkdir } from "fs/promises";
342
+ import { dirname, resolve as resolve2 } from "path";
343
+
344
+ // src/scanner/tailwind-scanner.ts
345
+ import { existsSync } from "fs";
346
+ import { resolve } from "path";
347
+ import { pathToFileURL } from "url";
348
+ import resolveConfig from "tailwindcss/resolveConfig.js";
349
+ var CONFIG_FILES = [
350
+ "tailwind.config.ts",
351
+ "tailwind.config.js",
352
+ "tailwind.config.cjs",
353
+ "tailwind.config.mjs"
354
+ ];
355
+ function findConfigFile(cwd) {
356
+ for (const fileName of CONFIG_FILES) {
357
+ const configPath = resolve(cwd, fileName);
358
+ if (existsSync(configPath)) {
359
+ return configPath;
360
+ }
361
+ }
362
+ return null;
363
+ }
364
+ async function scanTailwindConfig(configPath) {
365
+ const absolutePath = resolve(configPath);
366
+ if (!existsSync(absolutePath)) {
367
+ throw new Error(`Tailwind config not found: ${absolutePath}`);
368
+ }
369
+ let userConfig;
370
+ try {
371
+ const fileUrl = pathToFileURL(absolutePath).href;
372
+ const module = await import(fileUrl);
373
+ userConfig = module.default || module;
374
+ } catch (error) {
375
+ throw new Error(
376
+ `Failed to load Tailwind config: ${error instanceof Error ? error.message : String(error)}`
377
+ );
378
+ }
379
+ const resolvedConfig = resolveConfig(userConfig);
380
+ const theme = resolvedConfig.theme;
381
+ const hasCustomColors = Boolean(
382
+ userConfig.theme?.colors || userConfig.theme?.extend?.colors
383
+ );
384
+ const hasCustomSpacing = Boolean(
385
+ userConfig.theme?.spacing || userConfig.theme?.extend?.spacing
386
+ );
387
+ return {
388
+ theme,
389
+ configPath: absolutePath,
390
+ hasCustomColors,
391
+ hasCustomSpacing
392
+ };
393
+ }
394
+ function flattenColors(colors2) {
395
+ const result = [];
396
+ for (const [key, value] of Object.entries(colors2)) {
397
+ if (key === "inherit" || key === "current" || key === "transparent") {
398
+ result.push(key);
399
+ continue;
400
+ }
401
+ if (typeof value === "string") {
402
+ result.push(key);
403
+ } else if (typeof value === "object" && value !== null) {
404
+ for (const shade of Object.keys(value)) {
405
+ if (shade === "DEFAULT") {
406
+ result.push(key);
407
+ } else {
408
+ result.push(`${key}-${shade}`);
409
+ }
410
+ }
411
+ }
412
+ }
413
+ return result.sort();
414
+ }
415
+ function extractSpacingKeys(spacing) {
416
+ return Object.keys(spacing).sort((a, b) => {
417
+ const aNum = parseFloat(a);
418
+ const bNum = parseFloat(b);
419
+ if (!isNaN(aNum) && !isNaN(bNum)) {
420
+ return aNum - bNum;
421
+ }
422
+ if (!isNaN(aNum)) {
423
+ return -1;
424
+ }
425
+ if (!isNaN(bNum)) {
426
+ return 1;
427
+ }
428
+ return a.localeCompare(b);
429
+ });
430
+ }
431
+ function extractScreenKeys(screens) {
432
+ return Object.keys(screens);
433
+ }
434
+
435
+ // src/generator/type-generator.ts
436
+ var PROPERTY_MAPPINGS = [
437
+ // Layout
438
+ {
439
+ prop: "display",
440
+ prefix: "",
441
+ valueType: "display",
442
+ description: "CSS display property"
443
+ },
444
+ {
445
+ prop: "position",
446
+ prefix: "",
447
+ valueType: "position",
448
+ description: "CSS position property"
449
+ },
450
+ {
451
+ prop: "overflow",
452
+ prefix: "overflow",
453
+ valueType: "overflow",
454
+ description: "CSS overflow property"
455
+ },
456
+ {
457
+ prop: "z",
458
+ prefix: "z",
459
+ valueType: "zIndex",
460
+ description: "CSS z-index property"
461
+ },
462
+ // Flexbox & Grid
463
+ {
464
+ prop: "flex",
465
+ prefix: "flex",
466
+ valueType: "flex",
467
+ description: "Flex shorthand"
468
+ },
469
+ {
470
+ prop: "flexDir",
471
+ prefix: "flex",
472
+ valueType: "flexDirection",
473
+ description: "Flex direction"
474
+ },
475
+ {
476
+ prop: "justify",
477
+ prefix: "justify",
478
+ valueType: "justify",
479
+ description: "Justify content"
480
+ },
481
+ {
482
+ prop: "items",
483
+ prefix: "items",
484
+ valueType: "items",
485
+ description: "Align items"
486
+ },
487
+ {
488
+ prop: "gap",
489
+ prefix: "gap",
490
+ valueType: "spacing",
491
+ description: "Gap between flex/grid items"
492
+ },
493
+ {
494
+ prop: "grid",
495
+ prefix: "grid",
496
+ valueType: "grid",
497
+ description: "Grid shorthand"
498
+ },
499
+ {
500
+ prop: "gridCols",
501
+ prefix: "grid-cols",
502
+ valueType: "gridCols",
503
+ description: "Grid template columns"
504
+ },
505
+ {
506
+ prop: "gridRows",
507
+ prefix: "grid-rows",
508
+ valueType: "gridRows",
509
+ description: "Grid template rows"
510
+ },
511
+ {
512
+ prop: "col",
513
+ prefix: "col",
514
+ valueType: "col",
515
+ description: "Grid column span"
516
+ },
517
+ {
518
+ prop: "row",
519
+ prefix: "row",
520
+ valueType: "row",
521
+ description: "Grid row span"
522
+ },
523
+ // Spacing
524
+ {
525
+ prop: "p",
526
+ prefix: "p",
527
+ valueType: "spacing",
528
+ responsive: true,
529
+ description: "Padding (all sides)"
530
+ },
531
+ {
532
+ prop: "px",
533
+ prefix: "px",
534
+ valueType: "spacing",
535
+ responsive: true,
536
+ description: "Padding horizontal"
537
+ },
538
+ {
539
+ prop: "py",
540
+ prefix: "py",
541
+ valueType: "spacing",
542
+ responsive: true,
543
+ description: "Padding vertical"
544
+ },
545
+ {
546
+ prop: "pt",
547
+ prefix: "pt",
548
+ valueType: "spacing",
549
+ responsive: true,
550
+ description: "Padding top"
551
+ },
552
+ {
553
+ prop: "pr",
554
+ prefix: "pr",
555
+ valueType: "spacing",
556
+ responsive: true,
557
+ description: "Padding right"
558
+ },
559
+ {
560
+ prop: "pb",
561
+ prefix: "pb",
562
+ valueType: "spacing",
563
+ responsive: true,
564
+ description: "Padding bottom"
565
+ },
566
+ {
567
+ prop: "pl",
568
+ prefix: "pl",
569
+ valueType: "spacing",
570
+ responsive: true,
571
+ description: "Padding left"
572
+ },
573
+ {
574
+ prop: "m",
575
+ prefix: "m",
576
+ valueType: "spacing",
577
+ responsive: true,
578
+ description: "Margin (all sides)"
579
+ },
580
+ {
581
+ prop: "mx",
582
+ prefix: "mx",
583
+ valueType: "spacing",
584
+ responsive: true,
585
+ description: "Margin horizontal"
586
+ },
587
+ {
588
+ prop: "my",
589
+ prefix: "my",
590
+ valueType: "spacing",
591
+ responsive: true,
592
+ description: "Margin vertical"
593
+ },
594
+ {
595
+ prop: "mt",
596
+ prefix: "mt",
597
+ valueType: "spacing",
598
+ responsive: true,
599
+ description: "Margin top"
600
+ },
601
+ {
602
+ prop: "mr",
603
+ prefix: "mr",
604
+ valueType: "spacing",
605
+ responsive: true,
606
+ description: "Margin right"
607
+ },
608
+ {
609
+ prop: "mb",
610
+ prefix: "mb",
611
+ valueType: "spacing",
612
+ responsive: true,
613
+ description: "Margin bottom"
614
+ },
615
+ {
616
+ prop: "ml",
617
+ prefix: "ml",
618
+ valueType: "spacing",
619
+ responsive: true,
620
+ description: "Margin left"
621
+ },
622
+ // Sizing
623
+ {
624
+ prop: "w",
625
+ prefix: "w",
626
+ valueType: "sizing",
627
+ responsive: true,
628
+ description: "Width"
629
+ },
630
+ {
631
+ prop: "h",
632
+ prefix: "h",
633
+ valueType: "sizing",
634
+ responsive: true,
635
+ description: "Height"
636
+ },
637
+ {
638
+ prop: "minW",
639
+ prefix: "min-w",
640
+ valueType: "minWidth",
641
+ description: "Minimum width"
642
+ },
643
+ {
644
+ prop: "maxW",
645
+ prefix: "max-w",
646
+ valueType: "maxWidth",
647
+ description: "Maximum width"
648
+ },
649
+ {
650
+ prop: "minH",
651
+ prefix: "min-h",
652
+ valueType: "minHeight",
653
+ description: "Minimum height"
654
+ },
655
+ {
656
+ prop: "maxH",
657
+ prefix: "max-h",
658
+ valueType: "maxHeight",
659
+ description: "Maximum height"
660
+ },
661
+ // Colors
662
+ {
663
+ prop: "bg",
664
+ prefix: "bg",
665
+ valueType: "colors",
666
+ stateful: true,
667
+ description: "Background color"
668
+ },
669
+ {
670
+ prop: "text",
671
+ prefix: "text",
672
+ valueType: "colors",
673
+ stateful: true,
674
+ description: "Text color"
675
+ },
676
+ {
677
+ prop: "border",
678
+ prefix: "border",
679
+ valueType: "colors",
680
+ stateful: true,
681
+ description: "Border color"
682
+ },
683
+ {
684
+ prop: "ring",
685
+ prefix: "ring",
686
+ valueType: "colors",
687
+ stateful: true,
688
+ description: "Ring color"
689
+ },
690
+ {
691
+ prop: "fill",
692
+ prefix: "fill",
693
+ valueType: "colors",
694
+ description: "SVG fill color"
695
+ },
696
+ {
697
+ prop: "stroke",
698
+ prefix: "stroke",
699
+ valueType: "colors",
700
+ description: "SVG stroke color"
701
+ },
702
+ // Typography
703
+ {
704
+ prop: "font",
705
+ prefix: "font",
706
+ valueType: "fontWeight",
707
+ description: "Font weight"
708
+ },
709
+ {
710
+ prop: "fontFamily",
711
+ prefix: "font",
712
+ valueType: "fontFamily",
713
+ description: "Font family"
714
+ },
715
+ {
716
+ prop: "fontSize",
717
+ prefix: "text",
718
+ valueType: "fontSize",
719
+ description: "Font size"
720
+ },
721
+ {
722
+ prop: "leading",
723
+ prefix: "leading",
724
+ valueType: "lineHeight",
725
+ description: "Line height"
726
+ },
727
+ {
728
+ prop: "tracking",
729
+ prefix: "tracking",
730
+ valueType: "letterSpacing",
731
+ description: "Letter spacing"
732
+ },
733
+ {
734
+ prop: "textAlign",
735
+ prefix: "text",
736
+ valueType: "textAlign",
737
+ description: "Text alignment"
738
+ },
739
+ // Borders
740
+ {
741
+ prop: "rounded",
742
+ prefix: "rounded",
743
+ valueType: "borderRadius",
744
+ description: "Border radius"
745
+ },
746
+ {
747
+ prop: "borderW",
748
+ prefix: "border",
749
+ valueType: "borderWidth",
750
+ description: "Border width"
751
+ },
752
+ // Effects
753
+ {
754
+ prop: "shadow",
755
+ prefix: "shadow",
756
+ valueType: "boxShadow",
757
+ description: "Box shadow"
758
+ },
759
+ {
760
+ prop: "opacity",
761
+ prefix: "opacity",
762
+ valueType: "opacity",
763
+ description: "Opacity"
764
+ },
765
+ // Transforms
766
+ {
767
+ prop: "scale",
768
+ prefix: "scale",
769
+ valueType: "scale",
770
+ description: "Scale transform"
771
+ },
772
+ {
773
+ prop: "rotate",
774
+ prefix: "rotate",
775
+ valueType: "rotate",
776
+ description: "Rotate transform"
777
+ },
778
+ {
779
+ prop: "translate",
780
+ prefix: "translate",
781
+ valueType: "translate",
782
+ description: "Translate transform"
783
+ },
784
+ // Transitions
785
+ {
786
+ prop: "transition",
787
+ prefix: "transition",
788
+ valueType: "transition",
789
+ description: "Transition property"
790
+ },
791
+ {
792
+ prop: "duration",
793
+ prefix: "duration",
794
+ valueType: "duration",
795
+ description: "Transition duration"
796
+ },
797
+ {
798
+ prop: "ease",
799
+ prefix: "ease",
800
+ valueType: "ease",
801
+ description: "Transition timing function"
802
+ }
803
+ ];
804
+ var STATIC_VALUE_TYPES = {
805
+ display: [
806
+ "block",
807
+ "inline-block",
808
+ "inline",
809
+ "flex",
810
+ "inline-flex",
811
+ "grid",
812
+ "inline-grid",
813
+ "hidden",
814
+ "contents",
815
+ "flow-root"
816
+ ],
817
+ position: ["static", "fixed", "absolute", "relative", "sticky"],
818
+ overflow: [
819
+ "auto",
820
+ "hidden",
821
+ "clip",
822
+ "visible",
823
+ "scroll",
824
+ "x-auto",
825
+ "y-auto",
826
+ "x-hidden",
827
+ "y-hidden",
828
+ "x-clip",
829
+ "y-clip",
830
+ "x-visible",
831
+ "y-visible",
832
+ "x-scroll",
833
+ "y-scroll"
834
+ ],
835
+ flexDirection: ["row", "row-reverse", "col", "col-reverse"],
836
+ justify: [
837
+ "normal",
838
+ "start",
839
+ "end",
840
+ "center",
841
+ "between",
842
+ "around",
843
+ "evenly",
844
+ "stretch"
845
+ ],
846
+ items: ["start", "end", "center", "baseline", "stretch"],
847
+ flex: ["1", "auto", "initial", "none"],
848
+ grid: [
849
+ "flow-row",
850
+ "flow-col",
851
+ "flow-dense",
852
+ "flow-row-dense",
853
+ "flow-col-dense"
854
+ ],
855
+ gridCols: [
856
+ "1",
857
+ "2",
858
+ "3",
859
+ "4",
860
+ "5",
861
+ "6",
862
+ "7",
863
+ "8",
864
+ "9",
865
+ "10",
866
+ "11",
867
+ "12",
868
+ "none",
869
+ "subgrid"
870
+ ],
871
+ gridRows: ["1", "2", "3", "4", "5", "6", "none", "subgrid"],
872
+ col: [
873
+ "auto",
874
+ "span-1",
875
+ "span-2",
876
+ "span-3",
877
+ "span-4",
878
+ "span-5",
879
+ "span-6",
880
+ "span-7",
881
+ "span-8",
882
+ "span-9",
883
+ "span-10",
884
+ "span-11",
885
+ "span-12",
886
+ "span-full",
887
+ "start-1",
888
+ "start-2",
889
+ "start-3",
890
+ "start-4",
891
+ "start-5",
892
+ "start-6",
893
+ "start-7",
894
+ "start-8",
895
+ "start-9",
896
+ "start-10",
897
+ "start-11",
898
+ "start-12",
899
+ "start-13",
900
+ "start-auto",
901
+ "end-1",
902
+ "end-2",
903
+ "end-3",
904
+ "end-4",
905
+ "end-5",
906
+ "end-6",
907
+ "end-7",
908
+ "end-8",
909
+ "end-9",
910
+ "end-10",
911
+ "end-11",
912
+ "end-12",
913
+ "end-13",
914
+ "end-auto"
915
+ ],
916
+ row: [
917
+ "auto",
918
+ "span-1",
919
+ "span-2",
920
+ "span-3",
921
+ "span-4",
922
+ "span-5",
923
+ "span-6",
924
+ "span-full",
925
+ "start-1",
926
+ "start-2",
927
+ "start-3",
928
+ "start-4",
929
+ "start-5",
930
+ "start-6",
931
+ "start-7",
932
+ "start-auto",
933
+ "end-1",
934
+ "end-2",
935
+ "end-3",
936
+ "end-4",
937
+ "end-5",
938
+ "end-6",
939
+ "end-7",
940
+ "end-auto"
941
+ ],
942
+ textAlign: ["left", "center", "right", "justify", "start", "end"],
943
+ fontWeight: [
944
+ "thin",
945
+ "extralight",
946
+ "light",
947
+ "normal",
948
+ "medium",
949
+ "semibold",
950
+ "bold",
951
+ "extrabold",
952
+ "black"
953
+ ],
954
+ transition: ["none", "all", "colors", "opacity", "shadow", "transform"],
955
+ ease: ["linear", "in", "out", "in-out"]
956
+ };
957
+ function generateUnionType(values) {
958
+ if (values.length === 0) {
959
+ return "string";
960
+ }
961
+ return values.map((v) => `'${v}'`).join(" | ");
962
+ }
963
+ function generateTypeDeclarations(theme, options = {}) {
964
+ const { includeComments = true } = options;
965
+ const colors2 = flattenColors(theme.colors || {});
966
+ const spacing = extractSpacingKeys(theme.spacing || {});
967
+ const screens = extractScreenKeys(theme.screens || {});
968
+ const sizing = [
969
+ ...spacing,
970
+ "auto",
971
+ "full",
972
+ "screen",
973
+ "svw",
974
+ "lvw",
975
+ "dvw",
976
+ "min",
977
+ "max",
978
+ "fit",
979
+ "1/2",
980
+ "1/3",
981
+ "2/3",
982
+ "1/4",
983
+ "2/4",
984
+ "3/4",
985
+ "1/5",
986
+ "2/5",
987
+ "3/5",
988
+ "4/5",
989
+ "1/6",
990
+ "5/6"
991
+ ];
992
+ const valueTypeMap = {
993
+ colors: colors2,
994
+ spacing,
995
+ sizing,
996
+ screens,
997
+ ...STATIC_VALUE_TYPES,
998
+ // Extract from theme if available
999
+ zIndex: theme.zIndex ? Object.keys(theme.zIndex) : ["0", "10", "20", "30", "40", "50", "auto"],
1000
+ borderRadius: theme.borderRadius ? Object.keys(theme.borderRadius) : ["none", "sm", "md", "lg", "xl", "2xl", "3xl", "full"],
1001
+ boxShadow: theme.boxShadow ? Object.keys(theme.boxShadow) : ["sm", "md", "lg", "xl", "2xl", "inner", "none"],
1002
+ opacity: theme.opacity ? Object.keys(theme.opacity) : [
1003
+ "0",
1004
+ "5",
1005
+ "10",
1006
+ "20",
1007
+ "25",
1008
+ "30",
1009
+ "40",
1010
+ "50",
1011
+ "60",
1012
+ "70",
1013
+ "75",
1014
+ "80",
1015
+ "90",
1016
+ "95",
1017
+ "100"
1018
+ ],
1019
+ fontSize: theme.fontSize ? Object.keys(theme.fontSize) : [
1020
+ "xs",
1021
+ "sm",
1022
+ "base",
1023
+ "lg",
1024
+ "xl",
1025
+ "2xl",
1026
+ "3xl",
1027
+ "4xl",
1028
+ "5xl",
1029
+ "6xl",
1030
+ "7xl",
1031
+ "8xl",
1032
+ "9xl"
1033
+ ],
1034
+ fontFamily: theme.fontFamily ? Object.keys(theme.fontFamily) : ["sans", "serif", "mono"],
1035
+ lineHeight: [
1036
+ "none",
1037
+ "tight",
1038
+ "snug",
1039
+ "normal",
1040
+ "relaxed",
1041
+ "loose",
1042
+ "3",
1043
+ "4",
1044
+ "5",
1045
+ "6",
1046
+ "7",
1047
+ "8",
1048
+ "9",
1049
+ "10"
1050
+ ],
1051
+ letterSpacing: ["tighter", "tight", "normal", "wide", "wider", "widest"],
1052
+ borderWidth: ["0", "2", "4", "8", ""],
1053
+ minWidth: ["0", "full", "min", "max", "fit"],
1054
+ maxWidth: [
1055
+ "0",
1056
+ "none",
1057
+ "xs",
1058
+ "sm",
1059
+ "md",
1060
+ "lg",
1061
+ "xl",
1062
+ "2xl",
1063
+ "3xl",
1064
+ "4xl",
1065
+ "5xl",
1066
+ "6xl",
1067
+ "7xl",
1068
+ "full",
1069
+ "min",
1070
+ "max",
1071
+ "fit",
1072
+ "prose",
1073
+ "screen-sm",
1074
+ "screen-md",
1075
+ "screen-lg",
1076
+ "screen-xl",
1077
+ "screen-2xl"
1078
+ ],
1079
+ minHeight: [
1080
+ "0",
1081
+ "full",
1082
+ "screen",
1083
+ "svh",
1084
+ "lvh",
1085
+ "dvh",
1086
+ "min",
1087
+ "max",
1088
+ "fit"
1089
+ ],
1090
+ maxHeight: [
1091
+ "0",
1092
+ "none",
1093
+ "full",
1094
+ "screen",
1095
+ "svh",
1096
+ "lvh",
1097
+ "dvh",
1098
+ "min",
1099
+ "max",
1100
+ "fit"
1101
+ ],
1102
+ scale: ["0", "50", "75", "90", "95", "100", "105", "110", "125", "150"],
1103
+ rotate: ["0", "1", "2", "3", "6", "12", "45", "90", "180"],
1104
+ translate: spacing,
1105
+ duration: ["0", "75", "100", "150", "200", "300", "500", "700", "1000"]
1106
+ };
1107
+ const properties = [];
1108
+ for (const mapping of PROPERTY_MAPPINGS) {
1109
+ const values = valueTypeMap[mapping.valueType] || [];
1110
+ const unionType = generateUnionType(values);
1111
+ let propDef = "";
1112
+ if (includeComments && mapping.description) {
1113
+ propDef += ` /** ${mapping.description} */
1114
+ `;
1115
+ }
1116
+ propDef += ` ${mapping.prop}?: ${unionType} | (string & {}) | number;`;
1117
+ properties.push(propDef);
1118
+ }
1119
+ const variants = [
1120
+ "hover",
1121
+ "focus",
1122
+ "active",
1123
+ "disabled",
1124
+ "visited",
1125
+ "first",
1126
+ "last",
1127
+ "odd",
1128
+ "even",
1129
+ "group-hover",
1130
+ "dark"
1131
+ ];
1132
+ const variantProps = [];
1133
+ for (const variant of variants) {
1134
+ if (includeComments) {
1135
+ variantProps.push(` /** Styles applied on ${variant} state */`);
1136
+ }
1137
+ variantProps.push(` ${variant}?: SzVariantObject;`);
1138
+ }
1139
+ const responsiveProps = [];
1140
+ for (const screen of screens) {
1141
+ if (includeComments) {
1142
+ responsiveProps.push(
1143
+ ` /** Styles applied at ${screen} breakpoint and above */`
1144
+ );
1145
+ }
1146
+ responsiveProps.push(` ${screen}?: SzVariantObject;`);
1147
+ }
1148
+ const output = `/**
1149
+ * Auto-generated TypeScript declarations for csszyx.
1150
+ *
1151
+ * This file provides strict typing for the sz prop based on your
1152
+ * Tailwind CSS configuration.
1153
+ *
1154
+ * @generated by @csszyx/cli
1155
+ * @see https://github.com/nguyennhutien/csszyx
1156
+ */
1157
+
1158
+ import '@csszyx/types';
1159
+
1160
+ /**
1161
+ * Variant object type (used for hover, focus, responsive breakpoints, etc.)
1162
+ */
1163
+ type SzVariantObject = Partial<StrictSzObject>;
1164
+
1165
+ /**
1166
+ * Strict sz object interface with typed properties.
1167
+ */
1168
+ interface StrictSzObject {
1169
+ ${properties.join("\n")}
1170
+
1171
+ // State variants
1172
+ ${variantProps.join("\n")}
1173
+
1174
+ // Responsive variants
1175
+ ${responsiveProps.join("\n")}
1176
+
1177
+ // Allow arbitrary properties for escape hatch
1178
+ [key: string]: string | number | boolean | SzVariantObject | undefined;
1179
+ }
1180
+
1181
+ declare module '@csszyx/types' {
1182
+ /**
1183
+ * Override the base SzObject with strict typing.
1184
+ */
1185
+ interface SzObject extends StrictSzObject {}
1186
+ }
1187
+
1188
+ declare module 'react' {
1189
+ interface HTMLAttributes<T> {
1190
+ /**
1191
+ * csszyx object syntax for Tailwind CSS classes.
1192
+ * Provides IntelliSense for all Tailwind utilities.
1193
+ */
1194
+ sz?: StrictSzObject;
1195
+ }
1196
+
1197
+ interface SVGAttributes<T> {
1198
+ /**
1199
+ * csszyx object syntax for Tailwind CSS classes.
1200
+ */
1201
+ sz?: StrictSzObject;
1202
+ }
1203
+ }
1204
+
1205
+ export {};
1206
+ `;
1207
+ return output;
1208
+ }
1209
+ async function writeDeclarationFile(content, outputPath) {
1210
+ const absolutePath = resolve2(outputPath);
1211
+ const dir = dirname(absolutePath);
1212
+ await mkdir(dir, { recursive: true });
1213
+ writeFileSync(absolutePath, content, "utf-8");
1214
+ }
1215
+ async function generateAndWriteTypes(theme, options = {}) {
1216
+ const outputPath = options.output || "./csszyx.d.ts";
1217
+ const content = generateTypeDeclarations(theme, options);
1218
+ await writeDeclarationFile(content, outputPath);
1219
+ return resolve2(outputPath);
1220
+ }
1221
+
1222
+ // src/commands/generate-types.ts
1223
+ async function generateTypes(options = {}) {
1224
+ const cwd = options.cwd || process.cwd();
1225
+ const log = options.silent ? () => {
1226
+ } : console.log;
1227
+ const error = options.silent ? () => {
1228
+ } : console.error;
1229
+ let configPath, scanResult;
1230
+ if (options.config) {
1231
+ configPath = resolve3(cwd, options.config);
1232
+ } else {
1233
+ log("\u{1F50D} Searching for tailwind.config...");
1234
+ const foundConfig = findConfigFile(cwd);
1235
+ if (!foundConfig) {
1236
+ error("\u274C Could not find tailwind.config.js in current directory");
1237
+ error(" Please specify the path with --config flag");
1238
+ process.exit(1);
1239
+ }
1240
+ configPath = foundConfig;
1241
+ }
1242
+ log(`\u{1F4D6} Reading config from: ${configPath}`);
1243
+ try {
1244
+ scanResult = await scanTailwindConfig(configPath);
1245
+ } catch (err) {
1246
+ error(
1247
+ `\u274C Failed to read Tailwind config: ${err instanceof Error ? err.message : String(err)}`
1248
+ );
1249
+ process.exit(1);
1250
+ }
1251
+ log("\u2705 Config loaded successfully");
1252
+ if (scanResult.hasCustomColors) {
1253
+ log(" \u2022 Custom colors detected");
1254
+ }
1255
+ if (scanResult.hasCustomSpacing) {
1256
+ log(" \u2022 Custom spacing detected");
1257
+ }
1258
+ const outputPath = options.output || "./csszyx.d.ts";
1259
+ const generatorOptions = {
1260
+ output: resolve3(cwd, outputPath),
1261
+ includeComments: true
1262
+ };
1263
+ log("\n\u{1F4DD} Generating TypeScript declarations...");
1264
+ try {
1265
+ const writtenPath = await generateAndWriteTypes(
1266
+ scanResult.theme,
1267
+ generatorOptions
1268
+ );
1269
+ log("\n\u2728 Types generated successfully!");
1270
+ log(` Output: ${writtenPath}`);
1271
+ log('\n\u{1F4A1} Add this to your tsconfig.json "include" array:');
1272
+ log(' "include": ["src", "csszyx.d.ts"]');
1273
+ } catch (err) {
1274
+ error(
1275
+ `\u274C Failed to generate types: ${err instanceof Error ? err.message : String(err)}`
1276
+ );
1277
+ process.exit(1);
1278
+ }
1279
+ }
1280
+
1281
+ // src/commands/init.ts
1282
+ import path4 from "path";
1283
+ import { execa } from "execa";
1284
+ import fs4 from "fs-extra";
1285
+ import prompts from "prompts";
1286
+ async function init(options = {}) {
1287
+ const cwd = options.cwd || process.cwd();
1288
+ const projectInfo = getProjectInfo(cwd);
1289
+ printHeader("csszyx Setup Wizard");
1290
+ if (projectInfo.framework !== "unknown") {
1291
+ printSuccess(`Detected: ${getFrameworkName(projectInfo.framework)}`);
1292
+ printInfo(`Package Manager: ${projectInfo.packageManager}`);
1293
+ }
1294
+ let config = {
1295
+ enableSSR: true,
1296
+ enableRecovery: true,
1297
+ installTailwind: !projectInfo.hasTailwind
1298
+ };
1299
+ if (!options.yes) {
1300
+ const answers = await prompts([
1301
+ {
1302
+ type: projectInfo.hasTailwind ? null : "confirm",
1303
+ name: "installTailwind",
1304
+ message: "Install Tailwind CSS?",
1305
+ initial: true
1306
+ },
1307
+ {
1308
+ type: "confirm",
1309
+ name: "enableSSR",
1310
+ message: "Enable SSR Hydration Guard?",
1311
+ initial: true
1312
+ },
1313
+ {
1314
+ type: "confirm",
1315
+ name: "enableRecovery",
1316
+ message: "Enable development mode recovery?",
1317
+ initial: true
1318
+ }
1319
+ ]);
1320
+ config = { ...config, ...answers };
1321
+ }
1322
+ const spin = spinner.start("Installing csszyx...");
1323
+ try {
1324
+ await execa(projectInfo.packageManager, ["add", "csszyx"], { cwd });
1325
+ if (config.installTailwind) {
1326
+ await execa(
1327
+ projectInfo.packageManager,
1328
+ ["add", "-D", "tailwindcss", "postcss", "autoprefixer"],
1329
+ { cwd }
1330
+ );
1331
+ }
1332
+ spinner.succeed(spin, "Installed csszyx");
1333
+ } catch (error) {
1334
+ spinner.fail(spin, "Failed to install packages");
1335
+ printError(String(error));
1336
+ return;
1337
+ }
1338
+ const spin2 = spinner.start("Creating config files...");
1339
+ try {
1340
+ const configContent = generateConfigFile(config, projectInfo.framework);
1341
+ const configPath = path4.join(
1342
+ cwd,
1343
+ projectInfo.hasTypeScript ? "csszyx.config.ts" : "csszyx.config.js"
1344
+ );
1345
+ await fs4.writeFile(configPath, configContent);
1346
+ if (config.installTailwind) {
1347
+ await fs4.writeFile(
1348
+ path4.join(cwd, "tailwind.config.js"),
1349
+ generateTailwindConfig()
1350
+ );
1351
+ }
1352
+ spinner.succeed(spin2, "Created configuration files");
1353
+ } catch (error) {
1354
+ spinner.fail(spin2, "Failed to create config files");
1355
+ printError(String(error));
1356
+ return;
1357
+ }
1358
+ console.log();
1359
+ printSuccess("\u{1F389} All done!");
1360
+ console.log();
1361
+ printInfo("Next steps:");
1362
+ console.log(` \u2022 Run '${projectInfo.packageManager} run dev' to start`);
1363
+ console.log(" \u2022 Open http://localhost:5174 for the dashboard");
1364
+ console.log(" \u2022 Check the docs at https://github.com/nguyennhutien/csszyx");
1365
+ }
1366
+ function generateConfigFile(config, framework) {
1367
+ return `import type { CsszyxConfig } from 'csszyx';
1368
+
1369
+ const config: CsszyxConfig = {
1370
+ development: {
1371
+ debug: true,
1372
+ autoInjectRecovery: ${config.enableRecovery},
1373
+ allowCSRRecovery: ${config.enableRecovery},
1374
+ },
1375
+ production: {
1376
+ injectChecksum: ${config.enableSSR},
1377
+ },
1378
+ };
1379
+
1380
+ export default config;
1381
+ `;
1382
+ }
1383
+ function generateTailwindConfig() {
1384
+ return `/** @type {import('tailwindcss').Config} */
1385
+ export default {
1386
+ content: ['./index.html', './src/**/*.{js,ts,jsx,tsx,vue,svelte}'],
1387
+ theme: {
1388
+ extend: {},
1389
+ },
1390
+ plugins: [],
1391
+ };
1392
+ `;
1393
+ }
1394
+
1395
+ // src/commands/migrate.ts
1396
+ import fs5 from "fs";
1397
+ import path5 from "path";
1398
+ import fg from "fast-glob";
1399
+
1400
+ // src/migrate/sz-codegen.ts
1401
+ function generateSzExpression(obj) {
1402
+ return `{${objectToString(obj)}}`;
1403
+ }
1404
+ function objectToString(obj, indent = 0) {
1405
+ const entries = Object.entries(obj);
1406
+ if (entries.length === 0) {
1407
+ return "{}";
1408
+ }
1409
+ const spaces = " ".repeat(indent);
1410
+ const innerSpaces = " ".repeat(indent + 2);
1411
+ if (entries.length <= 2 && !hasDeepNesting(obj)) {
1412
+ const parts = entries.map(([k, v]) => `${formatKey(k)}: ${formatValue(v, indent)}`);
1413
+ return `{ ${parts.join(", ")} }`;
1414
+ }
1415
+ const lines = entries.map(([k, v]) => `${innerSpaces}${formatKey(k)}: ${formatValue(v, indent + 2)},`);
1416
+ return `{
1417
+ ${lines.join("\n")}
1418
+ ${spaces}}`;
1419
+ }
1420
+ function hasDeepNesting(obj) {
1421
+ return Object.values(obj).some(
1422
+ (v) => typeof v === "object" && v !== null && !isColorOpacityObj(v) && !isGradientObj(v)
1423
+ );
1424
+ }
1425
+ function isColorOpacityObj(v) {
1426
+ return typeof v === "object" && v !== null && "color" in v && "op" in v;
1427
+ }
1428
+ function isGradientObj(v) {
1429
+ return typeof v === "object" && v !== null && "gradient" in v;
1430
+ }
1431
+ function formatKey(key) {
1432
+ if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key)) {
1433
+ return key;
1434
+ }
1435
+ return `'${key}'`;
1436
+ }
1437
+ function formatValue(value, indent) {
1438
+ if (value === true) {
1439
+ return "true";
1440
+ }
1441
+ if (value === false) {
1442
+ return "false";
1443
+ }
1444
+ if (value === null) {
1445
+ return "null";
1446
+ }
1447
+ if (typeof value === "number") {
1448
+ return String(value);
1449
+ }
1450
+ if (typeof value === "string") {
1451
+ return `'${escapeString(value)}'`;
1452
+ }
1453
+ if (Array.isArray(value)) {
1454
+ const items = value.map((v) => formatValue(v, indent));
1455
+ return `[${items.join(", ")}]`;
1456
+ }
1457
+ if (typeof value === "object" && value !== null) {
1458
+ if (isColorOpacityObj(value)) {
1459
+ const parts = [`color: '${escapeString(String(value.color))}'`];
1460
+ if (typeof value.op === "number") {
1461
+ parts.push(`op: ${value.op}`);
1462
+ } else {
1463
+ parts.push(`op: '${escapeString(String(value.op))}'`);
1464
+ }
1465
+ return `{ ${parts.join(", ")} }`;
1466
+ }
1467
+ if (isGradientObj(value)) {
1468
+ const grad = value;
1469
+ const parts = [`gradient: '${grad.gradient}'`];
1470
+ if ("dir" in grad) {
1471
+ if (typeof grad.dir === "number") {
1472
+ parts.push(`dir: ${grad.dir}`);
1473
+ } else {
1474
+ parts.push(`dir: '${escapeString(String(grad.dir))}'`);
1475
+ }
1476
+ }
1477
+ if ("in" in grad) {
1478
+ parts.push(`in: '${escapeString(String(grad.in))}'`);
1479
+ }
1480
+ return `{ ${parts.join(", ")} }`;
1481
+ }
1482
+ return objectToString(value, indent);
1483
+ }
1484
+ return String(value);
1485
+ }
1486
+ function escapeString(s) {
1487
+ return s.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1488
+ }
1489
+
1490
+ // src/migrate/reverse-map.ts
1491
+ var REVERSE_PROPERTY_MAP = {
1492
+ // Background (ambiguous — disambiguated in class-parser)
1493
+ "bg": "bg",
1494
+ "bg-clip": "bgClip",
1495
+ "bg-origin": "bgOrigin",
1496
+ // Border Radius
1497
+ "rounded": "rounded",
1498
+ "rounded-t": "roundedT",
1499
+ "rounded-r": "roundedR",
1500
+ "rounded-b": "roundedB",
1501
+ "rounded-l": "roundedL",
1502
+ "rounded-tl": "roundedTl",
1503
+ "rounded-tr": "roundedTr",
1504
+ "rounded-bl": "roundedBl",
1505
+ "rounded-br": "roundedBr",
1506
+ "rounded-s": "roundedS",
1507
+ "rounded-e": "roundedE",
1508
+ "rounded-ss": "roundedSs",
1509
+ "rounded-se": "roundedSe",
1510
+ "rounded-es": "roundedEs",
1511
+ "rounded-ee": "roundedEe",
1512
+ // Border (ambiguous — disambiguated)
1513
+ "border": "border",
1514
+ "border-t": "borderT",
1515
+ "border-r": "borderR",
1516
+ "border-b": "borderB",
1517
+ "border-l": "borderL",
1518
+ "border-x": "borderX",
1519
+ "border-y": "borderY",
1520
+ "border-s": "borderS",
1521
+ "border-e": "borderE",
1522
+ // Divide
1523
+ "divide-x": "divideX",
1524
+ "divide-y": "divideY",
1525
+ "divide": "divideColor",
1526
+ // Outline (ambiguous)
1527
+ "outline": "outline",
1528
+ "outline-offset": "outlineOffset",
1529
+ // Ring
1530
+ "ring": "ring",
1531
+ "ring-offset": "ringOffset",
1532
+ // Spacing
1533
+ "p": "p",
1534
+ "pt": "pt",
1535
+ "pr": "pr",
1536
+ "pb": "pb",
1537
+ "pl": "pl",
1538
+ "px": "px",
1539
+ "py": "py",
1540
+ "ps": "ps",
1541
+ "pe": "pe",
1542
+ "m": "m",
1543
+ "mt": "mt",
1544
+ "mr": "mr",
1545
+ "mb": "mb",
1546
+ "ml": "ml",
1547
+ "mx": "mx",
1548
+ "my": "my",
1549
+ "ms": "ms",
1550
+ "me": "me",
1551
+ // Space between
1552
+ "space-x": "spaceX",
1553
+ "space-y": "spaceY",
1554
+ // Sizing
1555
+ "w": "w",
1556
+ "min-w": "minW",
1557
+ "max-w": "maxW",
1558
+ "h": "h",
1559
+ "min-h": "minH",
1560
+ "max-h": "maxH",
1561
+ "size": "size",
1562
+ // Layout
1563
+ "aspect": "aspect",
1564
+ "columns": "columns",
1565
+ "break-after": "breakAfter",
1566
+ "break-before": "breakBefore",
1567
+ "break-inside": "breakInside",
1568
+ "box-decoration": "boxDecoration",
1569
+ "box": "box",
1570
+ "float": "float",
1571
+ "clear": "clear",
1572
+ "object": "objectFit",
1573
+ // ambiguous — objectFit vs objectPos (objectPos for position values)
1574
+ "overflow": "overflow",
1575
+ "overflow-x": "overflowX",
1576
+ "overflow-y": "overflowY",
1577
+ "overscroll": "overscroll",
1578
+ "overscroll-x": "overscrollX",
1579
+ "overscroll-y": "overscrollY",
1580
+ "z": "z",
1581
+ // Inset
1582
+ "inset": "inset",
1583
+ "inset-x": "insetX",
1584
+ "inset-y": "insetY",
1585
+ "top": "top",
1586
+ "right": "right",
1587
+ "bottom": "bottom",
1588
+ "left": "left",
1589
+ "start": "start",
1590
+ "end": "end",
1591
+ // Typography (ambiguous — text-*, font-* disambiguated)
1592
+ "text": "color",
1593
+ // default for text- prefix
1594
+ "font": "fontWeight",
1595
+ // default for font- prefix
1596
+ "decoration": "decoration",
1597
+ // ambiguous
1598
+ "underline-offset": "underlineOffset",
1599
+ "indent": "indent",
1600
+ "align": "align",
1601
+ "whitespace": "whitespace",
1602
+ "break": "break",
1603
+ // ambiguous with break-after/before/inside (handled by prefix matching)
1604
+ "hyphens": "hyphens",
1605
+ "content": "content",
1606
+ "leading": "leading",
1607
+ "tracking": "tracking",
1608
+ "list": "list",
1609
+ // ambiguous
1610
+ "list-image": "listImg",
1611
+ // Flex & Grid
1612
+ "basis": "basis",
1613
+ "flex": "flex",
1614
+ // ambiguous (boolean flex, flexDirection, flexWrap)
1615
+ "grow": "grow",
1616
+ "shrink": "shrink",
1617
+ "order": "order",
1618
+ "items": "items",
1619
+ "self": "self",
1620
+ "justify": "justify",
1621
+ "justify-items": "justifyItems",
1622
+ "justify-self": "justifySelf",
1623
+ "place-content": "placeContent",
1624
+ "place-items": "placeItems",
1625
+ "place-self": "placeSelf",
1626
+ "gap": "gap",
1627
+ "gap-x": "gapX",
1628
+ "gap-y": "gapY",
1629
+ // Grid
1630
+ "grid-cols": "gridCols",
1631
+ "grid-rows": "gridRows",
1632
+ "col": "col",
1633
+ "col-span": "colSpan",
1634
+ "col-start": "colStart",
1635
+ "col-end": "colEnd",
1636
+ "row": "row",
1637
+ "row-span": "rowSpan",
1638
+ "row-start": "rowStart",
1639
+ "row-end": "rowEnd",
1640
+ "grid-flow": "gridFlow",
1641
+ "auto-cols": "autoCols",
1642
+ "auto-rows": "autoRows",
1643
+ // Effects
1644
+ "shadow": "shadow",
1645
+ // ambiguous (shadow vs shadowColor)
1646
+ "opacity": "opacity",
1647
+ "mix-blend": "mixBlend",
1648
+ "bg-blend": "bgBlend",
1649
+ // Filters
1650
+ "blur": "blur",
1651
+ "brightness": "brightness",
1652
+ "contrast": "contrast",
1653
+ "drop-shadow": "dropShadow",
1654
+ "grayscale": "grayscale",
1655
+ "hue-rotate": "hueRotate",
1656
+ "invert": "invert",
1657
+ "saturate": "saturate",
1658
+ "sepia": "sepia",
1659
+ "backdrop-blur": "backdropBlur",
1660
+ "backdrop-brightness": "backdropBrightness",
1661
+ "backdrop-contrast": "backdropContrast",
1662
+ "backdrop-grayscale": "backdropGrayscale",
1663
+ "backdrop-hue-rotate": "backdropHueRotate",
1664
+ "backdrop-invert": "backdropInvert",
1665
+ "backdrop-opacity": "backdropOpacity",
1666
+ "backdrop-saturate": "backdropSaturate",
1667
+ "backdrop-sepia": "backdropSepia",
1668
+ // Transforms
1669
+ "scale": "scale",
1670
+ "scale-x": "scaleX",
1671
+ "scale-y": "scaleY",
1672
+ "rotate": "rotate",
1673
+ "translate-x": "translateX",
1674
+ "translate-y": "translateY",
1675
+ "skew-x": "skewX",
1676
+ "skew-y": "skewY",
1677
+ "origin": "origin",
1678
+ // Transitions & Animation
1679
+ "transition": "transition",
1680
+ "duration": "duration",
1681
+ "ease": "ease",
1682
+ "delay": "delay",
1683
+ "animate": "animate",
1684
+ // Interactivity
1685
+ "cursor": "cursor",
1686
+ "caret": "caret",
1687
+ "pointer-events": "pointerEvents",
1688
+ "resize": "resize",
1689
+ "scroll": "scroll",
1690
+ "scroll-m": "scrollM",
1691
+ "scroll-mt": "scrollMt",
1692
+ "scroll-mr": "scrollMr",
1693
+ "scroll-mb": "scrollMb",
1694
+ "scroll-ml": "scrollMl",
1695
+ "scroll-ms": "scrollMs",
1696
+ "scroll-me": "scrollMe",
1697
+ "scroll-mx": "scrollMx",
1698
+ "scroll-my": "scrollMy",
1699
+ "scroll-p": "scrollP",
1700
+ "scroll-pt": "scrollPt",
1701
+ "scroll-pr": "scrollPr",
1702
+ "scroll-pb": "scrollPb",
1703
+ "scroll-pl": "scrollPl",
1704
+ "scroll-ps": "scrollPs",
1705
+ "scroll-pe": "scrollPe",
1706
+ "scroll-px": "scrollPx",
1707
+ "scroll-py": "scrollPy",
1708
+ "snap": "snapType",
1709
+ // ambiguous
1710
+ "touch": "touch",
1711
+ "select": "select",
1712
+ "will-change": "willChange",
1713
+ "accent": "accent",
1714
+ // SVG
1715
+ "fill": "fill",
1716
+ "stroke": "stroke",
1717
+ // Tables
1718
+ "border-spacing": "borderSpacing",
1719
+ "table": "tableLayout",
1720
+ // ambiguous with boolean "table" display
1721
+ "caption": "caption",
1722
+ // Line clamp
1723
+ "line-clamp": "lineClamp",
1724
+ "wrap": "wrap",
1725
+ // Text shadow
1726
+ "text-shadow": "textShadow",
1727
+ // Gradient stops
1728
+ "from": "from",
1729
+ "via": "via",
1730
+ "to": "to",
1731
+ // Masks
1732
+ "mask": "mask",
1733
+ // Forced colors
1734
+ "forced-color-adjust": "forcedColorAdjust",
1735
+ // Perspective
1736
+ "perspective": "perspective",
1737
+ "perspective-origin": "perspectiveOrigin",
1738
+ "backface": "backface"
1739
+ };
1740
+ var REVERSE_BOOLEAN_MAP = {
1741
+ // Display
1742
+ "block": "block",
1743
+ "inline": "inline",
1744
+ "inline-block": "inlineBlock",
1745
+ "flex": "flex",
1746
+ "inline-flex": "inlineFlex",
1747
+ "grid": "grid",
1748
+ "inline-grid": "inlineGrid",
1749
+ "hidden": "hidden",
1750
+ "contents": "contents",
1751
+ "table": "table",
1752
+ "table-row": "tableRow",
1753
+ "table-cell": "tableCell",
1754
+ "flow-root": "flowRoot",
1755
+ "list-item": "listItem",
1756
+ // Position
1757
+ "static": "static",
1758
+ "fixed": "fixed",
1759
+ "absolute": "absolute",
1760
+ "relative": "relative",
1761
+ "sticky": "sticky",
1762
+ // Visibility
1763
+ "visible": "visible",
1764
+ "invisible": "invisible",
1765
+ "collapse": "collapse",
1766
+ // Typography
1767
+ "truncate": "truncate",
1768
+ "uppercase": "uppercase",
1769
+ "lowercase": "lowercase",
1770
+ "capitalize": "capitalize",
1771
+ "normal-case": "normalCase",
1772
+ "underline": "underline",
1773
+ "overline": "overline",
1774
+ "line-through": "lineThrough",
1775
+ "no-underline": "noUnderline",
1776
+ "italic": "italic",
1777
+ "not-italic": "notItalic",
1778
+ "antialiased": "antialiased",
1779
+ "subpixel-antialiased": "subpixelAntialiased",
1780
+ // Flexbox
1781
+ // flexWrap is string-based, not boolean — removed from boolean map
1782
+ // Filters (defaults)
1783
+ "blur": "blur",
1784
+ "grayscale": "grayscale",
1785
+ "invert": "invert",
1786
+ "sepia": "sepia",
1787
+ "backdrop-blur": "backdropBlur",
1788
+ "backdrop-grayscale": "backdropGrayscale",
1789
+ "backdrop-invert": "backdropInvert",
1790
+ "backdrop-sepia": "backdropSepia",
1791
+ // Misc
1792
+ "container": "container",
1793
+ "prose": "prose",
1794
+ "sr-only": "srOnly",
1795
+ "not-sr-only": "notSrOnly",
1796
+ "isolate": "isolate",
1797
+ "ordinal": "ordinal",
1798
+ "slashed-zero": "slashedZero",
1799
+ // Divide/Space reverse
1800
+ "divide-x-reverse": "divideXReverse",
1801
+ "divide-y-reverse": "divideYReverse",
1802
+ "space-x-reverse": "spaceXReverse",
1803
+ "space-y-reverse": "spaceYReverse",
1804
+ // Ring/Outline (boolean defaults)
1805
+ "ring": "ring",
1806
+ "outline": "outline",
1807
+ // Transforms
1808
+ "scale-3d": "scale3d",
1809
+ "rotate-3d": "rotate3d",
1810
+ "translate-3d": "translate3d",
1811
+ "transform-gpu": "transformGpu",
1812
+ "transform-cpu": "transformCpu",
1813
+ "transform-none": "transformNone",
1814
+ // Font numeric
1815
+ "normal-nums": "fontVariant",
1816
+ "lining-nums": "fontVariant",
1817
+ "oldstyle-nums": "fontVariant",
1818
+ "proportional-nums": "fontVariant",
1819
+ "tabular-nums": "fontVariant",
1820
+ "diagonal-fractions": "fontVariant",
1821
+ "stacked-fractions": "fontVariant",
1822
+ // Snap
1823
+ "snap-none": "snapType",
1824
+ "snap-x": "snapType",
1825
+ "snap-y": "snapType",
1826
+ "snap-both": "snapType",
1827
+ "snap-mandatory": "snapStrictness",
1828
+ "snap-proximity": "snapStrictness",
1829
+ "snap-start": "snapAlign",
1830
+ "snap-end": "snapAlign",
1831
+ "snap-center": "snapAlign",
1832
+ "snap-align-none": "snapAlign",
1833
+ "snap-normal": "snapStop",
1834
+ "snap-always": "snapStop",
1835
+ // Divide styles
1836
+ "divide-solid": "divideStyle",
1837
+ "divide-dashed": "divideStyle",
1838
+ "divide-dotted": "divideStyle",
1839
+ "divide-double": "divideStyle",
1840
+ "divide-none": "divideStyle",
1841
+ // Appearance
1842
+ "appearance-none": "appearance",
1843
+ "appearance-auto": "appearance"
1844
+ };
1845
+ var BOOLEAN_VALUE_MAP = {
1846
+ // Snap types
1847
+ "snap-none": { prop: "snapType", value: "none" },
1848
+ "snap-x": { prop: "snapType", value: "x" },
1849
+ "snap-y": { prop: "snapType", value: "y" },
1850
+ "snap-both": { prop: "snapType", value: "both" },
1851
+ "snap-mandatory": { prop: "snapStrictness", value: "mandatory" },
1852
+ "snap-proximity": { prop: "snapStrictness", value: "proximity" },
1853
+ "snap-start": { prop: "snapAlign", value: "start" },
1854
+ "snap-end": { prop: "snapAlign", value: "end" },
1855
+ "snap-center": { prop: "snapAlign", value: "center" },
1856
+ "snap-align-none": { prop: "snapAlign", value: "none" },
1857
+ "snap-normal": { prop: "snapStop", value: "normal" },
1858
+ "snap-always": { prop: "snapStop", value: "always" },
1859
+ // Divide styles
1860
+ "divide-solid": { prop: "divideStyle", value: "solid" },
1861
+ "divide-dashed": { prop: "divideStyle", value: "dashed" },
1862
+ "divide-dotted": { prop: "divideStyle", value: "dotted" },
1863
+ "divide-double": { prop: "divideStyle", value: "double" },
1864
+ "divide-none": { prop: "divideStyle", value: "none" },
1865
+ // Font variants
1866
+ "normal-nums": { prop: "fontVariant", value: "normal-nums" },
1867
+ "lining-nums": { prop: "fontVariant", value: "lining-nums" },
1868
+ "oldstyle-nums": { prop: "fontVariant", value: "oldstyle-nums" },
1869
+ "proportional-nums": { prop: "fontVariant", value: "proportional-nums" },
1870
+ "tabular-nums": { prop: "fontVariant", value: "tabular-nums" },
1871
+ "diagonal-fractions": { prop: "fontVariant", value: "diagonal-fractions" },
1872
+ "stacked-fractions": { prop: "fontVariant", value: "stacked-fractions" },
1873
+ // Appearance
1874
+ "appearance-none": { prop: "appearance", value: "none" },
1875
+ "appearance-auto": { prop: "appearance", value: "auto" }
1876
+ };
1877
+ var SORTED_PREFIXES = Object.keys(REVERSE_PROPERTY_MAP).sort((a, b) => {
1878
+ if (b.length !== a.length) {
1879
+ return b.length - a.length;
1880
+ }
1881
+ return a.localeCompare(b);
1882
+ });
1883
+ var NEGATIVE_ALLOWED = /* @__PURE__ */ new Set([
1884
+ "m",
1885
+ "mt",
1886
+ "mr",
1887
+ "mb",
1888
+ "ml",
1889
+ "mx",
1890
+ "my",
1891
+ "ms",
1892
+ "me",
1893
+ "top",
1894
+ "right",
1895
+ "bottom",
1896
+ "left",
1897
+ "inset",
1898
+ "inset-x",
1899
+ "inset-y",
1900
+ "start",
1901
+ "end",
1902
+ "z",
1903
+ "order",
1904
+ "col",
1905
+ "col-start",
1906
+ "col-end",
1907
+ "row",
1908
+ "row-start",
1909
+ "row-end",
1910
+ "rotate",
1911
+ "skew-x",
1912
+ "skew-y",
1913
+ "translate-x",
1914
+ "translate-y",
1915
+ "space-x",
1916
+ "space-y",
1917
+ "tracking",
1918
+ "indent",
1919
+ "scroll-m",
1920
+ "scroll-mx",
1921
+ "scroll-my",
1922
+ "scroll-mt",
1923
+ "scroll-mr",
1924
+ "scroll-mb",
1925
+ "scroll-ml",
1926
+ "hue-rotate",
1927
+ "backdrop-hue-rotate"
1928
+ ]);
1929
+ var FRACTION_SUPPORTED = /* @__PURE__ */ new Set([
1930
+ "w",
1931
+ "min-w",
1932
+ "max-w",
1933
+ "h",
1934
+ "min-h",
1935
+ "max-h",
1936
+ "size",
1937
+ "basis",
1938
+ "inset",
1939
+ "inset-x",
1940
+ "inset-y",
1941
+ "top",
1942
+ "right",
1943
+ "bottom",
1944
+ "left",
1945
+ "start",
1946
+ "end",
1947
+ "translate-x",
1948
+ "translate-y"
1949
+ ]);
1950
+ var SPACING_PROPS = /* @__PURE__ */ new Set([
1951
+ "p",
1952
+ "pt",
1953
+ "pr",
1954
+ "pb",
1955
+ "pl",
1956
+ "px",
1957
+ "py",
1958
+ "ps",
1959
+ "pe",
1960
+ "m",
1961
+ "mt",
1962
+ "mr",
1963
+ "mb",
1964
+ "ml",
1965
+ "mx",
1966
+ "my",
1967
+ "ms",
1968
+ "me",
1969
+ "gap",
1970
+ "gap-x",
1971
+ "gap-y",
1972
+ "w",
1973
+ "h",
1974
+ "min-w",
1975
+ "max-w",
1976
+ "min-h",
1977
+ "max-h",
1978
+ "size",
1979
+ "basis",
1980
+ "inset",
1981
+ "inset-x",
1982
+ "inset-y",
1983
+ "top",
1984
+ "right",
1985
+ "bottom",
1986
+ "left",
1987
+ "start",
1988
+ "end",
1989
+ "space-x",
1990
+ "space-y",
1991
+ "indent",
1992
+ "scroll-m",
1993
+ "scroll-mx",
1994
+ "scroll-my",
1995
+ "scroll-mt",
1996
+ "scroll-mr",
1997
+ "scroll-mb",
1998
+ "scroll-ml",
1999
+ "scroll-ms",
2000
+ "scroll-me",
2001
+ "scroll-p",
2002
+ "scroll-px",
2003
+ "scroll-py",
2004
+ "scroll-pt",
2005
+ "scroll-pr",
2006
+ "scroll-pb",
2007
+ "scroll-pl",
2008
+ "scroll-ps",
2009
+ "scroll-pe",
2010
+ "border-spacing",
2011
+ "translate-x",
2012
+ "translate-y"
2013
+ ]);
2014
+ var TEXT_SIZE_KEYWORDS = /* @__PURE__ */ new Set([
2015
+ "xs",
2016
+ "sm",
2017
+ "base",
2018
+ "lg",
2019
+ "xl",
2020
+ "2xl",
2021
+ "3xl",
2022
+ "4xl",
2023
+ "5xl",
2024
+ "6xl",
2025
+ "7xl",
2026
+ "8xl",
2027
+ "9xl"
2028
+ ]);
2029
+ var TEXT_ALIGN_KEYWORDS = /* @__PURE__ */ new Set([
2030
+ "left",
2031
+ "center",
2032
+ "right",
2033
+ "justify",
2034
+ "start",
2035
+ "end"
2036
+ ]);
2037
+ var TEXT_WRAP_KEYWORDS = /* @__PURE__ */ new Set([
2038
+ "wrap",
2039
+ "nowrap",
2040
+ "balance",
2041
+ "pretty"
2042
+ ]);
2043
+ var TEXT_OVERFLOW_KEYWORDS = /* @__PURE__ */ new Set([
2044
+ "ellipsis",
2045
+ "clip"
2046
+ ]);
2047
+ var FONT_WEIGHT_KEYWORDS = /* @__PURE__ */ new Set([
2048
+ "thin",
2049
+ "extralight",
2050
+ "light",
2051
+ "normal",
2052
+ "medium",
2053
+ "semibold",
2054
+ "bold",
2055
+ "extrabold",
2056
+ "black"
2057
+ ]);
2058
+ var FONT_FAMILY_KEYWORDS = /* @__PURE__ */ new Set([
2059
+ "sans",
2060
+ "serif",
2061
+ "mono"
2062
+ ]);
2063
+ var FONT_STRETCH_KEYWORDS = /* @__PURE__ */ new Set([
2064
+ "ultra-condensed",
2065
+ "extra-condensed",
2066
+ "condensed",
2067
+ "semi-condensed",
2068
+ "semi-expanded",
2069
+ "expanded",
2070
+ "extra-expanded",
2071
+ "ultra-expanded"
2072
+ ]);
2073
+ var BORDER_WIDTH_KEYWORDS = /* @__PURE__ */ new Set(["0", "2", "4", "8"]);
2074
+ var BORDER_STYLE_KEYWORDS = /* @__PURE__ */ new Set([
2075
+ "solid",
2076
+ "dashed",
2077
+ "dotted",
2078
+ "double",
2079
+ "none",
2080
+ "hidden"
2081
+ ]);
2082
+ var BG_POSITION_KEYWORDS = /* @__PURE__ */ new Set([
2083
+ "center",
2084
+ "top",
2085
+ "bottom",
2086
+ "left",
2087
+ "right",
2088
+ "left-top",
2089
+ "left-bottom",
2090
+ "right-top",
2091
+ "right-bottom"
2092
+ ]);
2093
+ var BG_SIZE_KEYWORDS = /* @__PURE__ */ new Set(["cover", "contain", "auto"]);
2094
+ var BG_REPEAT_KEYWORDS = /* @__PURE__ */ new Set([
2095
+ "repeat",
2096
+ "no-repeat",
2097
+ "repeat-x",
2098
+ "repeat-y",
2099
+ "round",
2100
+ "space"
2101
+ ]);
2102
+ var BG_ATTACHMENT_KEYWORDS = /* @__PURE__ */ new Set(["fixed", "local", "scroll"]);
2103
+ var OBJECT_FIT_KEYWORDS = /* @__PURE__ */ new Set(["contain", "cover", "fill", "none", "scale-down"]);
2104
+ var OBJECT_POSITION_KEYWORDS = /* @__PURE__ */ new Set([
2105
+ "center",
2106
+ "top",
2107
+ "bottom",
2108
+ "left",
2109
+ "right",
2110
+ "left-top",
2111
+ "left-bottom",
2112
+ "right-top",
2113
+ "right-bottom"
2114
+ ]);
2115
+ var SHADOW_SIZE_KEYWORDS = /* @__PURE__ */ new Set(["sm", "md", "lg", "xl", "2xl", "inner", "none"]);
2116
+ var OUTLINE_STYLE_KEYWORDS = /* @__PURE__ */ new Set(["none", "dashed", "dotted", "double"]);
2117
+ var DECORATION_STYLE_KEYWORDS = /* @__PURE__ */ new Set(["solid", "double", "dotted", "dashed", "wavy"]);
2118
+ var DECORATION_THICKNESS_KEYWORDS = /* @__PURE__ */ new Set(["auto", "from-font", "0", "1", "2", "4", "8"]);
2119
+ var TRANSITION_PROPERTY_KEYWORDS = /* @__PURE__ */ new Set([
2120
+ "none",
2121
+ "all",
2122
+ "colors",
2123
+ "opacity",
2124
+ "shadow",
2125
+ "transform"
2126
+ ]);
2127
+ var REVERSE_VARIANT_MAP = {
2128
+ "focus-within": "focusWithin",
2129
+ "focus-visible": "focusVisible",
2130
+ "first-of-type": "firstOfType",
2131
+ "last-of-type": "lastOfType",
2132
+ "only-of-type": "onlyOfType",
2133
+ "motion-reduce": "motionReduce",
2134
+ "motion-safe": "motionSafe",
2135
+ "contrast-more": "contrastMore",
2136
+ "contrast-less": "contrastLess",
2137
+ "first-line": "firstLine",
2138
+ "first-letter": "firstLetter",
2139
+ "placeholder-shown": "placeholderShown",
2140
+ "in-range": "inRange",
2141
+ "out-of-range": "outOfRange",
2142
+ "read-only": "readOnly",
2143
+ "pointer-fine": "pointerFine",
2144
+ "pointer-coarse": "pointerCoarse",
2145
+ "pointer-none": "pointerNone",
2146
+ "@max-sm": "@maxSm",
2147
+ "@max-md": "@maxMd",
2148
+ "@max-lg": "@maxLg",
2149
+ "@max-xl": "@maxXl",
2150
+ "@max-2xl": "@max2xl"
2151
+ };
2152
+ var KNOWN_SIMPLE_VARIANTS = /* @__PURE__ */ new Set([
2153
+ "sm",
2154
+ "md",
2155
+ "lg",
2156
+ "xl",
2157
+ "2xl",
2158
+ "@sm",
2159
+ "@md",
2160
+ "@lg",
2161
+ "@xl",
2162
+ "@2xl",
2163
+ "dark",
2164
+ "light",
2165
+ "print",
2166
+ "portrait",
2167
+ "landscape",
2168
+ "hover",
2169
+ "focus",
2170
+ "active",
2171
+ "visited",
2172
+ "target",
2173
+ "disabled",
2174
+ "enabled",
2175
+ "checked",
2176
+ "indeterminate",
2177
+ "default",
2178
+ "required",
2179
+ "valid",
2180
+ "invalid",
2181
+ "autofill",
2182
+ "open",
2183
+ "first",
2184
+ "last",
2185
+ "only",
2186
+ "odd",
2187
+ "even",
2188
+ "empty",
2189
+ "before",
2190
+ "after",
2191
+ "placeholder",
2192
+ "file",
2193
+ "marker",
2194
+ "selection",
2195
+ "backdrop",
2196
+ "ltr",
2197
+ "rtl"
2198
+ ]);
2199
+ var KNOWN_VARIANTS = /* @__PURE__ */ new Set([
2200
+ ...KNOWN_SIMPLE_VARIANTS,
2201
+ "focus-within",
2202
+ "focus-visible",
2203
+ "first-of-type",
2204
+ "last-of-type",
2205
+ "only-of-type",
2206
+ "first-child",
2207
+ "last-child",
2208
+ "only-child",
2209
+ "motion-reduce",
2210
+ "motion-safe",
2211
+ "contrast-more",
2212
+ "contrast-less",
2213
+ "first-line",
2214
+ "first-letter",
2215
+ "placeholder-shown",
2216
+ "in-range",
2217
+ "out-of-range",
2218
+ "read-only",
2219
+ "pointer-fine",
2220
+ "pointer-coarse",
2221
+ "pointer-none"
2222
+ ]);
2223
+
2224
+ // src/migrate/class-parser.ts
2225
+ function parseClass(cls) {
2226
+ let important = false;
2227
+ let input = cls;
2228
+ if (input.endsWith("!")) {
2229
+ important = true;
2230
+ input = input.slice(0, -1);
2231
+ }
2232
+ let negative = false;
2233
+ let negInput = input;
2234
+ if (input.startsWith("-")) {
2235
+ negative = true;
2236
+ negInput = input.slice(1);
2237
+ }
2238
+ const boolResult = tryBooleanMatch(input);
2239
+ if (boolResult) {
2240
+ return applyImportant(boolResult, important);
2241
+ }
2242
+ const gradResult = tryGradient(negInput, negative);
2243
+ if (gradResult) {
2244
+ return applyImportant(gradResult, important);
2245
+ }
2246
+ const source = negative ? negInput : input;
2247
+ for (const prefix of SORTED_PREFIXES) {
2248
+ if (source === prefix) {
2249
+ const prop = REVERSE_PROPERTY_MAP[prefix];
2250
+ if (negative && NEGATIVE_ALLOWED.has(prefix)) {
2251
+ continue;
2252
+ }
2253
+ if (REVERSE_BOOLEAN_MAP[source]) {
2254
+ return applyImportant({ prop: REVERSE_BOOLEAN_MAP[source], value: true }, important);
2255
+ }
2256
+ if (prefix === "divide-x" || prefix === "divide-y") {
2257
+ return applyImportant({ prop, value: true }, important);
2258
+ }
2259
+ if (prefix === "border") {
2260
+ return applyImportant({ prop: "border", value: true }, important);
2261
+ }
2262
+ continue;
2263
+ }
2264
+ if (source.startsWith(prefix + "-")) {
2265
+ const rawValue = source.slice(prefix.length + 1);
2266
+ if (!rawValue) {
2267
+ continue;
2268
+ }
2269
+ if (negative && !NEGATIVE_ALLOWED.has(prefix)) {
2270
+ continue;
2271
+ }
2272
+ if (SPACING_PROPS.has(prefix) && !isValidSpacingValue(rawValue)) {
2273
+ continue;
2274
+ }
2275
+ const result = disambiguateAndParse(prefix, rawValue, negative);
2276
+ if (result) {
2277
+ return applyImportant(result, important);
2278
+ }
2279
+ }
2280
+ }
2281
+ const displayResult = tryDisplay(input);
2282
+ if (displayResult) {
2283
+ return applyImportant(displayResult, important);
2284
+ }
2285
+ if (input.startsWith("[") && input.endsWith("]") && input.includes(":")) {
2286
+ const inner = input.slice(1, -1);
2287
+ if (inner.startsWith("--")) {
2288
+ const colonIdx = inner.indexOf(":");
2289
+ return applyImportant({
2290
+ prop: inner.slice(0, colonIdx),
2291
+ value: inner.slice(colonIdx + 1)
2292
+ }, important);
2293
+ }
2294
+ }
2295
+ return null;
2296
+ }
2297
+ function applyImportant(result, important) {
2298
+ if (!important) {
2299
+ return result;
2300
+ }
2301
+ if (typeof result.value === "string") {
2302
+ return { prop: result.prop, value: result.value + "!" };
2303
+ }
2304
+ if (typeof result.value === "boolean") {
2305
+ return { prop: result.prop, value: "!" };
2306
+ }
2307
+ if (typeof result.value === "number") {
2308
+ return { prop: result.prop, value: String(result.value) + "!" };
2309
+ }
2310
+ return result;
2311
+ }
2312
+ function tryBooleanMatch(cls) {
2313
+ if (BOOLEAN_VALUE_MAP[cls]) {
2314
+ const { prop, value } = BOOLEAN_VALUE_MAP[cls];
2315
+ return { prop, value };
2316
+ }
2317
+ if (REVERSE_BOOLEAN_MAP[cls]) {
2318
+ return { prop: REVERSE_BOOLEAN_MAP[cls], value: true };
2319
+ }
2320
+ return null;
2321
+ }
2322
+ function tryDisplay(cls) {
2323
+ const displayValues = /* @__PURE__ */ new Set([
2324
+ "block",
2325
+ "inline",
2326
+ "inline-block",
2327
+ "flex",
2328
+ "inline-flex",
2329
+ "grid",
2330
+ "inline-grid",
2331
+ "hidden",
2332
+ "contents",
2333
+ "table",
2334
+ "table-row",
2335
+ "table-cell",
2336
+ "flow-root",
2337
+ "list-item"
2338
+ ]);
2339
+ if (displayValues.has(cls)) {
2340
+ return REVERSE_BOOLEAN_MAP[cls] ? { prop: REVERSE_BOOLEAN_MAP[cls], value: true } : null;
2341
+ }
2342
+ return null;
2343
+ }
2344
+ function tryGradient(cls, negative) {
2345
+ let input = cls;
2346
+ let type = null;
2347
+ if (input.startsWith("bg-linear")) {
2348
+ type = "linear";
2349
+ input = input.slice("bg-linear".length);
2350
+ } else if (input.startsWith("bg-radial")) {
2351
+ type = "radial";
2352
+ input = input.slice("bg-radial".length);
2353
+ } else if (input.startsWith("bg-conic")) {
2354
+ type = "conic";
2355
+ input = input.slice("bg-conic".length);
2356
+ }
2357
+ if (!type) {
2358
+ return null;
2359
+ }
2360
+ let colorInterp;
2361
+ const slashIdx = findTopLevelSlash(input);
2362
+ if (slashIdx !== -1) {
2363
+ colorInterp = input.slice(slashIdx + 1);
2364
+ input = input.slice(0, slashIdx);
2365
+ }
2366
+ const grad = { gradient: type };
2367
+ if (input === "" || input === void 0) {
2368
+ } else if (input.startsWith("-")) {
2369
+ const dir = input.slice(1);
2370
+ if (dir.startsWith("[") && dir.endsWith("]")) {
2371
+ grad.dir = dir.slice(1, -1).replace(/_/g, " ");
2372
+ } else if (dir.startsWith("(") && dir.endsWith(")")) {
2373
+ grad.dir = dir.slice(1, -1);
2374
+ } else if (/^\d+$/.test(dir)) {
2375
+ grad.dir = negative ? -parseInt(dir, 10) : parseInt(dir, 10);
2376
+ } else {
2377
+ grad.dir = dir;
2378
+ }
2379
+ }
2380
+ if (colorInterp) {
2381
+ grad.in = colorInterp;
2382
+ }
2383
+ return { prop: "bgImg", value: grad };
2384
+ }
2385
+ function findTopLevelSlash(s) {
2386
+ let depth = 0;
2387
+ for (let i = 0; i < s.length; i++) {
2388
+ if (s[i] === "[" || s[i] === "(") {
2389
+ depth++;
2390
+ } else if (s[i] === "]" || s[i] === ")") {
2391
+ depth--;
2392
+ } else if (s[i] === "/" && depth === 0) {
2393
+ return i;
2394
+ }
2395
+ }
2396
+ return -1;
2397
+ }
2398
+ function disambiguateAndParse(prefix, rawValue, negative) {
2399
+ const slashIdx = findTopLevelSlash(rawValue);
2400
+ let opacity;
2401
+ let value = rawValue;
2402
+ if (slashIdx !== -1 && !isGradientPrefix(prefix)) {
2403
+ const isFraction = FRACTION_SUPPORTED.has(prefix) && /^\d+\/\d+$/.test(rawValue);
2404
+ if (!isFraction) {
2405
+ opacity = rawValue.slice(slashIdx + 1);
2406
+ value = rawValue.slice(0, slashIdx);
2407
+ if (opacity.startsWith("[") && opacity.endsWith("]")) {
2408
+ opacity = opacity.slice(1, -1);
2409
+ } else if (opacity.startsWith("(") && opacity.endsWith(")")) {
2410
+ opacity = opacity.slice(1, -1);
2411
+ } else {
2412
+ const opNum = Number(opacity);
2413
+ if (!isNaN(opNum)) {
2414
+ opacity = opNum;
2415
+ }
2416
+ }
2417
+ }
2418
+ }
2419
+ const result = disambiguate(prefix, value, negative);
2420
+ if (!result) {
2421
+ return null;
2422
+ }
2423
+ if (opacity !== void 0 && typeof result.value === "string") {
2424
+ return {
2425
+ prop: result.prop,
2426
+ value: { color: result.value, op: opacity }
2427
+ };
2428
+ }
2429
+ return result;
2430
+ }
2431
+ function isGradientPrefix(prefix) {
2432
+ return prefix === "from" || prefix === "via" || prefix === "to";
2433
+ }
2434
+ function disambiguate(prefix, value, negative) {
2435
+ switch (prefix) {
2436
+ case "text":
2437
+ return disambiguateText(value);
2438
+ case "font":
2439
+ return disambiguateFont(value);
2440
+ case "border":
2441
+ return disambiguateBorder(value);
2442
+ case "bg":
2443
+ return disambiguateBg(value);
2444
+ case "object":
2445
+ return disambiguateObject(value);
2446
+ case "shadow":
2447
+ return disambiguateShadow(value);
2448
+ case "outline":
2449
+ return disambiguateOutline(value);
2450
+ case "decoration":
2451
+ return disambiguateDecoration(value);
2452
+ case "transition":
2453
+ return disambiguateTransition(value);
2454
+ case "ring":
2455
+ return disambiguateRing(value, negative);
2456
+ case "ring-offset":
2457
+ return disambiguateRingOffset(value);
2458
+ case "stroke":
2459
+ return disambiguateStroke(value);
2460
+ case "list":
2461
+ return disambiguateList(value);
2462
+ case "ease":
2463
+ return { prop: "ease", value: parseValue("ease", value, negative) };
2464
+ case "snap":
2465
+ return disambiguateSnap(value);
2466
+ case "flex":
2467
+ return disambiguateFlex(value);
2468
+ case "table":
2469
+ return disambiguateTable(value);
2470
+ case "divide":
2471
+ return disambiguateDivide(value);
2472
+ case "break":
2473
+ if (value === "words") {
2474
+ return { prop: "wrap", value: "break-word" };
2475
+ }
2476
+ return { prop: "break", value };
2477
+ case "wrap":
2478
+ return { prop: "wrap", value };
2479
+ default:
2480
+ return {
2481
+ prop: REVERSE_PROPERTY_MAP[prefix] || prefix,
2482
+ value: parseValue(prefix, value, negative)
2483
+ };
2484
+ }
2485
+ }
2486
+ function disambiguateText(value) {
2487
+ if (TEXT_SIZE_KEYWORDS.has(value)) {
2488
+ return { prop: "text", value };
2489
+ }
2490
+ if (TEXT_ALIGN_KEYWORDS.has(value)) {
2491
+ return { prop: "textAlign", value };
2492
+ }
2493
+ if (TEXT_WRAP_KEYWORDS.has(value)) {
2494
+ return { prop: "textWrap", value };
2495
+ }
2496
+ if (TEXT_OVERFLOW_KEYWORDS.has(value)) {
2497
+ return { prop: "textOverflow", value };
2498
+ }
2499
+ return { prop: "color", value: parseStringValue(value) };
2500
+ }
2501
+ function disambiguateFont(value) {
2502
+ if (FONT_WEIGHT_KEYWORDS.has(value)) {
2503
+ return { prop: "fontWeight", value };
2504
+ }
2505
+ if (/^\d{3}$/.test(value)) {
2506
+ return { prop: "fontWeight", value: parseInt(value, 10) };
2507
+ }
2508
+ if (FONT_FAMILY_KEYWORDS.has(value)) {
2509
+ return { prop: "fontFamily", value };
2510
+ }
2511
+ if (value.startsWith("stretch-")) {
2512
+ const stretchVal = value.slice("stretch-".length);
2513
+ return { prop: "fontStretch", value: stretchVal };
2514
+ }
2515
+ if (FONT_STRETCH_KEYWORDS.has(value)) {
2516
+ return { prop: "fontStretch", value };
2517
+ }
2518
+ return { prop: "fontFamily", value: parseStringValue(value) };
2519
+ }
2520
+ function disambiguateBorder(value) {
2521
+ if (BORDER_WIDTH_KEYWORDS.has(value) || value === "px") {
2522
+ return { prop: "border", value: parseNumericOrString("border", value, false) };
2523
+ }
2524
+ if (BORDER_STYLE_KEYWORDS.has(value)) {
2525
+ return { prop: "borderStyle", value };
2526
+ }
2527
+ return { prop: "borderColor", value: parseStringValue(value) };
2528
+ }
2529
+ function disambiguateBg(value) {
2530
+ if (BG_POSITION_KEYWORDS.has(value)) {
2531
+ return { prop: "bgPos", value };
2532
+ }
2533
+ if (BG_SIZE_KEYWORDS.has(value)) {
2534
+ return { prop: "bgSize", value };
2535
+ }
2536
+ if (BG_REPEAT_KEYWORDS.has(value)) {
2537
+ return { prop: "bgRepeat", value };
2538
+ }
2539
+ if (BG_ATTACHMENT_KEYWORDS.has(value)) {
2540
+ return { prop: "bgAttach", value };
2541
+ }
2542
+ if (value === "none") {
2543
+ return { prop: "bgImg", value: "none" };
2544
+ }
2545
+ return { prop: "bg", value: parseStringValue(value) };
2546
+ }
2547
+ function disambiguateObject(value) {
2548
+ if (OBJECT_FIT_KEYWORDS.has(value)) {
2549
+ return { prop: "objectFit", value };
2550
+ }
2551
+ if (OBJECT_POSITION_KEYWORDS.has(value)) {
2552
+ return { prop: "objectPos", value };
2553
+ }
2554
+ return { prop: "objectPos", value: parseStringValue(value) };
2555
+ }
2556
+ function disambiguateShadow(value) {
2557
+ if (SHADOW_SIZE_KEYWORDS.has(value)) {
2558
+ return { prop: "shadow", value };
2559
+ }
2560
+ return { prop: "shadowColor", value: parseStringValue(value) };
2561
+ }
2562
+ function disambiguateOutline(value) {
2563
+ if (OUTLINE_STYLE_KEYWORDS.has(value)) {
2564
+ return { prop: "outlineStyle", value };
2565
+ }
2566
+ const num = Number(value);
2567
+ if (!isNaN(num) && Number.isInteger(num)) {
2568
+ return { prop: "outline", value: num };
2569
+ }
2570
+ return { prop: "outlineColor", value: parseStringValue(value) };
2571
+ }
2572
+ function disambiguateDecoration(value) {
2573
+ if (DECORATION_STYLE_KEYWORDS.has(value)) {
2574
+ return { prop: "decorationStyle", value };
2575
+ }
2576
+ if (DECORATION_THICKNESS_KEYWORDS.has(value)) {
2577
+ const num = Number(value);
2578
+ if (!isNaN(num)) {
2579
+ return { prop: "decorationThickness", value };
2580
+ }
2581
+ return { prop: "decorationThickness", value };
2582
+ }
2583
+ return { prop: "decorationColor", value: parseStringValue(value) };
2584
+ }
2585
+ function disambiguateRing(value, negative) {
2586
+ const num = Number(value);
2587
+ if (!isNaN(num) && Number.isInteger(num)) {
2588
+ return { prop: "ring", value: negative ? -num : num };
2589
+ }
2590
+ if (value === "inset") {
2591
+ return { prop: "ring", value: "inset" };
2592
+ }
2593
+ return { prop: "ringColor", value: parseStringValue(value) };
2594
+ }
2595
+ function disambiguateRingOffset(value) {
2596
+ const num = Number(value);
2597
+ if (!isNaN(num) && Number.isInteger(num)) {
2598
+ return { prop: "ringOffset", value: num };
2599
+ }
2600
+ return { prop: "ringOffsetColor", value: parseStringValue(value) };
2601
+ }
2602
+ function disambiguateStroke(value) {
2603
+ const num = Number(value);
2604
+ if (!isNaN(num) && Number.isInteger(num)) {
2605
+ return { prop: "strokeWidth", value: num };
2606
+ }
2607
+ return { prop: "stroke", value: parseStringValue(value) };
2608
+ }
2609
+ function disambiguateTransition(value) {
2610
+ if (TRANSITION_PROPERTY_KEYWORDS.has(value)) {
2611
+ return { prop: "transition", value };
2612
+ }
2613
+ return { prop: "transition", value: parseStringValue(value) };
2614
+ }
2615
+ function disambiguateList(value) {
2616
+ if (value === "inside" || value === "outside") {
2617
+ return { prop: "listPos", value };
2618
+ }
2619
+ return { prop: "list", value: parseStringValue(value) };
2620
+ }
2621
+ function disambiguateSnap(value) {
2622
+ return null;
2623
+ }
2624
+ function disambiguateFlex(value) {
2625
+ const dirValues = /* @__PURE__ */ new Set(["row", "col", "row-reverse", "col-reverse"]);
2626
+ if (dirValues.has(value)) {
2627
+ return { prop: "flexDir", value };
2628
+ }
2629
+ const wrapValues = /* @__PURE__ */ new Set(["wrap", "nowrap", "wrap-reverse"]);
2630
+ if (wrapValues.has(value)) {
2631
+ return { prop: "flexWrap", value };
2632
+ }
2633
+ if (value === "1" || value === "auto" || value === "initial" || value === "none") {
2634
+ return { prop: "flex", value: parseStringValue(value) };
2635
+ }
2636
+ return { prop: "flex", value: parseStringValue(value) };
2637
+ }
2638
+ function disambiguateTable(value) {
2639
+ if (value === "auto" || value === "fixed") {
2640
+ return { prop: "tableLayout", value };
2641
+ }
2642
+ return null;
2643
+ }
2644
+ function disambiguateDivide(value) {
2645
+ return { prop: "divideColor", value: parseStringValue(value) };
2646
+ }
2647
+ function isValidSpacingValue(value) {
2648
+ if (value.startsWith("[") && value.endsWith("]")) {
2649
+ return true;
2650
+ }
2651
+ if (value.startsWith("(") && value.endsWith(")")) {
2652
+ return true;
2653
+ }
2654
+ if (!isNaN(Number(value))) {
2655
+ return true;
2656
+ }
2657
+ if (/^\d+\/\d+$/.test(value)) {
2658
+ return true;
2659
+ }
2660
+ if ([
2661
+ "auto",
2662
+ "full",
2663
+ "screen",
2664
+ "px",
2665
+ "min",
2666
+ "max",
2667
+ "fit",
2668
+ "none",
2669
+ "dvh",
2670
+ "dvw",
2671
+ "svh",
2672
+ "svw",
2673
+ "lvh",
2674
+ "lvw",
2675
+ // Max-width size keywords
2676
+ "xs",
2677
+ "sm",
2678
+ "md",
2679
+ "lg",
2680
+ "xl",
2681
+ "2xl",
2682
+ "3xl",
2683
+ "4xl",
2684
+ "5xl",
2685
+ "6xl",
2686
+ "7xl",
2687
+ "prose",
2688
+ "screen-sm",
2689
+ "screen-md",
2690
+ "screen-lg",
2691
+ "screen-xl",
2692
+ "screen-2xl",
2693
+ // Size keywords used in min-h, max-h
2694
+ "content"
2695
+ ].includes(value)) {
2696
+ return true;
2697
+ }
2698
+ if (value.includes("/")) {
2699
+ return true;
2700
+ }
2701
+ return false;
2702
+ }
2703
+ function parseValue(prefix, value, negative) {
2704
+ if (value.startsWith("[") && value.endsWith("]")) {
2705
+ const inner = value.slice(1, -1).replace(/_/g, " ");
2706
+ if (negative) {
2707
+ return "-" + inner;
2708
+ }
2709
+ return inner;
2710
+ }
2711
+ if (value.startsWith("(") && value.endsWith(")")) {
2712
+ const inner = value.slice(1, -1);
2713
+ if (negative) {
2714
+ return "-" + inner;
2715
+ }
2716
+ return inner;
2717
+ }
2718
+ if (FRACTION_SUPPORTED.has(prefix) && /^\d+\/\d+$/.test(value)) {
2719
+ return value;
2720
+ }
2721
+ if (value === "px") {
2722
+ return "px";
2723
+ }
2724
+ if (value === "auto") {
2725
+ return "auto";
2726
+ }
2727
+ if (value === "full") {
2728
+ return "full";
2729
+ }
2730
+ if (value === "screen") {
2731
+ return "screen";
2732
+ }
2733
+ const num = Number(value);
2734
+ if (!isNaN(num)) {
2735
+ if (negative) {
2736
+ return -num;
2737
+ }
2738
+ return num;
2739
+ }
2740
+ if (negative) {
2741
+ return "-" + value;
2742
+ }
2743
+ return value;
2744
+ }
2745
+ function parseNumericOrString(prefix, value, negative) {
2746
+ if (value === "px") {
2747
+ return "px";
2748
+ }
2749
+ const num = Number(value);
2750
+ if (!isNaN(num)) {
2751
+ return negative ? -num : num;
2752
+ }
2753
+ return value;
2754
+ }
2755
+ function parseStringValue(value) {
2756
+ if (value.startsWith("[") && value.endsWith("]")) {
2757
+ return value.slice(1, -1).replace(/_/g, " ");
2758
+ }
2759
+ if (value.startsWith("(") && value.endsWith(")")) {
2760
+ return value.slice(1, -1);
2761
+ }
2762
+ return value;
2763
+ }
2764
+
2765
+ // src/migrate/variant-parser.ts
2766
+ function tokenize(className) {
2767
+ return className.trim().split(/\s+/).filter(Boolean);
2768
+ }
2769
+ function extractVariants(token) {
2770
+ const parts = [];
2771
+ let current = "";
2772
+ let depth = 0;
2773
+ for (let i = 0; i < token.length; i++) {
2774
+ const ch = token[i];
2775
+ if (ch === "[" || ch === "(") {
2776
+ depth++;
2777
+ current += ch;
2778
+ } else if (ch === "]" || ch === ")") {
2779
+ depth--;
2780
+ current += ch;
2781
+ } else if (ch === ":" && depth === 0) {
2782
+ parts.push(current);
2783
+ current = "";
2784
+ } else {
2785
+ current += ch;
2786
+ }
2787
+ }
2788
+ if (parts.length === 0) {
2789
+ return { variantParts: [], baseClass: current };
2790
+ }
2791
+ return { variantParts: parts, baseClass: current };
2792
+ }
2793
+ function mapVariant(variant) {
2794
+ if (variant.startsWith("@")) {
2795
+ if (variant === "@container") {
2796
+ return ["@container"];
2797
+ }
2798
+ const slashIdx = variant.indexOf("/");
2799
+ if (slashIdx !== -1) {
2800
+ const queryPart = variant.slice(0, slashIdx);
2801
+ const namePart = variant.slice(slashIdx + 1);
2802
+ return [normalizeVariantKey(queryPart), namePart];
2803
+ }
2804
+ const match = variant.match(/^(@min|@max)-\[(.+)\]$/);
2805
+ if (match) {
2806
+ return [match[1], match[2]];
2807
+ }
2808
+ return [normalizeVariantKey(variant)];
2809
+ }
2810
+ if (variant.startsWith("group-") || variant.startsWith("peer-")) {
2811
+ return parseGroupPeerVariant(variant);
2812
+ }
2813
+ if (variant.startsWith("has-")) {
2814
+ const rest = variant.slice(4);
2815
+ if (rest.startsWith("[") && rest.endsWith("]")) {
2816
+ let selector = rest.slice(1, -1);
2817
+ if (selector.startsWith(":")) {
2818
+ selector = selector.slice(1);
2819
+ }
2820
+ return ["has", selector];
2821
+ }
2822
+ return ["has", rest];
2823
+ }
2824
+ if (variant.startsWith("not-")) {
2825
+ const rest = variant.slice(4);
2826
+ if (rest.startsWith("supports-[") && rest.endsWith("]")) {
2827
+ const cond = rest.slice(10, -1);
2828
+ return ["not", "supports", cond];
2829
+ }
2830
+ return ["not", normalizeVariantKey(rest)];
2831
+ }
2832
+ if (variant.startsWith("data-")) {
2833
+ const rest = variant.slice(5);
2834
+ if (rest.startsWith("[") && rest.endsWith("]")) {
2835
+ return ["data", rest.slice(1, -1)];
2836
+ }
2837
+ return ["data", rest];
2838
+ }
2839
+ if (variant.startsWith("aria-")) {
2840
+ const rest = variant.slice(5);
2841
+ if (rest.startsWith("[") && rest.endsWith("]")) {
2842
+ return ["aria", rest.slice(1, -1)];
2843
+ }
2844
+ return ["aria", rest];
2845
+ }
2846
+ if (variant.startsWith("supports-")) {
2847
+ const rest = variant.slice(9);
2848
+ if (rest.startsWith("[") && rest.endsWith("]")) {
2849
+ return ["supports", rest.slice(1, -1)];
2850
+ }
2851
+ return ["supports", rest];
2852
+ }
2853
+ if (variant.startsWith("min-") || variant.startsWith("max-")) {
2854
+ const prefix = variant.startsWith("min-") ? "min" : "max";
2855
+ const rest = variant.slice(4);
2856
+ if (rest.startsWith("[") && rest.endsWith("]")) {
2857
+ return [prefix, rest.slice(1, -1)];
2858
+ }
2859
+ return [prefix, rest];
2860
+ }
2861
+ if (variant.startsWith("[") && variant.endsWith("]")) {
2862
+ return [variant];
2863
+ }
2864
+ return [normalizeVariantKey(variant)];
2865
+ }
2866
+ function parseGroupPeerVariant(variant) {
2867
+ const isGroup = variant.startsWith("group-");
2868
+ const type = isGroup ? "group" : "peer";
2869
+ let rest = variant.slice(type.length + 1);
2870
+ let name;
2871
+ const slashIdx = findTopLevelSlash2(rest);
2872
+ if (slashIdx !== -1) {
2873
+ name = rest.slice(slashIdx + 1);
2874
+ rest = rest.slice(0, slashIdx);
2875
+ }
2876
+ const keys = [type];
2877
+ if (name) {
2878
+ keys.push(name);
2879
+ }
2880
+ if (rest.startsWith("[") && rest.endsWith("]")) {
2881
+ keys.push(rest.slice(1, -1));
2882
+ } else if (rest.startsWith("has-")) {
2883
+ const hasRest = rest.slice(4);
2884
+ if (hasRest.startsWith("[") && hasRest.endsWith("]")) {
2885
+ keys.push("has");
2886
+ keys.push(hasRest.slice(1, -1));
2887
+ } else {
2888
+ keys.push("has");
2889
+ keys.push(hasRest);
2890
+ }
2891
+ } else {
2892
+ keys.push(normalizeVariantKey(rest));
2893
+ }
2894
+ return keys;
2895
+ }
2896
+ function findTopLevelSlash2(s) {
2897
+ let depth = 0;
2898
+ for (let i = 0; i < s.length; i++) {
2899
+ if (s[i] === "[" || s[i] === "(") {
2900
+ depth++;
2901
+ } else if (s[i] === "]" || s[i] === ")") {
2902
+ depth--;
2903
+ } else if (s[i] === "/" && depth === 0) {
2904
+ return i;
2905
+ }
2906
+ }
2907
+ return -1;
2908
+ }
2909
+ function normalizeVariantKey(variant) {
2910
+ if (REVERSE_VARIANT_MAP[variant]) {
2911
+ return REVERSE_VARIANT_MAP[variant];
2912
+ }
2913
+ if (variant.startsWith("@")) {
2914
+ return variant;
2915
+ }
2916
+ return variant;
2917
+ }
2918
+ function classNameToSzObject(className) {
2919
+ const tokens = tokenize(className);
2920
+ const szObject = {};
2921
+ const unrecognized = [];
2922
+ for (const token of tokens) {
2923
+ const { variantParts, baseClass } = extractVariants(token);
2924
+ const parsed = parseClass(baseClass);
2925
+ if (!parsed) {
2926
+ unrecognized.push(token);
2927
+ continue;
2928
+ }
2929
+ const variantKeys = variantParts.map((v) => mapVariant(v));
2930
+ const keyPath = [];
2931
+ for (const vk of variantKeys) {
2932
+ keyPath.push(...vk);
2933
+ }
2934
+ setNestedValue(szObject, keyPath, parsed.prop, parsed.value);
2935
+ }
2936
+ return { szObject, unrecognized };
2937
+ }
2938
+ function setNestedValue(obj, keyPath, prop, value) {
2939
+ let current = obj;
2940
+ for (const key of keyPath) {
2941
+ if (!(key in current) || typeof current[key] !== "object" || current[key] === null) {
2942
+ current[key] = {};
2943
+ }
2944
+ current = current[key];
2945
+ }
2946
+ current[prop] = value;
2947
+ }
2948
+
2949
+ // src/migrate/ast-transformer.ts
2950
+ function transformSourceSimple(source, filePath) {
2951
+ const warnings = [];
2952
+ let classNamesTransformed = 0;
2953
+ let classNamesSkipped = 0;
2954
+ const classesUnrecognized = [];
2955
+ let changed = false;
2956
+ const output = source.replace(/className="([^"]*)"/g, (match, classNameStr) => {
2957
+ return processClassNameMatch(match, classNameStr, '"');
2958
+ });
2959
+ const output2 = output.replace(/className='([^']*)'/g, (match, classNameStr) => {
2960
+ return processClassNameMatch(match, classNameStr, "'");
2961
+ });
2962
+ function processClassNameMatch(match, classNameStr, quote) {
2963
+ const trimmed = classNameStr.trim();
2964
+ if (!trimmed) {
2965
+ classNamesSkipped++;
2966
+ return match;
2967
+ }
2968
+ const { szObject, unrecognized } = classNameToSzObject(trimmed);
2969
+ if (Object.keys(szObject).length === 0) {
2970
+ classNamesSkipped++;
2971
+ classesUnrecognized.push(...unrecognized);
2972
+ return match;
2973
+ }
2974
+ const szExpr = generateSzExpression(szObject);
2975
+ changed = true;
2976
+ classNamesTransformed++;
2977
+ if (unrecognized.length > 0) {
2978
+ classesUnrecognized.push(...unrecognized);
2979
+ return `className=${quote}${unrecognized.join(" ")}${quote} sz=${szExpr}`;
2980
+ }
2981
+ return `sz=${szExpr}`;
2982
+ }
2983
+ return {
2984
+ code: output2,
2985
+ changed,
2986
+ warnings,
2987
+ stats: { classNamesTransformed, classNamesSkipped, classesUnrecognized }
2988
+ };
2989
+ }
2990
+
2991
+ // src/commands/migrate.ts
2992
+ async function migrate(options = {}) {
2993
+ const cwd = options.cwd || process.cwd();
2994
+ const dryRun = options.dryRun || false;
2995
+ const ignorePatterns = options.ignore || [];
2996
+ printHeader("csszyx Migration Tool");
2997
+ if (dryRun) {
2998
+ printInfo("Dry run mode \u2014 no files will be modified");
2999
+ }
3000
+ const patterns = options.pattern ? [options.pattern] : ["**/*.{jsx,tsx}"];
3001
+ const ignore = [
3002
+ "**/node_modules/**",
3003
+ "**/dist/**",
3004
+ "**/build/**",
3005
+ "**/.next/**",
3006
+ "**/.nuxt/**",
3007
+ ...ignorePatterns
3008
+ ];
3009
+ const s = spinner.start("Scanning for files...");
3010
+ const files = await fg(patterns, { cwd, ignore, absolute: true });
3011
+ s.succeed(`Found ${files.length} files`);
3012
+ if (files.length === 0) {
3013
+ printWarn("No JSX/TSX files found");
3014
+ return;
3015
+ }
3016
+ let totalTransformed = 0;
3017
+ let totalSkipped = 0;
3018
+ let totalFiles = 0;
3019
+ const allUnrecognized = [];
3020
+ const allWarnings = [];
3021
+ const s2 = spinner.start("Migrating...");
3022
+ for (const filePath of files) {
3023
+ const source = fs5.readFileSync(filePath, "utf-8");
3024
+ if (!source.includes("className=")) {
3025
+ continue;
3026
+ }
3027
+ const result = transformSourceSimple(source, filePath);
3028
+ if (result.changed) {
3029
+ totalFiles++;
3030
+ totalTransformed += result.stats.classNamesTransformed;
3031
+ totalSkipped += result.stats.classNamesSkipped;
3032
+ allUnrecognized.push(...result.stats.classesUnrecognized);
3033
+ allWarnings.push(...result.warnings);
3034
+ if (!dryRun) {
3035
+ fs5.writeFileSync(filePath, result.code, "utf-8");
3036
+ }
3037
+ const rel = path5.relative(cwd, filePath);
3038
+ if (dryRun) {
3039
+ printInfo(` ${rel}: ${result.stats.classNamesTransformed} className(s) \u2192 sz`);
3040
+ }
3041
+ }
3042
+ }
3043
+ s2.succeed("Migration complete");
3044
+ console.info();
3045
+ printSuccess(`Files modified: ${totalFiles}`);
3046
+ printSuccess(`classNames converted: ${totalTransformed}`);
3047
+ if (totalSkipped > 0) {
3048
+ printWarn(`classNames skipped (dynamic): ${totalSkipped}`);
3049
+ }
3050
+ if (allUnrecognized.length > 0) {
3051
+ const unique = [...new Set(allUnrecognized)];
3052
+ printWarn(`Unrecognized classes (${unique.length}): ${unique.slice(0, 10).join(", ")}${unique.length > 10 ? "..." : ""}`);
3053
+ }
3054
+ if (allWarnings.length > 0) {
3055
+ console.info();
3056
+ for (const w of allWarnings.slice(0, 5)) {
3057
+ printWarn(w);
3058
+ }
3059
+ if (allWarnings.length > 5) {
3060
+ printWarn(`... and ${allWarnings.length - 5} more warnings`);
3061
+ }
3062
+ }
3063
+ }
3064
+
3065
+ // src/index.ts
3066
+ var cli = cac("csszyx");
3067
+ var VERSION = "0.0.0";
3068
+ cli.command("init", "Setup csszyx in your project").option("--framework <name>", "Specify framework").option("--yes", "Skip prompts (use defaults)").option("--cwd <dir>", "Current working directory").action(async (options) => {
3069
+ await init({
3070
+ framework: options.framework,
3071
+ yes: options.yes,
3072
+ cwd: options.cwd
3073
+ });
3074
+ });
3075
+ cli.command("doctor", "Diagnose mangling issues").option("--fix", "Auto-fix common issues").option("--verbose", "Show detailed output").option("--cwd <dir>", "Current working directory").action(async (options) => {
3076
+ await doctor({
3077
+ fix: options.fix,
3078
+ verbose: options.verbose,
3079
+ cwd: options.cwd
3080
+ });
3081
+ });
3082
+ cli.command("audit", "Analyze mangling performance").option("--json", "Output as JSON").option("--watch", "Live updates").option("--compare <dir>", "Compare with previous build").option("--cwd <dir>", "Current working directory").action(async (options) => {
3083
+ await audit({
3084
+ json: options.json,
3085
+ watch: options.watch,
3086
+ compare: options.compare,
3087
+ cwd: options.cwd
3088
+ });
3089
+ });
3090
+ cli.command(
3091
+ "generate-types",
3092
+ "Generate TypeScript declarations from tailwind.config.js"
3093
+ ).option("-c, --config <path>", "Path to tailwind.config.js").option("-o, --output <path>", "Output file path (default: ./csszyx.d.ts)").option("--cwd <dir>", "Current working directory").option("--silent", "Silent mode (no output)").action(async (options) => {
3094
+ await generateTypes({
3095
+ config: options.config,
3096
+ output: options.output,
3097
+ cwd: options.cwd,
3098
+ silent: options.silent
3099
+ });
3100
+ });
3101
+ cli.command("migrate [dir]", "Convert Tailwind className to sz prop").option("--dry-run", "Show changes without modifying files").option("--ignore <patterns>", "Glob patterns to ignore (comma-separated)").option("--pattern <glob>", "Custom glob pattern for file discovery").option("--cwd <dir>", "Current working directory").action(async (dir, options) => {
3102
+ await migrate({
3103
+ dryRun: options.dryRun,
3104
+ ignore: options.ignore ? options.ignore.split(",") : void 0,
3105
+ pattern: options.pattern,
3106
+ cwd: dir || options.cwd
3107
+ });
3108
+ });
3109
+ cli.command("").action(() => {
3110
+ cli.outputHelp();
3111
+ });
3112
+ cli.help();
3113
+ cli.version(VERSION);
3114
+ cli.parse();
3115
+ export {
3116
+ extractScreenKeys,
3117
+ extractSpacingKeys,
3118
+ findConfigFile,
3119
+ flattenColors,
3120
+ generateAndWriteTypes,
3121
+ generateTypeDeclarations,
3122
+ generateTypes,
3123
+ scanTailwindConfig,
3124
+ writeDeclarationFile
3125
+ };