@@ -47,6 +47,155 @@ const rel = new Map([
4747] ) ;
4848VALID_VALUES . set ( 'rel' , rel ) ;
4949
50+ /**
51+ * The set of all possible HTML elements. Used for skipping custom types
52+ * @type {Set<string> }
53+ */
54+ const HTML_ELEMENTS = new Set ( [
55+ 'html' ,
56+ 'base' ,
57+ 'head' ,
58+ 'link' ,
59+ 'meta' ,
60+ 'style' ,
61+ 'title' ,
62+ 'body' ,
63+ 'address' ,
64+ 'article' ,
65+ 'aside' ,
66+ 'footer' ,
67+ 'header' ,
68+ 'h1' ,
69+ 'h2' ,
70+ 'h3' ,
71+ 'h4' ,
72+ 'h5' ,
73+ 'h6' ,
74+ 'main' ,
75+ 'nav' ,
76+ 'section' ,
77+ 'blockquote' ,
78+ 'dd' ,
79+ 'div' ,
80+ 'dl' ,
81+ 'dt' ,
82+ 'figcaption' ,
83+ 'figure' ,
84+ 'hr' ,
85+ 'li' ,
86+ 'ol' ,
87+ 'p' ,
88+ 'pre' ,
89+ 'ul' ,
90+ 'a' ,
91+ 'abbr' ,
92+ 'b' ,
93+ 'bdi' ,
94+ 'bdo' ,
95+ 'br' ,
96+ 'cite' ,
97+ 'code' ,
98+ 'data' ,
99+ 'dfn' ,
100+ 'em' ,
101+ 'i' ,
102+ 'kbd' ,
103+ 'mark' ,
104+ 'q' ,
105+ 'rp' ,
106+ 'rt' ,
107+ 'ruby' ,
108+ 's' ,
109+ 'samp' ,
110+ 'small' ,
111+ 'span' ,
112+ 'strong' ,
113+ 'sub' ,
114+ 'sup' ,
115+ 'time' ,
116+ 'u' ,
117+ 'var' ,
118+ 'wbr' ,
119+ 'area' ,
120+ 'audio' ,
121+ 'img' ,
122+ 'map' ,
123+ 'track' ,
124+ 'video' ,
125+ 'embed' ,
126+ 'iframe' ,
127+ 'object' ,
128+ 'param' ,
129+ 'picture' ,
130+ 'portal' ,
131+ 'source' ,
132+ 'svg' ,
133+ 'math' ,
134+ 'canvas' ,
135+ 'noscript' ,
136+ 'script' ,
137+ 'del' ,
138+ 'ins' ,
139+ 'caption' ,
140+ 'col' ,
141+ 'colgroup' ,
142+ 'table' ,
143+ 'tbody' ,
144+ 'td' ,
145+ 'tfoot' ,
146+ 'th' ,
147+ 'thead' ,
148+ 'tr' ,
149+ 'button' ,
150+ 'datalist' ,
151+ 'fieldset' ,
152+ 'form' ,
153+ 'input' ,
154+ 'label' ,
155+ 'legend' ,
156+ 'meter' ,
157+ 'optgroup' ,
158+ 'option' ,
159+ 'output' ,
160+ 'progress' ,
161+ 'select' ,
162+ 'textarea' ,
163+ 'details' ,
164+ 'dialog' ,
165+ 'menu' ,
166+ 'summary' ,
167+ 'slot' ,
168+ 'template' ,
169+ 'acronym' ,
170+ 'applet' ,
171+ 'basefont' ,
172+ 'bgsound' ,
173+ 'big' ,
174+ 'blink' ,
175+ 'center' ,
176+ 'content' ,
177+ 'dir' ,
178+ 'font' ,
179+ 'frame' ,
180+ 'frameset' ,
181+ 'hgroup' ,
182+ 'image' ,
183+ 'keygen' ,
184+ 'marquee' ,
185+ 'menuitem' ,
186+ 'nobr' ,
187+ 'noembed' ,
188+ 'noframes' ,
189+ 'plaintext' ,
190+ 'rb' ,
191+ 'rtc' ,
192+ 'shadow' ,
193+ 'spacer' ,
194+ 'strike' ,
195+ 'tt' ,
196+ 'xmp'
197+ ] ) ;
198+
50199/**
51200* Map between attributes and set of tags that the attribute is valid on
52201* @type {Map<string, Set<string>> }
@@ -205,14 +354,14 @@ function checkPropValidValue(context, node, value, attribute) {
205354 return context . report ( {
206355 node : value ,
207356 message : `${ value . raw } is never a valid "${ attribute } " attribute value.`
208- } )
357+ } ) ;
209358 }
210359
211360 if ( ! validTagSet . has ( node . arguments [ 0 ] . value ) ) {
212361 return context . report ( {
213362 node : value ,
214363 message : `${ value . raw } is not a valid value of "${ attribute } " for a ${ node . arguments [ 0 ] . raw } element`
215- } )
364+ } ) ;
216365 }
217366}
218367
@@ -223,23 +372,20 @@ function checkPropValidValue(context, node, value, attribute) {
223372 * @param {string } attribute
224373 */
225374function checkCreateProps ( context , node , attribute ) {
226- if ( node . arguments [ 0 ] . type !== 'Literal' ) {
227- return ; // can only check literals
228- }
229-
230375 const propsArg = node . arguments [ 1 ] ;
231376
232- if ( ! propsArg || propsArg . type !== 'ObjectExpression'
233- ) {
377+ if ( ! propsArg || propsArg . type !== 'ObjectExpression' ) {
234378 return ; // can't check variables, computed, or shorthands
235379 }
236380
237381 for ( const prop of propsArg . properties ) {
238382 if ( prop . key . type !== 'Identifier' ) {
383+ // eslint-disable-next-line no-continue
239384 continue ; // cannot check computed keys
240385 }
241386
242387 if ( prop . key . name !== attribute ) {
388+ // eslint-disable-next-line no-continue
243389 continue ; // ignore not this attribute
244390 }
245391
@@ -254,6 +400,7 @@ function checkCreateProps(context, node, attribute) {
254400 message : `The "${ attribute } " attribute only has meaning on the tags: ${ tagNames } `
255401 } ) ;
256402
403+ // eslint-disable-next-line no-continue
257404 continue ;
258405 }
259406
@@ -263,10 +410,12 @@ function checkCreateProps(context, node, attribute) {
263410 message : `The "${ attribute } " attribute cannot be a method.`
264411 } ) ;
265412
413+ // eslint-disable-next-line no-continue
266414 continue ;
267415 }
268416
269417 if ( prop . shorthand || prop . computed ) {
418+ // eslint-disable-next-line no-continue
270419 continue ; // cannot check these
271420 }
272421
@@ -275,6 +424,7 @@ function checkCreateProps(context, node, attribute) {
275424 checkPropValidValue ( context , node , value , attribute ) ;
276425 }
277426
427+ // eslint-disable-next-line no-continue
278428 continue ;
279429 }
280430
@@ -309,6 +459,11 @@ module.exports = {
309459 return ;
310460 }
311461
462+ // ignore non-HTML elements
463+ if ( ! HTML_ELEMENTS . has ( node . parent . name . name ) ) {
464+ return ;
465+ }
466+
312467 checkAttribute ( context , node ) ;
313468 } ,
314469
@@ -317,6 +472,17 @@ module.exports = {
317472 return ;
318473 }
319474
475+ const elemNameArg = node . arguments [ 0 ] ;
476+
477+ if ( ! elemNameArg || elemNameArg . type !== 'Literal' ) {
478+ return ; // can only check literals
479+ }
480+
481+ // ignore non-HTML elements
482+ if ( ! HTML_ELEMENTS . has ( elemNameArg . value ) ) {
483+ return ;
484+ }
485+
320486 const attributes = new Set ( context . options [ 0 ] || DEFAULT_ATTRIBUTES ) ;
321487
322488 for ( const attribute of attributes ) {
0 commit comments