summaryrefslogtreecommitdiff
path: root/node_modules/markdown-it/lib/rules_block
diff options
context:
space:
mode:
authorMinteck <contact@minteck.org>2022-01-20 13:43:34 +0100
committerMinteck <contact@minteck.org>2022-01-20 13:43:34 +0100
commitc2aa7bf38fb30de2d04f87f8e7780e4c768ae6b1 (patch)
tree226598e8d17d20e3721358f7c60b1cc6b851163a /node_modules/markdown-it/lib/rules_block
downloadcobalt-c2aa7bf38fb30de2d04f87f8e7780e4c768ae6b1.tar.gz
cobalt-c2aa7bf38fb30de2d04f87f8e7780e4c768ae6b1.tar.bz2
cobalt-c2aa7bf38fb30de2d04f87f8e7780e4c768ae6b1.zip
Initial commit
Diffstat (limited to 'node_modules/markdown-it/lib/rules_block')
-rw-r--r--node_modules/markdown-it/lib/rules_block/blockquote.js284
-rw-r--r--node_modules/markdown-it/lib/rules_block/code.js34
-rw-r--r--node_modules/markdown-it/lib/rules_block/fence.js98
-rw-r--r--node_modules/markdown-it/lib/rules_block/heading.js55
-rw-r--r--node_modules/markdown-it/lib/rules_block/hr.js45
-rw-r--r--node_modules/markdown-it/lib/rules_block/html_block.js74
-rw-r--r--node_modules/markdown-it/lib/rules_block/lheading.js83
-rw-r--r--node_modules/markdown-it/lib/rules_block/list.js364
-rw-r--r--node_modules/markdown-it/lib/rules_block/paragraph.js52
-rw-r--r--node_modules/markdown-it/lib/rules_block/reference.js198
-rw-r--r--node_modules/markdown-it/lib/rules_block/state_block.js231
-rw-r--r--node_modules/markdown-it/lib/rules_block/table.js221
12 files changed, 1739 insertions, 0 deletions
diff --git a/node_modules/markdown-it/lib/rules_block/blockquote.js b/node_modules/markdown-it/lib/rules_block/blockquote.js
new file mode 100644
index 0000000..a02699a
--- /dev/null
+++ b/node_modules/markdown-it/lib/rules_block/blockquote.js
@@ -0,0 +1,284 @@
+// Block quotes
+
+'use strict';
+
+var isSpace = require('../common/utils').isSpace;
+
+
+module.exports = function blockquote(state, startLine, endLine, silent) {
+ var adjustTab,
+ ch,
+ i,
+ initial,
+ l,
+ lastLineEmpty,
+ lines,
+ nextLine,
+ offset,
+ oldBMarks,
+ oldBSCount,
+ oldIndent,
+ oldParentType,
+ oldSCount,
+ oldTShift,
+ spaceAfterMarker,
+ terminate,
+ terminatorRules,
+ token,
+ isOutdented,
+ oldLineMax = state.lineMax,
+ pos = state.bMarks[startLine] + state.tShift[startLine],
+ 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; }
+
+ // 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; }
+
+ // set offset past spaces and ">"
+ initial = offset = state.sCount[startLine] + 1;
+
+ // skip one optional space after '>'
+ if (state.src.charCodeAt(pos) === 0x20 /* space */) {
+ // ' > test '
+ // ^ -- position start of line here:
+ pos++;
+ initial++;
+ offset++;
+ adjustTab = false;
+ spaceAfterMarker = true;
+ } else if (state.src.charCodeAt(pos) === 0x09 /* tab */) {
+ spaceAfterMarker = true;
+
+ if ((state.bsCount[startLine] + offset) % 4 === 3) {
+ // ' >\t test '
+ // ^ -- position start of line here (tab has width===1)
+ pos++;
+ initial++;
+ offset++;
+ adjustTab = false;
+ } else {
+ // ' >\t test '
+ // ^ -- position start of line here + shift bsCount slightly
+ // to make extra space appear
+ adjustTab = true;
+ }
+ } else {
+ spaceAfterMarker = false;
+ }
+
+ oldBMarks = [ state.bMarks[startLine] ];
+ state.bMarks[startLine] = pos;
+
+ while (pos < max) {
+ ch = state.src.charCodeAt(pos);
+
+ if (isSpace(ch)) {
+ if (ch === 0x09) {
+ offset += 4 - (offset + state.bsCount[startLine] + (adjustTab ? 1 : 0)) % 4;
+ } else {
+ offset++;
+ }
+ } else {
+ break;
+ }
+
+ pos++;
+ }
+
+ oldBSCount = [ state.bsCount[startLine] ];
+ state.bsCount[startLine] = state.sCount[startLine] + 1 + (spaceAfterMarker ? 1 : 0);
+
+ lastLineEmpty = pos >= max;
+
+ oldSCount = [ state.sCount[startLine] ];
+ state.sCount[startLine] = offset - initial;
+
+ oldTShift = [ state.tShift[startLine] ];
+ state.tShift[startLine] = pos - state.bMarks[startLine];
+
+ terminatorRules = state.md.block.ruler.getRules('blockquote');
+
+ oldParentType = state.parentType;
+ state.parentType = 'blockquote';
+
+ // 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 + 1; 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
+ // ```
+ 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 ">"
+ initial = offset = state.sCount[nextLine] + 1;
+
+ // skip one optional space after '>'
+ if (state.src.charCodeAt(pos) === 0x20 /* space */) {
+ // ' > test '
+ // ^ -- position start of line here:
+ pos++;
+ initial++;
+ offset++;
+ adjustTab = false;
+ spaceAfterMarker = true;
+ } else if (state.src.charCodeAt(pos) === 0x09 /* tab */) {
+ spaceAfterMarker = true;
+
+ if ((state.bsCount[nextLine] + offset) % 4 === 3) {
+ // ' >\t test '
+ // ^ -- position start of line here (tab has width===1)
+ pos++;
+ initial++;
+ offset++;
+ adjustTab = false;
+ } else {
+ // ' >\t test '
+ // ^ -- position start of line here + shift bsCount slightly
+ // to make extra space appear
+ adjustTab = true;
+ }
+ } else {
+ spaceAfterMarker = false;
+ }
+
+ oldBMarks.push(state.bMarks[nextLine]);
+ state.bMarks[nextLine] = pos;
+
+ while (pos < max) {
+ 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.
+ terminate = false;
+ for (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;
+ }
+
+ oldIndent = state.blkIndent;
+ state.blkIndent = 0;
+
+ token = state.push('blockquote_open', 'blockquote', 1);
+ token.markup = '>';
+ token.map = lines = [ startLine, 0 ];
+
+ state.md.block.tokenize(state, startLine, nextLine);
+
+ token = state.push('blockquote_close', 'blockquote', -1);
+ token.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 (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/node_modules/markdown-it/lib/rules_block/code.js b/node_modules/markdown-it/lib/rules_block/code.js
new file mode 100644
index 0000000..018e019
--- /dev/null
+++ b/node_modules/markdown-it/lib/rules_block/code.js
@@ -0,0 +1,34 @@
+// Code block (4 spaces padded)
+
+'use strict';
+
+
+module.exports = function code(state, startLine, endLine/*, silent*/) {
+ var nextLine, last, token;
+
+ if (state.sCount[startLine] - state.blkIndent < 4) { return false; }
+
+ last = nextLine = startLine + 1;
+
+ while (nextLine < endLine) {
+ if (state.isEmpty(nextLine)) {
+ nextLine++;
+ continue;
+ }
+
+ if (state.sCount[nextLine] - state.blkIndent >= 4) {
+ nextLine++;
+ last = nextLine;
+ continue;
+ }
+ break;
+ }
+
+ state.line = last;
+
+ 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/node_modules/markdown-it/lib/rules_block/fence.js b/node_modules/markdown-it/lib/rules_block/fence.js
new file mode 100644
index 0000000..44f1538
--- /dev/null
+++ b/node_modules/markdown-it/lib/rules_block/fence.js
@@ -0,0 +1,98 @@
+// fences (``` lang, ~~~ lang)
+
+'use strict';
+
+
+module.exports = function fence(state, startLine, endLine, silent) {
+ var marker, len, params, nextLine, mem, token, markup,
+ haveEndMarker = false,
+ pos = state.bMarks[startLine] + state.tShift[startLine],
+ 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; }
+
+ marker = state.src.charCodeAt(pos);
+
+ if (marker !== 0x7E/* ~ */ && marker !== 0x60 /* ` */) {
+ return false;
+ }
+
+ // scan marker length
+ mem = pos;
+ pos = state.skipChars(pos, marker);
+
+ len = pos - mem;
+
+ if (len < 3) { return false; }
+
+ markup = state.src.slice(mem, pos);
+ 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
+ nextLine = startLine;
+
+ 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);
+
+ 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/node_modules/markdown-it/lib/rules_block/heading.js b/node_modules/markdown-it/lib/rules_block/heading.js
new file mode 100644
index 0000000..9863f48
--- /dev/null
+++ b/node_modules/markdown-it/lib/rules_block/heading.js
@@ -0,0 +1,55 @@
+// heading (#, ##, ...)
+
+'use strict';
+
+var isSpace = require('../common/utils').isSpace;
+
+
+module.exports = function heading(state, startLine, endLine, silent) {
+ var ch, level, tmp, token,
+ pos = state.bMarks[startLine] + state.tShift[startLine],
+ 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; }
+
+ ch = state.src.charCodeAt(pos);
+
+ if (ch !== 0x23/* # */ || pos >= max) { return false; }
+
+ // count heading level
+ 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);
+ tmp = state.skipCharsBack(max, 0x23, pos); // #
+ if (tmp > pos && isSpace(state.src.charCodeAt(tmp - 1))) {
+ max = tmp;
+ }
+
+ state.line = startLine + 1;
+
+ token = state.push('heading_open', 'h' + String(level), 1);
+ token.markup = '########'.slice(0, level);
+ token.map = [ startLine, state.line ];
+
+ token = state.push('inline', '', 0);
+ token.content = state.src.slice(pos, max).trim();
+ token.map = [ startLine, state.line ];
+ token.children = [];
+
+ token = state.push('heading_close', 'h' + String(level), -1);
+ token.markup = '########'.slice(0, level);
+
+ return true;
+};
diff --git a/node_modules/markdown-it/lib/rules_block/hr.js b/node_modules/markdown-it/lib/rules_block/hr.js
new file mode 100644
index 0000000..a3bb14e
--- /dev/null
+++ b/node_modules/markdown-it/lib/rules_block/hr.js
@@ -0,0 +1,45 @@
+// Horizontal rule
+
+'use strict';
+
+var isSpace = require('../common/utils').isSpace;
+
+
+module.exports = function hr(state, startLine, endLine, silent) {
+ var marker, cnt, ch, token,
+ pos = state.bMarks[startLine] + state.tShift[startLine],
+ 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; }
+
+ 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
+
+ cnt = 1;
+ while (pos < max) {
+ 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;
+
+ 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/node_modules/markdown-it/lib/rules_block/html_block.js b/node_modules/markdown-it/lib/rules_block/html_block.js
new file mode 100644
index 0000000..2f17675
--- /dev/null
+++ b/node_modules/markdown-it/lib/rules_block/html_block.js
@@ -0,0 +1,74 @@
+// HTML block
+
+'use strict';
+
+
+var block_names = require('../common/html_blocks');
+var HTML_OPEN_CLOSE_TAG_RE = require('../common/html_re').HTML_OPEN_CLOSE_TAG_RE;
+
+// An array of opening and corresponding closing sequences for html tags,
+// last argument defines whether it can terminate a paragraph or not
+//
+var 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 ]
+];
+
+
+module.exports = function html_block(state, startLine, endLine, silent) {
+ var i, nextLine, token, lineText,
+ pos = state.bMarks[startLine] + state.tShift[startLine],
+ 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; }
+
+ lineText = state.src.slice(pos, max);
+
+ for (i = 0; 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];
+ }
+
+ 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;
+
+ token = state.push('html_block', '', 0);
+ token.map = [ startLine, nextLine ];
+ token.content = state.getLines(startLine, nextLine, state.blkIndent, true);
+
+ return true;
+};
diff --git a/node_modules/markdown-it/lib/rules_block/lheading.js b/node_modules/markdown-it/lib/rules_block/lheading.js
new file mode 100644
index 0000000..19bdc39
--- /dev/null
+++ b/node_modules/markdown-it/lib/rules_block/lheading.js
@@ -0,0 +1,83 @@
+// lheading (---, ===)
+
+'use strict';
+
+
+module.exports = function lheading(state, startLine, endLine/*, silent*/) {
+ var content, terminate, i, l, token, pos, max, level, marker,
+ nextLine = startLine + 1, oldParentType,
+ 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; }
+
+ oldParentType = state.parentType;
+ state.parentType = 'paragraph'; // use paragraph to match terminatorRules
+
+ // 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; }
+
+ //
+ // Check for underline in setext header
+ //
+ if (state.sCount[nextLine] >= state.blkIndent) {
+ pos = state.bMarks[nextLine] + state.tShift[nextLine];
+ 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.
+ terminate = false;
+ for (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;
+ }
+
+ content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
+
+ state.line = nextLine + 1;
+
+ token = state.push('heading_open', 'h' + String(level), 1);
+ token.markup = String.fromCharCode(marker);
+ token.map = [ startLine, state.line ];
+
+ token = state.push('inline', '', 0);
+ token.content = content;
+ token.map = [ startLine, state.line - 1 ];
+ token.children = [];
+
+ token = state.push('heading_close', 'h' + String(level), -1);
+ token.markup = String.fromCharCode(marker);
+
+ state.parentType = oldParentType;
+
+ return true;
+};
diff --git a/node_modules/markdown-it/lib/rules_block/list.js b/node_modules/markdown-it/lib/rules_block/list.js
new file mode 100644
index 0000000..1e5e87b
--- /dev/null
+++ b/node_modules/markdown-it/lib/rules_block/list.js
@@ -0,0 +1,364 @@
+// Lists
+
+'use strict';
+
+var isSpace = require('../common/utils').isSpace;
+
+
+// Search `[-+*][\n ]`, returns next pos after marker on success
+// or -1 on fail.
+function skipBulletListMarker(state, startLine) {
+ var marker, pos, max, ch;
+
+ pos = state.bMarks[startLine] + state.tShift[startLine];
+ max = state.eMarks[startLine];
+
+ marker = state.src.charCodeAt(pos++);
+ // Check bullet
+ if (marker !== 0x2A/* * */ &&
+ marker !== 0x2D/* - */ &&
+ marker !== 0x2B/* + */) {
+ return -1;
+ }
+
+ if (pos < max) {
+ 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) {
+ var ch,
+ start = state.bMarks[startLine] + state.tShift[startLine],
+ pos = start,
+ max = state.eMarks[startLine];
+
+ // List marker should have at least 2 chars (digit + dot)
+ if (pos + 1 >= max) { return -1; }
+
+ 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) {
+ var i, l,
+ level = state.level + 2;
+
+ for (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;
+ }
+ }
+}
+
+
+module.exports = function list(state, startLine, endLine, silent) {
+ var ch,
+ contentStart,
+ i,
+ indent,
+ indentAfterMarker,
+ initial,
+ isOrdered,
+ itemLines,
+ l,
+ listLines,
+ listTokIdx,
+ markerCharCode,
+ markerValue,
+ max,
+ nextLine,
+ offset,
+ oldListIndent,
+ oldParentType,
+ oldSCount,
+ oldTShift,
+ oldTight,
+ pos,
+ posAfterMarker,
+ prevEmptyEnd,
+ start,
+ terminate,
+ terminatorRules,
+ token,
+ isTerminatingParagraph = false,
+ tight = true;
+
+ // if it's indented more than 3 spaces, it should be a code block
+ if (state.sCount[startLine] - 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[startLine] - state.listIndent >= 4 &&
+ state.sCount[startLine] < state.blkIndent) {
+ return 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[startLine] >= state.blkIndent) {
+ isTerminatingParagraph = true;
+ }
+ }
+
+ // Detect list type and position after marker
+ if ((posAfterMarker = skipOrderedListMarker(state, startLine)) >= 0) {
+ isOrdered = true;
+ start = state.bMarks[startLine] + state.tShift[startLine];
+ 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, startLine)) >= 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[startLine]) return false;
+ }
+
+ // We should terminate list on style change. Remember first one to compare.
+ markerCharCode = state.src.charCodeAt(posAfterMarker - 1);
+
+ // For validation mode we can terminate immediately
+ if (silent) { return true; }
+
+ // Start list
+ 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);
+ }
+
+ token.map = listLines = [ startLine, 0 ];
+ token.markup = String.fromCharCode(markerCharCode);
+
+ //
+ // Iterate list items
+ //
+
+ nextLine = startLine;
+ prevEmptyEnd = false;
+ terminatorRules = state.md.block.ruler.getRules('list');
+
+ oldParentType = state.parentType;
+ state.parentType = 'list';
+
+ while (nextLine < endLine) {
+ pos = posAfterMarker;
+ max = state.eMarks[nextLine];
+
+ initial = offset = state.sCount[nextLine] + posAfterMarker - (state.bMarks[startLine] + state.tShift[startLine]);
+
+ while (pos < max) {
+ ch = state.src.charCodeAt(pos);
+
+ if (ch === 0x09) {
+ offset += 4 - (offset + state.bsCount[nextLine]) % 4;
+ } else if (ch === 0x20) {
+ offset++;
+ } else {
+ break;
+ }
+
+ pos++;
+ }
+
+ contentStart = pos;
+
+ 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
+ indent = initial + indentAfterMarker;
+
+ // Run subparser & write tokens
+ token = state.push('list_item_open', 'li', 1);
+ token.markup = String.fromCharCode(markerCharCode);
+ token.map = itemLines = [ startLine, 0 ];
+ if (isOrdered) {
+ token.info = state.src.slice(start, posAfterMarker - 1);
+ }
+
+ // change current state, then restore it after parser subcall
+ oldTight = state.tight;
+ oldTShift = state.tShift[startLine];
+ oldSCount = state.sCount[startLine];
+
+ // - example list
+ // ^ listIndent position will be here
+ // ^ blkIndent position will be here
+ //
+ oldListIndent = state.listIndent;
+ state.listIndent = state.blkIndent;
+ state.blkIndent = indent;
+
+ state.tight = true;
+ state.tShift[startLine] = contentStart - state.bMarks[startLine];
+ state.sCount[startLine] = offset;
+
+ if (contentStart >= max && state.isEmpty(startLine + 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, startLine, 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 - startLine) > 1 && state.isEmpty(state.line - 1);
+
+ state.blkIndent = state.listIndent;
+ state.listIndent = oldListIndent;
+ state.tShift[startLine] = oldTShift;
+ state.sCount[startLine] = oldSCount;
+ state.tight = oldTight;
+
+ token = state.push('list_item_close', 'li', -1);
+ token.markup = String.fromCharCode(markerCharCode);
+
+ nextLine = startLine = state.line;
+ itemLines[1] = nextLine;
+ contentStart = state.bMarks[startLine];
+
+ 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[startLine] - state.blkIndent >= 4) { break; }
+
+ // fail if terminating block found
+ terminate = false;
+ for (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/node_modules/markdown-it/lib/rules_block/paragraph.js b/node_modules/markdown-it/lib/rules_block/paragraph.js
new file mode 100644
index 0000000..f0c6872
--- /dev/null
+++ b/node_modules/markdown-it/lib/rules_block/paragraph.js
@@ -0,0 +1,52 @@
+// Paragraph
+
+'use strict';
+
+
+module.exports = function paragraph(state, startLine/*, endLine*/) {
+ var content, terminate, i, l, token, oldParentType,
+ nextLine = startLine + 1,
+ terminatorRules = state.md.block.ruler.getRules('paragraph'),
+ endLine = state.lineMax;
+
+ oldParentType = state.parentType;
+ 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.
+ terminate = false;
+ for (i = 0, l = terminatorRules.length; i < l; i++) {
+ if (terminatorRules[i](state, nextLine, endLine, true)) {
+ terminate = true;
+ break;
+ }
+ }
+ if (terminate) { break; }
+ }
+
+ content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
+
+ state.line = nextLine;
+
+ token = state.push('paragraph_open', 'p', 1);
+ token.map = [ startLine, state.line ];
+
+ token = state.push('inline', '', 0);
+ token.content = content;
+ token.map = [ startLine, state.line ];
+ token.children = [];
+
+ token = state.push('paragraph_close', 'p', -1);
+
+ state.parentType = oldParentType;
+
+ return true;
+};
diff --git a/node_modules/markdown-it/lib/rules_block/reference.js b/node_modules/markdown-it/lib/rules_block/reference.js
new file mode 100644
index 0000000..78daa26
--- /dev/null
+++ b/node_modules/markdown-it/lib/rules_block/reference.js
@@ -0,0 +1,198 @@
+'use strict';
+
+
+var normalizeReference = require('../common/utils').normalizeReference;
+var isSpace = require('../common/utils').isSpace;
+
+
+module.exports = function reference(state, startLine, _endLine, silent) {
+ var ch,
+ destEndPos,
+ destEndLineNo,
+ endLine,
+ href,
+ i,
+ l,
+ label,
+ labelEnd,
+ oldParentType,
+ res,
+ start,
+ str,
+ terminate,
+ terminatorRules,
+ title,
+ lines = 0,
+ pos = state.bMarks[startLine] + state.tShift[startLine],
+ max = state.eMarks[startLine],
+ 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; }
+
+ // Simple check to quickly interrupt scan on [link](url) at the start of line.
+ // Can be useful on practice: https://github.com/markdown-it/markdown-it/issues/54
+ while (++pos < max) {
+ if (state.src.charCodeAt(pos) === 0x5D /* ] */ &&
+ state.src.charCodeAt(pos - 1) !== 0x5C/* \ */) {
+ if (pos + 1 === max) { return false; }
+ if (state.src.charCodeAt(pos + 1) !== 0x3A/* : */) { return false; }
+ break;
+ }
+ }
+
+ endLine = state.lineMax;
+
+ // jump line-by-line until empty one or EOF
+ terminatorRules = state.md.block.ruler.getRules('reference');
+
+ oldParentType = state.parentType;
+ state.parentType = 'reference';
+
+ 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.
+ terminate = false;
+ for (i = 0, l = terminatorRules.length; i < l; i++) {
+ if (terminatorRules[i](state, nextLine, endLine, true)) {
+ terminate = true;
+ break;
+ }
+ }
+ if (terminate) { break; }
+ }
+
+ str = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
+ max = str.length;
+
+ for (pos = 1; pos < max; pos++) {
+ ch = str.charCodeAt(pos);
+ if (ch === 0x5B /* [ */) {
+ return false;
+ } else if (ch === 0x5D /* ] */) {
+ labelEnd = pos;
+ break;
+ } else if (ch === 0x0A /* \n */) {
+ lines++;
+ } else if (ch === 0x5C /* \ */) {
+ pos++;
+ if (pos < max && str.charCodeAt(pos) === 0x0A) {
+ lines++;
+ }
+ }
+ }
+
+ if (labelEnd < 0 || str.charCodeAt(labelEnd + 1) !== 0x3A/* : */) { return false; }
+
+ // [label]: destination 'title'
+ // ^^^ skip optional whitespace here
+ for (pos = labelEnd + 2; pos < max; pos++) {
+ ch = str.charCodeAt(pos);
+ if (ch === 0x0A) {
+ lines++;
+ } else if (isSpace(ch)) {
+ /*eslint no-empty:0*/
+ } else {
+ break;
+ }
+ }
+
+ // [label]: destination 'title'
+ // ^^^^^^^^^^^ parse this
+ res = state.md.helpers.parseLinkDestination(str, pos, max);
+ if (!res.ok) { return false; }
+
+ href = state.md.normalizeLink(res.str);
+ if (!state.md.validateLink(href)) { return false; }
+
+ pos = res.pos;
+ lines += res.lines;
+
+ // save cursor state, we could require to rollback later
+ destEndPos = pos;
+ destEndLineNo = lines;
+
+ // [label]: destination 'title'
+ // ^^^ skipping those spaces
+ start = pos;
+ for (; pos < max; pos++) {
+ ch = str.charCodeAt(pos);
+ if (ch === 0x0A) {
+ lines++;
+ } else if (isSpace(ch)) {
+ /*eslint no-empty:0*/
+ } else {
+ break;
+ }
+ }
+
+ // [label]: destination 'title'
+ // ^^^^^^^ parse this
+ res = state.md.helpers.parseLinkTitle(str, pos, max);
+ if (pos < max && start !== pos && res.ok) {
+ title = res.str;
+ pos = res.pos;
+ lines += res.lines;
+ } else {
+ title = '';
+ pos = destEndPos;
+ lines = destEndLineNo;
+ }
+
+ // skip trailing spaces until the rest of the line
+ while (pos < max) {
+ 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;
+ lines = destEndLineNo;
+ while (pos < max) {
+ 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;
+ }
+
+ 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: title, href: href };
+ }
+
+ state.parentType = oldParentType;
+
+ state.line = startLine + lines + 1;
+ return true;
+};
diff --git a/node_modules/markdown-it/lib/rules_block/state_block.js b/node_modules/markdown-it/lib/rules_block/state_block.js
new file mode 100644
index 0000000..e42cb4b
--- /dev/null
+++ b/node_modules/markdown-it/lib/rules_block/state_block.js
@@ -0,0 +1,231 @@
+// Parser state class
+
+'use strict';
+
+var Token = require('../token');
+var isSpace = require('../common/utils').isSpace;
+
+
+function StateBlock(src, md, env, tokens) {
+ var ch, s, start, pos, len, indent, offset, indent_found;
+
+ 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
+ this.blkIndent = 0; // required block content indent (for example, if we are
+ // inside a list, it would be positioned after list marker)
+ 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;
+
+ // renderer
+ this.result = '';
+
+ // Create caches
+ // Generate markers.
+ s = this.src;
+ indent_found = false;
+
+ for (start = pos = indent = offset = 0, len = s.length; pos < len; pos++) {
+ 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) {
+ var 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 (var 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) {
+ var ch;
+
+ for (var max = this.src.length; pos < max; pos++) {
+ 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 (var 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) {
+ var i, lineIndent, ch, first, last, queue, lineStart,
+ line = begin;
+
+ if (begin >= end) {
+ return '';
+ }
+
+ queue = new Array(end - begin);
+
+ for (i = 0; line < end; line++, i++) {
+ lineIndent = 0;
+ lineStart = first = this.bMarks[line];
+
+ 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) {
+ 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;
+
+
+module.exports = StateBlock;
diff --git a/node_modules/markdown-it/lib/rules_block/table.js b/node_modules/markdown-it/lib/rules_block/table.js
new file mode 100644
index 0000000..7d9208f
--- /dev/null
+++ b/node_modules/markdown-it/lib/rules_block/table.js
@@ -0,0 +1,221 @@
+// GFM table, https://github.github.com/gfm/#tables-extension-
+
+'use strict';
+
+var isSpace = require('../common/utils').isSpace;
+
+
+function getLine(state, line) {
+ var pos = state.bMarks[line] + state.tShift[line],
+ max = state.eMarks[line];
+
+ return state.src.substr(pos, max - pos);
+}
+
+function escapedSplit(str) {
+ var result = [],
+ pos = 0,
+ max = str.length,
+ ch,
+ isEscaped = false,
+ lastPos = 0,
+ current = '';
+
+ ch = str.charCodeAt(pos);
+
+ 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;
+}
+
+
+module.exports = function table(state, startLine, endLine, silent) {
+ var ch, lineText, pos, i, l, nextLine, columns, columnCount, token,
+ aligns, t, tableLines, tbodyLines, oldParentType, terminate,
+ terminatorRules, firstCh, secondCh;
+
+ // should have at least two lines
+ if (startLine + 2 > endLine) { return false; }
+
+ 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
+
+ pos = state.bMarks[nextLine] + state.tShift[nextLine];
+ if (pos >= state.eMarks[nextLine]) { return false; }
+
+ firstCh = state.src.charCodeAt(pos++);
+ if (firstCh !== 0x7C/* | */ && firstCh !== 0x2D/* - */ && firstCh !== 0x3A/* : */) { return false; }
+
+ if (pos >= state.eMarks[nextLine]) { return false; }
+
+ 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]) {
+ ch = state.src.charCodeAt(pos);
+
+ if (ch !== 0x7C/* | */ && ch !== 0x2D/* - */ && ch !== 0x3A/* : */ && !isSpace(ch)) { return false; }
+
+ pos++;
+ }
+
+ lineText = getLine(state, startLine + 1);
+
+ columns = lineText.split('|');
+ aligns = [];
+ for (i = 0; i < columns.length; i++) {
+ 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)
+ columnCount = columns.length;
+ if (columnCount === 0 || columnCount !== aligns.length) { return false; }
+
+ if (silent) { return true; }
+
+ oldParentType = state.parentType;
+ state.parentType = 'table';
+
+ // use 'blockquote' lists for termination because it's
+ // the most similar to tables
+ terminatorRules = state.md.block.ruler.getRules('blockquote');
+
+ token = state.push('table_open', 'table', 1);
+ token.map = tableLines = [ startLine, 0 ];
+
+ token = state.push('thead_open', 'thead', 1);
+ token.map = [ startLine, startLine + 1 ];
+
+ token = state.push('tr_open', 'tr', 1);
+ token.map = [ startLine, startLine + 1 ];
+
+ for (i = 0; i < columns.length; i++) {
+ token = state.push('th_open', 'th', 1);
+ if (aligns[i]) {
+ token.attrs = [ [ 'style', 'text-align:' + aligns[i] ] ];
+ }
+
+ token = state.push('inline', '', 0);
+ token.content = columns[i].trim();
+ token.children = [];
+
+ token = state.push('th_close', 'th', -1);
+ }
+
+ token = state.push('tr_close', 'tr', -1);
+ token = state.push('thead_close', 'thead', -1);
+
+ for (nextLine = startLine + 2; nextLine < endLine; nextLine++) {
+ if (state.sCount[nextLine] < state.blkIndent) { break; }
+
+ terminate = false;
+ for (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();
+
+ if (nextLine === startLine + 2) {
+ token = state.push('tbody_open', 'tbody', 1);
+ token.map = tbodyLines = [ startLine + 2, 0 ];
+ }
+
+ token = state.push('tr_open', 'tr', 1);
+ token.map = [ nextLine, nextLine + 1 ];
+
+ for (i = 0; i < columnCount; i++) {
+ token = state.push('td_open', 'td', 1);
+ if (aligns[i]) {
+ token.attrs = [ [ 'style', 'text-align:' + aligns[i] ] ];
+ }
+
+ token = state.push('inline', '', 0);
+ token.content = columns[i] ? columns[i].trim() : '';
+ token.children = [];
+
+ token = state.push('td_close', 'td', -1);
+ }
+ token = state.push('tr_close', 'tr', -1);
+ }
+
+ if (tbodyLines) {
+ token = state.push('tbody_close', 'tbody', -1);
+ tbodyLines[1] = nextLine;
+ }
+
+ token = state.push('table_close', 'table', -1);
+ tableLines[1] = nextLine;
+
+ state.parentType = oldParentType;
+ state.line = nextLine;
+ return true;
+};