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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-primer-react",
3
- "version": "5.4.0",
3
+ "version": "5.5.0-rc.40574df",
4
4
  "description": "ESLint rules for Primer React",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
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
+ }