Refactor routing in App component to enhance navigation and improve error handling by integrating dynamic routes and updating the NotFound route.

This commit is contained in:
becarta
2025-05-23 12:43:00 +02:00
parent f40db0f5c9
commit a544759a3b
11127 changed files with 1647032 additions and 0 deletions

6
node_modules/hast-util-to-html/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,6 @@
export { toHtml } from "./lib/index.js";
export type CharacterReferences = import("./lib/index.js").CharacterReferences;
export type Options = import("./lib/index.js").Options;
export type Quote = import("./lib/index.js").Quote;
export type Space = import("./lib/index.js").Space;
//# sourceMappingURL=index.d.ts.map

1
node_modules/hast-util-to-html/index.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":";kCACa,OAAO,gBAAgB,EAAE,mBAAmB;sBAC5C,OAAO,gBAAgB,EAAE,OAAO;oBAChC,OAAO,gBAAgB,EAAE,KAAK;oBAC9B,OAAO,gBAAgB,EAAE,KAAK"}

8
node_modules/hast-util-to-html/index.js generated vendored Normal file
View File

@@ -0,0 +1,8 @@
/**
* @typedef {import('./lib/index.js').CharacterReferences} CharacterReferences
* @typedef {import('./lib/index.js').Options} Options
* @typedef {import('./lib/index.js').Quote} Quote
* @typedef {import('./lib/index.js').Space} Space
*/
export {toHtml} from './lib/index.js'

19
node_modules/hast-util-to-html/lib/handle/comment.d.ts generated vendored Normal file
View File

@@ -0,0 +1,19 @@
/**
* Serialize a comment.
*
* @param {Comment} node
* Node to handle.
* @param {number | undefined} _1
* Index of `node` in `parent.
* @param {Parents | undefined} _2
* Parent of `node`.
* @param {State} state
* Info passed around about the current state.
* @returns {string}
* Serialized node.
*/
export function comment(node: Comment, _1: number | undefined, _2: Parents | undefined, state: State): string;
import type { Comment } from 'hast';
import type { Parents } from 'hast';
import type { State } from '../index.js';
//# sourceMappingURL=comment.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"comment.d.ts","sourceRoot":"","sources":["comment.js"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;GAaG;AACH,8BAXW,OAAO,MAEP,MAAM,GAAG,SAAS,MAElB,OAAO,GAAG,SAAS,SAEnB,KAAK,GAEH,MAAM,CA2BlB;6BAlDkC,MAAM;6BAAN,MAAM;2BACjB,aAAa"}

52
node_modules/hast-util-to-html/lib/handle/comment.js generated vendored Normal file
View File

@@ -0,0 +1,52 @@
/**
* @import {Comment, Parents} from 'hast'
* @import {State} from '../index.js'
*/
import {stringifyEntities} from 'stringify-entities'
const htmlCommentRegex = /^>|^->|<!--|-->|--!>|<!-$/g
// Declare arrays as variables so it can be cached by `stringifyEntities`
const bogusCommentEntitySubset = ['>']
const commentEntitySubset = ['<', '>']
/**
* Serialize a comment.
*
* @param {Comment} node
* Node to handle.
* @param {number | undefined} _1
* Index of `node` in `parent.
* @param {Parents | undefined} _2
* Parent of `node`.
* @param {State} state
* Info passed around about the current state.
* @returns {string}
* Serialized node.
*/
export function comment(node, _1, _2, state) {
// See: <https://html.spec.whatwg.org/multipage/syntax.html#comments>
return state.settings.bogusComments
? '<?' +
stringifyEntities(
node.value,
Object.assign({}, state.settings.characterReferences, {
subset: bogusCommentEntitySubset
})
) +
'>'
: '<!--' + node.value.replace(htmlCommentRegex, encode) + '-->'
/**
* @param {string} $0
*/
function encode($0) {
return stringifyEntities(
$0,
Object.assign({}, state.settings.characterReferences, {
subset: commentEntitySubset
})
)
}
}

23
node_modules/hast-util-to-html/lib/handle/doctype.d.ts generated vendored Normal file
View File

@@ -0,0 +1,23 @@
/**
* @import {Doctype, Parents} from 'hast'
* @import {State} from '../index.js'
*/
/**
* Serialize a doctype.
*
* @param {Doctype} _1
* Node to handle.
* @param {number | undefined} _2
* Index of `node` in `parent.
* @param {Parents | undefined} _3
* Parent of `node`.
* @param {State} state
* Info passed around about the current state.
* @returns {string}
* Serialized node.
*/
export function doctype(_1: Doctype, _2: number | undefined, _3: Parents | undefined, state: State): string;
import type { Doctype } from 'hast';
import type { Parents } from 'hast';
import type { State } from '../index.js';
//# sourceMappingURL=doctype.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"doctype.d.ts","sourceRoot":"","sources":["doctype.js"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;GAaG;AACH,4BAXW,OAAO,MAEP,MAAM,GAAG,SAAS,MAElB,OAAO,GAAG,SAAS,SAEnB,KAAK,GAEH,MAAM,CAUlB;6BAzBkC,MAAM;6BAAN,MAAM;2BACjB,aAAa"}

27
node_modules/hast-util-to-html/lib/handle/doctype.js generated vendored Normal file
View File

@@ -0,0 +1,27 @@
/**
* @import {Doctype, Parents} from 'hast'
* @import {State} from '../index.js'
*/
/**
* Serialize a doctype.
*
* @param {Doctype} _1
* Node to handle.
* @param {number | undefined} _2
* Index of `node` in `parent.
* @param {Parents | undefined} _3
* Parent of `node`.
* @param {State} state
* Info passed around about the current state.
* @returns {string}
* Serialized node.
*/
export function doctype(_1, _2, _3, state) {
return (
'<!' +
(state.settings.upperDoctype ? 'DOCTYPE' : 'doctype') +
(state.settings.tightDoctype ? '' : ' ') +
'html>'
)
}

19
node_modules/hast-util-to-html/lib/handle/element.d.ts generated vendored Normal file
View File

@@ -0,0 +1,19 @@
/**
* Serialize an element node.
*
* @param {Element} node
* Node to handle.
* @param {number | undefined} index
* Index of `node` in `parent.
* @param {Parents | undefined} parent
* Parent of `node`.
* @param {State} state
* Info passed around about the current state.
* @returns {string}
* Serialized node.
*/
export function element(node: Element, index: number | undefined, parent: Parents | undefined, state: State): string;
import type { Element } from 'hast';
import type { Parents } from 'hast';
import type { State } from '../index.js';
//# sourceMappingURL=element.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"element.d.ts","sourceRoot":"","sources":["element.js"],"names":[],"mappings":"AA6CA;;;;;;;;;;;;;GAaG;AACH,8BAXW,OAAO,SAEP,MAAM,GAAG,SAAS,UAElB,OAAO,GAAG,SAAS,SAEnB,KAAK,GAEH,MAAM,CAgElB;6BAvH8C,MAAM;6BAAN,MAAM;2BAC7B,aAAa"}

265
node_modules/hast-util-to-html/lib/handle/element.js generated vendored Normal file
View File

@@ -0,0 +1,265 @@
/**
* @import {Element, Parents, Properties} from 'hast'
* @import {State} from '../index.js'
*/
import {ccount} from 'ccount'
import {stringify as commas} from 'comma-separated-tokens'
import {find, svg} from 'property-information'
import {stringify as spaces} from 'space-separated-tokens'
import {stringifyEntities} from 'stringify-entities'
import {closing} from '../omission/closing.js'
import {opening} from '../omission/opening.js'
/**
* Maps of subsets.
*
* Each value is a matrix of tuples.
* The value at `0` causes parse errors, the value at `1` is valid.
* Of both, the value at `0` is unsafe, and the value at `1` is safe.
*
* @type {Record<'double' | 'name' | 'single' | 'unquoted', Array<[Array<string>, Array<string>]>>}
*/
const constants = {
// See: <https://html.spec.whatwg.org/#attribute-name-state>.
name: [
['\t\n\f\r &/=>'.split(''), '\t\n\f\r "&\'/=>`'.split('')],
['\0\t\n\f\r "&\'/<=>'.split(''), '\0\t\n\f\r "&\'/<=>`'.split('')]
],
// See: <https://html.spec.whatwg.org/#attribute-value-(unquoted)-state>.
unquoted: [
['\t\n\f\r &>'.split(''), '\0\t\n\f\r "&\'<=>`'.split('')],
['\0\t\n\f\r "&\'<=>`'.split(''), '\0\t\n\f\r "&\'<=>`'.split('')]
],
// See: <https://html.spec.whatwg.org/#attribute-value-(single-quoted)-state>.
single: [
["&'".split(''), '"&\'`'.split('')],
["\0&'".split(''), '\0"&\'`'.split('')]
],
// See: <https://html.spec.whatwg.org/#attribute-value-(double-quoted)-state>.
double: [
['"&'.split(''), '"&\'`'.split('')],
['\0"&'.split(''), '\0"&\'`'.split('')]
]
}
/**
* Serialize an element node.
*
* @param {Element} node
* Node to handle.
* @param {number | undefined} index
* Index of `node` in `parent.
* @param {Parents | undefined} parent
* Parent of `node`.
* @param {State} state
* Info passed around about the current state.
* @returns {string}
* Serialized node.
*/
export function element(node, index, parent, state) {
const schema = state.schema
const omit = schema.space === 'svg' ? false : state.settings.omitOptionalTags
let selfClosing =
schema.space === 'svg'
? state.settings.closeEmptyElements
: state.settings.voids.includes(node.tagName.toLowerCase())
/** @type {Array<string>} */
const parts = []
/** @type {string} */
let last
if (schema.space === 'html' && node.tagName === 'svg') {
state.schema = svg
}
const attributes = serializeAttributes(state, node.properties)
const content = state.all(
schema.space === 'html' && node.tagName === 'template' ? node.content : node
)
state.schema = schema
// If the node is categorised as void, but it has children, remove the
// categorisation.
// This enables for example `menuitem`s, which are void in W3C HTML but not
// void in WHATWG HTML, to be stringified properly.
// Note: `menuitem` has since been removed from the HTML spec, and so is no
// longer void.
if (content) selfClosing = false
if (attributes || !omit || !opening(node, index, parent)) {
parts.push('<', node.tagName, attributes ? ' ' + attributes : '')
if (
selfClosing &&
(schema.space === 'svg' || state.settings.closeSelfClosing)
) {
last = attributes.charAt(attributes.length - 1)
if (
!state.settings.tightSelfClosing ||
last === '/' ||
(last && last !== '"' && last !== "'")
) {
parts.push(' ')
}
parts.push('/')
}
parts.push('>')
}
parts.push(content)
if (!selfClosing && (!omit || !closing(node, index, parent))) {
parts.push('</' + node.tagName + '>')
}
return parts.join('')
}
/**
* @param {State} state
* @param {Properties | null | undefined} properties
* @returns {string}
*/
function serializeAttributes(state, properties) {
/** @type {Array<string>} */
const values = []
let index = -1
/** @type {string} */
let key
if (properties) {
for (key in properties) {
if (properties[key] !== null && properties[key] !== undefined) {
const value = serializeAttribute(state, key, properties[key])
if (value) values.push(value)
}
}
}
while (++index < values.length) {
const last = state.settings.tightAttributes
? values[index].charAt(values[index].length - 1)
: undefined
// In tight mode, dont add a space after quoted attributes.
if (index !== values.length - 1 && last !== '"' && last !== "'") {
values[index] += ' '
}
}
return values.join('')
}
/**
* @param {State} state
* @param {string} key
* @param {Properties[keyof Properties]} value
* @returns {string}
*/
function serializeAttribute(state, key, value) {
const info = find(state.schema, key)
const x =
state.settings.allowParseErrors && state.schema.space === 'html' ? 0 : 1
const y = state.settings.allowDangerousCharacters ? 0 : 1
let quote = state.quote
/** @type {string | undefined} */
let result
if (info.overloadedBoolean && (value === info.attribute || value === '')) {
value = true
} else if (
(info.boolean || info.overloadedBoolean) &&
(typeof value !== 'string' || value === info.attribute || value === '')
) {
value = Boolean(value)
}
if (
value === null ||
value === undefined ||
value === false ||
(typeof value === 'number' && Number.isNaN(value))
) {
return ''
}
const name = stringifyEntities(
info.attribute,
Object.assign({}, state.settings.characterReferences, {
// Always encode without parse errors in non-HTML.
subset: constants.name[x][y]
})
)
// No value.
// There is currently only one boolean property in SVG: `[download]` on
// `<a>`.
// This property does not seem to work in browsers (Firefox, Safari, Chrome),
// so I cant test if dropping the value works.
// But I assume that it should:
//
// ```html
// <!doctype html>
// <svg viewBox="0 0 100 100">
// <a href=https://example.com download>
// <circle cx=50 cy=40 r=35 />
// </a>
// </svg>
// ```
//
// See: <https://github.com/wooorm/property-information/blob/main/lib/svg.js>
if (value === true) return name
// `spaces` doesnt accept a second argument, but its given here just to
// keep the code cleaner.
value = Array.isArray(value)
? (info.commaSeparated ? commas : spaces)(value, {
padLeft: !state.settings.tightCommaSeparatedLists
})
: String(value)
if (state.settings.collapseEmptyAttributes && !value) return name
// Check unquoted value.
if (state.settings.preferUnquoted) {
result = stringifyEntities(
value,
Object.assign({}, state.settings.characterReferences, {
attribute: true,
subset: constants.unquoted[x][y]
})
)
}
// If we dont want unquoted, or if `value` contains character references when
// unquoted…
if (result !== value) {
// If the alternative is less common than `quote`, switch.
if (
state.settings.quoteSmart &&
ccount(value, quote) > ccount(value, state.alternative)
) {
quote = state.alternative
}
result =
quote +
stringifyEntities(
value,
Object.assign({}, state.settings.characterReferences, {
// Always encode without parse errors in non-HTML.
subset: (quote === "'" ? constants.single : constants.double)[x][y],
attribute: true
})
) +
quote
}
// Dont add a `=` for unquoted empties.
return name + (result ? '=' + result : result)
}

8
node_modules/hast-util-to-html/lib/handle/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,8 @@
/**
* @type {(node: Nodes, index: number | undefined, parent: Parents | undefined, state: State) => string}
*/
export const handle: (node: Nodes, index: number | undefined, parent: Parents | undefined, state: State) => string;
import type { Nodes } from 'hast';
import type { Parents } from 'hast';
import type { State } from '../index.js';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":"AAaA;;GAEG;AACH,qBAFU,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,OAAO,GAAG,SAAS,EAAE,KAAK,EAAE,KAAK,KAAK,MAAM,CAMrG;2BAnB+B,MAAM;6BAAN,MAAM;2BACf,aAAa"}

47
node_modules/hast-util-to-html/lib/handle/index.js generated vendored Normal file
View File

@@ -0,0 +1,47 @@
/**
* @import {Nodes, Parents} from 'hast'
* @import {State} from '../index.js'
*/
import {zwitch} from 'zwitch'
import {comment} from './comment.js'
import {doctype} from './doctype.js'
import {element} from './element.js'
import {raw} from './raw.js'
import {root} from './root.js'
import {text} from './text.js'
/**
* @type {(node: Nodes, index: number | undefined, parent: Parents | undefined, state: State) => string}
*/
export const handle = zwitch('type', {
invalid,
unknown,
handlers: {comment, doctype, element, raw, root, text}
})
/**
* Fail when a non-node is found in the tree.
*
* @param {unknown} node
* Unknown value.
* @returns {never}
* Never.
*/
function invalid(node) {
throw new Error('Expected node, not `' + node + '`')
}
/**
* Fail when a node with an unknown type is found in the tree.
*
* @param {unknown} node_
* Unknown node.
* @returns {never}
* Never.
*/
function unknown(node_) {
// `type` is guaranteed by runtime JS.
const node = /** @type {Nodes} */ (node_)
throw new Error('Cannot compile unknown node `' + node.type + '`')
}

19
node_modules/hast-util-to-html/lib/handle/raw.d.ts generated vendored Normal file
View File

@@ -0,0 +1,19 @@
/**
* Serialize a raw node.
*
* @param {Raw} node
* Node to handle.
* @param {number | undefined} index
* Index of `node` in `parent.
* @param {Parents | undefined} parent
* Parent of `node`.
* @param {State} state
* Info passed around about the current state.
* @returns {string}
* Serialized node.
*/
export function raw(node: Raw, index: number | undefined, parent: Parents | undefined, state: State): string;
import type { Raw } from 'mdast-util-to-hast';
import type { Parents } from 'hast';
import type { State } from '../index.js';
//# sourceMappingURL=raw.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"raw.d.ts","sourceRoot":"","sources":["raw.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;GAaG;AACH,0BAXW,GAAG,SAEH,MAAM,GAAG,SAAS,UAElB,OAAO,GAAG,SAAS,SAEnB,KAAK,GAEH,MAAM,CAOlB;yBAxBqB,oBAAoB;6BADhB,MAAM;2BAER,aAAa"}

27
node_modules/hast-util-to-html/lib/handle/raw.js generated vendored Normal file
View File

@@ -0,0 +1,27 @@
/**
* @import {Parents} from 'hast'
* @import {Raw} from 'mdast-util-to-hast'
* @import {State} from '../index.js'
*/
import {text} from './text.js'
/**
* Serialize a raw node.
*
* @param {Raw} node
* Node to handle.
* @param {number | undefined} index
* Index of `node` in `parent.
* @param {Parents | undefined} parent
* Parent of `node`.
* @param {State} state
* Info passed around about the current state.
* @returns {string}
* Serialized node.
*/
export function raw(node, index, parent, state) {
return state.settings.allowDangerousHtml
? node.value
: text(node, index, parent, state)
}

23
node_modules/hast-util-to-html/lib/handle/root.d.ts generated vendored Normal file
View File

@@ -0,0 +1,23 @@
/**
* @import {Parents, Root} from 'hast'
* @import {State} from '../index.js'
*/
/**
* Serialize a root.
*
* @param {Root} node
* Node to handle.
* @param {number | undefined} _1
* Index of `node` in `parent.
* @param {Parents | undefined} _2
* Parent of `node`.
* @param {State} state
* Info passed around about the current state.
* @returns {string}
* Serialized node.
*/
export function root(node: Root, _1: number | undefined, _2: Parents | undefined, state: State): string;
import type { Root } from 'hast';
import type { Parents } from 'hast';
import type { State } from '../index.js';
//# sourceMappingURL=root.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"root.d.ts","sourceRoot":"","sources":["root.js"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;GAaG;AACH,2BAXW,IAAI,MAEJ,MAAM,GAAG,SAAS,MAElB,OAAO,GAAG,SAAS,SAEnB,KAAK,GAEH,MAAM,CAKlB;0BApB+B,MAAM;6BAAN,MAAM;2BACd,aAAa"}

22
node_modules/hast-util-to-html/lib/handle/root.js generated vendored Normal file
View File

@@ -0,0 +1,22 @@
/**
* @import {Parents, Root} from 'hast'
* @import {State} from '../index.js'
*/
/**
* Serialize a root.
*
* @param {Root} node
* Node to handle.
* @param {number | undefined} _1
* Index of `node` in `parent.
* @param {Parents | undefined} _2
* Parent of `node`.
* @param {State} state
* Info passed around about the current state.
* @returns {string}
* Serialized node.
*/
export function root(node, _1, _2, state) {
return state.all(node)
}

20
node_modules/hast-util-to-html/lib/handle/text.d.ts generated vendored Normal file
View File

@@ -0,0 +1,20 @@
/**
* Serialize a text node.
*
* @param {Raw | Text} node
* Node to handle.
* @param {number | undefined} _
* Index of `node` in `parent.
* @param {Parents | undefined} parent
* Parent of `node`.
* @param {State} state
* Info passed around about the current state.
* @returns {string}
* Serialized node.
*/
export function text(node: Raw | Text, _: number | undefined, parent: Parents | undefined, state: State): string;
import type { Raw } from 'mdast-util-to-hast';
import type { Text } from 'hast';
import type { Parents } from 'hast';
import type { State } from '../index.js';
//# sourceMappingURL=text.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["text.js"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;GAaG;AACH,2BAXW,GAAG,GAAG,IAAI,KAEV,MAAM,GAAG,SAAS,UAElB,OAAO,GAAG,SAAS,SAEnB,KAAK,GAEH,MAAM,CAelB;yBAnCqB,oBAAoB;0BADV,MAAM;6BAAN,MAAM;2BAEd,aAAa"}

38
node_modules/hast-util-to-html/lib/handle/text.js generated vendored Normal file
View File

@@ -0,0 +1,38 @@
/**
* @import {Parents, Text} from 'hast'
* @import {Raw} from 'mdast-util-to-hast'
* @import {State} from '../index.js'
*/
import {stringifyEntities} from 'stringify-entities'
// Declare array as variable so it can be cached by `stringifyEntities`
const textEntitySubset = ['<', '&']
/**
* Serialize a text node.
*
* @param {Raw | Text} node
* Node to handle.
* @param {number | undefined} _
* Index of `node` in `parent.
* @param {Parents | undefined} parent
* Parent of `node`.
* @param {State} state
* Info passed around about the current state.
* @returns {string}
* Serialized node.
*/
export function text(node, _, parent, state) {
// Check if content of `node` should be escaped.
return parent &&
parent.type === 'element' &&
(parent.tagName === 'script' || parent.tagName === 'style')
? node.value
: stringifyEntities(
node.value,
Object.assign({}, state.settings.characterReferences, {
subset: textEntitySubset
})
)
}

223
node_modules/hast-util-to-html/lib/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,223 @@
/**
* Serialize hast as HTML.
*
* @param {Array<RootContent> | Nodes} tree
* Tree to serialize.
* @param {Options | null | undefined} [options]
* Configuration (optional).
* @returns {string}
* Serialized HTML.
*/
export function toHtml(tree: Array<RootContent> | Nodes, options?: Options | null | undefined): string;
/**
* Serialize all children of `parent`.
*
* @this {State}
* Info passed around about the current state.
* @param {Parents | undefined} parent
* Parent whose children to serialize.
* @returns {string}
*/
export function all(this: State, parent: Parents | undefined): string;
export type CharacterReferences = Omit<StringifyEntitiesOptions, "attribute" | "escapeOnly" | "subset">;
/**
* Configuration.
*/
export type Options = {
/**
* Do not encode some characters which cause XSS vulnerabilities in older
* browsers (default: `false`).
*
* > ⚠️ **Danger**: only set this if you completely trust the content.
*/
allowDangerousCharacters?: boolean | null | undefined;
/**
* Allow `raw` nodes and insert them as raw HTML (default: `false`).
*
* When `false`, `Raw` nodes are encoded.
*
* > ⚠️ **Danger**: only set this if you completely trust the content.
*/
allowDangerousHtml?: boolean | null | undefined;
/**
* Do not encode characters which cause parse errors (even though they work),
* to save bytes (default: `false`).
*
* Not used in the SVG space.
*
* > 👉 **Note**: intentionally creates parse errors in markup (how parse
* > errors are handled is well defined, so this works but isnt pretty).
*/
allowParseErrors?: boolean | null | undefined;
/**
* Use “bogus comments” instead of comments to save byes: `<?charlie>`
* instead of `<!--charlie-->` (default: `false`).
*
* > 👉 **Note**: intentionally creates parse errors in markup (how parse
* > errors are handled is well defined, so this works but isnt pretty).
*/
bogusComments?: boolean | null | undefined;
/**
* Configure how to serialize character references (optional).
*/
characterReferences?: CharacterReferences | null | undefined;
/**
* Close SVG elements without any content with slash (`/`) on the opening tag
* instead of an end tag: `<circle />` instead of `<circle></circle>`
* (default: `false`).
*
* See `tightSelfClosing` to control whether a space is used before the
* slash.
*
* Not used in the HTML space.
*/
closeEmptyElements?: boolean | null | undefined;
/**
* Close self-closing nodes with an extra slash (`/`): `<img />` instead of
* `<img>` (default: `false`).
*
* See `tightSelfClosing` to control whether a space is used before the
* slash.
*
* Not used in the SVG space.
*/
closeSelfClosing?: boolean | null | undefined;
/**
* Collapse empty attributes: get `class` instead of `class=""` (default:
* `false`).
*
* Not used in the SVG space.
*
* > 👉 **Note**: boolean attributes (such as `hidden`) are always collapsed.
*/
collapseEmptyAttributes?: boolean | null | undefined;
/**
* Omit optional opening and closing tags (default: `false`).
*
* For example, in `<ol><li>one</li><li>two</li></ol>`, both `</li>` closing
* tags can be omitted.
* The first because its followed by another `li`, the last because its
* followed by nothing.
*
* Not used in the SVG space.
*/
omitOptionalTags?: boolean | null | undefined;
/**
* Leave attributes unquoted if that results in less bytes (default: `false`).
*
* Not used in the SVG space.
*/
preferUnquoted?: boolean | null | undefined;
/**
* Use the other quote if that results in less bytes (default: `false`).
*/
quoteSmart?: boolean | null | undefined;
/**
* Preferred quote to use (default: `'"'`).
*/
quote?: Quote | null | undefined;
/**
* When an `<svg>` element is found in the HTML space, this package already
* automatically switches to and from the SVG space when entering and exiting
* it (default: `'html'`).
*
* > 👉 **Note**: hast is not XML.
* > It supports SVG as embedded in HTML.
* > It does not support the features available in XML.
* > Passing SVG might break but fragments of modern SVG should be fine.
* > Use [`xast`][xast] if you need to support SVG as XML.
*/
space?: Space | null | undefined;
/**
* Join attributes together, without whitespace, if possible: get
* `class="a b"title="c d"` instead of `class="a b" title="c d"` to save
* bytes (default: `false`).
*
* Not used in the SVG space.
*
* > 👉 **Note**: intentionally creates parse errors in markup (how parse
* > errors are handled is well defined, so this works but isnt pretty).
*/
tightAttributes?: boolean | null | undefined;
/**
* Join known comma-separated attribute values with just a comma (`,`),
* instead of padding them on the right as well (`,␠`, where `␠` represents a
* space) (default: `false`).
*/
tightCommaSeparatedLists?: boolean | null | undefined;
/**
* Drop unneeded spaces in doctypes: `<!doctypehtml>` instead of
* `<!doctype html>` to save bytes (default: `false`).
*
* > 👉 **Note**: intentionally creates parse errors in markup (how parse
* > errors are handled is well defined, so this works but isnt pretty).
*/
tightDoctype?: boolean | null | undefined;
/**
* Do not use an extra space when closing self-closing elements: `<img/>`
* instead of `<img />` (default: `false`).
*
* > 👉 **Note**: only used if `closeSelfClosing: true` or
* > `closeEmptyElements: true`.
*/
tightSelfClosing?: boolean | null | undefined;
/**
* Use a `<!DOCTYPE…` instead of `<!doctype…` (default: `false`).
*
* Useless except for XHTML.
*/
upperDoctype?: boolean | null | undefined;
/**
* Tag names of elements to serialize without closing tag (default: `html-void-elements`).
*
* Not used in the SVG space.
*
* > 👉 **Note**: Its highly unlikely that you want to pass this, because
* > hast is not for XML, and HTML will not add more void elements.
*/
voids?: ReadonlyArray<string> | null | undefined;
};
/**
* HTML quotes for attribute values.
*/
export type Quote = "\"" | "'";
export type Settings = Omit<Required<{ [key in keyof Options]: Exclude<Options[key], null | undefined>; }>, "space" | "quote">;
/**
* Namespace.
*/
export type Space = "html" | "svg";
/**
* Info passed around about the current state.
*/
export type State = {
/**
* Serialize the children of a parent node.
*/
all: (node: Parents | undefined) => string;
/**
* Alternative quote.
*/
alternative: Quote;
/**
* Serialize one node.
*/
one: (node: Nodes, index: number | undefined, parent: Parents | undefined) => string;
/**
* Preferred quote.
*/
quote: Quote;
/**
* Current schema.
*/
schema: Schema;
/**
* User configuration.
*/
settings: Settings;
};
import type { RootContent } from 'hast';
import type { Nodes } from 'hast';
import type { Parents } from 'hast';
import type { Options as StringifyEntitiesOptions } from 'stringify-entities';
import type { Schema } from 'property-information';
//# sourceMappingURL=index.d.ts.map

1
node_modules/hast-util-to-html/lib/index.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":"AAmKA;;;;;;;;;GASG;AACH,6BAPW,KAAK,CAAC,WAAW,CAAC,GAAG,KAAK,YAE1B,OAAO,GAAG,IAAI,GAAG,SAAS,GAExB,MAAM,CA8ClB;AAoBD;;;;;;;;GAQG;AACH,yCAJW,OAAO,GAAG,SAAS,GAEjB,MAAM,CAalB;kCAzPY,IAAI,CAAC,wBAAwB,EAAE,WAAW,GAAG,YAAY,GAAG,QAAQ,CAAC;;;;;;;;;;;+BAIpE,OAAO,GAAG,IAAI,GAAG,SAAS;;;;;;;;yBAK1B,OAAO,GAAG,IAAI,GAAG,SAAS;;;;;;;;;;uBAM1B,OAAO,GAAG,IAAI,GAAG,SAAS;;;;;;;;oBAQ1B,OAAO,GAAG,IAAI,GAAG,SAAS;;;;0BAM1B,mBAAmB,GAAG,IAAI,GAAG,SAAS;;;;;;;;;;;yBAEtC,OAAO,GAAG,IAAI,GAAG,SAAS;;;;;;;;;;uBAS1B,OAAO,GAAG,IAAI,GAAG,SAAS;;;;;;;;;8BAQ1B,OAAO,GAAG,IAAI,GAAG,SAAS;;;;;;;;;;;uBAO1B,OAAO,GAAG,IAAI,GAAG,SAAS;;;;;;qBAS1B,OAAO,GAAG,IAAI,GAAG,SAAS;;;;iBAI1B,OAAO,GAAG,IAAI,GAAG,SAAS;;;;YAE1B,KAAK,GAAG,IAAI,GAAG,SAAS;;;;;;;;;;;;YAExB,KAAK,GAAG,IAAI,GAAG,SAAS;;;;;;;;;;;sBAUxB,OAAO,GAAG,IAAI,GAAG,SAAS;;;;;;+BAS1B,OAAO,GAAG,IAAI,GAAG,SAAS;;;;;;;;mBAI1B,OAAO,GAAG,IAAI,GAAG,SAAS;;;;;;;;uBAM1B,OAAO,GAAG,IAAI,GAAG,SAAS;;;;;;mBAM1B,OAAO,GAAG,IAAI,GAAG,SAAS;;;;;;;;;YAI1B,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,SAAS;;;;;oBAQzC,IAAG,GAAG,GAAG;uBAGT,IAAI,CAAC,QAAQ,CAAC,GAAE,GAAG,IAAI,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC,GAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;;;;oBAEpG,MAAM,GAAG,KAAK;;;;;;;;SAKb,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,KAAK,MAAM;;;;iBAErC,KAAK;;;;SAEL,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,OAAO,GAAG,SAAS,KAAK,MAAM;;;;WAE/E,KAAK;;;;YAEL,MAAM;;;;cAEN,QAAQ;;iCAjJwB,MAAM;2BAAN,MAAM;6BAAN,MAAM;yDAEE,oBAAoB;4BADjD,sBAAsB"}

257
node_modules/hast-util-to-html/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,257 @@
/**
* @import {Nodes, Parents, RootContent} from 'hast'
* @import {Schema} from 'property-information'
* @import {Options as StringifyEntitiesOptions} from 'stringify-entities'
*/
/**
* @typedef {Omit<StringifyEntitiesOptions, 'attribute' | 'escapeOnly' | 'subset'>} CharacterReferences
*
* @typedef Options
* Configuration.
* @property {boolean | null | undefined} [allowDangerousCharacters=false]
* Do not encode some characters which cause XSS vulnerabilities in older
* browsers (default: `false`).
*
* > ⚠️ **Danger**: only set this if you completely trust the content.
* @property {boolean | null | undefined} [allowDangerousHtml=false]
* Allow `raw` nodes and insert them as raw HTML (default: `false`).
*
* When `false`, `Raw` nodes are encoded.
*
* > ⚠️ **Danger**: only set this if you completely trust the content.
* @property {boolean | null | undefined} [allowParseErrors=false]
* Do not encode characters which cause parse errors (even though they work),
* to save bytes (default: `false`).
*
* Not used in the SVG space.
*
* > 👉 **Note**: intentionally creates parse errors in markup (how parse
* > errors are handled is well defined, so this works but isnt pretty).
* @property {boolean | null | undefined} [bogusComments=false]
* Use “bogus comments” instead of comments to save byes: `<?charlie>`
* instead of `<!--charlie-->` (default: `false`).
*
* > 👉 **Note**: intentionally creates parse errors in markup (how parse
* > errors are handled is well defined, so this works but isnt pretty).
* @property {CharacterReferences | null | undefined} [characterReferences]
* Configure how to serialize character references (optional).
* @property {boolean | null | undefined} [closeEmptyElements=false]
* Close SVG elements without any content with slash (`/`) on the opening tag
* instead of an end tag: `<circle />` instead of `<circle></circle>`
* (default: `false`).
*
* See `tightSelfClosing` to control whether a space is used before the
* slash.
*
* Not used in the HTML space.
* @property {boolean | null | undefined} [closeSelfClosing=false]
* Close self-closing nodes with an extra slash (`/`): `<img />` instead of
* `<img>` (default: `false`).
*
* See `tightSelfClosing` to control whether a space is used before the
* slash.
*
* Not used in the SVG space.
* @property {boolean | null | undefined} [collapseEmptyAttributes=false]
* Collapse empty attributes: get `class` instead of `class=""` (default:
* `false`).
*
* Not used in the SVG space.
*
* > 👉 **Note**: boolean attributes (such as `hidden`) are always collapsed.
* @property {boolean | null | undefined} [omitOptionalTags=false]
* Omit optional opening and closing tags (default: `false`).
*
* For example, in `<ol><li>one</li><li>two</li></ol>`, both `</li>` closing
* tags can be omitted.
* The first because its followed by another `li`, the last because its
* followed by nothing.
*
* Not used in the SVG space.
* @property {boolean | null | undefined} [preferUnquoted=false]
* Leave attributes unquoted if that results in less bytes (default: `false`).
*
* Not used in the SVG space.
* @property {boolean | null | undefined} [quoteSmart=false]
* Use the other quote if that results in less bytes (default: `false`).
* @property {Quote | null | undefined} [quote='"']
* Preferred quote to use (default: `'"'`).
* @property {Space | null | undefined} [space='html']
* When an `<svg>` element is found in the HTML space, this package already
* automatically switches to and from the SVG space when entering and exiting
* it (default: `'html'`).
*
* > 👉 **Note**: hast is not XML.
* > It supports SVG as embedded in HTML.
* > It does not support the features available in XML.
* > Passing SVG might break but fragments of modern SVG should be fine.
* > Use [`xast`][xast] if you need to support SVG as XML.
* @property {boolean | null | undefined} [tightAttributes=false]
* Join attributes together, without whitespace, if possible: get
* `class="a b"title="c d"` instead of `class="a b" title="c d"` to save
* bytes (default: `false`).
*
* Not used in the SVG space.
*
* > 👉 **Note**: intentionally creates parse errors in markup (how parse
* > errors are handled is well defined, so this works but isnt pretty).
* @property {boolean | null | undefined} [tightCommaSeparatedLists=false]
* Join known comma-separated attribute values with just a comma (`,`),
* instead of padding them on the right as well (`,␠`, where `␠` represents a
* space) (default: `false`).
* @property {boolean | null | undefined} [tightDoctype=false]
* Drop unneeded spaces in doctypes: `<!doctypehtml>` instead of
* `<!doctype html>` to save bytes (default: `false`).
*
* > 👉 **Note**: intentionally creates parse errors in markup (how parse
* > errors are handled is well defined, so this works but isnt pretty).
* @property {boolean | null | undefined} [tightSelfClosing=false]
* Do not use an extra space when closing self-closing elements: `<img/>`
* instead of `<img />` (default: `false`).
*
* > 👉 **Note**: only used if `closeSelfClosing: true` or
* > `closeEmptyElements: true`.
* @property {boolean | null | undefined} [upperDoctype=false]
* Use a `<!DOCTYPE…` instead of `<!doctype…` (default: `false`).
*
* Useless except for XHTML.
* @property {ReadonlyArray<string> | null | undefined} [voids]
* Tag names of elements to serialize without closing tag (default: `html-void-elements`).
*
* Not used in the SVG space.
*
* > 👉 **Note**: Its highly unlikely that you want to pass this, because
* > hast is not for XML, and HTML will not add more void elements.
*
* @typedef {'"' | "'"} Quote
* HTML quotes for attribute values.
*
* @typedef {Omit<Required<{[key in keyof Options]: Exclude<Options[key], null | undefined>}>, 'space' | 'quote'>} Settings
*
* @typedef {'html' | 'svg'} Space
* Namespace.
*
* @typedef State
* Info passed around about the current state.
* @property {(node: Parents | undefined) => string} all
* Serialize the children of a parent node.
* @property {Quote} alternative
* Alternative quote.
* @property {(node: Nodes, index: number | undefined, parent: Parents | undefined) => string} one
* Serialize one node.
* @property {Quote} quote
* Preferred quote.
* @property {Schema} schema
* Current schema.
* @property {Settings} settings
* User configuration.
*/
import {htmlVoidElements} from 'html-void-elements'
import {html, svg} from 'property-information'
import {handle} from './handle/index.js'
/** @type {Options} */
const emptyOptions = {}
/** @type {CharacterReferences} */
const emptyCharacterReferences = {}
/** @type {Array<never>} */
const emptyChildren = []
/**
* Serialize hast as HTML.
*
* @param {Array<RootContent> | Nodes} tree
* Tree to serialize.
* @param {Options | null | undefined} [options]
* Configuration (optional).
* @returns {string}
* Serialized HTML.
*/
export function toHtml(tree, options) {
const options_ = options || emptyOptions
const quote = options_.quote || '"'
const alternative = quote === '"' ? "'" : '"'
if (quote !== '"' && quote !== "'") {
throw new Error('Invalid quote `' + quote + '`, expected `\'` or `"`')
}
/** @type {State} */
const state = {
one,
all,
settings: {
omitOptionalTags: options_.omitOptionalTags || false,
allowParseErrors: options_.allowParseErrors || false,
allowDangerousCharacters: options_.allowDangerousCharacters || false,
quoteSmart: options_.quoteSmart || false,
preferUnquoted: options_.preferUnquoted || false,
tightAttributes: options_.tightAttributes || false,
upperDoctype: options_.upperDoctype || false,
tightDoctype: options_.tightDoctype || false,
bogusComments: options_.bogusComments || false,
tightCommaSeparatedLists: options_.tightCommaSeparatedLists || false,
tightSelfClosing: options_.tightSelfClosing || false,
collapseEmptyAttributes: options_.collapseEmptyAttributes || false,
allowDangerousHtml: options_.allowDangerousHtml || false,
voids: options_.voids || htmlVoidElements,
characterReferences:
options_.characterReferences || emptyCharacterReferences,
closeSelfClosing: options_.closeSelfClosing || false,
closeEmptyElements: options_.closeEmptyElements || false
},
schema: options_.space === 'svg' ? svg : html,
quote,
alternative
}
return state.one(
Array.isArray(tree) ? {type: 'root', children: tree} : tree,
undefined,
undefined
)
}
/**
* Serialize a node.
*
* @this {State}
* Info passed around about the current state.
* @param {Nodes} node
* Node to handle.
* @param {number | undefined} index
* Index of `node` in `parent.
* @param {Parents | undefined} parent
* Parent of `node`.
* @returns {string}
* Serialized node.
*/
function one(node, index, parent) {
return handle(node, index, parent, this)
}
/**
* Serialize all children of `parent`.
*
* @this {State}
* Info passed around about the current state.
* @param {Parents | undefined} parent
* Parent whose children to serialize.
* @returns {string}
*/
export function all(parent) {
/** @type {Array<string>} */
const results = []
const children = (parent && parent.children) || emptyChildren
let index = -1
while (++index < children.length) {
results[index] = this.one(children[index], index, parent)
}
return results.join('')
}

View File

@@ -0,0 +1,2 @@
export const closing: import("./omission.js").OmitHandle;
//# sourceMappingURL=closing.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"closing.d.ts","sourceRoot":"","sources":["closing.js"],"names":[],"mappings":"AAQA,yDAoBE"}

358
node_modules/hast-util-to-html/lib/omission/closing.js generated vendored Normal file
View File

@@ -0,0 +1,358 @@
/**
* @import {Element, Parents} from 'hast'
*/
import {whitespace} from 'hast-util-whitespace'
import {siblingAfter} from './util/siblings.js'
import {omission} from './omission.js'
export const closing = omission({
body,
caption: headOrColgroupOrCaption,
colgroup: headOrColgroupOrCaption,
dd,
dt,
head: headOrColgroupOrCaption,
html,
li,
optgroup,
option,
p,
rp: rubyElement,
rt: rubyElement,
tbody,
td: cells,
tfoot,
th: cells,
thead,
tr
})
/**
* Macro for `</head>`, `</colgroup>`, and `</caption>`.
*
* @param {Element} _
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the closing tag can be omitted.
*/
function headOrColgroupOrCaption(_, index, parent) {
const next = siblingAfter(parent, index, true)
return (
!next ||
(next.type !== 'comment' &&
!(next.type === 'text' && whitespace(next.value.charAt(0))))
)
}
/**
* Whether to omit `</html>`.
*
* @param {Element} _
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the closing tag can be omitted.
*/
function html(_, index, parent) {
const next = siblingAfter(parent, index)
return !next || next.type !== 'comment'
}
/**
* Whether to omit `</body>`.
*
* @param {Element} _
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the closing tag can be omitted.
*/
function body(_, index, parent) {
const next = siblingAfter(parent, index)
return !next || next.type !== 'comment'
}
/**
* Whether to omit `</p>`.
*
* @param {Element} _
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the closing tag can be omitted.
*/
function p(_, index, parent) {
const next = siblingAfter(parent, index)
return next
? next.type === 'element' &&
(next.tagName === 'address' ||
next.tagName === 'article' ||
next.tagName === 'aside' ||
next.tagName === 'blockquote' ||
next.tagName === 'details' ||
next.tagName === 'div' ||
next.tagName === 'dl' ||
next.tagName === 'fieldset' ||
next.tagName === 'figcaption' ||
next.tagName === 'figure' ||
next.tagName === 'footer' ||
next.tagName === 'form' ||
next.tagName === 'h1' ||
next.tagName === 'h2' ||
next.tagName === 'h3' ||
next.tagName === 'h4' ||
next.tagName === 'h5' ||
next.tagName === 'h6' ||
next.tagName === 'header' ||
next.tagName === 'hgroup' ||
next.tagName === 'hr' ||
next.tagName === 'main' ||
next.tagName === 'menu' ||
next.tagName === 'nav' ||
next.tagName === 'ol' ||
next.tagName === 'p' ||
next.tagName === 'pre' ||
next.tagName === 'section' ||
next.tagName === 'table' ||
next.tagName === 'ul')
: !parent ||
// Confusing parent.
!(
parent.type === 'element' &&
(parent.tagName === 'a' ||
parent.tagName === 'audio' ||
parent.tagName === 'del' ||
parent.tagName === 'ins' ||
parent.tagName === 'map' ||
parent.tagName === 'noscript' ||
parent.tagName === 'video')
)
}
/**
* Whether to omit `</li>`.
*
* @param {Element} _
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the closing tag can be omitted.
*/
function li(_, index, parent) {
const next = siblingAfter(parent, index)
return !next || (next.type === 'element' && next.tagName === 'li')
}
/**
* Whether to omit `</dt>`.
*
* @param {Element} _
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the closing tag can be omitted.
*/
function dt(_, index, parent) {
const next = siblingAfter(parent, index)
return Boolean(
next &&
next.type === 'element' &&
(next.tagName === 'dt' || next.tagName === 'dd')
)
}
/**
* Whether to omit `</dd>`.
*
* @param {Element} _
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the closing tag can be omitted.
*/
function dd(_, index, parent) {
const next = siblingAfter(parent, index)
return (
!next ||
(next.type === 'element' &&
(next.tagName === 'dt' || next.tagName === 'dd'))
)
}
/**
* Whether to omit `</rt>` or `</rp>`.
*
* @param {Element} _
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the closing tag can be omitted.
*/
function rubyElement(_, index, parent) {
const next = siblingAfter(parent, index)
return (
!next ||
(next.type === 'element' &&
(next.tagName === 'rp' || next.tagName === 'rt'))
)
}
/**
* Whether to omit `</optgroup>`.
*
* @param {Element} _
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the closing tag can be omitted.
*/
function optgroup(_, index, parent) {
const next = siblingAfter(parent, index)
return !next || (next.type === 'element' && next.tagName === 'optgroup')
}
/**
* Whether to omit `</option>`.
*
* @param {Element} _
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the closing tag can be omitted.
*/
function option(_, index, parent) {
const next = siblingAfter(parent, index)
return (
!next ||
(next.type === 'element' &&
(next.tagName === 'option' || next.tagName === 'optgroup'))
)
}
/**
* Whether to omit `</thead>`.
*
* @param {Element} _
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the closing tag can be omitted.
*/
function thead(_, index, parent) {
const next = siblingAfter(parent, index)
return Boolean(
next &&
next.type === 'element' &&
(next.tagName === 'tbody' || next.tagName === 'tfoot')
)
}
/**
* Whether to omit `</tbody>`.
*
* @param {Element} _
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the closing tag can be omitted.
*/
function tbody(_, index, parent) {
const next = siblingAfter(parent, index)
return (
!next ||
(next.type === 'element' &&
(next.tagName === 'tbody' || next.tagName === 'tfoot'))
)
}
/**
* Whether to omit `</tfoot>`.
*
* @param {Element} _
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the closing tag can be omitted.
*/
function tfoot(_, index, parent) {
return !siblingAfter(parent, index)
}
/**
* Whether to omit `</tr>`.
*
* @param {Element} _
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the closing tag can be omitted.
*/
function tr(_, index, parent) {
const next = siblingAfter(parent, index)
return !next || (next.type === 'element' && next.tagName === 'tr')
}
/**
* Whether to omit `</td>` or `</th>`.
*
* @param {Element} _
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the closing tag can be omitted.
*/
function cells(_, index, parent) {
const next = siblingAfter(parent, index)
return (
!next ||
(next.type === 'element' &&
(next.tagName === 'td' || next.tagName === 'th'))
)
}

View File

@@ -0,0 +1,17 @@
/**
* Factory to check if a given node can have a tag omitted.
*
* @param {Record<string, OmitHandle>} handlers
* Omission handlers, where each key is a tag name, and each value is the
* corresponding handler.
* @returns {OmitHandle}
* Whether to omit a tag of an element.
*/
export function omission(handlers: Record<string, OmitHandle>): OmitHandle;
/**
* Check if a tag can be omitted.
*/
export type OmitHandle = (element: Element, index: number | undefined, parent: Parents | undefined) => boolean;
import type { Element } from 'hast';
import type { Parents } from 'hast';
//# sourceMappingURL=omission.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"omission.d.ts","sourceRoot":"","sources":["omission.js"],"names":[],"mappings":"AAoBA;;;;;;;;GAQG;AACH,mCANW,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAGxB,UAAU,CAiBtB;;;;mCApCU,OAAO,SAEP,MAAM,GAAG,SAAS,UAElB,OAAO,GAAG,SAAS,KAEjB,OAAO;6BAZe,MAAM;6BAAN,MAAM"}

View File

@@ -0,0 +1,44 @@
/**
* @import {Element, Parents} from 'hast'
*/
/**
* @callback OmitHandle
* Check if a tag can be omitted.
* @param {Element} element
* Element to check.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether to omit a tag.
*
*/
const own = {}.hasOwnProperty
/**
* Factory to check if a given node can have a tag omitted.
*
* @param {Record<string, OmitHandle>} handlers
* Omission handlers, where each key is a tag name, and each value is the
* corresponding handler.
* @returns {OmitHandle}
* Whether to omit a tag of an element.
*/
export function omission(handlers) {
return omit
/**
* Check if a given node can have a tag omitted.
*
* @type {OmitHandle}
*/
function omit(node, index, parent) {
return (
own.call(handlers, node.tagName) &&
handlers[node.tagName](node, index, parent)
)
}
}

View File

@@ -0,0 +1,2 @@
export const opening: import("./omission.js").OmitHandle;
//# sourceMappingURL=opening.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"opening.d.ts","sourceRoot":"","sources":["opening.js"],"names":[],"mappings":"AASA,yDAME"}

148
node_modules/hast-util-to-html/lib/omission/opening.js generated vendored Normal file
View File

@@ -0,0 +1,148 @@
/**
* @import {Element, Parents} from 'hast'
*/
import {whitespace} from 'hast-util-whitespace'
import {siblingAfter, siblingBefore} from './util/siblings.js'
import {closing} from './closing.js'
import {omission} from './omission.js'
export const opening = omission({
body,
colgroup,
head,
html,
tbody
})
/**
* Whether to omit `<html>`.
*
* @param {Element} node
* Element.
* @returns {boolean}
* Whether the opening tag can be omitted.
*/
function html(node) {
const head = siblingAfter(node, -1)
return !head || head.type !== 'comment'
}
/**
* Whether to omit `<head>`.
*
* @param {Element} node
* Element.
* @returns {boolean}
* Whether the opening tag can be omitted.
*/
function head(node) {
/** @type {Set<string>} */
const seen = new Set()
// Whether `srcdoc` or not,
// make sure the content model at least doesnt have too many `base`s/`title`s.
for (const child of node.children) {
if (
child.type === 'element' &&
(child.tagName === 'base' || child.tagName === 'title')
) {
if (seen.has(child.tagName)) return false
seen.add(child.tagName)
}
}
// “May be omitted if the element is empty,
// or if the first thing inside the head element is an element.”
const child = node.children[0]
return !child || child.type === 'element'
}
/**
* Whether to omit `<body>`.
*
* @param {Element} node
* Element.
* @returns {boolean}
* Whether the opening tag can be omitted.
*/
function body(node) {
const head = siblingAfter(node, -1, true)
return (
!head ||
(head.type !== 'comment' &&
!(head.type === 'text' && whitespace(head.value.charAt(0))) &&
!(
head.type === 'element' &&
(head.tagName === 'meta' ||
head.tagName === 'link' ||
head.tagName === 'script' ||
head.tagName === 'style' ||
head.tagName === 'template')
))
)
}
/**
* Whether to omit `<colgroup>`.
* The spec describes some logic for the opening tag, but its easier to
* implement in the closing tag, to the same effect, so we handle it there
* instead.
*
* @param {Element} node
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the opening tag can be omitted.
*/
function colgroup(node, index, parent) {
const previous = siblingBefore(parent, index)
const head = siblingAfter(node, -1, true)
// Previous colgroup was already omitted.
if (
parent &&
previous &&
previous.type === 'element' &&
previous.tagName === 'colgroup' &&
closing(previous, parent.children.indexOf(previous), parent)
) {
return false
}
return Boolean(head && head.type === 'element' && head.tagName === 'col')
}
/**
* Whether to omit `<tbody>`.
*
* @param {Element} node
* Element.
* @param {number | undefined} index
* Index of element in parent.
* @param {Parents | undefined} parent
* Parent of element.
* @returns {boolean}
* Whether the opening tag can be omitted.
*/
function tbody(node, index, parent) {
const previous = siblingBefore(parent, index)
const head = siblingAfter(node, -1)
// Previous table section was already omitted.
if (
parent &&
previous &&
previous.type === 'element' &&
(previous.tagName === 'thead' || previous.tagName === 'tbody') &&
closing(previous, parent.children.indexOf(previous), parent)
) {
return false
}
return Boolean(head && head.type === 'element' && head.tagName === 'tr')
}

View File

@@ -0,0 +1,36 @@
/**
* Find applicable siblings in a direction.
*
* @template {Parents} Parent
* Parent type.
* @param {Parent | undefined} parent
* Parent.
* @param {number | undefined} index
* Index of child in `parent`.
* @param {boolean | undefined} [includeWhitespace=false]
* Whether to include whitespace (default: `false`).
* @returns {Parent extends {children: Array<infer Child>} ? Child | undefined : never}
* Child of parent.
*/
export function siblingAfter<Parent extends Parents>(parent: Parent | undefined, index: number | undefined, includeWhitespace?: boolean | undefined): Parent extends {
children: Array<infer Child>;
} ? Child | undefined : never;
/**
* Find applicable siblings in a direction.
*
* @template {Parents} Parent
* Parent type.
* @param {Parent | undefined} parent
* Parent.
* @param {number | undefined} index
* Index of child in `parent`.
* @param {boolean | undefined} [includeWhitespace=false]
* Whether to include whitespace (default: `false`).
* @returns {Parent extends {children: Array<infer Child>} ? Child | undefined : never}
* Child of parent.
*/
export function siblingBefore<Parent extends Parents>(parent: Parent | undefined, index: number | undefined, includeWhitespace?: boolean | undefined): Parent extends {
children: Array<infer Child>;
} ? Child | undefined : never;
import type { Parents } from 'hast';
//# sourceMappingURL=siblings.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"siblings.d.ts","sourceRoot":"","sources":["siblings.js"],"names":[],"mappings":"AAoBE;;;;;;;;;;;;;GAaG;AACH,6BAXuB,MAAM,SAAhB,OAAS,UAEX,MAAM,GAAG,SAAS,SAElB,MAAM,GAAG,SAAS,sBAElB,OAAO,GAAG,SAAS,GAEjB,MAAM,SAAS;IAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,KAAK,CAAC,CAAA;CAAC,GAAG,KAAK,GAAG,SAAS,GAAG,KAAK,CAiBrF;AA5BD;;;;;;;;;;;;;GAaG;AACH,8BAXuB,MAAM,SAAhB,OAAS,UAEX,MAAM,GAAG,SAAS,SAElB,MAAM,GAAG,SAAS,sBAElB,OAAO,GAAG,SAAS,GAEjB,MAAM,SAAS;IAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,KAAK,CAAC,CAAA;CAAC,GAAG,KAAK,GAAG,SAAS,GAAG,KAAK,CAiBrF;6BA/CoC,MAAM"}

View File

@@ -0,0 +1,50 @@
/**
* @import {Parents, RootContent} from 'hast'
*/
import {whitespace} from 'hast-util-whitespace'
export const siblingAfter = siblings(1)
export const siblingBefore = siblings(-1)
/** @type {Array<RootContent>} */
const emptyChildren = []
/**
* Factory to check siblings in a direction.
*
* @param {number} increment
*/
function siblings(increment) {
return sibling
/**
* Find applicable siblings in a direction.
*
* @template {Parents} Parent
* Parent type.
* @param {Parent | undefined} parent
* Parent.
* @param {number | undefined} index
* Index of child in `parent`.
* @param {boolean | undefined} [includeWhitespace=false]
* Whether to include whitespace (default: `false`).
* @returns {Parent extends {children: Array<infer Child>} ? Child | undefined : never}
* Child of parent.
*/
function sibling(parent, index, includeWhitespace) {
const siblings = parent ? parent.children : emptyChildren
let offset = (index || 0) + increment
let next = siblings[offset]
if (!includeWhitespace) {
while (next && whitespace(next)) {
offset += increment
next = siblings[offset]
}
}
// @ts-expect-error: its a correct child.
return next
}
}

22
node_modules/hast-util-to-html/license generated vendored Normal file
View File

@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) Titus Wormer <tituswormer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

106
node_modules/hast-util-to-html/package.json generated vendored Normal file
View File

@@ -0,0 +1,106 @@
{
"author": "Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)",
"bugs": "https://github.com/syntax-tree/hast-util-to-html/issues",
"contributors": [
"Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)"
],
"dependencies": {
"@types/hast": "^3.0.0",
"@types/unist": "^3.0.0",
"ccount": "^2.0.0",
"comma-separated-tokens": "^2.0.0",
"hast-util-whitespace": "^3.0.0",
"html-void-elements": "^3.0.0",
"mdast-util-to-hast": "^13.0.0",
"property-information": "^7.0.0",
"space-separated-tokens": "^2.0.0",
"stringify-entities": "^4.0.0",
"zwitch": "^2.0.4"
},
"description": "hast utility to serialize to HTML",
"devDependencies": {
"@types/node": "^22.0.0",
"c8": "^10.0.0",
"hastscript": "^9.0.0",
"prettier": "^3.0.0",
"remark-cli": "^12.0.0",
"remark-preset-wooorm": "^11.0.0",
"type-coverage": "^2.0.0",
"typescript": "^5.0.0",
"xo": "^0.60.0"
},
"exports": "./index.js",
"files": [
"index.d.ts.map",
"index.d.ts",
"index.js",
"lib/"
],
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
},
"keywords": [
"hast-util",
"hast",
"html",
"serialize",
"stringify",
"tostring",
"unist",
"utility",
"util"
],
"license": "MIT",
"name": "hast-util-to-html",
"prettier": {
"bracketSpacing": false,
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "none",
"useTabs": false
},
"remarkConfig": {
"plugins": [
"remark-preset-wooorm",
[
"remark-lint-no-html",
false
]
]
},
"repository": "syntax-tree/hast-util-to-html",
"scripts": {
"build": "tsc --build --clean && tsc --build && type-coverage",
"format": "remark --frail --output --quiet -- . && prettier --log-level warn --write -- . && xo --fix",
"test-api": "node --conditions development test/index.js",
"test-coverage": "c8 --100 --reporter lcov -- npm run test-api",
"test": "npm run build && npm run format && npm run test-coverage"
},
"sideEffects": false,
"typeCoverage": {
"atLeast": 100,
"strict": true
},
"type": "module",
"version": "9.0.5",
"xo": {
"overrides": [
{
"files": [
"test/**/*.js"
],
"rules": {
"no-await-in-loop": "off"
}
}
],
"prettier": true,
"rules": {
"complexity": "off",
"unicorn/prefer-at": "off",
"unicorn/prefer-string-replace-all": "off"
}
}
}

486
node_modules/hast-util-to-html/readme.md generated vendored Normal file
View File

@@ -0,0 +1,486 @@
# hast-util-to-html
[![Build][badge-build-image]][badge-build-url]
[![Coverage][badge-coverage-image]][badge-coverage-url]
[![Downloads][badge-downloads-image]][badge-downloads-url]
[![Size][badge-size-image]][badge-size-url]
[hast][github-hast] utility to serialize hast as HTML.
## Contents
* [What is this?](#what-is-this)
* [When should I use this?](#when-should-i-use-this)
* [Install](#install)
* [Use](#use)
* [API](#api)
* [`toHtml(tree[, options])`](#tohtmltree-options)
* [`CharacterReferences`](#characterreferences)
* [`Options`](#options)
* [`Quote`](#quote-1)
* [`Space`](#space-1)
* [Syntax](#syntax)
* [Types](#types)
* [Compatibility](#compatibility)
* [Security](#security)
* [Related](#related)
* [Contribute](#contribute)
* [License](#license)
## What is this?
This package is a utility that turns a hast tree into a string of HTML.
## When should I use this?
You can use this utility when you want to get the serialized HTML that is
represented by the syntax tree,
either because youre done with the syntax tree,
or because youre integrating with another tool that does not support syntax
trees.
This utility has many options to configure how the HTML is serialized.
These options help when building tools that make output pretty (such as
formatters) or ugly (such as minifiers).
The utility [`hast-util-from-html`][github-hast-util-from-html] does the
inverse of this utility.
It turns HTML into hast.
The rehype plugin [`rehype-stringify`][github-rehype-stringify] wraps this
utility to also serialize HTML at a higher-level (easier) abstraction.
## Install
This package is [ESM only][github-gist-esm].
In Node.js (version 16+),
install with [npm][npmjs-install]:
```sh
npm install hast-util-to-html
```
In Deno with [`esm.sh`][esmsh]:
```js
import {toHtml} from 'https://esm.sh/hast-util-to-html@9'
```
In browsers with [`esm.sh`][esmsh]:
```html
<script type="module">
import {toHtml} from 'https://esm.sh/hast-util-to-html@9?bundle'
</script>
```
## Use
```js
import {h} from 'hastscript'
import {toHtml} from 'hast-util-to-html'
const tree = h('.alpha', [
'bravo ',
h('b', 'charlie'),
' delta ',
h('a.echo', {download: true}, 'foxtrot')
])
console.log(toHtml(tree))
```
Yields:
```html
<div class="alpha">bravo <b>charlie</b> delta <a class="echo" download>foxtrot</a></div>
```
## API
This package exports the identifier [`toHtml`][api-to-html].
There is no default export.
### `toHtml(tree[, options])`
Serialize hast as HTML.
###### Parameters
* `tree`
([`Node`][github-hast-nodes] or `Array<Node>`)
— tree to serialize
* `options`
([`Options`][api-options], optional)
— configuration
###### Returns
Serialized HTML (`string`).
### `CharacterReferences`
How to serialize character references (TypeScript type).
##### Fields
###### `useNamedReferences`
Prefer named character references (`&amp;`) where possible
(`boolean`, default: `false`).
###### `omitOptionalSemicolons`
Whether to omit semicolons when possible
(`boolean`, default: `false`).
> ⚠️ **Note**:
> this creates what HTML calls “parse errors” but is otherwise still valid HTML:
> dont use this except when building a minifier;
> omitting semicolons is possible for certain named and numeric references in
> some cases.
###### `useShortestReferences`
Prefer the shortest possible reference,
if that results in less bytes
(`boolean`, default: `false`).
> ⚠️ **Note**:
> `useNamedReferences` can be omitted when using `useShortestReferences`.
### `Options`
Configuration (TypeScript type).
##### Fields
###### `allowDangerousCharacters`
Do not encode some characters which cause XSS vulnerabilities in older browsers
(`boolean`, default: `false`).
> ⚠️ **Danger**:
> only set this if you completely trust the content.
###### `allowDangerousHtml`
Allow `raw` nodes and insert them as raw HTML
(`boolean`, default: `false`).
When `false`,
`Raw` nodes are encoded.
> ⚠️ **Danger**:
> only set this if you completely trust the content.
###### `allowParseErrors`
Do not encode characters which cause parse errors
(even though they work),
to save bytes
(`boolean`, default: `false`).
Not used in the SVG space.
> 👉 **Note**:
> intentionally creates parse errors in markup
> (how parse errors are handled is well defined,
> so this works but isnt pretty).
###### `bogusComments`
Use “bogus comments” instead of comments to save byes:
`<?charlie>` instead of `<!--charlie-->`
(`boolean`, default: `false`).
> 👉 **Note**:
> intentionally creates parse errors in markup
> (how parse errors are handled is well defined,
> so this works but isnt pretty).
###### `characterReferences`
Configure how to serialize character references
([`CharacterReferences`][api-character-references], optional).
###### `closeEmptyElements`
Close SVG elements without any content with slash (`/`) on the opening tag
instead of an end tag:
`<circle />` instead of `<circle></circle>`
(`boolean`, default: `false`).
See `tightSelfClosing` to control whether a space is used before the slash.
Not used in the HTML space.
###### `closeSelfClosing`
Close self-closing nodes with an extra slash (`/`):
`<img />` instead of `<img>`
(`boolean`, default: `false`).
See `tightSelfClosing` to control whether a space is used before the slash.
Not used in the SVG space.
###### `collapseEmptyAttributes`
Collapse empty attributes:
get `class` instead of `class=""`
(`boolean`, default: `false`).
Not used in the SVG space.
> 👉 **Note**:
> boolean attributes
> (such as `hidden`)
> are always collapsed.
###### `omitOptionalTags`
Omit optional opening and closing tags
(`boolean`, default: `false`).
For example,
in `<ol><li>one</li><li>two</li></ol>`,
both `</li>` closing tags can be omitted.
The first because its followed by another `li`,
the last because its followed by nothing.
Not used in the SVG space.
###### `preferUnquoted`
Leave attributes unquoted if that results in less bytes
(`boolean`, default: `false`).
Not used in the SVG space.
###### `quote`
Preferred quote to use
([`Quote`][api-quote], default: `'"'`).
###### `quoteSmart`
Use the other quote if that results in less bytes
(`boolean`, default: `false`).
###### `space`
Which space the document is in
([`Space`][api-space], default: `'html'`).
When an `<svg>` element is found in the HTML space,
this package already automatically switches to and from the SVG space when
entering and exiting it.
> 👉 **Note**:
> hast is not XML.
> It supports SVG as embedded in HTML.
> It does not support the features available in XML.
> Passing SVG might break but fragments of modern SVG should be fine.
> Use [`xast`][github-xast] if you need to support SVG as XML.
###### `tightAttributes`
Join attributes together,
without whitespace,
if possible:
get `class="a b"title="c d"` instead of `class="a b" title="c d"` to save bytes
(`boolean`, default: `false`).
Not used in the SVG space.
> 👉 **Note**:
> intentionally creates parse errors in markup
> (how parse errors are handled is well defined,
> so this works but isnt pretty).
###### `tightCommaSeparatedLists`
Join known comma-separated attribute values with just a comma (`,`),
instead of padding them on the right as well
(`,␠`, where `␠` represents a space)
(`boolean`, default: `false`).
###### `tightDoctype`
Drop unneeded spaces in doctypes:
`<!doctypehtml>` instead of `<!doctype html>` to save bytes
(`boolean`, default: `false`).
> 👉 **Note**:
> intentionally creates parse errors in markup
> (how parse errors are handled is well defined,
> so this works but isnt pretty).
###### `tightSelfClosing`
Do not use an extra space when closing self-closing elements:
`<img/>` instead of `<img />`
(`boolean`, default: `false`).
> 👉 **Note**:
> only used if `closeSelfClosing: true` or `closeEmptyElements: true`.
###### `upperDoctype`
Use a `<!DOCTYPE…` instead of `<!doctype…`
(`boolean`, default: `false`).
Useless except for XHTML.
###### `voids`
Tag names of elements to serialize without closing tag
(`Array<string>`,
default: [`html-void-elements`][github-html-void-elements]).
Not used in the SVG space.
> 👉 **Note**:
> its highly unlikely that you want to pass this,
> because hast is not for XML,
> and HTML will not add more void elements.
### `Quote`
HTML quotes for attribute values (TypeScript type).
###### Type
```ts
type Quote = '"' | "'"
```
### `Space`
Namespace (TypeScript type).
###### Type
```ts
type Space = 'html' | 'svg'
```
## Syntax
HTML is serialized according to WHATWG HTML (the living standard),
which is also followed by browsers such as Chrome and Firefox.
## Types
This package is fully typed with [TypeScript][].
It exports the additional types
[`CharacterReferences`][api-character-references],
[`Options`][api-options],
[`Quote`][api-quote],
and
[`Space`][api-space].
## Compatibility
Projects maintained by the unified collective are compatible with maintained
versions of Node.js.
When we cut a new major release,
we drop support for unmaintained versions of Node.
This means we try to keep the current release line,
`hast-util-to-html@9`,
compatible with Node.js 16.
## Security
Use of `hast-util-to-html` can open you up to a
[cross-site scripting (XSS)][wikipedia-xss] attack if the hast tree is unsafe.
Use [`hast-util-santize`][github-hast-util-sanitize] to make the hast tree
safe.
## Related
* [`hast-util-sanitize`][github-hast-util-sanitize]
— sanitize hast
## Contribute
See [`contributing.md`][health-contributing]
in
[`syntax-tree/.github`][health]
for ways to get started.
See [`support.md`][health-support] for ways to get help.
This project has a [code of conduct][health-coc].
By interacting with this repository,
organization,
or community you agree to abide by its terms.
## License
[MIT][file-license] © [Titus Wormer][wooorm]
<!-- Definitions -->
[api-character-references]: #characterreferences
[api-options]: #options
[api-quote]: #quote-1
[api-space]: #space-1
[api-to-html]: #tohtmltree-options
[badge-build-image]: https://github.com/syntax-tree/hast-util-to-html/workflows/main/badge.svg
[badge-build-url]: https://github.com/syntax-tree/hast-util-to-html/actions
[badge-coverage-image]: https://img.shields.io/codecov/c/github/syntax-tree/hast-util-to-html.svg
[badge-coverage-url]: https://codecov.io/github/syntax-tree/hast-util-to-html
[badge-downloads-image]: https://img.shields.io/npm/dm/hast-util-to-html.svg
[badge-downloads-url]: https://www.npmjs.com/package/hast-util-to-html
[badge-size-image]: https://img.shields.io/bundlejs/size/hast-util-to-html
[badge-size-url]: https://bundlejs.com/?q=hast-util-to-html
[esmsh]: https://esm.sh
[file-license]: license
[github-gist-esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
[github-hast]: https://github.com/syntax-tree/hast
[github-hast-nodes]: https://github.com/syntax-tree/hast#nodes
[github-hast-util-from-html]: https://github.com/syntax-tree/hast-util-from-html
[github-hast-util-sanitize]: https://github.com/syntax-tree/hast-util-sanitize
[github-html-void-elements]: https://github.com/wooorm/html-void-elements
[github-rehype-stringify]: https://github.com/rehypejs/rehype/tree/main/packages/rehype-stringify#readme
[github-xast]: https://github.com/syntax-tree/xast
[health]: https://github.com/syntax-tree/.github
[health-coc]: https://github.com/syntax-tree/.github/blob/main/code-of-conduct.md
[health-contributing]: https://github.com/syntax-tree/.github/blob/main/contributing.md
[health-support]: https://github.com/syntax-tree/.github/blob/main/support.md
[npmjs-install]: https://docs.npmjs.com/cli/install
[typescript]: https://www.typescriptlang.org
[wikipedia-xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
[wooorm]: https://wooorm.com