Socket
Socket
Sign inDemoInstall

mdast-util-to-hast

Package Overview
Dependencies
Maintainers
2
Versions
59
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mdast-util-to-hast - npm Package Compare versions

Comparing version 12.3.0 to 13.0.0

73

index.d.ts

@@ -1,35 +0,41 @@

import type {Literal} from 'hast'
import type {State} from './lib/state.js'
import type {Data, ElementContent, Literal, Properties} from 'hast'
// Expose types.
export type {State, Handler, Handlers, Options} from './lib/state.js'
export type {
FootnoteBackContentTemplate,
FootnoteBackLabelTemplate
} from './lib/footer.js'
export type {Handler, Handlers, Options, State} from './lib/state.js'
// To do: next major: remove.
/**
* Deprecated: use `State`.
*/
export type H = State
// Expose JS API.
export {handlers as defaultHandlers} from './lib/handlers/index.js'
// To do: next major: remove.
export {one, all} from './lib/state.js'
export {
defaultFootnoteBackContent,
defaultFootnoteBackLabel
} from './lib/footer.js'
export {toHast} from './lib/index.js'
// Expose node type.
/**
* Raw string of HTML embedded into HTML AST.
*/
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
export interface Raw extends Literal {
/**
* Node type.
* Node type of raw.
*/
type: 'raw'
/**
* Data associated with the hast raw.
*/
data?: RawData | undefined
}
/**
* Info associated with hast raw nodes by the ecosystem.
*/
export interface RawData extends Data {}
// Register nodes in content.
declare module 'hast' {
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
interface RootContentMap {
interface ElementContentMap {
/**

@@ -41,4 +47,3 @@ * Raw string of HTML embedded into HTML AST.

// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
interface ElementContentMap {
interface RootContentMap {
/**

@@ -50,1 +55,33 @@ * Raw string of HTML embedded into HTML AST.

}
// Register data on mdast.
declare module 'mdast' {
interface Data {
/**
* Field supported by `mdast-util-to-hast` to signal that a node should
* result in something with these children.
*
* When this is defined, when a parent is created, these children will
* be used.
*/
hChildren?: ElementContent[] | undefined
/**
* Field supported by `mdast-util-to-hast` to signal that a node should
* result in a particular element, instead of its default behavior.
*
* When this is defined, an element with the given tag name is created.
* For example, when setting `hName` to `'b'`, a `<b>` element is created.
*/
hName?: string | undefined
/**
* Field supported by `mdast-util-to-hast` to signal that a node should
* result in an element with these properties.
*
* When this is defined, when an element is created, these properties will
* be used.
*/
hProperties?: Properties | undefined
}
}
// Note: types exposed from `index.d.ts`.
export {handlers as defaultHandlers} from './lib/handlers/index.js'
// To do: next major: remove.
export {one, all} from './lib/state.js'
export {toHast} from './lib/index.js'
export {
defaultFootnoteBackContent,
defaultFootnoteBackLabel
} from './lib/footer.js'
/**
* Generate the default content that GitHub uses on backreferences.
*
* @param {number} _
* Index of the definition in the order that they are first referenced,
* 0-indexed.
* @param {number} rereferenceIndex
* Index of calls to the same definition, 0-indexed.
* @returns {Array<ElementContent>}
* Content.
*/
export function defaultFootnoteBackContent(_: number, rereferenceIndex: number): Array<ElementContent>;
/**
* Generate the default label that GitHub uses on backreferences.
*
* @param {number} referenceIndex
* Index of the definition in the order that they are first referenced,
* 0-indexed.
* @param {number} rereferenceIndex
* Index of calls to the same definition, 0-indexed.
* @returns {string}
* Label.
*/
export function defaultFootnoteBackLabel(referenceIndex: number, rereferenceIndex: number): string;
/**
* Generate a hast footer for called footnote definitions.

@@ -9,5 +33,49 @@ *

*/
export function footer(state: State): Element | undefined
export type Element = import('hast').Element
export type ElementContent = import('hast').ElementContent
export type State = import('./state.js').State
export function footer(state: State): Element | undefined;
export type Element = import('hast').Element;
export type ElementContent = import('hast').ElementContent;
export type State = import('./state.js').State;
/**
* Generate content for the backreference dynamically.
*
* For the following markdown:
*
* ```markdown
* Alpha[^micromark], bravo[^micromark], and charlie[^remark].
*
* [^remark]: things about remark
* [^micromark]: things about micromark
* ```
*
* This function will be called with:
*
* * `0` and `0` for the backreference from `things about micromark` to
* `alpha`, as it is the first used definition, and the first call to it
* * `0` and `1` for the backreference from `things about micromark` to
* `bravo`, as it is the first used definition, and the second call to it
* * `1` and `0` for the backreference from `things about remark` to
* `charlie`, as it is the second used definition
*/
export type FootnoteBackContentTemplate = (referenceIndex: number, rereferenceIndex: number) => Array<ElementContent> | ElementContent | string;
/**
* Generate a back label dynamically.
*
* For the following markdown:
*
* ```markdown
* Alpha[^micromark], bravo[^micromark], and charlie[^remark].
*
* [^remark]: things about remark
* [^micromark]: things about micromark
* ```
*
* This function will be called with:
*
* * `0` and `0` for the backreference from `things about micromark` to
* `alpha`, as it is the first used definition, and the first call to it
* * `0` and `1` for the backreference from `things about micromark` to
* `bravo`, as it is the first used definition, and the second call to it
* * `1` and `0` for the backreference from `things about remark` to
* `charlie`, as it is the second used definition
*/
export type FootnoteBackLabelTemplate = (referenceIndex: number, rereferenceIndex: number) => string;

@@ -8,5 +8,111 @@ /**

/**
* @callback FootnoteBackContentTemplate
* Generate content for the backreference dynamically.
*
* For the following markdown:
*
* ```markdown
* Alpha[^micromark], bravo[^micromark], and charlie[^remark].
*
* [^remark]: things about remark
* [^micromark]: things about micromark
* ```
*
* This function will be called with:
*
* * `0` and `0` for the backreference from `things about micromark` to
* `alpha`, as it is the first used definition, and the first call to it
* * `0` and `1` for the backreference from `things about micromark` to
* `bravo`, as it is the first used definition, and the second call to it
* * `1` and `0` for the backreference from `things about remark` to
* `charlie`, as it is the second used definition
* @param {number} referenceIndex
* Index of the definition in the order that they are first referenced,
* 0-indexed.
* @param {number} rereferenceIndex
* Index of calls to the same definition, 0-indexed.
* @returns {Array<ElementContent> | ElementContent | string}
* Content for the backreference when linking back from definitions to their
* reference.
*
* @callback FootnoteBackLabelTemplate
* Generate a back label dynamically.
*
* For the following markdown:
*
* ```markdown
* Alpha[^micromark], bravo[^micromark], and charlie[^remark].
*
* [^remark]: things about remark
* [^micromark]: things about micromark
* ```
*
* This function will be called with:
*
* * `0` and `0` for the backreference from `things about micromark` to
* `alpha`, as it is the first used definition, and the first call to it
* * `0` and `1` for the backreference from `things about micromark` to
* `bravo`, as it is the first used definition, and the second call to it
* * `1` and `0` for the backreference from `things about remark` to
* `charlie`, as it is the second used definition
* @param {number} referenceIndex
* Index of the definition in the order that they are first referenced,
* 0-indexed.
* @param {number} rereferenceIndex
* Index of calls to the same definition, 0-indexed.
* @returns {string}
* Back label to use when linking back from definitions to their reference.
*/
import structuredClone from '@ungap/structured-clone'
import {normalizeUri} from 'micromark-util-sanitize-uri'
/**
* Generate the default content that GitHub uses on backreferences.
*
* @param {number} _
* Index of the definition in the order that they are first referenced,
* 0-indexed.
* @param {number} rereferenceIndex
* Index of calls to the same definition, 0-indexed.
* @returns {Array<ElementContent>}
* Content.
*/
export function defaultFootnoteBackContent(_, rereferenceIndex) {
/** @type {Array<ElementContent>} */
const result = [{type: 'text', value: '↩'}]
if (rereferenceIndex > 1) {
result.push({
type: 'element',
tagName: 'sup',
properties: {},
children: [{type: 'text', value: String(rereferenceIndex)}]
})
}
return result
}
/**
* Generate the default label that GitHub uses on backreferences.
*
* @param {number} referenceIndex
* Index of the definition in the order that they are first referenced,
* 0-indexed.
* @param {number} rereferenceIndex
* Index of calls to the same definition, 0-indexed.
* @returns {string}
* Label.
*/
export function defaultFootnoteBackLabel(referenceIndex, rereferenceIndex) {
return (
'Back to reference ' +
(referenceIndex + 1) +
(rereferenceIndex > 1 ? '-' + rereferenceIndex : '')
)
}
/**
* Generate a hast footer for called footnote definitions.

@@ -19,9 +125,23 @@ *

*/
// eslint-disable-next-line complexity
export function footer(state) {
const clobberPrefix =
typeof state.options.clobberPrefix === 'string'
? state.options.clobberPrefix
: 'user-content-'
const footnoteBackContent =
state.options.footnoteBackContent || defaultFootnoteBackContent
const footnoteBackLabel =
state.options.footnoteBackLabel || defaultFootnoteBackLabel
const footnoteLabel = state.options.footnoteLabel || 'Footnotes'
const footnoteLabelTagName = state.options.footnoteLabelTagName || 'h2'
const footnoteLabelProperties = state.options.footnoteLabelProperties || {
className: ['sr-only']
}
/** @type {Array<ElementContent>} */
const listItems = []
let index = -1
let referenceIndex = -1
while (++index < state.footnoteOrder.length) {
const def = state.footnoteById[state.footnoteOrder[index]]
while (++referenceIndex < state.footnoteOrder.length) {
const def = state.footnoteById.get(state.footnoteOrder[referenceIndex])

@@ -35,9 +155,23 @@ if (!def) {

const safeId = normalizeUri(id.toLowerCase())
let referenceIndex = 0
let rereferenceIndex = 0
/** @type {Array<ElementContent>} */
const backReferences = []
const counts = state.footnoteCounts.get(id)
while (++referenceIndex <= state.footnoteCounts[id]) {
/** @type {Element} */
const backReference = {
// eslint-disable-next-line no-unmodified-loop-condition
while (counts !== undefined && ++rereferenceIndex <= counts) {
if (backReferences.length > 0) {
backReferences.push({type: 'text', value: ' '})
}
let children =
typeof footnoteBackContent === 'string'
? footnoteBackContent
: footnoteBackContent(referenceIndex, rereferenceIndex)
if (typeof children === 'string') {
children = {type: 'text', value: children}
}
backReferences.push({
type: 'element',

@@ -48,26 +182,15 @@ tagName: 'a',

'#' +
state.clobberPrefix +
clobberPrefix +
'fnref-' +
safeId +
(referenceIndex > 1 ? '-' + referenceIndex : ''),
dataFootnoteBackref: true,
className: ['data-footnote-backref'],
ariaLabel: state.footnoteBackLabel
(rereferenceIndex > 1 ? '-' + rereferenceIndex : ''),
dataFootnoteBackref: '',
ariaLabel:
typeof footnoteBackLabel === 'string'
? footnoteBackLabel
: footnoteBackLabel(referenceIndex, rereferenceIndex),
className: ['data-footnote-backref']
},
children: [{type: 'text', value: '↩'}]
}
if (referenceIndex > 1) {
backReference.children.push({
type: 'element',
tagName: 'sup',
children: [{type: 'text', value: String(referenceIndex)}]
})
}
if (backReferences.length > 0) {
backReferences.push({type: 'text', value: ' '})
}
backReferences.push(backReference)
children: Array.isArray(children) ? children : [children]
})
}

@@ -94,3 +217,3 @@

tagName: 'li',
properties: {id: state.clobberPrefix + 'fn-' + safeId},
properties: {id: clobberPrefix + 'fn-' + safeId},
children: state.wrap(content, true)

@@ -115,9 +238,8 @@ }

type: 'element',
tagName: state.footnoteLabelTagName,
tagName: footnoteLabelTagName,
properties: {
// To do: use structured clone.
...JSON.parse(JSON.stringify(state.footnoteLabelProperties)),
...structuredClone(footnoteLabelProperties),
id: 'footnote-label'
},
children: [{type: 'text', value: state.footnoteLabel}]
children: [{type: 'text', value: footnoteLabel}]
},

@@ -124,0 +246,0 @@ {type: 'text', value: '\n'},

/**
* @typedef {import('hast').Element} Element
* @typedef {import('mdast').Blockquote} Blockquote
* @typedef {import('../state.js').State} State
*/
/**
* Turn an mdast `blockquote` node into hast.

@@ -16,5 +11,5 @@ *

*/
export function blockquote(state: State, node: Blockquote): Element
export type Element = import('hast').Element
export type Blockquote = import('mdast').Blockquote
export type State = import('../state.js').State
export function blockquote(state: State, node: Blockquote): Element;
export type Element = import('hast').Element;
export type Blockquote = import('mdast').Blockquote;
export type State = import('../state.js').State;

@@ -7,2 +7,5 @@ /**

// Make VS Code show references to the above types.
''
/**

@@ -9,0 +12,0 @@ * Turn an mdast `blockquote` node into hast.

/**
* @typedef {import('hast').Element} Element
* @typedef {import('hast').Text} Text
* @typedef {import('mdast').Break} Break
* @typedef {import('../state.js').State} State
*/
/**
* Turn an mdast `break` node into hast.

@@ -17,6 +11,6 @@ *

*/
export function hardBreak(state: State, node: Break): Array<Element | Text>
export type Element = import('hast').Element
export type Text = import('hast').Text
export type Break = import('mdast').Break
export type State = import('../state.js').State
export function hardBreak(state: State, node: Break): Array<Element | Text>;
export type Element = import('hast').Element;
export type Text = import('hast').Text;
export type Break = import('mdast').Break;
export type State = import('../state.js').State;

@@ -8,2 +8,5 @@ /**

// Make VS Code show references to the above types.
''
/**

@@ -10,0 +13,0 @@ * Turn an mdast `break` node into hast.

/**
* @typedef {import('hast').Element} Element
* @typedef {import('hast').Properties} Properties
* @typedef {import('mdast').Code} Code
* @typedef {import('../state.js').State} State
*/
/**
* Turn an mdast `code` node into hast.

@@ -18,6 +11,6 @@ *

*/
export function code(state: State, node: Code): Element
export type Element = import('hast').Element
export type Properties = import('hast').Properties
export type Code = import('mdast').Code
export type State = import('../state.js').State
export function code(state: State, node: Code): Element;
export type Element = import('hast').Element;
export type Properties = import('hast').Properties;
export type Code = import('mdast').Code;
export type State = import('../state.js').State;

@@ -6,5 +6,7 @@ /**

* @typedef {import('../state.js').State} State
*/
// Make VS Code show references to the above types.
''
/**

@@ -22,10 +24,7 @@ * Turn an mdast `code` node into hast.

const value = node.value ? node.value + '\n' : ''
// To do: next major, use `node.lang` w/o regex, the splitting’s been going
// on for years in remark now.
const lang = node.lang ? node.lang.match(/^[^ \t]+(?=[ \t]|$)/) : null
/** @type {Properties} */
const properties = {}
if (lang) {
properties.className = ['language-' + lang]
if (node.lang) {
properties.className = ['language-' + node.lang]
}

@@ -32,0 +31,0 @@

/**
* @typedef {import('hast').Element} Element
* @typedef {import('mdast').Delete} Delete
* @typedef {import('../state.js').State} State
*/
/**
* Turn an mdast `delete` node into hast.

@@ -17,5 +11,5 @@ *

*/
export function strikethrough(state: State, node: Delete): Element
export type Element = import('hast').Element
export type Delete = import('mdast').Delete
export type State = import('../state.js').State
export function strikethrough(state: State, node: Delete): Element;
export type Element = import('hast').Element;
export type Delete = import('mdast').Delete;
export type State = import('../state.js').State;

@@ -5,5 +5,7 @@ /**

* @typedef {import('../state.js').State} State
*/
// Make VS Code show references to the above types.
''
/**

@@ -10,0 +12,0 @@ * Turn an mdast `delete` node into hast.

/**
* @typedef {import('hast').Element} Element
* @typedef {import('mdast').Emphasis} Emphasis
* @typedef {import('../state.js').State} State
*/
/**
* Turn an mdast `emphasis` node into hast.

@@ -16,5 +11,5 @@ *

*/
export function emphasis(state: State, node: Emphasis): Element
export type Element = import('hast').Element
export type Emphasis = import('mdast').Emphasis
export type State = import('../state.js').State
export function emphasis(state: State, node: Emphasis): Element;
export type Element = import('hast').Element;
export type Emphasis = import('mdast').Emphasis;
export type State = import('../state.js').State;

@@ -7,2 +7,5 @@ /**

// Make VS Code show references to the above types.
''
/**

@@ -9,0 +12,0 @@ * Turn an mdast `emphasis` node into hast.

@@ -11,8 +11,5 @@ /**

*/
export function footnoteReference(
state: State,
node: FootnoteReference
): Element
export type FootnoteReference = import('mdast').FootnoteReference
export type Element = import('hast').Element
export type State = import('../state.js').State
export function footnoteReference(state: State, node: FootnoteReference): Element;
export type Element = import('hast').Element;
export type FootnoteReference = import('mdast').FootnoteReference;
export type State = import('../state.js').State;
/**
* @typedef {import('hast').Element} Element
* @typedef {import('mdast').FootnoteReference} FootnoteReference
* @typedef {import('hast').Element} Element
* @typedef {import('../state.js').State} State

@@ -20,2 +20,6 @@ */

export function footnoteReference(state, node) {
const clobberPrefix =
typeof state.options.clobberPrefix === 'string'
? state.options.clobberPrefix
: 'user-content-'
const id = String(node.identifier).toUpperCase()

@@ -27,12 +31,14 @@ const safeId = normalizeUri(id.toLowerCase())

if (index === -1) {
let reuseCounter = state.footnoteCounts.get(id)
if (reuseCounter === undefined) {
reuseCounter = 0
state.footnoteOrder.push(id)
state.footnoteCounts[id] = 1
counter = state.footnoteOrder.length
} else {
state.footnoteCounts[id]++
counter = index + 1
}
const reuseCounter = state.footnoteCounts[id]
reuseCounter += 1
state.footnoteCounts.set(id, reuseCounter)

@@ -44,5 +50,5 @@ /** @type {Element} */

properties: {
href: '#' + state.clobberPrefix + 'fn-' + safeId,
href: '#' + clobberPrefix + 'fn-' + safeId,
id:
state.clobberPrefix +
clobberPrefix +
'fnref-' +

@@ -49,0 +55,0 @@ safeId +

@@ -6,3 +6,3 @@ /**

* Info passed around.
* @param {Footnote} node
* @param {Node} node
* mdast node.

@@ -12,5 +12,6 @@ * @returns {Element}

*/
export function footnote(state: State, node: Footnote): Element
export type Element = import('hast').Element
export type Footnote = import('mdast').Footnote
export type State = import('../state.js').State
export function footnote(state: State, node: Node): Element;
export type Element = import('hast').Element;
export type FootnoteDefinition = import('mdast').FootnoteDefinition;
export type Node = import('mdast').Node;
export type State = import('../state.js').State;
/**
* @typedef {import('hast').Element} Element
* @typedef {import('mdast').Heading} Heading
* @typedef {import('../state.js').State} State
*/
/**
* Turn an mdast `heading` node into hast.

@@ -16,5 +11,5 @@ *

*/
export function heading(state: State, node: Heading): Element
export type Element = import('hast').Element
export type Heading = import('mdast').Heading
export type State = import('../state.js').State
export function heading(state: State, node: Heading): Element;
export type Element = import('hast').Element;
export type Heading = import('mdast').Heading;
export type State = import('../state.js').State;

@@ -7,2 +7,5 @@ /**

// Make VS Code show references to the above types.
''
/**

@@ -9,0 +12,0 @@ * Turn an mdast `heading` node into hast.

/**
* @typedef {import('hast').Element} Element
* @typedef {import('mdast').HTML} Html
* @typedef {import('../state.js').State} State
* @typedef {import('../../index.js').Raw} Raw
*/
/**
* Turn an mdast `html` node into hast (`raw` node in dangerous mode, otherwise

@@ -15,9 +9,9 @@ * nothing).

* mdast node.
* @returns {Raw | Element | null}
* @returns {Element | Raw | undefined}
* hast node.
*/
export function html(state: State, node: Html): Raw | Element | null
export type Element = import('hast').Element
export type Html = import('mdast').HTML
export type State = import('../state.js').State
export type Raw = import('../../index.js').Raw
export function html(state: State, node: Html): Element | Raw | undefined;
export type Element = import('hast').Element;
export type Html = import('mdast').Html;
export type State = import('../state.js').State;
export type Raw = import('../../index.js').Raw;
/**
* @typedef {import('hast').Element} Element
* @typedef {import('mdast').HTML} Html
* @typedef {import('mdast').Html} Html
* @typedef {import('../state.js').State} State

@@ -8,2 +8,5 @@ * @typedef {import('../../index.js').Raw} Raw

// Make VS Code show references to the above types.
''
/**

@@ -17,7 +20,7 @@ * Turn an mdast `html` node into hast (`raw` node in dangerous mode, otherwise

* mdast node.
* @returns {Raw | Element | null}
* @returns {Element | Raw | undefined}
* hast node.
*/
export function html(state, node) {
if (state.dangerous) {
if (state.options.allowDangerousHtml) {
/** @type {Raw} */

@@ -29,4 +32,3 @@ const result = {type: 'raw', value: node.value}

// To do: next major: return `undefined`.
return null
return undefined
}

@@ -8,13 +8,10 @@ /**

* mdast node.
* @returns {ElementContent | Array<ElementContent>}
* @returns {Array<ElementContent> | ElementContent}
* hast node.
*/
export function imageReference(
state: State,
node: ImageReference
): ElementContent | Array<ElementContent>
export type ElementContent = import('hast').ElementContent
export type Element = import('hast').Element
export type Properties = import('hast').Properties
export type ImageReference = import('mdast').ImageReference
export type State = import('../state.js').State
export function imageReference(state: State, node: ImageReference): Array<ElementContent> | ElementContent;
export type Element = import('hast').Element;
export type ElementContent = import('hast').ElementContent;
export type Properties = import('hast').Properties;
export type ImageReference = import('mdast').ImageReference;
export type State = import('../state.js').State;
/**
* @typedef {import('hast').Element} Element
* @typedef {import('hast').ElementContent} ElementContent
* @typedef {import('hast').Element} Element
* @typedef {import('hast').Properties} Properties

@@ -19,7 +19,8 @@ * @typedef {import('mdast').ImageReference} ImageReference

* mdast node.
* @returns {ElementContent | Array<ElementContent>}
* @returns {Array<ElementContent> | ElementContent}
* hast node.
*/
export function imageReference(state, node) {
const def = state.definition(node.identifier)
const id = String(node.identifier).toUpperCase()
const def = state.definitionById.get(id)

@@ -26,0 +27,0 @@ if (!def) {

@@ -11,6 +11,6 @@ /**

*/
export function image(state: State, node: Image): Element
export type Element = import('hast').Element
export type Properties = import('hast').Properties
export type Image = import('mdast').Image
export type State = import('../state.js').State
export function image(state: State, node: Image): Element;
export type Element = import('hast').Element;
export type Properties = import('hast').Properties;
export type Image = import('mdast').Image;
export type State = import('../state.js').State;
export namespace handlers {
export {blockquote}
export {hardBreak as break}
export {code}
export {strikethrough as delete}
export {emphasis}
export {footnoteReference}
export {footnote}
export {heading}
export {html}
export {imageReference}
export {image}
export {inlineCode}
export {linkReference}
export {link}
export {listItem}
export {list}
export {paragraph}
export {root}
export {strong}
export {table}
export {tableCell}
export {tableRow}
export {text}
export {thematicBreak}
export {ignore as toml}
export {ignore as yaml}
export {ignore as definition}
export {ignore as footnoteDefinition}
export { blockquote };
export { hardBreak as break };
export { code };
export { strikethrough as delete };
export { emphasis };
export { footnoteReference };
export { heading };
export { html };
export { imageReference };
export { image };
export { inlineCode };
export { linkReference };
export { link };
export { listItem };
export { list };
export { paragraph };
export { root };
export { strong };
export { table };
export { tableCell };
export { tableRow };
export { text };
export { thematicBreak };
export { ignore as toml };
export { ignore as yaml };
export { ignore as definition };
export { ignore as footnoteDefinition };
}
import {blockquote} from './blockquote.js'
import {hardBreak} from './break.js'
import {code} from './code.js'
import {strikethrough} from './delete.js'
import {emphasis} from './emphasis.js'
import {footnoteReference} from './footnote-reference.js'
import {footnote} from './footnote.js'
import {heading} from './heading.js'
import {html} from './html.js'
import {imageReference} from './image-reference.js'
import {image} from './image.js'
import {inlineCode} from './inline-code.js'
import {linkReference} from './link-reference.js'
import {link} from './link.js'
import {listItem} from './list-item.js'
import {list} from './list.js'
import {paragraph} from './paragraph.js'
import {root} from './root.js'
import {strong} from './strong.js'
import {table} from './table.js'
import {tableCell} from './table-cell.js'
import {tableRow} from './table-row.js'
import {text} from './text.js'
import {thematicBreak} from './thematic-break.js'
declare function ignore(): null
export {}
import { blockquote } from './blockquote.js';
import { hardBreak } from './break.js';
import { code } from './code.js';
import { strikethrough } from './delete.js';
import { emphasis } from './emphasis.js';
import { footnoteReference } from './footnote-reference.js';
import { heading } from './heading.js';
import { html } from './html.js';
import { imageReference } from './image-reference.js';
import { image } from './image.js';
import { inlineCode } from './inline-code.js';
import { linkReference } from './link-reference.js';
import { link } from './link.js';
import { listItem } from './list-item.js';
import { list } from './list.js';
import { paragraph } from './paragraph.js';
import { root } from './root.js';
import { strong } from './strong.js';
import { table } from './table.js';
import { tableCell } from './table-cell.js';
import { tableRow } from './table-row.js';
import { text } from './text.js';
import { thematicBreak } from './thematic-break.js';
declare function ignore(): undefined;
export {};

@@ -7,3 +7,2 @@ import {blockquote} from './blockquote.js'

import {footnoteReference} from './footnote-reference.js'
import {footnote} from './footnote.js'
import {heading} from './heading.js'

@@ -29,2 +28,4 @@ import {html} from './html.js'

* Default handlers for nodes.
*
* @satisfies {import('../state.js').Handlers}
*/

@@ -38,3 +39,2 @@ export const handlers = {

footnoteReference,
footnote,
heading,

@@ -50,2 +50,3 @@ html,

paragraph,
// @ts-expect-error: root is different, but hard to type.
root,

@@ -66,4 +67,3 @@ strong,

function ignore() {
// To do: next major: return `undefined`.
return null
return undefined
}
/**
* @typedef {import('hast').Element} Element
* @typedef {import('hast').Text} Text
* @typedef {import('mdast').InlineCode} InlineCode
* @typedef {import('../state.js').State} State
*/
/**
* Turn an mdast `inlineCode` node into hast.

@@ -17,6 +11,6 @@ *

*/
export function inlineCode(state: State, node: InlineCode): Element
export type Element = import('hast').Element
export type Text = import('hast').Text
export type InlineCode = import('mdast').InlineCode
export type State = import('../state.js').State
export function inlineCode(state: State, node: InlineCode): Element;
export type Element = import('hast').Element;
export type Text = import('hast').Text;
export type InlineCode = import('mdast').InlineCode;
export type State = import('../state.js').State;

@@ -8,2 +8,5 @@ /**

// Make VS Code show references to the above types.
''
/**

@@ -10,0 +13,0 @@ * Turn an mdast `inlineCode` node into hast.

@@ -8,13 +8,10 @@ /**

* mdast node.
* @returns {ElementContent | Array<ElementContent>}
* @returns {Array<ElementContent> | ElementContent}
* hast node.
*/
export function linkReference(
state: State,
node: LinkReference
): ElementContent | Array<ElementContent>
export type Element = import('hast').Element
export type ElementContent = import('hast').ElementContent
export type Properties = import('hast').Properties
export type LinkReference = import('mdast').LinkReference
export type State = import('../state.js').State
export function linkReference(state: State, node: LinkReference): Array<ElementContent> | ElementContent;
export type Element = import('hast').Element;
export type ElementContent = import('hast').ElementContent;
export type Properties = import('hast').Properties;
export type LinkReference = import('mdast').LinkReference;
export type State = import('../state.js').State;

@@ -19,7 +19,8 @@ /**

* mdast node.
* @returns {ElementContent | Array<ElementContent>}
* @returns {Array<ElementContent> | ElementContent}
* hast node.
*/
export function linkReference(state, node) {
const def = state.definition(node.identifier)
const id = String(node.identifier).toUpperCase()
const def = state.definitionById.get(id)

@@ -26,0 +27,0 @@ if (!def) {

@@ -11,6 +11,6 @@ /**

*/
export function link(state: State, node: Link): Element
export type Element = import('hast').Element
export type Properties = import('hast').Properties
export type Link = import('mdast').Link
export type State = import('../state.js').State
export function link(state: State, node: Link): Element;
export type Element = import('hast').Element;
export type Properties = import('hast').Properties;
export type Link = import('mdast').Link;
export type State = import('../state.js').State;
/**
* @typedef {import('hast').Element} Element
* @typedef {import('hast').ElementContent} ElementContent
* @typedef {import('hast').Properties} Properties
* @typedef {import('mdast').Content} Content
* @typedef {import('mdast').ListItem} ListItem
* @typedef {import('mdast').Parent} Parent
* @typedef {import('mdast').Root} Root
* @typedef {import('../state.js').State} State
*/
/**
* @typedef {Root | Content} Nodes
* @typedef {Extract<Nodes, Parent>} Parents
*/
/**
* Turn an mdast `listItem` node into hast.

@@ -22,3 +8,3 @@ *

* mdast node.
* @param {Parents | null | undefined} parent
* @param {Parents | undefined} parent
* Parent of `node`.

@@ -28,16 +14,8 @@ * @returns {Element}

*/
export function listItem(
state: State,
node: ListItem,
parent: Parents | null | undefined
): Element
export type Element = import('hast').Element
export type ElementContent = import('hast').ElementContent
export type Properties = import('hast').Properties
export type Content = import('mdast').Content
export type ListItem = import('mdast').ListItem
export type Parent = import('mdast').Parent
export type Root = import('mdast').Root
export type State = import('../state.js').State
export type Nodes = Root | Content
export type Parents = Extract<Nodes, Parent>
export function listItem(state: State, node: ListItem, parent: Parents | undefined): Element;
export type Element = import('hast').Element;
export type ElementContent = import('hast').ElementContent;
export type Properties = import('hast').Properties;
export type ListItem = import('mdast').ListItem;
export type Parents = import('mdast').Parents;
export type State = import('../state.js').State;

@@ -5,13 +5,9 @@ /**

* @typedef {import('hast').Properties} Properties
* @typedef {import('mdast').Content} Content
* @typedef {import('mdast').ListItem} ListItem
* @typedef {import('mdast').Parent} Parent
* @typedef {import('mdast').Root} Root
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../state.js').State} State
*/
/**
* @typedef {Root | Content} Nodes
* @typedef {Extract<Nodes, Parent>} Parents
*/
// Make VS Code show references to the above types.
''

@@ -25,3 +21,3 @@ /**

* mdast node.
* @param {Parents | null | undefined} parent
* @param {Parents | undefined} parent
* Parent of `node`.

@@ -128,5 +124,5 @@ * @returns {Element}

return spread === undefined || spread === null
return spread === null || spread === undefined
? node.children.length > 1
: spread
}
/**
* @typedef {import('hast').Element} Element
* @typedef {import('hast').Properties} Properties
* @typedef {import('mdast').List} List
* @typedef {import('../state.js').State} State
*/
/**
* Turn an mdast `list` node into hast.

@@ -17,6 +11,6 @@ *

*/
export function list(state: State, node: List): Element
export type Element = import('hast').Element
export type Properties = import('hast').Properties
export type List = import('mdast').List
export type State = import('../state.js').State
export function list(state: State, node: List): Element;
export type Element = import('hast').Element;
export type Properties = import('hast').Properties;
export type List = import('mdast').List;
export type State = import('../state.js').State;

@@ -8,2 +8,5 @@ /**

// Make VS Code show references to the above types.
''
/**

@@ -10,0 +13,0 @@ * Turn an mdast `list` node into hast.

/**
* @typedef {import('hast').Element} Element
* @typedef {import('mdast').Paragraph} Paragraph
* @typedef {import('../state.js').State} State
*/
/**
* Turn an mdast `paragraph` node into hast.

@@ -16,5 +11,5 @@ *

*/
export function paragraph(state: State, node: Paragraph): Element
export type Element = import('hast').Element
export type Paragraph = import('mdast').Paragraph
export type State = import('../state.js').State
export function paragraph(state: State, node: Paragraph): Element;
export type Element = import('hast').Element;
export type Paragraph = import('mdast').Paragraph;
export type State = import('../state.js').State;

@@ -7,2 +7,5 @@ /**

// Make VS Code show references to the above types.
''
/**

@@ -9,0 +12,0 @@ * Turn an mdast `paragraph` node into hast.

/**
* @typedef {import('hast').Root} HastRoot
* @typedef {import('hast').Element} HastElement
* @typedef {import('mdast').Root} MdastRoot
* @typedef {import('../state.js').State} State
*/
/**
* Turn an mdast `root` node into hast.

@@ -14,9 +8,9 @@ *

* mdast node.
* @returns {HastRoot | HastElement}
* @returns {HastParents}
* hast node.
*/
export function root(state: State, node: MdastRoot): HastRoot | HastElement
export type HastRoot = import('hast').Root
export type HastElement = import('hast').Element
export type MdastRoot = import('mdast').Root
export type State = import('../state.js').State
export function root(state: State, node: MdastRoot): HastParents;
export type HastParents = import('hast').Parents;
export type HastRoot = import('hast').Root;
export type MdastRoot = import('mdast').Root;
export type State = import('../state.js').State;
/**
* @typedef {import('hast').Parents} HastParents
* @typedef {import('hast').Root} HastRoot
* @typedef {import('hast').Element} HastElement
* @typedef {import('mdast').Root} MdastRoot

@@ -8,2 +8,5 @@ * @typedef {import('../state.js').State} State

// Make VS Code show references to the above types.
''
/**

@@ -16,3 +19,3 @@ * Turn an mdast `root` node into hast.

* mdast node.
* @returns {HastRoot | HastElement}
* @returns {HastParents}
* hast node.

@@ -19,0 +22,0 @@ */

/**
* @typedef {import('hast').Element} Element
* @typedef {import('mdast').Strong} Strong
* @typedef {import('../state.js').State} State
*/
/**
* Turn an mdast `strong` node into hast.

@@ -16,5 +11,5 @@ *

*/
export function strong(state: State, node: Strong): Element
export type Element = import('hast').Element
export type Strong = import('mdast').Strong
export type State = import('../state.js').State
export function strong(state: State, node: Strong): Element;
export type Element = import('hast').Element;
export type Strong = import('mdast').Strong;
export type State = import('../state.js').State;

@@ -7,2 +7,5 @@ /**

// Make VS Code show references to the above types.
''
/**

@@ -9,0 +12,0 @@ * Turn an mdast `strong` node into hast.

/**
* @typedef {import('hast').Element} Element
* @typedef {import('mdast').TableCell} TableCell
* @typedef {import('../state.js').State} State
*/
/**
* Turn an mdast `tableCell` node into hast.

@@ -16,5 +11,5 @@ *

*/
export function tableCell(state: State, node: TableCell): Element
export type Element = import('hast').Element
export type TableCell = import('mdast').TableCell
export type State = import('../state.js').State
export function tableCell(state: State, node: TableCell): Element;
export type Element = import('hast').Element;
export type TableCell = import('mdast').TableCell;
export type State = import('../state.js').State;

@@ -7,2 +7,5 @@ /**

// Make VS Code show references to the above types.
''
/**

@@ -9,0 +12,0 @@ * Turn an mdast `tableCell` node into hast.

/**
* @typedef {import('hast').Properties} Properties
* @typedef {import('hast').Element} Element
* @typedef {import('hast').ElementContent} ElementContent
* @typedef {import('mdast').Content} Content
* @typedef {import('mdast').Parent} Parent
* @typedef {import('mdast').Root} Root
* @typedef {import('mdast').TableRow} TableRow
* @typedef {import('../state.js').State} State
*/
/**
* @typedef {Root | Content} Nodes
* @typedef {Extract<Nodes, Parent>} Parents
*/
/**
* Turn an mdast `tableRow` node into hast.

@@ -22,3 +8,3 @@ *

* mdast node.
* @param {Parents | null | undefined} parent
* @param {Parents | undefined} parent
* Parent of `node`.

@@ -28,16 +14,8 @@ * @returns {Element}

*/
export function tableRow(
state: State,
node: TableRow,
parent: Parents | null | undefined
): Element
export type Properties = import('hast').Properties
export type Element = import('hast').Element
export type ElementContent = import('hast').ElementContent
export type Content = import('mdast').Content
export type Parent = import('mdast').Parent
export type Root = import('mdast').Root
export type TableRow = import('mdast').TableRow
export type State = import('../state.js').State
export type Nodes = Root | Content
export type Parents = Extract<Nodes, Parent>
export function tableRow(state: State, node: TableRow, parent: Parents | undefined): Element;
export type Element = import('hast').Element;
export type ElementContent = import('hast').ElementContent;
export type Properties = import('hast').Properties;
export type Parents = import('mdast').Parents;
export type TableRow = import('mdast').TableRow;
export type State = import('../state.js').State;
/**
* @typedef {import('hast').Properties} Properties
* @typedef {import('hast').Element} Element
* @typedef {import('hast').ElementContent} ElementContent
* @typedef {import('mdast').Content} Content
* @typedef {import('mdast').Parent} Parent
* @typedef {import('mdast').Root} Root
* @typedef {import('hast').Properties} Properties
* @typedef {import('mdast').Parents} Parents
* @typedef {import('mdast').TableRow} TableRow

@@ -12,6 +10,4 @@ * @typedef {import('../state.js').State} State

/**
* @typedef {Root | Content} Nodes
* @typedef {Extract<Nodes, Parent>} Parents
*/
// Make VS Code show references to the above types.
''

@@ -25,3 +21,3 @@ /**

* mdast node.
* @param {Parents | null | undefined} parent
* @param {Parents | undefined} parent
* Parent of `node`.

@@ -36,2 +32,3 @@ * @returns {Element}

const tagName = rowIndex === 0 ? 'th' : 'td'
// To do: option to use `style`?
const align = parent && parent.type === 'table' ? parent.align : undefined

@@ -38,0 +35,0 @@ const length = align ? align.length : node.children.length

@@ -11,5 +11,5 @@ /**

*/
export function table(state: State, node: Table): Element
export type Element = import('hast').Element
export type Table = import('mdast').Table
export type State = import('../state.js').State
export function table(state: State, node: Table): Element;
export type Element = import('hast').Element;
export type Table = import('mdast').Table;
export type State = import('../state.js').State;

@@ -7,3 +7,3 @@ /**

import {pointStart, pointEnd} from 'unist-util-position'
import {pointEnd, pointStart} from 'unist-util-position'

@@ -49,3 +49,3 @@ /**

const end = pointEnd(node.children[node.children.length - 1])
if (start.line && end.line) body.position = {start, end}
if (start && end) body.position = {start, end}
tableContent.push(body)

@@ -52,0 +52,0 @@ }

@@ -8,9 +8,9 @@ /**

* mdast node.
* @returns {HastText | HastElement}
* @returns {HastElement | HastText}
* hast node.
*/
export function text(state: State, node: MdastText): HastText | HastElement
export type HastElement = import('hast').Element
export type HastText = import('hast').Text
export type MdastText = import('mdast').Text
export type State = import('../state.js').State
export function text(state: State, node: MdastText): HastElement | HastText;
export type HastElement = import('hast').Element;
export type HastText = import('hast').Text;
export type MdastText = import('mdast').Text;
export type State = import('../state.js').State;

@@ -17,3 +17,3 @@ /**

* mdast node.
* @returns {HastText | HastElement}
* @returns {HastElement | HastText}
* hast node.

@@ -20,0 +20,0 @@ */

/**
* @typedef {import('hast').Element} Element
* @typedef {import('mdast').ThematicBreak} ThematicBreak
* @typedef {import('../state.js').State} State
*/
/**
* Turn an mdast `thematicBreak` node into hast.

@@ -16,5 +11,5 @@ *

*/
export function thematicBreak(state: State, node: ThematicBreak): Element
export type Element = import('hast').Element
export type ThematicBreak = import('mdast').ThematicBreak
export type State = import('../state.js').State
export function thematicBreak(state: State, node: ThematicBreak): Element;
export type Element = import('hast').Element;
export type ThematicBreak = import('mdast').ThematicBreak;
export type State = import('../state.js').State;

@@ -7,2 +7,5 @@ /**

// Make VS Code show references to the above types.
''
/**

@@ -9,0 +12,0 @@ * Turn an mdast `thematicBreak` node into hast.

@@ -74,16 +74,9 @@ /**

* @param {Options | null | undefined} [options]
* Configuration.
* @returns {HastNodes | null | undefined}
* Configuration (optional).
* @returns {HastNodes}
* hast tree.
*/
export function toHast(
tree: MdastNodes,
options?: Options | null | undefined
): HastNodes | null | undefined
export type HastContent = import('hast').Content
export type HastRoot = import('hast').Root
export type MdastContent = import('mdast').Content
export type MdastRoot = import('mdast').Root
export type Options = import('./state.js').Options
export type HastNodes = HastRoot | HastContent
export type MdastNodes = MdastRoot | MdastContent
export function toHast(tree: MdastNodes, options?: Options | null | undefined): HastNodes;
export type HastNodes = import('hast').Nodes;
export type MdastNodes = import('mdast').Nodes;
export type Options = import('./state.js').Options;
/**
* @typedef {import('hast').Content} HastContent
* @typedef {import('hast').Root} HastRoot
*
* @typedef {import('mdast').Content} MdastContent
* @typedef {import('mdast').Root} MdastRoot
*
* @typedef {import('hast').Nodes} HastNodes
* @typedef {import('mdast').Nodes} MdastNodes
* @typedef {import('./state.js').Options} Options
*/
/**
* @typedef {HastRoot | HastContent} HastNodes
* @typedef {MdastRoot | MdastContent} MdastNodes
*/
import {ok as assert} from 'devlop'
import {footer} from './footer.js'

@@ -92,21 +84,24 @@ import {createState} from './state.js'

* @param {Options | null | undefined} [options]
* Configuration.
* @returns {HastNodes | null | undefined}
* Configuration (optional).
* @returns {HastNodes}
* hast tree.
*/
// To do: next major: always return a single `root`.
export function toHast(tree, options) {
const state = createState(tree, options)
const node = state.one(tree, null)
const node = state.one(tree, undefined)
const foot = footer(state)
/** @type {HastNodes} */
const result = Array.isArray(node)
? {type: 'root', children: node}
: node || {type: 'root', children: []}
if (foot) {
// @ts-expect-error If there’s a footer, there were definitions, meaning block
// If there’s a footer, there were definitions, meaning block
// content.
// So assume `node` is a parent node.
node.children.push({type: 'text', value: '\n'}, foot)
// So `result` is a parent node.
assert('children' in result)
result.children.push({type: 'text', value: '\n'}, foot)
}
// To do: next major: always return root?
return Array.isArray(node) ? {type: 'root', children: node} : node
return result
}
/**
* @typedef {import('hast').ElementContent} ElementContent
*
* @typedef {import('mdast').Content} Content
* @typedef {import('mdast').Reference} Reference
* @typedef {import('mdast').Root} Root
*
* @typedef {import('./state.js').State} State
*/
/**
* @typedef {Root | Content} Nodes
* @typedef {Extract<Nodes, Reference>} References
*/
/**
* Return the content of a reference without definition as plain text.

@@ -19,17 +6,11 @@ *

* Info passed around.
* @param {References} node
* @param {Extract<Nodes, Reference>} node
* Reference node (image, link).
* @returns {ElementContent | Array<ElementContent>}
* @returns {Array<ElementContent>}
* hast content.
*/
export function revert(
state: State,
node: References
): ElementContent | Array<ElementContent>
export type ElementContent = import('hast').ElementContent
export type Content = import('mdast').Content
export type Reference = import('mdast').Reference
export type Root = import('mdast').Root
export type State = import('./state.js').State
export type Nodes = Root | Content
export type References = Extract<Nodes, Reference>
export function revert(state: State, node: Extract<Nodes, Reference>): Array<ElementContent>;
export type ElementContent = import('hast').ElementContent;
export type Nodes = import('mdast').Nodes;
export type Reference = import('mdast').Reference;
export type State = import('./state.js').State;
/**
* @typedef {import('hast').ElementContent} ElementContent
*
* @typedef {import('mdast').Content} Content
* @typedef {import('mdast').Nodes} Nodes
* @typedef {import('mdast').Reference} Reference
* @typedef {import('mdast').Root} Root
*

@@ -11,9 +10,5 @@ * @typedef {import('./state.js').State} State

/**
* @typedef {Root | Content} Nodes
* @typedef {Extract<Nodes, Reference>} References
*/
// Make VS Code show references to the above types.
''
// To do: next major: always return array.
/**

@@ -24,5 +19,5 @@ * Return the content of a reference without definition as plain text.

* Info passed around.
* @param {References} node
* @param {Extract<Nodes, Reference>} node
* Reference node (image, link).
* @returns {ElementContent | Array<ElementContent>}
* @returns {Array<ElementContent>}
* hast content.

@@ -41,3 +36,3 @@ */

if (node.type === 'imageReference') {
return {type: 'text', value: '![' + node.alt + suffix}
return [{type: 'text', value: '![' + node.alt + suffix}]
}

@@ -44,0 +39,0 @@

@@ -7,297 +7,222 @@ /**

* @param {Options | null | undefined} [options]
* Configuration.
* Configuration (optional).
* @returns {State}
* `state` function.
*/
export function createState(
tree: MdastNodes,
options?: Options | null | undefined
): State
export function createState(tree: MdastNodes, options?: Options | null | undefined): State;
/**
* Transform an mdast node into a hast node.
*
* @param {State} state
* Info passed around.
* @param {MdastNodes} node
* mdast node.
* @param {MdastParents | null | undefined} [parent]
* Parent of `node`.
* @returns {HastElementContent | Array<HastElementContent> | null | undefined}
* Resulting hast node.
*/
export function one(
state: State,
node: MdastNodes,
parent?: MdastParents | null | undefined
): HastElementContent | Array<HastElementContent> | null | undefined
/**
* Transform the children of an mdast node into hast nodes.
*
* @param {State} state
* Info passed around.
* @param {MdastNodes} parent
* mdast node to compile
* @returns {Array<HastElementContent>}
* Resulting hast nodes.
*/
export function all(state: State, parent: MdastNodes): Array<HastElementContent>
/**
* Wrap `nodes` with line endings between each node.
*
* @template {HastContent} Type
* @template {HastRootContent} Type
* Node type.
* @param {Array<Type>} nodes
* List of nodes to wrap.
* @param {boolean | null | undefined} [loose=false]
* Whether to add line endings at start and end.
* @returns {Array<Type | HastText>}
* @param {boolean | undefined} [loose=false]
* Whether to add line endings at start and end (default: `false`).
* @returns {Array<HastText | Type>}
* Wrapped nodes.
*/
export function wrap<Type extends import('hast').Content>(
nodes: Type[],
loose?: boolean | null | undefined
): (import('hast').Text | Type)[]
export type HastContent = import('hast').Content
export type HastElement = import('hast').Element
export type HastElementContent = import('hast').ElementContent
export type HastProperties = import('hast').Properties
export type HastRoot = import('hast').Root
export type HastText = import('hast').Text
export type MdastContent = import('mdast').Content
export type MdastDefinition = import('mdast').Definition
export type MdastFootnoteDefinition = import('mdast').FootnoteDefinition
export type MdastParent = import('mdast').Parent
export type MdastRoot = import('mdast').Root
export type HastNodes = HastRoot | HastContent
export type MdastNodes = MdastRoot | MdastContent
export type MdastParents = Extract<MdastNodes, MdastParent>
export function wrap<Type extends import("hast").RootContent>(nodes: Type[], loose?: boolean | undefined): (import("hast").Text | Type)[];
export type HastElement = import('hast').Element;
export type HastElementContent = import('hast').ElementContent;
export type HastNodes = import('hast').Nodes;
export type HastProperties = import('hast').Properties;
export type HastRootContent = import('hast').RootContent;
export type HastText = import('hast').Text;
export type MdastDefinition = import('mdast').Definition;
export type MdastFootnoteDefinition = import('mdast').FootnoteDefinition;
export type MdastNodes = import('mdast').Nodes;
export type MdastParents = import('mdast').Parents;
export type FootnoteBackContentTemplate = import('./footer.js').FootnoteBackContentTemplate;
export type FootnoteBackLabelTemplate = import('./footer.js').FootnoteBackLabelTemplate;
/**
* hast fields.
*/
export type EmbeddedHastFields = {
/**
* Generate a specific element with this tag name instead.
*/
hName?: string | null | undefined
/**
* Generate an element with these properties instead.
*/
hProperties?: HastProperties | null | undefined
/**
* Generate an element with this content instead.
*/
hChildren?: Array<HastElementContent> | null | undefined
}
/**
* mdast data with embedded hast fields.
*/
export type MdastData = Record<string, unknown> & EmbeddedHastFields
/**
* mdast node with embedded hast data.
*/
export type MdastNodeWithData = MdastNodes & {
data?: MdastData | null | undefined
}
/**
* Point-like value.
*/
export type PointLike = {
/**
* Line.
*/
line?: number | null | undefined
/**
* Column.
*/
column?: number | null | undefined
/**
* Offset.
*/
offset?: number | null | undefined
}
/**
* Position-like value.
*/
export type PositionLike = {
/**
* Point-like value.
*/
start?: PointLike | null | undefined
/**
* Point-like value.
*/
end?: PointLike | null | undefined
}
/**
* Handle a node.
*/
export type Handler = (
state: State,
node: any,
parent: MdastParents | null | undefined
) => HastElementContent | Array<HastElementContent> | null | undefined
export type Handler = (state: State, node: any, parent: MdastParents | undefined) => Array<HastElementContent> | HastElementContent | undefined;
/**
* Signature of `state` for when props are passed.
* Handle nodes.
*/
export type HFunctionProps = (
node: MdastNodes | PositionLike | null | undefined,
tagName: string,
props: HastProperties,
children?: Array<HastElementContent> | null | undefined
) => HastElement
export type Handlers = Partial<Record<MdastNodes['type'], Handler>>;
/**
* Signature of `state` for when no props are passed.
*/
export type HFunctionNoProps = (
node: MdastNodes | PositionLike | null | undefined,
tagName: string,
children?: Array<HastElementContent> | null | undefined
) => HastElement
/**
* Info on `state`.
*/
export type HFields = {
/**
* Whether HTML is allowed.
*/
dangerous: boolean
/**
* Prefix to use to prevent DOM clobbering.
*/
clobberPrefix: string
/**
* Label to use to introduce the footnote section.
*/
footnoteLabel: string
/**
* HTML used for the footnote label.
*/
footnoteLabelTagName: string
/**
* Properties on the HTML tag used for the footnote label.
*/
footnoteLabelProperties: HastProperties
/**
* Label to use from backreferences back to their footnote call.
*/
footnoteBackLabel: string
/**
* Definition cache.
*/
definition: (identifier: string) => MdastDefinition | null
/**
* Footnote definitions by their identifier.
*/
footnoteById: Record<string, MdastFootnoteDefinition>
/**
* Identifiers of order when footnote calls first appear in tree order.
*/
footnoteOrder: Array<string>
/**
* Counts for how often the same footnote was called.
*/
footnoteCounts: Record<string, number>
/**
* Applied handlers.
*/
handlers: Handlers
/**
* Handler for any none not in `passThrough` or otherwise handled.
*/
unknownHandler: Handler
/**
* Copy a node’s positional info.
*/
patch: (from: MdastNodes, node: HastNodes) => void
/**
* Honor the `data` of `from`, and generate an element instead of `node`.
*/
applyData: <Type extends HastNodes>(
from: MdastNodes,
to: Type
) => import('hast').Element | Type
/**
* Transform an mdast node to hast.
*/
one: (
node: MdastNodes,
parent: MdastParents | null | undefined
) => HastElementContent | Array<HastElementContent> | null | undefined
/**
* Transform the children of an mdast parent to hast.
*/
all: (node: MdastNodes) => Array<HastElementContent>
/**
* Wrap `nodes` with line endings between each node, adds initial/final line endings when `loose`.
*/
wrap: <Type_1 extends import('hast').Content>(
nodes: Type_1[],
loose?: boolean | null | undefined
) => (Type_1 | import('hast').Text)[]
/**
* Like `state` but lower-level and usable on non-elements.
* Deprecated: use `patch` and `applyData`.
*/
augment: (
left: MdastNodeWithData | PositionLike | null | undefined,
right: HastElementContent
) => HastElementContent
/**
* List of node types to pass through untouched (except for their children).
*/
passThrough: Array<string>
}
/**
* Configuration (optional).
*/
export type Options = {
/**
* Whether to persist raw HTML in markdown in the hast tree.
*/
allowDangerousHtml?: boolean | null | undefined
/**
* Prefix to use before the `id` attribute on footnotes to prevent it from
* *clobbering*.
*/
clobberPrefix?: string | null | undefined
/**
* Label to use from backreferences back to their footnote call (affects
* screen readers).
*/
footnoteBackLabel?: string | null | undefined
/**
* Label to use for the footnotes section (affects screen readers).
*/
footnoteLabel?: string | null | undefined
/**
* Properties to use on the footnote label (note that `id: 'footnote-label'`
* is always added as footnote calls use it with `aria-describedby` to
* provide an accessible label).
*/
footnoteLabelProperties?: HastProperties | null | undefined
/**
* Tag name to use for the footnote label.
*/
footnoteLabelTagName?: string | null | undefined
/**
* Extra handlers for nodes.
*/
handlers?: Handlers | null | undefined
/**
* List of custom mdast node types to pass through (keep) in hast (note that
* the node itself is passed, but eventual children are transformed).
*/
passThrough?: Array<string> | null | undefined
/**
* Handler for all unknown nodes.
*/
unknownHandler?: Handler | null | undefined
}
/**
* Whether to persist raw HTML in markdown in the hast tree (default:
* `false`).
*/
allowDangerousHtml?: boolean | null | undefined;
/**
* Prefix to use before the `id` property on footnotes to prevent them from
* *clobbering* (default: `'user-content-'`).
*
* Pass `''` for trusted markdown and when you are careful with
* polyfilling.
* You could pass a different prefix.
*
* DOM clobbering is this:
*
* ```html
* <p id="x"></p>
* <script>alert(x) // `x` now refers to the `p#x` DOM element</script>
* ```
*
* The above example shows that elements are made available by browsers, by
* their ID, on the `window` object.
* This is a security risk because you might be expecting some other variable
* at that place.
* It can also break polyfills.
* Using a prefix solves these problems.
*/
clobberPrefix?: string | null | undefined;
/**
* Content of the backreference back to references (default: `defaultFootnoteBackContent`).
*
* The default value is:
*
* ```js
* function defaultFootnoteBackContent(_, rereferenceIndex) {
* const result = [{type: 'text', value: '↩'}]
*
* if (rereferenceIndex > 1) {
* result.push({
* type: 'element',
* tagName: 'sup',
* properties: {},
* children: [{type: 'text', value: String(rereferenceIndex)}]
* })
* }
*
* return result
* }
* ```
*
* This content is used in the `a` element of each backreference (the `↩`
* links).
*/
footnoteBackContent?: FootnoteBackContentTemplate | string | null | undefined;
/**
* Label to describe the backreference back to references (default:
* `defaultFootnoteBackLabel`).
*
* The default value is:
*
* ```js
* function defaultFootnoteBackLabel(referenceIndex, rereferenceIndex) {
* return (
* 'Back to reference ' +
* (referenceIndex + 1) +
* (rereferenceIndex > 1 ? '-' + rereferenceIndex : '')
* )
* }
* ```
*
* Change it when the markdown is not in English.
*
* This label is used in the `ariaLabel` property on each backreference
* (the `↩` links).
* It affects users of assistive technology.
*/
footnoteBackLabel?: FootnoteBackLabelTemplate | string | null | undefined;
/**
* Textual label to use for the footnotes section (default: `'Footnotes'`).
*
* Change it when the markdown is not in English.
*
* This label is typically hidden visually (assuming a `sr-only` CSS class
* is defined that does that) and so affects screen readers only.
* If you do have such a class, but want to show this section to everyone,
* pass different properties with the `footnoteLabelProperties` option.
*/
footnoteLabel?: string | null | undefined;
/**
* Properties to use on the footnote label (default: `{className:
* ['sr-only']}`).
*
* Change it to show the label and add other properties.
*
* This label is typically hidden visually (assuming an `sr-only` CSS class
* is defined that does that) and so affects screen readers only.
* If you do have such a class, but want to show this section to everyone,
* pass an empty string.
* You can also add different properties.
*
* > 👉 **Note**: `id: 'footnote-label'` is always added, because footnote
* > calls use it with `aria-describedby` to provide an accessible label.
*/
footnoteLabelProperties?: HastProperties | null | undefined;
/**
* HTML tag name to use for the footnote label element (default: `'h2'`).
*
* Change it to match your document structure.
*
* This label is typically hidden visually (assuming a `sr-only` CSS class
* is defined that does that) and so affects screen readers only.
* If you do have such a class, but want to show this section to everyone,
* pass different properties with the `footnoteLabelProperties` option.
*/
footnoteLabelTagName?: string | null | undefined;
/**
* Extra handlers for nodes (optional).
*/
handlers?: Handlers | null | undefined;
/**
* List of custom mdast node types to pass through (keep) in hast (note that
* the node itself is passed, but eventual children are transformed)
* (optional).
*/
passThrough?: Array<MdastNodes['type']> | null | undefined;
/**
* Handler for all unknown nodes (optional).
*/
unknownHandler?: Handler | null | undefined;
};
/**
* Handle nodes.
*/
export type Handlers = Record<string, Handler>
/**
* Info passed around.
*/
export type State = HFunctionProps & HFunctionNoProps & HFields
export type State = {
/**
* Transform the children of an mdast parent to hast.
*/
all: (node: MdastNodes) => Array<HastElementContent>;
/**
* Honor the `data` of `from`, and generate an element instead of `node`.
*/
applyData: <Type extends import("hast").Nodes>(from: MdastNodes, to: Type) => import("hast").Element | Type;
/**
* Definitions by their identifier.
*/
definitionById: Map<string, MdastDefinition>;
/**
* Footnote definitions by their identifier.
*/
footnoteById: Map<string, MdastFootnoteDefinition>;
/**
* Counts for how often the same footnote was called.
*/
footnoteCounts: Map<string, number>;
/**
* Identifiers of order when footnote calls first appear in tree order.
*/
footnoteOrder: Array<string>;
/**
* Applied handlers.
*/
handlers: Handlers;
/**
* Transform an mdast node to hast.
*/
one: (node: MdastNodes, parent: MdastParents | undefined) => Array<HastElementContent> | HastElementContent | undefined;
/**
* Configuration.
*/
options: Options;
/**
* Copy a node’s positional info.
*/
patch: (from: MdastNodes, node: HastNodes) => undefined;
/**
* Wrap `nodes` with line endings between each node, adds initial/final line endings when `loose`.
*/
wrap: <Type_1 extends import("hast").RootContent>(nodes: Type_1[], loose?: boolean | undefined) => (import("hast").Text | Type_1)[];
};
/**
* @typedef {import('hast').Content} HastContent
* @typedef {import('hast').Element} HastElement
* @typedef {import('hast').ElementContent} HastElementContent
* @typedef {import('hast').Nodes} HastNodes
* @typedef {import('hast').Properties} HastProperties
* @typedef {import('hast').Root} HastRoot
* @typedef {import('hast').RootContent} HastRootContent
* @typedef {import('hast').Text} HastText
*
* @typedef {import('mdast').Content} MdastContent
* @typedef {import('mdast').Definition} MdastDefinition
* @typedef {import('mdast').FootnoteDefinition} MdastFootnoteDefinition
* @typedef {import('mdast').Parent} MdastParent
* @typedef {import('mdast').Root} MdastRoot
* @typedef {import('mdast').Nodes} MdastNodes
* @typedef {import('mdast').Parents} MdastParents
*
* @typedef {import('./footer.js').FootnoteBackContentTemplate} FootnoteBackContentTemplate
* @typedef {import('./footer.js').FootnoteBackLabelTemplate} FootnoteBackLabelTemplate
*/
/**
* @typedef {HastRoot | HastContent} HastNodes
* @typedef {MdastRoot | MdastContent} MdastNodes
* @typedef {Extract<MdastNodes, MdastParent>} MdastParents
*
* @typedef EmbeddedHastFields
* hast fields.
* @property {string | null | undefined} [hName]
* Generate a specific element with this tag name instead.
* @property {HastProperties | null | undefined} [hProperties]
* Generate an element with these properties instead.
* @property {Array<HastElementContent> | null | undefined} [hChildren]
* Generate an element with this content instead.
*
* @typedef {Record<string, unknown> & EmbeddedHastFields} MdastData
* mdast data with embedded hast fields.
*
* @typedef {MdastNodes & {data?: MdastData | null | undefined}} MdastNodeWithData
* mdast node with embedded hast data.
*
* @typedef PointLike
* Point-like value.
* @property {number | null | undefined} [line]
* Line.
* @property {number | null | undefined} [column]
* Column.
* @property {number | null | undefined} [offset]
* Offset.
*
* @typedef PositionLike
* Position-like value.
* @property {PointLike | null | undefined} [start]
* Point-like value.
* @property {PointLike | null | undefined} [end]
* Point-like value.
*
* @callback Handler

@@ -58,114 +25,158 @@ * Handle a node.

* mdast node to handle.
* @param {MdastParents | null | undefined} parent
* @param {MdastParents | undefined} parent
* Parent of `node`.
* @returns {HastElementContent | Array<HastElementContent> | null | undefined}
* @returns {Array<HastElementContent> | HastElementContent | undefined}
* hast node.
*
* @callback HFunctionProps
* Signature of `state` for when props are passed.
* @param {MdastNodes | PositionLike | null | undefined} node
* mdast node or unist position.
* @param {string} tagName
* HTML tag name.
* @param {HastProperties} props
* Properties.
* @param {Array<HastElementContent> | null | undefined} [children]
* hast content.
* @returns {HastElement}
* Compiled element.
* @typedef {Partial<Record<MdastNodes['type'], Handler>>} Handlers
* Handle nodes.
*
* @callback HFunctionNoProps
* Signature of `state` for when no props are passed.
* @param {MdastNodes | PositionLike | null | undefined} node
* mdast node or unist position.
* @param {string} tagName
* HTML tag name.
* @param {Array<HastElementContent> | null | undefined} [children]
* hast content.
* @returns {HastElement}
* Compiled element.
*
* @typedef HFields
* Info on `state`.
* @property {boolean} dangerous
* Whether HTML is allowed.
* @property {string} clobberPrefix
* Prefix to use to prevent DOM clobbering.
* @property {string} footnoteLabel
* Label to use to introduce the footnote section.
* @property {string} footnoteLabelTagName
* HTML used for the footnote label.
* @property {HastProperties} footnoteLabelProperties
* Properties on the HTML tag used for the footnote label.
* @property {string} footnoteBackLabel
* Label to use from backreferences back to their footnote call.
* @property {(identifier: string) => MdastDefinition | null} definition
* Definition cache.
* @property {Record<string, MdastFootnoteDefinition>} footnoteById
* Footnote definitions by their identifier.
* @property {Array<string>} footnoteOrder
* Identifiers of order when footnote calls first appear in tree order.
* @property {Record<string, number>} footnoteCounts
* Counts for how often the same footnote was called.
* @property {Handlers} handlers
* Applied handlers.
* @property {Handler} unknownHandler
* Handler for any none not in `passThrough` or otherwise handled.
* @property {(from: MdastNodes, node: HastNodes) => void} patch
* Copy a node’s positional info.
* @property {<Type extends HastNodes>(from: MdastNodes, to: Type) => Type | HastElement} applyData
* Honor the `data` of `from`, and generate an element instead of `node`.
* @property {(node: MdastNodes, parent: MdastParents | null | undefined) => HastElementContent | Array<HastElementContent> | null | undefined} one
* Transform an mdast node to hast.
* @property {(node: MdastNodes) => Array<HastElementContent>} all
* Transform the children of an mdast parent to hast.
* @property {<Type extends HastContent>(nodes: Array<Type>, loose?: boolean | null | undefined) => Array<Type | HastText>} wrap
* Wrap `nodes` with line endings between each node, adds initial/final line endings when `loose`.
* @property {(left: MdastNodeWithData | PositionLike | null | undefined, right: HastElementContent) => HastElementContent} augment
* Like `state` but lower-level and usable on non-elements.
* Deprecated: use `patch` and `applyData`.
* @property {Array<string>} passThrough
* List of node types to pass through untouched (except for their children).
*
* @typedef Options
* Configuration (optional).
* @property {boolean | null | undefined} [allowDangerousHtml=false]
* Whether to persist raw HTML in markdown in the hast tree.
* Whether to persist raw HTML in markdown in the hast tree (default:
* `false`).
* @property {string | null | undefined} [clobberPrefix='user-content-']
* Prefix to use before the `id` attribute on footnotes to prevent it from
* *clobbering*.
* @property {string | null | undefined} [footnoteBackLabel='Back to content']
* Label to use from backreferences back to their footnote call (affects
* screen readers).
* Prefix to use before the `id` property on footnotes to prevent them from
* *clobbering* (default: `'user-content-'`).
*
* Pass `''` for trusted markdown and when you are careful with
* polyfilling.
* You could pass a different prefix.
*
* DOM clobbering is this:
*
* ```html
* <p id="x"></p>
* <script>alert(x) // `x` now refers to the `p#x` DOM element</script>
* ```
*
* The above example shows that elements are made available by browsers, by
* their ID, on the `window` object.
* This is a security risk because you might be expecting some other variable
* at that place.
* It can also break polyfills.
* Using a prefix solves these problems.
* @property {FootnoteBackContentTemplate | string | null | undefined} [footnoteBackContent]
* Content of the backreference back to references (default: `defaultFootnoteBackContent`).
*
* The default value is:
*
* ```js
* function defaultFootnoteBackContent(_, rereferenceIndex) {
* const result = [{type: 'text', value: '↩'}]
*
* if (rereferenceIndex > 1) {
* result.push({
* type: 'element',
* tagName: 'sup',
* properties: {},
* children: [{type: 'text', value: String(rereferenceIndex)}]
* })
* }
*
* return result
* }
* ```
*
* This content is used in the `a` element of each backreference (the `↩`
* links).
* @property {FootnoteBackLabelTemplate | string | null | undefined} [footnoteBackLabel]
* Label to describe the backreference back to references (default:
* `defaultFootnoteBackLabel`).
*
* The default value is:
*
* ```js
* function defaultFootnoteBackLabel(referenceIndex, rereferenceIndex) {
* return (
* 'Back to reference ' +
* (referenceIndex + 1) +
* (rereferenceIndex > 1 ? '-' + rereferenceIndex : '')
* )
* }
* ```
*
* Change it when the markdown is not in English.
*
* This label is used in the `ariaLabel` property on each backreference
* (the `↩` links).
* It affects users of assistive technology.
* @property {string | null | undefined} [footnoteLabel='Footnotes']
* Label to use for the footnotes section (affects screen readers).
* Textual label to use for the footnotes section (default: `'Footnotes'`).
*
* Change it when the markdown is not in English.
*
* This label is typically hidden visually (assuming a `sr-only` CSS class
* is defined that does that) and so affects screen readers only.
* If you do have such a class, but want to show this section to everyone,
* pass different properties with the `footnoteLabelProperties` option.
* @property {HastProperties | null | undefined} [footnoteLabelProperties={className: ['sr-only']}]
* Properties to use on the footnote label (note that `id: 'footnote-label'`
* is always added as footnote calls use it with `aria-describedby` to
* provide an accessible label).
* Properties to use on the footnote label (default: `{className:
* ['sr-only']}`).
*
* Change it to show the label and add other properties.
*
* This label is typically hidden visually (assuming an `sr-only` CSS class
* is defined that does that) and so affects screen readers only.
* If you do have such a class, but want to show this section to everyone,
* pass an empty string.
* You can also add different properties.
*
* > 👉 **Note**: `id: 'footnote-label'` is always added, because footnote
* > calls use it with `aria-describedby` to provide an accessible label.
* @property {string | null | undefined} [footnoteLabelTagName='h2']
* Tag name to use for the footnote label.
* HTML tag name to use for the footnote label element (default: `'h2'`).
*
* Change it to match your document structure.
*
* This label is typically hidden visually (assuming a `sr-only` CSS class
* is defined that does that) and so affects screen readers only.
* If you do have such a class, but want to show this section to everyone,
* pass different properties with the `footnoteLabelProperties` option.
* @property {Handlers | null | undefined} [handlers]
* Extra handlers for nodes.
* @property {Array<string> | null | undefined} [passThrough]
* Extra handlers for nodes (optional).
* @property {Array<MdastNodes['type']> | null | undefined} [passThrough]
* List of custom mdast node types to pass through (keep) in hast (note that
* the node itself is passed, but eventual children are transformed).
* the node itself is passed, but eventual children are transformed)
* (optional).
* @property {Handler | null | undefined} [unknownHandler]
* Handler for all unknown nodes.
* Handler for all unknown nodes (optional).
*
* @typedef {Record<string, Handler>} Handlers
* Handle nodes.
*
* @typedef {HFunctionProps & HFunctionNoProps & HFields} State
* @typedef State
* Info passed around.
* @property {(node: MdastNodes) => Array<HastElementContent>} all
* Transform the children of an mdast parent to hast.
* @property {<Type extends HastNodes>(from: MdastNodes, to: Type) => HastElement | Type} applyData
* Honor the `data` of `from`, and generate an element instead of `node`.
* @property {Map<string, MdastDefinition>} definitionById
* Definitions by their identifier.
* @property {Map<string, MdastFootnoteDefinition>} footnoteById
* Footnote definitions by their identifier.
* @property {Map<string, number>} footnoteCounts
* Counts for how often the same footnote was called.
* @property {Array<string>} footnoteOrder
* Identifiers of order when footnote calls first appear in tree order.
* @property {Handlers} handlers
* Applied handlers.
* @property {(node: MdastNodes, parent: MdastParents | undefined) => Array<HastElementContent> | HastElementContent | undefined} one
* Transform an mdast node to hast.
* @property {Options} options
* Configuration.
* @property {(from: MdastNodes, node: HastNodes) => undefined} patch
* Copy a node’s positional info.
* @property {<Type extends HastRootContent>(nodes: Array<Type>, loose?: boolean | undefined) => Array<HastText | Type>} wrap
* Wrap `nodes` with line endings between each node, adds initial/final line endings when `loose`.
*/
import structuredClone from '@ungap/structured-clone'
import {visit} from 'unist-util-visit'
import {position, pointStart, pointEnd} from 'unist-util-position'
import {generated} from 'unist-util-generated'
import {definitions} from 'mdast-util-definitions'
import {handlers} from './handlers/index.js'
import {position} from 'unist-util-position'
import {handlers as defaultHandlers} from './handlers/index.js'
const own = {}.hasOwnProperty
/** @type {Options} */
const emptyOptions = {}
/**

@@ -177,3 +188,3 @@ * Create `state` from an mdast tree.

* @param {Options | null | undefined} [options]
* Configuration.
* Configuration (optional).
* @returns {State}

@@ -183,152 +194,80 @@ * `state` function.

export function createState(tree, options) {
const settings = options || {}
const dangerous = settings.allowDangerousHtml || false
/** @type {Record<string, MdastFootnoteDefinition>} */
const footnoteById = {}
const settings = options || emptyOptions
/** @type {Map<string, MdastDefinition>} */
const definitionById = new Map()
/** @type {Map<string, MdastFootnoteDefinition>} */
const footnoteById = new Map()
/** @type {Map<string, number>} */
const footnoteCounts = new Map()
/** @type {Handlers} */
// @ts-expect-error: the root handler returns a root.
// Hard to type.
const handlers = {...defaultHandlers, ...settings.handlers}
// To do: next major: add `options` to state, remove:
// `dangerous`, `clobberPrefix`, `footnoteLabel`, `footnoteLabelTagName`,
// `footnoteLabelProperties`, `footnoteBackLabel`, `passThrough`,
// `unknownHandler`.
// To do: next major: move to `state.options.allowDangerousHtml`.
state.dangerous = dangerous
// To do: next major: move to `state.options`.
state.clobberPrefix =
settings.clobberPrefix === undefined || settings.clobberPrefix === null
? 'user-content-'
: settings.clobberPrefix
// To do: next major: move to `state.options`.
state.footnoteLabel = settings.footnoteLabel || 'Footnotes'
// To do: next major: move to `state.options`.
state.footnoteLabelTagName = settings.footnoteLabelTagName || 'h2'
// To do: next major: move to `state.options`.
state.footnoteLabelProperties = settings.footnoteLabelProperties || {
className: ['sr-only']
/** @type {State} */
const state = {
all,
applyData,
definitionById,
footnoteById,
footnoteCounts,
footnoteOrder: [],
handlers,
one,
options: settings,
patch,
wrap
}
// To do: next major: move to `state.options`.
state.footnoteBackLabel = settings.footnoteBackLabel || 'Back to content'
// To do: next major: move to `state.options`.
state.unknownHandler = settings.unknownHandler
// To do: next major: move to `state.options`.
state.passThrough = settings.passThrough
state.handlers = {...handlers, ...settings.handlers}
visit(tree, function (node) {
if (node.type === 'definition' || node.type === 'footnoteDefinition') {
const map = node.type === 'definition' ? definitionById : footnoteById
const id = String(node.identifier).toUpperCase()
// To do: next major: replace utility with `definitionById` object, so we
// only walk once (as we need footnotes too).
state.definition = definitions(tree)
state.footnoteById = footnoteById
/** @type {Array<string>} */
state.footnoteOrder = []
/** @type {Record<string, number>} */
state.footnoteCounts = {}
state.patch = patch
state.applyData = applyData
state.one = oneBound
state.all = allBound
state.wrap = wrap
// To do: next major: remove `augment`.
state.augment = augment
visit(tree, 'footnoteDefinition', (definition) => {
const id = String(definition.identifier).toUpperCase()
// Mimick CM behavior of link definitions.
// See: <https://github.com/syntax-tree/mdast-util-definitions/blob/8290999/index.js#L26>.
if (!own.call(footnoteById, id)) {
footnoteById[id] = definition
// Mimick CM behavior of link definitions.
// See: <https://github.com/syntax-tree/mdast-util-definitions/blob/9032189/lib/index.js#L20-L21>.
if (!map.has(id)) {
// @ts-expect-error: node type matches map.
map.set(id, node)
}
}
})
// @ts-expect-error Hush, it’s fine!
return state
/**
* Finalise the created `right`, a hast node, from `left`, an mdast node.
* Transform an mdast node into a hast node.
*
* @param {MdastNodeWithData | PositionLike | null | undefined} left
* @param {HastElementContent} right
* @returns {HastElementContent}
* @param {MdastNodes} node
* mdast node.
* @param {MdastParents | undefined} [parent]
* Parent of `node`.
* @returns {Array<HastElementContent> | HastElementContent | undefined}
* Resulting hast node.
*/
/* c8 ignore start */
// To do: next major: remove.
function augment(left, right) {
// Handle `data.hName`, `data.hProperties, `data.hChildren`.
if (left && 'data' in left && left.data) {
/** @type {MdastData} */
const data = left.data
function one(node, parent) {
const type = node.type
const handle = state.handlers[type]
if (data.hName) {
if (right.type !== 'element') {
right = {
type: 'element',
tagName: '',
properties: {},
children: []
}
}
right.tagName = data.hName
}
if (right.type === 'element' && data.hProperties) {
right.properties = {...right.properties, ...data.hProperties}
}
if ('children' in right && right.children && data.hChildren) {
right.children = data.hChildren
}
if (own.call(state.handlers, type) && handle) {
return handle(state, node, parent)
}
if (left) {
const ctx = 'type' in left ? left : {position: left}
if (!generated(ctx)) {
// @ts-expect-error: fine.
right.position = {start: pointStart(ctx), end: pointEnd(ctx)}
if (state.options.passThrough && state.options.passThrough.includes(type)) {
if ('children' in node) {
const {children, ...shallow} = node
const result = structuredClone(shallow)
// @ts-expect-error: TS doesn’t understand…
result.children = state.all(node)
// @ts-expect-error: TS doesn’t understand…
return result
}
}
return right
}
/* c8 ignore stop */
/**
* Create an element for `node`.
*
* @type {HFunctionProps}
*/
/* c8 ignore start */
// To do: next major: remove.
function state(node, tagName, props, children) {
if (Array.isArray(props)) {
children = props
props = {}
// @ts-expect-error: it’s custom.
return structuredClone(node)
}
// @ts-expect-error augmenting an element yields an element.
return augment(node, {
type: 'element',
tagName,
properties: props || {},
children: children || []
})
}
/* c8 ignore stop */
const unknown = state.options.unknownHandler || defaultUnknownHandler
/**
* Transform an mdast node into a hast node.
*
* @param {MdastNodes} node
* mdast node.
* @param {MdastParents | null | undefined} [parent]
* Parent of `node`.
* @returns {HastElementContent | Array<HastElementContent> | null | undefined}
* Resulting hast node.
*/
function oneBound(node, parent) {
// @ts-expect-error: that’s a state :)
return one(state, node, parent)
return unknown(state, node, parent)
}

@@ -344,5 +283,38 @@

*/
function allBound(parent) {
// @ts-expect-error: that’s a state :)
return all(state, parent)
function all(parent) {
/** @type {Array<HastElementContent>} */
const values = []
if ('children' in parent) {
const nodes = parent.children
let index = -1
while (++index < nodes.length) {
const result = state.one(nodes[index], parent)
// To do: see if we van clean this? Can we merge texts?
if (result) {
if (index && nodes[index - 1].type === 'break') {
if (!Array.isArray(result) && result.type === 'text') {
result.value = result.value.replace(/^\s+/, '')
}
if (!Array.isArray(result) && result.type === 'element') {
const head = result.children[0]
if (head && head.type === 'text') {
head.value = head.value.replace(/^\s+/, '')
}
}
}
if (Array.isArray(result)) {
values.push(...result)
} else {
values.push(result)
}
}
}
}
return values
}

@@ -358,3 +330,3 @@ }

* hast node to copy into.
* @returns {void}
* @returns {undefined}
* Nothing.

@@ -375,7 +347,7 @@ */

* hast node to change.
* @returns {Type | HastElement}
* @returns {HastElement | Type}
* Nothing.
*/
function applyData(from, to) {
/** @type {Type | HastElement} */
/** @type {HastElement | Type} */
let result = to

@@ -397,21 +369,9 @@

// raw, text, and root nodes (unless custom handlers are passed).
// The intent is likely to keep the content around (otherwise: pass
// `hChildren`).
// The intent of `hName` is to create an element, but likely also to keep
// the content around (otherwise: pass `hChildren`).
else {
result = {
type: 'element',
tagName: hName,
properties: {},
children: []
}
// To do: next major: take the children from the `root`, or inject the
// raw/text/comment or so into the element?
// if ('children' in node) {
// // @ts-expect-error: assume `children` are allowed in elements.
// result.children = node.children
// } else {
// // @ts-expect-error: assume `node` is allowed in elements.
// result.children.push(node)
// }
/** @type {Array<HastElementContent>} */
// @ts-expect-error: assume no doctypes in `root`.
const children = 'children' in result ? result.children : [result]
result = {type: 'element', tagName: hName, properties: {}, children}
}

@@ -421,3 +381,3 @@ }

if (result.type === 'element' && hProperties) {
result.properties = {...result.properties, ...hProperties}
Object.assign(result.properties, structuredClone(hProperties))
}

@@ -431,3 +391,2 @@

) {
// @ts-expect-error: assume valid children are defined.
result.children = hChildren

@@ -441,89 +400,2 @@ }

/**
* Transform an mdast node into a hast node.
*
* @param {State} state
* Info passed around.
* @param {MdastNodes} node
* mdast node.
* @param {MdastParents | null | undefined} [parent]
* Parent of `node`.
* @returns {HastElementContent | Array<HastElementContent> | null | undefined}
* Resulting hast node.
*/
// To do: next major: do not expose, keep bound.
export function one(state, node, parent) {
const type = node && node.type
// Fail on non-nodes.
if (!type) {
throw new Error('Expected node, got `' + node + '`')
}
if (own.call(state.handlers, type)) {
return state.handlers[type](state, node, parent)
}
if (state.passThrough && state.passThrough.includes(type)) {
// To do: next major: deep clone.
// @ts-expect-error: types of passed through nodes are expected to be added manually.
return 'children' in node ? {...node, children: all(state, node)} : node
}
if (state.unknownHandler) {
return state.unknownHandler(state, node, parent)
}
return defaultUnknownHandler(state, node)
}
/**
* Transform the children of an mdast node into hast nodes.
*
* @param {State} state
* Info passed around.
* @param {MdastNodes} parent
* mdast node to compile
* @returns {Array<HastElementContent>}
* Resulting hast nodes.
*/
// To do: next major: do not expose, keep bound.
export function all(state, parent) {
/** @type {Array<HastElementContent>} */
const values = []
if ('children' in parent) {
const nodes = parent.children
let index = -1
while (++index < nodes.length) {
const result = one(state, nodes[index], parent)
// To do: see if we van clean this? Can we merge texts?
if (result) {
if (index && nodes[index - 1].type === 'break') {
if (!Array.isArray(result) && result.type === 'text') {
result.value = result.value.replace(/^\s+/, '')
}
if (!Array.isArray(result) && result.type === 'element') {
const head = result.children[0]
if (head && head.type === 'text') {
head.value = head.value.replace(/^\s+/, '')
}
}
}
if (Array.isArray(result)) {
values.push(...result)
} else {
values.push(result)
}
}
}
}
return values
}
/**
* Transform an unknown node.

@@ -535,3 +407,3 @@ *

* Unknown mdast node.
* @returns {HastText | HastElement}
* @returns {HastElement | HastText}
* Resulting hast node.

@@ -541,3 +413,3 @@ */

const data = node.data || {}
/** @type {HastText | HastElement} */
/** @type {HastElement | HastText} */
const result =

@@ -551,3 +423,3 @@ 'value' in node &&

properties: {},
children: all(state, node)
children: state.all(node)
}

@@ -562,13 +434,13 @@

*
* @template {HastContent} Type
* @template {HastRootContent} Type
* Node type.
* @param {Array<Type>} nodes
* List of nodes to wrap.
* @param {boolean | null | undefined} [loose=false]
* Whether to add line endings at start and end.
* @returns {Array<Type | HastText>}
* @param {boolean | undefined} [loose=false]
* Whether to add line endings at start and end (default: `false`).
* @returns {Array<HastText | Type>}
* Wrapped nodes.
*/
export function wrap(nodes, loose) {
/** @type {Array<Type | HastText>} */
/** @type {Array<HastText | Type>} */
const result = []

@@ -575,0 +447,0 @@ let index = -1

{
"name": "mdast-util-to-hast",
"version": "12.3.0",
"version": "13.0.0",
"description": "mdast utility to transform to hast",

@@ -29,7 +29,5 @@ "license": "MIT",

"type": "module",
"main": "index.js",
"types": "index.d.ts",
"exports": "./index.js",
"files": [
"lib/",
"complex-types.d.ts",
"index.d.ts",

@@ -39,25 +37,26 @@ "index.js"

"dependencies": {
"@types/hast": "^2.0.0",
"@types/mdast": "^3.0.0",
"mdast-util-definitions": "^5.0.0",
"micromark-util-sanitize-uri": "^1.1.0",
"@types/hast": "^3.0.0",
"@types/mdast": "^4.0.0",
"@ungap/structured-clone": "^1.0.0",
"devlop": "^1.0.0",
"micromark-util-sanitize-uri": "^2.0.0",
"trim-lines": "^3.0.0",
"unist-util-generated": "^2.0.0",
"unist-util-position": "^4.0.0",
"unist-util-visit": "^4.0.0"
"unist-util-position": "^5.0.0",
"unist-util-visit": "^5.0.0"
},
"devDependencies": {
"@types/node": "^18.0.0",
"c8": "^7.0.0",
"@types/node": "^20.0.0",
"@types/ungap__structured-clone": "^0.3.0",
"c8": "^8.0.0",
"hast-util-to-html": "^8.0.4",
"hastscript": "^7.0.0",
"mdast-util-from-markdown": "^1.0.0",
"mdast-util-gfm": "^2.0.0",
"micromark-extension-gfm": "^2.0.0",
"prettier": "^2.0.0",
"mdast-util-from-markdown": "^2.0.0",
"mdast-util-gfm": "^3.0.0",
"micromark-extension-gfm": "^3.0.0",
"prettier": "^3.0.0",
"remark-cli": "^11.0.0",
"remark-preset-wooorm": "^9.0.0",
"type-coverage": "^2.0.0",
"typescript": "^4.0.0",
"xo": "^0.53.0"
"typescript": "^5.0.0",
"xo": "^0.55.0"
},

@@ -67,27 +66,20 @@ "scripts": {

"build": "tsc --build --clean && tsc --build && type-coverage",
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix",
"format": "remark . -qfo && prettier . -w --log-level warn && xo --fix",
"test-api": "node --conditions development test/index.js",
"test-coverage": "c8 --check-coverage --100 --reporter lcov npm run test-api",
"test-coverage": "c8 --100 --reporter lcov npm run test-api",
"test": "npm run build && npm run format && npm run test-coverage"
},
"prettier": {
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"bracketSpacing": false,
"semi": false,
"trailingComma": "none"
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "none",
"useTabs": false
},
"xo": {
"prettier": true,
"rules": {
"max-depth": "off",
"import/no-cycle": "error"
}
},
"remarkConfig": {
"plugins": [
"preset-wooorm",
"remark-preset-wooorm",
[
"lint-no-html",
"remark-lint-no-html",
false

@@ -100,8 +92,28 @@ ]

"detail": true,
"strict": true,
"ignoreCatch": true,
"#": "needed `any`s",
"ignoreFiles": [
"lib/state.d.ts"
]
],
"strict": true
},
"xo": {
"overrides": [
{
"files": [
"**/*.ts"
],
"rules": {
"@typescript-eslint/consistent-type-definitions": "off"
}
}
],
"prettier": true,
"rules": {
"import/no-cycle": "error",
"max-depth": "off",
"unicorn/prefer-at": "off",
"unicorn/prefer-string-replace-all": "off"
}
}
}

@@ -20,4 +20,8 @@ # mdast-util-to-hast

* [API](#api)
* [`defaultFootnoteBackContent(referenceIndex, rereferenceIndex)`](#defaultfootnotebackcontentreferenceindex-rereferenceindex)
* [`defaultFootnoteBackLabel(referenceIndex, rereferenceIndex)`](#defaultfootnotebacklabelreferenceindex-rereferenceindex)
* [`defaultHandlers`](#defaulthandlers)
* [`toHast(tree[, options])`](#tohasttree-options)
* [`defaultHandlers`](#defaulthandlers)
* [`FootnoteBackContentTemplate`](#footnotebackcontenttemplate)
* [`FootnoteBackLabelTemplate`](#footnotebacklabeltemplate)
* [`Handler`](#handler)

@@ -66,3 +70,3 @@ * [`Handlers`](#handlers)

This package is [ESM only][esm].
In Node.js (version 14.14+ and 16.0+), install with [npm][]:
In Node.js (version 16+), install with [npm][]:

@@ -76,3 +80,3 @@ ```sh

```js
import {toHast} from 'https://esm.sh/mdast-util-to-hast@12'
import {toHast} from 'https://esm.sh/mdast-util-to-hast@13'
```

@@ -84,3 +88,3 @@

<script type="module">
import {toHast} from 'https://esm.sh/mdast-util-to-hast@12?bundle'
import {toHast} from 'https://esm.sh/mdast-util-to-hast@13?bundle'
</script>

@@ -101,5 +105,5 @@ ```

import {fs} from 'node:fs/promises'
import {toHtml} from 'hast-util-to-html'
import {fromMarkdown} from 'mdast-util-from-markdown'
import {toHast} from 'mdast-util-to-hast'
import {toHtml} from 'hast-util-to-html'

@@ -122,6 +126,45 @@ const markdown = String(await fs.readFile('example.md'))

This package exports the identifiers [`defaultHandlers`][api-default-handlers]
and [`toHast`][api-to-hast].
This package exports the identifiers
[`defaultFootnoteBackContent`][api-default-footnote-back-content],
[`defaultFootnoteBackLabel`][api-default-footnote-back-label],
[`defaultHandlers`][api-default-handlers], and
[`toHast`][api-to-hast].
There is no default export.
### `defaultFootnoteBackContent(referenceIndex, rereferenceIndex)`
Generate the default content that GitHub uses on backreferences.
###### Parameters
* `referenceIndex` (`number`)
— index of the definition in the order that they are first referenced,
0-indexed
* `rereferenceIndex` (`number`)
— index of calls to the same definition, 0-indexed
###### Returns
Content (`Array<ElementContent>`).
### `defaultFootnoteBackLabel(referenceIndex, rereferenceIndex)`
Generate the default label that GitHub uses on backreferences.
###### Parameters
* `referenceIndex` (`number`)
— index of the definition in the order that they are first referenced,
0-indexed
* `rereferenceIndex` (`number`)
— index of calls to the same definition, 0-indexed
###### Returns
Label (`string`).
### `defaultHandlers`
Default handlers for nodes ([`Handlers`][api-handlers]).
### `toHast(tree[, options])`

@@ -140,3 +183,3 @@

hast tree ([`HastNode | null | undefined`][hast-node]).
hast tree ([`HastNode`][hast-node]).

@@ -210,6 +253,72 @@ ##### Notes

### `defaultHandlers`
### `FootnoteBackContentTemplate`
Default handlers for nodes ([`Handlers`][api-handlers]).
Generate content for the backreference dynamically.
For the following markdown:
```markdown
Alpha[^micromark], bravo[^micromark], and charlie[^remark].
[^remark]: things about remark
[^micromark]: things about micromark
```
This function will be called with:
* `0` and `0` for the backreference from `things about micromark` to
`alpha`, as it is the first used definition, and the first call to it
* `0` and `1` for the backreference from `things about micromark` to
`bravo`, as it is the first used definition, and the second call to it
* `1` and `0` for the backreference from `things about remark` to
`charlie`, as it is the second used definition
###### Parameters
* `referenceIndex` (`number`)
— index of the definition in the order that they are first referenced,
0-indexed
* `rereferenceIndex` (`number`)
— index of calls to the same definition, 0-indexed
###### Returns
Content for the backreference when linking back from definitions to their
reference (`Array<ElementContent>`, `ElementContent`, or `string`).
### `FootnoteBackLabelTemplate`
Generate a back label dynamically.
For the following markdown:
```markdown
Alpha[^micromark], bravo[^micromark], and charlie[^remark].
[^remark]: things about remark
[^micromark]: things about micromark
```
This function will be called with:
* `0` and `0` for the backreference from `things about micromark` to
`alpha`, as it is the first used definition, and the first call to it
* `0` and `1` for the backreference from `things about micromark` to
`bravo`, as it is the first used definition, and the second call to it
* `1` and `0` for the backreference from `things about remark` to
`charlie`, as it is the second used definition
###### Parameters
* `referenceIndex` (`number`)
— index of the definition in the order that they are first referenced,
0-indexed
* `rereferenceIndex` (`number`)
— index of calls to the same definition, 0-indexed
###### Returns
Back label to use when linking back from definitions to their reference
(`string`).
### `Handler`

@@ -225,3 +334,3 @@

— node to handle
* `parent` ([`MdastNode | null | undefined`][mdast-node])
* `parent` ([`MdastNode | undefined`][mdast-node])
— parent of `node`

@@ -231,3 +340,3 @@

Result ([`HastNode | Array<HastNode> | null | undefined`][mdast-node]).
Result ([`Array<HastNode> | HastNode | undefined`][hast-node]).

@@ -241,3 +350,3 @@ ### `Handlers`

```ts
type Handlers = Record<string, Handler>
type Handlers = Partial<Record<Nodes['type'], Handler>>
```

@@ -254,7 +363,14 @@

* `clobberPrefix` (`string`, default: `'user-content-'`)
— prefix to use before the `id` attribute on footnotes to prevent it from
— prefix to use before the `id` property on footnotes to prevent them from
*clobbering*
* `footnoteBackLabel` (`string`, default: `'Back to content'`)
— label to use from backreferences back to their footnote call (affects
screen readers)
* `footnoteBackContent`
([`FootnoteBackContentTemplate`][api-footnote-back-content-template]
or `string`, default:
[`defaultFootnoteBackContent`][api-default-footnote-back-content])
— content of the backreference back to references
* `footnoteBackLabel`
([`FootnoteBackLabelTemplate`][api-footnote-back-label-template]
or `string`, default:
[`defaultFootnoteBackLabel`][api-default-footnote-back-label])
— label to describe the backreference back to references
* `footnoteLabel` (`string`, default: `'Footnotes'`)

@@ -271,3 +387,3 @@ — label to use for the footnotes section (affects screen readers)

— extra handlers for nodes
* `passThrough` (`Array<string>`, optional)
* `passThrough` (`Array<Nodes['type']>`, optional)
— list of custom mdast node types to pass through (keep) in hast (note that

@@ -285,7 +401,10 @@ the node itself is passed, but eventual children are transformed)

```ts
import type {Literal} from 'hast'
import type {Data, Literal} from 'hast'
interface Raw extends Literal {
type: 'raw'
data?: RawData | undefined
}
interface RawData extends Data {}
```

@@ -299,23 +418,24 @@

<!-- To do: add `options`, alternative to `definition`. -->
* `patch` (`(from: MdastNode, to: HastNode) => void`)
— copy a node’s positional info
* `all` (`(node: MdastNode) => Array<HastNode>`)
— transform the children of an mdast parent to hast
* `applyData` (`<Type extends HastNode>(from: MdastNode, to: Type) => Type | HastElement`)
— honor the `data` of `from` and maybe generate an element instead of `to`
* `definitionById` (`Map<string, Definition>`)
— definitions by their uppercased identifier
* `footnoteById` (`Map<string, FootnoteDefinition>`)
— footnote definitions by their uppercased identifier
* `footnoteCounts` (`Map<string, number>`)
— counts for how often the same footnote was called
* `footnoteOrder` (`Array<string>`)
— identifiers of order when footnote calls first appear in tree order
* `handlers` ([`Handlers`][api-handlers])
— applied node handlers
* `one` (`(node: MdastNode, parent: MdastNode | undefined) => HastNode | Array<HastNode> | undefined`)
— transform an mdast node to hast
* `all` (`(node: MdastNode) => Array<HastNode>`)
— transform the children of an mdast parent to hast
* `options` ([`Options`][api-options])
— configuration
* `patch` (`(from: MdastNode, to: HastNode) => undefined`)
* `wrap` (`<Type extends HastNode>(nodes: Array<Type>, loose?: boolean) => Array<Type | HastText>`)
— wrap `nodes` with line endings between each node, adds initial/final line
endings when `loose`
* `handlers` ([`Handlers`][api-handlers])
— applied node handlers
* `footnoteById` (`Record<string, MdastFootnoteDefinition>`)
— footnote definitions by their uppercased identifier
* `footnoteOrder` (`Array<string>`)
— identifiers of order when footnote calls first appear in tree order
* `footnoteCounts` (`Record<string, number>`)
— counts for how often the same footnote was called

@@ -364,7 +484,7 @@ ## Examples

```js
import {fromMarkdown} from 'mdast-util-from-markdown'
import {toHast} from 'mdast-util-to-hast'
import {raw} from 'hast-util-raw'
import {sanitize} from 'hast-util-sanitize'
import {toHtml} from 'hast-util-to-html'
import {fromMarkdown} from 'mdast-util-from-markdown'
import {toHast} from 'mdast-util-to-hast'

@@ -399,7 +519,7 @@ const markdown = 'It <i>works</i>! <img onerror="alert(1)">'

```js
import {toHtml} from 'hast-util-to-html'
import {gfm} from 'micromark-extension-gfm'
import {fromMarkdown} from 'mdast-util-from-markdown'
import {gfm} from 'micromark-extension-gfm'
import {gfmFromMarkdown} from 'mdast-util-gfm'
import {toHast} from 'mdast-util-to-hast'
import {toHtml} from 'hast-util-to-html'

@@ -424,3 +544,3 @@ const markdown = 'Bonjour[^1]\n\n[^1]: Monde!'

<li id="user-content-fn-1">
<p>Monde! <a href="#user-content-fnref-1" data-footnote-backref class="data-footnote-backref" aria-label="Back to content">↩</a></p>
<p>Monde! <a href="#user-content-fnref-1" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>

@@ -437,3 +557,3 @@ </ol>

```diff
@@ -9,7 +9,10 @@ const mdast = fromMarkdown(markdown, {
@@ -9,7 +9,16 @@ const mdast = fromMarkdown(markdown, {
extensions: [gfm()],

@@ -445,3 +565,9 @@ mdastExtensions: [gfmFromMarkdown()]

+ footnoteLabel: 'Notes de bas de page',
+ footnoteBackLabel: 'Arrière'
+ footnoteBackLabel(referenceIndex, rereferenceIndex) {
+ return (
+ 'Retour à la référence ' +
+ (referenceIndex + 1) +
+ (rereferenceIndex > 1 ? '-' + rereferenceIndex : '')
+ )
+ }
+})

@@ -462,4 +588,4 @@ const html = toHtml(hast)

<li id="user-content-fn-1">
-<p>Monde! <a href="#user-content-fnref-1" data-footnote-backref class="data-footnote-backref" aria-label="Back to content">↩</a></p>
+<p>Monde! <a href="#user-content-fnref-1" data-footnote-backref class="data-footnote-backref" aria-label="Arrière">↩</a></p>
-<p>Monde! <a href="#user-content-fnref-1" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
+<p>Monde! <a href="#user-content-fnref-1" data-footnote-backref="" aria-label="Retour à la référence 1" class="data-footnote-backref">↩</a></p>
</li>

@@ -481,4 +607,4 @@ </ol>

```js
import {toHtml} from 'hast-util-to-html'
import {toHast} from 'mdast-util-to-hast'
import {toHtml} from 'hast-util-to-html'

@@ -509,4 +635,4 @@ const mdast = {

```js
import {toHtml} from 'hast-util-to-html'
import {toHast} from 'mdast-util-to-hast'
import {toHtml} from 'hast-util-to-html'

@@ -1366,6 +1492,12 @@ const mdast = {

This package is fully typed with [TypeScript][].
It also exports [`Handler`][api-handler], [`Handlers`][api-handlers],
[`Options`][api-options], [`Raw`][api-raw], and [`State`][api-state] types.
It exports the
[`FootnoteBackContentTemplate`][api-footnote-back-content-template],
[`FootnoteBackLabelTemplate`][api-footnote-back-label-template],
[`Handler`][api-handler],
[`Handlers`][api-handlers],
[`Options`][api-options],
[`Raw`][api-raw], and
[`State`][api-state] types.
It also registers the `Raw` node type with `@types/mdast`.
It also registers the `Raw` node type with `@types/hast`.
If you’re working with the syntax tree (and you pass

@@ -1385,3 +1517,3 @@ `allowDangerousHtml: true`), make sure to import this utility somewhere in your

visit(tree, (node) => {
visit(tree, function (node) {
// `node` can now be `raw`.

@@ -1391,9 +1523,30 @@ })

Finally, it also registers the `hChildren`, `hName`, and `hProperties` fields
on `Data` of `@types/mdast`.
If you’re working with the syntax tree, make sure to import this utility
somewhere in your types, as that registers the data fields in the tree.
```js
/**
* @typedef {import('mdast-util-to-hast')}
*/
import {visit} from 'unist-util-visit'
/** @type {import('hast').Root} */
const tree = { /* … */ }
console.log(tree.data?.hName) // Types as `string | undefined`.
```
## Compatibility
Projects maintained by the unified collective are compatible with all maintained
Projects maintained by the unified collective are compatible with maintained
versions of Node.js.
As of now, that is Node.js 14.14+ and 16.0+.
Our projects sometimes work with older versions, but this is not guaranteed.
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, `mdast-util-to-hast@^13`,
compatible with Node.js 16.
## Security

@@ -1505,5 +1658,5 @@

[size-badge]: https://img.shields.io/bundlephobia/minzip/mdast-util-to-hast.svg
[size-badge]: https://img.shields.io/badge/dynamic/json?label=minzipped%20size&query=$.size.compressedSize&url=https://deno.bundlejs.com/?q=mdast-util-to-hast
[size]: https://bundlephobia.com/result?p=mdast-util-to-hast
[size]: https://bundlejs.com/?q=mdast-util-to-hast

@@ -1572,6 +1725,12 @@ [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg

[api-default-footnote-back-content]: #defaultfootnotebackcontentreferenceindex-rereferenceindex
[api-default-footnote-back-label]: #defaultfootnotebacklabelreferenceindex-rereferenceindex
[api-default-handlers]: #defaulthandlers
[api-to-hast]: #tohasttree-options
[api-footnote-back-content-template]: #footnotebackcontenttemplate
[api-footnote-back-label-template]: #footnotebacklabeltemplate
[api-handler]: #handler

@@ -1586,1 +1745,3 @@

[api-state]: #state
[api-to-hast]: #tohasttree-options
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc