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