@wise/wds-codemods 1.0.0-experimental-49d2d08 → 1.0.0-experimental-88f6022
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/{helpers-59xSDDPO.js → helpers-RWhTD5Is.js} +1 -441
- package/dist/helpers-RWhTD5Is.js.map +1 -0
- package/dist/index.js +2 -2
- package/dist/{transformer-DnE3TyyV.js → transformer-BxHkGbvJ.js} +19 -25
- package/dist/transformer-BxHkGbvJ.js.map +1 -0
- package/dist/transforms/button/transformer.js +377 -30
- package/dist/transforms/button/transformer.js.map +1 -1
- package/dist/transforms/list-item/transformer.js +2 -2
- package/package.json +1 -1
- package/dist/helpers-59xSDDPO.js.map +0 -1
- package/dist/transformer-DnE3TyyV.js.map +0 -1
|
@@ -1,6 +1,353 @@
|
|
|
1
1
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
|
-
const require_helpers = require('../../helpers-
|
|
2
|
+
const require_helpers = require('../../helpers-RWhTD5Is.js');
|
|
3
3
|
|
|
4
|
+
//#region src/helpers/addImport.ts
|
|
5
|
+
/**
|
|
6
|
+
* Adds a named import if it doesn't already exist.
|
|
7
|
+
*/
|
|
8
|
+
function addImport(root, sourceValue, importName, j) {
|
|
9
|
+
const existingImports = root.find(j.ImportDeclaration, { source: { value: sourceValue } });
|
|
10
|
+
if (existingImports.size() > 0) {
|
|
11
|
+
if (existingImports.find(j.ImportSpecifier, { imported: { name: importName } }).size() > 0) return;
|
|
12
|
+
existingImports.forEach((path) => {
|
|
13
|
+
if (path.node.specifiers) path.node.specifiers.push(j.importSpecifier(j.identifier(importName)));
|
|
14
|
+
});
|
|
15
|
+
} else {
|
|
16
|
+
const newImport = j.importDeclaration([j.importSpecifier(j.identifier(importName))], j.literal(sourceValue));
|
|
17
|
+
const firstImport = root.find(j.ImportDeclaration).at(0);
|
|
18
|
+
if (firstImport.size() > 0) firstImport.insertBefore(newImport);
|
|
19
|
+
else {
|
|
20
|
+
const program = root.find(j.Program);
|
|
21
|
+
if (program.size() > 0) program.get("body", 0).insertBefore(newImport);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
var addImport_default = addImport;
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/helpers/hasImport.ts
|
|
29
|
+
/**
|
|
30
|
+
* Checks if a specific import exists in the given root collection and provides
|
|
31
|
+
* a method to remove it if found.
|
|
32
|
+
*/
|
|
33
|
+
function hasImport(root, sourceValue, importName, j) {
|
|
34
|
+
const importDeclarations = root.find(j.ImportDeclaration, { source: { value: sourceValue } });
|
|
35
|
+
/**
|
|
36
|
+
* Finds all ImportSpecifier nodes that expose `importName` but
|
|
37
|
+
* from a different source than `sourceValue`.
|
|
38
|
+
*/
|
|
39
|
+
const conflictingImports = (() => {
|
|
40
|
+
const result = [];
|
|
41
|
+
root.find(j.ImportDeclaration).filter((path) => path.node.source.value !== sourceValue).forEach((path) => {
|
|
42
|
+
for (const specifier of path.node.specifiers ?? []) if (specifier.type === "ImportSpecifier" && specifier.imported.name === importName && specifier.local?.name === importName) result.push(specifier);
|
|
43
|
+
});
|
|
44
|
+
return result;
|
|
45
|
+
})();
|
|
46
|
+
if (importDeclarations.size() === 0) return {
|
|
47
|
+
exists: false,
|
|
48
|
+
remove: () => {},
|
|
49
|
+
resolvedName: importName,
|
|
50
|
+
conflictingImports
|
|
51
|
+
};
|
|
52
|
+
const namedImport = importDeclarations.find(j.ImportSpecifier, { imported: { name: importName } });
|
|
53
|
+
const defaultImport = importDeclarations.find(j.ImportDefaultSpecifier, { local: { name: importName } });
|
|
54
|
+
const aliasImport = importDeclarations.find(j.ImportSpecifier).filter((path) => {
|
|
55
|
+
return path.node.imported.name === importName && path.node.imported.name !== path.node.local?.name;
|
|
56
|
+
});
|
|
57
|
+
const exists = namedImport.size() > 0 || defaultImport.size() > 0;
|
|
58
|
+
const resolveName = () => {
|
|
59
|
+
if (aliasImport.size() > 0) {
|
|
60
|
+
const localName = aliasImport.get(0).node.local?.name;
|
|
61
|
+
if (typeof localName === "string") return localName;
|
|
62
|
+
if (localName && typeof localName === "object" && "name" in localName && typeof localName.name === "string") return localName.name;
|
|
63
|
+
return importName;
|
|
64
|
+
}
|
|
65
|
+
return importName;
|
|
66
|
+
};
|
|
67
|
+
const remove = () => {
|
|
68
|
+
importDeclarations.forEach((path) => {
|
|
69
|
+
const filteredSpecifiers = path.node.specifiers?.filter((specifier) => {
|
|
70
|
+
if (specifier.type === "ImportSpecifier" && specifier.imported.name === importName) return false;
|
|
71
|
+
if (specifier.type === "ImportDefaultSpecifier" && specifier.local?.name === importName) return false;
|
|
72
|
+
return true;
|
|
73
|
+
}) ?? [];
|
|
74
|
+
if (filteredSpecifiers.length === 0) path.prune();
|
|
75
|
+
else j(path).replaceWith(j.importDeclaration(filteredSpecifiers, path.node.source, path.node.importKind));
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
return {
|
|
79
|
+
exists,
|
|
80
|
+
remove,
|
|
81
|
+
aliases: aliasImport,
|
|
82
|
+
resolvedName: resolveName(),
|
|
83
|
+
conflictingImports
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
var hasImport_default = hasImport;
|
|
87
|
+
|
|
88
|
+
//#endregion
|
|
89
|
+
//#region src/helpers/iconUtils.ts
|
|
90
|
+
/**
|
|
91
|
+
* Process children of a JSX element to detect icon components and add iconStart or iconEnd attributes accordingly.
|
|
92
|
+
* This is specific to icon handling but can be reused in codemods dealing with icon children.
|
|
93
|
+
*/
|
|
94
|
+
const processIconChildren = (j, children, iconImports, openingElement) => {
|
|
95
|
+
if (!children || !openingElement.attributes) return;
|
|
96
|
+
const unwrapJsxElement = (node) => {
|
|
97
|
+
if (typeof node === "object" && node !== null && "type" in node && node.type === "JSXExpressionContainer" && j.JSXElement.check(node.expression)) return node.expression;
|
|
98
|
+
return node;
|
|
99
|
+
};
|
|
100
|
+
const totalChildren = children.length;
|
|
101
|
+
const iconChildIndex = children.findIndex((child) => {
|
|
102
|
+
const unwrapped = unwrapJsxElement(child);
|
|
103
|
+
return j.JSXElement.check(unwrapped) && unwrapped.openingElement.name.type === "JSXIdentifier" && iconImports.has(unwrapped.openingElement.name.name);
|
|
104
|
+
});
|
|
105
|
+
if (iconChildIndex === -1) return;
|
|
106
|
+
const iconChild = unwrapJsxElement(children[iconChildIndex]);
|
|
107
|
+
if (!iconChild || iconChild.openingElement.name.type !== "JSXIdentifier") return;
|
|
108
|
+
iconChild.openingElement.name.name;
|
|
109
|
+
const iconPropName = iconChildIndex <= totalChildren - 1 - iconChildIndex ? "addonStart" : "addonEnd";
|
|
110
|
+
const iconObject = j.objectExpression([j.property("init", j.identifier("type"), j.literal("icon")), j.property("init", j.identifier("value"), iconChild)]);
|
|
111
|
+
const iconProp = j.jsxAttribute(j.jsxIdentifier(iconPropName), j.jsxExpressionContainer(iconObject));
|
|
112
|
+
openingElement.attributes.push(iconProp);
|
|
113
|
+
children.splice(iconChildIndex, 1);
|
|
114
|
+
const isWhitespaceJsxText = (node) => {
|
|
115
|
+
return typeof node === "object" && node !== null && node.type === "JSXText" && typeof node.value === "string" && node.value.trim() === "";
|
|
116
|
+
};
|
|
117
|
+
if (iconChildIndex - 1 >= 0 && isWhitespaceJsxText(children[iconChildIndex - 1])) children.splice(iconChildIndex - 1, 1);
|
|
118
|
+
else if (isWhitespaceJsxText(children[iconChildIndex])) children.splice(iconChildIndex, 1);
|
|
119
|
+
};
|
|
120
|
+
var iconUtils_default = processIconChildren;
|
|
121
|
+
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/helpers/jsxElementUtils.ts
|
|
124
|
+
/**
|
|
125
|
+
* Rename a JSX element name if it is a JSXIdentifier.
|
|
126
|
+
*/
|
|
127
|
+
const setNameIfJSXIdentifier = (elementName, newName) => {
|
|
128
|
+
if (elementName && elementName.type === "JSXIdentifier") return {
|
|
129
|
+
...elementName,
|
|
130
|
+
name: newName
|
|
131
|
+
};
|
|
132
|
+
return elementName;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Check if a list of attributes contains a specific attribute by name.
|
|
136
|
+
*/
|
|
137
|
+
const hasAttribute = (attributes, attributeName) => {
|
|
138
|
+
return Array.isArray(attributes) && attributes.some((attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === attributeName);
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* Check if a JSX element's openingElement has a specific attribute.
|
|
142
|
+
*/
|
|
143
|
+
const hasAttributeOnElement = (element, attributeName) => {
|
|
144
|
+
return hasAttribute(element.attributes, attributeName);
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Add specified attributes to a JSX element's openingElement if they are not already present.
|
|
148
|
+
*/
|
|
149
|
+
const addAttributesIfMissing = (j, openingElement, attributesToAdd) => {
|
|
150
|
+
if (!Array.isArray(openingElement.attributes)) return;
|
|
151
|
+
const attrs = openingElement.attributes;
|
|
152
|
+
attributesToAdd.forEach(({ attribute, name }) => {
|
|
153
|
+
if (!hasAttributeOnElement(openingElement, name)) attrs.push(attribute);
|
|
154
|
+
});
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* Returns a collection of JSX elements that match the specified
|
|
158
|
+
* exported name or names of the found aliases.
|
|
159
|
+
*/
|
|
160
|
+
const findJSXElementsByName = (root, j) => (exportedName, aliases) => {
|
|
161
|
+
const aliasNames = aliases?.size() ? aliases.paths().map((path) => path.node.local?.name) : [];
|
|
162
|
+
return root.find(j.JSXElement).filter((path) => {
|
|
163
|
+
const { name } = path.node.openingElement;
|
|
164
|
+
return name.type === "JSXIdentifier" && (name.name === exportedName || aliasNames.includes(name.name));
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* Removes an attribute by name from a JSX element's openingElement.
|
|
169
|
+
*/
|
|
170
|
+
const removeAttributeByName = (j, openingElement, attributeName) => {
|
|
171
|
+
if (!Array.isArray(openingElement.attributes)) return;
|
|
172
|
+
openingElement.attributes = openingElement.attributes.filter((attr) => {
|
|
173
|
+
return !(attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === attributeName);
|
|
174
|
+
});
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
//#endregion
|
|
178
|
+
//#region src/helpers/jsxReportingUtils.ts
|
|
179
|
+
/**
|
|
180
|
+
* CodemodReporter is a utility class for reporting issues found during codemod transformations.
|
|
181
|
+
* It provides methods to report issues related to JSX elements, props, and attributes.
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```typescript
|
|
185
|
+
* const issues: string[] = [];
|
|
186
|
+
* const reporter = createReporter(j, issues);
|
|
187
|
+
*
|
|
188
|
+
* // Report a deprecated prop
|
|
189
|
+
* reporter.reportDeprecatedProp(buttonElement, 'flat', 'variant="text"');
|
|
190
|
+
*
|
|
191
|
+
* // Report complex expression that needs review
|
|
192
|
+
* reporter.reportAmbiguousExpression(element, 'size');
|
|
193
|
+
*
|
|
194
|
+
* // Auto-detect common issues
|
|
195
|
+
* reporter.reportAttributeIssues(element);
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
var CodemodReporter = class {
|
|
199
|
+
j;
|
|
200
|
+
issues;
|
|
201
|
+
constructor(options) {
|
|
202
|
+
this.j = options.jscodeshift;
|
|
203
|
+
this.issues = options.issues;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Reports an issue with a JSX element
|
|
207
|
+
*/
|
|
208
|
+
reportElement(element, reason) {
|
|
209
|
+
const node = this.getNode(element);
|
|
210
|
+
const componentName = this.getComponentName(node);
|
|
211
|
+
const line = this.getLineNumber(node);
|
|
212
|
+
this.addIssue(`Manual review required: <${componentName}> at line ${line} ${reason}.`);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Reports an issue with a specific prop
|
|
216
|
+
*/
|
|
217
|
+
reportProp(element, propName, reason) {
|
|
218
|
+
const node = this.getNode(element);
|
|
219
|
+
const componentName = this.getComponentName(node);
|
|
220
|
+
const line = this.getLineNumber(node);
|
|
221
|
+
this.addIssue(`Manual review required: prop "${propName}" on <${componentName}> at line ${line} ${reason}.`);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Reports an issue with a JSX attribute directly
|
|
225
|
+
*/
|
|
226
|
+
reportAttribute(attr, element, reason) {
|
|
227
|
+
const node = this.getNode(element);
|
|
228
|
+
const componentName = this.getComponentName(node);
|
|
229
|
+
const propName = this.getAttributeName(attr);
|
|
230
|
+
const line = this.getLineNumber(attr) || this.getLineNumber(node);
|
|
231
|
+
const defaultReason = this.getAttributeReason(attr);
|
|
232
|
+
const finalReason = reason || defaultReason;
|
|
233
|
+
this.addIssue(`Manual review required: prop "${propName}" on <${componentName}> at line ${line} ${finalReason}.`);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Reports spread props on an element
|
|
237
|
+
*/
|
|
238
|
+
reportSpreadProps(element) {
|
|
239
|
+
this.reportElement(element, "contains spread props that need manual review");
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Reports conflicting prop and children
|
|
243
|
+
*/
|
|
244
|
+
reportPropWithChildren(element, propName) {
|
|
245
|
+
this.reportProp(element, propName, `conflicts with children - both "${propName}" prop and children are present`);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Reports unsupported prop value
|
|
249
|
+
*/
|
|
250
|
+
reportUnsupportedValue(element, propName, value) {
|
|
251
|
+
this.reportProp(element, propName, `has unsupported value "${value}"`);
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Reports ambiguous expression in prop
|
|
255
|
+
*/
|
|
256
|
+
reportAmbiguousExpression(element, propName) {
|
|
257
|
+
this.reportProp(element, propName, "contains a complex expression that needs manual review");
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Reports ambiguous children (like dynamic icons)
|
|
261
|
+
*/
|
|
262
|
+
reportAmbiguousChildren(element, childType = "content") {
|
|
263
|
+
this.reportElement(element, `contains ambiguous ${childType} that needs manual review`);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Reports deprecated prop usage
|
|
267
|
+
*/
|
|
268
|
+
reportDeprecatedProp(element, propName, alternative) {
|
|
269
|
+
const suggestion = alternative ? ` Use ${alternative} instead` : "";
|
|
270
|
+
this.reportProp(element, propName, `is deprecated${suggestion}`);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Reports missing required prop
|
|
274
|
+
*/
|
|
275
|
+
reportMissingRequiredProp(element, propName) {
|
|
276
|
+
this.reportProp(element, propName, "is required but missing");
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Reports conflicting props
|
|
280
|
+
*/
|
|
281
|
+
reportConflictingProps(element, propNames) {
|
|
282
|
+
const propList = propNames.map((name) => `"${name}"`).join(", ");
|
|
283
|
+
this.reportElement(element, `has conflicting props: ${propList} cannot be used together`);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Auto-detects and reports common attribute issues
|
|
287
|
+
*/
|
|
288
|
+
reportAttributeIssues(element) {
|
|
289
|
+
const { attributes } = this.getNode(element).openingElement;
|
|
290
|
+
if (!attributes) return;
|
|
291
|
+
if (attributes.some((attr) => attr.type === "JSXSpreadAttribute")) this.reportSpreadProps(element);
|
|
292
|
+
attributes.forEach((attr) => {
|
|
293
|
+
if (attr.type === "JSXAttribute" && attr.value?.type === "JSXExpressionContainer") this.reportAttribute(attr, element);
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Finds and reports instances of components that are under an alias (imported with a different name)
|
|
298
|
+
*/
|
|
299
|
+
reportAliases(element) {
|
|
300
|
+
this.reportElement(element, "is used via an import alias and needs manual review");
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Finds and reports instances of non-DS import declarations that conflict with the component name
|
|
304
|
+
*/
|
|
305
|
+
reportConflictingImports(node) {
|
|
306
|
+
this.addIssue(`Manual review required: Non-WDS package resulting in an import conflict at line ${this.getLineNumber(node)}.`);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Reports enum usage for future conversion tracking
|
|
310
|
+
*/
|
|
311
|
+
reportEnumUsage(element, propName, enumValue) {
|
|
312
|
+
this.reportProp(element, propName, `uses enum value "${enumValue}" which has been preserved but should be migrated to a string literal in the future`);
|
|
313
|
+
}
|
|
314
|
+
getNode(element) {
|
|
315
|
+
return "node" in element ? element.node : element;
|
|
316
|
+
}
|
|
317
|
+
getComponentName(node) {
|
|
318
|
+
const { name } = node.openingElement;
|
|
319
|
+
if (name.type === "JSXIdentifier") return name.name;
|
|
320
|
+
return this.j(name).toSource();
|
|
321
|
+
}
|
|
322
|
+
getLineNumber(node) {
|
|
323
|
+
return node.loc?.start.line?.toString() || "unknown";
|
|
324
|
+
}
|
|
325
|
+
getAttributeName(attr) {
|
|
326
|
+
if (attr.name.type === "JSXIdentifier") return attr.name.name;
|
|
327
|
+
return this.j(attr.name).toSource();
|
|
328
|
+
}
|
|
329
|
+
getAttributeReason(attr) {
|
|
330
|
+
if (!attr.value) return "has no value";
|
|
331
|
+
if (attr.value.type === "JSXExpressionContainer") {
|
|
332
|
+
const expr = attr.value.expression;
|
|
333
|
+
const expressionType = expr.type.replace("Expression", "").toLowerCase();
|
|
334
|
+
if (expr.type === "Identifier" || expr.type === "MemberExpression") return `contains a ${expressionType} (${this.j(expr).toSource()})`;
|
|
335
|
+
return `contains a complex ${expressionType} expression`;
|
|
336
|
+
}
|
|
337
|
+
return "needs manual review";
|
|
338
|
+
}
|
|
339
|
+
addIssue(message) {
|
|
340
|
+
this.issues.push(message);
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
const createReporter = (j, issues) => {
|
|
344
|
+
return new CodemodReporter({
|
|
345
|
+
jscodeshift: j,
|
|
346
|
+
issues
|
|
347
|
+
});
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
//#endregion
|
|
4
351
|
//#region src/transforms/button/transformer.ts
|
|
5
352
|
const parser = "tsx";
|
|
6
353
|
const buildPriorityMapping = (opts) => {
|
|
@@ -135,10 +482,10 @@ const transformer = (file, api, options) => {
|
|
|
135
482
|
if (type && priority) return priorityMapping[type]?.[priority] || priority;
|
|
136
483
|
return priority;
|
|
137
484
|
};
|
|
138
|
-
const reporter =
|
|
139
|
-
const { exists: hasButtonImport, aliases: buttonAliases, resolvedName: buttonName, conflictingImports: conflictingButtonImport } =
|
|
485
|
+
const reporter = createReporter(j, manualReviewIssues);
|
|
486
|
+
const { exists: hasButtonImport, aliases: buttonAliases, resolvedName: buttonName, conflictingImports: conflictingButtonImport } = hasImport_default(root, "@transferwise/components", "Button", j);
|
|
140
487
|
if (conflictingButtonImport.length) conflictingButtonImport.forEach((node) => reporter.reportConflictingImports(node));
|
|
141
|
-
const { exists: hasActionButtonImport, remove: removeActionButtonImport, aliases: actionButtonAliases } =
|
|
488
|
+
const { exists: hasActionButtonImport, remove: removeActionButtonImport, aliases: actionButtonAliases } = hasImport_default(root, "@transferwise/components", "ActionButton", j);
|
|
142
489
|
if (!hasButtonImport && !hasActionButtonImport) return file.source;
|
|
143
490
|
const iconImports = /* @__PURE__ */ new Set();
|
|
144
491
|
root.find(j.ImportDeclaration, { source: { value: "@transferwise/icons" } }).forEach((path) => {
|
|
@@ -150,12 +497,12 @@ const transformer = (file, api, options) => {
|
|
|
150
497
|
});
|
|
151
498
|
});
|
|
152
499
|
if (hasActionButtonImport) {
|
|
153
|
-
if (!hasButtonImport)
|
|
154
|
-
|
|
500
|
+
if (!hasButtonImport) addImport_default(root, "@transferwise/components", "Button", j);
|
|
501
|
+
findJSXElementsByName(root, j)("ActionButton", actionButtonAliases).forEach((path) => {
|
|
155
502
|
const { openingElement, closingElement } = path.node;
|
|
156
|
-
openingElement.name =
|
|
157
|
-
if (closingElement) closingElement.name =
|
|
158
|
-
|
|
503
|
+
openingElement.name = setNameIfJSXIdentifier(openingElement.name, buttonName);
|
|
504
|
+
if (closingElement) closingElement.name = setNameIfJSXIdentifier(closingElement.name, buttonName);
|
|
505
|
+
iconUtils_default(j, path.node.children, iconImports, openingElement);
|
|
159
506
|
if ((openingElement.attributes ?? []).some((attr) => attr.type === "JSXSpreadAttribute")) reporter.reportSpreadProps(path);
|
|
160
507
|
const legacyPropNames = [
|
|
161
508
|
"priority",
|
|
@@ -178,7 +525,7 @@ const transformer = (file, api, options) => {
|
|
|
178
525
|
const hasChildren = path.node.children?.some((child) => child.type === "JSXText" && child.value.trim() !== "" || child.type === "JSXElement" || child.type === "JSXExpressionContainer") || path.node.children && path.node.children?.length > 0;
|
|
179
526
|
if (hasTextProp && hasChildren) reporter.reportPropWithChildren(path, "text");
|
|
180
527
|
else if (hasTextProp && !hasChildren && openingElement.selfClosing) path.replace(j.jsxElement(j.jsxOpeningElement(openingElement.name, openingElement.attributes), j.jsxClosingElement(openingElement.name), [j.jsxText(legacyProps.text || "")]));
|
|
181
|
-
|
|
528
|
+
addAttributesIfMissing(j, path.node.openingElement, [{
|
|
182
529
|
attribute: j.jsxAttribute(j.jsxIdentifier("v2")),
|
|
183
530
|
name: "v2"
|
|
184
531
|
}, {
|
|
@@ -194,17 +541,17 @@ const transformer = (file, api, options) => {
|
|
|
194
541
|
});
|
|
195
542
|
removeActionButtonImport();
|
|
196
543
|
}
|
|
197
|
-
if (hasButtonImport)
|
|
544
|
+
if (hasButtonImport) findJSXElementsByName(root, j)("Button", buttonAliases).forEach((path) => {
|
|
198
545
|
const { openingElement } = path.node;
|
|
199
|
-
if (
|
|
546
|
+
if (hasAttributeOnElement(openingElement, "v2")) return;
|
|
200
547
|
const hasJSXChildren = path.node.children?.some((child) => child.type === "JSXText" && child.value.trim() !== "" || child.type === "JSXElement" || child.type === "JSXFragment" && child.children && child.children.length > 0 || child.type === "JSXExpressionContainer" && child.expression.type !== "JSXEmptyExpression");
|
|
201
548
|
const hasChildrenAsProp = openingElement.attributes?.some((attr) => attr.type === "JSXAttribute" && attr.name?.type === "JSXIdentifier" && attr.name.name === "children");
|
|
202
549
|
if (!hasJSXChildren && !hasChildrenAsProp) return;
|
|
203
|
-
|
|
550
|
+
addAttributesIfMissing(j, openingElement, [{
|
|
204
551
|
attribute: j.jsxAttribute(j.jsxIdentifier("v2")),
|
|
205
552
|
name: "v2"
|
|
206
553
|
}]);
|
|
207
|
-
|
|
554
|
+
iconUtils_default(j, path.node.children, iconImports, openingElement);
|
|
208
555
|
const legacyProps = {};
|
|
209
556
|
const legacyPropNames = [
|
|
210
557
|
"priority",
|
|
@@ -240,7 +587,7 @@ const transformer = (file, api, options) => {
|
|
|
240
587
|
"lg",
|
|
241
588
|
"xl"
|
|
242
589
|
].includes(resolved)) {
|
|
243
|
-
|
|
590
|
+
removeAttributeByName(j, openingElement, "size");
|
|
244
591
|
openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("size"), j.literal(resolved)));
|
|
245
592
|
} else if (typeof rawValue === "string") reporter.reportUnsupportedValue(path, "size", rawValue);
|
|
246
593
|
else if (rawValue !== void 0) reporter.reportAmbiguousExpression(path, "size");
|
|
@@ -265,7 +612,7 @@ const transformer = (file, api, options) => {
|
|
|
265
612
|
"tertiary",
|
|
266
613
|
"secondary-neutral"
|
|
267
614
|
].includes(mapped)) {
|
|
268
|
-
|
|
615
|
+
removeAttributeByName(j, openingElement, "priority");
|
|
269
616
|
openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("priority"), j.literal(mapped)));
|
|
270
617
|
} else if (typeof rawValue === "string") reporter.reportUnsupportedValue(path, "priority", rawValue);
|
|
271
618
|
else if (rawValue !== void 0) reporter.reportAmbiguousExpression(path, "priority");
|
|
@@ -297,20 +644,20 @@ const transformer = (file, api, options) => {
|
|
|
297
644
|
"reset"
|
|
298
645
|
];
|
|
299
646
|
if (resolvedType === "negative" && isControlTypeEnum) {
|
|
300
|
-
|
|
301
|
-
if (
|
|
302
|
-
|
|
647
|
+
removeAttributeByName(j, openingElement, "type");
|
|
648
|
+
if (hasAttributeOnElement(openingElement, "sentiment")) removeAttributeByName(j, openingElement, "sentiment");
|
|
649
|
+
addAttributesIfMissing(j, openingElement, [{
|
|
303
650
|
attribute: j.jsxAttribute(j.jsxIdentifier("priority"), j.literal("primary")),
|
|
304
651
|
name: "priority"
|
|
305
652
|
}]);
|
|
306
653
|
if (rawType) openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("sentiment"), j.jsxExpressionContainer(j.identifier(rawType))));
|
|
307
654
|
} else if (resolvedType === "negative" && !isTypeEnum) {
|
|
308
|
-
|
|
309
|
-
if (
|
|
655
|
+
removeAttributeByName(j, openingElement, "type");
|
|
656
|
+
if (hasAttributeOnElement(openingElement, "sentiment")) removeAttributeByName(j, openingElement, "sentiment");
|
|
310
657
|
openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("sentiment"), j.literal("negative")));
|
|
311
658
|
} else if (isControlTypeEnum && resolvedType && ["positive", "accent"].includes(resolvedType)) {
|
|
312
|
-
|
|
313
|
-
|
|
659
|
+
removeAttributeByName(j, openingElement, "type");
|
|
660
|
+
addAttributesIfMissing(j, openingElement, [{
|
|
314
661
|
attribute: j.jsxAttribute(j.jsxIdentifier("priority"), j.literal("primary")),
|
|
315
662
|
name: "priority"
|
|
316
663
|
}]);
|
|
@@ -318,21 +665,21 @@ const transformer = (file, api, options) => {
|
|
|
318
665
|
if (resolvedType && typeof resolvedType === "string" && legacyButtonTypes.includes(resolvedType) && !isTypeEnum) {
|
|
319
666
|
const consistentConversion = getConsistentTypeConversions(resolvedType);
|
|
320
667
|
if (consistentConversion) {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
668
|
+
removeAttributeByName(j, openingElement, "type");
|
|
669
|
+
removeAttributeByName(j, openingElement, "priority");
|
|
670
|
+
removeAttributeByName(j, openingElement, "sentiment");
|
|
324
671
|
if (consistentConversion.priority) openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("priority"), j.literal(consistentConversion.priority)));
|
|
325
672
|
if (consistentConversion.sentiment) openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("sentiment"), j.literal(consistentConversion.sentiment)));
|
|
326
673
|
} else {
|
|
327
|
-
|
|
328
|
-
|
|
674
|
+
removeAttributeByName(j, openingElement, "type");
|
|
675
|
+
addAttributesIfMissing(j, openingElement, [{
|
|
329
676
|
attribute: j.jsxAttribute(j.jsxIdentifier("priority"), j.literal("primary")),
|
|
330
677
|
name: "priority"
|
|
331
678
|
}]);
|
|
332
679
|
}
|
|
333
680
|
} else if (isTypeEnum) {}
|
|
334
681
|
if (typeof finalHtmlType === "string" && htmlTypes.includes(finalHtmlType)) {
|
|
335
|
-
|
|
682
|
+
removeAttributeByName(j, openingElement, "htmlType");
|
|
336
683
|
openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("type"), j.literal(finalHtmlType)));
|
|
337
684
|
} else if (typeof rawType === "string" || typeof rawHtmlType === "string") {
|
|
338
685
|
const valueToCheck = rawType ?? rawHtmlType ?? "";
|
|
@@ -351,7 +698,7 @@ const transformer = (file, api, options) => {
|
|
|
351
698
|
if (!openingElement.attributes?.some((attr) => attr.type === "JSXAttribute" && attr.name && attr.name.name === "sentiment")) {
|
|
352
699
|
const rawValue = legacyProps.sentiment;
|
|
353
700
|
if (rawValue === "negative") {
|
|
354
|
-
|
|
701
|
+
removeAttributeByName(j, openingElement, "sentiment");
|
|
355
702
|
openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("sentiment"), j.literal("negative")));
|
|
356
703
|
} else if (typeof rawValue === "string") reporter.reportUnsupportedValue(path, "sentiment", rawValue);
|
|
357
704
|
else if (rawValue !== void 0) reporter.reportAmbiguousExpression(path, "sentiment");
|