diff --git a/.editorconfig b/.editorconfig
index 4a7ea3036a..319299684a 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -7,6 +7,7 @@ end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
+quote_type = single
[*.md]
trim_trailing_whitespace = false
diff --git a/lib/rules/jsx-props-no-spreading.js b/lib/rules/jsx-props-no-spreading.js
index 2a311a0a6f..f23879a4d6 100644
--- a/lib/rules/jsx-props-no-spreading.js
+++ b/lib/rules/jsx-props-no-spreading.js
@@ -79,11 +79,23 @@ module.exports = {
const exceptions = configuration.exceptions || DEFAULTS.exceptions;
const isException = (tag, allExceptions) => allExceptions.indexOf(tag) !== -1;
const isProperty = property => property.type === 'Property';
+ const getTagNameFromMemberExpression = ({property}) => `${property.parent.object.name}.${property.name}`;
return {
JSXSpreadAttribute(node) {
- const tagName = node.parent.name.name;
+ const jsxOpeningElement = node.parent.name;
+ const type = jsxOpeningElement.type;
+
+ let tagName;
+ if (type === 'JSXIdentifier') {
+ tagName = jsxOpeningElement.name;
+ } else if (type === 'JSXMemberExpression') {
+ tagName = getTagNameFromMemberExpression(jsxOpeningElement);
+ } else {
+ tagName = undefined;
+ }
+
const isHTMLTag = tagName && tagName[0] !== tagName[0].toUpperCase();
- const isCustomTag = tagName && tagName[0] === tagName[0].toUpperCase();
+ const isCustomTag = tagName && (tagName[0] === tagName[0].toUpperCase() || tagName.includes('.'));
if (
isHTMLTag &&
((ignoreHtmlTags && !isException(tagName, exceptions)) ||
diff --git a/tests/lib/rules/jsx-props-no-spreading.js b/tests/lib/rules/jsx-props-no-spreading.js
index fbb22504b3..016c00590f 100644
--- a/tests/lib/rules/jsx-props-no-spreading.js
+++ b/tests/lib/rules/jsx-props-no-spreading.js
@@ -89,6 +89,37 @@ ruleTester.run('jsx-props-no-spreading', rule, {
`,
options: [{explicitSpread: 'ignore'}]
+ }, {
+ code: [
+ 'const props = {};',
+ '',
+ ' ',
+ ' ',
+ ''
+ ].join('\n'),
+ options: [{exceptions: ['components.Group', 'Nav.Item']}]
+ }, {
+ code: [
+ 'const props = {};',
+ '',
+ ' ',
+ ' ',
+ ''
+ ].join('\n'),
+ options: [{custom: 'ignore'}]
+ }, {
+ code: [
+ 'const props = {};',
+ '',
+ ' ',
+ ' ',
+ ''
+ ].join('\n'),
+ options: [{
+ custom: 'enforce',
+ html: 'ignore',
+ exceptions: ['components.Group', 'Nav.Item']
+ }]
}],
invalid: [{
@@ -192,5 +223,15 @@ ruleTester.run('jsx-props-no-spreading', rule, {
`,
options: [{explicitSpread: 'ignore'}],
errors: [expectedError]
+ }, {
+ code: [
+ 'const props = {};',
+ '',
+ ' ',
+ ' ',
+ ''
+ ].join('\n'),
+ options: [{exceptions: ['components.DropdownIndicator', 'Nav.Item']}],
+ errors: [expectedError]
}]
});