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

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
}
}