@atlaskit/button 16.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 +1485 -0
- package/LICENSE +13 -0
- package/README.md +13 -0
- package/__perf__/button.tsx +19 -0
- package/__perf__/custom.tsx +19 -0
- package/__perf__/customised.tsx +11 -0
- package/__perf__/default.tsx +5 -0
- package/__perf__/loading.tsx +5 -0
- package/__perf__/utils/example-runner.tsx +48 -0
- package/__perf__/utils/interaction-tasks.tsx +98 -0
- package/button-group/package.json +7 -0
- package/codemods/15.0.0-lite-mode.ts +49 -0
- package/codemods/15.1.1-data-testid.ts +173 -0
- package/codemods/__tests__/15.0.0-lite-mode/optimistic.ts +646 -0
- package/codemods/__tests__/15.0.0-lite-mode/safe.ts +223 -0
- package/codemods/__tests__/15.0.0-lite-mode/shared.ts +257 -0
- package/codemods/__tests__/15.1.1-data-testid/rename-data-testid.ts +186 -0
- package/codemods/__tests__/_framework.ts +47 -0
- package/codemods/helpers/15.0.0-runner.ts +169 -0
- package/codemods/helpers/helpers-generic.ts +662 -0
- package/codemods/optimistic-15.0.0-lite-mode.ts +279 -0
- package/codemods/readme.md +1 -0
- package/custom-theme-button/package.json +7 -0
- package/dist/cjs/button-group.js +50 -0
- package/dist/cjs/button.js +104 -0
- package/dist/cjs/custom-theme-button/custom-theme-button-types.js +5 -0
- package/dist/cjs/custom-theme-button/custom-theme-button.js +229 -0
- package/dist/cjs/custom-theme-button/index.js +23 -0
- package/dist/cjs/custom-theme-button/theme.js +108 -0
- package/dist/cjs/entry-points/button-group.js +15 -0
- package/dist/cjs/entry-points/custom-theme-button.js +25 -0
- package/dist/cjs/entry-points/loading-button.js +15 -0
- package/dist/cjs/entry-points/standard-button.js +15 -0
- package/dist/cjs/entry-points/types.js +5 -0
- package/dist/cjs/index.js +51 -0
- package/dist/cjs/loading-button.js +34 -0
- package/dist/cjs/shared/block-events.js +44 -0
- package/dist/cjs/shared/button-base.js +158 -0
- package/dist/cjs/shared/colors.js +409 -0
- package/dist/cjs/shared/css.js +265 -0
- package/dist/cjs/shared/get-is-only-single-icon.js +26 -0
- package/dist/cjs/shared/loading-spinner.js +45 -0
- package/dist/cjs/types.js +5 -0
- package/dist/cjs/version.json +5 -0
- package/dist/es2019/button-group.js +36 -0
- package/dist/es2019/button.js +69 -0
- package/dist/es2019/custom-theme-button/custom-theme-button-types.js +1 -0
- package/dist/es2019/custom-theme-button/custom-theme-button.js +164 -0
- package/dist/es2019/custom-theme-button/index.js +2 -0
- package/dist/es2019/custom-theme-button/theme.js +81 -0
- package/dist/es2019/entry-points/button-group.js +1 -0
- package/dist/es2019/entry-points/custom-theme-button.js +1 -0
- package/dist/es2019/entry-points/loading-button.js +1 -0
- package/dist/es2019/entry-points/standard-button.js +1 -0
- package/dist/es2019/entry-points/types.js +1 -0
- package/dist/es2019/index.js +6 -0
- package/dist/es2019/loading-button.js +17 -0
- package/dist/es2019/shared/block-events.js +37 -0
- package/dist/es2019/shared/button-base.js +127 -0
- package/dist/es2019/shared/colors.js +393 -0
- package/dist/es2019/shared/css.js +249 -0
- package/dist/es2019/shared/get-is-only-single-icon.js +19 -0
- package/dist/es2019/shared/loading-spinner.js +33 -0
- package/dist/es2019/types.js +1 -0
- package/dist/es2019/version.json +5 -0
- package/dist/esm/button-group.js +35 -0
- package/dist/esm/button.js +79 -0
- package/dist/esm/custom-theme-button/custom-theme-button-types.js +1 -0
- package/dist/esm/custom-theme-button/custom-theme-button.js +203 -0
- package/dist/esm/custom-theme-button/index.js +2 -0
- package/dist/esm/custom-theme-button/theme.js +90 -0
- package/dist/esm/entry-points/button-group.js +1 -0
- package/dist/esm/entry-points/custom-theme-button.js +1 -0
- package/dist/esm/entry-points/loading-button.js +1 -0
- package/dist/esm/entry-points/standard-button.js +1 -0
- package/dist/esm/entry-points/types.js +1 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/loading-button.js +19 -0
- package/dist/esm/shared/block-events.js +36 -0
- package/dist/esm/shared/button-base.js +135 -0
- package/dist/esm/shared/colors.js +393 -0
- package/dist/esm/shared/css.js +245 -0
- package/dist/esm/shared/get-is-only-single-icon.js +19 -0
- package/dist/esm/shared/loading-spinner.js +35 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/version.json +5 -0
- package/dist/types/button-group.d.ts +18 -0
- package/dist/types/button.d.ts +8 -0
- package/dist/types/custom-theme-button/custom-theme-button-types.d.ts +21 -0
- package/dist/types/custom-theme-button/custom-theme-button.d.ts +6 -0
- package/dist/types/custom-theme-button/index.d.ts +2 -0
- package/dist/types/custom-theme-button/theme.d.ts +21 -0
- package/dist/types/entry-points/button-group.d.ts +1 -0
- package/dist/types/entry-points/custom-theme-button.d.ts +2 -0
- package/dist/types/entry-points/loading-button.d.ts +2 -0
- package/dist/types/entry-points/standard-button.d.ts +2 -0
- package/dist/types/entry-points/types.d.ts +4 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/loading-button.d.ts +11 -0
- package/dist/types/shared/block-events.d.ts +3 -0
- package/dist/types/shared/button-base.d.ts +10 -0
- package/dist/types/shared/colors.d.ts +31 -0
- package/dist/types/shared/css.d.ts +22 -0
- package/dist/types/shared/get-is-only-single-icon.d.ts +2 -0
- package/dist/types/shared/loading-spinner.d.ts +4 -0
- package/dist/types/types.d.ts +51 -0
- package/extract-react-types/custom-theme-button-props.tsx +7 -0
- package/extract-react-types/loading-button-props.tsx +5 -0
- package/extract-react-types/shared-props.tsx +5 -0
- package/loading-button/package.json +7 -0
- package/package.json +83 -0
- package/standard-button/package.json +7 -0
- package/types/package.json +7 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
jest.autoMockOff();
|
|
2
|
+
|
|
3
|
+
import transformer from '../../15.1.1-data-testid';
|
|
4
|
+
import { check } from '../_framework';
|
|
5
|
+
|
|
6
|
+
check({
|
|
7
|
+
transformer,
|
|
8
|
+
it: 'should rename data-testid to testId (default import)',
|
|
9
|
+
original: `
|
|
10
|
+
import DSButton from '@atlaskit/button';
|
|
11
|
+
|
|
12
|
+
function App() {
|
|
13
|
+
return <DSButton data-testid="my-testid">click me</DSButton>;
|
|
14
|
+
}
|
|
15
|
+
`,
|
|
16
|
+
expected: `
|
|
17
|
+
import DSButton from '@atlaskit/button';
|
|
18
|
+
|
|
19
|
+
function App() {
|
|
20
|
+
return <DSButton testId="my-testid">click me</DSButton>;
|
|
21
|
+
}
|
|
22
|
+
`,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
check({
|
|
26
|
+
transformer,
|
|
27
|
+
it: 'should rename data-testid to testId (standard button)',
|
|
28
|
+
original: `
|
|
29
|
+
import Button from '@atlaskit/button/standard-button';
|
|
30
|
+
|
|
31
|
+
function App() {
|
|
32
|
+
return <Button data-testid="my-testid">click me</Button>;
|
|
33
|
+
}
|
|
34
|
+
`,
|
|
35
|
+
expected: `
|
|
36
|
+
import Button from '@atlaskit/button/standard-button';
|
|
37
|
+
|
|
38
|
+
function App() {
|
|
39
|
+
return <Button testId="my-testid">click me</Button>;
|
|
40
|
+
}
|
|
41
|
+
`,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
check({
|
|
45
|
+
transformer,
|
|
46
|
+
it: 'should rename data-testid to testId (loading button)',
|
|
47
|
+
original: `
|
|
48
|
+
import Button from '@atlaskit/button/loading-button';
|
|
49
|
+
|
|
50
|
+
function App() {
|
|
51
|
+
return <Button data-testid="my-testid">click me</Button>;
|
|
52
|
+
}
|
|
53
|
+
`,
|
|
54
|
+
expected: `
|
|
55
|
+
import Button from '@atlaskit/button/loading-button';
|
|
56
|
+
|
|
57
|
+
function App() {
|
|
58
|
+
return <Button testId="my-testid">click me</Button>;
|
|
59
|
+
}
|
|
60
|
+
`,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
check({
|
|
64
|
+
transformer,
|
|
65
|
+
it: 'should rename data-testid to testId (custom theme button)',
|
|
66
|
+
original: `
|
|
67
|
+
import Button from '@atlaskit/button/custom-theme-button';
|
|
68
|
+
|
|
69
|
+
function App() {
|
|
70
|
+
return <Button data-testid="my-testid">click me</Button>;
|
|
71
|
+
}
|
|
72
|
+
`,
|
|
73
|
+
expected: `
|
|
74
|
+
import Button from '@atlaskit/button/custom-theme-button';
|
|
75
|
+
|
|
76
|
+
function App() {
|
|
77
|
+
return <Button testId="my-testid">click me</Button>;
|
|
78
|
+
}
|
|
79
|
+
`,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
check({
|
|
83
|
+
transformer,
|
|
84
|
+
it: 'should rename data-testid to testId (named imports)',
|
|
85
|
+
original: `
|
|
86
|
+
import { StandardButton, LoadingButton, CustomThemeButton } from '@atlaskit/button';
|
|
87
|
+
|
|
88
|
+
function App() {
|
|
89
|
+
return <>
|
|
90
|
+
<StandardButton data-testid="my-testid">click me</StandardButton>
|
|
91
|
+
<LoadingButton data-testid="my-testid">click me</LoadingButton>
|
|
92
|
+
<CustomThemeButton data-testid="my-testid">click me</CustomThemeButton>
|
|
93
|
+
</>;
|
|
94
|
+
}
|
|
95
|
+
`,
|
|
96
|
+
expected: `
|
|
97
|
+
import { StandardButton, LoadingButton, CustomThemeButton } from '@atlaskit/button';
|
|
98
|
+
|
|
99
|
+
function App() {
|
|
100
|
+
return <>
|
|
101
|
+
<StandardButton testId="my-testid">click me</StandardButton>
|
|
102
|
+
<LoadingButton testId="my-testid">click me</LoadingButton>
|
|
103
|
+
<CustomThemeButton testId="my-testid">click me</CustomThemeButton>
|
|
104
|
+
</>;
|
|
105
|
+
}
|
|
106
|
+
`,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
check({
|
|
110
|
+
transformer,
|
|
111
|
+
it: 'should rename data-testid to testId (named imports with alias)',
|
|
112
|
+
original: `
|
|
113
|
+
import { StandardButton as SB, LoadingButton as LB, CustomThemeButton as CTB } from '@atlaskit/button';
|
|
114
|
+
|
|
115
|
+
function App() {
|
|
116
|
+
return <>
|
|
117
|
+
<SB data-testid="my-testid">click me</SB>
|
|
118
|
+
<LB data-testid="my-testid">click me</LB>
|
|
119
|
+
<CTB data-testid="my-testid">click me</CTB>
|
|
120
|
+
</>;
|
|
121
|
+
}
|
|
122
|
+
`,
|
|
123
|
+
expected: `
|
|
124
|
+
import { StandardButton as SB, LoadingButton as LB, CustomThemeButton as CTB } from '@atlaskit/button';
|
|
125
|
+
|
|
126
|
+
function App() {
|
|
127
|
+
return <>
|
|
128
|
+
<SB testId="my-testid">click me</SB>
|
|
129
|
+
<LB testId="my-testid">click me</LB>
|
|
130
|
+
<CTB testId="my-testid">click me</CTB>
|
|
131
|
+
</>;
|
|
132
|
+
}
|
|
133
|
+
`,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
check({
|
|
137
|
+
transformer,
|
|
138
|
+
it:
|
|
139
|
+
'should add a warning when both the testId and data-testid props are being used',
|
|
140
|
+
original: `
|
|
141
|
+
import StandardButton from '@atlaskit/button';
|
|
142
|
+
|
|
143
|
+
function App() {
|
|
144
|
+
return <StandardButton testId="oh-my" data-testid="oh-dear">Click me</StandardButton>
|
|
145
|
+
}
|
|
146
|
+
`,
|
|
147
|
+
expected: `
|
|
148
|
+
/* TODO: (from codemod) Cannot rename data-testid to testId on StandardButton.
|
|
149
|
+
A StandardButton was detected with both data-testid and testId props.
|
|
150
|
+
Please remove the data-testid prop and check your tests */
|
|
151
|
+
import StandardButton from '@atlaskit/button';
|
|
152
|
+
|
|
153
|
+
function App() {
|
|
154
|
+
return <StandardButton testId="oh-my" data-testid="oh-dear">Click me</StandardButton>
|
|
155
|
+
}
|
|
156
|
+
`,
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
check({
|
|
160
|
+
transformer,
|
|
161
|
+
it: 'should not touch unrelated testids',
|
|
162
|
+
original: `
|
|
163
|
+
import DSButton from '@atlaskit/button';
|
|
164
|
+
import Something from '@atlaskit/foobar';
|
|
165
|
+
|
|
166
|
+
function App() {
|
|
167
|
+
return <>
|
|
168
|
+
<DSButton data-testid="my-testid">
|
|
169
|
+
<Something data-testid="hello">click me</Something>
|
|
170
|
+
</DSButton>
|
|
171
|
+
</>;
|
|
172
|
+
}
|
|
173
|
+
`,
|
|
174
|
+
expected: `
|
|
175
|
+
import DSButton from '@atlaskit/button';
|
|
176
|
+
import Something from '@atlaskit/foobar';
|
|
177
|
+
|
|
178
|
+
function App() {
|
|
179
|
+
return <>
|
|
180
|
+
<DSButton testId="my-testid">
|
|
181
|
+
<Something data-testid="hello">click me</Something>
|
|
182
|
+
</DSButton>
|
|
183
|
+
</>;
|
|
184
|
+
}
|
|
185
|
+
`,
|
|
186
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { API, FileInfo, Options } from 'jscodeshift';
|
|
2
|
+
|
|
3
|
+
const applyTransform = require('jscodeshift/dist/testUtils').applyTransform;
|
|
4
|
+
|
|
5
|
+
type Transformer = (file: FileInfo, jscodeshift: API, options: Options) => void;
|
|
6
|
+
|
|
7
|
+
type TestArgs = {
|
|
8
|
+
it: string;
|
|
9
|
+
original: string;
|
|
10
|
+
expected: string;
|
|
11
|
+
transformer: Transformer;
|
|
12
|
+
mode?: 'only' | 'skip' | 'standard';
|
|
13
|
+
before?: () => void;
|
|
14
|
+
after?: () => void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function noop() {}
|
|
18
|
+
|
|
19
|
+
export function check({
|
|
20
|
+
it: name,
|
|
21
|
+
original,
|
|
22
|
+
expected,
|
|
23
|
+
transformer,
|
|
24
|
+
before = noop,
|
|
25
|
+
after = noop,
|
|
26
|
+
mode = 'standard',
|
|
27
|
+
}: TestArgs) {
|
|
28
|
+
const run = mode === 'only' ? it.only : mode === 'skip' ? it.skip : it;
|
|
29
|
+
|
|
30
|
+
run(name, () => {
|
|
31
|
+
before();
|
|
32
|
+
try {
|
|
33
|
+
const output: string = applyTransform(
|
|
34
|
+
{ default: transformer, parser: 'tsx' },
|
|
35
|
+
{},
|
|
36
|
+
{ source: original },
|
|
37
|
+
);
|
|
38
|
+
expect(output).toBe(expected.trim());
|
|
39
|
+
} catch (e) {
|
|
40
|
+
// a failed assertion will throw
|
|
41
|
+
after();
|
|
42
|
+
throw e;
|
|
43
|
+
}
|
|
44
|
+
// will only be hit if we don't throw
|
|
45
|
+
after();
|
|
46
|
+
});
|
|
47
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { NodePath } from 'ast-types/lib/node-path';
|
|
2
|
+
import core, { FileInfo, JSXElement } from 'jscodeshift';
|
|
3
|
+
import { Collection } from 'jscodeshift/src/Collection';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
addToImport,
|
|
7
|
+
changeImportFor,
|
|
8
|
+
hasImportDeclaration,
|
|
9
|
+
removeImport,
|
|
10
|
+
tryCreateImport,
|
|
11
|
+
} from './helpers-generic';
|
|
12
|
+
|
|
13
|
+
export function convertButtonType({
|
|
14
|
+
j,
|
|
15
|
+
base,
|
|
16
|
+
elements,
|
|
17
|
+
name,
|
|
18
|
+
newPackageName,
|
|
19
|
+
}: {
|
|
20
|
+
j: core.JSCodeshift;
|
|
21
|
+
base: Collection<any>;
|
|
22
|
+
elements: NodePath<JSXElement, JSXElement>[];
|
|
23
|
+
name: string;
|
|
24
|
+
newPackageName: string;
|
|
25
|
+
}) {
|
|
26
|
+
// Don't need to do anything if there are no elements of this type
|
|
27
|
+
if (!elements.length) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
tryCreateImport({
|
|
32
|
+
j,
|
|
33
|
+
base,
|
|
34
|
+
relativeToPackage: '@atlaskit/button',
|
|
35
|
+
packageName: newPackageName,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
addToImport({
|
|
39
|
+
j,
|
|
40
|
+
base,
|
|
41
|
+
importSpecifier: j.importDefaultSpecifier(j.identifier(name)),
|
|
42
|
+
packageName: newPackageName,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
elements.forEach((path: NodePath<JSXElement, JSXElement>) => {
|
|
46
|
+
path.replace(
|
|
47
|
+
j.jsxElement(
|
|
48
|
+
j.jsxOpeningElement(
|
|
49
|
+
// name: new!
|
|
50
|
+
j.jsxIdentifier(name),
|
|
51
|
+
// keep the old attributes
|
|
52
|
+
path.value.openingElement.attributes,
|
|
53
|
+
// self closing
|
|
54
|
+
path.value.openingElement.selfClosing,
|
|
55
|
+
),
|
|
56
|
+
// Only create a closing element if the original had one
|
|
57
|
+
// <Button /> => <Button /> (rather than <Button></Button>)
|
|
58
|
+
path.value.closingElement
|
|
59
|
+
? j.jsxClosingElement(j.jsxIdentifier(name))
|
|
60
|
+
: null,
|
|
61
|
+
path.value.children,
|
|
62
|
+
),
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function changeType({
|
|
68
|
+
j,
|
|
69
|
+
base,
|
|
70
|
+
oldName,
|
|
71
|
+
newName,
|
|
72
|
+
fallbackNameAlias,
|
|
73
|
+
}: {
|
|
74
|
+
j: core.JSCodeshift;
|
|
75
|
+
base: Collection<any>;
|
|
76
|
+
oldName: string;
|
|
77
|
+
newName: string;
|
|
78
|
+
fallbackNameAlias: string;
|
|
79
|
+
}) {
|
|
80
|
+
changeImportFor({
|
|
81
|
+
j,
|
|
82
|
+
base,
|
|
83
|
+
option: {
|
|
84
|
+
type: 'change-name',
|
|
85
|
+
oldName,
|
|
86
|
+
newName,
|
|
87
|
+
fallbackNameAlias,
|
|
88
|
+
},
|
|
89
|
+
oldPackagePath: '@atlaskit/button',
|
|
90
|
+
newPackagePath: '@atlaskit/button/types',
|
|
91
|
+
});
|
|
92
|
+
changeImportFor({
|
|
93
|
+
j,
|
|
94
|
+
base,
|
|
95
|
+
option: {
|
|
96
|
+
type: 'change-name',
|
|
97
|
+
oldName,
|
|
98
|
+
newName,
|
|
99
|
+
fallbackNameAlias,
|
|
100
|
+
},
|
|
101
|
+
oldPackagePath: '@atlaskit/button/types',
|
|
102
|
+
newPackagePath: '@atlaskit/button/types',
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function transformButton({
|
|
107
|
+
j,
|
|
108
|
+
file,
|
|
109
|
+
custom: fn,
|
|
110
|
+
}: {
|
|
111
|
+
j: core.JSCodeshift;
|
|
112
|
+
file: FileInfo;
|
|
113
|
+
custom: (base: Collection<any>) => void;
|
|
114
|
+
}) {
|
|
115
|
+
const base: Collection<any> = j(file.source);
|
|
116
|
+
|
|
117
|
+
// Exit early if not relevant
|
|
118
|
+
// We are doing this so we don't touch the formatting of unrelated files
|
|
119
|
+
const willChange: boolean =
|
|
120
|
+
hasImportDeclaration(j, file.source, '@atlaskit/button') ||
|
|
121
|
+
hasImportDeclaration(j, file.source, '@atlaskit/button/types');
|
|
122
|
+
|
|
123
|
+
if (!willChange) {
|
|
124
|
+
return file.source;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
changeType({
|
|
128
|
+
j,
|
|
129
|
+
base,
|
|
130
|
+
oldName: 'ButtonAppearances',
|
|
131
|
+
newName: 'Appearance',
|
|
132
|
+
fallbackNameAlias: 'DSButtonAppearance',
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
changeImportFor({
|
|
136
|
+
j,
|
|
137
|
+
base,
|
|
138
|
+
// Not changing the name
|
|
139
|
+
option: {
|
|
140
|
+
type: 'keep-name',
|
|
141
|
+
name: 'Theme',
|
|
142
|
+
behaviour: 'keep-as-named-import',
|
|
143
|
+
},
|
|
144
|
+
oldPackagePath: '@atlaskit/button',
|
|
145
|
+
newPackagePath: '@atlaskit/button/custom-theme-button',
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
changeImportFor({
|
|
149
|
+
j,
|
|
150
|
+
base,
|
|
151
|
+
option: {
|
|
152
|
+
type: 'keep-name',
|
|
153
|
+
name: 'ButtonGroup',
|
|
154
|
+
behaviour: 'move-to-default-import',
|
|
155
|
+
},
|
|
156
|
+
oldPackagePath: '@atlaskit/button',
|
|
157
|
+
newPackagePath: '@atlaskit/button/button-group',
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
fn(base);
|
|
161
|
+
|
|
162
|
+
removeImport({
|
|
163
|
+
j,
|
|
164
|
+
base,
|
|
165
|
+
packageName: '@atlaskit/button',
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
return base.toSource({ quote: 'single' });
|
|
169
|
+
}
|
|
@@ -0,0 +1,662 @@
|
|
|
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 addCommentToStartOfFile({
|
|
424
|
+
j,
|
|
425
|
+
base,
|
|
426
|
+
message,
|
|
427
|
+
}: {
|
|
428
|
+
j: core.JSCodeshift;
|
|
429
|
+
base: Collection<Node>;
|
|
430
|
+
message: string;
|
|
431
|
+
}) {
|
|
432
|
+
addCommentBefore({
|
|
433
|
+
j,
|
|
434
|
+
target: base.find(j.Program),
|
|
435
|
+
message,
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export function addCommentBefore({
|
|
440
|
+
j,
|
|
441
|
+
target,
|
|
442
|
+
message,
|
|
443
|
+
}: {
|
|
444
|
+
j: core.JSCodeshift;
|
|
445
|
+
target:
|
|
446
|
+
| Collection<Node>
|
|
447
|
+
| Collection<Program>
|
|
448
|
+
| Collection<ImportDeclaration>;
|
|
449
|
+
message: string;
|
|
450
|
+
}) {
|
|
451
|
+
const content: string = ` TODO: (from codemod) ${clean(message)} `;
|
|
452
|
+
target.forEach((path) => {
|
|
453
|
+
path.value.comments = path.value.comments || [];
|
|
454
|
+
|
|
455
|
+
const exists = path.value.comments.find(
|
|
456
|
+
(comment) => comment.value === content,
|
|
457
|
+
);
|
|
458
|
+
|
|
459
|
+
// avoiding duplicates of the same comment
|
|
460
|
+
if (exists) {
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
path.value.comments.push(j.commentBlock(content));
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
export function shiftDefaultImport({
|
|
469
|
+
j,
|
|
470
|
+
base,
|
|
471
|
+
defaultName,
|
|
472
|
+
oldPackagePath,
|
|
473
|
+
newPackagePath,
|
|
474
|
+
}: {
|
|
475
|
+
j: core.JSCodeshift;
|
|
476
|
+
base: Collection<any>;
|
|
477
|
+
defaultName: string;
|
|
478
|
+
oldPackagePath: string;
|
|
479
|
+
newPackagePath: string;
|
|
480
|
+
}) {
|
|
481
|
+
tryCreateImport({
|
|
482
|
+
j,
|
|
483
|
+
base,
|
|
484
|
+
relativeToPackage: oldPackagePath,
|
|
485
|
+
packageName: newPackagePath,
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
addToImport({
|
|
489
|
+
j,
|
|
490
|
+
base,
|
|
491
|
+
importSpecifier: j.importDefaultSpecifier(j.identifier(defaultName)),
|
|
492
|
+
packageName: newPackagePath,
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
// removing old default specifier
|
|
496
|
+
base
|
|
497
|
+
.find(j.ImportDeclaration)
|
|
498
|
+
.filter((path) => path.node.source.value === oldPackagePath)
|
|
499
|
+
.find(j.ImportDefaultSpecifier)
|
|
500
|
+
.remove();
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
type Option =
|
|
504
|
+
| {
|
|
505
|
+
type: 'change-name';
|
|
506
|
+
oldName: string;
|
|
507
|
+
newName: string;
|
|
508
|
+
fallbackNameAlias: string;
|
|
509
|
+
}
|
|
510
|
+
| {
|
|
511
|
+
type: 'keep-name';
|
|
512
|
+
name: string;
|
|
513
|
+
behaviour: 'move-to-default-import' | 'keep-as-named-import';
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
// try to avoid this one if you can. I'm not super happy with it
|
|
517
|
+
export function changeImportFor({
|
|
518
|
+
j,
|
|
519
|
+
base,
|
|
520
|
+
option,
|
|
521
|
+
oldPackagePath,
|
|
522
|
+
newPackagePath,
|
|
523
|
+
}: {
|
|
524
|
+
j: core.JSCodeshift;
|
|
525
|
+
base: Collection<any>;
|
|
526
|
+
option: Option;
|
|
527
|
+
oldPackagePath: string;
|
|
528
|
+
newPackagePath: string;
|
|
529
|
+
}) {
|
|
530
|
+
const currentName: string =
|
|
531
|
+
option.type === 'change-name' ? option.oldName : option.name;
|
|
532
|
+
const desiredName: string =
|
|
533
|
+
option.type === 'change-name' ? option.newName : option.name;
|
|
534
|
+
|
|
535
|
+
const isUsingName: boolean =
|
|
536
|
+
base
|
|
537
|
+
.find(j.ImportDeclaration)
|
|
538
|
+
.filter((path) => path.node.source.value === oldPackagePath)
|
|
539
|
+
.find(j.ImportSpecifier)
|
|
540
|
+
.find(j.Identifier)
|
|
541
|
+
.filter((identifier) => identifier.value.name === currentName).length > 0;
|
|
542
|
+
|
|
543
|
+
if (!isUsingName) {
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
const existingAlias: Nullable<string> =
|
|
548
|
+
base
|
|
549
|
+
.find(j.ImportDeclaration)
|
|
550
|
+
.filter((path) => path.node.source.value === oldPackagePath)
|
|
551
|
+
.find(j.ImportSpecifier)
|
|
552
|
+
.nodes()
|
|
553
|
+
.map(
|
|
554
|
+
(specifier): Nullable<string> => {
|
|
555
|
+
if (specifier.imported.name !== currentName) {
|
|
556
|
+
return null;
|
|
557
|
+
}
|
|
558
|
+
// If aliased: return the alias
|
|
559
|
+
if (specifier.local && specifier.local.name !== currentName) {
|
|
560
|
+
return specifier.local.name;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
return null;
|
|
564
|
+
},
|
|
565
|
+
)
|
|
566
|
+
.filter(Boolean)[0] || null;
|
|
567
|
+
|
|
568
|
+
base
|
|
569
|
+
.find(j.ImportDeclaration)
|
|
570
|
+
.filter((path) => path.node.source.value === oldPackagePath)
|
|
571
|
+
.find(j.ImportSpecifier)
|
|
572
|
+
.find(j.Identifier)
|
|
573
|
+
.filter((identifier) => {
|
|
574
|
+
if (identifier.value.name === currentName) {
|
|
575
|
+
return true;
|
|
576
|
+
}
|
|
577
|
+
if (identifier.value.name === existingAlias) {
|
|
578
|
+
return true;
|
|
579
|
+
}
|
|
580
|
+
return false;
|
|
581
|
+
})
|
|
582
|
+
.remove();
|
|
583
|
+
|
|
584
|
+
// Check to see if need to create new package path
|
|
585
|
+
// Try create an import declaration just before the old import
|
|
586
|
+
tryCreateImport({
|
|
587
|
+
j,
|
|
588
|
+
base,
|
|
589
|
+
relativeToPackage: oldPackagePath,
|
|
590
|
+
packageName: newPackagePath,
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
if (option.type === 'keep-name') {
|
|
594
|
+
const newSpecifier: ImportSpecifier | ImportDefaultSpecifier = (() => {
|
|
595
|
+
if (option.behaviour === 'keep-as-named-import') {
|
|
596
|
+
if (existingAlias) {
|
|
597
|
+
return j.importSpecifier(
|
|
598
|
+
j.identifier(desiredName),
|
|
599
|
+
j.identifier(existingAlias),
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
return j.importSpecifier(j.identifier(desiredName));
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// moving to default specifier
|
|
607
|
+
return j.importDefaultSpecifier(
|
|
608
|
+
j.identifier(existingAlias || desiredName),
|
|
609
|
+
);
|
|
610
|
+
})();
|
|
611
|
+
|
|
612
|
+
// We don't need to touch anything else in the file
|
|
613
|
+
|
|
614
|
+
addToImport({
|
|
615
|
+
j,
|
|
616
|
+
base,
|
|
617
|
+
importSpecifier: newSpecifier,
|
|
618
|
+
packageName: newPackagePath,
|
|
619
|
+
});
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
const isNewNameAvailable: boolean =
|
|
624
|
+
base.find(j.Identifier).filter((i) => i.value.name === option.newName)
|
|
625
|
+
.length === 0;
|
|
626
|
+
|
|
627
|
+
const newSpecifier: ImportSpecifier = (() => {
|
|
628
|
+
if (existingAlias) {
|
|
629
|
+
return j.importSpecifier(
|
|
630
|
+
j.identifier(desiredName),
|
|
631
|
+
j.identifier(existingAlias),
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
if (isNewNameAvailable) {
|
|
636
|
+
return j.importSpecifier(j.identifier(desiredName));
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// new type name is not available: need to use a new alias
|
|
640
|
+
return j.importSpecifier(
|
|
641
|
+
j.identifier(desiredName),
|
|
642
|
+
j.identifier(option.fallbackNameAlias),
|
|
643
|
+
);
|
|
644
|
+
})();
|
|
645
|
+
|
|
646
|
+
addToImport({
|
|
647
|
+
j,
|
|
648
|
+
base,
|
|
649
|
+
importSpecifier: newSpecifier,
|
|
650
|
+
packageName: newPackagePath,
|
|
651
|
+
});
|
|
652
|
+
|
|
653
|
+
// Change usages of old type in file
|
|
654
|
+
base
|
|
655
|
+
.find(j.Identifier)
|
|
656
|
+
.filter((identifier) => identifier.value.name === option.oldName)
|
|
657
|
+
.replaceWith(
|
|
658
|
+
j.identifier(
|
|
659
|
+
isNewNameAvailable ? option.newName : option.fallbackNameAlias,
|
|
660
|
+
),
|
|
661
|
+
);
|
|
662
|
+
}
|