Skip to content

Commit 9a77a1b

Browse files
sjarvaljharb
authored andcommitted
[Fix] no-unknown-property: add more audio/video attributes
1 parent 1d373c9 commit 9a77a1b

File tree

3 files changed

+54
-1
lines changed

3 files changed

+54
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
88
### Fixed
99
* [`no-unknown-property`]: `onError` and `onLoad` both work on `img` and `script` ([#3388][] @ljharb)
1010
* [`no-unknown-property`]: data-* attributes can have numbers ([#3390][] @sjarva)
11+
* [`no-unknown-property`]: add more audio/video attributes ([#3390][] @sjarva)
1112

1213
[#3390]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3390
1314
[#3388]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3388

lib/rules/no-unknown-property.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,16 @@ const ATTRIBUTE_TAGS_MAP = {
8282
onWaiting: ['audio', 'video'],
8383
scrolling: ['iframe'],
8484
playsInline: ['video'],
85+
// Video related attributes
86+
autoPictureInPicture: ['video'],
87+
controls: ['audio', 'video'],
88+
controlList: ['video'],
89+
disablePictureInPicture: ['video'],
90+
disableRemotePlayback: ['audio', 'video'],
91+
loop: ['audio', 'video'],
92+
muted: ['audio', 'video'],
93+
poster: ['video'],
94+
preload: ['audio', 'video'],
8595
};
8696

8797
const SVGDOM_ATTRIBUTE_NAMES = {
@@ -199,6 +209,8 @@ const DOM_PROPERTY_NAMES_ONE_WORD = [
199209
'property',
200210
// React specific attributes
201211
'ref', 'key', 'children',
212+
// Video specific
213+
'controls',
202214
];
203215

204216
const DOM_PROPERTY_NAMES_TWO_WORDS = [
@@ -258,6 +270,8 @@ const DOM_PROPERTY_NAMES_TWO_WORDS = [
258270
'onAbort', 'onCanPlay', 'onCanPlayThrough', 'onDurationChange', 'onEmptied', 'onEncrypted', 'onEnded',
259271
'onLoadedData', 'onLoadedMetadata', 'onLoadStart', 'onPause', 'onPlay', 'onPlaying', 'onProgress', 'onRateChange',
260272
'onSeeked', 'onSeeking', 'onStalled', 'onSuspend', 'onTimeUpdate', 'onVolumeChange', 'onWaiting',
273+
// Video specific,
274+
'autoPictureInPicture', 'controlList', 'disablePictureInPicture', 'disableRemotePlayback',
261275
];
262276

263277
const DOM_PROPERTIES_IGNORE_CASE = ['charset'];

tests/lib/rules/no-unknown-property.js

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ ruleTester.run('no-unknown-property', rule, {
102102
{ code: '<details onToggle={this.onToggle}>Some details</details>' },
103103
{ code: '<path fill="pink" d="M 10,30 A 20,20 0,0,1 50,30 A 20,20 0,0,1 90,30 Q 90,60 50,90 Q 10,60 10,30 z"></path>' },
104104
{ code: '<link as="audio">Audio content</link>' },
105-
{ code: '<audio onAbort={this.abort} onDurationChange={this.durationChange} onEmptied={this.emptied} onEnded={this.end} onError={this.error}></audio>' },
105+
{ code: '<video controls={this.controls} loop={true} muted={false} src={this.videoSrc} playsInline={true}></video>' },
106+
{ code: '<audio controls={this.controls} crossOrigin="anonymous" disableRemotePlayback loop muted preload="none" src="something" onAbort={this.abort} onDurationChange={this.durationChange} onEmptied={this.emptied} onEnded={this.end} onError={this.error}></audio>' },
106107
]),
107108
invalid: parsers.all([
108109
{
@@ -391,5 +392,42 @@ ruleTester.run('no-unknown-property', rule, {
391392
},
392393
],
393394
},
395+
{
396+
code: '<div controls={this.controls} loop={true} muted={false} src={this.videoSrc} playsInline={true}></div>',
397+
errors: [
398+
{
399+
messageId: 'invalidPropOnTag',
400+
data: {
401+
name: 'controls',
402+
tagName: 'div',
403+
allowedTags: 'audio, video',
404+
},
405+
},
406+
{
407+
messageId: 'invalidPropOnTag',
408+
data: {
409+
name: 'loop',
410+
tagName: 'div',
411+
allowedTags: 'audio, video',
412+
},
413+
},
414+
{
415+
messageId: 'invalidPropOnTag',
416+
data: {
417+
name: 'muted',
418+
tagName: 'div',
419+
allowedTags: 'audio, video',
420+
},
421+
},
422+
{
423+
messageId: 'invalidPropOnTag',
424+
data: {
425+
name: 'playsInline',
426+
tagName: 'div',
427+
allowedTags: 'video',
428+
},
429+
},
430+
],
431+
},
394432
]),
395433
});

0 commit comments

Comments
 (0)