// Tweaked from https://github.com/developit/snarkdown
const markup = (() => {
const TAGS = {
'' : ['',''],
_ : ['',''],
'~' : ['',''],
'\n' : ['
'],
' ' : ['
'],
'-': ['
']
};
const outdent = str =>
str.replace(RegExp('^'+(str.match(/^(\t| )+/) || '')[0], 'gm'), '');
const encodeAttr = str =>
(str+'').replace(/"/g, '"').replace(//g, '>');
return (md, prevLinks) => {
let tokenizer = new RegExp(
"((?:^|\\n+)(?:\\n---+|\\* \\*(?: \\*)+)\\n)|" +
"(?:^``` *(\\w*)\\n([\\s\\S]*?)\\n```$)|" +
"((?:(?:^|\\n+)(?:\\t| {2,}).+)+\\n*)|" +
"((?:(?:^|\\n)([>*+-]|\\d+\\.)\\s+.*)+)|" +
"(?:\\!\\[([^\\]]*?)\\]\\(([^\\)]+?)\\))|" +
"(\\[)|" + "(\\](?:\\(([^\\)]+?)\\))?)|" +
"(?:(?:^|\\n+)([^\\s].*)\\n(\\-{3,}|={3,})(?:\\n+|$))|" +
"(?:(?:^|\\n+)(#{1,6})\\s*(.+)(?:\\n+|$))|" +
"(?:`([^`].*?)`)|( \\n\\n*|\\n{2,}|__|\\*\\*|[_*]|~~)", "gm"),
context = [],
out = '',
links = prevLinks || {},
last = 0,
chunk, prev, token, inner, t;
function tag(token) {
const desc = TAGS[token.replace(/\*/g,'_')[1] || ''],
end = context[context.length-1]==token;
if (!desc) return token;
if (!desc[1]) return desc[0];
context[end?'pop':'push'](token);
return desc[end|0];
}
function flush() {
let str = '';
while (context.length) str += tag(context[context.length-1]);
return str;
}
md = md.replace(/^\[(.+?)\]:\s*(.+)$/gm, (s, name, url) => {
links[name.toLowerCase()] = url;
return '';
}).replace(/^\n+|\n+$/g, '');
while ((token = tokenizer.exec(md))) {
prev = md.substring(last, token.index);
last = tokenizer.lastIndex;
chunk = token[0];
if (prev.match(/[^\\](\\\\)*\\$/)) {
// escaped
}
// Code/Indent blocks:
else if (token[3] || token[4]) {
chunk = ''+
outdent(encodeAttr(token[3] || token[4]).replace(/^\n+|\n+$/g, ''))+'
';
}
// > Quotes, -* lists:
else if (token[6]) {
t = token[6];
if (t.match(/\./)) {
token[5] = token[5].replace(/^\d+/gm, '');
}
inner = parse(outdent(token[5].replace(/^\s*[>*+.-]/gm, '')));
if (t==='>') t = 'blockquote';
else {
t = t.match(/\./) ? 'ol' : 'ul';
inner = inner.replace(/^(.*)(\n|$)/gm, '$1');
}
chunk = '<'+t+'>' + inner + ''+t+'>';
}
// Images:
else if (token[8]) {
chunk = ``;
}
// Links:
else if (token[10]) {
out = out.replace('', ``);
chunk = flush() + '';
}
else if (token[9]) {
chunk = '';
}
// Headings:
else if (token[12] || token[14]) {
t = 'h' + (token[14] ? token[14].length : (token[13][0]==='='?1:2));
chunk = '<'+t+'>' + parse(token[12] || token[15], links) + ''+t+'>';
}
// `code`:
else if (token[16]) {
chunk = ''+encodeAttr(token[16])+'
';
}
// Inline formatting: *em*, **strong** & friends
else if (token[17] || token[1]) {
chunk = tag(token[17] || '--');
}
out += prev;
out += chunk;
}
return "" + (out + md.substring(last) + flush()).trim() + "
";
};
})();