@atlaskit/eslint-plugin-design-system 10.9.0 → 10.10.1
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 +19 -0
- package/README.md +1 -0
- package/dist/cjs/presets/all.codegen.js +2 -1
- package/dist/cjs/rules/ensure-design-token-usage/index.js +199 -227
- package/dist/cjs/rules/index.codegen.js +3 -1
- package/dist/cjs/rules/no-custom-icons/checks/has-prop.js +12 -0
- package/dist/cjs/rules/no-custom-icons/checks/is-from-import-source.js +42 -0
- package/dist/cjs/rules/no-custom-icons/checks/is-imported-jsx-element.js +10 -0
- package/dist/cjs/rules/no-custom-icons/index.js +67 -0
- package/dist/cjs/rules/no-legacy-icons/checks.js +63 -67
- package/dist/cjs/rules/no-legacy-icons/helpers.js +29 -24
- package/dist/cjs/rules/no-legacy-icons/index.js +15 -88
- package/dist/cjs/rules/use-tokens-typography/index.js +4 -8
- package/dist/cjs/rules/utils/error-boundary.js +58 -11
- package/dist/es2019/presets/all.codegen.js +2 -1
- package/dist/es2019/rules/ensure-design-token-usage/index.js +16 -30
- package/dist/es2019/rules/index.codegen.js +3 -1
- package/dist/es2019/rules/no-custom-icons/checks/has-prop.js +4 -0
- package/dist/es2019/rules/no-custom-icons/checks/is-from-import-source.js +23 -0
- package/dist/es2019/rules/no-custom-icons/checks/is-imported-jsx-element.js +4 -0
- package/dist/es2019/rules/no-custom-icons/index.js +61 -0
- package/dist/es2019/rules/no-legacy-icons/checks.js +20 -33
- package/dist/es2019/rules/no-legacy-icons/helpers.js +24 -21
- package/dist/es2019/rules/no-legacy-icons/index.js +15 -70
- package/dist/es2019/rules/use-tokens-typography/index.js +3 -7
- package/dist/es2019/rules/utils/error-boundary.js +55 -11
- package/dist/esm/presets/all.codegen.js +2 -1
- package/dist/esm/rules/ensure-design-token-usage/index.js +199 -227
- package/dist/esm/rules/index.codegen.js +3 -1
- package/dist/esm/rules/no-custom-icons/checks/has-prop.js +6 -0
- package/dist/esm/rules/no-custom-icons/checks/is-from-import-source.js +36 -0
- package/dist/esm/rules/no-custom-icons/checks/is-imported-jsx-element.js +4 -0
- package/dist/esm/rules/no-custom-icons/index.js +61 -0
- package/dist/esm/rules/no-legacy-icons/checks.js +64 -68
- package/dist/esm/rules/no-legacy-icons/helpers.js +28 -23
- package/dist/esm/rules/no-legacy-icons/index.js +15 -88
- package/dist/esm/rules/use-tokens-typography/index.js +4 -8
- package/dist/esm/rules/utils/error-boundary.js +56 -10
- package/dist/types/index.codegen.d.ts +1 -0
- package/dist/types/presets/all.codegen.d.ts +2 -1
- package/dist/types/rules/index.codegen.d.ts +1 -0
- package/dist/types/rules/no-custom-icons/checks/has-prop.d.ts +2 -0
- package/dist/types/rules/no-custom-icons/checks/is-from-import-source.d.ts +8 -0
- package/dist/types/rules/no-custom-icons/checks/is-imported-jsx-element.d.ts +8 -0
- package/dist/types/rules/no-custom-icons/index.d.ts +3 -0
- package/dist/types/rules/no-legacy-icons/helpers.d.ts +3 -13
- package/dist/types/rules/no-legacy-icons/index.d.ts +1 -2
- package/dist/types/rules/utils/error-boundary.d.ts +8 -5
- package/dist/types-ts4.5/index.codegen.d.ts +1 -0
- package/dist/types-ts4.5/presets/all.codegen.d.ts +2 -1
- package/dist/types-ts4.5/rules/index.codegen.d.ts +1 -0
- package/dist/types-ts4.5/rules/no-custom-icons/checks/has-prop.d.ts +2 -0
- package/dist/types-ts4.5/rules/no-custom-icons/checks/is-from-import-source.d.ts +8 -0
- package/dist/types-ts4.5/rules/no-custom-icons/checks/is-imported-jsx-element.d.ts +8 -0
- package/dist/types-ts4.5/rules/no-custom-icons/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/no-legacy-icons/helpers.d.ts +3 -13
- package/dist/types-ts4.5/rules/no-legacy-icons/index.d.ts +1 -2
- package/dist/types-ts4.5/rules/utils/error-boundary.d.ts +8 -5
- package/package.json +2 -2
- package/constellation/consistent-css-prop-usage/usage.mdx +0 -210
- package/constellation/ensure-design-token-usage/usage.mdx +0 -77
- package/constellation/ensure-design-token-usage-preview/usage.mdx +0 -6
- package/constellation/icon-label/usage.mdx +0 -41
- package/constellation/index/props.mdx +0 -30
- package/constellation/index/usage.mdx +0 -56
- package/constellation/no-banned-imports/usage.mdx +0 -19
- package/constellation/no-css-tagged-template-expression/usage.mdx +0 -71
- package/constellation/no-deprecated-apis/usage.mdx +0 -82
- package/constellation/no-deprecated-design-token-usage/usage.mdx +0 -30
- package/constellation/no-deprecated-imports/usage.mdx +0 -66
- package/constellation/no-direct-use-of-web-platform-drag-and-drop/usage.mdx +0 -149
- package/constellation/no-empty-styled-expression/usage.mdx +0 -82
- package/constellation/no-exported-css/usage.mdx +0 -55
- package/constellation/no-exported-keyframes/usage.mdx +0 -55
- package/constellation/no-html-anchor/usage.mdx +0 -46
- package/constellation/no-html-button/usage.mdx +0 -52
- package/constellation/no-invalid-css-map/usage.mdx +0 -210
- package/constellation/no-keyframes-tagged-template-expression/usage.mdx +0 -80
- package/constellation/no-legacy-icons/usage.mdx +0 -42
- package/constellation/no-margin/usage.mdx +0 -21
- package/constellation/no-nested-styles/usage.mdx +0 -47
- package/constellation/no-physical-properties/usage.mdx +0 -53
- package/constellation/no-styled-tagged-template-expression/usage.mdx +0 -135
- package/constellation/no-unsafe-design-token-usage/usage.mdx +0 -50
- package/constellation/no-unsafe-style-overrides/usage.mdx +0 -52
- package/constellation/no-unsupported-drag-and-drop-libraries/usage.mdx +0 -23
- package/constellation/prefer-primitives/usage.mdx +0 -32
- package/constellation/use-button-group-label/usage.mdx +0 -60
- package/constellation/use-drawer-label/usage.mdx +0 -55
- package/constellation/use-heading/usage.mdx +0 -31
- package/constellation/use-heading-level-in-spotlight-card/usage.mdx +0 -21
- package/constellation/use-href-in-link-item/usage.mdx +0 -19
- package/constellation/use-latest-xcss-syntax/usage.mdx +0 -33
- package/constellation/use-latest-xcss-syntax-typography/usage.mdx +0 -34
- package/constellation/use-menu-section-title/usage.mdx +0 -55
- package/constellation/use-popup-label/usage.mdx +0 -56
- package/constellation/use-primitives/usage.mdx +0 -78
- package/constellation/use-primitives-text/usage.mdx +0 -35
- package/constellation/use-tokens-space/usage.mdx +0 -34
- package/constellation/use-tokens-typography/usage.mdx +0 -55
- package/constellation/use-visually-hidden/usage.mdx +0 -35
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
3
4
|
Object.defineProperty(exports, "__esModule", {
|
|
4
5
|
value: true
|
|
5
6
|
});
|
|
6
|
-
exports.errorBoundary =
|
|
7
|
+
exports.errorBoundary = errorBoundary;
|
|
8
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
|
+
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
|
10
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
11
|
+
|
|
12
|
+
// Need to intersect type RuleListener with a generic function to allow use of Parameters<...> to be used
|
|
13
|
+
|
|
14
|
+
// Allow config to be to be easily passed from rules
|
|
15
|
+
|
|
7
16
|
/**
|
|
8
17
|
* ESLint rules should NEVER throw exceptions, because that breaks the VSCode ESLint server
|
|
9
18
|
* (and probably the IntelliJ one too), which causes linting to fail in a file.
|
|
@@ -11,14 +20,52 @@ exports.errorBoundary = void 0;
|
|
|
11
20
|
* It also breaks CI, which was the reason this error boundary was added. It's a final
|
|
12
21
|
* catch all.
|
|
13
22
|
*/
|
|
14
|
-
|
|
15
|
-
var config =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
function errorBoundary(ruleOrRules) {
|
|
24
|
+
var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
25
|
+
var failSilently = failSilentlyFromConfig(config);
|
|
26
|
+
if (isSingleRuleListener(ruleOrRules)) {
|
|
27
|
+
return wrapSingleRuleListener(ruleOrRules, failSilently);
|
|
28
|
+
}
|
|
29
|
+
return wrapRuleListener(ruleOrRules, failSilently);
|
|
30
|
+
}
|
|
31
|
+
function isSingleRuleListener(rule) {
|
|
32
|
+
return typeof rule === 'function';
|
|
33
|
+
}
|
|
34
|
+
function failSilentlyFromConfig(c) {
|
|
35
|
+
switch ((0, _typeof2.default)(c)) {
|
|
36
|
+
case 'undefined':
|
|
37
|
+
return false;
|
|
38
|
+
case 'boolean':
|
|
39
|
+
return c;
|
|
40
|
+
case 'object':
|
|
41
|
+
if ('failSilently' in c) {
|
|
42
|
+
var _c$failSilently;
|
|
43
|
+
return (_c$failSilently = c.failSilently) !== null && _c$failSilently !== void 0 ? _c$failSilently : false;
|
|
44
|
+
} else if ('config' in c) {
|
|
45
|
+
var _c$config$failSilentl;
|
|
46
|
+
return (_c$config$failSilentl = c.config.failSilently) !== null && _c$config$failSilentl !== void 0 ? _c$config$failSilentl : false;
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
default:
|
|
50
|
+
throw new Error('Invalid config');
|
|
23
51
|
}
|
|
24
|
-
}
|
|
52
|
+
}
|
|
53
|
+
function wrapSingleRuleListener(rule, failSilently) {
|
|
54
|
+
return function () {
|
|
55
|
+
try {
|
|
56
|
+
rule.apply(void 0, arguments);
|
|
57
|
+
} catch (err) {
|
|
58
|
+
if (!failSilently) {
|
|
59
|
+
// eslint-disable-next-line no-console
|
|
60
|
+
console.warn(err);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function wrapRuleListener(ruleListener, failSilently) {
|
|
66
|
+
return Object.entries(ruleListener).reduce(function (wrappedRuleListener, e) {
|
|
67
|
+
var ruleName = e[0];
|
|
68
|
+
var rule = e[1];
|
|
69
|
+
return Object.assign(wrappedRuleListener, (0, _defineProperty2.default)({}, ruleName, wrapSingleRuleListener(rule, failSilently)));
|
|
70
|
+
}, {});
|
|
71
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
|
|
3
|
-
* @codegen <<SignedSource::
|
|
3
|
+
* @codegen <<SignedSource::ab43b6e1a867d07b9a27eae78d48834a>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
export default {
|
|
@@ -12,6 +12,7 @@ export default {
|
|
|
12
12
|
'@atlaskit/design-system/icon-label': 'warn',
|
|
13
13
|
'@atlaskit/design-system/no-banned-imports': 'error',
|
|
14
14
|
'@atlaskit/design-system/no-css-tagged-template-expression': 'error',
|
|
15
|
+
'@atlaskit/design-system/no-custom-icons': 'warn',
|
|
15
16
|
'@atlaskit/design-system/no-deprecated-apis': 'error',
|
|
16
17
|
'@atlaskit/design-system/no-deprecated-design-token-usage': 'warn',
|
|
17
18
|
'@atlaskit/design-system/no-deprecated-imports': 'error',
|
|
@@ -27,25 +27,21 @@ const createWithConfig = initialConfig => context => {
|
|
|
27
27
|
failSilently: (userConfig === null || userConfig === void 0 ? void 0 : userConfig.failSilently) || defaultConfig.failSilently
|
|
28
28
|
};
|
|
29
29
|
let tokenNode = null;
|
|
30
|
-
return {
|
|
31
|
-
ImportDeclaration: node =>
|
|
30
|
+
return errorBoundary({
|
|
31
|
+
ImportDeclaration: node => {
|
|
32
32
|
if (node.source.value === '@atlaskit/tokens' && config.applyImport) {
|
|
33
33
|
tokenNode = node;
|
|
34
34
|
}
|
|
35
|
-
},
|
|
36
|
-
config
|
|
37
|
-
}),
|
|
35
|
+
},
|
|
38
36
|
// For expressions within template literals (e.g. `color: ${red}`) - color only
|
|
39
|
-
'TemplateLiteral > Identifier': node =>
|
|
37
|
+
'TemplateLiteral > Identifier': node => {
|
|
40
38
|
if (config.domains.includes('color')) {
|
|
41
39
|
return lintTemplateIdentifierForColor(node, context, config);
|
|
42
40
|
}
|
|
43
41
|
return;
|
|
44
|
-
},
|
|
45
|
-
config
|
|
46
|
-
}),
|
|
42
|
+
},
|
|
47
43
|
// const styles = css({ color: 'red', margin: '4px' }), styled.div({ color: 'red', margin: '4px' })
|
|
48
|
-
ObjectExpression: parentNode =>
|
|
44
|
+
ObjectExpression: parentNode => {
|
|
49
45
|
const {
|
|
50
46
|
references
|
|
51
47
|
} = context.getScope();
|
|
@@ -115,13 +111,11 @@ const createWithConfig = initialConfig => context => {
|
|
|
115
111
|
}
|
|
116
112
|
}
|
|
117
113
|
parentNode.properties.forEach(findObjectStyles);
|
|
118
|
-
},
|
|
119
|
-
config
|
|
120
|
-
}),
|
|
114
|
+
},
|
|
121
115
|
// CSSTemplateLiteral and StyledTemplateLiteral
|
|
122
116
|
// const cssTemplateLiteral = css`color: red; padding: 12px`;
|
|
123
117
|
// const styledTemplateLiteral = styled.p`color: red; padding: 8px`;
|
|
124
|
-
'TaggedTemplateExpression[tag.name="css"],TaggedTemplateExpression[tag.object.name="styled"],TaggedTemplateExpression[tag.callee.name="styled"]': node =>
|
|
118
|
+
'TaggedTemplateExpression[tag.name="css"],TaggedTemplateExpression[tag.object.name="styled"],TaggedTemplateExpression[tag.callee.name="styled"]': node => {
|
|
125
119
|
// To force the correct node type
|
|
126
120
|
if (!isNodeOfType(node, 'TaggedTemplateExpression')) {
|
|
127
121
|
return;
|
|
@@ -249,37 +243,29 @@ const createWithConfig = initialConfig => context => {
|
|
|
249
243
|
}
|
|
250
244
|
});
|
|
251
245
|
}
|
|
252
|
-
},
|
|
253
|
-
config
|
|
254
|
-
}),
|
|
246
|
+
},
|
|
255
247
|
// For inline JSX styles - literals (e.g. <Test color="red"/>) - color only
|
|
256
|
-
'JSXAttribute > Literal': node =>
|
|
248
|
+
'JSXAttribute > Literal': node => {
|
|
257
249
|
if (config.domains.includes('color')) {
|
|
258
250
|
return lintJSXLiteralForColor(node, context, config);
|
|
259
251
|
}
|
|
260
252
|
return;
|
|
261
|
-
},
|
|
262
|
-
config
|
|
263
|
-
}),
|
|
253
|
+
},
|
|
264
254
|
// For inline JSX styles - members (e.g. <Test color={color.red}/>) - color only
|
|
265
|
-
'JSXExpressionContainer > MemberExpression': node =>
|
|
255
|
+
'JSXExpressionContainer > MemberExpression': node => {
|
|
266
256
|
if (config.domains.includes('color')) {
|
|
267
257
|
return lintJSXMemberForColor(node, context, config);
|
|
268
258
|
}
|
|
269
259
|
return;
|
|
270
|
-
},
|
|
271
|
-
config
|
|
272
|
-
}),
|
|
260
|
+
},
|
|
273
261
|
// For inline JSX styles - identifiers (e.g. <Test color={red}/>) - color only
|
|
274
|
-
'JSXExpressionContainer > Identifier': node =>
|
|
262
|
+
'JSXExpressionContainer > Identifier': node => {
|
|
275
263
|
if (config.domains.includes('color')) {
|
|
276
264
|
return lintJSXIdentifierForColor(node, context, config);
|
|
277
265
|
}
|
|
278
266
|
return;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
})
|
|
282
|
-
};
|
|
267
|
+
}
|
|
268
|
+
}, config);
|
|
283
269
|
};
|
|
284
270
|
const rule = createLintRule({
|
|
285
271
|
meta: ruleMeta,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
|
|
3
|
-
* @codegen <<SignedSource::
|
|
3
|
+
* @codegen <<SignedSource::402e6eb5433560b1032e5ed926bb5564>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
import consistentCssPropUsage from './consistent-css-prop-usage';
|
|
@@ -9,6 +9,7 @@ import ensureDesignTokenUsagePreview from './ensure-design-token-usage-preview';
|
|
|
9
9
|
import iconLabel from './icon-label';
|
|
10
10
|
import noBannedImports from './no-banned-imports';
|
|
11
11
|
import noCssTaggedTemplateExpression from './no-css-tagged-template-expression';
|
|
12
|
+
import noCustomIcons from './no-custom-icons';
|
|
12
13
|
import noDeprecatedApis from './no-deprecated-apis';
|
|
13
14
|
import noDeprecatedDesignTokenUsage from './no-deprecated-design-token-usage';
|
|
14
15
|
import noDeprecatedImports from './no-deprecated-imports';
|
|
@@ -50,6 +51,7 @@ export default {
|
|
|
50
51
|
'icon-label': iconLabel,
|
|
51
52
|
'no-banned-imports': noBannedImports,
|
|
52
53
|
'no-css-tagged-template-expression': noCssTaggedTemplateExpression,
|
|
54
|
+
'no-custom-icons': noCustomIcons,
|
|
53
55
|
'no-deprecated-apis': noDeprecatedApis,
|
|
54
56
|
'no-deprecated-design-token-usage': noDeprecatedDesignTokenUsage,
|
|
55
57
|
'no-deprecated-imports': noDeprecatedImports,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { isImportedJSXElement } from './is-imported-jsx-element';
|
|
2
|
+
export function createIsFromImportSourceFor(...importSources) {
|
|
3
|
+
const literalImportSources = importSources.filter(s => typeof s === 'string');
|
|
4
|
+
const matchImportSources = importSources.filter(s => s instanceof RegExp);
|
|
5
|
+
const varImportSourceMap = new Map();
|
|
6
|
+
function isFromImportSource(node) {
|
|
7
|
+
return isImportedJSXElement(node) && varImportSourceMap.has(node.openingElement.name.name);
|
|
8
|
+
}
|
|
9
|
+
isFromImportSource.importDeclarationHook = node => {
|
|
10
|
+
const source = node.source.value;
|
|
11
|
+
if (typeof source !== 'string' || !(literalImportSources.includes(source) || matchImportSources.some(r => r.test(source)))) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
node.specifiers.filter(spec => ['ImportSpecifier', 'ImportDefaultSpecifier'].includes(spec.type)).forEach(spec => varImportSourceMap.set(spec.local.name, source));
|
|
15
|
+
};
|
|
16
|
+
isFromImportSource.getImportSource = node => {
|
|
17
|
+
if (!isFromImportSource(node)) {
|
|
18
|
+
throw new Error('Node is not an imported JSX element');
|
|
19
|
+
}
|
|
20
|
+
return varImportSourceMap.get(node.openingElement.name.name);
|
|
21
|
+
};
|
|
22
|
+
return isFromImportSource;
|
|
23
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
+
|
|
3
|
+
import { createLintRule } from '../utils/create-rule';
|
|
4
|
+
import { errorBoundary } from '../utils/error-boundary';
|
|
5
|
+
import { hasProp } from './checks/has-prop';
|
|
6
|
+
import { createIsFromImportSourceFor } from './checks/is-from-import-source';
|
|
7
|
+
const rule = createLintRule({
|
|
8
|
+
meta: {
|
|
9
|
+
name: 'no-custom-icons',
|
|
10
|
+
type: 'problem',
|
|
11
|
+
docs: {
|
|
12
|
+
description: 'Enforces custom glyph icons are used.',
|
|
13
|
+
recommended: false,
|
|
14
|
+
severity: 'warn'
|
|
15
|
+
},
|
|
16
|
+
schema: [{
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
centralLocation: {
|
|
20
|
+
type: 'string'
|
|
21
|
+
},
|
|
22
|
+
failSilently: {
|
|
23
|
+
type: 'boolean'
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
additionalProperties: false
|
|
27
|
+
}],
|
|
28
|
+
messages: {
|
|
29
|
+
noCustomIcons: `Custom icons from {{importSource}} are no longer supported. Migrate to an icon from '@atlaskit/(icon-labs|icon/core|icon/utility)'{{locationMessage}}.
|
|
30
|
+
[Migration guide](https://hello.atlassian.net/wiki/spaces/DST/pages/3748692796/New+ADS+iconography+-+Code+migration+guide).`
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
create(context) {
|
|
34
|
+
var _context$options$;
|
|
35
|
+
const isIconBase = createIsFromImportSourceFor('@atlaskit/icon', '@atlaskit/icon/base');
|
|
36
|
+
const {
|
|
37
|
+
centralLocation = '',
|
|
38
|
+
failSilently = false
|
|
39
|
+
} = (_context$options$ = context.options[0]) !== null && _context$options$ !== void 0 ? _context$options$ : {};
|
|
40
|
+
const locationMessage = centralLocation ? ` or move the icon to '${centralLocation}'` : '';
|
|
41
|
+
return errorBoundary({
|
|
42
|
+
JSXElement(node) {
|
|
43
|
+
var _isIconBase$getImport;
|
|
44
|
+
if (!isIconBase(node) || !hasProp(node, 'glyph')) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const importSource = (_isIconBase$getImport = isIconBase.getImportSource(node)) !== null && _isIconBase$getImport !== void 0 ? _isIconBase$getImport : '';
|
|
48
|
+
context.report({
|
|
49
|
+
node: node.openingElement,
|
|
50
|
+
messageId: 'noCustomIcons',
|
|
51
|
+
data: {
|
|
52
|
+
importSource,
|
|
53
|
+
locationMessage
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
},
|
|
57
|
+
ImportDeclaration: isIconBase.importDeclarationHook
|
|
58
|
+
}, failSilently);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
export default rule;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
|
-
import { canAutoMigrateNewIconBasedOnSize, canMigrateColor, createAutoMigrationError, createCantFindSuitableReplacementError, createCantMigrateColorError, createCantMigrateFunctionUnknownError, createCantMigrateIdentifierError, createCantMigrateReExportError, createCantMigrateSizeUnknown, createCantMigrateSpreadPropsError, createCantMigrateUnsafeProp, createGuidance, createHelpers, findUNSAFEProp,
|
|
2
|
+
import { canAutoMigrateNewIconBasedOnSize, canMigrateColor, createAutoMigrationError, createCantFindSuitableReplacementError, createCantMigrateColorError, createCantMigrateFunctionUnknownError, createCantMigrateIdentifierError, createCantMigrateReExportError, createCantMigrateSizeUnknown, createCantMigrateSpreadPropsError, createCantMigrateUnsafeProp, createGuidance, createHelpers, findUNSAFEProp, getMigrationMapObject, locToString } from './helpers';
|
|
3
3
|
import { isSize } from './migration-map-temp';
|
|
4
4
|
export const createChecks = context => {
|
|
5
5
|
//create global variables to be shared by the checks
|
|
@@ -100,15 +100,17 @@ export const createChecks = context => {
|
|
|
100
100
|
if (node.source && isNodeOfType(node.source, 'Literal') && 'value' in node.source) {
|
|
101
101
|
const moduleSource = node.source.value;
|
|
102
102
|
if (typeof moduleSource === 'string' && ['@atlaskit/icon/glyph/', '@atlaskit/icon-object/glyph/'].find(val => moduleSource.startsWith(val)) && node.specifiers.length) {
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
for (const spec of node.specifiers) {
|
|
104
|
+
createCantMigrateReExportError(spec, moduleSource, spec.exported.name, errorsManual);
|
|
105
|
+
guidance[locToString(spec)] = createGuidance(moduleSource);
|
|
106
|
+
}
|
|
105
107
|
}
|
|
106
108
|
} else if (node.declaration && isNodeOfType(node.declaration, 'VariableDeclaration')) {
|
|
107
109
|
// export const Icon = AddIcon;
|
|
108
110
|
for (const decl of node.declaration.declarations) {
|
|
109
111
|
if (isNodeOfType(decl, 'VariableDeclarator') && 'init' in decl && decl.init && isNodeOfType(decl.init, 'Identifier') && decl.init.name in legacyIconImports) {
|
|
110
112
|
createCantMigrateReExportError(node, legacyIconImports[decl.init.name].packageName, decl.init.name, errorsManual);
|
|
111
|
-
guidance[locToString(node)] = createGuidance(
|
|
113
|
+
guidance[locToString(node)] = createGuidance(legacyIconImports[decl.init.name].packageName);
|
|
112
114
|
}
|
|
113
115
|
}
|
|
114
116
|
} else if (!node.source && node.specifiers && node.specifiers.length > 0) {
|
|
@@ -174,18 +176,17 @@ export const createChecks = context => {
|
|
|
174
176
|
UNSAFE_propName = result.UNSAFE_propName;
|
|
175
177
|
}
|
|
176
178
|
if (newIcon && isInNewButton && isNewIconMigratable && UNSAFE_size !== 'large' && UNSAFE_size !== 'xlarge') {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
guidance[locToString(node)] = createGuidance(legacyIconImports[node.name].packageName, 'medium');
|
|
179
|
+
createAutoMigrationError(node, legacyIconImports[node.name].packageName, node.name, errorsAuto);
|
|
180
|
+
guidance[locToString(node)] = createGuidance(legacyIconImports[node.name].packageName, isInNewButton, 'medium');
|
|
180
181
|
} else if ((!newIcon || !isNewIconMigratable) && !UNSAFE_size) {
|
|
181
182
|
createCantFindSuitableReplacementError(node, legacyIconImports[node.name].packageName, node.name, errorsManual);
|
|
182
|
-
guidance[locToString(node)] = createGuidance(legacyIconImports[node.name].packageName);
|
|
183
|
+
guidance[locToString(node)] = createGuidance(legacyIconImports[node.name].packageName, isInNewButton);
|
|
183
184
|
} else if ((UNSAFE_size === 'large' || UNSAFE_size === 'xlarge') && UNSAFE_propName) {
|
|
184
185
|
createCantMigrateUnsafeProp(node, UNSAFE_propName, UNSAFE_size, legacyIconImports[node.name].packageName, node.name, errorsManual);
|
|
185
|
-
guidance[locToString(node)] = createGuidance(legacyIconImports[node.name].packageName, UNSAFE_size);
|
|
186
|
+
guidance[locToString(node)] = createGuidance(legacyIconImports[node.name].packageName, isInNewButton, UNSAFE_size);
|
|
186
187
|
} else if (!isInNewButton) {
|
|
187
188
|
createCantMigrateFunctionUnknownError(node, legacyIconImports[node.name].packageName, node.name, errorsManual);
|
|
188
|
-
guidance[locToString(node)] = createGuidance(legacyIconImports[node.name].packageName);
|
|
189
|
+
guidance[locToString(node)] = createGuidance(legacyIconImports[node.name].packageName, isInNewButton);
|
|
189
190
|
}
|
|
190
191
|
}
|
|
191
192
|
};
|
|
@@ -272,7 +273,6 @@ export const createChecks = context => {
|
|
|
272
273
|
createCantMigrateSizeUnknown(node, errorsManual, legacyIconImports[name].packageName, name);
|
|
273
274
|
hasManualMigration = true;
|
|
274
275
|
}
|
|
275
|
-
guidance[locToString(node)] = createGuidance(legacyIconImports[name].packageName, size ? size : undefined);
|
|
276
276
|
// Check for unsafe size
|
|
277
277
|
if ((UNSAFE_size === 'large' || UNSAFE_size === 'xlarge') && (UNSAFE_propName === 'UNSAFE_iconAfter_size' || UNSAFE_propName === 'UNSAFE_iconBefore_size' || UNSAFE_propName === 'UNSAFE_size')) {
|
|
278
278
|
createCantMigrateUnsafeProp(node, UNSAFE_propName, UNSAFE_size, legacyIconImports[name].packageName, name, errorsManual);
|
|
@@ -290,14 +290,14 @@ export const createChecks = context => {
|
|
|
290
290
|
hasManualMigration = true;
|
|
291
291
|
}
|
|
292
292
|
const migrationMapObject = getMigrationMapObject(legacyIconImports[name].packageName);
|
|
293
|
-
const iconKey = getIconKey(legacyIconImports[name].packageName);
|
|
294
293
|
const newIcon = migrationMapObject === null || migrationMapObject === void 0 ? void 0 : migrationMapObject.newIcon;
|
|
295
294
|
const isNewIconMigratable = canAutoMigrateNewIconBasedOnSize(migrationMapObject === null || migrationMapObject === void 0 ? void 0 : migrationMapObject.sizeGuidance[(_size = size) !== null && _size !== void 0 ? _size : 'medium']);
|
|
296
295
|
if (!hasManualMigration && newIcon && isNewIconMigratable) {
|
|
297
|
-
createAutoMigrationError(node, legacyIconImports[name].packageName, name,
|
|
296
|
+
createAutoMigrationError(node, legacyIconImports[name].packageName, name, errorsAuto);
|
|
298
297
|
} else if ((!newIcon || !isNewIconMigratable) && size) {
|
|
299
|
-
createCantFindSuitableReplacementError(node, legacyIconImports[name].packageName, name, errorsManual);
|
|
298
|
+
createCantFindSuitableReplacementError(node, legacyIconImports[name].packageName, name, errorsManual, migrationMapObject ? true : false);
|
|
300
299
|
}
|
|
300
|
+
guidance[locToString(node)] = createGuidance(legacyIconImports[name].packageName, insideNewButton, size && isSize(size) ? size : undefined);
|
|
301
301
|
}
|
|
302
302
|
};
|
|
303
303
|
|
|
@@ -324,28 +324,20 @@ export const createChecks = context => {
|
|
|
324
324
|
for (const [key, errorList] of Object.entries(errorsManual)) {
|
|
325
325
|
const node = 'node' in errorList.errors[0] ? errorList.errors[0].node : null;
|
|
326
326
|
if (node) {
|
|
327
|
+
const guidanceMessage = key in guidance ? guidance[key] : '';
|
|
327
328
|
context.report({
|
|
328
329
|
node,
|
|
329
330
|
messageId: 'noLegacyIconsManualMigration',
|
|
330
331
|
data: {
|
|
331
332
|
iconName: errorList.iconName,
|
|
332
333
|
importSource: errorList.importSource,
|
|
333
|
-
|
|
334
|
+
guidance: isQuietMode ? guidanceMessage : `${guidanceMessage}For more information see the below errors.\n`
|
|
334
335
|
}
|
|
335
336
|
});
|
|
336
337
|
if (!isQuietMode) {
|
|
337
338
|
for (const error of errorList.errors) {
|
|
338
339
|
context.report(error);
|
|
339
340
|
}
|
|
340
|
-
if (key in guidance) {
|
|
341
|
-
context.report({
|
|
342
|
-
node,
|
|
343
|
-
messageId: 'guidance',
|
|
344
|
-
data: {
|
|
345
|
-
guidance: guidance[key]
|
|
346
|
-
}
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
341
|
}
|
|
350
342
|
}
|
|
351
343
|
}
|
|
@@ -360,16 +352,11 @@ export const createChecks = context => {
|
|
|
360
352
|
}
|
|
361
353
|
const node = 'node' in error ? error.node : null;
|
|
362
354
|
if (node) {
|
|
363
|
-
|
|
364
|
-
if (
|
|
365
|
-
|
|
366
|
-
node,
|
|
367
|
-
messageId: 'guidance',
|
|
368
|
-
data: {
|
|
369
|
-
guidance: guidance[key]
|
|
370
|
-
}
|
|
371
|
-
});
|
|
355
|
+
const guidanceMessage = key in guidance ? guidance[key] : '';
|
|
356
|
+
if ('data' in error && error.data) {
|
|
357
|
+
error.data.guidance = guidanceMessage;
|
|
372
358
|
}
|
|
359
|
+
context.report(error);
|
|
373
360
|
}
|
|
374
361
|
}
|
|
375
362
|
}
|
|
@@ -19,7 +19,7 @@ export const getMigrationMapObject = iconPackage => {
|
|
|
19
19
|
* @param iconPackage The name of the legacy icon package
|
|
20
20
|
* @returns The unique identifier for the icon (the part after "@atlaskit/icon/glyph")
|
|
21
21
|
*/
|
|
22
|
-
|
|
22
|
+
const getIconKey = iconPackage => {
|
|
23
23
|
const key = iconPackage.replace(/^@atlaskit\/icon\/glyph\//, '');
|
|
24
24
|
return key;
|
|
25
25
|
};
|
|
@@ -34,36 +34,43 @@ export const canAutoMigrateNewIconBasedOnSize = guidance => {
|
|
|
34
34
|
/**
|
|
35
35
|
* Creates the written guidance for migrating a legacy icon to a new icon
|
|
36
36
|
*/
|
|
37
|
-
export const createGuidance = (iconPackage, size) => {
|
|
37
|
+
export const createGuidance = (iconPackage, insideNewButton = false, size) => {
|
|
38
38
|
const migrationMapObject = getMigrationMapObject(iconPackage);
|
|
39
39
|
if (migrationMapObject) {
|
|
40
40
|
const newIcon = migrationMapObject.newIcon;
|
|
41
41
|
if (!newIcon) {
|
|
42
42
|
return 'No equivalent icon in new set. An option is to contribute a custom icon into icon-labs package instead.\n';
|
|
43
43
|
}
|
|
44
|
+
const buttonGuidanceStr = "Please set 'spacing' property of the new icon to 'none', to ensure appropriate spacing inside `@atlaskit/button`.\n";
|
|
45
|
+
let guidance = '';
|
|
44
46
|
if (size) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
guidance += ` Please: ${outcomeDescriptionMap[migrationMapObject.sizeGuidance[size]]}\n`;
|
|
47
|
+
if (migrationMapObject.sizeGuidance[size] && canAutoMigrateNewIconBasedOnSize(migrationMapObject.sizeGuidance[size])) {
|
|
48
|
+
guidance += `Fix: Use ${newIcon.name} from @atlaskit/${newIcon.library}/${newIcon.type}/${newIcon.name} instead.`;
|
|
48
49
|
} else {
|
|
49
|
-
guidance +=
|
|
50
|
+
guidance += `No equivalent icon for this size, ${size}, in new set.`;
|
|
50
51
|
}
|
|
51
|
-
|
|
52
|
+
guidance += `${migrationMapObject.sizeGuidance[size] in outcomeDescriptionMap ? ` Please: ${outcomeDescriptionMap[migrationMapObject.sizeGuidance[size]]}` : ' No migration size advice given.'}\n`;
|
|
52
53
|
} else {
|
|
53
|
-
|
|
54
|
+
guidance = `Use ${newIcon.name} from @atlaskit/${newIcon.library}/${newIcon.type}/${newIcon.name} instead.\nMigration suggestions, depending on the legacy icon size:\n`;
|
|
54
55
|
for (const [size, value] of Object.entries(migrationMapObject.sizeGuidance)) {
|
|
55
56
|
guidance += `\t- ${size}: `;
|
|
56
57
|
if (!(value in outcomeDescriptionMap)) {
|
|
57
58
|
guidance += 'No migration advice given.\n';
|
|
58
59
|
} else {
|
|
59
|
-
guidance += `${outcomeDescriptionMap[value]}
|
|
60
|
+
guidance += `${outcomeDescriptionMap[value]}.\n`;
|
|
60
61
|
}
|
|
61
|
-
guidance;
|
|
62
62
|
}
|
|
63
|
-
return guidance;
|
|
64
63
|
}
|
|
64
|
+
if (insideNewButton) {
|
|
65
|
+
guidance += buttonGuidanceStr;
|
|
66
|
+
} else if (size && size === 'medium') {
|
|
67
|
+
guidance += "Setting the spacing property to 'spacious' will maintain the icon's box dimensions - but consider setting spacing='none' as it allows for easier control of spacing by parent elements.\n";
|
|
68
|
+
} else if (size) {
|
|
69
|
+
guidance += "In the new icon, please use spacing='none'.\n";
|
|
70
|
+
}
|
|
71
|
+
return guidance;
|
|
65
72
|
} else {
|
|
66
|
-
return
|
|
73
|
+
return `Migration suggestions not found for "${iconPackage}".\n`;
|
|
67
74
|
}
|
|
68
75
|
};
|
|
69
76
|
|
|
@@ -139,13 +146,14 @@ export const createCantMigrateUnsafeProp = (node, propName, value, packageName,
|
|
|
139
146
|
};
|
|
140
147
|
pushManualError(locToString(node), errors, myError, packageName, iconName);
|
|
141
148
|
};
|
|
142
|
-
export const createCantFindSuitableReplacementError = (node, importSource, iconName, errors) => {
|
|
149
|
+
export const createCantFindSuitableReplacementError = (node, importSource, iconName, errors, sizeIssue) => {
|
|
143
150
|
const myError = {
|
|
144
151
|
node,
|
|
145
152
|
messageId: 'cantFindSuitableReplacement',
|
|
146
153
|
data: {
|
|
147
154
|
importSource,
|
|
148
|
-
iconName
|
|
155
|
+
iconName,
|
|
156
|
+
sizeGuidance: sizeIssue ? ' at the current size' : ''
|
|
149
157
|
}
|
|
150
158
|
};
|
|
151
159
|
pushManualError(locToString(node), errors, myError, importSource, iconName);
|
|
@@ -188,18 +196,13 @@ export const createCantMigrateSizeUnknown = (node, errors, importSource, iconNam
|
|
|
188
196
|
};
|
|
189
197
|
pushManualError(locToString(node), errors, myError, importSource, iconName);
|
|
190
198
|
};
|
|
191
|
-
export const createAutoMigrationError = (node, importSource, iconName,
|
|
192
|
-
const migrationKey = newIcon.name === oldIconName ? newIcon.name : `${newIcon.name}--${oldIconName}`;
|
|
193
|
-
const newMigrationIconPackage = `@atlaskit/${newIcon.library}/${newIcon.type}/migration/${migrationKey}`;
|
|
199
|
+
export const createAutoMigrationError = (node, importSource, iconName, errors) => {
|
|
194
200
|
const myError = {
|
|
195
201
|
node,
|
|
196
202
|
messageId: 'noLegacyIconsAutoMigration',
|
|
197
203
|
data: {
|
|
198
204
|
importSource,
|
|
199
|
-
iconName
|
|
200
|
-
newIcon: newIcon.name,
|
|
201
|
-
//TODO: provide size guidance
|
|
202
|
-
newPackage: newMigrationIconPackage
|
|
205
|
+
iconName
|
|
203
206
|
}
|
|
204
207
|
};
|
|
205
208
|
errors[locToString(node)] = myError;
|