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