1
1
import { type CompilerError , compile } from '../../src'
2
+ import { isValidHTMLNesting } from '../../src/htmlNesting'
2
3
3
4
describe ( 'validate html nesting' , ( ) => {
4
5
it ( 'should warn with p > div' , ( ) => {
@@ -17,4 +18,185 @@ describe('validate html nesting', () => {
17
18
} )
18
19
expect ( err ) . toBeUndefined ( )
19
20
} )
21
+
22
+ // #13318
23
+ it ( 'should not warn when parent tag is template' , ( ) => {
24
+ let err : CompilerError | undefined
25
+ compile ( `<template><tr/></template>` , {
26
+ onWarn : e => ( err = e ) ,
27
+ } )
28
+ expect ( err ) . toBeUndefined ( )
29
+ } )
30
+ } )
31
+
32
+ /**
33
+ * Copied from https://github.com/MananTank/validate-html-nesting
34
+ * with ISC license
35
+ */
36
+ describe ( 'isValidHTMLNesting' , ( ) => {
37
+ test ( 'form' , ( ) => {
38
+ // invalid
39
+ expect ( isValidHTMLNesting ( 'form' , 'form' ) ) . toBe ( false )
40
+
41
+ // valid
42
+ expect ( isValidHTMLNesting ( 'form' , 'div' ) ) . toBe ( true )
43
+ expect ( isValidHTMLNesting ( 'form' , 'input' ) ) . toBe ( true )
44
+ expect ( isValidHTMLNesting ( 'form' , 'select' ) ) . toBe ( true )
45
+ expect ( isValidHTMLNesting ( 'form' , 'button' ) ) . toBe ( true )
46
+ expect ( isValidHTMLNesting ( 'form' , 'label' ) ) . toBe ( true )
47
+ expect ( isValidHTMLNesting ( 'form' , 'h1' ) ) . toBe ( true )
48
+ } )
49
+
50
+ test ( 'p' , ( ) => {
51
+ // invalid
52
+ expect ( isValidHTMLNesting ( 'p' , 'p' ) ) . toBe ( false )
53
+ expect ( isValidHTMLNesting ( 'p' , 'div' ) ) . toBe ( false )
54
+ expect ( isValidHTMLNesting ( 'p' , 'hr' ) ) . toBe ( false )
55
+ expect ( isValidHTMLNesting ( 'p' , 'blockquote' ) ) . toBe ( false )
56
+ expect ( isValidHTMLNesting ( 'p' , 'pre' ) ) . toBe ( false )
57
+
58
+ // valid
59
+ expect ( isValidHTMLNesting ( 'p' , 'a' ) ) . toBe ( true )
60
+ expect ( isValidHTMLNesting ( 'p' , 'span' ) ) . toBe ( true )
61
+ expect ( isValidHTMLNesting ( 'p' , 'abbr' ) ) . toBe ( true )
62
+ expect ( isValidHTMLNesting ( 'p' , 'button' ) ) . toBe ( true )
63
+ expect ( isValidHTMLNesting ( 'p' , 'b' ) ) . toBe ( true )
64
+ expect ( isValidHTMLNesting ( 'p' , 'i' ) ) . toBe ( true )
65
+ expect ( isValidHTMLNesting ( 'p' , 'input' ) ) . toBe ( true )
66
+ expect ( isValidHTMLNesting ( 'p' , 'label' ) ) . toBe ( true )
67
+ } )
68
+
69
+ test ( 'a' , ( ) => {
70
+ // invalid
71
+ expect ( isValidHTMLNesting ( 'a' , 'a' ) ) . toBe ( false )
72
+
73
+ // valid
74
+ expect ( isValidHTMLNesting ( 'a' , 'div' ) ) . toBe ( true )
75
+ expect ( isValidHTMLNesting ( 'a' , 'span' ) ) . toBe ( true )
76
+ } )
77
+
78
+ test ( 'button' , ( ) => {
79
+ // invalid
80
+ expect ( isValidHTMLNesting ( 'button' , 'button' ) ) . toBe ( false )
81
+
82
+ // valid
83
+ expect ( isValidHTMLNesting ( 'button' , 'div' ) ) . toBe ( true )
84
+ expect ( isValidHTMLNesting ( 'button' , 'span' ) ) . toBe ( true )
85
+ } )
86
+
87
+ test ( 'table' , ( ) => {
88
+ // invalid
89
+ expect ( isValidHTMLNesting ( 'table' , 'tr' ) ) . toBe ( false )
90
+ expect ( isValidHTMLNesting ( 'table' , 'table' ) ) . toBe ( false )
91
+ expect ( isValidHTMLNesting ( 'table' , 'td' ) ) . toBe ( false )
92
+
93
+ // valid
94
+ expect ( isValidHTMLNesting ( 'table' , 'thead' ) ) . toBe ( true )
95
+ expect ( isValidHTMLNesting ( 'table' , 'tbody' ) ) . toBe ( true )
96
+ expect ( isValidHTMLNesting ( 'table' , 'tfoot' ) ) . toBe ( true )
97
+ expect ( isValidHTMLNesting ( 'table' , 'caption' ) ) . toBe ( true )
98
+ expect ( isValidHTMLNesting ( 'table' , 'colgroup' ) ) . toBe ( true )
99
+ } )
100
+
101
+ test ( 'td' , ( ) => {
102
+ // valid
103
+ expect ( isValidHTMLNesting ( 'td' , 'span' ) ) . toBe ( true )
104
+ expect ( isValidHTMLNesting ( 'tr' , 'td' ) ) . toBe ( true )
105
+
106
+ // invalid
107
+ expect ( isValidHTMLNesting ( 'td' , 'td' ) ) . toBe ( false )
108
+ expect ( isValidHTMLNesting ( 'div' , 'td' ) ) . toBe ( false )
109
+ } )
110
+
111
+ test ( 'tbody' , ( ) => {
112
+ // invalid
113
+ expect ( isValidHTMLNesting ( 'tbody' , 'td' ) ) . toBe ( false )
114
+
115
+ // valid
116
+ expect ( isValidHTMLNesting ( 'tbody' , 'tr' ) ) . toBe ( true )
117
+ } )
118
+
119
+ test ( 'tr' , ( ) => {
120
+ // invalid
121
+ expect ( isValidHTMLNesting ( 'tr' , 'tr' ) ) . toBe ( false )
122
+ expect ( isValidHTMLNesting ( 'table' , 'tr' ) ) . toBe ( false )
123
+
124
+ // valid
125
+ expect ( isValidHTMLNesting ( 'tbody' , 'tr' ) ) . toBe ( true )
126
+ expect ( isValidHTMLNesting ( 'thead' , 'tr' ) ) . toBe ( true )
127
+ expect ( isValidHTMLNesting ( 'tfoot' , 'tr' ) ) . toBe ( true )
128
+ expect ( isValidHTMLNesting ( 'tr' , 'td' ) ) . toBe ( true )
129
+ expect ( isValidHTMLNesting ( 'tr' , 'th' ) ) . toBe ( true )
130
+ } )
131
+
132
+ test ( 'li' , ( ) => {
133
+ // invalid
134
+ expect ( isValidHTMLNesting ( 'li' , 'li' ) ) . toBe ( false )
135
+ // valid
136
+ expect ( isValidHTMLNesting ( 'li' , 'div' ) ) . toBe ( true )
137
+ expect ( isValidHTMLNesting ( 'li' , 'ul' ) ) . toBe ( true )
138
+ } )
139
+
140
+ test ( 'headings' , ( ) => {
141
+ // invalid
142
+ expect ( isValidHTMLNesting ( 'h1' , 'h1' ) ) . toBe ( false )
143
+ expect ( isValidHTMLNesting ( 'h2' , 'h1' ) ) . toBe ( false )
144
+ expect ( isValidHTMLNesting ( 'h3' , 'h1' ) ) . toBe ( false )
145
+ expect ( isValidHTMLNesting ( 'h1' , 'h6' ) ) . toBe ( false )
146
+
147
+ // valid
148
+ expect ( isValidHTMLNesting ( 'h1' , 'div' ) ) . toBe ( true )
149
+ } )
150
+
151
+ describe ( 'SVG' , ( ) => {
152
+ test ( 'svg' , ( ) => {
153
+ // invalid non-svg tags as children
154
+ expect ( isValidHTMLNesting ( 'svg' , 'div' ) ) . toBe ( false )
155
+ expect ( isValidHTMLNesting ( 'svg' , 'img' ) ) . toBe ( false )
156
+ expect ( isValidHTMLNesting ( 'svg' , 'p' ) ) . toBe ( false )
157
+ expect ( isValidHTMLNesting ( 'svg' , 'h2' ) ) . toBe ( false )
158
+ expect ( isValidHTMLNesting ( 'svg' , 'span' ) ) . toBe ( false )
159
+
160
+ // valid non-svg tags as children
161
+ expect ( isValidHTMLNesting ( 'svg' , 'a' ) ) . toBe ( true )
162
+ expect ( isValidHTMLNesting ( 'svg' , 'textarea' ) ) . toBe ( true )
163
+ expect ( isValidHTMLNesting ( 'svg' , 'input' ) ) . toBe ( true )
164
+ expect ( isValidHTMLNesting ( 'svg' , 'select' ) ) . toBe ( true )
165
+
166
+ // valid svg tags as children
167
+ expect ( isValidHTMLNesting ( 'svg' , 'g' ) ) . toBe ( true )
168
+ expect ( isValidHTMLNesting ( 'svg' , 'ellipse' ) ) . toBe ( true )
169
+ expect ( isValidHTMLNesting ( 'svg' , 'feOffset' ) ) . toBe ( true )
170
+ } )
171
+
172
+ test ( 'foreignObject' , ( ) => {
173
+ // valid
174
+ expect ( isValidHTMLNesting ( 'foreignObject' , 'g' ) ) . toBe ( true )
175
+ expect ( isValidHTMLNesting ( 'foreignObject' , 'div' ) ) . toBe ( true )
176
+ expect ( isValidHTMLNesting ( 'foreignObject' , 'a' ) ) . toBe ( true )
177
+ expect ( isValidHTMLNesting ( 'foreignObject' , 'textarea' ) ) . toBe ( true )
178
+ } )
179
+
180
+ test ( 'g' , ( ) => {
181
+ // valid
182
+ expect ( isValidHTMLNesting ( 'g' , 'div' ) ) . toBe ( true )
183
+ expect ( isValidHTMLNesting ( 'g' , 'p' ) ) . toBe ( true )
184
+ expect ( isValidHTMLNesting ( 'g' , 'a' ) ) . toBe ( true )
185
+ expect ( isValidHTMLNesting ( 'g' , 'textarea' ) ) . toBe ( true )
186
+ expect ( isValidHTMLNesting ( 'g' , 'g' ) ) . toBe ( true )
187
+ } )
188
+
189
+ test ( 'dl' , ( ) => {
190
+ // valid
191
+ expect ( isValidHTMLNesting ( 'dl' , 'dt' ) ) . toBe ( true )
192
+ expect ( isValidHTMLNesting ( 'dl' , 'dd' ) ) . toBe ( true )
193
+ expect ( isValidHTMLNesting ( 'dl' , 'div' ) ) . toBe ( true )
194
+ expect ( isValidHTMLNesting ( 'div' , 'dt' ) ) . toBe ( true )
195
+ expect ( isValidHTMLNesting ( 'div' , 'dd' ) ) . toBe ( true )
196
+
197
+ // invalid
198
+ expect ( isValidHTMLNesting ( 'span' , 'dt' ) ) . toBe ( false )
199
+ expect ( isValidHTMLNesting ( 'span' , 'dd' ) ) . toBe ( false )
200
+ } )
201
+ } )
20
202
} )
0 commit comments