@atlaskit/eslint-plugin-design-system 8.2.2 → 8.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +16 -15
- package/constellation/index/usage.mdx +49 -16
- package/dist/cjs/presets/all.codegen.js +2 -1
- package/dist/cjs/rules/index.codegen.js +3 -1
- package/dist/cjs/rules/no-banned-imports/paths.js +3 -0
- package/dist/cjs/rules/prefer-primitives/index.js +108 -0
- package/dist/cjs/rules/prefer-primitives/utils.js +33 -0
- package/dist/cjs/rules/use-primitives/utils.js +7 -3
- package/dist/es2019/presets/all.codegen.js +2 -1
- package/dist/es2019/rules/index.codegen.js +3 -1
- package/dist/es2019/rules/no-banned-imports/paths.js +3 -0
- package/dist/es2019/rules/prefer-primitives/index.js +102 -0
- package/dist/es2019/rules/prefer-primitives/utils.js +24 -0
- package/dist/es2019/rules/use-primitives/utils.js +5 -4
- package/dist/esm/presets/all.codegen.js +2 -1
- package/dist/esm/rules/index.codegen.js +3 -1
- package/dist/esm/rules/no-banned-imports/paths.js +3 -0
- package/dist/esm/rules/prefer-primitives/index.js +101 -0
- package/dist/esm/rules/prefer-primitives/utils.js +26 -0
- package/dist/esm/rules/use-primitives/utils.js +5 -4
- 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/prefer-primitives/index.d.ts +3 -0
- package/dist/types/rules/prefer-primitives/utils.d.ts +2 -0
- package/dist/types/rules/use-primitives/utils.d.ts +7 -1
- 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/prefer-primitives/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/prefer-primitives/utils.d.ts +2 -0
- package/dist/types-ts4.5/rules/use-primitives/utils.d.ts +7 -1
- package/package.json +2 -2
- package/report.api.md +2 -0
- package/tmp/api-report-tmp.d.ts +2 -0
- package/dist/cjs/version.json +0 -5
- package/dist/es2019/version.json +0 -5
- package/dist/esm/version.json +0 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @atlaskit/eslint-plugin-design-system
|
|
2
2
|
|
|
3
|
+
## 8.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`0128df16060`](https://bitbucket.org/atlassian/atlassian-frontend/commits/0128df16060) - Added new `prefer-primitives` rule that detects use of `<div>` and `<span>` either as HTML tags or via styled components (`styled.div`, `styled('div')`) and suggests using primitive components instead.
|
|
8
|
+
|
|
9
|
+
## 8.3.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [`87feea3d8e0`](https://bitbucket.org/atlassian/atlassian-frontend/commits/87feea3d8e0) - Add banned import rule for `@atlaskit/primitives/pressable`
|
|
14
|
+
|
|
3
15
|
## 8.2.2
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -47,20 +47,21 @@ module.exports = {
|
|
|
47
47
|
<!-- START_RULE_TABLE_CODEGEN -->
|
|
48
48
|
<!-- @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen -->
|
|
49
49
|
|
|
50
|
-
| Rule | Description
|
|
51
|
-
| ------------------------------------------------------------------------------------------------------- |
|
|
52
|
-
| <a href="./src/rules/consistent-css-prop-usage/README.md">consistent-css-prop-usage</a> | Ensures consistency with CSS and xcss prop usages
|
|
53
|
-
| <a href="./src/rules/ensure-design-token-usage/README.md">ensure-design-token-usage</a> | Enforces usage of design tokens rather than hard-coded values.
|
|
54
|
-
| <a href="./src/rules/ensure-design-token-usage-preview/README.md">ensure-design-token-usage/preview</a> | Enforces usage of pre-release design tokens rather than hard-coded values.
|
|
55
|
-
| <a href="./src/rules/icon-label/README.md">icon-label</a> | Enforces accessible usage of icon labels when composed with Atlassian Design System components.
|
|
56
|
-
| <a href="./src/rules/no-banned-imports/README.md">no-banned-imports</a> | Disallow importing banned modules.
|
|
57
|
-
| <a href="./src/rules/no-deprecated-apis/README.md">no-deprecated-apis</a> | Disallow using deprecated APIs.
|
|
58
|
-
| <a href="./src/rules/no-deprecated-design-token-usage/README.md">no-deprecated-design-token-usage</a> | Disallow using deprecated design tokens.
|
|
59
|
-
| <a href="./src/rules/no-deprecated-imports/README.md">no-deprecated-imports</a> | Disallow importing deprecated modules.
|
|
60
|
-
| <a href="./src/rules/no-margin/README.md">no-margin</a> | Disallow using the margin CSS property.
|
|
61
|
-
| <a href="./src/rules/no-nested-styles/README.md">no-nested-styles</a> | Disallows use of nested styles in `css` functions.
|
|
62
|
-
| <a href="./src/rules/no-unsafe-design-token-usage/README.md">no-unsafe-design-token-usage</a> | Enforces design token usage is statically and locally analyzable.
|
|
63
|
-
| <a href="./src/rules/
|
|
64
|
-
| <a href="./src/rules/use-
|
|
50
|
+
| Rule | Description | Recommended | Fixable | Suggestions |
|
|
51
|
+
| ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- | ----------- |
|
|
52
|
+
| <a href="./src/rules/consistent-css-prop-usage/README.md">consistent-css-prop-usage</a> | Ensures consistency with CSS and xcss prop usages | Yes | Yes | |
|
|
53
|
+
| <a href="./src/rules/ensure-design-token-usage/README.md">ensure-design-token-usage</a> | Enforces usage of design tokens rather than hard-coded values. | Yes | Yes | Yes |
|
|
54
|
+
| <a href="./src/rules/ensure-design-token-usage-preview/README.md">ensure-design-token-usage/preview</a> | Enforces usage of pre-release design tokens rather than hard-coded values. | | Yes | Yes |
|
|
55
|
+
| <a href="./src/rules/icon-label/README.md">icon-label</a> | Enforces accessible usage of icon labels when composed with Atlassian Design System components. | Yes | Yes | |
|
|
56
|
+
| <a href="./src/rules/no-banned-imports/README.md">no-banned-imports</a> | Disallow importing banned modules. | Yes | | |
|
|
57
|
+
| <a href="./src/rules/no-deprecated-apis/README.md">no-deprecated-apis</a> | Disallow using deprecated APIs. | Yes | | |
|
|
58
|
+
| <a href="./src/rules/no-deprecated-design-token-usage/README.md">no-deprecated-design-token-usage</a> | Disallow using deprecated design tokens. | Yes | Yes | |
|
|
59
|
+
| <a href="./src/rules/no-deprecated-imports/README.md">no-deprecated-imports</a> | Disallow importing deprecated modules. | Yes | | |
|
|
60
|
+
| <a href="./src/rules/no-margin/README.md">no-margin</a> | Disallow using the margin CSS property. | | | |
|
|
61
|
+
| <a href="./src/rules/no-nested-styles/README.md">no-nested-styles</a> | Disallows use of nested styles in `css` functions. | Yes | | |
|
|
62
|
+
| <a href="./src/rules/no-unsafe-design-token-usage/README.md">no-unsafe-design-token-usage</a> | Enforces design token usage is statically and locally analyzable. | Yes | Yes | |
|
|
63
|
+
| <a href="./src/rules/prefer-primitives/README.md">prefer-primitives</a> | Increase awareness of primitive components via code hints. Strictly used for education purposes and discoverability. To enforce usage please refer to the `use-primitives` rule. | | | |
|
|
64
|
+
| <a href="./src/rules/use-primitives/README.md">use-primitives</a> | Encourage the usage of primitives components. | | Yes | Yes |
|
|
65
|
+
| <a href="./src/rules/use-visually-hidden/README.md">use-visually-hidden</a> | Enforce usage of the visually hidden component. | Yes | Yes | |
|
|
65
66
|
|
|
66
67
|
<!-- END_RULE_TABLE_CODEGEN -->
|
|
@@ -11,21 +11,22 @@ This plugin contains rules that should be used when working with the [Atlassian
|
|
|
11
11
|
<!-- START_RULE_TABLE_CODEGEN -->
|
|
12
12
|
<!-- @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen -->
|
|
13
13
|
|
|
14
|
-
| Rule | Description
|
|
15
|
-
| ---------------------------------------------------------------------------------- |
|
|
16
|
-
| <a href="#consistent-css-prop-usage">consistent-css-prop-usage</a> | Ensures consistency with CSS and xcss prop usages
|
|
17
|
-
| <a href="#ensure-design-token-usage">ensure-design-token-usage</a> | Enforces usage of design tokens rather than hard-coded values.
|
|
18
|
-
| <a href="#ensure-design-token-usage-preview">ensure-design-token-usage/preview</a> | Enforces usage of pre-release design tokens rather than hard-coded values.
|
|
19
|
-
| <a href="#icon-label">icon-label</a> | Enforces accessible usage of icon labels when composed with Atlassian Design System components.
|
|
20
|
-
| <a href="#no-banned-imports">no-banned-imports</a> | Disallow importing banned modules.
|
|
21
|
-
| <a href="#no-deprecated-apis">no-deprecated-apis</a> | Disallow using deprecated APIs.
|
|
22
|
-
| <a href="#no-deprecated-design-token-usage">no-deprecated-design-token-usage</a> | Disallow using deprecated design tokens.
|
|
23
|
-
| <a href="#no-deprecated-imports">no-deprecated-imports</a> | Disallow importing deprecated modules.
|
|
24
|
-
| <a href="#no-margin">no-margin</a> | Disallow using the margin CSS property.
|
|
25
|
-
| <a href="#no-nested-styles">no-nested-styles</a> | Disallows use of nested styles in `css` functions.
|
|
26
|
-
| <a href="#no-unsafe-design-token-usage">no-unsafe-design-token-usage</a> | Enforces design token usage is statically and locally analyzable.
|
|
27
|
-
| <a href="#
|
|
28
|
-
| <a href="#use-
|
|
14
|
+
| Rule | Description | Recommended | Fixable | Suggestions |
|
|
15
|
+
| ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- | ----------- |
|
|
16
|
+
| <a href="#consistent-css-prop-usage">consistent-css-prop-usage</a> | Ensures consistency with CSS and xcss prop usages | Yes | Yes | |
|
|
17
|
+
| <a href="#ensure-design-token-usage">ensure-design-token-usage</a> | Enforces usage of design tokens rather than hard-coded values. | Yes | Yes | Yes |
|
|
18
|
+
| <a href="#ensure-design-token-usage-preview">ensure-design-token-usage/preview</a> | Enforces usage of pre-release design tokens rather than hard-coded values. | | Yes | Yes |
|
|
19
|
+
| <a href="#icon-label">icon-label</a> | Enforces accessible usage of icon labels when composed with Atlassian Design System components. | Yes | Yes | |
|
|
20
|
+
| <a href="#no-banned-imports">no-banned-imports</a> | Disallow importing banned modules. | Yes | | |
|
|
21
|
+
| <a href="#no-deprecated-apis">no-deprecated-apis</a> | Disallow using deprecated APIs. | Yes | | |
|
|
22
|
+
| <a href="#no-deprecated-design-token-usage">no-deprecated-design-token-usage</a> | Disallow using deprecated design tokens. | Yes | Yes | |
|
|
23
|
+
| <a href="#no-deprecated-imports">no-deprecated-imports</a> | Disallow importing deprecated modules. | Yes | | |
|
|
24
|
+
| <a href="#no-margin">no-margin</a> | Disallow using the margin CSS property. | | | |
|
|
25
|
+
| <a href="#no-nested-styles">no-nested-styles</a> | Disallows use of nested styles in `css` functions. | Yes | | |
|
|
26
|
+
| <a href="#no-unsafe-design-token-usage">no-unsafe-design-token-usage</a> | Enforces design token usage is statically and locally analyzable. | Yes | Yes | |
|
|
27
|
+
| <a href="#prefer-primitives">prefer-primitives</a> | Increase awareness of primitive components via code hints. Strictly used for education purposes and discoverability. To enforce usage please refer to the `use-primitives` rule. | | | |
|
|
28
|
+
| <a href="#use-primitives">use-primitives</a> | Encourage the usage of primitives components. | | Yes | Yes |
|
|
29
|
+
| <a href="#use-visually-hidden">use-visually-hidden</a> | Enforce usage of the visually hidden component. | Yes | Yes | |
|
|
29
30
|
|
|
30
31
|
<!-- END_RULE_TABLE_CODEGEN -->
|
|
31
32
|
|
|
@@ -544,6 +545,38 @@ This rule comes with options to aid in migrating to design tokens.
|
|
|
544
545
|
When `true` the rule will mark token function usage as violations when fallbacks aren't defined.
|
|
545
546
|
When `false` the rule will mark token function usage as violations when fallbacks are defined.
|
|
546
547
|
|
|
548
|
+
## prefer-primitives
|
|
549
|
+
|
|
550
|
+
Using primitives allows you to delete bespoke component code and replace it with ready made solutions made by the Atlassian Design System Team.
|
|
551
|
+
|
|
552
|
+
<h3>Examples</h3>
|
|
553
|
+
|
|
554
|
+
This rule marks code as violations when it may be able to be replaced with a primitive component.
|
|
555
|
+
|
|
556
|
+
#### Incorrect
|
|
557
|
+
|
|
558
|
+
```js
|
|
559
|
+
<div />
|
|
560
|
+
^^^^^^^
|
|
561
|
+
|
|
562
|
+
<Component>
|
|
563
|
+
<div css={someStyles}></div>
|
|
564
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
565
|
+
</Component>
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
#### Correct
|
|
569
|
+
|
|
570
|
+
```js
|
|
571
|
+
<Box />
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
```js
|
|
575
|
+
<Component>
|
|
576
|
+
<Box xcss={someStyles}></Box>
|
|
577
|
+
</Component>
|
|
578
|
+
```
|
|
579
|
+
|
|
547
580
|
## use-primitives
|
|
548
581
|
|
|
549
582
|
Using primitives allows you to delete bespoke component code and replace it with ready made solutions made by the Atlassian Design System Team.
|
|
@@ -572,7 +605,7 @@ This rule marks code as violations when it can be replaced 1:1 with a primitive
|
|
|
572
605
|
|
|
573
606
|
```js
|
|
574
607
|
<Component>
|
|
575
|
-
<Box
|
|
608
|
+
<Box xcss={someStyles}></Box>
|
|
576
609
|
</Component>
|
|
577
610
|
```
|
|
578
611
|
|
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
/**
|
|
8
8
|
* THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
|
|
9
|
-
* @codegen <<SignedSource::
|
|
9
|
+
* @codegen <<SignedSource::e58419a8541918577b92cf04e5172973>>
|
|
10
10
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
11
11
|
*/
|
|
12
12
|
var _default = {
|
|
@@ -23,6 +23,7 @@ var _default = {
|
|
|
23
23
|
'@atlaskit/design-system/no-margin': 'warn',
|
|
24
24
|
'@atlaskit/design-system/no-nested-styles': 'error',
|
|
25
25
|
'@atlaskit/design-system/no-unsafe-design-token-usage': 'error',
|
|
26
|
+
'@atlaskit/design-system/prefer-primitives': 'warn',
|
|
26
27
|
'@atlaskit/design-system/use-primitives': 'warn',
|
|
27
28
|
'@atlaskit/design-system/use-visually-hidden': 'error'
|
|
28
29
|
}
|
|
@@ -16,11 +16,12 @@ var _noDeprecatedImports = _interopRequireDefault(require("./no-deprecated-impor
|
|
|
16
16
|
var _noMargin = _interopRequireDefault(require("./no-margin"));
|
|
17
17
|
var _noNestedStyles = _interopRequireDefault(require("./no-nested-styles"));
|
|
18
18
|
var _noUnsafeDesignTokenUsage = _interopRequireDefault(require("./no-unsafe-design-token-usage"));
|
|
19
|
+
var _preferPrimitives = _interopRequireDefault(require("./prefer-primitives"));
|
|
19
20
|
var _usePrimitives = _interopRequireDefault(require("./use-primitives"));
|
|
20
21
|
var _useVisuallyHidden = _interopRequireDefault(require("./use-visually-hidden"));
|
|
21
22
|
/**
|
|
22
23
|
* THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
|
|
23
|
-
* @codegen <<SignedSource::
|
|
24
|
+
* @codegen <<SignedSource::4d3e671ea25ef8fe248882948fda472c>>
|
|
24
25
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
25
26
|
*/
|
|
26
27
|
var _default = {
|
|
@@ -35,6 +36,7 @@ var _default = {
|
|
|
35
36
|
'no-margin': _noMargin.default,
|
|
36
37
|
'no-nested-styles': _noNestedStyles.default,
|
|
37
38
|
'no-unsafe-design-token-usage': _noUnsafeDesignTokenUsage.default,
|
|
39
|
+
'prefer-primitives': _preferPrimitives.default,
|
|
38
40
|
'use-primitives': _usePrimitives.default,
|
|
39
41
|
'use-visually-hidden': _useVisuallyHidden.default
|
|
40
42
|
};
|
|
@@ -10,5 +10,8 @@ var restrictedPaths = [{
|
|
|
10
10
|
}, {
|
|
11
11
|
path: '@atlaskit/ds-explorations',
|
|
12
12
|
message: "The @atlaskit/ds-explorations package is used for experiments and should not be consumed directly."
|
|
13
|
+
}, {
|
|
14
|
+
path: '@atlaskit/primitives/pressable',
|
|
15
|
+
message: "The @atlaskit/primitives/pressable export is currently under development and should not be consumed directly."
|
|
13
16
|
}];
|
|
14
17
|
exports.restrictedPaths = restrictedPaths;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _eslintCodemodUtils = require("eslint-codemod-utils");
|
|
8
|
+
var _utils = require("../use-primitives/utils");
|
|
9
|
+
var _createRule = require("../utils/create-rule");
|
|
10
|
+
var _utils2 = require("./utils");
|
|
11
|
+
var primitiveDocsUrl = 'https://go.atlassian.com/dst-prefer-primitives';
|
|
12
|
+
var rule = (0, _createRule.createLintRule)({
|
|
13
|
+
meta: {
|
|
14
|
+
name: 'prefer-primitives',
|
|
15
|
+
type: 'suggestion',
|
|
16
|
+
hasSuggestions: false,
|
|
17
|
+
docs: {
|
|
18
|
+
description: 'Increase awareness of primitive components via code hints. Strictly used for education purposes and discoverability. To enforce usage please refer to the `use-primitives` rule.',
|
|
19
|
+
recommended: false,
|
|
20
|
+
severity: 'warn'
|
|
21
|
+
},
|
|
22
|
+
messages: {
|
|
23
|
+
preferPrimitives: "This \"{{element}}\" may be able to be replaced with a primitive component. See ".concat(primitiveDocsUrl, " for guidance.")
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
create: function create(context) {
|
|
27
|
+
return {
|
|
28
|
+
// Look for HTML elements - <div>, <span>
|
|
29
|
+
// Look for styled calls/templates - styled.div(...), styled.span`...`
|
|
30
|
+
JSXOpeningElement: function JSXOpeningElement(node) {
|
|
31
|
+
if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXOpeningElement')) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (!(0, _eslintCodemodUtils.isNodeOfType)(node.name, 'JSXIdentifier')) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
var suggest = (0, _utils2.shouldSuggest)(node === null || node === void 0 ? void 0 : node.parent);
|
|
38
|
+
if (suggest) {
|
|
39
|
+
context.report({
|
|
40
|
+
node: node,
|
|
41
|
+
messageId: 'preferPrimitives',
|
|
42
|
+
data: {
|
|
43
|
+
element: node.name.name
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
// styled.x`` | styled2.x`` | styled.div()
|
|
49
|
+
'MemberExpression[object.name="styled"],MemberExpression[object.name="styled2"]': function MemberExpressionObjectNameStyledMemberExpressionObjectNameStyled2(node) {
|
|
50
|
+
if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'MemberExpression')) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// styled.div``
|
|
55
|
+
if ((0, _eslintCodemodUtils.isNodeOfType)(node.property, 'Identifier')) {
|
|
56
|
+
if (_utils.validPrimitiveElements.test(node.property.name)) {
|
|
57
|
+
var styledIdentifier = node.object.name;
|
|
58
|
+
var elementName = node.property.name;
|
|
59
|
+
|
|
60
|
+
// Including the `styled.` portion in the message to help makers understand it's not just the `div` element that should be replaced
|
|
61
|
+
var reportName = "".concat(styledIdentifier, ".").concat(elementName); // styled.div
|
|
62
|
+
|
|
63
|
+
context.report({
|
|
64
|
+
node: node,
|
|
65
|
+
messageId: 'preferPrimitives',
|
|
66
|
+
data: {
|
|
67
|
+
element: reportName
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
// styled(X)``
|
|
74
|
+
'CallExpression[callee.name="styled"]': function CallExpressionCalleeNameStyled(node) {
|
|
75
|
+
if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'CallExpression')) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// styled('div')`` - We only care about 'div'/'span', ignore extending other components
|
|
80
|
+
if ((0, _eslintCodemodUtils.isNodeOfType)(node.arguments[0], 'Literal')) {
|
|
81
|
+
var argValue = node.arguments[0].raw;
|
|
82
|
+
if (typeof argValue === 'string') {
|
|
83
|
+
var suggest = _utils.validPrimitiveElements.test(argValue.replaceAll("'", '') // argValue will have '' around the element name, strip it out for this test
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
if (suggest) {
|
|
87
|
+
var styledIdentifier = node.callee.name;
|
|
88
|
+
var elementName = argValue;
|
|
89
|
+
|
|
90
|
+
// Including the `styled()` portion in the message to help makers understand it's not just the `div` element that should be replaced
|
|
91
|
+
var reportName = "".concat(styledIdentifier, "(").concat(elementName, ")"); // styled('div')
|
|
92
|
+
|
|
93
|
+
context.report({
|
|
94
|
+
node: node,
|
|
95
|
+
messageId: 'preferPrimitives',
|
|
96
|
+
data: {
|
|
97
|
+
element: reportName
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
var _default = rule;
|
|
108
|
+
exports.default = _default;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.shouldSuggest = void 0;
|
|
7
|
+
var _utils = require("../use-primitives/utils");
|
|
8
|
+
var shouldSuggest = function shouldSuggest(node) {
|
|
9
|
+
if (!node) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
if (!(0, _utils.isValidPrimitiveElement)(node)) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Ignore text, check for things like:
|
|
18
|
+
* ```
|
|
19
|
+
* <div>
|
|
20
|
+
* <h2>heading</h2>
|
|
21
|
+
* subheading <= rejected because of standalone piece of text
|
|
22
|
+
* </div>
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
var nonWhiteSpaceTextChildren = (0, _utils.getChildrenByType)(node, ['JSXText']).filter(function (child) {
|
|
26
|
+
return !(0, _utils.isWhiteSpace)(child.value);
|
|
27
|
+
});
|
|
28
|
+
if (nonWhiteSpaceTextChildren.length > 0) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
};
|
|
33
|
+
exports.shouldSuggest = shouldSuggest;
|
|
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.shouldSuggestText = exports.shouldSuggestStack = exports.shouldSuggestInline = exports.shouldSuggestBox = exports.primitiveFixer = void 0;
|
|
7
|
+
exports.validPrimitiveElements = exports.shouldSuggestText = exports.shouldSuggestStack = exports.shouldSuggestInline = exports.shouldSuggestBox = exports.primitiveFixer = exports.isWhiteSpace = exports.isValidPrimitiveElement = exports.getChildrenByType = void 0;
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
9
|
var _eslintCodemodUtils = require("eslint-codemod-utils");
|
|
10
10
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
@@ -255,6 +255,7 @@ var getJSXAttributeByName = function getJSXAttributeByName(node, attrName) {
|
|
|
255
255
|
var isWhiteSpace = function isWhiteSpace(value) {
|
|
256
256
|
return value.trim() === '';
|
|
257
257
|
};
|
|
258
|
+
exports.isWhiteSpace = isWhiteSpace;
|
|
258
259
|
function containsOnlyWhitespace(node) {
|
|
259
260
|
return node.children.every(function (child) {
|
|
260
261
|
if (!(0, _eslintCodemodUtils.isNodeOfType)(child, 'JSXText')) {
|
|
@@ -272,7 +273,7 @@ var getChildrenByType = function getChildrenByType(node, types) {
|
|
|
272
273
|
};
|
|
273
274
|
|
|
274
275
|
// FIXME: This not correctly typed
|
|
275
|
-
|
|
276
|
+
exports.getChildrenByType = getChildrenByType;
|
|
276
277
|
var getCSSPropStyleObject = function getCSSPropStyleObject(node, context) {
|
|
277
278
|
var cssAttr = getJSXAttributeByName(node.openingElement, 'css');
|
|
278
279
|
var styleObj = {};
|
|
@@ -321,10 +322,13 @@ var getCSSPropStyleObject = function getCSSPropStyleObject(node, context) {
|
|
|
321
322
|
}
|
|
322
323
|
return styleObj;
|
|
323
324
|
};
|
|
325
|
+
var validPrimitiveElements = /^div|span|article|aside|dialog|footer|header|li|main|nav|ol|section|ul$/;
|
|
326
|
+
exports.validPrimitiveElements = validPrimitiveElements;
|
|
324
327
|
var isValidPrimitiveElement = function isValidPrimitiveElement(node) {
|
|
325
328
|
// For now we are only targeting div and span elements
|
|
326
|
-
return
|
|
329
|
+
return validPrimitiveElements.test(node.openingElement.name.name);
|
|
327
330
|
};
|
|
331
|
+
exports.isValidPrimitiveElement = isValidPrimitiveElement;
|
|
328
332
|
var hasInlineCompatibleStyles = function hasInlineCompatibleStyles(cssStyleObject) {
|
|
329
333
|
if (!['flex', 'inline-flex'].includes(cssStyleObject['display'])) {
|
|
330
334
|
return false;
|
|
@@ -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::e58419a8541918577b92cf04e5172973>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
export default {
|
|
@@ -17,6 +17,7 @@ export default {
|
|
|
17
17
|
'@atlaskit/design-system/no-margin': 'warn',
|
|
18
18
|
'@atlaskit/design-system/no-nested-styles': 'error',
|
|
19
19
|
'@atlaskit/design-system/no-unsafe-design-token-usage': 'error',
|
|
20
|
+
'@atlaskit/design-system/prefer-primitives': 'warn',
|
|
20
21
|
'@atlaskit/design-system/use-primitives': 'warn',
|
|
21
22
|
'@atlaskit/design-system/use-visually-hidden': 'error'
|
|
22
23
|
}
|
|
@@ -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::4d3e671ea25ef8fe248882948fda472c>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
import consistentCssPropUsage from './consistent-css-prop-usage';
|
|
@@ -14,6 +14,7 @@ import noDeprecatedImports from './no-deprecated-imports';
|
|
|
14
14
|
import noMargin from './no-margin';
|
|
15
15
|
import noNestedStyles from './no-nested-styles';
|
|
16
16
|
import noUnsafeDesignTokenUsage from './no-unsafe-design-token-usage';
|
|
17
|
+
import preferPrimitives from './prefer-primitives';
|
|
17
18
|
import usePrimitives from './use-primitives';
|
|
18
19
|
import useVisuallyHidden from './use-visually-hidden';
|
|
19
20
|
export default {
|
|
@@ -28,6 +29,7 @@ export default {
|
|
|
28
29
|
'no-margin': noMargin,
|
|
29
30
|
'no-nested-styles': noNestedStyles,
|
|
30
31
|
'no-unsafe-design-token-usage': noUnsafeDesignTokenUsage,
|
|
32
|
+
'prefer-primitives': preferPrimitives,
|
|
31
33
|
'use-primitives': usePrimitives,
|
|
32
34
|
'use-visually-hidden': useVisuallyHidden
|
|
33
35
|
};
|
|
@@ -4,4 +4,7 @@ export const restrictedPaths = [{
|
|
|
4
4
|
}, {
|
|
5
5
|
path: '@atlaskit/ds-explorations',
|
|
6
6
|
message: `The @atlaskit/ds-explorations package is used for experiments and should not be consumed directly.`
|
|
7
|
+
}, {
|
|
8
|
+
path: '@atlaskit/primitives/pressable',
|
|
9
|
+
message: `The @atlaskit/primitives/pressable export is currently under development and should not be consumed directly.`
|
|
7
10
|
}];
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
|
+
import { validPrimitiveElements } from '../use-primitives/utils';
|
|
3
|
+
import { createLintRule } from '../utils/create-rule';
|
|
4
|
+
import { shouldSuggest } from './utils';
|
|
5
|
+
const primitiveDocsUrl = 'https://go.atlassian.com/dst-prefer-primitives';
|
|
6
|
+
const rule = createLintRule({
|
|
7
|
+
meta: {
|
|
8
|
+
name: 'prefer-primitives',
|
|
9
|
+
type: 'suggestion',
|
|
10
|
+
hasSuggestions: false,
|
|
11
|
+
docs: {
|
|
12
|
+
description: 'Increase awareness of primitive components via code hints. Strictly used for education purposes and discoverability. To enforce usage please refer to the `use-primitives` rule.',
|
|
13
|
+
recommended: false,
|
|
14
|
+
severity: 'warn'
|
|
15
|
+
},
|
|
16
|
+
messages: {
|
|
17
|
+
preferPrimitives: `This "{{element}}" may be able to be replaced with a primitive component. See ${primitiveDocsUrl} for guidance.`
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
create(context) {
|
|
21
|
+
return {
|
|
22
|
+
// Look for HTML elements - <div>, <span>
|
|
23
|
+
// Look for styled calls/templates - styled.div(...), styled.span`...`
|
|
24
|
+
|
|
25
|
+
JSXOpeningElement(node) {
|
|
26
|
+
if (!isNodeOfType(node, 'JSXOpeningElement')) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (!isNodeOfType(node.name, 'JSXIdentifier')) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const suggest = shouldSuggest(node === null || node === void 0 ? void 0 : node.parent);
|
|
33
|
+
if (suggest) {
|
|
34
|
+
context.report({
|
|
35
|
+
node: node,
|
|
36
|
+
messageId: 'preferPrimitives',
|
|
37
|
+
data: {
|
|
38
|
+
element: node.name.name
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
// styled.x`` | styled2.x`` | styled.div()
|
|
44
|
+
'MemberExpression[object.name="styled"],MemberExpression[object.name="styled2"]': node => {
|
|
45
|
+
if (!isNodeOfType(node, 'MemberExpression')) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// styled.div``
|
|
50
|
+
if (isNodeOfType(node.property, 'Identifier')) {
|
|
51
|
+
if (validPrimitiveElements.test(node.property.name)) {
|
|
52
|
+
const styledIdentifier = node.object.name;
|
|
53
|
+
const elementName = node.property.name;
|
|
54
|
+
|
|
55
|
+
// Including the `styled.` portion in the message to help makers understand it's not just the `div` element that should be replaced
|
|
56
|
+
const reportName = `${styledIdentifier}.${elementName}`; // styled.div
|
|
57
|
+
|
|
58
|
+
context.report({
|
|
59
|
+
node: node,
|
|
60
|
+
messageId: 'preferPrimitives',
|
|
61
|
+
data: {
|
|
62
|
+
element: reportName
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
// styled(X)``
|
|
69
|
+
'CallExpression[callee.name="styled"]': node => {
|
|
70
|
+
if (!isNodeOfType(node, 'CallExpression')) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// styled('div')`` - We only care about 'div'/'span', ignore extending other components
|
|
75
|
+
if (isNodeOfType(node.arguments[0], 'Literal')) {
|
|
76
|
+
const argValue = node.arguments[0].raw;
|
|
77
|
+
if (typeof argValue === 'string') {
|
|
78
|
+
const suggest = validPrimitiveElements.test(argValue.replaceAll(`'`, '') // argValue will have '' around the element name, strip it out for this test
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
if (suggest) {
|
|
82
|
+
const styledIdentifier = node.callee.name;
|
|
83
|
+
const elementName = argValue;
|
|
84
|
+
|
|
85
|
+
// Including the `styled()` portion in the message to help makers understand it's not just the `div` element that should be replaced
|
|
86
|
+
const reportName = `${styledIdentifier}(${elementName})`; // styled('div')
|
|
87
|
+
|
|
88
|
+
context.report({
|
|
89
|
+
node: node,
|
|
90
|
+
messageId: 'preferPrimitives',
|
|
91
|
+
data: {
|
|
92
|
+
element: reportName
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
export default rule;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { getChildrenByType, isValidPrimitiveElement, isWhiteSpace } from '../use-primitives/utils';
|
|
2
|
+
export const shouldSuggest = node => {
|
|
3
|
+
if (!node) {
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
if (!isValidPrimitiveElement(node)) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Ignore text, check for things like:
|
|
12
|
+
* ```
|
|
13
|
+
* <div>
|
|
14
|
+
* <h2>heading</h2>
|
|
15
|
+
* subheading <= rejected because of standalone piece of text
|
|
16
|
+
* </div>
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
const nonWhiteSpaceTextChildren = getChildrenByType(node, ['JSXText']).filter(child => !isWhiteSpace(child.value));
|
|
20
|
+
if (nonWhiteSpaceTextChildren.length > 0) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
return true;
|
|
24
|
+
};
|
|
@@ -235,7 +235,7 @@ const getJSXAttributeByName = (node, attrName) => {
|
|
|
235
235
|
return attr.name.name === attrName;
|
|
236
236
|
});
|
|
237
237
|
};
|
|
238
|
-
const isWhiteSpace = value => value.trim() === '';
|
|
238
|
+
export const isWhiteSpace = value => value.trim() === '';
|
|
239
239
|
function containsOnlyWhitespace(node) {
|
|
240
240
|
return node.children.every(child => {
|
|
241
241
|
if (!isNodeOfType(child, 'JSXText')) {
|
|
@@ -244,7 +244,7 @@ function containsOnlyWhitespace(node) {
|
|
|
244
244
|
return isWhiteSpace(child.value);
|
|
245
245
|
});
|
|
246
246
|
}
|
|
247
|
-
const getChildrenByType = (node, types) => {
|
|
247
|
+
export const getChildrenByType = (node, types) => {
|
|
248
248
|
return node.children.filter(child => {
|
|
249
249
|
return types.find(type => isNodeOfType(child, type));
|
|
250
250
|
});
|
|
@@ -303,9 +303,10 @@ const getCSSPropStyleObject = (node, context) => {
|
|
|
303
303
|
}
|
|
304
304
|
return styleObj;
|
|
305
305
|
};
|
|
306
|
-
const
|
|
306
|
+
export const validPrimitiveElements = /^div|span|article|aside|dialog|footer|header|li|main|nav|ol|section|ul$/;
|
|
307
|
+
export const isValidPrimitiveElement = node => {
|
|
307
308
|
// For now we are only targeting div and span elements
|
|
308
|
-
return
|
|
309
|
+
return validPrimitiveElements.test(node.openingElement.name.name);
|
|
309
310
|
};
|
|
310
311
|
const hasInlineCompatibleStyles = cssStyleObject => {
|
|
311
312
|
if (!['flex', 'inline-flex'].includes(cssStyleObject['display'])) {
|
|
@@ -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::e58419a8541918577b92cf04e5172973>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
export default {
|
|
@@ -17,6 +17,7 @@ export default {
|
|
|
17
17
|
'@atlaskit/design-system/no-margin': 'warn',
|
|
18
18
|
'@atlaskit/design-system/no-nested-styles': 'error',
|
|
19
19
|
'@atlaskit/design-system/no-unsafe-design-token-usage': 'error',
|
|
20
|
+
'@atlaskit/design-system/prefer-primitives': 'warn',
|
|
20
21
|
'@atlaskit/design-system/use-primitives': 'warn',
|
|
21
22
|
'@atlaskit/design-system/use-visually-hidden': 'error'
|
|
22
23
|
}
|
|
@@ -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::4d3e671ea25ef8fe248882948fda472c>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
import consistentCssPropUsage from './consistent-css-prop-usage';
|
|
@@ -14,6 +14,7 @@ import noDeprecatedImports from './no-deprecated-imports';
|
|
|
14
14
|
import noMargin from './no-margin';
|
|
15
15
|
import noNestedStyles from './no-nested-styles';
|
|
16
16
|
import noUnsafeDesignTokenUsage from './no-unsafe-design-token-usage';
|
|
17
|
+
import preferPrimitives from './prefer-primitives';
|
|
17
18
|
import usePrimitives from './use-primitives';
|
|
18
19
|
import useVisuallyHidden from './use-visually-hidden';
|
|
19
20
|
export default {
|
|
@@ -28,6 +29,7 @@ export default {
|
|
|
28
29
|
'no-margin': noMargin,
|
|
29
30
|
'no-nested-styles': noNestedStyles,
|
|
30
31
|
'no-unsafe-design-token-usage': noUnsafeDesignTokenUsage,
|
|
32
|
+
'prefer-primitives': preferPrimitives,
|
|
31
33
|
'use-primitives': usePrimitives,
|
|
32
34
|
'use-visually-hidden': useVisuallyHidden
|
|
33
35
|
};
|
|
@@ -4,4 +4,7 @@ export var restrictedPaths = [{
|
|
|
4
4
|
}, {
|
|
5
5
|
path: '@atlaskit/ds-explorations',
|
|
6
6
|
message: "The @atlaskit/ds-explorations package is used for experiments and should not be consumed directly."
|
|
7
|
+
}, {
|
|
8
|
+
path: '@atlaskit/primitives/pressable',
|
|
9
|
+
message: "The @atlaskit/primitives/pressable export is currently under development and should not be consumed directly."
|
|
7
10
|
}];
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
|
+
import { validPrimitiveElements } from '../use-primitives/utils';
|
|
3
|
+
import { createLintRule } from '../utils/create-rule';
|
|
4
|
+
import { shouldSuggest } from './utils';
|
|
5
|
+
var primitiveDocsUrl = 'https://go.atlassian.com/dst-prefer-primitives';
|
|
6
|
+
var rule = createLintRule({
|
|
7
|
+
meta: {
|
|
8
|
+
name: 'prefer-primitives',
|
|
9
|
+
type: 'suggestion',
|
|
10
|
+
hasSuggestions: false,
|
|
11
|
+
docs: {
|
|
12
|
+
description: 'Increase awareness of primitive components via code hints. Strictly used for education purposes and discoverability. To enforce usage please refer to the `use-primitives` rule.',
|
|
13
|
+
recommended: false,
|
|
14
|
+
severity: 'warn'
|
|
15
|
+
},
|
|
16
|
+
messages: {
|
|
17
|
+
preferPrimitives: "This \"{{element}}\" may be able to be replaced with a primitive component. See ".concat(primitiveDocsUrl, " for guidance.")
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
create: function create(context) {
|
|
21
|
+
return {
|
|
22
|
+
// Look for HTML elements - <div>, <span>
|
|
23
|
+
// Look for styled calls/templates - styled.div(...), styled.span`...`
|
|
24
|
+
JSXOpeningElement: function JSXOpeningElement(node) {
|
|
25
|
+
if (!isNodeOfType(node, 'JSXOpeningElement')) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (!isNodeOfType(node.name, 'JSXIdentifier')) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
var suggest = shouldSuggest(node === null || node === void 0 ? void 0 : node.parent);
|
|
32
|
+
if (suggest) {
|
|
33
|
+
context.report({
|
|
34
|
+
node: node,
|
|
35
|
+
messageId: 'preferPrimitives',
|
|
36
|
+
data: {
|
|
37
|
+
element: node.name.name
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
// styled.x`` | styled2.x`` | styled.div()
|
|
43
|
+
'MemberExpression[object.name="styled"],MemberExpression[object.name="styled2"]': function MemberExpressionObjectNameStyledMemberExpressionObjectNameStyled2(node) {
|
|
44
|
+
if (!isNodeOfType(node, 'MemberExpression')) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// styled.div``
|
|
49
|
+
if (isNodeOfType(node.property, 'Identifier')) {
|
|
50
|
+
if (validPrimitiveElements.test(node.property.name)) {
|
|
51
|
+
var styledIdentifier = node.object.name;
|
|
52
|
+
var elementName = node.property.name;
|
|
53
|
+
|
|
54
|
+
// Including the `styled.` portion in the message to help makers understand it's not just the `div` element that should be replaced
|
|
55
|
+
var reportName = "".concat(styledIdentifier, ".").concat(elementName); // styled.div
|
|
56
|
+
|
|
57
|
+
context.report({
|
|
58
|
+
node: node,
|
|
59
|
+
messageId: 'preferPrimitives',
|
|
60
|
+
data: {
|
|
61
|
+
element: reportName
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
// styled(X)``
|
|
68
|
+
'CallExpression[callee.name="styled"]': function CallExpressionCalleeNameStyled(node) {
|
|
69
|
+
if (!isNodeOfType(node, 'CallExpression')) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// styled('div')`` - We only care about 'div'/'span', ignore extending other components
|
|
74
|
+
if (isNodeOfType(node.arguments[0], 'Literal')) {
|
|
75
|
+
var argValue = node.arguments[0].raw;
|
|
76
|
+
if (typeof argValue === 'string') {
|
|
77
|
+
var suggest = validPrimitiveElements.test(argValue.replaceAll("'", '') // argValue will have '' around the element name, strip it out for this test
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
if (suggest) {
|
|
81
|
+
var styledIdentifier = node.callee.name;
|
|
82
|
+
var elementName = argValue;
|
|
83
|
+
|
|
84
|
+
// Including the `styled()` portion in the message to help makers understand it's not just the `div` element that should be replaced
|
|
85
|
+
var reportName = "".concat(styledIdentifier, "(").concat(elementName, ")"); // styled('div')
|
|
86
|
+
|
|
87
|
+
context.report({
|
|
88
|
+
node: node,
|
|
89
|
+
messageId: 'preferPrimitives',
|
|
90
|
+
data: {
|
|
91
|
+
element: reportName
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
export default rule;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { getChildrenByType, isValidPrimitiveElement, isWhiteSpace } from '../use-primitives/utils';
|
|
2
|
+
export var shouldSuggest = function shouldSuggest(node) {
|
|
3
|
+
if (!node) {
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
if (!isValidPrimitiveElement(node)) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Ignore text, check for things like:
|
|
12
|
+
* ```
|
|
13
|
+
* <div>
|
|
14
|
+
* <h2>heading</h2>
|
|
15
|
+
* subheading <= rejected because of standalone piece of text
|
|
16
|
+
* </div>
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
var nonWhiteSpaceTextChildren = getChildrenByType(node, ['JSXText']).filter(function (child) {
|
|
20
|
+
return !isWhiteSpace(child.value);
|
|
21
|
+
});
|
|
22
|
+
if (nonWhiteSpaceTextChildren.length > 0) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
};
|
|
@@ -240,7 +240,7 @@ var getJSXAttributeByName = function getJSXAttributeByName(node, attrName) {
|
|
|
240
240
|
return attr.name.name === attrName;
|
|
241
241
|
});
|
|
242
242
|
};
|
|
243
|
-
var isWhiteSpace = function isWhiteSpace(value) {
|
|
243
|
+
export var isWhiteSpace = function isWhiteSpace(value) {
|
|
244
244
|
return value.trim() === '';
|
|
245
245
|
};
|
|
246
246
|
function containsOnlyWhitespace(node) {
|
|
@@ -251,7 +251,7 @@ function containsOnlyWhitespace(node) {
|
|
|
251
251
|
return isWhiteSpace(child.value);
|
|
252
252
|
});
|
|
253
253
|
}
|
|
254
|
-
var getChildrenByType = function getChildrenByType(node, types) {
|
|
254
|
+
export var getChildrenByType = function getChildrenByType(node, types) {
|
|
255
255
|
return node.children.filter(function (child) {
|
|
256
256
|
return types.find(function (type) {
|
|
257
257
|
return isNodeOfType(child, type);
|
|
@@ -309,9 +309,10 @@ var getCSSPropStyleObject = function getCSSPropStyleObject(node, context) {
|
|
|
309
309
|
}
|
|
310
310
|
return styleObj;
|
|
311
311
|
};
|
|
312
|
-
var
|
|
312
|
+
export var validPrimitiveElements = /^div|span|article|aside|dialog|footer|header|li|main|nav|ol|section|ul$/;
|
|
313
|
+
export var isValidPrimitiveElement = function isValidPrimitiveElement(node) {
|
|
313
314
|
// For now we are only targeting div and span elements
|
|
314
|
-
return
|
|
315
|
+
return validPrimitiveElements.test(node.openingElement.name.name);
|
|
315
316
|
};
|
|
316
317
|
var hasInlineCompatibleStyles = function hasInlineCompatibleStyles(cssStyleObject) {
|
|
317
318
|
if (!['flex', 'inline-flex'].includes(cssStyleObject['display'])) {
|
|
@@ -14,6 +14,7 @@ export declare const configs: {
|
|
|
14
14
|
'@atlaskit/design-system/no-margin': string;
|
|
15
15
|
'@atlaskit/design-system/no-nested-styles': string;
|
|
16
16
|
'@atlaskit/design-system/no-unsafe-design-token-usage': string;
|
|
17
|
+
'@atlaskit/design-system/prefer-primitives': string;
|
|
17
18
|
'@atlaskit/design-system/use-primitives': string;
|
|
18
19
|
'@atlaskit/design-system/use-visually-hidden': string;
|
|
19
20
|
};
|
|
@@ -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::e58419a8541918577b92cf04e5172973>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
declare const _default: {
|
|
@@ -17,6 +17,7 @@ declare const _default: {
|
|
|
17
17
|
'@atlaskit/design-system/no-margin': string;
|
|
18
18
|
'@atlaskit/design-system/no-nested-styles': string;
|
|
19
19
|
'@atlaskit/design-system/no-unsafe-design-token-usage': string;
|
|
20
|
+
'@atlaskit/design-system/prefer-primitives': string;
|
|
20
21
|
'@atlaskit/design-system/use-primitives': string;
|
|
21
22
|
'@atlaskit/design-system/use-visually-hidden': string;
|
|
22
23
|
};
|
|
@@ -14,6 +14,7 @@ declare const _default: {
|
|
|
14
14
|
'no-margin': import("eslint").Rule.RuleModule;
|
|
15
15
|
'no-nested-styles': import("eslint").Rule.RuleModule;
|
|
16
16
|
'no-unsafe-design-token-usage': import("eslint").Rule.RuleModule;
|
|
17
|
+
'prefer-primitives': import("eslint").Rule.RuleModule;
|
|
17
18
|
'use-primitives': import("eslint").Rule.RuleModule;
|
|
18
19
|
'use-visually-hidden': import("eslint").Rule.RuleModule;
|
|
19
20
|
};
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { Rule, Scope } from 'eslint';
|
|
2
|
-
import { EslintNode, JSXElement } from 'eslint-codemod-utils';
|
|
2
|
+
import { EslintNode, JSXElement, JSXExpressionContainer, JSXText } from 'eslint-codemod-utils';
|
|
3
3
|
export declare const shouldSuggestBox: (node: JSXElement) => boolean;
|
|
4
4
|
export declare const shouldSuggestInline: (node: JSXElement, context: Rule.RuleContext) => boolean;
|
|
5
5
|
export declare const shouldSuggestStack: (node: JSXElement, context: Rule.RuleContext) => boolean;
|
|
6
6
|
export declare const shouldSuggestText: (node: JSXElement | undefined, scope: Scope.Scope) => boolean;
|
|
7
7
|
export declare const primitiveFixer: (node: EslintNode, nodeName: string, context: Rule.RuleContext) => (fixer: Rule.RuleFixer) => Rule.Fix[];
|
|
8
|
+
export declare const isWhiteSpace: (value: string) => boolean;
|
|
9
|
+
type JSXChild = 'JSXElement' | 'JSXExpressionContainer' | 'JSXFragment' | 'JSXText' | 'JSXSpreadChild'[];
|
|
10
|
+
export declare const getChildrenByType: (node: JSXElement, types: JSXChild[]) => (JSXElement | JSXExpressionContainer | import("estree-jsx").JSXFragment | JSXText | import("estree-jsx").JSXSpreadChild)[];
|
|
11
|
+
export declare const validPrimitiveElements: RegExp;
|
|
12
|
+
export declare const isValidPrimitiveElement: (node: JSXElement) => boolean;
|
|
13
|
+
export {};
|
|
@@ -14,6 +14,7 @@ export declare const configs: {
|
|
|
14
14
|
'@atlaskit/design-system/no-margin': string;
|
|
15
15
|
'@atlaskit/design-system/no-nested-styles': string;
|
|
16
16
|
'@atlaskit/design-system/no-unsafe-design-token-usage': string;
|
|
17
|
+
'@atlaskit/design-system/prefer-primitives': string;
|
|
17
18
|
'@atlaskit/design-system/use-primitives': string;
|
|
18
19
|
'@atlaskit/design-system/use-visually-hidden': string;
|
|
19
20
|
};
|
|
@@ -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::e58419a8541918577b92cf04e5172973>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
declare const _default: {
|
|
@@ -17,6 +17,7 @@ declare const _default: {
|
|
|
17
17
|
'@atlaskit/design-system/no-margin': string;
|
|
18
18
|
'@atlaskit/design-system/no-nested-styles': string;
|
|
19
19
|
'@atlaskit/design-system/no-unsafe-design-token-usage': string;
|
|
20
|
+
'@atlaskit/design-system/prefer-primitives': string;
|
|
20
21
|
'@atlaskit/design-system/use-primitives': string;
|
|
21
22
|
'@atlaskit/design-system/use-visually-hidden': string;
|
|
22
23
|
};
|
|
@@ -18,6 +18,7 @@ declare const _default: {
|
|
|
18
18
|
'no-margin': import("eslint").Rule.RuleModule;
|
|
19
19
|
'no-nested-styles': import("eslint").Rule.RuleModule;
|
|
20
20
|
'no-unsafe-design-token-usage': import("eslint").Rule.RuleModule;
|
|
21
|
+
'prefer-primitives': import("eslint").Rule.RuleModule;
|
|
21
22
|
'use-primitives': import("eslint").Rule.RuleModule;
|
|
22
23
|
'use-visually-hidden': import("eslint").Rule.RuleModule;
|
|
23
24
|
};
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { Rule, Scope } from 'eslint';
|
|
2
|
-
import { EslintNode, JSXElement } from 'eslint-codemod-utils';
|
|
2
|
+
import { EslintNode, JSXElement, JSXExpressionContainer, JSXText } from 'eslint-codemod-utils';
|
|
3
3
|
export declare const shouldSuggestBox: (node: JSXElement) => boolean;
|
|
4
4
|
export declare const shouldSuggestInline: (node: JSXElement, context: Rule.RuleContext) => boolean;
|
|
5
5
|
export declare const shouldSuggestStack: (node: JSXElement, context: Rule.RuleContext) => boolean;
|
|
6
6
|
export declare const shouldSuggestText: (node: JSXElement | undefined, scope: Scope.Scope) => boolean;
|
|
7
7
|
export declare const primitiveFixer: (node: EslintNode, nodeName: string, context: Rule.RuleContext) => (fixer: Rule.RuleFixer) => Rule.Fix[];
|
|
8
|
+
export declare const isWhiteSpace: (value: string) => boolean;
|
|
9
|
+
type JSXChild = 'JSXElement' | 'JSXExpressionContainer' | 'JSXFragment' | 'JSXText' | 'JSXSpreadChild'[];
|
|
10
|
+
export declare const getChildrenByType: (node: JSXElement, types: JSXChild[]) => (JSXElement | JSXExpressionContainer | import("estree-jsx").JSXFragment | JSXText | import("estree-jsx").JSXSpreadChild)[];
|
|
11
|
+
export declare const validPrimitiveElements: RegExp;
|
|
12
|
+
export declare const isValidPrimitiveElement: (node: JSXElement) => boolean;
|
|
13
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/eslint-plugin-design-system",
|
|
3
3
|
"description": "The essential plugin for use with the Atlassian Design System.",
|
|
4
|
-
"version": "8.
|
|
4
|
+
"version": "8.4.0",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
".": "./src/index.tsx"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@atlaskit/tokens": "^1.
|
|
36
|
+
"@atlaskit/tokens": "^1.14.0",
|
|
37
37
|
"@babel/runtime": "^7.0.0",
|
|
38
38
|
"@typescript-eslint/utils": "^5.48.1",
|
|
39
39
|
"ajv": "^6.12.6",
|
package/report.api.md
CHANGED
|
@@ -35,6 +35,7 @@ export const configs: {
|
|
|
35
35
|
'@atlaskit/design-system/no-margin': string;
|
|
36
36
|
'@atlaskit/design-system/no-nested-styles': string;
|
|
37
37
|
'@atlaskit/design-system/no-unsafe-design-token-usage': string;
|
|
38
|
+
'@atlaskit/design-system/prefer-primitives': string;
|
|
38
39
|
'@atlaskit/design-system/use-primitives': string;
|
|
39
40
|
'@atlaskit/design-system/use-visually-hidden': string;
|
|
40
41
|
};
|
|
@@ -120,6 +121,7 @@ export const rules: {
|
|
|
120
121
|
'no-margin': Rule.RuleModule;
|
|
121
122
|
'no-nested-styles': Rule.RuleModule;
|
|
122
123
|
'no-unsafe-design-token-usage': Rule.RuleModule;
|
|
124
|
+
'prefer-primitives': Rule.RuleModule;
|
|
123
125
|
'use-primitives': Rule.RuleModule;
|
|
124
126
|
'use-visually-hidden': Rule.RuleModule;
|
|
125
127
|
};
|
package/tmp/api-report-tmp.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export const configs: {
|
|
|
24
24
|
'@atlaskit/design-system/no-margin': string;
|
|
25
25
|
'@atlaskit/design-system/no-nested-styles': string;
|
|
26
26
|
'@atlaskit/design-system/no-unsafe-design-token-usage': string;
|
|
27
|
+
'@atlaskit/design-system/prefer-primitives': string;
|
|
27
28
|
'@atlaskit/design-system/use-primitives': string;
|
|
28
29
|
'@atlaskit/design-system/use-visually-hidden': string;
|
|
29
30
|
};
|
|
@@ -94,6 +95,7 @@ export const rules: {
|
|
|
94
95
|
'no-margin': Rule.RuleModule;
|
|
95
96
|
'no-nested-styles': Rule.RuleModule;
|
|
96
97
|
'no-unsafe-design-token-usage': Rule.RuleModule;
|
|
98
|
+
'prefer-primitives': Rule.RuleModule;
|
|
97
99
|
'use-primitives': Rule.RuleModule;
|
|
98
100
|
'use-visually-hidden': Rule.RuleModule;
|
|
99
101
|
};
|
package/dist/cjs/version.json
DELETED
package/dist/es2019/version.json
DELETED