@atlaskit/eslint-plugin-design-system 10.12.3 → 10.12.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/cjs/rules/no-legacy-icons/checks.js +100 -52
- package/dist/cjs/rules/no-legacy-icons/helpers.js +95 -22
- package/dist/cjs/rules/no-legacy-icons/index.js +5 -3
- package/dist/cjs/rules/no-legacy-icons/upcoming-icons.js +7 -0
- package/dist/es2019/rules/no-legacy-icons/checks.js +85 -41
- package/dist/es2019/rules/no-legacy-icons/helpers.js +80 -10
- package/dist/es2019/rules/no-legacy-icons/index.js +5 -3
- package/dist/es2019/rules/no-legacy-icons/upcoming-icons.js +1 -0
- package/dist/esm/rules/no-legacy-icons/checks.js +101 -53
- package/dist/esm/rules/no-legacy-icons/helpers.js +94 -21
- package/dist/esm/rules/no-legacy-icons/index.js +5 -3
- package/dist/esm/rules/no-legacy-icons/upcoming-icons.js +1 -0
- package/dist/types/rules/no-legacy-icons/checks.d.ts +4 -1
- package/dist/types/rules/no-legacy-icons/helpers.d.ts +25 -14
- package/dist/types/rules/no-legacy-icons/upcoming-icons.d.ts +1 -0
- package/dist/types-ts4.5/rules/no-legacy-icons/checks.d.ts +4 -1
- package/dist/types-ts4.5/rules/no-legacy-icons/helpers.d.ts +25 -14
- package/dist/types-ts4.5/rules/no-legacy-icons/upcoming-icons.d.ts +1 -0
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
|
-
import { canAutoMigrateNewIconBasedOnSize, canMigrateColor, createAutoMigrationError, createCantFindSuitableReplacementError, createCantMigrateColorError, createCantMigrateFunctionUnknownError, createCantMigrateIdentifierError, createCantMigrateReExportError, createCantMigrateSizeUnknown, createCantMigrateSpreadPropsError, createGuidance, createHelpers, getMigrationMapObject, isSize, locToString } from './helpers';
|
|
2
|
+
import { addToListOfRanges, canAutoMigrateNewIconBasedOnSize, canMigrateColor, createAutoMigrationError, createCantFindSuitableReplacementError, createCantMigrateColorError, createCantMigrateFunctionUnknownError, createCantMigrateIdentifierError, createCantMigrateIdentifierMapOrArrayError, createCantMigrateReExportError, createCantMigrateSizeUnknown, createCantMigrateSpreadPropsError, createGuidance, createHelpers, getMigrationMapObject, getUpcomingIcons, isInRangeList, isSize, locToString } from './helpers';
|
|
3
3
|
export const createChecks = context => {
|
|
4
4
|
//create global variables to be shared by the checks
|
|
5
5
|
const {
|
|
@@ -17,6 +17,9 @@ export const createChecks = context => {
|
|
|
17
17
|
const shouldErrorForAutoMigration = getConfigFlag('shouldErrorForAutoMigration', true);
|
|
18
18
|
const isQuietMode = getConfigFlag('quiet', false);
|
|
19
19
|
|
|
20
|
+
// Sorted list of ranges
|
|
21
|
+
let errorRanges = [];
|
|
22
|
+
|
|
20
23
|
/**
|
|
21
24
|
* Adds the legacy Icon and new button imports to the correct global arrays to be used by the other checks
|
|
22
25
|
* @param node The import node found by ESLint
|
|
@@ -56,8 +59,8 @@ export const createChecks = context => {
|
|
|
56
59
|
if (isNodeOfType(node, 'VariableDeclaration')) {
|
|
57
60
|
const isExported = node.parent && isNodeOfType(node.parent, 'ExportNamedDeclaration');
|
|
58
61
|
for (const decl of node.declarations) {
|
|
59
|
-
if (isNodeOfType(decl, 'VariableDeclarator') && 'init'
|
|
60
|
-
if (decl.init.name
|
|
62
|
+
if (isNodeOfType(decl, 'VariableDeclarator') && Object.keys(decl).includes('init') && Object.keys(decl).includes('id') && decl.init && decl.id && 'name' in decl.id && decl.id.name && isNodeOfType(decl.init, 'Identifier')) {
|
|
63
|
+
if (Object.keys(legacyIconImports).includes(decl.init.name)) {
|
|
61
64
|
legacyIconImports[decl.id.name] = {
|
|
62
65
|
packageName: legacyIconImports[decl.init.name].packageName,
|
|
63
66
|
exported: legacyIconImports[decl.init.name].exported || isExported
|
|
@@ -77,16 +80,17 @@ export const createChecks = context => {
|
|
|
77
80
|
const checkExportDefaultDeclaration = node => {
|
|
78
81
|
let exportName = '';
|
|
79
82
|
let packageName = '';
|
|
80
|
-
if ('declaration'
|
|
83
|
+
if (Object.keys(node).includes('declaration') && node.declaration && isNodeOfType(node.declaration, 'Identifier') && Object.keys(legacyIconImports).includes(node.declaration.name)) {
|
|
81
84
|
packageName = legacyIconImports[node.declaration.name].packageName;
|
|
82
85
|
exportName = 'Default export';
|
|
83
|
-
} else if ('declaration'
|
|
86
|
+
} else if (Object.keys(node).includes('declaration') && node.declaration && isNodeOfType(node.declaration, 'AssignmentExpression') && isNodeOfType(node.declaration.left, 'Identifier') && isNodeOfType(node.declaration.right, 'Identifier') && Object.keys(legacyIconImports).includes(node.declaration.right.name)) {
|
|
84
87
|
packageName = legacyIconImports[node.declaration.right.name].packageName;
|
|
85
88
|
exportName = node.declaration.left.name;
|
|
86
89
|
} else {
|
|
87
90
|
return;
|
|
88
91
|
}
|
|
89
92
|
createCantMigrateReExportError(node, packageName, exportName, errorsManual);
|
|
93
|
+
addToListOfRanges(node, errorRanges);
|
|
90
94
|
guidance[locToString(node)] = createGuidance(packageName);
|
|
91
95
|
};
|
|
92
96
|
|
|
@@ -96,19 +100,21 @@ export const createChecks = context => {
|
|
|
96
100
|
*/
|
|
97
101
|
const checkExportNamedVariables = node => {
|
|
98
102
|
// export {default as AddIcon} from '@atlaskit/icon/glyph/add';
|
|
99
|
-
if (node.source && isNodeOfType(node.source, 'Literal') &&
|
|
103
|
+
if (node.source && isNodeOfType(node.source, 'Literal') && Object.keys(node.source).includes('value')) {
|
|
100
104
|
const moduleSource = node.source.value;
|
|
101
105
|
if (typeof moduleSource === 'string' && ['@atlaskit/icon/glyph/', '@atlaskit/icon-object/glyph/'].find(val => moduleSource.startsWith(val)) && node.specifiers.length) {
|
|
102
106
|
for (const spec of node.specifiers) {
|
|
103
107
|
createCantMigrateReExportError(spec, moduleSource, spec.exported.name, errorsManual);
|
|
108
|
+
addToListOfRanges(spec, errorRanges);
|
|
104
109
|
guidance[locToString(spec)] = createGuidance(moduleSource);
|
|
105
110
|
}
|
|
106
111
|
}
|
|
107
112
|
} else if (node.declaration && isNodeOfType(node.declaration, 'VariableDeclaration')) {
|
|
108
113
|
// export const Icon = AddIcon;
|
|
109
114
|
for (const decl of node.declaration.declarations) {
|
|
110
|
-
if (isNodeOfType(decl, 'VariableDeclarator') && 'init'
|
|
115
|
+
if (isNodeOfType(decl, 'VariableDeclarator') && Object.keys(decl).includes('init') && decl.init && isNodeOfType(decl.init, 'Identifier') && Object.keys(legacyIconImports).includes(decl.init.name)) {
|
|
111
116
|
createCantMigrateReExportError(node, legacyIconImports[decl.init.name].packageName, decl.init.name, errorsManual);
|
|
117
|
+
addToListOfRanges(node, errorRanges);
|
|
112
118
|
guidance[locToString(node)] = createGuidance(legacyIconImports[decl.init.name].packageName);
|
|
113
119
|
}
|
|
114
120
|
}
|
|
@@ -120,13 +126,14 @@ export const createChecks = context => {
|
|
|
120
126
|
* export { AddIcon, CrossIcon as default }
|
|
121
127
|
*/
|
|
122
128
|
for (const spec of node.specifiers) {
|
|
123
|
-
if (spec.local.name
|
|
129
|
+
if (Object.keys(legacyIconImports).includes(spec.local.name)) {
|
|
124
130
|
//update legacy imports to be exported
|
|
125
131
|
legacyIconImports[spec.local.name] = {
|
|
126
132
|
packageName: legacyIconImports[spec.local.name].packageName,
|
|
127
133
|
exported: true
|
|
128
134
|
};
|
|
129
135
|
createCantMigrateReExportError(spec, legacyIconImports[spec.local.name].packageName, spec.exported.name, errorsManual);
|
|
136
|
+
addToListOfRanges(spec, errorRanges);
|
|
130
137
|
guidance[locToString(spec)] = createGuidance(legacyIconImports[spec.local.name].packageName);
|
|
131
138
|
}
|
|
132
139
|
}
|
|
@@ -141,8 +148,9 @@ export const createChecks = context => {
|
|
|
141
148
|
if (!isNodeOfType(node, 'Identifier')) {
|
|
142
149
|
return;
|
|
143
150
|
}
|
|
144
|
-
if (node.name && node.name
|
|
145
|
-
|
|
151
|
+
if (node.name && Object.keys(legacyIconImports).includes(node.name) && legacyIconImports[node.name].packageName) {
|
|
152
|
+
createCantMigrateIdentifierMapOrArrayError(node, legacyIconImports[node.name].packageName, node.name, errorsManual);
|
|
153
|
+
addToListOfRanges(node, errorRanges);
|
|
146
154
|
guidance[locToString(node)] = createGuidance(legacyIconImports[node.name].packageName);
|
|
147
155
|
}
|
|
148
156
|
};
|
|
@@ -161,24 +169,44 @@ export const createChecks = context => {
|
|
|
161
169
|
if (!isNodeOfType(node.parent, 'JSXExpressionContainer') || !isNodeOfType(node.parent.parent, 'JSXAttribute') || !isNodeOfType(node.parent.parent.parent, 'JSXOpeningElement')) {
|
|
162
170
|
return;
|
|
163
171
|
}
|
|
164
|
-
if (node.name
|
|
172
|
+
if (Object.keys(legacyIconImports).includes(node.name) && isNodeOfType(node.parent.parent.name, 'JSXIdentifier') && node.parent.parent.name.name !== 'LEGACY_fallbackIcon') {
|
|
165
173
|
var _migrationMapObject$s;
|
|
166
174
|
const migrationMapObject = getMigrationMapObject(legacyIconImports[node.name].packageName);
|
|
175
|
+
const upcomingIcon = getUpcomingIcons(legacyIconImports[node.name].packageName);
|
|
167
176
|
const newIcon = migrationMapObject === null || migrationMapObject === void 0 ? void 0 : migrationMapObject.newIcon;
|
|
168
|
-
const isNewIconMigratable = canAutoMigrateNewIconBasedOnSize(migrationMapObject === null || migrationMapObject === void 0 ? void 0 : (_migrationMapObject$s = migrationMapObject.sizeGuidance) === null || _migrationMapObject$s === void 0 ? void 0 : _migrationMapObject$s.medium);
|
|
177
|
+
const isNewIconMigratable = canAutoMigrateNewIconBasedOnSize(upcomingIcon ? upcomingIcon.sizeGuidance.medium : migrationMapObject === null || migrationMapObject === void 0 ? void 0 : (_migrationMapObject$s = migrationMapObject.sizeGuidance) === null || _migrationMapObject$s === void 0 ? void 0 : _migrationMapObject$s.medium);
|
|
169
178
|
const isInNewButton = isNodeOfType(node.parent.parent.parent.name, 'JSXIdentifier') && newButtonImports.has(node.parent.parent.parent.name.name);
|
|
170
|
-
if (newIcon && isInNewButton && isNewIconMigratable) {
|
|
179
|
+
if (newIcon && isInNewButton && isNewIconMigratable || upcomingIcon && isInNewButton && isNewIconMigratable) {
|
|
171
180
|
createAutoMigrationError(node, legacyIconImports[node.name].packageName, node.name, errorsAuto);
|
|
181
|
+
addToListOfRanges(node, errorRanges);
|
|
172
182
|
guidance[locToString(node)] = createGuidance(legacyIconImports[node.name].packageName, isInNewButton, 'medium');
|
|
173
|
-
} else if (!newIcon || !isNewIconMigratable) {
|
|
183
|
+
} else if (!newIcon && !upcomingIcon || !isNewIconMigratable) {
|
|
174
184
|
createCantFindSuitableReplacementError(node, legacyIconImports[node.name].packageName, node.name, errorsManual);
|
|
185
|
+
addToListOfRanges(node, errorRanges);
|
|
175
186
|
guidance[locToString(node)] = createGuidance(legacyIconImports[node.name].packageName, isInNewButton);
|
|
176
187
|
} else if (!isInNewButton) {
|
|
177
188
|
createCantMigrateFunctionUnknownError(node, legacyIconImports[node.name].packageName, node.name, errorsManual);
|
|
189
|
+
addToListOfRanges(node, errorRanges);
|
|
178
190
|
guidance[locToString(node)] = createGuidance(legacyIconImports[node.name].packageName, isInNewButton);
|
|
179
191
|
}
|
|
180
192
|
}
|
|
181
193
|
};
|
|
194
|
+
const checkIconReference = node => {
|
|
195
|
+
//check the reference to see if it's a legacy icon, if not exit early
|
|
196
|
+
if (!Object.keys(legacyIconImports).includes(node.name)) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
//if this is an import statement then exit early
|
|
200
|
+
if (node.parent && (isNodeOfType(node.parent, 'ImportSpecifier') || isNodeOfType(node.parent, 'ImportDefaultSpecifier'))) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
//if in Fallback prop, do not error
|
|
204
|
+
if (node.parent && node.parent.parent && isNodeOfType(node.parent.parent, 'JSXAttribute') && isNodeOfType(node.parent.parent.name, 'JSXIdentifier') && node.parent.parent.name.name === 'LEGACY_fallbackIcon') {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
// manually error
|
|
208
|
+
createCantMigrateIdentifierError(node, legacyIconImports[node.name].packageName, node.name, errorsManual);
|
|
209
|
+
};
|
|
182
210
|
|
|
183
211
|
/**
|
|
184
212
|
* Checks if a legacy icon is being rendered and stores the errors in the global array
|
|
@@ -196,8 +224,8 @@ export const createChecks = context => {
|
|
|
196
224
|
}
|
|
197
225
|
const name = node.openingElement.name.name;
|
|
198
226
|
// Legacy icons rendered as JSX elements
|
|
199
|
-
if (
|
|
200
|
-
var _node$parent2, _node$parent2$parent, _node$parent3, _node$parent3$parent, _node$parent3$parent$, _size;
|
|
227
|
+
if (Object.keys(legacyIconImports).includes(name)) {
|
|
228
|
+
var _node$parent2, _node$parent2$parent, _node$parent3, _node$parent3$parent, _node$parent3$parent$, _size, _size2;
|
|
201
229
|
// Determine if inside a new button - if so:
|
|
202
230
|
// - Assume spread props are safe - still error if props explicitly set to unmigratable values
|
|
203
231
|
let insideNewButton = false;
|
|
@@ -268,13 +296,15 @@ export const createChecks = context => {
|
|
|
268
296
|
hasManualMigration = true;
|
|
269
297
|
}
|
|
270
298
|
const migrationMapObject = getMigrationMapObject(legacyIconImports[name].packageName);
|
|
299
|
+
const upcomingIcon = getUpcomingIcons(legacyIconImports[name].packageName);
|
|
271
300
|
const newIcon = migrationMapObject === null || migrationMapObject === void 0 ? void 0 : migrationMapObject.newIcon;
|
|
272
|
-
const isNewIconMigratable = canAutoMigrateNewIconBasedOnSize(migrationMapObject === null || migrationMapObject === void 0 ? void 0 : migrationMapObject.sizeGuidance[(
|
|
273
|
-
if (!hasManualMigration && newIcon && isNewIconMigratable) {
|
|
301
|
+
const isNewIconMigratable = canAutoMigrateNewIconBasedOnSize(upcomingIcon ? upcomingIcon.sizeGuidance[(_size = size) !== null && _size !== void 0 ? _size : 'medium'] : migrationMapObject === null || migrationMapObject === void 0 ? void 0 : migrationMapObject.sizeGuidance[(_size2 = size) !== null && _size2 !== void 0 ? _size2 : 'medium']);
|
|
302
|
+
if (!hasManualMigration && (newIcon || upcomingIcon) && isNewIconMigratable) {
|
|
274
303
|
createAutoMigrationError(node, legacyIconImports[name].packageName, name, errorsAuto);
|
|
275
|
-
} else if ((!newIcon || !isNewIconMigratable) && size) {
|
|
276
|
-
createCantFindSuitableReplacementError(node, legacyIconImports[name].packageName, name, errorsManual, migrationMapObject ? true : false);
|
|
304
|
+
} else if ((!newIcon && !upcomingIcon || !isNewIconMigratable) && size) {
|
|
305
|
+
createCantFindSuitableReplacementError(node, legacyIconImports[name].packageName, name, errorsManual, upcomingIcon ? true : migrationMapObject ? true : false);
|
|
277
306
|
}
|
|
307
|
+
addToListOfRanges(node, errorRanges);
|
|
278
308
|
guidance[locToString(node)] = createGuidance(legacyIconImports[name].packageName, insideNewButton, size && isSize(size) ? size : undefined);
|
|
279
309
|
}
|
|
280
310
|
};
|
|
@@ -284,10 +314,11 @@ export const createChecks = context => {
|
|
|
284
314
|
* @param node The function call node found by ESLint
|
|
285
315
|
*/
|
|
286
316
|
const checkCallExpression = node => {
|
|
287
|
-
if ('arguments'
|
|
317
|
+
if (Object.keys(node).includes('arguments') && node.arguments.length) {
|
|
288
318
|
for (const arg of node.arguments) {
|
|
289
|
-
if (isNodeOfType(arg, 'Identifier') && arg.name
|
|
319
|
+
if (isNodeOfType(arg, 'Identifier') && Object.keys(legacyIconImports).includes(arg.name) && legacyIconImports[arg.name].packageName) {
|
|
290
320
|
createCantMigrateFunctionUnknownError(node, legacyIconImports[arg.name].packageName, arg.name, errorsManual);
|
|
321
|
+
addToListOfRanges(node, errorRanges);
|
|
291
322
|
guidance[locToString(node)] = createGuidance(legacyIconImports[arg.name].packageName);
|
|
292
323
|
}
|
|
293
324
|
}
|
|
@@ -301,20 +332,29 @@ export const createChecks = context => {
|
|
|
301
332
|
if (shouldErrorForManualMigration) {
|
|
302
333
|
for (const [key, errorList] of Object.entries(errorsManual)) {
|
|
303
334
|
const node = 'node' in errorList.errors[0] ? errorList.errors[0].node : null;
|
|
335
|
+
const cantMigrateIdentifierError = errorList.errors.find(x => 'messageId' in x && x.messageId === 'cantMigrateIdentifier');
|
|
304
336
|
if (node) {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
337
|
+
let isInRange = false;
|
|
338
|
+
if (cantMigrateIdentifierError && isInRangeList(node, errorRanges)) {
|
|
339
|
+
isInRange = true;
|
|
340
|
+
}
|
|
341
|
+
if (isInRange && errorList.errors.length - 1 > 0 || !isInRange && errorList.errors.length > 0) {
|
|
342
|
+
const guidanceMessage = Object.keys(guidance).includes(key) ? guidance[key] : '';
|
|
343
|
+
context.report({
|
|
344
|
+
node,
|
|
345
|
+
messageId: 'noLegacyIconsManualMigration',
|
|
346
|
+
data: {
|
|
347
|
+
iconName: errorList.iconName,
|
|
348
|
+
importSource: errorList.importSource,
|
|
349
|
+
guidance: isQuietMode ? guidanceMessage : `${guidanceMessage}For more information see the below errors.\n`
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
if (!isQuietMode) {
|
|
353
|
+
for (const error of errorList.errors) {
|
|
354
|
+
if ('messageId' in error && (error.messageId !== 'cantMigrateIdentifier' || error.messageId === 'cantMigrateIdentifier' && !isInRange)) {
|
|
355
|
+
context.report(error);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
318
358
|
}
|
|
319
359
|
}
|
|
320
360
|
}
|
|
@@ -324,14 +364,17 @@ export const createChecks = context => {
|
|
|
324
364
|
for (const [key, error] of Object.entries(errorsAuto)) {
|
|
325
365
|
// If there's a manual error that exists for this same component,
|
|
326
366
|
// don't throw the auto error
|
|
327
|
-
if (
|
|
328
|
-
|
|
329
|
-
|
|
367
|
+
if (Object.keys(errorsManual).includes(key)) {
|
|
368
|
+
const cantMigrateIdentifierError = errorsManual[key].errors.find(x => 'messageId' in x && x.messageId === 'cantMigrateIdentifier');
|
|
369
|
+
if (!cantMigrateIdentifierError || cantMigrateIdentifierError && errorsManual[key].errors.length > 1) {
|
|
370
|
+
delete errorsAuto[key];
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
330
373
|
}
|
|
331
374
|
const node = 'node' in error ? error.node : null;
|
|
332
375
|
if (node) {
|
|
333
|
-
const guidanceMessage = key
|
|
334
|
-
if ('data'
|
|
376
|
+
const guidanceMessage = Object.keys(guidance).includes(key) ? guidance[key] : '';
|
|
377
|
+
if (Object.keys(error).includes('data') && error.data) {
|
|
335
378
|
error.data.guidance = guidanceMessage;
|
|
336
379
|
}
|
|
337
380
|
context.report(error);
|
|
@@ -348,6 +391,7 @@ export const createChecks = context => {
|
|
|
348
391
|
checkIconAsProp,
|
|
349
392
|
checkJSXElement,
|
|
350
393
|
checkCallExpression,
|
|
351
|
-
throwErrors
|
|
394
|
+
throwErrors,
|
|
395
|
+
checkIconReference
|
|
352
396
|
};
|
|
353
397
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
2
|
import baseMigrationMap, { migrationOutcomeDescriptionMap } from '@atlaskit/icon/UNSAFE_migration-map';
|
|
3
3
|
import { getImportName } from '../utils/get-import-name';
|
|
4
|
+
import { upcomingIcons } from './upcoming-icons';
|
|
4
5
|
const sizes = ['small', 'medium', 'large', 'xlarge'];
|
|
5
6
|
export const isSize = size => sizes.includes(size);
|
|
6
7
|
|
|
@@ -11,11 +12,26 @@ export const isSize = size => sizes.includes(size);
|
|
|
11
12
|
*/
|
|
12
13
|
export const getMigrationMapObject = iconPackage => {
|
|
13
14
|
const key = getIconKey(iconPackage);
|
|
14
|
-
if (
|
|
15
|
+
if (Object.keys(baseMigrationMap).includes(key)) {
|
|
15
16
|
return baseMigrationMap[key];
|
|
16
17
|
}
|
|
17
18
|
return null;
|
|
18
19
|
};
|
|
20
|
+
export const getUpcomingIcons = iconPackage => {
|
|
21
|
+
const key = getIconKey(iconPackage);
|
|
22
|
+
if (upcomingIcons.includes(key)) {
|
|
23
|
+
const retval = {
|
|
24
|
+
sizeGuidance: {
|
|
25
|
+
small: 'swap',
|
|
26
|
+
medium: 'swap',
|
|
27
|
+
large: 'icon-tile',
|
|
28
|
+
xlarge: 'icon-tile'
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
return retval;
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
};
|
|
19
35
|
|
|
20
36
|
/**
|
|
21
37
|
* Returns the key of a legacy icon
|
|
@@ -39,7 +55,29 @@ export const canAutoMigrateNewIconBasedOnSize = guidance => {
|
|
|
39
55
|
*/
|
|
40
56
|
export const createGuidance = (iconPackage, insideNewButton = false, size) => {
|
|
41
57
|
const migrationMapObject = getMigrationMapObject(iconPackage);
|
|
42
|
-
|
|
58
|
+
const upcomingIcon = getUpcomingIcons(iconPackage);
|
|
59
|
+
if (upcomingIcon) {
|
|
60
|
+
let guidance = '';
|
|
61
|
+
if (size) {
|
|
62
|
+
if (upcomingIcon.sizeGuidance[size] && canAutoMigrateNewIconBasedOnSize(upcomingIcon.sizeGuidance[size])) {
|
|
63
|
+
guidance += `Fix: An upcoming icon release is planned to migrate this legacy icon.`;
|
|
64
|
+
} else {
|
|
65
|
+
guidance += `No equivalent icon for this size, ${size}, in the current or upcoming set of icons.`;
|
|
66
|
+
}
|
|
67
|
+
guidance += `${Object.keys(migrationOutcomeDescriptionMap).includes(upcomingIcon.sizeGuidance[size]) ? ` Once the upcoming icons are released, please: ${migrationOutcomeDescriptionMap[upcomingIcon.sizeGuidance[size]]}` : ' No migration size advice given.'}\n`;
|
|
68
|
+
} else {
|
|
69
|
+
guidance = `Please wait for the upcoming icons released, as it will contain an alternative for this legacy icon.\nMigration suggestions, depending on the legacy icon size:\n`;
|
|
70
|
+
for (const [size, value] of Object.entries(upcomingIcon.sizeGuidance)) {
|
|
71
|
+
guidance += `\t- ${size}: `;
|
|
72
|
+
if (!Object.keys(migrationOutcomeDescriptionMap).includes(value)) {
|
|
73
|
+
guidance += 'No migration advice given.\n';
|
|
74
|
+
} else {
|
|
75
|
+
guidance += `${migrationOutcomeDescriptionMap[value]}.\n`;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return guidance;
|
|
80
|
+
} else if (migrationMapObject) {
|
|
43
81
|
const newIcon = migrationMapObject.newIcon;
|
|
44
82
|
if (!newIcon) {
|
|
45
83
|
return 'No equivalent icon in new set. An option is to contribute a custom icon into icon-labs package instead.\n';
|
|
@@ -52,12 +90,12 @@ export const createGuidance = (iconPackage, insideNewButton = false, size) => {
|
|
|
52
90
|
} else {
|
|
53
91
|
guidance += `No equivalent icon for this size, ${size}, in new set.`;
|
|
54
92
|
}
|
|
55
|
-
guidance += `${migrationMapObject.sizeGuidance[size]
|
|
93
|
+
guidance += `${Object.keys(migrationOutcomeDescriptionMap).includes(migrationMapObject.sizeGuidance[size]) ? ` Please: ${migrationOutcomeDescriptionMap[migrationMapObject.sizeGuidance[size]]}` : ' No migration size advice given.'}\n`;
|
|
56
94
|
} else {
|
|
57
95
|
guidance = `Use ${newIcon.name} from ${newIcon.package}/${newIcon.type}/${newIcon.name} instead.\nMigration suggestions, depending on the legacy icon size:\n`;
|
|
58
96
|
Object.entries(migrationMapObject.sizeGuidance).forEach(([size, value]) => {
|
|
59
97
|
guidance += `\t- ${size}: `;
|
|
60
|
-
if (!(
|
|
98
|
+
if (!Object.keys(migrationOutcomeDescriptionMap).includes(value)) {
|
|
61
99
|
guidance += 'No migration advice given.\n';
|
|
62
100
|
} else {
|
|
63
101
|
guidance += `${migrationOutcomeDescriptionMap[value]}.\n`;
|
|
@@ -96,8 +134,11 @@ export const canMigrateColor = color => {
|
|
|
96
134
|
}
|
|
97
135
|
};
|
|
98
136
|
export const locToString = node => {
|
|
99
|
-
|
|
100
|
-
|
|
137
|
+
if (node.range && node.range.length >= 2) {
|
|
138
|
+
return `${node.range[0]}:${node.range[1]}`;
|
|
139
|
+
} else {
|
|
140
|
+
return '';
|
|
141
|
+
}
|
|
101
142
|
};
|
|
102
143
|
export const createCantMigrateReExportError = (node, packageName, exportName, errors) => {
|
|
103
144
|
const myError = {
|
|
@@ -110,10 +151,10 @@ export const createCantMigrateReExportError = (node, packageName, exportName, er
|
|
|
110
151
|
};
|
|
111
152
|
pushManualError(locToString(node), errors, myError, packageName, exportName);
|
|
112
153
|
};
|
|
113
|
-
export const
|
|
154
|
+
export const createCantMigrateIdentifierMapOrArrayError = (node, packageName, exportName, errors) => {
|
|
114
155
|
const myError = {
|
|
115
156
|
node,
|
|
116
|
-
messageId: '
|
|
157
|
+
messageId: 'cantMigrateIdentifierMapOrArray',
|
|
117
158
|
data: {
|
|
118
159
|
packageName,
|
|
119
160
|
exportName
|
|
@@ -121,6 +162,17 @@ export const createCantMigrateIdentifierError = (node, packageName, exportName,
|
|
|
121
162
|
};
|
|
122
163
|
pushManualError(locToString(node), errors, myError, packageName, exportName);
|
|
123
164
|
};
|
|
165
|
+
export const createCantMigrateIdentifierError = (node, packageName, exportName, errors) => {
|
|
166
|
+
const myError = {
|
|
167
|
+
node,
|
|
168
|
+
messageId: 'cantMigrateIdentifier',
|
|
169
|
+
data: {
|
|
170
|
+
iconSource: packageName,
|
|
171
|
+
iconName: exportName
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
pushManualError(locToString(node), errors, myError, packageName, exportName);
|
|
175
|
+
};
|
|
124
176
|
export const createCantFindSuitableReplacementError = (node, importSource, iconName, errors, sizeIssue) => {
|
|
125
177
|
const myError = {
|
|
126
178
|
node,
|
|
@@ -183,7 +235,7 @@ export const createAutoMigrationError = (node, importSource, iconName, errors) =
|
|
|
183
235
|
errors[locToString(node)] = myError;
|
|
184
236
|
};
|
|
185
237
|
const pushManualError = (key, errors, myError, importSource, iconName) => {
|
|
186
|
-
if (
|
|
238
|
+
if (Object.keys(errors).includes(key)) {
|
|
187
239
|
errors[key].errors.push(myError);
|
|
188
240
|
} else {
|
|
189
241
|
errors[key] = {
|
|
@@ -231,7 +283,7 @@ export const createHelpers = context => {
|
|
|
231
283
|
* @returns defaultValue if the configuration flag is not set, the defaultValue of the configuration flag otherwise
|
|
232
284
|
*/
|
|
233
285
|
const getConfigFlag = (key, defaultValue) => {
|
|
234
|
-
if (context.options.length > 0 && context.options[0] &&
|
|
286
|
+
if (context.options.length > 0 && context.options[0] && Object.keys(context.options[0]).includes(key)) {
|
|
235
287
|
return context.options[0][key] === !defaultValue ? !defaultValue : defaultValue;
|
|
236
288
|
}
|
|
237
289
|
return defaultValue;
|
|
@@ -250,4 +302,22 @@ export const createHelpers = context => {
|
|
|
250
302
|
getTokenCallValue,
|
|
251
303
|
getConfigFlag
|
|
252
304
|
};
|
|
305
|
+
};
|
|
306
|
+
export const addToListOfRanges = (node, sortedListOfRangesForErrors) => {
|
|
307
|
+
if (node.range && node.range.length >= 2) {
|
|
308
|
+
sortedListOfRangesForErrors.push({
|
|
309
|
+
start: node.range[0],
|
|
310
|
+
end: node.range[1]
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
export const isInRangeList = (node, sortedListOfRangesForErrors) => {
|
|
315
|
+
const {
|
|
316
|
+
range
|
|
317
|
+
} = node;
|
|
318
|
+
if (!range || range.length < 2) {
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
const found = sortedListOfRangesForErrors.find(currRange => range[0] >= currRange.start && range[1] <= currRange.end);
|
|
322
|
+
return !!found;
|
|
253
323
|
};
|
|
@@ -35,8 +35,8 @@ const rule = createLintRule({
|
|
|
35
35
|
cantMigrateSpreadProps: `This usage of Icon uses spread props in a way that can't be automatically migrated. Please explicitly define the following props after spread: '{{missingProps}}' `,
|
|
36
36
|
cantMigrateSizeUnknown: `This usage of Icon sets the size via a variable or function that can't be determined.`,
|
|
37
37
|
cantMigrateFunctionUnknown: `'{{iconName}}' from legacy '{{importSource}}' is used in unknown function/component. Please manually migrate this icon.`,
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
cantMigrateIdentifierMapOrArray: `This icon is passed to other components via a map or array, in a way that can't be automatically migrated. Please manually migrate wherever this expression is used and use the icon components directly.`,
|
|
39
|
+
cantMigrateIdentifier: `This is a legacy icon, {{iconName}} from {{iconSource}}, being referenced. Please manually migrate.`
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
42
|
create(context) {
|
|
@@ -53,7 +53,8 @@ const rule = createLintRule({
|
|
|
53
53
|
checkIconAsProp,
|
|
54
54
|
checkJSXElement,
|
|
55
55
|
checkCallExpression,
|
|
56
|
-
throwErrors
|
|
56
|
+
throwErrors,
|
|
57
|
+
checkIconReference
|
|
57
58
|
} = createChecks(context);
|
|
58
59
|
return errorBoundary({
|
|
59
60
|
// Track imports of relevant components
|
|
@@ -70,6 +71,7 @@ const rule = createLintRule({
|
|
|
70
71
|
JSXElement: checkJSXElement,
|
|
71
72
|
// Icons called as an argument of a function (i.e. icon={DefaultIcon(AddIcon)})
|
|
72
73
|
CallExpression: checkCallExpression,
|
|
74
|
+
Identifier: checkIconReference,
|
|
73
75
|
'Program:exit': throwErrors
|
|
74
76
|
}, failSilently);
|
|
75
77
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const upcomingIcons = ['app-switcher', 'check-circle-outline', 'export', 'file', 'flag-filled', 'lightbulb-filled', 'lock-filled', 'menu-expand', 'menu', 'notification-direct', 'notification', 'people-group', 'people', 'refresh', 'switcher', 'editor/align-image-center', 'editor/align-image-left', 'editor/align-image-right', 'editor/background-color', 'editor/bold', 'editor/indent', 'editor/italic', 'editor/horizontal-rule', 'editor-layout-three-equal', 'editor-layout-three-with-sidebars', 'editor/layout-two-equal', 'editor/layout-two-left-sidebars', 'editor/layout-two-right-sidebar', 'editor/media-center', 'editor/media-full-width', 'editor/media-wide', 'editor/number-list', 'emoji/activity', 'editor/file', 'emoji/flags', 'emoji/food', 'emoji/nature', 'emoji/people', 'emoji/productivity', 'emoji/travel', 'bitbucket/repos'];
|