eslint-plugin-primer-react 5.0.0-rc.2db7a42 → 5.0.0-rc.b79eafb
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 +4 -0
- package/README.md +0 -1
- package/package-lock.json +0 -14
- package/package.json +1 -3
- package/src/configs/recommended.js +0 -1
- package/src/index.js +0 -1
- package/docs/rules/no-deprecated-colors.md +0 -91
- package/src/rules/__tests__/no-deprecated-colors.test.js +0 -221
- package/src/rules/no-deprecated-colors.js +0 -193
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
### Major Changes
|
|
6
6
|
|
|
7
|
+
- [#174](https://github.com/primer/eslint-plugin-primer-react/pull/174) [`d9832b8`](https://github.com/primer/eslint-plugin-primer-react/commit/d9832b850cbcf808ddcdfd3efbbab7d2bf913ccd) Thanks [@langermank](https://github.com/langermank)! - - Remove `no-deprecated-colors` plugin
|
|
8
|
+
|
|
9
|
+
- Remove dependency on `primer/primitives`
|
|
10
|
+
|
|
7
11
|
- [#172](https://github.com/primer/eslint-plugin-primer-react/pull/172) [`8e24d66`](https://github.com/primer/eslint-plugin-primer-react/commit/8e24d660065b3c690a14d826580c793d7b305068) Thanks [@langermank](https://github.com/langermank)! - [Breaking] Remove `new-color-css-vars-have-fallback`
|
|
8
12
|
|
|
9
13
|
## 4.2.0
|
package/README.md
CHANGED
|
@@ -32,7 +32,6 @@ ESLint rules for Primer React
|
|
|
32
32
|
## Rules
|
|
33
33
|
|
|
34
34
|
- [direct-slot-children](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/direct-slot-children.md)
|
|
35
|
-
- [no-deprecated-colors](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-deprecated-colors.md)
|
|
36
35
|
- [no-system-props](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-system-props.md)
|
|
37
36
|
- [a11y-tooltip-interactive-trigger](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-tooltip-interactive-trigger.md)
|
|
38
37
|
- [a11y-explicit-heading](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-explicit-heading.md)
|
package/package-lock.json
CHANGED
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
"@changesets/cli": "^2.16.0",
|
|
22
22
|
"@github/markdownlint-github": "^0.6.0",
|
|
23
23
|
"@github/prettier-config": "0.0.6",
|
|
24
|
-
"@primer/primitives": "^7.14.0",
|
|
25
24
|
"eslint": "^8.42.0",
|
|
26
25
|
"eslint-plugin-prettier": "^5.0.1",
|
|
27
26
|
"jest": "^29.7.0",
|
|
@@ -29,7 +28,6 @@
|
|
|
29
28
|
"markdownlint-cli2-formatter-pretty": "^0.0.5"
|
|
30
29
|
},
|
|
31
30
|
"peerDependencies": {
|
|
32
|
-
"@primer/primitives": ">=4.6.2",
|
|
33
31
|
"eslint": "^8.42.0"
|
|
34
32
|
}
|
|
35
33
|
},
|
|
@@ -1897,12 +1895,6 @@
|
|
|
1897
1895
|
"url": "https://opencollective.com/unts"
|
|
1898
1896
|
}
|
|
1899
1897
|
},
|
|
1900
|
-
"node_modules/@primer/primitives": {
|
|
1901
|
-
"version": "7.15.15",
|
|
1902
|
-
"resolved": "https://registry.npmjs.org/@primer/primitives/-/primitives-7.15.15.tgz",
|
|
1903
|
-
"integrity": "sha512-K9fPgKVBtdmBMl+lHKUK4ctsRf+DUUKdJYEHnFhkua71m9FORK16ycJ4gHDpc4g/0xgNvEwQ9/ArsV1i8w3ZmQ==",
|
|
1904
|
-
"dev": true
|
|
1905
|
-
},
|
|
1906
1898
|
"node_modules/@sinclair/typebox": {
|
|
1907
1899
|
"version": "0.27.8",
|
|
1908
1900
|
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
|
|
@@ -9972,12 +9964,6 @@
|
|
|
9972
9964
|
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz",
|
|
9973
9965
|
"integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ=="
|
|
9974
9966
|
},
|
|
9975
|
-
"@primer/primitives": {
|
|
9976
|
-
"version": "7.15.15",
|
|
9977
|
-
"resolved": "https://registry.npmjs.org/@primer/primitives/-/primitives-7.15.15.tgz",
|
|
9978
|
-
"integrity": "sha512-K9fPgKVBtdmBMl+lHKUK4ctsRf+DUUKdJYEHnFhkua71m9FORK16ycJ4gHDpc4g/0xgNvEwQ9/ArsV1i8w3ZmQ==",
|
|
9979
|
-
"dev": true
|
|
9980
|
-
},
|
|
9981
9967
|
"@sinclair/typebox": {
|
|
9982
9968
|
"version": "0.27.8",
|
|
9983
9969
|
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-primer-react",
|
|
3
|
-
"version": "5.0.0-rc.
|
|
3
|
+
"version": "5.0.0-rc.b79eafb",
|
|
4
4
|
"description": "ESLint rules for Primer React",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
},
|
|
26
26
|
"homepage": "https://github.com/primer/eslint-plugin-primer-react#readme",
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"@primer/primitives": ">=4.6.2",
|
|
29
28
|
"eslint": "^8.42.0"
|
|
30
29
|
},
|
|
31
30
|
"dependencies": {
|
|
@@ -41,7 +40,6 @@
|
|
|
41
40
|
"@changesets/cli": "^2.16.0",
|
|
42
41
|
"@github/markdownlint-github": "^0.6.0",
|
|
43
42
|
"@github/prettier-config": "0.0.6",
|
|
44
|
-
"@primer/primitives": "^7.14.0",
|
|
45
43
|
"eslint": "^8.42.0",
|
|
46
44
|
"eslint-plugin-prettier": "^5.0.1",
|
|
47
45
|
"jest": "^29.7.0",
|
|
@@ -11,7 +11,6 @@ module.exports = {
|
|
|
11
11
|
extends: ['plugin:github/react'],
|
|
12
12
|
rules: {
|
|
13
13
|
'primer-react/direct-slot-children': 'error',
|
|
14
|
-
'primer-react/no-deprecated-colors': 'warn',
|
|
15
14
|
'primer-react/no-system-props': 'warn',
|
|
16
15
|
'primer-react/a11y-tooltip-interactive-trigger': 'error',
|
|
17
16
|
'primer-react/new-color-css-vars': 'error',
|
package/src/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
rules: {
|
|
3
3
|
'direct-slot-children': require('./rules/direct-slot-children'),
|
|
4
|
-
'no-deprecated-colors': require('./rules/no-deprecated-colors'),
|
|
5
4
|
'no-deprecated-entrypoints': require('./rules/no-deprecated-entrypoints'),
|
|
6
5
|
'no-system-props': require('./rules/no-system-props'),
|
|
7
6
|
'a11y-tooltip-interactive-trigger': require('./rules/a11y-tooltip-interactive-trigger'),
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# Disallow references to deprecated color variables (no-deprecated-colors)
|
|
2
|
-
|
|
3
|
-
🔧 The `--fix` option on the [ESLint CLI](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can
|
|
4
|
-
automatically fix some of the problems reported by this rule.
|
|
5
|
-
|
|
6
|
-
[Theming](https://primer.style/react/theming) in Primer React is made possible by a theme object that defines your
|
|
7
|
-
application's colors, spacing, fonts, and more. The color variables in Primer React's
|
|
8
|
-
[default theme object](https://primer.style/react/theme-reference) are pulled from
|
|
9
|
-
[Primer Primitives](https://github.com/primer/primitives). When a color variable is deprecated in Primer Primitives,
|
|
10
|
-
it's important to remove references to that color variable in your application before it's removed from the library.
|
|
11
|
-
|
|
12
|
-
## Rule details
|
|
13
|
-
|
|
14
|
-
This rule disallows references to color variables that are deprecated in
|
|
15
|
-
[Primer Primitives](https://github.com/primer/primitives).
|
|
16
|
-
|
|
17
|
-
👎 Examples of **incorrect** code for this rule:
|
|
18
|
-
|
|
19
|
-
```jsx
|
|
20
|
-
/* eslint primer-react/no-deprecated-colors: "error" */
|
|
21
|
-
import {Box, themeGet} from '@primer/react'
|
|
22
|
-
import styled from 'styled-components'
|
|
23
|
-
|
|
24
|
-
const SystemPropExample() = () => <Box color="some.deprecated.color">Incorrect</Box>
|
|
25
|
-
|
|
26
|
-
const SxPropExample() = () => <Box sx={{color: 'some.deprecated.color'}}>Incorrect</Box>
|
|
27
|
-
|
|
28
|
-
const SxPropExample2() = () => <Box sx={{boxShadow: theme => `0 1px 2px ${theme.colors.some.deprecated.color}`}}>Incorrect</Box>
|
|
29
|
-
|
|
30
|
-
const ThemeGetExample = styled.div`
|
|
31
|
-
color: ${themeGet('colors.some.deprecated.color')};
|
|
32
|
-
`
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
👍 Examples of **correct** code for this rule:
|
|
36
|
-
|
|
37
|
-
```jsx
|
|
38
|
-
/* eslint primer-react/no-deprecated-colors: "error" */
|
|
39
|
-
import {Box, themeGet} from '@primer/react'
|
|
40
|
-
import styled from 'styled-components'
|
|
41
|
-
|
|
42
|
-
const SystemPropExample() = () => <Box color="some.color">Correct</Box>
|
|
43
|
-
|
|
44
|
-
const SxPropExample() = () => <Box sx={{color: 'some.color'}}>Correct</Box>
|
|
45
|
-
|
|
46
|
-
const SxPropExample2() = () => <Box sx={{boxShadow: theme => `0 1px 2px ${theme.colors.some.color}`}}>Correct</Box>
|
|
47
|
-
|
|
48
|
-
const ThemeGetExample = styled.div`
|
|
49
|
-
color: ${themeGet('colors.some.color')};
|
|
50
|
-
`
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## Options
|
|
54
|
-
|
|
55
|
-
- `skipImportCheck` (default: `false`)
|
|
56
|
-
|
|
57
|
-
By default, the `no-deprecated-colors` rule will only check for deprecated colors used in functions and components
|
|
58
|
-
that are imported from `@primer/react`. You can disable this behavior by setting `skipImportCheck` to `true`. This is
|
|
59
|
-
useful for linting custom components that pass color-related props down to Primer React components.
|
|
60
|
-
|
|
61
|
-
```js
|
|
62
|
-
/* eslint primer-react/no-deprecated-colors: ["warn", {"skipImportCheck": true}] */
|
|
63
|
-
import {Box} from '@primer/react'
|
|
64
|
-
|
|
65
|
-
function MyBox({color, children}) {
|
|
66
|
-
return <Box color={color}>{children}</Box>
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function App() {
|
|
70
|
-
// Enabling `skipImportCheck` will find deprecated colors used like this:
|
|
71
|
-
return <MyBox color="text.primary">Hello</MyBox>
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
- `checkAllStrings` (default: `false`)
|
|
76
|
-
|
|
77
|
-
If `checkAllStrings` is set to `true`, the `no-deprecated-colors` rule will check for deprecated colors in all
|
|
78
|
-
strings. This is useful for catching uses of deprecated colors outside system props and the `sx` prop.
|
|
79
|
-
|
|
80
|
-
```js
|
|
81
|
-
/* eslint primer-react/no-deprecated-colors: ["warn", {"checkAllStrings": true}] */
|
|
82
|
-
import {Box} from '@primer/react'
|
|
83
|
-
|
|
84
|
-
function ExampleComponent() {
|
|
85
|
-
const styles = {
|
|
86
|
-
// Enabling `checkAllStrings` will find deprecated colors used like this:
|
|
87
|
-
color: 'text.primary',
|
|
88
|
-
}
|
|
89
|
-
return <Box sx={styles}>Hello</Box>
|
|
90
|
-
}
|
|
91
|
-
```
|
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
const rule = require('../no-deprecated-colors')
|
|
2
|
-
const {RuleTester} = require('eslint')
|
|
3
|
-
|
|
4
|
-
const deprecatedVars = {
|
|
5
|
-
'text.primary': 'fg.default',
|
|
6
|
-
'bg.primary': 'canvas.default',
|
|
7
|
-
'auto.green.5': ['success.fg', 'success.emphasis'],
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const removedVars = {
|
|
11
|
-
'fade.fg10': null,
|
|
12
|
-
'autocomplete.shadow': 'shadow.medium',
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
jest.mock('@primer/primitives/dist/deprecated/colors', () => deprecatedVars)
|
|
16
|
-
jest.mock('@primer/primitives/dist/removed/colors', () => removedVars)
|
|
17
|
-
|
|
18
|
-
const ruleTester = new RuleTester({
|
|
19
|
-
parserOptions: {
|
|
20
|
-
ecmaVersion: 'latest',
|
|
21
|
-
sourceType: 'module',
|
|
22
|
-
ecmaFeatures: {
|
|
23
|
-
jsx: true,
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
ruleTester.run('no-deprecated-colors', rule, {
|
|
29
|
-
valid: [
|
|
30
|
-
`import {Box} from '@other/design-system'; <Box color="text.primary">Hello</Box>`,
|
|
31
|
-
`import {Box} from "@primer/react"; <Box color="fg.default">Hello</Box>`,
|
|
32
|
-
`import {hello} from "@primer/react"; hello("colors.text.primary")`,
|
|
33
|
-
`import {themeGet} from "@primer/react"; themeGet("space.text.primary")`,
|
|
34
|
-
`import {themeGet} from "@primer/react"; themeGet(props.backgroundColorThemeValue)`,
|
|
35
|
-
`import {themeGet} from "@primer/react"; themeGet(2)`,
|
|
36
|
-
`import {themeGet} from "@other/design-system"; themeGet("colors.text.primary")`,
|
|
37
|
-
`import {get} from "@other/constants"; get("space.text.primary")`,
|
|
38
|
-
`import {Box} from '@primer/react'; <Box sx={styles}>Hello</Box>`,
|
|
39
|
-
`import {Box} from '@primer/react'; <Box sx={{color: text.primary}}>Hello</Box>`,
|
|
40
|
-
`import {Box} from '@primer/react'; <Box sx={{color: "fg.default"}}>Hello</Box>`,
|
|
41
|
-
`{color: 'text.primary'}`,
|
|
42
|
-
],
|
|
43
|
-
invalid: [
|
|
44
|
-
{
|
|
45
|
-
code: `{color: 'text.primary'}`,
|
|
46
|
-
output: `{color: "fg.default"}`,
|
|
47
|
-
options: [{checkAllStrings: true}],
|
|
48
|
-
errors: [
|
|
49
|
-
{
|
|
50
|
-
message: '"text.primary" is deprecated. Use "fg.default" instead.',
|
|
51
|
-
},
|
|
52
|
-
],
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
code: `import {Box} from "@primer/react"; function Example() { return <Box color="text.primary">Hello</Box> }`,
|
|
56
|
-
output: `import {Box} from "@primer/react"; function Example() { return <Box color="fg.default">Hello</Box> }`,
|
|
57
|
-
errors: [
|
|
58
|
-
{
|
|
59
|
-
message: '"text.primary" is deprecated. Use "fg.default" instead.',
|
|
60
|
-
},
|
|
61
|
-
],
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
code: `import {Box} from "../components"; function Example() { return <Box color="text.primary">Hello</Box> }`,
|
|
65
|
-
output: `import {Box} from "../components"; function Example() { return <Box color="fg.default">Hello</Box> }`,
|
|
66
|
-
options: [{skipImportCheck: true}],
|
|
67
|
-
errors: [
|
|
68
|
-
{
|
|
69
|
-
message: '"text.primary" is deprecated. Use "fg.default" instead.',
|
|
70
|
-
},
|
|
71
|
-
],
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
code: `import Box from '@primer/react/lib-esm/Box'; function Example() { return <Box color="text.primary">Hello</Box> }`,
|
|
75
|
-
output: `import Box from '@primer/react/lib-esm/Box'; function Example() { return <Box color="fg.default">Hello</Box> }`,
|
|
76
|
-
errors: [
|
|
77
|
-
{
|
|
78
|
-
message: '"text.primary" is deprecated. Use "fg.default" instead.',
|
|
79
|
-
},
|
|
80
|
-
],
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
code: `import {Box} from "@primer/react"; const Example = () => <Box color="text.primary">Hello</Box>`,
|
|
84
|
-
output: `import {Box} from "@primer/react"; const Example = () => <Box color="fg.default">Hello</Box>`,
|
|
85
|
-
errors: [
|
|
86
|
-
{
|
|
87
|
-
message: '"text.primary" is deprecated. Use "fg.default" instead.',
|
|
88
|
-
},
|
|
89
|
-
],
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
code: `import {Box} from "@primer/react"; <Box bg="bg.primary" m={1} />`,
|
|
93
|
-
output: `import {Box} from "@primer/react"; <Box bg="canvas.default" m={1} />`,
|
|
94
|
-
errors: [
|
|
95
|
-
{
|
|
96
|
-
message: '"bg.primary" is deprecated. Use "canvas.default" instead.',
|
|
97
|
-
},
|
|
98
|
-
],
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
code: `import {Box} from "@primer/react"; <Box sx={{bg: "bg.primary", m: 1, ...rest}} />`,
|
|
102
|
-
output: `import {Box} from "@primer/react"; <Box sx={{bg: "canvas.default", m: 1, ...rest}} />`,
|
|
103
|
-
errors: [
|
|
104
|
-
{
|
|
105
|
-
message: '"bg.primary" is deprecated. Use "canvas.default" instead.',
|
|
106
|
-
},
|
|
107
|
-
],
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
code: `import {Box} from "@primer/react"; <Box sx={{boxShadow: theme => theme.shadows.autocomplete.shadow}} />`,
|
|
111
|
-
output: `import {Box} from "@primer/react"; <Box sx={{boxShadow: theme => theme.shadows.shadow.medium}} />`,
|
|
112
|
-
errors: [
|
|
113
|
-
{
|
|
114
|
-
message: '"theme.shadows.autocomplete.shadow" is deprecated. Use "theme.shadows.shadow.medium" instead.',
|
|
115
|
-
},
|
|
116
|
-
],
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
code: `import {Box} from "@primer/react"; <Box sx={{boxShadow: theme => \`0 1px 2px \${theme.colors.text.primary}\`}} />`,
|
|
120
|
-
output: `import {Box} from "@primer/react"; <Box sx={{boxShadow: theme => \`0 1px 2px \${theme.colors.fg.default}\`}} />`,
|
|
121
|
-
errors: [
|
|
122
|
-
{
|
|
123
|
-
message: '"theme.colors.text.primary" is deprecated. Use "theme.colors.fg.default" instead.',
|
|
124
|
-
},
|
|
125
|
-
],
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
code: `import {Box} from "@primer/react"; <Box sx={{boxShadow: t => \`0 1px 2px \${t.colors.text.primary}\`}} />`,
|
|
129
|
-
output: `import {Box} from "@primer/react"; <Box sx={{boxShadow: t => \`0 1px 2px \${t.colors.fg.default}\`}} />`,
|
|
130
|
-
errors: [
|
|
131
|
-
{
|
|
132
|
-
message: '"t.colors.text.primary" is deprecated. Use "t.colors.fg.default" instead.',
|
|
133
|
-
},
|
|
134
|
-
],
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
code: `import {Box} from "@primer/react"; <Box sx={{"&:hover": {bg: "bg.primary"}}} />`,
|
|
138
|
-
output: `import {Box} from "@primer/react"; <Box sx={{"&:hover": {bg: "canvas.default"}}} />`,
|
|
139
|
-
errors: [
|
|
140
|
-
{
|
|
141
|
-
message: '"bg.primary" is deprecated. Use "canvas.default" instead.',
|
|
142
|
-
},
|
|
143
|
-
],
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
code: `import {Box} from "@primer/react"; <Box color="auto.green.5" />`,
|
|
147
|
-
errors: [
|
|
148
|
-
{
|
|
149
|
-
message: '"auto.green.5" is deprecated.',
|
|
150
|
-
suggestions: [
|
|
151
|
-
{
|
|
152
|
-
desc: 'Use "success.fg" instead.',
|
|
153
|
-
output: `import {Box} from "@primer/react"; <Box color="success.fg" />`,
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
desc: 'Use "success.emphasis" instead.',
|
|
157
|
-
output: `import {Box} from "@primer/react"; <Box color="success.emphasis" />`,
|
|
158
|
-
},
|
|
159
|
-
],
|
|
160
|
-
},
|
|
161
|
-
],
|
|
162
|
-
},
|
|
163
|
-
{
|
|
164
|
-
code: `import {Box} from "@primer/react"; <Box color="fade.fg10" />`,
|
|
165
|
-
errors: [
|
|
166
|
-
{
|
|
167
|
-
message:
|
|
168
|
-
'"fade.fg10" is deprecated. Go to https://primer.style/primitives or reach out in the #primer channel on Slack to find a suitable replacement.',
|
|
169
|
-
},
|
|
170
|
-
],
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
code: `import {Box, Text} from "@primer/react"; <Box bg="bg.primary"><Text color="text.primary">Hello</Text></Box>`,
|
|
174
|
-
output: `import {Box, Text} from "@primer/react"; <Box bg="canvas.default"><Text color="fg.default">Hello</Text></Box>`,
|
|
175
|
-
errors: [
|
|
176
|
-
{
|
|
177
|
-
message: '"bg.primary" is deprecated. Use "canvas.default" instead.',
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
message: '"text.primary" is deprecated. Use "fg.default" instead.',
|
|
181
|
-
},
|
|
182
|
-
],
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
code: `import {themeGet} from "@primer/react"; themeGet("colors.text.primary")`,
|
|
186
|
-
output: `import {themeGet} from "@primer/react"; themeGet("colors.fg.default")`,
|
|
187
|
-
errors: [
|
|
188
|
-
{
|
|
189
|
-
message: '"colors.text.primary" is deprecated. Use "colors.fg.default" instead.',
|
|
190
|
-
},
|
|
191
|
-
],
|
|
192
|
-
},
|
|
193
|
-
{
|
|
194
|
-
code: `import {themeGet} from "@primer/react"; themeGet("shadows.autocomplete.shadow")`,
|
|
195
|
-
output: `import {themeGet} from "@primer/react"; themeGet("shadows.shadow.medium")`,
|
|
196
|
-
errors: [
|
|
197
|
-
{
|
|
198
|
-
message: '"shadows.autocomplete.shadow" is deprecated. Use "shadows.shadow.medium" instead.',
|
|
199
|
-
},
|
|
200
|
-
],
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
code: `import {get} from "./constants"; get("colors.text.primary")`,
|
|
204
|
-
output: `import {get} from "./constants"; get("colors.fg.default")`,
|
|
205
|
-
errors: [
|
|
206
|
-
{
|
|
207
|
-
message: '"colors.text.primary" is deprecated. Use "colors.fg.default" instead.',
|
|
208
|
-
},
|
|
209
|
-
],
|
|
210
|
-
},
|
|
211
|
-
{
|
|
212
|
-
code: `import {get} from "../constants"; get("colors.text.primary")`,
|
|
213
|
-
output: `import {get} from "../constants"; get("colors.fg.default")`,
|
|
214
|
-
errors: [
|
|
215
|
-
{
|
|
216
|
-
message: '"colors.text.primary" is deprecated. Use "colors.fg.default" instead.',
|
|
217
|
-
},
|
|
218
|
-
],
|
|
219
|
-
},
|
|
220
|
-
],
|
|
221
|
-
})
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
const deprecatedVars = require('@primer/primitives/dist/deprecated/colors')
|
|
2
|
-
const removedVars = require('@primer/primitives/dist/removed/colors')
|
|
3
|
-
const traverse = require('eslint-traverse')
|
|
4
|
-
const {isImportedFrom} = require('../utils/is-imported-from')
|
|
5
|
-
const {isPrimerComponent} = require('../utils/is-primer-component')
|
|
6
|
-
|
|
7
|
-
const styledSystemColorProps = ['color', 'bg', 'backgroundColor', 'borderColor', 'textShadow', 'boxShadow']
|
|
8
|
-
const deprecations = {...deprecatedVars, ...removedVars}
|
|
9
|
-
|
|
10
|
-
module.exports = {
|
|
11
|
-
meta: {
|
|
12
|
-
type: 'suggestion',
|
|
13
|
-
hasSuggestions: true,
|
|
14
|
-
fixable: 'code',
|
|
15
|
-
schema: [
|
|
16
|
-
{
|
|
17
|
-
type: 'object',
|
|
18
|
-
properties: {
|
|
19
|
-
skipImportCheck: {
|
|
20
|
-
type: 'boolean',
|
|
21
|
-
},
|
|
22
|
-
checkAllStrings: {
|
|
23
|
-
type: 'boolean',
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
additionalProperties: false,
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
|
-
},
|
|
30
|
-
create(context) {
|
|
31
|
-
// If `skipImportCheck` is true, this rule will check for deprecated colors
|
|
32
|
-
// used in any components (not just ones that are imported from `@primer/react`).
|
|
33
|
-
const skipImportCheck = context.options[0] ? context.options[0].skipImportCheck : false
|
|
34
|
-
|
|
35
|
-
const checkAllStrings = context.options[0] ? context.options[0].checkAllStrings : false
|
|
36
|
-
|
|
37
|
-
// Track visited string literals to avoid reporting the same string multiple times
|
|
38
|
-
const visitedStrings = new Set()
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
Literal(node) {
|
|
42
|
-
if (checkAllStrings && Object.keys(deprecations).includes(node.value) && !visitedStrings.has(node)) {
|
|
43
|
-
replaceDeprecatedColor(context, node, node.value)
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
JSXOpeningElement(node) {
|
|
47
|
-
// Skip if component was not imported from @primer/react
|
|
48
|
-
if (!skipImportCheck && !isPrimerComponent(node.name, context.getScope(node))) {
|
|
49
|
-
return
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
for (const attribute of node.attributes) {
|
|
53
|
-
if (!attribute.name || !attribute.value) {
|
|
54
|
-
continue
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const propName = attribute.name.name
|
|
58
|
-
const propValue = attribute.value.value
|
|
59
|
-
|
|
60
|
-
// Check for the sx prop
|
|
61
|
-
if (propName === 'sx' && attribute.value.expression.type === 'ObjectExpression') {
|
|
62
|
-
// Search all properties of the sx object (even nested properties)
|
|
63
|
-
traverse(context, attribute.value, path => {
|
|
64
|
-
if (path.node.type === 'Property' && path.node.value.type === 'Literal') {
|
|
65
|
-
const prop = path.node
|
|
66
|
-
const propName = prop.key.name
|
|
67
|
-
const propValue = prop.value.value
|
|
68
|
-
|
|
69
|
-
if (styledSystemColorProps.includes(propName) && Object.keys(deprecations).includes(propValue)) {
|
|
70
|
-
replaceDeprecatedColor(context, prop.value, propValue)
|
|
71
|
-
visitedStrings.add(prop.value)
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Check functions passed to sx object properties
|
|
76
|
-
// (e.g. boxShadow: theme => `0 1px 2px ${theme.colors.text.primary}` )
|
|
77
|
-
if (path.node.type === 'Property' && path.node.value.type === 'ArrowFunctionExpression') {
|
|
78
|
-
traverse(context, path.node.value.body, path => {
|
|
79
|
-
if (path.node.type === 'MemberExpression') {
|
|
80
|
-
// Convert MemberExpression AST to string
|
|
81
|
-
const code = context.getSourceCode().getText(path.node)
|
|
82
|
-
|
|
83
|
-
const [param, key, ...rest] = code.split('.')
|
|
84
|
-
const name = rest.join('.')
|
|
85
|
-
|
|
86
|
-
if (['colors', 'shadows'].includes(key) && Object.keys(deprecations).includes(name)) {
|
|
87
|
-
replaceDeprecatedColor(
|
|
88
|
-
context,
|
|
89
|
-
path.node,
|
|
90
|
-
name,
|
|
91
|
-
str => [param, key, str].join('.'),
|
|
92
|
-
str => str,
|
|
93
|
-
)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Don't traverse any nested member expressions.
|
|
97
|
-
// The root-level member expression gives us all the data we need.
|
|
98
|
-
return traverse.SKIP
|
|
99
|
-
}
|
|
100
|
-
})
|
|
101
|
-
}
|
|
102
|
-
})
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Check if styled-system color prop is using a deprecated color
|
|
106
|
-
if (styledSystemColorProps.includes(propName) && Object.keys(deprecations).includes(propValue)) {
|
|
107
|
-
replaceDeprecatedColor(context, attribute.value, propValue)
|
|
108
|
-
visitedStrings.add(attribute.value)
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
CallExpression(node) {
|
|
113
|
-
// Skip if not calling the `themeGet` or `get` function
|
|
114
|
-
// `get` is the internal version of `themeGet` that's used in the primer/react repository
|
|
115
|
-
if (
|
|
116
|
-
!isThemeGet(node.callee, context.getScope(node), skipImportCheck) &&
|
|
117
|
-
!isGet(node.callee, context.getScope(node))
|
|
118
|
-
) {
|
|
119
|
-
return
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const argument = node.arguments[0]
|
|
123
|
-
// Skip if the argument is not a Literal (themeGet(props.backgroundColor))
|
|
124
|
-
// or a string themeGet(2)
|
|
125
|
-
if (argument.type !== 'Literal' || typeof argument.value !== 'string') {
|
|
126
|
-
return
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const [key, ...path] = argument.value.split('.')
|
|
130
|
-
const name = path.join('.')
|
|
131
|
-
|
|
132
|
-
if (['colors', 'shadows'].includes(key) && Object.keys(deprecations).includes(name)) {
|
|
133
|
-
replaceDeprecatedColor(context, argument, name, str => [key, str].join('.'))
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function isThemeGet(identifier, scope, skipImportCheck = false) {
|
|
141
|
-
if (!skipImportCheck) {
|
|
142
|
-
return isImportedFrom(/^@primer\/react/, identifier, scope) && identifier.name === 'themeGet'
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return identifier.name === 'themeGet'
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// `get` is the internal version of `themeGet` that's used in the primer/react repository.
|
|
149
|
-
function isGet(identifier, scope) {
|
|
150
|
-
// This is a flaky way to check for the `get` function and should probably be improved.
|
|
151
|
-
return isImportedFrom(/^\.\.?\/constants$/, identifier, scope) && identifier.name === 'get'
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function replaceDeprecatedColor(
|
|
155
|
-
context,
|
|
156
|
-
node,
|
|
157
|
-
deprecatedName,
|
|
158
|
-
transformName = str => str,
|
|
159
|
-
transformReplacementValue = str => JSON.stringify(str),
|
|
160
|
-
) {
|
|
161
|
-
const replacement = deprecations[deprecatedName]
|
|
162
|
-
|
|
163
|
-
if (replacement === null) {
|
|
164
|
-
// No replacement
|
|
165
|
-
context.report({
|
|
166
|
-
node,
|
|
167
|
-
message: `"${transformName(
|
|
168
|
-
deprecatedName,
|
|
169
|
-
)}" is deprecated. Go to https://primer.style/primitives or reach out in the #primer channel on Slack to find a suitable replacement.`,
|
|
170
|
-
})
|
|
171
|
-
} else if (Array.isArray(replacement)) {
|
|
172
|
-
// Multiple possible replacements
|
|
173
|
-
context.report({
|
|
174
|
-
node,
|
|
175
|
-
message: `"${transformName(deprecatedName)}" is deprecated.`,
|
|
176
|
-
suggest: replacement.map(replacementValue => ({
|
|
177
|
-
desc: `Use "${transformName(replacementValue)}" instead.`,
|
|
178
|
-
fix(fixer) {
|
|
179
|
-
return fixer.replaceText(node, transformReplacementValue(transformName(replacementValue)))
|
|
180
|
-
},
|
|
181
|
-
})),
|
|
182
|
-
})
|
|
183
|
-
} else {
|
|
184
|
-
// One replacement
|
|
185
|
-
context.report({
|
|
186
|
-
node,
|
|
187
|
-
message: `"${transformName(deprecatedName)}" is deprecated. Use "${transformName(replacement)}" instead.`,
|
|
188
|
-
fix(fixer) {
|
|
189
|
-
return fixer.replaceText(node, transformReplacementValue(transformName(replacement)))
|
|
190
|
-
},
|
|
191
|
-
})
|
|
192
|
-
}
|
|
193
|
-
}
|