Skip to content

Commit f9aee94

Browse files
jonathanpalmaljharb
authored andcommitted
[Fix] jsx-props-no-spreading: add support for namespaced jsx components
1 parent e69b113 commit f9aee94

File tree

3 files changed

+56
-2
lines changed

3 files changed

+56
-2
lines changed

.editorconfig

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ end_of_line = lf
77
charset = utf-8
88
trim_trailing_whitespace = true
99
insert_final_newline = true
10+
quote_type = single
1011

1112
[*.md]
1213
trim_trailing_whitespace = false

lib/rules/jsx-props-no-spreading.js

+14-2
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,23 @@ module.exports = {
7979
const exceptions = configuration.exceptions || DEFAULTS.exceptions;
8080
const isException = (tag, allExceptions) => allExceptions.indexOf(tag) !== -1;
8181
const isProperty = property => property.type === 'Property';
82+
const getTagNameFromMemberExpression = node => `${node.property.parent.object.name}.${node.property.name}`;
8283
return {
8384
JSXSpreadAttribute(node) {
84-
const tagName = node.parent.name.name;
85+
const jsxOpeningElement = node.parent.name;
86+
const type = jsxOpeningElement.type;
87+
88+
let tagName;
89+
if (type === 'JSXIdentifier') {
90+
tagName = jsxOpeningElement.name;
91+
} else if (type === 'JSXMemberExpression') {
92+
tagName = getTagNameFromMemberExpression(jsxOpeningElement);
93+
} else {
94+
tagName = undefined;
95+
}
96+
8597
const isHTMLTag = tagName && tagName[0] !== tagName[0].toUpperCase();
86-
const isCustomTag = tagName && tagName[0] === tagName[0].toUpperCase();
98+
const isCustomTag = tagName && (tagName[0] === tagName[0].toUpperCase() || tagName.includes('.'));
8799
if (
88100
isHTMLTag &&
89101
((ignoreHtmlTags && !isException(tagName, exceptions)) ||

tests/lib/rules/jsx-props-no-spreading.js

+41
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,37 @@ ruleTester.run('jsx-props-no-spreading', rule, {
8989
</App>
9090
`,
9191
options: [{explicitSpread: 'ignore'}]
92+
}, {
93+
code: [
94+
'const props = {};',
95+
'<App>',
96+
' <components.Group {...props}/>',
97+
' <Nav.Item {...props}/>',
98+
'</App>'
99+
].join('\n'),
100+
options: [{exceptions: ['components.Group', 'Nav.Item']}]
101+
}, {
102+
code: [
103+
'const props = {};',
104+
'<App>',
105+
' <components.Group {...props}/>',
106+
' <Nav.Item {...props}/>',
107+
'</App>'
108+
].join('\n'),
109+
options: [{custom: 'ignore'}]
110+
}, {
111+
code: [
112+
'const props = {};',
113+
'<App>',
114+
' <components.Group {...props}/>',
115+
' <Nav.Item {...props}/>',
116+
'</App>'
117+
].join('\n'),
118+
options: [{
119+
custom: 'enforce',
120+
html: 'ignore',
121+
exceptions: ['components.Group', 'Nav.Item']
122+
}]
92123
}],
93124

94125
invalid: [{
@@ -192,5 +223,15 @@ ruleTester.run('jsx-props-no-spreading', rule, {
192223
`,
193224
options: [{explicitSpread: 'ignore'}],
194225
errors: [expectedError]
226+
}, {
227+
code: [
228+
'const props = {};',
229+
'<App>',
230+
' <components.Group {...props}/>',
231+
' <Nav.Item {...props}/>',
232+
'</App>'
233+
].join('\n'),
234+
options: [{exceptions: ['components.DropdownIndicator', 'Nav.Item']}],
235+
errors: [expectedError]
195236
}]
196237
});

0 commit comments

Comments
 (0)