|
|
@@ -1,196 +0,0 @@
|
|
|
-/**
|
|
|
- * Copied from https://github.com/MananTank/validate-html-nesting
|
|
|
- * with ISC license
|
|
|
- *
|
|
|
- * To avoid runtime dependency on validate-html-nesting
|
|
|
- * This file should not change very often in the original repo
|
|
|
- * but we may need to keep it up-to-date from time to time.
|
|
|
- */
|
|
|
-
|
|
|
-/**
|
|
|
- * returns true if given parent-child nesting is valid HTML
|
|
|
- */
|
|
|
-export function isValidHTMLNesting(parent: string, child: string): boolean {
|
|
|
- // if we know the list of children that are the only valid children for the given parent
|
|
|
- if (parent in onlyValidChildren) {
|
|
|
- return onlyValidChildren[parent].has(child)
|
|
|
- }
|
|
|
-
|
|
|
- // if we know the list of parents that are the only valid parents for the given child
|
|
|
- if (child in onlyValidParents) {
|
|
|
- return onlyValidParents[child].has(parent)
|
|
|
- }
|
|
|
-
|
|
|
- // if we know the list of children that are NOT valid for the given parent
|
|
|
- if (parent in knownInvalidChildren) {
|
|
|
- // check if the child is in the list of invalid children
|
|
|
- // if so, return false
|
|
|
- if (knownInvalidChildren[parent].has(child)) return false
|
|
|
- }
|
|
|
-
|
|
|
- // if we know the list of parents that are NOT valid for the given child
|
|
|
- if (child in knownInvalidParents) {
|
|
|
- // check if the parent is in the list of invalid parents
|
|
|
- // if so, return false
|
|
|
- if (knownInvalidParents[child].has(parent)) return false
|
|
|
- }
|
|
|
-
|
|
|
- return true
|
|
|
-}
|
|
|
-
|
|
|
-const headings = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6'])
|
|
|
-const emptySet = new Set([])
|
|
|
-
|
|
|
-/**
|
|
|
- * maps element to set of elements that can be it's children, no other */
|
|
|
-const onlyValidChildren: Record<string, Set<string>> = {
|
|
|
- head: new Set([
|
|
|
- 'base',
|
|
|
- 'basefront',
|
|
|
- 'bgsound',
|
|
|
- 'link',
|
|
|
- 'meta',
|
|
|
- 'title',
|
|
|
- 'noscript',
|
|
|
- 'noframes',
|
|
|
- 'style',
|
|
|
- 'script',
|
|
|
- 'template',
|
|
|
- ]),
|
|
|
- optgroup: new Set(['option']),
|
|
|
- select: new Set(['optgroup', 'option']),
|
|
|
- math: new Set(['mrow']),
|
|
|
- script: new Set(),
|
|
|
- // table
|
|
|
- table: new Set(['caption', 'colgroup', 'tbody', 'tfoot', 'thead']),
|
|
|
- tr: new Set(['td', 'th']),
|
|
|
- colgroup: new Set(['col']),
|
|
|
- tbody: new Set(['tr']),
|
|
|
- thead: new Set(['tr']),
|
|
|
- tfoot: new Set(['tr']),
|
|
|
- // these elements can not have any children elements
|
|
|
- iframe: emptySet,
|
|
|
- option: emptySet,
|
|
|
- textarea: emptySet,
|
|
|
- style: emptySet,
|
|
|
- title: emptySet,
|
|
|
-}
|
|
|
-
|
|
|
-/** maps elements to set of elements which can be it's parent, no other */
|
|
|
-const onlyValidParents: Record<string, Set<string>> = {
|
|
|
- // sections
|
|
|
- html: emptySet,
|
|
|
- body: new Set(['html']),
|
|
|
- head: new Set(['html']),
|
|
|
- // table
|
|
|
- td: new Set(['tr']),
|
|
|
- colgroup: new Set(['table']),
|
|
|
- caption: new Set(['table']),
|
|
|
- tbody: new Set(['table']),
|
|
|
- tfoot: new Set(['table']),
|
|
|
- col: new Set(['colgroup']),
|
|
|
- th: new Set(['tr']),
|
|
|
- thead: new Set(['table']),
|
|
|
- tr: new Set(['tbody', 'thead', 'tfoot']),
|
|
|
- // data list
|
|
|
- dd: new Set(['dl', 'div']),
|
|
|
- dt: new Set(['dl', 'div']),
|
|
|
- // other
|
|
|
- figcaption: new Set(['figure']),
|
|
|
- // li: new Set(["ul", "ol"]),
|
|
|
- summary: new Set(['details']),
|
|
|
- area: new Set(['map']),
|
|
|
-} as const
|
|
|
-
|
|
|
-/** maps element to set of elements that can not be it's children, others can */
|
|
|
-const knownInvalidChildren: Record<string, Set<string>> = {
|
|
|
- p: new Set([
|
|
|
- 'address',
|
|
|
- 'article',
|
|
|
- 'aside',
|
|
|
- 'blockquote',
|
|
|
- 'center',
|
|
|
- 'details',
|
|
|
- 'dialog',
|
|
|
- 'dir',
|
|
|
- 'div',
|
|
|
- 'dl',
|
|
|
- 'fieldset',
|
|
|
- 'figure',
|
|
|
- 'footer',
|
|
|
- 'form',
|
|
|
- 'h1',
|
|
|
- 'h2',
|
|
|
- 'h3',
|
|
|
- 'h4',
|
|
|
- 'h5',
|
|
|
- 'h6',
|
|
|
- 'header',
|
|
|
- 'hgroup',
|
|
|
- 'hr',
|
|
|
- 'li',
|
|
|
- 'main',
|
|
|
- 'nav',
|
|
|
- 'menu',
|
|
|
- 'ol',
|
|
|
- 'p',
|
|
|
- 'pre',
|
|
|
- 'section',
|
|
|
- 'table',
|
|
|
- 'ul',
|
|
|
- ]),
|
|
|
- svg: new Set([
|
|
|
- 'b',
|
|
|
- 'blockquote',
|
|
|
- 'br',
|
|
|
- 'code',
|
|
|
- 'dd',
|
|
|
- 'div',
|
|
|
- 'dl',
|
|
|
- 'dt',
|
|
|
- 'em',
|
|
|
- 'embed',
|
|
|
- 'h1',
|
|
|
- 'h2',
|
|
|
- 'h3',
|
|
|
- 'h4',
|
|
|
- 'h5',
|
|
|
- 'h6',
|
|
|
- 'hr',
|
|
|
- 'i',
|
|
|
- 'img',
|
|
|
- 'li',
|
|
|
- 'menu',
|
|
|
- 'meta',
|
|
|
- 'ol',
|
|
|
- 'p',
|
|
|
- 'pre',
|
|
|
- 'ruby',
|
|
|
- 's',
|
|
|
- 'small',
|
|
|
- 'span',
|
|
|
- 'strong',
|
|
|
- 'sub',
|
|
|
- 'sup',
|
|
|
- 'table',
|
|
|
- 'u',
|
|
|
- 'ul',
|
|
|
- 'var',
|
|
|
- ]),
|
|
|
-} as const
|
|
|
-
|
|
|
-/** maps element to set of elements that can not be it's parent, others can */
|
|
|
-const knownInvalidParents: Record<string, Set<string>> = {
|
|
|
- a: new Set(['a']),
|
|
|
- button: new Set(['button']),
|
|
|
- dd: new Set(['dd', 'dt']),
|
|
|
- dt: new Set(['dd', 'dt']),
|
|
|
- form: new Set(['form']),
|
|
|
- li: new Set(['li']),
|
|
|
- h1: headings,
|
|
|
- h2: headings,
|
|
|
- h3: headings,
|
|
|
- h4: headings,
|
|
|
- h5: headings,
|
|
|
- h6: headings,
|
|
|
-}
|