mirror of
https://github.com/fooflington/selfdefined.git
synced 2025-08-06 04:28:34 +00:00
update
This commit is contained in:
285
node_modules/markdown-it/lib/rules_block/blockquote.js
generated
vendored
Normal file
285
node_modules/markdown-it/lib/rules_block/blockquote.js
generated
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
// 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,
|
||||
wasOutdented,
|
||||
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; }
|
||||
|
||||
// skip spaces after ">" and re-calculate offset
|
||||
initial = offset = state.sCount[startLine] + pos - (state.bMarks[startLine] + state.tShift[startLine]);
|
||||
|
||||
// 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';
|
||||
wasOutdented = false;
|
||||
|
||||
// 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
|
||||
// ```
|
||||
if (state.sCount[nextLine] < state.blkIndent) wasOutdented = true;
|
||||
|
||||
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/* > */ && !wasOutdented) {
|
||||
// This line is inside the blockquote.
|
||||
|
||||
// skip spaces after ">" and re-calculate offset
|
||||
initial = offset = state.sCount[nextLine] + pos - (state.bMarks[nextLine] + state.tShift[nextLine]);
|
||||
|
||||
// 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;
|
||||
};
|
34
node_modules/markdown-it/lib/rules_block/code.js
generated
vendored
Normal file
34
node_modules/markdown-it/lib/rules_block/code.js
generated
vendored
Normal file
@@ -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, true);
|
||||
token.map = [ startLine, state.line ];
|
||||
|
||||
return true;
|
||||
};
|
94
node_modules/markdown-it/lib/rules_block/fence.js
generated
vendored
Normal file
94
node_modules/markdown-it/lib/rules_block/fence.js
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
// 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 (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;
|
||||
};
|
55
node_modules/markdown-it/lib/rules_block/heading.js
generated
vendored
Normal file
55
node_modules/markdown-it/lib/rules_block/heading.js
generated
vendored
Normal file
@@ -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;
|
||||
};
|
45
node_modules/markdown-it/lib/rules_block/hr.js
generated
vendored
Normal file
45
node_modules/markdown-it/lib/rules_block/hr.js
generated
vendored
Normal file
@@ -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;
|
||||
};
|
74
node_modules/markdown-it/lib/rules_block/html_block.js
generated
vendored
Normal file
74
node_modules/markdown-it/lib/rules_block/html_block.js
generated
vendored
Normal file
@@ -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)(?=(\s|>|$))/i, /<\/(script|pre|style)>/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;
|
||||
};
|
83
node_modules/markdown-it/lib/rules_block/lheading.js
generated
vendored
Normal file
83
node_modules/markdown-it/lib/rules_block/lheading.js
generated
vendored
Normal file
@@ -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;
|
||||
};
|
336
node_modules/markdown-it/lib/rules_block/list.js
generated
vendored
Normal file
336
node_modules/markdown-it/lib/rules_block/list.js
generated
vendored
Normal file
@@ -0,0 +1,336 @@
|
||||
// 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,
|
||||
oldIndent,
|
||||
oldLIndent,
|
||||
oldParentType,
|
||||
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; }
|
||||
|
||||
// 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.tShift[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.substr(start, posAfterMarker - start - 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 ];
|
||||
|
||||
oldIndent = state.blkIndent;
|
||||
oldTight = state.tight;
|
||||
oldTShift = state.tShift[startLine];
|
||||
oldLIndent = state.sCount[startLine];
|
||||
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 = oldIndent;
|
||||
state.tShift[startLine] = oldTShift;
|
||||
state.sCount[startLine] = oldLIndent;
|
||||
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; }
|
||||
|
||||
// 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; }
|
||||
} 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;
|
||||
};
|
52
node_modules/markdown-it/lib/rules_block/paragraph.js
generated
vendored
Normal file
52
node_modules/markdown-it/lib/rules_block/paragraph.js
generated
vendored
Normal file
@@ -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;
|
||||
};
|
198
node_modules/markdown-it/lib/rules_block/reference.js
generated
vendored
Normal file
198
node_modules/markdown-it/lib/rules_block/reference.js
generated
vendored
Normal file
@@ -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;
|
||||
};
|
230
node_modules/markdown-it/lib/rules_block/state_block.js
generated
vendored
Normal file
230
node_modules/markdown-it/lib/rules_block/state_block.js
generated
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
// 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 in list)
|
||||
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)
|
||||
|
||||
// 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--; }
|
||||
token.level = this.level;
|
||||
if (nesting > 0) { this.level++; }
|
||||
|
||||
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;
|
196
node_modules/markdown-it/lib/rules_block/table.js
generated
vendored
Normal file
196
node_modules/markdown-it/lib/rules_block/table.js
generated
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
// GFM table, non-standard
|
||||
|
||||
'use strict';
|
||||
|
||||
var isSpace = require('../common/utils').isSpace;
|
||||
|
||||
|
||||
function getLine(state, line) {
|
||||
var pos = state.bMarks[line] + state.blkIndent,
|
||||
max = state.eMarks[line];
|
||||
|
||||
return state.src.substr(pos, max - pos);
|
||||
}
|
||||
|
||||
function escapedSplit(str) {
|
||||
var result = [],
|
||||
pos = 0,
|
||||
max = str.length,
|
||||
ch,
|
||||
escapes = 0,
|
||||
lastPos = 0,
|
||||
backTicked = false,
|
||||
lastBackTick = 0;
|
||||
|
||||
ch = str.charCodeAt(pos);
|
||||
|
||||
while (pos < max) {
|
||||
if (ch === 0x60/* ` */) {
|
||||
if (backTicked) {
|
||||
// make \` close code sequence, but not open it;
|
||||
// the reason is: `\` is correct code block
|
||||
backTicked = false;
|
||||
lastBackTick = pos;
|
||||
} else if (escapes % 2 === 0) {
|
||||
backTicked = true;
|
||||
lastBackTick = pos;
|
||||
}
|
||||
} else if (ch === 0x7c/* | */ && (escapes % 2 === 0) && !backTicked) {
|
||||
result.push(str.substring(lastPos, pos));
|
||||
lastPos = pos + 1;
|
||||
}
|
||||
|
||||
if (ch === 0x5c/* \ */) {
|
||||
escapes++;
|
||||
} else {
|
||||
escapes = 0;
|
||||
}
|
||||
|
||||
pos++;
|
||||
|
||||
// If there was an un-closed backtick, go back to just after
|
||||
// the last backtick, but as if it was a normal character
|
||||
if (pos === max && backTicked) {
|
||||
backTicked = false;
|
||||
pos = lastBackTick + 1;
|
||||
}
|
||||
|
||||
ch = str.charCodeAt(pos);
|
||||
}
|
||||
|
||||
result.push(str.substring(lastPos));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
module.exports = function table(state, startLine, endLine, silent) {
|
||||
var ch, lineText, pos, i, nextLine, columns, columnCount, token,
|
||||
aligns, t, tableLines, tbodyLines;
|
||||
|
||||
// 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; }
|
||||
|
||||
ch = state.src.charCodeAt(pos++);
|
||||
if (ch !== 0x7C/* | */ && ch !== 0x2D/* - */ && ch !== 0x3A/* : */) { 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.replace(/^\||\|$/g, ''));
|
||||
|
||||
// header row will define an amount of columns in the entire table,
|
||||
// and align row shouldn't be smaller than that (the rest of the rows can)
|
||||
columnCount = columns.length;
|
||||
if (columnCount > aligns.length) { return false; }
|
||||
|
||||
if (silent) { return true; }
|
||||
|
||||
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);
|
||||
token.map = [ startLine, startLine + 1 ];
|
||||
if (aligns[i]) {
|
||||
token.attrs = [ [ 'style', 'text-align:' + aligns[i] ] ];
|
||||
}
|
||||
|
||||
token = state.push('inline', '', 0);
|
||||
token.content = columns[i].trim();
|
||||
token.map = [ startLine, startLine + 1 ];
|
||||
token.children = [];
|
||||
|
||||
token = state.push('th_close', 'th', -1);
|
||||
}
|
||||
|
||||
token = state.push('tr_close', 'tr', -1);
|
||||
token = state.push('thead_close', 'thead', -1);
|
||||
|
||||
token = state.push('tbody_open', 'tbody', 1);
|
||||
token.map = tbodyLines = [ startLine + 2, 0 ];
|
||||
|
||||
for (nextLine = startLine + 2; nextLine < endLine; nextLine++) {
|
||||
if (state.sCount[nextLine] < state.blkIndent) { break; }
|
||||
|
||||
lineText = getLine(state, nextLine).trim();
|
||||
if (lineText.indexOf('|') === -1) { break; }
|
||||
if (state.sCount[nextLine] - state.blkIndent >= 4) { break; }
|
||||
columns = escapedSplit(lineText.replace(/^\||\|$/g, ''));
|
||||
|
||||
token = state.push('tr_open', 'tr', 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);
|
||||
}
|
||||
token = state.push('tbody_close', 'tbody', -1);
|
||||
token = state.push('table_close', 'table', -1);
|
||||
|
||||
tableLines[1] = tbodyLines[1] = nextLine;
|
||||
state.line = nextLine;
|
||||
return true;
|
||||
};
|
Reference in New Issue
Block a user