|
@@ -170,7 +170,8 @@ function splitCells(tableRow, count) {
|
|
|
// ensure that every cell-delimiting pipe has a space
|
|
|
// before it to distinguish it from an escaped pipe
|
|
|
const row = tableRow.replace(/\|/g, (match, offset, str) => {
|
|
|
- let escaped = false, curr = offset;
|
|
|
+ let escaped = false;
|
|
|
+ let curr = offset;
|
|
|
while (--curr >= 0 && str[curr] === '\\')
|
|
|
escaped = !escaped;
|
|
|
if (escaped) {
|
|
@@ -240,9 +241,8 @@ function findClosingBracket(str, b) {
|
|
|
if (str.indexOf(b[1]) === -1) {
|
|
|
return -1;
|
|
|
}
|
|
|
- const l = str.length;
|
|
|
- let level = 0, i = 0;
|
|
|
- for (; i < l; i++) {
|
|
|
+ let level = 0;
|
|
|
+ for (let i = 0; i < str.length; i++) {
|
|
|
if (str[i] === '\\') {
|
|
|
i++;
|
|
|
}
|
|
@@ -339,6 +339,7 @@ function indentCodeCompensation(raw, text) {
|
|
|
*/
|
|
|
class _Tokenizer {
|
|
|
options;
|
|
|
+ // TODO: Fix this rules type
|
|
|
rules;
|
|
|
lexer;
|
|
|
constructor(options) {
|
|
@@ -432,7 +433,6 @@ class _Tokenizer {
|
|
|
list(src) {
|
|
|
let cap = this.rules.block.list.exec(src);
|
|
|
if (cap) {
|
|
|
- let raw, istask, ischecked, indent, i, blankLine, endsWithBlankLine, line, nextLine, rawLine, itemContents, endEarly;
|
|
|
let bull = cap[1].trim();
|
|
|
const isordered = bull.length > 1;
|
|
|
const list = {
|
|
@@ -449,9 +449,12 @@ class _Tokenizer {
|
|
|
}
|
|
|
// Get next list item
|
|
|
const itemRegex = new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`);
|
|
|
+ let raw = '';
|
|
|
+ let itemContents = '';
|
|
|
+ let endsWithBlankLine = false;
|
|
|
// Check if current bullet point can start a new List Item
|
|
|
while (src) {
|
|
|
- endEarly = false;
|
|
|
+ let endEarly = false;
|
|
|
if (!(cap = itemRegex.exec(src))) {
|
|
|
break;
|
|
|
}
|
|
@@ -460,8 +463,9 @@ class _Tokenizer {
|
|
|
}
|
|
|
raw = cap[0];
|
|
|
src = src.substring(raw.length);
|
|
|
- line = cap[2].split('\n', 1)[0].replace(/^\t+/, (t) => ' '.repeat(3 * t.length));
|
|
|
- nextLine = src.split('\n', 1)[0];
|
|
|
+ let line = cap[2].split('\n', 1)[0].replace(/^\t+/, (t) => ' '.repeat(3 * t.length));
|
|
|
+ let nextLine = src.split('\n', 1)[0];
|
|
|
+ let indent = 0;
|
|
|
if (this.options.pedantic) {
|
|
|
indent = 2;
|
|
|
itemContents = line.trimLeft();
|
|
@@ -472,7 +476,7 @@ class _Tokenizer {
|
|
|
itemContents = line.slice(indent);
|
|
|
indent += cap[1].length;
|
|
|
}
|
|
|
- blankLine = false;
|
|
|
+ let blankLine = false;
|
|
|
if (!line && /^ *$/.test(nextLine)) { // Items begin with at most one blank line
|
|
|
raw += nextLine + '\n';
|
|
|
src = src.substring(nextLine.length + 1);
|
|
@@ -485,7 +489,7 @@ class _Tokenizer {
|
|
|
const headingBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`);
|
|
|
// Check if following lines should be included in List Item
|
|
|
while (src) {
|
|
|
- rawLine = src.split('\n', 1)[0];
|
|
|
+ const rawLine = src.split('\n', 1)[0];
|
|
|
nextLine = rawLine;
|
|
|
// Re-align to follow commonmark nesting rules
|
|
|
if (this.options.pedantic) {
|
|
@@ -547,6 +551,8 @@ class _Tokenizer {
|
|
|
endsWithBlankLine = true;
|
|
|
}
|
|
|
}
|
|
|
+ let istask = null;
|
|
|
+ let ischecked;
|
|
|
// Check for task list items
|
|
|
if (this.options.gfm) {
|
|
|
istask = /^\[[ xX]\] /.exec(itemContents);
|
|
@@ -561,7 +567,8 @@ class _Tokenizer {
|
|
|
task: !!istask,
|
|
|
checked: ischecked,
|
|
|
loose: false,
|
|
|
- text: itemContents
|
|
|
+ text: itemContents,
|
|
|
+ tokens: []
|
|
|
});
|
|
|
list.raw += raw;
|
|
|
}
|
|
@@ -569,9 +576,8 @@ class _Tokenizer {
|
|
|
list.items[list.items.length - 1].raw = raw.trimRight();
|
|
|
list.items[list.items.length - 1].text = itemContents.trimRight();
|
|
|
list.raw = list.raw.trimRight();
|
|
|
- const l = list.items.length;
|
|
|
// Item child tokens handled here at end because we needed to have the final item to trim it first
|
|
|
- for (i = 0; i < l; i++) {
|
|
|
+ for (let i = 0; i < list.items.length; i++) {
|
|
|
this.lexer.state.top = false;
|
|
|
list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []);
|
|
|
if (!list.loose) {
|
|
@@ -583,7 +589,7 @@ class _Tokenizer {
|
|
|
}
|
|
|
// Set all items to loose if list is loose
|
|
|
if (list.loose) {
|
|
|
- for (i = 0; i < l; i++) {
|
|
|
+ for (let i = 0; i < list.items.length; i++) {
|
|
|
list.items[i].loose = true;
|
|
|
}
|
|
|
}
|
|
@@ -633,7 +639,7 @@ class _Tokenizer {
|
|
|
type: 'table',
|
|
|
raw: cap[0],
|
|
|
header: splitCells(cap[1]).map(c => {
|
|
|
- return { text: c };
|
|
|
+ return { text: c, tokens: [] };
|
|
|
}),
|
|
|
align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
|
|
|
rows: cap[3] && cap[3].trim() ? cap[3].replace(/\n[ \t]*$/, '').split('\n') : []
|
|
@@ -642,23 +648,26 @@ class _Tokenizer {
|
|
|
let l = item.align.length;
|
|
|
let i, j, k, row;
|
|
|
for (i = 0; i < l; i++) {
|
|
|
- if (/^ *-+: *$/.test(item.align[i])) {
|
|
|
- item.align[i] = 'right';
|
|
|
- }
|
|
|
- else if (/^ *:-+: *$/.test(item.align[i])) {
|
|
|
- item.align[i] = 'center';
|
|
|
- }
|
|
|
- else if (/^ *:-+ *$/.test(item.align[i])) {
|
|
|
- item.align[i] = 'left';
|
|
|
- }
|
|
|
- else {
|
|
|
- item.align[i] = null;
|
|
|
+ const align = item.align[i];
|
|
|
+ if (align) {
|
|
|
+ if (/^ *-+: *$/.test(align)) {
|
|
|
+ item.align[i] = 'right';
|
|
|
+ }
|
|
|
+ else if (/^ *:-+: *$/.test(align)) {
|
|
|
+ item.align[i] = 'center';
|
|
|
+ }
|
|
|
+ else if (/^ *:-+ *$/.test(align)) {
|
|
|
+ item.align[i] = 'left';
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ item.align[i] = null;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
l = item.rows.length;
|
|
|
for (i = 0; i < l; i++) {
|
|
|
item.rows[i] = splitCells(item.rows[i], item.header.length).map(c => {
|
|
|
- return { text: c };
|
|
|
+ return { text: c, tokens: [] };
|
|
|
});
|
|
|
}
|
|
|
// parse child tokens inside headers and cells
|
|
@@ -1309,13 +1318,11 @@ function smartypants(text) {
|
|
|
* mangle email addresses
|
|
|
*/
|
|
|
function mangle(text) {
|
|
|
- let out = '', i, ch;
|
|
|
- const l = text.length;
|
|
|
- for (i = 0; i < l; i++) {
|
|
|
- ch = text.charCodeAt(i);
|
|
|
- if (Math.random() > 0.5) {
|
|
|
- ch = 'x' + ch.toString(16);
|
|
|
- }
|
|
|
+ let out = '';
|
|
|
+ for (let i = 0; i < text.length; i++) {
|
|
|
+ const ch = Math.random() > 0.5
|
|
|
+ ? 'x' + text.charCodeAt(i).toString(16)
|
|
|
+ : text.charCodeAt(i).toString();
|
|
|
out += '&#' + ch + ';';
|
|
|
}
|
|
|
return out;
|
|
@@ -1761,7 +1768,7 @@ class _Renderer {
|
|
|
this.options = options || exports.defaults;
|
|
|
}
|
|
|
code(code, infostring, escaped) {
|
|
|
- const lang = (infostring || '').match(/\S*/)[0];
|
|
|
+ const lang = (infostring || '').match(/^\S*/)?.[0];
|
|
|
if (this.options.highlight) {
|
|
|
const out = this.options.highlight(code, lang);
|
|
|
if (out != null && out !== code) {
|
|
@@ -1800,7 +1807,8 @@ class _Renderer {
|
|
|
return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
|
|
|
}
|
|
|
list(body, ordered, start) {
|
|
|
- const type = ordered ? 'ol' : 'ul', startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';
|
|
|
+ const type = ordered ? 'ol' : 'ul';
|
|
|
+ const startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';
|
|
|
return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
|
|
|
}
|
|
|
listitem(text, task, checked) {
|
|
@@ -1855,10 +1863,11 @@ class _Renderer {
|
|
|
return `<del>${text}</del>`;
|
|
|
}
|
|
|
link(href, title, text) {
|
|
|
- href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
|
|
|
- if (href === null) {
|
|
|
+ const cleanHref = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
|
|
|
+ if (cleanHref === null) {
|
|
|
return text;
|
|
|
}
|
|
|
+ href = cleanHref;
|
|
|
let out = '<a href="' + href + '"';
|
|
|
if (title) {
|
|
|
out += ' title="' + title + '"';
|
|
@@ -1867,10 +1876,11 @@ class _Renderer {
|
|
|
return out;
|
|
|
}
|
|
|
image(href, title, text) {
|
|
|
- href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
|
|
|
- if (href === null) {
|
|
|
+ const cleanHref = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
|
|
|
+ if (cleanHref === null) {
|
|
|
return text;
|
|
|
}
|
|
|
+ href = cleanHref;
|
|
|
let out = `<img src="${href}" alt="${text}"`;
|
|
|
if (title) {
|
|
|
out += ` title="${title}"`;
|
|
@@ -1998,14 +2008,14 @@ class _Parser {
|
|
|
* Parse Loop
|
|
|
*/
|
|
|
parse(tokens, top = true) {
|
|
|
- let out = '', i, j, k, l2, l3, row, cell, header, body, token, ordered, start, loose, itemBody, item, checked, task, checkbox, ret;
|
|
|
- const l = tokens.length;
|
|
|
- for (i = 0; i < l; i++) {
|
|
|
- token = tokens[i];
|
|
|
+ let out = '';
|
|
|
+ for (let i = 0; i < tokens.length; i++) {
|
|
|
+ const token = tokens[i];
|
|
|
// Run any renderer extensions
|
|
|
if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
|
|
|
- ret = this.options.extensions.renderers[token.type].call({ parser: this }, token);
|
|
|
- if (ret !== false || !['space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text'].includes(token.type)) {
|
|
|
+ const genericToken = token;
|
|
|
+ const ret = this.options.extensions.renderers[genericToken.type].call({ parser: this }, genericToken);
|
|
|
+ if (ret !== false || !['space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text'].includes(genericToken.type)) {
|
|
|
out += ret || '';
|
|
|
continue;
|
|
|
}
|
|
@@ -2019,30 +2029,30 @@ class _Parser {
|
|
|
continue;
|
|
|
}
|
|
|
case 'heading': {
|
|
|
- out += this.renderer.heading(this.parseInline(token.tokens), token.depth, unescape(this.parseInline(token.tokens, this.textRenderer)), this.slugger);
|
|
|
+ const headingToken = token;
|
|
|
+ out += this.renderer.heading(this.parseInline(headingToken.tokens), headingToken.depth, unescape(this.parseInline(headingToken.tokens, this.textRenderer)), this.slugger);
|
|
|
continue;
|
|
|
}
|
|
|
case 'code': {
|
|
|
- out += this.renderer.code(token.text, token.lang, !!token.escaped);
|
|
|
+ const codeToken = token;
|
|
|
+ out += this.renderer.code(codeToken.text, codeToken.lang, !!codeToken.escaped);
|
|
|
continue;
|
|
|
}
|
|
|
case 'table': {
|
|
|
- header = '';
|
|
|
+ const tableToken = token;
|
|
|
+ let header = '';
|
|
|
// header
|
|
|
- cell = '';
|
|
|
- l2 = token.header.length;
|
|
|
- for (j = 0; j < l2; j++) {
|
|
|
- cell += this.renderer.tablecell(this.parseInline(token.header[j].tokens), { header: true, align: token.align[j] });
|
|
|
+ let cell = '';
|
|
|
+ for (let j = 0; j < tableToken.header.length; j++) {
|
|
|
+ cell += this.renderer.tablecell(this.parseInline(tableToken.header[j].tokens), { header: true, align: tableToken.align[j] });
|
|
|
}
|
|
|
header += this.renderer.tablerow(cell);
|
|
|
- body = '';
|
|
|
- l2 = token.rows.length;
|
|
|
- for (j = 0; j < l2; j++) {
|
|
|
- row = token.rows[j];
|
|
|
+ let body = '';
|
|
|
+ for (let j = 0; j < tableToken.rows.length; j++) {
|
|
|
+ const row = tableToken.rows[j];
|
|
|
cell = '';
|
|
|
- l3 = row.length;
|
|
|
- for (k = 0; k < l3; k++) {
|
|
|
- cell += this.renderer.tablecell(this.parseInline(row[k].tokens), { header: false, align: token.align[k] });
|
|
|
+ for (let k = 0; k < row.length; k++) {
|
|
|
+ cell += this.renderer.tablecell(this.parseInline(row[k].tokens), { header: false, align: tableToken.align[k] });
|
|
|
}
|
|
|
body += this.renderer.tablerow(cell);
|
|
|
}
|
|
@@ -2050,23 +2060,24 @@ class _Parser {
|
|
|
continue;
|
|
|
}
|
|
|
case 'blockquote': {
|
|
|
- body = this.parse(token.tokens);
|
|
|
+ const blockquoteToken = token;
|
|
|
+ const body = this.parse(blockquoteToken.tokens);
|
|
|
out += this.renderer.blockquote(body);
|
|
|
continue;
|
|
|
}
|
|
|
case 'list': {
|
|
|
- ordered = token.ordered;
|
|
|
- start = token.start;
|
|
|
- loose = token.loose;
|
|
|
- l2 = token.items.length;
|
|
|
- body = '';
|
|
|
- for (j = 0; j < l2; j++) {
|
|
|
- item = token.items[j];
|
|
|
- checked = item.checked;
|
|
|
- task = item.task;
|
|
|
- itemBody = '';
|
|
|
+ const listToken = token;
|
|
|
+ const ordered = listToken.ordered;
|
|
|
+ const start = listToken.start;
|
|
|
+ const loose = listToken.loose;
|
|
|
+ let body = '';
|
|
|
+ for (let j = 0; j < listToken.items.length; j++) {
|
|
|
+ const item = listToken.items[j];
|
|
|
+ const checked = item.checked;
|
|
|
+ const task = item.task;
|
|
|
+ let itemBody = '';
|
|
|
if (item.task) {
|
|
|
- checkbox = this.renderer.checkbox(!!checked);
|
|
|
+ const checkbox = this.renderer.checkbox(!!checked);
|
|
|
if (loose) {
|
|
|
if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') {
|
|
|
item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
|
|
@@ -2092,18 +2103,21 @@ class _Parser {
|
|
|
continue;
|
|
|
}
|
|
|
case 'html': {
|
|
|
- out += this.renderer.html(token.text, token.block);
|
|
|
+ const htmlToken = token;
|
|
|
+ out += this.renderer.html(htmlToken.text, htmlToken.block);
|
|
|
continue;
|
|
|
}
|
|
|
case 'paragraph': {
|
|
|
- out += this.renderer.paragraph(this.parseInline(token.tokens));
|
|
|
+ const paragraphToken = token;
|
|
|
+ out += this.renderer.paragraph(this.parseInline(paragraphToken.tokens));
|
|
|
continue;
|
|
|
}
|
|
|
case 'text': {
|
|
|
- body = token.tokens ? this.parseInline(token.tokens) : token.text;
|
|
|
- while (i + 1 < l && tokens[i + 1].type === 'text') {
|
|
|
- token = tokens[++i];
|
|
|
- body += '\n' + (token.tokens ? this.parseInline(token.tokens) : token.text);
|
|
|
+ let textToken = token;
|
|
|
+ let body = textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text;
|
|
|
+ while (i + 1 < tokens.length && tokens[i + 1].type === 'text') {
|
|
|
+ textToken = tokens[++i];
|
|
|
+ body += '\n' + (textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text);
|
|
|
}
|
|
|
out += top ? this.renderer.paragraph(body) : body;
|
|
|
continue;
|
|
@@ -2127,13 +2141,12 @@ class _Parser {
|
|
|
*/
|
|
|
parseInline(tokens, renderer) {
|
|
|
renderer = renderer || this.renderer;
|
|
|
- let out = '', i, token, ret;
|
|
|
- const l = tokens.length;
|
|
|
- for (i = 0; i < l; i++) {
|
|
|
- token = tokens[i];
|
|
|
+ let out = '';
|
|
|
+ for (let i = 0; i < tokens.length; i++) {
|
|
|
+ const token = tokens[i];
|
|
|
// Run any renderer extensions
|
|
|
if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
|
|
|
- ret = this.options.extensions.renderers[token.type].call({ parser: this }, token);
|
|
|
+ const ret = this.options.extensions.renderers[token.type].call({ parser: this }, token);
|
|
|
if (ret !== false || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(token.type)) {
|
|
|
out += ret || '';
|
|
|
continue;
|
|
@@ -2141,31 +2154,38 @@ class _Parser {
|
|
|
}
|
|
|
switch (token.type) {
|
|
|
case 'escape': {
|
|
|
- out += renderer.text(token.text);
|
|
|
+ const escapeToken = token;
|
|
|
+ out += renderer.text(escapeToken.text);
|
|
|
break;
|
|
|
}
|
|
|
case 'html': {
|
|
|
- out += renderer.html(token.text);
|
|
|
+ const tagToken = token;
|
|
|
+ out += renderer.html(tagToken.text);
|
|
|
break;
|
|
|
}
|
|
|
case 'link': {
|
|
|
- out += renderer.link(token.href, token.title, this.parseInline(token.tokens, renderer));
|
|
|
+ const linkToken = token;
|
|
|
+ out += renderer.link(linkToken.href, linkToken.title, this.parseInline(linkToken.tokens, renderer));
|
|
|
break;
|
|
|
}
|
|
|
case 'image': {
|
|
|
- out += renderer.image(token.href, token.title, token.text);
|
|
|
+ const imageToken = token;
|
|
|
+ out += renderer.image(imageToken.href, imageToken.title, imageToken.text);
|
|
|
break;
|
|
|
}
|
|
|
case 'strong': {
|
|
|
- out += renderer.strong(this.parseInline(token.tokens, renderer));
|
|
|
+ const strongToken = token;
|
|
|
+ out += renderer.strong(this.parseInline(strongToken.tokens, renderer));
|
|
|
break;
|
|
|
}
|
|
|
case 'em': {
|
|
|
- out += renderer.em(this.parseInline(token.tokens, renderer));
|
|
|
+ const emToken = token;
|
|
|
+ out += renderer.em(this.parseInline(emToken.tokens, renderer));
|
|
|
break;
|
|
|
}
|
|
|
case 'codespan': {
|
|
|
- out += renderer.codespan(token.text);
|
|
|
+ const codespanToken = token;
|
|
|
+ out += renderer.codespan(codespanToken.text);
|
|
|
break;
|
|
|
}
|
|
|
case 'br': {
|
|
@@ -2173,11 +2193,13 @@ class _Parser {
|
|
|
break;
|
|
|
}
|
|
|
case 'del': {
|
|
|
- out += renderer.del(this.parseInline(token.tokens, renderer));
|
|
|
+ const delToken = token;
|
|
|
+ out += renderer.del(this.parseInline(delToken.tokens, renderer));
|
|
|
break;
|
|
|
}
|
|
|
case 'text': {
|
|
|
- out += renderer.text(token.text);
|
|
|
+ const textToken = token;
|
|
|
+ out += renderer.text(textToken.text);
|
|
|
break;
|
|
|
}
|
|
|
default: {
|
|
@@ -2245,10 +2267,11 @@ class Marked {
|
|
|
values = values.concat(callback.call(this, token));
|
|
|
switch (token.type) {
|
|
|
case 'table': {
|
|
|
- for (const cell of token.header) {
|
|
|
+ const tableToken = token;
|
|
|
+ for (const cell of tableToken.header) {
|
|
|
values = values.concat(this.walkTokens(cell.tokens, callback));
|
|
|
}
|
|
|
- for (const row of token.rows) {
|
|
|
+ for (const row of tableToken.rows) {
|
|
|
for (const cell of row) {
|
|
|
values = values.concat(this.walkTokens(cell.tokens, callback));
|
|
|
}
|
|
@@ -2256,18 +2279,19 @@ class Marked {
|
|
|
break;
|
|
|
}
|
|
|
case 'list': {
|
|
|
- values = values.concat(this.walkTokens(token.items, callback));
|
|
|
+ const listToken = token;
|
|
|
+ values = values.concat(this.walkTokens(listToken.items, callback));
|
|
|
break;
|
|
|
}
|
|
|
default: {
|
|
|
- if (this.defaults.extensions && this.defaults.extensions.childTokens && this.defaults.extensions.childTokens[token.type]) { // Walk any extensions
|
|
|
- this.defaults.extensions.childTokens[token.type].forEach((childTokens) => {
|
|
|
- // @ts-expect-error we assume token[childToken] is an array of tokens but we can't be sure
|
|
|
- values = values.concat(this.walkTokens(token[childTokens], callback));
|
|
|
+ const genericToken = token;
|
|
|
+ if (this.defaults.extensions?.childTokens?.[genericToken.type]) {
|
|
|
+ this.defaults.extensions.childTokens[genericToken.type].forEach((childTokens) => {
|
|
|
+ values = values.concat(this.walkTokens(genericToken[childTokens], callback));
|
|
|
});
|
|
|
}
|
|
|
- else if (token.tokens) {
|
|
|
- values = values.concat(this.walkTokens(token.tokens, callback));
|
|
|
+ else if (genericToken.tokens) {
|
|
|
+ values = values.concat(this.walkTokens(genericToken.tokens, callback));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -2307,8 +2331,9 @@ class Marked {
|
|
|
if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) {
|
|
|
throw new Error("extension level must be 'block' or 'inline'");
|
|
|
}
|
|
|
- if (extensions[ext.level]) {
|
|
|
- extensions[ext.level].unshift(ext.tokenizer);
|
|
|
+ const extLevel = extensions[ext.level];
|
|
|
+ if (extLevel) {
|
|
|
+ extLevel.unshift(ext.tokenizer);
|
|
|
}
|
|
|
else {
|
|
|
extensions[ext.level] = [ext.tokenizer];
|
|
@@ -2406,9 +2431,10 @@ class Marked {
|
|
|
// ==-- Parse WalkTokens extensions --== //
|
|
|
if (pack.walkTokens) {
|
|
|
const walkTokens = this.defaults.walkTokens;
|
|
|
+ const packWalktokens = pack.walkTokens;
|
|
|
opts.walkTokens = function (token) {
|
|
|
let values = [];
|
|
|
- values.push(pack.walkTokens.call(this, token));
|
|
|
+ values.push(packWalktokens.call(this, token));
|
|
|
if (walkTokens) {
|
|
|
values = values.concat(walkTokens.call(this, token));
|
|
|
}
|
|
@@ -2445,6 +2471,7 @@ class Marked {
|
|
|
opt.hooks.options = opt;
|
|
|
}
|
|
|
if (callback) {
|
|
|
+ const resultCallback = callback;
|
|
|
const highlight = opt.highlight;
|
|
|
let tokens;
|
|
|
try {
|
|
@@ -2475,7 +2502,7 @@ class Marked {
|
|
|
opt.highlight = highlight;
|
|
|
return err
|
|
|
? throwError(err)
|
|
|
- : callback(null, out);
|
|
|
+ : resultCallback(null, out);
|
|
|
};
|
|
|
if (!highlight || highlight.length < 3) {
|
|
|
return done();
|