@sproutsocial/racine 13.3.0 → 13.4.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 +39 -0
- package/bin/racine-codemod.js +37 -6
- package/codemods/__tests__/icon-library.test.js +224 -0
- package/codemods/__tests__/icon-name-substitution.test.js +39 -0
- package/codemods/codemod-docs.js +54 -0
- package/codemods/icon-library.js +315 -0
- package/codemods/icon-name-substitution.js +43 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 13.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- b6f0228d: Adds Icon Library codemod to address upcoming breaking changes
|
|
8
|
+
|
|
9
|
+
**Deprecation Notice**: Upcoming breaking changes to the Icon component and tooling
|
|
10
|
+
|
|
11
|
+
In Q1 2023, we will be making several major changes to the Icon component. Key changes:
|
|
12
|
+
|
|
13
|
+
- Icon assets will be stored in a new package called @sproutsocial/seeds-icons. This will allow consumers of Racine to update to the latest icons without waiting for Racine to release an update. @sproutsocial/seeds-icons will be a peer and dev dependency of Racine.
|
|
14
|
+
- Most icons will have solid and outline variants, with outline being the default. Variants can be included in the icon name (e.g., `bell-solid`) or as a prop (e.g., `<Icon name=”bell” variant=”solid” />`).
|
|
15
|
+
- Icons will be renamed to use descriptive instead of prescriptive naming. For instance, the `ads` icon will be renamed to `dollar-outline` so that its name will visually describe the icon instead of prescribing its intended usage.
|
|
16
|
+
|
|
17
|
+
Due to the scale of the changes, we are unable to make the changes backwards-compatible. You can preview the migration process below, but you should not complete the migration until these changes are released.
|
|
18
|
+
|
|
19
|
+
Migration steps:
|
|
20
|
+
|
|
21
|
+
- Dependencies: Add @sproutsocial/seeds-icons to your application’s dependencies.
|
|
22
|
+
- Sprites: Instead of using icon.svg from Racine’s dist/ directory, the sprites should be imported from @sproutsocial/seeds-icons for each category of icons you want to include. Attach these spritesheets to the DOM in the same way you do icon.svg.
|
|
23
|
+
- Icon names: Most icon names are changing as a part of this refactor. Run the `icon-library` codemod to automatically update as many icon names as possible. For more information on how to use Racine codemods, view [our Migration docs on Seeds](https://seeds.sproutsocial.com/components/migration).
|
|
24
|
+
|
|
25
|
+
- f84feaf3: Adds icon-name-substitution codemod
|
|
26
|
+
- This codemod complements the existing icon-library codemod, helping to automate icon name updates that cannot be automatically handled by the icon-library codemod.
|
|
27
|
+
- The codemod replaces string literals that are deprecated icon names with their updated names. Please note that this codemod will change any strings that happen to match a deprecated icon name, even if they are unrelated to icons, so we recommend running it against specific files (not your entire codebase) and carefully checking the results.
|
|
28
|
+
- Use `racine-codemod icon-name-substitution` to run this codemod and view the docs
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- f84feaf3: Fixes icon-library codemod bugs
|
|
33
|
+
|
|
34
|
+
The following unwanted behaviors have been removed:
|
|
35
|
+
|
|
36
|
+
- Erroneously removing the first comment in a file
|
|
37
|
+
- Erroneously removing the Icon import when Icon is still being used for a styled component or for "typeof Icon"
|
|
38
|
+
- Incorrect parsing of the "components" argument, leading to it not being used
|
|
39
|
+
- Adding multiple shim imports if there are multiple @sproutsocial/racine imports in the same file
|
|
40
|
+
- Breaking aliased and type imports from @sproutsocial/racine
|
|
41
|
+
|
|
3
42
|
## 13.3.0
|
|
4
43
|
|
|
5
44
|
### Minor Changes
|
package/bin/racine-codemod.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
const childProcess = require('child_process');
|
|
7
7
|
const fs = require('fs');
|
|
8
8
|
const path = require('path');
|
|
9
|
+
const docs = require('../codemods/codemod-docs');
|
|
9
10
|
|
|
10
11
|
const currentDir = process.cwd();
|
|
11
12
|
process.chdir(__dirname);
|
|
@@ -13,22 +14,46 @@ process.chdir(__dirname);
|
|
|
13
14
|
const codemods = fs
|
|
14
15
|
.readdirSync('../codemods')
|
|
15
16
|
.filter((x) => x.slice(-3) === '.js')
|
|
16
|
-
.map((x) => x.slice(0, -3))
|
|
17
|
+
.map((x) => x.slice(0, -3))
|
|
18
|
+
.filter((x) => x !== 'codemod-docs');
|
|
17
19
|
|
|
18
20
|
const transform = process.argv[2];
|
|
19
21
|
const dest = process.argv[3];
|
|
20
|
-
const usage = `
|
|
22
|
+
const usage = `racine-codemod <transformName> <path> <...otherArgs>\n`;
|
|
21
23
|
if (!transform || codemods.indexOf(transform) === -1) {
|
|
22
24
|
console.log(usage);
|
|
23
25
|
console.error(
|
|
24
|
-
'
|
|
26
|
+
'Missing/invalid transform name. Pick one of:\n' +
|
|
25
27
|
codemods.map((x) => '- ' + x).join('\n')
|
|
26
28
|
);
|
|
27
29
|
process.exit(1);
|
|
28
30
|
}
|
|
31
|
+
|
|
32
|
+
const formatCodemodDocs = (docs) => {
|
|
33
|
+
return ` Description: ${docs.description}
|
|
34
|
+
Usage: ${docs.example}
|
|
35
|
+
Arguments:
|
|
36
|
+
${Object.entries(docs.arguments)
|
|
37
|
+
.map(([argumentName, argumentDocs]) => {
|
|
38
|
+
return ` --${argumentName}
|
|
39
|
+
Description: ${argumentDocs.description}
|
|
40
|
+
Default: ${argumentDocs.default}
|
|
41
|
+
${
|
|
42
|
+
argumentDocs.options
|
|
43
|
+
? `Options: ${argumentDocs.options}`
|
|
44
|
+
: `Example: ${argumentDocs.example}`
|
|
45
|
+
}`;
|
|
46
|
+
})
|
|
47
|
+
.join('\n')}`;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// If a path argument is not passed, log the available arguments and example usage for the codemod.
|
|
29
51
|
if (!dest) {
|
|
30
|
-
console.log(
|
|
31
|
-
|
|
52
|
+
console.log(
|
|
53
|
+
docs[transform]
|
|
54
|
+
? formatCodemodDocs(docs[transform])
|
|
55
|
+
: 'Missing path argument'
|
|
56
|
+
);
|
|
32
57
|
process.exit(1);
|
|
33
58
|
}
|
|
34
59
|
|
|
@@ -39,6 +64,12 @@ const cmd = `npx jscodeshift -- --parser=flow -t ${path.join(
|
|
|
39
64
|
...process.argv,
|
|
40
65
|
]
|
|
41
66
|
.slice(4)
|
|
67
|
+
// Remove any spaces from args. Otherwise, anything after the space will be treated as a path argument.
|
|
68
|
+
.map((arg) => arg.replace(/\s/g, ''))
|
|
42
69
|
.join(' ')}`;
|
|
43
70
|
console.log('running', cmd);
|
|
44
|
-
childProcess.execSync(cmd);
|
|
71
|
+
childProcess.execSync(cmd, {stdio: 'inherit'});
|
|
72
|
+
|
|
73
|
+
console.log(
|
|
74
|
+
`Codemod complete! Please run prettier on "${dest}" to fix any formatting issues caused by the codemod.`
|
|
75
|
+
);
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
jest.autoMockOff();
|
|
2
|
+
const defineInlineTest = require('jscodeshift/dist/testUtils').defineInlineTest;
|
|
3
|
+
const transform = require('../icon-library');
|
|
4
|
+
|
|
5
|
+
describe('icon-library codemod', () => {
|
|
6
|
+
function createTest(testName, input, output, options = {}) {
|
|
7
|
+
return defineInlineTest(
|
|
8
|
+
transform,
|
|
9
|
+
{parser: 'flow', ...options},
|
|
10
|
+
input,
|
|
11
|
+
output,
|
|
12
|
+
testName
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
createTest(
|
|
17
|
+
'No changes for already-migrated icons',
|
|
18
|
+
`<Icon name='dollar-outline' />`,
|
|
19
|
+
`<Icon name='dollar-outline' />`
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
createTest(
|
|
23
|
+
'Simple replacement',
|
|
24
|
+
`<Icon name='ads' />`,
|
|
25
|
+
`<Icon name='dollar-outline' />`
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
createTest(
|
|
29
|
+
'deprecatedIcons',
|
|
30
|
+
`<Icon name='backtotop' />`,
|
|
31
|
+
`<Icon name='arrow-up-outline' />`
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
createTest(
|
|
35
|
+
'Handle subcomponents',
|
|
36
|
+
`<Icon.Toggle activeName='like' inactiveName='like-outline'/>;`,
|
|
37
|
+
`<Icon.Toggle activeName='thumbs-up-solid' inactiveName='thumbs-up-outline'/>;`
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
createTest(
|
|
41
|
+
'ssiconsvg regex replacements',
|
|
42
|
+
`<use
|
|
43
|
+
xlink:href="#ssiconsvg-rejected"
|
|
44
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
45
|
+
/>`,
|
|
46
|
+
`<use
|
|
47
|
+
xlink:href="#seeds-svgs_ban-outline"
|
|
48
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
49
|
+
/>`
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
createTest(
|
|
53
|
+
'icon/iconName regex replacements',
|
|
54
|
+
`expect(queryByDataQaLabel({icon: 'dashboard'})).toBeFalsy();
|
|
55
|
+
const iconMap = {iconName: "like"};
|
|
56
|
+
const iconName = 'reply';`,
|
|
57
|
+
`expect(queryByDataQaLabel({icon: 'gauge-outline'})).toBeFalsy();
|
|
58
|
+
const iconMap = {iconName: "thumbs-up-solid"};
|
|
59
|
+
const iconName = 'reply-solid';`
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
createTest(
|
|
63
|
+
'Add comments',
|
|
64
|
+
`import { Badge, Icon } from '@sproutsocial/racine';
|
|
65
|
+
|
|
66
|
+
<>
|
|
67
|
+
<Icon name='dashboard' />
|
|
68
|
+
<Icon name='not-a-real-name' />
|
|
69
|
+
<Badge iconName={iconName} />
|
|
70
|
+
</>`,
|
|
71
|
+
`/*TODO (icon-library codemod): Please manually migrate icon names passed to 2 component(s) in this file.
|
|
72
|
+
Look for usages of these components: Icon, Badge*/
|
|
73
|
+
import { Badge, Icon } from '@sproutsocial/racine';
|
|
74
|
+
|
|
75
|
+
<>
|
|
76
|
+
<Icon name='gauge-outline' />
|
|
77
|
+
<Icon name='not-a-real-name' />
|
|
78
|
+
<Badge iconName={iconName} />
|
|
79
|
+
</>`
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// Test shim component adding behavior with a mix of cases.
|
|
83
|
+
// The valid name Icon is migrated.
|
|
84
|
+
// The invalid string name Icon prompts a comment. The shim would not help map an invalid string name.
|
|
85
|
+
// The variable name Icon is converted to IconShim and does not contribute to the count of issues in the comment.
|
|
86
|
+
createTest(
|
|
87
|
+
'Add shim component and add comments',
|
|
88
|
+
`import { Icon } from '@sproutsocial/racine';
|
|
89
|
+
|
|
90
|
+
<>
|
|
91
|
+
<Icon name='dashboard' />
|
|
92
|
+
<Icon name='not-a-real-name' />
|
|
93
|
+
<Icon name={iconName} />
|
|
94
|
+
</>`,
|
|
95
|
+
`/*TODO (icon-library codemod): Please manually migrate icon names passed to 1 component(s) in this file.
|
|
96
|
+
Look for usages of these components: Icon*/
|
|
97
|
+
import { Icon } from '@sproutsocial/racine';
|
|
98
|
+
|
|
99
|
+
import { IconShim } from 'script/core/react/IconShim';
|
|
100
|
+
|
|
101
|
+
<>
|
|
102
|
+
<Icon name='gauge-outline' />
|
|
103
|
+
<Icon name='not-a-real-name' />
|
|
104
|
+
<IconShim name={iconName} />
|
|
105
|
+
</>`,
|
|
106
|
+
{
|
|
107
|
+
shimName: 'IconShim',
|
|
108
|
+
shimImportPath: 'script/core/react/IconShim',
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
createTest(
|
|
113
|
+
'Add shim, remove Icon import',
|
|
114
|
+
`import { Icon } from '@sproutsocial/racine';
|
|
115
|
+
|
|
116
|
+
<Icon name={iconName} />`,
|
|
117
|
+
`import { IconShim } from 'script/core/react/IconShim';
|
|
118
|
+
|
|
119
|
+
<IconShim name={iconName} />
|
|
120
|
+
`,
|
|
121
|
+
{
|
|
122
|
+
shimName: 'IconShim',
|
|
123
|
+
shimImportPath: 'script/core/react/IconShim',
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
createTest(
|
|
128
|
+
'Add shim, keep Icon import due to styled usage',
|
|
129
|
+
`import { Icon } from '@sproutsocial/racine';
|
|
130
|
+
const StyledIcon = styled(Icon);
|
|
131
|
+
<Icon name={iconName} />`,
|
|
132
|
+
`import { Icon } from '@sproutsocial/racine';
|
|
133
|
+
import { IconShim } from 'script/core/react/IconShim';
|
|
134
|
+
const StyledIcon = styled(Icon);
|
|
135
|
+
<IconShim name={iconName} />
|
|
136
|
+
`,
|
|
137
|
+
{
|
|
138
|
+
shimName: 'IconShim',
|
|
139
|
+
shimImportPath: 'script/core/react/IconShim',
|
|
140
|
+
}
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
createTest(
|
|
144
|
+
'Add shim, keep Icon import due to typeof Icon usage',
|
|
145
|
+
`import { Icon } from '@sproutsocial/racine';
|
|
146
|
+
const iconType = typeof Icon;
|
|
147
|
+
<Icon name={iconName} />;`,
|
|
148
|
+
`import { Icon } from '@sproutsocial/racine';
|
|
149
|
+
import { IconShim } from 'script/core/react/IconShim';
|
|
150
|
+
const iconType = typeof Icon;
|
|
151
|
+
<IconShim name={iconName} />;
|
|
152
|
+
`,
|
|
153
|
+
{
|
|
154
|
+
shimName: 'IconShim',
|
|
155
|
+
shimImportPath: 'script/core/react/IconShim',
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
createTest(
|
|
160
|
+
'Retain first comments when Icon import is removed',
|
|
161
|
+
`// @flow
|
|
162
|
+
import { Icon } from '@sproutsocial/racine';
|
|
163
|
+
|
|
164
|
+
<Icon name={iconName} />`,
|
|
165
|
+
`// @flow
|
|
166
|
+
import { IconShim } from 'script/core/react/IconShim';
|
|
167
|
+
|
|
168
|
+
<IconShim name={iconName} />
|
|
169
|
+
`,
|
|
170
|
+
{
|
|
171
|
+
shimName: 'IconShim',
|
|
172
|
+
shimImportPath: 'script/core/react/IconShim',
|
|
173
|
+
}
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
createTest(
|
|
177
|
+
'Retain first comments and add new comments',
|
|
178
|
+
`// @flow
|
|
179
|
+
import { Badge, Icon } from '@sproutsocial/racine';
|
|
180
|
+
|
|
181
|
+
<>
|
|
182
|
+
<Icon name='dashboard' />
|
|
183
|
+
<Icon name='not-a-real-name' />
|
|
184
|
+
<Badge iconName={iconName} />
|
|
185
|
+
</>`,
|
|
186
|
+
`// @flow
|
|
187
|
+
/*TODO (icon-library codemod): Please manually migrate icon names passed to 2 component(s) in this file.
|
|
188
|
+
Look for usages of these components: Icon, Badge*/
|
|
189
|
+
import { Badge, Icon } from '@sproutsocial/racine';
|
|
190
|
+
|
|
191
|
+
<>
|
|
192
|
+
<Icon name='gauge-outline' />
|
|
193
|
+
<Icon name='not-a-real-name' />
|
|
194
|
+
<Badge iconName={iconName} />
|
|
195
|
+
</>`
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
createTest(
|
|
199
|
+
'Test "components" option',
|
|
200
|
+
`
|
|
201
|
+
<>
|
|
202
|
+
<Icon name='dashboard' />
|
|
203
|
+
<Message.Header iconName='reply' />
|
|
204
|
+
<SearchInput iconLeft='search' iconRight='x' />
|
|
205
|
+
</>`,
|
|
206
|
+
`
|
|
207
|
+
<>
|
|
208
|
+
<Icon name='gauge-outline' />
|
|
209
|
+
<Message.Header iconName='reply-solid' />
|
|
210
|
+
<SearchInput iconLeft='magnifying-glass-outline' iconRight='x-outline' />
|
|
211
|
+
</>`,
|
|
212
|
+
{
|
|
213
|
+
// This tests if the following argument was passed to `racine-codemod`:
|
|
214
|
+
// --components="{'Message.Header':['iconName'],SearchInput:['iconLeft','iconRight']}"
|
|
215
|
+
// Unfortunately, because it's getting passed directly to the transform in this case,
|
|
216
|
+
// We need to simulate the way that it gets mangled when passed through the console.
|
|
217
|
+
components: [
|
|
218
|
+
'Message.Header:[iconName]',
|
|
219
|
+
'SearchInput:[iconLeft',
|
|
220
|
+
'iconRight]',
|
|
221
|
+
],
|
|
222
|
+
}
|
|
223
|
+
);
|
|
224
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
jest.autoMockOff();
|
|
2
|
+
const defineInlineTest = require('jscodeshift/dist/testUtils').defineInlineTest;
|
|
3
|
+
const transform = require('../icon-name-substitution');
|
|
4
|
+
|
|
5
|
+
describe('icon-name-substitution codemod', () => {
|
|
6
|
+
function createTest(testName, input, output, options = {}) {
|
|
7
|
+
return defineInlineTest(
|
|
8
|
+
transform,
|
|
9
|
+
{parser: 'flow', ...options},
|
|
10
|
+
input,
|
|
11
|
+
output,
|
|
12
|
+
testName
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
createTest(
|
|
17
|
+
'No changes for already-migrated icon names. Empty output due to returning null.',
|
|
18
|
+
`const IconMap = {ads: 'dollar-outline', draft: 'paper-solid'};`,
|
|
19
|
+
''
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
createTest(
|
|
23
|
+
'Simple replacements',
|
|
24
|
+
`const IconMap = {ads: 'ads', draft: 'drafts'}`,
|
|
25
|
+
`const IconMap = {ads: 'dollar-outline', draft: 'paper-solid'}`
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
createTest(
|
|
29
|
+
'Example of an expected but unwanted change: the "ads" key and value are both mapped.',
|
|
30
|
+
`const IconMap = {'ads': 'ads', 'draft': 'drafts'}`,
|
|
31
|
+
`const IconMap = {'dollar-outline': 'dollar-outline', 'draft': 'paper-solid'}`
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
createTest(
|
|
35
|
+
'deprecatedIcons',
|
|
36
|
+
`const name = 'backtotop';`,
|
|
37
|
+
`const name = 'arrow-up-outline';`
|
|
38
|
+
);
|
|
39
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Ideally, docs would be colocated with the codemod they are for, but I don't know how to make that work because
|
|
2
|
+
// the transform needs to be the only export from the codemod file in order for jscodeshift to know how to find it.
|
|
3
|
+
|
|
4
|
+
// Reused arguments
|
|
5
|
+
const quote = {
|
|
6
|
+
default: 'single',
|
|
7
|
+
options: 'single|double',
|
|
8
|
+
description:
|
|
9
|
+
'What kind of quotation marks should be preferred when converting updated files back to JS?',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
'icon-library': {
|
|
14
|
+
description:
|
|
15
|
+
'Assists in migrating Icon names and usages. Due to abstraction such as using variables and mappings to define icon names, the codemod cannot automatically migrate every icon name. To help you identify these cases, the codemod can add comments or shim component usages.',
|
|
16
|
+
example:
|
|
17
|
+
"racine-codemod icon-library src --components=\"{IconButton:['name'],MessageMeta:['iconNameLeft','iconNameRight']}\" --shimComponent=IconShim --shimImportPath=src/components/IconShim --quote=double --addComments=false",
|
|
18
|
+
arguments: {
|
|
19
|
+
quote,
|
|
20
|
+
addComments: {
|
|
21
|
+
default: 'true',
|
|
22
|
+
options: 'true|false',
|
|
23
|
+
description:
|
|
24
|
+
'Should code comments be added when the codemod identifies a case that cannot be automatically migrated? Comments will include "icon-library" to help you locate and remediate them.',
|
|
25
|
+
},
|
|
26
|
+
components: {
|
|
27
|
+
default: '"{}"',
|
|
28
|
+
example:
|
|
29
|
+
"\"{IconButton:['name'],MessageMeta:['iconNameLeft','iconNameRight']}\"",
|
|
30
|
+
description:
|
|
31
|
+
'What additional component names + prop name combinations would you like the codemod to target for the migration? Wrap this argument in quotes.',
|
|
32
|
+
},
|
|
33
|
+
shimName: {
|
|
34
|
+
default: '""',
|
|
35
|
+
example: 'IconShim',
|
|
36
|
+
description:
|
|
37
|
+
"If you provide a shim component name, any Icon that has a variable for its `name` prop will be renamed to the shim component's name. You must create this component in your own codebase, it is not provided.",
|
|
38
|
+
},
|
|
39
|
+
shimImportPath: {
|
|
40
|
+
default: '""',
|
|
41
|
+
example: 'src/components/IconShim',
|
|
42
|
+
description:
|
|
43
|
+
'shimImportPath is the import path for your shim component (see "shimName") so that imports can be automatically when usages are added.',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
'icon-name-substitution': {
|
|
48
|
+
description:
|
|
49
|
+
'Replaces string literals that are deprecated icon names with their updated names. Please note that this codemod will change any strings that happen to match a deprecated icon name, even if they are unrelated to icons, so we recommend running it against specific files (not your entire codebase) and carefully checking the results.',
|
|
50
|
+
example:
|
|
51
|
+
'racine-codemod icon-name-substitution src/constants.js --quote=double',
|
|
52
|
+
arguments: {quote},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
// We need the deprecated icon name mapping so that we can migrate icons still
|
|
2
|
+
// using the ancient names all the way to the new names.
|
|
3
|
+
// prettier-ignore
|
|
4
|
+
const deprecatedNames = {backtotop: 'back-to-top', 'circle-check-filled': 'circle-check', 'circle-check-no-fill': 'circle-check', 'circle-check-inverse-outline': 'circle-check-outline', 'circle-check-inverse': 'circle-check-outline', 'circle+-filled': 'circle+', 'circlex-filled': 'circlex', 'circle+-nofill': 'circle+', 'circlex-nofill': 'circlex', creditcard: 'credit-card', 'direct-message': 'messages', 'facebook-nofill': 'facebook', googleanalytics: 'google-analytics-color', 'instagram-brand-keyword': 'hashtag', 'help-white': 'help', 'info-white': 'info', 'instagram-nofill': 'instagram', 'key-circle': 'key', 'key-square': 'key', 'linkedin-nofill': 'linkedin', 'listening-home': 'listening', 'location-pub': 'location', 'location-pub-outline': 'location-outline', 'publishing-calendar': 'calendar', qrcode: 'qr-code', 'sparkles-solid': 'sparkles', 'star-inverse': 'star-outline', 'triangle-white': 'triangle', 'triangle-nofill': 'triangle', 'tripadvisor-circle-filled': 'tripadvisor-circle', 'tripadvisor-circle-empty': 'tripadvisor-circle-outline', 'tumblr-square': 'tumblr', 'tumblr-nofill': 'tumblr', 'twitter-business-mention': 'search', 'verified-nofill': 'verified', 'window-maximize-solid': 'window-maximize'};
|
|
5
|
+
|
|
6
|
+
// Mapping from old icon names to new icon names
|
|
7
|
+
// prettier-ignore
|
|
8
|
+
const IconMap = {'active-listener': 'listening-outline', 'add-item': 'plus-outline', 'add-keyword': 'plus-outline', 'add-team-member': 'user-plus-outline', 'add-variable': 'curly-brackets-plus-outline', 'address-card-outline': 'profile-card-outline', 'address-card-solid': 'profile-card-solid', ads: 'dollar-outline', 'advocacy-outline': 'advocacy-outline', advocacy: 'advocacy-solid', 'approval-indicator-outline': 'stamp-outline', 'approval-indicator': 'stamp-solid', archive: 'file-box-outline', 'arrow-down-line': 'arrow-down-to-line-outline', 'arrow-down': 'arrow-down-outline', 'arrow-left-line': 'arrow-left-to-line-outline', 'arrow-left': 'arrow-left-outline', 'arrow-right-line': 'arrow-right-to-line-outline', 'arrow-right': 'arrow-right-outline', 'arrow-up-line': 'arrow-up-to-line-outline', 'arrow-up': 'arrow-up-outline', arrows: 'arrows-up-down-left-right-outline', 'asset-library-outline': 'asset-library-outline', 'asset-library': 'asset-library-solid', assign: 'sitemap-outline', atom: 'atom-outline', audio: 'audio-outline', 'back-to-top': 'arrow-up-outline', 'bambu-icon-outline': 'bambu-outline', 'bambu-icon': 'bambu-solid', barcode: 'barcode-outline', basketball: 'basketball-outline', 'bell-outline': 'bell-outline', bold: 'bold-outline', book: 'book-outline', 'bookmark-filled': 'bookmark-solid', bookmark: 'bookmark-outline', bot: 'robot-outline', browser: 'window-full-outline', 'bulk-select': 'square-check-outline', business: 'briefcase-outline', 'calendar-outline': 'calendar-outline', calendar: 'calendar-solid', 'camera-outline': 'camera-outline', 'camera-story': 'camera-story-solid', camera: 'camera-solid', campaign: 'megaphone-outline', carousel: 'carousel-outline', 'cart-plus': 'cart-plus-outline', check: 'check-outline', 'chevron-down-filled': 'caret-down-outline', 'chevron-down': 'chevron-down-outline', 'chevron-left': 'chevron-left-outline', 'chevron-right': 'chevron-right-outline', 'chevron-up-down-filled': 'caret-up-down-outline', 'chevron-up-filled': 'caret-up-outline', 'chevron-up': 'chevron-up-outline', 'circle-check-outline': 'circle-check-outline', 'circle-check': 'circle-check-solid', circle: 'circle-no-fill-outline', 'circle+': 'plus-outline', circles: 'large-circle-small-circle-outline', circleX: 'circle-x-outline', circlex: 'circle-x-outline', 'click-to-view': 'hand-pointer-clicking-outline', clicks: 'pointer-outline', 'clipboard-outline': 'clipboard-outline', clipboard: 'clipboard-solid', clock: 'clock-outline', 'closed-captioning': 'closed-caption-outline', cloud: 'cloud-outline', code: 'code-outline', columns: 'columns-outline', 'comment-alt-outline': 'comments-outline', 'comment-alt': 'comment-solid', 'comment-lines-alt-outline': 'comment-outline', comment: 'comments-outline', 'compact-density': 'bars-density-small-outline', 'compact-indicator': 'bars-density-small-outline', comparison: 'diamond-vs-outline', competitor: 'office-building-outline', compose: 'pencil-to-square-outline', 'content-suggestions': 'comment-sparkle-outline', 'credit-card': 'credit-card-outline', crop: 'crop-outline', crown: 'crown-outline', dashboard: 'gauge-outline', 'deconstructed-negative-sentiment': 'expression-frown-outline', 'deconstructed-neutral-sentiment': 'expression-neutral-outline', 'deconstructed-positive-sentiment': 'expression-smile-open-outline', discovery: 'compass-outline', 'dislike-outline': 'thumbs-down-outline', dislike: 'thumbs-down-solid', 'dm-link-outline': 'comment-plus-outline', 'dm-link': 'comment-plus-solid', 'doesnt-recommend': 'comment-star-slash-outline', dotdotdot: 'ellipsis-horizontal-outline', download: 'arrow-down-to-bracket-outline', 'drafts-outline': 'paper-outline', drafts: 'paper-solid', 'duplicate-outline': 'papers-outline', duplicate: 'papers-solid', 'emoji-outline': 'face-smile-outline', emoji: 'face-smile-solid', 'empty-image': 'camera-x-outline', 'engagement-per-post': 'comment-outline', engagements: 'comments-outline', error: 'circle-exclamation-outline', 'exchange-alt': 'arrows-left-right-outline', 'expanded-indicator': 'bars-density-large-outline', export: 'square-round-arrow-up-right-outline', 'extended-circles': 'large-circle-small-circle-outline', 'external-link-alt': 'squares-arrow-up-right-outline', 'external-link': 'square-round-arrow-up-right-outline', 'extreme-negative-sentiment': 'face-frown-open-outline', 'eye-outline': 'eye-outline', 'eye-slash-outline': 'eye-slash-outline', 'eye-slash': 'eye-slash-solid', eye: 'eye-solid', 'facebook-branded-content-outline': 'handshake-outline', 'facebook-branded-content': 'handshake-solid', feeds: 'unordered-list-outline', female: 'symbol-venus-outline', 'file-chart-line': 'paper-bars-outline', 'file-edit': 'paper-pencil-outline', 'file-times-solid': 'paper-x-outline', filter: 'filter-outline', 'flag-outline': 'flag-outline', flag: 'flag-solid', 'folder-open': 'folder-open-outline', folder: 'folder-outline', 'follow-outline': 'user-plus-outline', follow: 'user-plus-solid', 'follower-increase': 'user-arrow-up-outline', following: 'user-check-outline', font: 'font-case-outline', 'full-access': 'circle-fill-outline', gear: 'gear-outline', gears: 'gear-outline', glasses: 'glasses-outline', globe: 'globe-outline', grip: 'grip-lines-vertical-outline', h1: 'h1-outline', h2: 'h2-outline', h3: 'h3-outline', h4: 'h3-outline', hamburger: 'horizontal-lines-outline', hashtag: 'hashtag-outline', headset: 'headset-outline', 'heart-outline': 'heart-outline', heart: 'heart-solid', heartbeat: 'heart-pulse-outline', 'help-alt': 'question-mark-outline', help: 'circle-question-outline', hiking: 'person-hiking-outline', history: 'clock-rotate-left-outline', home: 'house-outline', hourglass: 'hourglass-outline', 'image-caption': 'rectangle-caption-outline', image: 'image-outline', images: 'images-outline', 'impressions-per-post': 'comment-eye-outline', impressions: 'eye-outline', 'inactive-listener': 'file-box-outline', 'inbox-action': 'inbox-check-outline', 'inbox-views': 'inboxes-outline', inbox: 'inbox-outline', indicator: 'circle-fill-outline', industry: 'office-building-outline', info: 'circle-i-outline', 'internal-activity-outline': 'clock-rotate-left-outline', 'internal-activity': 'clock-rotate-left-solid', italic: 'italics-outline', key: 'key-outline', keyboard: 'keyboard-outline', 'laptop-phone': 'laptop-mobile-outline', 'large-density': 'bars-density-large-outline', lift: 'circle-dollar-arrow-up-outline', 'like-outline': 'thumbs-up-outline', like: 'thumbs-up-solid', link: 'link-outline', 'list-ol': 'ordered-list-outline', listening: 'listening-outline', lists: 'unordered-list-outline', 'location-outline': 'location-pin-outline', location: 'location-pin-solid', lock: 'lock-outline', 'magic-wand': 'magic-wand-outline', male: 'symbol-mars-outline', mention: 'symbol-at-outline', 'message-preview-outline': 'eye-outline', 'message-preview': 'eye-solid', message: 'comment-outline', 'messages-outline': 'envelope-outline', messages: 'envelope-solid', 'metric-table': 'metric-table-outline', minus: 'minus-outline', mobile: 'mobile-outline', monitor: 'pulse-outline', moon: 'moon-crescent-outline', 'negative-sentiment': 'face-frown-outline', 'neutral-positive-sentiment': 'face-smile-outline', 'neutral-sentiment': 'face-neutral-outline', 'new-trend': 'fire-outline', newspaper: 'newspaper-outline', 'no-access': 'circle-minus-outline', 'no-notifications-filled': 'bell-slash-solid', 'no-notifications': 'bell-slash-outline', notepad: 'clipboard-outline', 'notifications-publishing': 'alarm-clock-outline', notifications: 'bell-outline', offline: 'wifi-slash-outline', online: 'wifi-outline', 'paid-promotion-outline': 'circle-dollar-outline', 'paid-promotion': 'circle-dollar-solid', paid: 'calculator-outline', paint: 'paint-can-outline', palette: 'art-palette-outline', paperclip: 'paperclip-outline', pause: 'pause-outline', 'pencil-outline': 'pencil-outline', pencil: 'pencil-solid', person: 'user-outline', phone: 'phone-outline', 'pinterest-boards-outline': 'mood-boards-outline', 'pinterest-boards': 'mood-boards-solid', 'play-circle': 'play-outline', play: 'play-outline', plug: 'plug-outline', plus: 'plus-outline', 'positive-sentiment': 'face-smile-open-outline', 'power-up-outline': 'lightning-bolt-outline', 'power-up': 'lightning-bolt-solid', 'profile-connect': 'leaf-plus-outline', 'profile-disconnect': 'leaf-minus-outline', 'publishing-outline': 'paper-plane-outline', publishing: 'paper-plane-outline', 'puzzle-piece': 'puzzle-piece-outline', 'qr-code': 'qr-code-outline', queue: 'queue-outline', recommendation: 'comment-star-outline', referrals: 'star-full-outline', refresh: 'arrows-rotate-outline', rejected: 'ban-outline', 'reply-outline': 'reply-outline', reply: 'reply-solid', 'reporting-period': 'calendar-range-outline', reporting: 'chart-bar-simple-outline', 'reports-home': 'four-squares-outline', reports: 'chart-pie-outline', retweet: 'repost-outline', rss: 'rss-outline', sales: 'dollar-outline', 'save-assets': 'asset-library-plus-outline', 'saved-messages': 'comment-bookmark-outline', 'saved-reply-outline': 'bookmark-reply-outline', 'saved-reply': 'bookmark-reply-solid', search: 'magnifying-glass-outline', 'sent-message-outline': 'inbox-arrow-up-outline', 'sent-message': 'inbox-arrow-up-solid', share: 'square-round-arrow-up-right-outline', 'shopping-bag-outline': 'shopping-bag-outline', 'shopping-bag': 'shopping-bag-solid', 'show-navigation': 'browser-nav-bar-outline', 'small-density': 'bars-density-medium-outline', smiley: 'face-smile-outline', 'some-access': 'circle-half-outline', sparkles: 'sparkle-outline', 'spike-alert': 'comment-exclamation-outline', 'star-half-alt-solid': 'star-half-outline', 'star-of-life': 'star-of-life-outline', 'star-outline': 'star-outline', star: 'star-full-outline', 'sticky-note-outline': 'note-outline', 'sticky-note': 'note-solid', story: 'camera-story-outline', stories: 'story-outline', suggestions: 'comment-light-bulb-outline', sun: 'sun-outline', 'tag-outline': 'tag-outline', tag: 'tag-solid', 'targeting-outline': 'bullseye-arrow-outline', targeting: 'bullseye-arrow-solid', 'tasks-outline': 'thumbtack-outline', tasks: 'thumbtack-solid', 'team-conversation-outline': 'sprout-leaf-lightning-bolt-outline', 'team-conversation': 'sprout-leaf-lightning-bolt-solid', team: 'users-outline', 'text-asset': 'text-serif-outline', text: 'text-serif-outline', times: 'x-outline', tools: 'screwdriver-hammer-outline', 'trash-can-outline': 'trash-outline', 'trash-can': 'trash-solid', 'trend-down': 'arrow-right-down-outline', 'trend-up': 'arrow-right-up-outline', 'trend-neutral': 'arrow-right-outline', trends: 'fire-outline', 'triangle-black': 'triangle-outline', triangle: 'triangle-exclamation-outline', 'trophy-outline': 'trophy-outline', 'unfollow-outline': 'user-x-outline', unfollow: 'user-x-solid', unlink: 'link-slash-outline', unlock: 'unlock-outline', upload: 'arrow-up-from-bracket-outline', 'user-circle': 'user-sprout-outline', users: 'users-outline', 'video-camera-story': 'video-camera-story-outline', 'video-camera': 'video-camera-outline', vip: 'gem-outline', weight: 'weight-outline', 'window-maximize': 'window-modal-outline', 'window-minimize': 'window-minimize-outline', 'window-regular': 'browser-outline', 'window-restore': 'browser-restore-outline', x: 'x-outline', 'tripadvisor-circle-filled': 'tripadvisor-cicle-solid', 'tripadvisor-circle-empty': 'tripadvisor-circle-outline', 'flat-positive-sentiment': 'face-smile-outline', 'flat-negative-sentiment': 'face-frown-outline', 'flat-neutral-sentiment': 'face-neutral-outline'};
|
|
9
|
+
|
|
10
|
+
// All the new icon names. Used to avoid attempting to migrate an icon name that has already been migrated.
|
|
11
|
+
// prettier-ignore
|
|
12
|
+
const ExternalIconNames = ["fb-reactions-angry","fb-reactions-haha","fb-reactions-like","fb-reactions-love","fb-reactions-sad","fb-reactions-wow","recommendation","reels-outline","reels-solid","tripadvisor-circle-outline","tripadvisor-circle-solid","verified","yelp-full-star","yelp-half-star"];
|
|
13
|
+
// prettier-ignore
|
|
14
|
+
const GeneralIconNames = ["alarm-clock-outline","alarm-clock-solid","all-caps-outline","all-caps-solid","alt-text-outline","alt-text-solid","arrow-down-outline","arrow-down-solid","arrow-down-to-bracket-outline","arrow-down-to-bracket-solid","arrow-down-to-line-outline","arrow-down-to-line-solid","arrow-left-outline","arrow-left-solid","arrow-left-to-line-outline","arrow-left-to-line-solid","arrow-right-down-outline","arrow-right-down-solid","arrow-right-from-bracket-outline","arrow-right-from-bracket-solid","arrow-right-outline","arrow-right-solid","arrow-right-to-line-outline","arrow-right-to-line-solid","arrow-right-up-outline","arrow-right-up-solid","arrow-up-from-bracket-outline","arrow-up-from-bracket-solid","arrow-up-outline","arrow-up-solid","arrow-up-to-line-outline","arrow-up-to-line-solid","arrows-left-right-outline","arrows-left-right-solid","arrows-pointing-in-outline","arrows-pointing-in-solid","arrows-pointing-out-outline","arrows-pointing-out-solid","arrows-rotate-outline","arrows-rotate-solid","arrows-up-down-left-right-outline","arrows-up-down-left-right-solid","art-palette-outline","art-palette-solid","atom-outline","atom-solid","audio-outline","audio-solid","ban-outline","ban-solid","barcode-outline","barcode-solid","bars-density-large-outline","bars-density-large-solid","bars-density-medium-outline","bars-density-medium-solid","bars-density-small-outline","bars-density-small-solid","bars-density-two-panel-outline","bars-density-two-panel-solid","basketball-outline","basketball-solid","bell-outline","bell-slash-outline","bell-slash-solid","bell-solid","bold-outline","bold-solid","book-open-outline","book-open-solid","book-outline","book-solid","bookmark-filter-outline","bookmark-filter-solid","bookmark-outline","bookmark-reply-outline","bookmark-reply-solid","bookmark-solid","briefcase-outline","briefcase-solid","browser-nav-bar-outline","browser-nav-bar-solid","browser-outline","browser-restore-outline","browser-restore-solid","browser-solid","bullseye-arrow-outline","bullseye-arrow-solid","calculator-outline","calculator-solid","calendar-clock-outline","calendar-clock-solid","calendar-day-outline","calendar-day-solid","calendar-outline","calendar-range-outline","calendar-range-solid","calendar-solid","camera-outline","camera-solid","camera-story-outline","camera-story-solid","camera-x-outline","camera-x-solid","caret-down-outline","caret-down-solid","caret-up-down-outline","caret-up-down-solid","caret-up-down-sort-down-outline","caret-up-down-sort-down-solid","caret-up-down-sort-up-outline","caret-up-down-sort-up-solid","caret-up-outline","caret-up-solid","carousel-outline","carousel-solid","cart-outline","cart-plus-outline","cart-plus-solid","cart-solid","chart-area-outline","chart-area-solid","chart-arrow-down-outline","chart-arrow-down-solid","chart-arrow-neutral-outline","chart-arrow-neutral-solid","chart-arrow-up-outline","chart-arrow-up-solid","chart-bar-outline","chart-bar-simple-outline","chart-bar-simple-solid","chart-bar-solid","chart-donut-outline","chart-donut-solid","chart-line-outline","chart-line-solid","chart-pie-outline","chart-pie-solid","check-outline","check-solid","chevron-down-outline","chevron-down-solid","chevron-left-outline","chevron-left-solid","chevron-right-outline","chevron-right-solid","chevron-up-outline","chevron-up-solid","circle-check-double-outline","circle-check-double-solid","circle-check-outline","circle-check-solid","circle-dollar-arrow-up-outline","circle-dollar-arrow-up-solid","circle-dollar-outline","circle-dollar-solid","circle-exclamation-outline","circle-exclamation-solid","circle-fill-outline","circle-fill-solid","circle-half-outline","circle-half-solid","circle-i-outline","circle-i-solid","circle-minus-outline","circle-minus-solid","circle-no-fill-outline","circle-no-fill-solid","circle-question-outline","circle-question-solid","circle-user-outline","circle-user-solid","circle-x-outline","circle-x-solid","clipboard-outline","clipboard-solid","clock-outline","clock-rotate-left-outline","clock-rotate-left-solid","clock-solid","closed-caption-outline","closed-caption-solid","cloud-outline","cloud-solid","code-outline","code-solid","columns-outline","columns-solid","comment-plus-outline","comment-plus-solid","comment-star-outline","comment-star-slash-outline","comment-star-slash-solid","comment-star-solid","compass-outline","compass-solid","credit-card-outline","credit-card-solid","crop-outline","crop-solid","crown-outline","crown-solid","curly-brackets-plus-outline","curly-brackets-plus-solid","delete-left-outline","delete-left-solid","diamond-outline","diamond-solid","diamond-vs-outline","diamond-vs-solid","dollar-outline","dollar-solid","ellipsis-horizontal-outline","ellipsis-horizontal-solid","ellipsis-vertical-outline","ellipsis-vertical-solid","envelope-outline","envelope-solid","expression-frown-outline","expression-frown-solid","expression-neutral-outline","expression-neutral-solid","expression-smile-open-outline","expression-smile-open-solid","eye-dropper-outline","eye-dropper-solid","eye-outline","eye-slash-outline","eye-slash-solid","eye-solid","face-frown-open-outline","face-frown-open-solid","face-frown-outline","face-frown-solid","face-neutral-outline","face-neutral-solid","face-smile-open-outline","face-smile-open-solid","face-smile-outline","face-smile-solid","file-box-arrow-up-outline","file-box-arrow-up-solid","file-box-outline","file-box-solid","filter-outline","filter-solid","fire-outline","fire-solid","flag-outline","flag-solid","folder-open-outline","folder-open-solid","folder-outline","folder-solid","font-case-outline","font-case-solid","four-squares-outline","four-squares-solid","gauge-outline","gauge-solid","gear-outline","gear-solid","gem-outline","gem-solid","gif-outline","gif-solid","glasses-outline","glasses-solid","globe-outline","globe-solid","grip-lines-vertical-outline","grip-lines-vertical-solid","h1-outline","h1-solid","h2-outline","h2-solid","h3-outline","h3-solid","h4-outline","h4-solid","hand-pointer-clicking-outline","hand-pointer-clicking-solid","handshake-outline","handshake-solid","hashtag-outline","hashtag-solid","headset-outline","headset-solid","heart-outline","heart-pulse-outline","heart-pulse-solid","heart-solid","horizontal-lines-outline","horizontal-lines-solid","hourglass-outline","hourglass-solid","house-outline","house-solid","image-outline","image-solid","images-outline","images-solid","inbox-arrow-up-outline","inbox-arrow-up-solid","inbox-check-outline","inbox-check-solid","inbox-lightning-bolt-outline","inbox-lightning-bolt-solid","inbox-outline","inbox-solid","inboxes-outline","inboxes-solid","italics-outline","italics-solid","justify-center-outline","justify-center-solid","justify-left-outline","justify-left-solid","justify-right-outline","justify-right-solid","key-outline","key-solid","keyboard-outline","keyboard-solid","language-outline","language-solid","laptop-mobile-outline","laptop-mobile-solid","larger-circle-small-circle-outline","larger-circle-small-circle-solid","lightbulb-outline","lightbulb-solid","lightning-bolt-outline","lightning-bolt-solid","link-broken-outline","link-broken-solid","link-outline","link-slash-outline","link-slash-solid","link-solid","locate-outline","locate-solid","location-pin-outline","location-pin-solid","lock-outline","lock-solid","magic-wand-outline","magic-wand-solid","magnifying-glass-outline","magnifying-glass-solid","magnifying-glass-twitter-outline","magnifying-glass-twitter-solid","masks-theater-outline","masks-theater-solid","megaphone-dollar-outline","megaphone-dollar-solid","megaphone-outline","megaphone-solid","metric-table-outline","metric-table-solid","microphone-outline","microphone-solid","minus-outline","minus-solid","mobile-outline","mobile-solid","mood-boards-outline","mood-boards-solid","moon-crescent-outline","moon-crescent-solid","newspaper-outline","newspaper-solid","note-outline","note-solid","office-building-outline","office-building-solid","ordered-list-outline","ordered-list-solid","paint-can-outline","paint-can-solid","paper-bars-outline","paper-bars-solid","paper-outline","paper-pencil-outline","paper-pencil-solid","paper-plane-arrows-rotate-outline","paper-plane-arrows-rotate-solid","paper-plane-outline","paper-plane-solid","paper-solid","paper-x-outline","paper-x-solid","paperclip-outline","paperclip-solid","papers-outline","papers-solid","pattern-circle-triangle-square-outline","pattern-circle-triangle-square-solid","pause-outline","pause-solid","pencil-outline","pencil-solid","person-hiking-outline","person-hiking-solid","phone-outline","phone-solid","play-outline","play-solid","plug-outline","plug-solid","plus-outline","plus-solid","pointer-outline","pointer-solid","profile-card-outline","profile-card-solid","pulse-outline","pulse-solid","puzzle-piece-outline","puzzle-piece-solid","qr-code-outline","qr-code-solid","question-mark-outline","question-mark-solid","rectangle-caption-outline","rectangle-caption-solid","reply-outline","reply-solid","repost-outline","repost-solid","robot-outline","robot-solid","route-outline","route-solid","rss-outline","rss-solid","screwdriver-hammer-outline","screwdriver-hammer-solid","seeds-outline","seeds-solid","shopping-bag-outline","shopping-bag-solid","sitemap-outline","sitemap-solid","sparkle-outline","sparkle-solid","square-check-outline","square-check-solid","square-outline","square-solid","squares-arrow-up-right-outline","squares-arrow-up-right-solid","stamp-check-outline","stamp-check-solid","stamp-outline","stamp-solid","star-full-outline","star-full-solid","star-half-outline","star-half-solid","star-of-life-outline","star-of-life-solid","star-outline","star-solid","story-outline","story-solid","strikethrough-outline","strikethrough-solid","sun-outline","sun-solid","symbol-at-outline","symbol-at-solid","symbol-mars-outline","symbol-mars-solid","symbol-venus-outline","symbol-venus-solid","tag-outline","tag-solid","tags-outline","tags-solid","text-serif-outline","text-serif-solid","thread-outline","thread-solid","thumbs-down-outline","thumbs-down-solid","thumbs-up-outline","thumbs-up-solid","thumbtack-check-outline","thumbtack-check-solid","thumbtack-outline","thumbtack-solid","ticket-outline","ticket-solid","trash-outline","trash-solid","triangle-exclamation-outline","triangle-exclamation-solid","triangle-outline","triangle-solid","trophy-outline","trophy-solid","underline-outline","underline-solid","unlock-outline","unlock-solid","unordered-list-outline","unordered-list-solid","user-arrow-up-outline","user-arrow-up-solid","user-check-outline","user-check-solid","user-minus-outline","user-minus-solid","user-outline","user-plus-outline","user-plus-solid","user-solid","user-x-outline","user-x-solid","users-outline","users-solid","video-camera-outline","video-camera-solid","video-camera-story-outline","video-camera-story-solid","weight-outline","weight-solid","wifi-outline","wifi-slash-outline","wifi-slash-solid","wifi-solid","window-arrow-up-left-outline","window-arrow-up-left-solid","window-dock-left-outline","window-dock-left-solid","window-dock-right-outline","window-dock-right-solid","window-full-outline","window-full-solid","window-minimize-outline","window-minimize-solid","window-modal-outline","window-modal-solid","x-outline","x-solid"]
|
|
15
|
+
// prettier-ignore
|
|
16
|
+
const SproutIconNames = ["advocacy-outline","advocacy-solid","asset-library-outline","asset-library-plus-outline","asset-library-plus-solid","asset-library-solid","bambu-outline","bambu-solid","comment-bookmark-outline","comment-bookmark-solid","comment-exclamation-outline","comment-exclamation-solid","comment-eye-outline","comment-eye-solid","comment-light-bulb-outline","comment-light-bulb-solid","comment-outline","comment-solid","comment-sparkle-outline","comment-sparkle-solid","comments-outline","comments-solid","leaf-minus-outline","leaf-minus-solid","leaf-plus-outline","leaf-plus-solid","listening-outline","listening-solid","pencil-to-square-outline","pencil-to-square-solid","queue-outline","queue-solid","sprout-leaf-ellipsis-outline","sprout-leaf-ellipsis-solid","sprout-leaf-lightning-bolt-outline","sprout-leaf-lightning-bolt-solid","sprout-leaf-sync-outline","sprout-leaf-sync-solid","square-round-arrow-up-right-outline","square-round-arrow-up-right-solid","user-sprout-outline","user-sprout-solid"];
|
|
17
|
+
const newIconNames = [
|
|
18
|
+
...ExternalIconNames,
|
|
19
|
+
...GeneralIconNames,
|
|
20
|
+
...SproutIconNames,
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
// Map the current icon name to the new icon name
|
|
24
|
+
const mapIconName = (currentName) => {
|
|
25
|
+
if (IconMap[currentName]) {
|
|
26
|
+
return IconMap[currentName];
|
|
27
|
+
}
|
|
28
|
+
// Migrates icons using icon names that were deprecated in 2020
|
|
29
|
+
if (IconMap[deprecatedNames[currentName]]) {
|
|
30
|
+
return IconMap[deprecatedNames[currentName]];
|
|
31
|
+
}
|
|
32
|
+
// Checks if the icon name has already been migrated. Makes the codemod semi-idempotent.
|
|
33
|
+
if (
|
|
34
|
+
newIconNames.includes(currentName) ||
|
|
35
|
+
newIconNames.includes(`${currentName}-solid`) // All icons with a solid variant also have an outline variant, so we don't need to check both.
|
|
36
|
+
) {
|
|
37
|
+
return currentName;
|
|
38
|
+
}
|
|
39
|
+
return '';
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Perform regex replacements with the raw file text
|
|
43
|
+
function replaceIconNames(file, firstRegex, secondRegex) {
|
|
44
|
+
let source = file.source;
|
|
45
|
+
firstRegex?.forEach((result) => {
|
|
46
|
+
// Extract just the icon name from the regex result
|
|
47
|
+
const iconName = result.match(/['"]([^'"]+)['"]/g)[0].replace(/['"]/g, '');
|
|
48
|
+
const mappedIcon = mapIconName(iconName);
|
|
49
|
+
if (mappedIcon) {
|
|
50
|
+
const replacement = result.replace(iconName, mappedIcon);
|
|
51
|
+
source = source.replace(result, replacement);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
secondRegex?.forEach((result) => {
|
|
55
|
+
// Extract just the icon name from the regex result
|
|
56
|
+
const iconName = result.replace('ssiconsvg-', '').replace(/['"]/g, '');
|
|
57
|
+
const mappedIcon = mapIconName(iconName);
|
|
58
|
+
if (mappedIcon) {
|
|
59
|
+
const replacement = result
|
|
60
|
+
.replace('ssiconsvg-', 'seeds-svgs_')
|
|
61
|
+
.replace(iconName, mappedIcon);
|
|
62
|
+
source = source.replace(result, replacement);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
return source;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Racine components that accept icon names as top-level props.
|
|
69
|
+
// Users can pass in additional components in their codebase that accept icon names as props with "--components={componentName: [iconPropNames], ...}".
|
|
70
|
+
// A non-top-level prop example is the "iconName" prop nested under TokenInput's "tokens" prop. We can't fix those automatically.
|
|
71
|
+
const defaultComponents = {
|
|
72
|
+
Icon: ['name'],
|
|
73
|
+
'Icon.Toggle': ['activeName', 'inactiveName'],
|
|
74
|
+
Badge: ['iconName'],
|
|
75
|
+
TokenInput: ['iconName'],
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// We need to concatenate a few properties to get subcomponent names from AST (e.g., Icon.Toggle).
|
|
79
|
+
const getSubcomponentName = (element) => {
|
|
80
|
+
return `${element.value.name.object.name}.${element.value.name.property.name}`;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// Reformat the components option until it's the same format as defaultComponents above. It comes through like this:
|
|
84
|
+
// '0': 'Accordion:[icon]',
|
|
85
|
+
// '1': 'FacebookPMAux:[iconName',
|
|
86
|
+
// '2': 'secondaryIconName]',
|
|
87
|
+
// Wrap each word in quotes and join it all together with commas, then wrap it in bracket and parse it from JSON.
|
|
88
|
+
const optionToObject = (components) => {
|
|
89
|
+
const withQuotesAndCommas = components
|
|
90
|
+
.join(',')
|
|
91
|
+
// (\w|\.) = letters or periods. Handles component names with periods in them such as subcomponents.
|
|
92
|
+
.replace(/((\w|\.)+)/g, '"$1"');
|
|
93
|
+
try {
|
|
94
|
+
return JSON.parse('{' + withQuotesAndCommas + '}');
|
|
95
|
+
} catch (e) {
|
|
96
|
+
e.message = `
|
|
97
|
+
Failed to parse the components argument. Please verify that it is formatted correctly:
|
|
98
|
+
Format: --components="{ComponentName: ['nameProp']}"
|
|
99
|
+
- The argument should be an object wrapped in quotes
|
|
100
|
+
- Name props must be passed as an array because some components may have multiple relevant props.`;
|
|
101
|
+
throw e;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
module.exports = function transformer(file, api, options) {
|
|
106
|
+
const quote = options?.quote ?? 'single';
|
|
107
|
+
const components = options?.components
|
|
108
|
+
? {...defaultComponents, ...optionToObject(options.components)}
|
|
109
|
+
: defaultComponents;
|
|
110
|
+
const addComments = options?.addComments ?? true;
|
|
111
|
+
const shimComponentName = options?.shimName ?? '';
|
|
112
|
+
const shimComponentPath = options?.shimImportPath ?? '';
|
|
113
|
+
const addShimComponent = !!shimComponentName;
|
|
114
|
+
|
|
115
|
+
let source = file.source;
|
|
116
|
+
|
|
117
|
+
// Codemods run faster and cause fewer formatting issues if you only write files with modifications.
|
|
118
|
+
let hasModifications = false;
|
|
119
|
+
|
|
120
|
+
// Keep track of which components have usages that cannot be migrated and how many total usages per file cannot be migrated.
|
|
121
|
+
const unmigratedComponents = [];
|
|
122
|
+
let unmigratedCount = 0;
|
|
123
|
+
|
|
124
|
+
// Track how many components in the file were converted to the shim component.
|
|
125
|
+
let shimmedCount = 0;
|
|
126
|
+
// Count how many "Icon" components in particular are in the file so that we can determine if they were all shimmed.
|
|
127
|
+
// Other components can have their string icon names migrated, but only "Icon" can be shimmed.
|
|
128
|
+
let iconCount = 0;
|
|
129
|
+
|
|
130
|
+
// Regex: This code can migrate icon names outside of js files as well as some cases in js files that the codemod cannot identify.
|
|
131
|
+
// We do any regex-based replacements and then, if it's a js file, we parse the result to AST and look for any additional icon names to migrate.
|
|
132
|
+
|
|
133
|
+
// Regex 1: This regex looks for "icon" or "iconName" followed 0+ whitespace characters, a colon or equal sign,
|
|
134
|
+
// 0+ whitespace characters, then something wrapped in single or double quotes.
|
|
135
|
+
const firstRegex = file.source.match(
|
|
136
|
+
/(icon|iconName)\s*([:=])\s*(['"])([^'"]+)(['"])/g
|
|
137
|
+
);
|
|
138
|
+
// Regex 2: This regex looks for "ssiconsvg-" + any non-quote characters until the next quote.
|
|
139
|
+
// This appears in snap files and when manually rendering icons in non-React code like stache files.
|
|
140
|
+
const secondRegex = file.source.match(/(ssiconsvg-)([^'"]+)(['"])/g);
|
|
141
|
+
|
|
142
|
+
// If either regex found results, execute find+replace before parsing the file into AST.
|
|
143
|
+
if (firstRegex || secondRegex) {
|
|
144
|
+
const sourceWithReplacements = replaceIconNames(
|
|
145
|
+
file,
|
|
146
|
+
firstRegex,
|
|
147
|
+
secondRegex
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
// Only set hasModifications to true if the replacement step changed anything.
|
|
151
|
+
if (sourceWithReplacements !== file.source) {
|
|
152
|
+
hasModifications = true;
|
|
153
|
+
source = sourceWithReplacements;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// We want to short-circuit before parsing to AST for non-JS/TS files.
|
|
158
|
+
if (
|
|
159
|
+
// file.path is undefined during test runs only
|
|
160
|
+
file.path &&
|
|
161
|
+
!file.path.endsWith('js') &&
|
|
162
|
+
!file.path.endsWith('ts') &&
|
|
163
|
+
!file.path.endsWith('tsx')
|
|
164
|
+
) {
|
|
165
|
+
return hasModifications ? source : null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Now the AST modifications happen.
|
|
169
|
+
const j = api.jscodeshift;
|
|
170
|
+
const ast = j(source);
|
|
171
|
+
const icons = ast.find(j.JSXOpeningElement).filter((element) => {
|
|
172
|
+
let componentName = element.value.name.name;
|
|
173
|
+
if (element.value.name?.type === 'JSXMemberExpression') {
|
|
174
|
+
componentName = getSubcomponentName(element);
|
|
175
|
+
}
|
|
176
|
+
if (componentName === 'Icon') {
|
|
177
|
+
iconCount += 1;
|
|
178
|
+
}
|
|
179
|
+
return components[componentName];
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Save comments at the top of the file if they exist. Otherwise, they may be deleted if we modify the first import.
|
|
183
|
+
const originalFirstNode = ast.find(j.Program).get('body', 0).node;
|
|
184
|
+
const originalFirstComments = originalFirstNode.comments;
|
|
185
|
+
|
|
186
|
+
icons.forEach((iconPath) => {
|
|
187
|
+
const attrs = j(iconPath).find(j.JSXAttribute);
|
|
188
|
+
const componentName =
|
|
189
|
+
iconPath.value.name.name ?? getSubcomponentName(iconPath);
|
|
190
|
+
const nameProps = components[componentName];
|
|
191
|
+
attrs.forEach((path) => {
|
|
192
|
+
const {node} = path;
|
|
193
|
+
// nameProps is an array because some components accept icon names for multiple props
|
|
194
|
+
// (e.g., Icon.Toggle's activeName and inactiveName props)
|
|
195
|
+
if (nameProps.includes(node.name.name)) {
|
|
196
|
+
const value = node.value.value;
|
|
197
|
+
if (value) {
|
|
198
|
+
// Map string icon names
|
|
199
|
+
const mappedValue = mapIconName(value);
|
|
200
|
+
if (mappedValue) {
|
|
201
|
+
node.value = j.literal(mappedValue);
|
|
202
|
+
hasModifications = true;
|
|
203
|
+
} else {
|
|
204
|
+
// This case handles invalid string icon names.
|
|
205
|
+
unmigratedCount += 1;
|
|
206
|
+
!unmigratedComponents.includes(componentName) &&
|
|
207
|
+
unmigratedComponents.push(componentName);
|
|
208
|
+
}
|
|
209
|
+
} else if (node.value.expression.type === 'ConditionalExpression') {
|
|
210
|
+
// Handle ternary statements (eg, `name={isActive ? 'like' : 'like-outline'}`)
|
|
211
|
+
const oldConsequent = node.value.expression.consequent?.value;
|
|
212
|
+
const oldAlternate = node.value.expression.alternate?.value;
|
|
213
|
+
const newConsequent = oldConsequent
|
|
214
|
+
? mapIconName(oldConsequent)
|
|
215
|
+
: undefined;
|
|
216
|
+
const newAlternate = oldAlternate
|
|
217
|
+
? mapIconName(oldAlternate)
|
|
218
|
+
: undefined;
|
|
219
|
+
|
|
220
|
+
if (newConsequent && newAlternate) {
|
|
221
|
+
hasModifications = true;
|
|
222
|
+
node.value.expression.consequent = j.literal(newConsequent);
|
|
223
|
+
node.value.expression.alternate = j.literal(newAlternate);
|
|
224
|
+
} else {
|
|
225
|
+
unmigratedCount += 1;
|
|
226
|
+
!unmigratedComponents.includes(componentName) &&
|
|
227
|
+
unmigratedComponents.push(componentName);
|
|
228
|
+
}
|
|
229
|
+
} else {
|
|
230
|
+
// This case handles when the nameProp value is a variable.
|
|
231
|
+
if (componentName === 'Icon' && addShimComponent) {
|
|
232
|
+
iconPath.node.name = shimComponentName;
|
|
233
|
+
shimmedCount += 1;
|
|
234
|
+
hasModifications = true;
|
|
235
|
+
} else {
|
|
236
|
+
unmigratedCount += 1;
|
|
237
|
+
!unmigratedComponents.includes(componentName) &&
|
|
238
|
+
unmigratedComponents.push(componentName);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
if (addShimComponent && shimmedCount > 0) {
|
|
246
|
+
// Add the shim import after the racine import
|
|
247
|
+
ast
|
|
248
|
+
.find(j.ImportDeclaration, {
|
|
249
|
+
source: {value: '@sproutsocial/racine'},
|
|
250
|
+
})
|
|
251
|
+
.filter((element) => {
|
|
252
|
+
// There may be multiple Racine import statements. Only change the one that imports Icon.
|
|
253
|
+
return element.node.specifiers
|
|
254
|
+
.map((specifier) => specifier.imported.name)
|
|
255
|
+
.includes('Icon');
|
|
256
|
+
})
|
|
257
|
+
.insertAfter(
|
|
258
|
+
j.importDeclaration(
|
|
259
|
+
[j.importSpecifier(j.identifier(shimComponentName))],
|
|
260
|
+
j.literal(shimComponentPath)
|
|
261
|
+
)
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
// Checks for non-standard usages of the Icon component: styled(Icon) and typeof Icon
|
|
265
|
+
// We don't want to delete the import if Icon is used in this way in the file.
|
|
266
|
+
const hasOtherIconUsages =
|
|
267
|
+
source.match(/\(Icon\)/) || source.match(/typeof Icon/);
|
|
268
|
+
|
|
269
|
+
// If we migrated every Icon in the file to the shim component, remove the Icon import.
|
|
270
|
+
if (shimmedCount === iconCount && !hasOtherIconUsages) {
|
|
271
|
+
ast
|
|
272
|
+
.find(j.ImportDeclaration, {
|
|
273
|
+
source: {value: '@sproutsocial/racine'},
|
|
274
|
+
})
|
|
275
|
+
.replaceWith((path) => {
|
|
276
|
+
// Remove "Icon" from the imported items
|
|
277
|
+
const importedItems = path.node.specifiers.filter(
|
|
278
|
+
(specifier) => specifier.imported.name !== 'Icon'
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
// If Icon was the only item being imported from Racine, delete the import statement.
|
|
282
|
+
if (!importedItems.length) {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return j.importDeclaration(
|
|
287
|
+
importedItems,
|
|
288
|
+
j.literal(path.node.source.value)
|
|
289
|
+
);
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
hasModifications = true;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// If the first node has been modified or deleted, reattach the comments to the new first node.
|
|
297
|
+
const newFirstNode = ast.find(j.Program).get('body', 0).node;
|
|
298
|
+
if (newFirstNode !== originalFirstNode) {
|
|
299
|
+
newFirstNode.comments = originalFirstComments;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (addComments && unmigratedCount > 0) {
|
|
303
|
+
const comment = j.commentBlock(
|
|
304
|
+
`TODO (icon-library codemod): Please manually migrate icon names passed to ${unmigratedCount} component(s) in this file.
|
|
305
|
+
Look for usages of these components: ${unmigratedComponents.join(', ')}`
|
|
306
|
+
);
|
|
307
|
+
// Add this comment after any comments on the first node.
|
|
308
|
+
newFirstNode.comments = newFirstNode.comments
|
|
309
|
+
? [...newFirstNode.comments, comment]
|
|
310
|
+
: [comment];
|
|
311
|
+
hasModifications = true;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return hasModifications ? ast.toSource({quote}) : null;
|
|
315
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// We need the deprecated icon name mapping so that we can migrate icons still using the ancient names all the way to the new names.
|
|
2
|
+
// prettier-ignore
|
|
3
|
+
const deprecatedNames = {backtotop: 'back-to-top', 'circle-check-filled': 'circle-check', 'circle-check-no-fill': 'circle-check', 'circle-check-inverse-outline': 'circle-check-outline', 'circle-check-inverse': 'circle-check-outline', 'circle+-filled': 'circle+', 'circlex-filled': 'circlex', 'circle+-nofill': 'circle+', 'circlex-nofill': 'circlex', creditcard: 'credit-card', 'direct-message': 'messages', 'facebook-nofill': 'facebook', googleanalytics: 'google-analytics-color', 'instagram-brand-keyword': 'hashtag', 'help-white': 'help', 'info-white': 'info', 'instagram-nofill': 'instagram', 'key-circle': 'key', 'key-square': 'key', 'linkedin-nofill': 'linkedin', 'listening-home': 'listening', 'location-pub': 'location', 'location-pub-outline': 'location-outline', 'publishing-calendar': 'calendar', qrcode: 'qr-code', 'sparkles-solid': 'sparkles', 'star-inverse': 'star-outline', 'triangle-white': 'triangle', 'triangle-nofill': 'triangle', 'tripadvisor-circle-filled': 'tripadvisor-circle', 'tripadvisor-circle-empty': 'tripadvisor-circle-outline', 'tumblr-square': 'tumblr', 'tumblr-nofill': 'tumblr', 'twitter-business-mention': 'search', 'verified-nofill': 'verified', 'window-maximize-solid': 'window-maximize'};
|
|
4
|
+
|
|
5
|
+
// Mapping from old icon names to new icon names
|
|
6
|
+
// prettier-ignore
|
|
7
|
+
const IconMap = {'active-listener': 'listening-outline', 'add-item': 'plus-outline', 'add-keyword': 'plus-outline', 'add-team-member': 'user-plus-outline', 'add-variable': 'curly-brackets-plus-outline', 'address-card-outline': 'profile-card-outline', 'address-card-solid': 'profile-card-solid', ads: 'dollar-outline', 'advocacy-outline': 'advocacy-outline', advocacy: 'advocacy-solid', 'approval-indicator-outline': 'stamp-outline', 'approval-indicator': 'stamp-solid', archive: 'file-box-outline', 'arrow-down-line': 'arrow-down-to-line-outline', 'arrow-down': 'arrow-down-outline', 'arrow-left-line': 'arrow-left-to-line-outline', 'arrow-left': 'arrow-left-outline', 'arrow-right-line': 'arrow-right-to-line-outline', 'arrow-right': 'arrow-right-outline', 'arrow-up-line': 'arrow-up-to-line-outline', 'arrow-up': 'arrow-up-outline', arrows: 'arrows-up-down-left-right-outline', 'asset-library-outline': 'asset-library-outline', 'asset-library': 'asset-library-solid', assign: 'sitemap-outline', atom: 'atom-outline', audio: 'audio-outline', 'back-to-top': 'arrow-up-outline', 'bambu-icon-outline': 'bambu-outline', 'bambu-icon': 'bambu-solid', barcode: 'barcode-outline', basketball: 'basketball-outline', 'bell-outline': 'bell-outline', bold: 'bold-outline', book: 'book-outline', 'bookmark-filled': 'bookmark-solid', bookmark: 'bookmark-outline', bot: 'robot-outline', browser: 'window-full-outline', 'bulk-select': 'square-check-outline', business: 'briefcase-outline', 'calendar-outline': 'calendar-outline', calendar: 'calendar-solid', 'camera-outline': 'camera-outline', 'camera-story': 'camera-story-solid', camera: 'camera-solid', campaign: 'megaphone-outline', carousel: 'carousel-outline', 'cart-plus': 'cart-plus-outline', check: 'check-outline', 'chevron-down-filled': 'caret-down-outline', 'chevron-down': 'chevron-down-outline', 'chevron-left': 'chevron-left-outline', 'chevron-right': 'chevron-right-outline', 'chevron-up-down-filled': 'caret-up-down-outline', 'chevron-up-filled': 'caret-up-outline', 'chevron-up': 'chevron-up-outline', 'circle-check-outline': 'circle-check-outline', 'circle-check': 'circle-check-solid', circle: 'circle-no-fill-outline', 'circle+': 'plus-outline', circles: 'large-circle-small-circle-outline', circleX: 'circle-x-outline', circlex: 'circle-x-outline', 'click-to-view': 'hand-pointer-clicking-outline', clicks: 'pointer-outline', 'clipboard-outline': 'clipboard-outline', clipboard: 'clipboard-solid', clock: 'clock-outline', 'closed-captioning': 'closed-caption-outline', cloud: 'cloud-outline', code: 'code-outline', columns: 'columns-outline', 'comment-alt-outline': 'comments-outline', 'comment-alt': 'comment-solid', 'comment-lines-alt-outline': 'comment-outline', comment: 'comments-outline', 'compact-density': 'bars-density-small-outline', 'compact-indicator': 'bars-density-small-outline', comparison: 'diamond-vs-outline', competitor: 'office-building-outline', compose: 'pencil-to-square-outline', 'content-suggestions': 'comment-sparkle-outline', 'credit-card': 'credit-card-outline', crop: 'crop-outline', crown: 'crown-outline', dashboard: 'gauge-outline', 'deconstructed-negative-sentiment': 'expression-frown-outline', 'deconstructed-neutral-sentiment': 'expression-neutral-outline', 'deconstructed-positive-sentiment': 'expression-smile-open-outline', discovery: 'compass-outline', 'dislike-outline': 'thumbs-down-outline', dislike: 'thumbs-down-solid', 'dm-link-outline': 'comment-plus-outline', 'dm-link': 'comment-plus-solid', 'doesnt-recommend': 'comment-star-slash-outline', dotdotdot: 'ellipsis-horizontal-outline', download: 'arrow-down-to-bracket-outline', 'drafts-outline': 'paper-outline', drafts: 'paper-solid', 'duplicate-outline': 'papers-outline', duplicate: 'papers-solid', 'emoji-outline': 'face-smile-outline', emoji: 'face-smile-solid', 'empty-image': 'camera-x-outline', 'engagement-per-post': 'comment-outline', engagements: 'comments-outline', error: 'circle-exclamation-outline', 'exchange-alt': 'arrows-left-right-outline', 'expanded-indicator': 'bars-density-large-outline', export: 'square-round-arrow-up-right-outline', 'extended-circles': 'large-circle-small-circle-outline', 'external-link-alt': 'squares-arrow-up-right-outline', 'external-link': 'square-round-arrow-up-right-outline', 'extreme-negative-sentiment': 'face-frown-open-outline', 'eye-outline': 'eye-outline', 'eye-slash-outline': 'eye-slash-outline', 'eye-slash': 'eye-slash-solid', eye: 'eye-solid', 'facebook-branded-content-outline': 'handshake-outline', 'facebook-branded-content': 'handshake-solid', feeds: 'unordered-list-outline', female: 'symbol-venus-outline', 'file-chart-line': 'paper-bars-outline', 'file-edit': 'paper-pencil-outline', 'file-times-solid': 'paper-x-outline', filter: 'filter-outline', 'flag-outline': 'flag-outline', flag: 'flag-solid', 'folder-open': 'folder-open-outline', folder: 'folder-outline', 'follow-outline': 'user-plus-outline', follow: 'user-plus-solid', 'follower-increase': 'user-arrow-up-outline', following: 'user-check-outline', font: 'font-case-outline', 'full-access': 'circle-fill-outline', gear: 'gear-outline', gears: 'gear-outline', glasses: 'glasses-outline', globe: 'globe-outline', grip: 'grip-lines-vertical-outline', h1: 'h1-outline', h2: 'h2-outline', h3: 'h3-outline', h4: 'h3-outline', hamburger: 'horizontal-lines-outline', hashtag: 'hashtag-outline', headset: 'headset-outline', 'heart-outline': 'heart-outline', heart: 'heart-solid', heartbeat: 'heart-pulse-outline', 'help-alt': 'question-mark-outline', help: 'circle-question-outline', hiking: 'person-hiking-outline', history: 'clock-rotate-left-outline', home: 'house-outline', hourglass: 'hourglass-outline', 'image-caption': 'rectangle-caption-outline', image: 'image-outline', images: 'images-outline', 'impressions-per-post': 'comment-eye-outline', impressions: 'eye-outline', 'inactive-listener': 'file-box-outline', 'inbox-action': 'inbox-check-outline', 'inbox-views': 'inboxes-outline', inbox: 'inbox-outline', indicator: 'circle-fill-outline', industry: 'office-building-outline', info: 'circle-i-outline', 'internal-activity-outline': 'clock-rotate-left-outline', 'internal-activity': 'clock-rotate-left-solid', italic: 'italics-outline', key: 'key-outline', keyboard: 'keyboard-outline', 'laptop-phone': 'laptop-mobile-outline', 'large-density': 'bars-density-large-outline', lift: 'circle-dollar-arrow-up-outline', 'like-outline': 'thumbs-up-outline', like: 'thumbs-up-solid', link: 'link-outline', 'list-ol': 'ordered-list-outline', listening: 'listening-outline', lists: 'unordered-list-outline', 'location-outline': 'location-pin-outline', location: 'location-pin-solid', lock: 'lock-outline', 'magic-wand': 'magic-wand-outline', male: 'symbol-mars-outline', mention: 'symbol-at-outline', 'message-preview-outline': 'eye-outline', 'message-preview': 'eye-solid', message: 'comment-outline', 'messages-outline': 'envelope-outline', messages: 'envelope-solid', 'metric-table': 'metric-table-outline', minus: 'minus-outline', mobile: 'mobile-outline', monitor: 'pulse-outline', moon: 'moon-crescent-outline', 'negative-sentiment': 'face-frown-outline', 'neutral-positive-sentiment': 'face-smile-outline', 'neutral-sentiment': 'face-neutral-outline', 'new-trend': 'fire-outline', newspaper: 'newspaper-outline', 'no-access': 'circle-minus-outline', 'no-notifications-filled': 'bell-slash-solid', 'no-notifications': 'bell-slash-outline', notepad: 'clipboard-outline', 'notifications-publishing': 'alarm-clock-outline', notifications: 'bell-outline', offline: 'wifi-slash-outline', online: 'wifi-outline', 'paid-promotion-outline': 'circle-dollar-outline', 'paid-promotion': 'circle-dollar-solid', paid: 'calculator-outline', paint: 'paint-can-outline', palette: 'art-palette-outline', paperclip: 'paperclip-outline', pause: 'pause-outline', 'pencil-outline': 'pencil-outline', pencil: 'pencil-solid', person: 'user-outline', phone: 'phone-outline', 'pinterest-boards-outline': 'mood-boards-outline', 'pinterest-boards': 'mood-boards-solid', 'play-circle': 'play-outline', play: 'play-outline', plug: 'plug-outline', plus: 'plus-outline', 'positive-sentiment': 'face-smile-open-outline', 'power-up-outline': 'lightning-bolt-outline', 'power-up': 'lightning-bolt-solid', 'profile-connect': 'leaf-plus-outline', 'profile-disconnect': 'leaf-minus-outline', 'publishing-outline': 'paper-plane-outline', publishing: 'paper-plane-outline', 'puzzle-piece': 'puzzle-piece-outline', 'qr-code': 'qr-code-outline', queue: 'queue-outline', recommendation: 'comment-star-outline', referrals: 'star-full-outline', refresh: 'arrows-rotate-outline', rejected: 'ban-outline', 'reply-outline': 'reply-outline', reply: 'reply-solid', 'reporting-period': 'calendar-range-outline', reporting: 'chart-bar-simple-outline', 'reports-home': 'four-squares-outline', reports: 'chart-pie-outline', retweet: 'repost-outline', rss: 'rss-outline', sales: 'dollar-outline', 'save-assets': 'asset-library-plus-outline', 'saved-messages': 'comment-bookmark-outline', 'saved-reply-outline': 'bookmark-reply-outline', 'saved-reply': 'bookmark-reply-solid', search: 'magnifying-glass-outline', 'sent-message-outline': 'inbox-arrow-up-outline', 'sent-message': 'inbox-arrow-up-solid', share: 'square-round-arrow-up-right-outline', 'shopping-bag-outline': 'shopping-bag-outline', 'shopping-bag': 'shopping-bag-solid', 'show-navigation': 'browser-nav-bar-outline', 'small-density': 'bars-density-medium-outline', smiley: 'face-smile-outline', 'some-access': 'circle-half-outline', sparkles: 'sparkle-outline', 'spike-alert': 'comment-exclamation-outline', 'star-half-alt-solid': 'star-half-outline', 'star-of-life': 'star-of-life-outline', 'star-outline': 'star-outline', star: 'star-full-outline', 'sticky-note-outline': 'note-outline', 'sticky-note': 'note-solid', story: 'camera-story-outline', stories: 'story-outline', suggestions: 'comment-light-bulb-outline', sun: 'sun-outline', 'tag-outline': 'tag-outline', tag: 'tag-solid', 'targeting-outline': 'bullseye-arrow-outline', targeting: 'bullseye-arrow-solid', 'tasks-outline': 'thumbtack-outline', tasks: 'thumbtack-solid', 'team-conversation-outline': 'sprout-leaf-lightning-bolt-outline', 'team-conversation': 'sprout-leaf-lightning-bolt-solid', team: 'users-outline', 'text-asset': 'text-serif-outline', text: 'text-serif-outline', times: 'x-outline', tools: 'screwdriver-hammer-outline', 'trash-can-outline': 'trash-outline', 'trash-can': 'trash-solid', 'trend-down': 'arrow-right-down-outline', 'trend-up': 'arrow-right-up-outline', 'trend-neutral': 'arrow-right-outline', trends: 'fire-outline', 'triangle-black': 'triangle-outline', triangle: 'triangle-exclamation-outline', 'trophy-outline': 'trophy-outline', 'unfollow-outline': 'user-x-outline', unfollow: 'user-x-solid', unlink: 'link-slash-outline', unlock: 'unlock-outline', upload: 'arrow-up-from-bracket-outline', 'user-circle': 'user-sprout-outline', users: 'users-outline', 'video-camera-story': 'video-camera-story-outline', 'video-camera': 'video-camera-outline', vip: 'gem-outline', weight: 'weight-outline', 'window-maximize': 'window-modal-outline', 'window-minimize': 'window-minimize-outline', 'window-regular': 'browser-outline', 'window-restore': 'browser-restore-outline', x: 'x-outline', 'tripadvisor-circle-filled': 'tripadvisor-cicle-solid', 'tripadvisor-circle-empty': 'tripadvisor-circle-outline', 'flat-positive-sentiment': 'face-smile-outline', 'flat-negative-sentiment': 'face-frown-outline', 'flat-neutral-sentiment': 'face-neutral-outline'};
|
|
8
|
+
|
|
9
|
+
// Map the current icon name to the new icon name
|
|
10
|
+
const mapIconName = (currentName) => {
|
|
11
|
+
if (IconMap[currentName]) {
|
|
12
|
+
return IconMap[currentName];
|
|
13
|
+
}
|
|
14
|
+
// Migrates icons using icon names that were deprecated in 2020
|
|
15
|
+
if (IconMap[deprecatedNames[currentName]]) {
|
|
16
|
+
return IconMap[deprecatedNames[currentName]];
|
|
17
|
+
}
|
|
18
|
+
return '';
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
module.exports = function transformer(file, api, options) {
|
|
22
|
+
const quote = options?.quote ?? 'single';
|
|
23
|
+
const j = api.jscodeshift;
|
|
24
|
+
const ast = j(file.source);
|
|
25
|
+
let hasModifications = false;
|
|
26
|
+
|
|
27
|
+
// Because we do not filter down the literals we find in any way to confirm they are icon-related,
|
|
28
|
+
// we may end up inadvertently mapping non-icon-name usages of strings that happen to be icon names.
|
|
29
|
+
// Thus, it is *extremely important* to manually check the results of this codemod!
|
|
30
|
+
// Otherwise, non-icon-related bugs may be introduced.
|
|
31
|
+
ast.find(j.Literal).forEach((path) => {
|
|
32
|
+
const value = path.value.value;
|
|
33
|
+
if (value) {
|
|
34
|
+
const mappedValue = mapIconName(value);
|
|
35
|
+
if (mappedValue) {
|
|
36
|
+
path.value.value = mappedValue;
|
|
37
|
+
hasModifications = true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return hasModifications ? ast.toSource({quote}) : null;
|
|
43
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sproutsocial/racine",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.4.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"files": [
|
|
6
6
|
"__flow__",
|
|
@@ -150,7 +150,7 @@
|
|
|
150
150
|
"jest": "27.x.x",
|
|
151
151
|
"jest-axe": "6.0.0",
|
|
152
152
|
"jest-styled-components": "7.0.0-beta.1",
|
|
153
|
-
"jscodeshift": "^0.
|
|
153
|
+
"jscodeshift": "^0.13.0",
|
|
154
154
|
"json-to-scss": "^1.6.2",
|
|
155
155
|
"lint-staged": "^13.0.3",
|
|
156
156
|
"moment": "^2.29.4",
|