Repository: jsx-eslint/eslint-plugin-react
Pull request #3407 (2022-09-05 13:06:37)

[Fix] `no-unknown-property`: allow `imageSrcSet` and `imageSizes` attributes on `<link>`
This pull requests allows `imageSrcSet` and `imageSizes` on the `<link />` element, as these properties are actually valid and allowed:

* MDN Docs: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#attr-imagesrcset
* React typings: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L2276

This is a fix for #3401


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1a333bf8..595fb3f2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,7 +13,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 * [`no-unknown-property`]: add more capture event properties ([#3402][] @sjarva)
 * [`no-unknown-property`]: Add more one word properties found in DefinitelyTyped's react/index.d.ts ([#3402][] @sjarva)
 * [`no-unknown-property`]: Mark onLoad/onError as supported on iframes ([#3398][] @maiis, [#3406][] @akx)
+* [`no-unknown-property`]: allow `imageSrcSet` and `imageSizes` attributes on `<link>` ([#3407][] @terrymun)
 
+[#3407]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3407
 [#3406]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3406
 [#3402]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3402
 [#3398]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3398
diff --git a/lib/rules/no-unknown-property.js b/lib/rules/no-unknown-property.js
index 6af662d1..64f0f874 100644
--- a/lib/rules/no-unknown-property.js
+++ b/lib/rules/no-unknown-property.js
@@ -57,6 +57,8 @@ const ATTRIBUTE_TAGS_MAP = {
     'animateTransform',
     'set',
   ],
+  imageSizes: ['link'],
+  imageSrcSet: ['link'],
   property: ['meta'],
   viewBox: ['svg'],
   as: ['link'],
@@ -230,7 +232,7 @@ const DOM_PROPERTY_NAMES_TWO_WORDS = [
   // To be considered if these should be added also to ATTRIBUTE_TAGS_MAP
   'acceptCharset', 'autoComplete', 'autoPlay', 'cellPadding', 'cellSpacing', 'classID', 'codeBase',
   'colSpan', 'contextMenu', 'dateTime', 'encType', 'formAction', 'formEncType', 'formMethod', 'formNoValidate', 'formTarget',
-  'frameBorder', 'hrefLang', 'httpEquiv', 'isMap', 'keyParams', 'keyType', 'marginHeight', 'marginWidth',
+  'frameBorder', 'hrefLang', 'httpEquiv', 'imageSizes', 'imageSrcSet', 'isMap', 'keyParams', 'keyType', 'marginHeight', 'marginWidth',
   'maxLength', 'mediaGroup', 'minLength', 'noValidate', 'onAnimationEnd', 'onAnimationIteration', 'onAnimationStart',
   'onBlur', 'onChange', 'onClick', 'onContextMenu', 'onCopy', 'onCompositionEnd', 'onCompositionStart',
   'onCompositionUpdate', 'onCut', 'onDoubleClick', 'onDrag', 'onDragEnd', 'onDragEnter', 'onDragExit', 'onDragLeave',


Test patch:
diff --git a/tests/lib/rules/no-unknown-property.js b/tests/lib/rules/no-unknown-property.js
index d2f39932..2cd111c1 100644
--- a/tests/lib/rules/no-unknown-property.js
+++ b/tests/lib/rules/no-unknown-property.js
@@ -65,6 +65,7 @@ ruleTester.run('no-unknown-property', rule, {
     { code: '<script onLoad={bar} onError={foo} />' },
     { code: '<source onError={foo} />' },
     { code: '<link onLoad={bar} onError={foo} />' },
+    { code: '<link rel="preload" as="image" href="someHref" imageSrcSet="someImageSrcSet" imageSizes="someImageSizes" />' },
     { code: '<div allowFullScreen webkitAllowFullScreen mozAllowFullScreen />' },
     {
       code: '<div allowTransparency="true" />',
@@ -483,5 +484,31 @@ ruleTester.run('no-unknown-property', rule, {
         },
       ],
     },
+    {
+      code: '<div imageSrcSet="someImageSrcSet" />',
+      errors: [
+        {
+          messageId: 'invalidPropOnTag',
+          data: {
+            name: 'imageSrcSet',
+            tagName: 'div',
+            allowedTags: 'link',
+          },
+        },
+      ],
+    },
+    {
+      code: '<div imageSizes="someImageSizes" />',
+      errors: [
+        {
+          messageId: 'invalidPropOnTag',
+          data: {
+            name: 'imageSizes',
+            tagName: 'div',
+            allowedTags: 'link',
+          },
+        },
+      ],
+    },
   ]),
 });