Skip to content

Commit 689672c

Browse files
authored
Merge pull request #10 from primer/check-all-strings
Add `checkAllStrings` option
2 parents 30d0a35 + 31d069b commit 689672c

File tree

4 files changed

+80
-4
lines changed

4 files changed

+80
-4
lines changed

.changeset/curvy-pears-perform.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
"eslint-plugin-primer-react": minor
3+
---
4+
5+
Add a `checkAllStrings` option to the `no-deprecated-colors` rule.
6+
7+
If `checkAllStrings` is set to `true`, the `no-deprecated-colors` rule will check for deprecated colors in all strings. This is useful for catching uses of deprecated colors outside system props and the `sx` prop.
8+
9+
```js
10+
/* eslint primer-react/no-deprecated-colors: ["warn", {"checkAllStrings": true}] */
11+
import {Box} from '@primer/components'
12+
13+
function ExampleComponent() {
14+
const styles = {
15+
// Enabling `checkAllStrings` will find deprecated colors used like this:
16+
color: 'text.primary'
17+
}
18+
return <Box sx={styles}>Hello</Box>
19+
}
20+
```

docs/rules/no-deprecated-colors.md

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ const SystemPropExample() = () => <Box color="some.deprecated.color">Incorrect</
1919

2020
const SxPropExample() = () => <Box sx={{color: 'some.deprecated.color'}}>Incorrect</Box>
2121

22+
const SxPropExample2() = () => <Box sx={{boxShadow: theme => `0 1px 2px ${theme.colors.some.deprecated.color}`}}>Incorrect</Box>
23+
2224
const ThemeGetExample = styled.div`
2325
color: ${themeGet('colors.some.deprecated.color')};
2426
`
@@ -31,9 +33,11 @@ const ThemeGetExample = styled.div`
3133
import {Box, themeGet} from '@primer/components'
3234
import styled from 'styled-components'
3335

34-
const SystemPropExample() = () => <Box color="some.color">Incorrect</Box>
36+
const SystemPropExample() = () => <Box color="some.color">Correct</Box>
37+
38+
const SxPropExample() = () => <Box sx={{color: 'some.color'}}>Correct</Box>
3539

36-
const SxPropExample() = () => <Box sx={{color: 'some.color'}}>Incorrect</Box>
40+
const SxPropExample2() = () => <Box sx={{boxShadow: theme => `0 1px 2px ${theme.colors.some.color}`}}>Correct</Box>
3741

3842
const ThemeGetExample = styled.div`
3943
color: ${themeGet('colors.some.color')};
@@ -46,7 +50,33 @@ const ThemeGetExample = styled.div`
4650

4751
By default, the `no-deprecated-colors` rule will only check for deprecated colors used in functions and components that are imported from `@primer/components`. You can disable this behavior by setting `skipImportCheck` to `true`. This is useful for linting custom components that pass color-related props down to Primer React components.
4852

53+
```js
54+
/* eslint primer-react/no-deprecated-colors: ["warn", {"skipImportCheck": true}] */
55+
import {Box} from '@primer/components'
4956

57+
function MyBox({color, children}) {
58+
return <Box color={color}>{children}</Box>
59+
}
60+
61+
function App() {
62+
// Enabling `skipImportCheck` will find deprecated colors used like this:
63+
return <MyBox color="text.primary">Hello</MyBox>
64+
}
5065
```
51-
"primer-react/no-deprecated-colors": ["warn", {"skipImportCheck": true}]
66+
67+
- `checkAllStrings` (default: `false`)
68+
69+
If `checkAllStrings` is set to `true`, the `no-deprecated-colors` rule will check for deprecated colors in all strings. This is useful for catching uses of deprecated colors outside system props and the `sx` prop.
70+
71+
```js
72+
/* eslint primer-react/no-deprecated-colors: ["warn", {"checkAllStrings": true}] */
73+
import {Box} from '@primer/components'
74+
75+
function ExampleComponent() {
76+
const styles = {
77+
// Enabling `checkAllStrings` will find deprecated colors used like this:
78+
color: 'text.primary'
79+
}
80+
return <Box sx={styles}>Hello</Box>
81+
}
5282
```

src/rules/__tests__/no-deprecated-colors.test.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,20 @@ ruleTester.run('no-deprecated-colors', rule, {
3131
`import {get} from "@other/constants"; get("space.text.primary")`,
3232
`import {Box} from '@primer/components'; <Box sx={styles}>Hello</Box>`,
3333
`import {Box} from '@primer/components'; <Box sx={{color: text.primary}}>Hello</Box>`,
34-
`import {Box} from '@primer/components'; <Box sx={{color: "fg.default"}}>Hello</Box>`
34+
`import {Box} from '@primer/components'; <Box sx={{color: "fg.default"}}>Hello</Box>`,
35+
`{color: 'text.primary'}`
3536
],
3637
invalid: [
38+
{
39+
code: `{color: 'text.primary'}`,
40+
output: `{color: "fg.default"}`,
41+
options: [{checkAllStrings: true}],
42+
errors: [
43+
{
44+
message: '"text.primary" is deprecated. Use "fg.default" instead.'
45+
}
46+
]
47+
},
3748
{
3849
code: `import {Box} from "@primer/components"; function Example() { return <Box color="text.primary">Hello</Box> }`,
3950
output: `import {Box} from "@primer/components"; function Example() { return <Box color="fg.default">Hello</Box> }`,

src/rules/no-deprecated-colors.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ module.exports = {
1313
properties: {
1414
skipImportCheck: {
1515
type: 'boolean'
16+
},
17+
checkAllStrings: {
18+
type: 'boolean'
1619
}
1720
},
1821
additionalProperties: false
@@ -24,7 +27,17 @@ module.exports = {
2427
// used in any components (not just ones that are imported from `@primer/components`).
2528
const skipImportCheck = context.options[0] ? context.options[0].skipImportCheck : false
2629

30+
const checkAllStrings = context.options[0] ? context.options[0].checkAllStrings : false
31+
32+
// Track visited string literals to avoid reporting the same string multiple times
33+
const visitedStrings = new Set()
34+
2735
return {
36+
Literal(node) {
37+
if (checkAllStrings && Object.keys(deprecations).includes(node.value) && !visitedStrings.has(node)) {
38+
replaceDeprecatedColor(context, node, node.value)
39+
}
40+
},
2841
JSXOpeningElement(node) {
2942
// Skip if component was not imported from @primer/components
3043
if (!skipImportCheck && !isPrimerComponent(node.name, context.getScope(node))) {
@@ -50,6 +63,7 @@ module.exports = {
5063

5164
if (styledSystemColorProps.includes(propName) && Object.keys(deprecations).includes(propValue)) {
5265
replaceDeprecatedColor(context, prop.value, propValue)
66+
visitedStrings.add(prop.value)
5367
}
5468
}
5569

@@ -86,6 +100,7 @@ module.exports = {
86100
// Check if styled-system color prop is using a deprecated color
87101
if (styledSystemColorProps.includes(propName) && Object.keys(deprecations).includes(propValue)) {
88102
replaceDeprecatedColor(context, attribute.value, propValue)
103+
visitedStrings.add(attribute.value)
89104
}
90105
}
91106
},

0 commit comments

Comments
 (0)