@@ -29,62 +29,176 @@ const ruleTester = new RuleTester({parserOptions});
2929ruleTester . run ( 'no-invalid-html-attribute' , rule , {
3030 valid : [
3131 { code : '<a rel="alternate"></a>' } ,
32+ { code : 'React.createElement("a", { rel: "alternate" })' } ,
33+ { code : 'React.createElement("a", { rel: ["alternate"] })' } ,
3234 { code : '<a rel="author"></a>' } ,
35+ { code : 'React.createElement("a", { rel: "author" })' } ,
36+ { code : 'React.createElement("a", { rel: ["author"] })' } ,
3337 { code : '<a rel="bookmark"></a>' } ,
38+ { code : 'React.createElement("a", { rel: "bookmark" })' } ,
39+ { code : 'React.createElement("a", { rel: ["bookmark"] })' } ,
3440 { code : '<a rel="external"></a>' } ,
41+ { code : 'React.createElement("a", { rel: "external" })' } ,
42+ { code : 'React.createElement("a", { rel: ["external"] })' } ,
3543 { code : '<a rel="help"></a>' } ,
44+ { code : 'React.createElement("a", { rel: "help" })' } ,
45+ { code : 'React.createElement("a", { rel: ["help"] })' } ,
3646 { code : '<a rel="license"></a>' } ,
47+ { code : 'React.createElement("a", { rel: "license" })' } ,
48+ { code : 'React.createElement("a", { rel: ["license"] })' } ,
3749 { code : '<a rel="next"></a>' } ,
50+ { code : 'React.createElement("a", { rel: "next" })' } ,
51+ { code : 'React.createElement("a", { rel: ["next"] })' } ,
3852 { code : '<a rel="nofollow"></a>' } ,
53+ { code : 'React.createElement("a", { rel: "nofollow" })' } ,
54+ { code : 'React.createElement("a", { rel: ["nofollow"] })' } ,
3955 { code : '<a rel="noopener"></a>' } ,
56+ { code : 'React.createElement("a", { rel: "noopener" })' } ,
57+ { code : 'React.createElement("a", { rel: ["noopener"] })' } ,
4058 { code : '<a rel="noreferrer"></a>' } ,
59+ { code : 'React.createElement("a", { rel: "noreferrer" })' } ,
60+ { code : 'React.createElement("a", { rel: ["noreferrer"] })' } ,
4161 { code : '<a rel="opener"></a>' } ,
62+ { code : 'React.createElement("a", { rel: "opener" })' } ,
63+ { code : 'React.createElement("a", { rel: ["opener"] })' } ,
4264 { code : '<a rel="prev"></a>' } ,
65+ { code : 'React.createElement("a", { rel: "prev" })' } ,
66+ { code : 'React.createElement("a", { rel: ["prev"] })' } ,
4367 { code : '<a rel="search"></a>' } ,
68+ { code : 'React.createElement("a", { rel: "search" })' } ,
69+ { code : 'React.createElement("a", { rel: ["search"] })' } ,
4470 { code : '<a rel="tag"></a>' } ,
71+ { code : 'React.createElement("a", { rel: "tag" })' } ,
72+ { code : 'React.createElement("a", { rel: ["tag"] })' } ,
4573 { code : '<area rel="alternate"></area>' } ,
74+ { code : 'React.createElement("area", { rel: "alternate" })' } ,
75+ { code : 'React.createElement("area", { rel: ["alternate"] })' } ,
4676 { code : '<area rel="author"></area>' } ,
77+ { code : 'React.createElement("area", { rel: "author" })' } ,
78+ { code : 'React.createElement("area", { rel: ["author"] })' } ,
4779 { code : '<area rel="bookmark"></area>' } ,
80+ { code : 'React.createElement("area", { rel: "bookmark" })' } ,
81+ { code : 'React.createElement("area", { rel: ["bookmark"] })' } ,
4882 { code : '<area rel="external"></area>' } ,
83+ { code : 'React.createElement("area", { rel: "external" })' } ,
84+ { code : 'React.createElement("area", { rel: ["external"] })' } ,
4985 { code : '<area rel="help"></area>' } ,
86+ { code : 'React.createElement("area", { rel: "help" })' } ,
87+ { code : 'React.createElement("area", { rel: ["help"] })' } ,
5088 { code : '<area rel="license"></area>' } ,
89+ { code : 'React.createElement("area", { rel: "license" })' } ,
90+ { code : 'React.createElement("area", { rel: ["license"] })' } ,
5191 { code : '<area rel="next"></area>' } ,
92+ { code : 'React.createElement("area", { rel: "next" })' } ,
93+ { code : 'React.createElement("area", { rel: ["next"] })' } ,
5294 { code : '<area rel="nofollow"></area>' } ,
95+ { code : 'React.createElement("area", { rel: "nofollow" })' } ,
96+ { code : 'React.createElement("area", { rel: ["nofollow"] })' } ,
5397 { code : '<area rel="noopener"></area>' } ,
98+ { code : 'React.createElement("area", { rel: "noopener" })' } ,
99+ { code : 'React.createElement("area", { rel: ["noopener"] })' } ,
54100 { code : '<area rel="noreferrer"></area>' } ,
101+ { code : 'React.createElement("area", { rel: "noreferrer" })' } ,
102+ { code : 'React.createElement("area", { rel: ["noreferrer"] })' } ,
55103 { code : '<area rel="opener"></area>' } ,
104+ { code : 'React.createElement("area", { rel: "opener" })' } ,
105+ { code : 'React.createElement("area", { rel: ["opener"] })' } ,
56106 { code : '<area rel="prev"></area>' } ,
107+ { code : 'React.createElement("area", { rel: "prev" })' } ,
108+ { code : 'React.createElement("area", { rel: ["prev"] })' } ,
57109 { code : '<area rel="search"></area>' } ,
110+ { code : 'React.createElement("area", { rel: "search" })' } ,
111+ { code : 'React.createElement("area", { rel: ["search"] })' } ,
58112 { code : '<area rel="tag"></area>' } ,
113+ { code : 'React.createElement("area", { rel: "tag" })' } ,
114+ { code : 'React.createElement("area", { rel: ["tag"] })' } ,
59115 { code : '<link rel="alternate"></link>' } ,
116+ { code : 'React.createElement("link", { rel: "alternate" })' } ,
117+ { code : 'React.createElement("link", { rel: ["alternate"] })' } ,
60118 { code : '<link rel="author"></link>' } ,
119+ { code : 'React.createElement("link", { rel: "author" })' } ,
120+ { code : 'React.createElement("link", { rel: ["author"] })' } ,
61121 { code : '<link rel="canonical"></link>' } ,
122+ { code : 'React.createElement("link", { rel: "canonical" })' } ,
123+ { code : 'React.createElement("link", { rel: ["canonical"] })' } ,
62124 { code : '<link rel="dns-prefetch"></link>' } ,
125+ { code : 'React.createElement("link", { rel: "dns-prefetch" })' } ,
126+ { code : 'React.createElement("link", { rel: ["dns-prefetch"] })' } ,
63127 { code : '<link rel="help"></link>' } ,
128+ { code : 'React.createElement("link", { rel: "help" })' } ,
129+ { code : 'React.createElement("link", { rel: ["help"] })' } ,
64130 { code : '<link rel="icon"></link>' } ,
131+ { code : 'React.createElement("link", { rel: "icon" })' } ,
132+ { code : 'React.createElement("link", { rel: ["icon"] })' } ,
65133 { code : '<link rel="license"></link>' } ,
134+ { code : 'React.createElement("link", { rel: "license" })' } ,
135+ { code : 'React.createElement("link", { rel: ["license"] })' } ,
66136 { code : '<link rel="manifest"></link>' } ,
137+ { code : 'React.createElement("link", { rel: "manifest" })' } ,
138+ { code : 'React.createElement("link", { rel: ["manifest"] })' } ,
67139 { code : '<link rel="modulepreload"></link>' } ,
140+ { code : 'React.createElement("link", { rel: "modulepreload" })' } ,
141+ { code : 'React.createElement("link", { rel: ["modulepreload"] })' } ,
68142 { code : '<link rel="next"></link>' } ,
143+ { code : 'React.createElement("link", { rel: "next" })' } ,
144+ { code : 'React.createElement("link", { rel: ["next"] })' } ,
69145 { code : '<link rel="pingback"></link>' } ,
146+ { code : 'React.createElement("link", { rel: "pingback" })' } ,
147+ { code : 'React.createElement("link", { rel: ["pingback"] })' } ,
70148 { code : '<link rel="preconnect"></link>' } ,
149+ { code : 'React.createElement("link", { rel: "preconnect" })' } ,
150+ { code : 'React.createElement("link", { rel: ["preconnect"] })' } ,
71151 { code : '<link rel="prefetch"></link>' } ,
152+ { code : 'React.createElement("link", { rel: "prefetch" })' } ,
153+ { code : 'React.createElement("link", { rel: ["prefetch"] })' } ,
72154 { code : '<link rel="preload"></link>' } ,
155+ { code : 'React.createElement("link", { rel: "preload" })' } ,
156+ { code : 'React.createElement("link", { rel: ["preload"] })' } ,
73157 { code : '<link rel="prerender"></link>' } ,
158+ { code : 'React.createElement("link", { rel: "prerender" })' } ,
159+ { code : 'React.createElement("link", { rel: ["prerender"] })' } ,
74160 { code : '<link rel="prev"></link>' } ,
161+ { code : 'React.createElement("link", { rel: "prev" })' } ,
162+ { code : 'React.createElement("link", { rel: ["prev"] })' } ,
75163 { code : '<link rel="search"></link>' } ,
164+ { code : 'React.createElement("link", { rel: "search" })' } ,
165+ { code : 'React.createElement("link", { rel: ["search"] })' } ,
76166 { code : '<link rel="stylesheet"></link>' } ,
167+ { code : 'React.createElement("link", { rel: "stylesheet" })' } ,
168+ { code : 'React.createElement("link", { rel: ["stylesheet"] })' } ,
77169 { code : '<form rel="external"></form>' } ,
170+ { code : 'React.createElement("form", { rel: "external" })' } ,
171+ { code : 'React.createElement("form", { rel: ["external"] })' } ,
78172 { code : '<form rel="help"></form>' } ,
173+ { code : 'React.createElement("form", { rel: "help" })' } ,
174+ { code : 'React.createElement("form", { rel: ["help"] })' } ,
79175 { code : '<form rel="license"></form>' } ,
176+ { code : 'React.createElement("form", { rel: "license" })' } ,
177+ { code : 'React.createElement("form", { rel: ["license"] })' } ,
80178 { code : '<form rel="next"></form>' } ,
179+ { code : 'React.createElement("form", { rel: "next" })' } ,
180+ { code : 'React.createElement("form", { rel: ["next"] })' } ,
81181 { code : '<form rel="nofollow"></form>' } ,
182+ { code : 'React.createElement("form", { rel: "nofollow" })' } ,
183+ { code : 'React.createElement("form", { rel: ["nofollow"] })' } ,
82184 { code : '<form rel="noopener"></form>' } ,
185+ { code : 'React.createElement("form", { rel: "noopener" })' } ,
186+ { code : 'React.createElement("form", { rel: ["noopener"] })' } ,
83187 { code : '<form rel="noreferrer"></form>' } ,
188+ { code : 'React.createElement("form", { rel: "noreferrer" })' } ,
189+ { code : 'React.createElement("form", { rel: ["noreferrer"] })' } ,
84190 { code : '<form rel="opener"></form>' } ,
191+ { code : 'React.createElement("form", { rel: "opener" })' } ,
192+ { code : 'React.createElement("form", { rel: ["opener"] })' } ,
85193 { code : '<form rel="prev"></form>' } ,
194+ { code : 'React.createElement("form", { rel: "prev" })' } ,
195+ { code : 'React.createElement("form", { rel: ["prev"] })' } ,
86196 { code : '<form rel="search"></form>' } ,
197+ { code : 'React.createElement("form", { rel: "search" })' } ,
198+ { code : 'React.createElement("form", { rel: ["search"] })' } ,
87199 { code : '<form rel={callFoo()}></form>' } ,
200+ { code : 'React.createElement("form", { rel: callFoo() })' } ,
201+ { code : 'React.createElement("form", { rel: [callFoo()] })' } ,
88202 { code : '<a rel={{a: "noreferrer"}["a"]}></a>' } ,
89203 { code : '<a rel={{a: "noreferrer"}["b"]}></a>' }
90204 ] ,
@@ -96,20 +210,44 @@ ruleTester.run('no-invalid-html-attribute', rule, {
96210 message : 'The "rel" attribute only has meaning on the tags: "<link>", "<a>", "<area>", "<form>"'
97211 } ]
98212 } ,
213+ {
214+ code : 'React.createElement("html", { rel: 1 })' ,
215+ errors : [ {
216+ message : 'The "rel" attribute only has meaning on the tags: "<link>", "<a>", "<area>", "<form>"'
217+ } ]
218+ } ,
99219 {
100220 code : '<Foo rel></Foo>' ,
101221 output : '<Foo ></Foo>' ,
102222 errors : [ {
103223 message : 'The "rel" attribute only has meaning on the tags: "<link>", "<a>", "<area>", "<form>"'
104224 } ]
105225 } ,
226+ {
227+ code : 'React.createElement("Foo", { rel: true })' ,
228+ errors : [ {
229+ message : 'The "rel" attribute only has meaning on the tags: "<link>", "<a>", "<area>", "<form>"'
230+ } ]
231+ } ,
106232 {
107233 code : '<a rel></a>' ,
108234 output : '<a ></a>' ,
109235 errors : [ {
110236 message : 'An empty "rel" attribute is meaningless.'
111237 } ]
112238 } ,
239+ {
240+ code : 'React.createElement("a", { rel: 1 })' ,
241+ errors : [ {
242+ message : '1 is never a valid "rel" attribute value.'
243+ } ]
244+ } ,
245+ {
246+ code : 'React.createElement("a", { rel() { return 1; } })' ,
247+ errors : [ {
248+ message : 'The "rel" attribute cannot be a method.'
249+ } ]
250+ } ,
113251 {
114252 code : '<any rel></any>' ,
115253 output : '<any ></any>' ,
@@ -173,6 +311,12 @@ ruleTester.run('no-invalid-html-attribute', rule, {
173311 message : '"foobar" is never a valid "rel" attribute value.'
174312 } ]
175313 } ,
314+ {
315+ code : 'React.createElement("a", { rel: ["noreferrer", "noopener", "foobar" ] })' ,
316+ errors : [ {
317+ message : '"foobar" is never a valid "rel" attribute value.'
318+ } ]
319+ } ,
176320 {
177321 code : '<a rel={"foobar noreferrer noopener"}></a>' ,
178322 output : '<a rel={" noreferrer noopener"}></a>' ,
0 commit comments