/** * Map of elements that have certain elements that are not allowed inside them, in the sense that they will auto-close the parent/ancestor element. * Theoretically one could take advantage of it but most of the time it will just result in confusing behavior and break when SSR'd. * There are more elements that are invalid inside other elements, but they're not auto-closed and so don't break SSR and are therefore not listed here. * @type {Record} */ const autoclosing_children = { // based on http://developers.whatwg.org/syntax.html#syntax-tag-omission li: { direct: ['li'] }, // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt#technical_summary dt: { descendant: ['dt', 'dd'], reset_by: ['dl'] }, dd: { descendant: ['dt', 'dd'], reset_by: ['dl'] }, p: { descendant: [ 'address', 'article', 'aside', 'blockquote', 'div', 'dl', 'fieldset', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'ul' ] }, rt: { descendant: ['rt', 'rp'] }, rp: { descendant: ['rt', 'rp'] }, optgroup: { descendant: ['optgroup'] }, option: { descendant: ['option', 'optgroup'] }, thead: { direct: ['tbody', 'tfoot'] }, tbody: { direct: ['tbody', 'tfoot'] }, tfoot: { direct: ['tbody'] }, tr: { direct: ['tr', 'tbody'] }, td: { direct: ['td', 'th', 'tr'] }, th: { direct: ['td', 'th', 'tr'] } }; /** * Returns true if the tag is either the last in the list of siblings and will be autoclosed, * or not allowed inside the parent tag such that it will auto-close it. The latter results * in the browser repairing the HTML, which will likely result in an error during hydration. * @param {string} current * @param {string} [next] */ export function closing_tag_omitted(current, next) { const disallowed = autoclosing_children[current]; if (disallowed) { if ( !next || ('direct' in disallowed ? disallowed.direct : disallowed.descendant).includes(next) ) { return true; } } return false; } /** * Map of elements that have certain elements that are not allowed inside them, in the sense that the browser will somehow repair the HTML. * There are more elements that are invalid inside other elements, but they're not repaired and so don't break SSR and are therefore not listed here. * @type {Record} */ const disallowed_children = { ...autoclosing_children, // Strictly speaking, seeing an