@atlaskit/side-navigation 3.2.1 → 3.3.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 +14 -1
- package/README.md +7 -3
- package/codemods/0.8.0-change-css-fn-prop.tsx +136 -164
- package/codemods/__tests__/0.8.0-change-css-fn-prop.tsx +77 -77
- package/codemods/helpers/generic.tsx +528 -564
- package/constellation/index/examples.mdx +20 -20
- package/constellation/index/props.mdx +8 -8
- package/constellation/index/usage.mdx +27 -11
- package/dist/cjs/components/Header/index.js +4 -0
- package/dist/cjs/components/Item/link-item.js +3 -1
- package/dist/cjs/components/LoadingItems/index.js +7 -3
- package/dist/cjs/components/NavigationContent/index.js +8 -1
- package/dist/cjs/components/NavigationHeader/index.js +4 -0
- package/dist/cjs/components/NestableNavigationContent/index.js +5 -0
- package/dist/cjs/components/NestableNavigationContent/nesting-motion.js +3 -1
- package/dist/cjs/components/NestingItem/index.js +4 -0
- package/dist/cjs/components/SideNavigation/index.js +5 -0
- package/dist/es2019/components/Header/index.js +5 -0
- package/dist/es2019/components/Item/link-item.js +3 -1
- package/dist/es2019/components/LoadingItems/index.js +7 -3
- package/dist/es2019/components/NavigationContent/index.js +8 -1
- package/dist/es2019/components/NavigationHeader/index.js +4 -0
- package/dist/es2019/components/NestableNavigationContent/index.js +5 -0
- package/dist/es2019/components/NestableNavigationContent/nesting-motion.js +4 -0
- package/dist/es2019/components/NestingItem/index.js +5 -0
- package/dist/es2019/components/SideNavigation/index.js +5 -0
- package/dist/esm/components/Header/index.js +5 -0
- package/dist/esm/components/Item/link-item.js +3 -1
- package/dist/esm/components/LoadingItems/index.js +7 -3
- package/dist/esm/components/NavigationContent/index.js +8 -1
- package/dist/esm/components/NavigationHeader/index.js +4 -0
- package/dist/esm/components/NestableNavigationContent/index.js +5 -0
- package/dist/esm/components/NestableNavigationContent/nesting-motion.js +4 -0
- package/dist/esm/components/NestingItem/index.js +5 -0
- package/dist/esm/components/SideNavigation/index.js +5 -0
- package/dist/types/components/LoadingItems/index.d.ts +1 -1
- package/dist/types/components/NavigationContent/index.d.ts +3 -0
- package/dist/types/components/NavigationHeader/index.d.ts +3 -0
- package/dist/types/components/NestableNavigationContent/nesting-motion.d.ts +3 -0
- package/dist/types/components/NestingItem/index.d.ts +3 -0
- package/dist/types/components/index.d.ts +2 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types-ts4.5/components/LoadingItems/index.d.ts +1 -1
- package/dist/types-ts4.5/components/NavigationContent/index.d.ts +3 -0
- package/dist/types-ts4.5/components/NavigationHeader/index.d.ts +3 -0
- package/dist/types-ts4.5/components/NestableNavigationContent/nesting-motion.d.ts +3 -0
- package/dist/types-ts4.5/components/NestingItem/index.d.ts +3 -0
- package/dist/types-ts4.5/components/index.d.ts +2 -2
- package/dist/types-ts4.5/index.d.ts +1 -1
- package/docs/00-intro.tsx +4 -6
- package/docs/ert/footer.tsx +6 -6
- package/package.json +97 -97
- package/report.api.md +102 -123
|
@@ -1,410 +1,401 @@
|
|
|
1
1
|
import { type NodePath } from 'ast-types/lib/node-path';
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
type ASTPath,
|
|
4
|
+
type default as core,
|
|
5
|
+
type ImportDeclaration,
|
|
6
|
+
type ImportDefaultSpecifier,
|
|
7
|
+
type ImportSpecifier,
|
|
8
|
+
type JSXAttribute,
|
|
9
|
+
type JSXElement,
|
|
10
|
+
type Node,
|
|
11
|
+
type Program,
|
|
12
12
|
} from 'jscodeshift';
|
|
13
13
|
import { type Collection } from 'jscodeshift/src/Collection';
|
|
14
14
|
|
|
15
15
|
export type Nullable<T> = T | null;
|
|
16
16
|
|
|
17
17
|
export function hasImportDeclaration(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
j: core.JSCodeshift,
|
|
19
|
+
source: string,
|
|
20
|
+
importPath: string,
|
|
21
21
|
): boolean {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
).length > 0
|
|
29
|
-
);
|
|
22
|
+
return (
|
|
23
|
+
j(source)
|
|
24
|
+
.find(j.ImportDeclaration)
|
|
25
|
+
.filter((path: ASTPath<ImportDeclaration>) => path.node.source.value === importPath).length >
|
|
26
|
+
0
|
|
27
|
+
);
|
|
30
28
|
}
|
|
31
29
|
|
|
32
30
|
export function getDefaultSpecifierName({
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
j,
|
|
32
|
+
base,
|
|
33
|
+
packageName,
|
|
36
34
|
}: {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
j: core.JSCodeshift;
|
|
36
|
+
base: Collection<any>;
|
|
37
|
+
packageName: string;
|
|
40
38
|
}): Nullable<string> {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
39
|
+
const specifiers = base
|
|
40
|
+
.find(j.ImportDeclaration)
|
|
41
|
+
.filter((path) => path.node.source.value === packageName)
|
|
42
|
+
.find(j.ImportDefaultSpecifier);
|
|
43
|
+
|
|
44
|
+
if (!specifiers.length) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return specifiers.nodes()[0]!.local!.name;
|
|
50
48
|
}
|
|
51
49
|
|
|
52
50
|
export function getJSXAttributesByName({
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
j,
|
|
52
|
+
element,
|
|
53
|
+
attributeName,
|
|
56
54
|
}: {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
j: core.JSCodeshift;
|
|
56
|
+
element: JSXElement;
|
|
57
|
+
attributeName: string;
|
|
60
58
|
}): Collection<JSXAttribute> {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
59
|
+
return j(element)
|
|
60
|
+
.find(j.JSXOpeningElement)
|
|
61
|
+
.find(j.JSXAttribute)
|
|
62
|
+
.filter((attribute) => {
|
|
63
|
+
const matches = j(attribute)
|
|
64
|
+
// This will find identifiers on nested jsx elements
|
|
65
|
+
// so we are going to do a filter to ensure we are only
|
|
66
|
+
// going one level deep
|
|
67
|
+
.find(j.JSXIdentifier)
|
|
68
|
+
.filter((identifer) => {
|
|
69
|
+
j(identifer).closest(j.JSXOpeningElement);
|
|
70
|
+
// Checking we are on the same level as the jsx element
|
|
71
|
+
const closest = j(identifer).closest(j.JSXOpeningElement).nodes()[0];
|
|
72
|
+
|
|
73
|
+
if (!closest) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
return (
|
|
77
|
+
closest.name.type === 'JSXIdentifier' &&
|
|
78
|
+
element.openingElement.name.type === 'JSXIdentifier' &&
|
|
79
|
+
element.openingElement.name.name === closest.name.name
|
|
80
|
+
);
|
|
81
|
+
})
|
|
82
|
+
.filter((identifier) => identifier.value.name === attributeName);
|
|
83
|
+
return Boolean(matches.length);
|
|
84
|
+
});
|
|
87
85
|
}
|
|
88
86
|
|
|
89
87
|
export function hasJSXAttributesByName({
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
j,
|
|
89
|
+
element,
|
|
90
|
+
attributeName,
|
|
93
91
|
}: {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
92
|
+
j: core.JSCodeshift;
|
|
93
|
+
element: JSXElement;
|
|
94
|
+
attributeName: string;
|
|
97
95
|
}): boolean {
|
|
98
|
-
|
|
96
|
+
return getJSXAttributesByName({ j, element, attributeName }).length > 0;
|
|
99
97
|
}
|
|
100
98
|
|
|
101
99
|
export function removeImport({
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
j,
|
|
101
|
+
base,
|
|
102
|
+
packageName,
|
|
105
103
|
}: {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
104
|
+
j: core.JSCodeshift;
|
|
105
|
+
base: Collection<any>;
|
|
106
|
+
packageName: string;
|
|
109
107
|
}) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
base
|
|
109
|
+
.find(j.ImportDeclaration)
|
|
110
|
+
.filter((path) => path.node.source.value === packageName)
|
|
111
|
+
.remove();
|
|
114
112
|
}
|
|
115
113
|
|
|
116
114
|
export function tryCreateImport({
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
115
|
+
j,
|
|
116
|
+
base,
|
|
117
|
+
relativeToPackage,
|
|
118
|
+
packageName,
|
|
121
119
|
}: {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
120
|
+
j: core.JSCodeshift;
|
|
121
|
+
base: Collection<any>;
|
|
122
|
+
relativeToPackage: string;
|
|
123
|
+
packageName: string;
|
|
126
124
|
}) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
.insertBefore(j.importDeclaration([], j.literal(packageName)));
|
|
125
|
+
const exists: boolean =
|
|
126
|
+
base.find(j.ImportDeclaration).filter((path) => path.value.source.value === packageName)
|
|
127
|
+
.length > 0;
|
|
128
|
+
|
|
129
|
+
if (exists) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
base
|
|
134
|
+
.find(j.ImportDeclaration)
|
|
135
|
+
.filter((path) => path.value.source.value === relativeToPackage)
|
|
136
|
+
.insertBefore(j.importDeclaration([], j.literal(packageName)));
|
|
140
137
|
}
|
|
141
138
|
|
|
142
139
|
export function addToImport({
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
140
|
+
j,
|
|
141
|
+
base,
|
|
142
|
+
importSpecifier,
|
|
143
|
+
packageName,
|
|
147
144
|
}: {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
145
|
+
j: core.JSCodeshift;
|
|
146
|
+
base: Collection<any>;
|
|
147
|
+
importSpecifier: ImportSpecifier | ImportDefaultSpecifier;
|
|
148
|
+
packageName: string;
|
|
152
149
|
}) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
150
|
+
base
|
|
151
|
+
.find(j.ImportDeclaration)
|
|
152
|
+
.filter((path) => path.value.source.value === packageName)
|
|
153
|
+
.replaceWith((declaration) => {
|
|
154
|
+
return j.importDeclaration(
|
|
155
|
+
[
|
|
156
|
+
// we are appending to the existing specifiers
|
|
157
|
+
// We are doing a filter hear because sometimes specifiers can be removed
|
|
158
|
+
// but they hand around in the declaration
|
|
159
|
+
...(declaration.value.specifiers || []).filter(
|
|
160
|
+
(item) => item.type === 'ImportSpecifier' && item.imported != null,
|
|
161
|
+
),
|
|
162
|
+
importSpecifier,
|
|
163
|
+
],
|
|
164
|
+
j.literal(packageName),
|
|
165
|
+
);
|
|
166
|
+
});
|
|
170
167
|
}
|
|
171
168
|
|
|
172
169
|
export function doesIdentifierExist({
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
170
|
+
j,
|
|
171
|
+
base,
|
|
172
|
+
name,
|
|
176
173
|
}: {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
174
|
+
j: core.JSCodeshift;
|
|
175
|
+
base: Collection<any>;
|
|
176
|
+
name: string;
|
|
180
177
|
}): boolean {
|
|
181
|
-
|
|
182
|
-
base.find(j.Identifier).filter((identifer) => identifer.value.name === name)
|
|
183
|
-
.length > 0
|
|
184
|
-
);
|
|
178
|
+
return base.find(j.Identifier).filter((identifer) => identifer.value.name === name).length > 0;
|
|
185
179
|
}
|
|
186
180
|
|
|
187
181
|
export function isUsingSupportedSpread({
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
182
|
+
j,
|
|
183
|
+
base,
|
|
184
|
+
element,
|
|
191
185
|
}: {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
186
|
+
j: core.JSCodeshift;
|
|
187
|
+
base: Collection<any>;
|
|
188
|
+
element: NodePath<JSXElement, JSXElement>;
|
|
195
189
|
}): boolean {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
);
|
|
190
|
+
const isUsingSpread: boolean = j(element).find(j.JSXSpreadAttribute).length > 0;
|
|
191
|
+
|
|
192
|
+
if (!isUsingSpread) {
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return (
|
|
197
|
+
j(element)
|
|
198
|
+
.find(j.JSXSpreadAttribute)
|
|
199
|
+
.filter((spread) => {
|
|
200
|
+
const argument = spread.value.argument;
|
|
201
|
+
// in place expression is supported
|
|
202
|
+
if (argument.type === 'ObjectExpression') {
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Supporting identifiers that point to an a local object expression
|
|
207
|
+
if (argument.type === 'Identifier') {
|
|
208
|
+
return (
|
|
209
|
+
base.find(j.VariableDeclarator).filter((declarator): boolean => {
|
|
210
|
+
return Boolean(
|
|
211
|
+
declarator.value.id.type === 'Identifier' &&
|
|
212
|
+
declarator.value.init &&
|
|
213
|
+
declarator.value.init.type === 'ObjectExpression',
|
|
214
|
+
);
|
|
215
|
+
}).length > 0
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// We don't support anything else
|
|
220
|
+
return false;
|
|
221
|
+
}).length > 0
|
|
222
|
+
);
|
|
230
223
|
}
|
|
231
224
|
|
|
232
225
|
export function isOnlyUsingNameForJSX({
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
226
|
+
j,
|
|
227
|
+
base,
|
|
228
|
+
name,
|
|
236
229
|
}: {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
230
|
+
j: core.JSCodeshift;
|
|
231
|
+
base: Collection<any>;
|
|
232
|
+
name: string;
|
|
240
233
|
}): boolean {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
return true;
|
|
234
|
+
const jsxIdentifierCount: number = base
|
|
235
|
+
.find(j.JSXIdentifier)
|
|
236
|
+
.filter((identifier) => identifier.value.name === name).length;
|
|
237
|
+
|
|
238
|
+
// Not used in JSX at all
|
|
239
|
+
if (jsxIdentifierCount === 0) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const nonJSXIdentifierCount: number = base.find(j.Identifier).filter((identifier) => {
|
|
244
|
+
if (identifier.value.name !== name) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// @ts-ignore
|
|
249
|
+
if (identifier.value.type === 'JSXIdentifier') {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Excluding exports
|
|
254
|
+
if (j(identifier).closest(j.ImportDefaultSpecifier).length) {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
if (j(identifier).closest(j.ImportSpecifier).length) {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return true;
|
|
262
|
+
}).length;
|
|
263
|
+
|
|
264
|
+
if (nonJSXIdentifierCount > 0) {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return true;
|
|
278
269
|
}
|
|
279
270
|
|
|
280
271
|
export function getSafeImportName({
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
272
|
+
j,
|
|
273
|
+
base,
|
|
274
|
+
currentDefaultSpecifierName,
|
|
275
|
+
desiredName,
|
|
276
|
+
fallbackName,
|
|
286
277
|
}: {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
278
|
+
j: core.JSCodeshift;
|
|
279
|
+
base: Collection<any>;
|
|
280
|
+
currentDefaultSpecifierName: string;
|
|
281
|
+
desiredName: string;
|
|
282
|
+
fallbackName: string;
|
|
292
283
|
}) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
284
|
+
if (currentDefaultSpecifierName === desiredName) {
|
|
285
|
+
return desiredName;
|
|
286
|
+
}
|
|
296
287
|
|
|
297
|
-
|
|
288
|
+
const isUsed: boolean = doesIdentifierExist({ j, base, name: desiredName });
|
|
298
289
|
|
|
299
|
-
|
|
290
|
+
return isUsed ? fallbackName : desiredName;
|
|
300
291
|
}
|
|
301
292
|
|
|
302
293
|
export function isUsingThroughSpread({
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
294
|
+
j,
|
|
295
|
+
base,
|
|
296
|
+
element,
|
|
297
|
+
propName,
|
|
307
298
|
}: {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
299
|
+
j: core.JSCodeshift;
|
|
300
|
+
base: Collection<any>;
|
|
301
|
+
element: NodePath<JSXElement, JSXElement>;
|
|
302
|
+
propName: string;
|
|
312
303
|
}): boolean {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
304
|
+
if (!isUsingSupportedSpread({ j, base, element })) {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const isUsedThroughExpression: boolean =
|
|
309
|
+
j(element)
|
|
310
|
+
.find(j.JSXSpreadAttribute)
|
|
311
|
+
.find(j.ObjectExpression)
|
|
312
|
+
.filter((item) => {
|
|
313
|
+
const match: boolean =
|
|
314
|
+
item.value.properties.filter(
|
|
315
|
+
(property) =>
|
|
316
|
+
property.type === 'ObjectProperty' &&
|
|
317
|
+
property.key.type === 'Identifier' &&
|
|
318
|
+
property.key.name === propName,
|
|
319
|
+
).length > 0;
|
|
320
|
+
|
|
321
|
+
return match;
|
|
322
|
+
}).length > 0;
|
|
323
|
+
|
|
324
|
+
if (isUsedThroughExpression) {
|
|
325
|
+
return true;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const isUsedThroughIdentifier: boolean =
|
|
329
|
+
j(element)
|
|
330
|
+
.find(j.JSXSpreadAttribute)
|
|
331
|
+
.find(j.Identifier)
|
|
332
|
+
.filter((identifier): boolean => {
|
|
333
|
+
return (
|
|
334
|
+
base
|
|
335
|
+
.find(j.VariableDeclarator)
|
|
336
|
+
.filter(
|
|
337
|
+
(declarator) =>
|
|
338
|
+
declarator.value.id.type === 'Identifier' &&
|
|
339
|
+
declarator.value.id.name === identifier.value.name,
|
|
340
|
+
)
|
|
341
|
+
.filter((declarator) => {
|
|
342
|
+
const value = declarator.value;
|
|
343
|
+
if (value.id.type !== 'Identifier') {
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (value.id.name !== identifier.value.name) {
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (!value.init) {
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (value.init.type !== 'ObjectExpression') {
|
|
356
|
+
return false;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const match: boolean =
|
|
360
|
+
value.init.properties.filter(
|
|
361
|
+
(property) =>
|
|
362
|
+
property.type === 'ObjectProperty' &&
|
|
363
|
+
property.key.type === 'Identifier' &&
|
|
364
|
+
property.key.name === propName,
|
|
365
|
+
).length > 0;
|
|
366
|
+
|
|
367
|
+
return match;
|
|
368
|
+
}).length > 0
|
|
369
|
+
);
|
|
370
|
+
}).length > 0;
|
|
371
|
+
|
|
372
|
+
return isUsedThroughIdentifier;
|
|
382
373
|
}
|
|
383
374
|
|
|
384
375
|
export function isUsingProp({
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
376
|
+
j,
|
|
377
|
+
base,
|
|
378
|
+
element,
|
|
379
|
+
propName,
|
|
389
380
|
}: {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
381
|
+
j: core.JSCodeshift;
|
|
382
|
+
base: Collection<any>;
|
|
383
|
+
element: NodePath<JSXElement, JSXElement>;
|
|
384
|
+
propName: string;
|
|
394
385
|
}): boolean {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
386
|
+
return (
|
|
387
|
+
hasJSXAttributesByName({
|
|
388
|
+
j,
|
|
389
|
+
element: element.value,
|
|
390
|
+
attributeName: propName,
|
|
391
|
+
}) ||
|
|
392
|
+
isUsingThroughSpread({
|
|
393
|
+
j,
|
|
394
|
+
base,
|
|
395
|
+
element,
|
|
396
|
+
propName,
|
|
397
|
+
})
|
|
398
|
+
);
|
|
408
399
|
}
|
|
409
400
|
|
|
410
401
|
// not replacing newlines (which \s does)
|
|
@@ -412,262 +403,235 @@ const spacesAndTabs: RegExp = /[ \t]{2,}/g;
|
|
|
412
403
|
const lineStartWithSpaces: RegExp = /^[ \t]*/gm;
|
|
413
404
|
|
|
414
405
|
function clean(value: string): string {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
406
|
+
return (
|
|
407
|
+
value
|
|
408
|
+
.replace(spacesAndTabs, ' ')
|
|
409
|
+
.replace(lineStartWithSpaces, '')
|
|
410
|
+
// using .trim() to clear the any newlines before the first text and after last text
|
|
411
|
+
.trim()
|
|
412
|
+
);
|
|
422
413
|
}
|
|
423
414
|
|
|
424
|
-
export function addCommentBeforeJSX(
|
|
425
|
-
|
|
426
|
-
element: NodePath,
|
|
427
|
-
message: string,
|
|
428
|
-
) {
|
|
429
|
-
const content: string = `\nTODO: (from codemod) ${clean(message)}\n`;
|
|
415
|
+
export function addCommentBeforeJSX(j: core.JSCodeshift, element: NodePath, message: string) {
|
|
416
|
+
const content: string = `\nTODO: (from codemod) ${clean(message)}\n`;
|
|
430
417
|
|
|
431
|
-
|
|
418
|
+
const comment = j.commentBlock(content, false, true);
|
|
432
419
|
|
|
433
|
-
|
|
420
|
+
element.insertBefore(comment);
|
|
434
421
|
}
|
|
435
422
|
|
|
436
423
|
export function addCommentToStartOfFile({
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
424
|
+
j,
|
|
425
|
+
base,
|
|
426
|
+
message,
|
|
440
427
|
}: {
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
428
|
+
j: core.JSCodeshift;
|
|
429
|
+
base: Collection<Node>;
|
|
430
|
+
message: string;
|
|
444
431
|
}) {
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
432
|
+
addCommentBefore({
|
|
433
|
+
j,
|
|
434
|
+
target: base.find(j.Program),
|
|
435
|
+
message,
|
|
436
|
+
});
|
|
450
437
|
}
|
|
451
438
|
|
|
452
439
|
export function addCommentBefore({
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
440
|
+
j,
|
|
441
|
+
target,
|
|
442
|
+
message,
|
|
456
443
|
}: {
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
| Collection<Program>
|
|
461
|
-
| Collection<ImportDeclaration>;
|
|
462
|
-
message: string;
|
|
444
|
+
j: core.JSCodeshift;
|
|
445
|
+
target: Collection<Node> | Collection<Program> | Collection<ImportDeclaration>;
|
|
446
|
+
message: string;
|
|
463
447
|
}) {
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
448
|
+
const content: string = ` TODO: (from codemod) ${clean(message)} `;
|
|
449
|
+
target.forEach((path) => {
|
|
450
|
+
path.value.comments = path.value.comments || [];
|
|
467
451
|
|
|
468
|
-
|
|
469
|
-
(comment) => comment.value === content,
|
|
470
|
-
);
|
|
452
|
+
const exists = path.value.comments.find((comment) => comment.value === content);
|
|
471
453
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
454
|
+
// avoiding duplicates of the same comment
|
|
455
|
+
if (exists) {
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
476
458
|
|
|
477
|
-
|
|
478
|
-
|
|
459
|
+
path.value.comments.push(j.commentBlock(content));
|
|
460
|
+
});
|
|
479
461
|
}
|
|
480
462
|
|
|
481
463
|
export function shiftDefaultImport({
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
464
|
+
j,
|
|
465
|
+
base,
|
|
466
|
+
defaultName,
|
|
467
|
+
oldPackagePath,
|
|
468
|
+
newPackagePath,
|
|
487
469
|
}: {
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
470
|
+
j: core.JSCodeshift;
|
|
471
|
+
base: Collection<any>;
|
|
472
|
+
defaultName: string;
|
|
473
|
+
oldPackagePath: string;
|
|
474
|
+
newPackagePath: string;
|
|
493
475
|
}) {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
476
|
+
tryCreateImport({
|
|
477
|
+
j,
|
|
478
|
+
base,
|
|
479
|
+
relativeToPackage: oldPackagePath,
|
|
480
|
+
packageName: newPackagePath,
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
addToImport({
|
|
484
|
+
j,
|
|
485
|
+
base,
|
|
486
|
+
importSpecifier: j.importDefaultSpecifier(j.identifier(defaultName)),
|
|
487
|
+
packageName: newPackagePath,
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
// removing old default specifier
|
|
491
|
+
base
|
|
492
|
+
.find(j.ImportDeclaration)
|
|
493
|
+
.filter((path) => path.node.source.value === oldPackagePath)
|
|
494
|
+
.find(j.ImportDefaultSpecifier)
|
|
495
|
+
.remove();
|
|
514
496
|
}
|
|
515
497
|
|
|
516
498
|
type Option =
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
499
|
+
| {
|
|
500
|
+
type: 'change-name';
|
|
501
|
+
oldName: string;
|
|
502
|
+
newName: string;
|
|
503
|
+
fallbackNameAlias: string;
|
|
504
|
+
}
|
|
505
|
+
| {
|
|
506
|
+
type: 'keep-name';
|
|
507
|
+
name: string;
|
|
508
|
+
behaviour: 'move-to-default-import' | 'keep-as-named-import';
|
|
509
|
+
};
|
|
528
510
|
|
|
529
511
|
// try to avoid this one if you can. I'm not super happy with it
|
|
530
512
|
export function changeImportFor({
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
513
|
+
j,
|
|
514
|
+
base,
|
|
515
|
+
option,
|
|
516
|
+
oldPackagePath,
|
|
517
|
+
newPackagePath,
|
|
536
518
|
}: {
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
519
|
+
j: core.JSCodeshift;
|
|
520
|
+
base: Collection<any>;
|
|
521
|
+
option: Option;
|
|
522
|
+
oldPackagePath: string;
|
|
523
|
+
newPackagePath: string;
|
|
542
524
|
}) {
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
})();
|
|
656
|
-
|
|
657
|
-
addToImport({
|
|
658
|
-
j,
|
|
659
|
-
base,
|
|
660
|
-
importSpecifier: newSpecifier,
|
|
661
|
-
packageName: newPackagePath,
|
|
662
|
-
});
|
|
663
|
-
|
|
664
|
-
// Change usages of old type in file
|
|
665
|
-
base
|
|
666
|
-
.find(j.Identifier)
|
|
667
|
-
.filter((identifier) => identifier.value.name === option.oldName)
|
|
668
|
-
.replaceWith(
|
|
669
|
-
j.identifier(
|
|
670
|
-
isNewNameAvailable ? option.newName : option.fallbackNameAlias,
|
|
671
|
-
),
|
|
672
|
-
);
|
|
525
|
+
const currentName: string = option.type === 'change-name' ? option.oldName : option.name;
|
|
526
|
+
const desiredName: string = option.type === 'change-name' ? option.newName : option.name;
|
|
527
|
+
|
|
528
|
+
const isUsingName: boolean =
|
|
529
|
+
base
|
|
530
|
+
.find(j.ImportDeclaration)
|
|
531
|
+
.filter((path) => path.node.source.value === oldPackagePath)
|
|
532
|
+
.find(j.ImportSpecifier)
|
|
533
|
+
.find(j.Identifier)
|
|
534
|
+
.filter((identifier) => identifier.value.name === currentName).length > 0;
|
|
535
|
+
|
|
536
|
+
if (!isUsingName) {
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
const existingAlias: Nullable<string> =
|
|
541
|
+
base
|
|
542
|
+
.find(j.ImportDeclaration)
|
|
543
|
+
.filter((path) => path.node.source.value === oldPackagePath)
|
|
544
|
+
.find(j.ImportSpecifier)
|
|
545
|
+
.nodes()
|
|
546
|
+
.map((specifier): Nullable<string> => {
|
|
547
|
+
if (specifier.imported.name !== currentName) {
|
|
548
|
+
return null;
|
|
549
|
+
}
|
|
550
|
+
// If aliased: return the alias
|
|
551
|
+
if (specifier.local && specifier.local.name !== currentName) {
|
|
552
|
+
return specifier.local.name;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
return null;
|
|
556
|
+
})
|
|
557
|
+
.filter(Boolean)[0] || null;
|
|
558
|
+
|
|
559
|
+
base
|
|
560
|
+
.find(j.ImportDeclaration)
|
|
561
|
+
.filter((path) => path.node.source.value === oldPackagePath)
|
|
562
|
+
.find(j.ImportSpecifier)
|
|
563
|
+
.find(j.Identifier)
|
|
564
|
+
.filter((identifier) => {
|
|
565
|
+
if (identifier.value.name === currentName) {
|
|
566
|
+
return true;
|
|
567
|
+
}
|
|
568
|
+
if (identifier.value.name === existingAlias) {
|
|
569
|
+
return true;
|
|
570
|
+
}
|
|
571
|
+
return false;
|
|
572
|
+
})
|
|
573
|
+
.remove();
|
|
574
|
+
|
|
575
|
+
// Check to see if need to create new package path
|
|
576
|
+
// Try create an import declaration just before the old import
|
|
577
|
+
tryCreateImport({
|
|
578
|
+
j,
|
|
579
|
+
base,
|
|
580
|
+
relativeToPackage: oldPackagePath,
|
|
581
|
+
packageName: newPackagePath,
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
if (option.type === 'keep-name') {
|
|
585
|
+
const newSpecifier: ImportSpecifier | ImportDefaultSpecifier = (() => {
|
|
586
|
+
if (option.behaviour === 'keep-as-named-import') {
|
|
587
|
+
if (existingAlias) {
|
|
588
|
+
return j.importSpecifier(j.identifier(desiredName), j.identifier(existingAlias));
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
return j.importSpecifier(j.identifier(desiredName));
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// moving to default specifier
|
|
595
|
+
return j.importDefaultSpecifier(j.identifier(existingAlias || desiredName));
|
|
596
|
+
})();
|
|
597
|
+
|
|
598
|
+
// We don't need to touch anything else in the file
|
|
599
|
+
|
|
600
|
+
addToImport({
|
|
601
|
+
j,
|
|
602
|
+
base,
|
|
603
|
+
importSpecifier: newSpecifier,
|
|
604
|
+
packageName: newPackagePath,
|
|
605
|
+
});
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
const isNewNameAvailable: boolean =
|
|
610
|
+
base.find(j.Identifier).filter((i) => i.value.name === option.newName).length === 0;
|
|
611
|
+
|
|
612
|
+
const newSpecifier: ImportSpecifier = (() => {
|
|
613
|
+
if (existingAlias) {
|
|
614
|
+
return j.importSpecifier(j.identifier(desiredName), j.identifier(existingAlias));
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
if (isNewNameAvailable) {
|
|
618
|
+
return j.importSpecifier(j.identifier(desiredName));
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// new type name is not available: need to use a new alias
|
|
622
|
+
return j.importSpecifier(j.identifier(desiredName), j.identifier(option.fallbackNameAlias));
|
|
623
|
+
})();
|
|
624
|
+
|
|
625
|
+
addToImport({
|
|
626
|
+
j,
|
|
627
|
+
base,
|
|
628
|
+
importSpecifier: newSpecifier,
|
|
629
|
+
packageName: newPackagePath,
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
// Change usages of old type in file
|
|
633
|
+
base
|
|
634
|
+
.find(j.Identifier)
|
|
635
|
+
.filter((identifier) => identifier.value.name === option.oldName)
|
|
636
|
+
.replaceWith(j.identifier(isNewNameAvailable ? option.newName : option.fallbackNameAlias));
|
|
673
637
|
}
|