Socket
Socket
Sign inDemoInstall

eslint-plugin-react

Package Overview
Dependencies
Maintainers
2
Versions
210
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-react - npm Package Compare versions

Comparing version 7.31.6 to 7.31.7

153

lib/rules/no-unknown-property.js

@@ -33,2 +33,4 @@ /**

crossOrigin: ['script', 'img', 'video', 'audio', 'link', 'image'],
// https://html.spec.whatwg.org/multipage/links.html#downloading-resources
download: ['a', 'area'],
fill: [ // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill

@@ -59,5 +61,9 @@ // Fill color

],
focusable: ['svg'],
imageSizes: ['link'],
imageSrcSet: ['link'],
property: ['meta'],
viewBox: ['svg'],
as: ['link'],
valign: ['tr', 'td', 'th', 'thead', 'tbody', 'tfoot', 'colgroup', 'col'], // deprecated, but known
// Media events allowed only on audio and video tags, see https://github.com/facebook/react/blob/256aefbea1449869620fb26f6ec695536ab453f5/CHANGELOG.md#notable-enhancements

@@ -71,4 +77,4 @@ onAbort: ['audio', 'video'],

onEnded: ['audio', 'video'],
onError: ['audio', 'video', 'img', 'link', 'source', 'script'],
onLoad: ['script', 'img', 'link'],
onError: ['audio', 'video', 'img', 'link', 'source', 'script', 'picture', 'iframe'],
onLoad: ['script', 'img', 'link', 'picture', 'iframe'],
onLoadedData: ['audio', 'video'],

@@ -89,8 +95,5 @@ onLoadedMetadata: ['audio', 'video'],

onWaiting: ['audio', 'video'],
scrolling: ['iframe'],
playsInline: ['video'],
// Video related attributes
autoPictureInPicture: ['video'],
controls: ['audio', 'video'],
controlList: ['video'],
controlsList: ['audio', 'video'],
disablePictureInPicture: ['video'],

@@ -100,4 +103,6 @@ disableRemotePlayback: ['audio', 'video'],

muted: ['audio', 'video'],
playsInline: ['video'],
poster: ['video'],
preload: ['audio', 'video'],
scrolling: ['iframe'],
};

@@ -200,6 +205,6 @@

'headers', 'height', 'high', 'href', 'icon', 'importance', 'integrity', 'kind', 'label',
'language', 'loading', 'list', 'loop', 'low', 'max', 'media', 'method', 'min', 'multiple', 'muted',
'language', 'loading', 'list', 'loop', 'low', 'manifest', 'max', 'media', 'method', 'min', 'multiple', 'muted',
'name', 'open', 'optimum', 'pattern', 'ping', 'placeholder', 'poster', 'preload', 'profile',
'rel', 'required', 'reversed', 'role', 'rows', 'sandbox', 'scope', 'selected', 'shape', 'size', 'sizes',
'span', 'src', 'start', 'step', 'target', 'type', 'value', 'width', 'wrap',
'rel', 'required', 'reversed', 'role', 'rows', 'sandbox', 'scope', 'seamless', 'selected', 'shape', 'size', 'sizes',
'span', 'src', 'start', 'step', 'summary', 'target', 'type', 'value', 'width', 'wmode', 'wrap',
// SVG attributes

@@ -221,2 +226,4 @@ // See https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute

'ref', 'key', 'children',
// Non-standard
'results', 'security',
// Video specific

@@ -234,5 +241,5 @@ 'controls',

// To be considered if these should be added also to ATTRIBUTE_TAGS_MAP
'acceptCharset', 'autoComplete', 'autoPlay', 'cellPadding', 'cellSpacing', 'classID', 'codeBase',
'acceptCharset', 'autoComplete', 'autoPlay', 'border', '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',

@@ -279,3 +286,5 @@ 'onBlur', 'onChange', 'onClick', 'onContextMenu', 'onCopy', 'onCompositionEnd', 'onCompositionStart',

// React specific attributes https://reactjs.org/docs/dom-elements.html#differences-in-attributes
'className', 'dangerouslySetInnerHTML', 'defaultValue', 'defaultChecked', 'htmlFor', 'onChange',
'className', 'dangerouslySetInnerHTML', 'defaultValue', 'defaultChecked', 'htmlFor',
// Events' capture events
'onBeforeInput', 'onChange',
'onInvalid', 'onReset', 'onTouchCancel', 'onTouchEnd', 'onTouchMove', 'onTouchStart', 'suppressContentEditableWarning', 'suppressHydrationWarning',

@@ -285,8 +294,20 @@ 'onAbort', 'onCanPlay', 'onCanPlayThrough', 'onDurationChange', 'onEmptied', 'onEncrypted', 'onEnded',

'onSeeked', 'onSeeking', 'onStalled', 'onSuspend', 'onTimeUpdate', 'onVolumeChange', 'onWaiting',
'onMouseMoveCapture',
// Video specific,
'autoPictureInPicture', 'controlList', 'disablePictureInPicture', 'disableRemotePlayback',
'onCopyCapture', 'onCutCapture', 'onPasteCapture', 'onCompositionEndCapture', 'onCompositionStartCapture', 'onCompositionUpdateCapture',
'onFocusCapture', 'onBlurCapture', 'onChangeCapture', 'onBeforeInputCapture', 'onInputCapture', 'onResetCapture', 'onSubmitCapture',
'onInvalidCapture', 'onLoadCapture', 'onErrorCapture', 'onKeyDownCapture', 'onKeyPressCapture', 'onKeyUpCapture',
'onAbortCapture', 'onCanPlayCapture', 'onCanPlayThroughCapture', 'onDurationChangeCapture', 'onEmptiedCapture', 'onEncryptedCapture',
'onEndedCapture', 'onLoadedDataCapture', 'onLoadedMetadataCapture', 'onLoadStartCapture', 'onPauseCapture', 'onPlayCapture',
'onPlayingCapture', 'onProgressCapture', 'onRateChangeCapture', 'onSeekedCapture', 'onSeekingCapture', 'onStalledCapture', 'onSuspendCapture',
'onTimeUpdateCapture', 'onVolumeChangeCapture', 'onWaitingCapture', 'onSelectCapture', 'onTouchCancelCapture', 'onTouchEndCapture',
'onTouchMoveCapture', 'onTouchStartCapture', 'onScrollCapture', 'onWheelCapture', 'onAnimationEndCapture', 'onAnimationIteration',
'onAnimationStartCapture', 'onTransitionEndCapture',
'onAuxClick', 'onAuxClickCapture', 'onClickCapture', 'onContextMenuCapture', 'onDoubleClickCapture',
'onDragCapture', 'onDragEndCapture', 'onDragEnterCapture', 'onDragExitCapture', 'onDragLeaveCapture',
'onDragOverCapture', 'onDragStartCapture', 'onDropCapture', 'onMouseDown', 'onMouseDownCapture',
'onMouseMoveCapture', 'onMouseOutCapture', 'onMouseOverCapture', 'onMouseUpCapture',
// Video specific
'autoPictureInPicture', 'controlsList', 'disablePictureInPicture', 'disableRemotePlayback',
];
const DOM_PROPERTIES_IGNORE_CASE = ['charset', 'allowfullscreen'];
const DOM_PROPERTIES_IGNORE_CASE = ['charset', 'allowFullScreen', 'webkitAllowFullScreen', 'mozAllowFullScreen'];

@@ -312,11 +333,22 @@ const ARIA_PROPERTIES = [

'onGotPointerCapture',
'onGotPointerCaptureCapture',
'onLostPointerCapture',
'onLostPointerCapture',
'onLostPointerCaptureCapture',
'onPointerCancel',
'onPointerCancelCapture',
'onPointerDown',
'onPointerDownCapture',
'onPointerEnter',
'onPointerEnterCapture',
'onPointerLeave',
'onPointerLeaveCapture',
'onPointerMove',
'onPointerMoveCapture',
'onPointerOut',
'onPointerOutCapture',
'onPointerOver',
'onPointerOverCapture',
'onPointerUp',
'onPointerUpCapture',
];

@@ -370,4 +402,5 @@

* Checks if an attribute name is a valid `data-*` attribute:
* if the name starts with "data-" and has some lowcase (a to z) words that can contain numbers, separated but hyphens (-)
* (which is also called "kebab case" or "dash case"), then the attribute is valid data attribute.
* if the name starts with "data-" and has alphanumeric words (browsers require lowercase, but React and TS lowercase them),
* not start with any casing of "xml", and separated by hyphens (-) (which is also called "kebab case" or "dash case"),
* then the attribute is a valid data attribute.
*

@@ -378,4 +411,3 @@ * @param {String} name - Attribute name to be tested

function isValidDataAttribute(name) {
const dataAttrConvention = /^data(-[a-z1-9]*)*$/;
return !!dataAttrConvention.test(name);
return /^data(-[^:]*)*$/.test(name) && !/^data-xml/i.test(name);
}

@@ -409,3 +441,3 @@

function isCaseIgnoredAttribute(name) {
return DOM_PROPERTIES_IGNORE_CASE.some((element) => element === name.toLowerCase());
return DOM_PROPERTIES_IGNORE_CASE.some((element) => element.toLowerCase() === name.toLowerCase());
}

@@ -519,56 +551,59 @@

// Let's dive deeper into tags that are HTML/DOM elements (`<button>`), and not React components (`<Button />`)
if (isValidHTMLTagInJSX(node)) {
// Some attributes are allowed on some tags only
const allowedTags = has(ATTRIBUTE_TAGS_MAP, name) ? ATTRIBUTE_TAGS_MAP[name] : null;
if (tagName && allowedTags) {
// Scenario 1A: Allowed attribute found where not supposed to, report it
if (allowedTags.indexOf(tagName) === -1) {
report(context, messages.invalidPropOnTag, 'invalidPropOnTag', {
node,
data: {
name,
tagName,
allowedTags: allowedTags.join(', '),
},
});
}
// Scenario 1B: There are allowed attributes on allowed tags, no need to report it
return;
}
if (tagName === 'fbt') { return; } // fbt nodes are bonkers, let's not go there
// Let's see if the attribute is a close version to some standard property name
const standardName = getStandardName(name, context);
if (!isValidHTMLTagInJSX(node)) { return; }
const hasStandardNameButIsNotUsed = standardName && standardName !== name;
const usesStandardName = standardName && standardName === name;
// Let's dive deeper into tags that are HTML/DOM elements (`<button>`), and not React components (`<Button />`)
if (usesStandardName) {
// Scenario 2A: The attribute name is the standard name, no need to report it
return;
}
if (hasStandardNameButIsNotUsed) {
// Scenario 2B: The name of the attribute is close to a standard one, report it with the standard name
report(context, messages.unknownPropWithStandardName, 'unknownPropWithStandardName', {
// Some attributes are allowed on some tags only
const allowedTags = has(ATTRIBUTE_TAGS_MAP, name) ? ATTRIBUTE_TAGS_MAP[name] : null;
if (tagName && allowedTags) {
// Scenario 1A: Allowed attribute found where not supposed to, report it
if (allowedTags.indexOf(tagName) === -1) {
report(context, messages.invalidPropOnTag, 'invalidPropOnTag', {
node,
data: {
name,
standardName,
tagName,
allowedTags: allowedTags.join(', '),
},
fix(fixer) {
return fixer.replaceText(node.name, standardName);
},
});
return;
}
// Scenario 1B: There are allowed attributes on allowed tags, no need to report it
return;
}
// Scenario 3: We have an attribute that is unknown, report it
report(context, messages.unknownProp, 'unknownProp', {
// Let's see if the attribute is a close version to some standard property name
const standardName = getStandardName(name, context);
const hasStandardNameButIsNotUsed = standardName && standardName !== name;
const usesStandardName = standardName && standardName === name;
if (usesStandardName) {
// Scenario 2A: The attribute name is the standard name, no need to report it
return;
}
if (hasStandardNameButIsNotUsed) {
// Scenario 2B: The name of the attribute is close to a standard one, report it with the standard name
report(context, messages.unknownPropWithStandardName, 'unknownPropWithStandardName', {
node,
data: {
name,
standardName,
},
fix(fixer) {
return fixer.replaceText(node.name, standardName);
},
});
return;
}
// Scenario 3: We have an attribute that is unknown, report it
report(context, messages.unknownProp, 'unknownProp', {
node,
data: {
name,
},
});
},

@@ -575,0 +610,0 @@ };

{
"name": "eslint-plugin-react",
"version": "7.31.6",
"version": "7.31.7",
"author": "Yannick Croissant <yannick.croissant+npm@gmail.com>",

@@ -44,5 +44,5 @@ "description": "React specific linting rules for ESLint",

"devDependencies": {
"@babel/core": "^7.18.13",
"@babel/core": "^7.19.0",
"@babel/eslint-parser": "^7.18.9",
"@babel/plugin-syntax-decorators": "^7.18.6",
"@babel/plugin-syntax-decorators": "^7.19.0",
"@babel/plugin-syntax-do-expressions": "^7.18.6",

@@ -49,0 +49,0 @@ "@babel/plugin-syntax-function-bind": "^7.18.6",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc