diff options
| author | altaf-creator <dev@altafcreator.com> | 2026-04-30 22:01:53 +0800 |
|---|---|---|
| committer | altaf-creator <dev@altafcreator.com> | 2026-04-30 22:01:53 +0800 |
| commit | db1c6676a13798ee57dbac429a1d5045b60356fb (patch) | |
| tree | 5ff305c09686de50bbcac404c1954e42c26ba494 /packages/markdown-it-14.1.0/lib/rules_block | |
| parent | 97fa8f57fbefcbfa6b3e56c31a1e5b60ef1a9e37 (diff) | |
quite a big commit
Diffstat (limited to 'packages/markdown-it-14.1.0/lib/rules_block')
12 files changed, 0 insertions, 1612 deletions
diff --git a/packages/markdown-it-14.1.0/lib/rules_block/blockquote.mjs b/packages/markdown-it-14.1.0/lib/rules_block/blockquote.mjs deleted file mode 100644 index b61da02..0000000 --- a/packages/markdown-it-14.1.0/lib/rules_block/blockquote.mjs +++ /dev/null @@ -1,209 +0,0 @@ -// Block quotes - -import { isSpace } from '../common/utils.mjs' - -export default function blockquote (state, startLine, endLine, silent) { - let pos = state.bMarks[startLine] + state.tShift[startLine] - let max = state.eMarks[startLine] - - const oldLineMax = state.lineMax - - // if it's indented more than 3 spaces, it should be a code block - if (state.sCount[startLine] - state.blkIndent >= 4) { return false } - - // check the block quote marker - if (state.src.charCodeAt(pos) !== 0x3E/* > */) { return false } - - // we know that it's going to be a valid blockquote, - // so no point trying to find the end of it in silent mode - if (silent) { return true } - - const oldBMarks = [] - const oldBSCount = [] - const oldSCount = [] - const oldTShift = [] - - const terminatorRules = state.md.block.ruler.getRules('blockquote') - - const oldParentType = state.parentType - state.parentType = 'blockquote' - let lastLineEmpty = false - let nextLine - - // Search the end of the block - // - // Block ends with either: - // 1. an empty line outside: - // ``` - // > test - // - // ``` - // 2. an empty line inside: - // ``` - // > - // test - // ``` - // 3. another tag: - // ``` - // > test - // - - - - // ``` - for (nextLine = startLine; nextLine < endLine; nextLine++) { - // check if it's outdented, i.e. it's inside list item and indented - // less than said list item: - // - // ``` - // 1. anything - // > current blockquote - // 2. checking this line - // ``` - const isOutdented = state.sCount[nextLine] < state.blkIndent - - pos = state.bMarks[nextLine] + state.tShift[nextLine] - max = state.eMarks[nextLine] - - if (pos >= max) { - // Case 1: line is not inside the blockquote, and this line is empty. - break - } - - if (state.src.charCodeAt(pos++) === 0x3E/* > */ && !isOutdented) { - // This line is inside the blockquote. - - // set offset past spaces and ">" - let initial = state.sCount[nextLine] + 1 - let spaceAfterMarker - let adjustTab - - // skip one optional space after '>' - if (state.src.charCodeAt(pos) === 0x20 /* space */) { - // ' > test ' - // ^ -- position start of line here: - pos++ - initial++ - adjustTab = false - spaceAfterMarker = true - } else if (state.src.charCodeAt(pos) === 0x09 /* tab */) { - spaceAfterMarker = true - - if ((state.bsCount[nextLine] + initial) % 4 === 3) { - // ' >\t test ' - // ^ -- position start of line here (tab has width===1) - pos++ - initial++ - adjustTab = false - } else { - // ' >\t test ' - // ^ -- position start of line here + shift bsCount slightly - // to make extra space appear - adjustTab = true - } - } else { - spaceAfterMarker = false - } - - let offset = initial - oldBMarks.push(state.bMarks[nextLine]) - state.bMarks[nextLine] = pos - - while (pos < max) { - const ch = state.src.charCodeAt(pos) - - if (isSpace(ch)) { - if (ch === 0x09) { - offset += 4 - (offset + state.bsCount[nextLine] + (adjustTab ? 1 : 0)) % 4 - } else { - offset++ - } - } else { - break - } - - pos++ - } - - lastLineEmpty = pos >= max - - oldBSCount.push(state.bsCount[nextLine]) - state.bsCount[nextLine] = state.sCount[nextLine] + 1 + (spaceAfterMarker ? 1 : 0) - - oldSCount.push(state.sCount[nextLine]) - state.sCount[nextLine] = offset - initial - - oldTShift.push(state.tShift[nextLine]) - state.tShift[nextLine] = pos - state.bMarks[nextLine] - continue - } - - // Case 2: line is not inside the blockquote, and the last line was empty. - if (lastLineEmpty) { break } - - // Case 3: another tag found. - let terminate = false - for (let i = 0, l = terminatorRules.length; i < l; i++) { - if (terminatorRules[i](state, nextLine, endLine, true)) { - terminate = true - break - } - } - - if (terminate) { - // Quirk to enforce "hard termination mode" for paragraphs; - // normally if you call `tokenize(state, startLine, nextLine)`, - // paragraphs will look below nextLine for paragraph continuation, - // but if blockquote is terminated by another tag, they shouldn't - state.lineMax = nextLine - - if (state.blkIndent !== 0) { - // state.blkIndent was non-zero, we now set it to zero, - // so we need to re-calculate all offsets to appear as - // if indent wasn't changed - oldBMarks.push(state.bMarks[nextLine]) - oldBSCount.push(state.bsCount[nextLine]) - oldTShift.push(state.tShift[nextLine]) - oldSCount.push(state.sCount[nextLine]) - state.sCount[nextLine] -= state.blkIndent - } - - break - } - - oldBMarks.push(state.bMarks[nextLine]) - oldBSCount.push(state.bsCount[nextLine]) - oldTShift.push(state.tShift[nextLine]) - oldSCount.push(state.sCount[nextLine]) - - // A negative indentation means that this is a paragraph continuation - // - state.sCount[nextLine] = -1 - } - - const oldIndent = state.blkIndent - state.blkIndent = 0 - - const token_o = state.push('blockquote_open', 'blockquote', 1) - token_o.markup = '>' - const lines = [startLine, 0] - token_o.map = lines - - state.md.block.tokenize(state, startLine, nextLine) - - const token_c = state.push('blockquote_close', 'blockquote', -1) - token_c.markup = '>' - - state.lineMax = oldLineMax - state.parentType = oldParentType - lines[1] = state.line - - // Restore original tShift; this might not be necessary since the parser - // has already been here, but just to make sure we can do that. - for (let i = 0; i < oldTShift.length; i++) { - state.bMarks[i + startLine] = oldBMarks[i] - state.tShift[i + startLine] = oldTShift[i] - state.sCount[i + startLine] = oldSCount[i] - state.bsCount[i + startLine] = oldBSCount[i] - } - state.blkIndent = oldIndent - - return true -} diff --git a/packages/markdown-it-14.1.0/lib/rules_block/code.mjs b/packages/markdown-it-14.1.0/lib/rules_block/code.mjs deleted file mode 100644 index e45e6f9..0000000 --- a/packages/markdown-it-14.1.0/lib/rules_block/code.mjs +++ /dev/null @@ -1,30 +0,0 @@ -// Code block (4 spaces padded) - -export default function code (state, startLine, endLine/*, silent */) { - if (state.sCount[startLine] - state.blkIndent < 4) { return false } - - let nextLine = startLine + 1 - let last = nextLine - - while (nextLine < endLine) { - if (state.isEmpty(nextLine)) { - nextLine++ - continue - } - - if (state.sCount[nextLine] - state.blkIndent >= 4) { - nextLine++ - last = nextLine - continue - } - break - } - - state.line = last - - const token = state.push('code_block', 'code', 0) - token.content = state.getLines(startLine, last, 4 + state.blkIndent, false) + '\n' - token.map = [startLine, state.line] - - return true -} diff --git a/packages/markdown-it-14.1.0/lib/rules_block/fence.mjs b/packages/markdown-it-14.1.0/lib/rules_block/fence.mjs deleted file mode 100644 index 930f7b3..0000000 --- a/packages/markdown-it-14.1.0/lib/rules_block/fence.mjs +++ /dev/null @@ -1,94 +0,0 @@ -// fences (``` lang, ~~~ lang) - -export default function fence (state, startLine, endLine, silent) { - let pos = state.bMarks[startLine] + state.tShift[startLine] - let max = state.eMarks[startLine] - - // if it's indented more than 3 spaces, it should be a code block - if (state.sCount[startLine] - state.blkIndent >= 4) { return false } - - if (pos + 3 > max) { return false } - - const marker = state.src.charCodeAt(pos) - - if (marker !== 0x7E/* ~ */ && marker !== 0x60 /* ` */) { - return false - } - - // scan marker length - let mem = pos - pos = state.skipChars(pos, marker) - - let len = pos - mem - - if (len < 3) { return false } - - const markup = state.src.slice(mem, pos) - const params = state.src.slice(pos, max) - - if (marker === 0x60 /* ` */) { - if (params.indexOf(String.fromCharCode(marker)) >= 0) { - return false - } - } - - // Since start is found, we can report success here in validation mode - if (silent) { return true } - - // search end of block - let nextLine = startLine - let haveEndMarker = false - - for (;;) { - nextLine++ - if (nextLine >= endLine) { - // unclosed block should be autoclosed by end of document. - // also block seems to be autoclosed by end of parent - break - } - - pos = mem = state.bMarks[nextLine] + state.tShift[nextLine] - max = state.eMarks[nextLine] - - if (pos < max && state.sCount[nextLine] < state.blkIndent) { - // non-empty line with negative indent should stop the list: - // - ``` - // test - break - } - - if (state.src.charCodeAt(pos) !== marker) { continue } - - if (state.sCount[nextLine] - state.blkIndent >= 4) { - // closing fence should be indented less than 4 spaces - continue - } - - pos = state.skipChars(pos, marker) - - // closing code fence must be at least as long as the opening one - if (pos - mem < len) { continue } - - // make sure tail has spaces only - pos = state.skipSpaces(pos) - - if (pos < max) { continue } - - haveEndMarker = true - // found! - break - } - - // If a fence has heading spaces, they should be removed from its inner block - len = state.sCount[startLine] - - state.line = nextLine + (haveEndMarker ? 1 : 0) - - const token = state.push('fence', 'code', 0) - token.info = params - token.content = state.getLines(startLine + 1, nextLine, len, true) - token.markup = markup - token.map = [startLine, state.line] - - return true -} diff --git a/packages/markdown-it-14.1.0/lib/rules_block/heading.mjs b/packages/markdown-it-14.1.0/lib/rules_block/heading.mjs deleted file mode 100644 index d2f7b79..0000000 --- a/packages/markdown-it-14.1.0/lib/rules_block/heading.mjs +++ /dev/null @@ -1,51 +0,0 @@ -// heading (#, ##, ...) - -import { isSpace } from '../common/utils.mjs' - -export default function heading (state, startLine, endLine, silent) { - let pos = state.bMarks[startLine] + state.tShift[startLine] - let max = state.eMarks[startLine] - - // if it's indented more than 3 spaces, it should be a code block - if (state.sCount[startLine] - state.blkIndent >= 4) { return false } - - let ch = state.src.charCodeAt(pos) - - if (ch !== 0x23/* # */ || pos >= max) { return false } - - // count heading level - let level = 1 - ch = state.src.charCodeAt(++pos) - while (ch === 0x23/* # */ && pos < max && level <= 6) { - level++ - ch = state.src.charCodeAt(++pos) - } - - if (level > 6 || (pos < max && !isSpace(ch))) { return false } - - if (silent) { return true } - - // Let's cut tails like ' ### ' from the end of string - - max = state.skipSpacesBack(max, pos) - const tmp = state.skipCharsBack(max, 0x23, pos) // # - if (tmp > pos && isSpace(state.src.charCodeAt(tmp - 1))) { - max = tmp - } - - state.line = startLine + 1 - - const token_o = state.push('heading_open', 'h' + String(level), 1) - token_o.markup = '########'.slice(0, level) - token_o.map = [startLine, state.line] - - const token_i = state.push('inline', '', 0) - token_i.content = state.src.slice(pos, max).trim() - token_i.map = [startLine, state.line] - token_i.children = [] - - const token_c = state.push('heading_close', 'h' + String(level), -1) - token_c.markup = '########'.slice(0, level) - - return true -} diff --git a/packages/markdown-it-14.1.0/lib/rules_block/hr.mjs b/packages/markdown-it-14.1.0/lib/rules_block/hr.mjs deleted file mode 100644 index d467b21..0000000 --- a/packages/markdown-it-14.1.0/lib/rules_block/hr.mjs +++ /dev/null @@ -1,40 +0,0 @@ -// Horizontal rule - -import { isSpace } from '../common/utils.mjs' - -export default function hr (state, startLine, endLine, silent) { - const max = state.eMarks[startLine] - // if it's indented more than 3 spaces, it should be a code block - if (state.sCount[startLine] - state.blkIndent >= 4) { return false } - - let pos = state.bMarks[startLine] + state.tShift[startLine] - const marker = state.src.charCodeAt(pos++) - - // Check hr marker - if (marker !== 0x2A/* * */ && - marker !== 0x2D/* - */ && - marker !== 0x5F/* _ */) { - return false - } - - // markers can be mixed with spaces, but there should be at least 3 of them - - let cnt = 1 - while (pos < max) { - const ch = state.src.charCodeAt(pos++) - if (ch !== marker && !isSpace(ch)) { return false } - if (ch === marker) { cnt++ } - } - - if (cnt < 3) { return false } - - if (silent) { return true } - - state.line = startLine + 1 - - const token = state.push('hr', 'hr', 0) - token.map = [startLine, state.line] - token.markup = Array(cnt + 1).join(String.fromCharCode(marker)) - - return true -} diff --git a/packages/markdown-it-14.1.0/lib/rules_block/html_block.mjs b/packages/markdown-it-14.1.0/lib/rules_block/html_block.mjs deleted file mode 100644 index 197520f..0000000 --- a/packages/markdown-it-14.1.0/lib/rules_block/html_block.mjs +++ /dev/null @@ -1,69 +0,0 @@ -// HTML block - -import block_names from '../common/html_blocks.mjs' -import { HTML_OPEN_CLOSE_TAG_RE } from '../common/html_re.mjs' - -// An array of opening and corresponding closing sequences for html tags, -// last argument defines whether it can terminate a paragraph or not -// -const HTML_SEQUENCES = [ - [/^<(script|pre|style|textarea)(?=(\s|>|$))/i, /<\/(script|pre|style|textarea)>/i, true], - [/^<!--/, /-->/, true], - [/^<\?/, /\?>/, true], - [/^<![A-Z]/, />/, true], - [/^<!\[CDATA\[/, /\]\]>/, true], - [new RegExp('^</?(' + block_names.join('|') + ')(?=(\\s|/?>|$))', 'i'), /^$/, true], - [new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + '\\s*$'), /^$/, false] -] - -export default function html_block (state, startLine, endLine, silent) { - let pos = state.bMarks[startLine] + state.tShift[startLine] - let max = state.eMarks[startLine] - - // if it's indented more than 3 spaces, it should be a code block - if (state.sCount[startLine] - state.blkIndent >= 4) { return false } - - if (!state.md.options.html) { return false } - - if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false } - - let lineText = state.src.slice(pos, max) - - let i = 0 - for (; i < HTML_SEQUENCES.length; i++) { - if (HTML_SEQUENCES[i][0].test(lineText)) { break } - } - if (i === HTML_SEQUENCES.length) { return false } - - if (silent) { - // true if this sequence can be a terminator, false otherwise - return HTML_SEQUENCES[i][2] - } - - let nextLine = startLine + 1 - - // If we are here - we detected HTML block. - // Let's roll down till block end. - if (!HTML_SEQUENCES[i][1].test(lineText)) { - for (; nextLine < endLine; nextLine++) { - if (state.sCount[nextLine] < state.blkIndent) { break } - - pos = state.bMarks[nextLine] + state.tShift[nextLine] - max = state.eMarks[nextLine] - lineText = state.src.slice(pos, max) - - if (HTML_SEQUENCES[i][1].test(lineText)) { - if (lineText.length !== 0) { nextLine++ } - break - } - } - } - - state.line = nextLine - - const token = state.push('html_block', '', 0) - token.map = [startLine, nextLine] - token.content = state.getLines(startLine, nextLine, state.blkIndent, true) - - return true -} diff --git a/packages/markdown-it-14.1.0/lib/rules_block/lheading.mjs b/packages/markdown-it-14.1.0/lib/rules_block/lheading.mjs deleted file mode 100644 index ee3b9a3..0000000 --- a/packages/markdown-it-14.1.0/lib/rules_block/lheading.mjs +++ /dev/null @@ -1,82 +0,0 @@ -// lheading (---, ===) - -export default function lheading (state, startLine, endLine/*, silent */) { - const terminatorRules = state.md.block.ruler.getRules('paragraph') - - // if it's indented more than 3 spaces, it should be a code block - if (state.sCount[startLine] - state.blkIndent >= 4) { return false } - - const oldParentType = state.parentType - state.parentType = 'paragraph' // use paragraph to match terminatorRules - - // jump line-by-line until empty one or EOF - let level = 0 - let marker - let nextLine = startLine + 1 - - for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) { - // this would be a code block normally, but after paragraph - // it's considered a lazy continuation regardless of what's there - if (state.sCount[nextLine] - state.blkIndent > 3) { continue } - - // - // Check for underline in setext header - // - if (state.sCount[nextLine] >= state.blkIndent) { - let pos = state.bMarks[nextLine] + state.tShift[nextLine] - const max = state.eMarks[nextLine] - - if (pos < max) { - marker = state.src.charCodeAt(pos) - - if (marker === 0x2D/* - */ || marker === 0x3D/* = */) { - pos = state.skipChars(pos, marker) - pos = state.skipSpaces(pos) - - if (pos >= max) { - level = (marker === 0x3D/* = */ ? 1 : 2) - break - } - } - } - } - - // quirk for blockquotes, this line should already be checked by that rule - if (state.sCount[nextLine] < 0) { continue } - - // Some tags can terminate paragraph without empty line. - let terminate = false - for (let i = 0, l = terminatorRules.length; i < l; i++) { - if (terminatorRules[i](state, nextLine, endLine, true)) { - terminate = true - break - } - } - if (terminate) { break } - } - - if (!level) { - // Didn't find valid underline - return false - } - - const content = state.getLines(startLine, nextLine, state.blkIndent, false).trim() - - state.line = nextLine + 1 - - const token_o = state.push('heading_open', 'h' + String(level), 1) - token_o.markup = String.fromCharCode(marker) - token_o.map = [startLine, state.line] - - const token_i = state.push('inline', '', 0) - token_i.content = content - token_i.map = [startLine, state.line - 1] - token_i.children = [] - - const token_c = state.push('heading_close', 'h' + String(level), -1) - token_c.markup = String.fromCharCode(marker) - - state.parentType = oldParentType - - return true -} diff --git a/packages/markdown-it-14.1.0/lib/rules_block/list.mjs b/packages/markdown-it-14.1.0/lib/rules_block/list.mjs deleted file mode 100644 index fb53abd..0000000 --- a/packages/markdown-it-14.1.0/lib/rules_block/list.mjs +++ /dev/null @@ -1,331 +0,0 @@ -// Lists - -import { isSpace } from '../common/utils.mjs' - -// Search `[-+*][\n ]`, returns next pos after marker on success -// or -1 on fail. -function skipBulletListMarker (state, startLine) { - const max = state.eMarks[startLine] - let pos = state.bMarks[startLine] + state.tShift[startLine] - - const marker = state.src.charCodeAt(pos++) - // Check bullet - if (marker !== 0x2A/* * */ && - marker !== 0x2D/* - */ && - marker !== 0x2B/* + */) { - return -1 - } - - if (pos < max) { - const ch = state.src.charCodeAt(pos) - - if (!isSpace(ch)) { - // " -test " - is not a list item - return -1 - } - } - - return pos -} - -// Search `\d+[.)][\n ]`, returns next pos after marker on success -// or -1 on fail. -function skipOrderedListMarker (state, startLine) { - const start = state.bMarks[startLine] + state.tShift[startLine] - const max = state.eMarks[startLine] - let pos = start - - // List marker should have at least 2 chars (digit + dot) - if (pos + 1 >= max) { return -1 } - - let ch = state.src.charCodeAt(pos++) - - if (ch < 0x30/* 0 */ || ch > 0x39/* 9 */) { return -1 } - - for (;;) { - // EOL -> fail - if (pos >= max) { return -1 } - - ch = state.src.charCodeAt(pos++) - - if (ch >= 0x30/* 0 */ && ch <= 0x39/* 9 */) { - // List marker should have no more than 9 digits - // (prevents integer overflow in browsers) - if (pos - start >= 10) { return -1 } - - continue - } - - // found valid marker - if (ch === 0x29/* ) */ || ch === 0x2e/* . */) { - break - } - - return -1 - } - - if (pos < max) { - ch = state.src.charCodeAt(pos) - - if (!isSpace(ch)) { - // " 1.test " - is not a list item - return -1 - } - } - return pos -} - -function markTightParagraphs (state, idx) { - const level = state.level + 2 - - for (let i = idx + 2, l = state.tokens.length - 2; i < l; i++) { - if (state.tokens[i].level === level && state.tokens[i].type === 'paragraph_open') { - state.tokens[i + 2].hidden = true - state.tokens[i].hidden = true - i += 2 - } - } -} - -export default function list (state, startLine, endLine, silent) { - let max, pos, start, token - let nextLine = startLine - let tight = true - - // if it's indented more than 3 spaces, it should be a code block - if (state.sCount[nextLine] - state.blkIndent >= 4) { return false } - - // Special case: - // - item 1 - // - item 2 - // - item 3 - // - item 4 - // - this one is a paragraph continuation - if (state.listIndent >= 0 && - state.sCount[nextLine] - state.listIndent >= 4 && - state.sCount[nextLine] < state.blkIndent) { - return false - } - - let isTerminatingParagraph = false - - // limit conditions when list can interrupt - // a paragraph (validation mode only) - if (silent && state.parentType === 'paragraph') { - // Next list item should still terminate previous list item; - // - // This code can fail if plugins use blkIndent as well as lists, - // but I hope the spec gets fixed long before that happens. - // - if (state.sCount[nextLine] >= state.blkIndent) { - isTerminatingParagraph = true - } - } - - // Detect list type and position after marker - let isOrdered - let markerValue - let posAfterMarker - if ((posAfterMarker = skipOrderedListMarker(state, nextLine)) >= 0) { - isOrdered = true - start = state.bMarks[nextLine] + state.tShift[nextLine] - markerValue = Number(state.src.slice(start, posAfterMarker - 1)) - - // If we're starting a new ordered list right after - // a paragraph, it should start with 1. - if (isTerminatingParagraph && markerValue !== 1) return false - } else if ((posAfterMarker = skipBulletListMarker(state, nextLine)) >= 0) { - isOrdered = false - } else { - return false - } - - // If we're starting a new unordered list right after - // a paragraph, first line should not be empty. - if (isTerminatingParagraph) { - if (state.skipSpaces(posAfterMarker) >= state.eMarks[nextLine]) return false - } - - // For validation mode we can terminate immediately - if (silent) { return true } - - // We should terminate list on style change. Remember first one to compare. - const markerCharCode = state.src.charCodeAt(posAfterMarker - 1) - - // Start list - const listTokIdx = state.tokens.length - - if (isOrdered) { - token = state.push('ordered_list_open', 'ol', 1) - if (markerValue !== 1) { - token.attrs = [['start', markerValue]] - } - } else { - token = state.push('bullet_list_open', 'ul', 1) - } - - const listLines = [nextLine, 0] - token.map = listLines - token.markup = String.fromCharCode(markerCharCode) - - // - // Iterate list items - // - - let prevEmptyEnd = false - const terminatorRules = state.md.block.ruler.getRules('list') - - const oldParentType = state.parentType - state.parentType = 'list' - - while (nextLine < endLine) { - pos = posAfterMarker - max = state.eMarks[nextLine] - - const initial = state.sCount[nextLine] + posAfterMarker - (state.bMarks[nextLine] + state.tShift[nextLine]) - let offset = initial - - while (pos < max) { - const ch = state.src.charCodeAt(pos) - - if (ch === 0x09) { - offset += 4 - (offset + state.bsCount[nextLine]) % 4 - } else if (ch === 0x20) { - offset++ - } else { - break - } - - pos++ - } - - const contentStart = pos - let indentAfterMarker - - if (contentStart >= max) { - // trimming space in "- \n 3" case, indent is 1 here - indentAfterMarker = 1 - } else { - indentAfterMarker = offset - initial - } - - // If we have more than 4 spaces, the indent is 1 - // (the rest is just indented code block) - if (indentAfterMarker > 4) { indentAfterMarker = 1 } - - // " - test" - // ^^^^^ - calculating total length of this thing - const indent = initial + indentAfterMarker - - // Run subparser & write tokens - token = state.push('list_item_open', 'li', 1) - token.markup = String.fromCharCode(markerCharCode) - const itemLines = [nextLine, 0] - token.map = itemLines - if (isOrdered) { - token.info = state.src.slice(start, posAfterMarker - 1) - } - - // change current state, then restore it after parser subcall - const oldTight = state.tight - const oldTShift = state.tShift[nextLine] - const oldSCount = state.sCount[nextLine] - - // - example list - // ^ listIndent position will be here - // ^ blkIndent position will be here - // - const oldListIndent = state.listIndent - state.listIndent = state.blkIndent - state.blkIndent = indent - - state.tight = true - state.tShift[nextLine] = contentStart - state.bMarks[nextLine] - state.sCount[nextLine] = offset - - if (contentStart >= max && state.isEmpty(nextLine + 1)) { - // workaround for this case - // (list item is empty, list terminates before "foo"): - // ~~~~~~~~ - // - - // - // foo - // ~~~~~~~~ - state.line = Math.min(state.line + 2, endLine) - } else { - state.md.block.tokenize(state, nextLine, endLine, true) - } - - // If any of list item is tight, mark list as tight - if (!state.tight || prevEmptyEnd) { - tight = false - } - // Item become loose if finish with empty line, - // but we should filter last element, because it means list finish - prevEmptyEnd = (state.line - nextLine) > 1 && state.isEmpty(state.line - 1) - - state.blkIndent = state.listIndent - state.listIndent = oldListIndent - state.tShift[nextLine] = oldTShift - state.sCount[nextLine] = oldSCount - state.tight = oldTight - - token = state.push('list_item_close', 'li', -1) - token.markup = String.fromCharCode(markerCharCode) - - nextLine = state.line - itemLines[1] = nextLine - - if (nextLine >= endLine) { break } - - // - // Try to check if list is terminated or continued. - // - if (state.sCount[nextLine] < state.blkIndent) { break } - - // if it's indented more than 3 spaces, it should be a code block - if (state.sCount[nextLine] - state.blkIndent >= 4) { break } - - // fail if terminating block found - let terminate = false - for (let i = 0, l = terminatorRules.length; i < l; i++) { - if (terminatorRules[i](state, nextLine, endLine, true)) { - terminate = true - break - } - } - if (terminate) { break } - - // fail if list has another type - if (isOrdered) { - posAfterMarker = skipOrderedListMarker(state, nextLine) - if (posAfterMarker < 0) { break } - start = state.bMarks[nextLine] + state.tShift[nextLine] - } else { - posAfterMarker = skipBulletListMarker(state, nextLine) - if (posAfterMarker < 0) { break } - } - - if (markerCharCode !== state.src.charCodeAt(posAfterMarker - 1)) { break } - } - - // Finalize list - if (isOrdered) { - token = state.push('ordered_list_close', 'ol', -1) - } else { - token = state.push('bullet_list_close', 'ul', -1) - } - token.markup = String.fromCharCode(markerCharCode) - - listLines[1] = nextLine - state.line = nextLine - - state.parentType = oldParentType - - // mark paragraphs tight if needed - if (tight) { - markTightParagraphs(state, listTokIdx) - } - - return true -} diff --git a/packages/markdown-it-14.1.0/lib/rules_block/paragraph.mjs b/packages/markdown-it-14.1.0/lib/rules_block/paragraph.mjs deleted file mode 100644 index 6ecdcef..0000000 --- a/packages/markdown-it-14.1.0/lib/rules_block/paragraph.mjs +++ /dev/null @@ -1,46 +0,0 @@ -// Paragraph - -export default function paragraph (state, startLine, endLine) { - const terminatorRules = state.md.block.ruler.getRules('paragraph') - const oldParentType = state.parentType - let nextLine = startLine + 1 - state.parentType = 'paragraph' - - // jump line-by-line until empty one or EOF - for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) { - // this would be a code block normally, but after paragraph - // it's considered a lazy continuation regardless of what's there - if (state.sCount[nextLine] - state.blkIndent > 3) { continue } - - // quirk for blockquotes, this line should already be checked by that rule - if (state.sCount[nextLine] < 0) { continue } - - // Some tags can terminate paragraph without empty line. - let terminate = false - for (let i = 0, l = terminatorRules.length; i < l; i++) { - if (terminatorRules[i](state, nextLine, endLine, true)) { - terminate = true - break - } - } - if (terminate) { break } - } - - const content = state.getLines(startLine, nextLine, state.blkIndent, false).trim() - - state.line = nextLine - - const token_o = state.push('paragraph_open', 'p', 1) - token_o.map = [startLine, state.line] - - const token_i = state.push('inline', '', 0) - token_i.content = content - token_i.map = [startLine, state.line] - token_i.children = [] - - state.push('paragraph_close', 'p', -1) - - state.parentType = oldParentType - - return true -} diff --git a/packages/markdown-it-14.1.0/lib/rules_block/reference.mjs b/packages/markdown-it-14.1.0/lib/rules_block/reference.mjs deleted file mode 100644 index 4166286..0000000 --- a/packages/markdown-it-14.1.0/lib/rules_block/reference.mjs +++ /dev/null @@ -1,212 +0,0 @@ -import { isSpace, normalizeReference } from '../common/utils.mjs' - -export default function reference (state, startLine, _endLine, silent) { - let pos = state.bMarks[startLine] + state.tShift[startLine] - let max = state.eMarks[startLine] - let nextLine = startLine + 1 - - // if it's indented more than 3 spaces, it should be a code block - if (state.sCount[startLine] - state.blkIndent >= 4) { return false } - - if (state.src.charCodeAt(pos) !== 0x5B/* [ */) { return false } - - function getNextLine (nextLine) { - const endLine = state.lineMax - - if (nextLine >= endLine || state.isEmpty(nextLine)) { - // empty line or end of input - return null - } - - let isContinuation = false - - // this would be a code block normally, but after paragraph - // it's considered a lazy continuation regardless of what's there - if (state.sCount[nextLine] - state.blkIndent > 3) { isContinuation = true } - - // quirk for blockquotes, this line should already be checked by that rule - if (state.sCount[nextLine] < 0) { isContinuation = true } - - if (!isContinuation) { - const terminatorRules = state.md.block.ruler.getRules('reference') - const oldParentType = state.parentType - state.parentType = 'reference' - - // Some tags can terminate paragraph without empty line. - let terminate = false - for (let i = 0, l = terminatorRules.length; i < l; i++) { - if (terminatorRules[i](state, nextLine, endLine, true)) { - terminate = true - break - } - } - - state.parentType = oldParentType - if (terminate) { - // terminated by another block - return null - } - } - - const pos = state.bMarks[nextLine] + state.tShift[nextLine] - const max = state.eMarks[nextLine] - - // max + 1 explicitly includes the newline - return state.src.slice(pos, max + 1) - } - - let str = state.src.slice(pos, max + 1) - - max = str.length - let labelEnd = -1 - - for (pos = 1; pos < max; pos++) { - const ch = str.charCodeAt(pos) - if (ch === 0x5B /* [ */) { - return false - } else if (ch === 0x5D /* ] */) { - labelEnd = pos - break - } else if (ch === 0x0A /* \n */) { - const lineContent = getNextLine(nextLine) - if (lineContent !== null) { - str += lineContent - max = str.length - nextLine++ - } - } else if (ch === 0x5C /* \ */) { - pos++ - if (pos < max && str.charCodeAt(pos) === 0x0A) { - const lineContent = getNextLine(nextLine) - if (lineContent !== null) { - str += lineContent - max = str.length - nextLine++ - } - } - } - } - - if (labelEnd < 0 || str.charCodeAt(labelEnd + 1) !== 0x3A/* : */) { return false } - - // [label]: destination 'title' - // ^^^ skip optional whitespace here - for (pos = labelEnd + 2; pos < max; pos++) { - const ch = str.charCodeAt(pos) - if (ch === 0x0A) { - const lineContent = getNextLine(nextLine) - if (lineContent !== null) { - str += lineContent - max = str.length - nextLine++ - } - } else if (isSpace(ch)) { - /* eslint no-empty:0 */ - } else { - break - } - } - - // [label]: destination 'title' - // ^^^^^^^^^^^ parse this - const destRes = state.md.helpers.parseLinkDestination(str, pos, max) - if (!destRes.ok) { return false } - - const href = state.md.normalizeLink(destRes.str) - if (!state.md.validateLink(href)) { return false } - - pos = destRes.pos - - // save cursor state, we could require to rollback later - const destEndPos = pos - const destEndLineNo = nextLine - - // [label]: destination 'title' - // ^^^ skipping those spaces - const start = pos - for (; pos < max; pos++) { - const ch = str.charCodeAt(pos) - if (ch === 0x0A) { - const lineContent = getNextLine(nextLine) - if (lineContent !== null) { - str += lineContent - max = str.length - nextLine++ - } - } else if (isSpace(ch)) { - /* eslint no-empty:0 */ - } else { - break - } - } - - // [label]: destination 'title' - // ^^^^^^^ parse this - let titleRes = state.md.helpers.parseLinkTitle(str, pos, max) - while (titleRes.can_continue) { - const lineContent = getNextLine(nextLine) - if (lineContent === null) break - str += lineContent - pos = max - max = str.length - nextLine++ - titleRes = state.md.helpers.parseLinkTitle(str, pos, max, titleRes) - } - let title - - if (pos < max && start !== pos && titleRes.ok) { - title = titleRes.str - pos = titleRes.pos - } else { - title = '' - pos = destEndPos - nextLine = destEndLineNo - } - - // skip trailing spaces until the rest of the line - while (pos < max) { - const ch = str.charCodeAt(pos) - if (!isSpace(ch)) { break } - pos++ - } - - if (pos < max && str.charCodeAt(pos) !== 0x0A) { - if (title) { - // garbage at the end of the line after title, - // but it could still be a valid reference if we roll back - title = '' - pos = destEndPos - nextLine = destEndLineNo - while (pos < max) { - const ch = str.charCodeAt(pos) - if (!isSpace(ch)) { break } - pos++ - } - } - } - - if (pos < max && str.charCodeAt(pos) !== 0x0A) { - // garbage at the end of the line - return false - } - - const label = normalizeReference(str.slice(1, labelEnd)) - if (!label) { - // CommonMark 0.20 disallows empty labels - return false - } - - // Reference can not terminate anything. This check is for safety only. - /* istanbul ignore if */ - if (silent) { return true } - - if (typeof state.env.references === 'undefined') { - state.env.references = {} - } - if (typeof state.env.references[label] === 'undefined') { - state.env.references[label] = { title, href } - } - - state.line = nextLine - return true -} diff --git a/packages/markdown-it-14.1.0/lib/rules_block/state_block.mjs b/packages/markdown-it-14.1.0/lib/rules_block/state_block.mjs deleted file mode 100644 index 3c2a876..0000000 --- a/packages/markdown-it-14.1.0/lib/rules_block/state_block.mjs +++ /dev/null @@ -1,220 +0,0 @@ -// Parser state class - -import Token from '../token.mjs' -import { isSpace } from '../common/utils.mjs' - -function StateBlock (src, md, env, tokens) { - this.src = src - - // link to parser instance - this.md = md - - this.env = env - - // - // Internal state vartiables - // - - this.tokens = tokens - - this.bMarks = [] // line begin offsets for fast jumps - this.eMarks = [] // line end offsets for fast jumps - this.tShift = [] // offsets of the first non-space characters (tabs not expanded) - this.sCount = [] // indents for each line (tabs expanded) - - // An amount of virtual spaces (tabs expanded) between beginning - // of each line (bMarks) and real beginning of that line. - // - // It exists only as a hack because blockquotes override bMarks - // losing information in the process. - // - // It's used only when expanding tabs, you can think about it as - // an initial tab length, e.g. bsCount=21 applied to string `\t123` - // means first tab should be expanded to 4-21%4 === 3 spaces. - // - this.bsCount = [] - - // block parser variables - - // required block content indent (for example, if we are - // inside a list, it would be positioned after list marker) - this.blkIndent = 0 - this.line = 0 // line index in src - this.lineMax = 0 // lines count - this.tight = false // loose/tight mode for lists - this.ddIndent = -1 // indent of the current dd block (-1 if there isn't any) - this.listIndent = -1 // indent of the current list block (-1 if there isn't any) - - // can be 'blockquote', 'list', 'root', 'paragraph' or 'reference' - // used in lists to determine if they interrupt a paragraph - this.parentType = 'root' - - this.level = 0 - - // Create caches - // Generate markers. - const s = this.src - - for (let start = 0, pos = 0, indent = 0, offset = 0, len = s.length, indent_found = false; pos < len; pos++) { - const ch = s.charCodeAt(pos) - - if (!indent_found) { - if (isSpace(ch)) { - indent++ - - if (ch === 0x09) { - offset += 4 - offset % 4 - } else { - offset++ - } - continue - } else { - indent_found = true - } - } - - if (ch === 0x0A || pos === len - 1) { - if (ch !== 0x0A) { pos++ } - this.bMarks.push(start) - this.eMarks.push(pos) - this.tShift.push(indent) - this.sCount.push(offset) - this.bsCount.push(0) - - indent_found = false - indent = 0 - offset = 0 - start = pos + 1 - } - } - - // Push fake entry to simplify cache bounds checks - this.bMarks.push(s.length) - this.eMarks.push(s.length) - this.tShift.push(0) - this.sCount.push(0) - this.bsCount.push(0) - - this.lineMax = this.bMarks.length - 1 // don't count last fake line -} - -// Push new token to "stream". -// -StateBlock.prototype.push = function (type, tag, nesting) { - const token = new Token(type, tag, nesting) - token.block = true - - if (nesting < 0) this.level-- // closing tag - token.level = this.level - if (nesting > 0) this.level++ // opening tag - - this.tokens.push(token) - return token -} - -StateBlock.prototype.isEmpty = function isEmpty (line) { - return this.bMarks[line] + this.tShift[line] >= this.eMarks[line] -} - -StateBlock.prototype.skipEmptyLines = function skipEmptyLines (from) { - for (let max = this.lineMax; from < max; from++) { - if (this.bMarks[from] + this.tShift[from] < this.eMarks[from]) { - break - } - } - return from -} - -// Skip spaces from given position. -StateBlock.prototype.skipSpaces = function skipSpaces (pos) { - for (let max = this.src.length; pos < max; pos++) { - const ch = this.src.charCodeAt(pos) - if (!isSpace(ch)) { break } - } - return pos -} - -// Skip spaces from given position in reverse. -StateBlock.prototype.skipSpacesBack = function skipSpacesBack (pos, min) { - if (pos <= min) { return pos } - - while (pos > min) { - if (!isSpace(this.src.charCodeAt(--pos))) { return pos + 1 } - } - return pos -} - -// Skip char codes from given position -StateBlock.prototype.skipChars = function skipChars (pos, code) { - for (let max = this.src.length; pos < max; pos++) { - if (this.src.charCodeAt(pos) !== code) { break } - } - return pos -} - -// Skip char codes reverse from given position - 1 -StateBlock.prototype.skipCharsBack = function skipCharsBack (pos, code, min) { - if (pos <= min) { return pos } - - while (pos > min) { - if (code !== this.src.charCodeAt(--pos)) { return pos + 1 } - } - return pos -} - -// cut lines range from source. -StateBlock.prototype.getLines = function getLines (begin, end, indent, keepLastLF) { - if (begin >= end) { - return '' - } - - const queue = new Array(end - begin) - - for (let i = 0, line = begin; line < end; line++, i++) { - let lineIndent = 0 - const lineStart = this.bMarks[line] - let first = lineStart - let last - - if (line + 1 < end || keepLastLF) { - // No need for bounds check because we have fake entry on tail. - last = this.eMarks[line] + 1 - } else { - last = this.eMarks[line] - } - - while (first < last && lineIndent < indent) { - const ch = this.src.charCodeAt(first) - - if (isSpace(ch)) { - if (ch === 0x09) { - lineIndent += 4 - (lineIndent + this.bsCount[line]) % 4 - } else { - lineIndent++ - } - } else if (first - lineStart < this.tShift[line]) { - // patched tShift masked characters to look like spaces (blockquotes, list markers) - lineIndent++ - } else { - break - } - - first++ - } - - if (lineIndent > indent) { - // partially expanding tabs in code blocks, e.g '\t\tfoobar' - // with indent=2 becomes ' \tfoobar' - queue[i] = new Array(lineIndent - indent + 1).join(' ') + this.src.slice(first, last) - } else { - queue[i] = this.src.slice(first, last) - } - } - - return queue.join('') -} - -// re-export Token class to use in block rules -StateBlock.prototype.Token = Token - -export default StateBlock diff --git a/packages/markdown-it-14.1.0/lib/rules_block/table.mjs b/packages/markdown-it-14.1.0/lib/rules_block/table.mjs deleted file mode 100644 index be0ba0a..0000000 --- a/packages/markdown-it-14.1.0/lib/rules_block/table.mjs +++ /dev/null @@ -1,228 +0,0 @@ -// GFM table, https://github.github.com/gfm/#tables-extension- - -import { isSpace } from '../common/utils.mjs' - -// Limit the amount of empty autocompleted cells in a table, -// see https://github.com/markdown-it/markdown-it/issues/1000, -// -// Both pulldown-cmark and commonmark-hs limit the number of cells this way to ~200k. -// We set it to 65k, which can expand user input by a factor of x370 -// (256x256 square is 1.8kB expanded into 650kB). -const MAX_AUTOCOMPLETED_CELLS = 0x10000 - -function getLine (state, line) { - const pos = state.bMarks[line] + state.tShift[line] - const max = state.eMarks[line] - - return state.src.slice(pos, max) -} - -function escapedSplit (str) { - const result = [] - const max = str.length - - let pos = 0 - let ch = str.charCodeAt(pos) - let isEscaped = false - let lastPos = 0 - let current = '' - - while (pos < max) { - if (ch === 0x7c/* | */) { - if (!isEscaped) { - // pipe separating cells, '|' - result.push(current + str.substring(lastPos, pos)) - current = '' - lastPos = pos + 1 - } else { - // escaped pipe, '\|' - current += str.substring(lastPos, pos - 1) - lastPos = pos - } - } - - isEscaped = (ch === 0x5c/* \ */) - pos++ - - ch = str.charCodeAt(pos) - } - - result.push(current + str.substring(lastPos)) - - return result -} - -export default function table (state, startLine, endLine, silent) { - // should have at least two lines - if (startLine + 2 > endLine) { return false } - - let nextLine = startLine + 1 - - if (state.sCount[nextLine] < state.blkIndent) { return false } - - // if it's indented more than 3 spaces, it should be a code block - if (state.sCount[nextLine] - state.blkIndent >= 4) { return false } - - // first character of the second line should be '|', '-', ':', - // and no other characters are allowed but spaces; - // basically, this is the equivalent of /^[-:|][-:|\s]*$/ regexp - - let pos = state.bMarks[nextLine] + state.tShift[nextLine] - if (pos >= state.eMarks[nextLine]) { return false } - - const firstCh = state.src.charCodeAt(pos++) - if (firstCh !== 0x7C/* | */ && firstCh !== 0x2D/* - */ && firstCh !== 0x3A/* : */) { return false } - - if (pos >= state.eMarks[nextLine]) { return false } - - const secondCh = state.src.charCodeAt(pos++) - if (secondCh !== 0x7C/* | */ && secondCh !== 0x2D/* - */ && secondCh !== 0x3A/* : */ && !isSpace(secondCh)) { - return false - } - - // if first character is '-', then second character must not be a space - // (due to parsing ambiguity with list) - if (firstCh === 0x2D/* - */ && isSpace(secondCh)) { return false } - - while (pos < state.eMarks[nextLine]) { - const ch = state.src.charCodeAt(pos) - - if (ch !== 0x7C/* | */ && ch !== 0x2D/* - */ && ch !== 0x3A/* : */ && !isSpace(ch)) { return false } - - pos++ - } - - let lineText = getLine(state, startLine + 1) - let columns = lineText.split('|') - const aligns = [] - for (let i = 0; i < columns.length; i++) { - const t = columns[i].trim() - if (!t) { - // allow empty columns before and after table, but not in between columns; - // e.g. allow ` |---| `, disallow ` ---||--- ` - if (i === 0 || i === columns.length - 1) { - continue - } else { - return false - } - } - - if (!/^:?-+:?$/.test(t)) { return false } - if (t.charCodeAt(t.length - 1) === 0x3A/* : */) { - aligns.push(t.charCodeAt(0) === 0x3A/* : */ ? 'center' : 'right') - } else if (t.charCodeAt(0) === 0x3A/* : */) { - aligns.push('left') - } else { - aligns.push('') - } - } - - lineText = getLine(state, startLine).trim() - if (lineText.indexOf('|') === -1) { return false } - if (state.sCount[startLine] - state.blkIndent >= 4) { return false } - columns = escapedSplit(lineText) - if (columns.length && columns[0] === '') columns.shift() - if (columns.length && columns[columns.length - 1] === '') columns.pop() - - // header row will define an amount of columns in the entire table, - // and align row should be exactly the same (the rest of the rows can differ) - const columnCount = columns.length - if (columnCount === 0 || columnCount !== aligns.length) { return false } - - if (silent) { return true } - - const oldParentType = state.parentType - state.parentType = 'table' - - // use 'blockquote' lists for termination because it's - // the most similar to tables - const terminatorRules = state.md.block.ruler.getRules('blockquote') - - const token_to = state.push('table_open', 'table', 1) - const tableLines = [startLine, 0] - token_to.map = tableLines - - const token_tho = state.push('thead_open', 'thead', 1) - token_tho.map = [startLine, startLine + 1] - - const token_htro = state.push('tr_open', 'tr', 1) - token_htro.map = [startLine, startLine + 1] - - for (let i = 0; i < columns.length; i++) { - const token_ho = state.push('th_open', 'th', 1) - if (aligns[i]) { - token_ho.attrs = [['style', 'text-align:' + aligns[i]]] - } - - const token_il = state.push('inline', '', 0) - token_il.content = columns[i].trim() - token_il.children = [] - - state.push('th_close', 'th', -1) - } - - state.push('tr_close', 'tr', -1) - state.push('thead_close', 'thead', -1) - - let tbodyLines - let autocompletedCells = 0 - - for (nextLine = startLine + 2; nextLine < endLine; nextLine++) { - if (state.sCount[nextLine] < state.blkIndent) { break } - - let terminate = false - for (let i = 0, l = terminatorRules.length; i < l; i++) { - if (terminatorRules[i](state, nextLine, endLine, true)) { - terminate = true - break - } - } - - if (terminate) { break } - lineText = getLine(state, nextLine).trim() - if (!lineText) { break } - if (state.sCount[nextLine] - state.blkIndent >= 4) { break } - columns = escapedSplit(lineText) - if (columns.length && columns[0] === '') columns.shift() - if (columns.length && columns[columns.length - 1] === '') columns.pop() - - // note: autocomplete count can be negative if user specifies more columns than header, - // but that does not affect intended use (which is limiting expansion) - autocompletedCells += columnCount - columns.length - if (autocompletedCells > MAX_AUTOCOMPLETED_CELLS) { break } - - if (nextLine === startLine + 2) { - const token_tbo = state.push('tbody_open', 'tbody', 1) - token_tbo.map = tbodyLines = [startLine + 2, 0] - } - - const token_tro = state.push('tr_open', 'tr', 1) - token_tro.map = [nextLine, nextLine + 1] - - for (let i = 0; i < columnCount; i++) { - const token_tdo = state.push('td_open', 'td', 1) - if (aligns[i]) { - token_tdo.attrs = [['style', 'text-align:' + aligns[i]]] - } - - const token_il = state.push('inline', '', 0) - token_il.content = columns[i] ? columns[i].trim() : '' - token_il.children = [] - - state.push('td_close', 'td', -1) - } - state.push('tr_close', 'tr', -1) - } - - if (tbodyLines) { - state.push('tbody_close', 'tbody', -1) - tbodyLines[1] = nextLine - } - - state.push('table_close', 'table', -1) - tableLines[1] = nextLine - - state.parentType = oldParentType - state.line = nextLine - return true -} |
