@atlaskit/codemod-cli 0.29.2 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/main.js +1 -1
  3. package/dist/cjs/presets/index.js +3 -1
  4. package/dist/cjs/presets/lozenge-appearance-to-color/codemods/lozenge-appearance-to-color.js +138 -0
  5. package/dist/cjs/presets/lozenge-appearance-to-color/lozenge-appearance-to-color.js +44 -0
  6. package/dist/cjs/presets/lozenge-to-tag-migration/codemods/lozenge-to-tag-migration.js +253 -0
  7. package/dist/cjs/presets/lozenge-to-tag-migration/lozenge-to-tag-migration.js +44 -0
  8. package/dist/es2019/presets/index.js +3 -1
  9. package/dist/es2019/presets/lozenge-appearance-to-color/codemods/lozenge-appearance-to-color.js +137 -0
  10. package/dist/es2019/presets/lozenge-appearance-to-color/lozenge-appearance-to-color.js +18 -0
  11. package/dist/es2019/presets/lozenge-to-tag-migration/codemods/lozenge-to-tag-migration.js +242 -0
  12. package/dist/es2019/presets/lozenge-to-tag-migration/lozenge-to-tag-migration.js +18 -0
  13. package/dist/esm/main.js +1 -1
  14. package/dist/esm/presets/index.js +3 -1
  15. package/dist/esm/presets/lozenge-appearance-to-color/codemods/lozenge-appearance-to-color.js +132 -0
  16. package/dist/esm/presets/lozenge-appearance-to-color/lozenge-appearance-to-color.js +37 -0
  17. package/dist/esm/presets/lozenge-to-tag-migration/codemods/lozenge-to-tag-migration.js +247 -0
  18. package/dist/esm/presets/lozenge-to-tag-migration/lozenge-to-tag-migration.js +37 -0
  19. package/dist/types/presets/index.d.ts +2 -0
  20. package/dist/types/presets/lozenge-appearance-to-color/codemods/lozenge-appearance-to-color.d.ts +10 -0
  21. package/dist/types/presets/lozenge-appearance-to-color/lozenge-appearance-to-color.d.ts +2 -0
  22. package/dist/types/presets/lozenge-to-tag-migration/codemods/lozenge-to-tag-migration.d.ts +3 -0
  23. package/dist/types/presets/lozenge-to-tag-migration/lozenge-to-tag-migration.d.ts +2 -0
  24. package/dist/types-ts4.5/presets/index.d.ts +2 -0
  25. package/dist/types-ts4.5/presets/lozenge-appearance-to-color/codemods/lozenge-appearance-to-color.d.ts +10 -0
  26. package/dist/types-ts4.5/presets/lozenge-appearance-to-color/lozenge-appearance-to-color.d.ts +2 -0
  27. package/dist/types-ts4.5/presets/lozenge-to-tag-migration/codemods/lozenge-to-tag-migration.d.ts +3 -0
  28. package/dist/types-ts4.5/presets/lozenge-to-tag-migration/lozenge-to-tag-migration.d.ts +2 -0
  29. package/package.json +2 -2
@@ -0,0 +1,247 @@
1
+ import { addCommentBefore } from '@atlaskit/codemod-utils';
2
+ var transformer = function transformer(file, api) {
3
+ var j = api.jscodeshift;
4
+ var source = j(file.source);
5
+
6
+ // Check if file has Lozenge imports
7
+ var lozengeImports = source.find(j.ImportDeclaration).filter(function (path) {
8
+ return path.node.source.value === '@atlaskit/lozenge';
9
+ });
10
+ if (lozengeImports.length === 0) {
11
+ return file.source;
12
+ }
13
+
14
+ // Get the import name for Lozenge (could be renamed)
15
+ var lozengeImportName = 'Lozenge';
16
+ lozengeImports.forEach(function (importPath) {
17
+ var _importPath$node$spec;
18
+ (_importPath$node$spec = importPath.node.specifiers) === null || _importPath$node$spec === void 0 || _importPath$node$spec.forEach(function (specifier) {
19
+ if (j.ImportDefaultSpecifier.check(specifier)) {
20
+ var _specifier$local;
21
+ lozengeImportName = ((_specifier$local = specifier.local) === null || _specifier$local === void 0 ? void 0 : _specifier$local.name) || 'Lozenge';
22
+ } else if (j.ImportSpecifier.check(specifier)) {
23
+ // Handle { default as Badge } syntax
24
+ if (j.Identifier.check(specifier.imported) && specifier.imported.name === 'default') {
25
+ var _specifier$local2;
26
+ lozengeImportName = ((_specifier$local2 = specifier.local) === null || _specifier$local2 === void 0 ? void 0 : _specifier$local2.name) || 'Lozenge';
27
+ }
28
+ }
29
+ });
30
+ });
31
+
32
+ // Appearance to color mapping
33
+ var appearanceToColorMap = {
34
+ success: 'lime',
35
+ default: 'standard',
36
+ removed: 'red',
37
+ inprogress: 'blue',
38
+ new: 'purple',
39
+ moved: 'orange'
40
+ };
41
+ var hasTransformed = false;
42
+
43
+ // Find and transform Lozenge elements
44
+ source.find(j.JSXElement).forEach(function (elementPath) {
45
+ var _element$openingEleme, _element$openingEleme2;
46
+ var element = elementPath.node;
47
+ if (!j.JSXIdentifier.check(element.openingElement.name)) {
48
+ return;
49
+ }
50
+ if (element.openingElement.name.name !== lozengeImportName) {
51
+ return;
52
+ }
53
+
54
+ // Check isBold attribute
55
+ var isBoldAttr = (_element$openingEleme = element.openingElement.attributes) === null || _element$openingEleme === void 0 ? void 0 : _element$openingEleme.find(function (attr) {
56
+ return j.JSXAttribute.check(attr) && j.JSXIdentifier.check(attr.name) && attr.name.name === 'isBold';
57
+ });
58
+
59
+ // Don't transform if isBold is true or boolean prop without value
60
+ if (isBoldAttr) {
61
+ if (j.JSXExpressionContainer.check(isBoldAttr.value)) {
62
+ var expression = isBoldAttr.value.expression;
63
+
64
+ // If it's a boolean literal true, don't transform
65
+ if (j.BooleanLiteral.check(expression) && expression.value === true) {
66
+ return;
67
+ }
68
+
69
+ // If it's a boolean literal false, we can transform
70
+ if (j.BooleanLiteral.check(expression) && expression.value === false) {
71
+ // Continue with transformation
72
+ } else {
73
+ // If it's not a boolean literal (dynamic value), add warning and don't transform
74
+ addCommentBefore(j, j(elementPath), "FIXME: This Lozenge component uses a dynamic `isBold` prop. Please manually review if this should be migrated to Tag component.\nIf isBold is typically false, consider migrating to <Tag /> from '@atlaskit/tag'.");
75
+ return;
76
+ }
77
+ } else if (!isBoldAttr.value) {
78
+ // isBold prop without value (boolean shorthand) means true, don't transform
79
+ return;
80
+ }
81
+ }
82
+
83
+ // Create new Tag element
84
+ var newAttributes = [];
85
+ var otherAttributes = [];
86
+ var colorAttribute = null;
87
+ var textContent = '';
88
+ var hasComplexChildren = false;
89
+ var hasStyleProp = false;
90
+ var hasMaxWidthProp = false;
91
+ var hasUnknownAppearance = false;
92
+ var dynamicAppearance = false;
93
+ var unknownAppearanceValue = '';
94
+
95
+ // Process children to extract text
96
+ if (element.children && element.children.length > 0) {
97
+ if (element.children.length === 1) {
98
+ var child = element.children[0];
99
+ if (j.JSXText.check(child)) {
100
+ var text = child.value.trim();
101
+ if (text) {
102
+ textContent = text;
103
+ }
104
+ } else if (j.JSXExpressionContainer.check(child) && j.StringLiteral.check(child.expression)) {
105
+ textContent = child.expression.value;
106
+ } else {
107
+ hasComplexChildren = true;
108
+ }
109
+ } else {
110
+ // Multiple children or complex structure
111
+ hasComplexChildren = true;
112
+ }
113
+ }
114
+
115
+ // Process attributes
116
+ (_element$openingEleme2 = element.openingElement.attributes) === null || _element$openingEleme2 === void 0 || _element$openingEleme2.forEach(function (attr) {
117
+ if (!j.JSXAttribute.check(attr) || !j.JSXIdentifier.check(attr.name)) {
118
+ return;
119
+ }
120
+ var attrName = attr.name.name;
121
+ switch (attrName) {
122
+ case 'appearance':
123
+ var colorValue = 'standard';
124
+ if (j.StringLiteral.check(attr.value)) {
125
+ var appearanceValue = attr.value.value;
126
+ colorValue = appearanceToColorMap[appearanceValue] || appearanceValue;
127
+ if (!appearanceToColorMap[appearanceValue]) {
128
+ hasUnknownAppearance = true;
129
+ unknownAppearanceValue = appearanceValue;
130
+ }
131
+ } else if (j.JSXExpressionContainer.check(attr.value)) {
132
+ // Dynamic appearance
133
+ dynamicAppearance = true;
134
+ colorValue = attr.value;
135
+ }
136
+ colorAttribute = j.jsxAttribute(j.jsxIdentifier('color'), typeof colorValue === 'string' ? j.stringLiteral(colorValue) : colorValue);
137
+ break;
138
+ case 'isBold':
139
+ // Skip isBold, already handled above
140
+ break;
141
+ case 'maxWidth':
142
+ hasMaxWidthProp = true;
143
+ break;
144
+ case 'style':
145
+ hasStyleProp = true;
146
+ otherAttributes.push(attr);
147
+ break;
148
+ default:
149
+ // Keep other attributes (testId, etc.)
150
+ otherAttributes.push(attr);
151
+ break;
152
+ }
153
+ });
154
+
155
+ // Assemble attributes in correct order: text, other props, color
156
+ if (textContent && !hasComplexChildren) {
157
+ newAttributes.push(j.jsxAttribute(j.jsxIdentifier('text'), j.stringLiteral(textContent)));
158
+ }
159
+
160
+ // Add other attributes
161
+ newAttributes.push.apply(newAttributes, otherAttributes);
162
+
163
+ // Add color attribute last (default to 'standard' if no appearance was found)
164
+ if (colorAttribute) {
165
+ newAttributes.push(colorAttribute);
166
+ } else {
167
+ // Default color when no appearance is specified
168
+ newAttributes.push(j.jsxAttribute(j.jsxIdentifier('color'), j.stringLiteral('standard')));
169
+ }
170
+
171
+ // Create new Tag element
172
+ var newElement = j.jsxElement(j.jsxOpeningElement(j.jsxIdentifier('Tag'), newAttributes, true), null, []);
173
+
174
+ // Add warning comments as needed
175
+ var warnings = [];
176
+ if (hasComplexChildren) {
177
+ warnings.push("FIXME: This Tag component has complex children that couldn't be automatically migrated to the text prop.\nTag component only supports simple text via the text prop. Please manually convert the children content.");
178
+ }
179
+ if (hasMaxWidthProp) {
180
+ warnings.push('FIXME: maxWidth prop was removed during migration from Lozenge to Tag.\nTag component does not support maxWidth. Please review if width constraints are needed.');
181
+ }
182
+ if (hasStyleProp) {
183
+ warnings.push('FIXME: This Tag component has a style prop that was kept during migration.\nTag component has limited style support. Please review if custom styles are compatible.');
184
+ }
185
+ if (hasUnknownAppearance) {
186
+ warnings.push("FIXME: This Tag component uses an unknown appearance value \"".concat(unknownAppearanceValue, "\".\nPlease update to a valid Tag color: standard, green, lime, blue, red, purple, magenta, grey, teal, orange, yellow."));
187
+ }
188
+ if (dynamicAppearance) {
189
+ warnings.push('FIXME: This Tag component uses a dynamic `appearance` prop that has been renamed to `color`.\nPlease verify that the values being passed are valid color values (semantic: default, inprogress, moved, new, removed, success).');
190
+ }
191
+
192
+ // Replace the element first
193
+ elementPath.replace(newElement);
194
+
195
+ // Add warning comments using addCommentBefore if needed
196
+ if (warnings.length > 0) {
197
+ var commentText = warnings.join('\n');
198
+ addCommentBefore(j, j(elementPath), commentText);
199
+ }
200
+ hasTransformed = true;
201
+ });
202
+
203
+ // Add Tag import if we transformed any elements
204
+ if (hasTransformed) {
205
+ // Check if Tag import already exists
206
+ var tagImports = source.find(j.ImportDeclaration).filter(function (path) {
207
+ return path.node.source.value === '@atlaskit/tag';
208
+ });
209
+ if (tagImports.length === 0) {
210
+ // Add Tag import after Lozenge import
211
+ var lozengeImportPath = lozengeImports.at(0);
212
+ var tagImport = j.importDeclaration([j.importDefaultSpecifier(j.identifier('Tag'))], j.stringLiteral('@atlaskit/tag'));
213
+ lozengeImportPath.insertAfter(tagImport);
214
+ }
215
+
216
+ // Check if there are any remaining Lozenge usages
217
+ var remainingLozengeUsages = source.find(j.JSXElement).filter(function (elementPath) {
218
+ var element = elementPath.node;
219
+ if (!j.JSXIdentifier.check(element.openingElement.name)) {
220
+ return false;
221
+ }
222
+ return element.openingElement.name.name === lozengeImportName;
223
+ });
224
+
225
+ // Also check for other usages like function calls, type references, etc.
226
+ var remainingLozengeReferences = source.find(j.Identifier).filter(function (identifierPath) {
227
+ // Skip JSX element names as they're already checked above
228
+ if (j.JSXElement.check(identifierPath.parent.node) || j.JSXOpeningElement.check(identifierPath.parent.node) || j.JSXClosingElement.check(identifierPath.parent.node)) {
229
+ return false;
230
+ }
231
+
232
+ // Skip import declaration identifiers
233
+ if (j.ImportDeclaration.check(identifierPath.parent.node) || j.ImportDefaultSpecifier.check(identifierPath.parent.node) || j.ImportSpecifier.check(identifierPath.parent.node)) {
234
+ return false;
235
+ }
236
+ return identifierPath.node.name === lozengeImportName;
237
+ });
238
+
239
+ // If no remaining usages, remove the Lozenge import
240
+ if (remainingLozengeUsages.length === 0 && remainingLozengeReferences.length === 0) {
241
+ lozengeImports.remove();
242
+ }
243
+ return source.toSource();
244
+ }
245
+ return source.toSource();
246
+ };
247
+ export default transformer;
@@ -0,0 +1,37 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
3
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
4
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
5
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
6
+ import lozengeToTagMigrationTransformer from './codemods/lozenge-to-tag-migration';
7
+ export default function transformer(_x, _x2) {
8
+ return _transformer.apply(this, arguments);
9
+ }
10
+ function _transformer() {
11
+ _transformer = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(file, api) {
12
+ var transformers, src;
13
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
14
+ while (1) switch (_context.prev = _context.next) {
15
+ case 0:
16
+ transformers = [lozengeToTagMigrationTransformer];
17
+ src = file.source;
18
+ transformers.forEach(function (transformer) {
19
+ if (typeof src === 'undefined') {
20
+ return;
21
+ }
22
+ var nextSrc = transformer(_objectSpread(_objectSpread({}, file), {}, {
23
+ source: src
24
+ }), api);
25
+ if (nextSrc) {
26
+ src = nextSrc;
27
+ }
28
+ });
29
+ return _context.abrupt("return", src);
30
+ case 4:
31
+ case "end":
32
+ return _context.stop();
33
+ }
34
+ }, _callee);
35
+ }));
36
+ return _transformer.apply(this, arguments);
37
+ }
@@ -10,5 +10,7 @@ import './migrate-icon-object-to-object/migrate-icon-object-to-object';
10
10
  import './upgrade-pragmatic-drag-and-drop-to-stable/upgrade-pragmatic-drag-and-drop-to-stable';
11
11
  import './remove-dark-theme-vr-options/remove-dark-theme-vr-options';
12
12
  import './remove-token-fallbacks/remove-token-fallbacks';
13
+ import './lozenge-appearance-to-color/lozenge-appearance-to-color';
14
+ import './lozenge-to-tag-migration/lozenge-to-tag-migration';
13
15
  declare const presets: string[];
14
16
  export default presets;
@@ -0,0 +1,10 @@
1
+ import { type API, type FileInfo } from 'jscodeshift';
2
+ /**
3
+ * Codemod to migrate Lozenge component from `appearance` prop to `color` prop.
4
+ *
5
+ * This codemod:
6
+ * 1. Renames `appearance` prop to `color` for semantic values
7
+ * 2. Maps existing semantic values directly (e.g. success → success)
8
+ * 3. Adds comments for dynamic values that need manual verification
9
+ */
10
+ export default function transformer(file: FileInfo, api: API): string;
@@ -0,0 +1,2 @@
1
+ import type { API, FileInfo } from 'jscodeshift';
2
+ export default function transformer(file: FileInfo, api: API): Promise<string>;
@@ -0,0 +1,3 @@
1
+ import type { API, FileInfo } from 'jscodeshift';
2
+ declare const transformer: (file: FileInfo, api: API) => string | undefined;
3
+ export default transformer;
@@ -0,0 +1,2 @@
1
+ import type { API, FileInfo } from 'jscodeshift';
2
+ export default function transformer(file: FileInfo, api: API): Promise<string>;
@@ -10,5 +10,7 @@ import './migrate-icon-object-to-object/migrate-icon-object-to-object';
10
10
  import './upgrade-pragmatic-drag-and-drop-to-stable/upgrade-pragmatic-drag-and-drop-to-stable';
11
11
  import './remove-dark-theme-vr-options/remove-dark-theme-vr-options';
12
12
  import './remove-token-fallbacks/remove-token-fallbacks';
13
+ import './lozenge-appearance-to-color/lozenge-appearance-to-color';
14
+ import './lozenge-to-tag-migration/lozenge-to-tag-migration';
13
15
  declare const presets: string[];
14
16
  export default presets;
@@ -0,0 +1,10 @@
1
+ import { type API, type FileInfo } from 'jscodeshift';
2
+ /**
3
+ * Codemod to migrate Lozenge component from `appearance` prop to `color` prop.
4
+ *
5
+ * This codemod:
6
+ * 1. Renames `appearance` prop to `color` for semantic values
7
+ * 2. Maps existing semantic values directly (e.g. success → success)
8
+ * 3. Adds comments for dynamic values that need manual verification
9
+ */
10
+ export default function transformer(file: FileInfo, api: API): string;
@@ -0,0 +1,2 @@
1
+ import type { API, FileInfo } from 'jscodeshift';
2
+ export default function transformer(file: FileInfo, api: API): Promise<string>;
@@ -0,0 +1,3 @@
1
+ import type { API, FileInfo } from 'jscodeshift';
2
+ declare const transformer: (file: FileInfo, api: API) => string | undefined;
3
+ export default transformer;
@@ -0,0 +1,2 @@
1
+ import type { API, FileInfo } from 'jscodeshift';
2
+ export default function transformer(file: FileInfo, api: API): Promise<string>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/codemod-cli",
3
- "version": "0.29.2",
3
+ "version": "0.31.0",
4
4
  "description": "A cli for distributing codemods for atlassian-frontend components and services",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -29,7 +29,7 @@
29
29
  "bin": "./bin/codemod-cli.js",
30
30
  "dependencies": {
31
31
  "@atlaskit/codemod-utils": "^4.2.0",
32
- "@atlaskit/tokens": "^7.0.0",
32
+ "@atlaskit/tokens": "^7.1.0",
33
33
  "@babel/runtime": "^7.0.0",
34
34
  "@codeshift/utils": "^0.2.4",
35
35
  "@hypermod/utils": "^0.4.2",