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