Skip to content

Commit

Permalink
Move higlight to global scope. Don't assign lang to save bytes
Browse files Browse the repository at this point in the history
  • Loading branch information
estrattonbailey committed Jul 8, 2017
1 parent 6fe6fc4 commit 160ef34
Showing 1 changed file with 87 additions and 83 deletions.
170 changes: 87 additions & 83 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ const TAGS = {
'-': ['<hr />']
};

/**
* Optional, skips entity encoding
*/
let highlight = false

/** Outdent a string based on the first indented line's leading whitespace
* @private
*/
Expand All @@ -21,96 +26,95 @@ function encodeAttr(str) {
}

/** Parse Markdown into an HTML String. */
export default function snarkdown(md, options = {}) {
const highlight = options.highlight;
function parse(md, prevLinks) {
let tokenizer = /((?:^|\n+)(?:\n---+|\* \*(?: \*)+)\n)|(?:^```(\w*)\n([\s\S]*?)\n```$)|((?:(?:^|\n+)(?:\t| {2,}).+)+\n*)|((?:(?:^|\n)([>*+-]|\d+\.)\s+.*)+)|(?:\!\[([^\]]*?)\]\(([^\)]+?)\))|(\[)|(\](?:\(([^\)]+?)\))?)|(?:(?:^|\n+)([^\s].*)\n(\-{3,}|={3,})(?:\n+|$))|(?:(?:^|\n+)(#{1,3})\s*(.+)(?:\n+|$))|(?:`([^`].*?)`)|( \n\n*|\n{2,}|__|\*\*|[_*])/gm,
context = [],
out = '',
links = prevLinks || {},
last = 0,
chunk, prev, token, inner, t;

return parse(md);
function tag(token) {
var 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 parse(md, prevLinks) {
let tokenizer = /((?:^|\n+)(?:\n---+|\* \*(?: \*)+)\n)|(?:^```(\w*)\n([\s\S]*?)\n```$)|((?:(?:^|\n+)(?:\t| {2,}).+)+\n*)|((?:(?:^|\n)([>*+-]|\d+\.)\s+.*)+)|(?:\!\[([^\]]*?)\]\(([^\)]+?)\))|(\[)|(\](?:\(([^\)]+?)\))?)|(?:(?:^|\n+)([^\s].*)\n(\-{3,}|={3,})(?:\n+|$))|(?:(?:^|\n+)(#{1,3})\s*(.+)(?:\n+|$))|(?:`([^`].*?)`)|( \n\n*|\n{2,}|__|\*\*|[_*])/gm,
context = [],
out = '',
links = prevLinks || {},
last = 0,
chunk, prev, token, inner, t;
function flush() {
let str = '';
while (context.length) str += tag(context[context.length-1]);
return str;
}

function tag(token) {
var 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];
}
md = md.replace(/^\[(.+?)\]:\s*(.+)$/gm, (s, name, url) => {
links[name.toLowerCase()] = url;
return '';
}).replace(/^\n+|\n+$/g, '');

function flush() {
let str = '';
while (context.length) str += tag(context[context.length-1]);
return str;
while ( (token=tokenizer.exec(md)) ) {
prev = md.substring(last, token.index);
last = tokenizer.lastIndex;
chunk = token[0];
if (prev.match(/[^\\](\\\\)*\\$/)) {
// escaped
}

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]) {
const lang = token[4]?'poetry':token[2].toLowerCase();
chunk = '<pre class="code '+lang+'">'+outdent(
highlight ? highlight(token[3] || token[4], lang) : encodeAttr(token[3] || token[4])
).replace(/^\n+|\n+$/g, '')+'</pre>';
}
// > 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, '<li>$1</li>');
}
chunk = '<'+t+'>' + inner + '</'+t+'>';
}
// Images:
else if (token[8]) {
chunk = `<img src="${encodeAttr(token[8])}" alt="${encodeAttr(token[7])}">`;
}
// Links:
else if (token[10]) {
out = out.replace('<a>', `<a href="${encodeAttr(token[11] || links[prev.toLowerCase()])}">`);
chunk = flush() + '</a>';
}
else if (token[9]) {
chunk = '<a>';
}
// 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 = '<code>'+encodeAttr(token[16])+'</code>';
// Code/Indent blocks:
else if (token[3] || token[4]) {
chunk = '<pre class="code '+(token[4]?'poetry':token[2].toLowerCase())+'">'+outdent(
highlight ? highlight(token[3] || token[4], (token[4]?'poetry':token[2].toLowerCase())) : encodeAttr(token[3] || token[4])
).replace(/^\n+|\n+$/g, '')+'</pre>';
}
// > Quotes, -* lists:
else if (token[6]) {
t = token[6];
if (t.match(/\./)) {
token[5] = token[5].replace(/^\d+/gm, '');
}
// Inline formatting: *em*, **strong** & friends
else if (token[17] || token[1]) {
chunk = tag(token[17] || '--');
inner = parse(outdent(token[5].replace(/^\s*[>*+.-]/gm, '')));
if (t==='>') t = 'blockquote';
else {
t = t.match(/\./) ? 'ol' : 'ul';
inner = inner.replace(/^(.*)(\n|$)/gm, '<li>$1</li>');
}
out += prev;
out += chunk;
chunk = '<'+t+'>' + inner + '</'+t+'>';
}

return (out + md.substring(last) + flush()).trim();
// Images:
else if (token[8]) {
chunk = `<img src="${encodeAttr(token[8])}" alt="${encodeAttr(token[7])}">`;
}
// Links:
else if (token[10]) {
out = out.replace('<a>', `<a href="${encodeAttr(token[11] || links[prev.toLowerCase()])}">`);
chunk = flush() + '</a>';
}
else if (token[9]) {
chunk = '<a>';
}
// 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 = '<code>'+encodeAttr(token[16])+'</code>';
}
// 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();
}

export default function snarkdown(md, opt) {
opt = opt || {};
highlight = opt.highlight;
return parse(md);
}

0 comments on commit 160ef34

Please sign in to comment.