trix-ui 0.2.14 → 0.3.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 (241) hide show
  1. package/dist/commands/add/analysis.d.ts +4 -4
  2. package/dist/commands/add/analysis.js +56 -56
  3. package/dist/commands/add/command.d.ts +2 -2
  4. package/dist/commands/add/command.js +205 -202
  5. package/dist/commands/add/command.js.map +1 -1
  6. package/dist/commands/add/config.d.ts +2 -2
  7. package/dist/commands/add/config.js +11 -11
  8. package/dist/commands/add/install.d.ts +27 -27
  9. package/dist/commands/add/install.js +80 -80
  10. package/dist/commands/add/package-manager.d.ts +1 -1
  11. package/dist/commands/add/package-manager.js +4 -4
  12. package/dist/commands/add/project-files.d.ts +2 -2
  13. package/dist/commands/add/project-files.js +17 -17
  14. package/dist/commands/add/prompts.d.ts +3 -3
  15. package/dist/commands/add/prompts.js +28 -28
  16. package/dist/commands/add/registry.d.ts +4 -4
  17. package/dist/commands/add/registry.js +6 -6
  18. package/dist/commands/add/types.d.ts +33 -33
  19. package/dist/commands/add/types.js +1 -1
  20. package/dist/commands/add/ui.d.ts +4 -4
  21. package/dist/commands/add/ui.js +55 -55
  22. package/dist/commands/add/validation.d.ts +3 -3
  23. package/dist/commands/add/validation.js +30 -30
  24. package/dist/commands/add-collection.d.ts +1 -1
  25. package/dist/commands/add-collection.js +1 -1
  26. package/dist/commands/add-composite.d.ts +2 -2
  27. package/dist/commands/add-composite.js +205 -201
  28. package/dist/commands/add-composite.js.map +1 -1
  29. package/dist/commands/add-section.d.ts +2 -2
  30. package/dist/commands/add-section.js +205 -201
  31. package/dist/commands/add-section.js.map +1 -1
  32. package/dist/commands/add-wrapper.d.ts +2 -2
  33. package/dist/commands/add-wrapper.js +205 -201
  34. package/dist/commands/add-wrapper.js.map +1 -1
  35. package/dist/commands/add.d.ts +1 -1
  36. package/dist/commands/add.js +1 -1
  37. package/dist/commands/build.d.ts +2 -2
  38. package/dist/commands/build.js +104 -104
  39. package/dist/commands/build.js.map +1 -1
  40. package/dist/commands/doctor.d.ts +2 -2
  41. package/dist/commands/doctor.js +67 -67
  42. package/dist/commands/doctor.js.map +1 -1
  43. package/dist/commands/init/command.d.ts +8 -2
  44. package/dist/commands/init/command.js +186 -114
  45. package/dist/commands/init/command.js.map +1 -1
  46. package/dist/commands/init/config.d.ts +9 -2
  47. package/dist/commands/init/config.js +45 -25
  48. package/dist/commands/init/config.js.map +1 -1
  49. package/dist/commands/init/constants.d.ts +3 -3
  50. package/dist/commands/init/constants.js +105 -105
  51. package/dist/commands/init/dependencies.d.ts +22 -5
  52. package/dist/commands/init/dependencies.js +86 -52
  53. package/dist/commands/init/dependencies.js.map +1 -1
  54. package/dist/commands/init/filesystem.d.ts +7 -1
  55. package/dist/commands/init/filesystem.js +16 -10
  56. package/dist/commands/init/filesystem.js.map +1 -1
  57. package/dist/commands/init/lockfile.d.ts +1 -1
  58. package/dist/commands/init/lockfile.js +1 -1
  59. package/dist/commands/init/package-json.d.ts +17 -6
  60. package/dist/commands/init/package-json.js +28 -18
  61. package/dist/commands/init/package-json.js.map +1 -1
  62. package/dist/commands/init/project.d.ts +15 -3
  63. package/dist/commands/init/project.js +120 -97
  64. package/dist/commands/init/project.js.map +1 -1
  65. package/dist/commands/init/tailwind.d.ts +14 -3
  66. package/dist/commands/init/tailwind.js +141 -33
  67. package/dist/commands/init/tailwind.js.map +1 -1
  68. package/dist/commands/init/templates.d.ts +15 -3
  69. package/dist/commands/init/templates.js +27 -15
  70. package/dist/commands/init/templates.js.map +1 -1
  71. package/dist/commands/init/tsconfig.d.ts +14 -2
  72. package/dist/commands/init/tsconfig.js +561 -273
  73. package/dist/commands/init/tsconfig.js.map +1 -1
  74. package/dist/commands/init/types.d.ts +34 -33
  75. package/dist/commands/init/types.js +1 -1
  76. package/dist/commands/init/ui.d.ts +12 -3
  77. package/dist/commands/init/ui.js +45 -33
  78. package/dist/commands/init/ui.js.map +1 -1
  79. package/dist/commands/init/vite.d.ts +1 -1
  80. package/dist/commands/init/vite.js +17 -27
  81. package/dist/commands/init/vite.js.map +1 -1
  82. package/dist/commands/init.d.ts +1 -1
  83. package/dist/commands/init.js +1 -1
  84. package/dist/commands/list.d.ts +2 -2
  85. package/dist/commands/list.js +69 -62
  86. package/dist/commands/list.js.map +1 -1
  87. package/dist/commands/remove.d.ts +2 -2
  88. package/dist/commands/remove.js +95 -93
  89. package/dist/commands/remove.js.map +1 -1
  90. package/dist/commands/shared/add-collection.d.ts +50 -50
  91. package/dist/commands/shared/add-collection.js +206 -206
  92. package/dist/commands/shared/list-entries.d.ts +6 -6
  93. package/dist/commands/shared/list-entries.js +12 -12
  94. package/dist/commands/shared/name-utils.d.ts +1 -1
  95. package/dist/commands/shared/name-utils.js +13 -13
  96. package/dist/commands/shared/remove-entries.d.ts +16 -16
  97. package/dist/commands/shared/remove-entries.js +41 -41
  98. package/dist/icons/index.d.ts +1 -1
  99. package/dist/icons/index.js +1 -1
  100. package/dist/icons/libraries.d.ts +37 -37
  101. package/dist/icons/libraries.js +34 -34
  102. package/dist/index.d.ts +1 -2
  103. package/dist/index.js +29 -30
  104. package/dist/index.js.map +1 -1
  105. package/dist/lib/config.d.ts +45 -45
  106. package/dist/lib/config.js +97 -97
  107. package/dist/lib/fs.d.ts +82 -76
  108. package/dist/lib/fs.js +299 -302
  109. package/dist/lib/fs.js.map +1 -1
  110. package/dist/lib/highlighter.d.ts +6 -6
  111. package/dist/lib/highlighter.js +7 -7
  112. package/dist/lib/install.d.ts +19 -19
  113. package/dist/lib/install.js +101 -55
  114. package/dist/lib/install.js.map +1 -1
  115. package/dist/lib/lockfile.d.ts +63 -63
  116. package/dist/lib/lockfile.js +179 -173
  117. package/dist/lib/lockfile.js.map +1 -1
  118. package/dist/lib/logger.d.ts +8 -8
  119. package/dist/lib/logger.js +41 -41
  120. package/dist/lib/logger.js.map +1 -1
  121. package/dist/lib/paths.d.ts +14 -14
  122. package/dist/lib/paths.js +41 -31
  123. package/dist/lib/paths.js.map +1 -1
  124. package/dist/lib/registry.d.ts +35 -35
  125. package/dist/lib/registry.js +180 -180
  126. package/dist/schema/index.d.ts +1128 -1128
  127. package/dist/schema/index.js +237 -238
  128. package/dist/schema/index.js.map +1 -1
  129. package/dist/styles/create-style-map.d.ts +4 -4
  130. package/dist/styles/create-style-map.js +68 -68
  131. package/dist/styles/transform-style-map.d.ts +3 -3
  132. package/dist/styles/transform-style-map.js +428 -428
  133. package/dist/styles/transform.d.ts +10 -10
  134. package/dist/styles/transform.js +15 -15
  135. package/dist/utils/index.d.ts +6 -6
  136. package/dist/utils/index.js +5 -5
  137. package/dist/utils/transformers/transform-icons.d.ts +2 -2
  138. package/dist/utils/transformers/transform-icons.js +164 -164
  139. package/dist/utils/transformers/transform-menu.d.ts +2 -2
  140. package/dist/utils/transformers/transform-menu.js +39 -39
  141. package/dist/utils/transformers/transform-render.d.ts +2 -2
  142. package/dist/utils/transformers/transform-render.js +97 -97
  143. package/dist/utils/transformers/types.d.ts +14 -14
  144. package/dist/utils/transformers/types.js +1 -1
  145. package/package.json +69 -69
  146. package/dist/__tests__/contracts/registry.test.d.ts +0 -1
  147. package/dist/__tests__/contracts/registry.test.js +0 -42
  148. package/dist/__tests__/contracts/registry.test.js.map +0 -1
  149. package/dist/__tests__/e2e/cli.test.d.ts +0 -1
  150. package/dist/__tests__/e2e/cli.test.js +0 -67
  151. package/dist/__tests__/e2e/cli.test.js.map +0 -1
  152. package/dist/__tests__/helpers/fs.d.ts +0 -5
  153. package/dist/__tests__/helpers/fs.js +0 -26
  154. package/dist/__tests__/helpers/fs.js.map +0 -1
  155. package/dist/__tests__/integration/commands.integration.test.d.ts +0 -1
  156. package/dist/__tests__/integration/commands.integration.test.js +0 -184
  157. package/dist/__tests__/integration/commands.integration.test.js.map +0 -1
  158. package/dist/commands/__tests__/add-composite.test.d.ts +0 -2
  159. package/dist/commands/__tests__/add-composite.test.js +0 -171
  160. package/dist/commands/__tests__/add-composite.test.js.map +0 -1
  161. package/dist/commands/__tests__/add-entry.mocks.d.ts +0 -23
  162. package/dist/commands/__tests__/add-entry.mocks.js +0 -64
  163. package/dist/commands/__tests__/add-entry.mocks.js.map +0 -1
  164. package/dist/commands/__tests__/add-section.test.d.ts +0 -2
  165. package/dist/commands/__tests__/add-section.test.js +0 -191
  166. package/dist/commands/__tests__/add-section.test.js.map +0 -1
  167. package/dist/commands/__tests__/add-wrapper.test.d.ts +0 -2
  168. package/dist/commands/__tests__/add-wrapper.test.js +0 -171
  169. package/dist/commands/__tests__/add-wrapper.test.js.map +0 -1
  170. package/dist/commands/__tests__/cli-mocks.d.ts +0 -1
  171. package/dist/commands/__tests__/cli-mocks.js +0 -24
  172. package/dist/commands/__tests__/cli-mocks.js.map +0 -1
  173. package/dist/commands/__tests__/doctor.mocks.d.ts +0 -6
  174. package/dist/commands/__tests__/doctor.mocks.js +0 -20
  175. package/dist/commands/__tests__/doctor.mocks.js.map +0 -1
  176. package/dist/commands/__tests__/doctor.test.d.ts +0 -2
  177. package/dist/commands/__tests__/doctor.test.js +0 -80
  178. package/dist/commands/__tests__/doctor.test.js.map +0 -1
  179. package/dist/commands/__tests__/list.mocks.d.ts +0 -8
  180. package/dist/commands/__tests__/list.mocks.js +0 -20
  181. package/dist/commands/__tests__/list.mocks.js.map +0 -1
  182. package/dist/commands/__tests__/list.test.d.ts +0 -2
  183. package/dist/commands/__tests__/list.test.js +0 -60
  184. package/dist/commands/__tests__/list.test.js.map +0 -1
  185. package/dist/commands/__tests__/remove.mocks.d.ts +0 -9
  186. package/dist/commands/__tests__/remove.mocks.js +0 -26
  187. package/dist/commands/__tests__/remove.mocks.js.map +0 -1
  188. package/dist/commands/__tests__/remove.test.d.ts +0 -2
  189. package/dist/commands/__tests__/remove.test.js +0 -116
  190. package/dist/commands/__tests__/remove.test.js.map +0 -1
  191. package/dist/commands/add/__tests__/__mocks__/cli-mocks.d.ts +0 -1
  192. package/dist/commands/add/__tests__/__mocks__/cli-mocks.js +0 -21
  193. package/dist/commands/add/__tests__/__mocks__/cli-mocks.js.map +0 -1
  194. package/dist/commands/add/__tests__/add.mocks.d.ts +0 -19
  195. package/dist/commands/add/__tests__/add.mocks.js +0 -60
  196. package/dist/commands/add/__tests__/add.mocks.js.map +0 -1
  197. package/dist/commands/add/__tests__/add.test.d.ts +0 -2
  198. package/dist/commands/add/__tests__/add.test.js +0 -141
  199. package/dist/commands/add/__tests__/add.test.js.map +0 -1
  200. package/dist/commands/init/__tests__/init.mocks.d.ts +0 -24
  201. package/dist/commands/init/__tests__/init.mocks.js +0 -84
  202. package/dist/commands/init/__tests__/init.mocks.js.map +0 -1
  203. package/dist/commands/init/__tests__/init.test.d.ts +0 -2
  204. package/dist/commands/init/__tests__/init.test.js +0 -283
  205. package/dist/commands/init/__tests__/init.test.js.map +0 -1
  206. package/dist/commands/init/__tests__/tailwind.test.d.ts +0 -1
  207. package/dist/commands/init/__tests__/tailwind.test.js +0 -56
  208. package/dist/commands/init/__tests__/tailwind.test.js.map +0 -1
  209. package/dist/commands/init/__tests__/tsconfig.test.d.ts +0 -1
  210. package/dist/commands/init/__tests__/tsconfig.test.js +0 -108
  211. package/dist/commands/init/__tests__/tsconfig.test.js.map +0 -1
  212. package/dist/commands/init/__tests__/vite.test.d.ts +0 -1
  213. package/dist/commands/init/__tests__/vite.test.js +0 -66
  214. package/dist/commands/init/__tests__/vite.test.js.map +0 -1
  215. package/dist/commands/list-sections.d.ts +0 -2
  216. package/dist/commands/list-sections.js +0 -20
  217. package/dist/commands/list-sections.js.map +0 -1
  218. package/dist/commands/list-wrappers.d.ts +0 -2
  219. package/dist/commands/list-wrappers.js +0 -20
  220. package/dist/commands/list-wrappers.js.map +0 -1
  221. package/dist/commands/remove-section.d.ts +0 -2
  222. package/dist/commands/remove-section.js +0 -37
  223. package/dist/commands/remove-section.js.map +0 -1
  224. package/dist/commands/remove-wrapper.d.ts +0 -2
  225. package/dist/commands/remove-wrapper.js +0 -37
  226. package/dist/commands/remove-wrapper.js.map +0 -1
  227. package/dist/lib/__tests__/config.test.d.ts +0 -1
  228. package/dist/lib/__tests__/config.test.js +0 -49
  229. package/dist/lib/__tests__/config.test.js.map +0 -1
  230. package/dist/lib/__tests__/install.test.d.ts +0 -1
  231. package/dist/lib/__tests__/install.test.js +0 -149
  232. package/dist/lib/__tests__/install.test.js.map +0 -1
  233. package/dist/lib/__tests__/lockfile.test.d.ts +0 -1
  234. package/dist/lib/__tests__/lockfile.test.js +0 -89
  235. package/dist/lib/__tests__/lockfile.test.js.map +0 -1
  236. package/dist/lib/__tests__/paths.test.d.ts +0 -1
  237. package/dist/lib/__tests__/paths.test.js +0 -39
  238. package/dist/lib/__tests__/paths.test.js.map +0 -1
  239. package/dist/lib/__tests__/registry.test.d.ts +0 -1
  240. package/dist/lib/__tests__/registry.test.js +0 -76
  241. package/dist/lib/__tests__/registry.test.js.map +0 -1
@@ -1,429 +1,429 @@
1
- import { Node, } from "ts-morph";
2
- /**
3
- * Classes that should never be removed during transformation.
4
- * These are typically used as CSS selectors or for other purposes
5
- * that require the class name to remain in the code.
6
- */
7
- const ALLOWLIST = new Set(["cn-menu-target"]);
8
- function isStringLiteralLike(node) {
9
- return (Node.isStringLiteral(node) || Node.isNoSubstitutionTemplateLiteral(node));
10
- }
11
- export const transformStyleMap = async ({ sourceFile, styleMap, }) => {
12
- const matchedClasses = new Set();
13
- applyToCvaCalls(sourceFile, styleMap, matchedClasses);
14
- applyToClassNameAttributes(sourceFile, styleMap, matchedClasses);
15
- applyToMergePropsCalls(sourceFile, styleMap, matchedClasses);
16
- return sourceFile;
17
- };
18
- function applyStyleToCvaString(stringNode, styleMap, matchedClasses) {
19
- const stringValue = stringNode.getLiteralText();
20
- const cnClasses = extractCnClasses(stringValue);
21
- if (cnClasses.length === 0) {
22
- return;
23
- }
24
- // Process all cn-* classes, not just the first one
25
- const unmatchedClasses = cnClasses.filter((cnClass) => !matchedClasses.has(cnClass));
26
- if (unmatchedClasses.length === 0) {
27
- // All classes already matched, just clean up non-allowlisted ones
28
- const updated = removeCnClasses(stringValue);
29
- stringNode.setLiteralValue(updated);
30
- return;
31
- }
32
- const tailwindClassesToApply = unmatchedClasses
33
- .map((cnClass) => styleMap[cnClass])
34
- .filter((classes) => Boolean(classes));
35
- if (tailwindClassesToApply.length > 0) {
36
- const mergedClasses = tailwindClassesToApply.join(" ");
37
- const updated = removeCnClasses(mergeClasses(mergedClasses, stringValue));
38
- stringNode.setLiteralValue(updated);
39
- unmatchedClasses.forEach((cnClass) => matchedClasses.add(cnClass));
40
- }
41
- else {
42
- // No styles to apply, but still need to clean up non-allowlisted classes
43
- const updated = removeCnClasses(stringValue);
44
- stringNode.setLiteralValue(updated);
45
- }
46
- }
47
- function applyToCvaCalls(sourceFile, styleMap, matchedClasses) {
48
- sourceFile.forEachDescendant((node) => {
49
- if (!Node.isCallExpression(node)) {
50
- return;
51
- }
52
- const expression = node.getExpression();
53
- if (!Node.isIdentifier(expression) || expression.getText() !== "cva") {
54
- return;
55
- }
56
- const baseArg = node.getArguments()[0];
57
- if (Node.isStringLiteral(baseArg)) {
58
- applyStyleToCvaString(baseArg, styleMap, matchedClasses);
59
- }
60
- const configArg = node.getArguments()[1];
61
- if (!configArg || !Node.isObjectLiteralExpression(configArg)) {
62
- return;
63
- }
64
- const variantsProp = configArg
65
- .getProperties()
66
- .find((prop) => Node.isPropertyAssignment(prop) &&
67
- Node.isIdentifier(prop.getNameNode()) &&
68
- prop.getNameNode().getText() === "variants");
69
- if (!variantsProp || !Node.isPropertyAssignment(variantsProp)) {
70
- return;
71
- }
72
- const variantsObj = variantsProp.getInitializer();
73
- if (!variantsObj || !Node.isObjectLiteralExpression(variantsObj)) {
74
- return;
75
- }
76
- variantsObj.getProperties().forEach((typeProp) => {
77
- if (!Node.isPropertyAssignment(typeProp)) {
78
- return;
79
- }
80
- const typeObj = typeProp.getInitializer();
81
- if (!typeObj || !Node.isObjectLiteralExpression(typeObj)) {
82
- return;
83
- }
84
- typeObj.getProperties().forEach((variantProp) => {
85
- if (!Node.isPropertyAssignment(variantProp)) {
86
- return;
87
- }
88
- const variantValue = variantProp.getInitializer();
89
- if (variantValue && Node.isStringLiteral(variantValue)) {
90
- applyStyleToCvaString(variantValue, styleMap, matchedClasses);
91
- }
92
- });
93
- });
94
- });
95
- }
96
- function applyToClassNameAttributes(sourceFile, styleMap, matchedClasses) {
97
- sourceFile.forEachDescendant((node) => {
98
- if (!Node.isJsxAttribute(node) ||
99
- node.getNameNode().getText() !== "className") {
100
- return;
101
- }
102
- const initializer = node.getInitializer();
103
- if (!initializer) {
104
- return;
105
- }
106
- const cnClasses = extractCnClassesFromAttribute(initializer);
107
- if (cnClasses.length === 0) {
108
- return;
109
- }
110
- const jsxElement = node.getParent()?.getParent();
111
- if (!jsxElement ||
112
- (!Node.isJsxOpeningElement(jsxElement) &&
113
- !Node.isJsxSelfClosingElement(jsxElement))) {
114
- return;
115
- }
116
- const unmatchedClasses = cnClasses.filter((cnClass) => !matchedClasses.has(cnClass));
117
- if (unmatchedClasses.length === 0) {
118
- // Even if all classes are already matched, we still need to clean them up
119
- cleanCnClassesFromAttribute(initializer);
120
- return;
121
- }
122
- const tailwindClassesToApply = unmatchedClasses
123
- .map((cnClass) => styleMap[cnClass])
124
- .filter((classes) => Boolean(classes));
125
- if (tailwindClassesToApply.length > 0) {
126
- const mergedClasses = tailwindClassesToApply.join(" ");
127
- applyClassesToElement(jsxElement, mergedClasses);
128
- }
129
- else {
130
- cleanCnClassesFromAttribute(initializer);
131
- }
132
- });
133
- }
134
- function extractCnClassesFromAttribute(initializer) {
135
- const classes = [];
136
- if (isStringLiteralLike(initializer)) {
137
- return extractCnClasses(initializer.getLiteralText());
138
- }
139
- if (!Node.isJsxExpression(initializer)) {
140
- return classes;
141
- }
142
- const expression = initializer.getExpression();
143
- if (!expression) {
144
- return classes;
145
- }
146
- if (isStringLiteralLike(expression)) {
147
- return extractCnClasses(expression.getLiteralText());
148
- }
149
- if (Node.isCallExpression(expression) && isCnCall(expression)) {
150
- for (const argument of expression.getArguments()) {
151
- if (isStringLiteralLike(argument)) {
152
- classes.push(...extractCnClasses(argument.getLiteralText()));
153
- }
154
- }
155
- }
156
- return classes;
157
- }
158
- function cleanCnClassesFromAttribute(initializer) {
159
- if (isStringLiteralLike(initializer)) {
160
- const cleaned = removeCnClasses(initializer.getLiteralText());
161
- initializer.setLiteralValue(cleaned);
162
- return;
163
- }
164
- if (!Node.isJsxExpression(initializer)) {
165
- return;
166
- }
167
- const expression = initializer.getExpression();
168
- if (!expression) {
169
- return;
170
- }
171
- if (isStringLiteralLike(expression)) {
172
- const cleaned = removeCnClasses(expression.getLiteralText());
173
- expression.setLiteralValue(cleaned);
174
- return;
175
- }
176
- if (Node.isCallExpression(expression) && isCnCall(expression)) {
177
- for (const argument of expression.getArguments()) {
178
- if (isStringLiteralLike(argument)) {
179
- const cleaned = removeCnClasses(argument.getLiteralText());
180
- argument.setLiteralValue(cleaned);
181
- }
182
- }
183
- removeEmptyArgumentsFromCnCall(expression);
184
- }
185
- }
186
- function extractCnClasses(str) {
187
- const matches = str.matchAll(/\bcn-[\w-]+\b/g);
188
- return Array.from(matches, (match) => match[0]);
189
- }
190
- function extractCnClass(str) {
191
- const classes = extractCnClasses(str);
192
- return classes[0] ?? null;
193
- }
194
- function removeCnClasses(str) {
195
- return str
196
- .replace(/\bcn-[\w-]+\b/g, (match) => {
197
- // Preserve allowlisted classes
198
- if (ALLOWLIST.has(match)) {
199
- return match;
200
- }
201
- return "";
202
- })
203
- .replace(/\s+/g, " ")
204
- .trim();
205
- }
206
- function removeEmptyArgumentsFromCnCall(callExpression) {
207
- if (!isCnCall(callExpression)) {
208
- return;
209
- }
210
- const args = callExpression.getArguments();
211
- const nonEmptyArgs = args.filter((arg) => {
212
- if (isStringLiteralLike(arg)) {
213
- const text = arg.getLiteralText().trim();
214
- return text !== "";
215
- }
216
- return true;
217
- });
218
- if (nonEmptyArgs.length !== args.length) {
219
- const argTexts = nonEmptyArgs.map((arg) => arg.getText());
220
- const parent = callExpression.getParent();
221
- if (parent && Node.isJsxExpression(parent)) {
222
- parent.replaceWithText(`{cn(${argTexts.join(", ")})}`);
223
- }
224
- else {
225
- callExpression.replaceWithText(`cn(${argTexts.join(", ")})`);
226
- }
227
- }
228
- }
229
- function applyClassesToElement(element, tailwindClasses) {
230
- if (!Node.isJsxOpeningElement(element) &&
231
- !Node.isJsxSelfClosingElement(element)) {
232
- return;
233
- }
234
- const attribute = element
235
- .getAttributes()
236
- .find((attr) => Node.isJsxAttribute(attr) &&
237
- attr.getNameNode().getText() === "className");
238
- if (!attribute || !Node.isJsxAttribute(attribute)) {
239
- element.addAttribute({
240
- name: "className",
241
- initializer: `{cn(${JSON.stringify(tailwindClasses)})}`,
242
- });
243
- return;
244
- }
245
- const initializer = attribute.getInitializer();
246
- if (!initializer) {
247
- attribute.setInitializer(`{cn(${JSON.stringify(tailwindClasses)})}`);
248
- return;
249
- }
250
- if (isStringLiteralLike(initializer)) {
251
- const existing = initializer.getLiteralText();
252
- const updated = removeCnClasses(mergeClasses(tailwindClasses, existing));
253
- initializer.setLiteralValue(updated);
254
- return;
255
- }
256
- if (!Node.isJsxExpression(initializer)) {
257
- return;
258
- }
259
- const expression = initializer.getExpression();
260
- if (!expression) {
261
- attribute.setInitializer(`{cn(${JSON.stringify(tailwindClasses)})}`);
262
- return;
263
- }
264
- if (isStringLiteralLike(expression)) {
265
- const existing = expression.getLiteralText();
266
- const updated = removeCnClasses(mergeClasses(tailwindClasses, existing));
267
- expression.setLiteralValue(updated);
268
- return;
269
- }
270
- if (Node.isCallExpression(expression) && isCnCall(expression)) {
271
- const firstArg = expression.getArguments()[0];
272
- if (isStringLiteralLike(firstArg)) {
273
- const existing = firstArg.getLiteralText();
274
- const updated = removeCnClasses(mergeClasses(tailwindClasses, existing));
275
- firstArg.setLiteralValue(updated);
276
- for (let i = 1; i < expression.getArguments().length; i++) {
277
- const arg = expression.getArguments()[i];
278
- if (isStringLiteralLike(arg)) {
279
- const argText = arg.getLiteralText();
280
- const cleaned = removeCnClasses(argText);
281
- if (cleaned !== argText) {
282
- arg.setLiteralValue(cleaned);
283
- }
284
- }
285
- }
286
- removeEmptyArgumentsFromCnCall(expression);
287
- return;
288
- }
289
- const argumentTexts = expression
290
- .getArguments()
291
- .map((argument) => {
292
- if (isStringLiteralLike(argument)) {
293
- const cleaned = removeCnClasses(argument.getLiteralText());
294
- return cleaned ? JSON.stringify(cleaned) : null;
295
- }
296
- return argument.getText();
297
- })
298
- .filter((arg) => arg !== null);
299
- const updatedArguments = [JSON.stringify(tailwindClasses), ...argumentTexts];
300
- attribute.setInitializer(`{cn(${updatedArguments.join(", ")})}`);
301
- return;
302
- }
303
- attribute.setInitializer(`{cn(${JSON.stringify(tailwindClasses)}, ${expression.getText()})}`);
304
- }
305
- function mergeClasses(newClasses, existing) {
306
- const existingParts = existing.split(/\s+/).filter(Boolean);
307
- const newParts = newClasses.split(/\s+/).filter(Boolean);
308
- const combined = [...newParts, ...existingParts];
309
- return combined.join(" ").trim();
310
- }
311
- function isCnCall(call) {
312
- const expression = call.getExpression();
313
- return Node.isIdentifier(expression) && expression.getText() === "cn";
314
- }
315
- function applyToMergePropsCalls(sourceFile, styleMap, matchedClasses) {
316
- sourceFile.forEachDescendant((node) => {
317
- if (!Node.isCallExpression(node)) {
318
- return;
319
- }
320
- const expression = node.getExpression();
321
- if (!Node.isIdentifier(expression) ||
322
- expression.getText() !== "mergeProps") {
323
- return;
324
- }
325
- // Look for object literals in mergeProps arguments
326
- for (const arg of node.getArguments()) {
327
- if (!Node.isObjectLiteralExpression(arg)) {
328
- continue;
329
- }
330
- // Find className property in the object literal
331
- const classNameProp = arg
332
- .getProperties()
333
- .find((prop) => Node.isPropertyAssignment(prop) &&
334
- Node.isIdentifier(prop.getNameNode()) &&
335
- prop.getNameNode().getText() === "className");
336
- if (!classNameProp || !Node.isPropertyAssignment(classNameProp)) {
337
- continue;
338
- }
339
- const classNameInitializer = classNameProp.getInitializer();
340
- if (!classNameInitializer) {
341
- continue;
342
- }
343
- // Handle cn() calls in className
344
- if (Node.isCallExpression(classNameInitializer) &&
345
- isCnCall(classNameInitializer)) {
346
- const cnClasses = extractCnClassesFromCnCall(classNameInitializer);
347
- if (cnClasses.length === 0) {
348
- continue;
349
- }
350
- const unmatchedClasses = cnClasses.filter((cnClass) => !matchedClasses.has(cnClass));
351
- if (unmatchedClasses.length === 0) {
352
- // Clean up cn-* classes even if already matched
353
- cleanCnClassesFromCnCall(classNameInitializer);
354
- continue;
355
- }
356
- const tailwindClassesToApply = unmatchedClasses
357
- .map((cnClass) => styleMap[cnClass])
358
- .filter((classes) => Boolean(classes));
359
- if (tailwindClassesToApply.length > 0) {
360
- const mergedClasses = tailwindClassesToApply.join(" ");
361
- applyClassesToCnCall(classNameInitializer, mergedClasses, matchedClasses, unmatchedClasses);
362
- }
363
- else {
364
- cleanCnClassesFromCnCall(classNameInitializer);
365
- }
366
- }
367
- }
368
- });
369
- }
370
- function extractCnClassesFromCnCall(cnCall) {
371
- const classes = [];
372
- for (const argument of cnCall.getArguments()) {
373
- if (isStringLiteralLike(argument)) {
374
- classes.push(...extractCnClasses(argument.getLiteralText()));
375
- }
376
- }
377
- return classes;
378
- }
379
- function cleanCnClassesFromCnCall(cnCall) {
380
- for (const argument of cnCall.getArguments()) {
381
- if (isStringLiteralLike(argument)) {
382
- const cleaned = removeCnClasses(argument.getLiteralText());
383
- argument.setLiteralValue(cleaned);
384
- }
385
- }
386
- removeEmptyArgumentsFromCnCall(cnCall);
387
- }
388
- function applyClassesToCnCall(cnCall, tailwindClasses, matchedClasses, unmatchedClasses) {
389
- const firstArg = cnCall.getArguments()[0];
390
- if (isStringLiteralLike(firstArg)) {
391
- const existing = firstArg.getLiteralText();
392
- const updated = removeCnClasses(mergeClasses(tailwindClasses, existing));
393
- firstArg.setLiteralValue(updated);
394
- // Mark classes as matched
395
- unmatchedClasses.forEach((cnClass) => matchedClasses.add(cnClass));
396
- // Clean up cn-* classes from remaining arguments
397
- for (let i = 1; i < cnCall.getArguments().length; i++) {
398
- const arg = cnCall.getArguments()[i];
399
- if (isStringLiteralLike(arg)) {
400
- const argText = arg.getLiteralText();
401
- const cleaned = removeCnClasses(argText);
402
- if (cleaned !== argText) {
403
- arg.setLiteralValue(cleaned);
404
- }
405
- }
406
- }
407
- removeEmptyArgumentsFromCnCall(cnCall);
408
- return;
409
- }
410
- // If first arg is not a string literal, prepend tailwind classes
411
- const argumentTexts = cnCall
412
- .getArguments()
413
- .map((argument) => {
414
- if (isStringLiteralLike(argument)) {
415
- const cleaned = removeCnClasses(argument.getLiteralText());
416
- return cleaned ? JSON.stringify(cleaned) : null;
417
- }
418
- return argument.getText();
419
- })
420
- .filter((arg) => arg !== null);
421
- const updatedArguments = [JSON.stringify(tailwindClasses), ...argumentTexts];
422
- // Mark classes as matched
423
- unmatchedClasses.forEach((cnClass) => matchedClasses.add(cnClass));
424
- const parent = cnCall.getParent();
425
- if (parent) {
426
- cnCall.replaceWithText(`cn(${updatedArguments.join(", ")})`);
427
- }
428
- }
1
+ import { Node, } from "ts-morph";
2
+ /**
3
+ * Classes that should never be removed during transformation.
4
+ * These are typically used as CSS selectors or for other purposes
5
+ * that require the class name to remain in the code.
6
+ */
7
+ const ALLOWLIST = new Set(["cn-menu-target"]);
8
+ function isStringLiteralLike(node) {
9
+ return (Node.isStringLiteral(node) || Node.isNoSubstitutionTemplateLiteral(node));
10
+ }
11
+ export const transformStyleMap = async ({ sourceFile, styleMap, }) => {
12
+ const matchedClasses = new Set();
13
+ applyToCvaCalls(sourceFile, styleMap, matchedClasses);
14
+ applyToClassNameAttributes(sourceFile, styleMap, matchedClasses);
15
+ applyToMergePropsCalls(sourceFile, styleMap, matchedClasses);
16
+ return sourceFile;
17
+ };
18
+ function applyStyleToCvaString(stringNode, styleMap, matchedClasses) {
19
+ const stringValue = stringNode.getLiteralText();
20
+ const cnClasses = extractCnClasses(stringValue);
21
+ if (cnClasses.length === 0) {
22
+ return;
23
+ }
24
+ // Process all cn-* classes, not just the first one
25
+ const unmatchedClasses = cnClasses.filter((cnClass) => !matchedClasses.has(cnClass));
26
+ if (unmatchedClasses.length === 0) {
27
+ // All classes already matched, just clean up non-allowlisted ones
28
+ const updated = removeCnClasses(stringValue);
29
+ stringNode.setLiteralValue(updated);
30
+ return;
31
+ }
32
+ const tailwindClassesToApply = unmatchedClasses
33
+ .map((cnClass) => styleMap[cnClass])
34
+ .filter((classes) => Boolean(classes));
35
+ if (tailwindClassesToApply.length > 0) {
36
+ const mergedClasses = tailwindClassesToApply.join(" ");
37
+ const updated = removeCnClasses(mergeClasses(mergedClasses, stringValue));
38
+ stringNode.setLiteralValue(updated);
39
+ unmatchedClasses.forEach((cnClass) => matchedClasses.add(cnClass));
40
+ }
41
+ else {
42
+ // No styles to apply, but still need to clean up non-allowlisted classes
43
+ const updated = removeCnClasses(stringValue);
44
+ stringNode.setLiteralValue(updated);
45
+ }
46
+ }
47
+ function applyToCvaCalls(sourceFile, styleMap, matchedClasses) {
48
+ sourceFile.forEachDescendant((node) => {
49
+ if (!Node.isCallExpression(node)) {
50
+ return;
51
+ }
52
+ const expression = node.getExpression();
53
+ if (!Node.isIdentifier(expression) || expression.getText() !== "cva") {
54
+ return;
55
+ }
56
+ const baseArg = node.getArguments()[0];
57
+ if (Node.isStringLiteral(baseArg)) {
58
+ applyStyleToCvaString(baseArg, styleMap, matchedClasses);
59
+ }
60
+ const configArg = node.getArguments()[1];
61
+ if (!configArg || !Node.isObjectLiteralExpression(configArg)) {
62
+ return;
63
+ }
64
+ const variantsProp = configArg
65
+ .getProperties()
66
+ .find((prop) => Node.isPropertyAssignment(prop) &&
67
+ Node.isIdentifier(prop.getNameNode()) &&
68
+ prop.getNameNode().getText() === "variants");
69
+ if (!variantsProp || !Node.isPropertyAssignment(variantsProp)) {
70
+ return;
71
+ }
72
+ const variantsObj = variantsProp.getInitializer();
73
+ if (!variantsObj || !Node.isObjectLiteralExpression(variantsObj)) {
74
+ return;
75
+ }
76
+ variantsObj.getProperties().forEach((typeProp) => {
77
+ if (!Node.isPropertyAssignment(typeProp)) {
78
+ return;
79
+ }
80
+ const typeObj = typeProp.getInitializer();
81
+ if (!typeObj || !Node.isObjectLiteralExpression(typeObj)) {
82
+ return;
83
+ }
84
+ typeObj.getProperties().forEach((variantProp) => {
85
+ if (!Node.isPropertyAssignment(variantProp)) {
86
+ return;
87
+ }
88
+ const variantValue = variantProp.getInitializer();
89
+ if (variantValue && Node.isStringLiteral(variantValue)) {
90
+ applyStyleToCvaString(variantValue, styleMap, matchedClasses);
91
+ }
92
+ });
93
+ });
94
+ });
95
+ }
96
+ function applyToClassNameAttributes(sourceFile, styleMap, matchedClasses) {
97
+ sourceFile.forEachDescendant((node) => {
98
+ if (!Node.isJsxAttribute(node) ||
99
+ node.getNameNode().getText() !== "className") {
100
+ return;
101
+ }
102
+ const initializer = node.getInitializer();
103
+ if (!initializer) {
104
+ return;
105
+ }
106
+ const cnClasses = extractCnClassesFromAttribute(initializer);
107
+ if (cnClasses.length === 0) {
108
+ return;
109
+ }
110
+ const jsxElement = node.getParent()?.getParent();
111
+ if (!jsxElement ||
112
+ (!Node.isJsxOpeningElement(jsxElement) &&
113
+ !Node.isJsxSelfClosingElement(jsxElement))) {
114
+ return;
115
+ }
116
+ const unmatchedClasses = cnClasses.filter((cnClass) => !matchedClasses.has(cnClass));
117
+ if (unmatchedClasses.length === 0) {
118
+ // Even if all classes are already matched, we still need to clean them up
119
+ cleanCnClassesFromAttribute(initializer);
120
+ return;
121
+ }
122
+ const tailwindClassesToApply = unmatchedClasses
123
+ .map((cnClass) => styleMap[cnClass])
124
+ .filter((classes) => Boolean(classes));
125
+ if (tailwindClassesToApply.length > 0) {
126
+ const mergedClasses = tailwindClassesToApply.join(" ");
127
+ applyClassesToElement(jsxElement, mergedClasses);
128
+ }
129
+ else {
130
+ cleanCnClassesFromAttribute(initializer);
131
+ }
132
+ });
133
+ }
134
+ function extractCnClassesFromAttribute(initializer) {
135
+ const classes = [];
136
+ if (isStringLiteralLike(initializer)) {
137
+ return extractCnClasses(initializer.getLiteralText());
138
+ }
139
+ if (!Node.isJsxExpression(initializer)) {
140
+ return classes;
141
+ }
142
+ const expression = initializer.getExpression();
143
+ if (!expression) {
144
+ return classes;
145
+ }
146
+ if (isStringLiteralLike(expression)) {
147
+ return extractCnClasses(expression.getLiteralText());
148
+ }
149
+ if (Node.isCallExpression(expression) && isCnCall(expression)) {
150
+ for (const argument of expression.getArguments()) {
151
+ if (isStringLiteralLike(argument)) {
152
+ classes.push(...extractCnClasses(argument.getLiteralText()));
153
+ }
154
+ }
155
+ }
156
+ return classes;
157
+ }
158
+ function cleanCnClassesFromAttribute(initializer) {
159
+ if (isStringLiteralLike(initializer)) {
160
+ const cleaned = removeCnClasses(initializer.getLiteralText());
161
+ initializer.setLiteralValue(cleaned);
162
+ return;
163
+ }
164
+ if (!Node.isJsxExpression(initializer)) {
165
+ return;
166
+ }
167
+ const expression = initializer.getExpression();
168
+ if (!expression) {
169
+ return;
170
+ }
171
+ if (isStringLiteralLike(expression)) {
172
+ const cleaned = removeCnClasses(expression.getLiteralText());
173
+ expression.setLiteralValue(cleaned);
174
+ return;
175
+ }
176
+ if (Node.isCallExpression(expression) && isCnCall(expression)) {
177
+ for (const argument of expression.getArguments()) {
178
+ if (isStringLiteralLike(argument)) {
179
+ const cleaned = removeCnClasses(argument.getLiteralText());
180
+ argument.setLiteralValue(cleaned);
181
+ }
182
+ }
183
+ removeEmptyArgumentsFromCnCall(expression);
184
+ }
185
+ }
186
+ function extractCnClasses(str) {
187
+ const matches = str.matchAll(/\bcn-[\w-]+\b/g);
188
+ return Array.from(matches, (match) => match[0]);
189
+ }
190
+ function extractCnClass(str) {
191
+ const classes = extractCnClasses(str);
192
+ return classes[0] ?? null;
193
+ }
194
+ function removeCnClasses(str) {
195
+ return str
196
+ .replace(/\bcn-[\w-]+\b/g, (match) => {
197
+ // Preserve allowlisted classes
198
+ if (ALLOWLIST.has(match)) {
199
+ return match;
200
+ }
201
+ return "";
202
+ })
203
+ .replace(/\s+/g, " ")
204
+ .trim();
205
+ }
206
+ function removeEmptyArgumentsFromCnCall(callExpression) {
207
+ if (!isCnCall(callExpression)) {
208
+ return;
209
+ }
210
+ const args = callExpression.getArguments();
211
+ const nonEmptyArgs = args.filter((arg) => {
212
+ if (isStringLiteralLike(arg)) {
213
+ const text = arg.getLiteralText().trim();
214
+ return text !== "";
215
+ }
216
+ return true;
217
+ });
218
+ if (nonEmptyArgs.length !== args.length) {
219
+ const argTexts = nonEmptyArgs.map((arg) => arg.getText());
220
+ const parent = callExpression.getParent();
221
+ if (parent && Node.isJsxExpression(parent)) {
222
+ parent.replaceWithText(`{cn(${argTexts.join(", ")})}`);
223
+ }
224
+ else {
225
+ callExpression.replaceWithText(`cn(${argTexts.join(", ")})`);
226
+ }
227
+ }
228
+ }
229
+ function applyClassesToElement(element, tailwindClasses) {
230
+ if (!Node.isJsxOpeningElement(element) &&
231
+ !Node.isJsxSelfClosingElement(element)) {
232
+ return;
233
+ }
234
+ const attribute = element
235
+ .getAttributes()
236
+ .find((attr) => Node.isJsxAttribute(attr) &&
237
+ attr.getNameNode().getText() === "className");
238
+ if (!attribute || !Node.isJsxAttribute(attribute)) {
239
+ element.addAttribute({
240
+ name: "className",
241
+ initializer: `{cn(${JSON.stringify(tailwindClasses)})}`,
242
+ });
243
+ return;
244
+ }
245
+ const initializer = attribute.getInitializer();
246
+ if (!initializer) {
247
+ attribute.setInitializer(`{cn(${JSON.stringify(tailwindClasses)})}`);
248
+ return;
249
+ }
250
+ if (isStringLiteralLike(initializer)) {
251
+ const existing = initializer.getLiteralText();
252
+ const updated = removeCnClasses(mergeClasses(tailwindClasses, existing));
253
+ initializer.setLiteralValue(updated);
254
+ return;
255
+ }
256
+ if (!Node.isJsxExpression(initializer)) {
257
+ return;
258
+ }
259
+ const expression = initializer.getExpression();
260
+ if (!expression) {
261
+ attribute.setInitializer(`{cn(${JSON.stringify(tailwindClasses)})}`);
262
+ return;
263
+ }
264
+ if (isStringLiteralLike(expression)) {
265
+ const existing = expression.getLiteralText();
266
+ const updated = removeCnClasses(mergeClasses(tailwindClasses, existing));
267
+ expression.setLiteralValue(updated);
268
+ return;
269
+ }
270
+ if (Node.isCallExpression(expression) && isCnCall(expression)) {
271
+ const firstArg = expression.getArguments()[0];
272
+ if (isStringLiteralLike(firstArg)) {
273
+ const existing = firstArg.getLiteralText();
274
+ const updated = removeCnClasses(mergeClasses(tailwindClasses, existing));
275
+ firstArg.setLiteralValue(updated);
276
+ for (let i = 1; i < expression.getArguments().length; i++) {
277
+ const arg = expression.getArguments()[i];
278
+ if (isStringLiteralLike(arg)) {
279
+ const argText = arg.getLiteralText();
280
+ const cleaned = removeCnClasses(argText);
281
+ if (cleaned !== argText) {
282
+ arg.setLiteralValue(cleaned);
283
+ }
284
+ }
285
+ }
286
+ removeEmptyArgumentsFromCnCall(expression);
287
+ return;
288
+ }
289
+ const argumentTexts = expression
290
+ .getArguments()
291
+ .map((argument) => {
292
+ if (isStringLiteralLike(argument)) {
293
+ const cleaned = removeCnClasses(argument.getLiteralText());
294
+ return cleaned ? JSON.stringify(cleaned) : null;
295
+ }
296
+ return argument.getText();
297
+ })
298
+ .filter((arg) => arg !== null);
299
+ const updatedArguments = [JSON.stringify(tailwindClasses), ...argumentTexts];
300
+ attribute.setInitializer(`{cn(${updatedArguments.join(", ")})}`);
301
+ return;
302
+ }
303
+ attribute.setInitializer(`{cn(${JSON.stringify(tailwindClasses)}, ${expression.getText()})}`);
304
+ }
305
+ function mergeClasses(newClasses, existing) {
306
+ const existingParts = existing.split(/\s+/).filter(Boolean);
307
+ const newParts = newClasses.split(/\s+/).filter(Boolean);
308
+ const combined = [...newParts, ...existingParts];
309
+ return combined.join(" ").trim();
310
+ }
311
+ function isCnCall(call) {
312
+ const expression = call.getExpression();
313
+ return Node.isIdentifier(expression) && expression.getText() === "cn";
314
+ }
315
+ function applyToMergePropsCalls(sourceFile, styleMap, matchedClasses) {
316
+ sourceFile.forEachDescendant((node) => {
317
+ if (!Node.isCallExpression(node)) {
318
+ return;
319
+ }
320
+ const expression = node.getExpression();
321
+ if (!Node.isIdentifier(expression) ||
322
+ expression.getText() !== "mergeProps") {
323
+ return;
324
+ }
325
+ // Look for object literals in mergeProps arguments
326
+ for (const arg of node.getArguments()) {
327
+ if (!Node.isObjectLiteralExpression(arg)) {
328
+ continue;
329
+ }
330
+ // Find className property in the object literal
331
+ const classNameProp = arg
332
+ .getProperties()
333
+ .find((prop) => Node.isPropertyAssignment(prop) &&
334
+ Node.isIdentifier(prop.getNameNode()) &&
335
+ prop.getNameNode().getText() === "className");
336
+ if (!classNameProp || !Node.isPropertyAssignment(classNameProp)) {
337
+ continue;
338
+ }
339
+ const classNameInitializer = classNameProp.getInitializer();
340
+ if (!classNameInitializer) {
341
+ continue;
342
+ }
343
+ // Handle cn() calls in className
344
+ if (Node.isCallExpression(classNameInitializer) &&
345
+ isCnCall(classNameInitializer)) {
346
+ const cnClasses = extractCnClassesFromCnCall(classNameInitializer);
347
+ if (cnClasses.length === 0) {
348
+ continue;
349
+ }
350
+ const unmatchedClasses = cnClasses.filter((cnClass) => !matchedClasses.has(cnClass));
351
+ if (unmatchedClasses.length === 0) {
352
+ // Clean up cn-* classes even if already matched
353
+ cleanCnClassesFromCnCall(classNameInitializer);
354
+ continue;
355
+ }
356
+ const tailwindClassesToApply = unmatchedClasses
357
+ .map((cnClass) => styleMap[cnClass])
358
+ .filter((classes) => Boolean(classes));
359
+ if (tailwindClassesToApply.length > 0) {
360
+ const mergedClasses = tailwindClassesToApply.join(" ");
361
+ applyClassesToCnCall(classNameInitializer, mergedClasses, matchedClasses, unmatchedClasses);
362
+ }
363
+ else {
364
+ cleanCnClassesFromCnCall(classNameInitializer);
365
+ }
366
+ }
367
+ }
368
+ });
369
+ }
370
+ function extractCnClassesFromCnCall(cnCall) {
371
+ const classes = [];
372
+ for (const argument of cnCall.getArguments()) {
373
+ if (isStringLiteralLike(argument)) {
374
+ classes.push(...extractCnClasses(argument.getLiteralText()));
375
+ }
376
+ }
377
+ return classes;
378
+ }
379
+ function cleanCnClassesFromCnCall(cnCall) {
380
+ for (const argument of cnCall.getArguments()) {
381
+ if (isStringLiteralLike(argument)) {
382
+ const cleaned = removeCnClasses(argument.getLiteralText());
383
+ argument.setLiteralValue(cleaned);
384
+ }
385
+ }
386
+ removeEmptyArgumentsFromCnCall(cnCall);
387
+ }
388
+ function applyClassesToCnCall(cnCall, tailwindClasses, matchedClasses, unmatchedClasses) {
389
+ const firstArg = cnCall.getArguments()[0];
390
+ if (isStringLiteralLike(firstArg)) {
391
+ const existing = firstArg.getLiteralText();
392
+ const updated = removeCnClasses(mergeClasses(tailwindClasses, existing));
393
+ firstArg.setLiteralValue(updated);
394
+ // Mark classes as matched
395
+ unmatchedClasses.forEach((cnClass) => matchedClasses.add(cnClass));
396
+ // Clean up cn-* classes from remaining arguments
397
+ for (let i = 1; i < cnCall.getArguments().length; i++) {
398
+ const arg = cnCall.getArguments()[i];
399
+ if (isStringLiteralLike(arg)) {
400
+ const argText = arg.getLiteralText();
401
+ const cleaned = removeCnClasses(argText);
402
+ if (cleaned !== argText) {
403
+ arg.setLiteralValue(cleaned);
404
+ }
405
+ }
406
+ }
407
+ removeEmptyArgumentsFromCnCall(cnCall);
408
+ return;
409
+ }
410
+ // If first arg is not a string literal, prepend tailwind classes
411
+ const argumentTexts = cnCall
412
+ .getArguments()
413
+ .map((argument) => {
414
+ if (isStringLiteralLike(argument)) {
415
+ const cleaned = removeCnClasses(argument.getLiteralText());
416
+ return cleaned ? JSON.stringify(cleaned) : null;
417
+ }
418
+ return argument.getText();
419
+ })
420
+ .filter((arg) => arg !== null);
421
+ const updatedArguments = [JSON.stringify(tailwindClasses), ...argumentTexts];
422
+ // Mark classes as matched
423
+ unmatchedClasses.forEach((cnClass) => matchedClasses.add(cnClass));
424
+ const parent = cnCall.getParent();
425
+ if (parent) {
426
+ cnCall.replaceWithText(`cn(${updatedArguments.join(", ")})`);
427
+ }
428
+ }
429
429
  //# sourceMappingURL=transform-style-map.js.map