Skip to content

Commit 5781a76

Browse files
committed
Add new rule no-deprecated-experimental-components
1 parent 7cc4f6b commit 5781a76

File tree

6 files changed

+136
-0
lines changed

6 files changed

+136
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,4 @@ ESLint rules for Primer React
4040
- [a11y-link-in-text-block](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-link-in-text-block.md)
4141
- [a11y-remove-disable-tooltip](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-remove-disable-tooltip.md)
4242
- [a11y-use-accessible-tooltip](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-use-accessible-tooltip.md)
43+
- [no-deprecated-experimental-components](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-deprecated-experimental-components)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# No experimental SelectPanel
2+
3+
## Rule Details
4+
5+
This rule enforces the usage of specific imports from `@primer/react/experimental`.
6+
7+
👎 Examples of **incorrect** code for this rule
8+
9+
```jsx
10+
import {SelectPanel} from '@primer/react/experimental'
11+
12+
function ExampleComponent() {
13+
return <SelectPanel />
14+
}
15+
```
16+
17+
👍 Examples of **correct** code for this rule:
18+
19+
You can satisfy the rule by either converting to the non-experimental version:
20+
21+
```jsx
22+
import {SelectPane} from '@primer/react'
23+
24+
function ExampleComponent() {
25+
return <SelectPanel />
26+
}
27+
```
28+
29+
Or by removing usage of the component.

src/configs/recommended.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module.exports = {
1212
rules: {
1313
'primer-react/direct-slot-children': 'error',
1414
'primer-react/no-system-props': 'warn',
15+
'no-deprecated-experimental-components': 'warn',
1516
'primer-react/a11y-tooltip-interactive-trigger': 'error',
1617
'primer-react/new-color-css-vars': 'error',
1718
'primer-react/a11y-explicit-heading': 'error',

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module.exports = {
33
'direct-slot-children': require('./rules/direct-slot-children'),
44
'no-deprecated-entrypoints': require('./rules/no-deprecated-entrypoints'),
55
'no-system-props': require('./rules/no-system-props'),
6+
'no-deprecated-experimental-components': require('./rules/no-deprecated-experimental-components'),
67
'a11y-tooltip-interactive-trigger': require('./rules/a11y-tooltip-interactive-trigger'),
78
'new-color-css-vars': require('./rules/new-color-css-vars'),
89
'a11y-explicit-heading': require('./rules/a11y-explicit-heading'),
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
'use strict'
2+
3+
const {RuleTester} = require('eslint')
4+
const rule = require('../no-deprecated-experimental-components')
5+
6+
const ruleTester = new RuleTester({
7+
parserOptions: {
8+
ecmaVersion: 'latest',
9+
sourceType: 'module',
10+
ecmaFeatures: {
11+
jsx: true,
12+
},
13+
},
14+
})
15+
16+
ruleTester.run('no-deprecated-experimental-components', rule, {
17+
valid: [
18+
{
19+
code: `import {SelectPanel} from '@primer/react'`,
20+
},
21+
{
22+
code: `import {DataTable} from '@primer/react/experimental'`,
23+
},
24+
{
25+
code: `import {DataTable, ActionBar} from '@primer/react/experimental'`,
26+
},
27+
],
28+
invalid: [
29+
// Single experimental import
30+
{
31+
code: `import {SelectPanel} from '@primer/react/experimental'`,
32+
errors: ['SelectPanelV2 is deprecated. Please import SelectPanelV1 from `@primer/react`'],
33+
},
34+
// Multiple experimental import
35+
{
36+
code: `import {SelectPanel, DataTable, ActionBar} from '@primer/react/experimental'`,
37+
errors: ['SelectPanelV2 is deprecated. Please import SelectPanelV1 from `@primer/react`'],
38+
},
39+
],
40+
})
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
'use strict'
2+
3+
const url = require('../url')
4+
5+
const components = [
6+
{
7+
identifier: 'SelectPanel',
8+
entrypoint: '@primer/react/experimental',
9+
},
10+
]
11+
12+
const entrypoints = new Map()
13+
14+
for (const component of components) {
15+
if (!entrypoints.has(component.entrypoint)) {
16+
entrypoints.set(component.entrypoint, new Set())
17+
}
18+
entrypoints.get(component.entrypoint).add(component.identifier)
19+
}
20+
21+
/**
22+
* @type {import('eslint').Rule.RuleModule}
23+
*/
24+
module.exports = {
25+
meta: {
26+
type: 'problem',
27+
docs: {
28+
description: 'Use deprecated components from the `@primer/react/deprecated` entrypoint',
29+
recommended: true,
30+
url: url(module),
31+
},
32+
fixable: true,
33+
schema: [],
34+
},
35+
create(context) {
36+
const sourceCode = context.getSourceCode()
37+
38+
return {
39+
ImportDeclaration(node) {
40+
if (!entrypoints.has(node.source.value)) {
41+
return
42+
}
43+
44+
const entrypoint = entrypoints.get(node.source.value)
45+
46+
const experimental = node.specifiers.filter(specifier => {
47+
return entrypoint.has(specifier.imported.name)
48+
})
49+
50+
if (experimental.length === 0) {
51+
return
52+
}
53+
54+
// All imports are deprecated
55+
if (experimental.length > 0) {
56+
context.report({
57+
node,
58+
message: 'SelectPanelV2 is deprecated. Please import SelectPanelV1 from `@primer/react`',
59+
})
60+
}
61+
},
62+
}
63+
},
64+
}

0 commit comments

Comments
 (0)