Skip to content

Commit 1e0167b

Browse files
committed
Add lint rule for deprecated Flash usage
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 70736adb-aaef-4999-bbdd-c76914f5f8aa
1 parent f2cfbc2 commit 1e0167b

6 files changed

Lines changed: 146 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ ESLint rules for Primer React
4343
- [enforce-css-module-default-import](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/enforce-css-module-default-import.md)
4444
- [enforce-css-module-identifier-casing](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/enforce-css-module-identifier-casing.md)
4545
- [new-color-css-vars](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/new-color-css-vars.md)
46+
- [no-deprecated-components](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-deprecated-components.md)
4647
- [no-deprecated-entrypoints](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-deprecated-entrypoints.md)
4748
- [no-deprecated-experimental-components](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-deprecated-experimental-components.md)
4849
- [no-deprecated-props](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-deprecated-props.md)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# No deprecated components
2+
3+
## Rule details
4+
5+
This rule discourages imports of deprecated Primer React components from
6+
`@primer/react` and `@primer/react/deprecated`.
7+
8+
👎 Example of **incorrect** code for this rule:
9+
10+
```jsx
11+
import {Flash} from '@primer/react'
12+
```
13+
14+
👍 Example of **correct** code for this rule:
15+
16+
```jsx
17+
import {Banner} from '@primer/react'
18+
```
19+
20+
Follow the
21+
[Flash migration guide](https://primer.style/product/getting-started/react/migration-guides/primer-flash)
22+
when replacing `Flash` with `Banner`.

src/configs/recommended.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module.exports = {
1111
rules: {
1212
'primer-react/direct-slot-children': 'error',
1313

14+
'primer-react/no-deprecated-components': 'warn',
1415
'primer-react/no-deprecated-experimental-components': 'warn',
1516
'primer-react/a11y-tooltip-interactive-trigger': 'error',
1617
'primer-react/new-color-css-vars': 'error',

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module.exports = {
1212
'enforce-css-module-default-import': require('./rules/enforce-css-module-default-import'),
1313
'enforce-css-module-identifier-casing': require('./rules/enforce-css-module-identifier-casing'),
1414
'new-color-css-vars': require('./rules/new-color-css-vars'),
15+
'no-deprecated-components': require('./rules/no-deprecated-components'),
1516
'no-deprecated-entrypoints': require('./rules/no-deprecated-entrypoints'),
1617
'no-deprecated-experimental-components': require('./rules/no-deprecated-experimental-components'),
1718
'no-deprecated-props': require('./rules/no-deprecated-props'),
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
'use strict'
2+
3+
const {RuleTester} = require('eslint')
4+
const rule = require('../no-deprecated-components')
5+
6+
const ruleTester = new RuleTester({
7+
languageOptions: {
8+
ecmaVersion: 'latest',
9+
sourceType: 'module',
10+
},
11+
})
12+
13+
const error = {
14+
messageId: 'deprecatedComponent',
15+
data: {
16+
component: 'Flash',
17+
replacement: 'Banner',
18+
migrationGuide: 'https://primer.style/product/getting-started/react/migration-guides/primer-flash',
19+
},
20+
}
21+
22+
ruleTester.run('no-deprecated-components', rule, {
23+
valid: [
24+
{
25+
code: `import {Banner} from '@primer/react'`,
26+
},
27+
{
28+
code: `import {Flash} from '@example/react'`,
29+
},
30+
{
31+
code: `import PrimerReact from '@primer/react'`,
32+
},
33+
{
34+
code: `import * as PrimerReact from '@primer/react'`,
35+
},
36+
],
37+
invalid: [
38+
{
39+
code: `import {Flash} from '@primer/react'`,
40+
errors: [error],
41+
},
42+
{
43+
code: `import {Flash} from '@primer/react/deprecated'`,
44+
errors: [error],
45+
},
46+
{
47+
code: `import {Flash as LegacyFlash} from '@primer/react'`,
48+
errors: [error],
49+
},
50+
{
51+
code: `import {Button, Flash, Link} from '@primer/react'`,
52+
errors: [error],
53+
},
54+
],
55+
})
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
'use strict'
2+
3+
const url = require('../url')
4+
5+
const migrationGuide = 'https://primer.style/product/getting-started/react/migration-guides/primer-flash'
6+
7+
const deprecatedComponents = new Map([
8+
[
9+
'Flash',
10+
{
11+
replacement: 'Banner',
12+
migrationGuide,
13+
},
14+
],
15+
])
16+
17+
const primerReactEntrypoints = new Set(['@primer/react', '@primer/react/deprecated'])
18+
19+
/**
20+
* @type {import('eslint').Rule.RuleModule}
21+
*/
22+
module.exports = {
23+
meta: {
24+
type: 'problem',
25+
docs: {
26+
description: 'Discourage the use of deprecated Primer React components',
27+
recommended: true,
28+
url: url(module),
29+
},
30+
messages: {
31+
deprecatedComponent:
32+
'`{{component}}` is deprecated. Use `{{replacement}}` from `@primer/react` instead. See the migration guide: {{migrationGuide}}',
33+
},
34+
schema: [],
35+
},
36+
create(context) {
37+
return {
38+
ImportDeclaration(node) {
39+
if (!primerReactEntrypoints.has(node.source.value)) {
40+
return
41+
}
42+
43+
for (const specifier of node.specifiers) {
44+
if (specifier.type !== 'ImportSpecifier') {
45+
continue
46+
}
47+
48+
const component = deprecatedComponents.get(specifier.imported.name)
49+
if (!component) {
50+
continue
51+
}
52+
53+
context.report({
54+
node: specifier,
55+
messageId: 'deprecatedComponent',
56+
data: {
57+
component: specifier.imported.name,
58+
replacement: component.replacement,
59+
migrationGuide: component.migrationGuide,
60+
},
61+
})
62+
}
63+
},
64+
}
65+
},
66+
}

0 commit comments

Comments
 (0)