diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3d0de88e60..153e4e21af 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
* [`jsx-handler-names`]: false positive when handler name begins with number ([#1689][] @jsphstls)
* [`prop-types`]: Detect JSX returned by sequential expression ([#2801][] @mikol)
* [`jsx-props-no-multi-spaces`]: "Expected no line gap between" false positive ([#2792][] @karolina-benitez)
+* [`no-unknown-property`]: check attributes with any input case ([#2790][] @julienw)
### Changed
* [Tests] [`jsx-one-expression-per-line`]: add passing tests ([#2799][] @TaLeaMonet)
@@ -30,6 +31,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
[#2796]: https://github.com/yannickcr/eslint-plugin-react/pull/2796
[#2792]: https://github.com/yannickcr/eslint-plugin-react/pull/2792
[#2791]: https://github.com/yannickcr/eslint-plugin-react/pull/2791
+[#2790]: https://github.com/yannickcr/eslint-plugin-react/pull/2790
[#2789]: https://github.com/yannickcr/eslint-plugin-react/pull/2789
[#2782]: https://github.com/yannickcr/eslint-plugin-react/pull/2782
[#2780]: https://github.com/yannickcr/eslint-plugin-react/pull/2780
diff --git a/lib/rules/no-unknown-property.js b/lib/rules/no-unknown-property.js
index 18634951c3..352c8e24e1 100644
--- a/lib/rules/no-unknown-property.js
+++ b/lib/rules/no-unknown-property.js
@@ -147,7 +147,8 @@ function getDOMPropertyNames(context) {
// ------------------------------------------------------------------------------
/**
- * Checks if a node matches the JSX tag convention.
+ * Checks if a node matches the JSX tag convention. This also checks if a node
+ * is extended as a webcomponent using the attribute "is".
* @param {Object} node - JSX element being tested.
* @returns {boolean} Whether or not the node name match the JSX tag convention.
*/
@@ -194,7 +195,7 @@ function tagNameHasDot(node) {
* Get the standard name of the attribute.
* @param {String} name - Name of the attribute.
* @param {String} context - eslint context
- * @returns {String} The standard name of the attribute.
+ * @returns {String | undefined} The standard name of the attribute, or undefined if no standard name was found.
*/
function getStandardName(name, context) {
if (DOM_ATTRIBUTE_NAMES[name]) {
@@ -203,13 +204,9 @@ function getStandardName(name, context) {
if (SVGDOM_ATTRIBUTE_NAMES[name]) {
return SVGDOM_ATTRIBUTE_NAMES[name];
}
- let i = -1;
const names = getDOMPropertyNames(context);
- const found = names.some((element, index) => {
- i = index;
- return element.toLowerCase() === name;
- });
- return found ? names[i] : null;
+ // Let's find a possible attribute match with a case-insensitive search.
+ return names.find((element) => element.toLowerCase() === name.toLowerCase());
}
// ------------------------------------------------------------------------------
@@ -259,6 +256,8 @@ module.exports = {
}
const tagName = getTagName(node);
+
+ // 1. Some attributes are allowed on some tags only.
const allowedTags = ATTRIBUTE_TAGS_MAP[name];
if (tagName && allowedTags && /[^A-Z]/.test(tagName.charAt(0)) && allowedTags.indexOf(tagName) === -1) {
context.report({
@@ -272,8 +271,12 @@ module.exports = {
});
}
+ // 2. Otherwise, we'll try to find if the attribute is a close version
+ // of what we should normally have with React. If yes, we'll report an
+ // error. We don't want to report if the input attribute name is the
+ // standard name though!
const standardName = getStandardName(name, context);
- if (!isTagName(node) || !standardName) {
+ if (!isTagName(node) || !standardName || standardName === name) {
return;
}
context.report({
diff --git a/tests/lib/rules/no-unknown-property.js b/tests/lib/rules/no-unknown-property.js
index 21197a4e06..5d9effecfa 100644
--- a/tests/lib/rules/no-unknown-property.js
+++ b/tests/lib/rules/no-unknown-property.js
@@ -37,6 +37,7 @@ ruleTester.run('no-unknown-property', rule, {
{code: '