eslint-plugin-primer-react 2.0.2 → 2.0.3
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
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# eslint-plugin-primer-react
|
|
2
2
|
|
|
3
|
+
## 2.0.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#47](https://github.com/primer/eslint-plugin-primer-react/pull/47) [`9964e4e`](https://github.com/primer/eslint-plugin-primer-react/commit/9964e4e5415c3bbeab78763b7b4d4e29a0bdbb95) Thanks [@colebemis](https://github.com/colebemis)! - - Update the no-system-props rule to properly check subcomponents for system props
|
|
8
|
+
- Adds valid sucomponent props to the allowlist
|
|
9
|
+
|
|
3
10
|
## 2.0.2
|
|
4
11
|
|
|
5
12
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -20,7 +20,8 @@ ruleTester.run('no-system-props', rule, {
|
|
|
20
20
|
`import {ProgressBar} from '@primer/react'; <ProgressBar bg="howdy" />`,
|
|
21
21
|
`import {Button} from '@primer/react'; <Button {...someExpression()} />`,
|
|
22
22
|
`import {Button} from '@primer/react'; <Button variant="large" />`,
|
|
23
|
-
`import {Button} from '@primer/react'; <Button size="large"
|
|
23
|
+
`import {Button} from '@primer/react'; <Button size="large" />`,
|
|
24
|
+
`import {ActionMenu} from '@primer/react'; <ActionMenu.Overlay width="large" />`
|
|
24
25
|
],
|
|
25
26
|
invalid: [
|
|
26
27
|
{
|
|
@@ -166,6 +167,16 @@ ruleTester.run('no-system-props', rule, {
|
|
|
166
167
|
data: {propNames: 'width', componentName: 'Foo'}
|
|
167
168
|
}
|
|
168
169
|
]
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
code: `import {Button} from '@primer/react'; <Button.Counter width={200} />`,
|
|
173
|
+
output: `import {Button} from '@primer/react'; <Button.Counter sx={{width: 200}} />`,
|
|
174
|
+
errors: [
|
|
175
|
+
{
|
|
176
|
+
messageId: 'noSystemProps',
|
|
177
|
+
data: {propNames: 'width', componentName: 'Button.Counter'}
|
|
178
|
+
}
|
|
179
|
+
]
|
|
169
180
|
}
|
|
170
181
|
]
|
|
171
182
|
})
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const {isPrimerComponent} = require('../utils/is-primer-component')
|
|
2
|
+
const {getJSXOpeningElementName} = require('../utils/get-jsx-opening-element-name')
|
|
2
3
|
const {last} = require('lodash')
|
|
3
4
|
|
|
4
5
|
const slotParentToChildMap = {
|
|
@@ -84,12 +85,3 @@ module.exports = {
|
|
|
84
85
|
}
|
|
85
86
|
}
|
|
86
87
|
}
|
|
87
|
-
|
|
88
|
-
// Convert JSXOpeningElement name to string
|
|
89
|
-
function getJSXOpeningElementName(jsxNode) {
|
|
90
|
-
if (jsxNode.name.type === 'JSXIdentifier') {
|
|
91
|
-
return jsxNode.name.name
|
|
92
|
-
} else if (jsxNode.name.type === 'JSXMemberExpression') {
|
|
93
|
-
return `${jsxNode.name.object.name}.${jsxNode.name.property.name}`
|
|
94
|
-
}
|
|
95
|
-
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const {isPrimerComponent} = require('../utils/is-primer-component')
|
|
2
|
+
const {getJSXOpeningElementName} = require('../utils/get-jsx-opening-element-name')
|
|
2
3
|
const {pick} = require('@styled-system/props')
|
|
3
4
|
const {some, last} = require('lodash')
|
|
4
5
|
|
|
@@ -12,18 +13,31 @@ const utilityComponents = new Set(['Box', 'Text'])
|
|
|
12
13
|
|
|
13
14
|
// Components for which we allow a set of prop names
|
|
14
15
|
const excludedComponentProps = new Map([
|
|
16
|
+
['ActionMenu.Overlay', new Set(['width', 'height', 'maxHeight', 'position', 'top', 'right', 'bottom', 'left'])],
|
|
17
|
+
['Autocomplete.Overlay', new Set(['width', 'height', 'maxHeight', 'position', 'top', 'right', 'bottom', 'left'])],
|
|
15
18
|
['AnchoredOverlay', new Set(['width', 'height'])],
|
|
16
19
|
['Avatar', new Set(['size'])],
|
|
17
20
|
['AvatarToken', new Set(['size'])],
|
|
18
21
|
['CircleOcticon', new Set(['size'])],
|
|
19
22
|
['Dialog', new Set(['width', 'height'])],
|
|
20
23
|
['IssueLabelToken', new Set(['size'])],
|
|
24
|
+
['Overlay', new Set(['width', 'height', 'maxHeight', 'position', 'top', 'right', 'bottom', 'left'])],
|
|
21
25
|
['ProgressBar', new Set(['bg'])],
|
|
22
26
|
['Spinner', new Set(['size'])],
|
|
27
|
+
['SplitPageLayout.Header', new Set(['padding'])],
|
|
28
|
+
['SplitPageLayout.Footer', new Set(['padding'])],
|
|
29
|
+
['SplitPageLayout.Pane', new Set(['padding', 'position', 'width'])],
|
|
30
|
+
['SplitPageLayout.Content', new Set(['padding', 'width'])],
|
|
23
31
|
['StyledOcticon', new Set(['size'])],
|
|
24
32
|
['PointerBox', new Set(['bg'])],
|
|
33
|
+
['TextInput', new Set(['size'])],
|
|
34
|
+
['TextInputWithTokens', new Set(['size', 'maxHeight'])],
|
|
25
35
|
['Token', new Set(['size'])],
|
|
26
36
|
['PageLayout', new Set(['padding'])],
|
|
37
|
+
['PageLayout.Header', new Set(['padding'])],
|
|
38
|
+
['PageLayout.Footer', new Set(['padding'])],
|
|
39
|
+
['PageLayout.Pane', new Set(['padding', 'position', 'width'])],
|
|
40
|
+
['PageLayout.Content', new Set(['padding', 'width'])],
|
|
27
41
|
['ProgressBar', new Set(['bg'])],
|
|
28
42
|
['PointerBox', new Set(['bg'])]
|
|
29
43
|
])
|
|
@@ -65,7 +79,10 @@ module.exports = {
|
|
|
65
79
|
return {
|
|
66
80
|
JSXOpeningElement(jsxNode) {
|
|
67
81
|
if (!skipImportCheck && !isPrimerComponent(jsxNode.name, context.getScope(jsxNode))) return
|
|
68
|
-
|
|
82
|
+
|
|
83
|
+
const componentName = getJSXOpeningElementName(jsxNode)
|
|
84
|
+
|
|
85
|
+
if (excludedComponents.has(componentName)) return
|
|
69
86
|
|
|
70
87
|
// Create an object mapping from prop name to the AST node for that attribute
|
|
71
88
|
const propsByNameObject = jsxNode.attributes.reduce((object, attribute) => {
|
|
@@ -80,8 +97,8 @@ module.exports = {
|
|
|
80
97
|
// Create an array of system prop attribute nodes
|
|
81
98
|
let systemProps = Object.values(pick(propsByNameObject))
|
|
82
99
|
|
|
83
|
-
const excludedProps = excludedComponentProps.has(
|
|
84
|
-
? new Set([...alwaysExcludedProps, ...excludedComponentProps.get(
|
|
100
|
+
const excludedProps = excludedComponentProps.has(componentName)
|
|
101
|
+
? new Set([...alwaysExcludedProps, ...excludedComponentProps.get(componentName)])
|
|
85
102
|
: alwaysExcludedProps
|
|
86
103
|
|
|
87
104
|
// Filter out our exceptional props
|
|
@@ -94,7 +111,7 @@ module.exports = {
|
|
|
94
111
|
node: jsxNode,
|
|
95
112
|
messageId: 'noSystemProps',
|
|
96
113
|
data: {
|
|
97
|
-
componentName
|
|
114
|
+
componentName,
|
|
98
115
|
propNames: systemProps.map(a => a.name.name).join(', ')
|
|
99
116
|
},
|
|
100
117
|
fix(fixer) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Convert JSXOpeningElement name to string */
|
|
2
|
+
function getJSXOpeningElementName(jsxNode) {
|
|
3
|
+
if (jsxNode.name.type === 'JSXIdentifier') {
|
|
4
|
+
return jsxNode.name.name
|
|
5
|
+
} else if (jsxNode.name.type === 'JSXMemberExpression') {
|
|
6
|
+
return `${jsxNode.name.object.name}.${jsxNode.name.property.name}`
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
exports.getJSXOpeningElementName = getJSXOpeningElementName
|