@atlaskit/codemod-cli 0.30.0 → 0.31.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/CHANGELOG.md +14 -0
- package/dist/cjs/main.js +1 -1
- package/dist/cjs/presets/index.js +2 -1
- package/dist/cjs/presets/lozenge-to-tag-migration/codemods/lozenge-to-tag-migration.js +253 -0
- package/dist/cjs/presets/lozenge-to-tag-migration/lozenge-to-tag-migration.js +44 -0
- package/dist/cjs/presets/remove-token-fallbacks/utils/reporter.js +3 -2
- package/dist/es2019/presets/index.js +2 -1
- package/dist/es2019/presets/lozenge-to-tag-migration/codemods/lozenge-to-tag-migration.js +242 -0
- package/dist/es2019/presets/lozenge-to-tag-migration/lozenge-to-tag-migration.js +18 -0
- package/dist/es2019/presets/remove-token-fallbacks/utils/reporter.js +4 -0
- package/dist/esm/main.js +1 -1
- package/dist/esm/presets/index.js +2 -1
- package/dist/esm/presets/lozenge-to-tag-migration/codemods/lozenge-to-tag-migration.js +247 -0
- package/dist/esm/presets/lozenge-to-tag-migration/lozenge-to-tag-migration.js +37 -0
- package/dist/esm/presets/remove-token-fallbacks/utils/reporter.js +4 -1
- package/dist/types/presets/index.d.ts +1 -0
- package/dist/types/presets/lozenge-to-tag-migration/codemods/lozenge-to-tag-migration.d.ts +3 -0
- package/dist/types/presets/lozenge-to-tag-migration/lozenge-to-tag-migration.d.ts +2 -0
- package/dist/types-ts4.5/presets/index.d.ts +1 -0
- package/dist/types-ts4.5/presets/lozenge-to-tag-migration/codemods/lozenge-to-tag-migration.d.ts +3 -0
- package/dist/types-ts4.5/presets/lozenge-to-tag-migration/lozenge-to-tag-migration.d.ts +2 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @atlaskit/codemod-cli
|
|
2
2
|
|
|
3
|
+
## 0.31.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
|
|
9
|
+
## 0.31.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [`2b2b250287a95`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/2b2b250287a95) -
|
|
14
|
+
Add a new codemod `lozenge-to-tag-migration` to automatically migrate `isBold={false}` Lozenge
|
|
15
|
+
usages to Tag component as part of the Labelling System Phase 1 migration.
|
|
16
|
+
|
|
3
17
|
## 0.30.0
|
|
4
18
|
|
|
5
19
|
### Minor Changes
|
package/dist/cjs/main.js
CHANGED
|
@@ -362,7 +362,7 @@ function _main() {
|
|
|
362
362
|
case 4:
|
|
363
363
|
_yield$parseArgs = _context6.sent;
|
|
364
364
|
packages = _yield$parseArgs.packages;
|
|
365
|
-
_process$env$_PACKAGE = "0.
|
|
365
|
+
_process$env$_PACKAGE = "0.0.0-development", _PACKAGE_VERSION_ = _process$env$_PACKAGE === void 0 ? '0.0.0-dev' : _process$env$_PACKAGE;
|
|
366
366
|
logger.log(_chalk.default.bgBlue(_chalk.default.black("\uD83D\uDCDA Atlassian-Frontend codemod library @ ".concat(_PACKAGE_VERSION_, " \uD83D\uDCDA"))));
|
|
367
367
|
if (packages && packages.length > 0) {
|
|
368
368
|
logger.log(_chalk.default.gray("Searching for codemods for newer versions of the following packages: ".concat(packages.map(function (pkg) {
|
|
@@ -15,12 +15,13 @@ require("./upgrade-pragmatic-drag-and-drop-to-stable/upgrade-pragmatic-drag-and-
|
|
|
15
15
|
require("./remove-dark-theme-vr-options/remove-dark-theme-vr-options");
|
|
16
16
|
require("./remove-token-fallbacks/remove-token-fallbacks");
|
|
17
17
|
require("./lozenge-appearance-to-color/lozenge-appearance-to-color");
|
|
18
|
+
require("./lozenge-to-tag-migration/lozenge-to-tag-migration");
|
|
18
19
|
/**
|
|
19
20
|
* Manually import presets to make sure typescript includes them
|
|
20
21
|
* in the final bundle.
|
|
21
22
|
*/
|
|
22
23
|
|
|
23
|
-
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'].map(function (preset) {
|
|
24
|
+
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) {
|
|
24
25
|
return _path.default.join(__dirname, preset, "".concat(preset, ".@(ts|js|tsx)"));
|
|
25
26
|
});
|
|
26
27
|
var _default = exports.default = presets;
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _codemodUtils = require("@atlaskit/codemod-utils");
|
|
8
|
+
var transformer = function transformer(file, api) {
|
|
9
|
+
var j = api.jscodeshift;
|
|
10
|
+
var source = j(file.source);
|
|
11
|
+
|
|
12
|
+
// Check if file has Lozenge imports
|
|
13
|
+
var lozengeImports = source.find(j.ImportDeclaration).filter(function (path) {
|
|
14
|
+
return path.node.source.value === '@atlaskit/lozenge';
|
|
15
|
+
});
|
|
16
|
+
if (lozengeImports.length === 0) {
|
|
17
|
+
return file.source;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Get the import name for Lozenge (could be renamed)
|
|
21
|
+
var lozengeImportName = 'Lozenge';
|
|
22
|
+
lozengeImports.forEach(function (importPath) {
|
|
23
|
+
var _importPath$node$spec;
|
|
24
|
+
(_importPath$node$spec = importPath.node.specifiers) === null || _importPath$node$spec === void 0 || _importPath$node$spec.forEach(function (specifier) {
|
|
25
|
+
if (j.ImportDefaultSpecifier.check(specifier)) {
|
|
26
|
+
var _specifier$local;
|
|
27
|
+
lozengeImportName = ((_specifier$local = specifier.local) === null || _specifier$local === void 0 ? void 0 : _specifier$local.name) || 'Lozenge';
|
|
28
|
+
} else if (j.ImportSpecifier.check(specifier)) {
|
|
29
|
+
// Handle { default as Badge } syntax
|
|
30
|
+
if (j.Identifier.check(specifier.imported) && specifier.imported.name === 'default') {
|
|
31
|
+
var _specifier$local2;
|
|
32
|
+
lozengeImportName = ((_specifier$local2 = specifier.local) === null || _specifier$local2 === void 0 ? void 0 : _specifier$local2.name) || 'Lozenge';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Appearance to color mapping
|
|
39
|
+
var appearanceToColorMap = {
|
|
40
|
+
success: 'lime',
|
|
41
|
+
default: 'standard',
|
|
42
|
+
removed: 'red',
|
|
43
|
+
inprogress: 'blue',
|
|
44
|
+
new: 'purple',
|
|
45
|
+
moved: 'orange'
|
|
46
|
+
};
|
|
47
|
+
var hasTransformed = false;
|
|
48
|
+
|
|
49
|
+
// Find and transform Lozenge elements
|
|
50
|
+
source.find(j.JSXElement).forEach(function (elementPath) {
|
|
51
|
+
var _element$openingEleme, _element$openingEleme2;
|
|
52
|
+
var element = elementPath.node;
|
|
53
|
+
if (!j.JSXIdentifier.check(element.openingElement.name)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (element.openingElement.name.name !== lozengeImportName) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Check isBold attribute
|
|
61
|
+
var isBoldAttr = (_element$openingEleme = element.openingElement.attributes) === null || _element$openingEleme === void 0 ? void 0 : _element$openingEleme.find(function (attr) {
|
|
62
|
+
return j.JSXAttribute.check(attr) && j.JSXIdentifier.check(attr.name) && attr.name.name === 'isBold';
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Don't transform if isBold is true or boolean prop without value
|
|
66
|
+
if (isBoldAttr) {
|
|
67
|
+
if (j.JSXExpressionContainer.check(isBoldAttr.value)) {
|
|
68
|
+
var expression = isBoldAttr.value.expression;
|
|
69
|
+
|
|
70
|
+
// If it's a boolean literal true, don't transform
|
|
71
|
+
if (j.BooleanLiteral.check(expression) && expression.value === true) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// If it's a boolean literal false, we can transform
|
|
76
|
+
if (j.BooleanLiteral.check(expression) && expression.value === false) {
|
|
77
|
+
// Continue with transformation
|
|
78
|
+
} else {
|
|
79
|
+
// If it's not a boolean literal (dynamic value), add warning and don't transform
|
|
80
|
+
(0, _codemodUtils.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'.");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
} else if (!isBoldAttr.value) {
|
|
84
|
+
// isBold prop without value (boolean shorthand) means true, don't transform
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Create new Tag element
|
|
90
|
+
var newAttributes = [];
|
|
91
|
+
var otherAttributes = [];
|
|
92
|
+
var colorAttribute = null;
|
|
93
|
+
var textContent = '';
|
|
94
|
+
var hasComplexChildren = false;
|
|
95
|
+
var hasStyleProp = false;
|
|
96
|
+
var hasMaxWidthProp = false;
|
|
97
|
+
var hasUnknownAppearance = false;
|
|
98
|
+
var dynamicAppearance = false;
|
|
99
|
+
var unknownAppearanceValue = '';
|
|
100
|
+
|
|
101
|
+
// Process children to extract text
|
|
102
|
+
if (element.children && element.children.length > 0) {
|
|
103
|
+
if (element.children.length === 1) {
|
|
104
|
+
var child = element.children[0];
|
|
105
|
+
if (j.JSXText.check(child)) {
|
|
106
|
+
var text = child.value.trim();
|
|
107
|
+
if (text) {
|
|
108
|
+
textContent = text;
|
|
109
|
+
}
|
|
110
|
+
} else if (j.JSXExpressionContainer.check(child) && j.StringLiteral.check(child.expression)) {
|
|
111
|
+
textContent = child.expression.value;
|
|
112
|
+
} else {
|
|
113
|
+
hasComplexChildren = true;
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
// Multiple children or complex structure
|
|
117
|
+
hasComplexChildren = true;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Process attributes
|
|
122
|
+
(_element$openingEleme2 = element.openingElement.attributes) === null || _element$openingEleme2 === void 0 || _element$openingEleme2.forEach(function (attr) {
|
|
123
|
+
if (!j.JSXAttribute.check(attr) || !j.JSXIdentifier.check(attr.name)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
var attrName = attr.name.name;
|
|
127
|
+
switch (attrName) {
|
|
128
|
+
case 'appearance':
|
|
129
|
+
var colorValue = 'standard';
|
|
130
|
+
if (j.StringLiteral.check(attr.value)) {
|
|
131
|
+
var appearanceValue = attr.value.value;
|
|
132
|
+
colorValue = appearanceToColorMap[appearanceValue] || appearanceValue;
|
|
133
|
+
if (!appearanceToColorMap[appearanceValue]) {
|
|
134
|
+
hasUnknownAppearance = true;
|
|
135
|
+
unknownAppearanceValue = appearanceValue;
|
|
136
|
+
}
|
|
137
|
+
} else if (j.JSXExpressionContainer.check(attr.value)) {
|
|
138
|
+
// Dynamic appearance
|
|
139
|
+
dynamicAppearance = true;
|
|
140
|
+
colorValue = attr.value;
|
|
141
|
+
}
|
|
142
|
+
colorAttribute = j.jsxAttribute(j.jsxIdentifier('color'), typeof colorValue === 'string' ? j.stringLiteral(colorValue) : colorValue);
|
|
143
|
+
break;
|
|
144
|
+
case 'isBold':
|
|
145
|
+
// Skip isBold, already handled above
|
|
146
|
+
break;
|
|
147
|
+
case 'maxWidth':
|
|
148
|
+
hasMaxWidthProp = true;
|
|
149
|
+
break;
|
|
150
|
+
case 'style':
|
|
151
|
+
hasStyleProp = true;
|
|
152
|
+
otherAttributes.push(attr);
|
|
153
|
+
break;
|
|
154
|
+
default:
|
|
155
|
+
// Keep other attributes (testId, etc.)
|
|
156
|
+
otherAttributes.push(attr);
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Assemble attributes in correct order: text, other props, color
|
|
162
|
+
if (textContent && !hasComplexChildren) {
|
|
163
|
+
newAttributes.push(j.jsxAttribute(j.jsxIdentifier('text'), j.stringLiteral(textContent)));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Add other attributes
|
|
167
|
+
newAttributes.push.apply(newAttributes, otherAttributes);
|
|
168
|
+
|
|
169
|
+
// Add color attribute last (default to 'standard' if no appearance was found)
|
|
170
|
+
if (colorAttribute) {
|
|
171
|
+
newAttributes.push(colorAttribute);
|
|
172
|
+
} else {
|
|
173
|
+
// Default color when no appearance is specified
|
|
174
|
+
newAttributes.push(j.jsxAttribute(j.jsxIdentifier('color'), j.stringLiteral('standard')));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Create new Tag element
|
|
178
|
+
var newElement = j.jsxElement(j.jsxOpeningElement(j.jsxIdentifier('Tag'), newAttributes, true), null, []);
|
|
179
|
+
|
|
180
|
+
// Add warning comments as needed
|
|
181
|
+
var warnings = [];
|
|
182
|
+
if (hasComplexChildren) {
|
|
183
|
+
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.");
|
|
184
|
+
}
|
|
185
|
+
if (hasMaxWidthProp) {
|
|
186
|
+
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.');
|
|
187
|
+
}
|
|
188
|
+
if (hasStyleProp) {
|
|
189
|
+
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.');
|
|
190
|
+
}
|
|
191
|
+
if (hasUnknownAppearance) {
|
|
192
|
+
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."));
|
|
193
|
+
}
|
|
194
|
+
if (dynamicAppearance) {
|
|
195
|
+
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).');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Replace the element first
|
|
199
|
+
elementPath.replace(newElement);
|
|
200
|
+
|
|
201
|
+
// Add warning comments using addCommentBefore if needed
|
|
202
|
+
if (warnings.length > 0) {
|
|
203
|
+
var commentText = warnings.join('\n');
|
|
204
|
+
(0, _codemodUtils.addCommentBefore)(j, j(elementPath), commentText);
|
|
205
|
+
}
|
|
206
|
+
hasTransformed = true;
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Add Tag import if we transformed any elements
|
|
210
|
+
if (hasTransformed) {
|
|
211
|
+
// Check if Tag import already exists
|
|
212
|
+
var tagImports = source.find(j.ImportDeclaration).filter(function (path) {
|
|
213
|
+
return path.node.source.value === '@atlaskit/tag';
|
|
214
|
+
});
|
|
215
|
+
if (tagImports.length === 0) {
|
|
216
|
+
// Add Tag import after Lozenge import
|
|
217
|
+
var lozengeImportPath = lozengeImports.at(0);
|
|
218
|
+
var tagImport = j.importDeclaration([j.importDefaultSpecifier(j.identifier('Tag'))], j.stringLiteral('@atlaskit/tag'));
|
|
219
|
+
lozengeImportPath.insertAfter(tagImport);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Check if there are any remaining Lozenge usages
|
|
223
|
+
var remainingLozengeUsages = source.find(j.JSXElement).filter(function (elementPath) {
|
|
224
|
+
var element = elementPath.node;
|
|
225
|
+
if (!j.JSXIdentifier.check(element.openingElement.name)) {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
return element.openingElement.name.name === lozengeImportName;
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// Also check for other usages like function calls, type references, etc.
|
|
232
|
+
var remainingLozengeReferences = source.find(j.Identifier).filter(function (identifierPath) {
|
|
233
|
+
// Skip JSX element names as they're already checked above
|
|
234
|
+
if (j.JSXElement.check(identifierPath.parent.node) || j.JSXOpeningElement.check(identifierPath.parent.node) || j.JSXClosingElement.check(identifierPath.parent.node)) {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Skip import declaration identifiers
|
|
239
|
+
if (j.ImportDeclaration.check(identifierPath.parent.node) || j.ImportDefaultSpecifier.check(identifierPath.parent.node) || j.ImportSpecifier.check(identifierPath.parent.node)) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
return identifierPath.node.name === lozengeImportName;
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// If no remaining usages, remove the Lozenge import
|
|
246
|
+
if (remainingLozengeUsages.length === 0 && remainingLozengeReferences.length === 0) {
|
|
247
|
+
lozengeImports.remove();
|
|
248
|
+
}
|
|
249
|
+
return source.toSource();
|
|
250
|
+
}
|
|
251
|
+
return source.toSource();
|
|
252
|
+
};
|
|
253
|
+
var _default = exports.default = transformer;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = transformer;
|
|
8
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
9
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
10
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
11
|
+
var _lozengeToTagMigration = _interopRequireDefault(require("./codemods/lozenge-to-tag-migration"));
|
|
12
|
+
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; }
|
|
13
|
+
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) { (0, _defineProperty2.default)(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; }
|
|
14
|
+
function transformer(_x, _x2) {
|
|
15
|
+
return _transformer.apply(this, arguments);
|
|
16
|
+
}
|
|
17
|
+
function _transformer() {
|
|
18
|
+
_transformer = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(file, api) {
|
|
19
|
+
var transformers, src;
|
|
20
|
+
return _regenerator.default.wrap(function _callee$(_context) {
|
|
21
|
+
while (1) switch (_context.prev = _context.next) {
|
|
22
|
+
case 0:
|
|
23
|
+
transformers = [_lozengeToTagMigration.default];
|
|
24
|
+
src = file.source;
|
|
25
|
+
transformers.forEach(function (transformer) {
|
|
26
|
+
if (typeof src === 'undefined') {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
var nextSrc = transformer(_objectSpread(_objectSpread({}, file), {}, {
|
|
30
|
+
source: src
|
|
31
|
+
}), api);
|
|
32
|
+
if (nextSrc) {
|
|
33
|
+
src = nextSrc;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
return _context.abrupt("return", src);
|
|
37
|
+
case 4:
|
|
38
|
+
case "end":
|
|
39
|
+
return _context.stop();
|
|
40
|
+
}
|
|
41
|
+
}, _callee);
|
|
42
|
+
}));
|
|
43
|
+
return _transformer.apply(this, arguments);
|
|
44
|
+
}
|
|
@@ -15,7 +15,7 @@ var _path = _interopRequireDefault(require("path"));
|
|
|
15
15
|
var _uuid = require("uuid");
|
|
16
16
|
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
17
17
|
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
18
|
-
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } /* eslint-disable no-console */
|
|
18
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } /* eslint-disable no-console */ // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
19
19
|
function writeToCsv(_x, _x2) {
|
|
20
20
|
return _writeToCsv.apply(this, arguments);
|
|
21
21
|
}
|
|
@@ -296,7 +296,8 @@ function _writeReports() {
|
|
|
296
296
|
return _regenerator.default.wrap(function _callee6$(_context6) {
|
|
297
297
|
while (1) switch (_context6.prev = _context6.next) {
|
|
298
298
|
case 0:
|
|
299
|
-
|
|
299
|
+
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
300
|
+
replacementsFilePath = _path.default.join(reportFolder, "".concat((0, _uuid.v4)(), "_success.csv")); // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
300
301
|
nonReplacementsFilePath = _path.default.join(reportFolder, "".concat((0, _uuid.v4)(), "_failed.csv"));
|
|
301
302
|
_context6.next = 4;
|
|
302
303
|
return _promises.default.mkdir(reportFolder, {
|
|
@@ -13,5 +13,6 @@ import './upgrade-pragmatic-drag-and-drop-to-stable/upgrade-pragmatic-drag-and-d
|
|
|
13
13
|
import './remove-dark-theme-vr-options/remove-dark-theme-vr-options';
|
|
14
14
|
import './remove-token-fallbacks/remove-token-fallbacks';
|
|
15
15
|
import './lozenge-appearance-to-color/lozenge-appearance-to-color';
|
|
16
|
-
|
|
16
|
+
import './lozenge-to-tag-migration/lozenge-to-tag-migration';
|
|
17
|
+
const 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(preset => path.join(__dirname, preset, `${preset}.@(ts|js|tsx)`));
|
|
17
18
|
export default presets;
|
|
@@ -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
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
import fs from 'fs/promises';
|
|
3
3
|
import path from 'path';
|
|
4
|
+
|
|
5
|
+
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
4
6
|
import { v4 as uuidv4 } from 'uuid';
|
|
5
7
|
async function writeToCsv(filePath, data) {
|
|
6
8
|
await fs.writeFile(filePath, data.join('\n'), 'utf-8');
|
|
@@ -112,7 +114,9 @@ function prepareCsvData(items) {
|
|
|
112
114
|
});
|
|
113
115
|
}
|
|
114
116
|
export async function writeReports(details, reportFolder) {
|
|
117
|
+
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
115
118
|
const replacementsFilePath = path.join(reportFolder, `${uuidv4()}_success.csv`);
|
|
119
|
+
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
116
120
|
const nonReplacementsFilePath = path.join(reportFolder, `${uuidv4()}_failed.csv`);
|
|
117
121
|
await fs.mkdir(reportFolder, {
|
|
118
122
|
recursive: true
|
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.
|
|
358
|
+
_process$env$_PACKAGE = "0.0.0-development", _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) {
|
|
@@ -13,7 +13,8 @@ import './upgrade-pragmatic-drag-and-drop-to-stable/upgrade-pragmatic-drag-and-d
|
|
|
13
13
|
import './remove-dark-theme-vr-options/remove-dark-theme-vr-options';
|
|
14
14
|
import './remove-token-fallbacks/remove-token-fallbacks';
|
|
15
15
|
import './lozenge-appearance-to-color/lozenge-appearance-to-color';
|
|
16
|
-
|
|
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) {
|
|
17
18
|
return path.join(__dirname, preset, "".concat(preset, ".@(ts|js|tsx)"));
|
|
18
19
|
});
|
|
19
20
|
export default presets;
|
|
@@ -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
|
+
}
|
|
@@ -7,6 +7,8 @@ import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
|
7
7
|
/* eslint-disable no-console */
|
|
8
8
|
import fs from 'fs/promises';
|
|
9
9
|
import path from 'path';
|
|
10
|
+
|
|
11
|
+
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
10
12
|
import { v4 as uuidv4 } from 'uuid';
|
|
11
13
|
function writeToCsv(_x, _x2) {
|
|
12
14
|
return _writeToCsv.apply(this, arguments);
|
|
@@ -288,7 +290,8 @@ function _writeReports() {
|
|
|
288
290
|
return _regeneratorRuntime.wrap(function _callee6$(_context6) {
|
|
289
291
|
while (1) switch (_context6.prev = _context6.next) {
|
|
290
292
|
case 0:
|
|
291
|
-
|
|
293
|
+
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
294
|
+
replacementsFilePath = path.join(reportFolder, "".concat(uuidv4(), "_success.csv")); // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
292
295
|
nonReplacementsFilePath = path.join(reportFolder, "".concat(uuidv4(), "_failed.csv"));
|
|
293
296
|
_context6.next = 4;
|
|
294
297
|
return fs.mkdir(reportFolder, {
|
|
@@ -11,5 +11,6 @@ import './upgrade-pragmatic-drag-and-drop-to-stable/upgrade-pragmatic-drag-and-d
|
|
|
11
11
|
import './remove-dark-theme-vr-options/remove-dark-theme-vr-options';
|
|
12
12
|
import './remove-token-fallbacks/remove-token-fallbacks';
|
|
13
13
|
import './lozenge-appearance-to-color/lozenge-appearance-to-color';
|
|
14
|
+
import './lozenge-to-tag-migration/lozenge-to-tag-migration';
|
|
14
15
|
declare const presets: string[];
|
|
15
16
|
export default presets;
|
|
@@ -11,5 +11,6 @@ import './upgrade-pragmatic-drag-and-drop-to-stable/upgrade-pragmatic-drag-and-d
|
|
|
11
11
|
import './remove-dark-theme-vr-options/remove-dark-theme-vr-options';
|
|
12
12
|
import './remove-token-fallbacks/remove-token-fallbacks';
|
|
13
13
|
import './lozenge-appearance-to-color/lozenge-appearance-to-color';
|
|
14
|
+
import './lozenge-to-tag-migration/lozenge-to-tag-migration';
|
|
14
15
|
declare const presets: string[];
|
|
15
16
|
export default presets;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/codemod-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.1",
|
|
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": "^
|
|
32
|
+
"@atlaskit/tokens": "^8.0.0",
|
|
33
33
|
"@babel/runtime": "^7.0.0",
|
|
34
34
|
"@codeshift/utils": "^0.2.4",
|
|
35
35
|
"@hypermod/utils": "^0.4.2",
|