summaryrefslogtreecommitdiff
path: root/node_modules/markdown-it/lib/rules_inline/balance_pairs.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/markdown-it/lib/rules_inline/balance_pairs.js')
-rw-r--r--node_modules/markdown-it/lib/rules_inline/balance_pairs.js130
1 files changed, 130 insertions, 0 deletions
diff --git a/node_modules/markdown-it/lib/rules_inline/balance_pairs.js b/node_modules/markdown-it/lib/rules_inline/balance_pairs.js
new file mode 100644
index 0000000..4faad90
--- /dev/null
+++ b/node_modules/markdown-it/lib/rules_inline/balance_pairs.js
@@ -0,0 +1,130 @@
+// For each opening emphasis-like marker find a matching closing one
+//
+'use strict';
+
+
+function processDelimiters(state, delimiters) {
+ var closerIdx, openerIdx, closer, opener, minOpenerIdx, newMinOpenerIdx,
+ isOddMatch, lastJump,
+ openersBottom = {},
+ max = delimiters.length;
+
+ if (!max) return;
+
+ // headerIdx is the first delimiter of the current (where closer is) delimiter run
+ var headerIdx = 0;
+ var lastTokenIdx = -2; // needs any value lower than -1
+ var jumps = [];
+
+ for (closerIdx = 0; closerIdx < max; closerIdx++) {
+ 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
+ if (!openersBottom.hasOwnProperty(closer.marker)) {
+ openersBottom[closer.marker] = [ -1, -1, -1, -1, -1, -1 ];
+ }
+
+ minOpenerIdx = openersBottom[closer.marker][(closer.open ? 3 : 0) + (closer.length % 3)];
+
+ openerIdx = headerIdx - jumps[headerIdx] - 1;
+
+ newMinOpenerIdx = openerIdx;
+
+ for (; openerIdx > minOpenerIdx; openerIdx -= jumps[openerIdx] + 1) {
+ opener = delimiters[openerIdx];
+
+ if (opener.marker !== closer.marker) continue;
+
+ if (opener.open && opener.end < 0) {
+
+ 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).
+ //
+ 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;
+ }
+ }
+}
+
+
+module.exports = function link_pairs(state) {
+ var curr,
+ tokens_meta = state.tokens_meta,
+ max = state.tokens_meta.length;
+
+ processDelimiters(state, state.delimiters);
+
+ for (curr = 0; curr < max; curr++) {
+ if (tokens_meta[curr] && tokens_meta[curr].delimiters) {
+ processDelimiters(state, tokens_meta[curr].delimiters);
+ }
+ }
+};