eslint-plugin-primer-react 2.0.1 → 2.0.2-rc.58f30d3
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 +10 -0
- package/package-lock.json +14601 -0
- package/package.json +1 -1
- package/src/rules/__tests__/direct-slot-children.test.js +24 -4
- package/src/rules/direct-slot-children.js +20 -7
package/package.json
CHANGED
|
@@ -17,10 +17,12 @@ ruleTester.run('direct-slot-children', rule, {
|
|
|
17
17
|
`import {PageLayout} from '@primer/react'; <PageLayout><div><PageLayout.Pane>Header</PageLayout.Pane></div></PageLayout>`,
|
|
18
18
|
`import {PageLayout} from '@primer/react'; <PageLayout>{true ? <PageLayout.Header>Header</PageLayout.Header> : null}</PageLayout>`,
|
|
19
19
|
`import {PageLayout} from './PageLayout'; <PageLayout.Header>Header</PageLayout.Header>`,
|
|
20
|
-
{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
20
|
+
`import {FormControl, Radio} from '@primer/react'; <FormControl><Radio value="one" /><FormControl.Label>Choice one</FormControl.Label></FormControl>`,
|
|
21
|
+
`import {ActionList} from '@primer/react';
|
|
22
|
+
<ActionList.Item><ActionList.LeadingVisual> <Avatar src="https://github.com/mona.png" /></ActionList.LeadingVisual>mona<ActionList.Description>Monalisa Octocat</ActionList.Description></ActionList.Item>`,
|
|
23
|
+
`import {ActionList} from '@primer/react';
|
|
24
|
+
<ActionList.LinkItem><ActionList.LeadingVisual></ActionList.LeadingVisual>mona<ActionList.Description>Monalisa Octocat</ActionList.Description></ActionList.LinkItem>`,
|
|
25
|
+
{code: `import {Foo} from './Foo'; <Foo><div><Foo.Bar></Foo.Bar></div></Foo>`, options: [{skipImportCheck: true}]}
|
|
24
26
|
],
|
|
25
27
|
invalid: [
|
|
26
28
|
{
|
|
@@ -32,6 +34,15 @@ ruleTester.run('direct-slot-children', rule, {
|
|
|
32
34
|
}
|
|
33
35
|
]
|
|
34
36
|
},
|
|
37
|
+
{
|
|
38
|
+
code: `import {PageLayout} from '@primer/react'; function Header() { return <PageLayout.Header>Header</PageLayout.Header>; }`,
|
|
39
|
+
errors: [
|
|
40
|
+
{
|
|
41
|
+
messageId: 'directSlotChildren',
|
|
42
|
+
data: {childName: 'PageLayout.Header', parentName: 'PageLayout'}
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
},
|
|
35
46
|
{
|
|
36
47
|
code: `import {PageLayout} from '@primer/react/drafts'; <PageLayout.Header>Header</PageLayout.Header>`,
|
|
37
48
|
errors: [
|
|
@@ -77,6 +88,15 @@ ruleTester.run('direct-slot-children', rule, {
|
|
|
77
88
|
data: {childName: 'PageLayout.Header', parentName: 'PageLayout'}
|
|
78
89
|
}
|
|
79
90
|
]
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
code: `import {ActionList} from '@primer/react'; <ActionList.Item><div><ActionList.LeadingVisual>Visual</ActionList.LeadingVisual></div></ActionList.Item>`,
|
|
94
|
+
errors: [
|
|
95
|
+
{
|
|
96
|
+
messageId: 'directSlotChildren',
|
|
97
|
+
data: {childName: 'ActionList.LeadingVisual', parentName: 'ActionList.Item or ActionList.LinkItem'}
|
|
98
|
+
}
|
|
99
|
+
]
|
|
80
100
|
}
|
|
81
101
|
]
|
|
82
102
|
})
|
|
@@ -3,17 +3,25 @@ const {last} = require('lodash')
|
|
|
3
3
|
|
|
4
4
|
const slotParentToChildMap = {
|
|
5
5
|
PageLayout: ['PageLayout.Header', 'PageLayout.Footer'],
|
|
6
|
+
SplitPageLayout: ['SplitPageLayout.Header', 'SplitPageLayout.Footer'],
|
|
6
7
|
FormControl: ['FormControl.Label', 'FormControl.Caption', 'FormControl.LeadingVisual', 'FormControl.TrailingVisual'],
|
|
7
|
-
MarkdownEditor: ['MarkdownEditor.Toolbar', 'MarkdownEditor.Actions', 'MarkdownEditor.Label'],
|
|
8
8
|
'ActionList.Item': ['ActionList.LeadingVisual', 'ActionList.TrailingVisual', 'ActionList.Description'],
|
|
9
|
+
'ActionList.LinkItem': ['ActionList.LeadingVisual', 'ActionList.TrailingVisual', 'ActionList.Description'],
|
|
10
|
+
'NavList.Item': ['NavList.LeadingVisual', 'NavList.TrailingVisual'],
|
|
9
11
|
'TreeView.Item': ['TreeView.LeadingVisual', 'TreeView.TrailingVisual'],
|
|
10
12
|
RadioGroup: ['RadioGroup.Label', 'RadioGroup.Caption', 'RadioGroup.Validation'],
|
|
11
13
|
CheckboxGroup: ['CheckboxGroup.Label', 'CheckboxGroup.Caption', 'CheckboxGroup.Validation']
|
|
14
|
+
// Ignore `MarkdownEditor` for now because it's still in drafts
|
|
15
|
+
// MarkdownEditor: ['MarkdownEditor.Toolbar', 'MarkdownEditor.Actions', 'MarkdownEditor.Label'],
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
const slotChildToParentMap = Object.entries(slotParentToChildMap).reduce((acc, [parent, children]) => {
|
|
15
19
|
for (const child of children) {
|
|
16
|
-
acc[child]
|
|
20
|
+
if (acc[child]) {
|
|
21
|
+
acc[child].push(parent)
|
|
22
|
+
} else {
|
|
23
|
+
acc[child] = [parent]
|
|
24
|
+
}
|
|
17
25
|
}
|
|
18
26
|
return acc
|
|
19
27
|
}, {})
|
|
@@ -50,19 +58,24 @@ module.exports = {
|
|
|
50
58
|
(skipImportCheck || isPrimerComponent(jsxNode.name, context.getScope(jsxNode))) &&
|
|
51
59
|
slotChildToParentMap[name]
|
|
52
60
|
) {
|
|
53
|
-
const
|
|
61
|
+
const expectedParentNames = slotChildToParentMap[name]
|
|
54
62
|
const parent = last(stack)
|
|
55
|
-
if (parent
|
|
63
|
+
if (!expectedParentNames.includes(parent)) {
|
|
56
64
|
context.report({
|
|
57
65
|
node: jsxNode,
|
|
58
66
|
messageId: 'directSlotChildren',
|
|
59
|
-
data: {
|
|
67
|
+
data: {
|
|
68
|
+
childName: name,
|
|
69
|
+
parentName: expectedParentNames.length > 1 ? expectedParentNames.join(' or ') : expectedParentNames[0]
|
|
70
|
+
}
|
|
60
71
|
})
|
|
61
72
|
}
|
|
62
73
|
}
|
|
63
74
|
|
|
64
|
-
//
|
|
65
|
-
|
|
75
|
+
// If tag is not self-closing, push it onto the stack
|
|
76
|
+
if (!jsxNode.selfClosing) {
|
|
77
|
+
stack.push(name)
|
|
78
|
+
}
|
|
66
79
|
},
|
|
67
80
|
JSXClosingElement() {
|
|
68
81
|
// Pop the current element off the stack
|