@wise/wds-codemods 0.0.1-experimental-cc95209 → 0.0.1-experimental-731cdc7

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 (60) hide show
  1. package/dist/index.js +133 -134
  2. package/dist/index.js.map +1 -1
  3. package/dist/reportManualReview-DQ00-OKx.js +50 -0
  4. package/dist/reportManualReview-DQ00-OKx.js.map +1 -0
  5. package/dist/transforms/button.js +493 -583
  6. package/dist/transforms/button.js.map +1 -1
  7. package/package.json +28 -23
  8. package/.changeset/better-impalas-drop.md +0 -5
  9. package/.changeset/config.json +0 -13
  10. package/.changeset/quick-mails-joke.md +0 -128
  11. package/.github/CODEOWNERS +0 -1
  12. package/.github/actions/bootstrap/action.yml +0 -49
  13. package/.github/actions/commitlint/action.yml +0 -27
  14. package/.github/actions/test/action.yml +0 -23
  15. package/.github/workflows/cd-cd.yml +0 -127
  16. package/.github/workflows/renovate.yml +0 -16
  17. package/.husky/commit-msg +0 -1
  18. package/.husky/pre-commit +0 -1
  19. package/.nvmrc +0 -1
  20. package/.prettierignore +0 -1
  21. package/.prettierrc.js +0 -5
  22. package/DEVELOPER.md +0 -783
  23. package/babel.config.js +0 -28
  24. package/commitlint.config.js +0 -3
  25. package/dist/index.d.ts +0 -1
  26. package/dist/transforms/button.d.ts +0 -16
  27. package/eslint.config.js +0 -15
  28. package/jest.config.js +0 -9
  29. package/mkdocs.yml +0 -4
  30. package/renovate.json +0 -9
  31. package/scripts/build.sh +0 -10
  32. package/src/__tests__/runCodemod.test.ts +0 -96
  33. package/src/index.ts +0 -4
  34. package/src/runCodemod.ts +0 -88
  35. package/src/transforms/button/__tests__/button.test.tsx +0 -153
  36. package/src/transforms/button/button.ts +0 -447
  37. package/src/transforms/helpers/__tests__/createTestTransform.test.ts +0 -27
  38. package/src/transforms/helpers/__tests__/hasImport.test.ts +0 -52
  39. package/src/transforms/helpers/__tests__/iconUtils.test.ts +0 -207
  40. package/src/transforms/helpers/__tests__/jsxElementUtils.test.ts +0 -130
  41. package/src/transforms/helpers/__tests__/jsxReportingUtils.test.ts +0 -265
  42. package/src/transforms/helpers/createTestTransform.ts +0 -18
  43. package/src/transforms/helpers/hasImport.ts +0 -60
  44. package/src/transforms/helpers/iconUtils.ts +0 -87
  45. package/src/transforms/helpers/index.ts +0 -5
  46. package/src/transforms/helpers/jsxElementUtils.ts +0 -67
  47. package/src/transforms/helpers/jsxReportingUtils.ts +0 -224
  48. package/src/utils/__tests__/getOptions.test.ts +0 -170
  49. package/src/utils/__tests__/handleError.test.ts +0 -18
  50. package/src/utils/__tests__/loadTransformModules.test.ts +0 -51
  51. package/src/utils/__tests__/reportManualReview.test.ts +0 -42
  52. package/src/utils/getOptions.ts +0 -63
  53. package/src/utils/handleError.ts +0 -6
  54. package/src/utils/index.ts +0 -4
  55. package/src/utils/loadTransformModules.ts +0 -28
  56. package/src/utils/reportManualReview.ts +0 -17
  57. package/test-button.tsx +0 -230
  58. package/test-file.js +0 -2
  59. package/tsconfig.json +0 -14
  60. package/tsup.config.js +0 -13
@@ -1,606 +1,516 @@
1
- // src/utils/reportManualReview.ts
2
- import fs from "node:fs/promises";
3
- import path from "path";
4
- var REPORT_PATH = path.resolve(process.cwd(), "codemod-report.txt");
5
- var reportManualReview = async (filePath, message) => {
6
- const lineMatch = /at line (\d+)/u.exec(message);
7
- const lineNumber = lineMatch?.[1];
8
- const cleanMessage = message.replace(/ at line \d+/u, "");
9
- const lineInfo = lineNumber ? `:${lineNumber}` : "";
10
- await fs.appendFile(REPORT_PATH, `[${filePath}${lineInfo}] ${cleanMessage}
11
- `, "utf8");
12
- };
13
- var reportManualReview_default = reportManualReview;
14
-
15
- // src/transforms/helpers/createTestTransform.ts
16
- import { applyTransform } from "jscodeshift/src/testUtils";
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+ const require_reportManualReview = require('../reportManualReview-DQ00-OKx.js');
17
3
 
18
- // src/transforms/helpers/hasImport.ts
4
+ //#region src/transforms/helpers/hasImport.ts
5
+ /**
6
+ * Checks if a specific import exists in the given root collection and provides
7
+ * a method to remove it if found.
8
+ */
19
9
  function hasImport(root, sourceValue, importName, j) {
20
- const importDeclarations = root.find(j.ImportDeclaration, {
21
- source: { value: sourceValue }
22
- });
23
- if (importDeclarations.size() === 0) {
24
- return {
25
- exists: false,
26
- remove: () => {
27
- }
28
- };
29
- }
30
- const namedImport = importDeclarations.find(j.ImportSpecifier, {
31
- imported: { name: importName }
32
- });
33
- const defaultImport = importDeclarations.find(j.ImportDefaultSpecifier, {
34
- local: { name: importName }
35
- });
36
- const exists = namedImport.size() > 0 || defaultImport.size() > 0;
37
- const remove = () => {
38
- importDeclarations.forEach((path2) => {
39
- const filteredSpecifiers = path2.node.specifiers?.filter((specifier) => {
40
- if (specifier.type === "ImportSpecifier" && specifier.imported.name === importName) {
41
- return false;
42
- }
43
- if (specifier.type === "ImportDefaultSpecifier" && specifier.local?.name === importName) {
44
- return false;
45
- }
46
- return true;
47
- }) ?? [];
48
- if (filteredSpecifiers.length === 0) {
49
- path2.prune();
50
- } else {
51
- j(path2).replaceWith(
52
- j.importDeclaration(filteredSpecifiers, path2.node.source, path2.node.importKind)
53
- );
54
- }
55
- });
56
- };
57
- return { exists, remove };
10
+ const importDeclarations = root.find(j.ImportDeclaration, { source: { value: sourceValue } });
11
+ if (importDeclarations.size() === 0) return {
12
+ exists: false,
13
+ remove: () => {}
14
+ };
15
+ const namedImport = importDeclarations.find(j.ImportSpecifier, { imported: { name: importName } });
16
+ const defaultImport = importDeclarations.find(j.ImportDefaultSpecifier, { local: { name: importName } });
17
+ const exists = namedImport.size() > 0 || defaultImport.size() > 0;
18
+ const remove = () => {
19
+ importDeclarations.forEach((path) => {
20
+ const filteredSpecifiers = path.node.specifiers?.filter((specifier) => {
21
+ if (specifier.type === "ImportSpecifier" && specifier.imported.name === importName) return false;
22
+ if (specifier.type === "ImportDefaultSpecifier" && specifier.local?.name === importName) return false;
23
+ return true;
24
+ }) ?? [];
25
+ if (filteredSpecifiers.length === 0) path.prune();
26
+ else j(path).replaceWith(j.importDeclaration(filteredSpecifiers, path.node.source, path.node.importKind));
27
+ });
28
+ };
29
+ return {
30
+ exists,
31
+ remove
32
+ };
58
33
  }
59
- var hasImport_default = hasImport;
60
34
 
61
- // src/transforms/helpers/iconUtils.ts
62
- var processIconChildren = (j, children, iconImports, openingElement) => {
63
- if (!children || !openingElement.attributes) return;
64
- const unwrapJsxElement = (node) => {
65
- if (typeof node === "object" && node !== null && "type" in node && node.type === "JSXExpressionContainer" && j.JSXElement.check(node.expression)) {
66
- return node.expression;
67
- }
68
- return node;
69
- };
70
- const totalChildren = children.length;
71
- const iconChildIndex = children.findIndex((child) => {
72
- const unwrapped = unwrapJsxElement(child);
73
- return j.JSXElement.check(unwrapped) && unwrapped.openingElement.name.type === "JSXIdentifier" && iconImports.has(unwrapped.openingElement.name.name);
74
- });
75
- if (iconChildIndex === -1) return;
76
- const iconChild = unwrapJsxElement(children[iconChildIndex]);
77
- if (!iconChild || iconChild.openingElement.name.type !== "JSXIdentifier") return;
78
- const iconName = iconChild.openingElement.name.name;
79
- const distanceToStart = iconChildIndex;
80
- const distanceToEnd = totalChildren - 1 - iconChildIndex;
81
- const iconPropName = distanceToStart <= distanceToEnd ? "addonStart" : "addonEnd";
82
- const iconObject = j.objectExpression([
83
- j.property("init", j.identifier("type"), j.literal("icon")),
84
- j.property("init", j.identifier("value"), iconChild)
85
- ]);
86
- const iconProp = j.jsxAttribute(
87
- j.jsxIdentifier(iconPropName),
88
- j.jsxExpressionContainer(iconObject)
89
- );
90
- openingElement.attributes.push(iconProp);
91
- children.splice(iconChildIndex, 1);
92
- const isWhitespaceJsxText = (node) => {
93
- return typeof node === "object" && node !== null && node.type === "JSXText" && typeof node.value === "string" && node.value.trim() === "";
94
- };
95
- if (iconChildIndex - 1 >= 0 && isWhitespaceJsxText(children[iconChildIndex - 1])) {
96
- children.splice(iconChildIndex - 1, 1);
97
- } else if (isWhitespaceJsxText(children[iconChildIndex])) {
98
- children.splice(iconChildIndex, 1);
99
- }
35
+ //#endregion
36
+ //#region src/transforms/helpers/iconUtils.ts
37
+ /**
38
+ * Process children of a JSX element to detect icon components and add iconStart or iconEnd attributes accordingly.
39
+ * This is specific to icon handling but can be reused in codemods dealing with icon children.
40
+ */
41
+ const processIconChildren = (j, children, iconImports, openingElement) => {
42
+ if (!children || !openingElement.attributes) return;
43
+ const unwrapJsxElement = (node) => {
44
+ if (typeof node === "object" && node !== null && "type" in node && node.type === "JSXExpressionContainer" && j.JSXElement.check(node.expression)) return node.expression;
45
+ return node;
46
+ };
47
+ const totalChildren = children.length;
48
+ const iconChildIndex = children.findIndex((child) => {
49
+ const unwrapped = unwrapJsxElement(child);
50
+ return j.JSXElement.check(unwrapped) && unwrapped.openingElement.name.type === "JSXIdentifier" && iconImports.has(unwrapped.openingElement.name.name);
51
+ });
52
+ if (iconChildIndex === -1) return;
53
+ const iconChild = unwrapJsxElement(children[iconChildIndex]);
54
+ if (!iconChild || iconChild.openingElement.name.type !== "JSXIdentifier") return;
55
+ iconChild.openingElement.name.name;
56
+ const distanceToStart = iconChildIndex;
57
+ const distanceToEnd = totalChildren - 1 - iconChildIndex;
58
+ const iconPropName = distanceToStart <= distanceToEnd ? "addonStart" : "addonEnd";
59
+ const iconObject = j.objectExpression([j.property("init", j.identifier("type"), j.literal("icon")), j.property("init", j.identifier("value"), iconChild)]);
60
+ const iconProp = j.jsxAttribute(j.jsxIdentifier(iconPropName), j.jsxExpressionContainer(iconObject));
61
+ openingElement.attributes.push(iconProp);
62
+ children.splice(iconChildIndex, 1);
63
+ const isWhitespaceJsxText = (node) => {
64
+ return typeof node === "object" && node !== null && node.type === "JSXText" && typeof node.value === "string" && node.value.trim() === "";
65
+ };
66
+ if (iconChildIndex - 1 >= 0 && isWhitespaceJsxText(children[iconChildIndex - 1])) children.splice(iconChildIndex - 1, 1);
67
+ else if (isWhitespaceJsxText(children[iconChildIndex])) children.splice(iconChildIndex, 1);
100
68
  };
101
- var iconUtils_default = processIconChildren;
102
69
 
103
- // src/transforms/helpers/jsxElementUtils.ts
104
- var setNameIfJSXIdentifier = (elementName, newName) => {
105
- if (elementName && elementName.type === "JSXIdentifier") {
106
- return { ...elementName, name: newName };
107
- }
108
- return elementName;
70
+ //#endregion
71
+ //#region src/transforms/helpers/jsxElementUtils.ts
72
+ /**
73
+ * Rename a JSX element name if it is a JSXIdentifier.
74
+ */
75
+ const setNameIfJSXIdentifier = (elementName, newName) => {
76
+ if (elementName && elementName.type === "JSXIdentifier") return {
77
+ ...elementName,
78
+ name: newName
79
+ };
80
+ return elementName;
109
81
  };
110
- var hasAttribute = (attributes, attributeName) => {
111
- return Array.isArray(attributes) && attributes.some(
112
- (attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === attributeName
113
- );
82
+ /**
83
+ * Check if a list of attributes contains a specific attribute by name.
84
+ */
85
+ const hasAttribute = (attributes, attributeName) => {
86
+ return Array.isArray(attributes) && attributes.some((attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === attributeName);
114
87
  };
115
- var hasAttributeOnElement = (element, attributeName) => {
116
- return hasAttribute(element.attributes, attributeName);
88
+ /**
89
+ * Check if a JSX element's openingElement has a specific attribute.
90
+ */
91
+ const hasAttributeOnElement = (element, attributeName) => {
92
+ return hasAttribute(element.attributes, attributeName);
117
93
  };
118
- var addAttributesIfMissing = (j, openingElement, attributesToAdd) => {
119
- if (!Array.isArray(openingElement.attributes)) return;
120
- const attrs = openingElement.attributes;
121
- attributesToAdd.forEach(({ attribute, name }) => {
122
- if (!hasAttributeOnElement(openingElement, name)) {
123
- attrs.push(attribute);
124
- }
125
- });
94
+ /**
95
+ * Add specified attributes to a JSX element's openingElement if they are not already present.
96
+ */
97
+ const addAttributesIfMissing = (j, openingElement, attributesToAdd) => {
98
+ if (!Array.isArray(openingElement.attributes)) return;
99
+ const attrs = openingElement.attributes;
100
+ attributesToAdd.forEach(({ attribute, name }) => {
101
+ if (!hasAttributeOnElement(openingElement, name)) attrs.push(attribute);
102
+ });
126
103
  };
127
104
 
128
- // src/transforms/helpers/jsxReportingUtils.ts
105
+ //#endregion
106
+ //#region src/transforms/helpers/jsxReportingUtils.ts
107
+ /**
108
+ * CodemodReporter is a utility class for reporting issues found during codemod transformations.
109
+ * It provides methods to report issues related to JSX elements, props, and attributes.
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * const issues: string[] = [];
114
+ * const reporter = createReporter(j, issues);
115
+ *
116
+ * // Report a deprecated prop
117
+ * reporter.reportDeprecatedProp(buttonElement, 'flat', 'variant="text"');
118
+ *
119
+ * // Report complex expression that needs review
120
+ * reporter.reportAmbiguousExpression(element, 'size');
121
+ *
122
+ * // Auto-detect common issues
123
+ * reporter.reportAttributeIssues(element);
124
+ * ```
125
+ */
129
126
  var CodemodReporter = class {
130
- j;
131
- issues;
132
- constructor(options) {
133
- this.j = options.jscodeshift;
134
- this.issues = options.issues;
135
- }
136
- /**
137
- * Reports an issue with a JSX element
138
- */
139
- reportElement(element, reason) {
140
- const node = this.getNode(element);
141
- const componentName = this.getComponentName(node);
142
- const line = this.getLineNumber(node);
143
- this.addIssue(`Manual review required: <${componentName}> at line ${line} ${reason}.`);
144
- }
145
- /**
146
- * Reports an issue with a specific prop
147
- */
148
- reportProp(element, propName, reason) {
149
- const node = this.getNode(element);
150
- const componentName = this.getComponentName(node);
151
- const line = this.getLineNumber(node);
152
- this.addIssue(
153
- `Manual review required: prop "${propName}" on <${componentName}> at line ${line} ${reason}.`
154
- );
155
- }
156
- /**
157
- * Reports an issue with a JSX attribute directly
158
- */
159
- reportAttribute(attr, element, reason) {
160
- const node = this.getNode(element);
161
- const componentName = this.getComponentName(node);
162
- const propName = this.getAttributeName(attr);
163
- const line = this.getLineNumber(attr) || this.getLineNumber(node);
164
- const defaultReason = this.getAttributeReason(attr);
165
- const finalReason = reason || defaultReason;
166
- this.addIssue(
167
- `Manual review required: prop "${propName}" on <${componentName}> at line ${line} ${finalReason}.`
168
- );
169
- }
170
- /**
171
- * Reports spread props on an element
172
- */
173
- reportSpreadProps(element) {
174
- this.reportElement(element, "contains spread props that need manual review");
175
- }
176
- /**
177
- * Reports conflicting prop and children
178
- */
179
- reportPropWithChildren(element, propName) {
180
- this.reportProp(
181
- element,
182
- propName,
183
- `conflicts with children - both "${propName}" prop and children are present`
184
- );
185
- }
186
- /**
187
- * Reports unsupported prop value
188
- */
189
- reportUnsupportedValue(element, propName, value) {
190
- this.reportProp(element, propName, `has unsupported value "${value}"`);
191
- }
192
- /**
193
- * Reports ambiguous expression in prop
194
- */
195
- reportAmbiguousExpression(element, propName) {
196
- this.reportProp(element, propName, "contains a complex expression that needs manual review");
197
- }
198
- /**
199
- * Reports ambiguous children (like dynamic icons)
200
- */
201
- reportAmbiguousChildren(element, childType = "content") {
202
- this.reportElement(element, `contains ambiguous ${childType} that needs manual review`);
203
- }
204
- /**
205
- * Reports deprecated prop usage
206
- */
207
- reportDeprecatedProp(element, propName, alternative) {
208
- const suggestion = alternative ? ` Use ${alternative} instead` : "";
209
- this.reportProp(element, propName, `is deprecated${suggestion}`);
210
- }
211
- /**
212
- * Reports missing required prop
213
- */
214
- reportMissingRequiredProp(element, propName) {
215
- this.reportProp(element, propName, "is required but missing");
216
- }
217
- /**
218
- * Reports conflicting props
219
- */
220
- reportConflictingProps(element, propNames) {
221
- const propList = propNames.map((name) => `"${name}"`).join(", ");
222
- this.reportElement(element, `has conflicting props: ${propList} cannot be used together`);
223
- }
224
- /**
225
- * Auto-detects and reports common attribute issues
226
- */
227
- reportAttributeIssues(element) {
228
- const node = this.getNode(element);
229
- const { attributes } = node.openingElement;
230
- if (!attributes) return;
231
- if (attributes.some((attr) => attr.type === "JSXSpreadAttribute")) {
232
- this.reportSpreadProps(element);
233
- }
234
- attributes.forEach((attr) => {
235
- if (attr.type === "JSXAttribute" && attr.value?.type === "JSXExpressionContainer") {
236
- this.reportAttribute(attr, element);
237
- }
238
- });
239
- }
240
- // Private helper methods
241
- getNode(element) {
242
- return "node" in element ? element.node : element;
243
- }
244
- getComponentName(node) {
245
- const { name } = node.openingElement;
246
- if (name.type === "JSXIdentifier") {
247
- return name.name;
248
- }
249
- return this.j(name).toSource();
250
- }
251
- getLineNumber(node) {
252
- return node.loc?.start.line?.toString() || "unknown";
253
- }
254
- getAttributeName(attr) {
255
- if (attr.name.type === "JSXIdentifier") {
256
- return attr.name.name;
257
- }
258
- return this.j(attr.name).toSource();
259
- }
260
- getAttributeReason(attr) {
261
- if (!attr.value) return "has no value";
262
- if (attr.value.type === "JSXExpressionContainer") {
263
- const expr = attr.value.expression;
264
- const expressionType = expr.type.replace("Expression", "").toLowerCase();
265
- if (expr.type === "Identifier" || expr.type === "MemberExpression") {
266
- const valueText = this.j(expr).toSource();
267
- return `contains a ${expressionType} (${valueText})`;
268
- }
269
- return `contains a complex ${expressionType} expression`;
270
- }
271
- return "needs manual review";
272
- }
273
- addIssue(message) {
274
- this.issues.push(message);
275
- }
127
+ j;
128
+ issues;
129
+ constructor(options) {
130
+ this.j = options.jscodeshift;
131
+ this.issues = options.issues;
132
+ }
133
+ /**
134
+ * Reports an issue with a JSX element
135
+ */
136
+ reportElement(element, reason) {
137
+ const node = this.getNode(element);
138
+ const componentName = this.getComponentName(node);
139
+ const line = this.getLineNumber(node);
140
+ this.addIssue(`Manual review required: <${componentName}> at line ${line} ${reason}.`);
141
+ }
142
+ /**
143
+ * Reports an issue with a specific prop
144
+ */
145
+ reportProp(element, propName, reason) {
146
+ const node = this.getNode(element);
147
+ const componentName = this.getComponentName(node);
148
+ const line = this.getLineNumber(node);
149
+ this.addIssue(`Manual review required: prop "${propName}" on <${componentName}> at line ${line} ${reason}.`);
150
+ }
151
+ /**
152
+ * Reports an issue with a JSX attribute directly
153
+ */
154
+ reportAttribute(attr, element, reason) {
155
+ const node = this.getNode(element);
156
+ const componentName = this.getComponentName(node);
157
+ const propName = this.getAttributeName(attr);
158
+ const line = this.getLineNumber(attr) || this.getLineNumber(node);
159
+ const defaultReason = this.getAttributeReason(attr);
160
+ const finalReason = reason || defaultReason;
161
+ this.addIssue(`Manual review required: prop "${propName}" on <${componentName}> at line ${line} ${finalReason}.`);
162
+ }
163
+ /**
164
+ * Reports spread props on an element
165
+ */
166
+ reportSpreadProps(element) {
167
+ this.reportElement(element, "contains spread props that need manual review");
168
+ }
169
+ /**
170
+ * Reports conflicting prop and children
171
+ */
172
+ reportPropWithChildren(element, propName) {
173
+ this.reportProp(element, propName, `conflicts with children - both "${propName}" prop and children are present`);
174
+ }
175
+ /**
176
+ * Reports unsupported prop value
177
+ */
178
+ reportUnsupportedValue(element, propName, value) {
179
+ this.reportProp(element, propName, `has unsupported value "${value}"`);
180
+ }
181
+ /**
182
+ * Reports ambiguous expression in prop
183
+ */
184
+ reportAmbiguousExpression(element, propName) {
185
+ this.reportProp(element, propName, "contains a complex expression that needs manual review");
186
+ }
187
+ /**
188
+ * Reports ambiguous children (like dynamic icons)
189
+ */
190
+ reportAmbiguousChildren(element, childType = "content") {
191
+ this.reportElement(element, `contains ambiguous ${childType} that needs manual review`);
192
+ }
193
+ /**
194
+ * Reports deprecated prop usage
195
+ */
196
+ reportDeprecatedProp(element, propName, alternative) {
197
+ const suggestion = alternative ? ` Use ${alternative} instead` : "";
198
+ this.reportProp(element, propName, `is deprecated${suggestion}`);
199
+ }
200
+ /**
201
+ * Reports missing required prop
202
+ */
203
+ reportMissingRequiredProp(element, propName) {
204
+ this.reportProp(element, propName, "is required but missing");
205
+ }
206
+ /**
207
+ * Reports conflicting props
208
+ */
209
+ reportConflictingProps(element, propNames) {
210
+ const propList = propNames.map((name) => `"${name}"`).join(", ");
211
+ this.reportElement(element, `has conflicting props: ${propList} cannot be used together`);
212
+ }
213
+ /**
214
+ * Auto-detects and reports common attribute issues
215
+ */
216
+ reportAttributeIssues(element) {
217
+ const node = this.getNode(element);
218
+ const { attributes } = node.openingElement;
219
+ if (!attributes) return;
220
+ if (attributes.some((attr) => attr.type === "JSXSpreadAttribute")) this.reportSpreadProps(element);
221
+ attributes.forEach((attr) => {
222
+ if (attr.type === "JSXAttribute" && attr.value?.type === "JSXExpressionContainer") this.reportAttribute(attr, element);
223
+ });
224
+ }
225
+ getNode(element) {
226
+ return "node" in element ? element.node : element;
227
+ }
228
+ getComponentName(node) {
229
+ const { name } = node.openingElement;
230
+ if (name.type === "JSXIdentifier") return name.name;
231
+ return this.j(name).toSource();
232
+ }
233
+ getLineNumber(node) {
234
+ return node.loc?.start.line?.toString() || "unknown";
235
+ }
236
+ getAttributeName(attr) {
237
+ if (attr.name.type === "JSXIdentifier") return attr.name.name;
238
+ return this.j(attr.name).toSource();
239
+ }
240
+ getAttributeReason(attr) {
241
+ if (!attr.value) return "has no value";
242
+ if (attr.value.type === "JSXExpressionContainer") {
243
+ const expr = attr.value.expression;
244
+ const expressionType = expr.type.replace("Expression", "").toLowerCase();
245
+ if (expr.type === "Identifier" || expr.type === "MemberExpression") {
246
+ const valueText = this.j(expr).toSource();
247
+ return `contains a ${expressionType} (${valueText})`;
248
+ }
249
+ return `contains a complex ${expressionType} expression`;
250
+ }
251
+ return "needs manual review";
252
+ }
253
+ addIssue(message) {
254
+ this.issues.push(message);
255
+ }
276
256
  };
277
- var createReporter = (j, issues) => {
278
- return new CodemodReporter({ jscodeshift: j, issues });
257
+ const createReporter = (j, issues) => {
258
+ return new CodemodReporter({
259
+ jscodeshift: j,
260
+ issues
261
+ });
279
262
  };
280
263
 
281
- // src/transforms/button/button.ts
282
- var parser = "tsx";
283
- var priorityMapping = {
284
- accent: {
285
- primary: "primary",
286
- secondary: "secondary-neutral",
287
- tertiary: "tertiary"
288
- },
289
- positive: {
290
- primary: "primary",
291
- secondary: "secondary-neutral",
292
- tertiary: "secondary-neutral"
293
- },
294
- negative: {
295
- primary: "primary",
296
- secondary: "secondary",
297
- tertiary: "secondary"
298
- }
264
+ //#endregion
265
+ //#region src/transforms/button/transformer.ts
266
+ const parser = "tsx";
267
+ const priorityMapping = {
268
+ accent: {
269
+ primary: "primary",
270
+ secondary: "secondary-neutral",
271
+ tertiary: "tertiary"
272
+ },
273
+ positive: {
274
+ primary: "primary",
275
+ secondary: "secondary-neutral",
276
+ tertiary: "secondary-neutral"
277
+ },
278
+ negative: {
279
+ primary: "primary",
280
+ secondary: "secondary",
281
+ tertiary: "secondary"
282
+ }
299
283
  };
300
- var sizeMap = {
301
- EXTRA_SMALL: "xs",
302
- SMALL: "sm",
303
- MEDIUM: "md",
304
- LARGE: "lg",
305
- EXTRA_LARGE: "xl",
306
- xs: "sm",
307
- sm: "sm",
308
- md: "md",
309
- lg: "lg",
310
- xl: "xl"
284
+ const sizeMap = {
285
+ EXTRA_SMALL: "xs",
286
+ SMALL: "sm",
287
+ MEDIUM: "md",
288
+ LARGE: "lg",
289
+ EXTRA_LARGE: "xl",
290
+ xs: "sm",
291
+ sm: "sm",
292
+ md: "md",
293
+ lg: "lg",
294
+ xl: "xl"
311
295
  };
312
- var resolveSize = (size) => {
313
- if (!size) return size;
314
- const match = /^Size\.(EXTRA_SMALL|SMALL|MEDIUM|LARGE|EXTRA_LARGE)$/u.exec(size);
315
- if (match) {
316
- return sizeMap[match[1]];
317
- }
318
- return sizeMap[size] || size;
296
+ const resolveSize = (size) => {
297
+ if (!size) return size;
298
+ const match = /^Size\.(EXTRA_SMALL|SMALL|MEDIUM|LARGE|EXTRA_LARGE)$/u.exec(size);
299
+ if (match) return sizeMap[match[1]];
300
+ return sizeMap[size] || size;
319
301
  };
320
- var resolvePriority = (type, priority) => {
321
- if (type && priority) {
322
- return priorityMapping[type]?.[priority] || priority;
323
- }
324
- return priority;
302
+ const resolvePriority = (type, priority) => {
303
+ if (type && priority) return priorityMapping[type]?.[priority] || priority;
304
+ return priority;
325
305
  };
326
- var resolveType = (type, htmlType) => {
327
- if (htmlType) {
328
- return htmlType;
329
- }
330
- const legacyButtonTypes = [
331
- "accent",
332
- "negative",
333
- "positive",
334
- "primary",
335
- "pay",
336
- "secondary",
337
- "danger",
338
- "link",
339
- "button",
340
- "reset",
341
- "submit"
342
- ];
343
- return type && legacyButtonTypes.includes(type) ? type : null;
306
+ const resolveType = (type, htmlType) => {
307
+ if (htmlType) return htmlType;
308
+ const legacyButtonTypes = [
309
+ "accent",
310
+ "negative",
311
+ "positive",
312
+ "primary",
313
+ "pay",
314
+ "secondary",
315
+ "danger",
316
+ "link"
317
+ ];
318
+ return type && legacyButtonTypes.includes(type) ? type : null;
344
319
  };
345
- var convertEnumValue = (value) => {
346
- if (!value) return { converted: value, wasEnum: false };
347
- const strippedValue = value.replace(/^['"]|['"]$/gu, "");
348
- const enumMapping = {
349
- "Priority.SECONDARY": "secondary",
350
- "Priority.PRIMARY": "primary",
351
- "Priority.TERTIARY": "tertiary",
352
- "ControlType.NEGATIVE": "negative",
353
- "ControlType.POSITIVE": "positive",
354
- "ControlType.ACCENT": "accent",
355
- "ControlType.BUTTON": "button",
356
- "ControlType.RESET": "reset",
357
- "HtmlType.SUBMIT": "submit",
358
- "HtmlType.BUTTON": "button",
359
- "HtmlType.RESET": "reset",
360
- "Sentiment.NEGATIVE": "negative"
361
- };
362
- const wasEnum = strippedValue in enumMapping;
363
- const converted = enumMapping[strippedValue] || strippedValue;
364
- return { converted, wasEnum };
320
+ const convertEnumValue = (value) => {
321
+ if (!value) return value;
322
+ const strippedValue = value.replace(/^['"]|['"]$/gu, "");
323
+ const enumMapping = {
324
+ "Priority.SECONDARY": "secondary",
325
+ "Priority.PRIMARY": "primary",
326
+ "Priority.TERTIARY": "tertiary",
327
+ "ControlType.NEGATIVE": "negative",
328
+ "ControlType.POSITIVE": "positive",
329
+ "ControlType.ACCENT": "accent"
330
+ };
331
+ return enumMapping[strippedValue] || strippedValue;
365
332
  };
366
- var transformer = (file, api, options) => {
367
- const j = api.jscodeshift;
368
- const root = j(file.source);
369
- const manualReviewIssues = [];
370
- const reporter = createReporter(j, manualReviewIssues);
371
- const { exists: hasButtonImport } = hasImport_default(root, "@transferwise/components", "Button", j);
372
- const { exists: hasActionButtonImport, remove: removeActionButtonImport } = hasImport_default(
373
- root,
374
- "@transferwise/components",
375
- "ActionButton",
376
- j
377
- );
378
- const iconImports = /* @__PURE__ */ new Set();
379
- root.find(j.ImportDeclaration, { source: { value: "@transferwise/icons" } }).forEach((path2) => {
380
- path2.node.specifiers?.forEach((specifier) => {
381
- if ((specifier.type === "ImportDefaultSpecifier" || specifier.type === "ImportSpecifier") && specifier.local) {
382
- const localName = specifier.local.name;
383
- iconImports.add(localName);
384
- }
385
- });
386
- });
387
- if (hasActionButtonImport) {
388
- root.findJSXElements("ActionButton").forEach((path2) => {
389
- const { openingElement, closingElement } = path2.node;
390
- openingElement.name = setNameIfJSXIdentifier(openingElement.name, "Button");
391
- if (closingElement) {
392
- closingElement.name = setNameIfJSXIdentifier(closingElement.name, "Button");
393
- }
394
- addAttributesIfMissing(j, openingElement, [
395
- { attribute: j.jsxAttribute(j.jsxIdentifier("v2")), name: "v2" },
396
- { attribute: j.jsxAttribute(j.jsxIdentifier("size"), j.literal("sm")), name: "size" }
397
- ]);
398
- iconUtils_default(j, path2.node.children, iconImports, openingElement);
399
- if ((openingElement.attributes ?? []).some((attr) => attr.type === "JSXSpreadAttribute")) {
400
- reporter.reportSpreadProps(path2);
401
- }
402
- const legacyPropNames = ["priority", "text"];
403
- const legacyProps = {};
404
- openingElement.attributes?.forEach((attr) => {
405
- if (attr.type === "JSXAttribute" && attr.name && attr.name.type === "JSXIdentifier") {
406
- const { name } = attr.name;
407
- if (legacyPropNames.includes(name)) {
408
- if (attr.value) {
409
- if (attr.value.type === "StringLiteral") {
410
- legacyProps[name] = attr.value.value;
411
- } else if (attr.value.type === "JSXExpressionContainer") {
412
- reporter.reportAttribute(attr, path2);
413
- }
414
- }
415
- }
416
- }
417
- });
418
- const hasTextProp = openingElement.attributes?.some(
419
- (attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "text"
420
- );
421
- const hasChildren = path2.node.children?.some(
422
- (child) => child.type === "JSXText" && child.value.trim() !== "" || child.type === "JSXElement" || child.type === "JSXExpressionContainer"
423
- );
424
- if (hasTextProp && hasChildren) {
425
- reporter.reportPropWithChildren(path2, "text");
426
- }
427
- (path2.node.children || []).forEach((child) => {
428
- if (child.type === "JSXExpressionContainer") {
429
- const expr = child.expression;
430
- if (expr.type === "ConditionalExpression" || expr.type === "CallExpression" || expr.type === "Identifier" || expr.type === "MemberExpression") {
431
- reporter.reportAmbiguousChildren(path2, "icon");
432
- }
433
- }
434
- });
435
- });
436
- removeActionButtonImport();
437
- }
438
- if (hasButtonImport) {
439
- root.findJSXElements("Button").forEach((path2) => {
440
- const { openingElement } = path2.node;
441
- if (hasAttributeOnElement(openingElement, "v2")) return;
442
- addAttributesIfMissing(j, openingElement, [
443
- { attribute: j.jsxAttribute(j.jsxIdentifier("v2")), name: "v2" }
444
- ]);
445
- iconUtils_default(j, path2.node.children, iconImports, openingElement);
446
- const legacyProps = {};
447
- const legacyPropNames = ["priority", "size", "type", "htmlType", "sentiment"];
448
- const keepAttributes = [];
449
- (openingElement.attributes ?? []).forEach((attr) => {
450
- if (attr.type === "JSXAttribute" && attr.name && attr.name.type === "JSXIdentifier" && legacyPropNames.includes(attr.name.name)) {
451
- const { name } = attr.name;
452
- let migrated = false;
453
- let rawStringValue;
454
- if (attr.value) {
455
- if (attr.value.type === "StringLiteral") {
456
- rawStringValue = attr.value.value;
457
- legacyProps[name] = attr.value.value;
458
- } else if (attr.value.type === "JSXExpressionContainer") {
459
- rawStringValue = String(j(attr.value.expression).toSource());
460
- const { converted } = convertEnumValue(rawStringValue);
461
- legacyProps[name] = converted;
462
- }
463
- } else {
464
- legacyProps[name] = void 0;
465
- }
466
- const { wasEnum } = convertEnumValue(rawStringValue);
467
- if (rawStringValue && wasEnum) {
468
- migrated = true;
469
- } else if (name === "size") {
470
- const rawValue = legacyProps.size;
471
- const resolved2 = resolveSize(rawValue);
472
- const supportedSizes = ["xs", "sm", "md", "lg", "xl"];
473
- if (typeof rawValue === "string" && typeof resolved2 === "string" && supportedSizes.includes(resolved2)) {
474
- migrated = true;
475
- } else if (typeof rawValue === "string") {
476
- reporter.reportUnsupportedValue(path2, "size", rawValue);
477
- } else if (rawValue !== void 0) {
478
- reporter.reportAmbiguousExpression(path2, "size");
479
- }
480
- } else if (name === "priority") {
481
- const rawValue = legacyProps.priority;
482
- const { converted } = convertEnumValue(rawValue);
483
- const mapped = resolvePriority(legacyProps.type, converted);
484
- const supportedPriorities = ["primary", "secondary", "tertiary", "secondary-neutral"];
485
- if (typeof rawValue === "string" && typeof mapped === "string" && supportedPriorities.includes(mapped)) {
486
- migrated = true;
487
- } else if (typeof rawValue === "string") {
488
- reporter.reportUnsupportedValue(path2, "priority", rawValue);
489
- } else if (rawValue !== void 0) {
490
- reporter.reportAmbiguousExpression(path2, "priority");
491
- }
492
- } else if (name === "type" || name === "htmlType") {
493
- const rawType2 = legacyProps.type;
494
- const rawHtmlType2 = legacyProps.htmlType;
495
- const resolvedType2 = typeof rawType2 === "string" ? rawType2 : rawType2 && typeof rawType2 === "object" ? convertEnumValue(j(rawType2).toSource()).converted : void 0;
496
- const resolved2 = resolveType(resolvedType2, rawHtmlType2);
497
- const supportedTypes2 = ["button", "reset", "submit"];
498
- if (typeof resolved2 === "string" && supportedTypes2.includes(resolved2)) {
499
- migrated = true;
500
- } else if (typeof rawType2 === "string" || typeof rawHtmlType2 === "string") {
501
- reporter.reportUnsupportedValue(path2, "type", rawType2 ?? rawHtmlType2 ?? "");
502
- } else if (rawType2 !== void 0 || rawHtmlType2 !== void 0) {
503
- reporter.reportAmbiguousExpression(path2, "type");
504
- }
505
- } else if (name === "sentiment") {
506
- const rawValue = legacyProps.sentiment;
507
- if (rawValue === "negative") {
508
- migrated = true;
509
- } else if (typeof rawValue === "string") {
510
- reporter.reportUnsupportedValue(path2, "sentiment", rawValue);
511
- } else if (rawValue !== void 0) {
512
- reporter.reportAmbiguousExpression(path2, "sentiment");
513
- }
514
- }
515
- if (!migrated) keepAttributes.push(attr);
516
- } else {
517
- keepAttributes.push(attr);
518
- }
519
- });
520
- const newAttributes = [];
521
- const rawSize = legacyProps.size;
522
- const resolvedSize = resolveSize(rawSize);
523
- if (typeof rawSize === "string" && typeof resolvedSize === "string" && ["xs", "sm", "md", "lg", "xl"].includes(resolvedSize)) {
524
- newAttributes.push(j.jsxAttribute(j.jsxIdentifier("size"), j.literal(resolvedSize)));
525
- }
526
- const rawPriority = legacyProps.priority;
527
- const { converted: convertedPriority } = convertEnumValue(rawPriority);
528
- const mappedPriority = resolvePriority(legacyProps.type, convertedPriority);
529
- if (typeof rawPriority === "string" && typeof mappedPriority === "string" && ["primary", "secondary", "tertiary", "secondary-neutral"].includes(mappedPriority)) {
530
- newAttributes.push(j.jsxAttribute(j.jsxIdentifier("priority"), j.literal(mappedPriority)));
531
- }
532
- const rawType = legacyProps.type;
533
- const rawHtmlType = legacyProps.htmlType;
534
- const resolvedType = typeof rawType === "string" ? rawType : rawType && typeof rawType === "object" ? convertEnumValue(j(rawType).toSource()).converted : void 0;
535
- const resolved = resolveType(resolvedType, rawHtmlType);
536
- const supportedTypes = ["button", "reset", "submit", "negative"];
537
- if (typeof resolved === "string" && supportedTypes.includes(resolved)) {
538
- if (resolved !== "negative") {
539
- newAttributes.push(j.jsxAttribute(j.jsxIdentifier("type"), j.literal(resolved)));
540
- }
541
- if (resolved === "negative") {
542
- newAttributes.push(j.jsxAttribute(j.jsxIdentifier("sentiment"), j.literal("negative")));
543
- }
544
- }
545
- const rawSentiment = legacyProps.sentiment;
546
- if (rawSentiment === "negative") {
547
- newAttributes.push(j.jsxAttribute(j.jsxIdentifier("sentiment"), j.literal("negative")));
548
- }
549
- Array.prototype.push.apply(newAttributes, keepAttributes);
550
- let asIndex = -1;
551
- let asValue = null;
552
- let hrefExists = false;
553
- let asAmbiguous = false;
554
- let hrefAmbiguous = false;
555
- newAttributes.forEach((attr, index) => {
556
- if (attr.type === "JSXAttribute" && attr.name) {
557
- if (attr.name.name === "as") {
558
- if (attr.value) {
559
- if (attr.value.type === "StringLiteral") {
560
- asValue = attr.value.value;
561
- } else if (attr.value.type === "JSXExpressionContainer") {
562
- asAmbiguous = true;
563
- reporter.reportAttribute(attr, path2);
564
- }
565
- }
566
- asIndex = index;
567
- }
568
- if (attr.name.name === "href") {
569
- hrefExists = true;
570
- if (attr.value && attr.value.type !== "StringLiteral") {
571
- hrefAmbiguous = true;
572
- reporter.reportAttribute(attr, path2);
573
- }
574
- }
575
- }
576
- });
577
- if (asValue && asValue !== "a") {
578
- reporter.reportUnsupportedValue(path2, "as", asValue);
579
- }
580
- if (asValue === "a") {
581
- if (asIndex !== -1) {
582
- newAttributes.splice(asIndex, 1);
583
- }
584
- if (!hrefExists) {
585
- newAttributes.push(j.jsxAttribute(j.jsxIdentifier("href"), j.literal("#")));
586
- }
587
- }
588
- openingElement.attributes = newAttributes;
589
- if ((openingElement.attributes ?? []).some((attr) => attr.type === "JSXSpreadAttribute")) {
590
- reporter.reportSpreadProps(path2);
591
- }
592
- });
593
- }
594
- if (manualReviewIssues.length > 0) {
595
- manualReviewIssues.forEach(async (issue) => {
596
- await reportManualReview_default(file.path, issue);
597
- });
598
- }
599
- return root.toSource();
600
- };
601
- var button_default = transformer;
602
- export {
603
- button_default as default,
604
- parser
333
+ /**
334
+ * This transform function modifies the Button and ActionButton components from the @transferwise/components library.
335
+ * It updates the ActionButton component to use the Button component with specific attributes and mappings.
336
+ * It also processes icon children and removes legacy props.
337
+ *
338
+ * @param {FileInfo} file - The file information object.
339
+ * @param {API} api - The API object for jscodeshift.
340
+ * @param {Options} options - The options object for jscodeshift.
341
+ * @returns {string} - The transformed source code.
342
+ */
343
+ const transformer = (file, api, options) => {
344
+ const j = api.jscodeshift;
345
+ const root = j(file.source);
346
+ const manualReviewIssues = [];
347
+ const reporter = createReporter(j, manualReviewIssues);
348
+ const { exists: hasButtonImport } = hasImport(root, "@transferwise/components", "Button", j);
349
+ const { exists: hasActionButtonImport, remove: removeActionButtonImport } = hasImport(root, "@transferwise/components", "ActionButton", j);
350
+ const iconImports = /* @__PURE__ */ new Set();
351
+ root.find(j.ImportDeclaration, { source: { value: "@transferwise/icons" } }).forEach((path) => {
352
+ path.node.specifiers?.forEach((specifier) => {
353
+ if ((specifier.type === "ImportDefaultSpecifier" || specifier.type === "ImportSpecifier") && specifier.local) {
354
+ const localName = specifier.local.name;
355
+ iconImports.add(localName);
356
+ }
357
+ });
358
+ });
359
+ if (hasActionButtonImport) {
360
+ root.findJSXElements("ActionButton").forEach((path) => {
361
+ const { openingElement, closingElement } = path.node;
362
+ openingElement.name = setNameIfJSXIdentifier(openingElement.name, "Button");
363
+ if (closingElement) closingElement.name = setNameIfJSXIdentifier(closingElement.name, "Button");
364
+ addAttributesIfMissing(j, openingElement, [{
365
+ attribute: j.jsxAttribute(j.jsxIdentifier("v2")),
366
+ name: "v2"
367
+ }, {
368
+ attribute: j.jsxAttribute(j.jsxIdentifier("size"), j.literal("sm")),
369
+ name: "size"
370
+ }]);
371
+ processIconChildren(j, path.node.children, iconImports, openingElement);
372
+ if ((openingElement.attributes ?? []).some((attr) => attr.type === "JSXSpreadAttribute")) reporter.reportSpreadProps(path);
373
+ const legacyPropNames = ["priority", "text"];
374
+ const legacyProps = {};
375
+ openingElement.attributes?.forEach((attr) => {
376
+ if (attr.type === "JSXAttribute" && attr.name && attr.name.type === "JSXIdentifier") {
377
+ const { name } = attr.name;
378
+ if (legacyPropNames.includes(name)) {
379
+ if (attr.value) {
380
+ if (attr.value.type === "StringLiteral") legacyProps[name] = attr.value.value;
381
+ else if (attr.value.type === "JSXExpressionContainer") reporter.reportAttribute(attr, path);
382
+ }
383
+ }
384
+ }
385
+ });
386
+ const hasTextProp = openingElement.attributes?.some((attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "text");
387
+ const hasChildren = path.node.children?.some((child) => child.type === "JSXText" && child.value.trim() !== "" || child.type === "JSXElement" || child.type === "JSXExpressionContainer");
388
+ if (hasTextProp && hasChildren) reporter.reportPropWithChildren(path, "text");
389
+ (path.node.children || []).forEach((child) => {
390
+ if (child.type === "JSXExpressionContainer") {
391
+ const expr = child.expression;
392
+ if (expr.type === "ConditionalExpression" || expr.type === "CallExpression" || expr.type === "Identifier" || expr.type === "MemberExpression") reporter.reportAmbiguousChildren(path, "icon");
393
+ }
394
+ });
395
+ });
396
+ removeActionButtonImport();
397
+ }
398
+ if (hasButtonImport) root.findJSXElements("Button").forEach((path) => {
399
+ const { openingElement } = path.node;
400
+ if (hasAttributeOnElement(openingElement, "v2")) return;
401
+ addAttributesIfMissing(j, openingElement, [{
402
+ attribute: j.jsxAttribute(j.jsxIdentifier("v2")),
403
+ name: "v2"
404
+ }]);
405
+ processIconChildren(j, path.node.children, iconImports, openingElement);
406
+ const legacyProps = {};
407
+ const legacyPropNames = [
408
+ "priority",
409
+ "size",
410
+ "type",
411
+ "htmlType",
412
+ "sentiment"
413
+ ];
414
+ openingElement.attributes?.forEach((attr) => {
415
+ if (attr.type === "JSXAttribute" && attr.name && attr.name.type === "JSXIdentifier") {
416
+ const { name } = attr.name;
417
+ if (legacyPropNames.includes(name)) if (attr.value) {
418
+ if (attr.value.type === "StringLiteral") legacyProps[name] = attr.value.value;
419
+ else if (attr.value.type === "JSXExpressionContainer") legacyProps[name] = convertEnumValue(String(j(attr.value.expression).toSource()));
420
+ } else legacyProps[name] = void 0;
421
+ }
422
+ });
423
+ if (openingElement.attributes) openingElement.attributes = openingElement.attributes.filter((attr) => !(attr.type === "JSXAttribute" && attr.name && legacyPropNames.includes(attr.name.name)));
424
+ if ("size" in legacyProps) {
425
+ const rawValue = legacyProps.size;
426
+ const resolved = resolveSize(rawValue);
427
+ const supportedSizes = [
428
+ "xs",
429
+ "sm",
430
+ "md",
431
+ "lg",
432
+ "xl"
433
+ ];
434
+ if (typeof rawValue === "string" && typeof resolved === "string" && supportedSizes.includes(resolved)) openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("size"), j.literal(resolved)));
435
+ else if (typeof rawValue === "string") reporter.reportUnsupportedValue(path, "size", rawValue);
436
+ else if (rawValue !== void 0) reporter.reportAmbiguousExpression(path, "size");
437
+ }
438
+ if ("priority" in legacyProps) {
439
+ const rawValue = legacyProps.priority;
440
+ const converted = convertEnumValue(rawValue);
441
+ const mapped = resolvePriority(legacyProps.type, converted);
442
+ const supportedPriorities = [
443
+ "primary",
444
+ "secondary",
445
+ "tertiary",
446
+ "secondary-neutral"
447
+ ];
448
+ if (typeof rawValue === "string" && typeof mapped === "string" && supportedPriorities.includes(mapped)) openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("priority"), j.literal(mapped)));
449
+ else if (typeof rawValue === "string") reporter.reportUnsupportedValue(path, "priority", rawValue);
450
+ else if (rawValue !== void 0) reporter.reportAmbiguousExpression(path, "priority");
451
+ }
452
+ if ("type" in legacyProps || "htmlType" in legacyProps) {
453
+ const rawType = legacyProps.type;
454
+ const rawHtmlType = legacyProps.htmlType;
455
+ const resolvedType = typeof rawType === "string" ? rawType : rawType && typeof rawType === "object" ? convertEnumValue(j(rawType).toSource()) : void 0;
456
+ const resolved = resolveType(resolvedType, rawHtmlType);
457
+ const supportedTypes = [
458
+ "accent",
459
+ "negative",
460
+ "positive",
461
+ "primary",
462
+ "pay",
463
+ "secondary",
464
+ "danger",
465
+ "link",
466
+ "submit",
467
+ "button",
468
+ "reset"
469
+ ];
470
+ if (typeof resolved === "string" && supportedTypes.includes(resolved)) {
471
+ openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("type"), j.literal(resolved)));
472
+ if (resolved === "negative") openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("sentiment"), j.literal("negative")));
473
+ } else if (typeof rawType === "string" || typeof rawHtmlType === "string") reporter.reportUnsupportedValue(path, "type", rawType ?? rawHtmlType ?? "");
474
+ else if (rawType !== void 0 || rawHtmlType !== void 0) reporter.reportAmbiguousExpression(path, "type");
475
+ }
476
+ if ("sentiment" in legacyProps) {
477
+ const rawValue = legacyProps.sentiment;
478
+ if (rawValue === "negative") openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("sentiment"), j.literal("negative")));
479
+ else if (typeof rawValue === "string") reporter.reportUnsupportedValue(path, "sentiment", rawValue);
480
+ else if (rawValue !== void 0) reporter.reportAmbiguousExpression(path, "sentiment");
481
+ }
482
+ let asIndex = -1;
483
+ let asValue = null;
484
+ let hrefExists = false;
485
+ openingElement.attributes?.forEach((attr, index) => {
486
+ if (attr.type === "JSXAttribute" && attr.name) {
487
+ if (attr.name.name === "as") {
488
+ if (attr.value) {
489
+ if (attr.value.type === "StringLiteral") asValue = attr.value.value;
490
+ else if (attr.value.type === "JSXExpressionContainer") reporter.reportAttribute(attr, path);
491
+ }
492
+ asIndex = index;
493
+ }
494
+ if (attr.name.name === "href") {
495
+ hrefExists = true;
496
+ if (attr.value && attr.value.type !== "StringLiteral") reporter.reportAttribute(attr, path);
497
+ }
498
+ }
499
+ });
500
+ if (asValue && asValue !== "a") reporter.reportUnsupportedValue(path, "as", asValue);
501
+ if (asValue === "a") {
502
+ if (asIndex !== -1) openingElement.attributes = openingElement.attributes?.filter((_, idx) => idx !== asIndex);
503
+ if (!hrefExists) openingElement.attributes = [...openingElement.attributes ?? [], j.jsxAttribute(j.jsxIdentifier("href"), j.literal("#"))];
504
+ }
505
+ if ((openingElement.attributes ?? []).some((attr) => attr.type === "JSXSpreadAttribute")) reporter.reportSpreadProps(path);
506
+ });
507
+ if (manualReviewIssues.length > 0) manualReviewIssues.forEach(async (issue) => {
508
+ await require_reportManualReview.reportManualReview(file.path, issue);
509
+ });
510
+ return root.toSource();
605
511
  };
512
+
513
+ //#endregion
514
+ exports.default = transformer;
515
+ exports.parser = parser;
606
516
  //# sourceMappingURL=button.js.map