Skip to content

Commit 4b9bb60

Browse files
authored
Implement no-deprecated-colors rule
1 parent 2843307 commit 4b9bb60

File tree

4 files changed

+117
-5
lines changed

4 files changed

+117
-5
lines changed

package-lock.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"homepage": "https://github.com/primer/eslint-plugin-primer-react#readme",
2222
"devDependencies": {
2323
"@github/prettier-config": "0.0.4",
24+
"@primer/primitives": "^4.6.1",
2425
"eslint": "^7.32.0",
2526
"jest": "^27.0.6"
2627
},
Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,70 @@
11
const rule = require('../no-deprecated-colors')
22
const {RuleTester} = require('eslint')
33

4-
const ruleTester = new RuleTester()
4+
const testDeprecations = {
5+
'text.primary': 'fg.default',
6+
'bg.primary': 'canvas.default',
7+
'auto.green.5': ['success.fg', 'success.emphasis'],
8+
'fade.fg10': null
9+
}
10+
11+
jest.mock('@primer/primitives/dist/deprecations/colors_v2', () => testDeprecations)
12+
13+
const ruleTester = new RuleTester({
14+
parserOptions: {
15+
ecmaFeatures: {
16+
jsx: true
17+
}
18+
}
19+
})
520

621
ruleTester.run('no-deprecated-colors', rule, {
722
valid: [],
8-
invalid: [{code: 'hello()', errors: ['Hello ESLint']}]
23+
invalid: [
24+
{
25+
code: '<Box color="text.primary" />',
26+
output: '<Box color="fg.default" />',
27+
errors: [
28+
{
29+
message: '"text.primary" is deprecated. Use "fg.default" instead.'
30+
}
31+
]
32+
},
33+
{
34+
code: '<Box bg="bg.primary" />',
35+
output: '<Box bg="canvas.default" />',
36+
errors: [
37+
{
38+
message: '"bg.primary" is deprecated. Use "canvas.default" instead.'
39+
}
40+
]
41+
},
42+
{
43+
code: '<Box color="auto.green.5" />',
44+
errors: [
45+
{
46+
message: '"auto.green.5" is deprecated.',
47+
suggestions: [
48+
{
49+
desc: 'Use "success.fg" instead.',
50+
output: '<Box color="success.fg" />'
51+
},
52+
{
53+
desc: 'Use "success.emphasis" instead.',
54+
output: '<Box color="success.emphasis" />'
55+
}
56+
]
57+
}
58+
]
59+
},
60+
{
61+
code: '<Box color="fade.fg10" />',
62+
errors: [
63+
{
64+
message:
65+
'"fade.fg10" is deprecated. See https://primer.style/primitives or reach out in the #primer Slack channel to find a suitable replacement.'
66+
}
67+
]
68+
}
69+
]
970
})

src/rules/no-deprecated-colors.js

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,53 @@
1+
const deprecations = require('@primer/primitives/dist/deprecations/colors_v2')
2+
3+
const styledSystemColorProps = ['color', 'bg', 'backgroundColor', 'borderColor', 'textShadow', 'boxShadow']
4+
15
module.exports = {
2-
meta: {},
6+
meta: {
7+
fixable: 'code'
8+
},
39
create(context) {
410
return {
5-
CallExpression(node) {
6-
context.report({node, message: 'Hello ESLint'})
11+
JSXOpeningElement(node) {
12+
// TODO: check if jsx element was imported from @primer/components
13+
14+
for (const attribute of node.attributes) {
15+
const propName = attribute.name.name
16+
const propValue = attribute.value.value
17+
18+
if (styledSystemColorProps.includes(propName) && Object.keys(deprecations).includes(propValue)) {
19+
const replacement = deprecations[propValue]
20+
21+
if (replacement === null) {
22+
// No replacement
23+
context.report({
24+
node: attribute.value,
25+
message: `"${propValue}" is deprecated. See https://primer.style/primitives or reach out in the #primer Slack channel to find a suitable replacement.`
26+
})
27+
} else if (Array.isArray(replacement)) {
28+
// Multiple possible replacements
29+
context.report({
30+
node: attribute.value,
31+
message: `"${propValue}" is deprecated.`,
32+
suggest: replacement.map(replacementValue => ({
33+
desc: `Use "${replacementValue}" instead.`,
34+
fix(fixer) {
35+
return fixer.replaceText(attribute.value, JSON.stringify(replacementValue))
36+
}
37+
}))
38+
})
39+
} else {
40+
// One replacement
41+
context.report({
42+
node: attribute.value,
43+
message: `"${propValue}" is deprecated. Use "${replacement}" instead.`,
44+
fix(fixer) {
45+
return fixer.replaceText(attribute.value, JSON.stringify(replacement))
46+
}
47+
})
48+
}
49+
}
50+
}
751
}
852
}
953
}

0 commit comments

Comments
 (0)