diff --git a/CHANGELOG.md b/CHANGELOG.md
index c7ace5dd6a..786484435b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
* [`no-unsafe`]: report on the method instead of the entire component (@ljharb)
* [`no-deprecated`]: report on the destructured property instead of the entire variable declarator (@ljharb)
* [`no-deprecated`]: report on the imported specifier instead of the entire import statement (@ljharb)
+* [`no-invalid-html-attribute`]: report more granularly (@ljharb)
[#3614]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3614
diff --git a/lib/rules/no-invalid-html-attribute.js b/lib/rules/no-invalid-html-attribute.js
index 997afc2c81..77f6d4de6e 100644
--- a/lib/rules/no-invalid-html-attribute.js
+++ b/lib/rules/no-invalid-html-attribute.js
@@ -389,7 +389,7 @@ function checkAttribute(context, node) {
(tagName) => `"<${tagName}>"`
).join(', ');
report(context, messages.onlyMeaningfulFor, 'onlyMeaningfulFor', {
- node,
+ node: node.name,
data: {
attributeName: attribute,
tagNames,
@@ -408,7 +408,7 @@ function checkAttribute(context, node) {
if (!node.value) {
report(context, messages.emptyIsMeaningless, 'emptyIsMeaningless', {
- node,
+ node: node.name,
data: { attributeName: attribute },
suggest: [
Object.assign(
@@ -434,7 +434,7 @@ function checkAttribute(context, node) {
if (node.value.expression.type === 'ObjectExpression') {
report(context, messages.onlyStrings, 'onlyStrings', {
- node,
+ node: node.value,
data: { attributeName: attribute },
suggest: [
Object.assign(
@@ -445,7 +445,7 @@ function checkAttribute(context, node) {
});
} else if (node.value.expression.type === 'Identifier' && node.value.expression.name === 'undefined') {
report(context, messages.onlyStrings, 'onlyStrings', {
- node,
+ node: node.value,
data: { attributeName: attribute },
suggest: [
Object.assign(
@@ -531,7 +531,7 @@ function checkCreateProps(context, node, attribute) {
).join(', ');
report(context, messages.onlyMeaningfulFor, 'onlyMeaningfulFor', {
- node,
+ node: prop.key,
data: {
attributeName: attribute,
tagNames,
diff --git a/tests/lib/rules/no-invalid-html-attribute.js b/tests/lib/rules/no-invalid-html-attribute.js
index 03e000bd66..3c3aace4a9 100644
--- a/tests/lib/rules/no-invalid-html-attribute.js
+++ b/tests/lib/rules/no-invalid-html-attribute.js
@@ -421,7 +421,7 @@ ruleTester.run('no-invalid-html-attribute', rule, {
output: '',
},
],
- type: 'JSXAttribute',
+ type: 'JSXIdentifier',
},
],
},
@@ -440,7 +440,8 @@ ruleTester.run('no-invalid-html-attribute', rule, {
// output: 'React.createElement("html", { })',
// },
// ],
- type: 'CallExpression',
+ column: 31,
+ type: 'Identifier',
},
],
},
@@ -456,7 +457,7 @@ ruleTester.run('no-invalid-html-attribute', rule, {
output: '',
},
],
- type: 'JSXAttribute',
+ type: 'JSXIdentifier',
},
],
},
@@ -504,7 +505,7 @@ ruleTester.run('no-invalid-html-attribute', rule, {
output: '',
},
],
- type: 'JSXAttribute',
+ type: 'JSXIdentifier',
},
],
},
@@ -568,7 +569,7 @@ ruleTester.run('no-invalid-html-attribute', rule, {
output: '',
},
],
- type: 'JSXAttribute',
+ type: 'JSXExpressionContainer',
},
],
},
@@ -584,7 +585,7 @@ ruleTester.run('no-invalid-html-attribute', rule, {
output: '',
},
],
- type: 'JSXAttribute',
+ type: 'JSXExpressionContainer',
},
],
},