From 947129cd00954911dceab3f7bfd4afa94e7576c7 Mon Sep 17 00:00:00 2001 From: booploops <49113086+booploops@users.noreply.github.com> Date: Mon, 28 Mar 2022 00:47:15 -0700 Subject: [PATCH] replaced showdown with marked for md renderer --- src/renderer/lib/marked.js | 2914 ++++++++++ src/renderer/lib/showdown.min.js | 5531 ------------------- src/renderer/views/main.ejs | 2 +- src/renderer/views/pages/plugins-github.ejs | 4 +- src/renderer/views/pages/themes-github.ejs | 4 +- 5 files changed, 2917 insertions(+), 5538 deletions(-) create mode 100644 src/renderer/lib/marked.js delete mode 100644 src/renderer/lib/showdown.min.js diff --git a/src/renderer/lib/marked.js b/src/renderer/lib/marked.js new file mode 100644 index 00000000..05e7a449 --- /dev/null +++ b/src/renderer/lib/marked.js @@ -0,0 +1,2914 @@ +/** + * marked - a markdown parser + * Copyright (c) 2011-2021, Christopher Jeffrey. (MIT Licensed) + * https://github.com/markedjs/marked + */ + +/** + * DO NOT EDIT THIS FILE + * The code in this file is generated from files in ./src/ + */ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.marked = {})); +})(this, (function (exports) { 'use strict'; + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + + return arr2; + } + + function _createForOfIteratorHelperLoose(o, allowArrayLike) { + var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; + if (it) return (it = it.call(o)).next.bind(it); + + if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { + if (it) o = it; + var i = 0; + return function () { + if (i >= o.length) return { + done: true + }; + return { + done: false, + value: o[i++] + }; + }; + } + + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + function getDefaults() { + return { + baseUrl: null, + breaks: false, + extensions: null, + gfm: true, + headerIds: true, + headerPrefix: '', + highlight: null, + langPrefix: 'language-', + mangle: true, + pedantic: false, + renderer: null, + sanitize: false, + sanitizer: null, + silent: false, + smartLists: false, + smartypants: false, + tokenizer: null, + walkTokens: null, + xhtml: false + }; + } + exports.defaults = getDefaults(); + function changeDefaults(newDefaults) { + exports.defaults = newDefaults; + } + + /** + * Helpers + */ + var escapeTest = /[&<>"']/; + var escapeReplace = /[&<>"']/g; + var escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/; + var escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g; + var escapeReplacements = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + + var getEscapeReplacement = function getEscapeReplacement(ch) { + return escapeReplacements[ch]; + }; + + function escape(html, encode) { + if (encode) { + if (escapeTest.test(html)) { + return html.replace(escapeReplace, getEscapeReplacement); + } + } else { + if (escapeTestNoEncode.test(html)) { + return html.replace(escapeReplaceNoEncode, getEscapeReplacement); + } + } + + return html; + } + var unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig; + function unescape(html) { + // explicitly match decimal, hex, and named HTML entities + return html.replace(unescapeTest, function (_, n) { + n = n.toLowerCase(); + if (n === 'colon') return ':'; + + if (n.charAt(0) === '#') { + return n.charAt(1) === 'x' ? String.fromCharCode(parseInt(n.substring(2), 16)) : String.fromCharCode(+n.substring(1)); + } + + return ''; + }); + } + var caret = /(^|[^\[])\^/g; + function edit(regex, opt) { + regex = regex.source || regex; + opt = opt || ''; + var obj = { + replace: function replace(name, val) { + val = val.source || val; + val = val.replace(caret, '$1'); + regex = regex.replace(name, val); + return obj; + }, + getRegex: function getRegex() { + return new RegExp(regex, opt); + } + }; + return obj; + } + var nonWordAndColonTest = /[^\w:]/g; + var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i; + function cleanUrl(sanitize, base, href) { + if (sanitize) { + var prot; + + try { + prot = decodeURIComponent(unescape(href)).replace(nonWordAndColonTest, '').toLowerCase(); + } catch (e) { + return null; + } + + if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) { + return null; + } + } + + if (base && !originIndependentUrl.test(href)) { + href = resolveUrl(base, href); + } + + try { + href = encodeURI(href).replace(/%25/g, '%'); + } catch (e) { + return null; + } + + return href; + } + var baseUrls = {}; + var justDomain = /^[^:]+:\/*[^/]*$/; + var protocol = /^([^:]+:)[\s\S]*$/; + var domain = /^([^:]+:\/*[^/]*)[\s\S]*$/; + function resolveUrl(base, href) { + if (!baseUrls[' ' + base]) { + // we can ignore everything in base after the last slash of its path component, + // but we might need to add _that_ + // https://tools.ietf.org/html/rfc3986#section-3 + if (justDomain.test(base)) { + baseUrls[' ' + base] = base + '/'; + } else { + baseUrls[' ' + base] = rtrim(base, '/', true); + } + } + + base = baseUrls[' ' + base]; + var relativeBase = base.indexOf(':') === -1; + + if (href.substring(0, 2) === '//') { + if (relativeBase) { + return href; + } + + return base.replace(protocol, '$1') + href; + } else if (href.charAt(0) === '/') { + if (relativeBase) { + return href; + } + + return base.replace(domain, '$1') + href; + } else { + return base + href; + } + } + var noopTest = { + exec: function noopTest() {} + }; + function merge(obj) { + var i = 1, + target, + key; + + for (; i < arguments.length; i++) { + target = arguments[i]; + + for (key in target) { + if (Object.prototype.hasOwnProperty.call(target, key)) { + obj[key] = target[key]; + } + } + } + + return obj; + } + function splitCells(tableRow, count) { + // ensure that every cell-delimiting pipe has a space + // before it to distinguish it from an escaped pipe + var row = tableRow.replace(/\|/g, function (match, offset, str) { + var escaped = false, + curr = offset; + + while (--curr >= 0 && str[curr] === '\\') { + escaped = !escaped; + } + + if (escaped) { + // odd number of slashes means | is escaped + // so we leave it alone + return '|'; + } else { + // add space before unescaped | + return ' |'; + } + }), + cells = row.split(/ \|/); + var i = 0; // First/last cell in a row cannot be empty if it has no leading/trailing pipe + + if (!cells[0].trim()) { + cells.shift(); + } + + if (!cells[cells.length - 1].trim()) { + cells.pop(); + } + + if (cells.length > count) { + cells.splice(count); + } else { + while (cells.length < count) { + cells.push(''); + } + } + + for (; i < cells.length; i++) { + // leading or trailing whitespace is ignored per the gfm spec + cells[i] = cells[i].trim().replace(/\\\|/g, '|'); + } + + return cells; + } // Remove trailing 'c's. Equivalent to str.replace(/c*$/, ''). + // /c*$/ is vulnerable to REDOS. + // invert: Remove suffix of non-c chars instead. Default falsey. + + function rtrim(str, c, invert) { + var l = str.length; + + if (l === 0) { + return ''; + } // Length of suffix matching the invert condition. + + + var suffLen = 0; // Step left until we fail to match the invert condition. + + while (suffLen < l) { + var currChar = str.charAt(l - suffLen - 1); + + if (currChar === c && !invert) { + suffLen++; + } else if (currChar !== c && invert) { + suffLen++; + } else { + break; + } + } + + return str.substr(0, l - suffLen); + } + function findClosingBracket(str, b) { + if (str.indexOf(b[1]) === -1) { + return -1; + } + + var l = str.length; + var level = 0, + i = 0; + + for (; i < l; i++) { + if (str[i] === '\\') { + i++; + } else if (str[i] === b[0]) { + level++; + } else if (str[i] === b[1]) { + level--; + + if (level < 0) { + return i; + } + } + } + + return -1; + } + function checkSanitizeDeprecation(opt) { + if (opt && opt.sanitize && !opt.silent) { + console.warn('marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options'); + } + } // copied from https://stackoverflow.com/a/5450113/806777 + + function repeatString(pattern, count) { + if (count < 1) { + return ''; + } + + var result = ''; + + while (count > 1) { + if (count & 1) { + result += pattern; + } + + count >>= 1; + pattern += pattern; + } + + return result + pattern; + } + + function outputLink(cap, link, raw, lexer) { + var href = link.href; + var title = link.title ? escape(link.title) : null; + var text = cap[1].replace(/\\([\[\]])/g, '$1'); + + if (cap[0].charAt(0) !== '!') { + lexer.state.inLink = true; + var token = { + type: 'link', + raw: raw, + href: href, + title: title, + text: text, + tokens: lexer.inlineTokens(text, []) + }; + lexer.state.inLink = false; + return token; + } else { + return { + type: 'image', + raw: raw, + href: href, + title: title, + text: escape(text) + }; + } + } + + function indentCodeCompensation(raw, text) { + var matchIndentToCode = raw.match(/^(\s+)(?:```)/); + + if (matchIndentToCode === null) { + return text; + } + + var indentToCode = matchIndentToCode[1]; + return text.split('\n').map(function (node) { + var matchIndentInNode = node.match(/^\s+/); + + if (matchIndentInNode === null) { + return node; + } + + var indentInNode = matchIndentInNode[0]; + + if (indentInNode.length >= indentToCode.length) { + return node.slice(indentToCode.length); + } + + return node; + }).join('\n'); + } + /** + * Tokenizer + */ + + + var Tokenizer = /*#__PURE__*/function () { + function Tokenizer(options) { + this.options = options || exports.defaults; + } + + var _proto = Tokenizer.prototype; + + _proto.space = function space(src) { + var cap = this.rules.block.newline.exec(src); + + if (cap) { + if (cap[0].length > 1) { + return { + type: 'space', + raw: cap[0] + }; + } + + return { + raw: '\n' + }; + } + }; + + _proto.code = function code(src) { + var cap = this.rules.block.code.exec(src); + + if (cap) { + var text = cap[0].replace(/^ {1,4}/gm, ''); + return { + type: 'code', + raw: cap[0], + codeBlockStyle: 'indented', + text: !this.options.pedantic ? rtrim(text, '\n') : text + }; + } + }; + + _proto.fences = function fences(src) { + var cap = this.rules.block.fences.exec(src); + + if (cap) { + var raw = cap[0]; + var text = indentCodeCompensation(raw, cap[3] || ''); + return { + type: 'code', + raw: raw, + lang: cap[2] ? cap[2].trim() : cap[2], + text: text + }; + } + }; + + _proto.heading = function heading(src) { + var cap = this.rules.block.heading.exec(src); + + if (cap) { + var text = cap[2].trim(); // remove trailing #s + + if (/#$/.test(text)) { + var trimmed = rtrim(text, '#'); + + if (this.options.pedantic) { + text = trimmed.trim(); + } else if (!trimmed || / $/.test(trimmed)) { + // CommonMark requires space before trailing #s + text = trimmed.trim(); + } + } + + var token = { + type: 'heading', + raw: cap[0], + depth: cap[1].length, + text: text, + tokens: [] + }; + this.lexer.inline(token.text, token.tokens); + return token; + } + }; + + _proto.hr = function hr(src) { + var cap = this.rules.block.hr.exec(src); + + if (cap) { + return { + type: 'hr', + raw: cap[0] + }; + } + }; + + _proto.blockquote = function blockquote(src) { + var cap = this.rules.block.blockquote.exec(src); + + if (cap) { + var text = cap[0].replace(/^ *> ?/gm, ''); + return { + type: 'blockquote', + raw: cap[0], + tokens: this.lexer.blockTokens(text, []), + text: text + }; + } + }; + + _proto.list = function list(src) { + var cap = this.rules.block.list.exec(src); + + if (cap) { + var raw, istask, ischecked, indent, i, blankLine, endsWithBlankLine, line, lines, itemContents; + var bull = cap[1].trim(); + var isordered = bull.length > 1; + var list = { + type: 'list', + raw: '', + ordered: isordered, + start: isordered ? +bull.slice(0, -1) : '', + loose: false, + items: [] + }; + bull = isordered ? "\\d{1,9}\\" + bull.slice(-1) : "\\" + bull; + + if (this.options.pedantic) { + bull = isordered ? bull : '[*+-]'; + } // Get next list item + + + var itemRegex = new RegExp("^( {0,3}" + bull + ")((?: [^\\n]*| *)(?:\\n[^\\n]*)*(?:\\n|$))"); // Get each top-level item + + while (src) { + if (this.rules.block.hr.test(src)) { + // End list if we encounter an HR (possibly move into itemRegex?) + break; + } + + if (!(cap = itemRegex.exec(src))) { + break; + } + + lines = cap[2].split('\n'); + + if (this.options.pedantic) { + indent = 2; + itemContents = lines[0].trimLeft(); + } else { + indent = cap[2].search(/[^ ]/); // Find first non-space char + + indent = cap[1].length + (indent > 4 ? 1 : indent); // intented code blocks after 4 spaces; indent is always 1 + + itemContents = lines[0].slice(indent - cap[1].length); + } + + blankLine = false; + raw = cap[0]; + + if (!lines[0] && /^ *$/.test(lines[1])) { + // items begin with at most one blank line + raw = cap[1] + lines.slice(0, 2).join('\n') + '\n'; + list.loose = true; + lines = []; + } + + var nextBulletRegex = new RegExp("^ {0," + Math.min(3, indent - 1) + "}(?:[*+-]|\\d{1,9}[.)])"); + + for (i = 1; i < lines.length; i++) { + line = lines[i]; + + if (this.options.pedantic) { + // Re-align to follow commonmark nesting rules + line = line.replace(/^ {1,4}(?=( {4})*[^ ])/g, ' '); + } // End list item if found start of new bullet + + + if (nextBulletRegex.test(line)) { + raw = cap[1] + lines.slice(0, i).join('\n') + '\n'; + break; + } // Until we encounter a blank line, item contents do not need indentation + + + if (!blankLine) { + if (!line.trim()) { + // Check if current line is empty + blankLine = true; + } // Dedent if possible + + + if (line.search(/[^ ]/) >= indent) { + itemContents += '\n' + line.slice(indent); + } else { + itemContents += '\n' + line; + } + + continue; + } // Dedent this line + + + if (line.search(/[^ ]/) >= indent || !line.trim()) { + itemContents += '\n' + line.slice(indent); + continue; + } else { + // Line was not properly indented; end of this item + raw = cap[1] + lines.slice(0, i).join('\n') + '\n'; + break; + } + } + + if (!list.loose) { + // If the previous item ended with a blank line, the list is loose + if (endsWithBlankLine) { + list.loose = true; + } else if (/\n *\n *$/.test(raw)) { + endsWithBlankLine = true; + } + } // Check for task list items + + + if (this.options.gfm) { + istask = /^\[[ xX]\] /.exec(itemContents); + + if (istask) { + ischecked = istask[0] !== '[ ] '; + itemContents = itemContents.replace(/^\[[ xX]\] +/, ''); + } + } + + list.items.push({ + type: 'list_item', + raw: raw, + task: !!istask, + checked: ischecked, + loose: false, + text: itemContents + }); + list.raw += raw; + src = src.slice(raw.length); + } // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic + + + list.items[list.items.length - 1].raw = raw.trimRight(); + list.items[list.items.length - 1].text = itemContents.trimRight(); + list.raw = list.raw.trimRight(); + var 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++) { + this.lexer.state.top = false; + list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []); + + if (list.items[i].tokens.some(function (t) { + return t.type === 'space'; + })) { + list.loose = true; + list.items[i].loose = true; + } + } + + return list; + } + }; + + _proto.html = function html(src) { + var cap = this.rules.block.html.exec(src); + + if (cap) { + var token = { + type: 'html', + raw: cap[0], + pre: !this.options.sanitizer && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), + text: cap[0] + }; + + if (this.options.sanitize) { + token.type = 'paragraph'; + token.text = this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]); + token.tokens = []; + this.lexer.inline(token.text, token.tokens); + } + + return token; + } + }; + + _proto.def = function def(src) { + var cap = this.rules.block.def.exec(src); + + if (cap) { + if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1); + var tag = cap[1].toLowerCase().replace(/\s+/g, ' '); + return { + type: 'def', + tag: tag, + raw: cap[0], + href: cap[2], + title: cap[3] + }; + } + }; + + _proto.table = function table(src) { + var cap = this.rules.block.table.exec(src); + + if (cap) { + var item = { + type: 'table', + header: splitCells(cap[1]).map(function (c) { + return { + text: c + }; + }), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + rows: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [] + }; + + if (item.header.length === item.align.length) { + item.raw = cap[0]; + var l = item.align.length; + var 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; + } + } + + l = item.rows.length; + + for (i = 0; i < l; i++) { + item.rows[i] = splitCells(item.rows[i], item.header.length).map(function (c) { + return { + text: c + }; + }); + } // parse child tokens inside headers and cells + // header child tokens + + + l = item.header.length; + + for (j = 0; j < l; j++) { + item.header[j].tokens = []; + this.lexer.inlineTokens(item.header[j].text, item.header[j].tokens); + } // cell child tokens + + + l = item.rows.length; + + for (j = 0; j < l; j++) { + row = item.rows[j]; + + for (k = 0; k < row.length; k++) { + row[k].tokens = []; + this.lexer.inlineTokens(row[k].text, row[k].tokens); + } + } + + return item; + } + } + }; + + _proto.lheading = function lheading(src) { + var cap = this.rules.block.lheading.exec(src); + + if (cap) { + var token = { + type: 'heading', + raw: cap[0], + depth: cap[2].charAt(0) === '=' ? 1 : 2, + text: cap[1], + tokens: [] + }; + this.lexer.inline(token.text, token.tokens); + return token; + } + }; + + _proto.paragraph = function paragraph(src) { + var cap = this.rules.block.paragraph.exec(src); + + if (cap) { + var token = { + type: 'paragraph', + raw: cap[0], + text: cap[1].charAt(cap[1].length - 1) === '\n' ? cap[1].slice(0, -1) : cap[1], + tokens: [] + }; + this.lexer.inline(token.text, token.tokens); + return token; + } + }; + + _proto.text = function text(src) { + var cap = this.rules.block.text.exec(src); + + if (cap) { + var token = { + type: 'text', + raw: cap[0], + text: cap[0], + tokens: [] + }; + this.lexer.inline(token.text, token.tokens); + return token; + } + }; + + _proto.escape = function escape$1(src) { + var cap = this.rules.inline.escape.exec(src); + + if (cap) { + return { + type: 'escape', + raw: cap[0], + text: escape(cap[1]) + }; + } + }; + + _proto.tag = function tag(src) { + var cap = this.rules.inline.tag.exec(src); + + if (cap) { + if (!this.lexer.state.inLink && /^/i.test(cap[0])) { + this.lexer.state.inLink = false; + } + + if (!this.lexer.state.inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) { + this.lexer.state.inRawBlock = true; + } else if (this.lexer.state.inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) { + this.lexer.state.inRawBlock = false; + } + + return { + type: this.options.sanitize ? 'text' : 'html', + raw: cap[0], + inLink: this.lexer.state.inLink, + inRawBlock: this.lexer.state.inRawBlock, + text: this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]) : cap[0] + }; + } + }; + + _proto.link = function link(src) { + var cap = this.rules.inline.link.exec(src); + + if (cap) { + var trimmedUrl = cap[2].trim(); + + if (!this.options.pedantic && /^$/.test(trimmedUrl)) { + return; + } // ending angle bracket cannot be escaped + + + var rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\'); + + if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) { + return; + } + } else { + // find closing parenthesis + var lastParenIndex = findClosingBracket(cap[2], '()'); + + if (lastParenIndex > -1) { + var start = cap[0].indexOf('!') === 0 ? 5 : 4; + var linkLen = start + cap[1].length + lastParenIndex; + cap[2] = cap[2].substring(0, lastParenIndex); + cap[0] = cap[0].substring(0, linkLen).trim(); + cap[3] = ''; + } + } + + var href = cap[2]; + var title = ''; + + if (this.options.pedantic) { + // split pedantic href and title + var link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href); + + if (link) { + href = link[1]; + title = link[3]; + } + } else { + title = cap[3] ? cap[3].slice(1, -1) : ''; + } + + href = href.trim(); + + if (/^$/.test(trimmedUrl)) { + // pedantic allows starting angle bracket without ending angle bracket + href = href.slice(1); + } else { + href = href.slice(1, -1); + } + } + + return outputLink(cap, { + href: href ? href.replace(this.rules.inline._escapes, '$1') : href, + title: title ? title.replace(this.rules.inline._escapes, '$1') : title + }, cap[0], this.lexer); + } + }; + + _proto.reflink = function reflink(src, links) { + var cap; + + if ((cap = this.rules.inline.reflink.exec(src)) || (cap = this.rules.inline.nolink.exec(src))) { + var link = (cap[2] || cap[1]).replace(/\s+/g, ' '); + link = links[link.toLowerCase()]; + + if (!link || !link.href) { + var text = cap[0].charAt(0); + return { + type: 'text', + raw: text, + text: text + }; + } + + return outputLink(cap, link, cap[0], this.lexer); + } + }; + + _proto.emStrong = function emStrong(src, maskedSrc, prevChar) { + if (prevChar === void 0) { + prevChar = ''; + } + + var match = this.rules.inline.emStrong.lDelim.exec(src); + if (!match) return; // _ can't be between two alphanumerics. \p{L}\p{N} includes non-english alphabet/numbers as well + + if (match[3] && prevChar.match(/(?:[0-9A-Za-z\xAA\xB2\xB3\xB5\xB9\xBA\xBC-\xBE\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u0660-\u0669\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07C0-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088E\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09F4-\u09F9\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AE6-\u0AEF\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71-\u0B77\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0BE6-\u0BF2\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5D\u0C60\u0C61\u0C66-\u0C6F\u0C78-\u0C7E\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDD\u0CDE\u0CE0\u0CE1\u0CE6-\u0CEF\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D58-\u0D61\u0D66-\u0D78\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DE6-\u0DEF\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F20-\u0F33\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F-\u1049\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1369-\u137C\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A16\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B50-\u1B59\u1B83-\u1BA0\u1BAE-\u1BE5\u1C00-\u1C23\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2070\u2071\u2074-\u2079\u207F-\u2089\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2150-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2CFD\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u3192-\u3195\u31A0-\u31BF\u31F0-\u31FF\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7CA\uA7D0\uA7D1\uA7D3\uA7D5-\uA7D9\uA7F2-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA830-\uA835\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uA9E0-\uA9E4\uA9E6-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD07-\uDD33\uDD40-\uDD78\uDD8A\uDD8B\uDE80-\uDE9C\uDEA0-\uDED0\uDEE1-\uDEFB\uDF00-\uDF23\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC58-\uDC76\uDC79-\uDC9E\uDCA7-\uDCAF\uDCE0-\uDCF2\uDCF4\uDCF5\uDCFB-\uDD1B\uDD20-\uDD39\uDD80-\uDDB7\uDDBC-\uDDCF\uDDD2-\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE40-\uDE48\uDE60-\uDE7E\uDE80-\uDE9F\uDEC0-\uDEC7\uDEC9-\uDEE4\uDEEB-\uDEEF\uDF00-\uDF35\uDF40-\uDF55\uDF58-\uDF72\uDF78-\uDF91\uDFA9-\uDFAF]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDCFA-\uDD23\uDD30-\uDD39\uDE60-\uDE7E\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF27\uDF30-\uDF45\uDF51-\uDF54\uDF70-\uDF81\uDFB0-\uDFCB\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC52-\uDC6F\uDC71\uDC72\uDC75\uDC83-\uDCAF\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD03-\uDD26\uDD36-\uDD3F\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDD0-\uDDDA\uDDDC\uDDE1-\uDDF4\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDEF0-\uDEF9\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC50-\uDC59\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE50-\uDE59\uDE80-\uDEAA\uDEB8\uDEC0-\uDEC9\uDF00-\uDF1A\uDF30-\uDF3B\uDF40-\uDF46]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCF2\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDD50-\uDD59\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEB0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC50-\uDC6C\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF2\uDFB0\uDFC0-\uDFD4]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|\uD80B[\uDF90-\uDFF0]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDE70-\uDEBE\uDEC0-\uDEC9\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF50-\uDF59\uDF5B-\uDF61\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE96\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD82C[\uDC00-\uDD22\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD834[\uDEE0-\uDEF3\uDF60-\uDF78]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD837[\uDF00-\uDF1E]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD40-\uDD49\uDD4E\uDE90-\uDEAD\uDEC0-\uDEEB\uDEF0-\uDEF9]|\uD839[\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]|\uD83A[\uDC00-\uDCC4\uDCC7-\uDCCF\uDD00-\uDD43\uDD4B\uDD50-\uDD59]|\uD83B[\uDC71-\uDCAB\uDCAD-\uDCAF\uDCB1-\uDCB4\uDD01-\uDD2D\uDD2F-\uDD3D\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83C[\uDD00-\uDD0C]|\uD83E[\uDFF0-\uDFF9]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF38\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])/)) return; + var nextChar = match[1] || match[2] || ''; + + if (!nextChar || nextChar && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))) { + var lLength = match[0].length - 1; + var rDelim, + rLength, + delimTotal = lLength, + midDelimTotal = 0; + var endReg = match[0][0] === '*' ? this.rules.inline.emStrong.rDelimAst : this.rules.inline.emStrong.rDelimUnd; + endReg.lastIndex = 0; // Clip maskedSrc to same section of string as src (move to lexer?) + + maskedSrc = maskedSrc.slice(-1 * src.length + lLength); + + while ((match = endReg.exec(maskedSrc)) != null) { + rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6]; + if (!rDelim) continue; // skip single * in __abc*abc__ + + rLength = rDelim.length; + + if (match[3] || match[4]) { + // found another Left Delim + delimTotal += rLength; + continue; + } else if (match[5] || match[6]) { + // either Left or Right Delim + if (lLength % 3 && !((lLength + rLength) % 3)) { + midDelimTotal += rLength; + continue; // CommonMark Emphasis Rules 9-10 + } + } + + delimTotal -= rLength; + if (delimTotal > 0) continue; // Haven't found enough closing delimiters + // Remove extra characters. *a*** -> *a* + + rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal); // Create `em` if smallest delimiter has odd char count. *a*** + + if (Math.min(lLength, rLength) % 2) { + var _text = src.slice(1, lLength + match.index + rLength); + + return { + type: 'em', + raw: src.slice(0, lLength + match.index + rLength + 1), + text: _text, + tokens: this.lexer.inlineTokens(_text, []) + }; + } // Create 'strong' if smallest delimiter has even char count. **a*** + + + var text = src.slice(2, lLength + match.index + rLength - 1); + return { + type: 'strong', + raw: src.slice(0, lLength + match.index + rLength + 1), + text: text, + tokens: this.lexer.inlineTokens(text, []) + }; + } + } + }; + + _proto.codespan = function codespan(src) { + var cap = this.rules.inline.code.exec(src); + + if (cap) { + var text = cap[2].replace(/\n/g, ' '); + var hasNonSpaceChars = /[^ ]/.test(text); + var hasSpaceCharsOnBothEnds = /^ /.test(text) && / $/.test(text); + + if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) { + text = text.substring(1, text.length - 1); + } + + text = escape(text, true); + return { + type: 'codespan', + raw: cap[0], + text: text + }; + } + }; + + _proto.br = function br(src) { + var cap = this.rules.inline.br.exec(src); + + if (cap) { + return { + type: 'br', + raw: cap[0] + }; + } + }; + + _proto.del = function del(src) { + var cap = this.rules.inline.del.exec(src); + + if (cap) { + return { + type: 'del', + raw: cap[0], + text: cap[2], + tokens: this.lexer.inlineTokens(cap[2], []) + }; + } + }; + + _proto.autolink = function autolink(src, mangle) { + var cap = this.rules.inline.autolink.exec(src); + + if (cap) { + var text, href; + + if (cap[2] === '@') { + text = escape(this.options.mangle ? mangle(cap[1]) : cap[1]); + href = 'mailto:' + text; + } else { + text = escape(cap[1]); + href = text; + } + + return { + type: 'link', + raw: cap[0], + text: text, + href: href, + tokens: [{ + type: 'text', + raw: text, + text: text + }] + }; + } + }; + + _proto.url = function url(src, mangle) { + var cap; + + if (cap = this.rules.inline.url.exec(src)) { + var text, href; + + if (cap[2] === '@') { + text = escape(this.options.mangle ? mangle(cap[0]) : cap[0]); + href = 'mailto:' + text; + } else { + // do extended autolink path validation + var prevCapZero; + + do { + prevCapZero = cap[0]; + cap[0] = this.rules.inline._backpedal.exec(cap[0])[0]; + } while (prevCapZero !== cap[0]); + + text = escape(cap[0]); + + if (cap[1] === 'www.') { + href = 'http://' + text; + } else { + href = text; + } + } + + return { + type: 'link', + raw: cap[0], + text: text, + href: href, + tokens: [{ + type: 'text', + raw: text, + text: text + }] + }; + } + }; + + _proto.inlineText = function inlineText(src, smartypants) { + var cap = this.rules.inline.text.exec(src); + + if (cap) { + var text; + + if (this.lexer.state.inRawBlock) { + text = this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]) : cap[0]; + } else { + text = escape(this.options.smartypants ? smartypants(cap[0]) : cap[0]); + } + + return { + type: 'text', + raw: cap[0], + text: text + }; + } + }; + + return Tokenizer; + }(); + + /** + * Block-Level Grammar + */ + + var block = { + newline: /^(?: *(?:\n|$))+/, + code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/, + fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?=\n|$)|$)/, + hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/, + heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/, + blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/, + list: /^( {0,3}bull)( [^\n]+?)?(?:\n|$)/, + html: '^ {0,3}(?:' // optional indentation + + '<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)' // (1) + + '|comment[^\\n]*(\\n+|$)' // (2) + + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3) + + '|\\n*|$)' // (4) + + '|\\n*|$)' // (5) + + '|)[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (6) + + '|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) open tag + + '|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) closing tag + + ')', + def: /^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/, + table: noopTest, + lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/, + // regex template, placeholders will be replaced according to different paragraph + // interruption rules of commonmark and the original markdown spec: + _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html| +\n)[^\n]+)*)/, + text: /^[^\n]+/ + }; + block._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/; + block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/; + block.def = edit(block.def).replace('label', block._label).replace('title', block._title).getRegex(); + block.bullet = /(?:[*+-]|\d{1,9}[.)])/; + block.listItemStart = edit(/^( *)(bull) */).replace('bull', block.bullet).getRegex(); + block.list = edit(block.list).replace(/bull/g, block.bullet).replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))').replace('def', '\\n+(?=' + block.def.source + ')').getRegex(); + block._tag = 'address|article|aside|base|basefont|blockquote|body|caption' + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption' + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe' + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option' + '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr' + '|track|ul'; + block._comment = /|$)/; + block.html = edit(block.html, 'i').replace('comment', block._comment).replace('tag', block._tag).replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(); + block.paragraph = edit(block._paragraph).replace('hr', block.hr).replace('heading', ' {0,3}#{1,6} ').replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs + .replace('blockquote', ' {0,3}>').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|textarea|!--)').replace('tag', block._tag) // pars can be interrupted by type (6) html blocks + .getRegex(); + block.blockquote = edit(block.blockquote).replace('paragraph', block.paragraph).getRegex(); + /** + * Normal Block Grammar + */ + + block.normal = merge({}, block); + /** + * GFM Block Grammar + */ + + block.gfm = merge({}, block.normal, { + table: '^ *([^\\n ].*\\|.*)\\n' // Header + + ' {0,3}(?:\\| *)?(:?-+:? *(?:\\| *:?-+:? *)*)(?:\\| *)?' // Align + + '(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)' // Cells + + }); + block.gfm.table = edit(block.gfm.table).replace('hr', block.hr).replace('heading', ' {0,3}#{1,6} ').replace('blockquote', ' {0,3}>').replace('code', ' {4}[^\\n]').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|textarea|!--)').replace('tag', block._tag) // tables can be interrupted by type (6) html blocks + .getRegex(); + /** + * Pedantic grammar (original John Gruber's loose markdown specification) + */ + + block.pedantic = merge({}, block.normal, { + html: edit('^ *(?:comment *(?:\\n|\\s*$)' + '|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)' // closed tag + + '|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))').replace('comment', block._comment).replace(/tag/g, '(?!(?:' + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub' + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)' + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b').getRegex(), + def: /^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, + heading: /^(#{1,6})(.*)(?:\n+|$)/, + fences: noopTest, + // fences not supported + paragraph: edit(block.normal._paragraph).replace('hr', block.hr).replace('heading', ' *#{1,6} *[^\n]').replace('lheading', block.lheading).replace('blockquote', ' {0,3}>').replace('|fences', '').replace('|list', '').replace('|html', '').getRegex() + }); + /** + * Inline-Level Grammar + */ + + var inline = { + escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/, + autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/, + url: noopTest, + tag: '^comment' + '|^' // self-closing tag + + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag + + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. + + '|^' // declaration, e.g. + + '|^', + // CDATA section + link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/, + reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/, + nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/, + reflinkSearch: 'reflink|nolink(?!\\()', + emStrong: { + lDelim: /^(?:\*+(?:([punct_])|[^\s*]))|^_+(?:([punct*])|([^\s_]))/, + // (1) and (2) can only be a Right Delimiter. (3) and (4) can only be Left. (5) and (6) can be either Left or Right. + // () Skip orphan delim inside strong (1) #*** (2) a***#, a*** (3) #***a, ***a (4) ***# (5) #***# (6) a***a + rDelimAst: /^[^_*]*?\_\_[^_*]*?\*[^_*]*?(?=\_\_)|[punct_](\*+)(?=[\s]|$)|[^punct*_\s](\*+)(?=[punct_\s]|$)|[punct_\s](\*+)(?=[^punct*_\s])|[\s](\*+)(?=[punct_])|[punct_](\*+)(?=[punct_])|[^punct*_\s](\*+)(?=[^punct*_\s])/, + rDelimUnd: /^[^_*]*?\*\*[^_*]*?\_[^_*]*?(?=\*\*)|[punct*](\_+)(?=[\s]|$)|[^punct*_\s](\_+)(?=[punct*\s]|$)|[punct*\s](\_+)(?=[^punct*_\s])|[\s](\_+)(?=[punct*])|[punct*](\_+)(?=[punct*])/ // ^- Not allowed for _ + + }, + code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/, + br: /^( {2,}|\\)\n(?!\s*$)/, + del: noopTest, + text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\?@\\[\\]`^{|}~'; + inline.punctuation = edit(inline.punctuation).replace(/punctuation/g, inline._punctuation).getRegex(); // sequences em should skip over [title](link), `code`, + + inline.blockSkip = /\[[^\]]*?\]\([^\)]*?\)|`[^`]*?`|<[^>]*?>/g; + inline.escapedEmSt = /\\\*|\\_/g; + inline._comment = edit(block._comment).replace('(?:-->|$)', '-->').getRegex(); + inline.emStrong.lDelim = edit(inline.emStrong.lDelim).replace(/punct/g, inline._punctuation).getRegex(); + inline.emStrong.rDelimAst = edit(inline.emStrong.rDelimAst, 'g').replace(/punct/g, inline._punctuation).getRegex(); + inline.emStrong.rDelimUnd = edit(inline.emStrong.rDelimUnd, 'g').replace(/punct/g, inline._punctuation).getRegex(); + inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g; + inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/; + inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/; + inline.autolink = edit(inline.autolink).replace('scheme', inline._scheme).replace('email', inline._email).getRegex(); + inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/; + inline.tag = edit(inline.tag).replace('comment', inline._comment).replace('attribute', inline._attribute).getRegex(); + inline._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/; + inline._href = /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/; + inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/; + inline.link = edit(inline.link).replace('label', inline._label).replace('href', inline._href).replace('title', inline._title).getRegex(); + inline.reflink = edit(inline.reflink).replace('label', inline._label).getRegex(); + inline.reflinkSearch = edit(inline.reflinkSearch, 'g').replace('reflink', inline.reflink).replace('nolink', inline.nolink).getRegex(); + /** + * Normal Inline Grammar + */ + + inline.normal = merge({}, inline); + /** + * Pedantic Inline Grammar + */ + + inline.pedantic = merge({}, inline.normal, { + strong: { + start: /^__|\*\*/, + middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, + endAst: /\*\*(?!\*)/g, + endUnd: /__(?!_)/g + }, + em: { + start: /^_|\*/, + middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/, + endAst: /\*(?!\*)/g, + endUnd: /_(?!_)/g + }, + link: edit(/^!?\[(label)\]\((.*?)\)/).replace('label', inline._label).getRegex(), + reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace('label', inline._label).getRegex() + }); + /** + * GFM Inline Grammar + */ + + inline.gfm = merge({}, inline.normal, { + escape: edit(inline.escape).replace('])', '~|])').getRegex(), + _extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/, + url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, + _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/, + del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/, + text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\ 0.5) { + ch = 'x' + ch.toString(16); + } + + out += '&#' + ch + ';'; + } + + return out; + } + /** + * Block Lexer + */ + + + var Lexer = /*#__PURE__*/function () { + function Lexer(options) { + this.tokens = []; + this.tokens.links = Object.create(null); + this.options = options || exports.defaults; + this.options.tokenizer = this.options.tokenizer || new Tokenizer(); + this.tokenizer = this.options.tokenizer; + this.tokenizer.options = this.options; + this.tokenizer.lexer = this; + this.inlineQueue = []; + this.state = { + inLink: false, + inRawBlock: false, + top: true + }; + var rules = { + block: block.normal, + inline: inline.normal + }; + + if (this.options.pedantic) { + rules.block = block.pedantic; + rules.inline = inline.pedantic; + } else if (this.options.gfm) { + rules.block = block.gfm; + + if (this.options.breaks) { + rules.inline = inline.breaks; + } else { + rules.inline = inline.gfm; + } + } + + this.tokenizer.rules = rules; + } + /** + * Expose Rules + */ + + + /** + * Static Lex Method + */ + Lexer.lex = function lex(src, options) { + var lexer = new Lexer(options); + return lexer.lex(src); + } + /** + * Static Lex Inline Method + */ + ; + + Lexer.lexInline = function lexInline(src, options) { + var lexer = new Lexer(options); + return lexer.inlineTokens(src); + } + /** + * Preprocessing + */ + ; + + var _proto = Lexer.prototype; + + _proto.lex = function lex(src) { + src = src.replace(/\r\n|\r/g, '\n').replace(/\t/g, ' '); + this.blockTokens(src, this.tokens); + var next; + + while (next = this.inlineQueue.shift()) { + this.inlineTokens(next.src, next.tokens); + } + + return this.tokens; + } + /** + * Lexing + */ + ; + + _proto.blockTokens = function blockTokens(src, tokens) { + var _this = this; + + if (tokens === void 0) { + tokens = []; + } + + if (this.options.pedantic) { + src = src.replace(/^ +$/gm, ''); + } + + var token, lastToken, cutSrc, lastParagraphClipped; + + while (src) { + if (this.options.extensions && this.options.extensions.block && this.options.extensions.block.some(function (extTokenizer) { + if (token = extTokenizer.call({ + lexer: _this + }, src, tokens)) { + src = src.substring(token.raw.length); + tokens.push(token); + return true; + } + + return false; + })) { + continue; + } // newline + + + if (token = this.tokenizer.space(src)) { + src = src.substring(token.raw.length); + + if (token.type) { + tokens.push(token); + } + + continue; + } // code + + + if (token = this.tokenizer.code(src)) { + src = src.substring(token.raw.length); + lastToken = tokens[tokens.length - 1]; // An indented code block cannot interrupt a paragraph. + + if (lastToken && (lastToken.type === 'paragraph' || lastToken.type === 'text')) { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text; + } else { + tokens.push(token); + } + + continue; + } // fences + + + if (token = this.tokenizer.fences(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } // heading + + + if (token = this.tokenizer.heading(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } // hr + + + if (token = this.tokenizer.hr(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } // blockquote + + + if (token = this.tokenizer.blockquote(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } // list + + + if (token = this.tokenizer.list(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } // html + + + if (token = this.tokenizer.html(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } // def + + + if (token = this.tokenizer.def(src)) { + src = src.substring(token.raw.length); + lastToken = tokens[tokens.length - 1]; + + if (lastToken && (lastToken.type === 'paragraph' || lastToken.type === 'text')) { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.raw; + this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text; + } else if (!this.tokens.links[token.tag]) { + this.tokens.links[token.tag] = { + href: token.href, + title: token.title + }; + } + + continue; + } // table (gfm) + + + if (token = this.tokenizer.table(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } // lheading + + + if (token = this.tokenizer.lheading(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } // top-level paragraph + // prevent paragraph consuming extensions by clipping 'src' to extension start + + + cutSrc = src; + + if (this.options.extensions && this.options.extensions.startBlock) { + (function () { + var startIndex = Infinity; + var tempSrc = src.slice(1); + var tempStart = void 0; + + _this.options.extensions.startBlock.forEach(function (getStartIndex) { + tempStart = getStartIndex.call({ + lexer: this + }, tempSrc); + + if (typeof tempStart === 'number' && tempStart >= 0) { + startIndex = Math.min(startIndex, tempStart); + } + }); + + if (startIndex < Infinity && startIndex >= 0) { + cutSrc = src.substring(0, startIndex + 1); + } + })(); + } + + if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) { + lastToken = tokens[tokens.length - 1]; + + if (lastParagraphClipped && lastToken.type === 'paragraph') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + this.inlineQueue.pop(); + this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text; + } else { + tokens.push(token); + } + + lastParagraphClipped = cutSrc.length !== src.length; + src = src.substring(token.raw.length); + continue; + } // text + + + if (token = this.tokenizer.text(src)) { + src = src.substring(token.raw.length); + lastToken = tokens[tokens.length - 1]; + + if (lastToken && lastToken.type === 'text') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + this.inlineQueue.pop(); + this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text; + } else { + tokens.push(token); + } + + continue; + } + + if (src) { + var errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0); + + if (this.options.silent) { + console.error(errMsg); + break; + } else { + throw new Error(errMsg); + } + } + } + + this.state.top = true; + return tokens; + }; + + _proto.inline = function inline(src, tokens) { + this.inlineQueue.push({ + src: src, + tokens: tokens + }); + } + /** + * Lexing/Compiling + */ + ; + + _proto.inlineTokens = function inlineTokens(src, tokens) { + var _this2 = this; + + if (tokens === void 0) { + tokens = []; + } + + var token, lastToken, cutSrc; // String with links masked to avoid interference with em and strong + + var maskedSrc = src; + var match; + var keepPrevChar, prevChar; // Mask out reflinks + + if (this.tokens.links) { + var links = Object.keys(this.tokens.links); + + if (links.length > 0) { + while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) { + if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) { + maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex); + } + } + } + } // Mask out other blocks + + + while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) { + maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex); + } // Mask out escaped em & strong delimiters + + + while ((match = this.tokenizer.rules.inline.escapedEmSt.exec(maskedSrc)) != null) { + maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.escapedEmSt.lastIndex); + } + + while (src) { + if (!keepPrevChar) { + prevChar = ''; + } + + keepPrevChar = false; // extensions + + if (this.options.extensions && this.options.extensions.inline && this.options.extensions.inline.some(function (extTokenizer) { + if (token = extTokenizer.call({ + lexer: _this2 + }, src, tokens)) { + src = src.substring(token.raw.length); + tokens.push(token); + return true; + } + + return false; + })) { + continue; + } // escape + + + if (token = this.tokenizer.escape(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } // tag + + + if (token = this.tokenizer.tag(src)) { + src = src.substring(token.raw.length); + lastToken = tokens[tokens.length - 1]; + + if (lastToken && token.type === 'text' && lastToken.type === 'text') { + lastToken.raw += token.raw; + lastToken.text += token.text; + } else { + tokens.push(token); + } + + continue; + } // link + + + if (token = this.tokenizer.link(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } // reflink, nolink + + + if (token = this.tokenizer.reflink(src, this.tokens.links)) { + src = src.substring(token.raw.length); + lastToken = tokens[tokens.length - 1]; + + if (lastToken && token.type === 'text' && lastToken.type === 'text') { + lastToken.raw += token.raw; + lastToken.text += token.text; + } else { + tokens.push(token); + } + + continue; + } // em & strong + + + if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } // code + + + if (token = this.tokenizer.codespan(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } // br + + + if (token = this.tokenizer.br(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } // del (gfm) + + + if (token = this.tokenizer.del(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } // autolink + + + if (token = this.tokenizer.autolink(src, mangle)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } // url (gfm) + + + if (!this.state.inLink && (token = this.tokenizer.url(src, mangle))) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } // text + // prevent inlineText consuming extensions by clipping 'src' to extension start + + + cutSrc = src; + + if (this.options.extensions && this.options.extensions.startInline) { + (function () { + var startIndex = Infinity; + var tempSrc = src.slice(1); + var tempStart = void 0; + + _this2.options.extensions.startInline.forEach(function (getStartIndex) { + tempStart = getStartIndex.call({ + lexer: this + }, tempSrc); + + if (typeof tempStart === 'number' && tempStart >= 0) { + startIndex = Math.min(startIndex, tempStart); + } + }); + + if (startIndex < Infinity && startIndex >= 0) { + cutSrc = src.substring(0, startIndex + 1); + } + })(); + } + + if (token = this.tokenizer.inlineText(cutSrc, smartypants)) { + src = src.substring(token.raw.length); + + if (token.raw.slice(-1) !== '_') { + // Track prevChar before string of ____ started + prevChar = token.raw.slice(-1); + } + + keepPrevChar = true; + lastToken = tokens[tokens.length - 1]; + + if (lastToken && lastToken.type === 'text') { + lastToken.raw += token.raw; + lastToken.text += token.text; + } else { + tokens.push(token); + } + + continue; + } + + if (src) { + var errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0); + + if (this.options.silent) { + console.error(errMsg); + break; + } else { + throw new Error(errMsg); + } + } + } + + return tokens; + }; + + _createClass(Lexer, null, [{ + key: "rules", + get: function get() { + return { + block: block, + inline: inline + }; + } + }]); + + return Lexer; + }(); + + /** + * Renderer + */ + + var Renderer = /*#__PURE__*/function () { + function Renderer(options) { + this.options = options || exports.defaults; + } + + var _proto = Renderer.prototype; + + _proto.code = function code(_code, infostring, escaped) { + var lang = (infostring || '').match(/\S*/)[0]; + + if (this.options.highlight) { + var out = this.options.highlight(_code, lang); + + if (out != null && out !== _code) { + escaped = true; + _code = out; + } + } + + _code = _code.replace(/\n$/, '') + '\n'; + + if (!lang) { + return '
' + (escaped ? _code : escape(_code, true)) + '
\n'; + } + + return '
' + (escaped ? _code : escape(_code, true)) + '
\n'; + }; + + _proto.blockquote = function blockquote(quote) { + return '
\n' + quote + '
\n'; + }; + + _proto.html = function html(_html) { + return _html; + }; + + _proto.heading = function heading(text, level, raw, slugger) { + if (this.options.headerIds) { + return '' + text + '\n'; + } // ignore IDs + + + return '' + text + '\n'; + }; + + _proto.hr = function hr() { + return this.options.xhtml ? '
\n' : '
\n'; + }; + + _proto.list = function list(body, ordered, start) { + var type = ordered ? 'ol' : 'ul', + startatt = ordered && start !== 1 ? ' start="' + start + '"' : ''; + return '<' + type + startatt + '>\n' + body + '\n'; + }; + + _proto.listitem = function listitem(text) { + return '
  • ' + text + '
  • \n'; + }; + + _proto.checkbox = function checkbox(checked) { + return ' '; + }; + + _proto.paragraph = function paragraph(text) { + return '

    ' + text + '

    \n'; + }; + + _proto.table = function table(header, body) { + if (body) body = '' + body + ''; + return '\n' + '\n' + header + '\n' + body + '
    \n'; + }; + + _proto.tablerow = function tablerow(content) { + return '\n' + content + '\n'; + }; + + _proto.tablecell = function tablecell(content, flags) { + var type = flags.header ? 'th' : 'td'; + var tag = flags.align ? '<' + type + ' align="' + flags.align + '">' : '<' + type + '>'; + return tag + content + '\n'; + } // span level renderer + ; + + _proto.strong = function strong(text) { + return '' + text + ''; + }; + + _proto.em = function em(text) { + return '' + text + ''; + }; + + _proto.codespan = function codespan(text) { + return '' + text + ''; + }; + + _proto.br = function br() { + return this.options.xhtml ? '
    ' : '
    '; + }; + + _proto.del = function del(text) { + return '' + text + ''; + }; + + _proto.link = function link(href, title, text) { + href = cleanUrl(this.options.sanitize, this.options.baseUrl, href); + + if (href === null) { + return text; + } + + var out = '
    '; + return out; + }; + + _proto.image = function image(href, title, text) { + href = cleanUrl(this.options.sanitize, this.options.baseUrl, href); + + if (href === null) { + return text; + } + + var out = '' + text + '' : '>'; + return out; + }; + + _proto.text = function text(_text) { + return _text; + }; + + return Renderer; + }(); + + /** + * TextRenderer + * returns only the textual part of the token + */ + var TextRenderer = /*#__PURE__*/function () { + function TextRenderer() {} + + var _proto = TextRenderer.prototype; + + // no need for block level renderers + _proto.strong = function strong(text) { + return text; + }; + + _proto.em = function em(text) { + return text; + }; + + _proto.codespan = function codespan(text) { + return text; + }; + + _proto.del = function del(text) { + return text; + }; + + _proto.html = function html(text) { + return text; + }; + + _proto.text = function text(_text) { + return _text; + }; + + _proto.link = function link(href, title, text) { + return '' + text; + }; + + _proto.image = function image(href, title, text) { + return '' + text; + }; + + _proto.br = function br() { + return ''; + }; + + return TextRenderer; + }(); + + /** + * Slugger generates header id + */ + var Slugger = /*#__PURE__*/function () { + function Slugger() { + this.seen = {}; + } + + var _proto = Slugger.prototype; + + _proto.serialize = function serialize(value) { + return value.toLowerCase().trim() // remove html tags + .replace(/<[!\/a-z].*?>/ig, '') // remove unwanted chars + .replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '').replace(/\s/g, '-'); + } + /** + * Finds the next safe (unique) slug to use + */ + ; + + _proto.getNextSafeSlug = function getNextSafeSlug(originalSlug, isDryRun) { + var slug = originalSlug; + var occurenceAccumulator = 0; + + if (this.seen.hasOwnProperty(slug)) { + occurenceAccumulator = this.seen[originalSlug]; + + do { + occurenceAccumulator++; + slug = originalSlug + '-' + occurenceAccumulator; + } while (this.seen.hasOwnProperty(slug)); + } + + if (!isDryRun) { + this.seen[originalSlug] = occurenceAccumulator; + this.seen[slug] = 0; + } + + return slug; + } + /** + * Convert string to unique id + * @param {object} options + * @param {boolean} options.dryrun Generates the next unique slug without updating the internal accumulator. + */ + ; + + _proto.slug = function slug(value, options) { + if (options === void 0) { + options = {}; + } + + var slug = this.serialize(value); + return this.getNextSafeSlug(slug, options.dryrun); + }; + + return Slugger; + }(); + + /** + * Parsing & Compiling + */ + + var Parser = /*#__PURE__*/function () { + function Parser(options) { + this.options = options || exports.defaults; + this.options.renderer = this.options.renderer || new Renderer(); + this.renderer = this.options.renderer; + this.renderer.options = this.options; + this.textRenderer = new TextRenderer(); + this.slugger = new Slugger(); + } + /** + * Static Parse Method + */ + + + Parser.parse = function parse(tokens, options) { + var parser = new Parser(options); + return parser.parse(tokens); + } + /** + * Static Parse Inline Method + */ + ; + + Parser.parseInline = function parseInline(tokens, options) { + var parser = new Parser(options); + return parser.parseInline(tokens); + } + /** + * Parse Loop + */ + ; + + var _proto = Parser.prototype; + + _proto.parse = function parse(tokens, top) { + if (top === void 0) { + top = true; + } + + var out = '', + i, + j, + k, + l2, + l3, + row, + cell, + header, + body, + token, + ordered, + start, + loose, + itemBody, + item, + checked, + task, + checkbox, + ret; + var l = tokens.length; + + for (i = 0; i < l; i++) { + 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)) { + out += ret || ''; + continue; + } + } + + switch (token.type) { + case 'space': + { + continue; + } + + case 'hr': + { + out += this.renderer.hr(); + continue; + } + + case 'heading': + { + out += this.renderer.heading(this.parseInline(token.tokens), token.depth, unescape(this.parseInline(token.tokens, this.textRenderer)), this.slugger); + continue; + } + + case 'code': + { + out += this.renderer.code(token.text, token.lang, token.escaped); + continue; + } + + case 'table': + { + 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] + }); + } + + header += this.renderer.tablerow(cell); + body = ''; + l2 = token.rows.length; + + for (j = 0; j < l2; j++) { + row = token.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] + }); + } + + body += this.renderer.tablerow(cell); + } + + out += this.renderer.table(header, body); + continue; + } + + case 'blockquote': + { + body = this.parse(token.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 = ''; + + if (item.task) { + 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; + + if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') { + item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text; + } + } else { + item.tokens.unshift({ + type: 'text', + text: checkbox + }); + } + } else { + itemBody += checkbox; + } + } + + itemBody += this.parse(item.tokens, loose); + body += this.renderer.listitem(itemBody, task, checked); + } + + out += this.renderer.list(body, ordered, start); + continue; + } + + case 'html': + { + // TODO parse inline content if parameter markdown=1 + out += this.renderer.html(token.text); + continue; + } + + case 'paragraph': + { + out += this.renderer.paragraph(this.parseInline(token.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); + } + + out += top ? this.renderer.paragraph(body) : body; + continue; + } + + default: + { + var errMsg = 'Token with "' + token.type + '" type was not found.'; + + if (this.options.silent) { + console.error(errMsg); + return; + } else { + throw new Error(errMsg); + } + } + } + } + + return out; + } + /** + * Parse Inline Tokens + */ + ; + + _proto.parseInline = function parseInline(tokens, renderer) { + renderer = renderer || this.renderer; + var out = '', + i, + token, + ret; + var l = tokens.length; + + for (i = 0; i < l; i++) { + 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 || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(token.type)) { + out += ret || ''; + continue; + } + } + + switch (token.type) { + case 'escape': + { + out += renderer.text(token.text); + break; + } + + case 'html': + { + out += renderer.html(token.text); + break; + } + + case 'link': + { + out += renderer.link(token.href, token.title, this.parseInline(token.tokens, renderer)); + break; + } + + case 'image': + { + out += renderer.image(token.href, token.title, token.text); + break; + } + + case 'strong': + { + out += renderer.strong(this.parseInline(token.tokens, renderer)); + break; + } + + case 'em': + { + out += renderer.em(this.parseInline(token.tokens, renderer)); + break; + } + + case 'codespan': + { + out += renderer.codespan(token.text); + break; + } + + case 'br': + { + out += renderer.br(); + break; + } + + case 'del': + { + out += renderer.del(this.parseInline(token.tokens, renderer)); + break; + } + + case 'text': + { + out += renderer.text(token.text); + break; + } + + default: + { + var errMsg = 'Token with "' + token.type + '" type was not found.'; + + if (this.options.silent) { + console.error(errMsg); + return; + } else { + throw new Error(errMsg); + } + } + } + } + + return out; + }; + + return Parser; + }(); + + /** + * Marked + */ + + function marked(src, opt, callback) { + // throw error in case of non string input + if (typeof src === 'undefined' || src === null) { + throw new Error('marked(): input parameter is undefined or null'); + } + + if (typeof src !== 'string') { + throw new Error('marked(): input parameter is of type ' + Object.prototype.toString.call(src) + ', string expected'); + } + + if (typeof opt === 'function') { + callback = opt; + opt = null; + } + + opt = merge({}, marked.defaults, opt || {}); + checkSanitizeDeprecation(opt); + + if (callback) { + var highlight = opt.highlight; + var tokens; + + try { + tokens = Lexer.lex(src, opt); + } catch (e) { + return callback(e); + } + + var done = function done(err) { + var out; + + if (!err) { + try { + if (opt.walkTokens) { + marked.walkTokens(tokens, opt.walkTokens); + } + + out = Parser.parse(tokens, opt); + } catch (e) { + err = e; + } + } + + opt.highlight = highlight; + return err ? callback(err) : callback(null, out); + }; + + if (!highlight || highlight.length < 3) { + return done(); + } + + delete opt.highlight; + if (!tokens.length) return done(); + var pending = 0; + marked.walkTokens(tokens, function (token) { + if (token.type === 'code') { + pending++; + setTimeout(function () { + highlight(token.text, token.lang, function (err, code) { + if (err) { + return done(err); + } + + if (code != null && code !== token.text) { + token.text = code; + token.escaped = true; + } + + pending--; + + if (pending === 0) { + done(); + } + }); + }, 0); + } + }); + + if (pending === 0) { + done(); + } + + return; + } + + try { + var _tokens = Lexer.lex(src, opt); + + if (opt.walkTokens) { + marked.walkTokens(_tokens, opt.walkTokens); + } + + return Parser.parse(_tokens, opt); + } catch (e) { + e.message += '\nPlease report this to https://github.com/markedjs/marked.'; + + if (opt.silent) { + return '

    An error occurred:

    ' + escape(e.message + '', true) + '
    '; + } + + throw e; + } + } + /** + * Options + */ + + + marked.options = marked.setOptions = function (opt) { + merge(marked.defaults, opt); + changeDefaults(marked.defaults); + return marked; + }; + + marked.getDefaults = getDefaults; + marked.defaults = exports.defaults; + /** + * Use Extension + */ + + marked.use = function () { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + var opts = merge.apply(void 0, [{}].concat(args)); + var extensions = marked.defaults.extensions || { + renderers: {}, + childTokens: {} + }; + var hasExtensions; + args.forEach(function (pack) { + // ==-- Parse "addon" extensions --== // + if (pack.extensions) { + hasExtensions = true; + pack.extensions.forEach(function (ext) { + if (!ext.name) { + throw new Error('extension name required'); + } + + if (ext.renderer) { + // Renderer extensions + var prevRenderer = extensions.renderers ? extensions.renderers[ext.name] : null; + + if (prevRenderer) { + // Replace extension with func to run new extension but fall back if false + extensions.renderers[ext.name] = function () { + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + + var ret = ext.renderer.apply(this, args); + + if (ret === false) { + ret = prevRenderer.apply(this, args); + } + + return ret; + }; + } else { + extensions.renderers[ext.name] = ext.renderer; + } + } + + if (ext.tokenizer) { + // Tokenizer Extensions + 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); + } else { + extensions[ext.level] = [ext.tokenizer]; + } + + if (ext.start) { + // Function to check for start of token + if (ext.level === 'block') { + if (extensions.startBlock) { + extensions.startBlock.push(ext.start); + } else { + extensions.startBlock = [ext.start]; + } + } else if (ext.level === 'inline') { + if (extensions.startInline) { + extensions.startInline.push(ext.start); + } else { + extensions.startInline = [ext.start]; + } + } + } + } + + if (ext.childTokens) { + // Child tokens to be visited by walkTokens + extensions.childTokens[ext.name] = ext.childTokens; + } + }); + } // ==-- Parse "overwrite" extensions --== // + + + if (pack.renderer) { + (function () { + var renderer = marked.defaults.renderer || new Renderer(); + + var _loop = function _loop(prop) { + var prevRenderer = renderer[prop]; // Replace renderer with func to run extension, but fall back if false + + renderer[prop] = function () { + for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + args[_key3] = arguments[_key3]; + } + + var ret = pack.renderer[prop].apply(renderer, args); + + if (ret === false) { + ret = prevRenderer.apply(renderer, args); + } + + return ret; + }; + }; + + for (var prop in pack.renderer) { + _loop(prop); + } + + opts.renderer = renderer; + })(); + } + + if (pack.tokenizer) { + (function () { + var tokenizer = marked.defaults.tokenizer || new Tokenizer(); + + var _loop2 = function _loop2(prop) { + var prevTokenizer = tokenizer[prop]; // Replace tokenizer with func to run extension, but fall back if false + + tokenizer[prop] = function () { + for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { + args[_key4] = arguments[_key4]; + } + + var ret = pack.tokenizer[prop].apply(tokenizer, args); + + if (ret === false) { + ret = prevTokenizer.apply(tokenizer, args); + } + + return ret; + }; + }; + + for (var prop in pack.tokenizer) { + _loop2(prop); + } + + opts.tokenizer = tokenizer; + })(); + } // ==-- Parse WalkTokens extensions --== // + + + if (pack.walkTokens) { + var _walkTokens = marked.defaults.walkTokens; + + opts.walkTokens = function (token) { + pack.walkTokens.call(this, token); + + if (_walkTokens) { + _walkTokens.call(this, token); + } + }; + } + + if (hasExtensions) { + opts.extensions = extensions; + } + + marked.setOptions(opts); + }); + }; + /** + * Run callback for every token + */ + + + marked.walkTokens = function (tokens, callback) { + var _loop3 = function _loop3() { + var token = _step.value; + callback.call(marked, token); + + switch (token.type) { + case 'table': + { + for (var _iterator2 = _createForOfIteratorHelperLoose(token.header), _step2; !(_step2 = _iterator2()).done;) { + var cell = _step2.value; + marked.walkTokens(cell.tokens, callback); + } + + for (var _iterator3 = _createForOfIteratorHelperLoose(token.rows), _step3; !(_step3 = _iterator3()).done;) { + var row = _step3.value; + + for (var _iterator4 = _createForOfIteratorHelperLoose(row), _step4; !(_step4 = _iterator4()).done;) { + var _cell = _step4.value; + marked.walkTokens(_cell.tokens, callback); + } + } + + break; + } + + case 'list': + { + marked.walkTokens(token.items, callback); + break; + } + + default: + { + if (marked.defaults.extensions && marked.defaults.extensions.childTokens && marked.defaults.extensions.childTokens[token.type]) { + // Walk any extensions + marked.defaults.extensions.childTokens[token.type].forEach(function (childTokens) { + marked.walkTokens(token[childTokens], callback); + }); + } else if (token.tokens) { + marked.walkTokens(token.tokens, callback); + } + } + } + }; + + for (var _iterator = _createForOfIteratorHelperLoose(tokens), _step; !(_step = _iterator()).done;) { + _loop3(); + } + }; + /** + * Parse Inline + */ + + + marked.parseInline = function (src, opt) { + // throw error in case of non string input + if (typeof src === 'undefined' || src === null) { + throw new Error('marked.parseInline(): input parameter is undefined or null'); + } + + if (typeof src !== 'string') { + throw new Error('marked.parseInline(): input parameter is of type ' + Object.prototype.toString.call(src) + ', string expected'); + } + + opt = merge({}, marked.defaults, opt || {}); + checkSanitizeDeprecation(opt); + + try { + var tokens = Lexer.lexInline(src, opt); + + if (opt.walkTokens) { + marked.walkTokens(tokens, opt.walkTokens); + } + + return Parser.parseInline(tokens, opt); + } catch (e) { + e.message += '\nPlease report this to https://github.com/markedjs/marked.'; + + if (opt.silent) { + return '

    An error occurred:

    ' + escape(e.message + '', true) + '
    '; + } + + throw e; + } + }; + /** + * Expose + */ + + + marked.Parser = Parser; + marked.parser = Parser.parse; + marked.Renderer = Renderer; + marked.TextRenderer = TextRenderer; + marked.Lexer = Lexer; + marked.lexer = Lexer.lex; + marked.Tokenizer = Tokenizer; + marked.Slugger = Slugger; + marked.parse = marked; + var options = marked.options; + var setOptions = marked.setOptions; + var use = marked.use; + var walkTokens = marked.walkTokens; + var parseInline = marked.parseInline; + var parse = marked; + var parser = Parser.parse; + var lexer = Lexer.lex; + + exports.Lexer = Lexer; + exports.Parser = Parser; + exports.Renderer = Renderer; + exports.Slugger = Slugger; + exports.TextRenderer = TextRenderer; + exports.Tokenizer = Tokenizer; + exports["default"] = marked; + exports.getDefaults = getDefaults; + exports.lexer = lexer; + exports.options = options; + exports.parse = parse; + exports.parseInline = parseInline; + exports.parser = parser; + exports.setOptions = setOptions; + exports.use = use; + exports.walkTokens = walkTokens; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); \ No newline at end of file diff --git a/src/renderer/lib/showdown.min.js b/src/renderer/lib/showdown.min.js deleted file mode 100644 index 7ed96f26..00000000 --- a/src/renderer/lib/showdown.min.js +++ /dev/null @@ -1,5531 +0,0 @@ -;/*! showdown v 2.0.0-alpha1 - 14-11-2021 */ -(function(){ - /** - * Created by Tivie on 13-07-2015. - */ - - function getDefaultOpts (simple) { - 'use strict'; - - var defaultOptions = { - omitExtraWLInCodeBlocks: { - defaultValue: false, - describe: 'Omit the default extra whiteline added to code blocks', - type: 'boolean' - }, - noHeaderId: { - defaultValue: false, - describe: 'Turn on/off generated header id', - type: 'boolean' - }, - prefixHeaderId: { - defaultValue: false, - describe: 'Add a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to true will add a generic \'section-\' prefix', - type: 'string' - }, - rawPrefixHeaderId: { - defaultValue: false, - describe: 'Setting this option to true will prevent showdown from modifying the prefix. This might result in malformed IDs (if, for instance, the " char is used in the prefix)', - type: 'boolean' - }, - ghCompatibleHeaderId: { - defaultValue: false, - describe: 'Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)', - type: 'boolean' - }, - rawHeaderId: { - defaultValue: false, - describe: 'Remove only spaces, \' and " from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids', - type: 'boolean' - }, - headerLevelStart: { - defaultValue: false, - describe: 'The header blocks level start', - type: 'integer' - }, - parseImgDimensions: { - defaultValue: false, - describe: 'Turn on/off image dimension parsing', - type: 'boolean' - }, - simplifiedAutoLink: { - defaultValue: false, - describe: 'Turn on/off GFM autolink style', - type: 'boolean' - }, - literalMidWordUnderscores: { - defaultValue: false, - describe: 'Parse midword underscores as literal underscores', - type: 'boolean' - }, - literalMidWordAsterisks: { - defaultValue: false, - describe: 'Parse midword asterisks as literal asterisks', - type: 'boolean' - }, - strikethrough: { - defaultValue: false, - describe: 'Turn on/off strikethrough support', - type: 'boolean' - }, - tables: { - defaultValue: false, - describe: 'Turn on/off tables support', - type: 'boolean' - }, - tablesHeaderId: { - defaultValue: false, - describe: 'Add an id to table headers', - type: 'boolean' - }, - ghCodeBlocks: { - defaultValue: true, - describe: 'Turn on/off GFM fenced code blocks support', - type: 'boolean' - }, - tasklists: { - defaultValue: false, - describe: 'Turn on/off GFM tasklist support', - type: 'boolean' - }, - smoothLivePreview: { - defaultValue: false, - describe: 'Prevents weird effects in live previews due to incomplete input', - type: 'boolean' - }, - smartIndentationFix: { - defaultValue: false, - description: 'Tries to smartly fix indentation in es6 strings', - type: 'boolean' - }, - disableForced4SpacesIndentedSublists: { - defaultValue: false, - description: 'Disables the requirement of indenting nested sublists by 4 spaces', - type: 'boolean' - }, - simpleLineBreaks: { - defaultValue: false, - description: 'Parses simple line breaks as
    (GFM Style)', - type: 'boolean' - }, - requireSpaceBeforeHeadingText: { - defaultValue: false, - description: 'Makes adding a space between `#` and the header text mandatory (GFM Style)', - type: 'boolean' - }, - ghMentions: { - defaultValue: false, - description: 'Enables github @mentions', - type: 'boolean' - }, - ghMentionsLink: { - defaultValue: 'https://github.com/{u}', - description: 'Changes the link generated by @mentions. Only applies if ghMentions option is enabled.', - type: 'string' - }, - encodeEmails: { - defaultValue: true, - description: 'Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities', - type: 'boolean' - }, - openLinksInNewWindow: { - defaultValue: false, - description: 'Open all links in new windows', - type: 'boolean' - }, - backslashEscapesHTMLTags: { - defaultValue: false, - description: 'Support for HTML Tag escaping. ex: \
    foo\
    ', - type: 'boolean' - }, - emoji: { - defaultValue: false, - description: 'Enable emoji support. Ex: `this is a :smile: emoji`', - type: 'boolean' - }, - underline: { - defaultValue: false, - description: 'Enable support for underline. Syntax is double or triple underscores: `__underline word__`. With this option enabled, underscores no longer parses into `` and ``', - type: 'boolean' - }, - ellipsis: { - defaultValue: true, - description: 'Replaces three dots with the ellipsis unicode character', - type: 'boolean' - }, - completeHTMLDocument: { - defaultValue: false, - description: 'Outputs a complete html document, including ``, `` and `` tags', - type: 'boolean' - }, - metadata: { - defaultValue: false, - description: 'Enable support for document metadata (defined at the top of the document between `«««` and `»»»` or between `---` and `---`).', - type: 'boolean' - }, - splitAdjacentBlockquotes: { - defaultValue: false, - description: 'Split adjacent blockquote blocks', - type: 'boolean' - }, - relativePathBaseUrl: { - defaultValue: false, - describe: 'Prepends a base URL to relative paths', - type: 'string' - }, - }; - if (simple === false) { - return JSON.parse(JSON.stringify(defaultOptions)); - } - var ret = {}; - for (var opt in defaultOptions) { - if (defaultOptions.hasOwnProperty(opt)) { - ret[opt] = defaultOptions[opt].defaultValue; - } - } - return ret; - } - - function allOptionsOn () { - 'use strict'; - var options = getDefaultOpts(true), - ret = {}; - for (var opt in options) { - if (options.hasOwnProperty(opt)) { - ret[opt] = true; - } - } - return ret; - } - - /** - * Created by Tivie on 06-01-2015. - */ -// Private properties - var showdown = {}, - parsers = {}, - extensions = {}, - globalOptions = getDefaultOpts(true), - setFlavor = 'vanilla', - flavor = { - github: { - omitExtraWLInCodeBlocks: true, - simplifiedAutoLink: true, - literalMidWordUnderscores: true, - strikethrough: true, - tables: true, - tablesHeaderId: true, - ghCodeBlocks: true, - tasklists: true, - disableForced4SpacesIndentedSublists: true, - simpleLineBreaks: true, - requireSpaceBeforeHeadingText: true, - ghCompatibleHeaderId: true, - ghMentions: true, - backslashEscapesHTMLTags: true, - emoji: true, - splitAdjacentBlockquotes: true - }, - original: { - noHeaderId: true, - ghCodeBlocks: false - }, - ghost: { - omitExtraWLInCodeBlocks: true, - parseImgDimensions: true, - simplifiedAutoLink: true, - literalMidWordUnderscores: true, - strikethrough: true, - tables: true, - tablesHeaderId: true, - ghCodeBlocks: true, - tasklists: true, - smoothLivePreview: true, - simpleLineBreaks: true, - requireSpaceBeforeHeadingText: true, - ghMentions: false, - encodeEmails: true - }, - vanilla: getDefaultOpts(true), - allOn: allOptionsOn() - }; - - /** - * helper namespace - * @type {{}} - */ - showdown.helper = {}; - - /** - * TODO LEGACY SUPPORT CODE - * @type {{}} - */ - showdown.extensions = {}; - - /** - * Set a global option - * @static - * @param {string} key - * @param {*} value - * @returns {showdown} - */ - showdown.setOption = function (key, value) { - 'use strict'; - globalOptions[key] = value; - return this; - }; - - /** - * Get a global option - * @static - * @param {string} key - * @returns {*} - */ - showdown.getOption = function (key) { - 'use strict'; - return globalOptions[key]; - }; - - /** - * Get the global options - * @static - * @returns {{}} - */ - showdown.getOptions = function () { - 'use strict'; - return globalOptions; - }; - - /** - * Reset global options to the default values - * @static - */ - showdown.resetOptions = function () { - 'use strict'; - globalOptions = getDefaultOpts(true); - }; - - /** - * Set the flavor showdown should use as default - * @param {string} name - */ - showdown.setFlavor = function (name) { - 'use strict'; - if (!flavor.hasOwnProperty(name)) { - throw Error(name + ' flavor was not found'); - } - showdown.resetOptions(); - var preset = flavor[name]; - setFlavor = name; - for (var option in preset) { - if (preset.hasOwnProperty(option)) { - globalOptions[option] = preset[option]; - } - } - }; - - /** - * Get the currently set flavor - * @returns {string} - */ - showdown.getFlavor = function () { - 'use strict'; - return setFlavor; - }; - - /** - * Get the options of a specified flavor. Returns undefined if the flavor was not found - * @param {string} name Name of the flavor - * @returns {{}|undefined} - */ - showdown.getFlavorOptions = function (name) { - 'use strict'; - if (flavor.hasOwnProperty(name)) { - return flavor[name]; - } - }; - - /** - * Get the default options - * @static - * @param {boolean} [simple=true] - * @returns {{}} - */ - showdown.getDefaultOptions = function (simple) { - 'use strict'; - return getDefaultOpts(simple); - }; - - /** - * Get or set a subParser - * - * subParser(name) - Get a registered subParser - * subParser(name, func) - Register a subParser - * @static - * @param {string} name - * @param {function} [func] - * @returns {*} - */ - showdown.subParser = function (name, func) { - 'use strict'; - if (showdown.helper.isString(name)) { - if (typeof func !== 'undefined') { - parsers[name] = func; - } else { - if (parsers.hasOwnProperty(name)) { - return parsers[name]; - } else { - throw Error('SubParser named ' + name + ' not registered!'); - } - } - } else { - throw Error('showdown.subParser function first argument must be a string (the name of the subparser)'); - } - }; - - /** - * Gets or registers an extension - * @static - * @param {string} name - * @param {object|function=} ext - * @returns {*} - */ - showdown.extension = function (name, ext) { - 'use strict'; - - if (!showdown.helper.isString(name)) { - throw Error('Extension \'name\' must be a string'); - } - - name = showdown.helper.stdExtName(name); - - // Getter - if (showdown.helper.isUndefined(ext)) { - if (!extensions.hasOwnProperty(name)) { - throw Error('Extension named ' + name + ' is not registered!'); - } - return extensions[name]; - - // Setter - } else { - // Expand extension if it's wrapped in a function - if (typeof ext === 'function') { - ext = ext(); - } - - // Ensure extension is an array - if (!showdown.helper.isArray(ext)) { - ext = [ext]; - } - - var validExtension = validate(ext, name); - - if (validExtension.valid) { - extensions[name] = ext; - } else { - throw Error(validExtension.error); - } - } - }; - - /** - * Gets all extensions registered - * @returns {{}} - */ - showdown.getAllExtensions = function () { - 'use strict'; - return extensions; - }; - - /** - * Remove an extension - * @param {string} name - */ - showdown.removeExtension = function (name) { - 'use strict'; - delete extensions[name]; - }; - - /** - * Removes all extensions - */ - showdown.resetExtensions = function () { - 'use strict'; - extensions = {}; - }; - - /** - * Validate extension - * @param {array} extension - * @param {string} name - * @returns {{valid: boolean, error: string}} - */ - function validate (extension, name) { - 'use strict'; - - var errMsg = (name) ? 'Error in ' + name + ' extension->' : 'Error in unnamed extension', - ret = { - valid: true, - error: '' - }; - - if (!showdown.helper.isArray(extension)) { - extension = [extension]; - } - - for (var i = 0; i < extension.length; ++i) { - var baseMsg = errMsg + ' sub-extension ' + i + ': ', - ext = extension[i]; - if (typeof ext !== 'object') { - ret.valid = false; - ret.error = baseMsg + 'must be an object, but ' + typeof ext + ' given'; - return ret; - } - - if (!showdown.helper.isString(ext.type)) { - ret.valid = false; - ret.error = baseMsg + 'property "type" must be a string, but ' + typeof ext.type + ' given'; - return ret; - } - - var type = ext.type = ext.type.toLowerCase(); - - // normalize extension type - if (type === 'language') { - type = ext.type = 'lang'; - } - - if (type === 'html') { - type = ext.type = 'output'; - } - - if (type !== 'lang' && type !== 'output' && type !== 'listener') { - ret.valid = false; - ret.error = baseMsg + 'type ' + type + ' is not recognized. Valid values: "lang/language", "output/html" or "listener"'; - return ret; - } - - if (type === 'listener') { - if (showdown.helper.isUndefined(ext.listeners)) { - ret.valid = false; - ret.error = baseMsg + '. Extensions of type "listener" must have a property called "listeners"'; - return ret; - } - } else { - if (showdown.helper.isUndefined(ext.filter) && showdown.helper.isUndefined(ext.regex)) { - ret.valid = false; - ret.error = baseMsg + type + ' extensions must define either a "regex" property or a "filter" method'; - return ret; - } - } - - if (ext.listeners) { - if (typeof ext.listeners !== 'object') { - ret.valid = false; - ret.error = baseMsg + '"listeners" property must be an object but ' + typeof ext.listeners + ' given'; - return ret; - } - for (var ln in ext.listeners) { - if (ext.listeners.hasOwnProperty(ln)) { - if (typeof ext.listeners[ln] !== 'function') { - ret.valid = false; - ret.error = baseMsg + '"listeners" property must be an hash of [event name]: [callback]. listeners.' + ln + - ' must be a function but ' + typeof ext.listeners[ln] + ' given'; - return ret; - } - } - } - } - - if (ext.filter) { - if (typeof ext.filter !== 'function') { - ret.valid = false; - ret.error = baseMsg + '"filter" must be a function, but ' + typeof ext.filter + ' given'; - return ret; - } - } else if (ext.regex) { - if (showdown.helper.isString(ext.regex)) { - ext.regex = new RegExp(ext.regex, 'g'); - } - if (!(ext.regex instanceof RegExp)) { - ret.valid = false; - ret.error = baseMsg + '"regex" property must either be a string or a RegExp object, but ' + typeof ext.regex + ' given'; - return ret; - } - if (showdown.helper.isUndefined(ext.replace)) { - ret.valid = false; - ret.error = baseMsg + '"regex" extensions must implement a replace string or function'; - return ret; - } - } - } - return ret; - } - - /** - * Validate extension - * @param {object} ext - * @returns {boolean} - */ - showdown.validateExtension = function (ext) { - 'use strict'; - - var validateExtension = validate(ext, null); - if (!validateExtension.valid) { - console.warn(validateExtension.error); - return false; - } - return true; - }; - - /** - * showdownjs helper functions - */ - - if (!showdown.hasOwnProperty('helper')) { - showdown.helper = {}; - } - - if (typeof this.document === 'undefined' && typeof this.window === 'undefined') { - var jsdom = require('jsdom'); - this.window = new jsdom.JSDOM('', {}).window; // jshint ignore:line - } - showdown.helper.document = this.window.document; - - /** - * Check if var is string - * @static - * @param {string} a - * @returns {boolean} - */ - showdown.helper.isString = function (a) { - 'use strict'; - return (typeof a === 'string' || a instanceof String); - }; - - /** - * Check if var is a function - * @static - * @param {*} a - * @returns {boolean} - */ - showdown.helper.isFunction = function (a) { - 'use strict'; - var getType = {}; - return a && getType.toString.call(a) === '[object Function]'; - }; - - /** - * isArray helper function - * @static - * @param {*} a - * @returns {boolean} - */ - showdown.helper.isArray = function (a) { - 'use strict'; - return Array.isArray(a); - }; - - /** - * Check if value is undefined - * @static - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. - */ - showdown.helper.isUndefined = function (value) { - 'use strict'; - return typeof value === 'undefined'; - }; - - /** - * ForEach helper function - * Iterates over Arrays and Objects (own properties only) - * @static - * @param {*} obj - * @param {function} callback Accepts 3 params: 1. value, 2. key, 3. the original array/object - */ - showdown.helper.forEach = function (obj, callback) { - 'use strict'; - // check if obj is defined - if (showdown.helper.isUndefined(obj)) { - throw new Error('obj param is required'); - } - - if (showdown.helper.isUndefined(callback)) { - throw new Error('callback param is required'); - } - - if (!showdown.helper.isFunction(callback)) { - throw new Error('callback param must be a function/closure'); - } - - if (typeof obj.forEach === 'function') { - obj.forEach(callback); - } else if (showdown.helper.isArray(obj)) { - for (var i = 0; i < obj.length; i++) { - callback(obj[i], i, obj); - } - } else if (typeof (obj) === 'object') { - for (var prop in obj) { - if (obj.hasOwnProperty(prop)) { - callback(obj[prop], prop, obj); - } - } - } else { - throw new Error('obj does not seem to be an array or an iterable object'); - } - }; - - /** - * Standardidize extension name - * @static - * @param {string} s extension name - * @returns {string} - */ - showdown.helper.stdExtName = function (s) { - 'use strict'; - return s.replace(/[_?*+\/\\.^-]/g, '').replace(/\s/g, '').toLowerCase(); - }; - - function escapeCharactersCallback (wholeMatch, m1) { - 'use strict'; - var charCodeToEscape = m1.charCodeAt(0); - return '¨E' + charCodeToEscape + 'E'; - } - - /** - * Callback used to escape characters when passing through String.replace - * @static - * @param {string} wholeMatch - * @param {string} m1 - * @returns {string} - */ - showdown.helper.escapeCharactersCallback = escapeCharactersCallback; - - /** - * Escape characters in a string - * @static - * @param {string} text - * @param {string} charsToEscape - * @param {boolean} afterBackslash - * @returns {XML|string|void|*} - */ - showdown.helper.escapeCharacters = function (text, charsToEscape, afterBackslash) { - 'use strict'; - // First we have to escape the escape characters so that - // we can build a character class out of them - var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])'; - - if (afterBackslash) { - regexString = '\\\\' + regexString; - } - - var regex = new RegExp(regexString, 'g'); - text = text.replace(regex, escapeCharactersCallback); - - return text; - }; - - var rgxFindMatchPos = function (str, left, right, flags) { - 'use strict'; - var f = flags || '', - g = f.indexOf('g') > -1, - x = new RegExp(left + '|' + right, 'g' + f.replace(/g/g, '')), - l = new RegExp(left, f.replace(/g/g, '')), - pos = [], - t, s, m, start, end; - - do { - t = 0; - while ((m = x.exec(str))) { - if (l.test(m[0])) { - if (!(t++)) { - s = x.lastIndex; - start = s - m[0].length; - } - } else if (t) { - if (!--t) { - end = m.index + m[0].length; - var obj = { - left: {start: start, end: s}, - match: {start: s, end: m.index}, - right: {start: m.index, end: end}, - wholeMatch: {start: start, end: end} - }; - pos.push(obj); - if (!g) { - return pos; - } - } - } - } - } while (t && (x.lastIndex = s)); - - return pos; - }; - - /** - * matchRecursiveRegExp - * - * (c) 2007 Steven Levithan - * MIT License - * - * Accepts a string to search, a left and right format delimiter - * as regex patterns, and optional regex flags. Returns an array - * of matches, allowing nested instances of left/right delimiters. - * Use the "g" flag to return all matches, otherwise only the - * first is returned. Be careful to ensure that the left and - * right format delimiters produce mutually exclusive matches. - * Backreferences are not supported within the right delimiter - * due to how it is internally combined with the left delimiter. - * When matching strings whose format delimiters are unbalanced - * to the left or right, the output is intentionally as a - * conventional regex library with recursion support would - * produce, e.g. "<" and ">" both produce ["x"] when using - * "<" and ">" as the delimiters (both strings contain a single, - * balanced instance of ""). - * - * examples: - * matchRecursiveRegExp("test", "\\(", "\\)") - * returns: [] - * matchRecursiveRegExp(">>t<>", "<", ">", "g") - * returns: ["t<>", ""] - * matchRecursiveRegExp("
    test
    ", "]*>", "", "gi") - * returns: ["test"] - */ - showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) { - 'use strict'; - - var matchPos = rgxFindMatchPos (str, left, right, flags), - results = []; - - for (var i = 0; i < matchPos.length; ++i) { - results.push([ - str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end), - str.slice(matchPos[i].match.start, matchPos[i].match.end), - str.slice(matchPos[i].left.start, matchPos[i].left.end), - str.slice(matchPos[i].right.start, matchPos[i].right.end) - ]); - } - return results; - }; - - /** - * - * @param {string} str - * @param {string|function} replacement - * @param {string} left - * @param {string} right - * @param {string} flags - * @returns {string} - */ - showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) { - 'use strict'; - - if (!showdown.helper.isFunction(replacement)) { - var repStr = replacement; - replacement = function () { - return repStr; - }; - } - - var matchPos = rgxFindMatchPos(str, left, right, flags), - finalStr = str, - lng = matchPos.length; - - if (lng > 0) { - var bits = []; - if (matchPos[0].wholeMatch.start !== 0) { - bits.push(str.slice(0, matchPos[0].wholeMatch.start)); - } - for (var i = 0; i < lng; ++i) { - bits.push( - replacement( - str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end), - str.slice(matchPos[i].match.start, matchPos[i].match.end), - str.slice(matchPos[i].left.start, matchPos[i].left.end), - str.slice(matchPos[i].right.start, matchPos[i].right.end) - ) - ); - if (i < lng - 1) { - bits.push(str.slice(matchPos[i].wholeMatch.end, matchPos[i + 1].wholeMatch.start)); - } - } - if (matchPos[lng - 1].wholeMatch.end < str.length) { - bits.push(str.slice(matchPos[lng - 1].wholeMatch.end)); - } - finalStr = bits.join(''); - } - return finalStr; - }; - - /** - * Returns the index within the passed String object of the first occurrence of the specified regex, - * starting the search at fromIndex. Returns -1 if the value is not found. - * - * @param {string} str string to search - * @param {RegExp} regex Regular expression to search - * @param {int} [fromIndex = 0] Index to start the search - * @returns {Number} - * @throws InvalidArgumentError - */ - showdown.helper.regexIndexOf = function (str, regex, fromIndex) { - 'use strict'; - if (!showdown.helper.isString(str)) { - throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string'; - } - if (regex instanceof RegExp === false) { - throw 'InvalidArgumentError: second parameter of showdown.helper.regexIndexOf function must be an instance of RegExp'; - } - var indexOf = str.substring(fromIndex || 0).search(regex); - return (indexOf >= 0) ? (indexOf + (fromIndex || 0)) : indexOf; - }; - - /** - * Splits the passed string object at the defined index, and returns an array composed of the two substrings - * @param {string} str string to split - * @param {int} index index to split string at - * @returns {[string,string]} - * @throws InvalidArgumentError - */ - showdown.helper.splitAtIndex = function (str, index) { - 'use strict'; - if (!showdown.helper.isString(str)) { - throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string'; - } - return [str.substring(0, index), str.substring(index)]; - }; - - /** - * Obfuscate an e-mail address through the use of Character Entities, - * transforming ASCII characters into their equivalent decimal or hex entities. - * - * Since it has a random component, subsequent calls to this function produce different results - * - * @param {string} mail - * @returns {string} - */ - showdown.helper.encodeEmailAddress = function (mail) { - 'use strict'; - var encode = [ - function (ch) { - return '&#' + ch.charCodeAt(0) + ';'; - }, - function (ch) { - return '&#x' + ch.charCodeAt(0).toString(16) + ';'; - }, - function (ch) { - return ch; - } - ]; - - mail = mail.replace(/./g, function (ch) { - if (ch === '@') { - // this *must* be encoded. I insist. - ch = encode[Math.floor(Math.random() * 2)](ch); - } else { - var r = Math.random(); - // roughly 10% raw, 45% hex, 45% dec - ch = ( - r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch) - ); - } - return ch; - }); - - return mail; - }; - - /** - * - * @param str - * @param targetLength - * @param padString - * @returns {string} - */ - showdown.helper.padEnd = function padEnd (str, targetLength, padString) { - 'use strict'; - /*jshint bitwise: false*/ - // eslint-disable-next-line space-infix-ops - targetLength = targetLength>>0; //floor if number or convert non-number to 0; - /*jshint bitwise: true*/ - padString = String(padString || ' '); - if (str.length > targetLength) { - return String(str); - } else { - targetLength = targetLength - str.length; - if (targetLength > padString.length) { - padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed - } - return String(str) + padString.slice(0,targetLength); - } - }; - - /** - * Unescape HTML entities - * @param txt - * @returns {string} - */ - showdown.helper.unescapeHTMLEntities = function (txt) { - 'use strict'; - - return txt - .replace(/"/g, '"') - .replace(/</g, '<') - .replace(/>/g, '>') - .replace(/&/g, '&'); - }; - - showdown.helper._hashHTMLSpan = function (html, globals) { - return '¨C' + (globals.gHtmlSpans.push(html) - 1) + 'C'; - }; - - /** - * Prepends a base URL to relative paths. - * - * @param {string} baseUrl the base URL to prepend to a relative path - * @param {string} url the path to modify, which may be relative - * @returns {string} the full URL - */ - showdown.helper.applyBaseUrl = function (baseUrl, url) { - // Only prepend if given a base URL and the path is not absolute. - if (baseUrl && !this.isAbsolutePath(url)) { - var urlResolve = require('url').resolve; - url = urlResolve(baseUrl, url); - } - - return url; - }; - - /** - * Checks if the given path is absolute. - * - * @param {string} path the path to test for absolution - * @returns {boolean} `true` if the given path is absolute, else `false` - */ - showdown.helper.isAbsolutePath = function (path) { - // Absolute paths begin with '[protocol:]//' or '#' (anchors) - return /(^([a-z]+:)?\/\/)|(^#)/i.test(path); - }; - - /** - * Showdown's Event Object - * @param {string} name Name of the event - * @param {string} text Text - * @param {{}} params optional. params of the event - * @constructor - */ - showdown.helper.Event = function (name, text, params) { - 'use strict'; - - var regexp = params.regexp || null; - var matches = params.matches || {}; - var options = params.options || {}; - var converter = params.converter || null; - var globals = params.globals || {}; - - /** - * Get the name of the event - * @returns {string} - */ - this.getName = function () { - return name; - }; - - this.getEventName = function () { - return name; - }; - - this._stopExecution = false; - - this.parsedText = params.parsedText || null; - - this.getRegexp = function () { - return regexp; - }; - - this.getOptions = function () { - return options; - }; - - this.getConverter = function () { - return converter; - }; - - this.getGlobals = function () { - return globals; - }; - - this.getCapturedText = function () { - return text; - }; - - this.getText = function () { - return text; - }; - - this.setText = function (newText) { - text = newText; - }; - - this.getMatches = function () { - return matches; - }; - - this.setMatches = function (newMatches) { - matches = newMatches; - }; - - this.preventDefault = function (bool) { - this._stopExecution = !bool; - }; - }; - - /** - * POLYFILLS - */ -// use this instead of builtin is undefined for IE8 compatibility - if (typeof (console) === 'undefined') { - console = { - warn: function (msg) { - 'use strict'; - alert(msg); - }, - log: function (msg) { - 'use strict'; - alert(msg); - }, - error: function (msg) { - 'use strict'; - throw msg; - } - }; - } - - /** - * Common regexes. - * We declare some common regexes to improve performance - */ - showdown.helper.regexes = { - asteriskDashTildeAndColon: /([*_:~])/g, - asteriskDashAndTilde: /([*_~])/g - }; - - /** - * EMOJIS LIST - */ - showdown.helper.emojis = { - '+1':'\ud83d\udc4d', - '-1':'\ud83d\udc4e', - '100':'\ud83d\udcaf', - '1234':'\ud83d\udd22', - '1st_place_medal':'\ud83e\udd47', - '2nd_place_medal':'\ud83e\udd48', - '3rd_place_medal':'\ud83e\udd49', - '8ball':'\ud83c\udfb1', - 'a':'\ud83c\udd70\ufe0f', - 'ab':'\ud83c\udd8e', - 'abc':'\ud83d\udd24', - 'abcd':'\ud83d\udd21', - 'accept':'\ud83c\ude51', - 'aerial_tramway':'\ud83d\udea1', - 'airplane':'\u2708\ufe0f', - 'alarm_clock':'\u23f0', - 'alembic':'\u2697\ufe0f', - 'alien':'\ud83d\udc7d', - 'ambulance':'\ud83d\ude91', - 'amphora':'\ud83c\udffa', - 'anchor':'\u2693\ufe0f', - 'angel':'\ud83d\udc7c', - 'anger':'\ud83d\udca2', - 'angry':'\ud83d\ude20', - 'anguished':'\ud83d\ude27', - 'ant':'\ud83d\udc1c', - 'apple':'\ud83c\udf4e', - 'aquarius':'\u2652\ufe0f', - 'aries':'\u2648\ufe0f', - 'arrow_backward':'\u25c0\ufe0f', - 'arrow_double_down':'\u23ec', - 'arrow_double_up':'\u23eb', - 'arrow_down':'\u2b07\ufe0f', - 'arrow_down_small':'\ud83d\udd3d', - 'arrow_forward':'\u25b6\ufe0f', - 'arrow_heading_down':'\u2935\ufe0f', - 'arrow_heading_up':'\u2934\ufe0f', - 'arrow_left':'\u2b05\ufe0f', - 'arrow_lower_left':'\u2199\ufe0f', - 'arrow_lower_right':'\u2198\ufe0f', - 'arrow_right':'\u27a1\ufe0f', - 'arrow_right_hook':'\u21aa\ufe0f', - 'arrow_up':'\u2b06\ufe0f', - 'arrow_up_down':'\u2195\ufe0f', - 'arrow_up_small':'\ud83d\udd3c', - 'arrow_upper_left':'\u2196\ufe0f', - 'arrow_upper_right':'\u2197\ufe0f', - 'arrows_clockwise':'\ud83d\udd03', - 'arrows_counterclockwise':'\ud83d\udd04', - 'art':'\ud83c\udfa8', - 'articulated_lorry':'\ud83d\ude9b', - 'artificial_satellite':'\ud83d\udef0', - 'astonished':'\ud83d\ude32', - 'athletic_shoe':'\ud83d\udc5f', - 'atm':'\ud83c\udfe7', - 'atom_symbol':'\u269b\ufe0f', - 'avocado':'\ud83e\udd51', - 'b':'\ud83c\udd71\ufe0f', - 'baby':'\ud83d\udc76', - 'baby_bottle':'\ud83c\udf7c', - 'baby_chick':'\ud83d\udc24', - 'baby_symbol':'\ud83d\udebc', - 'back':'\ud83d\udd19', - 'bacon':'\ud83e\udd53', - 'badminton':'\ud83c\udff8', - 'baggage_claim':'\ud83d\udec4', - 'baguette_bread':'\ud83e\udd56', - 'balance_scale':'\u2696\ufe0f', - 'balloon':'\ud83c\udf88', - 'ballot_box':'\ud83d\uddf3', - 'ballot_box_with_check':'\u2611\ufe0f', - 'bamboo':'\ud83c\udf8d', - 'banana':'\ud83c\udf4c', - 'bangbang':'\u203c\ufe0f', - 'bank':'\ud83c\udfe6', - 'bar_chart':'\ud83d\udcca', - 'barber':'\ud83d\udc88', - 'baseball':'\u26be\ufe0f', - 'basketball':'\ud83c\udfc0', - 'basketball_man':'\u26f9\ufe0f', - 'basketball_woman':'\u26f9\ufe0f‍\u2640\ufe0f', - 'bat':'\ud83e\udd87', - 'bath':'\ud83d\udec0', - 'bathtub':'\ud83d\udec1', - 'battery':'\ud83d\udd0b', - 'beach_umbrella':'\ud83c\udfd6', - 'bear':'\ud83d\udc3b', - 'bed':'\ud83d\udecf', - 'bee':'\ud83d\udc1d', - 'beer':'\ud83c\udf7a', - 'beers':'\ud83c\udf7b', - 'beetle':'\ud83d\udc1e', - 'beginner':'\ud83d\udd30', - 'bell':'\ud83d\udd14', - 'bellhop_bell':'\ud83d\udece', - 'bento':'\ud83c\udf71', - 'biking_man':'\ud83d\udeb4', - 'bike':'\ud83d\udeb2', - 'biking_woman':'\ud83d\udeb4‍\u2640\ufe0f', - 'bikini':'\ud83d\udc59', - 'biohazard':'\u2623\ufe0f', - 'bird':'\ud83d\udc26', - 'birthday':'\ud83c\udf82', - 'black_circle':'\u26ab\ufe0f', - 'black_flag':'\ud83c\udff4', - 'black_heart':'\ud83d\udda4', - 'black_joker':'\ud83c\udccf', - 'black_large_square':'\u2b1b\ufe0f', - 'black_medium_small_square':'\u25fe\ufe0f', - 'black_medium_square':'\u25fc\ufe0f', - 'black_nib':'\u2712\ufe0f', - 'black_small_square':'\u25aa\ufe0f', - 'black_square_button':'\ud83d\udd32', - 'blonde_man':'\ud83d\udc71', - 'blonde_woman':'\ud83d\udc71‍\u2640\ufe0f', - 'blossom':'\ud83c\udf3c', - 'blowfish':'\ud83d\udc21', - 'blue_book':'\ud83d\udcd8', - 'blue_car':'\ud83d\ude99', - 'blue_heart':'\ud83d\udc99', - 'blush':'\ud83d\ude0a', - 'boar':'\ud83d\udc17', - 'boat':'\u26f5\ufe0f', - 'bomb':'\ud83d\udca3', - 'book':'\ud83d\udcd6', - 'bookmark':'\ud83d\udd16', - 'bookmark_tabs':'\ud83d\udcd1', - 'books':'\ud83d\udcda', - 'boom':'\ud83d\udca5', - 'boot':'\ud83d\udc62', - 'bouquet':'\ud83d\udc90', - 'bowing_man':'\ud83d\ude47', - 'bow_and_arrow':'\ud83c\udff9', - 'bowing_woman':'\ud83d\ude47‍\u2640\ufe0f', - 'bowling':'\ud83c\udfb3', - 'boxing_glove':'\ud83e\udd4a', - 'boy':'\ud83d\udc66', - 'bread':'\ud83c\udf5e', - 'bride_with_veil':'\ud83d\udc70', - 'bridge_at_night':'\ud83c\udf09', - 'briefcase':'\ud83d\udcbc', - 'broken_heart':'\ud83d\udc94', - 'bug':'\ud83d\udc1b', - 'building_construction':'\ud83c\udfd7', - 'bulb':'\ud83d\udca1', - 'bullettrain_front':'\ud83d\ude85', - 'bullettrain_side':'\ud83d\ude84', - 'burrito':'\ud83c\udf2f', - 'bus':'\ud83d\ude8c', - 'business_suit_levitating':'\ud83d\udd74', - 'busstop':'\ud83d\ude8f', - 'bust_in_silhouette':'\ud83d\udc64', - 'busts_in_silhouette':'\ud83d\udc65', - 'butterfly':'\ud83e\udd8b', - 'cactus':'\ud83c\udf35', - 'cake':'\ud83c\udf70', - 'calendar':'\ud83d\udcc6', - 'call_me_hand':'\ud83e\udd19', - 'calling':'\ud83d\udcf2', - 'camel':'\ud83d\udc2b', - 'camera':'\ud83d\udcf7', - 'camera_flash':'\ud83d\udcf8', - 'camping':'\ud83c\udfd5', - 'cancer':'\u264b\ufe0f', - 'candle':'\ud83d\udd6f', - 'candy':'\ud83c\udf6c', - 'canoe':'\ud83d\udef6', - 'capital_abcd':'\ud83d\udd20', - 'capricorn':'\u2651\ufe0f', - 'car':'\ud83d\ude97', - 'card_file_box':'\ud83d\uddc3', - 'card_index':'\ud83d\udcc7', - 'card_index_dividers':'\ud83d\uddc2', - 'carousel_horse':'\ud83c\udfa0', - 'carrot':'\ud83e\udd55', - 'cat':'\ud83d\udc31', - 'cat2':'\ud83d\udc08', - 'cd':'\ud83d\udcbf', - 'chains':'\u26d3', - 'champagne':'\ud83c\udf7e', - 'chart':'\ud83d\udcb9', - 'chart_with_downwards_trend':'\ud83d\udcc9', - 'chart_with_upwards_trend':'\ud83d\udcc8', - 'checkered_flag':'\ud83c\udfc1', - 'cheese':'\ud83e\uddc0', - 'cherries':'\ud83c\udf52', - 'cherry_blossom':'\ud83c\udf38', - 'chestnut':'\ud83c\udf30', - 'chicken':'\ud83d\udc14', - 'children_crossing':'\ud83d\udeb8', - 'chipmunk':'\ud83d\udc3f', - 'chocolate_bar':'\ud83c\udf6b', - 'christmas_tree':'\ud83c\udf84', - 'church':'\u26ea\ufe0f', - 'cinema':'\ud83c\udfa6', - 'circus_tent':'\ud83c\udfaa', - 'city_sunrise':'\ud83c\udf07', - 'city_sunset':'\ud83c\udf06', - 'cityscape':'\ud83c\udfd9', - 'cl':'\ud83c\udd91', - 'clamp':'\ud83d\udddc', - 'clap':'\ud83d\udc4f', - 'clapper':'\ud83c\udfac', - 'classical_building':'\ud83c\udfdb', - 'clinking_glasses':'\ud83e\udd42', - 'clipboard':'\ud83d\udccb', - 'clock1':'\ud83d\udd50', - 'clock10':'\ud83d\udd59', - 'clock1030':'\ud83d\udd65', - 'clock11':'\ud83d\udd5a', - 'clock1130':'\ud83d\udd66', - 'clock12':'\ud83d\udd5b', - 'clock1230':'\ud83d\udd67', - 'clock130':'\ud83d\udd5c', - 'clock2':'\ud83d\udd51', - 'clock230':'\ud83d\udd5d', - 'clock3':'\ud83d\udd52', - 'clock330':'\ud83d\udd5e', - 'clock4':'\ud83d\udd53', - 'clock430':'\ud83d\udd5f', - 'clock5':'\ud83d\udd54', - 'clock530':'\ud83d\udd60', - 'clock6':'\ud83d\udd55', - 'clock630':'\ud83d\udd61', - 'clock7':'\ud83d\udd56', - 'clock730':'\ud83d\udd62', - 'clock8':'\ud83d\udd57', - 'clock830':'\ud83d\udd63', - 'clock9':'\ud83d\udd58', - 'clock930':'\ud83d\udd64', - 'closed_book':'\ud83d\udcd5', - 'closed_lock_with_key':'\ud83d\udd10', - 'closed_umbrella':'\ud83c\udf02', - 'cloud':'\u2601\ufe0f', - 'cloud_with_lightning':'\ud83c\udf29', - 'cloud_with_lightning_and_rain':'\u26c8', - 'cloud_with_rain':'\ud83c\udf27', - 'cloud_with_snow':'\ud83c\udf28', - 'clown_face':'\ud83e\udd21', - 'clubs':'\u2663\ufe0f', - 'cocktail':'\ud83c\udf78', - 'coffee':'\u2615\ufe0f', - 'coffin':'\u26b0\ufe0f', - 'cold_sweat':'\ud83d\ude30', - 'comet':'\u2604\ufe0f', - 'computer':'\ud83d\udcbb', - 'computer_mouse':'\ud83d\uddb1', - 'confetti_ball':'\ud83c\udf8a', - 'confounded':'\ud83d\ude16', - 'confused':'\ud83d\ude15', - 'congratulations':'\u3297\ufe0f', - 'construction':'\ud83d\udea7', - 'construction_worker_man':'\ud83d\udc77', - 'construction_worker_woman':'\ud83d\udc77‍\u2640\ufe0f', - 'control_knobs':'\ud83c\udf9b', - 'convenience_store':'\ud83c\udfea', - 'cookie':'\ud83c\udf6a', - 'cool':'\ud83c\udd92', - 'policeman':'\ud83d\udc6e', - 'copyright':'\u00a9\ufe0f', - 'corn':'\ud83c\udf3d', - 'couch_and_lamp':'\ud83d\udecb', - 'couple':'\ud83d\udc6b', - 'couple_with_heart_woman_man':'\ud83d\udc91', - 'couple_with_heart_man_man':'\ud83d\udc68‍\u2764\ufe0f‍\ud83d\udc68', - 'couple_with_heart_woman_woman':'\ud83d\udc69‍\u2764\ufe0f‍\ud83d\udc69', - 'couplekiss_man_man':'\ud83d\udc68‍\u2764\ufe0f‍\ud83d\udc8b‍\ud83d\udc68', - 'couplekiss_man_woman':'\ud83d\udc8f', - 'couplekiss_woman_woman':'\ud83d\udc69‍\u2764\ufe0f‍\ud83d\udc8b‍\ud83d\udc69', - 'cow':'\ud83d\udc2e', - 'cow2':'\ud83d\udc04', - 'cowboy_hat_face':'\ud83e\udd20', - 'crab':'\ud83e\udd80', - 'crayon':'\ud83d\udd8d', - 'credit_card':'\ud83d\udcb3', - 'crescent_moon':'\ud83c\udf19', - 'cricket':'\ud83c\udfcf', - 'crocodile':'\ud83d\udc0a', - 'croissant':'\ud83e\udd50', - 'crossed_fingers':'\ud83e\udd1e', - 'crossed_flags':'\ud83c\udf8c', - 'crossed_swords':'\u2694\ufe0f', - 'crown':'\ud83d\udc51', - 'cry':'\ud83d\ude22', - 'crying_cat_face':'\ud83d\ude3f', - 'crystal_ball':'\ud83d\udd2e', - 'cucumber':'\ud83e\udd52', - 'cupid':'\ud83d\udc98', - 'curly_loop':'\u27b0', - 'currency_exchange':'\ud83d\udcb1', - 'curry':'\ud83c\udf5b', - 'custard':'\ud83c\udf6e', - 'customs':'\ud83d\udec3', - 'cyclone':'\ud83c\udf00', - 'dagger':'\ud83d\udde1', - 'dancer':'\ud83d\udc83', - 'dancing_women':'\ud83d\udc6f', - 'dancing_men':'\ud83d\udc6f‍\u2642\ufe0f', - 'dango':'\ud83c\udf61', - 'dark_sunglasses':'\ud83d\udd76', - 'dart':'\ud83c\udfaf', - 'dash':'\ud83d\udca8', - 'date':'\ud83d\udcc5', - 'deciduous_tree':'\ud83c\udf33', - 'deer':'\ud83e\udd8c', - 'department_store':'\ud83c\udfec', - 'derelict_house':'\ud83c\udfda', - 'desert':'\ud83c\udfdc', - 'desert_island':'\ud83c\udfdd', - 'desktop_computer':'\ud83d\udda5', - 'male_detective':'\ud83d\udd75\ufe0f', - 'diamond_shape_with_a_dot_inside':'\ud83d\udca0', - 'diamonds':'\u2666\ufe0f', - 'disappointed':'\ud83d\ude1e', - 'disappointed_relieved':'\ud83d\ude25', - 'dizzy':'\ud83d\udcab', - 'dizzy_face':'\ud83d\ude35', - 'do_not_litter':'\ud83d\udeaf', - 'dog':'\ud83d\udc36', - 'dog2':'\ud83d\udc15', - 'dollar':'\ud83d\udcb5', - 'dolls':'\ud83c\udf8e', - 'dolphin':'\ud83d\udc2c', - 'door':'\ud83d\udeaa', - 'doughnut':'\ud83c\udf69', - 'dove':'\ud83d\udd4a', - 'dragon':'\ud83d\udc09', - 'dragon_face':'\ud83d\udc32', - 'dress':'\ud83d\udc57', - 'dromedary_camel':'\ud83d\udc2a', - 'drooling_face':'\ud83e\udd24', - 'droplet':'\ud83d\udca7', - 'drum':'\ud83e\udd41', - 'duck':'\ud83e\udd86', - 'dvd':'\ud83d\udcc0', - 'e-mail':'\ud83d\udce7', - 'eagle':'\ud83e\udd85', - 'ear':'\ud83d\udc42', - 'ear_of_rice':'\ud83c\udf3e', - 'earth_africa':'\ud83c\udf0d', - 'earth_americas':'\ud83c\udf0e', - 'earth_asia':'\ud83c\udf0f', - 'egg':'\ud83e\udd5a', - 'eggplant':'\ud83c\udf46', - 'eight_pointed_black_star':'\u2734\ufe0f', - 'eight_spoked_asterisk':'\u2733\ufe0f', - 'electric_plug':'\ud83d\udd0c', - 'elephant':'\ud83d\udc18', - 'email':'\u2709\ufe0f', - 'end':'\ud83d\udd1a', - 'envelope_with_arrow':'\ud83d\udce9', - 'euro':'\ud83d\udcb6', - 'european_castle':'\ud83c\udff0', - 'european_post_office':'\ud83c\udfe4', - 'evergreen_tree':'\ud83c\udf32', - 'exclamation':'\u2757\ufe0f', - 'expressionless':'\ud83d\ude11', - 'eye':'\ud83d\udc41', - 'eye_speech_bubble':'\ud83d\udc41‍\ud83d\udde8', - 'eyeglasses':'\ud83d\udc53', - 'eyes':'\ud83d\udc40', - 'face_with_head_bandage':'\ud83e\udd15', - 'face_with_thermometer':'\ud83e\udd12', - 'fist_oncoming':'\ud83d\udc4a', - 'factory':'\ud83c\udfed', - 'fallen_leaf':'\ud83c\udf42', - 'family_man_woman_boy':'\ud83d\udc6a', - 'family_man_boy':'\ud83d\udc68‍\ud83d\udc66', - 'family_man_boy_boy':'\ud83d\udc68‍\ud83d\udc66‍\ud83d\udc66', - 'family_man_girl':'\ud83d\udc68‍\ud83d\udc67', - 'family_man_girl_boy':'\ud83d\udc68‍\ud83d\udc67‍\ud83d\udc66', - 'family_man_girl_girl':'\ud83d\udc68‍\ud83d\udc67‍\ud83d\udc67', - 'family_man_man_boy':'\ud83d\udc68‍\ud83d\udc68‍\ud83d\udc66', - 'family_man_man_boy_boy':'\ud83d\udc68‍\ud83d\udc68‍\ud83d\udc66‍\ud83d\udc66', - 'family_man_man_girl':'\ud83d\udc68‍\ud83d\udc68‍\ud83d\udc67', - 'family_man_man_girl_boy':'\ud83d\udc68‍\ud83d\udc68‍\ud83d\udc67‍\ud83d\udc66', - 'family_man_man_girl_girl':'\ud83d\udc68‍\ud83d\udc68‍\ud83d\udc67‍\ud83d\udc67', - 'family_man_woman_boy_boy':'\ud83d\udc68‍\ud83d\udc69‍\ud83d\udc66‍\ud83d\udc66', - 'family_man_woman_girl':'\ud83d\udc68‍\ud83d\udc69‍\ud83d\udc67', - 'family_man_woman_girl_boy':'\ud83d\udc68‍\ud83d\udc69‍\ud83d\udc67‍\ud83d\udc66', - 'family_man_woman_girl_girl':'\ud83d\udc68‍\ud83d\udc69‍\ud83d\udc67‍\ud83d\udc67', - 'family_woman_boy':'\ud83d\udc69‍\ud83d\udc66', - 'family_woman_boy_boy':'\ud83d\udc69‍\ud83d\udc66‍\ud83d\udc66', - 'family_woman_girl':'\ud83d\udc69‍\ud83d\udc67', - 'family_woman_girl_boy':'\ud83d\udc69‍\ud83d\udc67‍\ud83d\udc66', - 'family_woman_girl_girl':'\ud83d\udc69‍\ud83d\udc67‍\ud83d\udc67', - 'family_woman_woman_boy':'\ud83d\udc69‍\ud83d\udc69‍\ud83d\udc66', - 'family_woman_woman_boy_boy':'\ud83d\udc69‍\ud83d\udc69‍\ud83d\udc66‍\ud83d\udc66', - 'family_woman_woman_girl':'\ud83d\udc69‍\ud83d\udc69‍\ud83d\udc67', - 'family_woman_woman_girl_boy':'\ud83d\udc69‍\ud83d\udc69‍\ud83d\udc67‍\ud83d\udc66', - 'family_woman_woman_girl_girl':'\ud83d\udc69‍\ud83d\udc69‍\ud83d\udc67‍\ud83d\udc67', - 'fast_forward':'\u23e9', - 'fax':'\ud83d\udce0', - 'fearful':'\ud83d\ude28', - 'feet':'\ud83d\udc3e', - 'female_detective':'\ud83d\udd75\ufe0f‍\u2640\ufe0f', - 'ferris_wheel':'\ud83c\udfa1', - 'ferry':'\u26f4', - 'field_hockey':'\ud83c\udfd1', - 'file_cabinet':'\ud83d\uddc4', - 'file_folder':'\ud83d\udcc1', - 'film_projector':'\ud83d\udcfd', - 'film_strip':'\ud83c\udf9e', - 'fire':'\ud83d\udd25', - 'fire_engine':'\ud83d\ude92', - 'fireworks':'\ud83c\udf86', - 'first_quarter_moon':'\ud83c\udf13', - 'first_quarter_moon_with_face':'\ud83c\udf1b', - 'fish':'\ud83d\udc1f', - 'fish_cake':'\ud83c\udf65', - 'fishing_pole_and_fish':'\ud83c\udfa3', - 'fist_raised':'\u270a', - 'fist_left':'\ud83e\udd1b', - 'fist_right':'\ud83e\udd1c', - 'flags':'\ud83c\udf8f', - 'flashlight':'\ud83d\udd26', - 'fleur_de_lis':'\u269c\ufe0f', - 'flight_arrival':'\ud83d\udeec', - 'flight_departure':'\ud83d\udeeb', - 'floppy_disk':'\ud83d\udcbe', - 'flower_playing_cards':'\ud83c\udfb4', - 'flushed':'\ud83d\ude33', - 'fog':'\ud83c\udf2b', - 'foggy':'\ud83c\udf01', - 'football':'\ud83c\udfc8', - 'footprints':'\ud83d\udc63', - 'fork_and_knife':'\ud83c\udf74', - 'fountain':'\u26f2\ufe0f', - 'fountain_pen':'\ud83d\udd8b', - 'four_leaf_clover':'\ud83c\udf40', - 'fox_face':'\ud83e\udd8a', - 'framed_picture':'\ud83d\uddbc', - 'free':'\ud83c\udd93', - 'fried_egg':'\ud83c\udf73', - 'fried_shrimp':'\ud83c\udf64', - 'fries':'\ud83c\udf5f', - 'frog':'\ud83d\udc38', - 'frowning':'\ud83d\ude26', - 'frowning_face':'\u2639\ufe0f', - 'frowning_man':'\ud83d\ude4d‍\u2642\ufe0f', - 'frowning_woman':'\ud83d\ude4d', - 'middle_finger':'\ud83d\udd95', - 'fuelpump':'\u26fd\ufe0f', - 'full_moon':'\ud83c\udf15', - 'full_moon_with_face':'\ud83c\udf1d', - 'funeral_urn':'\u26b1\ufe0f', - 'game_die':'\ud83c\udfb2', - 'gear':'\u2699\ufe0f', - 'gem':'\ud83d\udc8e', - 'gemini':'\u264a\ufe0f', - 'ghost':'\ud83d\udc7b', - 'gift':'\ud83c\udf81', - 'gift_heart':'\ud83d\udc9d', - 'girl':'\ud83d\udc67', - 'globe_with_meridians':'\ud83c\udf10', - 'goal_net':'\ud83e\udd45', - 'goat':'\ud83d\udc10', - 'golf':'\u26f3\ufe0f', - 'golfing_man':'\ud83c\udfcc\ufe0f', - 'golfing_woman':'\ud83c\udfcc\ufe0f‍\u2640\ufe0f', - 'gorilla':'\ud83e\udd8d', - 'grapes':'\ud83c\udf47', - 'green_apple':'\ud83c\udf4f', - 'green_book':'\ud83d\udcd7', - 'green_heart':'\ud83d\udc9a', - 'green_salad':'\ud83e\udd57', - 'grey_exclamation':'\u2755', - 'grey_question':'\u2754', - 'grimacing':'\ud83d\ude2c', - 'grin':'\ud83d\ude01', - 'grinning':'\ud83d\ude00', - 'guardsman':'\ud83d\udc82', - 'guardswoman':'\ud83d\udc82‍\u2640\ufe0f', - 'guitar':'\ud83c\udfb8', - 'gun':'\ud83d\udd2b', - 'haircut_woman':'\ud83d\udc87', - 'haircut_man':'\ud83d\udc87‍\u2642\ufe0f', - 'hamburger':'\ud83c\udf54', - 'hammer':'\ud83d\udd28', - 'hammer_and_pick':'\u2692', - 'hammer_and_wrench':'\ud83d\udee0', - 'hamster':'\ud83d\udc39', - 'hand':'\u270b', - 'handbag':'\ud83d\udc5c', - 'handshake':'\ud83e\udd1d', - 'hankey':'\ud83d\udca9', - 'hatched_chick':'\ud83d\udc25', - 'hatching_chick':'\ud83d\udc23', - 'headphones':'\ud83c\udfa7', - 'hear_no_evil':'\ud83d\ude49', - 'heart':'\u2764\ufe0f', - 'heart_decoration':'\ud83d\udc9f', - 'heart_eyes':'\ud83d\ude0d', - 'heart_eyes_cat':'\ud83d\ude3b', - 'heartbeat':'\ud83d\udc93', - 'heartpulse':'\ud83d\udc97', - 'hearts':'\u2665\ufe0f', - 'heavy_check_mark':'\u2714\ufe0f', - 'heavy_division_sign':'\u2797', - 'heavy_dollar_sign':'\ud83d\udcb2', - 'heavy_heart_exclamation':'\u2763\ufe0f', - 'heavy_minus_sign':'\u2796', - 'heavy_multiplication_x':'\u2716\ufe0f', - 'heavy_plus_sign':'\u2795', - 'helicopter':'\ud83d\ude81', - 'herb':'\ud83c\udf3f', - 'hibiscus':'\ud83c\udf3a', - 'high_brightness':'\ud83d\udd06', - 'high_heel':'\ud83d\udc60', - 'hocho':'\ud83d\udd2a', - 'hole':'\ud83d\udd73', - 'honey_pot':'\ud83c\udf6f', - 'horse':'\ud83d\udc34', - 'horse_racing':'\ud83c\udfc7', - 'hospital':'\ud83c\udfe5', - 'hot_pepper':'\ud83c\udf36', - 'hotdog':'\ud83c\udf2d', - 'hotel':'\ud83c\udfe8', - 'hotsprings':'\u2668\ufe0f', - 'hourglass':'\u231b\ufe0f', - 'hourglass_flowing_sand':'\u23f3', - 'house':'\ud83c\udfe0', - 'house_with_garden':'\ud83c\udfe1', - 'houses':'\ud83c\udfd8', - 'hugs':'\ud83e\udd17', - 'hushed':'\ud83d\ude2f', - 'ice_cream':'\ud83c\udf68', - 'ice_hockey':'\ud83c\udfd2', - 'ice_skate':'\u26f8', - 'icecream':'\ud83c\udf66', - 'id':'\ud83c\udd94', - 'ideograph_advantage':'\ud83c\ude50', - 'imp':'\ud83d\udc7f', - 'inbox_tray':'\ud83d\udce5', - 'incoming_envelope':'\ud83d\udce8', - 'tipping_hand_woman':'\ud83d\udc81', - 'information_source':'\u2139\ufe0f', - 'innocent':'\ud83d\ude07', - 'interrobang':'\u2049\ufe0f', - 'iphone':'\ud83d\udcf1', - 'izakaya_lantern':'\ud83c\udfee', - 'jack_o_lantern':'\ud83c\udf83', - 'japan':'\ud83d\uddfe', - 'japanese_castle':'\ud83c\udfef', - 'japanese_goblin':'\ud83d\udc7a', - 'japanese_ogre':'\ud83d\udc79', - 'jeans':'\ud83d\udc56', - 'joy':'\ud83d\ude02', - 'joy_cat':'\ud83d\ude39', - 'joystick':'\ud83d\udd79', - 'kaaba':'\ud83d\udd4b', - 'key':'\ud83d\udd11', - 'keyboard':'\u2328\ufe0f', - 'keycap_ten':'\ud83d\udd1f', - 'kick_scooter':'\ud83d\udef4', - 'kimono':'\ud83d\udc58', - 'kiss':'\ud83d\udc8b', - 'kissing':'\ud83d\ude17', - 'kissing_cat':'\ud83d\ude3d', - 'kissing_closed_eyes':'\ud83d\ude1a', - 'kissing_heart':'\ud83d\ude18', - 'kissing_smiling_eyes':'\ud83d\ude19', - 'kiwi_fruit':'\ud83e\udd5d', - 'koala':'\ud83d\udc28', - 'koko':'\ud83c\ude01', - 'label':'\ud83c\udff7', - 'large_blue_circle':'\ud83d\udd35', - 'large_blue_diamond':'\ud83d\udd37', - 'large_orange_diamond':'\ud83d\udd36', - 'last_quarter_moon':'\ud83c\udf17', - 'last_quarter_moon_with_face':'\ud83c\udf1c', - 'latin_cross':'\u271d\ufe0f', - 'laughing':'\ud83d\ude06', - 'leaves':'\ud83c\udf43', - 'ledger':'\ud83d\udcd2', - 'left_luggage':'\ud83d\udec5', - 'left_right_arrow':'\u2194\ufe0f', - 'leftwards_arrow_with_hook':'\u21a9\ufe0f', - 'lemon':'\ud83c\udf4b', - 'leo':'\u264c\ufe0f', - 'leopard':'\ud83d\udc06', - 'level_slider':'\ud83c\udf9a', - 'libra':'\u264e\ufe0f', - 'light_rail':'\ud83d\ude88', - 'link':'\ud83d\udd17', - 'lion':'\ud83e\udd81', - 'lips':'\ud83d\udc44', - 'lipstick':'\ud83d\udc84', - 'lizard':'\ud83e\udd8e', - 'lock':'\ud83d\udd12', - 'lock_with_ink_pen':'\ud83d\udd0f', - 'lollipop':'\ud83c\udf6d', - 'loop':'\u27bf', - 'loud_sound':'\ud83d\udd0a', - 'loudspeaker':'\ud83d\udce2', - 'love_hotel':'\ud83c\udfe9', - 'love_letter':'\ud83d\udc8c', - 'low_brightness':'\ud83d\udd05', - 'lying_face':'\ud83e\udd25', - 'm':'\u24c2\ufe0f', - 'mag':'\ud83d\udd0d', - 'mag_right':'\ud83d\udd0e', - 'mahjong':'\ud83c\udc04\ufe0f', - 'mailbox':'\ud83d\udceb', - 'mailbox_closed':'\ud83d\udcea', - 'mailbox_with_mail':'\ud83d\udcec', - 'mailbox_with_no_mail':'\ud83d\udced', - 'man':'\ud83d\udc68', - 'man_artist':'\ud83d\udc68‍\ud83c\udfa8', - 'man_astronaut':'\ud83d\udc68‍\ud83d\ude80', - 'man_cartwheeling':'\ud83e\udd38‍\u2642\ufe0f', - 'man_cook':'\ud83d\udc68‍\ud83c\udf73', - 'man_dancing':'\ud83d\udd7a', - 'man_facepalming':'\ud83e\udd26‍\u2642\ufe0f', - 'man_factory_worker':'\ud83d\udc68‍\ud83c\udfed', - 'man_farmer':'\ud83d\udc68‍\ud83c\udf3e', - 'man_firefighter':'\ud83d\udc68‍\ud83d\ude92', - 'man_health_worker':'\ud83d\udc68‍\u2695\ufe0f', - 'man_in_tuxedo':'\ud83e\udd35', - 'man_judge':'\ud83d\udc68‍\u2696\ufe0f', - 'man_juggling':'\ud83e\udd39‍\u2642\ufe0f', - 'man_mechanic':'\ud83d\udc68‍\ud83d\udd27', - 'man_office_worker':'\ud83d\udc68‍\ud83d\udcbc', - 'man_pilot':'\ud83d\udc68‍\u2708\ufe0f', - 'man_playing_handball':'\ud83e\udd3e‍\u2642\ufe0f', - 'man_playing_water_polo':'\ud83e\udd3d‍\u2642\ufe0f', - 'man_scientist':'\ud83d\udc68‍\ud83d\udd2c', - 'man_shrugging':'\ud83e\udd37‍\u2642\ufe0f', - 'man_singer':'\ud83d\udc68‍\ud83c\udfa4', - 'man_student':'\ud83d\udc68‍\ud83c\udf93', - 'man_teacher':'\ud83d\udc68‍\ud83c\udfeb', - 'man_technologist':'\ud83d\udc68‍\ud83d\udcbb', - 'man_with_gua_pi_mao':'\ud83d\udc72', - 'man_with_turban':'\ud83d\udc73', - 'tangerine':'\ud83c\udf4a', - 'mans_shoe':'\ud83d\udc5e', - 'mantelpiece_clock':'\ud83d\udd70', - 'maple_leaf':'\ud83c\udf41', - 'martial_arts_uniform':'\ud83e\udd4b', - 'mask':'\ud83d\ude37', - 'massage_woman':'\ud83d\udc86', - 'massage_man':'\ud83d\udc86‍\u2642\ufe0f', - 'meat_on_bone':'\ud83c\udf56', - 'medal_military':'\ud83c\udf96', - 'medal_sports':'\ud83c\udfc5', - 'mega':'\ud83d\udce3', - 'melon':'\ud83c\udf48', - 'memo':'\ud83d\udcdd', - 'men_wrestling':'\ud83e\udd3c‍\u2642\ufe0f', - 'menorah':'\ud83d\udd4e', - 'mens':'\ud83d\udeb9', - 'metal':'\ud83e\udd18', - 'metro':'\ud83d\ude87', - 'microphone':'\ud83c\udfa4', - 'microscope':'\ud83d\udd2c', - 'milk_glass':'\ud83e\udd5b', - 'milky_way':'\ud83c\udf0c', - 'minibus':'\ud83d\ude90', - 'minidisc':'\ud83d\udcbd', - 'mobile_phone_off':'\ud83d\udcf4', - 'money_mouth_face':'\ud83e\udd11', - 'money_with_wings':'\ud83d\udcb8', - 'moneybag':'\ud83d\udcb0', - 'monkey':'\ud83d\udc12', - 'monkey_face':'\ud83d\udc35', - 'monorail':'\ud83d\ude9d', - 'moon':'\ud83c\udf14', - 'mortar_board':'\ud83c\udf93', - 'mosque':'\ud83d\udd4c', - 'motor_boat':'\ud83d\udee5', - 'motor_scooter':'\ud83d\udef5', - 'motorcycle':'\ud83c\udfcd', - 'motorway':'\ud83d\udee3', - 'mount_fuji':'\ud83d\uddfb', - 'mountain':'\u26f0', - 'mountain_biking_man':'\ud83d\udeb5', - 'mountain_biking_woman':'\ud83d\udeb5‍\u2640\ufe0f', - 'mountain_cableway':'\ud83d\udea0', - 'mountain_railway':'\ud83d\ude9e', - 'mountain_snow':'\ud83c\udfd4', - 'mouse':'\ud83d\udc2d', - 'mouse2':'\ud83d\udc01', - 'movie_camera':'\ud83c\udfa5', - 'moyai':'\ud83d\uddff', - 'mrs_claus':'\ud83e\udd36', - 'muscle':'\ud83d\udcaa', - 'mushroom':'\ud83c\udf44', - 'musical_keyboard':'\ud83c\udfb9', - 'musical_note':'\ud83c\udfb5', - 'musical_score':'\ud83c\udfbc', - 'mute':'\ud83d\udd07', - 'nail_care':'\ud83d\udc85', - 'name_badge':'\ud83d\udcdb', - 'national_park':'\ud83c\udfde', - 'nauseated_face':'\ud83e\udd22', - 'necktie':'\ud83d\udc54', - 'negative_squared_cross_mark':'\u274e', - 'nerd_face':'\ud83e\udd13', - 'neutral_face':'\ud83d\ude10', - 'new':'\ud83c\udd95', - 'new_moon':'\ud83c\udf11', - 'new_moon_with_face':'\ud83c\udf1a', - 'newspaper':'\ud83d\udcf0', - 'newspaper_roll':'\ud83d\uddde', - 'next_track_button':'\u23ed', - 'ng':'\ud83c\udd96', - 'no_good_man':'\ud83d\ude45‍\u2642\ufe0f', - 'no_good_woman':'\ud83d\ude45', - 'night_with_stars':'\ud83c\udf03', - 'no_bell':'\ud83d\udd15', - 'no_bicycles':'\ud83d\udeb3', - 'no_entry':'\u26d4\ufe0f', - 'no_entry_sign':'\ud83d\udeab', - 'no_mobile_phones':'\ud83d\udcf5', - 'no_mouth':'\ud83d\ude36', - 'no_pedestrians':'\ud83d\udeb7', - 'no_smoking':'\ud83d\udead', - 'non-potable_water':'\ud83d\udeb1', - 'nose':'\ud83d\udc43', - 'notebook':'\ud83d\udcd3', - 'notebook_with_decorative_cover':'\ud83d\udcd4', - 'notes':'\ud83c\udfb6', - 'nut_and_bolt':'\ud83d\udd29', - 'o':'\u2b55\ufe0f', - 'o2':'\ud83c\udd7e\ufe0f', - 'ocean':'\ud83c\udf0a', - 'octopus':'\ud83d\udc19', - 'oden':'\ud83c\udf62', - 'office':'\ud83c\udfe2', - 'oil_drum':'\ud83d\udee2', - 'ok':'\ud83c\udd97', - 'ok_hand':'\ud83d\udc4c', - 'ok_man':'\ud83d\ude46‍\u2642\ufe0f', - 'ok_woman':'\ud83d\ude46', - 'old_key':'\ud83d\udddd', - 'older_man':'\ud83d\udc74', - 'older_woman':'\ud83d\udc75', - 'om':'\ud83d\udd49', - 'on':'\ud83d\udd1b', - 'oncoming_automobile':'\ud83d\ude98', - 'oncoming_bus':'\ud83d\ude8d', - 'oncoming_police_car':'\ud83d\ude94', - 'oncoming_taxi':'\ud83d\ude96', - 'open_file_folder':'\ud83d\udcc2', - 'open_hands':'\ud83d\udc50', - 'open_mouth':'\ud83d\ude2e', - 'open_umbrella':'\u2602\ufe0f', - 'ophiuchus':'\u26ce', - 'orange_book':'\ud83d\udcd9', - 'orthodox_cross':'\u2626\ufe0f', - 'outbox_tray':'\ud83d\udce4', - 'owl':'\ud83e\udd89', - 'ox':'\ud83d\udc02', - 'package':'\ud83d\udce6', - 'page_facing_up':'\ud83d\udcc4', - 'page_with_curl':'\ud83d\udcc3', - 'pager':'\ud83d\udcdf', - 'paintbrush':'\ud83d\udd8c', - 'palm_tree':'\ud83c\udf34', - 'pancakes':'\ud83e\udd5e', - 'panda_face':'\ud83d\udc3c', - 'paperclip':'\ud83d\udcce', - 'paperclips':'\ud83d\udd87', - 'parasol_on_ground':'\u26f1', - 'parking':'\ud83c\udd7f\ufe0f', - 'part_alternation_mark':'\u303d\ufe0f', - 'partly_sunny':'\u26c5\ufe0f', - 'passenger_ship':'\ud83d\udef3', - 'passport_control':'\ud83d\udec2', - 'pause_button':'\u23f8', - 'peace_symbol':'\u262e\ufe0f', - 'peach':'\ud83c\udf51', - 'peanuts':'\ud83e\udd5c', - 'pear':'\ud83c\udf50', - 'pen':'\ud83d\udd8a', - 'pencil2':'\u270f\ufe0f', - 'penguin':'\ud83d\udc27', - 'pensive':'\ud83d\ude14', - 'performing_arts':'\ud83c\udfad', - 'persevere':'\ud83d\ude23', - 'person_fencing':'\ud83e\udd3a', - 'pouting_woman':'\ud83d\ude4e', - 'phone':'\u260e\ufe0f', - 'pick':'\u26cf', - 'pig':'\ud83d\udc37', - 'pig2':'\ud83d\udc16', - 'pig_nose':'\ud83d\udc3d', - 'pill':'\ud83d\udc8a', - 'pineapple':'\ud83c\udf4d', - 'ping_pong':'\ud83c\udfd3', - 'pisces':'\u2653\ufe0f', - 'pizza':'\ud83c\udf55', - 'place_of_worship':'\ud83d\uded0', - 'plate_with_cutlery':'\ud83c\udf7d', - 'play_or_pause_button':'\u23ef', - 'point_down':'\ud83d\udc47', - 'point_left':'\ud83d\udc48', - 'point_right':'\ud83d\udc49', - 'point_up':'\u261d\ufe0f', - 'point_up_2':'\ud83d\udc46', - 'police_car':'\ud83d\ude93', - 'policewoman':'\ud83d\udc6e‍\u2640\ufe0f', - 'poodle':'\ud83d\udc29', - 'popcorn':'\ud83c\udf7f', - 'post_office':'\ud83c\udfe3', - 'postal_horn':'\ud83d\udcef', - 'postbox':'\ud83d\udcee', - 'potable_water':'\ud83d\udeb0', - 'potato':'\ud83e\udd54', - 'pouch':'\ud83d\udc5d', - 'poultry_leg':'\ud83c\udf57', - 'pound':'\ud83d\udcb7', - 'rage':'\ud83d\ude21', - 'pouting_cat':'\ud83d\ude3e', - 'pouting_man':'\ud83d\ude4e‍\u2642\ufe0f', - 'pray':'\ud83d\ude4f', - 'prayer_beads':'\ud83d\udcff', - 'pregnant_woman':'\ud83e\udd30', - 'previous_track_button':'\u23ee', - 'prince':'\ud83e\udd34', - 'princess':'\ud83d\udc78', - 'printer':'\ud83d\udda8', - 'purple_heart':'\ud83d\udc9c', - 'purse':'\ud83d\udc5b', - 'pushpin':'\ud83d\udccc', - 'put_litter_in_its_place':'\ud83d\udeae', - 'question':'\u2753', - 'rabbit':'\ud83d\udc30', - 'rabbit2':'\ud83d\udc07', - 'racehorse':'\ud83d\udc0e', - 'racing_car':'\ud83c\udfce', - 'radio':'\ud83d\udcfb', - 'radio_button':'\ud83d\udd18', - 'radioactive':'\u2622\ufe0f', - 'railway_car':'\ud83d\ude83', - 'railway_track':'\ud83d\udee4', - 'rainbow':'\ud83c\udf08', - 'rainbow_flag':'\ud83c\udff3\ufe0f‍\ud83c\udf08', - 'raised_back_of_hand':'\ud83e\udd1a', - 'raised_hand_with_fingers_splayed':'\ud83d\udd90', - 'raised_hands':'\ud83d\ude4c', - 'raising_hand_woman':'\ud83d\ude4b', - 'raising_hand_man':'\ud83d\ude4b‍\u2642\ufe0f', - 'ram':'\ud83d\udc0f', - 'ramen':'\ud83c\udf5c', - 'rat':'\ud83d\udc00', - 'record_button':'\u23fa', - 'recycle':'\u267b\ufe0f', - 'red_circle':'\ud83d\udd34', - 'registered':'\u00ae\ufe0f', - 'relaxed':'\u263a\ufe0f', - 'relieved':'\ud83d\ude0c', - 'reminder_ribbon':'\ud83c\udf97', - 'repeat':'\ud83d\udd01', - 'repeat_one':'\ud83d\udd02', - 'rescue_worker_helmet':'\u26d1', - 'restroom':'\ud83d\udebb', - 'revolving_hearts':'\ud83d\udc9e', - 'rewind':'\u23ea', - 'rhinoceros':'\ud83e\udd8f', - 'ribbon':'\ud83c\udf80', - 'rice':'\ud83c\udf5a', - 'rice_ball':'\ud83c\udf59', - 'rice_cracker':'\ud83c\udf58', - 'rice_scene':'\ud83c\udf91', - 'right_anger_bubble':'\ud83d\uddef', - 'ring':'\ud83d\udc8d', - 'robot':'\ud83e\udd16', - 'rocket':'\ud83d\ude80', - 'rofl':'\ud83e\udd23', - 'roll_eyes':'\ud83d\ude44', - 'roller_coaster':'\ud83c\udfa2', - 'rooster':'\ud83d\udc13', - 'rose':'\ud83c\udf39', - 'rosette':'\ud83c\udff5', - 'rotating_light':'\ud83d\udea8', - 'round_pushpin':'\ud83d\udccd', - 'rowing_man':'\ud83d\udea3', - 'rowing_woman':'\ud83d\udea3‍\u2640\ufe0f', - 'rugby_football':'\ud83c\udfc9', - 'running_man':'\ud83c\udfc3', - 'running_shirt_with_sash':'\ud83c\udfbd', - 'running_woman':'\ud83c\udfc3‍\u2640\ufe0f', - 'sa':'\ud83c\ude02\ufe0f', - 'sagittarius':'\u2650\ufe0f', - 'sake':'\ud83c\udf76', - 'sandal':'\ud83d\udc61', - 'santa':'\ud83c\udf85', - 'satellite':'\ud83d\udce1', - 'saxophone':'\ud83c\udfb7', - 'school':'\ud83c\udfeb', - 'school_satchel':'\ud83c\udf92', - 'scissors':'\u2702\ufe0f', - 'scorpion':'\ud83e\udd82', - 'scorpius':'\u264f\ufe0f', - 'scream':'\ud83d\ude31', - 'scream_cat':'\ud83d\ude40', - 'scroll':'\ud83d\udcdc', - 'seat':'\ud83d\udcba', - 'secret':'\u3299\ufe0f', - 'see_no_evil':'\ud83d\ude48', - 'seedling':'\ud83c\udf31', - 'selfie':'\ud83e\udd33', - 'shallow_pan_of_food':'\ud83e\udd58', - 'shamrock':'\u2618\ufe0f', - 'shark':'\ud83e\udd88', - 'shaved_ice':'\ud83c\udf67', - 'sheep':'\ud83d\udc11', - 'shell':'\ud83d\udc1a', - 'shield':'\ud83d\udee1', - 'shinto_shrine':'\u26e9', - 'ship':'\ud83d\udea2', - 'shirt':'\ud83d\udc55', - 'shopping':'\ud83d\udecd', - 'shopping_cart':'\ud83d\uded2', - 'shower':'\ud83d\udebf', - 'shrimp':'\ud83e\udd90', - 'signal_strength':'\ud83d\udcf6', - 'six_pointed_star':'\ud83d\udd2f', - 'ski':'\ud83c\udfbf', - 'skier':'\u26f7', - 'skull':'\ud83d\udc80', - 'skull_and_crossbones':'\u2620\ufe0f', - 'sleeping':'\ud83d\ude34', - 'sleeping_bed':'\ud83d\udecc', - 'sleepy':'\ud83d\ude2a', - 'slightly_frowning_face':'\ud83d\ude41', - 'slightly_smiling_face':'\ud83d\ude42', - 'slot_machine':'\ud83c\udfb0', - 'small_airplane':'\ud83d\udee9', - 'small_blue_diamond':'\ud83d\udd39', - 'small_orange_diamond':'\ud83d\udd38', - 'small_red_triangle':'\ud83d\udd3a', - 'small_red_triangle_down':'\ud83d\udd3b', - 'smile':'\ud83d\ude04', - 'smile_cat':'\ud83d\ude38', - 'smiley':'\ud83d\ude03', - 'smiley_cat':'\ud83d\ude3a', - 'smiling_imp':'\ud83d\ude08', - 'smirk':'\ud83d\ude0f', - 'smirk_cat':'\ud83d\ude3c', - 'smoking':'\ud83d\udeac', - 'snail':'\ud83d\udc0c', - 'snake':'\ud83d\udc0d', - 'sneezing_face':'\ud83e\udd27', - 'snowboarder':'\ud83c\udfc2', - 'snowflake':'\u2744\ufe0f', - 'snowman':'\u26c4\ufe0f', - 'snowman_with_snow':'\u2603\ufe0f', - 'sob':'\ud83d\ude2d', - 'soccer':'\u26bd\ufe0f', - 'soon':'\ud83d\udd1c', - 'sos':'\ud83c\udd98', - 'sound':'\ud83d\udd09', - 'space_invader':'\ud83d\udc7e', - 'spades':'\u2660\ufe0f', - 'spaghetti':'\ud83c\udf5d', - 'sparkle':'\u2747\ufe0f', - 'sparkler':'\ud83c\udf87', - 'sparkles':'\u2728', - 'sparkling_heart':'\ud83d\udc96', - 'speak_no_evil':'\ud83d\ude4a', - 'speaker':'\ud83d\udd08', - 'speaking_head':'\ud83d\udde3', - 'speech_balloon':'\ud83d\udcac', - 'speedboat':'\ud83d\udea4', - 'spider':'\ud83d\udd77', - 'spider_web':'\ud83d\udd78', - 'spiral_calendar':'\ud83d\uddd3', - 'spiral_notepad':'\ud83d\uddd2', - 'spoon':'\ud83e\udd44', - 'squid':'\ud83e\udd91', - 'stadium':'\ud83c\udfdf', - 'star':'\u2b50\ufe0f', - 'star2':'\ud83c\udf1f', - 'star_and_crescent':'\u262a\ufe0f', - 'star_of_david':'\u2721\ufe0f', - 'stars':'\ud83c\udf20', - 'station':'\ud83d\ude89', - 'statue_of_liberty':'\ud83d\uddfd', - 'steam_locomotive':'\ud83d\ude82', - 'stew':'\ud83c\udf72', - 'stop_button':'\u23f9', - 'stop_sign':'\ud83d\uded1', - 'stopwatch':'\u23f1', - 'straight_ruler':'\ud83d\udccf', - 'strawberry':'\ud83c\udf53', - 'stuck_out_tongue':'\ud83d\ude1b', - 'stuck_out_tongue_closed_eyes':'\ud83d\ude1d', - 'stuck_out_tongue_winking_eye':'\ud83d\ude1c', - 'studio_microphone':'\ud83c\udf99', - 'stuffed_flatbread':'\ud83e\udd59', - 'sun_behind_large_cloud':'\ud83c\udf25', - 'sun_behind_rain_cloud':'\ud83c\udf26', - 'sun_behind_small_cloud':'\ud83c\udf24', - 'sun_with_face':'\ud83c\udf1e', - 'sunflower':'\ud83c\udf3b', - 'sunglasses':'\ud83d\ude0e', - 'sunny':'\u2600\ufe0f', - 'sunrise':'\ud83c\udf05', - 'sunrise_over_mountains':'\ud83c\udf04', - 'surfing_man':'\ud83c\udfc4', - 'surfing_woman':'\ud83c\udfc4‍\u2640\ufe0f', - 'sushi':'\ud83c\udf63', - 'suspension_railway':'\ud83d\ude9f', - 'sweat':'\ud83d\ude13', - 'sweat_drops':'\ud83d\udca6', - 'sweat_smile':'\ud83d\ude05', - 'sweet_potato':'\ud83c\udf60', - 'swimming_man':'\ud83c\udfca', - 'swimming_woman':'\ud83c\udfca‍\u2640\ufe0f', - 'symbols':'\ud83d\udd23', - 'synagogue':'\ud83d\udd4d', - 'syringe':'\ud83d\udc89', - 'taco':'\ud83c\udf2e', - 'tada':'\ud83c\udf89', - 'tanabata_tree':'\ud83c\udf8b', - 'taurus':'\u2649\ufe0f', - 'taxi':'\ud83d\ude95', - 'tea':'\ud83c\udf75', - 'telephone_receiver':'\ud83d\udcde', - 'telescope':'\ud83d\udd2d', - 'tennis':'\ud83c\udfbe', - 'tent':'\u26fa\ufe0f', - 'thermometer':'\ud83c\udf21', - 'thinking':'\ud83e\udd14', - 'thought_balloon':'\ud83d\udcad', - 'ticket':'\ud83c\udfab', - 'tickets':'\ud83c\udf9f', - 'tiger':'\ud83d\udc2f', - 'tiger2':'\ud83d\udc05', - 'timer_clock':'\u23f2', - 'tipping_hand_man':'\ud83d\udc81‍\u2642\ufe0f', - 'tired_face':'\ud83d\ude2b', - 'tm':'\u2122\ufe0f', - 'toilet':'\ud83d\udebd', - 'tokyo_tower':'\ud83d\uddfc', - 'tomato':'\ud83c\udf45', - 'tongue':'\ud83d\udc45', - 'top':'\ud83d\udd1d', - 'tophat':'\ud83c\udfa9', - 'tornado':'\ud83c\udf2a', - 'trackball':'\ud83d\uddb2', - 'tractor':'\ud83d\ude9c', - 'traffic_light':'\ud83d\udea5', - 'train':'\ud83d\ude8b', - 'train2':'\ud83d\ude86', - 'tram':'\ud83d\ude8a', - 'triangular_flag_on_post':'\ud83d\udea9', - 'triangular_ruler':'\ud83d\udcd0', - 'trident':'\ud83d\udd31', - 'triumph':'\ud83d\ude24', - 'trolleybus':'\ud83d\ude8e', - 'trophy':'\ud83c\udfc6', - 'tropical_drink':'\ud83c\udf79', - 'tropical_fish':'\ud83d\udc20', - 'truck':'\ud83d\ude9a', - 'trumpet':'\ud83c\udfba', - 'tulip':'\ud83c\udf37', - 'tumbler_glass':'\ud83e\udd43', - 'turkey':'\ud83e\udd83', - 'turtle':'\ud83d\udc22', - 'tv':'\ud83d\udcfa', - 'twisted_rightwards_arrows':'\ud83d\udd00', - 'two_hearts':'\ud83d\udc95', - 'two_men_holding_hands':'\ud83d\udc6c', - 'two_women_holding_hands':'\ud83d\udc6d', - 'u5272':'\ud83c\ude39', - 'u5408':'\ud83c\ude34', - 'u55b6':'\ud83c\ude3a', - 'u6307':'\ud83c\ude2f\ufe0f', - 'u6708':'\ud83c\ude37\ufe0f', - 'u6709':'\ud83c\ude36', - 'u6e80':'\ud83c\ude35', - 'u7121':'\ud83c\ude1a\ufe0f', - 'u7533':'\ud83c\ude38', - 'u7981':'\ud83c\ude32', - 'u7a7a':'\ud83c\ude33', - 'umbrella':'\u2614\ufe0f', - 'unamused':'\ud83d\ude12', - 'underage':'\ud83d\udd1e', - 'unicorn':'\ud83e\udd84', - 'unlock':'\ud83d\udd13', - 'up':'\ud83c\udd99', - 'upside_down_face':'\ud83d\ude43', - 'v':'\u270c\ufe0f', - 'vertical_traffic_light':'\ud83d\udea6', - 'vhs':'\ud83d\udcfc', - 'vibration_mode':'\ud83d\udcf3', - 'video_camera':'\ud83d\udcf9', - 'video_game':'\ud83c\udfae', - 'violin':'\ud83c\udfbb', - 'virgo':'\u264d\ufe0f', - 'volcano':'\ud83c\udf0b', - 'volleyball':'\ud83c\udfd0', - 'vs':'\ud83c\udd9a', - 'vulcan_salute':'\ud83d\udd96', - 'walking_man':'\ud83d\udeb6', - 'walking_woman':'\ud83d\udeb6‍\u2640\ufe0f', - 'waning_crescent_moon':'\ud83c\udf18', - 'waning_gibbous_moon':'\ud83c\udf16', - 'warning':'\u26a0\ufe0f', - 'wastebasket':'\ud83d\uddd1', - 'watch':'\u231a\ufe0f', - 'water_buffalo':'\ud83d\udc03', - 'watermelon':'\ud83c\udf49', - 'wave':'\ud83d\udc4b', - 'wavy_dash':'\u3030\ufe0f', - 'waxing_crescent_moon':'\ud83c\udf12', - 'wc':'\ud83d\udebe', - 'weary':'\ud83d\ude29', - 'wedding':'\ud83d\udc92', - 'weight_lifting_man':'\ud83c\udfcb\ufe0f', - 'weight_lifting_woman':'\ud83c\udfcb\ufe0f‍\u2640\ufe0f', - 'whale':'\ud83d\udc33', - 'whale2':'\ud83d\udc0b', - 'wheel_of_dharma':'\u2638\ufe0f', - 'wheelchair':'\u267f\ufe0f', - 'white_check_mark':'\u2705', - 'white_circle':'\u26aa\ufe0f', - 'white_flag':'\ud83c\udff3\ufe0f', - 'white_flower':'\ud83d\udcae', - 'white_large_square':'\u2b1c\ufe0f', - 'white_medium_small_square':'\u25fd\ufe0f', - 'white_medium_square':'\u25fb\ufe0f', - 'white_small_square':'\u25ab\ufe0f', - 'white_square_button':'\ud83d\udd33', - 'wilted_flower':'\ud83e\udd40', - 'wind_chime':'\ud83c\udf90', - 'wind_face':'\ud83c\udf2c', - 'wine_glass':'\ud83c\udf77', - 'wink':'\ud83d\ude09', - 'wolf':'\ud83d\udc3a', - 'woman':'\ud83d\udc69', - 'woman_artist':'\ud83d\udc69‍\ud83c\udfa8', - 'woman_astronaut':'\ud83d\udc69‍\ud83d\ude80', - 'woman_cartwheeling':'\ud83e\udd38‍\u2640\ufe0f', - 'woman_cook':'\ud83d\udc69‍\ud83c\udf73', - 'woman_facepalming':'\ud83e\udd26‍\u2640\ufe0f', - 'woman_factory_worker':'\ud83d\udc69‍\ud83c\udfed', - 'woman_farmer':'\ud83d\udc69‍\ud83c\udf3e', - 'woman_firefighter':'\ud83d\udc69‍\ud83d\ude92', - 'woman_health_worker':'\ud83d\udc69‍\u2695\ufe0f', - 'woman_judge':'\ud83d\udc69‍\u2696\ufe0f', - 'woman_juggling':'\ud83e\udd39‍\u2640\ufe0f', - 'woman_mechanic':'\ud83d\udc69‍\ud83d\udd27', - 'woman_office_worker':'\ud83d\udc69‍\ud83d\udcbc', - 'woman_pilot':'\ud83d\udc69‍\u2708\ufe0f', - 'woman_playing_handball':'\ud83e\udd3e‍\u2640\ufe0f', - 'woman_playing_water_polo':'\ud83e\udd3d‍\u2640\ufe0f', - 'woman_scientist':'\ud83d\udc69‍\ud83d\udd2c', - 'woman_shrugging':'\ud83e\udd37‍\u2640\ufe0f', - 'woman_singer':'\ud83d\udc69‍\ud83c\udfa4', - 'woman_student':'\ud83d\udc69‍\ud83c\udf93', - 'woman_teacher':'\ud83d\udc69‍\ud83c\udfeb', - 'woman_technologist':'\ud83d\udc69‍\ud83d\udcbb', - 'woman_with_turban':'\ud83d\udc73‍\u2640\ufe0f', - 'womans_clothes':'\ud83d\udc5a', - 'womans_hat':'\ud83d\udc52', - 'women_wrestling':'\ud83e\udd3c‍\u2640\ufe0f', - 'womens':'\ud83d\udeba', - 'world_map':'\ud83d\uddfa', - 'worried':'\ud83d\ude1f', - 'wrench':'\ud83d\udd27', - 'writing_hand':'\u270d\ufe0f', - 'x':'\u274c', - 'yellow_heart':'\ud83d\udc9b', - 'yen':'\ud83d\udcb4', - 'yin_yang':'\u262f\ufe0f', - 'yum':'\ud83d\ude0b', - 'zap':'\u26a1\ufe0f', - 'zipper_mouth_face':'\ud83e\udd10', - 'zzz':'\ud83d\udca4', - - /* special emojis :P */ - 'octocat': '', - 'showdown': '' - }; - - /** - * These are all the transformations that form block-level - * tags like paragraphs, headers, and list items. - */ - showdown.subParser('makehtml.blockGamut', function (text, options, globals) { - 'use strict'; - - text = globals.converter._dispatch('makehtml.blockGamut.before', text, options, globals).getText(); - - // we parse blockquotes first so that we can have headings and hrs - // inside blockquotes - text = showdown.subParser('makehtml.blockQuotes')(text, options, globals); - text = showdown.subParser('makehtml.headers')(text, options, globals); - - // Do Horizontal Rules: - text = showdown.subParser('makehtml.horizontalRule')(text, options, globals); - - text = showdown.subParser('makehtml.lists')(text, options, globals); - text = showdown.subParser('makehtml.codeBlocks')(text, options, globals); - text = showdown.subParser('makehtml.tables')(text, options, globals); - - // We already ran _HashHTMLBlocks() before, in Markdown(), but that - // was to escape raw HTML in the original Markdown source. This time, - // we're escaping the markup we've just created, so that we don't wrap - //

    tags around block-level tags. - text = showdown.subParser('makehtml.hashHTMLBlocks')(text, options, globals); - text = showdown.subParser('makehtml.paragraphs')(text, options, globals); - - text = globals.converter._dispatch('makehtml.blockGamut.after', text, options, globals).getText(); - - return text; - }); - - showdown.subParser('makehtml.blockQuotes', function (text, options, globals) { - 'use strict'; - - text = globals.converter._dispatch('makehtml.blockQuotes.before', text, options, globals).getText(); - - // add a couple extra lines after the text and endtext mark - text = text + '\n\n'; - - var rgx = /(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm; - - if (options.splitAdjacentBlockquotes) { - rgx = /^ {0,3}>[\s\S]*?(?:\n\n)/gm; - } - - text = text.replace(rgx, function (bq) { - // attacklab: hack around Konqueror 3.5.4 bug: - // "----------bug".replace(/^-/g,"") == "bug" - bq = bq.replace(/^[ \t]*>[ \t]?/gm, ''); // trim one level of quoting - - // attacklab: clean up hack - bq = bq.replace(/¨0/g, ''); - - bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines - bq = showdown.subParser('makehtml.githubCodeBlocks')(bq, options, globals); - bq = showdown.subParser('makehtml.blockGamut')(bq, options, globals); // recurse - - bq = bq.replace(/(^|\n)/g, '$1 '); - // These leading spaces screw with

     content, so we need to fix that:
    -            bq = bq.replace(/(\s*
    [^\r]+?<\/pre>)/gm, function (wholeMatch, m1) {
    -                var pre = m1;
    -                // attacklab: hack around Konqueror 3.5.4 bug:
    -                pre = pre.replace(/^  /mg, '¨0');
    -                pre = pre.replace(/¨0/g, '');
    -                return pre;
    -            });
    -
    -            return showdown.subParser('makehtml.hashBlock')('
    \n' + bq + '\n
    ', options, globals); - }); - - text = globals.converter._dispatch('makehtml.blockQuotes.after', text, options, globals).getText(); - return text; - }); - - /** - * Process Markdown `
    ` blocks.
    -     */
    -    showdown.subParser('makehtml.codeBlocks', function (text, options, globals) {
    -        'use strict';
    -
    -        text = globals.converter._dispatch('makehtml.codeBlocks.before', text, options, globals).getText();
    -
    -        // sentinel workarounds for lack of \A and \Z, safari\khtml bug
    -        text += '¨0';
    -
    -        var pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g;
    -        text = text.replace(pattern, function (wholeMatch, m1, m2) {
    -            var codeblock = m1,
    -                nextChar = m2,
    -                end = '\n';
    -
    -            codeblock = showdown.subParser('makehtml.outdent')(codeblock, options, globals);
    -            codeblock = showdown.subParser('makehtml.encodeCode')(codeblock, options, globals);
    -            codeblock = showdown.subParser('makehtml.detab')(codeblock, options, globals);
    -            codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
    -            codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing newlines
    -
    -            if (options.omitExtraWLInCodeBlocks) {
    -                end = '';
    -            }
    -
    -            codeblock = '
    ' + codeblock + end + '
    '; - - return showdown.subParser('makehtml.hashBlock')(codeblock, options, globals) + nextChar; - }); - - // strip sentinel - text = text.replace(/¨0/, ''); - - text = globals.converter._dispatch('makehtml.codeBlocks.after', text, options, globals).getText(); - return text; - }); - - /** - * - * * Backtick quotes are used for spans. - * - * * You can use multiple backticks as the delimiters if you want to - * include literal backticks in the code span. So, this input: - * - * Just type ``foo `bar` baz`` at the prompt. - * - * Will translate to: - * - *

    Just type foo `bar` baz at the prompt.

    - * - * There's no arbitrary limit to the number of backticks you - * can use as delimters. If you need three consecutive backticks - * in your code, use four for delimiters, etc. - * - * * You can use spaces to get literal backticks at the edges: - * - * ... type `` `bar` `` ... - * - * Turns to: - * - * ... type `bar` ... - */ - showdown.subParser('makehtml.codeSpans', function (text, options, globals) { - 'use strict'; - - text = globals.converter._dispatch('makehtml.codeSpans.before', text, options, globals).getText(); - - if (typeof (text) === 'undefined') { - text = ''; - } - text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, - function (wholeMatch, m1, m2, m3) { - var c = m3; - c = c.replace(/^([ \t]*)/g, ''); // leading whitespace - c = c.replace(/[ \t]*$/g, ''); // trailing whitespace - c = showdown.subParser('makehtml.encodeCode')(c, options, globals); - c = m1 + '' + c + ''; - c = showdown.subParser('makehtml.hashHTMLSpans')(c, options, globals); - return c; - } - ); - - text = globals.converter._dispatch('makehtml.codeSpans.after', text, options, globals).getText(); - return text; - }); - - /** - * Create a full HTML document from the processed markdown - */ - showdown.subParser('makehtml.completeHTMLDocument', function (text, options, globals) { - 'use strict'; - - if (!options.completeHTMLDocument) { - return text; - } - - text = globals.converter._dispatch('makehtml.completeHTMLDocument.before', text, options, globals).getText(); - - var doctype = 'html', - doctypeParsed = '\n', - title = '', - charset = '\n', - lang = '', - metadata = ''; - - if (typeof globals.metadata.parsed.doctype !== 'undefined') { - doctypeParsed = '\n'; - doctype = globals.metadata.parsed.doctype.toString().toLowerCase(); - if (doctype === 'html' || doctype === 'html5') { - charset = ''; - } - } - - for (var meta in globals.metadata.parsed) { - if (globals.metadata.parsed.hasOwnProperty(meta)) { - switch (meta.toLowerCase()) { - case 'doctype': - break; - - case 'title': - title = '' + globals.metadata.parsed.title + '\n'; - break; - - case 'charset': - if (doctype === 'html' || doctype === 'html5') { - charset = '\n'; - } else { - charset = '\n'; - } - break; - - case 'language': - case 'lang': - lang = ' lang="' + globals.metadata.parsed[meta] + '"'; - metadata += '\n'; - break; - - default: - metadata += '\n'; - } - } - } - - text = doctypeParsed + '\n\n' + title + charset + metadata + '\n\n' + text.trim() + '\n\n'; - - text = globals.converter._dispatch('makehtml.completeHTMLDocument.after', text, options, globals).getText(); - return text; - }); - - /** - * Convert all tabs to spaces - */ - showdown.subParser('makehtml.detab', function (text, options, globals) { - 'use strict'; - text = globals.converter._dispatch('makehtml.detab.before', text, options, globals).getText(); - - // expand first n-1 tabs - text = text.replace(/\t(?=\t)/g, ' '); // g_tab_width - - // replace the nth with two sentinels - text = text.replace(/\t/g, '¨A¨B'); - - // use the sentinel to anchor our regex so it doesn't explode - text = text.replace(/¨B(.+?)¨A/g, function (wholeMatch, m1) { - var leadingText = m1, - numSpaces = 4 - leadingText.length % 4; // g_tab_width - - // there *must* be a better way to do this: - for (var i = 0; i < numSpaces; i++) { - leadingText += ' '; - } - - return leadingText; - }); - - // clean up sentinels - text = text.replace(/¨A/g, ' '); // g_tab_width - text = text.replace(/¨B/g, ''); - - text = globals.converter._dispatch('makehtml.detab.after', text, options, globals).getText(); - return text; - }); - - showdown.subParser('makehtml.ellipsis', function (text, options, globals) { - 'use strict'; - - if (!options.ellipsis) { - return text; - } - - text = globals.converter._dispatch('makehtml.ellipsis.before', text, options, globals).getText(); - - text = text.replace(/\.\.\./g, '…'); - - text = globals.converter._dispatch('makehtml.ellipsis.after', text, options, globals).getText(); - - return text; - }); - - /** - * Turn emoji codes into emojis - * - * List of supported emojis: https://github.com/showdownjs/showdown/wiki/Emojis - */ - showdown.subParser('makehtml.emoji', function (text, options, globals) { - 'use strict'; - - if (!options.emoji) { - return text; - } - - text = globals.converter._dispatch('makehtml.emoji.before', text, options, globals).getText(); - - var emojiRgx = /:([\S]+?):/g; - - text = text.replace(emojiRgx, function (wm, emojiCode) { - if (showdown.helper.emojis.hasOwnProperty(emojiCode)) { - return showdown.helper.emojis[emojiCode]; - } - return wm; - }); - - text = globals.converter._dispatch('makehtml.emoji.after', text, options, globals).getText(); - - return text; - }); - - /** - * Smart processing for ampersands and angle brackets that need to be encoded. - */ - showdown.subParser('makehtml.encodeAmpsAndAngles', function (text, options, globals) { - 'use strict'; - text = globals.converter._dispatch('makehtml.encodeAmpsAndAngles.before', text, options, globals).getText(); - - // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin: - // http://bumppo.net/projects/amputator/ - text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&'); - - // Encode naked <'s - text = text.replace(/<(?![a-z\/?$!])/gi, '<'); - - // Encode < - text = text.replace(/ - text = text.replace(/>/g, '>'); - - text = globals.converter._dispatch('makehtml.encodeAmpsAndAngles.after', text, options, globals).getText(); - return text; - }); - - /** - * Returns the string, with after processing the following backslash escape sequences. - * - * attacklab: The polite way to do this is with the new escapeCharacters() function: - * - * text = escapeCharacters(text,"\\",true); - * text = escapeCharacters(text,"`*_{}[]()>#+-.!",true); - * - * ...but we're sidestepping its use of the (slow) RegExp constructor - * as an optimization for Firefox. This function gets called a LOT. - */ - showdown.subParser('makehtml.encodeBackslashEscapes', function (text, options, globals) { - 'use strict'; - text = globals.converter._dispatch('makehtml.encodeBackslashEscapes.before', text, options, globals).getText(); - - text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback); - text = text.replace(/\\([`*_{}\[\]()>#+.!~=|:-])/g, showdown.helper.escapeCharactersCallback); - - text = globals.converter._dispatch('makehtml.encodeBackslashEscapes.after', text, options, globals).getText(); - return text; - }); - - /** - * Encode/escape certain characters inside Markdown code runs. - * The point is that in code, these characters are literals, - * and lose their special Markdown meanings. - */ - showdown.subParser('makehtml.encodeCode', function (text, options, globals) { - 'use strict'; - - text = globals.converter._dispatch('makehtml.encodeCode.before', text, options, globals).getText(); - - // Encode all ampersands; HTML entities are not - // entities within a Markdown code span. - text = text - .replace(/&/g, '&') - // Do the angle bracket song and dance: - .replace(//g, '>') - // Now, escape characters that are magic in Markdown: - .replace(/([*_{}\[\]\\=~-])/g, showdown.helper.escapeCharactersCallback); - - text = globals.converter._dispatch('makehtml.encodeCode.after', text, options, globals).getText(); - return text; - }); - - /** - * Within tags -- meaning between < and > -- encode [\ ` * _ ~ =] so they - * don't conflict with their use in Markdown for code, italics and strong. - */ - showdown.subParser('makehtml.escapeSpecialCharsWithinTagAttributes', function (text, options, globals) { - 'use strict'; - text = globals.converter._dispatch('makehtml.escapeSpecialCharsWithinTagAttributes.before', text, options, globals).getText(); - - // Build a regex to find HTML tags. - var tags = /<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi, - comments = /-]|-[^>])(?:[^-]|-[^-])*)--)>/gi; - - text = text.replace(tags, function (wholeMatch) { - return wholeMatch - .replace(/(.)<\/?code>(?=.)/g, '$1`') - .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback); - }); - - text = text.replace(comments, function (wholeMatch) { - return wholeMatch - .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback); - }); - - text = globals.converter._dispatch('makehtml.escapeSpecialCharsWithinTagAttributes.after', text, options, globals).getText(); - return text; - }); - - /** - * Handle github codeblocks prior to running HashHTML so that - * HTML contained within the codeblock gets escaped properly - * Example: - * ```ruby - * def hello_world(x) - * puts "Hello, #{x}" - * end - * ``` - */ - showdown.subParser('makehtml.githubCodeBlocks', function (text, options, globals) { - 'use strict'; - - // early exit if option is not enabled - if (!options.ghCodeBlocks) { - return text; - } - - text = globals.converter._dispatch('makehtml.githubCodeBlocks.before', text, options, globals).getText(); - - text += '¨0'; - - text = text.replace(/(?:^|\n)(?: {0,3})(```+|~~~+)(?: *)([^\s`~]*)\n([\s\S]*?)\n(?: {0,3})\1/g, function (wholeMatch, delim, language, codeblock) { - var end = (options.omitExtraWLInCodeBlocks) ? '' : '\n'; - - // First parse the github code block - codeblock = showdown.subParser('makehtml.encodeCode')(codeblock, options, globals); - codeblock = showdown.subParser('makehtml.detab')(codeblock, options, globals); - codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines - codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace - - codeblock = '
    ' + codeblock + end + '
    '; - - codeblock = showdown.subParser('makehtml.hashBlock')(codeblock, options, globals); - - // Since GHCodeblocks can be false positives, we need to - // store the primitive text and the parsed text in a global var, - // and then return a token - return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n'; - }); - - // attacklab: strip sentinel - text = text.replace(/¨0/, ''); - - return globals.converter._dispatch('makehtml.githubCodeBlocks.after', text, options, globals).getText(); - }); - - showdown.subParser('makehtml.hashBlock', function (text, options, globals) { - 'use strict'; - text = globals.converter._dispatch('makehtml.hashBlock.before', text, options, globals).getText(); - text = text.replace(/(^\n+|\n+$)/g, ''); - text = '\n\n¨K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n'; - text = globals.converter._dispatch('makehtml.hashBlock.after', text, options, globals).getText(); - return text; - }); - - /** - * Hash and escape elements that should not be parsed as markdown - */ - showdown.subParser('makehtml.hashCodeTags', function (text, options, globals) { - 'use strict'; - text = globals.converter._dispatch('makehtml.hashCodeTags.before', text, options, globals).getText(); - - var repFunc = function (wholeMatch, match, left, right) { - var codeblock = left + showdown.subParser('makehtml.encodeCode')(match, options, globals) + right; - return '¨C' + (globals.gHtmlSpans.push(codeblock) - 1) + 'C'; - }; - - // Hash naked - text = showdown.helper.replaceRecursiveRegExp(text, repFunc, ']*>', '', 'gim'); - - text = globals.converter._dispatch('makehtml.hashCodeTags.after', text, options, globals).getText(); - return text; - }); - - showdown.subParser('makehtml.hashElement', function (text, options, globals) { - 'use strict'; - - return function (wholeMatch, m1) { - var blockText = m1; - - // Undo double lines - blockText = blockText.replace(/\n\n/g, '\n'); - blockText = blockText.replace(/^\n/, ''); - - // strip trailing blank lines - blockText = blockText.replace(/\n+$/g, ''); - - // Replace the element text with a marker ("¨KxK" where x is its key) - blockText = '\n\n¨K' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n'; - - return blockText; - }; - }); - - showdown.subParser('makehtml.hashHTMLBlocks', function (text, options, globals) { - 'use strict'; - text = globals.converter._dispatch('makehtml.hashHTMLBlocks.before', text, options, globals).getText(); - - var blockTags = [ - 'pre', - 'div', - 'h1', - 'h2', - 'h3', - 'h4', - 'h5', - 'h6', - 'blockquote', - 'table', - 'dl', - 'ol', - 'ul', - 'script', - 'noscript', - 'form', - 'fieldset', - 'iframe', - 'math', - 'style', - 'section', - 'header', - 'footer', - 'nav', - 'article', - 'aside', - 'address', - 'audio', - 'canvas', - 'figure', - 'hgroup', - 'output', - 'video', - 'details', - 'p' - ], - repFunc = function (wholeMatch, match, left, right) { - var txt = wholeMatch; - // check if this html element is marked as markdown - // if so, it's contents should be parsed as markdown - if (left.search(/\bmarkdown\b/) !== -1) { - txt = left + globals.converter.makeHtml(match) + right; - } - return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n'; - }; - - if (options.backslashEscapesHTMLTags) { - // encode backslash escaped HTML tags - text = text.replace(/\\<(\/?[^>]+?)>/g, function (wm, inside) { - return '<' + inside + '>'; - }); - } - - // hash HTML Blocks - for (var i = 0; i < blockTags.length; ++i) { - - var opTagPos, - rgx1 = new RegExp('^ {0,3}(<' + blockTags[i] + '\\b[^>]*>)', 'im'), - patLeft = '<' + blockTags[i] + '\\b[^>]*>', - patRight = ''; - // 1. Look for the first position of the first opening HTML tag in the text - while ((opTagPos = showdown.helper.regexIndexOf(text, rgx1)) !== -1) { - - // if the HTML tag is \ escaped, we need to escape it and break - - - //2. Split the text in that position - var subTexts = showdown.helper.splitAtIndex(text, opTagPos), - //3. Match recursively - newSubText1 = showdown.helper.replaceRecursiveRegExp(subTexts[1], repFunc, patLeft, patRight, 'im'); - - // prevent an infinite loop - if (newSubText1 === subTexts[1]) { - break; - } - text = subTexts[0].concat(newSubText1); - } - } - // HR SPECIAL CASE - text = text.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, - showdown.subParser('makehtml.hashElement')(text, options, globals)); - - // Special case for standalone HTML comments - text = showdown.helper.replaceRecursiveRegExp(text, function (txt) { - return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n'; - }, '^ {0,3}', 'gm'); - - // PHP and ASP-style processor instructions ( and <%...%>) - text = text.replace(/(?:\n\n)( {0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, - showdown.subParser('makehtml.hashElement')(text, options, globals)); - - text = globals.converter._dispatch('makehtml.hashHTMLBlocks.after', text, options, globals).getText(); - return text; - }); - - /** - * Hash span elements that should not be parsed as markdown - */ - showdown.subParser('makehtml.hashHTMLSpans', function (text, options, globals) { - 'use strict'; - text = globals.converter._dispatch('makehtml.hashHTMLSpans.before', text, options, globals).getText(); - - // Hash Self Closing tags - text = text.replace(/<[^>]+?\/>/gi, function (wm) { - return showdown.helper._hashHTMLSpan(wm, globals); - }); - - // Hash tags without properties - text = text.replace(/<([^>]+?)>[\s\S]*?<\/\1>/g, function (wm) { - return showdown.helper._hashHTMLSpan(wm, globals); - }); - - // Hash tags with properties - text = text.replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g, function (wm) { - return showdown.helper._hashHTMLSpan(wm, globals); - }); - - // Hash self closing tags without /> - text = text.replace(/<[^>]+?>/gi, function (wm) { - return showdown.helper._hashHTMLSpan(wm, globals); - }); - - text = globals.converter._dispatch('makehtml.hashHTMLSpans.after', text, options, globals).getText(); - return text; - }); - - /** - * Unhash HTML spans - */ - showdown.subParser('makehtml.unhashHTMLSpans', function (text, options, globals) { - 'use strict'; - text = globals.converter._dispatch('makehtml.unhashHTMLSpans.before', text, options, globals).getText(); - - for (var i = 0; i < globals.gHtmlSpans.length; ++i) { - var repText = globals.gHtmlSpans[i], - // limiter to prevent infinite loop (assume 10 as limit for recurse) - limit = 0; - - while (/¨C(\d+)C/.test(repText)) { - var num = RegExp.$1; - repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]); - if (limit === 10) { - console.error('maximum nesting of 10 spans reached!!!'); - break; - } - ++limit; - } - text = text.replace('¨C' + i + 'C', repText); - } - - text = globals.converter._dispatch('makehtml.unhashHTMLSpans.after', text, options, globals).getText(); - return text; - }); - - /** - * Hash and escape
     elements that should not be parsed as markdown
    -     */
    -    showdown.subParser('makehtml.hashPreCodeTags', function (text, options, globals) {
    -        'use strict';
    -        text = globals.converter._dispatch('makehtml.hashPreCodeTags.before', text, options, globals).getText();
    -
    -        var repFunc = function (wholeMatch, match, left, right) {
    -            // encode html entities
    -            var codeblock = left + showdown.subParser('makehtml.encodeCode')(match, options, globals) + right;
    -            return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
    -        };
    -
    -        // Hash 
    
    -        text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^ {0,3}]*>\\s*]*>', '^ {0,3}\\s*
    ', 'gim'); - - text = globals.converter._dispatch('makehtml.hashPreCodeTags.after', text, options, globals).getText(); - return text; - }); - - showdown.subParser('makehtml.headers', function (text, options, globals) { - 'use strict'; - - text = globals.converter._dispatch('makehtml.headers.before', text, options, globals).getText(); - - var headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart), - - // Set text-style headers: - // Header 1 - // ======== - // - // Header 2 - // -------- - // - setextRegexH1 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm, - setextRegexH2 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n-+[ \t]*\n+/gm; - - text = text.replace(setextRegexH1, function (wholeMatch, m1) { - - var spanGamut = showdown.subParser('makehtml.spanGamut')(m1, options, globals), - hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"', - hLevel = headerLevelStart, - hashBlock = '' + spanGamut + ''; - return showdown.subParser('makehtml.hashBlock')(hashBlock, options, globals); - }); - - text = text.replace(setextRegexH2, function (matchFound, m1) { - var spanGamut = showdown.subParser('makehtml.spanGamut')(m1, options, globals), - hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"', - hLevel = headerLevelStart + 1, - hashBlock = '' + spanGamut + ''; - return showdown.subParser('makehtml.hashBlock')(hashBlock, options, globals); - }); - - // atx-style headers: - // # Header 1 - // ## Header 2 - // ## Header 2 with closing hashes ## - // ... - // ###### Header 6 - // - var atxStyle = (options.requireSpaceBeforeHeadingText) ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm; - - text = text.replace(atxStyle, function (wholeMatch, m1, m2) { - var hText = m2; - if (options.customizedHeaderId) { - hText = m2.replace(/\s?\{([^{]+?)}\s*$/, ''); - } - - var span = showdown.subParser('makehtml.spanGamut')(hText, options, globals), - hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"', - hLevel = headerLevelStart - 1 + m1.length, - header = '' + span + ''; - - return showdown.subParser('makehtml.hashBlock')(header, options, globals); - }); - - function headerId (m) { - var title, - prefix; - - // It is separate from other options to allow combining prefix and customized - if (options.customizedHeaderId) { - var match = m.match(/\{([^{]+?)}\s*$/); - if (match && match[1]) { - m = match[1]; - } - } - - title = m; - - // Prefix id to prevent causing inadvertent pre-existing style matches. - if (showdown.helper.isString(options.prefixHeaderId)) { - prefix = options.prefixHeaderId; - } else if (options.prefixHeaderId === true) { - prefix = 'section-'; - } else { - prefix = ''; - } - - if (!options.rawPrefixHeaderId) { - title = prefix + title; - } - - if (options.ghCompatibleHeaderId) { - title = title - .replace(/ /g, '-') - // replace previously escaped chars (&, ¨ and $) - .replace(/&/g, '') - .replace(/¨T/g, '') - .replace(/¨D/g, '') - // replace rest of the chars (&~$ are repeated as they might have been escaped) - // borrowed from github's redcarpet (some they should produce similar results) - .replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g, '') - .toLowerCase(); - } else if (options.rawHeaderId) { - title = title - .replace(/ /g, '-') - // replace previously escaped chars (&, ¨ and $) - .replace(/&/g, '&') - .replace(/¨T/g, '¨') - .replace(/¨D/g, '$') - // replace " and ' - .replace(/["']/g, '-') - .toLowerCase(); - } else { - title = title - .replace(/[^\w]/g, '') - .toLowerCase(); - } - - if (options.rawPrefixHeaderId) { - title = prefix + title; - } - - if (globals.hashLinkCounts[title]) { - title = title + '-' + (globals.hashLinkCounts[title]++); - } else { - globals.hashLinkCounts[title] = 1; - } - return title; - } - - text = globals.converter._dispatch('makehtml.headers.after', text, options, globals).getText(); - return text; - }); - - /** - * Turn Markdown horizontal rule shortcuts into
    tags. - * - * Any 3 or more unindented consecutive hyphens, asterisks or underscores with or without a space beetween them - * in a single line is considered a horizontal rule - */ - showdown.subParser('makehtml.horizontalRule', function (text, options, globals) { - 'use strict'; - text = globals.converter._dispatch('makehtml.horizontalRule.before', text, options, globals).getText(); - - var key = showdown.subParser('makehtml.hashBlock')('
    ', options, globals); - text = text.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm, key); - text = text.replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm, key); - text = text.replace(/^ {0,2}( ?_){3,}[ \t]*$/gm, key); - - text = globals.converter._dispatch('makehtml.horizontalRule.after', text, options, globals).getText(); - return text; - }); - - /** - * Turn Markdown image shortcuts into tags. - */ - showdown.subParser('makehtml.images', function (text, options, globals) { - 'use strict'; - - text = globals.converter._dispatch('makehtml.images.before', text, options, globals).getText(); - - var inlineRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]??(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g, - crazyRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g, - base64RegExp = /!\[([^\]]*?)][ \t]*()\([ \t]??(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g, - referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g, - refShortcutRegExp = /!\[([^\[\]]+)]()()()()()/g; - - function writeImageTagBase64 (wholeMatch, altText, linkId, url, width, height, m5, title) { - url = url.replace(/\s/g, ''); - return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title); - } - - function writeImageTagBaseUrl (wholeMatch, altText, linkId, url, width, height, m5, title) { - url = showdown.helper.applyBaseUrl(options.relativePathBaseUrl, url); - - return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title); - } - - function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) { - - var gUrls = globals.gUrls, - gTitles = globals.gTitles, - gDims = globals.gDimensions; - - linkId = linkId.toLowerCase(); - - if (!title) { - title = ''; - } - // Special case for explicit empty url - if (wholeMatch.search(/\(? ?(['"].*['"])?\)$/m) > -1) { - url = ''; - - } else if (url === '' || url === null) { - if (linkId === '' || linkId === null) { - // lower-case and turn embedded newlines into spaces - linkId = altText.toLowerCase().replace(/ ?\n/g, ' '); - } - url = '#' + linkId; - - if (!showdown.helper.isUndefined(gUrls[linkId])) { - url = gUrls[linkId]; - if (!showdown.helper.isUndefined(gTitles[linkId])) { - title = gTitles[linkId]; - } - if (!showdown.helper.isUndefined(gDims[linkId])) { - width = gDims[linkId].width; - height = gDims[linkId].height; - } - } else { - return wholeMatch; - } - } - - altText = altText - .replace(/"/g, '"') - //altText = showdown.helper.escapeCharacters(altText, '*_', false); - .replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); - //url = showdown.helper.escapeCharacters(url, '*_', false); - url = url.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); - var result = '' + altText + 'x "optional title") - - // base64 encoded images - text = text.replace(base64RegExp, writeImageTagBase64); - - // cases with crazy urls like ./image/cat1).png - text = text.replace(crazyRegExp, writeImageTagBaseUrl); - - // normal cases - text = text.replace(inlineRegExp, writeImageTagBaseUrl); - - // handle reference-style shortcuts: ![img text] - text = text.replace(refShortcutRegExp, writeImageTag); - - text = globals.converter._dispatch('makehtml.images.after', text, options, globals).getText(); - return text; - }); - - showdown.subParser('makehtml.italicsAndBold', function (text, options, globals) { - 'use strict'; - - text = globals.converter._dispatch('makehtml.italicsAndBold.before', text, options, globals).getText(); - - // it's faster to have 3 separate regexes for each case than have just one - // because of backtracing, in some cases, it could lead to an exponential effect - // called "catastrophic backtrace". Ominous! - - function parseInside (txt, left, right) { - return left + txt + right; - } - - // Parse underscores - if (options.literalMidWordUnderscores) { - text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) { - return parseInside (txt, '', ''); - }); - text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) { - return parseInside (txt, '', ''); - }); - text = text.replace(/\b_(\S[\s\S]*?)_\b/g, function (wm, txt) { - return parseInside (txt, '', ''); - }); - } else { - text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) { - return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; - }); - text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) { - return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; - }); - text = text.replace(/_([^\s_][\s\S]*?)_/g, function (wm, m) { - // !/^_[^_]/.test(m) - test if it doesn't start with __ (since it seems redundant, we removed it) - return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; - }); - } - - // Now parse asterisks - /* - if (options.literalMidWordAsterisks) { - text = text.replace(/([^*]|^)\B\*\*\*(\S[\s\S]+?)\*\*\*\B(?!\*)/g, function (wm, lead, txt) { - return parseInside (txt, lead + '', ''); - }); - text = text.replace(/([^*]|^)\B\*\*(\S[\s\S]+?)\*\*\B(?!\*)/g, function (wm, lead, txt) { - return parseInside (txt, lead + '', ''); - }); - text = text.replace(/([^*]|^)\B\*(\S[\s\S]+?)\*\B(?!\*)/g, function (wm, lead, txt) { - return parseInside (txt, lead + '', ''); - }); - } else { - */ - text = text.replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g, function (wm, m) { - return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; - }); - text = text.replace(/\*\*(\S[\s\S]*?)\*\*/g, function (wm, m) { - return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; - }); - text = text.replace(/\*([^\s*][\s\S]*?)\*/g, function (wm, m) { - // !/^\*[^*]/.test(m) - test if it doesn't start with ** (since it seems redundant, we removed it) - return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; - }); - //} - - text = globals.converter._dispatch('makehtml.italicsAndBold.after', text, options, globals).getText(); - return text; - }); - -//// -// makehtml/links.js -// Copyright (c) 2018 ShowdownJS -// -// Transforms MD links into `
    ` html anchors -// -// A link contains link text (the visible text), a link destination (the URI that is the link destination), and -// optionally a link title. There are two basic kinds of links in Markdown. -// In inline links the destination and title are given immediately after the link text. -// In reference links the destination and title are defined elsewhere in the document. -// -// ***Author:*** -// - Estevão Soares dos Santos (Tivie) -//// - - (function () { - /** - * Helper function: Wrapper function to pass as second replace parameter - * - * @param {RegExp} rgx - * @param {string} evtRootName - * @param {{}} options - * @param {{}} globals - * @returns {Function} - */ - function replaceAnchorTagReference (rgx, evtRootName, options, globals, emptyCase) { - emptyCase = !!emptyCase; - return function (wholeMatch, text, id, url, m5, m6, title) { - // bail we we find 2 newlines somewhere - if (/\n\n/.test(wholeMatch)) { - return wholeMatch; - } - - var evt = createEvent(rgx, evtRootName + '.captureStart', wholeMatch, text, id, url, title, options, globals); - return writeAnchorTag(evt, options, globals, emptyCase); - }; - } - - function replaceAnchorTagBaseUrl (rgx, evtRootName, options, globals, emptyCase) { - return function (wholeMatch, text, id, url, m5, m6, title) { - url = showdown.helper.applyBaseUrl(options.relativePathBaseUrl, url); - - var evt = createEvent(rgx, evtRootName + '.captureStart', wholeMatch, text, id, url, title, options, globals); - return writeAnchorTag(evt, options, globals, emptyCase); - }; - } - - /** - * TODO Normalize this - * Helper function: Create a capture event - * @param {RegExp} rgx - * @param {String} evtName Event name - * @param {String} wholeMatch - * @param {String} text - * @param {String} id - * @param {String} url - * @param {String} title - * @param {{}} options - * @param {{}} globals - * @returns {showdown.helper.Event|*} - */ - function createEvent (rgx, evtName, wholeMatch, text, id, url, title, options, globals) { - return globals.converter._dispatch(evtName, wholeMatch, options, globals, { - regexp: rgx, - matches: { - wholeMatch: wholeMatch, - text: text, - id: id, - url: url, - title: title - } - }); - } - - /** - * Helper Function: Normalize and write an anchor tag based on passed parameters - * @param evt - * @param options - * @param globals - * @param {boolean} emptyCase - * @returns {string} - */ - function writeAnchorTag (evt, options, globals, emptyCase) { - - var wholeMatch = evt.getMatches().wholeMatch; - var text = evt.getMatches().text; - var id = evt.getMatches().id; - var url = evt.getMatches().url; - var title = evt.getMatches().title; - var target = ''; - - if (!title) { - title = ''; - } - id = (id) ? id.toLowerCase() : ''; - - if (emptyCase) { - url = ''; - } else if (!url) { - if (!id) { - // lower-case and turn embedded newlines into spaces - id = text.toLowerCase().replace(/ ?\n/g, ' '); - } - url = '#' + id; - - if (!showdown.helper.isUndefined(globals.gUrls[id])) { - url = globals.gUrls[id]; - if (!showdown.helper.isUndefined(globals.gTitles[id])) { - title = globals.gTitles[id]; - } - } else { - return wholeMatch; - } - } - //url = showdown.helper.escapeCharacters(url, '*_:~', false); // replaced line to improve performance - url = url.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); - - if (title !== '' && title !== null) { - title = title.replace(/"/g, '"'); - //title = showdown.helper.escapeCharacters(title, '*_', false); // replaced line to improve performance - title = title.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); - title = ' title="' + title + '"'; - } - - // optionLinksInNewWindow only applies - // to external links. Hash links (#) open in same page - if (options.openLinksInNewWindow && !/^#/.test(url)) { - // escaped _ - target = ' rel="noopener noreferrer" target="¨E95Eblank"'; - } - - // Text can be a markdown element, so we run through the appropriate parsers - text = showdown.subParser('makehtml.codeSpans')(text, options, globals); - text = showdown.subParser('makehtml.emoji')(text, options, globals); - text = showdown.subParser('makehtml.underline')(text, options, globals); - text = showdown.subParser('makehtml.italicsAndBold')(text, options, globals); - text = showdown.subParser('makehtml.strikethrough')(text, options, globals); - text = showdown.subParser('makehtml.ellipsis')(text, options, globals); - text = showdown.subParser('makehtml.hashHTMLSpans')(text, options, globals); - - //evt = createEvent(rgx, evtRootName + '.captureEnd', wholeMatch, text, id, url, title, options, globals); - - var result = '' + text + ''; - - //evt = createEvent(rgx, evtRootName + '.beforeHash', wholeMatch, text, id, url, title, options, globals); - - result = showdown.subParser('makehtml.hashHTMLSpans')(result, options, globals); - - return result; - } - - var evtRootName = 'makehtml.links'; - - /** - * Turn Markdown link shortcuts into XHTML tags. - */ - showdown.subParser('makehtml.links', function (text, options, globals) { - - text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); - - // 1. Handle reference-style links: [link text] [id] - text = showdown.subParser('makehtml.links.reference')(text, options, globals); - - // 2. Handle inline-style links: [link text](url "optional title") - text = showdown.subParser('makehtml.links.inline')(text, options, globals); - - // 3. Handle reference-style shortcuts: [link text] - // These must come last in case there's a [link text][1] or [link text](/foo) - text = showdown.subParser('makehtml.links.referenceShortcut')(text, options, globals); - - // 4. Handle angle brackets links -> `` - // Must come after links, because you can use < and > delimiters in inline links like [this](). - text = showdown.subParser('makehtml.links.angleBrackets')(text, options, globals); - - // 5. Handle GithubMentions (if option is enabled) - text = showdown.subParser('makehtml.links.ghMentions')(text, options, globals); - - // 6. Handle tags and img tags - text = text.replace(/]*>[\s\S]*<\/a>/g, function (wholeMatch) { - return showdown.helper._hashHTMLSpan(wholeMatch, globals); - }); - - text = text.replace(/]*\/?>/g, function (wholeMatch) { - return showdown.helper._hashHTMLSpan(wholeMatch, globals); - }); - - // 7. Handle naked links (if option is enabled) - text = showdown.subParser('makehtml.links.naked')(text, options, globals); - - text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); - return text; - }); - - /** - * TODO WRITE THIS DOCUMENTATION - */ - showdown.subParser('makehtml.links.inline', function (text, options, globals) { - var evtRootName = evtRootName + '.inline'; - - text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); - - // 1. Look for empty cases: []() and [empty]() and []("title") - var rgxEmpty = /\[(.*?)]()()()()\(? ?(?:["'](.*)["'])?\)/g; - text = text.replace(rgxEmpty, replaceAnchorTagBaseUrl(rgxEmpty, evtRootName, options, globals, true)); - - // 2. Look for cases with crazy urls like ./image/cat1).png - var rgxCrazy = /\[((?:\[[^\]]*]|[^\[\]])*)]()\s?\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g; - text = text.replace(rgxCrazy, replaceAnchorTagBaseUrl(rgxCrazy, evtRootName, options, globals)); - - // 3. inline links with no title or titles wrapped in ' or ": - // [text](url.com) || [text]() || [text](url.com "title") || [text]( "title") - //var rgx2 = /\[[ ]*[\s]?[ ]*([^\n\[\]]*?)[ ]*[\s]?[ ]*] ?()\(?(?:[ ]*[\n]?[ ]*()(['"])(.*?)\5)?[ ]*[\s]?[ ]*\)/; // this regex is too slow!!! - var rgx2 = /\[([\S ]*?)]\s?()\( *?\s*(?:()(['"])(.*?)\5)? *\)/g; - text = text.replace(rgx2, replaceAnchorTagBaseUrl(rgx2, evtRootName, options, globals)); - - // 4. inline links with titles wrapped in (): [foo](bar.com (title)) - var rgx3 = /\[([\S ]*?)]\s?()\( *?\s+()()\((.*?)\) *\)/g; - text = text.replace(rgx3, replaceAnchorTagBaseUrl(rgx3, evtRootName, options, globals)); - - text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); - - return text; - }); - - /** - * TODO WRITE THIS DOCUMENTATION - */ - showdown.subParser('makehtml.links.reference', function (text, options, globals) { - var evtRootName = evtRootName + '.reference'; - - text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); - - var rgx = /\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g; - text = text.replace(rgx, replaceAnchorTagReference(rgx, evtRootName, options, globals)); - - text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); - - return text; - }); - - /** - * TODO WRITE THIS DOCUMENTATION - */ - showdown.subParser('makehtml.links.referenceShortcut', function (text, options, globals) { - var evtRootName = evtRootName + '.referenceShortcut'; - - text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); - - var rgx = /\[([^\[\]]+)]()()()()()/g; - text = text.replace(rgx, replaceAnchorTagReference(rgx, evtRootName, options, globals)); - - text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); - - return text; - }); - - /** - * TODO WRITE THIS DOCUMENTATION - */ - showdown.subParser('makehtml.links.ghMentions', function (text, options, globals) { - var evtRootName = evtRootName + 'ghMentions'; - - if (!options.ghMentions) { - return text; - } - - text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); - - var rgx = /(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d._-]+?[a-z\d]+)*))/gi; - - text = text.replace(rgx, function (wholeMatch, st, escape, mentions, username) { - // bail if the mentions was escaped - if (escape === '\\') { - return st + mentions; - } - - // check if options.ghMentionsLink is a string - // TODO Validation should be done at initialization not at runtime - if (!showdown.helper.isString(options.ghMentionsLink)) { - throw new Error('ghMentionsLink option must be a string'); - } - var url = options.ghMentionsLink.replace(/{u}/g, username); - var evt = createEvent(rgx, evtRootName + '.captureStart', wholeMatch, mentions, null, url, null, options, globals); - // captureEnd Event is triggered inside writeAnchorTag function - return st + writeAnchorTag(evt, options, globals); - }); - - text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); - - return text; - }); - - /** - * TODO WRITE THIS DOCUMENTATION - */ - showdown.subParser('makehtml.links.angleBrackets', function (text, options, globals) { - var evtRootName = 'makehtml.links.angleBrackets'; - - text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); - - // 1. Parse links first - var urlRgx = /<(((?:https?|ftp):\/\/|www\.)[^'">\s]+)>/gi; - text = text.replace(urlRgx, function (wholeMatch, url, urlStart) { - var text = url; - url = (urlStart === 'www.') ? 'http://' + url : url; - var evt = createEvent(urlRgx, evtRootName + '.captureStart', wholeMatch, text, null, url, null, options, globals); - return writeAnchorTag(evt, options, globals); - }); - - // 2. Then Mail Addresses - var mailRgx = /<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi; - text = text.replace(mailRgx, function (wholeMatch, mail) { - var url = 'mailto:'; - mail = showdown.subParser('makehtml.unescapeSpecialChars')(mail, options, globals); - if (options.encodeEmails) { - url = showdown.helper.encodeEmailAddress(url + mail); - mail = showdown.helper.encodeEmailAddress(mail); - } else { - url = url + mail; - } - var evt = createEvent(mailRgx, evtRootName + '.captureStart', wholeMatch, mail, null, url, null, options, globals); - return writeAnchorTag(evt, options, globals); - }); - - text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); - return text; - }); - - /** - * TODO MAKE THIS WORK (IT'S NOT ACTIVATED) - * TODO WRITE THIS DOCUMENTATION - */ - showdown.subParser('makehtml.links.naked', function (text, options, globals) { - if (!options.simplifiedAutoLink) { - return text; - } - - var evtRootName = 'makehtml.links.naked'; - - text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); - - // 2. Now we check for - // we also include leading markdown magic chars [_*~] for cases like __https://www.google.com/foobar__ - var urlRgx = /([_*~]*?)(((?:https?|ftp):\/\/|www\.)[^\s<>"'`´.-][^\s<>"'`´]*?\.[a-z\d.]+[^\s<>"']*)\1/gi; - text = text.replace(urlRgx, function (wholeMatch, leadingMDChars, url, urlPrefix) { - - // we now will start traversing the url from the front to back, looking for punctuation chars [_*~,;:.!?\)\]] - var len = url.length; - var suffix = ''; - for (var i = len - 1; i >= 0; --i) { - var char = url.charAt(i); - - if (/[_*~,;:.!?]/.test(char)) { - // it's a punctuation char - // we remove it from the url - url = url.slice(0, -1); - // and prepend it to the suffix - suffix = char + suffix; - } else if (/\)/.test(char)) { - var opPar = url.match(/\(/g) || []; - var clPar = url.match(/\)/g); - - // it's a curved parenthesis so we need to check for "balance" (kinda) - if (opPar.length < clPar.length) { - // there are more closing Parenthesis than opening so chop it!!!!! - url = url.slice(0, -1); - // and prepend it to the suffix - suffix = char + suffix; - } else { - // it's (kinda) balanced so our work is done - break; - } - } else if (/]/.test(char)) { - var opPar2 = url.match(/\[/g) || []; - var clPar2 = url.match(/\]/g); - // it's a squared parenthesis so we need to check for "balance" (kinda) - if (opPar2.length < clPar2.length) { - // there are more closing Parenthesis than opening so chop it!!!!! - url = url.slice(0, -1); - // and prepend it to the suffix - suffix = char + suffix; - } else { - // it's (kinda) balanced so our work is done - break; - } - } else { - // it's not a punctuation or a parenthesis so our work is done - break; - } - } - - // we copy the treated url to the text variable - var text = url; - // finally, if it's a www shortcut, we prepend http - url = (urlPrefix === 'www.') ? 'http://' + url : url; - - // url part is done so let's take care of text now - // we need to escape the text (because of links such as www.example.com/foo__bar__baz) - text = text.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); - - // finally we dispatch the event - var evt = createEvent(urlRgx, evtRootName + '.captureStart', wholeMatch, text, null, url, null, options, globals); - - // and return the link tag, with the leadingMDChars and suffix. The leadingMDChars are added at the end too because - // we consumed those characters in the regexp - return leadingMDChars + writeAnchorTag(evt, options, globals) + suffix + leadingMDChars; - }); - - // 2. Then mails - var mailRgx = /(^|\s)(?:mailto:)?([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?=$|\s)/gmi; - text = text.replace(mailRgx, function (wholeMatch, leadingChar, mail) { - var url = 'mailto:'; - mail = showdown.subParser('makehtml.unescapeSpecialChars')(mail, options, globals); - if (options.encodeEmails) { - url = showdown.helper.encodeEmailAddress(url + mail); - mail = showdown.helper.encodeEmailAddress(mail); - } else { - url = url + mail; - } - var evt = createEvent(mailRgx, evtRootName + '.captureStart', wholeMatch, mail, null, url, null, options, globals); - return leadingChar + writeAnchorTag(evt, options, globals); - }); - - - text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); - return text; - }); - })(); - - /** - * Form HTML ordered (numbered) and unordered (bulleted) lists. - */ - showdown.subParser('makehtml.lists', function (text, options, globals) { - 'use strict'; - - /** - * Process the contents of a single ordered or unordered list, splitting it - * into individual list items. - * @param {string} listStr - * @param {boolean} trimTrailing - * @returns {string} - */ - function processListItems (listStr, trimTrailing) { - // The $g_list_level global keeps track of when we're inside a list. - // Each time we enter a list, we increment it; when we leave a list, - // we decrement. If it's zero, we're not in a list anymore. - // - // We do this because when we're not inside a list, we want to treat - // something like this: - // - // I recommend upgrading to version - // 8. Oops, now this line is treated - // as a sub-list. - // - // As a single paragraph, despite the fact that the second line starts - // with a digit-period-space sequence. - // - // Whereas when we're inside a list (or sub-list), that line will be - // treated as the start of a sub-list. What a kludge, huh? This is - // an aspect of Markdown's syntax that's hard to parse perfectly - // without resorting to mind-reading. Perhaps the solution is to - // change the syntax rules such that sub-lists must start with a - // starting cardinal number; e.g. "1." or "a.". - globals.gListLevel++; - - // trim trailing blank lines: - listStr = listStr.replace(/\n{2,}$/, '\n'); - - // attacklab: add sentinel to emulate \z - listStr += '¨0'; - - var rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm, - isParagraphed = (/\n[ \t]*\n(?!¨0)/.test(listStr)); - - // Since version 1.5, nesting sublists requires 4 spaces (or 1 tab) indentation, - // which is a syntax breaking change - // activating this option reverts to old behavior - // This will be removed in version 2.0 - if (options.disableForced4SpacesIndentedSublists) { - rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm; - } - - listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) { - checked = (checked && checked.trim() !== ''); - - var item = showdown.subParser('makehtml.outdent')(m4, options, globals), - bulletStyle = ''; - - // Support for github tasklists - if (taskbtn && options.tasklists) { - bulletStyle = ' class="task-list-item" style="list-style-type: none;"'; - item = item.replace(/^[ \t]*\[(x|X| )?]/m, function () { - var otp = '
  • a
  • - // instead of: - //
    • - - a
    - // So, to prevent it, we will put a marker (¨A)in the beginning of the line - // Kind of hackish/monkey patching, but seems more effective than overcomplicating the list parser - item = item.replace(/^([-*+]|\d\.)[ \t]+[\S\n ]*/g, function (wm2) { - return '¨A' + wm2; - }); - - // SPECIAL CASE: an heading followed by a paragraph of text that is not separated by a double newline - // or/nor indented. ex: - // - // - # foo - // bar is great - // - // While this does now follow the spec per se, not allowing for this might cause confusion since - // header blocks don't need double newlines after - if (/^#+.+\n.+/.test(item)) { - item = item.replace(/^(#+.+)$/m, '$1\n'); - } - - // m1 - Leading line or - // Has a double return (multi paragraph) - if (m1 || (item.search(/\n{2,}/) > -1)) { - item = showdown.subParser('makehtml.githubCodeBlocks')(item, options, globals); - item = showdown.subParser('makehtml.blockGamut')(item, options, globals); - } else { - - // Recursion for sub-lists: - item = showdown.subParser('makehtml.lists')(item, options, globals); - item = item.replace(/\n$/, ''); // chomp(item) - item = showdown.subParser('makehtml.hashHTMLBlocks')(item, options, globals); - - // Colapse double linebreaks - item = item.replace(/\n\n+/g, '\n\n'); - - if (isParagraphed) { - item = showdown.subParser('makehtml.paragraphs')(item, options, globals); - } else { - item = showdown.subParser('makehtml.spanGamut')(item, options, globals); - } - } - - // now we need to remove the marker (¨A) - item = item.replace('¨A', ''); - // we can finally wrap the line in list item tags - item = '' + item + '\n'; - - return item; - }); - - // attacklab: strip sentinel - listStr = listStr.replace(/¨0/g, ''); - - globals.gListLevel--; - - if (trimTrailing) { - listStr = listStr.replace(/\s+$/, ''); - } - - return listStr; - } - - function styleStartNumber (list, listType) { - // check if ol and starts by a number different than 1 - if (listType === 'ol') { - var res = list.match(/^ *(\d+)\./); - if (res && res[1] !== '1') { - return ' start="' + res[1] + '"'; - } - } - return ''; - } - - /** - * Check and parse consecutive lists (better fix for issue #142) - * @param {string} list - * @param {string} listType - * @param {boolean} trimTrailing - * @returns {string} - */ - function parseConsecutiveLists (list, listType, trimTrailing) { - // check if we caught 2 or more consecutive lists by mistake - // we use the counterRgx, meaning if listType is UL we look for OL and vice versa - var olRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?\d+\.[ \t]/gm : /^ {0,3}\d+\.[ \t]/gm, - ulRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?[*+-][ \t]/gm : /^ {0,3}[*+-][ \t]/gm, - counterRxg = (listType === 'ul') ? olRgx : ulRgx, - result = ''; - - if (list.search(counterRxg) !== -1) { - (function parseCL (txt) { - var pos = txt.search(counterRxg), - style = styleStartNumber(list, listType); - if (pos !== -1) { - // slice - result += '\n\n<' + listType + style + '>\n' + processListItems(txt.slice(0, pos), !!trimTrailing) + '\n'; - - // invert counterType and listType - listType = (listType === 'ul') ? 'ol' : 'ul'; - counterRxg = (listType === 'ul') ? olRgx : ulRgx; - - //recurse - parseCL(txt.slice(pos)); - } else { - result += '\n\n<' + listType + style + '>\n' + processListItems(txt, !!trimTrailing) + '\n'; - } - })(list); - } else { - var style = styleStartNumber(list, listType); - result = '\n\n<' + listType + style + '>\n' + processListItems(list, !!trimTrailing) + '\n'; - } - - return result; - } - - // Start of list parsing - var subListRgx = /^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm; - var mainListRgx = /(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm; - - text = globals.converter._dispatch('lists.before', text, options, globals).getText(); - // add sentinel to hack around khtml/safari bug: - // http://bugs.webkit.org/show_bug.cgi?id=11231 - text += '¨0'; - - if (globals.gListLevel) { - text = text.replace(subListRgx, function (wholeMatch, list, m2) { - var listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol'; - return parseConsecutiveLists(list, listType, true); - }); - } else { - text = text.replace(mainListRgx, function (wholeMatch, m1, list, m3) { - var listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol'; - return parseConsecutiveLists(list, listType, false); - }); - } - - // strip sentinel - text = text.replace(/¨0/, ''); - text = globals.converter._dispatch('makehtml.lists.after', text, options, globals).getText(); - return text; - }); - - /** - * Parse metadata at the top of the document - */ - showdown.subParser('makehtml.metadata', function (text, options, globals) { - 'use strict'; - - if (!options.metadata) { - return text; - } - - text = globals.converter._dispatch('makehtml.metadata.before', text, options, globals).getText(); - - function parseMetadataContents (content) { - // raw is raw so it's not changed in any way - globals.metadata.raw = content; - - // escape chars forbidden in html attributes - // double quotes - content = content - // ampersand first - .replace(/&/g, '&') - // double quotes - .replace(/"/g, '"'); - - content = content.replace(/\n {4}/g, ' '); - content.replace(/^([\S ]+): +([\s\S]+?)$/gm, function (wm, key, value) { - globals.metadata.parsed[key] = value; - return ''; - }); - } - - text = text.replace(/^\s*«««+(\S*?)\n([\s\S]+?)\n»»»+\n/, function (wholematch, format, content) { - parseMetadataContents(content); - return '¨M'; - }); - - text = text.replace(/^\s*---+(\S*?)\n([\s\S]+?)\n---+\n/, function (wholematch, format, content) { - if (format) { - globals.metadata.format = format; - } - parseMetadataContents(content); - return '¨M'; - }); - - text = text.replace(/¨M/g, ''); - - text = globals.converter._dispatch('makehtml.metadata.after', text, options, globals).getText(); - return text; - }); - - /** - * Remove one level of line-leading tabs or spaces - */ - showdown.subParser('makehtml.outdent', function (text, options, globals) { - 'use strict'; - text = globals.converter._dispatch('makehtml.outdent.before', text, options, globals).getText(); - - // attacklab: hack around Konqueror 3.5.4 bug: - // "----------bug".replace(/^-/g,"") == "bug" - text = text.replace(/^(\t|[ ]{1,4})/gm, '¨0'); // attacklab: g_tab_width - - // attacklab: clean up hack - text = text.replace(/¨0/g, ''); - - text = globals.converter._dispatch('makehtml.outdent.after', text, options, globals).getText(); - return text; - }); - - /** - * - */ - showdown.subParser('makehtml.paragraphs', function (text, options, globals) { - 'use strict'; - - text = globals.converter._dispatch('makehtml.paragraphs.before', text, options, globals).getText(); - // Strip leading and trailing lines: - text = text.replace(/^\n+/g, ''); - text = text.replace(/\n+$/g, ''); - - var grafs = text.split(/\n{2,}/g), - grafsOut = [], - end = grafs.length; // Wrap

    tags - - for (var i = 0; i < end; i++) { - var str = grafs[i]; - // if this is an HTML marker, copy it - if (str.search(/¨(K|G)(\d+)\1/g) >= 0) { - grafsOut.push(str); - - // test for presence of characters to prevent empty lines being parsed - // as paragraphs (resulting in undesired extra empty paragraphs) - } else if (str.search(/\S/) >= 0) { - str = showdown.subParser('makehtml.spanGamut')(str, options, globals); - str = str.replace(/^([ \t]*)/g, '

    '); - str += '

    '; - grafsOut.push(str); - } - } - - /** Unhashify HTML blocks */ - end = grafsOut.length; - for (i = 0; i < end; i++) { - var blockText = '', - grafsOutIt = grafsOut[i], - codeFlag = false; - // if this is a marker for an html block... - // use RegExp.test instead of string.search because of QML bug - while (/¨(K|G)(\d+)\1/.test(grafsOutIt)) { - var delim = RegExp.$1, - num = RegExp.$2; - - if (delim === 'K') { - blockText = globals.gHtmlBlocks[num]; - } else { - // we need to check if ghBlock is a false positive - if (codeFlag) { - // use encoded version of all text - blockText = showdown.subParser('makehtml.encodeCode')(globals.ghCodeBlocks[num].text, options, globals); - } else { - blockText = globals.ghCodeBlocks[num].codeblock; - } - } - blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs - - grafsOutIt = grafsOutIt.replace(/(\n\n)?¨(K|G)\d+\2(\n\n)?/, blockText); - // Check if grafsOutIt is a pre->code - if (/^]*>\s*]*>/.test(grafsOutIt)) { - codeFlag = true; - } - } - grafsOut[i] = grafsOutIt; - } - text = grafsOut.join('\n'); - // Strip leading and trailing lines: - text = text.replace(/^\n+/g, ''); - text = text.replace(/\n+$/g, ''); - return globals.converter._dispatch('makehtml.paragraphs.after', text, options, globals).getText(); - }); - - /** - * Run extension - */ - showdown.subParser('makehtml.runExtension', function (ext, text, options, globals) { - 'use strict'; - - if (ext.filter) { - text = ext.filter(text, globals.converter, options); - - } else if (ext.regex) { - // TODO remove this when old extension loading mechanism is deprecated - var re = ext.regex; - if (!(re instanceof RegExp)) { - re = new RegExp(re, 'g'); - } - text = text.replace(re, ext.replace); - } - - return text; - }); - - /** - * These are all the transformations that occur *within* block-level - * tags like paragraphs, headers, and list items. - */ - showdown.subParser('makehtml.spanGamut', function (text, options, globals) { - 'use strict'; - - text = globals.converter._dispatch('makehtml.span.before', text, options, globals).getText(); - - text = showdown.subParser('makehtml.codeSpans')(text, options, globals); - text = showdown.subParser('makehtml.escapeSpecialCharsWithinTagAttributes')(text, options, globals); - text = showdown.subParser('makehtml.encodeBackslashEscapes')(text, options, globals); - - // Process link and image tags. Images must come first, - // because ![foo][f] looks like a link. - text = showdown.subParser('makehtml.images')(text, options, globals); - - text = globals.converter._dispatch('smakehtml.links.before', text, options, globals).getText(); - text = showdown.subParser('makehtml.links')(text, options, globals); - text = globals.converter._dispatch('smakehtml.links.after', text, options, globals).getText(); - - //text = showdown.subParser('makehtml.autoLinks')(text, options, globals); - //text = showdown.subParser('makehtml.simplifiedAutoLinks')(text, options, globals); - text = showdown.subParser('makehtml.emoji')(text, options, globals); - text = showdown.subParser('makehtml.underline')(text, options, globals); - text = showdown.subParser('makehtml.italicsAndBold')(text, options, globals); - text = showdown.subParser('makehtml.strikethrough')(text, options, globals); - text = showdown.subParser('makehtml.ellipsis')(text, options, globals); - - // we need to hash HTML tags inside spans - text = showdown.subParser('makehtml.hashHTMLSpans')(text, options, globals); - - // now we encode amps and angles - text = showdown.subParser('makehtml.encodeAmpsAndAngles')(text, options, globals); - - // Do hard breaks - if (options.simpleLineBreaks) { - // GFM style hard breaks - // only add line breaks if the text does not contain a block (special case for lists) - if (!/\n\n¨K/.test(text)) { - text = text.replace(/\n+/g, '
    \n'); - } - } else { - // Vanilla hard breaks - text = text.replace(/ +\n/g, '
    \n'); - } - - text = globals.converter._dispatch('makehtml.spanGamut.after', text, options, globals).getText(); - return text; - }); - - showdown.subParser('makehtml.strikethrough', function (text, options, globals) { - 'use strict'; - - if (options.strikethrough) { - text = globals.converter._dispatch('makehtml.strikethrough.before', text, options, globals).getText(); - text = text.replace(/(?:~){2}([\s\S]+?)(?:~){2}/g, function (wm, txt) { return '' + txt + ''; }); - text = globals.converter._dispatch('makehtml.strikethrough.after', text, options, globals).getText(); - } - - return text; - }); - - /** - * Strips link definitions from text, stores the URLs and titles in - * hash references. - * Link defs are in the form: ^[id]: url "optional title" - */ - showdown.subParser('makehtml.stripLinkDefinitions', function (text, options, globals) { - 'use strict'; - - var regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm, - base64Regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm; - - // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug - text += '¨0'; - - var replaceFunc = function (wholeMatch, linkId, url, width, height, blankLines, title) { - linkId = linkId.toLowerCase(); - if (url.match(/^data:.+?\/.+?;base64,/)) { - // remove newlines - globals.gUrls[linkId] = url.replace(/\s/g, ''); - } else { - url = showdown.helper.applyBaseUrl(options.relativePathBaseUrl, url); - - globals.gUrls[linkId] = showdown.subParser('makehtml.encodeAmpsAndAngles')(url, options, globals); // Link IDs are case-insensitive - } - - if (blankLines) { - // Oops, found blank lines, so it's not a title. - // Put back the parenthetical statement we stole. - return blankLines + title; - - } else { - if (title) { - globals.gTitles[linkId] = title.replace(/"|'/g, '"'); - } - if (options.parseImgDimensions && width && height) { - globals.gDimensions[linkId] = { - width: width, - height: height - }; - } - } - // Completely remove the definition from the text - return ''; - }; - - // first we try to find base64 link references - text = text.replace(base64Regex, replaceFunc); - - text = text.replace(regex, replaceFunc); - - // attacklab: strip sentinel - text = text.replace(/¨0/, ''); - - return text; - }); - - showdown.subParser('makehtml.tables', function (text, options, globals) { - 'use strict'; - - if (!options.tables) { - return text; - } - - var tableRgx = /^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm, - //singeColTblRgx = /^ {0,3}\|.+\|\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n(?: {0,3}\|.+\|\n)+(?:\n\n|¨0)/gm; - singeColTblRgx = /^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm; - - function parseStyles (sLine) { - if (/^:[ \t]*--*$/.test(sLine)) { - return ' style="text-align:left;"'; - } else if (/^--*[ \t]*:[ \t]*$/.test(sLine)) { - return ' style="text-align:right;"'; - } else if (/^:[ \t]*--*[ \t]*:$/.test(sLine)) { - return ' style="text-align:center;"'; - } else { - return ''; - } - } - - function parseHeaders (header, style) { - var id = ''; - header = header.trim(); - // support both tablesHeaderId and tableHeaderId due to error in documentation so we don't break backwards compatibility - if (options.tablesHeaderId || options.tableHeaderId) { - id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"'; - } - header = showdown.subParser('makehtml.spanGamut')(header, options, globals); - - return '' + header + '\n'; - } - - function parseCells (cell, style) { - var subText = showdown.subParser('makehtml.spanGamut')(cell, options, globals); - return '' + subText + '\n'; - } - - function buildTable (headers, cells) { - var tb = '\n\n\n', - tblLgn = headers.length; - - for (var i = 0; i < tblLgn; ++i) { - tb += headers[i]; - } - tb += '\n\n\n'; - - for (i = 0; i < cells.length; ++i) { - tb += '\n'; - for (var ii = 0; ii < tblLgn; ++ii) { - tb += cells[i][ii]; - } - tb += '\n'; - } - tb += '\n
    \n'; - return tb; - } - - function parseTable (rawTable) { - var i, tableLines = rawTable.split('\n'); - - for (i = 0; i < tableLines.length; ++i) { - // strip wrong first and last column if wrapped tables are used - if (/^ {0,3}\|/.test(tableLines[i])) { - tableLines[i] = tableLines[i].replace(/^ {0,3}\|/, ''); - } - if (/\|[ \t]*$/.test(tableLines[i])) { - tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, ''); - } - // parse code spans first, but we only support one line code spans - - tableLines[i] = showdown.subParser('makehtml.codeSpans')(tableLines[i], options, globals); - } - - var rawHeaders = tableLines[0].split('|').map(function (s) { return s.trim();}), - rawStyles = tableLines[1].split('|').map(function (s) { return s.trim();}), - rawCells = [], - headers = [], - styles = [], - cells = []; - - tableLines.shift(); - tableLines.shift(); - - for (i = 0; i < tableLines.length; ++i) { - if (tableLines[i].trim() === '') { - continue; - } - rawCells.push( - tableLines[i] - .split('|') - .map(function (s) { - return s.trim(); - }) - ); - } - - if (rawHeaders.length < rawStyles.length) { - return rawTable; - } - - for (i = 0; i < rawStyles.length; ++i) { - styles.push(parseStyles(rawStyles[i])); - } - - for (i = 0; i < rawHeaders.length; ++i) { - if (showdown.helper.isUndefined(styles[i])) { - styles[i] = ''; - } - headers.push(parseHeaders(rawHeaders[i], styles[i])); - } - - for (i = 0; i < rawCells.length; ++i) { - var row = []; - for (var ii = 0; ii < headers.length; ++ii) { - if (showdown.helper.isUndefined(rawCells[i][ii])) { - - } - row.push(parseCells(rawCells[i][ii], styles[ii])); - } - cells.push(row); - } - - return buildTable(headers, cells); - } - - text = globals.converter._dispatch('makehtml.tables.before', text, options, globals).getText(); - - // find escaped pipe characters - text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback); - - // parse multi column tables - text = text.replace(tableRgx, parseTable); - - // parse one column tables - text = text.replace(singeColTblRgx, parseTable); - - text = globals.converter._dispatch('makehtml.tables.after', text, options, globals).getText(); - - return text; - }); - - showdown.subParser('makehtml.underline', function (text, options, globals) { - 'use strict'; - - if (!options.underline) { - return text; - } - - text = globals.converter._dispatch('makehtml.underline.before', text, options, globals).getText(); - - if (options.literalMidWordUnderscores) { - text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) { - return '' + txt + ''; - }); - text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) { - return '' + txt + ''; - }); - } else { - text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) { - return (/\S$/.test(m)) ? '' + m + '' : wm; - }); - text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) { - return (/\S$/.test(m)) ? '' + m + '' : wm; - }); - } - - // escape remaining underscores to prevent them being parsed by italic and bold - text = text.replace(/(_)/g, showdown.helper.escapeCharactersCallback); - - text = globals.converter._dispatch('makehtml.underline.after', text, options, globals).getText(); - - return text; - }); - - /** - * Swap back in all the special characters we've hidden. - */ - showdown.subParser('makehtml.unescapeSpecialChars', function (text, options, globals) { - 'use strict'; - text = globals.converter._dispatch('makehtml.unescapeSpecialChars.before', text, options, globals).getText(); - - text = text.replace(/¨E(\d+)E/g, function (wholeMatch, m1) { - var charCodeToReplace = parseInt(m1); - return String.fromCharCode(charCodeToReplace); - }); - - text = globals.converter._dispatch('makehtml.unescapeSpecialChars.after', text, options, globals).getText(); - return text; - }); - - showdown.subParser('makeMarkdown.blockquote', function (node, globals) { - 'use strict'; - - var txt = ''; - if (node.hasChildNodes()) { - var children = node.childNodes, - childrenLength = children.length; - - for (var i = 0; i < childrenLength; ++i) { - var innerTxt = showdown.subParser('makeMarkdown.node')(children[i], globals); - - if (innerTxt === '') { - continue; - } - txt += innerTxt; - } - } - // cleanup - txt = txt.trim(); - txt = '> ' + txt.split('\n').join('\n> '); - return txt; - }); - - showdown.subParser('makeMarkdown.break', function () { - 'use strict'; - - return ' \n'; - }); - - showdown.subParser('makeMarkdown.codeBlock', function (node, globals) { - 'use strict'; - - var lang = node.getAttribute('language'), - num = node.getAttribute('precodenum'); - return '```' + lang + '\n' + globals.preList[num] + '\n```'; - }); - - showdown.subParser('makeMarkdown.codeSpan', function (node) { - 'use strict'; - - return '`' + node.innerHTML + '`'; - }); - - showdown.subParser('makeMarkdown.emphasis', function (node, globals) { - 'use strict'; - - var txt = ''; - if (node.hasChildNodes()) { - txt += '*'; - var children = node.childNodes, - childrenLength = children.length; - for (var i = 0; i < childrenLength; ++i) { - txt += showdown.subParser('makeMarkdown.node')(children[i], globals); - } - txt += '*'; - } - return txt; - }); - - showdown.subParser('makeMarkdown.header', function (node, globals, headerLevel) { - 'use strict'; - - var headerMark = new Array(headerLevel + 1).join('#'), - txt = ''; - - if (node.hasChildNodes()) { - txt = headerMark + ' '; - var children = node.childNodes, - childrenLength = children.length; - - for (var i = 0; i < childrenLength; ++i) { - txt += showdown.subParser('makeMarkdown.node')(children[i], globals); - } - } - return txt; - }); - - showdown.subParser('makeMarkdown.hr', function () { - 'use strict'; - - return '---'; - }); - - showdown.subParser('makeMarkdown.image', function (node) { - 'use strict'; - - var txt = ''; - if (node.hasAttribute('src')) { - txt += '![' + node.getAttribute('alt') + ']('; - txt += '<' + node.getAttribute('src') + '>'; - if (node.hasAttribute('width') && node.hasAttribute('height')) { - txt += ' =' + node.getAttribute('width') + 'x' + node.getAttribute('height'); - } - - if (node.hasAttribute('title')) { - txt += ' "' + node.getAttribute('title') + '"'; - } - txt += ')'; - } - return txt; - }); - - showdown.subParser('makeMarkdown.links', function (node, globals) { - 'use strict'; - - var txt = ''; - if (node.hasChildNodes() && node.hasAttribute('href')) { - var children = node.childNodes, - childrenLength = children.length; - txt = '['; - for (var i = 0; i < childrenLength; ++i) { - txt += showdown.subParser('makeMarkdown.node')(children[i], globals); - } - txt += ']('; - txt += '<' + node.getAttribute('href') + '>'; - if (node.hasAttribute('title')) { - txt += ' "' + node.getAttribute('title') + '"'; - } - txt += ')'; - } - return txt; - }); - - showdown.subParser('makeMarkdown.list', function (node, globals, type) { - 'use strict'; - - var txt = ''; - if (!node.hasChildNodes()) { - return ''; - } - var listItems = node.childNodes, - listItemsLenght = listItems.length, - listNum = node.getAttribute('start') || 1; - - for (var i = 0; i < listItemsLenght; ++i) { - if (typeof listItems[i].tagName === 'undefined' || listItems[i].tagName.toLowerCase() !== 'li') { - continue; - } - - // define the bullet to use in list - var bullet = ''; - if (type === 'ol') { - bullet = listNum.toString() + '. '; - } else { - bullet = '- '; - } - - // parse list item - txt += bullet + showdown.subParser('makeMarkdown.listItem')(listItems[i], globals); - ++listNum; - } - - return txt.trim(); - }); - - showdown.subParser('makeMarkdown.listItem', function (node, globals) { - 'use strict'; - - var listItemTxt = ''; - - var children = node.childNodes, - childrenLenght = children.length; - - for (var i = 0; i < childrenLenght; ++i) { - listItemTxt += showdown.subParser('makeMarkdown.node')(children[i], globals); - } - // if it's only one liner, we need to add a newline at the end - if (!/\n$/.test(listItemTxt)) { - listItemTxt += '\n'; - } else { - // it's multiparagraph, so we need to indent - listItemTxt = listItemTxt - .split('\n') - .join('\n ') - .replace(/^ {4}$/gm, '') - .replace(/\n\n+/g, '\n\n'); - } - - return listItemTxt; - }); - - - - showdown.subParser('makeMarkdown.node', function (node, globals, spansOnly) { - 'use strict'; - - spansOnly = spansOnly || false; - - var txt = ''; - - // edge case of text without wrapper paragraph - if (node.nodeType === 3) { - return showdown.subParser('makeMarkdown.txt')(node, globals); - } - - // HTML comment - if (node.nodeType === 8) { - return '\n\n'; - } - - // process only node elements - if (node.nodeType !== 1) { - return ''; - } - - var tagName = node.tagName.toLowerCase(); - - switch (tagName) { - - // - // BLOCKS - // - case 'h1': - if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 1) + '\n\n'; } - break; - case 'h2': - if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 2) + '\n\n'; } - break; - case 'h3': - if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 3) + '\n\n'; } - break; - case 'h4': - if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 4) + '\n\n'; } - break; - case 'h5': - if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 5) + '\n\n'; } - break; - case 'h6': - if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 6) + '\n\n'; } - break; - - case 'p': - if (!spansOnly) { txt = showdown.subParser('makeMarkdown.paragraph')(node, globals) + '\n\n'; } - break; - - case 'blockquote': - if (!spansOnly) { txt = showdown.subParser('makeMarkdown.blockquote')(node, globals) + '\n\n'; } - break; - - case 'hr': - if (!spansOnly) { txt = showdown.subParser('makeMarkdown.hr')(node, globals) + '\n\n'; } - break; - - case 'ol': - if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ol') + '\n\n'; } - break; - - case 'ul': - if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ul') + '\n\n'; } - break; - - case 'precode': - if (!spansOnly) { txt = showdown.subParser('makeMarkdown.codeBlock')(node, globals) + '\n\n'; } - break; - - case 'pre': - if (!spansOnly) { txt = showdown.subParser('makeMarkdown.pre')(node, globals) + '\n\n'; } - break; - - case 'table': - if (!spansOnly) { txt = showdown.subParser('makeMarkdown.table')(node, globals) + '\n\n'; } - break; - - // - // SPANS - // - case 'code': - txt = showdown.subParser('makeMarkdown.codeSpan')(node, globals); - break; - - case 'em': - case 'i': - txt = showdown.subParser('makeMarkdown.emphasis')(node, globals); - break; - - case 'strong': - case 'b': - txt = showdown.subParser('makeMarkdown.strong')(node, globals); - break; - - case 'del': - txt = showdown.subParser('makeMarkdown.strikethrough')(node, globals); - break; - - case 'a': - txt = showdown.subParser('makeMarkdown.links')(node, globals); - break; - - case 'img': - txt = showdown.subParser('makeMarkdown.image')(node, globals); - break; - - case 'br': - txt = showdown.subParser('makeMarkdown.break')(node, globals); - break; - - default: - txt = node.outerHTML + '\n\n'; - } - - // common normalization - // TODO eventually - - return txt; - }); - - showdown.subParser('makeMarkdown.paragraph', function (node, globals) { - 'use strict'; - - var txt = ''; - if (node.hasChildNodes()) { - var children = node.childNodes, - childrenLength = children.length; - for (var i = 0; i < childrenLength; ++i) { - txt += showdown.subParser('makeMarkdown.node')(children[i], globals); - } - } - - // some text normalization - txt = txt.trim(); - - return txt; - }); - - showdown.subParser('makeMarkdown.pre', function (node, globals) { - 'use strict'; - - var num = node.getAttribute('prenum'); - return '
    ' + globals.preList[num] + '
    '; - }); - - showdown.subParser('makeMarkdown.strikethrough', function (node, globals) { - 'use strict'; - - var txt = ''; - if (node.hasChildNodes()) { - txt += '~~'; - var children = node.childNodes, - childrenLength = children.length; - for (var i = 0; i < childrenLength; ++i) { - txt += showdown.subParser('makeMarkdown.node')(children[i], globals); - } - txt += '~~'; - } - return txt; - }); - - showdown.subParser('makeMarkdown.strong', function (node, globals) { - 'use strict'; - - var txt = ''; - if (node.hasChildNodes()) { - txt += '**'; - var children = node.childNodes, - childrenLength = children.length; - for (var i = 0; i < childrenLength; ++i) { - txt += showdown.subParser('makeMarkdown.node')(children[i], globals); - } - txt += '**'; - } - return txt; - }); - - showdown.subParser('makeMarkdown.table', function (node, globals) { - 'use strict'; - - var txt = '', - tableArray = [[], []], - headings = node.querySelectorAll('thead>tr>th'), - rows = node.querySelectorAll('tbody>tr'), - i, ii; - for (i = 0; i < headings.length; ++i) { - var headContent = showdown.subParser('makeMarkdown.tableCell')(headings[i], globals), - allign = '---'; - - if (headings[i].hasAttribute('style')) { - var style = headings[i].getAttribute('style').toLowerCase().replace(/\s/g, ''); - switch (style) { - case 'text-align:left;': - allign = ':---'; - break; - case 'text-align:right;': - allign = '---:'; - break; - case 'text-align:center;': - allign = ':---:'; - break; - } - } - tableArray[0][i] = headContent.trim(); - tableArray[1][i] = allign; - } - - for (i = 0; i < rows.length; ++i) { - var r = tableArray.push([]) - 1, - cols = rows[i].getElementsByTagName('td'); - - for (ii = 0; ii < headings.length; ++ii) { - var cellContent = ' '; - if (typeof cols[ii] !== 'undefined') { - cellContent = showdown.subParser('makeMarkdown.tableCell')(cols[ii], globals); - } - tableArray[r].push(cellContent); - } - } - - var cellSpacesCount = 3; - for (i = 0; i < tableArray.length; ++i) { - for (ii = 0; ii < tableArray[i].length; ++ii) { - var strLen = tableArray[i][ii].length; - if (strLen > cellSpacesCount) { - cellSpacesCount = strLen; - } - } - } - - for (i = 0; i < tableArray.length; ++i) { - for (ii = 0; ii < tableArray[i].length; ++ii) { - if (i === 1) { - if (tableArray[i][ii].slice(-1) === ':') { - tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii].slice(-1), cellSpacesCount - 1, '-') + ':'; - } else { - tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount, '-'); - } - } else { - tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount); - } - } - txt += '| ' + tableArray[i].join(' | ') + ' |\n'; - } - - return txt.trim(); - }); - - showdown.subParser('makeMarkdown.tableCell', function (node, globals) { - 'use strict'; - - var txt = ''; - if (!node.hasChildNodes()) { - return ''; - } - var children = node.childNodes, - childrenLength = children.length; - - for (var i = 0; i < childrenLength; ++i) { - txt += showdown.subParser('makeMarkdown.node')(children[i], globals, true); - } - return txt.trim(); - }); - - showdown.subParser('makeMarkdown.txt', function (node) { - 'use strict'; - - var txt = node.nodeValue; - - // multiple spaces are collapsed - txt = txt.replace(/ +/g, ' '); - - // replace the custom ¨NBSP; with a space - txt = txt.replace(/¨NBSP;/g, ' '); - - // ", <, > and & should replace escaped html entities - txt = showdown.helper.unescapeHTMLEntities(txt); - - // escape markdown magic characters - // emphasis, strong and strikethrough - can appear everywhere - // we also escape pipe (|) because of tables - // and escape ` because of code blocks and spans - txt = txt.replace(/([*_~|`])/g, '\\$1'); - - // escape > because of blockquotes - txt = txt.replace(/^(\s*)>/g, '\\$1>'); - - // hash character, only troublesome at the beginning of a line because of headers - txt = txt.replace(/^#/gm, '\\#'); - - // horizontal rules - txt = txt.replace(/^(\s*)([-=]{3,})(\s*)$/, '$1\\$2$3'); - - // dot, because of ordered lists, only troublesome at the beginning of a line when preceded by an integer - txt = txt.replace(/^( {0,3}\d+)\./gm, '$1\\.'); - - // +, * and -, at the beginning of a line becomes a list, so we need to escape them also (asterisk was already escaped) - txt = txt.replace(/^( {0,3})([+-])/gm, '$1\\$2'); - - // images and links, ] followed by ( is problematic, so we escape it - txt = txt.replace(/]([\s]*)\(/g, '\\]$1\\('); - - // reference URIs must also be escaped - txt = txt.replace(/^ {0,3}\[([\S \t]*?)]:/gm, '\\[$1]:'); - - return txt; - }); - - /** - * Created by Estevao on 31-05-2015. - */ - - /** - * Showdown Converter class - * @class - * @param {object} [converterOptions] - * @returns {Converter} - */ - showdown.Converter = function (converterOptions) { - 'use strict'; - - var - /** - * Options used by this converter - * @private - * @type {{}} - */ - options = {}, - - /** - * Language extensions used by this converter - * @private - * @type {Array} - */ - langExtensions = [], - - /** - * Output modifiers extensions used by this converter - * @private - * @type {Array} - */ - outputModifiers = [], - - /** - * Event listeners - * @private - * @type {{}} - */ - listeners = {}, - - /** - * The flavor set in this converter - */ - setConvFlavor = setFlavor, - - /** - * Metadata of the document - * @type {{parsed: {}, raw: string, format: string}} - */ - metadata = { - parsed: {}, - raw: '', - format: '' - }; - - _constructor(); - - /** - * Converter constructor - * @private - */ - function _constructor () { - converterOptions = converterOptions || {}; - - for (var gOpt in globalOptions) { - if (globalOptions.hasOwnProperty(gOpt)) { - options[gOpt] = globalOptions[gOpt]; - } - } - - // Merge options - if (typeof converterOptions === 'object') { - for (var opt in converterOptions) { - if (converterOptions.hasOwnProperty(opt)) { - options[opt] = converterOptions[opt]; - } - } - } else { - throw Error('Converter expects the passed parameter to be an object, but ' + typeof converterOptions + - ' was passed instead.'); - } - - if (options.extensions) { - showdown.helper.forEach(options.extensions, _parseExtension); - } - } - - /** - * Parse extension - * @param {*} ext - * @param {string} [name=''] - * @private - */ - function _parseExtension (ext, name) { - - name = name || null; - // If it's a string, the extension was previously loaded - if (showdown.helper.isString(ext)) { - ext = showdown.helper.stdExtName(ext); - name = ext; - - // LEGACY_SUPPORT CODE - if (showdown.extensions[ext]) { - console.warn('DEPRECATION WARNING: ' + ext + ' is an old extension that uses a deprecated loading method.' + - 'Please inform the developer that the extension should be updated!'); - legacyExtensionLoading(showdown.extensions[ext], ext); - return; - // END LEGACY SUPPORT CODE - - } else if (!showdown.helper.isUndefined(extensions[ext])) { - ext = extensions[ext]; - - } else { - throw Error('Extension "' + ext + '" could not be loaded. It was either not found or is not a valid extension.'); - } - } - - if (typeof ext === 'function') { - ext = ext(); - } - - if (!showdown.helper.isArray(ext)) { - ext = [ext]; - } - - var validExt = validate(ext, name); - if (!validExt.valid) { - throw Error(validExt.error); - } - - for (var i = 0; i < ext.length; ++i) { - switch (ext[i].type) { - - case 'lang': - langExtensions.push(ext[i]); - break; - - case 'output': - outputModifiers.push(ext[i]); - break; - } - if (ext[i].hasOwnProperty('listeners')) { - for (var ln in ext[i].listeners) { - if (ext[i].listeners.hasOwnProperty(ln)) { - listen(ln, ext[i].listeners[ln]); - } - } - } - } - - } - - /** - * LEGACY_SUPPORT - * @param {*} ext - * @param {string} name - */ - function legacyExtensionLoading (ext, name) { - if (typeof ext === 'function') { - ext = ext(new showdown.Converter()); - } - if (!showdown.helper.isArray(ext)) { - ext = [ext]; - } - var valid = validate(ext, name); - - if (!valid.valid) { - throw Error(valid.error); - } - - for (var i = 0; i < ext.length; ++i) { - switch (ext[i].type) { - case 'lang': - langExtensions.push(ext[i]); - break; - case 'output': - outputModifiers.push(ext[i]); - break; - default:// should never reach here - throw Error('Extension loader error: Type unrecognized!!!'); - } - } - } - - /** - * Listen to an event - * @param {string} name - * @param {function} callback - */ - function listen (name, callback) { - if (!showdown.helper.isString(name)) { - throw Error('Invalid argument in converter.listen() method: name must be a string, but ' + typeof name + ' given'); - } - - if (typeof callback !== 'function') { - throw Error('Invalid argument in converter.listen() method: callback must be a function, but ' + typeof callback + ' given'); - } - name = name.toLowerCase(); - if (!listeners.hasOwnProperty(name)) { - listeners[name] = []; - } - listeners[name].push(callback); - } - - function rTrimInputText (text) { - var rsp = text.match(/^\s*/)[0].length, - rgx = new RegExp('^\\s{0,' + rsp + '}', 'gm'); - return text.replace(rgx, ''); - } - - /** - * - * @param {string} evtName Event name - * @param {string} text Text - * @param {{}} options Converter Options - * @param {{}} globals Converter globals - * @param {{}} pParams extra params for event - * @returns showdown.helper.Event - * @private - */ - this._dispatch = function dispatch (evtName, text, options, globals, pParams) { - evtName = evtName.toLowerCase(); - var params = pParams || {}; - params.converter = this; - params.text = text; - params.options = options; - params.globals = globals; - var event = new showdown.helper.Event(evtName, text, params); - - if (listeners.hasOwnProperty(evtName)) { - for (var ei = 0; ei < listeners[evtName].length; ++ei) { - var nText = listeners[evtName][ei](event); - if (nText && typeof nText !== 'undefined') { - event.setText(nText); - } - } - } - return event; - }; - - /** - * Listen to an event - * @param {string} name - * @param {function} callback - * @returns {showdown.Converter} - */ - this.listen = function (name, callback) { - listen(name, callback); - return this; - }; - - /** - * Converts a markdown string into HTML string - * @param {string} text - * @returns {*} - */ - this.makeHtml = function (text) { - //check if text is not falsy - if (!text) { - return text; - } - - var globals = { - gHtmlBlocks: [], - gHtmlMdBlocks: [], - gHtmlSpans: [], - gUrls: {}, - gTitles: {}, - gDimensions: {}, - gListLevel: 0, - hashLinkCounts: {}, - langExtensions: langExtensions, - outputModifiers: outputModifiers, - converter: this, - ghCodeBlocks: [], - metadata: { - parsed: {}, - raw: '', - format: '' - } - }; - - // This lets us use ¨ trema as an escape char to avoid md5 hashes - // The choice of character is arbitrary; anything that isn't - // magic in Markdown will work. - text = text.replace(/¨/g, '¨T'); - - // Replace $ with ¨D - // RegExp interprets $ as a special character - // when it's in a replacement string - text = text.replace(/\$/g, '¨D'); - - // Standardize line endings - text = text.replace(/\r\n/g, '\n'); // DOS to Unix - text = text.replace(/\r/g, '\n'); // Mac to Unix - - // Stardardize line spaces - text = text.replace(/\u00A0/g, ' '); - - if (options.smartIndentationFix) { - text = rTrimInputText(text); - } - - // Make sure text begins and ends with a couple of newlines: - text = '\n\n' + text + '\n\n'; - - // detab - text = showdown.subParser('makehtml.detab')(text, options, globals); - - /** - * Strip any lines consisting only of spaces and tabs. - * This makes subsequent regexs easier to write, because we can - * match consecutive blank lines with /\n+/ instead of something - * contorted like /[ \t]*\n+/ - */ - text = text.replace(/^[ \t]+$/mg, ''); - - //run languageExtensions - showdown.helper.forEach(langExtensions, function (ext) { - text = showdown.subParser('makehtml.runExtension')(ext, text, options, globals); - }); - - // run the sub parsers - text = showdown.subParser('makehtml.metadata')(text, options, globals); - text = showdown.subParser('makehtml.hashPreCodeTags')(text, options, globals); - text = showdown.subParser('makehtml.githubCodeBlocks')(text, options, globals); - text = showdown.subParser('makehtml.hashHTMLBlocks')(text, options, globals); - text = showdown.subParser('makehtml.hashCodeTags')(text, options, globals); - text = showdown.subParser('makehtml.stripLinkDefinitions')(text, options, globals); - text = showdown.subParser('makehtml.blockGamut')(text, options, globals); - text = showdown.subParser('makehtml.unhashHTMLSpans')(text, options, globals); - text = showdown.subParser('makehtml.unescapeSpecialChars')(text, options, globals); - - // attacklab: Restore dollar signs - text = text.replace(/¨D/g, '$$'); - - // attacklab: Restore tremas - text = text.replace(/¨T/g, '¨'); - - // render a complete html document instead of a partial if the option is enabled - text = showdown.subParser('makehtml.completeHTMLDocument')(text, options, globals); - - // Run output modifiers - showdown.helper.forEach(outputModifiers, function (ext) { - text = showdown.subParser('makehtml.runExtension')(ext, text, options, globals); - }); - - // update metadata - metadata = globals.metadata; - return text; - }; - - /** - * Converts an HTML string into a markdown string - * @param src - * @returns {string} - */ - this.makeMarkdown = function (src) { - - // replace \r\n with \n - src = src.replace(/\r\n/g, '\n'); - src = src.replace(/\r/g, '\n'); // old macs - - // due to an edge case, we need to find this: > < - // to prevent removing of non silent white spaces - // ex: this is sparta - src = src.replace(/>[ \t]+¨NBSP;<'); - - var doc = showdown.helper.document.createElement('div'); - doc.innerHTML = src; - - var globals = { - preList: substitutePreCodeTags(doc) - }; - - // remove all newlines and collapse spaces - clean(doc); - - // some stuff, like accidental reference links must now be escaped - // TODO - // doc.innerHTML = doc.innerHTML.replace(/\[[\S\t ]]/); - - var nodes = doc.childNodes, - mdDoc = ''; - - for (var i = 0; i < nodes.length; i++) { - mdDoc += showdown.subParser('makeMarkdown.node')(nodes[i], globals); - } - - function clean (node) { - for (var n = 0; n < node.childNodes.length; ++n) { - var child = node.childNodes[n]; - if (child.nodeType === 3) { - if (!/\S/.test(child.nodeValue) && !/^[ ]+$/.test(child.nodeValue)) { - node.removeChild(child); - --n; - } else { - child.nodeValue = child.nodeValue.split('\n').join(' '); - child.nodeValue = child.nodeValue.replace(/(\s)+/g, '$1'); - } - } else if (child.nodeType === 1) { - clean(child); - } - } - } - - // find all pre tags and replace contents with placeholder - // we need this so that we can remove all indentation from html - // to ease up parsing - function substitutePreCodeTags (doc) { - - var pres = doc.querySelectorAll('pre'), - presPH = []; - - for (var i = 0; i < pres.length; ++i) { - - if (pres[i].childElementCount === 1 && pres[i].firstChild.tagName.toLowerCase() === 'code') { - var content = pres[i].firstChild.innerHTML.trim(), - language = pres[i].firstChild.getAttribute('data-language') || ''; - - // if data-language attribute is not defined, then we look for class language-* - if (language === '') { - var classes = pres[i].firstChild.className.split(' '); - for (var c = 0; c < classes.length; ++c) { - var matches = classes[c].match(/^language-(.+)$/); - if (matches !== null) { - language = matches[1]; - break; - } - } - } - - // unescape html entities in content - content = showdown.helper.unescapeHTMLEntities(content); - - presPH.push(content); - pres[i].outerHTML = ''; - } else { - presPH.push(pres[i].innerHTML); - pres[i].innerHTML = ''; - pres[i].setAttribute('prenum', i.toString()); - } - } - return presPH; - } - - return mdDoc; - }; - - /** - * Set an option of this Converter instance - * @param {string} key - * @param {*} value - */ - this.setOption = function (key, value) { - options[key] = value; - }; - - /** - * Get the option of this Converter instance - * @param {string} key - * @returns {*} - */ - this.getOption = function (key) { - return options[key]; - }; - - /** - * Get the options of this Converter instance - * @returns {{}} - */ - this.getOptions = function () { - return options; - }; - - /** - * Add extension to THIS converter - * @param {{}} extension - * @param {string} [name=null] - */ - this.addExtension = function (extension, name) { - name = name || null; - _parseExtension(extension, name); - }; - - /** - * Use a global registered extension with THIS converter - * @param {string} extensionName Name of the previously registered extension - */ - this.useExtension = function (extensionName) { - _parseExtension(extensionName); - }; - - /** - * Set the flavor THIS converter should use - * @param {string} name - */ - this.setFlavor = function (name) { - if (!flavor.hasOwnProperty(name)) { - throw Error(name + ' flavor was not found'); - } - var preset = flavor[name]; - setConvFlavor = name; - for (var option in preset) { - if (preset.hasOwnProperty(option)) { - options[option] = preset[option]; - } - } - }; - - /** - * Get the currently set flavor of this converter - * @returns {string} - */ - this.getFlavor = function () { - return setConvFlavor; - }; - - /** - * Remove an extension from THIS converter. - * Note: This is a costly operation. It's better to initialize a new converter - * and specify the extensions you wish to use - * @param {Array} extension - */ - this.removeExtension = function (extension) { - if (!showdown.helper.isArray(extension)) { - extension = [extension]; - } - for (var a = 0; a < extension.length; ++a) { - var ext = extension[a]; - for (var i = 0; i < langExtensions.length; ++i) { - if (langExtensions[i] === ext) { - langExtensions[i].splice(i, 1); - } - } - for (var ii = 0; ii < outputModifiers.length; ++i) { - if (outputModifiers[ii] === ext) { - outputModifiers[ii].splice(i, 1); - } - } - } - }; - - /** - * Get all extension of THIS converter - * @returns {{language: Array, output: Array}} - */ - this.getAllExtensions = function () { - return { - language: langExtensions, - output: outputModifiers - }; - }; - - /** - * Get the metadata of the previously parsed document - * @param raw - * @returns {string|{}} - */ - this.getMetadata = function (raw) { - if (raw) { - return metadata.raw; - } else { - return metadata.parsed; - } - }; - - /** - * Get the metadata format of the previously parsed document - * @returns {string} - */ - this.getMetadataFormat = function () { - return metadata.format; - }; - - /** - * Private: set a single key, value metadata pair - * @param {string} key - * @param {string} value - */ - this._setMetadataPair = function (key, value) { - metadata.parsed[key] = value; - }; - - /** - * Private: set metadata format - * @param {string} format - */ - this._setMetadataFormat = function (format) { - metadata.format = format; - }; - - /** - * Private: set metadata raw text - * @param {string} raw - */ - this._setMetadataRaw = function (raw) { - metadata.raw = raw; - }; - }; - - var root = this; - -// AMD Loader - if (typeof define === 'function' && define.amd) { - define(function () { - 'use strict'; - return showdown; - }); - -// CommonJS/nodeJS Loader - } else if (typeof module !== 'undefined' && module.exports) { - module.exports = showdown; - -// Regular Browser loader - } else { - root.showdown = showdown; - } -}).call(this); - -//# sourceMappingURL=showdown.js.map diff --git a/src/renderer/views/main.ejs b/src/renderer/views/main.ejs index a6ad5c6f..178bf632 100644 --- a/src/renderer/views/main.ejs +++ b/src/renderer/views/main.ejs @@ -34,7 +34,7 @@ - + diff --git a/src/renderer/views/pages/plugins-github.ejs b/src/renderer/views/pages/plugins-github.ejs index 751a8262..5d0bc28b 100644 --- a/src/renderer/views/pages/plugins-github.ejs +++ b/src/renderer/views/pages/plugins-github.ejs @@ -118,9 +118,7 @@ }); }, convertReadMe(text) { - var converter = new showdown.Converter(), - html = converter.makeHtml(text); - return html + return marked.parse(text) }, installThemeRepo(repo) { let self = this diff --git a/src/renderer/views/pages/themes-github.ejs b/src/renderer/views/pages/themes-github.ejs index 708341a6..0b1e0883 100644 --- a/src/renderer/views/pages/themes-github.ejs +++ b/src/renderer/views/pages/themes-github.ejs @@ -144,9 +144,7 @@ }); }, convertReadMe(text) { - var converter = new showdown.Converter(), - html = converter.makeHtml(text); - return html + return marked.parse(text) }, installThemeRepo(repo) { let self = this