@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,137 @@
1
+ import { getImportDeclaration } from '@hypermod/utils';
2
+ import { addCommentBefore } from '@atlaskit/codemod-utils';
3
+ const LOZENGE_ENTRY_POINT = '@atlaskit/lozenge';
4
+ const PRINT_SETTINGS = {
5
+ quote: 'single'
6
+ };
7
+
8
+ // Semantic appearance values that map directly to color values
9
+ const APPEARANCE_TO_COLOR_MAP = {
10
+ default: 'neutral',
11
+ inprogress: 'information',
12
+ moved: 'warning',
13
+ new: 'discovery',
14
+ removed: 'danger',
15
+ success: 'success'
16
+ };
17
+ /**
18
+ * Codemod to migrate Lozenge component from `appearance` prop to `color` prop.
19
+ *
20
+ * This codemod:
21
+ * 1. Renames `appearance` prop to `color` for semantic values
22
+ * 2. Maps existing semantic values directly (e.g. success → success)
23
+ * 3. Adds comments for dynamic values that need manual verification
24
+ */
25
+ export default function transformer(file, api) {
26
+ const j = api.jscodeshift;
27
+ const source = j(file.source);
28
+
29
+ // Find all Lozenge imports
30
+ const lozengeImports = getImportDeclaration(j, source, LOZENGE_ENTRY_POINT);
31
+
32
+ // If no Lozenge imports, exit early
33
+ if (!lozengeImports.length) {
34
+ return file.source;
35
+ }
36
+
37
+ // Get all imported Lozenge identifiers (could be renamed)
38
+ const lozengeIdentifiers = new Set();
39
+ lozengeImports.forEach(importPath => {
40
+ var _importPath$value$spe;
41
+ (_importPath$value$spe = importPath.value.specifiers) === null || _importPath$value$spe === void 0 ? void 0 : _importPath$value$spe.forEach(specifier => {
42
+ var _specifier$imported;
43
+ if (specifier.type === 'ImportDefaultSpecifier') {
44
+ var _specifier$local;
45
+ // Handle: import Lozenge from '@atlaskit/lozenge'
46
+ lozengeIdentifiers.add(((_specifier$local = specifier.local) === null || _specifier$local === void 0 ? void 0 : _specifier$local.name) || 'Lozenge');
47
+ } else if (specifier.type === 'ImportSpecifier' && ((_specifier$imported = specifier.imported) === null || _specifier$imported === void 0 ? void 0 : _specifier$imported.type) === 'Identifier' && specifier.imported.name === 'default') {
48
+ var _specifier$local2;
49
+ // Handle: import { default as Badge } from '@atlaskit/lozenge'
50
+ lozengeIdentifiers.add(((_specifier$local2 = specifier.local) === null || _specifier$local2 === void 0 ? void 0 : _specifier$local2.name) || 'Lozenge');
51
+ }
52
+ });
53
+ });
54
+
55
+ // If no Lozenge identifiers found, exit early
56
+ if (lozengeIdentifiers.size === 0) {
57
+ return file.source;
58
+ }
59
+
60
+ // Find all Lozenge JSX elements
61
+ const lozengeElements = [];
62
+ source.find(j.JSXElement).forEach(path => {
63
+ var _openingElement$name;
64
+ const openingElement = path.value.openingElement;
65
+ if (((_openingElement$name = openingElement.name) === null || _openingElement$name === void 0 ? void 0 : _openingElement$name.type) === 'JSXIdentifier' && lozengeIdentifiers.has(openingElement.name.name)) {
66
+ var _openingElement$attri;
67
+ const element = {
68
+ path,
69
+ hasAppearanceProp: false
70
+ };
71
+
72
+ // Check for appearance prop
73
+ (_openingElement$attri = openingElement.attributes) === null || _openingElement$attri === void 0 ? void 0 : _openingElement$attri.forEach(attr => {
74
+ var _attr$name;
75
+ if (attr.type === 'JSXAttribute' && ((_attr$name = attr.name) === null || _attr$name === void 0 ? void 0 : _attr$name.type) === 'JSXIdentifier') {
76
+ if (attr.name.name === 'appearance') {
77
+ var _attr$value, _attr$value2;
78
+ element.hasAppearanceProp = true;
79
+ if (((_attr$value = attr.value) === null || _attr$value === void 0 ? void 0 : _attr$value.type) === 'StringLiteral') {
80
+ element.appearanceValue = attr.value.value;
81
+ } else if (((_attr$value2 = attr.value) === null || _attr$value2 === void 0 ? void 0 : _attr$value2.type) === 'JSXExpressionContainer') {
82
+ // Handle dynamic values
83
+ const expression = attr.value.expression;
84
+ if (expression.type === 'StringLiteral') {
85
+ element.appearanceValue = expression.value;
86
+ } else {
87
+ element.appearanceValue = 'dynamic';
88
+ }
89
+ }
90
+ }
91
+ }
92
+ });
93
+ lozengeElements.push(element);
94
+ }
95
+ });
96
+
97
+ // Process each Lozenge element
98
+ lozengeElements.forEach(element => {
99
+ const {
100
+ path,
101
+ hasAppearanceProp,
102
+ appearanceValue
103
+ } = element;
104
+ const openingElement = path.value.openingElement;
105
+
106
+ // Transform appearance prop to color prop
107
+ if (hasAppearanceProp) {
108
+ var _openingElement$attri2;
109
+ (_openingElement$attri2 = openingElement.attributes) === null || _openingElement$attri2 === void 0 ? void 0 : _openingElement$attri2.forEach(attr => {
110
+ var _attr$name2;
111
+ if (attr.type === 'JSXAttribute' && ((_attr$name2 = attr.name) === null || _attr$name2 === void 0 ? void 0 : _attr$name2.type) === 'JSXIdentifier' && attr.name.name === 'appearance') {
112
+ // Rename appearance to color
113
+ attr.name.name = 'color';
114
+
115
+ // Handle different types of appearance values
116
+ if (appearanceValue === 'dynamic') {
117
+ // For dynamic values, add a comment
118
+ addCommentBefore(j, j(path), `FIXME: This Lozenge component uses a dynamic \`appearance\` prop that has been renamed to \`color\`.
119
+ Please verify that the values being passed are valid color values (semantic: default, inprogress, moved, new, removed, success).`);
120
+ } else if (appearanceValue && !APPEARANCE_TO_COLOR_MAP[appearanceValue]) {
121
+ // For invalid string values, add a warning comment
122
+ addCommentBefore(j, j(path), `FIXME: This Lozenge component uses an invalid \`appearance\` value "${appearanceValue}" that has been renamed to \`color\`.
123
+ Valid semantic color values are: ${Object.keys(APPEARANCE_TO_COLOR_MAP).join(', ')}.
124
+ Please update this value to a valid semantic color or use a custom color value.`);
125
+ } else if (appearanceValue && APPEARANCE_TO_COLOR_MAP[appearanceValue]) {
126
+ var _attr$value3;
127
+ // For valid string values, update the value to the mapped color
128
+ if (((_attr$value3 = attr.value) === null || _attr$value3 === void 0 ? void 0 : _attr$value3.type) === 'StringLiteral') {
129
+ attr.value.value = APPEARANCE_TO_COLOR_MAP[appearanceValue];
130
+ }
131
+ }
132
+ }
133
+ });
134
+ }
135
+ });
136
+ return source.toSource(PRINT_SETTINGS);
137
+ }
@@ -0,0 +1,18 @@
1
+ import lozengeAppearanceToColorTransformer from './codemods/lozenge-appearance-to-color';
2
+ export default async function transformer(file, api) {
3
+ const transformers = [lozengeAppearanceToColorTransformer];
4
+ let src = file.source;
5
+ transformers.forEach(transformer => {
6
+ if (typeof src === 'undefined') {
7
+ return;
8
+ }
9
+ const nextSrc = transformer({
10
+ ...file,
11
+ source: src
12
+ }, api);
13
+ if (nextSrc) {
14
+ src = nextSrc;
15
+ }
16
+ });
17
+ return src;
18
+ }
@@ -0,0 +1,242 @@
1
+ import { addCommentBefore } from '@atlaskit/codemod-utils';
2
+ const transformer = (file, api) => {
3
+ const j = api.jscodeshift;
4
+ const source = j(file.source);
5
+
6
+ // Check if file has Lozenge imports
7
+ const lozengeImports = source.find(j.ImportDeclaration).filter(path => path.node.source.value === '@atlaskit/lozenge');
8
+ if (lozengeImports.length === 0) {
9
+ return file.source;
10
+ }
11
+
12
+ // Get the import name for Lozenge (could be renamed)
13
+ let lozengeImportName = 'Lozenge';
14
+ lozengeImports.forEach(importPath => {
15
+ var _importPath$node$spec;
16
+ (_importPath$node$spec = importPath.node.specifiers) === null || _importPath$node$spec === void 0 ? void 0 : _importPath$node$spec.forEach(specifier => {
17
+ if (j.ImportDefaultSpecifier.check(specifier)) {
18
+ var _specifier$local;
19
+ lozengeImportName = ((_specifier$local = specifier.local) === null || _specifier$local === void 0 ? void 0 : _specifier$local.name) || 'Lozenge';
20
+ } else if (j.ImportSpecifier.check(specifier)) {
21
+ // Handle { default as Badge } syntax
22
+ if (j.Identifier.check(specifier.imported) && specifier.imported.name === 'default') {
23
+ var _specifier$local2;
24
+ lozengeImportName = ((_specifier$local2 = specifier.local) === null || _specifier$local2 === void 0 ? void 0 : _specifier$local2.name) || 'Lozenge';
25
+ }
26
+ }
27
+ });
28
+ });
29
+
30
+ // Appearance to color mapping
31
+ const appearanceToColorMap = {
32
+ success: 'lime',
33
+ default: 'standard',
34
+ removed: 'red',
35
+ inprogress: 'blue',
36
+ new: 'purple',
37
+ moved: 'orange'
38
+ };
39
+ let hasTransformed = false;
40
+
41
+ // Find and transform Lozenge elements
42
+ source.find(j.JSXElement).forEach(elementPath => {
43
+ var _element$openingEleme, _element$openingEleme2;
44
+ const element = elementPath.node;
45
+ if (!j.JSXIdentifier.check(element.openingElement.name)) {
46
+ return;
47
+ }
48
+ if (element.openingElement.name.name !== lozengeImportName) {
49
+ return;
50
+ }
51
+
52
+ // Check isBold attribute
53
+ const isBoldAttr = (_element$openingEleme = element.openingElement.attributes) === null || _element$openingEleme === void 0 ? void 0 : _element$openingEleme.find(attr => j.JSXAttribute.check(attr) && j.JSXIdentifier.check(attr.name) && attr.name.name === 'isBold');
54
+
55
+ // Don't transform if isBold is true or boolean prop without value
56
+ if (isBoldAttr) {
57
+ if (j.JSXExpressionContainer.check(isBoldAttr.value)) {
58
+ const expression = isBoldAttr.value.expression;
59
+
60
+ // If it's a boolean literal true, don't transform
61
+ if (j.BooleanLiteral.check(expression) && expression.value === true) {
62
+ return;
63
+ }
64
+
65
+ // If it's a boolean literal false, we can transform
66
+ if (j.BooleanLiteral.check(expression) && expression.value === false) {
67
+ // Continue with transformation
68
+ } else {
69
+ // If it's not a boolean literal (dynamic value), add warning and don't transform
70
+ addCommentBefore(j, j(elementPath), `FIXME: This Lozenge component uses a dynamic \`isBold\` prop. Please manually review if this should be migrated to Tag component.
71
+ If isBold is typically false, consider migrating to <Tag /> from '@atlaskit/tag'.`);
72
+ return;
73
+ }
74
+ } else if (!isBoldAttr.value) {
75
+ // isBold prop without value (boolean shorthand) means true, don't transform
76
+ return;
77
+ }
78
+ }
79
+
80
+ // Create new Tag element
81
+ const newAttributes = [];
82
+ const otherAttributes = [];
83
+ let colorAttribute = null;
84
+ let textContent = '';
85
+ let hasComplexChildren = false;
86
+ let hasStyleProp = false;
87
+ let hasMaxWidthProp = false;
88
+ let hasUnknownAppearance = false;
89
+ let dynamicAppearance = false;
90
+ let unknownAppearanceValue = '';
91
+
92
+ // Process children to extract text
93
+ if (element.children && element.children.length > 0) {
94
+ if (element.children.length === 1) {
95
+ const child = element.children[0];
96
+ if (j.JSXText.check(child)) {
97
+ const text = child.value.trim();
98
+ if (text) {
99
+ textContent = text;
100
+ }
101
+ } else if (j.JSXExpressionContainer.check(child) && j.StringLiteral.check(child.expression)) {
102
+ textContent = child.expression.value;
103
+ } else {
104
+ hasComplexChildren = true;
105
+ }
106
+ } else {
107
+ // Multiple children or complex structure
108
+ hasComplexChildren = true;
109
+ }
110
+ }
111
+
112
+ // Process attributes
113
+ (_element$openingEleme2 = element.openingElement.attributes) === null || _element$openingEleme2 === void 0 ? void 0 : _element$openingEleme2.forEach(attr => {
114
+ if (!j.JSXAttribute.check(attr) || !j.JSXIdentifier.check(attr.name)) {
115
+ return;
116
+ }
117
+ const attrName = attr.name.name;
118
+ switch (attrName) {
119
+ case 'appearance':
120
+ let colorValue = 'standard';
121
+ if (j.StringLiteral.check(attr.value)) {
122
+ const appearanceValue = attr.value.value;
123
+ colorValue = appearanceToColorMap[appearanceValue] || appearanceValue;
124
+ if (!appearanceToColorMap[appearanceValue]) {
125
+ hasUnknownAppearance = true;
126
+ unknownAppearanceValue = appearanceValue;
127
+ }
128
+ } else if (j.JSXExpressionContainer.check(attr.value)) {
129
+ // Dynamic appearance
130
+ dynamicAppearance = true;
131
+ colorValue = attr.value;
132
+ }
133
+ colorAttribute = j.jsxAttribute(j.jsxIdentifier('color'), typeof colorValue === 'string' ? j.stringLiteral(colorValue) : colorValue);
134
+ break;
135
+ case 'isBold':
136
+ // Skip isBold, already handled above
137
+ break;
138
+ case 'maxWidth':
139
+ hasMaxWidthProp = true;
140
+ break;
141
+ case 'style':
142
+ hasStyleProp = true;
143
+ otherAttributes.push(attr);
144
+ break;
145
+ default:
146
+ // Keep other attributes (testId, etc.)
147
+ otherAttributes.push(attr);
148
+ break;
149
+ }
150
+ });
151
+
152
+ // Assemble attributes in correct order: text, other props, color
153
+ if (textContent && !hasComplexChildren) {
154
+ newAttributes.push(j.jsxAttribute(j.jsxIdentifier('text'), j.stringLiteral(textContent)));
155
+ }
156
+
157
+ // Add other attributes
158
+ newAttributes.push(...otherAttributes);
159
+
160
+ // Add color attribute last (default to 'standard' if no appearance was found)
161
+ if (colorAttribute) {
162
+ newAttributes.push(colorAttribute);
163
+ } else {
164
+ // Default color when no appearance is specified
165
+ newAttributes.push(j.jsxAttribute(j.jsxIdentifier('color'), j.stringLiteral('standard')));
166
+ }
167
+
168
+ // Create new Tag element
169
+ const newElement = j.jsxElement(j.jsxOpeningElement(j.jsxIdentifier('Tag'), newAttributes, true), null, []);
170
+
171
+ // Add warning comments as needed
172
+ const warnings = [];
173
+ if (hasComplexChildren) {
174
+ 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.");
175
+ }
176
+ if (hasMaxWidthProp) {
177
+ 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.');
178
+ }
179
+ if (hasStyleProp) {
180
+ 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.');
181
+ }
182
+ if (hasUnknownAppearance) {
183
+ warnings.push(`FIXME: This Tag component uses an unknown appearance value "${unknownAppearanceValue}".\nPlease update to a valid Tag color: standard, green, lime, blue, red, purple, magenta, grey, teal, orange, yellow.`);
184
+ }
185
+ if (dynamicAppearance) {
186
+ 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).');
187
+ }
188
+
189
+ // Replace the element first
190
+ elementPath.replace(newElement);
191
+
192
+ // Add warning comments using addCommentBefore if needed
193
+ if (warnings.length > 0) {
194
+ const commentText = warnings.join('\n');
195
+ addCommentBefore(j, j(elementPath), commentText);
196
+ }
197
+ hasTransformed = true;
198
+ });
199
+
200
+ // Add Tag import if we transformed any elements
201
+ if (hasTransformed) {
202
+ // Check if Tag import already exists
203
+ const tagImports = source.find(j.ImportDeclaration).filter(path => path.node.source.value === '@atlaskit/tag');
204
+ if (tagImports.length === 0) {
205
+ // Add Tag import after Lozenge import
206
+ const lozengeImportPath = lozengeImports.at(0);
207
+ const tagImport = j.importDeclaration([j.importDefaultSpecifier(j.identifier('Tag'))], j.stringLiteral('@atlaskit/tag'));
208
+ lozengeImportPath.insertAfter(tagImport);
209
+ }
210
+
211
+ // Check if there are any remaining Lozenge usages
212
+ const remainingLozengeUsages = source.find(j.JSXElement).filter(elementPath => {
213
+ const element = elementPath.node;
214
+ if (!j.JSXIdentifier.check(element.openingElement.name)) {
215
+ return false;
216
+ }
217
+ return element.openingElement.name.name === lozengeImportName;
218
+ });
219
+
220
+ // Also check for other usages like function calls, type references, etc.
221
+ const remainingLozengeReferences = source.find(j.Identifier).filter(identifierPath => {
222
+ // Skip JSX element names as they're already checked above
223
+ if (j.JSXElement.check(identifierPath.parent.node) || j.JSXOpeningElement.check(identifierPath.parent.node) || j.JSXClosingElement.check(identifierPath.parent.node)) {
224
+ return false;
225
+ }
226
+
227
+ // Skip import declaration identifiers
228
+ if (j.ImportDeclaration.check(identifierPath.parent.node) || j.ImportDefaultSpecifier.check(identifierPath.parent.node) || j.ImportSpecifier.check(identifierPath.parent.node)) {
229
+ return false;
230
+ }
231
+ return identifierPath.node.name === lozengeImportName;
232
+ });
233
+
234
+ // If no remaining usages, remove the Lozenge import
235
+ if (remainingLozengeUsages.length === 0 && remainingLozengeReferences.length === 0) {
236
+ lozengeImports.remove();
237
+ }
238
+ return source.toSource();
239
+ }
240
+ return source.toSource();
241
+ };
242
+ export default transformer;
@@ -0,0 +1,18 @@
1
+ import lozengeToTagMigrationTransformer from './codemods/lozenge-to-tag-migration';
2
+ export default async function transformer(file, api) {
3
+ const transformers = [lozengeToTagMigrationTransformer];
4
+ let src = file.source;
5
+ transformers.forEach(transformer => {
6
+ if (typeof src === 'undefined') {
7
+ return;
8
+ }
9
+ const nextSrc = transformer({
10
+ ...file,
11
+ source: src
12
+ }, api);
13
+ if (nextSrc) {
14
+ src = nextSrc;
15
+ }
16
+ });
17
+ return src;
18
+ }
package/dist/esm/main.js CHANGED
@@ -355,7 +355,7 @@ function _main() {
355
355
  case 4:
356
356
  _yield$parseArgs = _context6.sent;
357
357
  packages = _yield$parseArgs.packages;
358
- _process$env$_PACKAGE = "0.29.1", _PACKAGE_VERSION_ = _process$env$_PACKAGE === void 0 ? '0.0.0-dev' : _process$env$_PACKAGE;
358
+ _process$env$_PACKAGE = "0.30.0", _PACKAGE_VERSION_ = _process$env$_PACKAGE === void 0 ? '0.0.0-dev' : _process$env$_PACKAGE;
359
359
  logger.log(chalk.bgBlue(chalk.black("\uD83D\uDCDA Atlassian-Frontend codemod library @ ".concat(_PACKAGE_VERSION_, " \uD83D\uDCDA"))));
360
360
  if (packages && packages.length > 0) {
361
361
  logger.log(chalk.gray("Searching for codemods for newer versions of the following packages: ".concat(packages.map(function (pkg) {
@@ -12,7 +12,9 @@ import './migrate-icon-object-to-object/migrate-icon-object-to-object';
12
12
  import './upgrade-pragmatic-drag-and-drop-to-stable/upgrade-pragmatic-drag-and-drop-to-stable';
13
13
  import './remove-dark-theme-vr-options/remove-dark-theme-vr-options';
14
14
  import './remove-token-fallbacks/remove-token-fallbacks';
15
- var presets = ['styled-to-emotion', 'theme-remove-deprecated-mixins', 'migrate-to-link', 'migrate-to-new-buttons', 'migrate-icon-object-to-object', 'upgrade-pragmatic-drag-and-drop-to-stable', 'remove-dark-theme-vr-options', 'remove-token-fallbacks'].map(function (preset) {
15
+ import './lozenge-appearance-to-color/lozenge-appearance-to-color';
16
+ import './lozenge-to-tag-migration/lozenge-to-tag-migration';
17
+ var presets = ['styled-to-emotion', 'theme-remove-deprecated-mixins', 'migrate-to-link', 'migrate-to-new-buttons', 'migrate-icon-object-to-object', 'upgrade-pragmatic-drag-and-drop-to-stable', 'remove-dark-theme-vr-options', 'remove-token-fallbacks', 'lozenge-appearance-to-color', 'lozenge-to-tag-migration'].map(function (preset) {
16
18
  return path.join(__dirname, preset, "".concat(preset, ".@(ts|js|tsx)"));
17
19
  });
18
20
  export default presets;
@@ -0,0 +1,132 @@
1
+ import { getImportDeclaration } from '@hypermod/utils';
2
+ import { addCommentBefore } from '@atlaskit/codemod-utils';
3
+ var LOZENGE_ENTRY_POINT = '@atlaskit/lozenge';
4
+ var PRINT_SETTINGS = {
5
+ quote: 'single'
6
+ };
7
+
8
+ // Semantic appearance values that map directly to color values
9
+ var APPEARANCE_TO_COLOR_MAP = {
10
+ default: 'neutral',
11
+ inprogress: 'information',
12
+ moved: 'warning',
13
+ new: 'discovery',
14
+ removed: 'danger',
15
+ success: 'success'
16
+ };
17
+ /**
18
+ * Codemod to migrate Lozenge component from `appearance` prop to `color` prop.
19
+ *
20
+ * This codemod:
21
+ * 1. Renames `appearance` prop to `color` for semantic values
22
+ * 2. Maps existing semantic values directly (e.g. success → success)
23
+ * 3. Adds comments for dynamic values that need manual verification
24
+ */
25
+ export default function transformer(file, api) {
26
+ var j = api.jscodeshift;
27
+ var source = j(file.source);
28
+
29
+ // Find all Lozenge imports
30
+ var lozengeImports = getImportDeclaration(j, source, LOZENGE_ENTRY_POINT);
31
+
32
+ // If no Lozenge imports, exit early
33
+ if (!lozengeImports.length) {
34
+ return file.source;
35
+ }
36
+
37
+ // Get all imported Lozenge identifiers (could be renamed)
38
+ var lozengeIdentifiers = new Set();
39
+ lozengeImports.forEach(function (importPath) {
40
+ var _importPath$value$spe;
41
+ (_importPath$value$spe = importPath.value.specifiers) === null || _importPath$value$spe === void 0 || _importPath$value$spe.forEach(function (specifier) {
42
+ var _specifier$imported;
43
+ if (specifier.type === 'ImportDefaultSpecifier') {
44
+ var _specifier$local;
45
+ // Handle: import Lozenge from '@atlaskit/lozenge'
46
+ lozengeIdentifiers.add(((_specifier$local = specifier.local) === null || _specifier$local === void 0 ? void 0 : _specifier$local.name) || 'Lozenge');
47
+ } else if (specifier.type === 'ImportSpecifier' && ((_specifier$imported = specifier.imported) === null || _specifier$imported === void 0 ? void 0 : _specifier$imported.type) === 'Identifier' && specifier.imported.name === 'default') {
48
+ var _specifier$local2;
49
+ // Handle: import { default as Badge } from '@atlaskit/lozenge'
50
+ lozengeIdentifiers.add(((_specifier$local2 = specifier.local) === null || _specifier$local2 === void 0 ? void 0 : _specifier$local2.name) || 'Lozenge');
51
+ }
52
+ });
53
+ });
54
+
55
+ // If no Lozenge identifiers found, exit early
56
+ if (lozengeIdentifiers.size === 0) {
57
+ return file.source;
58
+ }
59
+
60
+ // Find all Lozenge JSX elements
61
+ var lozengeElements = [];
62
+ source.find(j.JSXElement).forEach(function (path) {
63
+ var _openingElement$name;
64
+ var openingElement = path.value.openingElement;
65
+ if (((_openingElement$name = openingElement.name) === null || _openingElement$name === void 0 ? void 0 : _openingElement$name.type) === 'JSXIdentifier' && lozengeIdentifiers.has(openingElement.name.name)) {
66
+ var _openingElement$attri;
67
+ var element = {
68
+ path: path,
69
+ hasAppearanceProp: false
70
+ };
71
+
72
+ // Check for appearance prop
73
+ (_openingElement$attri = openingElement.attributes) === null || _openingElement$attri === void 0 || _openingElement$attri.forEach(function (attr) {
74
+ var _attr$name;
75
+ if (attr.type === 'JSXAttribute' && ((_attr$name = attr.name) === null || _attr$name === void 0 ? void 0 : _attr$name.type) === 'JSXIdentifier') {
76
+ if (attr.name.name === 'appearance') {
77
+ var _attr$value, _attr$value2;
78
+ element.hasAppearanceProp = true;
79
+ if (((_attr$value = attr.value) === null || _attr$value === void 0 ? void 0 : _attr$value.type) === 'StringLiteral') {
80
+ element.appearanceValue = attr.value.value;
81
+ } else if (((_attr$value2 = attr.value) === null || _attr$value2 === void 0 ? void 0 : _attr$value2.type) === 'JSXExpressionContainer') {
82
+ // Handle dynamic values
83
+ var expression = attr.value.expression;
84
+ if (expression.type === 'StringLiteral') {
85
+ element.appearanceValue = expression.value;
86
+ } else {
87
+ element.appearanceValue = 'dynamic';
88
+ }
89
+ }
90
+ }
91
+ }
92
+ });
93
+ lozengeElements.push(element);
94
+ }
95
+ });
96
+
97
+ // Process each Lozenge element
98
+ lozengeElements.forEach(function (element) {
99
+ var path = element.path,
100
+ hasAppearanceProp = element.hasAppearanceProp,
101
+ appearanceValue = element.appearanceValue;
102
+ var openingElement = path.value.openingElement;
103
+
104
+ // Transform appearance prop to color prop
105
+ if (hasAppearanceProp) {
106
+ var _openingElement$attri2;
107
+ (_openingElement$attri2 = openingElement.attributes) === null || _openingElement$attri2 === void 0 || _openingElement$attri2.forEach(function (attr) {
108
+ var _attr$name2;
109
+ if (attr.type === 'JSXAttribute' && ((_attr$name2 = attr.name) === null || _attr$name2 === void 0 ? void 0 : _attr$name2.type) === 'JSXIdentifier' && attr.name.name === 'appearance') {
110
+ // Rename appearance to color
111
+ attr.name.name = 'color';
112
+
113
+ // Handle different types of appearance values
114
+ if (appearanceValue === 'dynamic') {
115
+ // For dynamic values, add a comment
116
+ addCommentBefore(j, j(path), "FIXME: This Lozenge 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).");
117
+ } else if (appearanceValue && !APPEARANCE_TO_COLOR_MAP[appearanceValue]) {
118
+ // For invalid string values, add a warning comment
119
+ addCommentBefore(j, j(path), "FIXME: This Lozenge component uses an invalid `appearance` value \"".concat(appearanceValue, "\" that has been renamed to `color`.\nValid semantic color values are: ").concat(Object.keys(APPEARANCE_TO_COLOR_MAP).join(', '), ".\nPlease update this value to a valid semantic color or use a custom color value."));
120
+ } else if (appearanceValue && APPEARANCE_TO_COLOR_MAP[appearanceValue]) {
121
+ var _attr$value3;
122
+ // For valid string values, update the value to the mapped color
123
+ if (((_attr$value3 = attr.value) === null || _attr$value3 === void 0 ? void 0 : _attr$value3.type) === 'StringLiteral') {
124
+ attr.value.value = APPEARANCE_TO_COLOR_MAP[appearanceValue];
125
+ }
126
+ }
127
+ }
128
+ });
129
+ }
130
+ });
131
+ return source.toSource(PRINT_SETTINGS);
132
+ }
@@ -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 lozengeAppearanceToColorTransformer from './codemods/lozenge-appearance-to-color';
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 = [lozengeAppearanceToColorTransformer];
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
+ }