@atlaskit/codemod-cli 0.33.1 → 0.34.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.
- package/CHANGELOG.md +16 -0
- package/dist/cjs/main.js +1 -1
- package/dist/cjs/presets/index.js +3 -1
- package/dist/cjs/presets/lozenge-discovery-to-tag-with-fg/codemods/lozenge-discovery-to-tag-with-fg.js +219 -0
- package/dist/cjs/presets/lozenge-discovery-to-tag-with-fg/lozenge-discovery-to-tag-with-fg.js +44 -0
- package/dist/cjs/presets/migrate-deprecated-icon/codemods/migrate-deprecated-icon.js +142 -0
- package/dist/cjs/presets/migrate-deprecated-icon/migrate-deprecated-icon.js +44 -0
- package/dist/cjs/presets/migrate-deprecated-icon/utils/mock.js +81 -0
- package/dist/es2019/presets/index.js +3 -1
- package/dist/es2019/presets/lozenge-discovery-to-tag-with-fg/codemods/lozenge-discovery-to-tag-with-fg.js +207 -0
- package/dist/es2019/presets/lozenge-discovery-to-tag-with-fg/lozenge-discovery-to-tag-with-fg.js +18 -0
- package/dist/es2019/presets/migrate-deprecated-icon/codemods/migrate-deprecated-icon.js +130 -0
- package/dist/es2019/presets/migrate-deprecated-icon/migrate-deprecated-icon.js +18 -0
- package/dist/es2019/presets/migrate-deprecated-icon/utils/mock.js +75 -0
- package/dist/esm/main.js +1 -1
- package/dist/esm/presets/index.js +3 -1
- package/dist/esm/presets/lozenge-discovery-to-tag-with-fg/codemods/lozenge-discovery-to-tag-with-fg.js +213 -0
- package/dist/esm/presets/lozenge-discovery-to-tag-with-fg/lozenge-discovery-to-tag-with-fg.js +37 -0
- package/dist/esm/presets/migrate-deprecated-icon/codemods/migrate-deprecated-icon.js +135 -0
- package/dist/esm/presets/migrate-deprecated-icon/migrate-deprecated-icon.js +37 -0
- package/dist/esm/presets/migrate-deprecated-icon/utils/mock.js +75 -0
- package/dist/types/presets/index.d.ts +2 -0
- package/dist/types/presets/lozenge-discovery-to-tag-with-fg/codemods/lozenge-discovery-to-tag-with-fg.d.ts +12 -0
- package/dist/types/presets/lozenge-discovery-to-tag-with-fg/lozenge-discovery-to-tag-with-fg.d.ts +2 -0
- package/dist/types/presets/migrate-deprecated-icon/codemods/migrate-deprecated-icon.d.ts +3 -0
- package/dist/types/presets/migrate-deprecated-icon/migrate-deprecated-icon.d.ts +2 -0
- package/dist/types-ts4.5/presets/index.d.ts +2 -0
- package/dist/types-ts4.5/presets/lozenge-discovery-to-tag-with-fg/codemods/lozenge-discovery-to-tag-with-fg.d.ts +12 -0
- package/dist/types-ts4.5/presets/lozenge-discovery-to-tag-with-fg/lozenge-discovery-to-tag-with-fg.d.ts +2 -0
- package/dist/types-ts4.5/presets/migrate-deprecated-icon/codemods/migrate-deprecated-icon.d.ts +3 -0
- package/dist/types-ts4.5/presets/migrate-deprecated-icon/migrate-deprecated-icon.d.ts +2 -0
- package/package.json +4 -2
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/* eslint-disable @repo/internal/fs/filename-pattern-match */
|
|
2
|
+
|
|
3
|
+
const LOZENGE_ENTRY_POINT = '@atlaskit/lozenge';
|
|
4
|
+
const TAG_ENTRY_POINT = '@atlaskit/tag';
|
|
5
|
+
const FG_ENTRY_POINT = '@atlassian/jira-feature-gating';
|
|
6
|
+
const FEATURE_GATE_NAME = 'platform-dst-lozenge-tag-badge-visual-uplifts';
|
|
7
|
+
const PRINT_SETTINGS = {
|
|
8
|
+
quote: 'single'
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Codemod to migrate Lozenge components with appearance='new' or 'discovery' to Tag behind feature gate.
|
|
12
|
+
*
|
|
13
|
+
* This codemod:
|
|
14
|
+
* 1. Finds Lozenges with appearance="new" or appearance="discovery"
|
|
15
|
+
* 2. Also includes discovery Lozenges with isBold={true} or isBold
|
|
16
|
+
* 3. Wraps them in a feature gate: fg('platform-dst-lozenge-tag-badge-visual-uplifts')
|
|
17
|
+
* 4. Converts to Tag with color="purple" when feature gate is off
|
|
18
|
+
* 5. Adds necessary imports (Tag, fg)
|
|
19
|
+
*/
|
|
20
|
+
export default function transformer(file, api) {
|
|
21
|
+
const j = api.jscodeshift;
|
|
22
|
+
let source;
|
|
23
|
+
|
|
24
|
+
// Try to parse the file
|
|
25
|
+
try {
|
|
26
|
+
source = j(file.source);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
// eslint-disable-next-line no-console
|
|
29
|
+
console.error(error);
|
|
30
|
+
return file.source;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Check if Lozenge is imported from @atlaskit/lozenge
|
|
34
|
+
const hasLozengeImport = source.find(j.ImportDeclaration).some(importPath => {
|
|
35
|
+
return importPath.value.source.value === LOZENGE_ENTRY_POINT;
|
|
36
|
+
});
|
|
37
|
+
if (!hasLozengeImport) {
|
|
38
|
+
return file.source;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Get all Lozenge component names (handles renamed imports)
|
|
42
|
+
const lozengeNames = new Set();
|
|
43
|
+
source.find(j.ImportDeclaration).forEach(importPath => {
|
|
44
|
+
if (importPath.value.source.value === LOZENGE_ENTRY_POINT) {
|
|
45
|
+
var _importPath$value$spe;
|
|
46
|
+
(_importPath$value$spe = importPath.value.specifiers) === null || _importPath$value$spe === void 0 ? void 0 : _importPath$value$spe.forEach(specifier => {
|
|
47
|
+
if (specifier.type === 'ImportDefaultSpecifier') {
|
|
48
|
+
lozengeNames.add(specifier.local.name);
|
|
49
|
+
} else if (specifier.type === 'ImportSpecifier' && specifier.imported.name === 'default') {
|
|
50
|
+
lozengeNames.add(specifier.local.name);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Find all Lozenge elements that should be migrated
|
|
57
|
+
const lozengeElements = [];
|
|
58
|
+
source.find(j.JSXElement).forEach(path => {
|
|
59
|
+
var _openingElement$name;
|
|
60
|
+
const openingElement = path.value.openingElement;
|
|
61
|
+
if (((_openingElement$name = openingElement.name) === null || _openingElement$name === void 0 ? void 0 : _openingElement$name.type) === 'JSXIdentifier' && lozengeNames.has(openingElement.name.name)) {
|
|
62
|
+
var _openingElement$attri;
|
|
63
|
+
const element = {
|
|
64
|
+
path,
|
|
65
|
+
shouldMigrate: false
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// Check for appearance and isBold props
|
|
69
|
+
(_openingElement$attri = openingElement.attributes) === null || _openingElement$attri === void 0 ? void 0 : _openingElement$attri.forEach(attr => {
|
|
70
|
+
var _attr$name;
|
|
71
|
+
if (attr.type === 'JSXAttribute' && ((_attr$name = attr.name) === null || _attr$name === void 0 ? void 0 : _attr$name.type) === 'JSXIdentifier') {
|
|
72
|
+
if (attr.name.name === 'appearance') {
|
|
73
|
+
var _attr$value, _attr$value2;
|
|
74
|
+
if (((_attr$value = attr.value) === null || _attr$value === void 0 ? void 0 : _attr$value.type) === 'StringLiteral') {
|
|
75
|
+
element.appearanceValue = attr.value.value;
|
|
76
|
+
} else if (((_attr$value2 = attr.value) === null || _attr$value2 === void 0 ? void 0 : _attr$value2.type) === 'JSXExpressionContainer') {
|
|
77
|
+
const expression = attr.value.expression;
|
|
78
|
+
if (expression.type === 'StringLiteral') {
|
|
79
|
+
element.appearanceValue = expression.value;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} else if (attr.name.name === 'isBold') {
|
|
83
|
+
var _attr$value3;
|
|
84
|
+
if (attr.value === null) {
|
|
85
|
+
element.isBoldValue = true;
|
|
86
|
+
} else if (((_attr$value3 = attr.value) === null || _attr$value3 === void 0 ? void 0 : _attr$value3.type) === 'JSXExpressionContainer') {
|
|
87
|
+
const expression = attr.value.expression;
|
|
88
|
+
if (expression.type === 'BooleanLiteral') {
|
|
89
|
+
element.isBoldValue = expression.value;
|
|
90
|
+
} else if (expression.type === 'Literal' && typeof expression.value === 'boolean') {
|
|
91
|
+
element.isBoldValue = expression.value;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Determine if this Lozenge should be migrated
|
|
99
|
+
// Migrate if: appearance="new" OR appearance="discovery" OR (appearance="discovery" AND isBold={true})
|
|
100
|
+
if (element.appearanceValue === 'new' || element.appearanceValue === 'discovery' || element.appearanceValue === 'discovery' && element.isBoldValue === true) {
|
|
101
|
+
element.shouldMigrate = true;
|
|
102
|
+
}
|
|
103
|
+
if (element.shouldMigrate) {
|
|
104
|
+
lozengeElements.push(element);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// If no elements to migrate, return early
|
|
110
|
+
if (lozengeElements.length === 0) {
|
|
111
|
+
return file.source;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Check if Tag import exists
|
|
115
|
+
const hasTagImport = source.find(j.ImportDeclaration).some(importPath => importPath.value.source.value === TAG_ENTRY_POINT);
|
|
116
|
+
|
|
117
|
+
// Check if fg is already imported from @atlassian/jira-feature-gating
|
|
118
|
+
const hasFgImport = source.find(j.ImportDeclaration).some(importPath => {
|
|
119
|
+
if (importPath.value.source.value === FG_ENTRY_POINT) {
|
|
120
|
+
var _importPath$value$spe2;
|
|
121
|
+
// Check if 'fg' is in the specifiers
|
|
122
|
+
return (_importPath$value$spe2 = importPath.value.specifiers) === null || _importPath$value$spe2 === void 0 ? void 0 : _importPath$value$spe2.some(spec => {
|
|
123
|
+
return spec.type === 'ImportSpecifier' && spec.imported.name === 'fg';
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
return false;
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Add imports after Lozenge import to avoid blank lines
|
|
130
|
+
const lozengeImport = source.find(j.ImportDeclaration).filter(path => {
|
|
131
|
+
return path.value.source.value === LOZENGE_ENTRY_POINT;
|
|
132
|
+
}).at(0);
|
|
133
|
+
if (lozengeImport.length > 0) {
|
|
134
|
+
// Add imports in reverse order so they appear in the right order
|
|
135
|
+
if (!hasFgImport) {
|
|
136
|
+
lozengeImport.insertAfter(j.importDeclaration([j.importSpecifier(j.identifier('fg'))], j.stringLiteral(FG_ENTRY_POINT)));
|
|
137
|
+
}
|
|
138
|
+
if (!hasTagImport) {
|
|
139
|
+
lozengeImport.insertAfter(j.importDeclaration([j.importDefaultSpecifier(j.identifier('Tag'))], j.stringLiteral(TAG_ENTRY_POINT)));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Transform each element
|
|
144
|
+
lozengeElements.forEach(element => {
|
|
145
|
+
var _openingElement$attri2;
|
|
146
|
+
const {
|
|
147
|
+
path
|
|
148
|
+
} = element;
|
|
149
|
+
const openingElement = path.value.openingElement;
|
|
150
|
+
|
|
151
|
+
// Extract text content or JSX expression from children
|
|
152
|
+
const children = path.value.children;
|
|
153
|
+
let textAttribute = null;
|
|
154
|
+
if (children && children.length > 0) {
|
|
155
|
+
// Check if there's a single JSX expression child (e.g., {formatMessage(...)})
|
|
156
|
+
if (children.length === 1 && children[0].type === 'JSXExpressionContainer') {
|
|
157
|
+
const expression = children[0].expression;
|
|
158
|
+
// Use the expression as the text value
|
|
159
|
+
textAttribute = j.jsxAttribute(j.jsxIdentifier('text'), j.jsxExpressionContainer(expression));
|
|
160
|
+
} else {
|
|
161
|
+
// Extract plain text content from JSXText nodes
|
|
162
|
+
const textContent = children.filter(child => child.type === 'JSXText').map(child => child.value.trim()).filter(text => text.length > 0).join(' ');
|
|
163
|
+
if (textContent) {
|
|
164
|
+
textAttribute = j.jsxAttribute(j.jsxIdentifier('text'), j.stringLiteral(textContent));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Create the Tag element
|
|
170
|
+
const tagAttributes = [j.jsxAttribute(j.jsxIdentifier('color'), j.stringLiteral('purple'))];
|
|
171
|
+
if (textAttribute) {
|
|
172
|
+
tagAttributes.unshift(textAttribute);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Copy other props from Lozenge to Tag (except appearance and isBold)
|
|
176
|
+
(_openingElement$attri2 = openingElement.attributes) === null || _openingElement$attri2 === void 0 ? void 0 : _openingElement$attri2.forEach(attr => {
|
|
177
|
+
var _attr$name2;
|
|
178
|
+
if (attr.type === 'JSXAttribute' && ((_attr$name2 = attr.name) === null || _attr$name2 === void 0 ? void 0 : _attr$name2.type) === 'JSXIdentifier') {
|
|
179
|
+
if (attr.name.name !== 'appearance' && attr.name.name !== 'isBold') {
|
|
180
|
+
tagAttributes.push(attr);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
const tagElement = j.jsxElement(j.jsxOpeningElement(j.jsxIdentifier('Tag'), tagAttributes, true), null, []);
|
|
185
|
+
|
|
186
|
+
// Keep the original Lozenge element (just the element, without wrapping)
|
|
187
|
+
const lozengeElement = path.value;
|
|
188
|
+
|
|
189
|
+
// Create the conditional expression: fg(FEATURE_GATE_NAME) ? <Tag .../> : <Lozenge .../>
|
|
190
|
+
// When feature gate is ON, show Tag (new behavior)
|
|
191
|
+
// When feature gate is OFF, show Lozenge (old behavior)
|
|
192
|
+
const conditionalExpression = j.conditionalExpression(j.callExpression(j.identifier('fg'), [j.stringLiteral(FEATURE_GATE_NAME)]), tagElement, lozengeElement);
|
|
193
|
+
|
|
194
|
+
// Check if the parent is a JSXElement (means we're inside JSX, need curly braces)
|
|
195
|
+
// Otherwise, it's a regular expression (like in a return statement)
|
|
196
|
+
const parent = path.parent;
|
|
197
|
+
const needsJSXWrapper = parent && (parent.value.type === 'JSXElement' || parent.value.type === 'JSXExpressionContainer');
|
|
198
|
+
if (needsJSXWrapper) {
|
|
199
|
+
// Inside JSX, wrap in expression container
|
|
200
|
+
j(path).replaceWith(j.jsxExpressionContainer(conditionalExpression));
|
|
201
|
+
} else {
|
|
202
|
+
// In regular JS context (like return statement), just use the conditional
|
|
203
|
+
j(path).replaceWith(conditionalExpression);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
return source.toSource(PRINT_SETTINGS);
|
|
207
|
+
}
|
package/dist/es2019/presets/lozenge-discovery-to-tag-with-fg/lozenge-discovery-to-tag-with-fg.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import lozengeDiscoveryToTagWithFgTransformer from './codemods/lozenge-discovery-to-tag-with-fg';
|
|
2
|
+
export default async function transformer(file, api) {
|
|
3
|
+
const transformers = [lozengeDiscoveryToTagWithFgTransformer];
|
|
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,130 @@
|
|
|
1
|
+
/* eslint-disable @repo/internal/fs/filename-pattern-match */
|
|
2
|
+
|
|
3
|
+
import { deprecatedCore as deprecatedIconLabCore } from '@atlaskit/icon-lab/deprecated-map';
|
|
4
|
+
import coreIconLabMetadata from '@atlaskit/icon-lab/metadata';
|
|
5
|
+
import { deprecatedCore as deprecatedIconCore } from '@atlaskit/icon/deprecated-map';
|
|
6
|
+
import { coreIconMetadata } from '@atlaskit/icon/metadata';
|
|
7
|
+
const extractIconName = importPath => {
|
|
8
|
+
const match = importPath.match(/\/([^\/]+)$/);
|
|
9
|
+
return match ? match[1] : '';
|
|
10
|
+
};
|
|
11
|
+
const getIconComponentName = name => {
|
|
12
|
+
return name.split(/\W/).map(part => `${part[0].toUpperCase()}${part.slice(1)}`).join('').concat('Icon');
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates a new default import declaration for the transformed component
|
|
17
|
+
*/
|
|
18
|
+
const createDefaultImportDeclaration = (j, componentName, importPath) => {
|
|
19
|
+
const defaultSpecifier = j.importDefaultSpecifier(j.identifier(componentName));
|
|
20
|
+
return j.importDeclaration([defaultSpecifier], j.stringLiteral(importPath));
|
|
21
|
+
};
|
|
22
|
+
const PRINT_SETTINGS = {
|
|
23
|
+
quote: 'single',
|
|
24
|
+
trailingComma: true
|
|
25
|
+
};
|
|
26
|
+
const transformer = (file, api) => {
|
|
27
|
+
const j = api.jscodeshift;
|
|
28
|
+
const fileSource = j(file.source);
|
|
29
|
+
const deprecatedIcons = Object.keys(deprecatedIconCore);
|
|
30
|
+
const deprecatedIconLabIcons = Object.keys(deprecatedIconLabCore);
|
|
31
|
+
|
|
32
|
+
// Find all deprecated icon imports
|
|
33
|
+
const deprecatedIconImports = fileSource.find(j.ImportDeclaration).filter(path => {
|
|
34
|
+
var _coreIconMetadata$ico, _coreIconLabMetadata$;
|
|
35
|
+
const source = path.node.source.value;
|
|
36
|
+
|
|
37
|
+
//Extract icon name from import path
|
|
38
|
+
const iconName = extractIconName(source);
|
|
39
|
+
const isDeprecated = deprecatedIcons.includes(source) || deprecatedIconLabIcons.includes(source);
|
|
40
|
+
const hasReplacement = !!((_coreIconMetadata$ico = coreIconMetadata[iconName]) !== null && _coreIconMetadata$ico !== void 0 && _coreIconMetadata$ico.replacement) || !!((_coreIconLabMetadata$ = coreIconLabMetadata[iconName]) !== null && _coreIconLabMetadata$ !== void 0 && _coreIconLabMetadata$.replacement);
|
|
41
|
+
return typeof source === 'string' && isDeprecated && hasReplacement;
|
|
42
|
+
});
|
|
43
|
+
if (!deprecatedIconImports.length) {
|
|
44
|
+
return fileSource.toSource();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Track import name mappings (old name -> new name) and new imports to create
|
|
48
|
+
const importNameMappings = new Map();
|
|
49
|
+
const newImportsToCreate = [];
|
|
50
|
+
|
|
51
|
+
// Process each icon-object import
|
|
52
|
+
deprecatedIconImports.forEach(importPath => {
|
|
53
|
+
var _coreIconMetadata$ico2, _coreIconMetadata$ico3, _coreIconLabMetadata$2, _importDeclaration$sp;
|
|
54
|
+
const importDeclaration = importPath.node;
|
|
55
|
+
const source = importDeclaration.source.value;
|
|
56
|
+
|
|
57
|
+
//Extract icon name from import path
|
|
58
|
+
const iconName = extractIconName(source);
|
|
59
|
+
const replacementIconInfo = (_coreIconMetadata$ico2 = (_coreIconMetadata$ico3 = coreIconMetadata[iconName]) === null || _coreIconMetadata$ico3 === void 0 ? void 0 : _coreIconMetadata$ico3.replacement) !== null && _coreIconMetadata$ico2 !== void 0 ? _coreIconMetadata$ico2 : (_coreIconLabMetadata$2 = coreIconLabMetadata[iconName]) === null || _coreIconLabMetadata$2 === void 0 ? void 0 : _coreIconLabMetadata$2.replacement;
|
|
60
|
+
if (!replacementIconInfo) {
|
|
61
|
+
return; // No replacement found, skip
|
|
62
|
+
}
|
|
63
|
+
const replacementIconName = getIconComponentName(replacementIconInfo.name);
|
|
64
|
+
const replacementIconImport = `${replacementIconInfo.location}/core/${replacementIconInfo.name}`;
|
|
65
|
+
|
|
66
|
+
// Get the current import name (could be default import or renamed)
|
|
67
|
+
const defaultSpecifier = (_importDeclaration$sp = importDeclaration.specifiers) === null || _importDeclaration$sp === void 0 ? void 0 : _importDeclaration$sp.find(spec => spec.type === 'ImportDefaultSpecifier');
|
|
68
|
+
if (defaultSpecifier) {
|
|
69
|
+
var _defaultSpecifier$loc;
|
|
70
|
+
const currentImportName = (_defaultSpecifier$loc = defaultSpecifier.local) === null || _defaultSpecifier$loc === void 0 ? void 0 : _defaultSpecifier$loc.name;
|
|
71
|
+
if (currentImportName) {
|
|
72
|
+
// Map the old import name to the new component name
|
|
73
|
+
importNameMappings.set(currentImportName, replacementIconName);
|
|
74
|
+
|
|
75
|
+
// Track the new import to create
|
|
76
|
+
newImportsToCreate.push({
|
|
77
|
+
componentName: replacementIconName,
|
|
78
|
+
importPath: replacementIconImport,
|
|
79
|
+
oldImportPath: importPath
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Update JSX elements to use new component names
|
|
86
|
+
importNameMappings.forEach((newName, oldName) => {
|
|
87
|
+
fileSource.find(j.JSXElement).filter(path => {
|
|
88
|
+
const openingElement = path.value.openingElement;
|
|
89
|
+
return openingElement.name.type === 'JSXIdentifier' && openingElement.name.name === oldName;
|
|
90
|
+
}).forEach(elementPath => {
|
|
91
|
+
var _element$closingEleme;
|
|
92
|
+
const element = elementPath.value;
|
|
93
|
+
|
|
94
|
+
// Update opening tag
|
|
95
|
+
if (element.openingElement.name.type === 'JSXIdentifier') {
|
|
96
|
+
element.openingElement.name.name = newName;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Update closing tag if it exists
|
|
100
|
+
if (((_element$closingEleme = element.closingElement) === null || _element$closingEleme === void 0 ? void 0 : _element$closingEleme.name.type) === 'JSXIdentifier') {
|
|
101
|
+
element.closingElement.name.name = newName;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Update other references (like in render calls, etc.)
|
|
107
|
+
importNameMappings.forEach((newName, oldName) => {
|
|
108
|
+
fileSource.find(j.Identifier).filter(path => path.node.name === oldName).forEach(path => {
|
|
109
|
+
var _parent$value, _parent$value2;
|
|
110
|
+
// Only update if it's not part of an import declaration or JSX element
|
|
111
|
+
// (those are handled separately)
|
|
112
|
+
const parent = path.parent;
|
|
113
|
+
if ((parent === null || parent === void 0 ? void 0 : (_parent$value = parent.value) === null || _parent$value === void 0 ? void 0 : _parent$value.type) !== 'ImportDefaultSpecifier' && (parent === null || parent === void 0 ? void 0 : (_parent$value2 = parent.value) === null || _parent$value2 === void 0 ? void 0 : _parent$value2.type) !== 'JSXIdentifier') {
|
|
114
|
+
path.node.name = newName;
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Create new individual default imports
|
|
120
|
+
newImportsToCreate.forEach(({
|
|
121
|
+
componentName,
|
|
122
|
+
importPath,
|
|
123
|
+
oldImportPath
|
|
124
|
+
}) => {
|
|
125
|
+
const newImport = createDefaultImportDeclaration(j, componentName, importPath);
|
|
126
|
+
oldImportPath.replace(newImport);
|
|
127
|
+
});
|
|
128
|
+
return fileSource.toSource(PRINT_SETTINGS);
|
|
129
|
+
};
|
|
130
|
+
export default transformer;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import migrateDeprecatedIconTransformer from './codemods/migrate-deprecated-icon';
|
|
2
|
+
export default async function transformer(file, api) {
|
|
3
|
+
const transformers = [migrateDeprecatedIconTransformer];
|
|
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,75 @@
|
|
|
1
|
+
export const mockMetadata = {
|
|
2
|
+
coreIconMetadata: {
|
|
3
|
+
capture: {
|
|
4
|
+
keywords: ['capture', 'icon', 'focus', 'focus area', 'capture'],
|
|
5
|
+
componentName: 'CaptureIcon',
|
|
6
|
+
package: '@atlaskit/icon/core/capture',
|
|
7
|
+
oldName: ['jira/capture'],
|
|
8
|
+
replacement: {
|
|
9
|
+
name: 'focus-area',
|
|
10
|
+
location: '@atlaskit/icon'
|
|
11
|
+
},
|
|
12
|
+
categorization: 'single-purpose',
|
|
13
|
+
usage: 'Reserved for representing Focus Areas.',
|
|
14
|
+
team: 'Design System Team',
|
|
15
|
+
status: 'deprecated'
|
|
16
|
+
},
|
|
17
|
+
'chart-matrix': {
|
|
18
|
+
keywords: ['chart-matrix', 'chartmatrix', 'icon', 'dot chart', 'graph', 'matrix', ''],
|
|
19
|
+
componentName: 'ChartMatrixIcon',
|
|
20
|
+
package: '@atlaskit/icon/core/chart-matrix',
|
|
21
|
+
replacement: {
|
|
22
|
+
name: 'chart-bubble',
|
|
23
|
+
location: '@atlaskit/icon'
|
|
24
|
+
},
|
|
25
|
+
categorization: 'multi-purpose',
|
|
26
|
+
usage: 'Multi purpose - Known uses: Matrix view in in JPD, and other matrix charts.',
|
|
27
|
+
team: 'Design System Team',
|
|
28
|
+
status: 'deprecated'
|
|
29
|
+
},
|
|
30
|
+
close: {
|
|
31
|
+
keywords: ['close', 'icon', 'cross', 'x', 'close', 'remove'],
|
|
32
|
+
componentName: 'CloseIcon',
|
|
33
|
+
package: '@atlaskit/icon/core/close',
|
|
34
|
+
oldName: ['cross', 'editor/close'],
|
|
35
|
+
replacement: {
|
|
36
|
+
name: 'cross',
|
|
37
|
+
location: '@atlaskit/icon'
|
|
38
|
+
},
|
|
39
|
+
categorization: 'multi-purpose',
|
|
40
|
+
usage: 'Known uses: closing modals, panels, and transient views; removing tags',
|
|
41
|
+
team: 'Design System Team',
|
|
42
|
+
status: 'deprecated'
|
|
43
|
+
},
|
|
44
|
+
error: {
|
|
45
|
+
keywords: ['error', 'warning', 'alert', 'icon', 'filled', 'status', 'danger', 'exclamation', '!', 'error'],
|
|
46
|
+
componentName: 'ErrorIcon',
|
|
47
|
+
package: '@atlaskit/icon/core/error',
|
|
48
|
+
oldName: ['error'],
|
|
49
|
+
replacement: {
|
|
50
|
+
name: 'status-error',
|
|
51
|
+
location: '@atlaskit/icon'
|
|
52
|
+
},
|
|
53
|
+
categorization: 'single-purpose',
|
|
54
|
+
usage: 'Reserved for error statuses and messaging. Filled status icons provide higher visual contrast to draw attention to important information.',
|
|
55
|
+
team: 'Design System Team',
|
|
56
|
+
status: 'deprecated'
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
export const mockDeprecatedIcons = {
|
|
61
|
+
deprecatedCore: {
|
|
62
|
+
'@atlaskit/icon/core/capture': {
|
|
63
|
+
message: 'The icon "capture" is deprecated in favour of "focus-area" from "@atlaskit/icon/core"'
|
|
64
|
+
},
|
|
65
|
+
'@atlaskit/icon/core/chart-matrix': {
|
|
66
|
+
message: 'The icon "chart-matrix" is deprecated in favour of "chart-bubble" from "@atlaskit/icon/core"'
|
|
67
|
+
},
|
|
68
|
+
'@atlaskit/icon/core/close': {
|
|
69
|
+
message: 'The icon "close" is deprecated in favour of "cross" from "@atlaskit/icon/core"'
|
|
70
|
+
},
|
|
71
|
+
'@atlaskit/icon/core/error': {
|
|
72
|
+
message: 'The icon "error" is deprecated in favour of "status-error" from "@atlaskit/icon/core"'
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
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) {
|
|
@@ -14,9 +14,11 @@ 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-semantic-migration/lozenge-appearance-semantic-migration';
|
|
16
16
|
import './lozenge-to-tag-migration/lozenge-to-tag-migration';
|
|
17
|
+
import './lozenge-discovery-to-tag-with-fg/lozenge-discovery-to-tag-with-fg';
|
|
17
18
|
import './badge-appearance-semantic-migration/badge-appearance-semantic-migration';
|
|
18
19
|
import './tag-to-newTag-migration/tag-to-newTag-migration';
|
|
19
|
-
|
|
20
|
+
import './migrate-deprecated-icon/migrate-deprecated-icon';
|
|
21
|
+
var presets = ['styled-to-emotion', 'theme-remove-deprecated-mixins', 'migrate-deprecated-icon', '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-semantic-migration', 'lozenge-to-tag-migration', 'lozenge-discovery-to-tag-with-fg', 'badge-appearance-semantic-migration', 'tag-to-newTag-migration'].map(function (preset) {
|
|
20
22
|
return path.join(__dirname, preset, "".concat(preset, ".@(ts|js|tsx)"));
|
|
21
23
|
});
|
|
22
24
|
export default presets;
|