@wise/wds-codemods 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{claude-BHYfEMfb.js → claude-cHSlHbX1.js} +26 -42
- package/dist/claude-cHSlHbX1.js.map +1 -0
- package/dist/common-nTdKnfMB.js +13 -0
- package/dist/{common-DdEQmI2h.js.map → common-nTdKnfMB.js.map} +1 -1
- package/dist/{helpers-Cj5geKJl.js → helpers-9e0vtyED.js} +235 -382
- package/dist/helpers-9e0vtyED.js.map +1 -0
- package/dist/index.js +44 -49
- package/dist/index.js.map +1 -1
- package/dist/transforms/button/transformer.js +14 -26
- package/dist/transforms/button/transformer.js.map +1 -1
- package/dist/transforms/info-prompt/transformer.js +9 -12
- package/dist/transforms/info-prompt/transformer.js.map +1 -1
- package/dist/transforms/list-item/MIGRATION_RULES.md +20 -4
- package/dist/transforms/list-item/transformer.js +9 -13
- package/dist/transforms/list-item/transformer.js.map +1 -1
- package/package.json +25 -33
- package/dist/claude-BHYfEMfb.js.map +0 -1
- package/dist/common-DdEQmI2h.js +0 -59
- package/dist/helpers-Cj5geKJl.js.map +0 -1
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
const require_helpers = require('../../helpers-Cj5geKJl.js');
|
|
3
|
-
|
|
1
|
+
import { r as reportManualReview } from "../../helpers-9e0vtyED.js";
|
|
4
2
|
//#region src/helpers/jscodeshift/addImport.ts
|
|
5
3
|
/**
|
|
6
4
|
* Adds a named import if it doesn't already exist.
|
|
@@ -22,8 +20,6 @@ function addImport(root, sourceValue, importName, j) {
|
|
|
22
20
|
}
|
|
23
21
|
}
|
|
24
22
|
}
|
|
25
|
-
var addImport_default = addImport;
|
|
26
|
-
|
|
27
23
|
//#endregion
|
|
28
24
|
//#region src/helpers/jscodeshift/hasImport.ts
|
|
29
25
|
/**
|
|
@@ -83,8 +79,6 @@ function hasImport(root, sourceValue, importName, j) {
|
|
|
83
79
|
conflictingImports
|
|
84
80
|
};
|
|
85
81
|
}
|
|
86
|
-
var hasImport_default = hasImport;
|
|
87
|
-
|
|
88
82
|
//#endregion
|
|
89
83
|
//#region src/helpers/jscodeshift/iconUtils.ts
|
|
90
84
|
/**
|
|
@@ -104,7 +98,7 @@ const processIconChildren = (j, children, iconImports, openingElement) => {
|
|
|
104
98
|
});
|
|
105
99
|
if (iconChildIndex === -1) return;
|
|
106
100
|
const iconChild = unwrapJsxElement(children[iconChildIndex]);
|
|
107
|
-
if (
|
|
101
|
+
if (iconChild?.openingElement.name.type !== "JSXIdentifier") return;
|
|
108
102
|
iconChild.openingElement.name.name;
|
|
109
103
|
const iconPropName = iconChildIndex <= totalChildren - 1 - iconChildIndex ? "addonStart" : "addonEnd";
|
|
110
104
|
const iconObject = j.objectExpression([j.property("init", j.identifier("type"), j.literal("icon")), j.property("init", j.identifier("value"), iconChild)]);
|
|
@@ -117,15 +111,13 @@ const processIconChildren = (j, children, iconImports, openingElement) => {
|
|
|
117
111
|
if (iconChildIndex - 1 >= 0 && isWhitespaceJsxText(children[iconChildIndex - 1])) children.splice(iconChildIndex - 1, 1);
|
|
118
112
|
else if (isWhitespaceJsxText(children[iconChildIndex])) children.splice(iconChildIndex, 1);
|
|
119
113
|
};
|
|
120
|
-
var iconUtils_default = processIconChildren;
|
|
121
|
-
|
|
122
114
|
//#endregion
|
|
123
115
|
//#region src/helpers/jscodeshift/jsxElementUtils.ts
|
|
124
116
|
/**
|
|
125
117
|
* Rename a JSX element name if it is a JSXIdentifier.
|
|
126
118
|
*/
|
|
127
119
|
const setNameIfJSXIdentifier = (elementName, newName) => {
|
|
128
|
-
if (elementName
|
|
120
|
+
if (elementName?.type === "JSXIdentifier") return {
|
|
129
121
|
...elementName,
|
|
130
122
|
name: newName
|
|
131
123
|
};
|
|
@@ -173,7 +165,6 @@ const removeAttributeByName = (j, openingElement, attributeName) => {
|
|
|
173
165
|
return !(attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === attributeName);
|
|
174
166
|
});
|
|
175
167
|
};
|
|
176
|
-
|
|
177
168
|
//#endregion
|
|
178
169
|
//#region src/helpers/jscodeshift/jsxReportingUtils.ts
|
|
179
170
|
/**
|
|
@@ -346,7 +337,6 @@ const createReporter = (j, issues) => {
|
|
|
346
337
|
issues
|
|
347
338
|
});
|
|
348
339
|
};
|
|
349
|
-
|
|
350
340
|
//#endregion
|
|
351
341
|
//#region src/transforms/button/transformer.ts
|
|
352
342
|
const parser = "tsx";
|
|
@@ -483,9 +473,9 @@ const transformer = (file, api, options) => {
|
|
|
483
473
|
return priority;
|
|
484
474
|
};
|
|
485
475
|
const reporter = createReporter(j, manualReviewIssues);
|
|
486
|
-
const { exists: hasButtonImport, aliases: buttonAliases, resolvedName: buttonName, conflictingImports: conflictingButtonImport } =
|
|
476
|
+
const { exists: hasButtonImport, aliases: buttonAliases, resolvedName: buttonName, conflictingImports: conflictingButtonImport } = hasImport(root, "@transferwise/components", "Button", j);
|
|
487
477
|
if (conflictingButtonImport.length) conflictingButtonImport.forEach((node) => reporter.reportConflictingImports(node));
|
|
488
|
-
const { exists: hasActionButtonImport, remove: removeActionButtonImport, aliases: actionButtonAliases } =
|
|
478
|
+
const { exists: hasActionButtonImport, remove: removeActionButtonImport, aliases: actionButtonAliases } = hasImport(root, "@transferwise/components", "ActionButton", j);
|
|
489
479
|
if (!hasButtonImport && !hasActionButtonImport) return file.source;
|
|
490
480
|
const iconImports = /* @__PURE__ */ new Set();
|
|
491
481
|
root.find(j.ImportDeclaration, { source: { value: "@transferwise/icons" } }).forEach((path) => {
|
|
@@ -497,12 +487,12 @@ const transformer = (file, api, options) => {
|
|
|
497
487
|
});
|
|
498
488
|
});
|
|
499
489
|
if (hasActionButtonImport) {
|
|
500
|
-
if (!hasButtonImport)
|
|
490
|
+
if (!hasButtonImport) addImport(root, "@transferwise/components", "Button", j);
|
|
501
491
|
findJSXElementsByName(root, j)("ActionButton", actionButtonAliases).forEach((path) => {
|
|
502
492
|
const { openingElement, closingElement } = path.node;
|
|
503
493
|
openingElement.name = setNameIfJSXIdentifier(openingElement.name, buttonName);
|
|
504
494
|
if (closingElement) closingElement.name = setNameIfJSXIdentifier(closingElement.name, buttonName);
|
|
505
|
-
|
|
495
|
+
processIconChildren(j, path.node.children, iconImports, openingElement);
|
|
506
496
|
if ((openingElement.attributes ?? []).some((attr) => attr.type === "JSXSpreadAttribute")) reporter.reportSpreadProps(path);
|
|
507
497
|
const legacyPropNames = [
|
|
508
498
|
"priority",
|
|
@@ -511,7 +501,7 @@ const transformer = (file, api, options) => {
|
|
|
511
501
|
];
|
|
512
502
|
const legacyProps = {};
|
|
513
503
|
openingElement.attributes?.forEach((attr) => {
|
|
514
|
-
if (attr.type === "JSXAttribute" && attr.name
|
|
504
|
+
if (attr.type === "JSXAttribute" && attr.name?.type === "JSXIdentifier") {
|
|
515
505
|
const { name } = attr.name;
|
|
516
506
|
if (legacyPropNames.includes(name)) {
|
|
517
507
|
if (attr.value) {
|
|
@@ -551,7 +541,7 @@ const transformer = (file, api, options) => {
|
|
|
551
541
|
attribute: j.jsxAttribute(j.jsxIdentifier("v2")),
|
|
552
542
|
name: "v2"
|
|
553
543
|
}]);
|
|
554
|
-
|
|
544
|
+
processIconChildren(j, path.node.children, iconImports, openingElement);
|
|
555
545
|
const legacyProps = {};
|
|
556
546
|
const legacyPropNames = [
|
|
557
547
|
"priority",
|
|
@@ -561,7 +551,7 @@ const transformer = (file, api, options) => {
|
|
|
561
551
|
"sentiment"
|
|
562
552
|
];
|
|
563
553
|
openingElement.attributes?.forEach((attr) => {
|
|
564
|
-
if (attr.type === "JSXAttribute" && attr.name
|
|
554
|
+
if (attr.type === "JSXAttribute" && attr.name?.type === "JSXIdentifier") {
|
|
565
555
|
const { name } = attr.name;
|
|
566
556
|
if (legacyPropNames.includes(name)) if (attr.value) {
|
|
567
557
|
if (attr.value.type === "StringLiteral") legacyProps[name] = attr.value.value;
|
|
@@ -695,7 +685,7 @@ const transformer = (file, api, options) => {
|
|
|
695
685
|
} else if (rawType !== void 0 || rawHtmlType !== void 0) reporter.reportAmbiguousExpression(path, typeof rawType === "string" ? "type" : "htmlType");
|
|
696
686
|
}
|
|
697
687
|
if ("sentiment" in legacyProps) {
|
|
698
|
-
if (!openingElement.attributes?.some((attr) => attr.type === "JSXAttribute" && attr.name
|
|
688
|
+
if (!openingElement.attributes?.some((attr) => attr.type === "JSXAttribute" && attr.name?.name === "sentiment")) {
|
|
699
689
|
const rawValue = legacyProps.sentiment;
|
|
700
690
|
if (rawValue === "negative") {
|
|
701
691
|
removeAttributeByName(j, openingElement, "sentiment");
|
|
@@ -729,13 +719,11 @@ const transformer = (file, api, options) => {
|
|
|
729
719
|
if ((openingElement.attributes ?? []).some((attr) => attr.type === "JSXSpreadAttribute")) reporter.reportSpreadProps(path);
|
|
730
720
|
});
|
|
731
721
|
if (manualReviewIssues.length > 0) manualReviewIssues.forEach(async (issue) => {
|
|
732
|
-
await
|
|
722
|
+
await reportManualReview(file.path, issue);
|
|
733
723
|
});
|
|
734
724
|
return root.toSource();
|
|
735
725
|
};
|
|
736
|
-
var transformer_default = transformer;
|
|
737
|
-
|
|
738
726
|
//#endregion
|
|
739
|
-
|
|
740
|
-
|
|
727
|
+
export { transformer as default, parser };
|
|
728
|
+
|
|
741
729
|
//# sourceMappingURL=transformer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transformer.js","names":["result: ImportSpecifier[]","sizeMap: Record<string, string>","j: JSCodeshift","manualReviewIssues: string[]","hasImport","legacyProps: LegacyProps","resolvedType: string | undefined","typeValue: string | undefined","asValue: string | null","reportManualReview"],"sources":["../../../src/helpers/jscodeshift/addImport.ts","../../../src/helpers/jscodeshift/hasImport.ts","../../../src/helpers/jscodeshift/iconUtils.ts","../../../src/helpers/jscodeshift/jsxElementUtils.ts","../../../src/helpers/jscodeshift/jsxReportingUtils.ts","../../../src/transforms/button/transformer.ts"],"sourcesContent":["import type { Collection, JSCodeshift } from 'jscodeshift';\n\n/**\n * Adds a named import if it doesn't already exist.\n */\nfunction addImport(\n root: Collection,\n sourceValue: string,\n importName: string,\n j: JSCodeshift,\n): void {\n const existingImports = root.find(j.ImportDeclaration, {\n source: { value: sourceValue },\n });\n\n if (existingImports.size() > 0) {\n const namedImport = existingImports.find(j.ImportSpecifier, {\n imported: { name: importName },\n });\n\n if (namedImport.size() > 0) {\n return;\n }\n\n existingImports.forEach((path) => {\n if (path.node.specifiers) {\n path.node.specifiers.push(j.importSpecifier(j.identifier(importName)));\n }\n });\n } else {\n const newImport = j.importDeclaration(\n [j.importSpecifier(j.identifier(importName))],\n j.literal(sourceValue),\n );\n\n const firstImport = root.find(j.ImportDeclaration).at(0);\n if (firstImport.size() > 0) {\n firstImport.insertBefore(newImport);\n } else {\n // Insert at the beginning of the program\n const program = root.find(j.Program);\n if (program.size() > 0) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n program.get('body', 0).insertBefore(newImport);\n }\n }\n }\n}\n\nexport default addImport;\n","import type { ASTPath, Collection, ImportSpecifier, JSCodeshift } from 'jscodeshift';\n\n/**\n * Checks if a specific import exists in the given root collection and provides\n * a method to remove it if found.\n */\nfunction hasImport(\n root: Collection,\n sourceValue: string,\n importName: string,\n j: JSCodeshift,\n): {\n exists: boolean;\n remove: () => void;\n aliases?: Collection<ImportSpecifier>;\n resolvedName: string;\n conflictingImports: ImportSpecifier[];\n} {\n const importDeclarations = root.find(j.ImportDeclaration, {\n source: { value: sourceValue },\n });\n\n /**\n * Finds all ImportSpecifier nodes that expose `importName` but\n * from a different source than `sourceValue`.\n */\n const conflictingImports = ((): ImportSpecifier[] => {\n const result: ImportSpecifier[] = [];\n root\n .find(j.ImportDeclaration)\n .filter((path) => path.node.source.value !== sourceValue)\n .forEach((path) => {\n for (const specifier of path.node.specifiers ?? []) {\n if (\n specifier.type === 'ImportSpecifier' &&\n specifier.imported.name === importName &&\n specifier.local?.name === importName\n ) {\n result.push(specifier);\n }\n }\n });\n return result;\n })();\n\n if (importDeclarations.size() === 0) {\n return {\n exists: false,\n remove: () => {},\n resolvedName: importName,\n conflictingImports,\n };\n }\n\n const namedImport = importDeclarations.find(j.ImportSpecifier, {\n imported: { name: importName },\n });\n\n const defaultImport = importDeclarations.find(j.ImportDefaultSpecifier, {\n local: { name: importName },\n });\n\n const aliasImport = importDeclarations.find(j.ImportSpecifier).filter((path) => {\n return (\n path.node.imported.name === importName && path.node.imported.name !== path.node.local?.name\n );\n });\n\n const exists = namedImport.size() > 0 || defaultImport.size() > 0;\n\n const resolveName = (): string => {\n if (aliasImport.size() > 0) {\n const importPath = aliasImport.get(0) as ASTPath<ImportSpecifier>;\n const localName = importPath.node.local?.name;\n\n if (typeof localName === 'string') {\n return localName;\n }\n\n if (\n localName &&\n typeof localName === 'object' &&\n 'name' in localName &&\n typeof localName.name === 'string'\n ) {\n return localName.name;\n }\n\n return importName;\n }\n\n return importName;\n };\n\n const remove = () => {\n importDeclarations.forEach((path) => {\n const filteredSpecifiers =\n path.node.specifiers?.filter((specifier) => {\n if (specifier.type === 'ImportSpecifier' && specifier.imported.name === importName) {\n return false;\n }\n if (specifier.type === 'ImportDefaultSpecifier' && specifier.local?.name === importName) {\n return false;\n }\n return true;\n }) ?? [];\n\n if (filteredSpecifiers.length === 0) {\n path.prune();\n } else {\n j(path).replaceWith(\n j.importDeclaration(filteredSpecifiers, path.node.source, path.node.importKind),\n );\n }\n });\n };\n\n return {\n exists,\n remove,\n aliases: aliasImport,\n resolvedName: resolveName(),\n conflictingImports,\n };\n}\n\nexport default hasImport;\n","import type { JSCodeshift, JSXElement, JSXExpressionContainer } from 'jscodeshift';\n\n/**\n * Process children of a JSX element to detect icon components and add iconStart or iconEnd attributes accordingly.\n * This is specific to icon handling but can be reused in codemods dealing with icon children.\n */\nconst processIconChildren = (\n j: JSCodeshift,\n children: (JSXElement | JSXExpressionContainer | unknown)[] | undefined,\n iconImports: Set<string>,\n openingElement: JSXElement['openingElement'],\n) => {\n if (!children || !openingElement.attributes) return;\n\n const unwrapJsxElement = (node: unknown): JSXElement | unknown => {\n if (\n typeof node === 'object' &&\n node !== null &&\n 'type' in node &&\n node.type === 'JSXExpressionContainer' &&\n j.JSXElement.check((node as JSXExpressionContainer).expression)\n ) {\n return (node as JSXExpressionContainer).expression;\n }\n return node;\n };\n\n const totalChildren = children.length;\n\n // Find index of icon child\n const iconChildIndex = children.findIndex((child) => {\n const unwrapped = unwrapJsxElement(child);\n return (\n j.JSXElement.check(unwrapped) &&\n unwrapped.openingElement.name.type === 'JSXIdentifier' &&\n iconImports.has(unwrapped.openingElement.name.name)\n );\n });\n\n if (iconChildIndex === -1) return;\n\n const iconChild = unwrapJsxElement(children[iconChildIndex]) as JSXElement;\n\n if (!iconChild || iconChild.openingElement.name.type !== 'JSXIdentifier') return;\n\n const iconName = iconChild.openingElement.name.name;\n\n // Determine if icon is closer to start or end\n const distanceToStart = iconChildIndex;\n const distanceToEnd = totalChildren - 1 - iconChildIndex;\n const iconPropName = distanceToStart <= distanceToEnd ? 'addonStart' : 'addonEnd';\n\n // Build: { type: 'icon', value: <IconName /> }\n const iconObject = j.objectExpression([\n j.property('init', j.identifier('type'), j.literal('icon')),\n j.property('init', j.identifier('value'), iconChild),\n ]);\n const iconProp = j.jsxAttribute(\n j.jsxIdentifier(iconPropName),\n j.jsxExpressionContainer(iconObject),\n );\n\n openingElement.attributes.push(iconProp);\n\n // Remove the icon child\n children.splice(iconChildIndex, 1);\n\n // Helper to check if a child is whitespace-only JSXText\n const isWhitespaceJsxText = (node: unknown): boolean => {\n return (\n typeof node === 'object' &&\n node !== null &&\n (node as { type?: unknown }).type === 'JSXText' &&\n typeof (node as { value?: string }).value === 'string' &&\n (node as { value?: string }).value!.trim() === ''\n );\n };\n\n // Remove adjacent whitespace-only JSXText node if any\n if (iconChildIndex - 1 >= 0 && isWhitespaceJsxText(children[iconChildIndex - 1])) {\n children.splice(iconChildIndex - 1, 1);\n } else if (isWhitespaceJsxText(children[iconChildIndex])) {\n children.splice(iconChildIndex, 1);\n }\n};\n\nexport default processIconChildren;\n","import type {\n Collection,\n ImportSpecifier,\n JSCodeshift,\n JSXAttribute,\n JSXElement,\n JSXIdentifier,\n JSXMemberExpression,\n JSXNamespacedName,\n JSXSpreadAttribute,\n} from 'jscodeshift';\n\n/**\n * Rename a JSX element name if it is a JSXIdentifier.\n */\nexport const setNameIfJSXIdentifier = (\n elementName: JSXIdentifier | JSXNamespacedName | JSXMemberExpression | undefined,\n newName: string,\n): JSXIdentifier | JSXNamespacedName | JSXMemberExpression | undefined => {\n if (elementName && elementName.type === 'JSXIdentifier') {\n return { ...elementName, name: newName };\n }\n return elementName;\n};\n\n/**\n * Check if a list of attributes contains a specific attribute by name.\n */\nexport const hasAttribute = (\n attributes: (JSXAttribute | JSXSpreadAttribute)[] | undefined,\n attributeName: string,\n): boolean => {\n return (\n Array.isArray(attributes) &&\n attributes.some(\n (attr): attr is JSXAttribute =>\n attr.type === 'JSXAttribute' &&\n attr.name.type === 'JSXIdentifier' &&\n attr.name.name === attributeName,\n )\n );\n};\n\n/**\n * Check if a JSX element's openingElement has a specific attribute.\n */\nexport const hasAttributeOnElement = (\n element: JSXElement['openingElement'],\n attributeName: string,\n): boolean => {\n return hasAttribute(element.attributes, attributeName);\n};\n\n/**\n * Add specified attributes to a JSX element's openingElement if they are not already present.\n */\nexport const addAttributesIfMissing = (\n j: JSCodeshift,\n openingElement: JSXElement['openingElement'],\n attributesToAdd: { attribute: JSXAttribute; name: string }[],\n) => {\n if (!Array.isArray(openingElement.attributes)) return;\n const attrs = openingElement.attributes;\n attributesToAdd.forEach(({ attribute, name }) => {\n if (!hasAttributeOnElement(openingElement, name)) {\n attrs.push(attribute);\n }\n });\n};\n\n/**\n * Returns a collection of JSX elements that match the specified\n * exported name or names of the found aliases.\n */\nexport const findJSXElementsByName =\n (root: Collection, j: JSCodeshift) =>\n (exportedName: string, aliases?: Collection<ImportSpecifier>) => {\n const aliasNames = aliases?.size()\n ? aliases.paths().map((path) => path.node.local?.name as string)\n : [];\n\n return root.find(j.JSXElement).filter((path) => {\n const { name } = path.node.openingElement;\n return (\n name.type === 'JSXIdentifier' &&\n (name.name === exportedName || aliasNames.includes(name.name))\n );\n });\n };\n\n/**\n * Removes an attribute by name from a JSX element's openingElement.\n */\nexport const removeAttributeByName = (\n j: JSCodeshift,\n openingElement: JSXElement['openingElement'],\n attributeName: string,\n) => {\n if (!Array.isArray(openingElement.attributes)) return;\n // eslint-disable-next-line no-param-reassign\n openingElement.attributes = openingElement.attributes.filter((attr) => {\n return !(\n attr.type === 'JSXAttribute' &&\n attr.name.type === 'JSXIdentifier' &&\n attr.name.name === attributeName\n );\n });\n};\n","import type {\n ASTPath,\n ImportSpecifier,\n JSCodeshift,\n JSXAttribute,\n JSXElement,\n Node,\n} from 'jscodeshift';\n\nexport interface ReporterOptions {\n jscodeshift: JSCodeshift;\n issues: string[];\n}\n\n/**\n * CodemodReporter is a utility class for reporting issues found during codemod transformations.\n * It provides methods to report issues related to JSX elements, props, and attributes.\n *\n * @example\n * ```typescript\n * const issues: string[] = [];\n * const reporter = createReporter(j, issues);\n *\n * // Report a deprecated prop\n * reporter.reportDeprecatedProp(buttonElement, 'flat', 'variant=\"text\"');\n *\n * // Report complex expression that needs review\n * reporter.reportAmbiguousExpression(element, 'size');\n *\n * // Auto-detect common issues\n * reporter.reportAttributeIssues(element);\n * ```\n */\nexport class CodemodReporter {\n private readonly j: JSCodeshift;\n private readonly issues: string[];\n\n constructor(options: ReporterOptions) {\n this.j = options.jscodeshift;\n this.issues = options.issues;\n }\n\n /**\n * Reports an issue with a JSX element\n */\n reportElement(element: JSXElement | ASTPath<JSXElement>, reason: string): void {\n const node = this.getNode(element);\n const componentName = this.getComponentName(node);\n const line = this.getLineNumber(node);\n\n this.addIssue(`Manual review required: <${componentName}> at line ${line} ${reason}.`);\n }\n\n /**\n * Reports an issue with a specific prop\n */\n reportProp(element: JSXElement | ASTPath<JSXElement>, propName: string, reason: string): void {\n const node = this.getNode(element);\n const componentName = this.getComponentName(node);\n const line = this.getLineNumber(node);\n\n this.addIssue(\n `Manual review required: prop \"${propName}\" on <${componentName}> at line ${line} ${reason}.`,\n );\n }\n\n /**\n * Reports an issue with a JSX attribute directly\n */\n reportAttribute(\n attr: JSXAttribute,\n element: JSXElement | ASTPath<JSXElement>,\n reason?: string,\n ): void {\n const node = this.getNode(element);\n const componentName = this.getComponentName(node);\n const propName = this.getAttributeName(attr);\n const line = this.getLineNumber(attr) || this.getLineNumber(node);\n\n const defaultReason = this.getAttributeReason(attr);\n const finalReason = reason || defaultReason;\n\n this.addIssue(\n `Manual review required: prop \"${propName}\" on <${componentName}> at line ${line} ${finalReason}.`,\n );\n }\n\n /**\n * Reports spread props on an element\n */\n reportSpreadProps(element: JSXElement | ASTPath<JSXElement>): void {\n this.reportElement(element, 'contains spread props that need manual review');\n }\n\n /**\n * Reports conflicting prop and children\n */\n reportPropWithChildren(element: JSXElement | ASTPath<JSXElement>, propName: string): void {\n this.reportProp(\n element,\n propName,\n `conflicts with children - both \"${propName}\" prop and children are present`,\n );\n }\n\n /**\n * Reports unsupported prop value\n */\n reportUnsupportedValue(\n element: JSXElement | ASTPath<JSXElement>,\n propName: string,\n value: string,\n ): void {\n this.reportProp(element, propName, `has unsupported value \"${value}\"`);\n }\n\n /**\n * Reports ambiguous expression in prop\n */\n reportAmbiguousExpression(element: JSXElement | ASTPath<JSXElement>, propName: string): void {\n this.reportProp(element, propName, 'contains a complex expression that needs manual review');\n }\n\n /**\n * Reports ambiguous children (like dynamic icons)\n */\n reportAmbiguousChildren(element: JSXElement | ASTPath<JSXElement>, childType = 'content'): void {\n this.reportElement(element, `contains ambiguous ${childType} that needs manual review`);\n }\n\n /**\n * Reports deprecated prop usage\n */\n reportDeprecatedProp(\n element: JSXElement | ASTPath<JSXElement>,\n propName: string,\n alternative?: string,\n ): void {\n const suggestion = alternative ? ` Use ${alternative} instead` : '';\n this.reportProp(element, propName, `is deprecated${suggestion}`);\n }\n\n /**\n * Reports missing required prop\n */\n reportMissingRequiredProp(element: JSXElement | ASTPath<JSXElement>, propName: string): void {\n this.reportProp(element, propName, 'is required but missing');\n }\n\n /**\n * Reports conflicting props\n */\n reportConflictingProps(element: JSXElement | ASTPath<JSXElement>, propNames: string[]): void {\n const propList = propNames.map((name) => `\"${name}\"`).join(', ');\n this.reportElement(element, `has conflicting props: ${propList} cannot be used together`);\n }\n\n /**\n * Auto-detects and reports common attribute issues\n */\n reportAttributeIssues(element: JSXElement | ASTPath<JSXElement>): void {\n const node = this.getNode(element);\n const { attributes } = node.openingElement;\n\n if (!attributes) return;\n\n // Check for spread props\n if (attributes.some((attr) => attr.type === 'JSXSpreadAttribute')) {\n this.reportSpreadProps(element);\n }\n\n // Check for complex expressions in attributes\n attributes.forEach((attr) => {\n if (attr.type === 'JSXAttribute' && attr.value?.type === 'JSXExpressionContainer') {\n this.reportAttribute(attr, element);\n }\n });\n }\n\n /**\n * Finds and reports instances of components that are under an alias (imported with a different name)\n */\n reportAliases(element: JSXElement | ASTPath<JSXElement>): void {\n this.reportElement(element, 'is used via an import alias and needs manual review');\n }\n\n /**\n * Finds and reports instances of non-DS import declarations that conflict with the component name\n */\n reportConflictingImports(node: ImportSpecifier): void {\n this.addIssue(\n `Manual review required: Non-WDS package resulting in an import conflict at line ${this.getLineNumber(node)}.`,\n );\n }\n\n /**\n * Reports enum usage for future conversion tracking\n */\n reportEnumUsage(\n element: JSXElement | ASTPath<JSXElement>,\n propName: string,\n enumValue: string,\n ): void {\n this.reportProp(\n element,\n propName,\n `uses enum value \"${enumValue}\" which has been preserved but should be migrated to a string literal in the future`,\n );\n }\n\n // Private helper methods\n private getNode(element: JSXElement | ASTPath<JSXElement>): JSXElement {\n return 'node' in element ? element.node : element;\n }\n\n private getComponentName(node: JSXElement): string {\n const { name } = node.openingElement;\n if (name.type === 'JSXIdentifier') {\n return name.name;\n }\n // Handle JSXMemberExpression, JSXNamespacedName, etc.\n return this.j(name).toSource();\n }\n\n private getLineNumber(node: JSXElement | JSXAttribute | Node): string {\n return node.loc?.start.line?.toString() || 'unknown';\n }\n\n private getAttributeName(attr: JSXAttribute): string {\n if (attr.name.type === 'JSXIdentifier') {\n return attr.name.name;\n }\n return this.j(attr.name).toSource();\n }\n\n private getAttributeReason(attr: JSXAttribute): string {\n if (!attr.value) return 'has no value';\n\n if (attr.value.type === 'JSXExpressionContainer') {\n const expr = attr.value.expression;\n const expressionType = expr.type.replace('Expression', '').toLowerCase();\n\n // Show actual value for simple cases\n if (expr.type === 'Identifier' || expr.type === 'MemberExpression') {\n const valueText = this.j(expr).toSource();\n return `contains a ${expressionType} (${valueText})`;\n }\n\n return `contains a complex ${expressionType} expression`;\n }\n\n return 'needs manual review';\n }\n\n private addIssue(message: string): void {\n this.issues.push(message);\n }\n}\n\nexport const createReporter = (j: JSCodeshift, issues: string[]): CodemodReporter => {\n return new CodemodReporter({ jscodeshift: j, issues });\n};\n","import type { API, FileInfo, JSCodeshift, Options } from 'jscodeshift';\n\nimport { reportManualReview } from '../../controller/helpers';\nimport {\n addAttributesIfMissing,\n addImport,\n createReporter,\n findJSXElementsByName,\n hasAttributeOnElement,\n hasImport,\n processIconChildren,\n removeAttributeByName,\n setNameIfJSXIdentifier,\n} from '../../helpers/jscodeshift';\n\nexport const parser = 'tsx';\n\ninterface LegacyProps {\n priority?: string;\n size?: string;\n type?: string;\n htmlType?: string;\n sentiment?: string;\n [key: string]: unknown;\n}\n\ninterface ExtendedOptions extends Options {\n accentSecondaryMapping?: string;\n positiveSecondaryMapping?: string;\n}\n\ntype PriorityMapping = Record<string, Record<string, string>>;\n\nconst buildPriorityMapping = (opts: Options): PriorityMapping => {\n const extendedOpts = opts as ExtendedOptions;\n const accentSecondary = extendedOpts.accentSecondaryMapping || 'secondary-neutral';\n const positiveSecondary = extendedOpts.positiveSecondaryMapping || 'secondary-neutral';\n return {\n accent: {\n primary: 'primary',\n secondary: accentSecondary,\n tertiary: 'tertiary',\n },\n positive: {\n primary: 'primary',\n secondary: positiveSecondary,\n tertiary: positiveSecondary,\n },\n negative: {\n primary: 'primary',\n secondary: 'secondary',\n tertiary: 'secondary',\n },\n primary: {\n primary: 'primary',\n secondary: accentSecondary,\n tertiary: 'tertiary',\n },\n pay: {\n primary: 'primary',\n secondary: accentSecondary,\n tertiary: accentSecondary,\n },\n };\n};\n\nconst sizeMap: Record<string, string> = {\n EXTRA_SMALL: 'xs',\n SMALL: 'sm',\n MEDIUM: 'md',\n LARGE: 'lg',\n EXTRA_LARGE: 'xl',\n xs: 'sm',\n sm: 'sm',\n md: 'md',\n lg: 'lg',\n xl: 'xl',\n};\n\nconst resolveSize = (size?: string): string | undefined => {\n if (!size) return size;\n const match = /^Size\\.(EXTRA_SMALL|SMALL|MEDIUM|LARGE|EXTRA_LARGE)$/u.exec(size);\n if (match) {\n return sizeMap[match[1]];\n }\n return sizeMap[size] || size;\n};\n\nconst legacyButtonTypes = [\n 'accent',\n 'negative',\n 'positive',\n 'primary',\n 'pay',\n 'secondary',\n 'danger',\n 'link',\n];\n\nconst getConsistentTypeConversions = (\n type?: string,\n): { priority?: string; sentiment?: string } | null => {\n const consistentTypeConversions: Record<string, { priority?: string; sentiment?: string }> = {\n secondary: { priority: 'secondary-neutral' },\n link: { priority: 'tertiary' },\n danger: { priority: 'secondary', sentiment: 'negative' },\n };\n\n return consistentTypeConversions[type || ''] || null;\n};\n\nconst convertEnumValue = (value?: string): string | undefined => {\n if (!value) return value;\n const strippedValue = value.replace(/^['\"]|['\"]$/gu, '');\n const enumMapping: Record<string, string> = {\n 'Priority.SECONDARY': 'secondary',\n 'Priority.PRIMARY': 'primary',\n 'Priority.TERTIARY': 'tertiary',\n 'ControlType.NEGATIVE': 'negative',\n 'ControlType.POSITIVE': 'positive',\n 'ControlType.ACCENT': 'accent',\n };\n return enumMapping[strippedValue] || strippedValue;\n};\n\n/**\n * Detects if a value is an enum pattern (e.g., Priority.PRIMARY, ControlType.ACCENT, Size.LARGE, Type.PRIMARY)\n */\nconst isEnumValue = (value: string): boolean => {\n const enumPatterns = [\n /^Priority\\.(PRIMARY|SECONDARY|TERTIARY|SECONDARY_NEUTRAL)$/u,\n /^ControlType\\.(ACCENT|NEGATIVE|POSITIVE)$/u,\n /^Size\\.(EXTRA_SMALL|SMALL|MEDIUM|LARGE|EXTRA_LARGE)$/u,\n /^Type\\.(PRIMARY|SECONDARY|TERTIARY|PAY|DANGER|LINK|ACCENT|POSITIVE|NEGATIVE)$/u,\n ];\n return enumPatterns.some((pattern) => pattern.test(value));\n};\n\n/**\n * Maps enum values to their expected string equivalents for validation purposes\n * This is ONLY used to validate the enum maps to a supported value\n */\nconst getEnumEquivalent = (value: string): string | undefined => {\n const enumMapping: Record<string, string> = {\n 'Priority.PRIMARY': 'primary',\n 'Priority.SECONDARY': 'secondary',\n 'Priority.TERTIARY': 'tertiary',\n 'Priority.SECONDARY_NEUTRAL': 'secondary-neutral',\n 'ControlType.NEGATIVE': 'negative',\n 'ControlType.POSITIVE': 'positive',\n 'ControlType.ACCENT': 'accent',\n 'Size.EXTRA_SMALL': 'sm',\n 'Size.SMALL': 'sm',\n 'Size.MEDIUM': 'md',\n 'Size.LARGE': 'lg',\n 'Size.EXTRA_LARGE': 'xl',\n };\n return enumMapping[value];\n};\n\n/**\n * This transform function modifies the Button and ActionButton components from the @transferwise/components library.\n * It updates the ActionButton component to use the Button component with specific attributes and mappings.\n * It also processes icon children and removes legacy props.\n *\n * @param {FileInfo} file - The file information object.\n * @param {API} api - The API object for jscodeshift.\n * @param {Options} options - The options object for jscodeshift.\n * @returns {string} - The transformed source code.\n */\nconst transformer = (file: FileInfo, api: API, options: Options) => {\n const j: JSCodeshift = api.jscodeshift;\n const root = j(file.source);\n const manualReviewIssues: string[] = [];\n const priorityMapping = buildPriorityMapping(options);\n\n const resolvePriority = (type?: string, priority?: string): string | undefined => {\n if (type && priority) {\n return priorityMapping[type]?.[priority] || priority;\n }\n return priority;\n };\n\n // Create reporter instance\n const reporter = createReporter(j, manualReviewIssues);\n\n const {\n exists: hasButtonImport,\n aliases: buttonAliases,\n resolvedName: buttonName,\n conflictingImports: conflictingButtonImport,\n } = hasImport(root, '@transferwise/components', 'Button', j);\n\n if (conflictingButtonImport.length) {\n conflictingButtonImport.forEach((node) => reporter.reportConflictingImports(node));\n }\n\n const {\n exists: hasActionButtonImport,\n remove: removeActionButtonImport,\n aliases: actionButtonAliases,\n } = hasImport(root, '@transferwise/components', 'ActionButton', j);\n\n if (!hasButtonImport && !hasActionButtonImport) {\n return file.source;\n }\n\n const iconImports = new Set<string>();\n root.find(j.ImportDeclaration, { source: { value: '@transferwise/icons' } }).forEach((path) => {\n path.node.specifiers?.forEach((specifier) => {\n if (\n (specifier.type === 'ImportDefaultSpecifier' || specifier.type === 'ImportSpecifier') &&\n specifier.local\n ) {\n const localName = (specifier.local as { name: string }).name;\n iconImports.add(localName);\n }\n });\n });\n\n if (hasActionButtonImport) {\n if (!hasButtonImport) {\n addImport(root, '@transferwise/components', 'Button', j);\n }\n\n const instances = findJSXElementsByName(root, j)('ActionButton', actionButtonAliases);\n\n instances.forEach((path) => {\n const { openingElement, closingElement } = path.node;\n\n openingElement.name = setNameIfJSXIdentifier(openingElement.name, buttonName)!;\n if (closingElement) {\n closingElement.name = setNameIfJSXIdentifier(closingElement.name, buttonName)!;\n }\n\n processIconChildren(j, path.node.children, iconImports, openingElement);\n\n if ((openingElement.attributes ?? []).some((attr) => attr.type === 'JSXSpreadAttribute')) {\n reporter.reportSpreadProps(path);\n }\n\n const legacyPropNames = ['priority', 'text', 'size'];\n const legacyProps: LegacyProps = {};\n\n openingElement.attributes?.forEach((attr) => {\n if (attr.type === 'JSXAttribute' && attr.name && attr.name.type === 'JSXIdentifier') {\n const { name } = attr.name;\n if (legacyPropNames.includes(name)) {\n if (attr.value) {\n if (attr.value.type === 'StringLiteral') {\n legacyProps[name] = attr.value.value;\n } else if (attr.value.type === 'JSXExpressionContainer') {\n legacyProps[name] = convertEnumValue(String(j(attr.value.expression).toSource()));\n }\n }\n }\n }\n });\n\n const hasTextProp = 'text' in legacyProps;\n const hasChildren =\n path.node.children?.some(\n (child) =>\n (child.type === 'JSXText' && child.value.trim() !== '') ||\n child.type === 'JSXElement' ||\n child.type === 'JSXExpressionContainer',\n ) ||\n (path.node.children && path.node.children?.length > 0);\n\n if (hasTextProp && hasChildren) {\n reporter.reportPropWithChildren(path, 'text');\n } else if (hasTextProp && !hasChildren && openingElement.selfClosing) {\n // Self-closing tag with text prop but no children, so we can convert to a normal element with children\n path.replace(\n j.jsxElement(\n j.jsxOpeningElement(openingElement.name, openingElement.attributes),\n j.jsxClosingElement(openingElement.name),\n [j.jsxText((legacyProps.text as string) || '')],\n ),\n );\n }\n\n addAttributesIfMissing(j, path.node.openingElement, [\n { attribute: j.jsxAttribute(j.jsxIdentifier('v2')), name: 'v2' },\n { attribute: j.jsxAttribute(j.jsxIdentifier('size'), j.literal('sm')), name: 'size' },\n ]);\n\n (path.node.children || []).forEach((child) => {\n if (child.type === 'JSXExpressionContainer') {\n const expr = child.expression;\n if (\n expr.type === 'ConditionalExpression' ||\n expr.type === 'CallExpression' ||\n expr.type === 'Identifier' ||\n expr.type === 'MemberExpression'\n ) {\n reporter.reportAmbiguousChildren(path, 'icon');\n }\n }\n });\n });\n\n removeActionButtonImport();\n }\n\n if (hasButtonImport) {\n const instances = findJSXElementsByName(root, j)('Button', buttonAliases);\n\n instances.forEach((path) => {\n const { openingElement } = path.node;\n\n if (hasAttributeOnElement(openingElement, 'v2')) return;\n\n const hasJSXChildren = path.node.children?.some(\n (child) =>\n (child.type === 'JSXText' && child.value.trim() !== '') ||\n child.type === 'JSXElement' ||\n (child.type === 'JSXFragment' && child.children && child.children.length > 0) ||\n (child.type === 'JSXExpressionContainer' &&\n child.expression.type !== 'JSXEmptyExpression'),\n );\n const hasChildrenAsProp = openingElement.attributes?.some(\n (attr) =>\n attr.type === 'JSXAttribute' &&\n attr.name?.type === 'JSXIdentifier' &&\n attr.name.name === 'children',\n );\n if (!hasJSXChildren && !hasChildrenAsProp) return;\n\n addAttributesIfMissing(j, openingElement, [\n { attribute: j.jsxAttribute(j.jsxIdentifier('v2')), name: 'v2' },\n ]);\n processIconChildren(j, path.node.children, iconImports, openingElement);\n\n const legacyProps: LegacyProps = {};\n const legacyPropNames = ['priority', 'size', 'type', 'htmlType', 'sentiment'];\n\n openingElement.attributes?.forEach((attr) => {\n if (attr.type === 'JSXAttribute' && attr.name && attr.name.type === 'JSXIdentifier') {\n const { name } = attr.name;\n if (legacyPropNames.includes(name)) {\n if (attr.value) {\n if (attr.value.type === 'StringLiteral') {\n legacyProps[name] = attr.value.value;\n } else if (attr.value.type === 'JSXExpressionContainer') {\n const expressionSource = String(j(attr.value.expression).toSource());\n legacyProps[name] = expressionSource;\n }\n } else {\n legacyProps[name] = undefined;\n }\n }\n }\n });\n\n if ('size' in legacyProps) {\n const rawValue = legacyProps.size;\n\n if (typeof rawValue === 'string' && isEnumValue(rawValue)) {\n const equivalent = getEnumEquivalent(rawValue);\n const supportedSizes = ['sm', 'md', 'lg', 'xl'];\n\n if (equivalent && supportedSizes.includes(equivalent)) {\n } else {\n reporter.reportUnsupportedValue(path, 'size', rawValue);\n }\n } else {\n const resolved = resolveSize(rawValue);\n const supportedSizes = ['sm', 'md', 'lg', 'xl'];\n if (\n typeof rawValue === 'string' &&\n typeof resolved === 'string' &&\n supportedSizes.includes(resolved)\n ) {\n removeAttributeByName(j, openingElement, 'size');\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('size'), j.literal(resolved)),\n );\n } else if (typeof rawValue === 'string') {\n reporter.reportUnsupportedValue(path, 'size', rawValue);\n } else if (rawValue !== undefined) {\n reporter.reportAmbiguousExpression(path, 'size');\n }\n }\n }\n\n if ('priority' in legacyProps) {\n const rawValue = legacyProps.priority;\n\n if (typeof rawValue === 'string' && isEnumValue(rawValue)) {\n const equivalent = getEnumEquivalent(rawValue);\n const supportedPriorities = ['primary', 'secondary', 'tertiary', 'secondary-neutral'];\n\n if (equivalent && supportedPriorities.includes(equivalent)) {\n } else {\n reporter.reportUnsupportedValue(path, 'priority', rawValue);\n }\n } else {\n const converted = convertEnumValue(rawValue);\n const mapped = resolvePriority(legacyProps.type, converted);\n const supportedPriorities = ['primary', 'secondary', 'tertiary', 'secondary-neutral'];\n if (\n typeof rawValue === 'string' &&\n typeof mapped === 'string' &&\n supportedPriorities.includes(mapped)\n ) {\n removeAttributeByName(j, openingElement, 'priority');\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('priority'), j.literal(mapped)),\n );\n } else if (typeof rawValue === 'string') {\n reporter.reportUnsupportedValue(path, 'priority', rawValue);\n } else if (rawValue !== undefined) {\n reporter.reportAmbiguousExpression(path, 'priority');\n }\n }\n }\n\n if ('type' in legacyProps || 'htmlType' in legacyProps) {\n const rawType = legacyProps.type;\n const rawHtmlType = legacyProps.htmlType;\n\n let resolvedType: string | undefined;\n let isTypeEnum = false;\n let isControlTypeEnum = false;\n\n if (typeof rawType === 'string' && isEnumValue(rawType)) {\n isTypeEnum = true;\n const equivalent = getEnumEquivalent(rawType);\n resolvedType = equivalent;\n isControlTypeEnum = rawType.startsWith('ControlType.');\n\n if (!isControlTypeEnum) {\n reporter.reportUnsupportedValue(path, 'type', rawType);\n }\n } else {\n let typeValue: string | undefined;\n if (typeof rawType === 'string') {\n typeValue = rawType;\n } else if (rawType && typeof rawType === 'object') {\n typeValue = convertEnumValue(j(rawType).toSource());\n }\n resolvedType = typeValue;\n }\n\n let finalHtmlType = null;\n if (resolvedType && !legacyButtonTypes.includes(resolvedType)) {\n finalHtmlType = resolvedType;\n }\n\n if (rawHtmlType) {\n finalHtmlType = rawHtmlType;\n }\n\n const htmlTypes = ['submit', 'button', 'reset'];\n\n if (resolvedType === 'negative' && isControlTypeEnum) {\n removeAttributeByName(j, openingElement, 'type');\n\n if (hasAttributeOnElement(openingElement, 'sentiment')) {\n removeAttributeByName(j, openingElement, 'sentiment');\n }\n\n addAttributesIfMissing(j, openingElement, [\n {\n attribute: j.jsxAttribute(j.jsxIdentifier('priority'), j.literal('primary')),\n name: 'priority',\n },\n ]);\n\n // Keep as enum\n if (rawType) {\n openingElement.attributes?.push(\n j.jsxAttribute(\n j.jsxIdentifier('sentiment'),\n j.jsxExpressionContainer(j.identifier(rawType)),\n ),\n );\n }\n } else if (resolvedType === 'negative' && !isTypeEnum) {\n // String literal 'negative'\n removeAttributeByName(j, openingElement, 'type');\n\n if (hasAttributeOnElement(openingElement, 'sentiment')) {\n removeAttributeByName(j, openingElement, 'sentiment');\n }\n\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('sentiment'), j.literal('negative')),\n );\n } else if (\n isControlTypeEnum &&\n resolvedType &&\n ['positive', 'accent'].includes(resolvedType)\n ) {\n removeAttributeByName(j, openingElement, 'type');\n addAttributesIfMissing(j, openingElement, [\n {\n attribute: j.jsxAttribute(j.jsxIdentifier('priority'), j.literal('primary')),\n name: 'priority',\n },\n ]);\n }\n\n if (\n resolvedType &&\n typeof resolvedType === 'string' &&\n legacyButtonTypes.includes(resolvedType) &&\n !isTypeEnum // Don't convert if it's an enum\n ) {\n const consistentConversion = getConsistentTypeConversions(resolvedType);\n\n if (consistentConversion) {\n removeAttributeByName(j, openingElement, 'type');\n removeAttributeByName(j, openingElement, 'priority');\n removeAttributeByName(j, openingElement, 'sentiment');\n\n if (consistentConversion.priority) {\n openingElement.attributes?.push(\n j.jsxAttribute(\n j.jsxIdentifier('priority'),\n j.literal(consistentConversion.priority),\n ),\n );\n }\n if (consistentConversion.sentiment) {\n openingElement.attributes?.push(\n j.jsxAttribute(\n j.jsxIdentifier('sentiment'),\n j.literal(consistentConversion.sentiment),\n ),\n );\n }\n } else {\n // if priority is present, then type is already handled. if not, add priority. always remove legacy type\n removeAttributeByName(j, openingElement, 'type');\n addAttributesIfMissing(j, openingElement, [\n {\n attribute: j.jsxAttribute(j.jsxIdentifier('priority'), j.literal('primary')),\n name: 'priority',\n },\n ]);\n }\n } else if (isTypeEnum) {\n // Enum value that isn't a supported control type - keep it as-is (already reported above)\n // Don't modify the attribute\n }\n\n // Handle htmlType conversion to type\n if (typeof finalHtmlType === 'string' && htmlTypes.includes(finalHtmlType)) {\n removeAttributeByName(j, openingElement, 'htmlType');\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('type'), j.literal(finalHtmlType)),\n );\n } else if (typeof rawType === 'string' || typeof rawHtmlType === 'string') {\n const valueToCheck = rawType ?? rawHtmlType ?? '';\n const legacyTypes = [\n 'accent',\n 'positive',\n 'negative',\n 'primary',\n 'secondary',\n 'danger',\n 'link',\n ];\n\n if (!legacyTypes.includes(valueToCheck)) {\n reporter.reportUnsupportedValue(path, 'type', valueToCheck);\n }\n } else if (rawType !== undefined || rawHtmlType !== undefined) {\n // Report ambiguous if we cannot determine the value\n reporter.reportAmbiguousExpression(\n path,\n typeof rawType === 'string' ? 'type' : 'htmlType',\n );\n }\n }\n\n // Handle sentiment prop\n if ('sentiment' in legacyProps) {\n const hasSentimentAttribute = openingElement.attributes?.some(\n (attr) => attr.type === 'JSXAttribute' && attr.name && attr.name.name === 'sentiment',\n );\n\n if (!hasSentimentAttribute) {\n const rawValue = legacyProps.sentiment;\n\n if (rawValue === 'negative') {\n removeAttributeByName(j, openingElement, 'sentiment');\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('sentiment'), j.literal('negative')),\n );\n } else if (typeof rawValue === 'string') {\n reporter.reportUnsupportedValue(path, 'sentiment', rawValue);\n } else if (rawValue !== undefined) {\n reporter.reportAmbiguousExpression(path, 'sentiment');\n }\n }\n }\n\n // Handle as prop and href\n let asIndex = -1;\n let asValue: string | null = null;\n let hrefExists = false;\n let asAmbiguous = false;\n let hrefAmbiguous = false;\n\n openingElement.attributes?.forEach((attr, index) => {\n if (attr.type === 'JSXAttribute' && attr.name) {\n if (attr.name.name === 'as') {\n if (attr.value) {\n if (attr.value.type === 'StringLiteral') {\n asValue = attr.value.value;\n } else if (attr.value.type === 'JSXExpressionContainer') {\n asAmbiguous = true;\n reporter.reportAttribute(attr, path);\n }\n }\n asIndex = index;\n }\n if (attr.name.name === 'href') {\n hrefExists = true;\n if (attr.value && attr.value.type !== 'StringLiteral') {\n hrefAmbiguous = true;\n reporter.reportAttribute(attr, path);\n }\n }\n }\n });\n\n if (asValue === 'a') {\n if (asIndex !== -1) {\n openingElement.attributes = openingElement.attributes?.filter(\n (_attr, idx) => idx !== asIndex,\n );\n }\n if (!hrefExists) {\n openingElement.attributes = [\n ...(openingElement.attributes ?? []),\n j.jsxAttribute(j.jsxIdentifier('href'), j.literal('#')),\n ];\n }\n }\n\n if ((openingElement.attributes ?? []).some((attr) => attr.type === 'JSXSpreadAttribute')) {\n reporter.reportSpreadProps(path);\n }\n });\n }\n\n if (manualReviewIssues.length > 0) {\n manualReviewIssues.forEach(async (issue) => {\n await reportManualReview(file.path, issue);\n });\n }\n\n return root.toSource();\n};\n\nexport default transformer;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transformer.js","names":[],"sources":["../../../src/helpers/jscodeshift/addImport.ts","../../../src/helpers/jscodeshift/hasImport.ts","../../../src/helpers/jscodeshift/iconUtils.ts","../../../src/helpers/jscodeshift/jsxElementUtils.ts","../../../src/helpers/jscodeshift/jsxReportingUtils.ts","../../../src/transforms/button/transformer.ts"],"sourcesContent":["import type { Collection, JSCodeshift } from 'jscodeshift';\n\n/**\n * Adds a named import if it doesn't already exist.\n */\nfunction addImport(\n root: Collection,\n sourceValue: string,\n importName: string,\n j: JSCodeshift,\n): void {\n const existingImports = root.find(j.ImportDeclaration, {\n source: { value: sourceValue },\n });\n\n if (existingImports.size() > 0) {\n const namedImport = existingImports.find(j.ImportSpecifier, {\n imported: { name: importName },\n });\n\n if (namedImport.size() > 0) {\n return;\n }\n\n existingImports.forEach((path) => {\n if (path.node.specifiers) {\n path.node.specifiers.push(j.importSpecifier(j.identifier(importName)));\n }\n });\n } else {\n const newImport = j.importDeclaration(\n [j.importSpecifier(j.identifier(importName))],\n j.literal(sourceValue),\n );\n\n const firstImport = root.find(j.ImportDeclaration).at(0);\n if (firstImport.size() > 0) {\n firstImport.insertBefore(newImport);\n } else {\n // Insert at the beginning of the program\n const program = root.find(j.Program);\n if (program.size() > 0) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n program.get('body', 0).insertBefore(newImport);\n }\n }\n }\n}\n\nexport default addImport;\n","import type { ASTPath, Collection, ImportSpecifier, JSCodeshift } from 'jscodeshift';\n\n/**\n * Checks if a specific import exists in the given root collection and provides\n * a method to remove it if found.\n */\nfunction hasImport(\n root: Collection,\n sourceValue: string,\n importName: string,\n j: JSCodeshift,\n): {\n exists: boolean;\n remove: () => void;\n aliases?: Collection<ImportSpecifier>;\n resolvedName: string;\n conflictingImports: ImportSpecifier[];\n} {\n const importDeclarations = root.find(j.ImportDeclaration, {\n source: { value: sourceValue },\n });\n\n /**\n * Finds all ImportSpecifier nodes that expose `importName` but\n * from a different source than `sourceValue`.\n */\n const conflictingImports = ((): ImportSpecifier[] => {\n const result: ImportSpecifier[] = [];\n root\n .find(j.ImportDeclaration)\n .filter((path) => path.node.source.value !== sourceValue)\n .forEach((path) => {\n for (const specifier of path.node.specifiers ?? []) {\n if (\n specifier.type === 'ImportSpecifier' &&\n specifier.imported.name === importName &&\n specifier.local?.name === importName\n ) {\n result.push(specifier);\n }\n }\n });\n return result;\n })();\n\n if (importDeclarations.size() === 0) {\n return {\n exists: false,\n remove: () => {},\n resolvedName: importName,\n conflictingImports,\n };\n }\n\n const namedImport = importDeclarations.find(j.ImportSpecifier, {\n imported: { name: importName },\n });\n\n const defaultImport = importDeclarations.find(j.ImportDefaultSpecifier, {\n local: { name: importName },\n });\n\n const aliasImport = importDeclarations.find(j.ImportSpecifier).filter((path) => {\n return (\n path.node.imported.name === importName && path.node.imported.name !== path.node.local?.name\n );\n });\n\n const exists = namedImport.size() > 0 || defaultImport.size() > 0;\n\n const resolveName = (): string => {\n if (aliasImport.size() > 0) {\n const importPath = aliasImport.get(0) as ASTPath<ImportSpecifier>;\n const localName = importPath.node.local?.name;\n\n if (typeof localName === 'string') {\n return localName;\n }\n\n if (\n localName &&\n typeof localName === 'object' &&\n 'name' in localName &&\n typeof localName.name === 'string'\n ) {\n return localName.name;\n }\n\n return importName;\n }\n\n return importName;\n };\n\n const remove = () => {\n importDeclarations.forEach((path) => {\n const filteredSpecifiers =\n path.node.specifiers?.filter((specifier) => {\n if (specifier.type === 'ImportSpecifier' && specifier.imported.name === importName) {\n return false;\n }\n if (specifier.type === 'ImportDefaultSpecifier' && specifier.local?.name === importName) {\n return false;\n }\n return true;\n }) ?? [];\n\n if (filteredSpecifiers.length === 0) {\n path.prune();\n } else {\n j(path).replaceWith(\n j.importDeclaration(filteredSpecifiers, path.node.source, path.node.importKind),\n );\n }\n });\n };\n\n return {\n exists,\n remove,\n aliases: aliasImport,\n resolvedName: resolveName(),\n conflictingImports,\n };\n}\n\nexport default hasImport;\n","import type { JSCodeshift, JSXElement, JSXExpressionContainer } from 'jscodeshift';\n\n/**\n * Process children of a JSX element to detect icon components and add iconStart or iconEnd attributes accordingly.\n * This is specific to icon handling but can be reused in codemods dealing with icon children.\n */\nconst processIconChildren = (\n j: JSCodeshift,\n children: (JSXElement | JSXExpressionContainer | unknown)[] | undefined,\n iconImports: Set<string>,\n openingElement: JSXElement['openingElement'],\n) => {\n if (!children || !openingElement.attributes) return;\n\n const unwrapJsxElement = (node: unknown): JSXElement | unknown => {\n if (\n typeof node === 'object' &&\n node !== null &&\n 'type' in node &&\n node.type === 'JSXExpressionContainer' &&\n j.JSXElement.check((node as JSXExpressionContainer).expression)\n ) {\n return (node as JSXExpressionContainer).expression;\n }\n return node;\n };\n\n const totalChildren = children.length;\n\n // Find index of icon child\n const iconChildIndex = children.findIndex((child) => {\n const unwrapped = unwrapJsxElement(child);\n return (\n j.JSXElement.check(unwrapped) &&\n unwrapped.openingElement.name.type === 'JSXIdentifier' &&\n iconImports.has(unwrapped.openingElement.name.name)\n );\n });\n\n if (iconChildIndex === -1) return;\n\n const iconChild = unwrapJsxElement(children[iconChildIndex]) as JSXElement;\n\n if (iconChild?.openingElement.name.type !== 'JSXIdentifier') return;\n\n const iconName = iconChild.openingElement.name.name;\n\n // Determine if icon is closer to start or end\n const distanceToStart = iconChildIndex;\n const distanceToEnd = totalChildren - 1 - iconChildIndex;\n const iconPropName = distanceToStart <= distanceToEnd ? 'addonStart' : 'addonEnd';\n\n // Build: { type: 'icon', value: <IconName /> }\n const iconObject = j.objectExpression([\n j.property('init', j.identifier('type'), j.literal('icon')),\n j.property('init', j.identifier('value'), iconChild),\n ]);\n const iconProp = j.jsxAttribute(\n j.jsxIdentifier(iconPropName),\n j.jsxExpressionContainer(iconObject),\n );\n\n openingElement.attributes.push(iconProp);\n\n // Remove the icon child\n children.splice(iconChildIndex, 1);\n\n // Helper to check if a child is whitespace-only JSXText\n const isWhitespaceJsxText = (node: unknown): boolean => {\n return (\n typeof node === 'object' &&\n node !== null &&\n (node as { type?: unknown }).type === 'JSXText' &&\n typeof (node as { value?: string }).value === 'string' &&\n (node as { value?: string }).value!.trim() === ''\n );\n };\n\n // Remove adjacent whitespace-only JSXText node if any\n if (iconChildIndex - 1 >= 0 && isWhitespaceJsxText(children[iconChildIndex - 1])) {\n children.splice(iconChildIndex - 1, 1);\n } else if (isWhitespaceJsxText(children[iconChildIndex])) {\n children.splice(iconChildIndex, 1);\n }\n};\n\nexport default processIconChildren;\n","import type {\n Collection,\n ImportSpecifier,\n JSCodeshift,\n JSXAttribute,\n JSXElement,\n JSXIdentifier,\n JSXMemberExpression,\n JSXNamespacedName,\n JSXSpreadAttribute,\n} from 'jscodeshift';\n\n/**\n * Rename a JSX element name if it is a JSXIdentifier.\n */\nexport const setNameIfJSXIdentifier = (\n elementName: JSXIdentifier | JSXNamespacedName | JSXMemberExpression | undefined,\n newName: string,\n): JSXIdentifier | JSXNamespacedName | JSXMemberExpression | undefined => {\n if (elementName?.type === 'JSXIdentifier') {\n return { ...elementName, name: newName };\n }\n return elementName;\n};\n\n/**\n * Check if a list of attributes contains a specific attribute by name.\n */\nexport const hasAttribute = (\n attributes: (JSXAttribute | JSXSpreadAttribute)[] | undefined,\n attributeName: string,\n): boolean => {\n return (\n Array.isArray(attributes) &&\n attributes.some(\n (attr): attr is JSXAttribute =>\n attr.type === 'JSXAttribute' &&\n attr.name.type === 'JSXIdentifier' &&\n attr.name.name === attributeName,\n )\n );\n};\n\n/**\n * Check if a JSX element's openingElement has a specific attribute.\n */\nexport const hasAttributeOnElement = (\n element: JSXElement['openingElement'],\n attributeName: string,\n): boolean => {\n return hasAttribute(element.attributes, attributeName);\n};\n\n/**\n * Add specified attributes to a JSX element's openingElement if they are not already present.\n */\nexport const addAttributesIfMissing = (\n j: JSCodeshift,\n openingElement: JSXElement['openingElement'],\n attributesToAdd: { attribute: JSXAttribute; name: string }[],\n) => {\n if (!Array.isArray(openingElement.attributes)) return;\n const attrs = openingElement.attributes;\n attributesToAdd.forEach(({ attribute, name }) => {\n if (!hasAttributeOnElement(openingElement, name)) {\n attrs.push(attribute);\n }\n });\n};\n\n/**\n * Returns a collection of JSX elements that match the specified\n * exported name or names of the found aliases.\n */\nexport const findJSXElementsByName =\n (root: Collection, j: JSCodeshift) =>\n (exportedName: string, aliases?: Collection<ImportSpecifier>) => {\n const aliasNames = aliases?.size()\n ? aliases.paths().map((path) => path.node.local?.name as string)\n : [];\n\n return root.find(j.JSXElement).filter((path) => {\n const { name } = path.node.openingElement;\n return (\n name.type === 'JSXIdentifier' &&\n (name.name === exportedName || aliasNames.includes(name.name))\n );\n });\n };\n\n/**\n * Removes an attribute by name from a JSX element's openingElement.\n */\nexport const removeAttributeByName = (\n j: JSCodeshift,\n openingElement: JSXElement['openingElement'],\n attributeName: string,\n) => {\n if (!Array.isArray(openingElement.attributes)) return;\n // eslint-disable-next-line no-param-reassign\n openingElement.attributes = openingElement.attributes.filter((attr) => {\n return !(\n attr.type === 'JSXAttribute' &&\n attr.name.type === 'JSXIdentifier' &&\n attr.name.name === attributeName\n );\n });\n};\n","import type {\n ASTPath,\n ImportSpecifier,\n JSCodeshift,\n JSXAttribute,\n JSXElement,\n Node,\n} from 'jscodeshift';\n\nexport interface ReporterOptions {\n jscodeshift: JSCodeshift;\n issues: string[];\n}\n\n/**\n * CodemodReporter is a utility class for reporting issues found during codemod transformations.\n * It provides methods to report issues related to JSX elements, props, and attributes.\n *\n * @example\n * ```typescript\n * const issues: string[] = [];\n * const reporter = createReporter(j, issues);\n *\n * // Report a deprecated prop\n * reporter.reportDeprecatedProp(buttonElement, 'flat', 'variant=\"text\"');\n *\n * // Report complex expression that needs review\n * reporter.reportAmbiguousExpression(element, 'size');\n *\n * // Auto-detect common issues\n * reporter.reportAttributeIssues(element);\n * ```\n */\nexport class CodemodReporter {\n private readonly j: JSCodeshift;\n private readonly issues: string[];\n\n constructor(options: ReporterOptions) {\n this.j = options.jscodeshift;\n this.issues = options.issues;\n }\n\n /**\n * Reports an issue with a JSX element\n */\n reportElement(element: JSXElement | ASTPath<JSXElement>, reason: string): void {\n const node = this.getNode(element);\n const componentName = this.getComponentName(node);\n const line = this.getLineNumber(node);\n\n this.addIssue(`Manual review required: <${componentName}> at line ${line} ${reason}.`);\n }\n\n /**\n * Reports an issue with a specific prop\n */\n reportProp(element: JSXElement | ASTPath<JSXElement>, propName: string, reason: string): void {\n const node = this.getNode(element);\n const componentName = this.getComponentName(node);\n const line = this.getLineNumber(node);\n\n this.addIssue(\n `Manual review required: prop \"${propName}\" on <${componentName}> at line ${line} ${reason}.`,\n );\n }\n\n /**\n * Reports an issue with a JSX attribute directly\n */\n reportAttribute(\n attr: JSXAttribute,\n element: JSXElement | ASTPath<JSXElement>,\n reason?: string,\n ): void {\n const node = this.getNode(element);\n const componentName = this.getComponentName(node);\n const propName = this.getAttributeName(attr);\n const line = this.getLineNumber(attr) || this.getLineNumber(node);\n\n const defaultReason = this.getAttributeReason(attr);\n const finalReason = reason || defaultReason;\n\n this.addIssue(\n `Manual review required: prop \"${propName}\" on <${componentName}> at line ${line} ${finalReason}.`,\n );\n }\n\n /**\n * Reports spread props on an element\n */\n reportSpreadProps(element: JSXElement | ASTPath<JSXElement>): void {\n this.reportElement(element, 'contains spread props that need manual review');\n }\n\n /**\n * Reports conflicting prop and children\n */\n reportPropWithChildren(element: JSXElement | ASTPath<JSXElement>, propName: string): void {\n this.reportProp(\n element,\n propName,\n `conflicts with children - both \"${propName}\" prop and children are present`,\n );\n }\n\n /**\n * Reports unsupported prop value\n */\n reportUnsupportedValue(\n element: JSXElement | ASTPath<JSXElement>,\n propName: string,\n value: string,\n ): void {\n this.reportProp(element, propName, `has unsupported value \"${value}\"`);\n }\n\n /**\n * Reports ambiguous expression in prop\n */\n reportAmbiguousExpression(element: JSXElement | ASTPath<JSXElement>, propName: string): void {\n this.reportProp(element, propName, 'contains a complex expression that needs manual review');\n }\n\n /**\n * Reports ambiguous children (like dynamic icons)\n */\n reportAmbiguousChildren(element: JSXElement | ASTPath<JSXElement>, childType = 'content'): void {\n this.reportElement(element, `contains ambiguous ${childType} that needs manual review`);\n }\n\n /**\n * Reports deprecated prop usage\n */\n reportDeprecatedProp(\n element: JSXElement | ASTPath<JSXElement>,\n propName: string,\n alternative?: string,\n ): void {\n const suggestion = alternative ? ` Use ${alternative} instead` : '';\n this.reportProp(element, propName, `is deprecated${suggestion}`);\n }\n\n /**\n * Reports missing required prop\n */\n reportMissingRequiredProp(element: JSXElement | ASTPath<JSXElement>, propName: string): void {\n this.reportProp(element, propName, 'is required but missing');\n }\n\n /**\n * Reports conflicting props\n */\n reportConflictingProps(element: JSXElement | ASTPath<JSXElement>, propNames: string[]): void {\n const propList = propNames.map((name) => `\"${name}\"`).join(', ');\n this.reportElement(element, `has conflicting props: ${propList} cannot be used together`);\n }\n\n /**\n * Auto-detects and reports common attribute issues\n */\n reportAttributeIssues(element: JSXElement | ASTPath<JSXElement>): void {\n const node = this.getNode(element);\n const { attributes } = node.openingElement;\n\n if (!attributes) return;\n\n // Check for spread props\n if (attributes.some((attr) => attr.type === 'JSXSpreadAttribute')) {\n this.reportSpreadProps(element);\n }\n\n // Check for complex expressions in attributes\n attributes.forEach((attr) => {\n if (attr.type === 'JSXAttribute' && attr.value?.type === 'JSXExpressionContainer') {\n this.reportAttribute(attr, element);\n }\n });\n }\n\n /**\n * Finds and reports instances of components that are under an alias (imported with a different name)\n */\n reportAliases(element: JSXElement | ASTPath<JSXElement>): void {\n this.reportElement(element, 'is used via an import alias and needs manual review');\n }\n\n /**\n * Finds and reports instances of non-DS import declarations that conflict with the component name\n */\n reportConflictingImports(node: ImportSpecifier): void {\n this.addIssue(\n `Manual review required: Non-WDS package resulting in an import conflict at line ${this.getLineNumber(node)}.`,\n );\n }\n\n /**\n * Reports enum usage for future conversion tracking\n */\n reportEnumUsage(\n element: JSXElement | ASTPath<JSXElement>,\n propName: string,\n enumValue: string,\n ): void {\n this.reportProp(\n element,\n propName,\n `uses enum value \"${enumValue}\" which has been preserved but should be migrated to a string literal in the future`,\n );\n }\n\n // Private helper methods\n private getNode(element: JSXElement | ASTPath<JSXElement>): JSXElement {\n return 'node' in element ? element.node : element;\n }\n\n private getComponentName(node: JSXElement): string {\n const { name } = node.openingElement;\n if (name.type === 'JSXIdentifier') {\n return name.name;\n }\n // Handle JSXMemberExpression, JSXNamespacedName, etc.\n return this.j(name).toSource();\n }\n\n private getLineNumber(node: JSXElement | JSXAttribute | Node): string {\n return node.loc?.start.line?.toString() || 'unknown';\n }\n\n private getAttributeName(attr: JSXAttribute): string {\n if (attr.name.type === 'JSXIdentifier') {\n return attr.name.name;\n }\n return this.j(attr.name).toSource();\n }\n\n private getAttributeReason(attr: JSXAttribute): string {\n if (!attr.value) return 'has no value';\n\n if (attr.value.type === 'JSXExpressionContainer') {\n const expr = attr.value.expression;\n const expressionType = expr.type.replace('Expression', '').toLowerCase();\n\n // Show actual value for simple cases\n if (expr.type === 'Identifier' || expr.type === 'MemberExpression') {\n const valueText = this.j(expr).toSource();\n return `contains a ${expressionType} (${valueText})`;\n }\n\n return `contains a complex ${expressionType} expression`;\n }\n\n return 'needs manual review';\n }\n\n private addIssue(message: string): void {\n this.issues.push(message);\n }\n}\n\nexport const createReporter = (j: JSCodeshift, issues: string[]): CodemodReporter => {\n return new CodemodReporter({ jscodeshift: j, issues });\n};\n","import type { API, FileInfo, JSCodeshift, Options } from 'jscodeshift';\n\nimport { reportManualReview } from '../../controller/helpers';\nimport {\n addAttributesIfMissing,\n addImport,\n createReporter,\n findJSXElementsByName,\n hasAttributeOnElement,\n hasImport,\n processIconChildren,\n removeAttributeByName,\n setNameIfJSXIdentifier,\n} from '../../helpers/jscodeshift';\n\nexport const parser = 'tsx';\n\ninterface LegacyProps {\n priority?: string;\n size?: string;\n type?: string;\n htmlType?: string;\n sentiment?: string;\n [key: string]: unknown;\n}\n\ninterface ExtendedOptions extends Options {\n accentSecondaryMapping?: string;\n positiveSecondaryMapping?: string;\n}\n\ntype PriorityMapping = Record<string, Record<string, string>>;\n\nconst buildPriorityMapping = (opts: Options): PriorityMapping => {\n const extendedOpts = opts as ExtendedOptions;\n const accentSecondary = extendedOpts.accentSecondaryMapping || 'secondary-neutral';\n const positiveSecondary = extendedOpts.positiveSecondaryMapping || 'secondary-neutral';\n return {\n accent: {\n primary: 'primary',\n secondary: accentSecondary,\n tertiary: 'tertiary',\n },\n positive: {\n primary: 'primary',\n secondary: positiveSecondary,\n tertiary: positiveSecondary,\n },\n negative: {\n primary: 'primary',\n secondary: 'secondary',\n tertiary: 'secondary',\n },\n primary: {\n primary: 'primary',\n secondary: accentSecondary,\n tertiary: 'tertiary',\n },\n pay: {\n primary: 'primary',\n secondary: accentSecondary,\n tertiary: accentSecondary,\n },\n };\n};\n\nconst sizeMap: Record<string, string> = {\n EXTRA_SMALL: 'xs',\n SMALL: 'sm',\n MEDIUM: 'md',\n LARGE: 'lg',\n EXTRA_LARGE: 'xl',\n xs: 'sm',\n sm: 'sm',\n md: 'md',\n lg: 'lg',\n xl: 'xl',\n};\n\nconst resolveSize = (size?: string): string | undefined => {\n if (!size) return size;\n const match = /^Size\\.(EXTRA_SMALL|SMALL|MEDIUM|LARGE|EXTRA_LARGE)$/u.exec(size);\n if (match) {\n return sizeMap[match[1]];\n }\n return sizeMap[size] || size;\n};\n\nconst legacyButtonTypes = [\n 'accent',\n 'negative',\n 'positive',\n 'primary',\n 'pay',\n 'secondary',\n 'danger',\n 'link',\n];\n\nconst getConsistentTypeConversions = (\n type?: string,\n): { priority?: string; sentiment?: string } | null => {\n const consistentTypeConversions: Record<string, { priority?: string; sentiment?: string }> = {\n secondary: { priority: 'secondary-neutral' },\n link: { priority: 'tertiary' },\n danger: { priority: 'secondary', sentiment: 'negative' },\n };\n\n return consistentTypeConversions[type || ''] || null;\n};\n\nconst convertEnumValue = (value?: string): string | undefined => {\n if (!value) return value;\n const strippedValue = value.replace(/^['\"]|['\"]$/gu, '');\n const enumMapping: Record<string, string> = {\n 'Priority.SECONDARY': 'secondary',\n 'Priority.PRIMARY': 'primary',\n 'Priority.TERTIARY': 'tertiary',\n 'ControlType.NEGATIVE': 'negative',\n 'ControlType.POSITIVE': 'positive',\n 'ControlType.ACCENT': 'accent',\n };\n return enumMapping[strippedValue] || strippedValue;\n};\n\n/**\n * Detects if a value is an enum pattern (e.g., Priority.PRIMARY, ControlType.ACCENT, Size.LARGE, Type.PRIMARY)\n */\nconst isEnumValue = (value: string): boolean => {\n const enumPatterns = [\n /^Priority\\.(PRIMARY|SECONDARY|TERTIARY|SECONDARY_NEUTRAL)$/u,\n /^ControlType\\.(ACCENT|NEGATIVE|POSITIVE)$/u,\n /^Size\\.(EXTRA_SMALL|SMALL|MEDIUM|LARGE|EXTRA_LARGE)$/u,\n /^Type\\.(PRIMARY|SECONDARY|TERTIARY|PAY|DANGER|LINK|ACCENT|POSITIVE|NEGATIVE)$/u,\n ];\n return enumPatterns.some((pattern) => pattern.test(value));\n};\n\n/**\n * Maps enum values to their expected string equivalents for validation purposes\n * This is ONLY used to validate the enum maps to a supported value\n */\nconst getEnumEquivalent = (value: string): string | undefined => {\n const enumMapping: Record<string, string> = {\n 'Priority.PRIMARY': 'primary',\n 'Priority.SECONDARY': 'secondary',\n 'Priority.TERTIARY': 'tertiary',\n 'Priority.SECONDARY_NEUTRAL': 'secondary-neutral',\n 'ControlType.NEGATIVE': 'negative',\n 'ControlType.POSITIVE': 'positive',\n 'ControlType.ACCENT': 'accent',\n 'Size.EXTRA_SMALL': 'sm',\n 'Size.SMALL': 'sm',\n 'Size.MEDIUM': 'md',\n 'Size.LARGE': 'lg',\n 'Size.EXTRA_LARGE': 'xl',\n };\n return enumMapping[value];\n};\n\n/**\n * This transform function modifies the Button and ActionButton components from the @transferwise/components library.\n * It updates the ActionButton component to use the Button component with specific attributes and mappings.\n * It also processes icon children and removes legacy props.\n *\n * @param {FileInfo} file - The file information object.\n * @param {API} api - The API object for jscodeshift.\n * @param {Options} options - The options object for jscodeshift.\n * @returns {string} - The transformed source code.\n */\nconst transformer = (file: FileInfo, api: API, options: Options) => {\n const j: JSCodeshift = api.jscodeshift;\n const root = j(file.source);\n const manualReviewIssues: string[] = [];\n const priorityMapping = buildPriorityMapping(options);\n\n const resolvePriority = (type?: string, priority?: string): string | undefined => {\n if (type && priority) {\n return priorityMapping[type]?.[priority] || priority;\n }\n return priority;\n };\n\n // Create reporter instance\n const reporter = createReporter(j, manualReviewIssues);\n\n const {\n exists: hasButtonImport,\n aliases: buttonAliases,\n resolvedName: buttonName,\n conflictingImports: conflictingButtonImport,\n } = hasImport(root, '@transferwise/components', 'Button', j);\n\n if (conflictingButtonImport.length) {\n conflictingButtonImport.forEach((node) => reporter.reportConflictingImports(node));\n }\n\n const {\n exists: hasActionButtonImport,\n remove: removeActionButtonImport,\n aliases: actionButtonAliases,\n } = hasImport(root, '@transferwise/components', 'ActionButton', j);\n\n if (!hasButtonImport && !hasActionButtonImport) {\n return file.source;\n }\n\n const iconImports = new Set<string>();\n root.find(j.ImportDeclaration, { source: { value: '@transferwise/icons' } }).forEach((path) => {\n path.node.specifiers?.forEach((specifier) => {\n if (\n (specifier.type === 'ImportDefaultSpecifier' || specifier.type === 'ImportSpecifier') &&\n specifier.local\n ) {\n const localName = (specifier.local as { name: string }).name;\n iconImports.add(localName);\n }\n });\n });\n\n if (hasActionButtonImport) {\n if (!hasButtonImport) {\n addImport(root, '@transferwise/components', 'Button', j);\n }\n\n const instances = findJSXElementsByName(root, j)('ActionButton', actionButtonAliases);\n\n instances.forEach((path) => {\n const { openingElement, closingElement } = path.node;\n\n openingElement.name = setNameIfJSXIdentifier(openingElement.name, buttonName)!;\n if (closingElement) {\n closingElement.name = setNameIfJSXIdentifier(closingElement.name, buttonName)!;\n }\n\n processIconChildren(j, path.node.children, iconImports, openingElement);\n\n if ((openingElement.attributes ?? []).some((attr) => attr.type === 'JSXSpreadAttribute')) {\n reporter.reportSpreadProps(path);\n }\n\n const legacyPropNames = ['priority', 'text', 'size'];\n const legacyProps: LegacyProps = {};\n\n openingElement.attributes?.forEach((attr) => {\n if (attr.type === 'JSXAttribute' && attr.name?.type === 'JSXIdentifier') {\n const { name } = attr.name;\n if (legacyPropNames.includes(name)) {\n if (attr.value) {\n if (attr.value.type === 'StringLiteral') {\n legacyProps[name] = attr.value.value;\n } else if (attr.value.type === 'JSXExpressionContainer') {\n legacyProps[name] = convertEnumValue(String(j(attr.value.expression).toSource()));\n }\n }\n }\n }\n });\n\n const hasTextProp = 'text' in legacyProps;\n const hasChildren =\n path.node.children?.some(\n (child) =>\n (child.type === 'JSXText' && child.value.trim() !== '') ||\n child.type === 'JSXElement' ||\n child.type === 'JSXExpressionContainer',\n ) ||\n (path.node.children && path.node.children?.length > 0);\n\n if (hasTextProp && hasChildren) {\n reporter.reportPropWithChildren(path, 'text');\n } else if (hasTextProp && !hasChildren && openingElement.selfClosing) {\n // Self-closing tag with text prop but no children, so we can convert to a normal element with children\n path.replace(\n j.jsxElement(\n j.jsxOpeningElement(openingElement.name, openingElement.attributes),\n j.jsxClosingElement(openingElement.name),\n [j.jsxText((legacyProps.text as string) || '')],\n ),\n );\n }\n\n addAttributesIfMissing(j, path.node.openingElement, [\n { attribute: j.jsxAttribute(j.jsxIdentifier('v2')), name: 'v2' },\n { attribute: j.jsxAttribute(j.jsxIdentifier('size'), j.literal('sm')), name: 'size' },\n ]);\n\n (path.node.children || []).forEach((child) => {\n if (child.type === 'JSXExpressionContainer') {\n const expr = child.expression;\n if (\n expr.type === 'ConditionalExpression' ||\n expr.type === 'CallExpression' ||\n expr.type === 'Identifier' ||\n expr.type === 'MemberExpression'\n ) {\n reporter.reportAmbiguousChildren(path, 'icon');\n }\n }\n });\n });\n\n removeActionButtonImport();\n }\n\n if (hasButtonImport) {\n const instances = findJSXElementsByName(root, j)('Button', buttonAliases);\n\n instances.forEach((path) => {\n const { openingElement } = path.node;\n\n if (hasAttributeOnElement(openingElement, 'v2')) return;\n\n const hasJSXChildren = path.node.children?.some(\n (child) =>\n (child.type === 'JSXText' && child.value.trim() !== '') ||\n child.type === 'JSXElement' ||\n (child.type === 'JSXFragment' && child.children && child.children.length > 0) ||\n (child.type === 'JSXExpressionContainer' &&\n child.expression.type !== 'JSXEmptyExpression'),\n );\n const hasChildrenAsProp = openingElement.attributes?.some(\n (attr) =>\n attr.type === 'JSXAttribute' &&\n attr.name?.type === 'JSXIdentifier' &&\n attr.name.name === 'children',\n );\n if (!hasJSXChildren && !hasChildrenAsProp) return;\n\n addAttributesIfMissing(j, openingElement, [\n { attribute: j.jsxAttribute(j.jsxIdentifier('v2')), name: 'v2' },\n ]);\n processIconChildren(j, path.node.children, iconImports, openingElement);\n\n const legacyProps: LegacyProps = {};\n const legacyPropNames = ['priority', 'size', 'type', 'htmlType', 'sentiment'];\n\n openingElement.attributes?.forEach((attr) => {\n if (attr.type === 'JSXAttribute' && attr.name?.type === 'JSXIdentifier') {\n const { name } = attr.name;\n if (legacyPropNames.includes(name)) {\n if (attr.value) {\n if (attr.value.type === 'StringLiteral') {\n legacyProps[name] = attr.value.value;\n } else if (attr.value.type === 'JSXExpressionContainer') {\n const expressionSource = String(j(attr.value.expression).toSource());\n legacyProps[name] = expressionSource;\n }\n } else {\n legacyProps[name] = undefined;\n }\n }\n }\n });\n\n if ('size' in legacyProps) {\n const rawValue = legacyProps.size;\n\n if (typeof rawValue === 'string' && isEnumValue(rawValue)) {\n const equivalent = getEnumEquivalent(rawValue);\n const supportedSizes = ['sm', 'md', 'lg', 'xl'];\n\n if (equivalent && supportedSizes.includes(equivalent)) {\n } else {\n reporter.reportUnsupportedValue(path, 'size', rawValue);\n }\n } else {\n const resolved = resolveSize(rawValue);\n const supportedSizes = ['sm', 'md', 'lg', 'xl'];\n if (\n typeof rawValue === 'string' &&\n typeof resolved === 'string' &&\n supportedSizes.includes(resolved)\n ) {\n removeAttributeByName(j, openingElement, 'size');\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('size'), j.literal(resolved)),\n );\n } else if (typeof rawValue === 'string') {\n reporter.reportUnsupportedValue(path, 'size', rawValue);\n } else if (rawValue !== undefined) {\n reporter.reportAmbiguousExpression(path, 'size');\n }\n }\n }\n\n if ('priority' in legacyProps) {\n const rawValue = legacyProps.priority;\n\n if (typeof rawValue === 'string' && isEnumValue(rawValue)) {\n const equivalent = getEnumEquivalent(rawValue);\n const supportedPriorities = ['primary', 'secondary', 'tertiary', 'secondary-neutral'];\n\n if (equivalent && supportedPriorities.includes(equivalent)) {\n } else {\n reporter.reportUnsupportedValue(path, 'priority', rawValue);\n }\n } else {\n const converted = convertEnumValue(rawValue);\n const mapped = resolvePriority(legacyProps.type, converted);\n const supportedPriorities = ['primary', 'secondary', 'tertiary', 'secondary-neutral'];\n if (\n typeof rawValue === 'string' &&\n typeof mapped === 'string' &&\n supportedPriorities.includes(mapped)\n ) {\n removeAttributeByName(j, openingElement, 'priority');\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('priority'), j.literal(mapped)),\n );\n } else if (typeof rawValue === 'string') {\n reporter.reportUnsupportedValue(path, 'priority', rawValue);\n } else if (rawValue !== undefined) {\n reporter.reportAmbiguousExpression(path, 'priority');\n }\n }\n }\n\n if ('type' in legacyProps || 'htmlType' in legacyProps) {\n const rawType = legacyProps.type;\n const rawHtmlType = legacyProps.htmlType;\n\n let resolvedType: string | undefined;\n let isTypeEnum = false;\n let isControlTypeEnum = false;\n\n if (typeof rawType === 'string' && isEnumValue(rawType)) {\n isTypeEnum = true;\n const equivalent = getEnumEquivalent(rawType);\n resolvedType = equivalent;\n isControlTypeEnum = rawType.startsWith('ControlType.');\n\n if (!isControlTypeEnum) {\n reporter.reportUnsupportedValue(path, 'type', rawType);\n }\n } else {\n let typeValue: string | undefined;\n if (typeof rawType === 'string') {\n typeValue = rawType;\n } else if (rawType && typeof rawType === 'object') {\n typeValue = convertEnumValue(j(rawType).toSource());\n }\n resolvedType = typeValue;\n }\n\n let finalHtmlType = null;\n if (resolvedType && !legacyButtonTypes.includes(resolvedType)) {\n finalHtmlType = resolvedType;\n }\n\n if (rawHtmlType) {\n finalHtmlType = rawHtmlType;\n }\n\n const htmlTypes = ['submit', 'button', 'reset'];\n\n if (resolvedType === 'negative' && isControlTypeEnum) {\n removeAttributeByName(j, openingElement, 'type');\n\n if (hasAttributeOnElement(openingElement, 'sentiment')) {\n removeAttributeByName(j, openingElement, 'sentiment');\n }\n\n addAttributesIfMissing(j, openingElement, [\n {\n attribute: j.jsxAttribute(j.jsxIdentifier('priority'), j.literal('primary')),\n name: 'priority',\n },\n ]);\n\n // Keep as enum\n if (rawType) {\n openingElement.attributes?.push(\n j.jsxAttribute(\n j.jsxIdentifier('sentiment'),\n j.jsxExpressionContainer(j.identifier(rawType)),\n ),\n );\n }\n } else if (resolvedType === 'negative' && !isTypeEnum) {\n // String literal 'negative'\n removeAttributeByName(j, openingElement, 'type');\n\n if (hasAttributeOnElement(openingElement, 'sentiment')) {\n removeAttributeByName(j, openingElement, 'sentiment');\n }\n\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('sentiment'), j.literal('negative')),\n );\n } else if (\n isControlTypeEnum &&\n resolvedType &&\n ['positive', 'accent'].includes(resolvedType)\n ) {\n removeAttributeByName(j, openingElement, 'type');\n addAttributesIfMissing(j, openingElement, [\n {\n attribute: j.jsxAttribute(j.jsxIdentifier('priority'), j.literal('primary')),\n name: 'priority',\n },\n ]);\n }\n\n if (\n resolvedType &&\n typeof resolvedType === 'string' &&\n legacyButtonTypes.includes(resolvedType) &&\n !isTypeEnum // Don't convert if it's an enum\n ) {\n const consistentConversion = getConsistentTypeConversions(resolvedType);\n\n if (consistentConversion) {\n removeAttributeByName(j, openingElement, 'type');\n removeAttributeByName(j, openingElement, 'priority');\n removeAttributeByName(j, openingElement, 'sentiment');\n\n if (consistentConversion.priority) {\n openingElement.attributes?.push(\n j.jsxAttribute(\n j.jsxIdentifier('priority'),\n j.literal(consistentConversion.priority),\n ),\n );\n }\n if (consistentConversion.sentiment) {\n openingElement.attributes?.push(\n j.jsxAttribute(\n j.jsxIdentifier('sentiment'),\n j.literal(consistentConversion.sentiment),\n ),\n );\n }\n } else {\n // if priority is present, then type is already handled. if not, add priority. always remove legacy type\n removeAttributeByName(j, openingElement, 'type');\n addAttributesIfMissing(j, openingElement, [\n {\n attribute: j.jsxAttribute(j.jsxIdentifier('priority'), j.literal('primary')),\n name: 'priority',\n },\n ]);\n }\n } else if (isTypeEnum) {\n // Enum value that isn't a supported control type - keep it as-is (already reported above)\n // Don't modify the attribute\n }\n\n // Handle htmlType conversion to type\n if (typeof finalHtmlType === 'string' && htmlTypes.includes(finalHtmlType)) {\n removeAttributeByName(j, openingElement, 'htmlType');\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('type'), j.literal(finalHtmlType)),\n );\n } else if (typeof rawType === 'string' || typeof rawHtmlType === 'string') {\n const valueToCheck = rawType ?? rawHtmlType ?? '';\n const legacyTypes = [\n 'accent',\n 'positive',\n 'negative',\n 'primary',\n 'secondary',\n 'danger',\n 'link',\n ];\n\n if (!legacyTypes.includes(valueToCheck)) {\n reporter.reportUnsupportedValue(path, 'type', valueToCheck);\n }\n } else if (rawType !== undefined || rawHtmlType !== undefined) {\n // Report ambiguous if we cannot determine the value\n reporter.reportAmbiguousExpression(\n path,\n typeof rawType === 'string' ? 'type' : 'htmlType',\n );\n }\n }\n\n // Handle sentiment prop\n if ('sentiment' in legacyProps) {\n const hasSentimentAttribute = openingElement.attributes?.some(\n (attr) => attr.type === 'JSXAttribute' && attr.name?.name === 'sentiment',\n );\n\n if (!hasSentimentAttribute) {\n const rawValue = legacyProps.sentiment;\n\n if (rawValue === 'negative') {\n removeAttributeByName(j, openingElement, 'sentiment');\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('sentiment'), j.literal('negative')),\n );\n } else if (typeof rawValue === 'string') {\n reporter.reportUnsupportedValue(path, 'sentiment', rawValue);\n } else if (rawValue !== undefined) {\n reporter.reportAmbiguousExpression(path, 'sentiment');\n }\n }\n }\n\n // Handle as prop and href\n let asIndex = -1;\n let asValue: string | null = null;\n let hrefExists = false;\n let asAmbiguous = false;\n let hrefAmbiguous = false;\n\n openingElement.attributes?.forEach((attr, index) => {\n if (attr.type === 'JSXAttribute' && attr.name) {\n if (attr.name.name === 'as') {\n if (attr.value) {\n if (attr.value.type === 'StringLiteral') {\n asValue = attr.value.value;\n } else if (attr.value.type === 'JSXExpressionContainer') {\n asAmbiguous = true;\n reporter.reportAttribute(attr, path);\n }\n }\n asIndex = index;\n }\n if (attr.name.name === 'href') {\n hrefExists = true;\n if (attr.value && attr.value.type !== 'StringLiteral') {\n hrefAmbiguous = true;\n reporter.reportAttribute(attr, path);\n }\n }\n }\n });\n\n if (asValue === 'a') {\n if (asIndex !== -1) {\n openingElement.attributes = openingElement.attributes?.filter(\n (_attr, idx) => idx !== asIndex,\n );\n }\n if (!hrefExists) {\n openingElement.attributes = [\n ...(openingElement.attributes ?? []),\n j.jsxAttribute(j.jsxIdentifier('href'), j.literal('#')),\n ];\n }\n }\n\n if ((openingElement.attributes ?? []).some((attr) => attr.type === 'JSXSpreadAttribute')) {\n reporter.reportSpreadProps(path);\n }\n });\n }\n\n if (manualReviewIssues.length > 0) {\n manualReviewIssues.forEach(async (issue) => {\n await reportManualReview(file.path, issue);\n });\n }\n\n return root.toSource();\n};\n\nexport default transformer;\n"],"mappings":"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"}
|
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
let node_fs = require("node:fs");
|
|
6
|
-
|
|
1
|
+
import { t as claudeTransformer } from "../../claude-cHSlHbX1.js";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
7
5
|
//#region src/transforms/info-prompt/transformer.ts
|
|
8
6
|
const DEPRECATED_COMPONENT_NAMES = ["Alert"];
|
|
9
7
|
const GREP_PATTERN = new RegExp(`import\\s*\\{[\\s\\S]*?(${DEPRECATED_COMPONENT_NAMES.join("|")})[\\s\\S]*?\\}\\s*from\\s*['"]@transferwise/components['"]`, "u");
|
|
10
|
-
const MIGRATION_RULES_PATH =
|
|
8
|
+
const MIGRATION_RULES_PATH = join(dirname(fileURLToPath(import.meta.url)), "MIGRATION_RULES.md");
|
|
11
9
|
const transformer = async (targetDirectories, isDebug = false) => {
|
|
12
|
-
const migrationRules =
|
|
13
|
-
return
|
|
10
|
+
const migrationRules = readFileSync(MIGRATION_RULES_PATH, "utf-8");
|
|
11
|
+
return claudeTransformer({
|
|
14
12
|
targetDirectories,
|
|
15
13
|
isDebug,
|
|
16
14
|
componentGrepPattern: GREP_PATTERN,
|
|
17
15
|
additionalPromptContext: `Deprecated components: ${DEPRECATED_COMPONENT_NAMES.join(", ")}\n${migrationRules}`
|
|
18
16
|
});
|
|
19
17
|
};
|
|
20
|
-
var transformer_default = transformer;
|
|
21
|
-
|
|
22
18
|
//#endregion
|
|
23
|
-
|
|
19
|
+
export { transformer as default };
|
|
20
|
+
|
|
24
21
|
//# sourceMappingURL=transformer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transformer.js","names":[
|
|
1
|
+
{"version":3,"file":"transformer.js","names":[],"sources":["../../../src/transforms/info-prompt/transformer.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { claudeTransformer } from '../../helpers/claude';\n\nconst DEPRECATED_COMPONENT_NAMES = ['Alert'];\nconst GREP_PATTERN = new RegExp(\n `import\\\\s*\\\\{[\\\\s\\\\S]*?(${DEPRECATED_COMPONENT_NAMES.join('|')})[\\\\s\\\\S]*?\\\\}\\\\s*from\\\\s*['\"]@transferwise/components['\"]`,\n 'u',\n);\n\nconst MIGRATION_RULES_DIRECTORY = dirname(fileURLToPath(import.meta.url));\nconst MIGRATION_RULES_PATH = join(MIGRATION_RULES_DIRECTORY, 'MIGRATION_RULES.md');\n\nconst transformer = async (targetDirectories: string[], isDebug = false) => {\n const migrationRules = readFileSync(MIGRATION_RULES_PATH, 'utf-8');\n\n return claudeTransformer({\n targetDirectories,\n isDebug,\n componentGrepPattern: GREP_PATTERN,\n additionalPromptContext: `Deprecated components: ${DEPRECATED_COMPONENT_NAMES.join(', ')}\\n${migrationRules}`,\n });\n};\n\nexport default transformer;\n"],"mappings":";;;;;AAMA,MAAM,6BAA6B,CAAC,QAAQ;AAC5C,MAAM,eAAe,IAAI,OACvB,2BAA2B,2BAA2B,KAAK,IAAI,CAAC,6DAChE,IACD;AAGD,MAAM,uBAAuB,KADK,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC,EACZ,qBAAqB;AAElF,MAAM,cAAc,OAAO,mBAA6B,UAAU,UAAU;CAC1E,MAAM,iBAAiB,aAAa,sBAAsB,QAAQ;AAElE,QAAO,kBAAkB;EACvB;EACA;EACA,sBAAsB;EACtB,yBAAyB,0BAA0B,2BAA2B,KAAK,KAAK,CAAC,IAAI;EAC9F,CAAC"}
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
1. Remove imports: `{ ActionOption, NavigationOption, NavigationOptionList, Summary, SwitchOption, CheckboxOption, RadioOption }` from `'@transferwise/components'`
|
|
6
6
|
2. Add import: `{ ListItem }` from `'@transferwise/components'`
|
|
7
|
-
3. For
|
|
8
|
-
4. For Summary with info: Add `{
|
|
9
|
-
5. For Summary with info
|
|
7
|
+
3. For `ul`/`ol` wrappers or `NavigationOptionList`: Add `{ List }` from `'@transferwise/components'`
|
|
8
|
+
4. For Summary with info: Add `{ Modal }` and/or `{ Popover }` from `'@transferwise/components'`
|
|
9
|
+
5. For Summary with info: Add `{ QuestionMarkCircle }` from `'@transferwise/icons'`
|
|
10
|
+
6. For Summary with info modal: Add `{ useState }` from `'react'`
|
|
10
11
|
|
|
11
12
|
## Universal Rules
|
|
12
13
|
|
|
@@ -14,8 +15,23 @@
|
|
|
14
15
|
2. `content` or `description` → `subtitle`
|
|
15
16
|
3. `disabled` stays on `ListItem` (not controls)
|
|
16
17
|
4. `id` stays on `ListItem` (not controls)
|
|
17
|
-
5. Remove deprecated props: `as`, `complex`, `showMediaAtAllSizes`, `showMediaCircle`, `isContainerAligned`
|
|
18
|
+
5. Remove deprecated props: `as`, `complex`, `showMediaAtAllSizes`, `showMediaCircle`, `isContainerAligned` from deprecated components
|
|
18
19
|
6. Preserve string quotes exactly as they are (don't convert ``to`'`or`"`)
|
|
20
|
+
7. `ListItem` renders as a `li` element by default, it doesn't need wrapping
|
|
21
|
+
8. Convert `<ul>` or `<ol>` wrappers containing legacy components to `<List>` (import from `'@transferwise/components'`)
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## List Wrapper Conversion
|
|
26
|
+
|
|
27
|
+
- Convert `<ul>` or `<ol>` wrappers to `<List>`
|
|
28
|
+
- `<List>` defaults to `ul`, but can be `ol` or `div` via the `as` property
|
|
29
|
+
- Use `<List as="ol">` when converting `<ol>` tags to preserve semantic HTML
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
<ul><ActionOption /></ul> → <List><ListItem /></List>
|
|
33
|
+
<ol><ActionOption /></ol> → <List as="ol"><ListItem /></List>
|
|
34
|
+
```
|
|
19
35
|
|
|
20
36
|
---
|
|
21
37
|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
let node_fs = require("node:fs");
|
|
6
|
-
|
|
1
|
+
import { t as claudeTransformer } from "../../claude-cHSlHbX1.js";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
7
5
|
//#region src/transforms/list-item/constants.ts
|
|
8
6
|
const DEPRECATED_COMPONENT_NAMES = [
|
|
9
7
|
"ActionOption",
|
|
@@ -15,21 +13,19 @@ const DEPRECATED_COMPONENT_NAMES = [
|
|
|
15
13
|
"RadioOption"
|
|
16
14
|
];
|
|
17
15
|
const GREP_PATTERN = new RegExp(`import\\s*\\{[\\s\\S]*?(${DEPRECATED_COMPONENT_NAMES.join("|")})[\\s\\S]*?\\}\\s*from\\s*['"]@transferwise/components['"]`, "u");
|
|
18
|
-
|
|
19
16
|
//#endregion
|
|
20
17
|
//#region src/transforms/list-item/transformer.ts
|
|
21
|
-
const MIGRATION_RULES_PATH =
|
|
18
|
+
const MIGRATION_RULES_PATH = join(dirname(fileURLToPath(import.meta.url)), "MIGRATION_RULES.md");
|
|
22
19
|
const transformer = async (targetDirectories, isDebug = false) => {
|
|
23
|
-
const migrationRules =
|
|
24
|
-
return
|
|
20
|
+
const migrationRules = readFileSync(MIGRATION_RULES_PATH, "utf-8");
|
|
21
|
+
return claudeTransformer({
|
|
25
22
|
targetDirectories,
|
|
26
23
|
isDebug,
|
|
27
24
|
componentGrepPattern: GREP_PATTERN,
|
|
28
25
|
additionalPromptContext: `Deprecated components: ${DEPRECATED_COMPONENT_NAMES.join(", ")}\n${migrationRules}`
|
|
29
26
|
});
|
|
30
27
|
};
|
|
31
|
-
var transformer_default = transformer;
|
|
32
|
-
|
|
33
28
|
//#endregion
|
|
34
|
-
|
|
29
|
+
export { transformer as default };
|
|
30
|
+
|
|
35
31
|
//# sourceMappingURL=transformer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transformer.js","names":[
|
|
1
|
+
{"version":3,"file":"transformer.js","names":[],"sources":["../../../src/transforms/list-item/constants.ts","../../../src/transforms/list-item/transformer.ts"],"sourcesContent":["export const DEPRECATED_COMPONENT_NAMES = [\n 'ActionOption',\n 'NavigationOption',\n 'NavigationOptionList',\n 'Summary',\n 'SwitchOption',\n 'CheckboxOption',\n 'RadioOption',\n];\nexport const GREP_PATTERN = new RegExp(\n `import\\\\s*\\\\{[\\\\s\\\\S]*?(${DEPRECATED_COMPONENT_NAMES.join('|')})[\\\\s\\\\S]*?\\\\}\\\\s*from\\\\s*['\"]@transferwise/components['\"]`,\n 'u',\n);\n","import { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { claudeTransformer } from '../../helpers/claude';\nimport { DEPRECATED_COMPONENT_NAMES, GREP_PATTERN } from './constants';\n\nconst MIGRATION_RULES_DIRECTORY = dirname(fileURLToPath(import.meta.url));\nconst MIGRATION_RULES_PATH = join(MIGRATION_RULES_DIRECTORY, 'MIGRATION_RULES.md');\n\nconst transformer = async (targetDirectories: string[], isDebug = false) => {\n const migrationRules = readFileSync(MIGRATION_RULES_PATH, 'utf-8');\n\n return claudeTransformer({\n targetDirectories,\n isDebug,\n componentGrepPattern: GREP_PATTERN,\n additionalPromptContext: `Deprecated components: ${DEPRECATED_COMPONENT_NAMES.join(', ')}\\n${migrationRules}`,\n });\n};\n\nexport default transformer;\n"],"mappings":";;;;;AAAA,MAAa,6BAA6B;CACxC;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AACD,MAAa,eAAe,IAAI,OAC9B,2BAA2B,2BAA2B,KAAK,IAAI,CAAC,6DAChE,IACD;;;ACJD,MAAM,uBAAuB,KADK,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC,EACZ,qBAAqB;AAElF,MAAM,cAAc,OAAO,mBAA6B,UAAU,UAAU;CAC1E,MAAM,iBAAiB,aAAa,sBAAsB,QAAQ;AAElE,QAAO,kBAAkB;EACvB;EACA;EACA,sBAAsB;EACtB,yBAAyB,0BAA0B,2BAA2B,KAAK,KAAK,CAAC,IAAI;EAC9F,CAAC"}
|