Skip to content
This repository was archived by the owner on Jul 19, 2025. It is now read-only.

Commit 7548865

Browse files
committed
refactor(compiler-vapor): inline validate-html-nesting
1 parent 1af1f40 commit 7548865

File tree

4 files changed

+198
-11
lines changed

4 files changed

+198
-11
lines changed

packages/compiler-vapor/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
"dependencies": {
4040
"@vue/compiler-dom": "workspace:*",
4141
"@vue/shared": "workspace:*",
42-
"source-map-js": "^1.0.2",
43-
"validate-html-nesting": "^1.2.2"
42+
"source-map-js": "^1.0.2"
4443
}
4544
}
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/**
2+
* Copied from https://github.com/MananTank/validate-html-nesting
3+
* with ISC license
4+
*
5+
* To avoid runtime dependency on validate-html-nesting
6+
* This file should not change very often in the original repo
7+
* but we may need to keep it up-to-date from time to time.
8+
*/
9+
10+
/**
11+
* returns true if given parent-child nesting is valid HTML
12+
*/
13+
export function isValidHTMLNesting(parent: string, child: string): boolean {
14+
// if we know the list of children that are the only valid children for the given parent
15+
if (parent in onlyValidChildren) {
16+
return onlyValidChildren[parent].has(child)
17+
}
18+
19+
// if we know the list of parents that are the only valid parents for the given child
20+
if (child in onlyValidParents) {
21+
return onlyValidParents[child].has(parent)
22+
}
23+
24+
// if we know the list of children that are NOT valid for the given parent
25+
if (parent in knownInvalidChildren) {
26+
// check if the child is in the list of invalid children
27+
// if so, return false
28+
if (knownInvalidChildren[parent].has(child)) return false
29+
}
30+
31+
// if we know the list of parents that are NOT valid for the given child
32+
if (child in knownInvalidParents) {
33+
// check if the parent is in the list of invalid parents
34+
// if so, return false
35+
if (knownInvalidParents[child].has(parent)) return false
36+
}
37+
38+
return true
39+
}
40+
41+
const headings = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6'])
42+
const emptySet = new Set([])
43+
44+
/**
45+
* maps element to set of elements that can be it's children, no other */
46+
const onlyValidChildren: Record<string, Set<string>> = {
47+
head: new Set([
48+
'base',
49+
'basefront',
50+
'bgsound',
51+
'link',
52+
'meta',
53+
'title',
54+
'noscript',
55+
'noframes',
56+
'style',
57+
'script',
58+
'template',
59+
]),
60+
optgroup: new Set(['option']),
61+
select: new Set(['optgroup', 'option']),
62+
math: new Set(['mrow']),
63+
script: new Set(),
64+
// table
65+
table: new Set(['caption', 'colgroup', 'tbody', 'tfoot', 'thead']),
66+
tr: new Set(['td', 'th']),
67+
colgroup: new Set(['col']),
68+
tbody: new Set(['tr']),
69+
thead: new Set(['tr']),
70+
tfoot: new Set(['tr']),
71+
// these elements can not have any children elements
72+
iframe: emptySet,
73+
option: emptySet,
74+
textarea: emptySet,
75+
style: emptySet,
76+
title: emptySet,
77+
}
78+
79+
/** maps elements to set of elements which can be it's parent, no other */
80+
const onlyValidParents: Record<string, Set<string>> = {
81+
// sections
82+
html: emptySet,
83+
body: new Set(['html']),
84+
head: new Set(['html']),
85+
// table
86+
td: new Set(['tr']),
87+
colgroup: new Set(['table']),
88+
caption: new Set(['table']),
89+
tbody: new Set(['table']),
90+
tfoot: new Set(['table']),
91+
col: new Set(['colgroup']),
92+
th: new Set(['tr']),
93+
thead: new Set(['table']),
94+
tr: new Set(['tbody', 'thead', 'tfoot']),
95+
// data list
96+
dd: new Set(['dl', 'div']),
97+
dt: new Set(['dl', 'div']),
98+
// other
99+
figcaption: new Set(['figure']),
100+
// li: new Set(["ul", "ol"]),
101+
summary: new Set(['details']),
102+
area: new Set(['map']),
103+
} as const
104+
105+
/** maps element to set of elements that can not be it's children, others can */
106+
const knownInvalidChildren: Record<string, Set<string>> = {
107+
p: new Set([
108+
'address',
109+
'article',
110+
'aside',
111+
'blockquote',
112+
'center',
113+
'details',
114+
'dialog',
115+
'dir',
116+
'div',
117+
'dl',
118+
'fieldset',
119+
'figure',
120+
'footer',
121+
'form',
122+
'h1',
123+
'h2',
124+
'h3',
125+
'h4',
126+
'h5',
127+
'h6',
128+
'header',
129+
'hgroup',
130+
'hr',
131+
'li',
132+
'main',
133+
'nav',
134+
'menu',
135+
'ol',
136+
'p',
137+
'pre',
138+
'section',
139+
'table',
140+
'ul',
141+
]),
142+
svg: new Set([
143+
'b',
144+
'blockquote',
145+
'br',
146+
'code',
147+
'dd',
148+
'div',
149+
'dl',
150+
'dt',
151+
'em',
152+
'embed',
153+
'h1',
154+
'h2',
155+
'h3',
156+
'h4',
157+
'h5',
158+
'h6',
159+
'hr',
160+
'i',
161+
'img',
162+
'li',
163+
'menu',
164+
'meta',
165+
'ol',
166+
'p',
167+
'pre',
168+
'ruby',
169+
's',
170+
'small',
171+
'span',
172+
'strong',
173+
'sub',
174+
'sup',
175+
'table',
176+
'u',
177+
'ul',
178+
'var',
179+
]),
180+
} as const
181+
182+
/** maps element to set of elements that can not be it's parent, others can */
183+
const knownInvalidParents: Record<string, Set<string>> = {
184+
a: new Set(['a']),
185+
button: new Set(['button']),
186+
dd: new Set(['dd', 'dt']),
187+
dt: new Set(['dd', 'dt']),
188+
form: new Set(['form']),
189+
li: new Set(['li']),
190+
h1: headings,
191+
h2: headings,
192+
h3: headings,
193+
h4: headings,
194+
h5: headings,
195+
h6: headings,
196+
}

packages/compiler-vapor/src/transforms/transformElement.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isValidHTMLNesting } from 'validate-html-nesting'
1+
import { isValidHTMLNesting } from '../html-nesting'
22
import {
33
type AttributeNode,
44
type ElementNode,

pnpm-lock.yaml

Lines changed: 0 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)