eslint-plugin-primer-react 5.4.0 → 5.5.0-rc.40574df
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 +6 -0
- package/docs/rules/use-deprecated-from-deprecated.md +25 -0
- package/package-lock.json +14216 -0
- package/package.json +1 -1
- package/src/index.js +1 -0
- package/src/rules/__tests__/use-deprecated-from-deprecated.test.js +66 -0
- package/src/rules/use-deprecated-from-deprecated.js +130 -0
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -10,6 +10,7 @@ module.exports = {
|
|
|
10
10
|
'a11y-link-in-text-block': require('./rules/a11y-link-in-text-block'),
|
|
11
11
|
'a11y-remove-disable-tooltip': require('./rules/a11y-remove-disable-tooltip'),
|
|
12
12
|
'a11y-use-next-tooltip': require('./rules/a11y-use-next-tooltip'),
|
|
13
|
+
'use-deprecated-from-deprecated': require('./rules/use-deprecated-from-deprecated'),
|
|
13
14
|
},
|
|
14
15
|
configs: {
|
|
15
16
|
recommended: require('./configs/recommended'),
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {RuleTester} = require('eslint')
|
|
4
|
+
const rule = require('../use-deprecated-from-deprecated')
|
|
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('use-deprecated-from-deprecated', rule, {
|
|
17
|
+
valid: [],
|
|
18
|
+
invalid: [
|
|
19
|
+
// Single deprecated import
|
|
20
|
+
{
|
|
21
|
+
code: `import {Tooltip} from '@primer/react'`,
|
|
22
|
+
output: `import {Tooltip} from '@primer/react/deprecated'`,
|
|
23
|
+
errors: ['Import deprecated components from @primer/react/deprecated'],
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
// Single deprecated import with existing deprecated entrypoint
|
|
27
|
+
{
|
|
28
|
+
code: `import {Tooltip} from '@primer/react'
|
|
29
|
+
import {Dialog} from '@primer/react/deprecated'`,
|
|
30
|
+
output: `\nimport {Dialog, Tooltip} from '@primer/react/deprecated'`,
|
|
31
|
+
errors: ['Import deprecated components from @primer/react/deprecated'],
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
// Multiple deprecated imports
|
|
35
|
+
{
|
|
36
|
+
code: `import {Dialog, Tooltip} from '@primer/react'`,
|
|
37
|
+
output: `import {Dialog, Tooltip} from '@primer/react/deprecated'`,
|
|
38
|
+
errors: ['Import deprecated components from @primer/react/deprecated'],
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
// Mixed deprecated and non-deprecated imports
|
|
42
|
+
{
|
|
43
|
+
code: `import {Button, Tooltip} from '@primer/react'`,
|
|
44
|
+
output: `import {Button, } from '@primer/react'
|
|
45
|
+
import {Tooltip} from '@primer/react/deprecated'`,
|
|
46
|
+
errors: ['Import deprecated components from @primer/react/deprecated'],
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
// Mixed deprecated and non-deprecated imports with existing deprecated
|
|
50
|
+
{
|
|
51
|
+
code: `import {Button, Tooltip} from '@primer/react'
|
|
52
|
+
import {Dialog} from '@primer/react/deprecated'`,
|
|
53
|
+
output: `import {Button, } from '@primer/react'
|
|
54
|
+
import {Dialog, Tooltip} from '@primer/react/deprecated'`,
|
|
55
|
+
errors: ['Import deprecated components from @primer/react/deprecated'],
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
// Multiple mixed deprecated and non-deprecated imports
|
|
59
|
+
{
|
|
60
|
+
code: `import {Button, Dialog, Tooltip} from '@primer/react'`,
|
|
61
|
+
output: `import {Button, } from '@primer/react'
|
|
62
|
+
import {Dialog, Tooltip} from '@primer/react/deprecated'`,
|
|
63
|
+
errors: ['Import deprecated components from @primer/react/deprecated'],
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
})
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const url = require('../url')
|
|
4
|
+
|
|
5
|
+
const components = [
|
|
6
|
+
{
|
|
7
|
+
identifier: 'Dialog',
|
|
8
|
+
entrypoint: '@primer/react',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
identifier: 'Octicon',
|
|
12
|
+
entrypoint: '@primer/react',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
identifier: 'Pagehead',
|
|
16
|
+
entrypoint: '@primer/react',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
identifier: 'TabNav',
|
|
20
|
+
entrypoint: '@primer/react',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
identifier: 'Tooltip',
|
|
24
|
+
entrypoint: '@primer/react',
|
|
25
|
+
},
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
const entrypoints = new Map()
|
|
29
|
+
|
|
30
|
+
for (const component of components) {
|
|
31
|
+
if (!entrypoints.has(component.entrypoint)) {
|
|
32
|
+
entrypoints.set(component.entrypoint, new Set())
|
|
33
|
+
}
|
|
34
|
+
entrypoints.get(component.entrypoint).add(component.identifier)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @type {import('eslint').Rule.RuleModule}
|
|
39
|
+
*/
|
|
40
|
+
module.exports = {
|
|
41
|
+
meta: {
|
|
42
|
+
type: 'problem',
|
|
43
|
+
docs: {
|
|
44
|
+
description: 'Use deprecated components from the `@primer/react/deprecated` entrypoint',
|
|
45
|
+
recommended: true,
|
|
46
|
+
url: url(module),
|
|
47
|
+
},
|
|
48
|
+
fixable: true,
|
|
49
|
+
schema: [],
|
|
50
|
+
},
|
|
51
|
+
create(context) {
|
|
52
|
+
const sourceCode = context.getSourceCode()
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
ImportDeclaration(node) {
|
|
56
|
+
if (!entrypoints.has(node.source.value)) {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const entrypoint = entrypoints.get(node.source.value)
|
|
61
|
+
const deprecated = node.specifiers.filter(specifier => {
|
|
62
|
+
return entrypoint.has(specifier.imported.name)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
if (deprecated.length === 0) {
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const deprecatedEntrypoint = node.parent.body.find(node => {
|
|
70
|
+
if (node.type !== 'ImportDeclaration') {
|
|
71
|
+
return false
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return node.source.value === '@primer/react/deprecated'
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
// All imports are deprecated
|
|
78
|
+
if (deprecated.length === node.specifiers.length) {
|
|
79
|
+
context.report({
|
|
80
|
+
node,
|
|
81
|
+
message: 'Import deprecated components from @primer/react/deprecated',
|
|
82
|
+
*fix(fixer) {
|
|
83
|
+
if (deprecatedEntrypoint) {
|
|
84
|
+
const lastSpecifier = deprecatedEntrypoint.specifiers[deprecatedEntrypoint.specifiers.length - 1]
|
|
85
|
+
|
|
86
|
+
yield fixer.remove(node)
|
|
87
|
+
yield fixer.insertTextAfter(
|
|
88
|
+
lastSpecifier,
|
|
89
|
+
`, ${node.specifiers.map(specifier => specifier.imported.name).join(', ')}`,
|
|
90
|
+
)
|
|
91
|
+
} else {
|
|
92
|
+
yield fixer.replaceText(node.source, `'@primer/react/deprecated'`)
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
})
|
|
96
|
+
} else {
|
|
97
|
+
// There is a mix of deprecated and non-deprecated imports
|
|
98
|
+
context.report({
|
|
99
|
+
node,
|
|
100
|
+
message: 'Import deprecated components from @primer/react/deprecated',
|
|
101
|
+
*fix(fixer) {
|
|
102
|
+
for (const specifier of deprecated) {
|
|
103
|
+
yield fixer.remove(specifier)
|
|
104
|
+
const comma = sourceCode.getTokenAfter(specifier)
|
|
105
|
+
if (comma.value === ',') {
|
|
106
|
+
yield fixer.remove(comma)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (deprecatedEntrypoint) {
|
|
111
|
+
const lastSpecifier = deprecatedEntrypoint.specifiers[deprecatedEntrypoint.specifiers.length - 1]
|
|
112
|
+
yield fixer.insertTextAfter(
|
|
113
|
+
lastSpecifier,
|
|
114
|
+
`, ${deprecated.map(specifier => specifier.imported.name).join(', ')}`,
|
|
115
|
+
)
|
|
116
|
+
} else {
|
|
117
|
+
yield fixer.insertTextAfter(
|
|
118
|
+
node,
|
|
119
|
+
`\nimport {${deprecated
|
|
120
|
+
.map(specifier => specifier.imported.name)
|
|
121
|
+
.join(', ')}} from '@primer/react/deprecated'`,
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
}
|