Skip to content

Commit af4935f

Browse files
committed
Adds a no-system-props rule
1 parent f408f42 commit af4935f

12 files changed

+393
-36
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const styledSystemAttributes = ['width', 'height']
2+
3+
export default function(context) {
4+
return {
5+
JSXOpeningElement(node) {
6+
console.log(node.attributes)
7+
8+
const systemAttributeNodes = node.attributes.filter(attribute => {
9+
return styledSystemAttributes.indexOf(attribute.name) !== -1
10+
})
11+
12+
if (systemAttributeNodes.length !== 0) {
13+
context.report({
14+
node,
15+
message: `Styled-system attributes are deprecated (${attributes.map(a => a.name)})`,
16+
})
17+
18+
// fix(fixer) {
19+
20+
// }
21+
}
22+
}
23+
};
24+
};

docs/rules/no-system-props.md

Whitespace-only changes.

package-lock.json

Lines changed: 136 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
},
3535
"prettier": "@github/prettier-config",
3636
"dependencies": {
37-
"eslint-traverse": "^1.0.0"
37+
"@styled-system/props": "^5.1.5",
38+
"eslint-traverse": "^1.0.0",
39+
"styled-system": "^5.1.5"
3840
}
3941
}

src/configs/recommended.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module.exports = {
77
},
88
plugins: ['primer-react'],
99
rules: {
10-
'primer-react/no-deprecated-colors': 'warn'
10+
'primer-react/no-deprecated-colors': 'warn',
11+
'primer-react/no-system-props': 'warn'
1112
}
1213
}

src/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module.exports = {
22
rules: {
3-
'no-deprecated-colors': require('./rules/no-deprecated-colors')
3+
'no-deprecated-colors': require('./rules/no-deprecated-colors'),
4+
'no-system-props': require('./rules/no-system-props')
45
},
56
configs: {
67
recommended: require('./configs/recommended')
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
const rule = require('../no-system-props')
2+
const {RuleTester} = require('eslint')
3+
4+
const ruleTester = new RuleTester({
5+
parserOptions: {
6+
ecmaVersion: 'latest',
7+
sourceType: 'module',
8+
ecmaFeatures: {
9+
jsx: true
10+
}
11+
}
12+
})
13+
14+
ruleTester.run('no-system-props', rule, {
15+
valid: [
16+
`import {Button} from '@primer/components'; <Button sx={{width: 200}} />`,
17+
`import {Button} from 'coles-cool-design-system'; <Button width={200} />`,
18+
`import {Button} from '@primer/components'; <Button someOtherProp="foo" />`,
19+
`import {Box} from '@primer/components'; <Box width={200} />`,
20+
`import {TextInput} from '@primer/components'; <TextInput width={200} />`
21+
],
22+
invalid: [
23+
{
24+
code: `import {Button} from '@primer/components'; <Button width={200} />`,
25+
output: `import {Button} from '@primer/components'; <Button sx={{width: 200}} />`,
26+
errors: [
27+
{
28+
messageId: 'noSystemProps',
29+
data: {propNames: 'width'}
30+
}
31+
]
32+
},
33+
{
34+
code: `import {Button} from '@primer/components'; <Button width="200" />`,
35+
output: `import {Button} from '@primer/components'; <Button sx={{width: "200"}} />`,
36+
errors: [
37+
{
38+
messageId: 'noSystemProps',
39+
data: {propNames: 'width'}
40+
}
41+
]
42+
},
43+
{
44+
code: `import {Button} from '@primer/components'; <Button width={"200"} />`,
45+
output: `import {Button} from '@primer/components'; <Button sx={{width: "200"}} />`,
46+
errors: [
47+
{
48+
messageId: 'noSystemProps',
49+
data: {propNames: 'width'}
50+
}
51+
]
52+
},
53+
{
54+
code: `import {Button} from '@primer/components'; <Button width={myWidth} />`,
55+
output: `import {Button} from '@primer/components'; <Button sx={{width: myWidth}} />`,
56+
errors: [
57+
{
58+
messageId: 'noSystemProps',
59+
data: {propNames: 'width'}
60+
}
61+
]
62+
},
63+
{
64+
code: `import {Button} from '@primer/components'; <Button width={200} height={200} />`,
65+
output: `import {Button} from '@primer/components'; <Button sx={{width: 200, height: 200}} />`,
66+
errors: [
67+
{
68+
messageId: 'noSystemProps',
69+
data: {propNames: 'width, height'}
70+
}
71+
]
72+
},
73+
{
74+
code: `import {Button} from '@primer/components'; <Button width={200} sx={{height: 200}} />`,
75+
output: `import {Button} from '@primer/components'; <Button sx={{width: 200, height: 200}} />`,
76+
errors: [
77+
{
78+
messageId: 'noSystemProps',
79+
data: {propNames: 'width'}
80+
}
81+
]
82+
},
83+
{
84+
code: `import {Button} from '@primer/components'; <Button width={200} sx={{width: 300}} />`,
85+
output: `import {Button} from '@primer/components'; <Button sx={{width: 300}} />`,
86+
errors: [
87+
{
88+
messageId: 'noSystemProps',
89+
data: {propNames: 'width'}
90+
}
91+
]
92+
},
93+
{
94+
code: `import {Button} from '@primer/components'; <Button width={200} sx={myStylez} />`,
95+
output: `import {Button} from '@primer/components'; <Button width={200} sx={myStylez} />`,
96+
errors: [
97+
{
98+
messageId: 'noSystemProps',
99+
data: {propNames: 'width'}
100+
}
101+
]
102+
}
103+
]
104+
})

src/rules/no-deprecated-colors.js

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
const deprecations = require('@primer/primitives/dist/deprecations/colors')
22
const traverse = require('eslint-traverse')
3+
const {isImportedFrom} = require('../utils/isImportedFrom')
4+
const {isPrimerComponent} = require('../utils/isPrimerComponent')
5+
const {getVariableDeclaration} = require('../utils/getVariableDeclaration')
36

47
const styledSystemColorProps = ['color', 'bg', 'backgroundColor', 'borderColor', 'textShadow', 'boxShadow']
58

@@ -125,37 +128,6 @@ module.exports = {
125128
}
126129
}
127130

128-
/**
129-
* Get the variable declaration for the given identifier
130-
*/
131-
function getVariableDeclaration(scope, identifier) {
132-
if (scope === null) {
133-
return null
134-
}
135-
136-
for (const variable of scope.variables) {
137-
if (variable.name === identifier.name) {
138-
return variable.defs[0]
139-
}
140-
}
141-
142-
return getVariableDeclaration(scope.upper, identifier)
143-
}
144-
145-
/**
146-
* Check if the given identifier is imported from the given module
147-
*/
148-
function isImportedFrom(moduleRegex, identifier, scope) {
149-
const definition = getVariableDeclaration(scope, identifier)
150-
151-
// Return true if the variable was imported from the given module
152-
return definition && definition.type == 'ImportBinding' && moduleRegex.test(definition.parent.source.value)
153-
}
154-
155-
function isPrimerComponent(identifier, scope) {
156-
return isImportedFrom(/^@primer\/components/, identifier, scope)
157-
}
158-
159131
function isThemeGet(identifier, scope, skipImportCheck = false) {
160132
if (!skipImportCheck) {
161133
return isImportedFrom(/^@primer\/components/, identifier, scope) && identifier.name === 'themeGet'
@@ -205,7 +177,7 @@ function replaceDeprecatedColor(
205177
node,
206178
message: `"${transformName(deprecatedName)}" is deprecated. Use "${transformName(replacement)}" instead.`,
207179
fix(fixer) {
208-
return fixer.replaceText(node, transformReplacementValue(transformName(replacement)))
180+
// return fixer.replaceText(node, transformReplacementValue(transformName(replacement)))
209181
}
210182
})
211183
}

0 commit comments

Comments
 (0)