diff options
author | altaf-creator <dev@altafcreator.com> | 2024-05-12 12:14:02 +0700 |
---|---|---|
committer | altaf-creator <dev@altafcreator.com> | 2024-05-12 12:14:02 +0700 |
commit | d607ac12097afb5cb6f398a4e7b5cf4316efedc6 (patch) | |
tree | 6f4bc5b98a6ff3a1c3189f7ef9b570c0481e100d /packages/markdown-it-14.1.0/lib/rules_inline/balance_pairs.mjs | |
parent | 7441f212967256ac4c9a93ba0b1f026308a8bfb6 (diff) |
self host
Diffstat (limited to 'packages/markdown-it-14.1.0/lib/rules_inline/balance_pairs.mjs')
-rw-r--r-- | packages/markdown-it-14.1.0/lib/rules_inline/balance_pairs.mjs | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/packages/markdown-it-14.1.0/lib/rules_inline/balance_pairs.mjs b/packages/markdown-it-14.1.0/lib/rules_inline/balance_pairs.mjs new file mode 100644 index 0000000..8638d21 --- /dev/null +++ b/packages/markdown-it-14.1.0/lib/rules_inline/balance_pairs.mjs @@ -0,0 +1,124 @@ +// For each opening emphasis-like marker find a matching closing one +// + +function processDelimiters (delimiters) { + const openersBottom = {} + const max = delimiters.length + + if (!max) return + + // headerIdx is the first delimiter of the current (where closer is) delimiter run + let headerIdx = 0 + let lastTokenIdx = -2 // needs any value lower than -1 + const jumps = [] + + for (let closerIdx = 0; closerIdx < max; closerIdx++) { + const closer = delimiters[closerIdx] + + jumps.push(0) + + // markers belong to same delimiter run if: + // - they have adjacent tokens + // - AND markers are the same + // + if (delimiters[headerIdx].marker !== closer.marker || lastTokenIdx !== closer.token - 1) { + headerIdx = closerIdx + } + + lastTokenIdx = closer.token + + // Length is only used for emphasis-specific "rule of 3", + // if it's not defined (in strikethrough or 3rd party plugins), + // we can default it to 0 to disable those checks. + // + closer.length = closer.length || 0 + + if (!closer.close) continue + + // Previously calculated lower bounds (previous fails) + // for each marker, each delimiter length modulo 3, + // and for whether this closer can be an opener; + // https://github.com/commonmark/cmark/commit/34250e12ccebdc6372b8b49c44fab57c72443460 + /* eslint-disable-next-line no-prototype-builtins */ + if (!openersBottom.hasOwnProperty(closer.marker)) { + openersBottom[closer.marker] = [-1, -1, -1, -1, -1, -1] + } + + const minOpenerIdx = openersBottom[closer.marker][(closer.open ? 3 : 0) + (closer.length % 3)] + + let openerIdx = headerIdx - jumps[headerIdx] - 1 + + let newMinOpenerIdx = openerIdx + + for (; openerIdx > minOpenerIdx; openerIdx -= jumps[openerIdx] + 1) { + const opener = delimiters[openerIdx] + + if (opener.marker !== closer.marker) continue + + if (opener.open && opener.end < 0) { + let isOddMatch = false + + // from spec: + // + // If one of the delimiters can both open and close emphasis, then the + // sum of the lengths of the delimiter runs containing the opening and + // closing delimiters must not be a multiple of 3 unless both lengths + // are multiples of 3. + // + if (opener.close || closer.open) { + if ((opener.length + closer.length) % 3 === 0) { + if (opener.length % 3 !== 0 || closer.length % 3 !== 0) { + isOddMatch = true + } + } + } + + if (!isOddMatch) { + // If previous delimiter cannot be an opener, we can safely skip + // the entire sequence in future checks. This is required to make + // sure algorithm has linear complexity (see *_*_*_*_*_... case). + // + const lastJump = openerIdx > 0 && !delimiters[openerIdx - 1].open + ? jumps[openerIdx - 1] + 1 + : 0 + + jumps[closerIdx] = closerIdx - openerIdx + lastJump + jumps[openerIdx] = lastJump + + closer.open = false + opener.end = closerIdx + opener.close = false + newMinOpenerIdx = -1 + // treat next token as start of run, + // it optimizes skips in **<...>**a**<...>** pathological case + lastTokenIdx = -2 + break + } + } + } + + if (newMinOpenerIdx !== -1) { + // If match for this delimiter run failed, we want to set lower bound for + // future lookups. This is required to make sure algorithm has linear + // complexity. + // + // See details here: + // https://github.com/commonmark/cmark/issues/178#issuecomment-270417442 + // + openersBottom[closer.marker][(closer.open ? 3 : 0) + ((closer.length || 0) % 3)] = newMinOpenerIdx + } + } +} + +export default function link_pairs (state) { + const tokens_meta = state.tokens_meta + const max = state.tokens_meta.length + + processDelimiters(state.delimiters) + + for (let curr = 0; curr < max; curr++) { + if (tokens_meta[curr] && tokens_meta[curr].delimiters) { + processDelimiters(tokens_meta[curr].delimiters) + } + } +} |