@nifrajs/cli 2.14.1 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/README.md +10 -0
  2. package/dist/assure-hydration.d.ts.map +1 -1
  3. package/dist/assure-hydration.js +6 -1
  4. package/dist/assure-hydration.js.map +1 -1
  5. package/dist/assure.d.ts.map +1 -1
  6. package/dist/assure.js +3 -2
  7. package/dist/assure.js.map +1 -1
  8. package/dist/check-diagnostics.d.ts +165 -0
  9. package/dist/check-diagnostics.d.ts.map +1 -0
  10. package/dist/check-diagnostics.js +1009 -0
  11. package/dist/check-diagnostics.js.map +1 -0
  12. package/dist/check-scan.d.ts +245 -0
  13. package/dist/check-scan.d.ts.map +1 -0
  14. package/dist/check-scan.js +1599 -0
  15. package/dist/check-scan.js.map +1 -0
  16. package/dist/check.d.ts +4 -324
  17. package/dist/check.d.ts.map +1 -1
  18. package/dist/check.js +8 -2346
  19. package/dist/check.js.map +1 -1
  20. package/dist/cli.d.ts.map +1 -1
  21. package/dist/cli.js +285 -10
  22. package/dist/cli.js.map +1 -1
  23. package/dist/command-catalog.d.ts +27 -1
  24. package/dist/command-catalog.d.ts.map +1 -1
  25. package/dist/command-catalog.js +142 -2
  26. package/dist/command-catalog.js.map +1 -1
  27. package/dist/doctor.d.ts +42 -0
  28. package/dist/doctor.d.ts.map +1 -1
  29. package/dist/doctor.js +64 -7
  30. package/dist/doctor.js.map +1 -1
  31. package/dist/env-file.d.ts +17 -0
  32. package/dist/env-file.d.ts.map +1 -0
  33. package/dist/env-file.js +113 -0
  34. package/dist/env-file.js.map +1 -0
  35. package/dist/fix-recipes.d.ts.map +1 -1
  36. package/dist/fix-recipes.js +91 -15
  37. package/dist/fix-recipes.js.map +1 -1
  38. package/dist/frontend-guidance.d.ts +57 -0
  39. package/dist/frontend-guidance.d.ts.map +1 -0
  40. package/dist/frontend-guidance.js +195 -0
  41. package/dist/frontend-guidance.js.map +1 -0
  42. package/dist/internal/reserved-segment-codemod.d.ts +36 -0
  43. package/dist/internal/reserved-segment-codemod.d.ts.map +1 -0
  44. package/dist/internal/reserved-segment-codemod.js +134 -0
  45. package/dist/internal/reserved-segment-codemod.js.map +1 -0
  46. package/dist/internal/typescript-import.d.ts +1 -1
  47. package/dist/internal/typescript-import.d.ts.map +1 -1
  48. package/dist/internal/typescript-import.js +62 -11
  49. package/dist/internal/typescript-import.js.map +1 -1
  50. package/dist/introspect.d.ts +26 -1
  51. package/dist/introspect.d.ts.map +1 -1
  52. package/dist/introspect.js +74 -24
  53. package/dist/introspect.js.map +1 -1
  54. package/dist/levels-tool.d.ts.map +1 -1
  55. package/dist/levels-tool.js +6 -0
  56. package/dist/levels-tool.js.map +1 -1
  57. package/dist/load.d.ts.map +1 -1
  58. package/dist/load.js +4 -1
  59. package/dist/load.js.map +1 -1
  60. package/dist/mcp-context.d.ts +48 -0
  61. package/dist/mcp-context.d.ts.map +1 -0
  62. package/dist/mcp-context.js +215 -0
  63. package/dist/mcp-context.js.map +1 -0
  64. package/dist/mcp-docs-tools.d.ts.map +1 -1
  65. package/dist/mcp-docs-tools.js +31 -0
  66. package/dist/mcp-docs-tools.js.map +1 -1
  67. package/dist/mcp-exec.d.ts +74 -0
  68. package/dist/mcp-exec.d.ts.map +1 -0
  69. package/dist/mcp-exec.js +844 -0
  70. package/dist/mcp-exec.js.map +1 -0
  71. package/dist/mcp-http.js +1 -1
  72. package/dist/mcp-http.js.map +1 -1
  73. package/dist/mcp-io.d.ts +26 -0
  74. package/dist/mcp-io.d.ts.map +1 -0
  75. package/dist/mcp-io.js +100 -0
  76. package/dist/mcp-io.js.map +1 -0
  77. package/dist/mcp-reflect.d.ts +16 -0
  78. package/dist/mcp-reflect.d.ts.map +1 -0
  79. package/dist/mcp-reflect.js +101 -0
  80. package/dist/mcp-reflect.js.map +1 -0
  81. package/dist/mcp-root.d.ts +7 -0
  82. package/dist/mcp-root.d.ts.map +1 -1
  83. package/dist/mcp-root.js +51 -3
  84. package/dist/mcp-root.js.map +1 -1
  85. package/dist/mcp.d.ts +10 -84
  86. package/dist/mcp.d.ts.map +1 -1
  87. package/dist/mcp.js +13 -1170
  88. package/dist/mcp.js.map +1 -1
  89. package/dist/openapi-tool.d.ts +5 -10
  90. package/dist/openapi-tool.d.ts.map +1 -1
  91. package/dist/openapi-tool.js +21 -2
  92. package/dist/openapi-tool.js.map +1 -1
  93. package/dist/openapi-types.d.ts +21 -0
  94. package/dist/openapi-types.d.ts.map +1 -0
  95. package/dist/openapi-types.js +214 -0
  96. package/dist/openapi-types.js.map +1 -0
  97. package/dist/port.d.ts.map +1 -1
  98. package/dist/port.js +2 -1
  99. package/dist/port.js.map +1 -1
  100. package/dist/project-facts.d.ts +2 -1
  101. package/dist/project-facts.d.ts.map +1 -1
  102. package/dist/project-facts.js.map +1 -1
  103. package/dist/recipes/3.0.0.d.ts +10 -0
  104. package/dist/recipes/3.0.0.d.ts.map +1 -0
  105. package/dist/recipes/3.0.0.js +23 -0
  106. package/dist/recipes/3.0.0.js.map +1 -0
  107. package/dist/recipes/index.d.ts.map +1 -1
  108. package/dist/recipes/index.js +2 -0
  109. package/dist/recipes/index.js.map +1 -1
  110. package/dist/release-verification.d.ts +4 -1
  111. package/dist/release-verification.d.ts.map +1 -1
  112. package/dist/release-verification.js +6 -123
  113. package/dist/release-verification.js.map +1 -1
  114. package/dist/rules/codes.d.ts +4 -0
  115. package/dist/rules/codes.d.ts.map +1 -1
  116. package/dist/rules/codes.js +4 -0
  117. package/dist/rules/codes.js.map +1 -1
  118. package/dist/rules/islands.d.ts +4 -0
  119. package/dist/rules/islands.d.ts.map +1 -0
  120. package/dist/rules/islands.js +155 -0
  121. package/dist/rules/islands.js.map +1 -0
  122. package/dist/rules/nano.d.ts +6 -0
  123. package/dist/rules/nano.d.ts.map +1 -0
  124. package/dist/rules/nano.js +264 -0
  125. package/dist/rules/nano.js.map +1 -0
  126. package/dist/rules/routes.d.ts.map +1 -1
  127. package/dist/rules/routes.js +17 -30
  128. package/dist/rules/routes.js.map +1 -1
  129. package/dist/rules/security.d.ts.map +1 -1
  130. package/dist/rules/security.js +38 -4
  131. package/dist/rules/security.js.map +1 -1
  132. package/dist/scaffold.d.ts +12 -6
  133. package/dist/scaffold.d.ts.map +1 -1
  134. package/dist/scaffold.js +149 -10
  135. package/dist/scaffold.js.map +1 -1
  136. package/dist/search-terms.d.ts.map +1 -1
  137. package/dist/search-terms.js +5 -3
  138. package/dist/search-terms.js.map +1 -1
  139. package/dist/stylex-migrate.d.ts +38 -0
  140. package/dist/stylex-migrate.d.ts.map +1 -0
  141. package/dist/stylex-migrate.js +1052 -0
  142. package/dist/stylex-migrate.js.map +1 -0
  143. package/dist/sync-manifest.d.ts.map +1 -1
  144. package/dist/sync-manifest.js +2 -1
  145. package/dist/sync-manifest.js.map +1 -1
  146. package/dist/verification-plan.d.ts +24 -0
  147. package/dist/verification-plan.d.ts.map +1 -0
  148. package/dist/verification-plan.js +116 -0
  149. package/dist/verification-plan.js.map +1 -0
  150. package/dist/work-graph.d.ts.map +1 -1
  151. package/dist/work-graph.js +6 -3
  152. package/dist/work-graph.js.map +1 -1
  153. package/dist/workspace-link.d.ts +37 -0
  154. package/dist/workspace-link.d.ts.map +1 -0
  155. package/dist/workspace-link.js +72 -0
  156. package/dist/workspace-link.js.map +1 -0
  157. package/docs/examples.json +37 -1
  158. package/docs/llms-full.txt +1598 -44
  159. package/docs/types.json +5157 -172
  160. package/package.json +9 -9
  161. package/src/assure-hydration.ts +6 -1
  162. package/src/assure.ts +4 -2
  163. package/src/check-diagnostics.ts +1219 -0
  164. package/src/check-scan.ts +1825 -0
  165. package/src/check.ts +47 -2731
  166. package/src/cli.ts +291 -10
  167. package/src/command-catalog.ts +177 -2
  168. package/src/doctor.ts +99 -8
  169. package/src/env-file.ts +121 -0
  170. package/src/fix-recipes.ts +101 -15
  171. package/src/frontend-guidance.ts +259 -0
  172. package/src/internal/reserved-segment-codemod.ts +150 -0
  173. package/src/internal/typescript-import.ts +61 -11
  174. package/src/introspect.ts +82 -21
  175. package/src/levels-tool.ts +6 -0
  176. package/src/load.ts +4 -1
  177. package/src/mcp-context.ts +266 -0
  178. package/src/mcp-docs-tools.ts +37 -0
  179. package/src/mcp-exec.ts +1040 -0
  180. package/src/mcp-http.ts +1 -1
  181. package/src/mcp-io.ts +118 -0
  182. package/src/mcp-reflect.ts +140 -0
  183. package/src/mcp-root.ts +62 -4
  184. package/src/mcp.ts +61 -1436
  185. package/src/openapi-tool.ts +32 -2
  186. package/src/openapi-types.ts +261 -0
  187. package/src/port.ts +2 -1
  188. package/src/project-facts.ts +2 -4
  189. package/src/recipes/3.0.0.ts +24 -0
  190. package/src/recipes/index.ts +2 -0
  191. package/src/release-verification.ts +22 -147
  192. package/src/rules/codes.ts +4 -0
  193. package/src/rules/islands.ts +171 -0
  194. package/src/rules/nano.ts +295 -0
  195. package/src/rules/routes.ts +17 -30
  196. package/src/rules/security.ts +40 -4
  197. package/src/scaffold.ts +169 -9
  198. package/src/search-terms.ts +7 -3
  199. package/src/stylex-migrate.ts +1139 -0
  200. package/src/sync-manifest.ts +2 -1
  201. package/src/verification-plan.ts +242 -0
  202. package/src/work-graph.ts +6 -3
  203. package/src/workspace-link.ts +80 -0
@@ -0,0 +1,1052 @@
1
+ /**
2
+ * Safe, source-preserving Tailwind utility migration for StyleX.
3
+ *
4
+ * This is intentionally a bounded codemod rather than a Tailwind interpreter. Static utilities with
5
+ * a direct StyleX equivalent are rewritten; dynamic className expressions, parent-dependent variants,
6
+ * arbitrary values, and utilities outside the table are left untouched and reported.
7
+ */
8
+ import { readdir, readFile, writeFile } from "node:fs/promises";
9
+ import { relative, resolve } from "node:path";
10
+ const SOURCE_FILE = /\.[cm]?[jt]sx?$/;
11
+ const SKIP_DIRECTORIES = new Set([
12
+ ".git",
13
+ ".next",
14
+ ".nuxt",
15
+ ".planning",
16
+ ".turbo",
17
+ "build",
18
+ "coverage",
19
+ "dist",
20
+ "node_modules",
21
+ "out",
22
+ "public",
23
+ "vendor",
24
+ ]);
25
+ const BREAKPOINTS = {
26
+ sm: "640px",
27
+ md: "768px",
28
+ lg: "1024px",
29
+ xl: "1280px",
30
+ "2xl": "1536px",
31
+ };
32
+ const SPACING = {
33
+ "0": 0,
34
+ px: "1px",
35
+ "0.5": "0.125rem",
36
+ "1": "0.25rem",
37
+ "1.5": "0.375rem",
38
+ "2": "0.5rem",
39
+ "2.5": "0.625rem",
40
+ "3": "0.75rem",
41
+ "3.5": "0.875rem",
42
+ "4": "1rem",
43
+ "5": "1.25rem",
44
+ "6": "1.5rem",
45
+ "7": "1.75rem",
46
+ "8": "2rem",
47
+ "9": "2.25rem",
48
+ "10": "2.5rem",
49
+ "11": "2.75rem",
50
+ "12": "3rem",
51
+ "14": "3.5rem",
52
+ "16": "4rem",
53
+ "20": "5rem",
54
+ "24": "6rem",
55
+ "28": "7rem",
56
+ "32": "8rem",
57
+ "36": "9rem",
58
+ "40": "10rem",
59
+ "44": "11rem",
60
+ "48": "12rem",
61
+ "52": "13rem",
62
+ "56": "14rem",
63
+ "60": "15rem",
64
+ "64": "16rem",
65
+ "72": "18rem",
66
+ "80": "20rem",
67
+ "96": "24rem",
68
+ };
69
+ const FRACTIONS = {
70
+ "1/2": "50%",
71
+ "1/3": "33.333333%",
72
+ "2/3": "66.666667%",
73
+ "1/4": "25%",
74
+ "2/4": "50%",
75
+ "3/4": "75%",
76
+ "1/5": "20%",
77
+ "2/5": "40%",
78
+ "3/5": "60%",
79
+ "4/5": "80%",
80
+ "1/6": "16.666667%",
81
+ "2/6": "33.333333%",
82
+ "3/6": "50%",
83
+ "4/6": "66.666667%",
84
+ "5/6": "83.333333%",
85
+ "1/12": "8.333333%",
86
+ "2/12": "16.666667%",
87
+ "3/12": "25%",
88
+ "4/12": "33.333333%",
89
+ "5/12": "41.666667%",
90
+ "6/12": "50%",
91
+ "7/12": "58.333333%",
92
+ "8/12": "66.666667%",
93
+ "9/12": "75%",
94
+ "10/12": "83.333333%",
95
+ "11/12": "91.666667%",
96
+ };
97
+ const COLORS = {
98
+ transparent: "transparent",
99
+ current: "currentColor",
100
+ inherit: "inherit",
101
+ black: "#000000",
102
+ white: "#ffffff",
103
+ "slate-50": "#f8fafc",
104
+ "slate-100": "#f1f5f9",
105
+ "slate-200": "#e2e8f0",
106
+ "slate-300": "#cbd5e1",
107
+ "slate-400": "#94a3b8",
108
+ "slate-500": "#64748b",
109
+ "slate-600": "#475569",
110
+ "slate-700": "#334155",
111
+ "slate-800": "#1e293b",
112
+ "slate-900": "#0f172a",
113
+ "slate-950": "#020617",
114
+ "gray-50": "#f9fafb",
115
+ "gray-100": "#f3f4f6",
116
+ "gray-200": "#e5e7eb",
117
+ "gray-300": "#d1d5db",
118
+ "gray-400": "#9ca3af",
119
+ "gray-500": "#6b7280",
120
+ "gray-600": "#4b5563",
121
+ "gray-700": "#374151",
122
+ "gray-800": "#1f2937",
123
+ "gray-900": "#111827",
124
+ "gray-950": "#030712",
125
+ "red-50": "#fef2f2",
126
+ "red-100": "#fee2e2",
127
+ "red-200": "#fecaca",
128
+ "red-300": "#fca5a5",
129
+ "red-400": "#f87171",
130
+ "red-500": "#ef4444",
131
+ "red-600": "#dc2626",
132
+ "red-700": "#b91c1c",
133
+ "red-800": "#991b1b",
134
+ "red-900": "#7f1d1d",
135
+ "red-950": "#450a0a",
136
+ "orange-50": "#fff7ed",
137
+ "orange-100": "#ffedd5",
138
+ "orange-200": "#fed7aa",
139
+ "orange-300": "#fdba74",
140
+ "orange-400": "#fb923c",
141
+ "orange-500": "#f97316",
142
+ "orange-600": "#ea580c",
143
+ "orange-700": "#c2410c",
144
+ "orange-800": "#9a3412",
145
+ "orange-900": "#7c2d12",
146
+ "orange-950": "#431407",
147
+ "amber-50": "#fffbeb",
148
+ "amber-100": "#fef3c7",
149
+ "amber-200": "#fde68a",
150
+ "amber-300": "#fcd34d",
151
+ "amber-400": "#fbbf24",
152
+ "amber-500": "#f59e0b",
153
+ "amber-600": "#d97706",
154
+ "amber-700": "#b45309",
155
+ "amber-800": "#92400e",
156
+ "amber-900": "#78350f",
157
+ "amber-950": "#451a03",
158
+ "yellow-50": "#fefce8",
159
+ "yellow-100": "#fef9c3",
160
+ "yellow-200": "#fef08a",
161
+ "yellow-300": "#fde047",
162
+ "yellow-400": "#facc15",
163
+ "yellow-500": "#eab308",
164
+ "yellow-600": "#ca8a04",
165
+ "yellow-700": "#a16207",
166
+ "yellow-800": "#854d0e",
167
+ "yellow-900": "#713f12",
168
+ "yellow-950": "#422006",
169
+ "green-50": "#f0fdf4",
170
+ "green-100": "#dcfce7",
171
+ "green-200": "#bbf7d0",
172
+ "green-300": "#86efac",
173
+ "green-400": "#4ade80",
174
+ "green-500": "#22c55e",
175
+ "green-600": "#16a34a",
176
+ "green-700": "#15803d",
177
+ "green-800": "#166534",
178
+ "green-900": "#14532d",
179
+ "green-950": "#052e16",
180
+ "emerald-50": "#ecfdf5",
181
+ "emerald-100": "#d1fae5",
182
+ "emerald-200": "#a7f3d0",
183
+ "emerald-300": "#6ee7b7",
184
+ "emerald-400": "#34d399",
185
+ "emerald-500": "#10b981",
186
+ "emerald-600": "#059669",
187
+ "emerald-700": "#047857",
188
+ "emerald-800": "#065f46",
189
+ "emerald-900": "#064e3b",
190
+ "emerald-950": "#022c22",
191
+ "teal-50": "#f0fdfa",
192
+ "teal-100": "#ccfbf1",
193
+ "teal-200": "#99f6e4",
194
+ "teal-300": "#5eead4",
195
+ "teal-400": "#2dd4bf",
196
+ "teal-500": "#14b8a6",
197
+ "teal-600": "#0d9488",
198
+ "teal-700": "#0f766e",
199
+ "teal-800": "#115e59",
200
+ "teal-900": "#134e4a",
201
+ "teal-950": "#042f2e",
202
+ "cyan-50": "#ecfeff",
203
+ "cyan-100": "#cffafe",
204
+ "cyan-200": "#a5f3fc",
205
+ "cyan-300": "#67e8f9",
206
+ "cyan-400": "#22d3ee",
207
+ "cyan-500": "#06b6d4",
208
+ "cyan-600": "#0891b2",
209
+ "cyan-700": "#0e7490",
210
+ "cyan-800": "#155e75",
211
+ "cyan-900": "#164e63",
212
+ "cyan-950": "#083344",
213
+ "blue-50": "#eff6ff",
214
+ "blue-100": "#dbeafe",
215
+ "blue-200": "#bfdbfe",
216
+ "blue-300": "#93c5fd",
217
+ "blue-400": "#60a5fa",
218
+ "blue-500": "#3b82f6",
219
+ "blue-600": "#2563eb",
220
+ "blue-700": "#1d4ed8",
221
+ "blue-800": "#1e40af",
222
+ "blue-900": "#1e3a8a",
223
+ "blue-950": "#172554",
224
+ "indigo-50": "#eef2ff",
225
+ "indigo-100": "#e0e7ff",
226
+ "indigo-200": "#c7d2fe",
227
+ "indigo-300": "#a5b4fc",
228
+ "indigo-400": "#818cf8",
229
+ "indigo-500": "#6366f1",
230
+ "indigo-600": "#4f46e5",
231
+ "indigo-700": "#4338ca",
232
+ "indigo-800": "#3730a3",
233
+ "indigo-900": "#312e81",
234
+ "indigo-950": "#1e1b4b",
235
+ "violet-50": "#f5f3ff",
236
+ "violet-100": "#ede9fe",
237
+ "violet-200": "#ddd6fe",
238
+ "violet-300": "#c4b5fd",
239
+ "violet-400": "#a78bfa",
240
+ "violet-500": "#8b5cf6",
241
+ "violet-600": "#7c3aed",
242
+ "violet-700": "#6d28d9",
243
+ "violet-800": "#5b21b6",
244
+ "violet-900": "#4c1d95",
245
+ "violet-950": "#2e1065",
246
+ "purple-50": "#faf5ff",
247
+ "purple-100": "#f3e8ff",
248
+ "purple-200": "#e9d5ff",
249
+ "purple-300": "#d8b4fe",
250
+ "purple-400": "#c084fc",
251
+ "purple-500": "#a855f7",
252
+ "purple-600": "#9333ea",
253
+ "purple-700": "#7e22ce",
254
+ "purple-800": "#6b21a8",
255
+ "purple-900": "#581c87",
256
+ "purple-950": "#3b0764",
257
+ "pink-50": "#fdf2f8",
258
+ "pink-100": "#fce7f3",
259
+ "pink-200": "#fbcfe8",
260
+ "pink-300": "#f9a8d4",
261
+ "pink-400": "#f472b6",
262
+ "pink-500": "#ec4899",
263
+ "pink-600": "#db2777",
264
+ "pink-700": "#be185d",
265
+ "pink-800": "#9d174d",
266
+ "pink-900": "#831843",
267
+ "pink-950": "#500724",
268
+ "rose-50": "#fff1f2",
269
+ "rose-100": "#ffe4e6",
270
+ "rose-200": "#fecdd3",
271
+ "rose-300": "#fda4af",
272
+ "rose-400": "#fb7185",
273
+ "rose-500": "#f43f5e",
274
+ "rose-600": "#e11d48",
275
+ "rose-700": "#be123c",
276
+ "rose-800": "#9f1239",
277
+ "rose-900": "#881337",
278
+ "rose-950": "#4c0519",
279
+ };
280
+ const STATIC_STYLES = {
281
+ block: { display: "block" },
282
+ "inline-block": { display: "inline-block" },
283
+ inline: { display: "inline" },
284
+ flex: { display: "flex" },
285
+ "inline-flex": { display: "inline-flex" },
286
+ grid: { display: "grid" },
287
+ "inline-grid": { display: "inline-grid" },
288
+ contents: { display: "contents" },
289
+ "flow-root": { display: "flow-root" },
290
+ hidden: { display: "none" },
291
+ static: { position: "static" },
292
+ fixed: { position: "fixed" },
293
+ absolute: { position: "absolute" },
294
+ relative: { position: "relative" },
295
+ sticky: { position: "sticky" },
296
+ "flex-row": { flexDirection: "row" },
297
+ "flex-row-reverse": { flexDirection: "row-reverse" },
298
+ "flex-col": { flexDirection: "column" },
299
+ "flex-col-reverse": { flexDirection: "column-reverse" },
300
+ "flex-wrap": { flexWrap: "wrap" },
301
+ "flex-wrap-reverse": { flexWrap: "wrap-reverse" },
302
+ "flex-nowrap": { flexWrap: "nowrap" },
303
+ "flex-1": { flex: "1 1 0%" },
304
+ "flex-auto": { flex: "1 1 auto" },
305
+ "flex-initial": { flex: "0 1 auto" },
306
+ "flex-none": { flex: "none" },
307
+ grow: { flexGrow: 1 },
308
+ "grow-0": { flexGrow: 0 },
309
+ shrink: { flexShrink: 1 },
310
+ "shrink-0": { flexShrink: 0 },
311
+ "justify-normal": { justifyContent: "normal" },
312
+ "justify-start": { justifyContent: "flex-start" },
313
+ "justify-end": { justifyContent: "flex-end" },
314
+ "justify-center": { justifyContent: "center" },
315
+ "justify-between": { justifyContent: "space-between" },
316
+ "justify-around": { justifyContent: "space-around" },
317
+ "justify-evenly": { justifyContent: "space-evenly" },
318
+ "justify-stretch": { justifyContent: "stretch" },
319
+ "items-start": { alignItems: "flex-start" },
320
+ "items-end": { alignItems: "flex-end" },
321
+ "items-center": { alignItems: "center" },
322
+ "items-baseline": { alignItems: "baseline" },
323
+ "items-stretch": { alignItems: "stretch" },
324
+ "self-auto": { alignSelf: "auto" },
325
+ "self-start": { alignSelf: "flex-start" },
326
+ "self-end": { alignSelf: "flex-end" },
327
+ "self-center": { alignSelf: "center" },
328
+ "self-stretch": { alignSelf: "stretch" },
329
+ "place-items-start": { placeItems: "start" },
330
+ "place-items-end": { placeItems: "end" },
331
+ "place-items-center": { placeItems: "center" },
332
+ "place-items-stretch": { placeItems: "stretch" },
333
+ "place-content-start": { placeContent: "start" },
334
+ "place-content-end": { placeContent: "end" },
335
+ "place-content-center": { placeContent: "center" },
336
+ "place-content-between": { placeContent: "space-between" },
337
+ "place-content-around": { placeContent: "space-around" },
338
+ "place-content-evenly": { placeContent: "space-evenly" },
339
+ "place-content-stretch": { placeContent: "stretch" },
340
+ "text-left": { textAlign: "left" },
341
+ "text-center": { textAlign: "center" },
342
+ "text-right": { textAlign: "right" },
343
+ "text-justify": { textAlign: "justify" },
344
+ "text-start": { textAlign: "start" },
345
+ "text-end": { textAlign: "end" },
346
+ italic: { fontStyle: "italic" },
347
+ "not-italic": { fontStyle: "normal" },
348
+ uppercase: { textTransform: "uppercase" },
349
+ lowercase: { textTransform: "lowercase" },
350
+ capitalize: { textTransform: "capitalize" },
351
+ "normal-case": { textTransform: "none" },
352
+ underline: { textDecorationLine: "underline" },
353
+ overline: { textDecorationLine: "overline" },
354
+ "line-through": { textDecorationLine: "line-through" },
355
+ "no-underline": { textDecorationLine: "none" },
356
+ "whitespace-normal": { whiteSpace: "normal" },
357
+ "whitespace-nowrap": { whiteSpace: "nowrap" },
358
+ "whitespace-pre": { whiteSpace: "pre" },
359
+ "whitespace-pre-line": { whiteSpace: "pre-line" },
360
+ "whitespace-pre-wrap": { whiteSpace: "pre-wrap" },
361
+ "break-normal": { overflowWrap: "normal", wordBreak: "normal" },
362
+ "break-words": { overflowWrap: "break-word" },
363
+ "break-all": { wordBreak: "break-all" },
364
+ truncate: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
365
+ "overflow-auto": { overflow: "auto" },
366
+ "overflow-hidden": { overflow: "hidden" },
367
+ "overflow-clip": { overflow: "clip" },
368
+ "overflow-visible": { overflow: "visible" },
369
+ "overflow-scroll": { overflow: "scroll" },
370
+ "object-contain": { objectFit: "contain" },
371
+ "object-cover": { objectFit: "cover" },
372
+ "object-fill": { objectFit: "fill" },
373
+ "object-none": { objectFit: "none" },
374
+ "object-scale-down": { objectFit: "scale-down" },
375
+ "bg-fixed": { backgroundAttachment: "fixed" },
376
+ "bg-local": { backgroundAttachment: "local" },
377
+ "bg-scroll": { backgroundAttachment: "scroll" },
378
+ "bg-cover": { backgroundSize: "cover" },
379
+ "bg-contain": { backgroundSize: "contain" },
380
+ "bg-center": { backgroundPosition: "center" },
381
+ "bg-top": { backgroundPosition: "top" },
382
+ "bg-right": { backgroundPosition: "right" },
383
+ "bg-bottom": { backgroundPosition: "bottom" },
384
+ "bg-left": { backgroundPosition: "left" },
385
+ "border-solid": { borderStyle: "solid" },
386
+ "border-dashed": { borderStyle: "dashed" },
387
+ "border-dotted": { borderStyle: "dotted" },
388
+ "border-double": { borderStyle: "double" },
389
+ "border-hidden": { borderStyle: "hidden" },
390
+ "border-none": { borderStyle: "none" },
391
+ "rounded-none": { borderRadius: "0px" },
392
+ rounded: { borderRadius: "0.25rem" },
393
+ "rounded-sm": { borderRadius: "0.125rem" },
394
+ "rounded-md": { borderRadius: "0.375rem" },
395
+ "rounded-lg": { borderRadius: "0.5rem" },
396
+ "rounded-xl": { borderRadius: "0.75rem" },
397
+ "rounded-2xl": { borderRadius: "1rem" },
398
+ "rounded-3xl": { borderRadius: "1.5rem" },
399
+ "rounded-full": { borderRadius: "9999px" },
400
+ "shadow-sm": { boxShadow: "0 1px 2px 0 rgb(0 0 0 / 0.05)" },
401
+ shadow: { boxShadow: "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)" },
402
+ "shadow-md": { boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)" },
403
+ "shadow-lg": { boxShadow: "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)" },
404
+ "shadow-xl": { boxShadow: "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)" },
405
+ "shadow-2xl": { boxShadow: "0 25px 50px -12px rgb(0 0 0 / 0.25)" },
406
+ "shadow-inner": { boxShadow: "inset 0 2px 4px 0 rgb(0 0 0 / 0.05)" },
407
+ "shadow-none": { boxShadow: "0 0 #0000" },
408
+ "transition-none": { transitionProperty: "none" },
409
+ "transition-all": {
410
+ transitionProperty: "all",
411
+ transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)",
412
+ transitionDuration: "150ms",
413
+ },
414
+ "transition-colors": {
415
+ transitionProperty: "color, background-color, border-color, text-decoration-color, fill, stroke",
416
+ transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)",
417
+ transitionDuration: "150ms",
418
+ },
419
+ "transition-opacity": {
420
+ transitionProperty: "opacity",
421
+ transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)",
422
+ transitionDuration: "150ms",
423
+ },
424
+ "transition-shadow": {
425
+ transitionProperty: "box-shadow",
426
+ transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)",
427
+ transitionDuration: "150ms",
428
+ },
429
+ "transition-transform": {
430
+ transitionProperty: "transform",
431
+ transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)",
432
+ transitionDuration: "150ms",
433
+ },
434
+ "cursor-auto": { cursor: "auto" },
435
+ "cursor-default": { cursor: "default" },
436
+ "cursor-pointer": { cursor: "pointer" },
437
+ "cursor-wait": { cursor: "wait" },
438
+ "cursor-text": { cursor: "text" },
439
+ "cursor-move": { cursor: "move" },
440
+ "cursor-not-allowed": { cursor: "not-allowed" },
441
+ "select-none": { userSelect: "none" },
442
+ "select-text": { userSelect: "text" },
443
+ "select-all": { userSelect: "all" },
444
+ "select-auto": { userSelect: "auto" },
445
+ visible: { visibility: "visible" },
446
+ invisible: { visibility: "hidden" },
447
+ collapse: { visibility: "collapse" },
448
+ "appearance-none": { appearance: "none" },
449
+ "pointer-events-none": { pointerEvents: "none" },
450
+ "pointer-events-auto": { pointerEvents: "auto" },
451
+ "resize-none": { resize: "none" },
452
+ "resize-y": { resize: "vertical" },
453
+ "resize-x": { resize: "horizontal" },
454
+ resize: { resize: "both" },
455
+ };
456
+ const FONT_SIZES = {
457
+ xs: ["0.75rem", "1rem"],
458
+ sm: ["0.875rem", "1.25rem"],
459
+ base: ["1rem", "1.5rem"],
460
+ lg: ["1.125rem", "1.75rem"],
461
+ xl: ["1.25rem", "1.75rem"],
462
+ "2xl": ["1.5rem", "2rem"],
463
+ "3xl": ["1.875rem", "2.25rem"],
464
+ "4xl": ["2.25rem", "2.5rem"],
465
+ "5xl": ["3rem", "1"],
466
+ "6xl": ["3.75rem", "1"],
467
+ "7xl": ["4.5rem", "1"],
468
+ "8xl": ["6rem", "1"],
469
+ "9xl": ["8rem", "1"],
470
+ };
471
+ const FONT_WEIGHTS = {
472
+ thin: 100,
473
+ extralight: 200,
474
+ light: 300,
475
+ normal: 400,
476
+ medium: 500,
477
+ semibold: 600,
478
+ bold: 700,
479
+ extrabold: 800,
480
+ black: 900,
481
+ };
482
+ const LINE_HEIGHTS = {
483
+ none: "1",
484
+ tight: "1.25",
485
+ snug: "1.375",
486
+ normal: "1.5",
487
+ relaxed: "1.625",
488
+ loose: "2",
489
+ };
490
+ const MAX_WIDTHS = {
491
+ none: "none",
492
+ 0: "0rem",
493
+ xs: "20rem",
494
+ sm: "24rem",
495
+ md: "28rem",
496
+ lg: "32rem",
497
+ xl: "36rem",
498
+ "2xl": "42rem",
499
+ "3xl": "48rem",
500
+ "4xl": "56rem",
501
+ "5xl": "64rem",
502
+ "6xl": "72rem",
503
+ "7xl": "80rem",
504
+ full: "100%",
505
+ min: "min-content",
506
+ max: "max-content",
507
+ fit: "fit-content",
508
+ };
509
+ const PSEUDO_VARIANTS = {
510
+ hover: ":hover",
511
+ focus: ":focus",
512
+ "focus-visible": ":focus-visible",
513
+ active: ":active",
514
+ visited: ":visited",
515
+ target: ":target",
516
+ enabled: ":enabled",
517
+ disabled: ":disabled",
518
+ checked: ":checked",
519
+ indeterminate: ":indeterminate",
520
+ default: ":default",
521
+ required: ":required",
522
+ valid: ":valid",
523
+ invalid: ":invalid",
524
+ placeholder: "::placeholder",
525
+ "placeholder-shown": ":placeholder-shown",
526
+ autofill: ":autofill",
527
+ "read-only": ":read-only",
528
+ };
529
+ const CLASS_ATTRIBUTE = /\bclassName\s*=\s*(?:"([^"]*)"|'([^']*)'|\{\s*(?:"([^"]*)"|'([^']*)')\s*\}|\{([\s\S]*?)\})/g;
530
+ const isRecord = (value) => typeof value === "object" && value !== null;
531
+ const cloneStyle = (style) => {
532
+ const result = {};
533
+ for (const [key, value] of Object.entries(style))
534
+ result[key] = isRecord(value) ? cloneStyle(value) : value;
535
+ return result;
536
+ };
537
+ const withVariants = (style, variants) => {
538
+ let result = cloneStyle(style);
539
+ for (const variant of [...variants].reverse()) {
540
+ const breakpoint = BREAKPOINTS[variant];
541
+ if (breakpoint !== undefined) {
542
+ result = { [`@media (min-width: ${breakpoint})`]: result };
543
+ continue;
544
+ }
545
+ const pseudo = PSEUDO_VARIANTS[variant];
546
+ if (pseudo !== undefined) {
547
+ result = { [pseudo]: result };
548
+ continue;
549
+ }
550
+ if (variant === "motion-safe") {
551
+ result = { "@media (prefers-reduced-motion: no-preference)": result };
552
+ continue;
553
+ }
554
+ if (variant === "motion-reduce") {
555
+ result = { "@media (prefers-reduced-motion: reduce)": result };
556
+ continue;
557
+ }
558
+ return {
559
+ reason: `variant '${variant}:' depends on parent state, arbitrary selectors, or runtime configuration`,
560
+ };
561
+ }
562
+ return { style: result };
563
+ };
564
+ const negativeValue = (value, negative) => {
565
+ if (!negative)
566
+ return value;
567
+ if (typeof value === "number")
568
+ return -value;
569
+ if (value === "0")
570
+ return 0;
571
+ return value.startsWith("-") ? value.slice(1) : `-${value}`;
572
+ };
573
+ const spacingValue = (value, negative) => {
574
+ if (value === "auto")
575
+ return negative ? undefined : "auto";
576
+ const spacing = SPACING[value];
577
+ return spacing === undefined ? undefined : negativeValue(spacing, negative);
578
+ };
579
+ const dimensionValue = (value, axis) => {
580
+ if (value === "auto")
581
+ return "auto";
582
+ if (value === "full")
583
+ return "100%";
584
+ if (value === "screen")
585
+ return axis === "h" ? "100vh" : "100vw";
586
+ if (value === "svw")
587
+ return "100svw";
588
+ if (value === "lvw")
589
+ return "100lvw";
590
+ if (value === "dvw")
591
+ return "100dvw";
592
+ if (value === "svh")
593
+ return "100svh";
594
+ if (value === "lvh")
595
+ return "100lvh";
596
+ if (value === "dvh")
597
+ return "100dvh";
598
+ if (value === "min")
599
+ return "min-content";
600
+ if (value === "max")
601
+ return "max-content";
602
+ if (value === "fit")
603
+ return "fit-content";
604
+ return FRACTIONS[value] ?? SPACING[value];
605
+ };
606
+ const colorValue = (value) => COLORS[value];
607
+ const directionalProperty = (prefix, axis) => {
608
+ const properties = {
609
+ p: ["padding"],
610
+ px: ["paddingInline"],
611
+ py: ["paddingBlock"],
612
+ pt: ["paddingTop"],
613
+ pr: ["paddingRight"],
614
+ pb: ["paddingBottom"],
615
+ pl: ["paddingLeft"],
616
+ ps: ["paddingInlineStart"],
617
+ pe: ["paddingInlineEnd"],
618
+ m: ["margin"],
619
+ mx: ["marginInline"],
620
+ my: ["marginBlock"],
621
+ mt: ["marginTop"],
622
+ mr: ["marginRight"],
623
+ mb: ["marginBottom"],
624
+ ml: ["marginLeft"],
625
+ ms: ["marginInlineStart"],
626
+ me: ["marginInlineEnd"],
627
+ inset: ["inset"],
628
+ "inset-x": ["insetInline"],
629
+ "inset-y": ["insetBlock"],
630
+ start: ["insetInlineStart"],
631
+ end: ["insetInlineEnd"],
632
+ top: ["top"],
633
+ right: ["right"],
634
+ bottom: ["bottom"],
635
+ left: ["left"],
636
+ };
637
+ if (axis === undefined)
638
+ return properties[prefix];
639
+ return properties[`${prefix}-${axis}`];
640
+ };
641
+ const convertBase = (token, negative) => {
642
+ const staticStyle = STATIC_STYLES[token];
643
+ if (staticStyle !== undefined) {
644
+ if (negative)
645
+ return { reason: `negative utility '${token}' has no safe StyleX equivalent` };
646
+ return { style: staticStyle };
647
+ }
648
+ const spacing = /^(p|px|py|pt|pr|pb|pl|ps|pe|m|mx|my|mt|mr|mb|ml|ms|me|inset|start|end|top|right|bottom|left)(?:-(.+))$/.exec(token);
649
+ if (spacing !== null) {
650
+ const value = spacingValue(spacing[2], negative);
651
+ const properties = directionalProperty(spacing[1], undefined);
652
+ if (value !== undefined && properties !== undefined) {
653
+ return { style: Object.fromEntries(properties.map((property) => [property, value])) };
654
+ }
655
+ return { reason: `spacing value '${spacing[2]}' is not in the safe static scale` };
656
+ }
657
+ const gap = /^(gap|gap-x|gap-y)-(.+)$/.exec(token);
658
+ if (gap !== null) {
659
+ const value = spacingValue(gap[2], negative);
660
+ if (value !== undefined) {
661
+ const property = gap[1] === "gap-x" ? "columnGap" : gap[1] === "gap-y" ? "rowGap" : "gap";
662
+ return { style: { [property]: value } };
663
+ }
664
+ return { reason: `gap value '${gap[2]}' is not in the safe static scale` };
665
+ }
666
+ const size = /^(w|h|min-w|min-h|max-w|max-h)-(.+)$/.exec(token);
667
+ if (size !== null) {
668
+ const rawValue = size[2];
669
+ const axis = size[1]?.endsWith("h") ? "h" : "w";
670
+ const value = size[1] === "max-w" ? MAX_WIDTHS[rawValue] : dimensionValue(rawValue, axis);
671
+ if (value !== undefined) {
672
+ const property = size[1] === "w"
673
+ ? "width"
674
+ : size[1] === "h"
675
+ ? "height"
676
+ : size[1] === "min-w"
677
+ ? "minWidth"
678
+ : size[1] === "min-h"
679
+ ? "minHeight"
680
+ : size[1] === "max-w"
681
+ ? "maxWidth"
682
+ : "maxHeight";
683
+ return { style: { [property]: negativeValue(value, negative) } };
684
+ }
685
+ return { reason: `size value '${rawValue}' is not in the safe static scale` };
686
+ }
687
+ const inset = /^(inset|inset-x|inset-y|start|end|top|right|bottom|left)-(.+)$/.exec(token);
688
+ if (inset !== null) {
689
+ const value = spacingValue(inset[2], negative);
690
+ const properties = directionalProperty(inset[1], undefined);
691
+ if (value !== undefined && properties !== undefined)
692
+ return { style: Object.fromEntries(properties.map((property) => [property, value])) };
693
+ return { reason: `inset value '${inset[2]}' is not in the safe static scale` };
694
+ }
695
+ const zIndex = /^z-(.+)$/.exec(token);
696
+ if (zIndex !== null && (zIndex[1] === "auto" || /^\d+$/.test(zIndex[1])))
697
+ return { style: { zIndex: zIndex[1] === "auto" ? "auto" : Number(zIndex[1]) } };
698
+ const order = /^order-(.+)$/.exec(token);
699
+ if (order !== null) {
700
+ const value = { first: -9999, last: 9999, none: 0 }[order[1]];
701
+ if (value !== undefined)
702
+ return { style: { order: value } };
703
+ if (/^\d+$/.test(order[1]))
704
+ return { style: { order: Number(order[1]) } };
705
+ }
706
+ const textSize = /^text-(.+)$/.exec(token);
707
+ if (textSize !== null) {
708
+ const size = FONT_SIZES[textSize[1]];
709
+ if (size !== undefined)
710
+ return { style: { fontSize: size[0], lineHeight: size[1] } };
711
+ const color = colorValue(textSize[1]);
712
+ if (color !== undefined)
713
+ return { style: { color } };
714
+ return {
715
+ reason: `text utility '${textSize[1]}' is not in the safe static typography/color set`,
716
+ };
717
+ }
718
+ const background = /^bg-(.+)$/.exec(token);
719
+ if (background !== null) {
720
+ const color = colorValue(background[1]);
721
+ if (color !== undefined)
722
+ return { style: { backgroundColor: color } };
723
+ return { reason: `background utility '${background[1]}' is not in the safe static color set` };
724
+ }
725
+ const font = /^font-(.+)$/.exec(token);
726
+ if (font !== null) {
727
+ const weight = FONT_WEIGHTS[font[1]];
728
+ if (weight !== undefined)
729
+ return { style: { fontWeight: weight } };
730
+ if (font[1] === "sans")
731
+ return { style: { fontFamily: "ui-sans-serif, system-ui, sans-serif" } };
732
+ if (font[1] === "serif")
733
+ return { style: { fontFamily: "ui-serif, Georgia, serif" } };
734
+ if (font[1] === "mono")
735
+ return { style: { fontFamily: "ui-monospace, SFMono-Regular, monospace" } };
736
+ return { reason: `font utility '${font[1]}' is not in the safe static typography set` };
737
+ }
738
+ const leading = /^leading-(.+)$/.exec(token);
739
+ if (leading !== null) {
740
+ const value = LINE_HEIGHTS[leading[1]] ?? spacingValue(leading[1], false);
741
+ if (value !== undefined)
742
+ return { style: { lineHeight: value } };
743
+ return { reason: `line-height value '${leading[1]}' is not in the safe static scale` };
744
+ }
745
+ const tracking = /^tracking-(.+)$/.exec(token);
746
+ if (tracking !== null) {
747
+ const values = {
748
+ tighter: "-0.05em",
749
+ tight: "-0.025em",
750
+ normal: "0em",
751
+ wide: "0.025em",
752
+ wider: "0.05em",
753
+ widest: "0.1em",
754
+ };
755
+ const value = values[tracking[1]];
756
+ if (value !== undefined)
757
+ return { style: { letterSpacing: value } };
758
+ return { reason: `letter-spacing value '${tracking[1]}' is not in the safe static set` };
759
+ }
760
+ const opacity = /^opacity-(\d+)$/.exec(token);
761
+ if (opacity !== null && Number(opacity[1]) <= 100)
762
+ return { style: { opacity: Number(opacity[1]) / 100 } };
763
+ const borderWidth = /^(border(?:-[trblxyse])?)(?:-(0|2|4|8))?$/.exec(token);
764
+ if (borderWidth !== null) {
765
+ const value = borderWidth[2] === undefined ? "1px" : `${borderWidth[2]}px`;
766
+ const properties = {
767
+ border: "borderWidth",
768
+ "border-x": "borderInlineWidth",
769
+ "border-y": "borderBlockWidth",
770
+ "border-t": "borderTopWidth",
771
+ "border-r": "borderRightWidth",
772
+ "border-b": "borderBottomWidth",
773
+ "border-l": "borderLeftWidth",
774
+ "border-s": "borderInlineStartWidth",
775
+ "border-e": "borderInlineEndWidth",
776
+ };
777
+ const property = properties[borderWidth[1]];
778
+ if (property === undefined)
779
+ return { reason: `border utility '${token}' has no safe StyleX property mapping` };
780
+ return { style: { [property]: value } };
781
+ }
782
+ const borderColor = /^(border(?:-[trblxyse])?)-(.+)$/.exec(token);
783
+ if (borderColor !== null) {
784
+ const color = colorValue(borderColor[2]);
785
+ if (color !== undefined) {
786
+ const properties = {
787
+ border: "borderColor",
788
+ "border-x": "borderInlineColor",
789
+ "border-y": "borderBlockColor",
790
+ "border-t": "borderTopColor",
791
+ "border-r": "borderRightColor",
792
+ "border-b": "borderBottomColor",
793
+ "border-l": "borderLeftColor",
794
+ "border-s": "borderInlineStartColor",
795
+ "border-e": "borderInlineEndColor",
796
+ };
797
+ const property = properties[borderColor[1]];
798
+ if (property === undefined)
799
+ return { reason: `border utility '${token}' has no safe StyleX property mapping` };
800
+ return { style: { [property]: color } };
801
+ }
802
+ return { reason: `border color '${borderColor[2]}' is not in the safe static color set` };
803
+ }
804
+ const rounded = /^rounded(?:-([trblse]{1,2}))?(?:-(none|sm|md|lg|xl|2xl|3xl|full))?$/.exec(token);
805
+ if (rounded !== null) {
806
+ const sizes = {
807
+ none: "0px",
808
+ sm: "0.125rem",
809
+ md: "0.375rem",
810
+ lg: "0.5rem",
811
+ xl: "0.75rem",
812
+ "2xl": "1rem",
813
+ "3xl": "1.5rem",
814
+ full: "9999px",
815
+ };
816
+ const value = sizes[rounded[2] ?? "md"] ?? (rounded[2] === undefined ? "0.25rem" : undefined);
817
+ if (value !== undefined) {
818
+ const side = rounded[1];
819
+ if (side === undefined)
820
+ return { style: { borderRadius: value } };
821
+ const properties = {
822
+ t: ["borderTopLeftRadius", "borderTopRightRadius"],
823
+ r: ["borderTopRightRadius", "borderBottomRightRadius"],
824
+ b: ["borderBottomLeftRadius", "borderBottomRightRadius"],
825
+ l: ["borderTopLeftRadius", "borderBottomLeftRadius"],
826
+ s: ["borderStartStartRadius", "borderEndStartRadius"],
827
+ e: ["borderStartEndRadius", "borderEndEndRadius"],
828
+ };
829
+ const first = properties[side[0]];
830
+ const second = properties[side[1]];
831
+ if (first !== undefined && second !== undefined)
832
+ return {
833
+ style: Object.fromEntries([...first, ...second].map((property) => [property, value])),
834
+ };
835
+ if (first !== undefined)
836
+ return { style: Object.fromEntries(first.map((property) => [property, value])) };
837
+ }
838
+ }
839
+ return { reason: "utility is outside the safe static Tailwind-to-StyleX subset" };
840
+ };
841
+ const convertToken = (token) => {
842
+ const parts = token.split(":");
843
+ const base = parts.pop() ?? "";
844
+ const negative = base.startsWith("-");
845
+ const normalized = negative ? base.slice(1) : base;
846
+ const conversion = convertBase(normalized, negative);
847
+ if (conversion.style === undefined)
848
+ return conversion;
849
+ return withVariants(conversion.style, parts);
850
+ };
851
+ const lineOf = (source, offset) => {
852
+ let line = 1;
853
+ for (let index = 0; index < offset; index += 1)
854
+ if (source[index] === "\n")
855
+ line += 1;
856
+ return line;
857
+ };
858
+ const isLikelyJsxAttribute = (source, offset) => {
859
+ const tagStart = source.lastIndexOf("<", offset);
860
+ const tagEnd = source.lastIndexOf(">", offset);
861
+ return tagStart > tagEnd && !source.slice(tagStart, offset).includes("<!--");
862
+ };
863
+ const classAttributes = (source) => {
864
+ const attributes = [];
865
+ for (const match of source.matchAll(CLASS_ATTRIBUTE)) {
866
+ const start = match.index ?? 0;
867
+ if (!isLikelyJsxAttribute(source, start))
868
+ continue;
869
+ const end = start + match[0].length;
870
+ const value = match[1] ?? match[2] ?? match[3] ?? match[4];
871
+ attributes.push(value === undefined ? { start, end, expression: match[5] ?? "" } : { start, end, value });
872
+ }
873
+ return attributes;
874
+ };
875
+ const safeIdentifier = (value) => {
876
+ const normalized = value.replace(/[^A-Za-z0-9_$]+/g, "_").replace(/^\d/, "_$&");
877
+ return normalized.length === 0 ? "utility" : normalized;
878
+ };
879
+ const uniqueIdentifier = (source, base) => {
880
+ const names = new Set([...source.matchAll(/\b(?:const|let|var|function|class|import)\s+([A-Za-z_$][\w$]*)/g)].map((match) => match[1]));
881
+ let candidate = base;
882
+ let suffix = 2;
883
+ while (names.has(candidate))
884
+ candidate = `${base}${suffix++}`;
885
+ return candidate;
886
+ };
887
+ const existingStylexImport = (source) => {
888
+ const match = /import\s+\*\s+as\s+([A-Za-z_$][\w$]*)\s+from\s+["'](?:@stylexjs\/stylex|stylex)["']/.exec(source);
889
+ return match?.[1];
890
+ };
891
+ const insertionOffset = (source) => {
892
+ let offset = source.startsWith("#!") ? source.indexOf("\n") + 1 || source.length : 0;
893
+ const lines = source.slice(offset).split(/(?<=\n)/);
894
+ let consumed = 0;
895
+ let inImport = false;
896
+ for (const line of lines) {
897
+ const trimmed = line.trim();
898
+ const directive = /^(['"])(?:use client|use server)\1;?$/.test(trimmed);
899
+ if (inImport || trimmed.startsWith("import ") || trimmed.startsWith("import{")) {
900
+ inImport = !/(?:from\s+["'][^"']+["']|import\s+["'][^"']+["'])\s*;?$/.test(trimmed);
901
+ consumed += line.length;
902
+ continue;
903
+ }
904
+ if (directive || trimmed === "") {
905
+ consumed += line.length;
906
+ continue;
907
+ }
908
+ break;
909
+ }
910
+ offset += consumed;
911
+ return offset;
912
+ };
913
+ /** Transform one source file. The returned source is unchanged when every match is unsupported. */
914
+ export function migrateTailwindSource(source, file) {
915
+ const attributes = classAttributes(source);
916
+ if (attributes.length === 0)
917
+ return { source, changed: false, replacements: 0, issues: [] };
918
+ const replacements = [];
919
+ const issues = [];
920
+ const styles = new Map();
921
+ const tokenToKey = new Map();
922
+ for (const attribute of attributes) {
923
+ if (attribute.value === undefined) {
924
+ issues.push({
925
+ file,
926
+ line: lineOf(source, attribute.start),
927
+ token: attribute.expression?.trim() || "className expression",
928
+ reason: "dynamic className expressions are left for a manual StyleX props composition",
929
+ });
930
+ continue;
931
+ }
932
+ const tokens = attribute.value.trim().split(/\s+/).filter(Boolean);
933
+ if (tokens.length === 0)
934
+ continue;
935
+ const converted = [];
936
+ let unsupported = false;
937
+ for (const token of tokens) {
938
+ const conversion = convertToken(token);
939
+ if (conversion.style === undefined) {
940
+ issues.push({
941
+ file,
942
+ line: lineOf(source, attribute.start),
943
+ token,
944
+ reason: conversion.reason ?? "utility could not be converted safely",
945
+ });
946
+ unsupported = true;
947
+ }
948
+ else
949
+ converted.push({ token, style: conversion.style });
950
+ }
951
+ if (unsupported)
952
+ continue;
953
+ const refs = [];
954
+ for (const { token, style } of converted) {
955
+ let key = tokenToKey.get(token);
956
+ if (key === undefined) {
957
+ const base = `tw_${safeIdentifier(token)}`;
958
+ key = base;
959
+ let suffix = 2;
960
+ while (styles.has(key))
961
+ key = `${base}_${suffix++}`;
962
+ tokenToKey.set(token, key);
963
+ styles.set(key, style);
964
+ }
965
+ refs.push(`${stylesNamePlaceholder}.${key}`);
966
+ }
967
+ replacements.push({
968
+ start: attribute.start,
969
+ end: attribute.end,
970
+ text: `{...${stylexNamePlaceholder}.props(${refs.join(", ")})}`,
971
+ });
972
+ }
973
+ if (replacements.length === 0)
974
+ return { source, changed: false, replacements: 0, issues };
975
+ const stylexName = existingStylexImport(source) ?? uniqueIdentifier(source, "nifraStylex");
976
+ const stylesName = uniqueIdentifier(source, "nifraStyles");
977
+ const rewritten = [...replacements]
978
+ .sort((left, right) => right.start - left.start)
979
+ .reduce((current, replacement) => `${current.slice(0, replacement.start)}${replacement.text
980
+ .replaceAll(stylexNamePlaceholder, stylexName)
981
+ .replaceAll(stylesNamePlaceholder, stylesName)}${current.slice(replacement.end)}`, source);
982
+ const needsImport = existingStylexImport(source) === undefined;
983
+ const generated = `${needsImport ? `import * as ${stylexName} from "${STYLEX_SPECIFIER}"\n\n` : ""}const ${stylesName} = ${stylexName}.create(${JSON.stringify(Object.fromEntries(styles), null, 2)})\n\n`;
984
+ const offset = insertionOffset(rewritten);
985
+ const withGenerated = `${rewritten.slice(0, offset)}${generated}${rewritten.slice(offset)}`;
986
+ return { source: withGenerated, changed: true, replacements: replacements.length, issues };
987
+ }
988
+ const stylexNamePlaceholder = "__NIFRA_STYLEX__";
989
+ const stylesNamePlaceholder = "__NIFRA_STYLES__";
990
+ const STYLEX_SPECIFIER = "@stylexjs/" + "stylex";
991
+ async function sourceFiles(root) {
992
+ const files = [];
993
+ const visit = async (directory) => {
994
+ const entries = await readdir(directory, { withFileTypes: true });
995
+ for (const entry of entries) {
996
+ if (entry.name.startsWith(".") && entry.isDirectory())
997
+ continue;
998
+ if (entry.isDirectory()) {
999
+ if (!SKIP_DIRECTORIES.has(entry.name))
1000
+ await visit(resolve(directory, entry.name));
1001
+ continue;
1002
+ }
1003
+ if (entry.isFile() && SOURCE_FILE.test(entry.name))
1004
+ files.push(resolve(directory, entry.name));
1005
+ }
1006
+ };
1007
+ await visit(root);
1008
+ return files.sort();
1009
+ }
1010
+ /** Scan a project and optionally write only the statically safe transformations. */
1011
+ export async function migrateTailwindToStylex(root, options = {}) {
1012
+ const write = options.write === true;
1013
+ const files = [];
1014
+ const issues = [];
1015
+ const changed = [];
1016
+ const written = [];
1017
+ const paths = await sourceFiles(root);
1018
+ for (const path of paths) {
1019
+ const file = relative(root, path).replaceAll("\\", "/");
1020
+ const source = await readFile(path, "utf8");
1021
+ const migration = migrateTailwindSource(source, file);
1022
+ if (!migration.changed && migration.issues.length === 0)
1023
+ continue;
1024
+ const willWrite = write && migration.changed;
1025
+ if (migration.changed)
1026
+ changed.push(file);
1027
+ if (willWrite) {
1028
+ await writeFile(path, migration.source, "utf8");
1029
+ written.push(file);
1030
+ }
1031
+ issues.push(...migration.issues);
1032
+ files.push({
1033
+ file,
1034
+ changed: migration.changed,
1035
+ replacements: migration.replacements,
1036
+ written: willWrite,
1037
+ issues: migration.issues,
1038
+ });
1039
+ }
1040
+ return {
1041
+ ok: issues.length === 0,
1042
+ from: "tailwind",
1043
+ to: "stylex",
1044
+ write,
1045
+ scanned: paths.length,
1046
+ changed,
1047
+ written,
1048
+ issues,
1049
+ files,
1050
+ };
1051
+ }
1052
+ //# sourceMappingURL=stylex-migrate.js.map