function getDefaultOpts(simple) { 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: 'Specify a prefix to generated header ids', type: 'string' }, 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' }, 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 identation in es6 strings', type: 'boolean' } }; 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; } var showdown = {}; var parsers = {}; var extensions = {}; var globalOptions = getDefaultOpts(true); var flavor = { github: { omitExtraWLInCodeBlocks: true, prefixHeaderId: 'user-content-', simplifiedAutoLink: true, literalMidWordUnderscores: true, strikethrough: true, tables: true, tablesHeaderId: true, ghCodeBlocks: true, tasklists: true }, vanilla: getDefaultOpts(true) }; showdown.helper = {}; showdown.extensions = {}; showdown.setOption = function (key, value) { globalOptions[key] = value; return this; }; showdown.getOption = function (key) { return globalOptions[key]; }; showdown.getOptions = function () { return globalOptions; }; showdown.resetOptions = function () { globalOptions = getDefaultOpts(true); }; showdown.setFlavor = function (name) { if (flavor.hasOwnProperty(name)) { var preset = flavor[name]; for (var option in preset) { if (preset.hasOwnProperty(option)) { globalOptions[option] = preset[option]; } } } }; showdown.getDefaultOptions = function (simple) { return getDefaultOpts(simple); }; showdown.subParser = function (name, func) { 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!'); } } } }; showdown.extension = function (name, ext) { if (!showdown.helper.isString(name)) { throw Error("Extension 'name' must be a string"); } name = showdown.helper.stdExtName(name); if (showdown.helper.isUndefined(ext)) { if (!extensions.hasOwnProperty(name)) { throw Error('Extension named ' + name + ' is not registered!'); } return extensions[name]; } else { if (typeof ext === 'function') { ext = ext(); } if (!showdown.helper.isArray(ext)) { ext = [ext]; } var validExtension = validate(ext, name); if (validExtension.valid) { extensions[name] = ext; } else { throw Error(validExtension.error); } } }; showdown.getAllExtensions = function () { return extensions; }; showdown.removeExtension = function (name) { delete extensions[name]; }; showdown.resetExtensions = function () { extensions = {}; }; function validate(extension, name) { var errMsg = name ? 'Error in ' + name + ' extension->' : 'Error in unnamed extension'; var 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 + ': '; var 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()); 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; } showdown.validateExtension = function (ext) { var validateExtension = validate(ext, null); if (!validateExtension.valid) { console.warn(validateExtension.error); return false; } return true; }; if (!showdown.hasOwnProperty('helper')) { showdown.helper = {}; } showdown.helper.isString = function isString(a) { return typeof a === 'string' || a instanceof String; }; showdown.helper.isFunction = function isFunction(a) { var getType = {}; return a && getType.toString.call(a) === '[object Function]'; }; showdown.helper.forEach = function forEach(obj, callback) { if (typeof obj.forEach === 'function') { obj.forEach(callback); } else { for (var i = 0; i < obj.length; i++) { callback(obj[i], i, obj); } } }; showdown.helper.isArray = function isArray(a) { return a.constructor === Array; }; showdown.helper.isUndefined = function isUndefined(value) { return typeof value === 'undefined'; }; showdown.helper.stdExtName = function (s) { return s.replace(/[_-]||\s/g, '').toLowerCase(); }; function escapeCharactersCallback(wholeMatch, m1) { var charCodeToEscape = m1.charCodeAt(0); return '~E' + charCodeToEscape + 'E'; } showdown.helper.escapeCharactersCallback = escapeCharactersCallback; showdown.helper.escapeCharacters = function escapeCharacters(text, charsToEscape, afterBackslash) { 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) { var f = flags || ''; var g = f.indexOf('g') > -1; var x = new RegExp(left + '|' + right, 'g' + f.replace(/g/g, '')); var l = new RegExp(left, f.replace(/g/g, '')); var pos = []; var t; var s; var m; var start; var 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; }; showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) { var matchPos = rgxFindMatchPos(str, left, right, flags); var 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; }; showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) { if (!showdown.helper.isFunction(replacement)) { var repStr = replacement; replacement = function () { return repStr; }; } var matchPos = rgxFindMatchPos(str, left, right, flags); var finalStr = str; var 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; }; if (showdown.helper.isUndefined(console)) { console = { warn: function (msg) { alert(msg); }, log: function (msg) { alert(msg); }, error: function (msg) { throw msg; } }; } showdown.Converter = function (converterOptions) { var options = {}; var langExtensions = []; var outputModifiers = []; var listeners = {}; _constructor(); function _constructor() { converterOptions = converterOptions || {}; for (var gOpt in globalOptions) { if (globalOptions.hasOwnProperty(gOpt)) { options[gOpt] = globalOptions[gOpt]; } } 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); } } function _parseExtension(ext, name) { name = name || null; if (showdown.helper.isString(ext)) { ext = showdown.helper.stdExtName(ext); name = ext; 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; } 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]); } } } } } 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: throw Error('Extension loader error: Type unrecognized!!!'); } } } 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'); } if (!listeners.hasOwnProperty(name)) { listeners[name] = []; } listeners[name].push(callback); } function rTrimInputText(text) { var rsp = text.match(/^\s*/)[0].length; var rgx = new RegExp('^\\s{0,' + rsp + '}', 'gm'); return text.replace(rgx, ''); } this._dispatch = function dispatch(evtName, text, options, globals) { if (listeners.hasOwnProperty(evtName)) { for (var ei = 0; ei < listeners[evtName].length; ++ei) { var nText = listeners[evtName][ei](evtName, text, this, options, globals); if (nText && typeof nText !== 'undefined') { text = nText; } } } return text; }; this.listen = function (name, callback) { listen(name, callback); return this; }; this.makeHtml = function (text) { if (!text) { return text; } var globals = { gHtmlBlocks: [], gHtmlMdBlocks: [], gHtmlSpans: [], gUrls: {}, gTitles: {}, gDimensions: {}, gListLevel: 0, hashLinkCounts: {}, langExtensions: langExtensions, outputModifiers: outputModifiers, converter: this, ghCodeBlocks: [] }; text = text.replace(/~/g, '~T'); text = text.replace(/\$/g, '~D'); text = text.replace(/\r\n/g, '\n'); text = text.replace(/\r/g, '\n'); if (options.smartIndentationFix) { text = rTrimInputText(text); } text = text; text = showdown.subParser('detab')(text, options, globals); text = showdown.subParser('stripBlankLines')(text, options, globals); showdown.helper.forEach(langExtensions, function (ext) { text = showdown.subParser('runExtension')(ext, text, options, globals); }); text = showdown.subParser('hashPreCodeTags')(text, options, globals); text = showdown.subParser('githubCodeBlocks')(text, options, globals); text = showdown.subParser('hashHTMLBlocks')(text, options, globals); text = showdown.subParser('hashHTMLSpans')(text, options, globals); text = showdown.subParser('stripLinkDefinitions')(text, options, globals); text = showdown.subParser('blockGamut')(text, options, globals); text = showdown.subParser('unhashHTMLSpans')(text, options, globals); text = showdown.subParser('unescapeSpecialChars')(text, options, globals); text = text.replace(/~D/g, '$$'); text = text.replace(/~T/g, '~'); showdown.helper.forEach(outputModifiers, function (ext) { text = showdown.subParser('runExtension')(ext, text, options, globals); }); return text; }; this.setOption = function (key, value) { options[key] = value; }; this.getOption = function (key) { return options[key]; }; this.getOptions = function () { return options; }; this.addExtension = function (extension, name) { name = name || null; _parseExtension(extension, name); }; this.useExtension = function (extensionName) { _parseExtension(extensionName); }; this.setFlavor = function (name) { if (flavor.hasOwnProperty(name)) { var preset = flavor[name]; for (var option in preset) { if (preset.hasOwnProperty(option)) { options[option] = preset[option]; } } } }; 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); } } } }; this.getAllExtensions = function () { return { language: langExtensions, output: outputModifiers }; }; }; showdown.subParser('anchors', function (text, options, globals) { text = globals.converter._dispatch('anchors.before', text, options, globals); var writeAnchorTag = function (wholeMatch, m1, m2, m3, m4, m5, m6, m7) { if (showdown.helper.isUndefined(m7)) { m7 = ''; } wholeMatch = m1; var linkText = m2; var linkId = m3.toLowerCase(); var url = m4; var title = m7; if (!url) { if (!linkId) { linkId = linkText.toLowerCase().replace(/ ?\n/g, ' '); } url = '#' + linkId; if (!showdown.helper.isUndefined(globals.gUrls[linkId])) { url = globals.gUrls[linkId]; if (!showdown.helper.isUndefined(globals.gTitles[linkId])) { title = globals.gTitles[linkId]; } } else { if (wholeMatch.search(/\(\s*\)$/m) > -1) { url = ''; } else { return wholeMatch; } } } url = showdown.helper.escapeCharacters(url, '*_', false); var result = '' + linkText + ''; return result; }; text = text.replace(/(\[((?:\[[^\]]*]|[^\[\]])*)][ ]?(?:\n[ ]*)?\[(.*?)])()()()()/g, writeAnchorTag); text = text.replace(/(\[((?:\[[^\]]*]|[^\[\]])*)]\([ \t]*()(.*?(?:\(.*?\).*?)?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeAnchorTag); text = text.replace(/(\[([^\[\]]+)])()()()()()/g, writeAnchorTag); text = globals.converter._dispatch('anchors.after', text, options, globals); return text; }); showdown.subParser('autoLinks', function (text, options, globals) { text = globals.converter._dispatch('autoLinks.before', text, options, globals); var simpleURLRegex = /\b(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+)(?=\s|$)(?!["<>])/gi; var delimUrlRegex = /<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)>/gi; var simpleMailRegex = /(?:^|[ \n\t])([A-Za-z0-9!#$%&'*+-/=?^_`\{|}~\.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?:$|[ \n\t])/gi; var delimMailRegex = /<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi; text = text.replace(delimUrlRegex, replaceLink); text = text.replace(delimMailRegex, replaceMail); if (options.simplifiedAutoLink) { text = text.replace(simpleURLRegex, replaceLink); text = text.replace(simpleMailRegex, replaceMail); } function replaceLink(wm, link) { var lnkTxt = link; if (/^www\./i.test(link)) { link = link.replace(/^www\./i, 'http://www.'); } return '' + lnkTxt + ''; } function replaceMail(wholeMatch, m1) { var unescapedStr = showdown.subParser('unescapeSpecialChars')(m1); return showdown.subParser('encodeEmailAddress')(unescapedStr); } text = globals.converter._dispatch('autoLinks.after', text, options, globals); return text; }); showdown.subParser('blockGamut', function (text, options, globals) { text = globals.converter._dispatch('blockGamut.before', text, options, globals); text = showdown.subParser('blockQuotes')(text, options, globals); text = showdown.subParser('headers')(text, options, globals); var key = showdown.subParser('hashBlock')('
[^\r]+?<\/pre>)/gm, function (wholeMatch, m1) { var pre = m1; pre = pre.replace(/^ /gm, '~0'); pre = pre.replace(/~0/g, ''); return pre; }); return showdown.subParser('hashBlock')('\n' + bq + '\n', options, globals); }); text = globals.converter._dispatch('blockQuotes.after', text, options, globals); return text; }); showdown.subParser('codeBlocks', function (text, options, globals) { text = globals.converter._dispatch('codeBlocks.before', text, options, globals); 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; var nextChar = m2; var end = '\n'; codeblock = showdown.subParser('outdent')(codeblock); codeblock = showdown.subParser('encodeCode')(codeblock); codeblock = showdown.subParser('detab')(codeblock); codeblock = codeblock.replace(/^\n+/g, ''); codeblock = codeblock.replace(/\n+$/g, ''); if (options.omitExtraWLInCodeBlocks) { end = ''; } codeblock = ''; return showdown.subParser('hashBlock')(codeblock, options, globals) + nextChar; }); text = text.replace(/~0/, ''); text = globals.converter._dispatch('codeBlocks.after', text, options, globals); return text; }); showdown.subParser('codeSpans', function (text, options, globals) { text = globals.converter._dispatch('codeSpans.before', text, options, globals); if (typeof text === 'undefined') { text = ''; } text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, function (wholeMatch, m1, m2, m3) { var c = m3; c = c.replace(/^([ \t]*)/g, ''); c = c.replace(/[ \t]*$/g, ''); c = showdown.subParser('encodeCode')(c); return m1 + '' + codeblock + end + '
' + c + '
'; }); text = globals.converter._dispatch('codeSpans.after', text, options, globals); return text; }); showdown.subParser('detab', function (text) { text = text.replace(/\t(?=\t)/g, ' '); text = text.replace(/\t/g, '~A~B'); text = text.replace(/~B(.+?)~A/g, function (wholeMatch, m1) { var leadingText = m1; var numSpaces = 4 - (leadingText.length % 4); for (var i = 0; i < numSpaces; i++) { leadingText += ' '; } return leadingText; }); text = text.replace(/~A/g, ' '); text = text.replace(/~B/g, ''); return text; }); showdown.subParser('encodeAmpsAndAngles', function (text) { text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&'); text = text.replace(/<(?![a-z\/?\$!])/gi, '<'); return text; }); showdown.subParser('encodeBackslashEscapes', function (text) { text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback); text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g, showdown.helper.escapeCharactersCallback); return text; }); showdown.subParser('encodeCode', function (text) { text = text.replace(/&/g, '&'); text = text.replace(//g, '>'); text = showdown.helper.escapeCharacters(text, '*_{}[]\\', false); return text; }); showdown.subParser('encodeEmailAddress', function (addr) { var encode = [ function (ch) { return '' + ch.charCodeAt(0) + ';'; }, function (ch) { return '' + ch.charCodeAt(0).toString(16) + ';'; }, function (ch) { return ch; } ]; addr = 'mailto:' + addr; addr = addr.replace(/./g, function (ch) { if (ch === '@') { ch = encode[Math.floor(Math.random() * 2)](ch); } else { if (ch !== ':') { var r = Math.random(); ch = r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch); } } return ch; }); addr = '' + addr + ''; addr = addr.replace(/">.+:/g, '">'); return addr; }); showdown.subParser('escapeSpecialCharsWithinTagAttributes', function (text) { var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|)/gi; text = text.replace(regex, function (wholeMatch) { var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, '$1`'); tag = showdown.helper.escapeCharacters(tag, '\\`*_', false); return tag; }); return text; }); showdown.subParser('githubCodeBlocks', function (text, options, globals) { if (!options.ghCodeBlocks) { return text; } text = globals.converter._dispatch('githubCodeBlocks.before', text, options, globals); text += '~0'; text = text.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g, function (wholeMatch, language, codeblock) { var end = options.omitExtraWLInCodeBlocks ? '' : '\n'; codeblock = showdown.subParser('encodeCode')(codeblock); codeblock = showdown.subParser('detab')(codeblock); codeblock = codeblock.replace(/^\n+/g, ''); codeblock = codeblock.replace(/\n+$/g, ''); codeblock = ''; codeblock = showdown.subParser('hashBlock')(codeblock, options, globals); return ( '\n\n~G' + (globals.ghCodeBlocks.push({ text: wholeMatch, codeblock: codeblock }) - 1) + 'G\n\n' ); }); text = text.replace(/~0/, ''); return globals.converter._dispatch('githubCodeBlocks.after', text, options, globals); }); showdown.subParser('hashBlock', function (text, options, globals) { text = text.replace(/(^\n+|\n+$)/g, ''); return '\n\n~K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n'; }); showdown.subParser('hashElement', function (text, options, globals) { return function (wholeMatch, m1) { var blockText = m1; blockText = blockText.replace(/\n\n/g, '\n'); blockText = blockText.replace(/^\n/, ''); blockText = blockText.replace(/\n+$/g, ''); blockText = '\n\n~K' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n'; return blockText; }; }); showdown.subParser('hashHTMLBlocks', function (text, options, globals) { 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', 'p' ]; var repFunc = function (wholeMatch, match, left, right) { var txt = wholeMatch; 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'; }; for (var i = 0; i < blockTags.length; ++i) { text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^(?: |\\t){0,3}<' + blockTags[i] + '\\b[^>]*>', '' + blockTags[i] + '>', 'gim'); } text = text.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, showdown.subParser('hashElement')(text, options, globals)); text = text.replace(/()/g, showdown.subParser('hashElement')(text, options, globals)); text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, showdown.subParser('hashElement')(text, options, globals)); return text; }); showdown.subParser('hashHTMLSpans', function (text, config, globals) { var matches = showdown.helper.matchRecursiveRegExp(text, '' + codeblock + end + '
]*>', '
', 'gi'); for (var i = 0; i < matches.length; ++i) { text = text.replace(matches[i][0], '~L' + (globals.gHtmlSpans.push(matches[i][0]) - 1) + 'L'); } return text; }); showdown.subParser('unhashHTMLSpans', function (text, config, globals) { for (var i = 0; i < globals.gHtmlSpans.length; ++i) { text = text.replace('~L' + i + 'L', globals.gHtmlSpans[i]); } return text; }); showdown.subParser('hashPreCodeTags', function (text, config, globals) { var repFunc = function (wholeMatch, match, left, right) { var codeblock = left + showdown.subParser('encodeCode')(match) + right; return ( '\n\n~G' + (globals.ghCodeBlocks.push({ text: wholeMatch, codeblock: codeblock }) - 1) + 'G\n\n' ); }; text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^(?: |\\t){0,3}]*>\\s*', 'gim'); return text; }); showdown.subParser('headers', function (text, options, globals) { text = globals.converter._dispatch('headers.before', text, options, globals); var prefixHeader = options.prefixHeaderId; var headerLevelStart = isNaN(parseInt(options.headerLevelStart)) ? 1 : parseInt(options.headerLevelStart); var setextRegexH1 = options.smoothLivePreview ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm; var 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('spanGamut')(m1, options, globals); var hID = options.noHeaderId ? '' : ' id="' + headerId(m1) + '"'; var hLevel = headerLevelStart; var hashBlock = ']*>', '^(?: |\\t){0,3}
\\s*' + spanGamut + ' '; return showdown.subParser('hashBlock')(hashBlock, options, globals); }); text = text.replace(setextRegexH2, function (matchFound, m1) { var spanGamut = showdown.subParser('spanGamut')(m1, options, globals); var hID = options.noHeaderId ? '' : ' id="' + headerId(m1) + '"'; var hLevel = headerLevelStart + 1; var hashBlock = '' + spanGamut + ' '; return showdown.subParser('hashBlock')(hashBlock, options, globals); }); text = text.replace(/^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm, function (wholeMatch, m1, m2) { var span = showdown.subParser('spanGamut')(m2, options, globals); var hID = options.noHeaderId ? '' : ' id="' + headerId(m2) + '"'; var hLevel = headerLevelStart - 1 + m1.length; var header = '' + span + ' '; return showdown.subParser('hashBlock')(header, options, globals); }); function headerId(m) { var title; var escapedId = m.replace(/[^\w]/g, '').toLowerCase(); if (globals.hashLinkCounts[escapedId]) { title = escapedId + '-' + globals.hashLinkCounts[escapedId]++; } else { title = escapedId; globals.hashLinkCounts[escapedId] = 1; } if (prefixHeader === true) { prefixHeader = 'section'; } if (showdown.helper.isString(prefixHeader)) { return prefixHeader + title; } return title; } text = globals.converter._dispatch('headers.after', text, options, globals); return text; }); showdown.subParser('images', function (text, options, globals) { text = globals.converter._dispatch('images.before', text, options, globals); var inlineRegExp = /!\[(.*?)]\s?\([ \t]*()(\S+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(['"])(.*?)\6[ \t]*)?\)/g; var referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[(.*?)]()()()()()/g; function writeImageTag(wholeMatch, altText, linkId, url, width, height, m5, title) { var gUrls = globals.gUrls; var gTitles = globals.gTitles; var gDims = globals.gDimensions; linkId = linkId.toLowerCase(); if (!title) { title = ''; } if (url === '' || url === null) { if (linkId === '' || linkId === null) { 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); url = showdown.helper.escapeCharacters(url, '*_', false); var result = ''; return result; } text = text.replace(referenceRegExp, writeImageTag); text = text.replace(inlineRegExp, writeImageTag); text = globals.converter._dispatch('images.after', text, options, globals); return text; }); showdown.subParser('italicsAndBold', function (text, options, globals) { text = globals.converter._dispatch('italicsAndBold.before', text, options, globals); if (options.literalMidWordUnderscores) { text = text.replace(/(^|\s|>|\b)__(?=\S)([\s\S]+?)__(?=\b|<|\s|$)/gm, '$1$2'); text = text.replace(/(^|\s|>|\b)_(?=\S)([\s\S]+?)_(?=\b|<|\s|$)/gm, '$1$2'); text = text.replace(/(\*\*)(?=\S)([^\r]*?\S[*]*)\1/g, '$2'); text = text.replace(/(\*)(?=\S)([^\r]*?\S)\1/g, '$2'); } else { text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g, '$2'); text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g, '$2'); } text = globals.converter._dispatch('italicsAndBold.after', text, options, globals); return text; }); showdown.subParser('lists', function (text, options, globals) { text = globals.converter._dispatch('lists.before', text, options, globals); function processListItems(listStr, trimTrailing) { globals.gListLevel++; listStr = listStr.replace(/\n{2,}$/, '\n'); listStr += '~0'; var rgx = /(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm; var isParagraphed = /\n[ \t]*\n(?!~0)/.test(listStr); listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) { checked = checked && checked.trim() !== ''; var item = showdown.subParser('outdent')(m4, options, globals); var bulletStyle = ''; if (taskbtn && options.tasklists) { bulletStyle = ' class="task-list-item" style="list-style-type: none;"'; item = item.replace(/^[ \t]*\[(x|X| )?]/m, function () { var otp = ''; return otp; }); } if (m1 || item.search(/\n{2,}/) > -1) { item = showdown.subParser('githubCodeBlocks')(item, options, globals); item = showdown.subParser('blockGamut')(item, options, globals); } else { item = showdown.subParser('lists')(item, options, globals); item = item.replace(/\n$/, ''); if (isParagraphed) { item = showdown.subParser('paragraphs')(item, options, globals); } else { item = showdown.subParser('spanGamut')(item, options, globals); } } item = '\n
'); str += '
'; grafsOut.push(str); } } end = grafsOut.length; for (i = 0; i < end; i++) { var blockText = ''; var grafsOutIt = grafsOut[i]; var codeFlag = false; while (grafsOutIt.search(/~(K|G)(\d+)\1/) >= 0) { var delim = RegExp.$1; var num = RegExp.$2; if (delim === 'K') { blockText = globals.gHtmlBlocks[num]; } else { if (codeFlag) { blockText = showdown.subParser('encodeCode')(globals.ghCodeBlocks[num].text); } else { blockText = globals.ghCodeBlocks[num].codeblock; } } blockText = blockText.replace(/\$/g, '$$$$'); grafsOutIt = grafsOutIt.replace(/(\n\n)?~(K|G)\d+\2(\n\n)?/, blockText); if (/^]*>\s*]*>/.test(grafsOutIt)) {
codeFlag = true;
}
}
grafsOut[i] = grafsOutIt;
}
text = grafsOut.join('\n\n');
text = text.replace(/^\n+/g, '');
text = text.replace(/\n+$/g, '');
return globals.converter._dispatch('paragraphs.after', text, options, globals);
});
showdown.subParser('runExtension', function (ext, text, options, globals) {
if (ext.filter) {
text = ext.filter(text, globals.converter, options);
} else {
if (ext.regex) {
var re = ext.regex;
if (!re instanceof RegExp) {
re = new RegExp(re, 'g');
}
text = text.replace(re, ext.replace);
}
}
return text;
});
showdown.subParser('spanGamut', function (text, options, globals) {
text = globals.converter._dispatch('spanGamut.before', text, options, globals);
text = showdown.subParser('codeSpans')(text, options, globals);
text = showdown.subParser('escapeSpecialCharsWithinTagAttributes')(text, options, globals);
text = showdown.subParser('encodeBackslashEscapes')(text, options, globals);
text = showdown.subParser('images')(text, options, globals);
text = showdown.subParser('anchors')(text, options, globals);
text = showdown.subParser('autoLinks')(text, options, globals);
text = showdown.subParser('encodeAmpsAndAngles')(text, options, globals);
text = showdown.subParser('italicsAndBold')(text, options, globals);
text = showdown.subParser('strikethrough')(text, options, globals);
text = text.replace(/ +\n/g, '
\n');
text = globals.converter._dispatch('spanGamut.after', text, options, globals);
return text;
});
showdown.subParser('strikethrough', function (text, options, globals) {
if (options.strikethrough) {
text = globals.converter._dispatch('strikethrough.before', text, options, globals);
text = text.replace(/(?:~T){2}([\s\S]+?)(?:~T){2}/g, '$1');
text = globals.converter._dispatch('strikethrough.after', text, options, globals);
}
return text;
});
showdown.subParser('stripBlankLines', function (text) {
return text.replace(/^[ \t]+$/gm, '');
});
showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
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;
text += '~0';
text = text.replace(regex, function (wholeMatch, linkId, url, width, height, blankLines, title) {
linkId = linkId.toLowerCase();
globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url);
if (blankLines) {
return blankLines + title;
} else {
if (title) {
globals.gTitles[linkId] = title.replace(/"|'/g, '"');
}
if (options.parseImgDimensions && width && height) {
globals.gDimensions[linkId] = {
width: width,
height: height
};
}
}
return '';
});
text = text.replace(/~0/, '');
return text;
});
showdown.subParser('tables', function (text, options, globals) {
if (!options.tables) {
return text;
}
var tableRgx = /^[ \t]{0,3}\|?.+\|.+\n[ \t]{0,3}\|?[ \t]*:?[ \t]*(?:-|=){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:-|=){2,}[\s\S]+?(?:\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();
if (options.tableHeaderId) {
id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"';
}
header = showdown.subParser('spanGamut')(header, options, globals);
return '' + header + ' \n';
}
function parseCells(cell, style) {
var subText = showdown.subParser('spanGamut')(cell, options, globals);
return '' + subText + ' \n';
}
function buildTable(headers, cells) {
var tb = '\n\n\n';
var 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;
}
text = globals.converter._dispatch('tables.before', text, options, globals);
text = text.replace(tableRgx, function (rawTable) {
var i;
var tableLines = rawTable.split('\n');
for (i = 0; i < tableLines.length; ++i) {
if (/^[ \t]{0,3}\|/.test(tableLines[i])) {
tableLines[i] = tableLines[i].replace(/^[ \t]{0,3}\|/, '');
}
if (/\|[ \t]*$/.test(tableLines[i])) {
tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, '');
}
}
var rawHeaders = tableLines[0].split('|').map(function (s) {
return s.trim();
});
var rawStyles = tableLines[1].split('|').map(function (s) {
return s.trim();
});
var rawCells = [];
var headers = [];
var styles = [];
var 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('tables.after', text, options, globals);
return text;
});
showdown.subParser('unescapeSpecialChars', function (text) {
text = text.replace(/~E(\d+)E/g, function (wholeMatch, m1) {
var charCodeToReplace = parseInt(m1);
return String.fromCharCode(charCodeToReplace);
});
return text;
});
module.exports = showdown;