@atlaskit/eslint-plugin-design-system 13.6.0 → 13.8.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 +22 -0
- package/README.md +56 -54
- package/dist/cjs/presets/all-flat.codegen.js +3 -1
- package/dist/cjs/presets/all.codegen.js +3 -1
- package/dist/cjs/presets/recommended-flat.codegen.js +3 -1
- package/dist/cjs/presets/recommended.codegen.js +3 -1
- package/dist/cjs/rules/index.codegen.js +5 -1
- package/dist/cjs/rules/no-html-anchor/node-types/styled-component/index.js +2 -2
- package/dist/cjs/rules/no-html-button/node-types/styled-component/index.js +2 -2
- package/dist/cjs/rules/no-html-image/index.js +40 -0
- package/dist/cjs/rules/no-html-image/node-types/index.js +19 -0
- package/dist/cjs/rules/no-html-image/node-types/jsx-element/index.js +115 -0
- package/dist/cjs/rules/no-html-image/node-types/styled-component/index.js +42 -0
- package/dist/cjs/rules/no-html-image/node-types/supported.js +72 -0
- package/dist/cjs/rules/no-html-range/index.js +34 -0
- package/dist/cjs/rules/no-html-range/node-types/index.js +12 -0
- package/dist/cjs/rules/no-html-range/node-types/jsx-element/index.js +27 -0
- package/dist/cjs/rules/no-html-range/node-types/supported.js +70 -0
- package/dist/cjs/rules/utils/get-styled-component-call.js +1 -1
- package/dist/es2019/presets/all-flat.codegen.js +3 -1
- package/dist/es2019/presets/all.codegen.js +3 -1
- package/dist/es2019/presets/recommended-flat.codegen.js +3 -1
- package/dist/es2019/presets/recommended.codegen.js +3 -1
- package/dist/es2019/rules/index.codegen.js +5 -1
- package/dist/es2019/rules/no-html-anchor/node-types/styled-component/index.js +2 -2
- package/dist/es2019/rules/no-html-button/node-types/styled-component/index.js +2 -2
- package/dist/es2019/rules/no-html-image/index.js +34 -0
- package/dist/es2019/rules/no-html-image/node-types/index.js +2 -0
- package/dist/es2019/rules/no-html-image/node-types/jsx-element/index.js +80 -0
- package/dist/es2019/rules/no-html-image/node-types/styled-component/index.js +37 -0
- package/dist/es2019/rules/no-html-image/node-types/supported.js +62 -0
- package/dist/es2019/rules/no-html-range/index.js +28 -0
- package/dist/es2019/rules/no-html-range/node-types/index.js +1 -0
- package/dist/es2019/rules/no-html-range/node-types/jsx-element/index.js +19 -0
- package/dist/es2019/rules/no-html-range/node-types/supported.js +60 -0
- package/dist/es2019/rules/utils/get-styled-component-call.js +1 -1
- package/dist/esm/presets/all-flat.codegen.js +3 -1
- package/dist/esm/presets/all.codegen.js +3 -1
- package/dist/esm/presets/recommended-flat.codegen.js +3 -1
- package/dist/esm/presets/recommended.codegen.js +3 -1
- package/dist/esm/rules/index.codegen.js +5 -1
- package/dist/esm/rules/no-html-anchor/node-types/styled-component/index.js +2 -2
- package/dist/esm/rules/no-html-button/node-types/styled-component/index.js +2 -2
- package/dist/esm/rules/no-html-image/index.js +34 -0
- package/dist/esm/rules/no-html-image/node-types/index.js +2 -0
- package/dist/esm/rules/no-html-image/node-types/jsx-element/index.js +106 -0
- package/dist/esm/rules/no-html-image/node-types/styled-component/index.js +36 -0
- package/dist/esm/rules/no-html-image/node-types/supported.js +63 -0
- package/dist/esm/rules/no-html-range/index.js +28 -0
- package/dist/esm/rules/no-html-range/node-types/index.js +1 -0
- package/dist/esm/rules/no-html-range/node-types/jsx-element/index.js +18 -0
- package/dist/esm/rules/no-html-range/node-types/supported.js +61 -0
- package/dist/esm/rules/utils/get-styled-component-call.js +1 -1
- package/dist/types/index.codegen.d.ts +18 -0
- package/dist/types/presets/all-flat.codegen.d.ts +2 -0
- package/dist/types/presets/all.codegen.d.ts +2 -0
- package/dist/types/presets/recommended-flat.codegen.d.ts +2 -0
- package/dist/types/presets/recommended.codegen.d.ts +2 -0
- package/dist/types/rules/index.codegen.d.ts +2 -0
- package/dist/types/rules/no-html-image/index.d.ts +3 -0
- package/dist/types/rules/no-html-image/node-types/index.d.ts +2 -0
- package/dist/types/rules/no-html-image/node-types/jsx-element/index.d.ts +8 -0
- package/dist/types/rules/no-html-image/node-types/styled-component/index.d.ts +8 -0
- package/dist/types/rules/no-html-image/node-types/supported.d.ts +7 -0
- package/dist/types/rules/no-html-range/index.d.ts +3 -0
- package/dist/types/rules/no-html-range/node-types/index.d.ts +1 -0
- package/dist/types/rules/no-html-range/node-types/jsx-element/index.d.ts +8 -0
- package/dist/types/rules/no-html-range/node-types/supported.d.ts +7 -0
- package/dist/types-ts4.5/index.codegen.d.ts +18 -0
- package/dist/types-ts4.5/presets/all-flat.codegen.d.ts +2 -0
- package/dist/types-ts4.5/presets/all.codegen.d.ts +2 -0
- package/dist/types-ts4.5/presets/recommended-flat.codegen.d.ts +2 -0
- package/dist/types-ts4.5/presets/recommended.codegen.d.ts +2 -0
- package/dist/types-ts4.5/rules/index.codegen.d.ts +2 -0
- package/dist/types-ts4.5/rules/no-html-image/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/no-html-image/node-types/index.d.ts +2 -0
- package/dist/types-ts4.5/rules/no-html-image/node-types/jsx-element/index.d.ts +8 -0
- package/dist/types-ts4.5/rules/no-html-image/node-types/styled-component/index.d.ts +8 -0
- package/dist/types-ts4.5/rules/no-html-image/node-types/supported.d.ts +7 -0
- package/dist/types-ts4.5/rules/no-html-range/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/no-html-range/node-types/index.d.ts +1 -0
- package/dist/types-ts4.5/rules/no-html-range/node-types/jsx-element/index.d.ts +8 -0
- package/dist/types-ts4.5/rules/no-html-range/node-types/supported.d.ts +7 -0
- package/package.json +1 -1
- package/dist/cjs/rules/no-html-anchor/node-types/styled-component/get-styled-component-call.js +0 -47
- package/dist/cjs/rules/no-html-button/node-types/styled-component/get-styled-component-call.js +0 -47
- package/dist/cjs/rules/no-html-button/utils/get-jsx-element-by-name.js +0 -53
- package/dist/es2019/rules/no-html-anchor/node-types/styled-component/get-styled-component-call.js +0 -42
- package/dist/es2019/rules/no-html-button/node-types/styled-component/get-styled-component-call.js +0 -42
- package/dist/es2019/rules/no-html-button/utils/get-jsx-element-by-name.js +0 -39
- package/dist/esm/rules/no-html-anchor/node-types/styled-component/get-styled-component-call.js +0 -42
- package/dist/esm/rules/no-html-button/node-types/styled-component/get-styled-component-call.js +0 -42
- package/dist/esm/rules/no-html-button/utils/get-jsx-element-by-name.js +0 -47
- package/dist/types/rules/no-html-anchor/node-types/styled-component/get-styled-component-call.d.ts +0 -6
- package/dist/types/rules/no-html-anchor/utils/get-jsx-element-by-name.d.ts +0 -6
- package/dist/types/rules/no-html-button/node-types/styled-component/get-styled-component-call.d.ts +0 -6
- package/dist/types/rules/no-html-button/utils/get-jsx-element-by-name.d.ts +0 -6
- package/dist/types-ts4.5/rules/no-html-anchor/node-types/styled-component/get-styled-component-call.d.ts +0 -6
- package/dist/types-ts4.5/rules/no-html-button/node-types/styled-component/get-styled-component-call.d.ts +0 -6
- /package/dist/cjs/rules/{no-html-anchor → no-html-image}/utils/get-jsx-element-by-name.js +0 -0
- /package/dist/es2019/rules/{no-html-anchor → no-html-image}/utils/get-jsx-element-by-name.js +0 -0
- /package/dist/esm/rules/{no-html-anchor → no-html-image}/utils/get-jsx-element-by-name.js +0 -0
- /package/dist/{types-ts4.5/rules/no-html-button → types/rules/no-html-image}/utils/get-jsx-element-by-name.d.ts +0 -0
- /package/dist/types-ts4.5/rules/{no-html-anchor → no-html-image}/utils/get-jsx-element-by-name.d.ts +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.StyledComponent = void 0;
|
|
7
|
+
var _eslintCodemodUtils = require("eslint-codemod-utils");
|
|
8
|
+
var _contextCompat = require("@atlaskit/eslint-utils/context-compat");
|
|
9
|
+
var _getStyledComponentCall = require("../../../utils/get-styled-component-call");
|
|
10
|
+
var _getJsxElementByName2 = require("../../utils/get-jsx-element-by-name");
|
|
11
|
+
var _supported = require("../supported");
|
|
12
|
+
/* eslint-disable @repo/internal/react/require-jsdoc */
|
|
13
|
+
|
|
14
|
+
var StyledComponent = exports.StyledComponent = {
|
|
15
|
+
lint: function lint(node, _ref) {
|
|
16
|
+
var _getJsxElementByName;
|
|
17
|
+
var context = _ref.context;
|
|
18
|
+
if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'CallExpression') || !(0, _eslintCodemodUtils.isNodeOfType)(node.callee, 'MemberExpression') || !(0, _eslintCodemodUtils.isNodeOfType)(node.callee.object, 'Identifier') || !(0, _eslintCodemodUtils.isNodeOfType)(node.callee.property, 'Identifier')) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
var styles = (0, _getStyledComponentCall.getStyledComponentCall)(node);
|
|
22
|
+
var elementName = node.callee.property.name;
|
|
23
|
+
if (!styles || !(0, _eslintCodemodUtils.isNodeOfType)(styles.id, 'Identifier')) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
var jsxElement = (_getJsxElementByName = (0, _getJsxElementByName2.getJsxElementByName)(styles.id.name, (0, _contextCompat.getScope)(context, node))) === null || _getJsxElementByName === void 0 ? void 0 : _getJsxElementByName.parent;
|
|
27
|
+
if (!jsxElement) {
|
|
28
|
+
// If there's no JSX element, we can't determine if it's being used as an image or not
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (jsxElement && !(0, _supported.isSupportedForLint)(jsxElement, elementName)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
context.report({
|
|
35
|
+
node: styles,
|
|
36
|
+
messageId: 'noHtmlImage',
|
|
37
|
+
data: {
|
|
38
|
+
name: node.callee.property.name
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.isSupportedForLint = isSupportedForLint;
|
|
8
|
+
var _eslintCodemodUtils = require("eslint-codemod-utils");
|
|
9
|
+
var ast = _interopRequireWildcard(require("../../../ast-nodes"));
|
|
10
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
11
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
12
|
+
var supportedElements = [{
|
|
13
|
+
name: 'img'
|
|
14
|
+
}, {
|
|
15
|
+
name: '*',
|
|
16
|
+
attributes: [{
|
|
17
|
+
name: 'role',
|
|
18
|
+
values: ['img']
|
|
19
|
+
}]
|
|
20
|
+
}];
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Determines if the given JSX element is a supported element to lint with this rule.
|
|
24
|
+
*/
|
|
25
|
+
function isSupportedForLint(jsxNode, elementName) {
|
|
26
|
+
if (!(0, _eslintCodemodUtils.isNodeOfType)(jsxNode, 'JSXElement')) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Allow passing in the element name because the jsxNode doesn't
|
|
31
|
+
// represent the element name with styled components
|
|
32
|
+
var elName = elementName || ast.JSXElement.getName(jsxNode);
|
|
33
|
+
if (!elName) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Only check native HTML elements, not components
|
|
38
|
+
if (elName[0] !== elName[0].toLowerCase()) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
var supportedElement = supportedElements.find(function (_ref) {
|
|
42
|
+
var name = _ref.name;
|
|
43
|
+
return name === elName;
|
|
44
|
+
});
|
|
45
|
+
if (!supportedElement) {
|
|
46
|
+
supportedElement = supportedElements.find(function (_ref2) {
|
|
47
|
+
var name = _ref2.name;
|
|
48
|
+
return name === '*';
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
if (!supportedElement) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Check if the element has any attributes that are not supported
|
|
56
|
+
var attributes = ast.JSXElement.getAttributes(jsxNode);
|
|
57
|
+
if (supportedElement.attributes && !supportedElement.attributes.every(function (_ref3) {
|
|
58
|
+
var name = _ref3.name,
|
|
59
|
+
values = _ref3.values;
|
|
60
|
+
return attributes.some(function (attribute) {
|
|
61
|
+
if (attribute.type === 'JSXSpreadAttribute') {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
var isMatchingName = attribute.name.name === name;
|
|
65
|
+
var isMatchingValues = values && attribute.value && attribute.value.type === 'Literal' && typeof attribute.value.value === 'string' && (values === null || values === void 0 ? void 0 : values.includes(attribute.value.value));
|
|
66
|
+
return isMatchingName && isMatchingValues;
|
|
67
|
+
});
|
|
68
|
+
})) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _createRule = require("../utils/create-rule");
|
|
8
|
+
var _nodeTypes = require("./node-types");
|
|
9
|
+
var rule = (0, _createRule.createLintRule)({
|
|
10
|
+
meta: {
|
|
11
|
+
name: 'no-html-range',
|
|
12
|
+
type: 'suggestion',
|
|
13
|
+
hasSuggestions: true,
|
|
14
|
+
docs: {
|
|
15
|
+
description: 'Discourage direct usage of HTML range elements in favor of the Atlassian Design System range component.',
|
|
16
|
+
recommended: true,
|
|
17
|
+
severity: 'warn'
|
|
18
|
+
},
|
|
19
|
+
messages: {
|
|
20
|
+
noHtmlRange: "This <{{ name }}> should be replaced with a range component from the Atlassian Design System. ADS components include event tracking, ensure accessible implementations, and provide access to ADS styling features like design tokens."
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
create: function create(context) {
|
|
24
|
+
return {
|
|
25
|
+
// transforms <input type="range" css={...}> usages
|
|
26
|
+
JSXElement: function JSXElement(node) {
|
|
27
|
+
_nodeTypes.JSXElement.lint(node, {
|
|
28
|
+
context: context
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
var _default = exports.default = rule;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "JSXElement", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function get() {
|
|
9
|
+
return _jsxElement.JSXElement;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
var _jsxElement = require("./jsx-element");
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.JSXElement = void 0;
|
|
8
|
+
var ast = _interopRequireWildcard(require("../../../../ast-nodes"));
|
|
9
|
+
var _supported = require("../supported");
|
|
10
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
11
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
12
|
+
var JSXElement = exports.JSXElement = {
|
|
13
|
+
lint: function lint(node, _ref) {
|
|
14
|
+
var context = _ref.context;
|
|
15
|
+
if (!(0, _supported.isSupportedForLint)(node)) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
var nodeName = ast.JSXElement.getName(node);
|
|
19
|
+
context.report({
|
|
20
|
+
node: node.openingElement,
|
|
21
|
+
messageId: 'noHtmlRange',
|
|
22
|
+
data: {
|
|
23
|
+
name: nodeName
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.isSupportedForLint = isSupportedForLint;
|
|
8
|
+
var _eslintCodemodUtils = require("eslint-codemod-utils");
|
|
9
|
+
var ast = _interopRequireWildcard(require("../../../ast-nodes"));
|
|
10
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
11
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
12
|
+
var supportedElements = [{
|
|
13
|
+
name: 'input',
|
|
14
|
+
attributes: [{
|
|
15
|
+
name: 'type',
|
|
16
|
+
values: ['range']
|
|
17
|
+
}]
|
|
18
|
+
}];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Determines if the given JSX element is a supported element to lint with this rule.
|
|
22
|
+
*/
|
|
23
|
+
function isSupportedForLint(jsxNode, elementName) {
|
|
24
|
+
if (!(0, _eslintCodemodUtils.isNodeOfType)(jsxNode, 'JSXElement')) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Allow passing in the element name because the jsxNode doesn't
|
|
29
|
+
// represent the element name with styled components
|
|
30
|
+
var elName = elementName || ast.JSXElement.getName(jsxNode);
|
|
31
|
+
if (!elName) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Only check native HTML elements, not components
|
|
36
|
+
if (elName[0] !== elName[0].toLowerCase()) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
var supportedElement = supportedElements.find(function (_ref) {
|
|
40
|
+
var name = _ref.name;
|
|
41
|
+
return name === elName;
|
|
42
|
+
});
|
|
43
|
+
if (!supportedElement) {
|
|
44
|
+
supportedElement = supportedElements.find(function (_ref2) {
|
|
45
|
+
var name = _ref2.name;
|
|
46
|
+
return name === '*';
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (!supportedElement) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Check if the element has any attributes that are not supported
|
|
54
|
+
var attributes = ast.JSXElement.getAttributes(jsxNode);
|
|
55
|
+
if (supportedElement.attributes && !supportedElement.attributes.every(function (_ref3) {
|
|
56
|
+
var name = _ref3.name,
|
|
57
|
+
values = _ref3.values;
|
|
58
|
+
return attributes.some(function (attribute) {
|
|
59
|
+
if (attribute.type === 'JSXSpreadAttribute') {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
var isMatchingName = attribute.name.name === name;
|
|
63
|
+
var isMatchingValues = values && attribute.value && attribute.value.type === 'Literal' && typeof attribute.value.value === 'string' && (values === null || values === void 0 ? void 0 : values.includes(attribute.value.value));
|
|
64
|
+
return isMatchingName && isMatchingValues;
|
|
65
|
+
});
|
|
66
|
+
})) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
@@ -28,7 +28,7 @@ var getStyledComponentCall = exports.getStyledComponentCall = function getStyled
|
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* Some verbose precondition checks but all it does is check
|
|
31
|
-
* a call expression is of form `styled
|
|
31
|
+
* a call expression is of form `styled.<element>` or `styled2.<element>`
|
|
32
32
|
*/
|
|
33
33
|
var isStyledCallExpression = function isStyledCallExpression(call) {
|
|
34
34
|
if (!(0, _eslintCodemodUtils.isNodeOfType)(call, 'CallExpression')) {
|
|
@@ -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::cadedc68c5a8a92d8134b8aa5239937f>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -25,6 +25,8 @@ export default {
|
|
|
25
25
|
'@atlaskit/design-system/no-html-anchor': 'warn',
|
|
26
26
|
'@atlaskit/design-system/no-html-button': 'warn',
|
|
27
27
|
'@atlaskit/design-system/no-html-checkbox': 'warn',
|
|
28
|
+
'@atlaskit/design-system/no-html-image': 'warn',
|
|
29
|
+
'@atlaskit/design-system/no-html-range': 'warn',
|
|
28
30
|
'@atlaskit/design-system/no-invalid-css-map': ['error', {
|
|
29
31
|
allowedFunctionCalls: [['@atlaskit/tokens', 'token']]
|
|
30
32
|
}],
|
|
@@ -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::340bf9f79ec1de1340a89df9d626b929>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -24,6 +24,8 @@ export default {
|
|
|
24
24
|
'@atlaskit/design-system/no-html-anchor': 'warn',
|
|
25
25
|
'@atlaskit/design-system/no-html-button': 'warn',
|
|
26
26
|
'@atlaskit/design-system/no-html-checkbox': 'warn',
|
|
27
|
+
'@atlaskit/design-system/no-html-image': 'warn',
|
|
28
|
+
'@atlaskit/design-system/no-html-range': 'warn',
|
|
27
29
|
'@atlaskit/design-system/no-invalid-css-map': ['error', {
|
|
28
30
|
allowedFunctionCalls: [['@atlaskit/tokens', 'token']]
|
|
29
31
|
}],
|
|
@@ -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::c264ea60cc6348c4292744c1260543d8>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -20,6 +20,8 @@ export default {
|
|
|
20
20
|
'@atlaskit/design-system/no-html-anchor': 'warn',
|
|
21
21
|
'@atlaskit/design-system/no-html-button': 'warn',
|
|
22
22
|
'@atlaskit/design-system/no-html-checkbox': 'warn',
|
|
23
|
+
'@atlaskit/design-system/no-html-image': 'warn',
|
|
24
|
+
'@atlaskit/design-system/no-html-range': 'warn',
|
|
23
25
|
'@atlaskit/design-system/no-invalid-css-map': ['error', {
|
|
24
26
|
allowedFunctionCalls: [['@atlaskit/tokens', 'token']]
|
|
25
27
|
}],
|
|
@@ -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::0158deb3db6cafbdeae2aeb18673ebc2>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -19,6 +19,8 @@ export default {
|
|
|
19
19
|
'@atlaskit/design-system/no-html-anchor': 'warn',
|
|
20
20
|
'@atlaskit/design-system/no-html-button': 'warn',
|
|
21
21
|
'@atlaskit/design-system/no-html-checkbox': 'warn',
|
|
22
|
+
'@atlaskit/design-system/no-html-image': 'warn',
|
|
23
|
+
'@atlaskit/design-system/no-html-range': 'warn',
|
|
22
24
|
'@atlaskit/design-system/no-invalid-css-map': ['error', {
|
|
23
25
|
allowedFunctionCalls: [['@atlaskit/tokens', 'token']]
|
|
24
26
|
}],
|
|
@@ -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::5945e51ebc0b2c3553b51162f07dbd63>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
import consistentCssPropUsage from './consistent-css-prop-usage';
|
|
@@ -23,6 +23,8 @@ import noExportedKeyframes from './no-exported-keyframes';
|
|
|
23
23
|
import noHtmlAnchor from './no-html-anchor';
|
|
24
24
|
import noHtmlButton from './no-html-button';
|
|
25
25
|
import noHtmlCheckbox from './no-html-checkbox';
|
|
26
|
+
import noHtmlImage from './no-html-image';
|
|
27
|
+
import noHtmlRange from './no-html-range';
|
|
26
28
|
import noInvalidCssMap from './no-invalid-css-map';
|
|
27
29
|
import noKeyframesTaggedTemplateExpression from './no-keyframes-tagged-template-expression';
|
|
28
30
|
import noLegacyIcons from './no-legacy-icons';
|
|
@@ -76,6 +78,8 @@ export const rules = {
|
|
|
76
78
|
'no-html-anchor': noHtmlAnchor,
|
|
77
79
|
'no-html-button': noHtmlButton,
|
|
78
80
|
'no-html-checkbox': noHtmlCheckbox,
|
|
81
|
+
'no-html-image': noHtmlImage,
|
|
82
|
+
'no-html-range': noHtmlRange,
|
|
79
83
|
'no-invalid-css-map': noInvalidCssMap,
|
|
80
84
|
'no-keyframes-tagged-template-expression': noKeyframesTaggedTemplateExpression,
|
|
81
85
|
'no-legacy-icons': noLegacyIcons,
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
4
4
|
import { getScope } from '@atlaskit/eslint-utils/context-compat';
|
|
5
|
-
import { getJsxElementByName } from '
|
|
5
|
+
import { getJsxElementByName } from '../../../utils/get-jsx-element-by-name';
|
|
6
|
+
import { getStyledComponentCall } from '../../../utils/get-styled-component-call';
|
|
6
7
|
import { isSupportedForLint } from '../supported';
|
|
7
|
-
import { getStyledComponentCall } from './get-styled-component-call';
|
|
8
8
|
export const StyledComponent = {
|
|
9
9
|
lint(node, {
|
|
10
10
|
context
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
4
4
|
import { getScope } from '@atlaskit/eslint-utils/context-compat';
|
|
5
|
-
import { getJsxElementByName } from '
|
|
5
|
+
import { getJsxElementByName } from '../../../utils/get-jsx-element-by-name';
|
|
6
|
+
import { getStyledComponentCall } from '../../../utils/get-styled-component-call';
|
|
6
7
|
import { isSupportedForLint } from '../supported';
|
|
7
|
-
import { getStyledComponentCall } from './get-styled-component-call';
|
|
8
8
|
export const StyledComponent = {
|
|
9
9
|
lint(node, {
|
|
10
10
|
context
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createLintRule } from '../utils/create-rule';
|
|
2
|
+
import { JSXElement, StyledComponent } from './node-types';
|
|
3
|
+
const rule = createLintRule({
|
|
4
|
+
meta: {
|
|
5
|
+
name: 'no-html-image',
|
|
6
|
+
type: 'suggestion',
|
|
7
|
+
hasSuggestions: true,
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Discourage direct usage of HTML image elements in favor of the Atlassian Design System image component.',
|
|
10
|
+
recommended: true,
|
|
11
|
+
severity: 'warn'
|
|
12
|
+
},
|
|
13
|
+
messages: {
|
|
14
|
+
noHtmlImage: `This <{{ name }}> should be replaced with the image component from the Atlassian Design System. ADS images ensure accessible implementations, and provide access to ADS styling features like design tokens.`
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
create(context) {
|
|
18
|
+
return {
|
|
19
|
+
// transforms styled.<anchor>(...) usages
|
|
20
|
+
CallExpression(node) {
|
|
21
|
+
StyledComponent.lint(node, {
|
|
22
|
+
context
|
|
23
|
+
});
|
|
24
|
+
},
|
|
25
|
+
// transforms <anchor css={...}> usages
|
|
26
|
+
JSXElement(node) {
|
|
27
|
+
JSXElement.lint(node, {
|
|
28
|
+
context
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
export default rule;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
|
+
import { getSourceCode } from '@atlaskit/eslint-utils/context-compat';
|
|
3
|
+
import * as ast from '../../../../ast-nodes';
|
|
4
|
+
import { isSupportedForLint } from '../supported';
|
|
5
|
+
function isImportDeclaration(node) {
|
|
6
|
+
return node.type === 'ImportDeclaration';
|
|
7
|
+
}
|
|
8
|
+
export const JSXElement = {
|
|
9
|
+
lint(node, {
|
|
10
|
+
context
|
|
11
|
+
}) {
|
|
12
|
+
if (!isSupportedForLint(node)) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const nodeName = ast.JSXElement.getName(node);
|
|
16
|
+
const sourceCode = getSourceCode(context);
|
|
17
|
+
const importDeclarations = sourceCode.ast.body.filter(isImportDeclaration);
|
|
18
|
+
let existingImageName = null;
|
|
19
|
+
const usedNames = new Set();
|
|
20
|
+
|
|
21
|
+
// Check for existing imports
|
|
22
|
+
for (const declaration of importDeclarations) {
|
|
23
|
+
for (const specifier of declaration.specifiers) {
|
|
24
|
+
usedNames.add(specifier.local.name);
|
|
25
|
+
}
|
|
26
|
+
if (declaration.source.value === '@atlaskit/image') {
|
|
27
|
+
const defaultSpecifier = declaration.specifiers.find(specifier => specifier.type === 'ImportDefaultSpecifier');
|
|
28
|
+
if (defaultSpecifier) {
|
|
29
|
+
existingImageName = defaultSpecifier.local.name;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const generateUniqueName = baseName => {
|
|
34
|
+
let index = 1;
|
|
35
|
+
let newName = baseName;
|
|
36
|
+
while (usedNames.has(newName)) {
|
|
37
|
+
newName = `${baseName}${index}`;
|
|
38
|
+
index++;
|
|
39
|
+
}
|
|
40
|
+
return newName;
|
|
41
|
+
};
|
|
42
|
+
const imageName = existingImageName || generateUniqueName('Image');
|
|
43
|
+
context.report({
|
|
44
|
+
node: node.openingElement,
|
|
45
|
+
messageId: 'noHtmlImage',
|
|
46
|
+
data: {
|
|
47
|
+
name: nodeName
|
|
48
|
+
},
|
|
49
|
+
suggest: [{
|
|
50
|
+
desc: 'Replace with Image component from @atlaskit/image',
|
|
51
|
+
fix(fixer) {
|
|
52
|
+
var _node$closingElement;
|
|
53
|
+
const openingTagRange = node.openingElement.range;
|
|
54
|
+
const closingTagRange = (_node$closingElement = node.closingElement) === null || _node$closingElement === void 0 ? void 0 : _node$closingElement.range;
|
|
55
|
+
const attributesText = node.openingElement.attributes.filter(attr => !isNodeOfType(attr, 'JSXAttribute') || attr.name.name !== 'role').map(attr => sourceCode.getText(attr)).join(' ');
|
|
56
|
+
const fixers = [];
|
|
57
|
+
|
|
58
|
+
// Replace <img> with <Image> and retain attributes
|
|
59
|
+
if (openingTagRange) {
|
|
60
|
+
if (node.openingElement.selfClosing) {
|
|
61
|
+
fixers.push(fixer.replaceTextRange([openingTagRange[0] + 1, openingTagRange[1] - 1], `${imageName}${attributesText ? ` ${attributesText}` : ''} /`));
|
|
62
|
+
} else {
|
|
63
|
+
fixers.push(fixer.replaceTextRange([openingTagRange[0] + 1, openingTagRange[1] - 1], `${imageName}${attributesText ? ` ${attributesText}` : ''}`));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (closingTagRange && !node.openingElement.selfClosing) {
|
|
67
|
+
fixers.push(fixer.replaceTextRange([closingTagRange[0] + 2, closingTagRange[1] - 1], imageName));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Add import if not present
|
|
71
|
+
if (!existingImageName) {
|
|
72
|
+
const importStatement = `import ${imageName} from '@atlaskit/image';\n`;
|
|
73
|
+
fixers.push(fixer.insertTextBefore(sourceCode.ast, importStatement));
|
|
74
|
+
}
|
|
75
|
+
return fixers;
|
|
76
|
+
}
|
|
77
|
+
}]
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/* eslint-disable @repo/internal/react/require-jsdoc */
|
|
2
|
+
|
|
3
|
+
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
4
|
+
import { getScope } from '@atlaskit/eslint-utils/context-compat';
|
|
5
|
+
import { getStyledComponentCall } from '../../../utils/get-styled-component-call';
|
|
6
|
+
import { getJsxElementByName } from '../../utils/get-jsx-element-by-name';
|
|
7
|
+
import { isSupportedForLint } from '../supported';
|
|
8
|
+
export const StyledComponent = {
|
|
9
|
+
lint(node, {
|
|
10
|
+
context
|
|
11
|
+
}) {
|
|
12
|
+
var _getJsxElementByName;
|
|
13
|
+
if (!isNodeOfType(node, 'CallExpression') || !isNodeOfType(node.callee, 'MemberExpression') || !isNodeOfType(node.callee.object, 'Identifier') || !isNodeOfType(node.callee.property, 'Identifier')) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const styles = getStyledComponentCall(node);
|
|
17
|
+
const elementName = node.callee.property.name;
|
|
18
|
+
if (!styles || !isNodeOfType(styles.id, 'Identifier')) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const jsxElement = (_getJsxElementByName = getJsxElementByName(styles.id.name, getScope(context, node))) === null || _getJsxElementByName === void 0 ? void 0 : _getJsxElementByName.parent;
|
|
22
|
+
if (!jsxElement) {
|
|
23
|
+
// If there's no JSX element, we can't determine if it's being used as an image or not
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (jsxElement && !isSupportedForLint(jsxElement, elementName)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
context.report({
|
|
30
|
+
node: styles,
|
|
31
|
+
messageId: 'noHtmlImage',
|
|
32
|
+
data: {
|
|
33
|
+
name: node.callee.property.name
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
|
+
import * as ast from '../../../ast-nodes';
|
|
3
|
+
const supportedElements = [{
|
|
4
|
+
name: 'img'
|
|
5
|
+
}, {
|
|
6
|
+
name: '*',
|
|
7
|
+
attributes: [{
|
|
8
|
+
name: 'role',
|
|
9
|
+
values: ['img']
|
|
10
|
+
}]
|
|
11
|
+
}];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Determines if the given JSX element is a supported element to lint with this rule.
|
|
15
|
+
*/
|
|
16
|
+
export function isSupportedForLint(jsxNode, elementName) {
|
|
17
|
+
if (!isNodeOfType(jsxNode, 'JSXElement')) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Allow passing in the element name because the jsxNode doesn't
|
|
22
|
+
// represent the element name with styled components
|
|
23
|
+
const elName = elementName || ast.JSXElement.getName(jsxNode);
|
|
24
|
+
if (!elName) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Only check native HTML elements, not components
|
|
29
|
+
if (elName[0] !== elName[0].toLowerCase()) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
let supportedElement = supportedElements.find(({
|
|
33
|
+
name
|
|
34
|
+
}) => name === elName);
|
|
35
|
+
if (!supportedElement) {
|
|
36
|
+
supportedElement = supportedElements.find(({
|
|
37
|
+
name
|
|
38
|
+
}) => name === '*');
|
|
39
|
+
}
|
|
40
|
+
if (!supportedElement) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Check if the element has any attributes that are not supported
|
|
45
|
+
const attributes = ast.JSXElement.getAttributes(jsxNode);
|
|
46
|
+
if (supportedElement.attributes && !supportedElement.attributes.every(({
|
|
47
|
+
name,
|
|
48
|
+
values
|
|
49
|
+
}) => {
|
|
50
|
+
return attributes.some(attribute => {
|
|
51
|
+
if (attribute.type === 'JSXSpreadAttribute') {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
const isMatchingName = attribute.name.name === name;
|
|
55
|
+
const isMatchingValues = values && attribute.value && attribute.value.type === 'Literal' && typeof attribute.value.value === 'string' && (values === null || values === void 0 ? void 0 : values.includes(attribute.value.value));
|
|
56
|
+
return isMatchingName && isMatchingValues;
|
|
57
|
+
});
|
|
58
|
+
})) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createLintRule } from '../utils/create-rule';
|
|
2
|
+
import { JSXElement } from './node-types';
|
|
3
|
+
const rule = createLintRule({
|
|
4
|
+
meta: {
|
|
5
|
+
name: 'no-html-range',
|
|
6
|
+
type: 'suggestion',
|
|
7
|
+
hasSuggestions: true,
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Discourage direct usage of HTML range elements in favor of the Atlassian Design System range component.',
|
|
10
|
+
recommended: true,
|
|
11
|
+
severity: 'warn'
|
|
12
|
+
},
|
|
13
|
+
messages: {
|
|
14
|
+
noHtmlRange: `This <{{ name }}> should be replaced with a range component from the Atlassian Design System. ADS components include event tracking, ensure accessible implementations, and provide access to ADS styling features like design tokens.`
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
create(context) {
|
|
18
|
+
return {
|
|
19
|
+
// transforms <input type="range" css={...}> usages
|
|
20
|
+
JSXElement(node) {
|
|
21
|
+
JSXElement.lint(node, {
|
|
22
|
+
context
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
export default rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { JSXElement } from './jsx-element';
|