From 160ef3415d0d54b9d881efbf161ac5eb9f5714f9 Mon Sep 17 00:00:00 2001 From: estrattonbailey Date: Sat, 8 Jul 2017 11:10:32 -0400 Subject: [PATCH] Move higlight to global scope. Don't assign lang to save bytes --- src/index.js | 170 ++++++++++++++++++++++++++------------------------- 1 file changed, 87 insertions(+), 83 deletions(-) diff --git a/src/index.js b/src/index.js index 5bce355..4cfebb8 100644 --- a/src/index.js +++ b/src/index.js @@ -6,6 +6,11 @@ const TAGS = { '-': ['
'] }; +/** + * Optional, skips entity encoding + */ +let highlight = false + /** Outdent a string based on the first indented line's leading whitespace * @private */ @@ -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 = '
'+outdent(
-					highlight ? highlight(token[3] || token[4], lang) : 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 + ''; - } - // Images: - else if (token[8]) { - chunk = `${encodeAttr(token[7])}`; - } - // 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) + ''; - } - // `code`: - else if (token[16]) { - chunk = ''+encodeAttr(token[16])+''; + // Code/Indent blocks: + else if (token[3] || token[4]) { + chunk = '
    '+outdent(
    +				highlight ? highlight(token[3] || token[4], (token[4]?'poetry':token[2].toLowerCase())) : 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, ''); } - // 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, '
  • $1
  • '); } - out += prev; - out += chunk; + chunk = '<'+t+'>' + inner + ''; } - - return (out + md.substring(last) + flush()).trim(); + // Images: + else if (token[8]) { + chunk = `${encodeAttr(token[7])}`; + } + // 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) + ''; + } + // `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(); +} + +export default function snarkdown(md, opt) { + opt = opt || {}; + highlight = opt.highlight; + return parse(md); }