'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _syntheticDom = require('synthetic-dom'); var hasOwnProperty = Object.prototype.hasOwnProperty; var assign = Object.assign || function (obj) { var i = 1; for (; i < arguments.length; i++) { var target = arguments[i]; for (var key in target) { if (hasOwnProperty.call(target, key)) { obj[key] = target[key]; } } } return obj; }; var noop = function noop() {}; noop.exec = noop; var defaults = { gfm: true, breaks: false, pedantic: false, smartLists: false, silent: false, langPrefix: 'lang-', renderer: new Renderer(), xhtml: false }; var block = { newline: /^\n+/, code: /^( {4}[^\n]+\n*)+/, fences: noop, hr: /^( *[-*_]){3,} *(?:\n+|$)/, heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, nptable: noop, lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/, list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, def: /^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|def))+)\n*/, text: /^[^\n]+/ }; block.bullet = /(?:[*+-]|\d+\.)/; block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/; block.item = replace(block.item, 'gm')(/bull/g, block.bullet)(); block.list = replace(block.list)(/bull/g, block.bullet)('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')('def', '\\n+(?=' + block.def.source + ')')(); block.blockquote = replace(block.blockquote)('def', block.def)(); block.paragraph = replace(block.paragraph)('hr', block.hr)('heading', block.heading)('lheading', block.lheading)('blockquote', block.blockquote)('def', block.def)(); block.normal = assign({}, block); block.gfm = assign({}, block.normal, { fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/, paragraph: /^/, heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/ }); block.gfm.paragraph = replace(block.paragraph)('(?!', '(?!' + block.gfm.fences.source.replace('\\1', '\\2') + '|' + block.list.source.replace('\\1', '\\3') + '|')(); function Lexer(options) { this.tokens = []; this.tokens.links = {}; this.options = assign({}, options || defaults); this.rules = block.normal; if (this.options.gfm) { this.rules = block.gfm; } } Lexer.rules = block; Lexer.parse = function (src, options) { var lexer = new Lexer(options); return lexer.parse(src); }; Lexer.prototype.parse = function (src) { src = src.replace(/\r\n|\r/g, '\n').replace(/\t/g, ' ').replace(/\u00a0/g, ' ').replace(/\u2424/g, '\n'); return this.token(src, true); }; Lexer.prototype.token = function (src, top, bq) { var next; var loose; var cap; var bull; var b; var item; var space; var i; var l; src = src.replace(/^ +$/gm, ''); while (src) { if (cap = this.rules.newline.exec(src)) { src = src.substring(cap[0].length); if (cap[0].length > 1) { this.tokens.push({ type: 'space' }); } } if (cap = this.rules.code.exec(src)) { src = src.substring(cap[0].length); cap = cap[0].replace(/^ {4}/gm, ''); this.tokens.push({ type: 'code', text: !this.options.pedantic ? cap.replace(/\n+$/, '') : cap }); continue; } if (cap = this.rules.fences.exec(src)) { src = src.substring(cap[0].length); this.tokens.push({ type: 'code', lang: cap[2], text: cap[3] }); continue; } if (cap = this.rules.heading.exec(src)) { src = src.substring(cap[0].length); this.tokens.push({ type: 'heading', depth: cap[1].length, text: cap[2] }); continue; } if (cap = this.rules.lheading.exec(src)) { src = src.substring(cap[0].length); this.tokens.push({ type: 'heading', depth: cap[2] === '=' ? 1 : 2, text: cap[1] }); continue; } if (cap = this.rules.hr.exec(src)) { src = src.substring(cap[0].length); this.tokens.push({ type: 'hr' }); continue; } if (cap = this.rules.blockquote.exec(src)) { src = src.substring(cap[0].length); this.tokens.push({ type: 'blockquote_start' }); cap = cap[0].replace(/^ *> ?/gm, ''); this.token(cap, top, true); this.tokens.push({ type: 'blockquote_end' }); continue; } if (cap = this.rules.list.exec(src)) { src = src.substring(cap[0].length); bull = cap[2]; this.tokens.push({ type: 'list_start', ordered: bull.length > 1 }); cap = cap[0].match(this.rules.item); next = false; l = cap.length; i = 0; for (; i < l; i++) { item = cap[i]; space = item.length; item = item.replace(/^ *([*+-]|\d+\.) +/, ''); if (~item.indexOf('\n ')) { space -= item.length; item = !this.options.pedantic ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') : item.replace(/^ {1,4}/gm, ''); } if (this.options.smartLists && i !== l - 1) { b = block.bullet.exec(cap[i + 1])[0]; if (bull !== b && !(bull.length > 1 && b.length > 1)) { src = cap.slice(i + 1).join('\n') + src; i = l - 1; } } loose = next || /\n\n(?!\s*$)/.test(item); if (i !== l - 1) { next = item.charAt(item.length - 1) === '\n'; if (!loose) { loose = next; } } this.tokens.push({ type: loose ? 'loose_item_start' : 'list_item_start' }); this.token(item, false, bq); this.tokens.push({ type: 'list_item_end' }); } this.tokens.push({ type: 'list_end' }); continue; } if (!bq && top && (cap = this.rules.def.exec(src))) { src = src.substring(cap[0].length); this.tokens.links[cap[1].toLowerCase()] = { href: cap[2], title: cap[3] }; continue; } if (top && (cap = this.rules.paragraph.exec(src))) { src = src.substring(cap[0].length); this.tokens.push({ type: 'paragraph', text: cap[1].charAt(cap[1].length - 1) === '\n' ? cap[1].slice(0, -1) : cap[1] }); continue; } if (cap = this.rules.text.exec(src)) { src = src.substring(cap[0].length); this.tokens.push({ type: 'text', text: cap[0] }); continue; } if (src) { throw new Error('Infinite loop on byte: ' + src.charCodeAt(0)); } } return this.tokens; }; var inline = { escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, link: /^!?\[(inside)\]\(href\)/, reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/, strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/, br: /^ {2,}\n(?!\s*$)/, del: noop, ins: noop, text: /^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/; inline.link = replace(inline.link)('inside', inline._inside)('href', inline._href)(); inline.reflink = replace(inline.reflink)('inside', inline._inside)(); inline.normal = assign({}, inline); inline.pedantic = assign({}, inline.normal, { strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/ }); inline.gfm = assign({}, inline.normal, { escape: replace(inline.escape)('])', '~|])')(), del: /^~~(?=\S)([\s\S]*?\S)~~/, ins: /^\+\+(?=\S)([\s\S]*?\S)\+\+/, text: replace(inline.text)(']|', '~+]|')() }); inline.breaks = assign({}, inline.gfm, { br: replace(inline.br)('{2,}', '*')(), text: replace(inline.gfm.text)('{2,}', '*')() }); function InlineLexer(links, options) { this.options = assign({}, options || defaults); this.links = links; this.rules = inline.normal; this.renderer = this.options.renderer || new Renderer(); this.renderer.options = this.options; if (!this.links) { throw new Error('Tokens array requires a `links` property.'); } if (this.options.gfm) { if (this.options.breaks) { this.rules = inline.breaks; } else { this.rules = inline.gfm; } } else if (this.options.pedantic) { this.rules = inline.pedantic; } } InlineLexer.rules = inline; InlineLexer.parse = function (src, links, options) { var inline = new InlineLexer(links, options); return inline.parse(src); }; InlineLexer.prototype.parse = function (src) { var out = new _syntheticDom.FragmentNode(); var link; var cap; while (src) { if (cap = this.rules.escape.exec(src)) { src = src.substring(cap[0].length); out.appendChild(new _syntheticDom.TextNode(cap[1])); continue; } if (cap = this.rules.link.exec(src)) { src = src.substring(cap[0].length); this.inLink = true; out.appendChild(this.outputLink(cap, { href: cap[2], title: cap[3] })); this.inLink = false; continue; } if ((cap = this.rules.reflink.exec(src)) || (cap = this.rules.nolink.exec(src))) { src = src.substring(cap[0].length); link = (cap[2] || cap[1]).replace(/\s+/g, ' '); link = this.links[link.toLowerCase()]; if (!link || !link.href) { out.appendChild(new _syntheticDom.TextNode(cap[0].charAt(0))); src = cap[0].substring(1) + src; continue; } this.inLink = true; out.appendChild(this.outputLink(cap, link)); this.inLink = false; continue; } if (cap = this.rules.strong.exec(src)) { src = src.substring(cap[0].length); out.appendChild(this.renderer.strong(this.parse(cap[2] || cap[1]))); continue; } if (cap = this.rules.em.exec(src)) { src = src.substring(cap[0].length); out.appendChild(this.renderer.em(this.parse(cap[2] || cap[1]))); continue; } if (cap = this.rules.code.exec(src)) { src = src.substring(cap[0].length); out.appendChild(this.renderer.codespan(cap[2])); continue; } if (cap = this.rules.br.exec(src)) { src = src.substring(cap[0].length); out.appendChild(this.renderer.br()); continue; } if (cap = this.rules.del.exec(src)) { src = src.substring(cap[0].length); out.appendChild(this.renderer.del(this.parse(cap[1]))); continue; } if (cap = this.rules.ins.exec(src)) { src = src.substring(cap[0].length); out.appendChild(this.renderer.ins(this.parse(cap[1]))); continue; } if (cap = this.rules.text.exec(src)) { src = src.substring(cap[0].length); out.appendChild(this.renderer.text(new _syntheticDom.TextNode(cap[0]))); continue; } if (src) { throw new Error('Infinite loop on byte: ' + src.charCodeAt(0)); } } return out; }; InlineLexer.prototype.outputLink = function (cap, link) { var href = link.href; var title = link.title; return cap[0].charAt(0) !== '!' ? this.renderer.link(href, title, this.parse(cap[1])) : this.renderer.image(href, title, cap[1]); }; function Renderer(options) { this.options = options || {}; } Renderer.prototype.code = function (childNode, lang) { var attributes = []; if (lang) { attributes.push(['class', this.options.langPrefix + lang]); } var codeNode = new _syntheticDom.ElementNode('code', attributes, [childNode]); return new _syntheticDom.ElementNode('pre', [], [codeNode]); }; Renderer.prototype.blockquote = function (childNode) { return new _syntheticDom.ElementNode('blockquote', [], [childNode]); }; Renderer.prototype.heading = function (childNode, level) { return new _syntheticDom.ElementNode('h' + level, [], [childNode]); }; Renderer.prototype.hr = function () { return new _syntheticDom.ElementNode('hr', [], _syntheticDom.SELF_CLOSING); }; Renderer.prototype.list = function (childNode, isOrdered) { return new _syntheticDom.ElementNode(isOrdered ? 'ol' : 'ul', [], [childNode]); }; Renderer.prototype.listitem = function (childNode) { return new _syntheticDom.ElementNode('li', [], [childNode]); }; Renderer.prototype.paragraph = function (childNode) { return new _syntheticDom.ElementNode('p', [], [childNode]); }; Renderer.prototype.strong = function (childNode) { return new _syntheticDom.ElementNode('strong', [], [childNode]); }; Renderer.prototype.em = function (childNode) { return new _syntheticDom.ElementNode('em', [], [childNode]); }; Renderer.prototype.codespan = function (text) { return new _syntheticDom.ElementNode('code', [], [new _syntheticDom.TextNode(text)]); }; Renderer.prototype.br = function () { return new _syntheticDom.ElementNode('br', [], _syntheticDom.SELF_CLOSING); }; Renderer.prototype.del = function (childNode) { return new _syntheticDom.ElementNode('del', [], [childNode]); }; Renderer.prototype.ins = function (childNode) { return new _syntheticDom.ElementNode('ins', [], [childNode]); }; Renderer.prototype.link = function (href, title, childNode) { var attributes = [['href', href]]; if (title) { attributes.push(['title', title]); } return new _syntheticDom.ElementNode('a', attributes, [childNode]); }; Renderer.prototype.image = function (href, title, alt) { var attributes = [['src', href]]; if (title) { attributes.push(['title', title]); } if (alt) { attributes.push(['alt', alt]); } return new _syntheticDom.ElementNode('img', attributes, _syntheticDom.SELF_CLOSING); }; Renderer.prototype.text = function (childNode) { return childNode; }; function Parser(options) { this.tokens = []; this.token = null; this.options = assign({}, options || defaults); this.options.renderer = this.options.renderer || new Renderer(); this.renderer = this.options.renderer; this.renderer.options = this.options; } Parser.parse = function (src, options, renderer) { var parser = new Parser(options, renderer); return parser.parse(src); }; Parser.prototype.parse = function (src) { this.inline = new InlineLexer(src.links, this.options, this.renderer); this.tokens = src.slice().reverse(); var out = new _syntheticDom.FragmentNode(); while (this.next()) { out.appendChild(this.tok()); } return out; }; Parser.prototype.next = function () { return this.token = this.tokens.pop(); }; Parser.prototype.peek = function () { return this.tokens[this.tokens.length - 1] || 0; }; Parser.prototype.parseText = function () { var body = this.token.text; while (this.peek().type === 'text') { body += '\n' + this.next().text; } return this.inline.parse(body); }; Parser.prototype.tok = function () { switch (this.token.type) { case 'space': { return new _syntheticDom.TextNode(''); } case 'hr': { return this.renderer.hr(); } case 'heading': { return this.renderer.heading(this.inline.parse(this.token.text), this.token.depth); } case 'code': { return this.renderer.code(this.token.text, this.token.lang); } case 'blockquote_start': { var body = new _syntheticDom.FragmentNode(); while (this.next().type !== 'blockquote_end') { body.appendChild(this.tok()); } return this.renderer.blockquote(body); } case 'list_start': { var _body = new _syntheticDom.FragmentNode(); var ordered = this.token.ordered; while (this.next().type !== 'list_end') { _body.appendChild(this.tok()); } return this.renderer.list(_body, ordered); } case 'list_item_start': { var _body2 = new _syntheticDom.FragmentNode(); while (this.next().type !== 'list_item_end') { _body2.appendChild(this.token.type === 'text' ? this.parseText() : this.tok()); } return this.renderer.listitem(_body2); } case 'loose_item_start': { var _body3 = new _syntheticDom.FragmentNode(); while (this.next().type !== 'list_item_end') { _body3.appendChild(this.tok()); } return this.renderer.listitem(_body3); } case 'paragraph': { return this.renderer.paragraph(this.inline.parse(this.token.text)); } case 'text': { return this.renderer.paragraph(this.parseText()); } } }; function replace(regex, options) { regex = regex.source; options = options || ''; return function self(name, val) { if (!name) { return new RegExp(regex, options); } val = val.source || val; val = val.replace(/(^|[^\[])\^/g, '$1'); regex = regex.replace(name, val); return self; }; } var MarkdownParser = { parse: function parse(src, options) { options = assign({}, defaults, options); try { var fragment = Parser.parse(Lexer.parse(src, options), options); } catch (e) { if (options.silent) { fragment = new _syntheticDom.FragmentNode([new _syntheticDom.ElementNode('p', [], [new _syntheticDom.TextNode('An error occured:')]), new _syntheticDom.ElementNode('pre', [], [new _syntheticDom.TextNode(e.message)])]); } else { throw e; } } if (options.getAST) { return new _syntheticDom.ElementNode('body', [], [fragment]); } else { return fragment.toString(this.options.xhtml); } } }; exports.default = MarkdownParser;