2521 lines · 90.9 KB · JavaScript
RawDownload
/** * marked v14.1.2 - a markdown parser * Copyright (c) 2011-2024, Christopher Jeffrey. (MIT Licensed) * https://github.com/markedjs/marked */ /** * DO NOT EDIT THIS FILE * The code in this file is generated from files in ./src/ */ 'use strict'; /** * Gets the original marked default options. */function _getDefaults() {    return {        async: false,        breaks: false,        extensions: null,        gfm: true,        hooks: null,        pedantic: false,        renderer: null,        silent: false,        tokenizer: null,        walkTokens: null,    };}exports.defaults = _getDefaults();function changeDefaults(newDefaults) {    exports.defaults = newDefaults;} /** * Helpers */const escapeTest = /[&<>"']/;const escapeReplace = new RegExp(escapeTest.source, 'g');const escapeTestNoEncode = /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/;const escapeReplaceNoEncode = new RegExp(escapeTestNoEncode.source, 'g');const escapeReplacements = {    '&': '&amp;',    '<': '&lt;',    '>': '&gt;',    '"': '&quot;',    "'": '&#39;',};const getEscapeReplacement = (ch) => escapeReplacements[ch];function escape$1(html, encode) {    if (encode) {        if (escapeTest.test(html)) {            return html.replace(escapeReplace, getEscapeReplacement);        }    }    else {        if (escapeTestNoEncode.test(html)) {            return html.replace(escapeReplaceNoEncode, getEscapeReplacement);        }    }    return html;}const caret = /(^|[^\[])\^/g;function edit(regex, opt) {    let source = typeof regex === 'string' ? regex : regex.source;    opt = opt || '';    const obj = {        replace: (name, val) => {            let valSource = typeof val === 'string' ? val : val.source;            valSource = valSource.replace(caret, '$1');            source = source.replace(name, valSource);            return obj;        },        getRegex: () => {            return new RegExp(source, opt);        },    };    return obj;}function cleanUrl(href) {    try {        href = encodeURI(href).replace(/%25/g, '%');    }    catch {        return null;    }    return href;}const noopTest = { exec: () => null };function splitCells(tableRow, count) {    // ensure that every cell-delimiting pipe has a space    // before it to distinguish it from an escaped pipe    const row = tableRow.replace(/\|/g, (match, offset, str) => {        let escaped = false;        let curr = offset;        while (--curr >= 0 && str[curr] === '\\')            escaped = !escaped;        if (escaped) {            // odd number of slashes means | is escaped            // so we leave it alone            return '|';        }        else {            // add space before unescaped |            return ' |';        }    }), cells = row.split(/ \|/);    let i = 0;    // First/last cell in a row cannot be empty if it has no leading/trailing pipe    if (!cells[0].trim()) {        cells.shift();    }    if (cells.length > 0 && !cells[cells.length - 1].trim()) {        cells.pop();    }    if (count) {        if (cells.length > count) {            cells.splice(count);        }        else {            while (cells.length < count)                cells.push('');        }    }    for (; i < cells.length; i++) {        // leading or trailing whitespace is ignored per the gfm spec        cells[i] = cells[i].trim().replace(/\\\|/g, '|');    }    return cells;}/** * Remove trailing 'c's. Equivalent to str.replace(/c*$/, ''). * /c*$/ is vulnerable to REDOS. * * @param str * @param c * @param invert Remove suffix of non-c chars instead. Default falsey. */function rtrim(str, c, invert) {    const l = str.length;    if (l === 0) {        return '';    }    // Length of suffix matching the invert condition.    let suffLen = 0;    // Step left until we fail to match the invert condition.    while (suffLen < l) {        const currChar = str.charAt(l - suffLen - 1);        if (currChar === c && !invert) {            suffLen++;        }        else if (currChar !== c && invert) {            suffLen++;        }        else {            break;        }    }    return str.slice(0, l - suffLen);}function findClosingBracket(str, b) {    if (str.indexOf(b[1]) === -1) {        return -1;    }    let level = 0;    for (let i = 0; i < str.length; i++) {        if (str[i] === '\\') {            i++;        }        else if (str[i] === b[0]) {            level++;        }        else if (str[i] === b[1]) {            level--;            if (level < 0) {                return i;            }        }    }    return -1;} function outputLink(cap, link, raw, lexer) {    const href = link.href;    const title = link.title ? escape$1(link.title) : null;    const text = cap[1].replace(/\\([\[\]])/g, '$1');    if (cap[0].charAt(0) !== '!') {        lexer.state.inLink = true;        const token = {            type: 'link',            raw,            href,            title,            text,            tokens: lexer.inlineTokens(text),        };        lexer.state.inLink = false;        return token;    }    return {        type: 'image',        raw,        href,        title,        text: escape$1(text),    };}function indentCodeCompensation(raw, text) {    const matchIndentToCode = raw.match(/^(\s+)(?:```)/);    if (matchIndentToCode === null) {        return text;    }    const indentToCode = matchIndentToCode[1];    return text        .split('\n')        .map(node => {        const matchIndentInNode = node.match(/^\s+/);        if (matchIndentInNode === null) {            return node;        }        const [indentInNode] = matchIndentInNode;        if (indentInNode.length >= indentToCode.length) {            return node.slice(indentToCode.length);        }        return node;    })        .join('\n');}/** * Tokenizer */class _Tokenizer {    options;    rules; // set by the lexer    lexer; // set by the lexer    constructor(options) {        this.options = options || exports.defaults;    }    space(src) {        const cap = this.rules.block.newline.exec(src);        if (cap && cap[0].length > 0) {            return {                type: 'space',                raw: cap[0],            };        }    }    code(src) {        const cap = this.rules.block.code.exec(src);        if (cap) {            const text = cap[0].replace(/^(?: {1,4}| {0,3}\t)/gm, '');            return {                type: 'code',                raw: cap[0],                codeBlockStyle: 'indented',                text: !this.options.pedantic                    ? rtrim(text, '\n')                    : text,            };        }    }    fences(src) {        const cap = this.rules.block.fences.exec(src);        if (cap) {            const raw = cap[0];            const text = indentCodeCompensation(raw, cap[3] || '');            return {                type: 'code',                raw,                lang: cap[2] ? cap[2].trim().replace(this.rules.inline.anyPunctuation, '$1') : cap[2],                text,            };        }    }    heading(src) {        const cap = this.rules.block.heading.exec(src);        if (cap) {            let text = cap[2].trim();            // remove trailing #s            if (/#$/.test(text)) {                const trimmed = rtrim(text, '#');                if (this.options.pedantic) {                    text = trimmed.trim();                }                else if (!trimmed || / $/.test(trimmed)) {                    // CommonMark requires space before trailing #s                    text = trimmed.trim();                }            }            return {                type: 'heading',                raw: cap[0],                depth: cap[1].length,                text,                tokens: this.lexer.inline(text),            };        }    }    hr(src) {        const cap = this.rules.block.hr.exec(src);        if (cap) {            return {                type: 'hr',                raw: rtrim(cap[0], '\n'),            };        }    }    blockquote(src) {        const cap = this.rules.block.blockquote.exec(src);        if (cap) {            let lines = rtrim(cap[0], '\n').split('\n');            let raw = '';            let text = '';            const tokens = [];            while (lines.length > 0) {                let inBlockquote = false;                const currentLines = [];                let i;                for (i = 0; i < lines.length; i++) {                    // get lines up to a continuation                    if (/^ {0,3}>/.test(lines[i])) {                        currentLines.push(lines[i]);                        inBlockquote = true;                    }                    else if (!inBlockquote) {                        currentLines.push(lines[i]);                    }                    else {                        break;                    }                }                lines = lines.slice(i);                const currentRaw = currentLines.join('\n');                const currentText = currentRaw                    // precede setext continuation with 4 spaces so it isn't a setext                    .replace(/\n {0,3}((?:=+|-+) *)(?=\n|$)/g, '\n    $1')                    .replace(/^ {0,3}>[ \t]?/gm, '');                raw = raw ? `${raw}\n${currentRaw}` : currentRaw;                text = text ? `${text}\n${currentText}` : currentText;                // parse blockquote lines as top level tokens                // merge paragraphs if this is a continuation                const top = this.lexer.state.top;                this.lexer.state.top = true;                this.lexer.blockTokens(currentText, tokens, true);                this.lexer.state.top = top;                // if there is no continuation then we are done                if (lines.length === 0) {                    break;                }                const lastToken = tokens[tokens.length - 1];                if (lastToken?.type === 'code') {                    // blockquote continuation cannot be preceded by a code block                    break;                }                else if (lastToken?.type === 'blockquote') {                    // include continuation in nested blockquote                    const oldToken = lastToken;                    const newText = oldToken.raw + '\n' + lines.join('\n');                    const newToken = this.blockquote(newText);                    tokens[tokens.length - 1] = newToken;                    raw = raw.substring(0, raw.length - oldToken.raw.length) + newToken.raw;                    text = text.substring(0, text.length - oldToken.text.length) + newToken.text;                    break;                }                else if (lastToken?.type === 'list') {                    // include continuation in nested list                    const oldToken = lastToken;                    const newText = oldToken.raw + '\n' + lines.join('\n');                    const newToken = this.list(newText);                    tokens[tokens.length - 1] = newToken;                    raw = raw.substring(0, raw.length - lastToken.raw.length) + newToken.raw;                    text = text.substring(0, text.length - oldToken.raw.length) + newToken.raw;                    lines = newText.substring(tokens[tokens.length - 1].raw.length).split('\n');                    continue;                }            }            return {                type: 'blockquote',                raw,                tokens,                text,            };        }    }    list(src) {        let cap = this.rules.block.list.exec(src);        if (cap) {            let bull = cap[1].trim();            const isordered = bull.length > 1;            const list = {                type: 'list',                raw: '',                ordered: isordered,                start: isordered ? +bull.slice(0, -1) : '',                loose: false,                items: [],            };            bull = isordered ? `\\d{1,9}\\${bull.slice(-1)}` : `\\${bull}`;            if (this.options.pedantic) {                bull = isordered ? bull : '[*+-]';            }            // Get next list item            const itemRegex = new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`);            let endsWithBlankLine = false;            // Check if current bullet point can start a new List Item            while (src) {                let endEarly = false;                let raw = '';                let itemContents = '';                if (!(cap = itemRegex.exec(src))) {                    break;                }                if (this.rules.block.hr.test(src)) { // End list if bullet was actually HR (possibly move into itemRegex?)                    break;                }                raw = cap[0];                src = src.substring(raw.length);                let line = cap[2].split('\n', 1)[0].replace(/^\t+/, (t) => ' '.repeat(3 * t.length));                let nextLine = src.split('\n', 1)[0];                let blankLine = !line.trim();                let indent = 0;                if (this.options.pedantic) {                    indent = 2;                    itemContents = line.trimStart();                }                else if (blankLine) {                    indent = cap[1].length + 1;                }                else {                    indent = cap[2].search(/[^ ]/); // Find first non-space char                    indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent                    itemContents = line.slice(indent);                    indent += cap[1].length;                }                if (blankLine && /^[ \t]*$/.test(nextLine)) { // Items begin with at most one blank line                    raw += nextLine + '\n';                    src = src.substring(nextLine.length + 1);                    endEarly = true;                }                if (!endEarly) {                    const nextBulletRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`);                    const hrRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`);                    const fencesBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\`\`\`|~~~)`);                    const headingBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`);                    const htmlBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}<[a-z].*>`, 'i');                    // Check if following lines should be included in List Item                    while (src) {                        const rawLine = src.split('\n', 1)[0];                        let nextLineWithoutTabs;                        nextLine = rawLine;                        // Re-align to follow commonmark nesting rules                        if (this.options.pedantic) {                            nextLine = nextLine.replace(/^ {1,4}(?=( {4})*[^ ])/g, '  ');                            nextLineWithoutTabs = nextLine;                        }                        else {                            nextLineWithoutTabs = nextLine.replace(/\t/g, '    ');                        }                        // End list item if found code fences                        if (fencesBeginRegex.test(nextLine)) {                            break;                        }                        // End list item if found start of new heading                        if (headingBeginRegex.test(nextLine)) {                            break;                        }                        // End list item if found start of html block                        if (htmlBeginRegex.test(nextLine)) {                            break;                        }                        // End list item if found start of new bullet                        if (nextBulletRegex.test(nextLine)) {                            break;                        }                        // Horizontal rule found                        if (hrRegex.test(nextLine)) {                            break;                        }                        if (nextLineWithoutTabs.search(/[^ ]/) >= indent || !nextLine.trim()) { // Dedent if possible                            itemContents += '\n' + nextLineWithoutTabs.slice(indent);                        }                        else {                            // not enough indentation                            if (blankLine) {                                break;                            }                            // paragraph continuation unless last line was a different block level element                            if (line.replace(/\t/g, '    ').search(/[^ ]/) >= 4) { // indented code block                                break;                            }                            if (fencesBeginRegex.test(line)) {                                break;                            }                            if (headingBeginRegex.test(line)) {                                break;                            }                            if (hrRegex.test(line)) {                                break;                            }

Lines 1–500 of 2521.