@atlaskit/eslint-plugin-design-system 10.4.5 → 10.6.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 +16 -0
- package/README.md +2 -0
- package/constellation/index/usage.mdx +2 -0
- package/constellation/no-legacy-icons/usage.mdx +42 -0
- package/constellation/use-menu-section-title/usage.mdx +55 -0
- package/dist/cjs/presets/all.codegen.js +3 -1
- package/dist/cjs/presets/recommended.codegen.js +2 -1
- package/dist/cjs/rules/index.codegen.js +5 -1
- package/dist/cjs/rules/no-legacy-icons/index.js +174 -0
- package/dist/cjs/rules/use-menu-section-title/index.js +85 -0
- package/dist/es2019/presets/all.codegen.js +3 -1
- package/dist/es2019/presets/recommended.codegen.js +2 -1
- package/dist/es2019/rules/index.codegen.js +5 -1
- package/dist/es2019/rules/no-legacy-icons/index.js +133 -0
- package/dist/es2019/rules/use-menu-section-title/index.js +79 -0
- package/dist/esm/presets/all.codegen.js +3 -1
- package/dist/esm/presets/recommended.codegen.js +2 -1
- package/dist/esm/rules/index.codegen.js +5 -1
- package/dist/esm/rules/no-legacy-icons/index.js +168 -0
- package/dist/esm/rules/use-menu-section-title/index.js +79 -0
- package/dist/types/index.codegen.d.ts +3 -0
- package/dist/types/presets/all.codegen.d.ts +3 -1
- package/dist/types/presets/recommended.codegen.d.ts +2 -1
- package/dist/types/rules/index.codegen.d.ts +2 -0
- package/dist/types/rules/no-legacy-icons/index.d.ts +2 -0
- package/dist/types/rules/use-menu-section-title/index.d.ts +3 -0
- package/dist/types-ts4.5/index.codegen.d.ts +3 -0
- package/dist/types-ts4.5/presets/all.codegen.d.ts +3 -1
- package/dist/types-ts4.5/presets/recommended.codegen.d.ts +2 -1
- package/dist/types-ts4.5/rules/index.codegen.d.ts +2 -0
- package/dist/types-ts4.5/rules/no-legacy-icons/index.d.ts +2 -0
- package/dist/types-ts4.5/rules/use-menu-section-title/index.d.ts +3 -0
- package/package.json +1 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
|
+
import { createLintRule } from '../utils/create-rule';
|
|
3
|
+
const rule = createLintRule({
|
|
4
|
+
meta: {
|
|
5
|
+
name: 'no-legacy-icons',
|
|
6
|
+
type: 'problem',
|
|
7
|
+
docs: {
|
|
8
|
+
description: 'Enforces no legacy icons are used.',
|
|
9
|
+
recommended: false,
|
|
10
|
+
severity: 'warn'
|
|
11
|
+
},
|
|
12
|
+
messages: {
|
|
13
|
+
noLegacyIcons: `Legacy icon '{{iconName}}', is being rendered from import '{{importSource}}'. Migrate to an icon from '@atlaskit/icon/(core|utility)', or '@atlaskit/icon-labs/(core|utility)'.
|
|
14
|
+
Learn more in our [code migration guide](https://hello.atlassian.net/wiki/spaces/DST/pages/3748692796/New+ADS+iconography+-+Code+migration+guide).`
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
create(context) {
|
|
18
|
+
const legacyIconImports = {};
|
|
19
|
+
return {
|
|
20
|
+
ImportDeclaration(node) {
|
|
21
|
+
const moduleSource = node.source.value;
|
|
22
|
+
if (typeof moduleSource === 'string' && ['@atlaskit/icon/glyph/', '@atlaskit/icon-object/glyph/'].find(val => moduleSource.startsWith(val)) && node.specifiers.length) {
|
|
23
|
+
const defaultImport = node.specifiers.find(spec => spec.type === 'ImportDefaultSpecifier');
|
|
24
|
+
if (!defaultImport) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const defaultImportName = defaultImport.local.name;
|
|
28
|
+
legacyIconImports[defaultImportName] = moduleSource;
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
VariableDeclaration(node) {
|
|
32
|
+
if (isNodeOfType(node, 'VariableDeclaration')) {
|
|
33
|
+
for (const decl of node.declarations) {
|
|
34
|
+
if (isNodeOfType(decl, 'VariableDeclarator') && 'init' in decl && 'id' in decl && decl.init && decl.id && 'name' in decl.id && decl.id.name && isNodeOfType(decl.init, 'Identifier') && decl.init.name in legacyIconImports) {
|
|
35
|
+
legacyIconImports[decl.id.name] = legacyIconImports[decl.init.name];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
ExportDefaultDeclaration(node) {
|
|
41
|
+
if ('declaration' in node && node.declaration && isNodeOfType(node.declaration, 'Identifier') && node.declaration.name in legacyIconImports) {
|
|
42
|
+
context.report({
|
|
43
|
+
node,
|
|
44
|
+
messageId: 'noLegacyIcons',
|
|
45
|
+
data: {
|
|
46
|
+
importSource: legacyIconImports[node.declaration.name],
|
|
47
|
+
iconName: node.declaration.name
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
ExportNamedDeclaration(node) {
|
|
53
|
+
if ('source' in node && node.source && isNodeOfType(node.source, 'Literal') && 'value' in node.source) {
|
|
54
|
+
const moduleSource = node.source.value;
|
|
55
|
+
if (typeof moduleSource === 'string' && ['@atlaskit/icon/glyph/', '@atlaskit/icon-object/glyph/'].find(val => moduleSource.startsWith(val)) && node.specifiers.length) {
|
|
56
|
+
context.report({
|
|
57
|
+
node,
|
|
58
|
+
messageId: 'noLegacyIcons',
|
|
59
|
+
data: {
|
|
60
|
+
importSource: moduleSource,
|
|
61
|
+
iconName: node.specifiers[0].exported.name
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
} else if ('declaration' in node && node.declaration && isNodeOfType(node.declaration, 'VariableDeclaration')) {
|
|
66
|
+
for (const decl of node.declaration.declarations) {
|
|
67
|
+
if (isNodeOfType(decl, 'VariableDeclarator') && 'init' in decl && decl.init && isNodeOfType(decl.init, 'Identifier') && decl.init.name in legacyIconImports) {
|
|
68
|
+
context.report({
|
|
69
|
+
node,
|
|
70
|
+
messageId: 'noLegacyIcons',
|
|
71
|
+
data: {
|
|
72
|
+
importSource: legacyIconImports[decl.init.name],
|
|
73
|
+
iconName: decl.init.name
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
JSXAttribute(node) {
|
|
81
|
+
if (!isNodeOfType(node.value, 'JSXExpressionContainer')) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (isNodeOfType(node.value.expression, 'Identifier') && node.value.expression.name in legacyIconImports && isNodeOfType(node.name, 'JSXIdentifier') && !node.name.name.startsWith('LEGACY_')) {
|
|
85
|
+
context.report({
|
|
86
|
+
node,
|
|
87
|
+
messageId: 'noLegacyIcons',
|
|
88
|
+
data: {
|
|
89
|
+
importSource: legacyIconImports[node.value.expression.name],
|
|
90
|
+
iconName: node.value.expression.name
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
JSXElement(node) {
|
|
96
|
+
if (!isNodeOfType(node, 'JSXElement')) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (!isNodeOfType(node.openingElement.name, 'JSXIdentifier')) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const name = node.openingElement.name.name;
|
|
103
|
+
if (name in legacyIconImports) {
|
|
104
|
+
context.report({
|
|
105
|
+
node,
|
|
106
|
+
messageId: 'noLegacyIcons',
|
|
107
|
+
data: {
|
|
108
|
+
importSource: legacyIconImports[name],
|
|
109
|
+
iconName: name
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
CallExpression(node) {
|
|
115
|
+
if ('arguments' in node && node.arguments.length) {
|
|
116
|
+
for (const arg of node.arguments) {
|
|
117
|
+
if (isNodeOfType(arg, 'Identifier') && arg.name in legacyIconImports) {
|
|
118
|
+
context.report({
|
|
119
|
+
node: arg,
|
|
120
|
+
messageId: 'noLegacyIcons',
|
|
121
|
+
data: {
|
|
122
|
+
importSource: legacyIconImports[arg.name],
|
|
123
|
+
iconName: arg.name
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
export default rule;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
+
|
|
3
|
+
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
4
|
+
import { createLintRule } from '../utils/create-rule';
|
|
5
|
+
const elementsAccessibleNameProps = ['title', 'titleId'];
|
|
6
|
+
const rule = createLintRule({
|
|
7
|
+
meta: {
|
|
8
|
+
name: 'use-menu-section-title',
|
|
9
|
+
type: 'suggestion',
|
|
10
|
+
docs: {
|
|
11
|
+
description: 'Encourages makers to provide accessible title for Atlassian Design System Menu Section component.',
|
|
12
|
+
recommended: true,
|
|
13
|
+
severity: 'warn'
|
|
14
|
+
},
|
|
15
|
+
messages: {
|
|
16
|
+
missingTitleProp: 'Missing accessible title. If there is no visible content to associate use `title` prop, otherwise pass id of element to `titleId` prop to be associated as label.',
|
|
17
|
+
titlePropShouldHaveContents: 'Define the string that labels the interactive element.',
|
|
18
|
+
titleIdShouldHaveValue: '`titleId` should reference the id of the element that defines the accessible name.',
|
|
19
|
+
noBothPropsUsage: 'Do not include both `titleId` and `title` properties. Use `titleId` if the label text is available in the DOM to reference it, otherwise use `title` to provide accessible name explicitly.'
|
|
20
|
+
},
|
|
21
|
+
hasSuggestions: true
|
|
22
|
+
},
|
|
23
|
+
create(context) {
|
|
24
|
+
const contextLocalIdentifier = [];
|
|
25
|
+
return {
|
|
26
|
+
ImportDeclaration(node) {
|
|
27
|
+
var _node$specifiers;
|
|
28
|
+
const menuSectionIdentifier = (_node$specifiers = node.specifiers) === null || _node$specifiers === void 0 ? void 0 : _node$specifiers.filter(spec => {
|
|
29
|
+
if (node.source.value === '@atlaskit/menu') {
|
|
30
|
+
var _spec$imported;
|
|
31
|
+
return spec.type === 'ImportSpecifier' && ((_spec$imported = spec.imported) === null || _spec$imported === void 0 ? void 0 : _spec$imported.name) === 'Section';
|
|
32
|
+
} else if (node.source.value === '@atlaskit/menu/section') {
|
|
33
|
+
return spec.type === 'ImportDefaultSpecifier';
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
if (menuSectionIdentifier !== null && menuSectionIdentifier !== void 0 && menuSectionIdentifier.length) {
|
|
37
|
+
const {
|
|
38
|
+
local
|
|
39
|
+
} = menuSectionIdentifier[0];
|
|
40
|
+
contextLocalIdentifier.push(local.name);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
JSXElement(node) {
|
|
44
|
+
if (!isNodeOfType(node, 'JSXElement')) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (!isNodeOfType(node.openingElement.name, 'JSXIdentifier')) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const name = node.openingElement.name.name;
|
|
51
|
+
if (contextLocalIdentifier.includes(name)) {
|
|
52
|
+
const componentLabelProps = node.openingElement.attributes.filter(attr => isNodeOfType(attr, 'JSXAttribute') && isNodeOfType(attr.name, 'JSXIdentifier') && elementsAccessibleNameProps.includes(attr.name.name));
|
|
53
|
+
if (componentLabelProps.length === 1) {
|
|
54
|
+
const prop = componentLabelProps[0];
|
|
55
|
+
if ('value' in prop && prop.value) {
|
|
56
|
+
if (isNodeOfType(prop.value, 'Literal') && !prop.value.value || isNodeOfType(prop.value, 'JSXExpressionContainer') && !prop.value.expression) {
|
|
57
|
+
context.report({
|
|
58
|
+
node: prop,
|
|
59
|
+
messageId: prop.name.name === 'title' ? 'titlePropShouldHaveContents' : 'titleIdShouldHaveValue'
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} else if (componentLabelProps.length > 1) {
|
|
64
|
+
context.report({
|
|
65
|
+
node: node.openingElement,
|
|
66
|
+
messageId: 'noBothPropsUsage'
|
|
67
|
+
});
|
|
68
|
+
} else {
|
|
69
|
+
context.report({
|
|
70
|
+
node: node.openingElement,
|
|
71
|
+
messageId: 'missingTitleProp'
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
export default rule;
|
|
@@ -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::837556032f39113ae86785a120bb9ccb>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
export default {
|
|
@@ -23,6 +23,7 @@ export default {
|
|
|
23
23
|
'@atlaskit/design-system/no-html-button': 'warn',
|
|
24
24
|
'@atlaskit/design-system/no-invalid-css-map': 'error',
|
|
25
25
|
'@atlaskit/design-system/no-keyframes-tagged-template-expression': 'error',
|
|
26
|
+
'@atlaskit/design-system/no-legacy-icons': 'warn',
|
|
26
27
|
'@atlaskit/design-system/no-margin': 'warn',
|
|
27
28
|
'@atlaskit/design-system/no-nested-styles': 'error',
|
|
28
29
|
'@atlaskit/design-system/no-physical-properties': 'error',
|
|
@@ -37,6 +38,7 @@ export default {
|
|
|
37
38
|
'@atlaskit/design-system/use-heading-level-in-spotlight-card': 'warn',
|
|
38
39
|
'@atlaskit/design-system/use-href-in-link-item': 'warn',
|
|
39
40
|
'@atlaskit/design-system/use-latest-xcss-syntax': 'error',
|
|
41
|
+
'@atlaskit/design-system/use-menu-section-title': 'warn',
|
|
40
42
|
'@atlaskit/design-system/use-popup-label': 'warn',
|
|
41
43
|
'@atlaskit/design-system/use-primitives': 'warn',
|
|
42
44
|
'@atlaskit/design-system/use-primitives-text': 'warn',
|
|
@@ -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::b7ed527a03208f0bc68f9d34e4ef2260>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
export default {
|
|
@@ -28,6 +28,7 @@ export default {
|
|
|
28
28
|
'@atlaskit/design-system/use-heading-level-in-spotlight-card': 'warn',
|
|
29
29
|
'@atlaskit/design-system/use-href-in-link-item': 'warn',
|
|
30
30
|
'@atlaskit/design-system/use-latest-xcss-syntax': 'error',
|
|
31
|
+
'@atlaskit/design-system/use-menu-section-title': 'warn',
|
|
31
32
|
'@atlaskit/design-system/use-popup-label': 'warn',
|
|
32
33
|
'@atlaskit/design-system/use-visually-hidden': 'error'
|
|
33
34
|
}
|
|
@@ -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::287628b11d396c2bcbcf6f4a175a3d3a>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
import consistentCssPropUsage from './consistent-css-prop-usage';
|
|
@@ -20,6 +20,7 @@ import noHtmlAnchor from './no-html-anchor';
|
|
|
20
20
|
import noHtmlButton from './no-html-button';
|
|
21
21
|
import noInvalidCssMap from './no-invalid-css-map';
|
|
22
22
|
import noKeyframesTaggedTemplateExpression from './no-keyframes-tagged-template-expression';
|
|
23
|
+
import noLegacyIcons from './no-legacy-icons';
|
|
23
24
|
import noMargin from './no-margin';
|
|
24
25
|
import noNestedStyles from './no-nested-styles';
|
|
25
26
|
import noPhysicalProperties from './no-physical-properties';
|
|
@@ -34,6 +35,7 @@ import useHeading from './use-heading';
|
|
|
34
35
|
import useHeadingLevelInSpotlightCard from './use-heading-level-in-spotlight-card';
|
|
35
36
|
import useHrefInLinkItem from './use-href-in-link-item';
|
|
36
37
|
import useLatestXcssSyntax from './use-latest-xcss-syntax';
|
|
38
|
+
import useMenuSectionTitle from './use-menu-section-title';
|
|
37
39
|
import usePopupLabel from './use-popup-label';
|
|
38
40
|
import usePrimitives from './use-primitives';
|
|
39
41
|
import usePrimitivesText from './use-primitives-text';
|
|
@@ -58,6 +60,7 @@ export default {
|
|
|
58
60
|
'no-html-button': noHtmlButton,
|
|
59
61
|
'no-invalid-css-map': noInvalidCssMap,
|
|
60
62
|
'no-keyframes-tagged-template-expression': noKeyframesTaggedTemplateExpression,
|
|
63
|
+
'no-legacy-icons': noLegacyIcons,
|
|
61
64
|
'no-margin': noMargin,
|
|
62
65
|
'no-nested-styles': noNestedStyles,
|
|
63
66
|
'no-physical-properties': noPhysicalProperties,
|
|
@@ -72,6 +75,7 @@ export default {
|
|
|
72
75
|
'use-heading-level-in-spotlight-card': useHeadingLevelInSpotlightCard,
|
|
73
76
|
'use-href-in-link-item': useHrefInLinkItem,
|
|
74
77
|
'use-latest-xcss-syntax': useLatestXcssSyntax,
|
|
78
|
+
'use-menu-section-title': useMenuSectionTitle,
|
|
75
79
|
'use-popup-label': usePopupLabel,
|
|
76
80
|
'use-primitives': usePrimitives,
|
|
77
81
|
'use-primitives-text': usePrimitivesText,
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
2
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
3
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
4
|
+
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
5
|
+
import { createLintRule } from '../utils/create-rule';
|
|
6
|
+
var rule = createLintRule({
|
|
7
|
+
meta: {
|
|
8
|
+
name: 'no-legacy-icons',
|
|
9
|
+
type: 'problem',
|
|
10
|
+
docs: {
|
|
11
|
+
description: 'Enforces no legacy icons are used.',
|
|
12
|
+
recommended: false,
|
|
13
|
+
severity: 'warn'
|
|
14
|
+
},
|
|
15
|
+
messages: {
|
|
16
|
+
noLegacyIcons: "Legacy icon '{{iconName}}', is being rendered from import '{{importSource}}'. Migrate to an icon from '@atlaskit/icon/(core|utility)', or '@atlaskit/icon-labs/(core|utility)'.\nLearn more in our [code migration guide](https://hello.atlassian.net/wiki/spaces/DST/pages/3748692796/New+ADS+iconography+-+Code+migration+guide)."
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
create: function create(context) {
|
|
20
|
+
var legacyIconImports = {};
|
|
21
|
+
return {
|
|
22
|
+
ImportDeclaration: function ImportDeclaration(node) {
|
|
23
|
+
var moduleSource = node.source.value;
|
|
24
|
+
if (typeof moduleSource === 'string' && ['@atlaskit/icon/glyph/', '@atlaskit/icon-object/glyph/'].find(function (val) {
|
|
25
|
+
return moduleSource.startsWith(val);
|
|
26
|
+
}) && node.specifiers.length) {
|
|
27
|
+
var defaultImport = node.specifiers.find(function (spec) {
|
|
28
|
+
return spec.type === 'ImportDefaultSpecifier';
|
|
29
|
+
});
|
|
30
|
+
if (!defaultImport) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
var defaultImportName = defaultImport.local.name;
|
|
34
|
+
legacyIconImports[defaultImportName] = moduleSource;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
VariableDeclaration: function VariableDeclaration(node) {
|
|
38
|
+
if (isNodeOfType(node, 'VariableDeclaration')) {
|
|
39
|
+
var _iterator = _createForOfIteratorHelper(node.declarations),
|
|
40
|
+
_step;
|
|
41
|
+
try {
|
|
42
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
43
|
+
var decl = _step.value;
|
|
44
|
+
if (isNodeOfType(decl, 'VariableDeclarator') && 'init' in decl && 'id' in decl && decl.init && decl.id && 'name' in decl.id && decl.id.name && isNodeOfType(decl.init, 'Identifier') && decl.init.name in legacyIconImports) {
|
|
45
|
+
legacyIconImports[decl.id.name] = legacyIconImports[decl.init.name];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
} catch (err) {
|
|
49
|
+
_iterator.e(err);
|
|
50
|
+
} finally {
|
|
51
|
+
_iterator.f();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
ExportDefaultDeclaration: function ExportDefaultDeclaration(node) {
|
|
56
|
+
if ('declaration' in node && node.declaration && isNodeOfType(node.declaration, 'Identifier') && node.declaration.name in legacyIconImports) {
|
|
57
|
+
context.report({
|
|
58
|
+
node: node,
|
|
59
|
+
messageId: 'noLegacyIcons',
|
|
60
|
+
data: {
|
|
61
|
+
importSource: legacyIconImports[node.declaration.name],
|
|
62
|
+
iconName: node.declaration.name
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
ExportNamedDeclaration: function ExportNamedDeclaration(node) {
|
|
68
|
+
if ('source' in node && node.source && isNodeOfType(node.source, 'Literal') && 'value' in node.source) {
|
|
69
|
+
var moduleSource = node.source.value;
|
|
70
|
+
if (typeof moduleSource === 'string' && ['@atlaskit/icon/glyph/', '@atlaskit/icon-object/glyph/'].find(function (val) {
|
|
71
|
+
return moduleSource.startsWith(val);
|
|
72
|
+
}) && node.specifiers.length) {
|
|
73
|
+
context.report({
|
|
74
|
+
node: node,
|
|
75
|
+
messageId: 'noLegacyIcons',
|
|
76
|
+
data: {
|
|
77
|
+
importSource: moduleSource,
|
|
78
|
+
iconName: node.specifiers[0].exported.name
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
} else if ('declaration' in node && node.declaration && isNodeOfType(node.declaration, 'VariableDeclaration')) {
|
|
83
|
+
var _iterator2 = _createForOfIteratorHelper(node.declaration.declarations),
|
|
84
|
+
_step2;
|
|
85
|
+
try {
|
|
86
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
87
|
+
var decl = _step2.value;
|
|
88
|
+
if (isNodeOfType(decl, 'VariableDeclarator') && 'init' in decl && decl.init && isNodeOfType(decl.init, 'Identifier') && decl.init.name in legacyIconImports) {
|
|
89
|
+
context.report({
|
|
90
|
+
node: node,
|
|
91
|
+
messageId: 'noLegacyIcons',
|
|
92
|
+
data: {
|
|
93
|
+
importSource: legacyIconImports[decl.init.name],
|
|
94
|
+
iconName: decl.init.name
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} catch (err) {
|
|
100
|
+
_iterator2.e(err);
|
|
101
|
+
} finally {
|
|
102
|
+
_iterator2.f();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
JSXAttribute: function JSXAttribute(node) {
|
|
107
|
+
if (!isNodeOfType(node.value, 'JSXExpressionContainer')) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (isNodeOfType(node.value.expression, 'Identifier') && node.value.expression.name in legacyIconImports && isNodeOfType(node.name, 'JSXIdentifier') && !node.name.name.startsWith('LEGACY_')) {
|
|
111
|
+
context.report({
|
|
112
|
+
node: node,
|
|
113
|
+
messageId: 'noLegacyIcons',
|
|
114
|
+
data: {
|
|
115
|
+
importSource: legacyIconImports[node.value.expression.name],
|
|
116
|
+
iconName: node.value.expression.name
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
JSXElement: function JSXElement(node) {
|
|
122
|
+
if (!isNodeOfType(node, 'JSXElement')) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (!isNodeOfType(node.openingElement.name, 'JSXIdentifier')) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
var name = node.openingElement.name.name;
|
|
129
|
+
if (name in legacyIconImports) {
|
|
130
|
+
context.report({
|
|
131
|
+
node: node,
|
|
132
|
+
messageId: 'noLegacyIcons',
|
|
133
|
+
data: {
|
|
134
|
+
importSource: legacyIconImports[name],
|
|
135
|
+
iconName: name
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
CallExpression: function CallExpression(node) {
|
|
141
|
+
if ('arguments' in node && node.arguments.length) {
|
|
142
|
+
var _iterator3 = _createForOfIteratorHelper(node.arguments),
|
|
143
|
+
_step3;
|
|
144
|
+
try {
|
|
145
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
146
|
+
var arg = _step3.value;
|
|
147
|
+
if (isNodeOfType(arg, 'Identifier') && arg.name in legacyIconImports) {
|
|
148
|
+
context.report({
|
|
149
|
+
node: arg,
|
|
150
|
+
messageId: 'noLegacyIcons',
|
|
151
|
+
data: {
|
|
152
|
+
importSource: legacyIconImports[arg.name],
|
|
153
|
+
iconName: arg.name
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
} catch (err) {
|
|
159
|
+
_iterator3.e(err);
|
|
160
|
+
} finally {
|
|
161
|
+
_iterator3.f();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
export default rule;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
+
|
|
3
|
+
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
4
|
+
import { createLintRule } from '../utils/create-rule';
|
|
5
|
+
var elementsAccessibleNameProps = ['title', 'titleId'];
|
|
6
|
+
var rule = createLintRule({
|
|
7
|
+
meta: {
|
|
8
|
+
name: 'use-menu-section-title',
|
|
9
|
+
type: 'suggestion',
|
|
10
|
+
docs: {
|
|
11
|
+
description: 'Encourages makers to provide accessible title for Atlassian Design System Menu Section component.',
|
|
12
|
+
recommended: true,
|
|
13
|
+
severity: 'warn'
|
|
14
|
+
},
|
|
15
|
+
messages: {
|
|
16
|
+
missingTitleProp: 'Missing accessible title. If there is no visible content to associate use `title` prop, otherwise pass id of element to `titleId` prop to be associated as label.',
|
|
17
|
+
titlePropShouldHaveContents: 'Define the string that labels the interactive element.',
|
|
18
|
+
titleIdShouldHaveValue: '`titleId` should reference the id of the element that defines the accessible name.',
|
|
19
|
+
noBothPropsUsage: 'Do not include both `titleId` and `title` properties. Use `titleId` if the label text is available in the DOM to reference it, otherwise use `title` to provide accessible name explicitly.'
|
|
20
|
+
},
|
|
21
|
+
hasSuggestions: true
|
|
22
|
+
},
|
|
23
|
+
create: function create(context) {
|
|
24
|
+
var contextLocalIdentifier = [];
|
|
25
|
+
return {
|
|
26
|
+
ImportDeclaration: function ImportDeclaration(node) {
|
|
27
|
+
var _node$specifiers;
|
|
28
|
+
var menuSectionIdentifier = (_node$specifiers = node.specifiers) === null || _node$specifiers === void 0 ? void 0 : _node$specifiers.filter(function (spec) {
|
|
29
|
+
if (node.source.value === '@atlaskit/menu') {
|
|
30
|
+
var _spec$imported;
|
|
31
|
+
return spec.type === 'ImportSpecifier' && ((_spec$imported = spec.imported) === null || _spec$imported === void 0 ? void 0 : _spec$imported.name) === 'Section';
|
|
32
|
+
} else if (node.source.value === '@atlaskit/menu/section') {
|
|
33
|
+
return spec.type === 'ImportDefaultSpecifier';
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
if (menuSectionIdentifier !== null && menuSectionIdentifier !== void 0 && menuSectionIdentifier.length) {
|
|
37
|
+
var local = menuSectionIdentifier[0].local;
|
|
38
|
+
contextLocalIdentifier.push(local.name);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
JSXElement: function JSXElement(node) {
|
|
42
|
+
if (!isNodeOfType(node, 'JSXElement')) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (!isNodeOfType(node.openingElement.name, 'JSXIdentifier')) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
var name = node.openingElement.name.name;
|
|
49
|
+
if (contextLocalIdentifier.includes(name)) {
|
|
50
|
+
var componentLabelProps = node.openingElement.attributes.filter(function (attr) {
|
|
51
|
+
return isNodeOfType(attr, 'JSXAttribute') && isNodeOfType(attr.name, 'JSXIdentifier') && elementsAccessibleNameProps.includes(attr.name.name);
|
|
52
|
+
});
|
|
53
|
+
if (componentLabelProps.length === 1) {
|
|
54
|
+
var prop = componentLabelProps[0];
|
|
55
|
+
if ('value' in prop && prop.value) {
|
|
56
|
+
if (isNodeOfType(prop.value, 'Literal') && !prop.value.value || isNodeOfType(prop.value, 'JSXExpressionContainer') && !prop.value.expression) {
|
|
57
|
+
context.report({
|
|
58
|
+
node: prop,
|
|
59
|
+
messageId: prop.name.name === 'title' ? 'titlePropShouldHaveContents' : 'titleIdShouldHaveValue'
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} else if (componentLabelProps.length > 1) {
|
|
64
|
+
context.report({
|
|
65
|
+
node: node.openingElement,
|
|
66
|
+
messageId: 'noBothPropsUsage'
|
|
67
|
+
});
|
|
68
|
+
} else {
|
|
69
|
+
context.report({
|
|
70
|
+
node: node.openingElement,
|
|
71
|
+
messageId: 'missingTitleProp'
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
export default rule;
|
|
@@ -20,6 +20,7 @@ export declare const configs: {
|
|
|
20
20
|
'@atlaskit/design-system/no-html-button': string;
|
|
21
21
|
'@atlaskit/design-system/no-invalid-css-map': string;
|
|
22
22
|
'@atlaskit/design-system/no-keyframes-tagged-template-expression': string;
|
|
23
|
+
'@atlaskit/design-system/no-legacy-icons': string;
|
|
23
24
|
'@atlaskit/design-system/no-margin': string;
|
|
24
25
|
'@atlaskit/design-system/no-nested-styles': string;
|
|
25
26
|
'@atlaskit/design-system/no-physical-properties': string;
|
|
@@ -34,6 +35,7 @@ export declare const configs: {
|
|
|
34
35
|
'@atlaskit/design-system/use-heading-level-in-spotlight-card': string;
|
|
35
36
|
'@atlaskit/design-system/use-href-in-link-item': string;
|
|
36
37
|
'@atlaskit/design-system/use-latest-xcss-syntax': string;
|
|
38
|
+
'@atlaskit/design-system/use-menu-section-title': string;
|
|
37
39
|
'@atlaskit/design-system/use-popup-label': string;
|
|
38
40
|
'@atlaskit/design-system/use-primitives': string;
|
|
39
41
|
'@atlaskit/design-system/use-primitives-text': string;
|
|
@@ -67,6 +69,7 @@ export declare const configs: {
|
|
|
67
69
|
'@atlaskit/design-system/use-heading-level-in-spotlight-card': string;
|
|
68
70
|
'@atlaskit/design-system/use-href-in-link-item': string;
|
|
69
71
|
'@atlaskit/design-system/use-latest-xcss-syntax': string;
|
|
72
|
+
'@atlaskit/design-system/use-menu-section-title': string;
|
|
70
73
|
'@atlaskit/design-system/use-popup-label': string;
|
|
71
74
|
'@atlaskit/design-system/use-visually-hidden': string;
|
|
72
75
|
};
|
|
@@ -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::837556032f39113ae86785a120bb9ccb>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
declare const _default: {
|
|
@@ -23,6 +23,7 @@ declare const _default: {
|
|
|
23
23
|
'@atlaskit/design-system/no-html-button': string;
|
|
24
24
|
'@atlaskit/design-system/no-invalid-css-map': string;
|
|
25
25
|
'@atlaskit/design-system/no-keyframes-tagged-template-expression': string;
|
|
26
|
+
'@atlaskit/design-system/no-legacy-icons': string;
|
|
26
27
|
'@atlaskit/design-system/no-margin': string;
|
|
27
28
|
'@atlaskit/design-system/no-nested-styles': string;
|
|
28
29
|
'@atlaskit/design-system/no-physical-properties': string;
|
|
@@ -37,6 +38,7 @@ declare const _default: {
|
|
|
37
38
|
'@atlaskit/design-system/use-heading-level-in-spotlight-card': string;
|
|
38
39
|
'@atlaskit/design-system/use-href-in-link-item': string;
|
|
39
40
|
'@atlaskit/design-system/use-latest-xcss-syntax': string;
|
|
41
|
+
'@atlaskit/design-system/use-menu-section-title': string;
|
|
40
42
|
'@atlaskit/design-system/use-popup-label': string;
|
|
41
43
|
'@atlaskit/design-system/use-primitives': string;
|
|
42
44
|
'@atlaskit/design-system/use-primitives-text': string;
|
|
@@ -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::b7ed527a03208f0bc68f9d34e4ef2260>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
declare const _default: {
|
|
@@ -28,6 +28,7 @@ declare const _default: {
|
|
|
28
28
|
'@atlaskit/design-system/use-heading-level-in-spotlight-card': string;
|
|
29
29
|
'@atlaskit/design-system/use-href-in-link-item': string;
|
|
30
30
|
'@atlaskit/design-system/use-latest-xcss-syntax': string;
|
|
31
|
+
'@atlaskit/design-system/use-menu-section-title': string;
|
|
31
32
|
'@atlaskit/design-system/use-popup-label': string;
|
|
32
33
|
'@atlaskit/design-system/use-visually-hidden': string;
|
|
33
34
|
};
|
|
@@ -20,6 +20,7 @@ declare const _default: {
|
|
|
20
20
|
'no-html-button': import("eslint").Rule.RuleModule;
|
|
21
21
|
'no-invalid-css-map': import("eslint").Rule.RuleModule;
|
|
22
22
|
'no-keyframes-tagged-template-expression': import("eslint").Rule.RuleModule;
|
|
23
|
+
'no-legacy-icons': import("eslint").Rule.RuleModule;
|
|
23
24
|
'no-margin': import("eslint").Rule.RuleModule;
|
|
24
25
|
'no-nested-styles': import("eslint").Rule.RuleModule;
|
|
25
26
|
'no-physical-properties': import("eslint").Rule.RuleModule;
|
|
@@ -34,6 +35,7 @@ declare const _default: {
|
|
|
34
35
|
'use-heading-level-in-spotlight-card': import("eslint").Rule.RuleModule;
|
|
35
36
|
'use-href-in-link-item': import("eslint").Rule.RuleModule;
|
|
36
37
|
'use-latest-xcss-syntax': import("eslint").Rule.RuleModule;
|
|
38
|
+
'use-menu-section-title': import("eslint").Rule.RuleModule;
|
|
37
39
|
'use-popup-label': import("eslint").Rule.RuleModule;
|
|
38
40
|
'use-primitives': import("eslint").Rule.RuleModule;
|
|
39
41
|
'use-primitives-text': import("eslint").Rule.RuleModule;
|
|
@@ -20,6 +20,7 @@ export declare const configs: {
|
|
|
20
20
|
'@atlaskit/design-system/no-html-button': string;
|
|
21
21
|
'@atlaskit/design-system/no-invalid-css-map': string;
|
|
22
22
|
'@atlaskit/design-system/no-keyframes-tagged-template-expression': string;
|
|
23
|
+
'@atlaskit/design-system/no-legacy-icons': string;
|
|
23
24
|
'@atlaskit/design-system/no-margin': string;
|
|
24
25
|
'@atlaskit/design-system/no-nested-styles': string;
|
|
25
26
|
'@atlaskit/design-system/no-physical-properties': string;
|
|
@@ -34,6 +35,7 @@ export declare const configs: {
|
|
|
34
35
|
'@atlaskit/design-system/use-heading-level-in-spotlight-card': string;
|
|
35
36
|
'@atlaskit/design-system/use-href-in-link-item': string;
|
|
36
37
|
'@atlaskit/design-system/use-latest-xcss-syntax': string;
|
|
38
|
+
'@atlaskit/design-system/use-menu-section-title': string;
|
|
37
39
|
'@atlaskit/design-system/use-popup-label': string;
|
|
38
40
|
'@atlaskit/design-system/use-primitives': string;
|
|
39
41
|
'@atlaskit/design-system/use-primitives-text': string;
|
|
@@ -67,6 +69,7 @@ export declare const configs: {
|
|
|
67
69
|
'@atlaskit/design-system/use-heading-level-in-spotlight-card': string;
|
|
68
70
|
'@atlaskit/design-system/use-href-in-link-item': string;
|
|
69
71
|
'@atlaskit/design-system/use-latest-xcss-syntax': string;
|
|
72
|
+
'@atlaskit/design-system/use-menu-section-title': string;
|
|
70
73
|
'@atlaskit/design-system/use-popup-label': string;
|
|
71
74
|
'@atlaskit/design-system/use-visually-hidden': string;
|
|
72
75
|
};
|