This commit is contained in:
2024-03-22 03:47:51 +05:30
parent 8bcf3d211e
commit 89819f6fe2
28440 changed files with 3211033 additions and 2 deletions

323
node_modules/mdast-util-to-markdown/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,323 @@
import type {Info, State} from './lib/types.js'
/**
* Interface of registered constructs.
*
* When working on extensions that use new constructs, extend the corresponding
* interface to register its name:
*
* ```ts
* declare module 'mdast-util-to-markdown' {
* interface ConstructNameMap {
* // Register a new construct name (value is used, key should match it).
* gfmStrikethrough: 'gfmStrikethrough'
* }
* }
* ```
*/
export interface ConstructNameMap {
/**
* Whole autolink.
*
* ```markdown
* > | <https://example.com> and <admin@example.com>
* ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
* ```
*/
autolink: 'autolink'
/**
* Whole block quote.
*
* ```markdown
* > | > a
* ^^^
* > | b
* ^
* ```
*/
blockquote: 'blockquote'
/**
* Whole code (indented).
*
* ```markdown
* ␠␠␠␠console.log(1)
* ^^^^^^^^^^^^^^^^^^
* ```
*/
codeIndented: 'codeIndented'
/**
* Whole code (fenced).
*
* ````markdown
* > | ```js
* ^^^^^
* > | console.log(1)
* ^^^^^^^^^^^^^^
* > | ```
* ^^^
* ````
*/
codeFenced: 'codeFenced'
/**
* Code (fenced) language, when fenced with grave accents.
*
* ````markdown
* > | ```js
* ^^
* | console.log(1)
* | ```
* ````
*/
codeFencedLangGraveAccent: 'codeFencedLangGraveAccent'
/**
* Code (fenced) language, when fenced with tildes.
*
* ````markdown
* > | ~~~js
* ^^
* | console.log(1)
* | ~~~
* ````
*/
codeFencedLangTilde: 'codeFencedLangTilde'
/**
* Code (fenced) meta string, when fenced with grave accents.
*
* ````markdown
* > | ```js eval
* ^^^^
* | console.log(1)
* | ```
* ````
*/
codeFencedMetaGraveAccent: 'codeFencedMetaGraveAccent'
/**
* Code (fenced) meta string, when fenced with tildes.
*
* ````markdown
* > | ~~~js eval
* ^^^^
* | console.log(1)
* | ~~~
* ````
*/
codeFencedMetaTilde: 'codeFencedMetaTilde'
/**
* Whole definition.
*
* ```markdown
* > | [a]: b "c"
* ^^^^^^^^^^
* ```
*/
definition: 'definition'
/**
* Destination (literal) (occurs in definition, image, link).
*
* ```markdown
* > | [a]: <b> "c"
* ^^^
* > | a ![b](<c> "d") e
* ^^^
* ```
*/
destinationLiteral: 'destinationLiteral'
/**
* Destination (raw) (occurs in definition, image, link).
*
* ```markdown
* > | [a]: b "c"
* ^
* > | a ![b](c "d") e
* ^
* ```
*/
destinationRaw: 'destinationRaw'
/**
* Emphasis.
*
* ```markdown
* > | *a*
* ^^^
* ```
*/
emphasis: 'emphasis'
/**
* Whole heading (atx).
*
* ```markdown
* > | # alpha
* ^^^^^^^
* ```
*/
headingAtx: 'headingAtx'
/**
* Whole heading (setext).
*
* ```markdown
* > | alpha
* ^^^^^
* > | =====
* ^^^^^
* ```
*/
headingSetext: 'headingSetext'
/**
* Whole image.
*
* ```markdown
* > | ![a](b)
* ^^^^^^^
* > | ![c]
* ^^^^
* ```
*/
image: 'image'
/**
* Whole image reference.
*
* ```markdown
* > | ![a]
* ^^^^
* ```
*/
imageReference: 'imageReference'
/**
* Label (occurs in definitions, image reference, image, link reference,
* link).
*
* ```markdown
* > | [a]: b "c"
* ^^^
* > | a [b] c
* ^^^
* > | a ![b][c] d
* ^^^^
* > | a [b](c) d
* ^^^
* ```
*/
label: 'label'
/**
* Whole link.
*
* ```markdown
* > | [a](b)
* ^^^^^^
* > | [c]
* ^^^
* ```
*/
link: 'link'
/**
* Whole link reference.
*
* ```markdown
* > | [a]
* ^^^
* ```
*/
linkReference: 'linkReference'
/**
* List.
*
* ```markdown
* > | * a
* ^^^
* > | 1. b
* ^^^^
* ```
*/
list: 'list'
/**
* List item.
*
* ```markdown
* > | * a
* ^^^
* > | 1. b
* ^^^^
* ```
*/
listItem: 'listItem'
/**
* Paragraph.
*
* ```markdown
* > | a b
* ^^^
* > | c.
* ^^
* ```
*/
paragraph: 'paragraph'
/**
* Phrasing (occurs in headings, paragraphs, etc).
*
* ```markdown
* > | a
* ^
* ```
*/
phrasing: 'phrasing'
/**
* Reference (occurs in image, link).
*
* ```markdown
* > | [a][]
* ^^
* ```
*/
reference: 'reference'
/**
* Strong.
*
* ```markdown
* > | **a**
* ^^^^^
* ```
*/
strong: 'strong'
/**
* Title using single quotes (occurs in definition, image, link).
*
* ```markdown
* > | [a](b 'c')
* ^^^
* ```
*/
titleApostrophe: 'titleApostrophe'
/**
* Title using double quotes (occurs in definition, image, link).
*
* ```markdown
* > | [a](b "c")
* ^^^
* ```
*/
titleQuote: 'titleQuote'
}
/**
* Construct names for things generated by `mdast-util-to-markdown`.
*
* This is an enum of strings, each being a semantic label, useful to know when
* serializing whether were for example in a double (`"`) or single (`'`)
* quoted title.
*/
export type ConstructName = ConstructNameMap[keyof ConstructNameMap]
export {toMarkdown} from './lib/index.js'
export {handle as defaultHandlers} from './lib/handle/index.js'
export type {
Handle,
Handlers,
Info,
Join,
Map,
Options,
SafeConfig,
State,
Tracker,
Unsafe
} from './lib/types.js'

3
node_modules/mdast-util-to-markdown/index.js generated vendored Normal file
View File

@@ -0,0 +1,3 @@
// Note: extra types exposed from `index.d.ts`.
export {toMarkdown} from './lib/index.js'
export {handle as defaultHandlers} from './lib/handle/index.js'

View File

@@ -0,0 +1,8 @@
/**
* @param {State} base
* @param {Options} extension
* @returns {State}
*/
export function configure(base: State, extension: Options): State;
export type Options = import('./types.js').Options;
export type State = import('./types.js').State;

80
node_modules/mdast-util-to-markdown/lib/configure.js generated vendored Normal file
View File

@@ -0,0 +1,80 @@
/**
* @typedef {import('./types.js').Options} Options
* @typedef {import('./types.js').State} State
*/
const own = {}.hasOwnProperty
/**
* @param {State} base
* @param {Options} extension
* @returns {State}
*/
export function configure(base, extension) {
let index = -1
/** @type {keyof Options} */
let key
// First do subextensions.
if (extension.extensions) {
while (++index < extension.extensions.length) {
configure(base, extension.extensions[index])
}
}
for (key in extension) {
if (own.call(extension, key)) {
switch (key) {
case 'extensions': {
// Empty.
break
}
/* c8 ignore next 4 */
case 'unsafe': {
list(base[key], extension[key])
break
}
case 'join': {
list(base[key], extension[key])
break
}
case 'handlers': {
map(base[key], extension[key])
break
}
default: {
// @ts-expect-error: matches.
base.options[key] = extension[key]
}
}
}
}
return base
}
/**
* @template T
* @param {Array<T>} left
* @param {Array<T> | null | undefined} right
*/
function list(left, right) {
if (right) {
left.push(...right)
}
}
/**
* @template T
* @param {Record<string, T>} left
* @param {Record<string, T> | null | undefined} right
*/
function map(left, right) {
if (right) {
Object.assign(left, right)
}
}

View File

@@ -0,0 +1,20 @@
/**
* @typedef {import('mdast').Blockquote} Blockquote
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').Map} Map
* @typedef {import('../types.js').State} State
*/
/**
* @param {Blockquote} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function blockquote(node: Blockquote, _: Parents | undefined, state: State, info: Info): string;
export type Blockquote = import('mdast').Blockquote;
export type Parents = import('mdast').Parents;
export type Info = import('../types.js').Info;
export type Map = import('../types.js').Map;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,32 @@
/**
* @typedef {import('mdast').Blockquote} Blockquote
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').Map} Map
* @typedef {import('../types.js').State} State
*/
/**
* @param {Blockquote} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function blockquote(node, _, state, info) {
const exit = state.enter('blockquote')
const tracker = state.createTracker(info)
tracker.move('> ')
tracker.shift(2)
const value = state.indentLines(
state.containerFlow(node, tracker.current()),
map
)
exit()
return value
}
/** @type {Map} */
function map(line, _, blank) {
return '>' + (blank ? '' : ' ') + line
}

View File

@@ -0,0 +1,12 @@
/**
* @param {Break} _
* @param {Parents | undefined} _1
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function hardBreak(_: Break, _1: Parents | undefined, state: State, info: Info): string;
export type Break = import('mdast').Break;
export type Parents = import('mdast').Parents;
export type Info = import('../types.js').Info;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,32 @@
/**
* @typedef {import('mdast').Break} Break
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').State} State
*/
import {patternInScope} from '../util/pattern-in-scope.js'
/**
* @param {Break} _
* @param {Parents | undefined} _1
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function hardBreak(_, _1, state, info) {
let index = -1
while (++index < state.unsafe.length) {
// If we cant put eols in this construct (setext headings, tables), use a
// space instead.
if (
state.unsafe[index].character === '\n' &&
patternInScope(state.stack, state.unsafe[index])
) {
return /[ \t]/.test(info.before) ? '' : ' '
}
}
return '\\\n'
}

View File

@@ -0,0 +1,13 @@
/**
* @param {Code} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function code(node: Code, _: Parents | undefined, state: State, info: Info): string;
export type Code = import('mdast').Code;
export type Parents = import('mdast').Parents;
export type Info = import('../types.js').Info;
export type Map = import('../types.js').Map;
export type State = import('../types.js').State;

78
node_modules/mdast-util-to-markdown/lib/handle/code.js generated vendored Normal file
View File

@@ -0,0 +1,78 @@
/**
* @typedef {import('mdast').Code} Code
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').Map} Map
* @typedef {import('../types.js').State} State
*/
import {longestStreak} from 'longest-streak'
import {formatCodeAsIndented} from '../util/format-code-as-indented.js'
import {checkFence} from '../util/check-fence.js'
/**
* @param {Code} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function code(node, _, state, info) {
const marker = checkFence(state)
const raw = node.value || ''
const suffix = marker === '`' ? 'GraveAccent' : 'Tilde'
if (formatCodeAsIndented(node, state)) {
const exit = state.enter('codeIndented')
const value = state.indentLines(raw, map)
exit()
return value
}
const tracker = state.createTracker(info)
const sequence = marker.repeat(Math.max(longestStreak(raw, marker) + 1, 3))
const exit = state.enter('codeFenced')
let value = tracker.move(sequence)
if (node.lang) {
const subexit = state.enter(`codeFencedLang${suffix}`)
value += tracker.move(
state.safe(node.lang, {
before: value,
after: ' ',
encode: ['`'],
...tracker.current()
})
)
subexit()
}
if (node.lang && node.meta) {
const subexit = state.enter(`codeFencedMeta${suffix}`)
value += tracker.move(' ')
value += tracker.move(
state.safe(node.meta, {
before: value,
after: '\n',
encode: ['`'],
...tracker.current()
})
)
subexit()
}
value += tracker.move('\n')
if (raw) {
value += tracker.move(raw + '\n')
}
value += tracker.move(sequence)
exit()
return value
}
/** @type {Map} */
function map(line, _, blank) {
return (blank ? '' : ' ') + line
}

View File

@@ -0,0 +1,12 @@
/**
* @param {Definition} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function definition(node: Definition, _: Parents | undefined, state: State, info: Info): string;
export type Definition = import('mdast').Definition;
export type Parents = import('mdast').Parents;
export type Info = import('../types.js').Info;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,78 @@
/**
* @typedef {import('mdast').Definition} Definition
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').State} State
*/
import {checkQuote} from '../util/check-quote.js'
/**
* @param {Definition} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function definition(node, _, state, info) {
const quote = checkQuote(state)
const suffix = quote === '"' ? 'Quote' : 'Apostrophe'
const exit = state.enter('definition')
let subexit = state.enter('label')
const tracker = state.createTracker(info)
let value = tracker.move('[')
value += tracker.move(
state.safe(state.associationId(node), {
before: value,
after: ']',
...tracker.current()
})
)
value += tracker.move(']: ')
subexit()
if (
// If theres no url, or…
!node.url ||
// If there are control characters or whitespace.
/[\0- \u007F]/.test(node.url)
) {
subexit = state.enter('destinationLiteral')
value += tracker.move('<')
value += tracker.move(
state.safe(node.url, {before: value, after: '>', ...tracker.current()})
)
value += tracker.move('>')
} else {
// No whitespace, raw is prettier.
subexit = state.enter('destinationRaw')
value += tracker.move(
state.safe(node.url, {
before: value,
after: node.title ? ' ' : '\n',
...tracker.current()
})
)
}
subexit()
if (node.title) {
subexit = state.enter(`title${suffix}`)
value += tracker.move(' ' + quote)
value += tracker.move(
state.safe(node.title, {
before: value,
after: quote,
...tracker.current()
})
)
value += tracker.move(quote)
subexit()
}
exit()
return value
}

View File

@@ -0,0 +1,23 @@
/**
* @param {Emphasis} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function emphasis(node: Emphasis, _: Parents | undefined, state: State, info: Info): string;
export namespace emphasis {
export { emphasisPeek as peek };
}
export type Emphasis = import('mdast').Emphasis;
export type Parents = import('mdast').Parents;
export type Info = import('../types.js').Info;
export type State = import('../types.js').State;
/**
* @param {Emphasis} _
* @param {Parents | undefined} _1
* @param {State} state
* @returns {string}
*/
declare function emphasisPeek(_: Emphasis, _1: Parents | undefined, state: State): string;
export {};

View File

@@ -0,0 +1,48 @@
/**
* @typedef {import('mdast').Emphasis} Emphasis
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').State} State
*/
import {checkEmphasis} from '../util/check-emphasis.js'
emphasis.peek = emphasisPeek
// To do: there are cases where emphasis cannot “form” depending on the
// previous or next character of sequences.
// Theres no way around that though, except for injecting zero-width stuff.
// Do we need to safeguard against that?
/**
* @param {Emphasis} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function emphasis(node, _, state, info) {
const marker = checkEmphasis(state)
const exit = state.enter('emphasis')
const tracker = state.createTracker(info)
let value = tracker.move(marker)
value += tracker.move(
state.containerPhrasing(node, {
before: value,
after: marker,
...tracker.current()
})
)
value += tracker.move(marker)
exit()
return value
}
/**
* @param {Emphasis} _
* @param {Parents | undefined} _1
* @param {State} state
* @returns {string}
*/
function emphasisPeek(_, _1, state) {
return state.options.emphasis || '*'
}

View File

@@ -0,0 +1,12 @@
/**
* @param {Heading} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function heading(node: Heading, _: Parents | undefined, state: State, info: Info): string;
export type Heading = import('mdast').Heading;
export type Parents = import('mdast').Parents;
export type Info = import('../types.js').Info;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,80 @@
/**
* @typedef {import('mdast').Heading} Heading
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').State} State
*/
import {formatHeadingAsSetext} from '../util/format-heading-as-setext.js'
/**
* @param {Heading} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function heading(node, _, state, info) {
const rank = Math.max(Math.min(6, node.depth || 1), 1)
const tracker = state.createTracker(info)
if (formatHeadingAsSetext(node, state)) {
const exit = state.enter('headingSetext')
const subexit = state.enter('phrasing')
const value = state.containerPhrasing(node, {
...tracker.current(),
before: '\n',
after: '\n'
})
subexit()
exit()
return (
value +
'\n' +
(rank === 1 ? '=' : '-').repeat(
// The whole size…
value.length -
// Minus the position of the character after the last EOL (or
// 0 if there is none)…
(Math.max(value.lastIndexOf('\r'), value.lastIndexOf('\n')) + 1)
)
)
}
const sequence = '#'.repeat(rank)
const exit = state.enter('headingAtx')
const subexit = state.enter('phrasing')
// Note: for proper tracking, we should reset the output positions when there
// is no content returned, because then the space is not output.
// Practically, in that case, there is no content, so it doesnt matter that
// weve tracked one too many characters.
tracker.move(sequence + ' ')
let value = state.containerPhrasing(node, {
before: '# ',
after: '\n',
...tracker.current()
})
if (/^[\t ]/.test(value)) {
// To do: what effect has the character reference on tracking?
value =
'&#x' +
value.charCodeAt(0).toString(16).toUpperCase() +
';' +
value.slice(1)
}
value = value ? sequence + ' ' + value : sequence
if (state.options.closeAtx) {
value += ' ' + sequence
}
subexit()
exit()
return value
}

View File

@@ -0,0 +1,14 @@
/**
* @param {Html} node
* @returns {string}
*/
export function html(node: Html): string;
export namespace html {
export { htmlPeek as peek };
}
export type Html = import('mdast').Html;
/**
* @returns {string}
*/
declare function htmlPeek(): string;
export {};

20
node_modules/mdast-util-to-markdown/lib/handle/html.js generated vendored Normal file
View File

@@ -0,0 +1,20 @@
/**
* @typedef {import('mdast').Html} Html
*/
html.peek = htmlPeek
/**
* @param {Html} node
* @returns {string}
*/
export function html(node) {
return node.value || ''
}
/**
* @returns {string}
*/
function htmlPeek() {
return '<'
}

View File

@@ -0,0 +1,20 @@
/**
* @param {ImageReference} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function imageReference(node: ImageReference, _: Parents | undefined, state: State, info: Info): string;
export namespace imageReference {
export { imageReferencePeek as peek };
}
export type ImageReference = import('mdast').ImageReference;
export type Parents = import('mdast').Parents;
export type Info = import('../types.js').Info;
export type State = import('../types.js').State;
/**
* @returns {string}
*/
declare function imageReferencePeek(): string;
export {};

View File

@@ -0,0 +1,65 @@
/**
* @typedef {import('mdast').ImageReference} ImageReference
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').State} State
*/
imageReference.peek = imageReferencePeek
/**
* @param {ImageReference} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function imageReference(node, _, state, info) {
const type = node.referenceType
const exit = state.enter('imageReference')
let subexit = state.enter('label')
const tracker = state.createTracker(info)
let value = tracker.move('![')
const alt = state.safe(node.alt, {
before: value,
after: ']',
...tracker.current()
})
value += tracker.move(alt + '][')
subexit()
// Hide the fact that were in phrasing, because escapes dont work.
const stack = state.stack
state.stack = []
subexit = state.enter('reference')
// Note: for proper tracking, we should reset the output positions when we end
// up making a `shortcut` reference, because then there is no brace output.
// Practically, in that case, there is no content, so it doesnt matter that
// weve tracked one too many characters.
const reference = state.safe(state.associationId(node), {
before: value,
after: ']',
...tracker.current()
})
subexit()
state.stack = stack
exit()
if (type === 'full' || !alt || alt !== reference) {
value += tracker.move(reference + ']')
} else if (type === 'shortcut') {
// Remove the unwanted `[`.
value = value.slice(0, -1)
} else {
value += tracker.move(']')
}
return value
}
/**
* @returns {string}
*/
function imageReferencePeek() {
return '!'
}

View File

@@ -0,0 +1,20 @@
/**
* @param {Image} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function image(node: Image, _: Parents | undefined, state: State, info: Info): string;
export namespace image {
export { imagePeek as peek };
}
export type Image = import('mdast').Image;
export type Parents = import('mdast').Parents;
export type Info = import('../types.js').Info;
export type State = import('../types.js').State;
/**
* @returns {string}
*/
declare function imagePeek(): string;
export {};

View File

@@ -0,0 +1,84 @@
/**
* @typedef {import('mdast').Image} Image
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').State} State
*/
import {checkQuote} from '../util/check-quote.js'
image.peek = imagePeek
/**
* @param {Image} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function image(node, _, state, info) {
const quote = checkQuote(state)
const suffix = quote === '"' ? 'Quote' : 'Apostrophe'
const exit = state.enter('image')
let subexit = state.enter('label')
const tracker = state.createTracker(info)
let value = tracker.move('![')
value += tracker.move(
state.safe(node.alt, {before: value, after: ']', ...tracker.current()})
)
value += tracker.move('](')
subexit()
if (
// If theres no url but there is a title…
(!node.url && node.title) ||
// If there are control characters or whitespace.
/[\0- \u007F]/.test(node.url)
) {
subexit = state.enter('destinationLiteral')
value += tracker.move('<')
value += tracker.move(
state.safe(node.url, {before: value, after: '>', ...tracker.current()})
)
value += tracker.move('>')
} else {
// No whitespace, raw is prettier.
subexit = state.enter('destinationRaw')
value += tracker.move(
state.safe(node.url, {
before: value,
after: node.title ? ' ' : ')',
...tracker.current()
})
)
}
subexit()
if (node.title) {
subexit = state.enter(`title${suffix}`)
value += tracker.move(' ' + quote)
value += tracker.move(
state.safe(node.title, {
before: value,
after: quote,
...tracker.current()
})
)
value += tracker.move(quote)
subexit()
}
value += tracker.move(')')
exit()
return value
}
/**
* @returns {string}
*/
function imagePeek() {
return '!'
}

View File

@@ -0,0 +1,41 @@
export namespace handle {
export { blockquote };
export { hardBreak as break };
export { code };
export { definition };
export { emphasis };
export { hardBreak };
export { heading };
export { html };
export { image };
export { imageReference };
export { inlineCode };
export { link };
export { linkReference };
export { list };
export { listItem };
export { paragraph };
export { root };
export { strong };
export { text };
export { thematicBreak };
}
import { blockquote } from './blockquote.js';
import { hardBreak } from './break.js';
import { code } from './code.js';
import { definition } from './definition.js';
import { emphasis } from './emphasis.js';
import { heading } from './heading.js';
import { html } from './html.js';
import { image } from './image.js';
import { imageReference } from './image-reference.js';
import { inlineCode } from './inline-code.js';
import { link } from './link.js';
import { linkReference } from './link-reference.js';
import { list } from './list.js';
import { listItem } from './list-item.js';
import { paragraph } from './paragraph.js';
import { root } from './root.js';
import { strong } from './strong.js';
import { text } from './text.js';
import { thematicBreak } from './thematic-break.js';

View File

@@ -0,0 +1,45 @@
import {blockquote} from './blockquote.js'
import {hardBreak} from './break.js'
import {code} from './code.js'
import {definition} from './definition.js'
import {emphasis} from './emphasis.js'
import {heading} from './heading.js'
import {html} from './html.js'
import {image} from './image.js'
import {imageReference} from './image-reference.js'
import {inlineCode} from './inline-code.js'
import {link} from './link.js'
import {linkReference} from './link-reference.js'
import {list} from './list.js'
import {listItem} from './list-item.js'
import {paragraph} from './paragraph.js'
import {root} from './root.js'
import {strong} from './strong.js'
import {text} from './text.js'
import {thematicBreak} from './thematic-break.js'
/**
* Default (CommonMark) handlers.
*/
export const handle = {
blockquote,
break: hardBreak,
code,
definition,
emphasis,
hardBreak,
heading,
html,
image,
imageReference,
inlineCode,
link,
linkReference,
list,
listItem,
paragraph,
root,
strong,
text,
thematicBreak
}

View File

@@ -0,0 +1,18 @@
/**
* @param {InlineCode} node
* @param {Parents | undefined} _
* @param {State} state
* @returns {string}
*/
export function inlineCode(node: InlineCode, _: Parents | undefined, state: State): string;
export namespace inlineCode {
export { inlineCodePeek as peek };
}
export type InlineCode = import('mdast').InlineCode;
export type Parents = import('mdast').Parents;
export type State = import('../types.js').State;
/**
* @returns {string}
*/
declare function inlineCodePeek(): string;
export {};

View File

@@ -0,0 +1,77 @@
/**
* @typedef {import('mdast').InlineCode} InlineCode
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').State} State
*/
inlineCode.peek = inlineCodePeek
/**
* @param {InlineCode} node
* @param {Parents | undefined} _
* @param {State} state
* @returns {string}
*/
export function inlineCode(node, _, state) {
let value = node.value || ''
let sequence = '`'
let index = -1
// If there is a single grave accent on its own in the code, use a fence of
// two.
// If there are two in a row, use one.
while (new RegExp('(^|[^`])' + sequence + '([^`]|$)').test(value)) {
sequence += '`'
}
// If this is not just spaces or eols (tabs dont count), and either the
// first or last character are a space, eol, or tick, then pad with spaces.
if (
/[^ \r\n]/.test(value) &&
((/^[ \r\n]/.test(value) && /[ \r\n]$/.test(value)) || /^`|`$/.test(value))
) {
value = ' ' + value + ' '
}
// We have a potential problem: certain characters after eols could result in
// blocks being seen.
// For example, if someone injected the string `'\n# b'`, then that would
// result in an ATX heading.
// We cant escape characters in `inlineCode`, but because eols are
// transformed to spaces when going from markdown to HTML anyway, we can swap
// them out.
while (++index < state.unsafe.length) {
const pattern = state.unsafe[index]
const expression = state.compilePattern(pattern)
/** @type {RegExpExecArray | null} */
let match
// Only look for `atBreak`s.
// Btw: note that `atBreak` patterns will always start the regex at LF or
// CR.
if (!pattern.atBreak) continue
while ((match = expression.exec(value))) {
let position = match.index
// Support CRLF (patterns only look for one of the characters).
if (
value.charCodeAt(position) === 10 /* `\n` */ &&
value.charCodeAt(position - 1) === 13 /* `\r` */
) {
position--
}
value = value.slice(0, position) + ' ' + value.slice(match.index + 1)
}
}
return sequence + value + sequence
}
/**
* @returns {string}
*/
function inlineCodePeek() {
return '`'
}

View File

@@ -0,0 +1,20 @@
/**
* @param {LinkReference} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function linkReference(node: LinkReference, _: Parents | undefined, state: State, info: Info): string;
export namespace linkReference {
export { linkReferencePeek as peek };
}
export type LinkReference = import('mdast').LinkReference;
export type Parents = import('mdast').Parents;
export type Info = import('../types.js').Info;
export type State = import('../types.js').State;
/**
* @returns {string}
*/
declare function linkReferencePeek(): string;
export {};

View File

@@ -0,0 +1,65 @@
/**
* @typedef {import('mdast').LinkReference} LinkReference
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').State} State
*/
linkReference.peek = linkReferencePeek
/**
* @param {LinkReference} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function linkReference(node, _, state, info) {
const type = node.referenceType
const exit = state.enter('linkReference')
let subexit = state.enter('label')
const tracker = state.createTracker(info)
let value = tracker.move('[')
const text = state.containerPhrasing(node, {
before: value,
after: ']',
...tracker.current()
})
value += tracker.move(text + '][')
subexit()
// Hide the fact that were in phrasing, because escapes dont work.
const stack = state.stack
state.stack = []
subexit = state.enter('reference')
// Note: for proper tracking, we should reset the output positions when we end
// up making a `shortcut` reference, because then there is no brace output.
// Practically, in that case, there is no content, so it doesnt matter that
// weve tracked one too many characters.
const reference = state.safe(state.associationId(node), {
before: value,
after: ']',
...tracker.current()
})
subexit()
state.stack = stack
exit()
if (type === 'full' || !text || text !== reference) {
value += tracker.move(reference + ']')
} else if (type === 'shortcut') {
// Remove the unwanted `[`.
value = value.slice(0, -1)
} else {
value += tracker.move(']')
}
return value
}
/**
* @returns {string}
*/
function linkReferencePeek() {
return '['
}

View File

@@ -0,0 +1,24 @@
/**
* @param {Link} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function link(node: Link, _: Parents | undefined, state: State, info: Info): string;
export namespace link {
export { linkPeek as peek };
}
export type Link = import('mdast').Link;
export type Parents = import('mdast').Parents;
export type Exit = import('../types.js').Exit;
export type Info = import('../types.js').Info;
export type State = import('../types.js').State;
/**
* @param {Link} node
* @param {Parents | undefined} _
* @param {State} state
* @returns {string}
*/
declare function linkPeek(node: Link, _: Parents | undefined, state: State): string;
export {};

116
node_modules/mdast-util-to-markdown/lib/handle/link.js generated vendored Normal file
View File

@@ -0,0 +1,116 @@
/**
* @typedef {import('mdast').Link} Link
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').Exit} Exit
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').State} State
*/
import {checkQuote} from '../util/check-quote.js'
import {formatLinkAsAutolink} from '../util/format-link-as-autolink.js'
link.peek = linkPeek
/**
* @param {Link} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function link(node, _, state, info) {
const quote = checkQuote(state)
const suffix = quote === '"' ? 'Quote' : 'Apostrophe'
const tracker = state.createTracker(info)
/** @type {Exit} */
let exit
/** @type {Exit} */
let subexit
if (formatLinkAsAutolink(node, state)) {
// Hide the fact that were in phrasing, because escapes dont work.
const stack = state.stack
state.stack = []
exit = state.enter('autolink')
let value = tracker.move('<')
value += tracker.move(
state.containerPhrasing(node, {
before: value,
after: '>',
...tracker.current()
})
)
value += tracker.move('>')
exit()
state.stack = stack
return value
}
exit = state.enter('link')
subexit = state.enter('label')
let value = tracker.move('[')
value += tracker.move(
state.containerPhrasing(node, {
before: value,
after: '](',
...tracker.current()
})
)
value += tracker.move('](')
subexit()
if (
// If theres no url but there is a title…
(!node.url && node.title) ||
// If there are control characters or whitespace.
/[\0- \u007F]/.test(node.url)
) {
subexit = state.enter('destinationLiteral')
value += tracker.move('<')
value += tracker.move(
state.safe(node.url, {before: value, after: '>', ...tracker.current()})
)
value += tracker.move('>')
} else {
// No whitespace, raw is prettier.
subexit = state.enter('destinationRaw')
value += tracker.move(
state.safe(node.url, {
before: value,
after: node.title ? ' ' : ')',
...tracker.current()
})
)
}
subexit()
if (node.title) {
subexit = state.enter(`title${suffix}`)
value += tracker.move(' ' + quote)
value += tracker.move(
state.safe(node.title, {
before: value,
after: quote,
...tracker.current()
})
)
value += tracker.move(quote)
subexit()
}
value += tracker.move(')')
exit()
return value
}
/**
* @param {Link} node
* @param {Parents | undefined} _
* @param {State} state
* @returns {string}
*/
function linkPeek(node, _, state) {
return formatLinkAsAutolink(node, state) ? '<' : '['
}

View File

@@ -0,0 +1,13 @@
/**
* @param {ListItem} node
* @param {Parents | undefined} parent
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function listItem(node: ListItem, parent: Parents | undefined, state: State, info: Info): string;
export type ListItem = import('mdast').ListItem;
export type Parents = import('mdast').Parents;
export type Info = import('../types.js').Info;
export type Map = import('../types.js').Map;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,65 @@
/**
* @typedef {import('mdast').ListItem} ListItem
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').Map} Map
* @typedef {import('../types.js').State} State
*/
import {checkBullet} from '../util/check-bullet.js'
import {checkListItemIndent} from '../util/check-list-item-indent.js'
/**
* @param {ListItem} node
* @param {Parents | undefined} parent
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function listItem(node, parent, state, info) {
const listItemIndent = checkListItemIndent(state)
let bullet = state.bulletCurrent || checkBullet(state)
// Add the marker value for ordered lists.
if (parent && parent.type === 'list' && parent.ordered) {
bullet =
(typeof parent.start === 'number' && parent.start > -1
? parent.start
: 1) +
(state.options.incrementListMarker === false
? 0
: parent.children.indexOf(node)) +
bullet
}
let size = bullet.length + 1
if (
listItemIndent === 'tab' ||
(listItemIndent === 'mixed' &&
((parent && parent.type === 'list' && parent.spread) || node.spread))
) {
size = Math.ceil(size / 4) * 4
}
const tracker = state.createTracker(info)
tracker.move(bullet + ' '.repeat(size - bullet.length))
tracker.shift(size)
const exit = state.enter('listItem')
const value = state.indentLines(
state.containerFlow(node, tracker.current()),
map
)
exit()
return value
/** @type {Map} */
function map(line, index, blank) {
if (index) {
return (blank ? '' : ' '.repeat(size)) + line
}
return (blank ? bullet : bullet + ' '.repeat(size - bullet.length)) + line
}
}

View File

@@ -0,0 +1,12 @@
/**
* @param {List} node
* @param {Parents | undefined} parent
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function list(node: List, parent: Parents | undefined, state: State, info: Info): string;
export type List = import('mdast').List;
export type Parents = import('mdast').Parents;
export type Info = import('../types.js').Info;
export type State = import('../types.js').State;

102
node_modules/mdast-util-to-markdown/lib/handle/list.js generated vendored Normal file
View File

@@ -0,0 +1,102 @@
/**
* @typedef {import('mdast').List} List
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').State} State
*/
import {checkBullet} from '../util/check-bullet.js'
import {checkBulletOther} from '../util/check-bullet-other.js'
import {checkBulletOrdered} from '../util/check-bullet-ordered.js'
import {checkRule} from '../util/check-rule.js'
/**
* @param {List} node
* @param {Parents | undefined} parent
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function list(node, parent, state, info) {
const exit = state.enter('list')
const bulletCurrent = state.bulletCurrent
/** @type {string} */
let bullet = node.ordered ? checkBulletOrdered(state) : checkBullet(state)
/** @type {string} */
const bulletOther = node.ordered
? bullet === '.'
? ')'
: '.'
: checkBulletOther(state)
let useDifferentMarker =
parent && state.bulletLastUsed ? bullet === state.bulletLastUsed : false
if (!node.ordered) {
const firstListItem = node.children ? node.children[0] : undefined
// If theres an empty first list item directly in two list items,
// we have to use a different bullet:
//
// ```markdown
// * - *
// ```
//
// …because otherwise it would become one big thematic break.
if (
// Bullet could be used as a thematic break marker:
(bullet === '*' || bullet === '-') &&
// Empty first list item:
firstListItem &&
(!firstListItem.children || !firstListItem.children[0]) &&
// Directly in two other list items:
state.stack[state.stack.length - 1] === 'list' &&
state.stack[state.stack.length - 2] === 'listItem' &&
state.stack[state.stack.length - 3] === 'list' &&
state.stack[state.stack.length - 4] === 'listItem' &&
// That are each the first child.
state.indexStack[state.indexStack.length - 1] === 0 &&
state.indexStack[state.indexStack.length - 2] === 0 &&
state.indexStack[state.indexStack.length - 3] === 0
) {
useDifferentMarker = true
}
// If theres a thematic break at the start of the first list item,
// we have to use a different bullet:
//
// ```markdown
// * ---
// ```
//
// …because otherwise it would become one big thematic break.
if (checkRule(state) === bullet && firstListItem) {
let index = -1
while (++index < node.children.length) {
const item = node.children[index]
if (
item &&
item.type === 'listItem' &&
item.children &&
item.children[0] &&
item.children[0].type === 'thematicBreak'
) {
useDifferentMarker = true
break
}
}
}
}
if (useDifferentMarker) {
bullet = bulletOther
}
state.bulletCurrent = bullet
const value = state.containerFlow(node, info)
state.bulletLastUsed = bullet
state.bulletCurrent = bulletCurrent
exit()
return value
}

View File

@@ -0,0 +1,18 @@
/**
* @typedef {import('mdast').Paragraph} Paragraph
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').State} State
*/
/**
* @param {Paragraph} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function paragraph(node: Paragraph, _: Parents | undefined, state: State, info: Info): string;
export type Paragraph = import('mdast').Paragraph;
export type Parents = import('mdast').Parents;
export type Info = import('../types.js').Info;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,22 @@
/**
* @typedef {import('mdast').Paragraph} Paragraph
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').State} State
*/
/**
* @param {Paragraph} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function paragraph(node, _, state, info) {
const exit = state.enter('paragraph')
const subexit = state.enter('phrasing')
const value = state.containerPhrasing(node, info)
subexit()
exit()
return value
}

View File

@@ -0,0 +1,12 @@
/**
* @param {Root} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function root(node: Root, _: Parents | undefined, state: State, info: Info): string;
export type Parents = import('mdast').Parents;
export type Root = import('mdast').Root;
export type Info = import('../types.js').Info;
export type State = import('../types.js').State;

24
node_modules/mdast-util-to-markdown/lib/handle/root.js generated vendored Normal file
View File

@@ -0,0 +1,24 @@
/**
* @typedef {import('mdast').Parents} Parents
* @typedef {import('mdast').Root} Root
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').State} State
*/
import {phrasing} from 'mdast-util-phrasing'
/**
* @param {Root} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function root(node, _, state, info) {
// Note: `html` nodes are ambiguous.
const hasPhrasing = node.children.some(function (d) {
return phrasing(d)
})
const fn = hasPhrasing ? state.containerPhrasing : state.containerFlow
return fn.call(state, node, info)
}

View File

@@ -0,0 +1,23 @@
/**
* @param {Strong} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function strong(node: Strong, _: Parents | undefined, state: State, info: Info): string;
export namespace strong {
export { strongPeek as peek };
}
export type Parents = import('mdast').Parents;
export type Strong = import('mdast').Strong;
export type Info = import('../types.js').Info;
export type State = import('../types.js').State;
/**
* @param {Strong} _
* @param {Parents | undefined} _1
* @param {State} state
* @returns {string}
*/
declare function strongPeek(_: Strong, _1: Parents | undefined, state: State): string;
export {};

View File

@@ -0,0 +1,48 @@
/**
* @typedef {import('mdast').Parents} Parents
* @typedef {import('mdast').Strong} Strong
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').State} State
*/
import {checkStrong} from '../util/check-strong.js'
strong.peek = strongPeek
// To do: there are cases where emphasis cannot “form” depending on the
// previous or next character of sequences.
// Theres no way around that though, except for injecting zero-width stuff.
// Do we need to safeguard against that?
/**
* @param {Strong} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function strong(node, _, state, info) {
const marker = checkStrong(state)
const exit = state.enter('strong')
const tracker = state.createTracker(info)
let value = tracker.move(marker + marker)
value += tracker.move(
state.containerPhrasing(node, {
before: value,
after: marker,
...tracker.current()
})
)
value += tracker.move(marker + marker)
exit()
return value
}
/**
* @param {Strong} _
* @param {Parents | undefined} _1
* @param {State} state
* @returns {string}
*/
function strongPeek(_, _1, state) {
return state.options.strong || '*'
}

View File

@@ -0,0 +1,18 @@
/**
* @typedef {import('mdast').Parents} Parents
* @typedef {import('mdast').Text} Text
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').State} State
*/
/**
* @param {Text} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function text(node: Text, _: Parents | undefined, state: State, info: Info): string;
export type Parents = import('mdast').Parents;
export type Text = import('mdast').Text;
export type Info = import('../types.js').Info;
export type State = import('../types.js').State;

17
node_modules/mdast-util-to-markdown/lib/handle/text.js generated vendored Normal file
View File

@@ -0,0 +1,17 @@
/**
* @typedef {import('mdast').Parents} Parents
* @typedef {import('mdast').Text} Text
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').State} State
*/
/**
* @param {Text} node
* @param {Parents | undefined} _
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function text(node, _, state, info) {
return state.safe(node.value, info)
}

View File

@@ -0,0 +1,10 @@
/**
* @param {ThematicBreak} _
* @param {Parents | undefined} _1
* @param {State} state
* @returns {string}
*/
export function thematicBreak(_: ThematicBreak, _1: Parents | undefined, state: State): string;
export type Parents = import('mdast').Parents;
export type ThematicBreak = import('mdast').ThematicBreak;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,22 @@
/**
* @typedef {import('mdast').Parents} Parents
* @typedef {import('mdast').ThematicBreak} ThematicBreak
* @typedef {import('../types.js').State} State
*/
import {checkRuleRepetition} from '../util/check-rule-repetition.js'
import {checkRule} from '../util/check-rule.js'
/**
* @param {ThematicBreak} _
* @param {Parents | undefined} _1
* @param {State} state
* @returns {string}
*/
export function thematicBreak(_, _1, state) {
const value = (
checkRule(state) + (state.options.ruleSpaces ? ' ' : '')
).repeat(checkRuleRepetition(state))
return state.options.ruleSpaces ? value.slice(0, -1) : value
}

21
node_modules/mdast-util-to-markdown/lib/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,21 @@
/**
* Turn an mdast syntax tree into markdown.
*
* @param {Nodes} tree
* Tree to serialize.
* @param {Options} [options]
* Configuration (optional).
* @returns {string}
* Serialized markdown representing `tree`.
*/
export function toMarkdown(tree: Nodes, options?: import("./types.js").Options | undefined): string;
export type Nodes = import('mdast').Nodes;
export type Enter = import('./types.js').Enter;
export type Info = import('./types.js').Info;
export type Join = import('./types.js').Join;
export type FlowParents = import('./types.js').FlowParents;
export type Options = import('./types.js').Options;
export type PhrasingParents = import('./types.js').PhrasingParents;
export type SafeConfig = import('./types.js').SafeConfig;
export type State = import('./types.js').State;
export type TrackFields = import('./types.js').TrackFields;

193
node_modules/mdast-util-to-markdown/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,193 @@
/**
* @typedef {import('mdast').Nodes} Nodes
* @typedef {import('./types.js').Enter} Enter
* @typedef {import('./types.js').Info} Info
* @typedef {import('./types.js').Join} Join
* @typedef {import('./types.js').FlowParents} FlowParents
* @typedef {import('./types.js').Options} Options
* @typedef {import('./types.js').PhrasingParents} PhrasingParents
* @typedef {import('./types.js').SafeConfig} SafeConfig
* @typedef {import('./types.js').State} State
* @typedef {import('./types.js').TrackFields} TrackFields
*/
import {zwitch} from 'zwitch'
import {configure} from './configure.js'
import {handle as handlers} from './handle/index.js'
import {join} from './join.js'
import {unsafe} from './unsafe.js'
import {association} from './util/association.js'
import {compilePattern} from './util/compile-pattern.js'
import {containerPhrasing} from './util/container-phrasing.js'
import {containerFlow} from './util/container-flow.js'
import {indentLines} from './util/indent-lines.js'
import {safe} from './util/safe.js'
import {track} from './util/track.js'
/**
* Turn an mdast syntax tree into markdown.
*
* @param {Nodes} tree
* Tree to serialize.
* @param {Options} [options]
* Configuration (optional).
* @returns {string}
* Serialized markdown representing `tree`.
*/
export function toMarkdown(tree, options = {}) {
/** @type {State} */
const state = {
enter,
indentLines,
associationId: association,
containerPhrasing: containerPhrasingBound,
containerFlow: containerFlowBound,
createTracker: track,
compilePattern,
safe: safeBound,
stack: [],
unsafe: [...unsafe],
join: [...join],
// @ts-expect-error: GFM / frontmatter are typed in `mdast` but not defined
// here.
handlers: {...handlers},
options: {},
indexStack: [],
// @ts-expect-error: add `handle` in a second.
handle: undefined
}
configure(state, options)
if (state.options.tightDefinitions) {
state.join.push(joinDefinition)
}
state.handle = zwitch('type', {
invalid,
unknown,
handlers: state.handlers
})
let result = state.handle(tree, undefined, state, {
before: '\n',
after: '\n',
now: {line: 1, column: 1},
lineShift: 0
})
if (
result &&
result.charCodeAt(result.length - 1) !== 10 &&
result.charCodeAt(result.length - 1) !== 13
) {
result += '\n'
}
return result
/** @type {Enter} */
function enter(name) {
state.stack.push(name)
return exit
/**
* @returns {undefined}
*/
function exit() {
state.stack.pop()
}
}
}
/**
* @param {unknown} value
* @returns {never}
*/
function invalid(value) {
throw new Error('Cannot handle value `' + value + '`, expected node')
}
/**
* @param {unknown} value
* @returns {never}
*/
function unknown(value) {
// Always a node.
const node = /** @type {Nodes} */ (value)
throw new Error('Cannot handle unknown node `' + node.type + '`')
}
/** @type {Join} */
function joinDefinition(left, right) {
// No blank line between adjacent definitions.
if (left.type === 'definition' && left.type === right.type) {
return 0
}
}
/**
* Serialize the children of a parent that contains phrasing children.
*
* These children will be joined flush together.
*
* @this {State}
* Info passed around about the current state.
* @param {PhrasingParents} parent
* Parent of flow nodes.
* @param {Info} info
* Info on where we are in the document we are generating.
* @returns {string}
* Serialized children, joined together.
*/
function containerPhrasingBound(parent, info) {
return containerPhrasing(parent, this, info)
}
/**
* Serialize the children of a parent that contains flow children.
*
* These children will typically be joined by blank lines.
* What they are joined by exactly is defined by `Join` functions.
*
* @this {State}
* Info passed around about the current state.
* @param {FlowParents} parent
* Parent of flow nodes.
* @param {TrackFields} info
* Info on where we are in the document we are generating.
* @returns {string}
* Serialized children, joined by (blank) lines.
*/
function containerFlowBound(parent, info) {
return containerFlow(parent, this, info)
}
/**
* Make a string safe for embedding in markdown constructs.
*
* In markdown, almost all punctuation characters can, in certain cases,
* result in something.
* Whether they do is highly subjective to where they happen and in what
* they happen.
*
* To solve this, `mdast-util-to-markdown` tracks:
*
* * Characters before and after something;
* * What “constructs” we are in.
*
* This information is then used by this function to escape or encode
* special characters.
*
* @this {State}
* Info passed around about the current state.
* @param {string | null | undefined} value
* Raw value to make safe.
* @param {SafeConfig} config
* Configuration.
* @returns {string}
* Serialized markdown safe for embedding.
*/
function safeBound(value, config) {
return safe(this, value, config)
}

3
node_modules/mdast-util-to-markdown/lib/join.d.ts generated vendored Normal file
View File

@@ -0,0 +1,3 @@
/** @type {Array<Join>} */
export const join: Array<Join>;
export type Join = import('./types.js').Join;

39
node_modules/mdast-util-to-markdown/lib/join.js generated vendored Normal file
View File

@@ -0,0 +1,39 @@
/**
* @typedef {import('./types.js').Join} Join
*/
import {formatCodeAsIndented} from './util/format-code-as-indented.js'
import {formatHeadingAsSetext} from './util/format-heading-as-setext.js'
/** @type {Array<Join>} */
export const join = [joinDefaults]
/** @type {Join} */
function joinDefaults(left, right, parent, state) {
// Indented code after list or another indented code.
if (
right.type === 'code' &&
formatCodeAsIndented(right, state) &&
(left.type === 'list' ||
(left.type === right.type && formatCodeAsIndented(left, state)))
) {
return false
}
// Join children of a list or an item.
// In which case, `parent` has a `spread` field.
if ('spread' in parent && typeof parent.spread === 'boolean') {
if (
left.type === 'paragraph' &&
// Two paragraphs.
(left.type === right.type ||
right.type === 'definition' ||
// Paragraph followed by a setext heading.
(right.type === 'heading' && formatHeadingAsSetext(right, state)))
) {
return
}
return parent.spread ? 1 : 0
}
}

440
node_modules/mdast-util-to-markdown/lib/types.d.ts generated vendored Normal file
View File

@@ -0,0 +1,440 @@
export type Point = import('unist').Point;
export type Association = import('mdast').Association;
export type Nodes = import('mdast').Nodes;
export type Parents = import('mdast').Parents;
export type PhrasingContent = import('mdast').PhrasingContent;
export type TableCell = import('mdast').TableCell;
export type TableRow = import('mdast').TableRow;
export type ConstructName = import('../index.js').ConstructName;
export type FlowParents = Exclude<Parents, PhrasingContent | TableCell | TableRow>;
export type FlowChildren = import("mdast").Blockquote | import("mdast").Code | import("mdast").Heading | import("mdast").Html | import("mdast").List | import("mdast").Paragraph | import("mdast").Table | import("mdast").ThematicBreak | import("mdast").Definition | import("mdast").FootnoteDefinition | import("mdast").Yaml | import("mdast").ListItem | import("mdast").Break | import("mdast").Delete | import("mdast").Emphasis | import("mdast").FootnoteReference | import("mdast").Image | import("mdast").ImageReference | import("mdast").InlineCode | import("mdast").Link | import("mdast").LinkReference | import("mdast").Strong | import("mdast").Text | import("mdast").TableCell | import("mdast").TableRow;
export type PhrasingParents = import("mdast").Blockquote | import("mdast").Heading | import("mdast").List | import("mdast").Paragraph | import("mdast").Table | import("mdast").FootnoteDefinition | import("mdast").ListItem | import("mdast").Delete | import("mdast").Emphasis | import("mdast").Link | import("mdast").LinkReference | import("mdast").Strong | import("mdast").TableCell | import("mdast").TableRow | import("mdast").Root;
/**
* Info on where we are in the document we are generating.
*/
export type TrackFields = {
/**
* Current point.
*/
now: Point;
/**
* Number of columns each line will be shifted by wrapping nodes.
*/
lineShift: number;
};
/**
* Info on the characters that are around the current thing we are
* generating.
*/
export type SafeFields = {
/**
* Characters before this (guaranteed to be one, can be more).
*/
before: string;
/**
* Characters after this (guaranteed to be one, can be more).
*/
after: string;
};
/**
* Info on the surrounding of the node that is serialized.
*/
export type Info = TrackFields & SafeFields;
/**
* Get current tracked info.
*/
export type TrackCurrent = () => TrackFields;
/**
* Define a relative increased line shift (the typical indent for lines).
*/
export type TrackShift = (value: number) => undefined;
/**
* Move past some generated markdown.
*/
export type TrackMove = (value: string | null | undefined) => string;
/**
* Track positional info in the output.
*
* This info isnt used yet but such functionality will allow line wrapping,
* source maps, etc.
*/
export type Tracker = {
/**
* Get the current tracked info.
*/
current: TrackCurrent;
/**
* Define an increased line shift (the typical indent for lines).
*/
shift: TrackShift;
/**
* Move past some generated markdown.
*/
move: TrackMove;
};
/**
* Track positional info in the output.
*
* This info isnt used yet but such functionality will allow line wrapping,
* source maps, etc.
*/
export type CreateTracker = (info: TrackFields) => Tracker;
/**
* Compile an unsafe pattern to a regex.
*/
export type CompilePattern = (info: Unsafe) => RegExp;
/**
* Get an identifier from an association to match it to others.
*
* Associations are nodes that match to something else through an ID:
* <https://github.com/syntax-tree/mdast#association>.
*
* The `label` of an association is the string value: character escapes and
* references work, and casing is intact.
* The `identifier` is used to match one association to another:
* controversially, character escapes and references dont work in this
* matching: `&copy;` does not match `©`, and `\+` does not match `+`.
*
* But casing is ignored (and whitespace) is trimmed and collapsed: ` A\nb`
* matches `a b`.
* So, we do prefer the label when figuring out how were going to serialize:
* it has whitespace, casing, and we can ignore most useless character
* escapes and all character references.
*/
export type AssociationId = (node: Association) => string;
/**
* Map function to pad a single line.
*/
export type Map = (value: string, line: number, blank: boolean) => string;
/**
* Pad serialized markdown.
*/
export type IndentLines = (value: string, map: Map) => string;
/**
* Serialize the children of a parent that contains phrasing children.
*
* These children will be joined flush together.
*/
export type ContainerPhrasing = (parent: PhrasingParents, info: Info) => string;
/**
* Serialize the children of a parent that contains flow children.
*
* These children will typically be joined by blank lines.
* What they are joined by exactly is defined by `Join` functions.
*/
export type ContainerFlow = (parent: FlowParents, info: TrackFields) => string;
/**
* Extra configuration for `safe`
*/
export type SafeEncodeFields = {
/**
* Extra characters that *must* be encoded (as character references) instead
* of escaped (character escapes) (optional).
*
* Only ASCII punctuation will use character escapes, so you never need to
* pass non-ASCII-punctuation here.
*/
encode?: Array<string> | null | undefined;
};
export type SafeConfig = SafeFields & SafeEncodeFields;
/**
* Make a string safe for embedding in markdown constructs.
*
* In markdown, almost all punctuation characters can, in certain cases,
* result in something.
* Whether they do is highly subjective to where they happen and in what
* they happen.
*
* To solve this, `mdast-util-to-markdown` tracks:
*
* * Characters before and after something;
* * What “constructs” we are in.
*
* This information is then used by this function to escape or encode
* special characters.
*/
export type Safe = (input: string | null | undefined, config: SafeConfig) => string;
/**
* Enter something.
*/
export type Enter = (name: ConstructName) => Exit;
/**
* Exit something.
*/
export type Exit = () => undefined;
/**
* Info passed around about the current state.
*/
export type State = {
/**
* Stack of constructs were in.
*/
stack: Array<ConstructName>;
/**
* Positions of child nodes in their parents.
*/
indexStack: Array<number>;
/**
* Pad serialized markdown.
*/
indentLines: IndentLines;
/**
* Get an identifier from an association to match it to others.
*/
associationId: AssociationId;
/**
* Compile an unsafe pattern to a regex.
*/
compilePattern: CompilePattern;
/**
* Serialize the children of a parent that contains phrasing children.
*/
containerPhrasing: ContainerPhrasing;
/**
* Serialize the children of a parent that contains flow children.
*/
containerFlow: ContainerFlow;
/**
* Track positional info in the output.
*/
createTracker: CreateTracker;
/**
* Serialize the children of a parent that contains flow children.
*/
safe: Safe;
/**
* Enter a construct (returns a corresponding exit function).
*/
enter: Enter;
/**
* Applied user configuration.
*/
options: Options;
/**
* Applied unsafe patterns.
*/
unsafe: Array<Unsafe>;
/**
* Applied join handlers.
*/
join: Array<Join>;
/**
* Call the configured handler for the given node.
*/
handle: Handle;
/**
* Applied handlers.
*/
handlers: Handlers;
/**
* List marker currently in use.
*/
bulletCurrent: string | undefined;
/**
* List marker previously in use.
*/
bulletLastUsed: string | undefined;
};
/**
* Handle a particular node.
*/
export type Handle = (node: any, parent: Parents | undefined, state: State, Info: Info) => string;
/**
* Handle particular nodes.
*
* Each key is a node type, each value its corresponding handler.
*/
export type Handlers = Record<Nodes['type'], Handle>;
/**
* How to join two blocks.
*
* “Blocks” are typically joined by one blank line.
* Sometimes its nicer to have them flush next to each other, yet other
* times they cannot occur together at all.
*
* Join functions receive two adjacent siblings and their parent and what
* they return defines how many blank lines to use between them.
*/
export type Join = (left: FlowChildren, right: FlowChildren, parent: FlowParents, state: State) => boolean | number | null | undefined | void;
/**
* Schema that defines when a character cannot occur.
*/
export type Unsafe = {
/**
* Single unsafe character.
*/
character: string;
/**
* Constructs where this is bad (optional).
*/
inConstruct?: Array<ConstructName> | ConstructName | null | undefined;
/**
* Constructs where this is fine again (optional).
*/
notInConstruct?: Array<ConstructName> | ConstructName | null | undefined;
/**
* `character` is bad when this is before it (cannot be used together with
* `atBreak`) (optional).
*/
before?: string | null | undefined;
/**
* `character` is bad when this is after it (optional).
*/
after?: string | null | undefined;
/**
* `character` is bad at a break (cannot be used together with `before`) (optional).
*/
atBreak?: boolean | null | undefined;
/**
* The unsafe pattern (this whole object) compiled as a regex (do not use).
*
* This is internal and must not be defined.
*/
_compiled?: RegExp | null | undefined;
};
/**
* Configuration (optional).
*/
export type Options = {
/**
* Marker to use for bullets of items in unordered lists (default: `'*'`).
*
* There are three cases where the primary bullet cannot be used:
*
* * when three or more list items are on their own, the last one is empty,
* and `bullet` is also a valid `rule`: `* - +`; this would turn into a
* thematic break if serialized with three primary bullets; `bulletOther`
* is used for the last item
* * when a thematic break is the first child of a list item and `bullet` is
* the same character as `rule`: `- ***`; this would turn into a single
* thematic break if serialized with primary bullets; `bulletOther` is used
* for the item
* * when two unordered lists appear next to each other: `* a\n- b`;
* `bulletOther` is used for such lists
*/
bullet?: '*' | '+' | '-' | null | undefined;
/**
* Marker to use in certain cases where the primary bullet doesnt work
* (default: `'-'` when `bullet` is `'*'`, `'*'` otherwise).
*
* Cannot be equal to `bullet`.
*/
bulletOther?: '*' | '+' | '-' | null | undefined;
/**
* Marker to use for bullets of items in ordered lists (default: `'.'`).
*
* There is one case where the primary bullet for ordered items cannot be
* used:
*
* * when two ordered lists appear next to each other: `1. a\n2) b`; to
* solve
* that, `'.'` will be used when `bulletOrdered` is `')'`, and `'.'`
* otherwise
*/
bulletOrdered?: '.' | ')' | null | undefined;
/**
* Whether to add the same number of number signs (`#`) at the end of an ATX
* heading as the opening sequence (default: `false`).
*/
closeAtx?: boolean | null | undefined;
/**
* Marker to use for emphasis (default: `'*'`).
*/
emphasis?: '*' | '_' | null | undefined;
/**
* Marker to use for fenced code (default: ``'`'``).
*/
fence?: '`' | '~' | null | undefined;
/**
* Whether to use fenced code always (default: `true`).
*
* The default is to use fenced code if there is a language defined, if the
* code is empty, or if it starts or ends in blank lines.
*/
fences?: boolean | null | undefined;
/**
* Whether to increment the counter of ordered lists items (default: `true`).
*/
incrementListMarker?: boolean | null | undefined;
/**
* How to indent the content of list items (default: `'one'`).
*
* Either with the size of the bullet plus one space (when `'one'`), a tab
* stop (`'tab'`), or depending on the item and its parent list (`'mixed'`,
* uses `'one'` if the item and list are tight and `'tab'` otherwise).
*/
listItemIndent?: 'mixed' | 'one' | 'tab' | null | undefined;
/**
* Marker to use for titles (default: `'"'`).
*/
quote?: '"' | "'" | null | undefined;
/**
* Whether to always use resource links (default: `false`).
*
* The default is to use autolinks (`<https://example.com>`) when possible
* and resource links (`[text](url)`) otherwise.
*/
resourceLink?: boolean | null | undefined;
/**
* Marker to use for thematic breaks (default: `'*'`).
*/
rule?: '*' | '-' | '_' | null | undefined;
/**
* Number of markers to use for thematic breaks (default: `3`).
*/
ruleRepetition?: number | null | undefined;
/**
* Whether to add spaces between markers in thematic breaks (default:
* `false`).
*/
ruleSpaces?: boolean | null | undefined;
/**
* Whether to use setext headings when possible (default: `false`).
*
* The default is to always use ATX headings (`# heading`) instead of setext
* headings (`heading\n=======`).
* Setext headings cannot be used for empty headings or headings with a rank
* of three or more.
*/
setext?: boolean | null | undefined;
/**
* Marker to use for strong (default: `'*'`).
*/
strong?: '*' | '_' | null | undefined;
/**
* Whether to join definitions without a blank line (default: `false`).
*
* The default is to add blank lines between any flow (“block”) construct.
* Turning this option on is a shortcut for a join function like so:
*
* ```js
* function joinTightDefinitions(left, right) {
* if (left.type === 'definition' && right.type === 'definition') {
* return 0
* }
* }
* ```
*/
tightDefinitions?: boolean | null | undefined;
/**
* Handle particular nodes (optional).
*
* Each key is a node type, each value its corresponding handler.
*/
handlers?: Partial<Handlers> | null | undefined;
/**
* How to join blocks (optional).
*/
join?: Array<Join> | null | undefined;
/**
* Schemas that define when characters cannot occur (optional).
*/
unsafe?: Array<Unsafe> | null | undefined;
/**
* List of extensions to include (optional).
*
* Each `ToMarkdownExtension` is an object with the same interface as
* `Options` here.
*/
extensions?: Array<Options> | null | undefined;
};

410
node_modules/mdast-util-to-markdown/lib/types.js generated vendored Normal file
View File

@@ -0,0 +1,410 @@
/**
* @typedef {import('unist').Point} Point
* @typedef {import('mdast').Association} Association
* @typedef {import('mdast').Nodes} Nodes
* @typedef {import('mdast').Parents} Parents
* @typedef {import('mdast').PhrasingContent} PhrasingContent
* @typedef {import('mdast').TableCell} TableCell
* @typedef {import('mdast').TableRow} TableRow
* @typedef {import('../index.js').ConstructName} ConstructName
*/
/**
* @typedef {Exclude<Parents, PhrasingContent | TableCell | TableRow>} FlowParents
* @typedef {FlowParents extends {children: Array<infer T>} ? T : never} FlowChildren
* @typedef {Parents extends {children: Array<infer T>} ? PhrasingContent extends T ? Parents : never : never} PhrasingParents
*/
/**
* @typedef TrackFields
* Info on where we are in the document we are generating.
* @property {Point} now
* Current point.
* @property {number} lineShift
* Number of columns each line will be shifted by wrapping nodes.
*
* @typedef SafeFields
* Info on the characters that are around the current thing we are
* generating.
* @property {string} before
* Characters before this (guaranteed to be one, can be more).
* @property {string} after
* Characters after this (guaranteed to be one, can be more).
*
* @typedef {TrackFields & SafeFields} Info
* Info on the surrounding of the node that is serialized.
*
* @callback TrackCurrent
* Get current tracked info.
* @returns {TrackFields}
* Current tracked info.
*
* @callback TrackShift
* Define a relative increased line shift (the typical indent for lines).
* @param {number} value
* Relative increment in how much each line will be padded.
* @returns {undefined}
* Nothing.
*
* @callback TrackMove
* Move past some generated markdown.
* @param {string | null | undefined} value
* Generated markdown.
* @returns {string}
* Given markdown.
*
* @typedef Tracker
* Track positional info in the output.
*
* This info isnt used yet but such functionality will allow line wrapping,
* source maps, etc.
* @property {TrackCurrent} current
* Get the current tracked info.
* @property {TrackShift} shift
* Define an increased line shift (the typical indent for lines).
* @property {TrackMove} move
* Move past some generated markdown.
*
* @callback CreateTracker
* Track positional info in the output.
*
* This info isnt used yet but such functionality will allow line wrapping,
* source maps, etc.
* @param {TrackFields} info
* Info on where we are in the document we are generating.
* @returns {Tracker}
* Tracker.
*
* @callback CompilePattern
* Compile an unsafe pattern to a regex.
* @param {Unsafe} info
* Pattern.
* @returns {RegExp}
* Regex.
*
* @callback AssociationId
* Get an identifier from an association to match it to others.
*
* Associations are nodes that match to something else through an ID:
* <https://github.com/syntax-tree/mdast#association>.
*
* The `label` of an association is the string value: character escapes and
* references work, and casing is intact.
* The `identifier` is used to match one association to another:
* controversially, character escapes and references dont work in this
* matching: `&copy;` does not match `©`, and `\+` does not match `+`.
*
* But casing is ignored (and whitespace) is trimmed and collapsed: ` A\nb`
* matches `a b`.
* So, we do prefer the label when figuring out how were going to serialize:
* it has whitespace, casing, and we can ignore most useless character
* escapes and all character references.
* @param {Association} node
* Node that includes an association.
* @returns {string}
* ID.
*
* @callback Map
* Map function to pad a single line.
* @param {string} value
* A single line of serialized markdown.
* @param {number} line
* Line number relative to the fragment.
* @param {boolean} blank
* Whether the line is considered blank in markdown.
* @returns {string}
* Padded line.
*
* @callback IndentLines
* Pad serialized markdown.
* @param {string} value
* Whole fragment of serialized markdown.
* @param {Map} map
* Map function.
* @returns {string}
* Padded value.
*
* @callback ContainerPhrasing
* Serialize the children of a parent that contains phrasing children.
*
* These children will be joined flush together.
* @param {PhrasingParents} parent
* Parent of flow nodes.
* @param {Info} info
* Info on where we are in the document we are generating.
* @returns {string}
* Serialized children, joined together.
*
* @callback ContainerFlow
* Serialize the children of a parent that contains flow children.
*
* These children will typically be joined by blank lines.
* What they are joined by exactly is defined by `Join` functions.
* @param {FlowParents} parent
* Parent of flow nodes.
* @param {TrackFields} info
* Info on where we are in the document we are generating.
* @returns {string}
* Serialized children, joined by (blank) lines.
*
* @typedef SafeEncodeFields
* Extra configuration for `safe`
* @property {Array<string> | null | undefined} [encode]
* Extra characters that *must* be encoded (as character references) instead
* of escaped (character escapes) (optional).
*
* Only ASCII punctuation will use character escapes, so you never need to
* pass non-ASCII-punctuation here.
*
* @typedef {SafeFields & SafeEncodeFields} SafeConfig
*
* @callback Safe
* Make a string safe for embedding in markdown constructs.
*
* In markdown, almost all punctuation characters can, in certain cases,
* result in something.
* Whether they do is highly subjective to where they happen and in what
* they happen.
*
* To solve this, `mdast-util-to-markdown` tracks:
*
* * Characters before and after something;
* * What “constructs” we are in.
*
* This information is then used by this function to escape or encode
* special characters.
* @param {string | null | undefined} input
* Raw value to make safe.
* @param {SafeConfig} config
* Configuration.
* @returns {string}
* Serialized markdown safe for embedding.
*
* @callback Enter
* Enter something.
* @param {ConstructName} name
* Label, more similar to a micromark event than an mdast node type.
* @returns {Exit}
* Revert.
*
* @callback Exit
* Exit something.
* @returns {undefined}
* Nothing.
*
* @typedef State
* Info passed around about the current state.
* @property {Array<ConstructName>} stack
* Stack of constructs were in.
* @property {Array<number>} indexStack
* Positions of child nodes in their parents.
* @property {IndentLines} indentLines
* Pad serialized markdown.
* @property {AssociationId} associationId
* Get an identifier from an association to match it to others.
* @property {CompilePattern} compilePattern
* Compile an unsafe pattern to a regex.
* @property {ContainerPhrasing} containerPhrasing
* Serialize the children of a parent that contains phrasing children.
* @property {ContainerFlow} containerFlow
* Serialize the children of a parent that contains flow children.
* @property {CreateTracker} createTracker
* Track positional info in the output.
* @property {Safe} safe
* Serialize the children of a parent that contains flow children.
* @property {Enter} enter
* Enter a construct (returns a corresponding exit function).
* @property {Options} options
* Applied user configuration.
* @property {Array<Unsafe>} unsafe
* Applied unsafe patterns.
* @property {Array<Join>} join
* Applied join handlers.
* @property {Handle} handle
* Call the configured handler for the given node.
* @property {Handlers} handlers
* Applied handlers.
* @property {string | undefined} bulletCurrent
* List marker currently in use.
* @property {string | undefined} bulletLastUsed
* List marker previously in use.
*
* @callback Handle
* Handle a particular node.
* @param {any} node
* Expected mdast node.
* @param {Parents | undefined} parent
* Parent of `node`.
* @param {State} state
* Info passed around about the current state.
* @param {Info} Info
* Info on the surrounding of the node that is serialized.
* @returns {string}
* Serialized markdown representing `node`.
*
* @typedef {Record<Nodes['type'], Handle>} Handlers
* Handle particular nodes.
*
* Each key is a node type, each value its corresponding handler.
*
* @callback Join
* How to join two blocks.
*
* “Blocks” are typically joined by one blank line.
* Sometimes its nicer to have them flush next to each other, yet other
* times they cannot occur together at all.
*
* Join functions receive two adjacent siblings and their parent and what
* they return defines how many blank lines to use between them.
* @param {FlowChildren} left
* First of two adjacent siblings.
* @param {FlowChildren} right
* Second of two adjacent siblings.
* @param {FlowParents} parent
* Parent of the two siblings.
* @param {State} state
* Info passed around about the current state.
* @returns {boolean | number | null | undefined | void}
* How many blank lines to use between the siblings.
*
* Where `true` is as passing `1` and `false` means the nodes cannot be
* joined by a blank line, such as two adjacent block quotes or indented code
* after a list, in which case a comment will be injected to break them up:
*
* ```markdown
* > Quote 1
*
* <!---->
*
* > Quote 2
* ```
*
* > 👉 **Note**: abusing this feature will break markdown.
* > One such example is when returning `0` for two paragraphs, which will
* > result in the text running together, and in the future to be seen as
* > one paragraph.
*
* @typedef Unsafe
* Schema that defines when a character cannot occur.
* @property {string} character
* Single unsafe character.
* @property {Array<ConstructName> | ConstructName | null | undefined} [inConstruct]
* Constructs where this is bad (optional).
* @property {Array<ConstructName> | ConstructName | null | undefined} [notInConstruct]
* Constructs where this is fine again (optional).
* @property {string | null | undefined} [before]
* `character` is bad when this is before it (cannot be used together with
* `atBreak`) (optional).
* @property {string | null | undefined} [after]
* `character` is bad when this is after it (optional).
* @property {boolean | null | undefined} [atBreak]
* `character` is bad at a break (cannot be used together with `before`) (optional).
* @property {RegExp | null | undefined} [_compiled]
* The unsafe pattern (this whole object) compiled as a regex (do not use).
*
* This is internal and must not be defined.
*
* @typedef Options
* Configuration (optional).
* @property {'*' | '+' | '-' | null | undefined} [bullet='*']
* Marker to use for bullets of items in unordered lists (default: `'*'`).
*
* There are three cases where the primary bullet cannot be used:
*
* * when three or more list items are on their own, the last one is empty,
* and `bullet` is also a valid `rule`: `* - +`; this would turn into a
* thematic break if serialized with three primary bullets; `bulletOther`
* is used for the last item
* * when a thematic break is the first child of a list item and `bullet` is
* the same character as `rule`: `- ***`; this would turn into a single
* thematic break if serialized with primary bullets; `bulletOther` is used
* for the item
* * when two unordered lists appear next to each other: `* a\n- b`;
* `bulletOther` is used for such lists
* @property {'*' | '+' | '-' | null | undefined} [bulletOther]
* Marker to use in certain cases where the primary bullet doesnt work
* (default: `'-'` when `bullet` is `'*'`, `'*'` otherwise).
*
* Cannot be equal to `bullet`.
* @property {'.' | ')' | null | undefined} [bulletOrdered='.']
* Marker to use for bullets of items in ordered lists (default: `'.'`).
*
* There is one case where the primary bullet for ordered items cannot be
* used:
*
* * when two ordered lists appear next to each other: `1. a\n2) b`; to
* solve
* that, `'.'` will be used when `bulletOrdered` is `')'`, and `'.'`
* otherwise
* @property {boolean | null | undefined} [closeAtx=false]
* Whether to add the same number of number signs (`#`) at the end of an ATX
* heading as the opening sequence (default: `false`).
* @property {'*' | '_' | null | undefined} [emphasis='*']
* Marker to use for emphasis (default: `'*'`).
* @property {'`' | '~' | null | undefined} [fence='`']
* Marker to use for fenced code (default: ``'`'``).
* @property {boolean | null | undefined} [fences=true]
* Whether to use fenced code always (default: `true`).
*
* The default is to use fenced code if there is a language defined, if the
* code is empty, or if it starts or ends in blank lines.
* @property {boolean | null | undefined} [incrementListMarker=true]
* Whether to increment the counter of ordered lists items (default: `true`).
* @property {'mixed' | 'one' | 'tab' | null | undefined} [listItemIndent='one']
* How to indent the content of list items (default: `'one'`).
*
* Either with the size of the bullet plus one space (when `'one'`), a tab
* stop (`'tab'`), or depending on the item and its parent list (`'mixed'`,
* uses `'one'` if the item and list are tight and `'tab'` otherwise).
* @property {'"' | "'" | null | undefined} [quote='"']
* Marker to use for titles (default: `'"'`).
* @property {boolean | null | undefined} [resourceLink=false]
* Whether to always use resource links (default: `false`).
*
* The default is to use autolinks (`<https://example.com>`) when possible
* and resource links (`[text](url)`) otherwise.
* @property {'*' | '-' | '_' | null | undefined} [rule='*']
* Marker to use for thematic breaks (default: `'*'`).
* @property {number | null | undefined} [ruleRepetition=3]
* Number of markers to use for thematic breaks (default: `3`).
* @property {boolean | null | undefined} [ruleSpaces=false]
* Whether to add spaces between markers in thematic breaks (default:
* `false`).
* @property {boolean | null | undefined} [setext=false]
* Whether to use setext headings when possible (default: `false`).
*
* The default is to always use ATX headings (`# heading`) instead of setext
* headings (`heading\n=======`).
* Setext headings cannot be used for empty headings or headings with a rank
* of three or more.
* @property {'*' | '_' | null | undefined} [strong='*']
* Marker to use for strong (default: `'*'`).
* @property {boolean | null | undefined} [tightDefinitions=false]
* Whether to join definitions without a blank line (default: `false`).
*
* The default is to add blank lines between any flow (“block”) construct.
* Turning this option on is a shortcut for a join function like so:
*
* ```js
* function joinTightDefinitions(left, right) {
* if (left.type === 'definition' && right.type === 'definition') {
* return 0
* }
* }
* ```
* @property {Partial<Handlers> | null | undefined} [handlers={}]
* Handle particular nodes (optional).
*
* Each key is a node type, each value its corresponding handler.
* @property {Array<Join> | null | undefined} [join=[]]
* How to join blocks (optional).
* @property {Array<Unsafe> | null | undefined} [unsafe=[]]
* Schemas that define when characters cannot occur (optional).
* @property {Array<Options> | null | undefined} [extensions=[]]
* List of extensions to include (optional).
*
* Each `ToMarkdownExtension` is an object with the same interface as
* `Options` here.
*/
export {}

4
node_modules/mdast-util-to-markdown/lib/unsafe.d.ts generated vendored Normal file
View File

@@ -0,0 +1,4 @@
/** @type {Array<Unsafe>} */
export const unsafe: Array<Unsafe>;
export type ConstructName = import('./types.js').ConstructName;
export type Unsafe = import('./types.js').Unsafe;

147
node_modules/mdast-util-to-markdown/lib/unsafe.js generated vendored Normal file
View File

@@ -0,0 +1,147 @@
/**
* @typedef {import('./types.js').ConstructName} ConstructName
* @typedef {import('./types.js').Unsafe} Unsafe
*/
/**
* List of constructs that occur in phrasing (paragraphs, headings), but cannot
* contain things like attention (emphasis, strong), images, or links.
* So they sort of cancel each other out.
* Note: could use a better name.
*
* @type {Array<ConstructName>}
*/
const fullPhrasingSpans = [
'autolink',
'destinationLiteral',
'destinationRaw',
'reference',
'titleQuote',
'titleApostrophe'
]
/** @type {Array<Unsafe>} */
export const unsafe = [
{character: '\t', after: '[\\r\\n]', inConstruct: 'phrasing'},
{character: '\t', before: '[\\r\\n]', inConstruct: 'phrasing'},
{
character: '\t',
inConstruct: ['codeFencedLangGraveAccent', 'codeFencedLangTilde']
},
{
character: '\r',
inConstruct: [
'codeFencedLangGraveAccent',
'codeFencedLangTilde',
'codeFencedMetaGraveAccent',
'codeFencedMetaTilde',
'destinationLiteral',
'headingAtx'
]
},
{
character: '\n',
inConstruct: [
'codeFencedLangGraveAccent',
'codeFencedLangTilde',
'codeFencedMetaGraveAccent',
'codeFencedMetaTilde',
'destinationLiteral',
'headingAtx'
]
},
{character: ' ', after: '[\\r\\n]', inConstruct: 'phrasing'},
{character: ' ', before: '[\\r\\n]', inConstruct: 'phrasing'},
{
character: ' ',
inConstruct: ['codeFencedLangGraveAccent', 'codeFencedLangTilde']
},
// An exclamation mark can start an image, if it is followed by a link or
// a link reference.
{
character: '!',
after: '\\[',
inConstruct: 'phrasing',
notInConstruct: fullPhrasingSpans
},
// A quote can break out of a title.
{character: '"', inConstruct: 'titleQuote'},
// A number sign could start an ATX heading if it starts a line.
{atBreak: true, character: '#'},
{character: '#', inConstruct: 'headingAtx', after: '(?:[\r\n]|$)'},
// Dollar sign and percentage are not used in markdown.
// An ampersand could start a character reference.
{character: '&', after: '[#A-Za-z]', inConstruct: 'phrasing'},
// An apostrophe can break out of a title.
{character: "'", inConstruct: 'titleApostrophe'},
// A left paren could break out of a destination raw.
{character: '(', inConstruct: 'destinationRaw'},
// A left paren followed by `]` could make something into a link or image.
{
before: '\\]',
character: '(',
inConstruct: 'phrasing',
notInConstruct: fullPhrasingSpans
},
// A right paren could start a list item or break out of a destination
// raw.
{atBreak: true, before: '\\d+', character: ')'},
{character: ')', inConstruct: 'destinationRaw'},
// An asterisk can start thematic breaks, list items, emphasis, strong.
{atBreak: true, character: '*', after: '(?:[ \t\r\n*])'},
{character: '*', inConstruct: 'phrasing', notInConstruct: fullPhrasingSpans},
// A plus sign could start a list item.
{atBreak: true, character: '+', after: '(?:[ \t\r\n])'},
// A dash can start thematic breaks, list items, and setext heading
// underlines.
{atBreak: true, character: '-', after: '(?:[ \t\r\n-])'},
// A dot could start a list item.
{atBreak: true, before: '\\d+', character: '.', after: '(?:[ \t\r\n]|$)'},
// Slash, colon, and semicolon are not used in markdown for constructs.
// A less than can start html (flow or text) or an autolink.
// HTML could start with an exclamation mark (declaration, cdata, comment),
// slash (closing tag), question mark (instruction), or a letter (tag).
// An autolink also starts with a letter.
// Finally, it could break out of a destination literal.
{atBreak: true, character: '<', after: '[!/?A-Za-z]'},
{
character: '<',
after: '[!/?A-Za-z]',
inConstruct: 'phrasing',
notInConstruct: fullPhrasingSpans
},
{character: '<', inConstruct: 'destinationLiteral'},
// An equals to can start setext heading underlines.
{atBreak: true, character: '='},
// A greater than can start block quotes and it can break out of a
// destination literal.
{atBreak: true, character: '>'},
{character: '>', inConstruct: 'destinationLiteral'},
// Question mark and at sign are not used in markdown for constructs.
// A left bracket can start definitions, references, labels,
{atBreak: true, character: '['},
{character: '[', inConstruct: 'phrasing', notInConstruct: fullPhrasingSpans},
{character: '[', inConstruct: ['label', 'reference']},
// A backslash can start an escape (when followed by punctuation) or a
// hard break (when followed by an eol).
// Note: typical escapes are handled in `safe`!
{character: '\\', after: '[\\r\\n]', inConstruct: 'phrasing'},
// A right bracket can exit labels.
{character: ']', inConstruct: ['label', 'reference']},
// Caret is not used in markdown for constructs.
// An underscore can start emphasis, strong, or a thematic break.
{atBreak: true, character: '_'},
{character: '_', inConstruct: 'phrasing', notInConstruct: fullPhrasingSpans},
// A grave accent can start code (fenced or text), or it can break out of
// a grave accent code fence.
{atBreak: true, character: '`'},
{
character: '`',
inConstruct: ['codeFencedLangGraveAccent', 'codeFencedMetaGraveAccent']
},
{character: '`', inConstruct: 'phrasing', notInConstruct: fullPhrasingSpans},
// Left brace, vertical bar, right brace are not used in markdown for
// constructs.
// A tilde can start code (fenced).
{atBreak: true, character: '~'}
]

View File

@@ -0,0 +1,2 @@
export function association(node: import("mdast").Association): string;
export type AssociationId = import('../types.js').AssociationId;

View File

@@ -0,0 +1,33 @@
/**
* @typedef {import('../types.js').AssociationId} AssociationId
*/
import {decodeString} from 'micromark-util-decode-string'
/**
* Get an identifier from an association to match it to others.
*
* Associations are nodes that match to something else through an ID:
* <https://github.com/syntax-tree/mdast#association>.
*
* The `label` of an association is the string value: character escapes and
* references work, and casing is intact.
* The `identifier` is used to match one association to another:
* controversially, character escapes and references dont work in this
* matching: `&copy;` does not match `©`, and `\+` does not match `+`.
*
* But casing is ignored (and whitespace) is trimmed and collapsed: ` A\nb`
* matches `a b`.
* So, we do prefer the label when figuring out how were going to serialize:
* it has whitespace, casing, and we can ignore most useless character
* escapes and all character references.
*
* @type {AssociationId}
*/
export function association(node) {
if (node.label || !node.identifier) {
return node.label || ''
}
return decodeString(node.identifier)
}

View File

@@ -0,0 +1,11 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['bulletOrdered'], null | undefined>}
*/
export function checkBulletOrdered(state: State): Exclude<Options['bulletOrdered'], null | undefined>;
export type Options = import('../types.js').Options;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,22 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['bulletOrdered'], null | undefined>}
*/
export function checkBulletOrdered(state) {
const marker = state.options.bulletOrdered || '.'
if (marker !== '.' && marker !== ')') {
throw new Error(
'Cannot serialize items with `' +
marker +
'` for `options.bulletOrdered`, expected `.` or `)`'
)
}
return marker
}

View File

@@ -0,0 +1,7 @@
/**
* @param {State} state
* @returns {Exclude<Options['bullet'], null | undefined>}
*/
export function checkBulletOther(state: State): Exclude<Options['bullet'], null | undefined>;
export type Options = import('../types.js').Options;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,39 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
import {checkBullet} from './check-bullet.js'
/**
* @param {State} state
* @returns {Exclude<Options['bullet'], null | undefined>}
*/
export function checkBulletOther(state) {
const bullet = checkBullet(state)
const bulletOther = state.options.bulletOther
if (!bulletOther) {
return bullet === '*' ? '-' : '*'
}
if (bulletOther !== '*' && bulletOther !== '+' && bulletOther !== '-') {
throw new Error(
'Cannot serialize items with `' +
bulletOther +
'` for `options.bulletOther`, expected `*`, `+`, or `-`'
)
}
if (bulletOther === bullet) {
throw new Error(
'Expected `bullet` (`' +
bullet +
'`) and `bulletOther` (`' +
bulletOther +
'`) to be different'
)
}
return bulletOther
}

View File

@@ -0,0 +1,11 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['bullet'], null | undefined>}
*/
export function checkBullet(state: State): Exclude<Options['bullet'], null | undefined>;
export type Options = import('../types.js').Options;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,22 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['bullet'], null | undefined>}
*/
export function checkBullet(state) {
const marker = state.options.bullet || '*'
if (marker !== '*' && marker !== '+' && marker !== '-') {
throw new Error(
'Cannot serialize items with `' +
marker +
'` for `options.bullet`, expected `*`, `+`, or `-`'
)
}
return marker
}

View File

@@ -0,0 +1,11 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['emphasis'], null | undefined>}
*/
export function checkEmphasis(state: State): Exclude<Options['emphasis'], null | undefined>;
export type Options = import('../types.js').Options;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,22 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['emphasis'], null | undefined>}
*/
export function checkEmphasis(state) {
const marker = state.options.emphasis || '*'
if (marker !== '*' && marker !== '_') {
throw new Error(
'Cannot serialize emphasis with `' +
marker +
'` for `options.emphasis`, expected `*`, or `_`'
)
}
return marker
}

View File

@@ -0,0 +1,11 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['fence'], null | undefined>}
*/
export function checkFence(state: State): Exclude<Options['fence'], null | undefined>;
export type Options = import('../types.js').Options;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,22 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['fence'], null | undefined>}
*/
export function checkFence(state) {
const marker = state.options.fence || '`'
if (marker !== '`' && marker !== '~') {
throw new Error(
'Cannot serialize code with `' +
marker +
'` for `options.fence`, expected `` ` `` or `~`'
)
}
return marker
}

View File

@@ -0,0 +1,11 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['listItemIndent'], null | undefined>}
*/
export function checkListItemIndent(state: State): Exclude<Options['listItemIndent'], null | undefined>;
export type Options = import('../types.js').Options;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,22 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['listItemIndent'], null | undefined>}
*/
export function checkListItemIndent(state) {
const style = state.options.listItemIndent || 'one'
if (style !== 'tab' && style !== 'one' && style !== 'mixed') {
throw new Error(
'Cannot serialize items with `' +
style +
'` for `options.listItemIndent`, expected `tab`, `one`, or `mixed`'
)
}
return style
}

View File

@@ -0,0 +1,11 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['quote'], null | undefined>}
*/
export function checkQuote(state: State): Exclude<Options['quote'], null | undefined>;
export type Options = import('../types.js').Options;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,22 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['quote'], null | undefined>}
*/
export function checkQuote(state) {
const marker = state.options.quote || '"'
if (marker !== '"' && marker !== "'") {
throw new Error(
'Cannot serialize title with `' +
marker +
'` for `options.quote`, expected `"`, or `\'`'
)
}
return marker
}

View File

@@ -0,0 +1,11 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['ruleRepetition'], null | undefined>}
*/
export function checkRuleRepetition(state: State): Exclude<Options['ruleRepetition'], null | undefined>;
export type Options = import('../types.js').Options;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,22 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['ruleRepetition'], null | undefined>}
*/
export function checkRuleRepetition(state) {
const repetition = state.options.ruleRepetition || 3
if (repetition < 3) {
throw new Error(
'Cannot serialize rules with repetition `' +
repetition +
'` for `options.ruleRepetition`, expected `3` or more'
)
}
return repetition
}

View File

@@ -0,0 +1,11 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['rule'], null | undefined>}
*/
export function checkRule(state: State): Exclude<Options['rule'], null | undefined>;
export type Options = import('../types.js').Options;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,22 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['rule'], null | undefined>}
*/
export function checkRule(state) {
const marker = state.options.rule || '*'
if (marker !== '*' && marker !== '-' && marker !== '_') {
throw new Error(
'Cannot serialize rules with `' +
marker +
'` for `options.rule`, expected `*`, `-`, or `_`'
)
}
return marker
}

View File

@@ -0,0 +1,11 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['strong'], null | undefined>}
*/
export function checkStrong(state: State): Exclude<Options['strong'], null | undefined>;
export type Options = import('../types.js').Options;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,22 @@
/**
* @typedef {import('../types.js').Options} Options
* @typedef {import('../types.js').State} State
*/
/**
* @param {State} state
* @returns {Exclude<Options['strong'], null | undefined>}
*/
export function checkStrong(state) {
const marker = state.options.strong || '*'
if (marker !== '*' && marker !== '_') {
throw new Error(
'Cannot serialize strong with `' +
marker +
'` for `options.strong`, expected `*`, or `_`'
)
}
return marker
}

View File

@@ -0,0 +1,2 @@
export function compilePattern(info: import("../types.js").Unsafe): RegExp;
export type CompilePattern = import('../types.js').CompilePattern;

View File

@@ -0,0 +1,24 @@
/**
* @typedef {import('../types.js').CompilePattern} CompilePattern
*/
/**
* @type {CompilePattern}
*/
export function compilePattern(pattern) {
if (!pattern._compiled) {
const before =
(pattern.atBreak ? '[\\r\\n][\\t ]*' : '') +
(pattern.before ? '(?:' + pattern.before + ')' : '')
pattern._compiled = new RegExp(
(before ? '(' + before + ')' : '') +
(/[|\\{}()[\]^$+*?.-]/.test(pattern.character) ? '\\' : '') +
pattern.character +
(pattern.after ? '(?:' + pattern.after + ')' : ''),
'g'
)
}
return pattern._compiled
}

View File

@@ -0,0 +1,21 @@
/**
* @typedef {import('../types.js').FlowParents} FlowParents
* @typedef {import('../types.js').FlowChildren} FlowChildren
* @typedef {import('../types.js').State} State
* @typedef {import('../types.js').TrackFields} TrackFields
*/
/**
* @param {FlowParents} parent
* Parent of flow nodes.
* @param {State} state
* Info passed around about the current state.
* @param {TrackFields} info
* Info on where we are in the document we are generating.
* @returns {string}
* Serialized children, joined by (blank) lines.
*/
export function containerFlow(parent: FlowParents, state: State, info: TrackFields): string;
export type FlowParents = import('../types.js').FlowParents;
export type FlowChildren = import('../types.js').FlowChildren;
export type State = import('../types.js').State;
export type TrackFields = import('../types.js').TrackFields;

View File

@@ -0,0 +1,86 @@
/**
* @typedef {import('../types.js').FlowParents} FlowParents
* @typedef {import('../types.js').FlowChildren} FlowChildren
* @typedef {import('../types.js').State} State
* @typedef {import('../types.js').TrackFields} TrackFields
*/
/**
* @param {FlowParents} parent
* Parent of flow nodes.
* @param {State} state
* Info passed around about the current state.
* @param {TrackFields} info
* Info on where we are in the document we are generating.
* @returns {string}
* Serialized children, joined by (blank) lines.
*/
export function containerFlow(parent, state, info) {
const indexStack = state.indexStack
const children = parent.children || []
const tracker = state.createTracker(info)
/** @type {Array<string>} */
const results = []
let index = -1
indexStack.push(-1)
while (++index < children.length) {
const child = children[index]
indexStack[indexStack.length - 1] = index
results.push(
tracker.move(
state.handle(child, parent, state, {
before: '\n',
after: '\n',
...tracker.current()
})
)
)
if (child.type !== 'list') {
state.bulletLastUsed = undefined
}
if (index < children.length - 1) {
results.push(
tracker.move(between(child, children[index + 1], parent, state))
)
}
}
indexStack.pop()
return results.join('')
}
/**
* @param {FlowChildren} left
* @param {FlowChildren} right
* @param {FlowParents} parent
* @param {State} state
* @returns {string}
*/
function between(left, right, parent, state) {
let index = state.join.length
while (index--) {
const result = state.join[index](left, right, parent, state)
if (result === true || result === 1) {
break
}
if (typeof result === 'number') {
return '\n'.repeat(1 + result)
}
if (result === false) {
return '\n\n<!---->\n\n'
}
}
return '\n\n'
}

View File

@@ -0,0 +1,25 @@
/**
* @typedef {import('../types.js').Handle} Handle
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').PhrasingParents} PhrasingParents
* @typedef {import('../types.js').State} State
*/
/**
* Serialize the children of a parent that contains phrasing children.
*
* These children will be joined flush together.
*
* @param {PhrasingParents} parent
* Parent of flow nodes.
* @param {State} state
* Info passed around about the current state.
* @param {Info} info
* Info on where we are in the document we are generating.
* @returns {string}
* Serialized children, joined together.
*/
export function containerPhrasing(parent: PhrasingParents, state: State, info: Info): string;
export type Handle = import('../types.js').Handle;
export type Info = import('../types.js').Info;
export type PhrasingParents = import('../types.js').PhrasingParents;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,96 @@
/**
* @typedef {import('../types.js').Handle} Handle
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').PhrasingParents} PhrasingParents
* @typedef {import('../types.js').State} State
*/
/**
* Serialize the children of a parent that contains phrasing children.
*
* These children will be joined flush together.
*
* @param {PhrasingParents} parent
* Parent of flow nodes.
* @param {State} state
* Info passed around about the current state.
* @param {Info} info
* Info on where we are in the document we are generating.
* @returns {string}
* Serialized children, joined together.
*/
export function containerPhrasing(parent, state, info) {
const indexStack = state.indexStack
const children = parent.children || []
/** @type {Array<string>} */
const results = []
let index = -1
let before = info.before
indexStack.push(-1)
let tracker = state.createTracker(info)
while (++index < children.length) {
const child = children[index]
/** @type {string} */
let after
indexStack[indexStack.length - 1] = index
if (index + 1 < children.length) {
/** @type {Handle} */
// @ts-expect-error: hush, its actually a `zwitch`.
let handle = state.handle.handlers[children[index + 1].type]
/** @type {Handle} */
// @ts-expect-error: hush, its actually a `zwitch`.
if (handle && handle.peek) handle = handle.peek
after = handle
? handle(children[index + 1], parent, state, {
before: '',
after: '',
...tracker.current()
}).charAt(0)
: ''
} else {
after = info.after
}
// In some cases, html (text) can be found in phrasing right after an eol.
// When wed serialize that, in most cases that would be seen as html
// (flow).
// As we cant escape or so to prevent it from happening, we take a somewhat
// reasonable approach: replace that eol with a space.
// See: <https://github.com/syntax-tree/mdast-util-to-markdown/issues/15>
if (
results.length > 0 &&
(before === '\r' || before === '\n') &&
child.type === 'html'
) {
results[results.length - 1] = results[results.length - 1].replace(
/(\r?\n|\r)$/,
' '
)
before = ' '
// To do: does this work to reset tracker?
tracker = state.createTracker(info)
tracker.move(results.join(''))
}
results.push(
tracker.move(
state.handle(child, parent, state, {
...tracker.current(),
before,
after
})
)
)
before = results[results.length - 1].slice(-1)
}
indexStack.pop()
return results.join('')
}

View File

@@ -0,0 +1,12 @@
/**
* @typedef {import('mdast').Code} Code
* @typedef {import('../types.js').State} State
*/
/**
* @param {Code} node
* @param {State} state
* @returns {boolean}
*/
export function formatCodeAsIndented(node: Code, state: State): boolean;
export type Code = import('mdast').Code;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,22 @@
/**
* @typedef {import('mdast').Code} Code
* @typedef {import('../types.js').State} State
*/
/**
* @param {Code} node
* @param {State} state
* @returns {boolean}
*/
export function formatCodeAsIndented(node, state) {
return Boolean(
state.options.fences === false &&
node.value &&
// If theres no info…
!node.lang &&
// And theres a non-whitespace character…
/[^ \r\n]/.test(node.value) &&
// And the value doesnt start or end in a blank…
!/^[\t ]*(?:[\r\n]|$)|(?:^|[\r\n])[\t ]*$/.test(node.value)
)
}

View File

@@ -0,0 +1,8 @@
/**
* @param {Heading} node
* @param {State} state
* @returns {boolean}
*/
export function formatHeadingAsSetext(node: Heading, state: State): boolean;
export type Heading = import('mdast').Heading;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,34 @@
/**
* @typedef {import('mdast').Heading} Heading
* @typedef {import('../types.js').State} State
*/
import {EXIT, visit} from 'unist-util-visit'
import {toString} from 'mdast-util-to-string'
/**
* @param {Heading} node
* @param {State} state
* @returns {boolean}
*/
export function formatHeadingAsSetext(node, state) {
let literalWithBreak = false
// Look for literals with a line break.
// Note that this also
visit(node, function (node) {
if (
('value' in node && /\r?\n|\r/.test(node.value)) ||
node.type === 'break'
) {
literalWithBreak = true
return EXIT
}
})
return Boolean(
(!node.depth || node.depth < 3) &&
toString(node) &&
(state.options.setext || literalWithBreak)
)
}

View File

@@ -0,0 +1,8 @@
/**
* @param {Link} node
* @param {State} state
* @returns {boolean}
*/
export function formatLinkAsAutolink(node: Link, state: State): boolean;
export type Link = import('mdast').Link;
export type State = import('../types.js').State;

View File

@@ -0,0 +1,34 @@
/**
* @typedef {import('mdast').Link} Link
* @typedef {import('../types.js').State} State
*/
import {toString} from 'mdast-util-to-string'
/**
* @param {Link} node
* @param {State} state
* @returns {boolean}
*/
export function formatLinkAsAutolink(node, state) {
const raw = toString(node)
return Boolean(
!state.options.resourceLink &&
// If theres a url…
node.url &&
// And theres a no title…
!node.title &&
// And the content of `node` is a single text node…
node.children &&
node.children.length === 1 &&
node.children[0].type === 'text' &&
// And if the url is the same as the content…
(raw === node.url || 'mailto:' + raw === node.url) &&
// And that starts w/ a protocol…
/^[a-z][a-z+.-]+:/i.test(node.url) &&
// And that doesnt contain ASCII control codes (character escapes and
// references dont work), space, or angle brackets…
!/[\0- <>\u007F]/.test(node.url)
)
}

View File

@@ -0,0 +1,2 @@
export function indentLines(value: string, map: import("../types.js").Map): string;
export type IndentLines = import('../types.js').IndentLines;

View File

@@ -0,0 +1,35 @@
/**
* @typedef {import('../types.js').IndentLines} IndentLines
*/
const eol = /\r?\n|\r/g
/**
* @type {IndentLines}
*/
export function indentLines(value, map) {
/** @type {Array<string>} */
const result = []
let start = 0
let line = 0
/** @type {RegExpExecArray | null} */
let match
while ((match = eol.exec(value))) {
one(value.slice(start, match.index))
result.push(match[0])
start = match.index + match[0].length
line++
}
one(value.slice(start))
return result.join('')
/**
* @param {string} value
*/
function one(value) {
result.push(map(value, line, !value))
}
}

View File

@@ -0,0 +1,12 @@
/**
* @typedef {import('../types.js').ConstructName} ConstructName
* @typedef {import('../types.js').Unsafe} Unsafe
*/
/**
* @param {Array<ConstructName>} stack
* @param {Unsafe} pattern
* @returns {boolean}
*/
export function patternInScope(stack: Array<ConstructName>, pattern: Unsafe): boolean;
export type ConstructName = import('../types.js').ConstructName;
export type Unsafe = import('../types.js').Unsafe;

View File

@@ -0,0 +1,42 @@
/**
* @typedef {import('../types.js').ConstructName} ConstructName
* @typedef {import('../types.js').Unsafe} Unsafe
*/
/**
* @param {Array<ConstructName>} stack
* @param {Unsafe} pattern
* @returns {boolean}
*/
export function patternInScope(stack, pattern) {
return (
listInScope(stack, pattern.inConstruct, true) &&
!listInScope(stack, pattern.notInConstruct, false)
)
}
/**
* @param {Array<ConstructName>} stack
* @param {Unsafe['inConstruct']} list
* @param {boolean} none
* @returns {boolean}
*/
function listInScope(stack, list, none) {
if (typeof list === 'string') {
list = [list]
}
if (!list || list.length === 0) {
return none
}
let index = -1
while (++index < list.length) {
if (stack.includes(list[index])) {
return true
}
}
return false
}

28
node_modules/mdast-util-to-markdown/lib/util/safe.d.ts generated vendored Normal file
View File

@@ -0,0 +1,28 @@
/**
* Make a string safe for embedding in markdown constructs.
*
* In markdown, almost all punctuation characters can, in certain cases,
* result in something.
* Whether they do is highly subjective to where they happen and in what
* they happen.
*
* To solve this, `mdast-util-to-markdown` tracks:
*
* * Characters before and after something;
* * What “constructs” we are in.
*
* This information is then used by this function to escape or encode
* special characters.
*
* @param {State} state
* Info passed around about the current state.
* @param {string | null | undefined} input
* Raw value to make safe.
* @param {SafeConfig} config
* Configuration.
* @returns {string}
* Serialized markdown safe for embedding.
*/
export function safe(state: State, input: string | null | undefined, config: SafeConfig): string;
export type SafeConfig = import('../types.js').SafeConfig;
export type State = import('../types.js').State;

176
node_modules/mdast-util-to-markdown/lib/util/safe.js generated vendored Normal file
View File

@@ -0,0 +1,176 @@
/**
* @typedef {import('../types.js').SafeConfig} SafeConfig
* @typedef {import('../types.js').State} State
*/
import {patternInScope} from './pattern-in-scope.js'
/**
* Make a string safe for embedding in markdown constructs.
*
* In markdown, almost all punctuation characters can, in certain cases,
* result in something.
* Whether they do is highly subjective to where they happen and in what
* they happen.
*
* To solve this, `mdast-util-to-markdown` tracks:
*
* * Characters before and after something;
* * What “constructs” we are in.
*
* This information is then used by this function to escape or encode
* special characters.
*
* @param {State} state
* Info passed around about the current state.
* @param {string | null | undefined} input
* Raw value to make safe.
* @param {SafeConfig} config
* Configuration.
* @returns {string}
* Serialized markdown safe for embedding.
*/
export function safe(state, input, config) {
const value = (config.before || '') + (input || '') + (config.after || '')
/** @type {Array<number>} */
const positions = []
/** @type {Array<string>} */
const result = []
/** @type {Record<number, {before: boolean, after: boolean}>} */
const infos = {}
let index = -1
while (++index < state.unsafe.length) {
const pattern = state.unsafe[index]
if (!patternInScope(state.stack, pattern)) {
continue
}
const expression = state.compilePattern(pattern)
/** @type {RegExpExecArray | null} */
let match
while ((match = expression.exec(value))) {
const before = 'before' in pattern || Boolean(pattern.atBreak)
const after = 'after' in pattern
const position = match.index + (before ? match[1].length : 0)
if (positions.includes(position)) {
if (infos[position].before && !before) {
infos[position].before = false
}
if (infos[position].after && !after) {
infos[position].after = false
}
} else {
positions.push(position)
infos[position] = {before, after}
}
}
}
positions.sort(numerical)
let start = config.before ? config.before.length : 0
const end = value.length - (config.after ? config.after.length : 0)
index = -1
while (++index < positions.length) {
const position = positions[index]
// Character before or after matched:
if (position < start || position >= end) {
continue
}
// If this character is supposed to be escaped because it has a condition on
// the next character, and the next character is definitly being escaped,
// then skip this escape.
if (
(position + 1 < end &&
positions[index + 1] === position + 1 &&
infos[position].after &&
!infos[position + 1].before &&
!infos[position + 1].after) ||
(positions[index - 1] === position - 1 &&
infos[position].before &&
!infos[position - 1].before &&
!infos[position - 1].after)
) {
continue
}
if (start !== position) {
// If we have to use a character reference, an ampersand would be more
// correct, but as backslashes only care about punctuation, either will
// do the trick
result.push(escapeBackslashes(value.slice(start, position), '\\'))
}
start = position
if (
/[!-/:-@[-`{-~]/.test(value.charAt(position)) &&
(!config.encode || !config.encode.includes(value.charAt(position)))
) {
// Character escape.
result.push('\\')
} else {
// Character reference.
result.push(
'&#x' + value.charCodeAt(position).toString(16).toUpperCase() + ';'
)
start++
}
}
result.push(escapeBackslashes(value.slice(start, end), config.after))
return result.join('')
}
/**
* @param {number} a
* @param {number} b
* @returns {number}
*/
function numerical(a, b) {
return a - b
}
/**
* @param {string} value
* @param {string} after
* @returns {string}
*/
function escapeBackslashes(value, after) {
const expression = /\\(?=[!-/:-@[-`{-~])/g
/** @type {Array<number>} */
const positions = []
/** @type {Array<string>} */
const results = []
const whole = value + after
let index = -1
let start = 0
/** @type {RegExpExecArray | null} */
let match
while ((match = expression.exec(whole))) {
positions.push(match.index)
}
while (++index < positions.length) {
if (start !== positions[index]) {
results.push(value.slice(start, positions[index]))
}
results.push('\\')
start = positions[index]
}
results.push(value.slice(start))
return results.join('')
}

View File

@@ -0,0 +1,5 @@
export function track(info: import("../types.js").TrackFields): import("../types.js").Tracker;
export type CreateTracker = import('../types.js').CreateTracker;
export type TrackCurrent = import('../types.js').TrackCurrent;
export type TrackMove = import('../types.js').TrackMove;
export type TrackShift = import('../types.js').TrackShift;

58
node_modules/mdast-util-to-markdown/lib/util/track.js generated vendored Normal file
View File

@@ -0,0 +1,58 @@
/**
* @typedef {import('../types.js').CreateTracker} CreateTracker
* @typedef {import('../types.js').TrackCurrent} TrackCurrent
* @typedef {import('../types.js').TrackMove} TrackMove
* @typedef {import('../types.js').TrackShift} TrackShift
*/
/**
* Track positional info in the output.
*
* @type {CreateTracker}
*/
export function track(config) {
// Defaults are used to prevent crashes when older utilities somehow activate
// this code.
/* c8 ignore next 5 */
const options = config || {}
const now = options.now || {}
let lineShift = options.lineShift || 0
let line = now.line || 1
let column = now.column || 1
return {move, current, shift}
/**
* Get the current tracked info.
*
* @type {TrackCurrent}
*/
function current() {
return {now: {line, column}, lineShift}
}
/**
* Define an increased line shift (the typical indent for lines).
*
* @type {TrackShift}
*/
function shift(value) {
lineShift += value
}
/**
* Move past some generated markdown.
*
* @type {TrackMove}
*/
function move(input) {
// eslint-disable-next-line unicorn/prefer-default-parameters
const value = input || ''
const chunks = value.split(/\r?\n|\r/g)
const tail = chunks[chunks.length - 1]
line += chunks.length - 1
column =
chunks.length === 1 ? column + tail.length : 1 + tail.length + lineShift
return value
}
}

22
node_modules/mdast-util-to-markdown/license generated vendored Normal file
View File

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

109
node_modules/mdast-util-to-markdown/package.json generated vendored Normal file
View File

@@ -0,0 +1,109 @@
{
"name": "mdast-util-to-markdown",
"version": "2.1.0",
"description": "mdast utility to serialize markdown",
"license": "MIT",
"keywords": [
"unist",
"mdast",
"mdast-util",
"util",
"utility",
"markdown",
"markup",
"serialize",
"stringify",
"compile",
"syntax",
"tree",
"ast"
],
"repository": "syntax-tree/mdast-util-to-markdown",
"bugs": "https://github.com/syntax-tree/mdast-util-to-markdown/issues",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
},
"author": "Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)",
"contributors": [
"Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)"
],
"sideEffects": false,
"type": "module",
"exports": "./index.js",
"files": [
"lib/",
"index.d.ts",
"index.js"
],
"dependencies": {
"@types/mdast": "^4.0.0",
"@types/unist": "^3.0.0",
"longest-streak": "^3.0.0",
"mdast-util-phrasing": "^4.0.0",
"mdast-util-to-string": "^4.0.0",
"micromark-util-decode-string": "^2.0.0",
"unist-util-visit": "^5.0.0",
"zwitch": "^2.0.0"
},
"devDependencies": {
"@types/node": "^20.0.0",
"c8": "^8.0.0",
"mdast-util-from-markdown": "^2.0.0",
"prettier": "^3.0.0",
"remark-cli": "^11.0.0",
"remark-preset-wooorm": "^9.0.0",
"type-coverage": "^2.0.0",
"typescript": "^5.0.0",
"unist-util-remove-position": "^5.0.0",
"xo": "^0.55.0"
},
"scripts": {
"prepack": "npm run build && npm run format",
"build": "tsc --build --clean && tsc --build && type-coverage",
"format": "remark . -qfo && prettier . -w --log-level warn && xo --fix",
"test-api": "node --conditions development test/index.js",
"test-coverage": "c8 --100 --reporter lcov npm run test-api",
"test": "npm run build && npm run format && npm run test-coverage"
},
"prettier": {
"bracketSpacing": false,
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "none",
"useTabs": false
},
"remarkConfig": {
"plugins": [
"remark-preset-wooorm"
]
},
"typeCoverage": {
"atLeast": 100,
"detail": true,
"ignoreFiles": [
"lib/types.d.ts"
],
"ignoreCatch": true,
"strict": true
},
"xo": {
"overrides": [
{
"files": [
"**/*.ts"
],
"rules": {
"@typescript-eslint/consistent-type-definitions": "off"
}
}
],
"prettier": true,
"rules": {
"complexity": "off",
"unicorn/prefer-at": "off",
"unicorn/prefer-code-point": "off"
}
}
}

746
node_modules/mdast-util-to-markdown/readme.md generated vendored Normal file
View File

@@ -0,0 +1,746 @@
# mdast-util-to-markdown
[![Build][build-badge]][build]
[![Coverage][coverage-badge]][coverage]
[![Downloads][downloads-badge]][downloads]
[![Size][size-badge]][size]
[![Sponsors][sponsors-badge]][collective]
[![Backers][backers-badge]][collective]
[![Chat][chat-badge]][chat]
**[mdast][]** utility that turns a syntax tree into markdown.
## Contents
* [What is this?](#what-is-this)
* [When should I use this?](#when-should-i-use-this)
* [Install](#install)
* [Use](#use)
* [API](#api)
* [`toMarkdown(tree[, options])`](#tomarkdowntree-options)
* [`defaultHandlers`](#defaulthandlers)
* [`ConstructName`](#constructname)
* [`ConstructNameMap`](#constructnamemap)
* [`Handle`](#handle)
* [`Handlers`](#handlers)
* [`Info`](#info)
* [`Join`](#join)
* [`Map`](#map)
* [`Options`](#options)
* [`SafeConfig`](#safeconfig)
* [`State`](#state)
* [`Tracker`](#tracker)
* [`Unsafe`](#unsafe)
* [List of extensions](#list-of-extensions)
* [Syntax](#syntax)
* [Syntax tree](#syntax-tree)
* [Types](#types)
* [Compatibility](#compatibility)
* [Security](#security)
* [Related](#related)
* [Contribute](#contribute)
* [License](#license)
## What is this?
This package is a utility that takes an [mdast][] syntax tree as input and turns
it into serialized markdown.
This utility is a low level project.
Its used in [`remark-stringify`][remark-stringify], which focusses on making it
easier to transform content by abstracting these internals away.
## When should I use this?
If you want to handle syntax trees manually, use this.
For an easier time processing content, use the **[remark][]** ecosystem instead.
You can combine this utility with other utilities to add syntax extensions.
Notable examples that deeply integrate with it are
[`mdast-util-gfm`][mdast-util-gfm],
[`mdast-util-mdx`][mdast-util-mdx],
[`mdast-util-frontmatter`][mdast-util-frontmatter],
[`mdast-util-math`][mdast-util-math], and
[`mdast-util-directive`][mdast-util-directive].
## Install
This package is [ESM only][esm].
In Node.js (version 16+), install with [npm][]:
```sh
npm install mdast-util-to-markdown
```
In Deno with [`esm.sh`][esmsh]:
```js
import {toMarkdown} from 'https://esm.sh/mdast-util-to-markdown@2'
```
In browsers with [`esm.sh`][esmsh]:
```html
<script type="module">
import {toMarkdown} from 'https://esm.sh/mdast-util-to-markdown@2?bundle'
</script>
```
## Use
Say our module `example.js` looks as follows:
```js
import {toMarkdown} from 'mdast-util-to-markdown'
/** @type {import('mdast').Root} */
const tree = {
type: 'root',
children: [
{
type: 'blockquote',
children: [
{type: 'thematicBreak'},
{
type: 'paragraph',
children: [
{type: 'text', value: '- a\nb !'},
{
type: 'link',
url: 'example.com',
children: [{type: 'text', value: 'd'}]
}
]
}
]
}
]
}
console.log(toMarkdown(tree))
```
…now running `node example.js` yields:
```markdown
> ***
>
> \- a
> b \![d](example.com)
```
> 👉 **Note**: observe the properly escaped characters which would otherwise
> turn into a list and image respectively.
## API
This package exports the identifiers [`defaultHandlers`][api-default-handlers]
and [`toMarkdown`][api-to-markdown].
There is no default export.
### `toMarkdown(tree[, options])`
Turn an **[mdast][]** syntax tree into markdown.
###### Parameters
* `tree` ([`Node`][node])
— tree to serialize
* `options` ([`Options`][api-options], optional)
— configuration
###### Returns
Serialized markdown representing `tree` (`string`).
### `defaultHandlers`
Default (CommonMark) handlers ([`Handlers`][api-handlers]).
### `ConstructName`
Construct names for things generated by `mdast-util-to-markdown` (TypeScript
type).
This is an enum of strings, each being a semantic label, useful to know when
serializing whether were for example in a double (`"`) or single (`'`) quoted
title.
###### Type
```ts
type ConstructName = ConstructNameMap[keyof ConstructNameMap]
```
### `ConstructNameMap`
Interface of registered constructs (TypeScript type).
###### Type
```ts
interface ConstructNameMap { /* see code */ }
```
When working on extensions that use new constructs, extend the corresponding
interface to register its name:
```ts
declare module 'mdast-util-to-markdown' {
interface ConstructNameMap {
// Register a new construct name (value is used, key should match it).
gfmStrikethrough: 'gfmStrikethrough'
}
}
```
### `Handle`
Handle a particular node (TypeScript type).
###### Parameters
* `node` (`any`)
— expected mdast node
* `parent` ([`Node`][node], optional)
— parent of `node`
* `state` ([`State`][api-state])
— info passed around about the current state
* `info` ([`Info`][api-info])
— info on the surrounding of the node that is serialized
###### Returns
Serialized markdown representing `node` (`string`).
### `Handlers`
Handle particular nodes (TypeScript type).
Each key is a node type (`Node['type']`), each value its corresponding handler
([`Handle`][api-handle]).
###### Type
```ts
type Handlers = Record<Node['type'], Handle>
```
### `Info`
Info on the surrounding of the node that is serialized (TypeScript type).
###### Fields
* `now` ([`Point`][point])
— current point
* `lineShift` (`number`)
— number of columns each line will be shifted by wrapping nodes
* `before` (`string`)
— characters before this (guaranteed to be one, can be more)
* `after` (`string`)
— characters after this (guaranteed to be one, can be more)
### `Join`
How to join two blocks (TypeScript type).
“Blocks” are typically joined by one blank line.
Sometimes its nicer to have them flush next to each other, yet other times
they cannot occur together at all.
Join functions receive two adjacent siblings and their parent and what they
return defines how many blank lines to use between them.
###### Parameters
* `left` ([`Node`][node])
— first of two adjacent siblings
* `right` ([`Node`][node])
— second of two adjacent siblings
* `parent` ([`Node`][node])
— parent of the two siblings
* `state` ([`State`][api-state])
— info passed around about the current state
###### Returns
How many blank lines to use between the siblings (`boolean`, `number`,
optional).
Where `true` is as passing `1` and `false` means the nodes cannot be
joined by a blank line, such as two adjacent block quotes or indented code
after a list, in which case a comment will be injected to break them up:
```markdown
> Quote 1
<!---->
> Quote 2
```
> 👉 **Note**: abusing this feature will break markdown.
> One such example is when returning `0` for two paragraphs, which will result
> in the text running together, and in the future to be seen as one paragraph.
### `Map`
Map function to pad a single line (TypeScript type).
###### Parameters
* `value` (`string`)
— a single line of serialized markdown
* `line` (`number`)
— line number relative to the fragment
* `blank` (`boolean`)
— whether the line is considered blank in markdown
###### Returns
Padded line (`string`).
### `Options`
Configuration (TypeScript type).
##### Fields
The following fields influence how markdown is serialized.
###### `options.bullet`
Marker to use for bullets of items in unordered lists (`'*'`, `'+'`, or `'-'`,
default: `'*'`).
There are three cases where the primary bullet cannot be used:
* when three or more list items are on their own, the last one is empty, and
`bullet` is also a valid `rule`: `* - +`; this would turn into a thematic
break if serialized with three primary bullets; `bulletOther` is used for
the last item
* when a thematic break is the first child of a list item and `bullet` is the
same character as `rule`: `- ***`; this would turn into a single thematic
break if serialized with primary bullets; `bulletOther` is used for the
item
* when two unordered lists appear next to each other: `* a\n- b`;
`bulletOther` is used for such lists
###### `options.bulletOther`
Marker to use in certain cases where the primary bullet doesnt work (`'*'`,
`'+'`, or `'-'`, default: `'-'` when `bullet` is `'*'`, `'*'` otherwise).
Cannot be equal to `bullet`.
###### `options.bulletOrdered`
Marker to use for bullets of items in ordered lists (`'.'` or `')'`, default:
`'.'`).
There is one case where the primary bullet for ordered items cannot be used:
* when two ordered lists appear next to each other: `1. a\n2) b`; to solve
that, `'.'` will be used when `bulletOrdered` is `')'`, and `'.'` otherwise
###### `options.closeAtx`
Whether to add the same number of number signs (`#`) at the end of an ATX
heading as the opening sequence (`boolean`, default: `false`).
###### `options.emphasis`
Marker to use for emphasis (`'*'` or `'_'`, default: `'*'`).
###### `options.fence`
Marker to use for fenced code (``'`'`` or `'~'`, default: ``'`'``).
###### `options.fences`
Whether to use fenced code always (`boolean`, default: `true`).
The default is to use fenced code if there is a language defined, if the code is
empty, or if it starts or ends in blank lines.
###### `options.incrementListMarker`
Whether to increment the counter of ordered lists items (`boolean`, default:
`true`).
###### `options.listItemIndent`
How to indent the content of list items (`'mixed'`, `'one'`, or `'tab'`,
default: `'one'`).
Either with the size of the bullet plus one space (when `'one'`), a tab stop
(`'tab'`), or depending on the item and its parent list (`'mixed'`, uses `'one'`
if the item and list are tight and `'tab'` otherwise).
###### `options.quote`
Marker to use for titles (`'"'` or `"'"`, default: `'"'`).
###### `options.resourceLink`
Whether to always use resource links (`boolean`, default: `false`).
The default is to use autolinks (`<https://example.com>`) when possible
and resource links (`[text](url)`) otherwise.
###### `options.rule`
Marker to use for thematic breaks (`'*'`, `'-'`, or `'_'`, default: `'*'`).
###### `options.ruleRepetition`
Number of markers to use for thematic breaks (`number`, default: `3`, min: `3`).
###### `options.ruleSpaces`
Whether to add spaces between markers in thematic breaks (`boolean`, default:
`false`).
###### `options.setext`
Whether to use setext headings when possible (`boolean`, default: `false`).
The default is to always use ATX headings (`# heading`) instead of setext
headings (`heading\n=======`).
Setext headings cannot be used for empty headings or headings with a rank of
three or more.
###### `options.strong`
Marker to use for strong (`'*'` or `'_'`, default: `'*'`).
###### `options.tightDefinitions`
Whether to join definitions without a blank line (`boolean`, default: `false`).
The default is to add blank lines between any flow (“block”) construct.
Turning this option on is a shortcut for a [`Join`][api-join] function like so:
```js
function joinTightDefinitions(left, right) {
if (left.type === 'definition' && right.type === 'definition') {
return 0
}
}
```
###### `options.handlers`
Handle particular nodes ([`Handlers`][api-handlers], optional).
###### `options.join`
How to join blocks ([`Array<Join>`][api-join], optional).
###### `options.unsafe`
Schemas that define when characters cannot occur
([`Array<Unsafe>`][api-unsafe], optional).
###### `options.extensions`
List of extensions (`Array<Options>`, default: `[]`).
Each extension is an object with the same interface as `Options` itself.
### `SafeConfig`
Configuration passed to `state.safe` (TypeScript type).
###### Fields
* `before` (`string`)
— characters before this (guaranteed to be one, can be more)
* `after` (`string`)
— characters after this (guaranteed to be one, can be more)
* `encode` (`Array<string>`, optional)
— extra characters that *must* be encoded (as character references) instead
of escaped (character escapes).
Only ASCII punctuation will use character escapes, so you never need to
pass non-ASCII-punctuation here
### `State`
Info passed around about the current state (TypeScript type).
###### Fields
* `stack` ([`Array<ConstructName>`][api-construct-name])
— stack of constructs were in
* `indexStack` (`Array<number>`)
— positions of child nodes in their parents
* `associationId` (`(node: Association) => string`)
— get an identifier from an association to match it to others (see
[`Association`][association])
* `enter` (`(construct: ConstructName) => () => undefined`)
— enter a construct (returns a corresponding exit function)
(see [`ConstructName`][api-construct-name])
* `indentLines` (`(value: string, map: Map) => string`)
— pad serialized markdown (see [`Map`][api-map])
* `compilePattern` (`(pattern: Unsafe) => RegExp`)
— compile an unsafe pattern to a regex (see [`Unsafe`][api-unsafe])
* `containerFlow` (`(parent: Node, info: Info) => string`)
— serialize flow children (see [`Info`][api-info])
* `containerPhrasing` (`(parent: Node, info: Info) => string`)
— serialize phrasing children (see [`Info`][api-info])
* `createTracker` (`(info: Info) => Tracker`)
— track positional info in the output (see [`Info`][api-info],
[`Tracker`][api-tracker])
* `safe` (`(value: string, config: SafeConfig) => string`)
— make a string safe for embedding (see [`SafeConfig`][api-safe-config])
* `options` ([`Options`][api-options])
— applied user configuration
* `unsafe` ([`Array<Unsafe>`][api-unsafe])
— applied unsafe patterns
* `join` ([`Array<Join>`][api-join])
— applied join handlers
* `handle` ([`Handle`][api-handle])
— call the configured handler for the given node
* `handlers` ([`Handlers`][api-handlers])
— applied handlers
* `bulletCurrent` (`string` or `undefined`)
— list marker currently in use
* `bulletLastUsed` (`string` or `undefined`)
— list marker previously in use
### `Tracker`
Track positional info in the output (TypeScript type).
This info isnt used yet but such functionality will allow line wrapping,
source maps, etc.
###### Fields
* `current` (`() => Info`)
— get current tracked info
* `shift` (`(value: number) => undefined`)
— define a relative increased line shift (the typical indent for lines)
* `move` (`(value: string) => string`)
— move past some generated markdown
### `Unsafe`
Schema that defines when a character cannot occur (TypeScript type).
###### Fields
* `character` (`string`)
— single unsafe character
* `inConstruct` ([`Array<ConstructName>`][api-construct-name],
`ConstructName`, optional)
— constructs where this is bad
* `notInConstruct` ([`Array<ConstructName>`][api-construct-name],
`ConstructName`, optional)
— constructs where this is fine again
* `before` (`string`, optional)
— `character` is bad when this is before it (cannot be used together with
`atBreak`)
* `after` (`string`, optional)
— `character` is bad when this is after it
* `atBreak` (`boolean`, optional)
— `character` is bad at a break (cannot be used together with `before`)
## List of extensions
* [`syntax-tree/mdast-util-directive`](https://github.com/syntax-tree/mdast-util-directive)
— directives
* [`syntax-tree/mdast-util-frontmatter`](https://github.com/syntax-tree/mdast-util-frontmatter)
— frontmatter (YAML, TOML, more)
* [`syntax-tree/mdast-util-gfm`](https://github.com/syntax-tree/mdast-util-gfm)
— GFM
* [`syntax-tree/mdast-util-gfm-autolink-literal`](https://github.com/syntax-tree/mdast-util-gfm-autolink-literal)
— GFM autolink literals
* [`syntax-tree/mdast-util-gfm-footnote`](https://github.com/syntax-tree/mdast-util-gfm-footnote)
— GFM footnotes
* [`syntax-tree/mdast-util-gfm-strikethrough`](https://github.com/syntax-tree/mdast-util-gfm-strikethrough)
— GFM strikethrough
* [`syntax-tree/mdast-util-gfm-table`](https://github.com/syntax-tree/mdast-util-gfm-table)
— GFM tables
* [`syntax-tree/mdast-util-gfm-task-list-item`](https://github.com/syntax-tree/mdast-util-gfm-task-list-item)
— GFM task list items
* [`syntax-tree/mdast-util-math`](https://github.com/syntax-tree/mdast-util-math)
— math
* [`syntax-tree/mdast-util-mdx`](https://github.com/syntax-tree/mdast-util-mdx)
— MDX
* [`syntax-tree/mdast-util-mdx-expression`](https://github.com/syntax-tree/mdast-util-mdx-expression)
— MDX expressions
* [`syntax-tree/mdast-util-mdx-jsx`](https://github.com/syntax-tree/mdast-util-mdx-jsx)
— MDX JSX
* [`syntax-tree/mdast-util-mdxjs-esm`](https://github.com/syntax-tree/mdast-util-mdxjs-esm)
— MDX ESM
## Syntax
Markdown is serialized according to CommonMark but care is taken to format in
such a way that the resulting markdown should work with most markdown parsers.
Extensions can add support for custom syntax.
## Syntax tree
The syntax tree is [mdast][].
## Types
This package is fully typed with [TypeScript][].
It exports the additional types
[`ConstructName`][api-construct-name],
[`ConstructNameMap`][api-construct-name-map],
[`Handle`][api-handle],
[`Handlers`][api-handlers],
[`Info`][api-info],
[`Join`][api-join],
[`Map`][api-map],
[`Options`][api-options],
[`SafeConfig`][api-safe-config],
[`State`][api-State], and
[`Unsafe`][api-Unsafe].
## Compatibility
Projects maintained by the unified collective are compatible with maintained
versions of Node.js.
When we cut a new major release, we drop support for unmaintained versions of
Node.
This means we try to keep the current release line, `mdast-util-to-markdown@^2`,
compatible with Node.js 16.
## Security
`mdast-util-to-markdown` will do its best to serialize markdown to match the
syntax tree, but there are several cases where that is impossible.
Itll do its best, but complete roundtripping is impossible given that any value
could be injected into the tree.
As markdown is sometimes used for HTML, and improper use of HTML can open you up
to a [cross-site scripting (XSS)][xss] attack, use of `mdast-util-to-markdown`
and parsing it again later could potentially be unsafe.
When parsing markdown afterwards and then going to HTML, use something like
[`hast-util-sanitize`][hast-util-sanitize] to make the tree safe.
## Related
* [`syntax-tree/mdast-util-from-markdown`](https://github.com/syntax-tree/mdast-util-from-markdown)
— parse markdown to mdast
* [`micromark/micromark`](https://github.com/micromark/micromark)
— parse markdown
* [`remarkjs/remark`](https://github.com/remarkjs/remark)
— process markdown
## Contribute
See [`contributing.md`][contributing] in [`syntax-tree/.github`][health] for
ways to get started.
See [`support.md`][support] for ways to get help.
This project has a [code of conduct][coc].
By interacting with this repository, organization, or community you agree to
abide by its terms.
## License
[MIT][license] © [Titus Wormer][author]
<!-- Definitions -->
[build-badge]: https://github.com/syntax-tree/mdast-util-to-markdown/workflows/main/badge.svg
[build]: https://github.com/syntax-tree/mdast-util-to-markdown/actions
[coverage-badge]: https://img.shields.io/codecov/c/github/syntax-tree/mdast-util-to-markdown.svg
[coverage]: https://codecov.io/github/syntax-tree/mdast-util-to-markdown
[downloads-badge]: https://img.shields.io/npm/dm/mdast-util-to-markdown.svg
[downloads]: https://www.npmjs.com/package/mdast-util-to-markdown
[size-badge]: https://img.shields.io/badge/dynamic/json?label=minzipped%20size&query=$.size.compressedSize&url=https://deno.bundlejs.com/?q=mdast-util-to-markdown
[size]: https://bundlejs.com/?q=mdast-util-to-markdown
[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg
[backers-badge]: https://opencollective.com/unified/backers/badge.svg
[collective]: https://opencollective.com/unified
[chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg
[chat]: https://github.com/syntax-tree/unist/discussions
[npm]: https://docs.npmjs.com/cli/install
[esmsh]: https://esm.sh
[license]: license
[author]: https://wooorm.com
[health]: https://github.com/syntax-tree/.github
[contributing]: https://github.com/syntax-tree/.github/blob/main/contributing.md
[support]: https://github.com/syntax-tree/.github/blob/main/support.md
[coc]: https://github.com/syntax-tree/.github/blob/main/code-of-conduct.md
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
[typescript]: https://www.typescriptlang.org
[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
[hast-util-sanitize]: https://github.com/syntax-tree/hast-util-sanitize
[point]: https://github.com/syntax-tree/unist#point
[mdast]: https://github.com/syntax-tree/mdast
[node]: https://github.com/syntax-tree/mdast#nodes
[association]: https://github.com/syntax-tree/mdast#association
[mdast-util-gfm]: https://github.com/syntax-tree/mdast-util-gfm
[mdast-util-mdx]: https://github.com/syntax-tree/mdast-util-mdx
[mdast-util-frontmatter]: https://github.com/syntax-tree/mdast-util-frontmatter
[mdast-util-math]: https://github.com/syntax-tree/mdast-util-math
[mdast-util-directive]: https://github.com/syntax-tree/mdast-util-directive
[remark]: https://github.com/remarkjs/remark
[remark-stringify]: https://github.com/remarkjs/remark/tree/main/packages/remark-stringify
[api-construct-name]: #constructname
[api-construct-name-map]: #constructnamemap
[api-default-handlers]: #defaulthandlers
[api-handle]: #handle
[api-handlers]: #handlers
[api-info]: #info
[api-join]: #join
[api-map]: #map
[api-options]: #options
[api-safe-config]: #safeconfig
[api-state]: #state
[api-to-markdown]: #tomarkdowntree-options
[api-tracker]: #tracker
[api-unsafe]: #unsafe