From ca40f984b0dfda58af1aa55d167edf615582192a Mon Sep 17 00:00:00 2001 From: John Chilton Date: Tue, 10 Jan 2017 12:25:31 -0500 Subject: [PATCH] Markdown datatype support. With test tools demonstrating HTML and Markdown outputs from tools. Implements #3396 as part of the Qiime hackathon. --- client/bower.json | 3 +- client/galaxy/scripts/libs/showdown.js | 2602 +++++++++++++++++ client/grunt-tasks/install-libs.js | 1 + config/datatypes_conf.xml.sample | 1 + lib/galaxy/datatypes/data.py | 6 +- lib/galaxy/datatypes/text.py | 17 + static/maps/libs/showdown.js.map | 1 + static/scripts/libs/showdown.js | 2 + .../webapps/galaxy/dataset/markdown.mako | 15 + test/functional/tools/creates_html.xml | 14 + test/functional/tools/creates_html_index.html | 12 + test/functional/tools/creates_markdown.xml | 14 + .../tools/creates_markdown_index.md | 9 + .../tools/sample_datatypes_conf.xml | 2 + test/functional/tools/samples_tool_conf.xml | 2 + 15 files changed, 2699 insertions(+), 2 deletions(-) create mode 100644 client/galaxy/scripts/libs/showdown.js create mode 100644 static/maps/libs/showdown.js.map create mode 100644 static/scripts/libs/showdown.js create mode 100644 templates/webapps/galaxy/dataset/markdown.mako create mode 100644 test/functional/tools/creates_html.xml create mode 100644 test/functional/tools/creates_html_index.html create mode 100644 test/functional/tools/creates_markdown.xml create mode 100644 test/functional/tools/creates_markdown_index.md diff --git a/client/bower.json b/client/bower.json index 6f45f82cb01..b8e05800417 100644 --- a/client/bower.json +++ b/client/bower.json @@ -30,7 +30,8 @@ "jstree": "~3.0.9", "jquery-ui": "git://github.com/jquery/jquery-ui.git#~1.11.2", "jquery.complexify": "git://github.com/danpalmer/jquery.complexify.js.git#~0.5.1", - "threedubmedia.jquery.event": "*", + "threedubmedia.jquery.event": "*", + "showdown": "~1.6.0", "jquery-migrate": "~1.4", "requirejs": "~2" }, diff --git a/client/galaxy/scripts/libs/showdown.js b/client/galaxy/scripts/libs/showdown.js new file mode 100644 index 00000000000..52fb0da3779 --- /dev/null +++ b/client/galaxy/scripts/libs/showdown.js @@ -0,0 +1,2602 @@ +;/*! showdown 09-01-2017 */ +(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: 'Specify a prefix to generated header ids', + type: 'string' + }, + 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' + }, + 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' + }, + excludeTrailingPunctuationFromURLs: { + defaultValue: false, + describe: 'Excludes trailing punctuation from links generated with autoLinking', + 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 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' + } + }; + 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, + prefixHeaderId: 'user-content-', + simplifiedAutoLink: true, + excludeTrailingPunctuationFromURLs: true, + literalMidWordUnderscores: true, + strikethrough: true, + tables: true, + tablesHeaderId: true, + ghCodeBlocks: true, + tasklists: true, + disableForced4SpacesIndentedSublists: true, + simpleLineBreaks: true, + requireSpaceBeforeHeadingText: true, + ghCompatibleHeaderId: true, + ghMentions: 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'); + } + 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!'); + } + } + } +}; + +/** + * 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 = {}; +} + +/** + * Check if var is string + * @static + * @param {string} a + * @returns {boolean} + */ +showdown.helper.isString = function isString(a) { + 'use strict'; + return (typeof a === 'string' || a instanceof String); +}; + +/** + * Check if var is a function + * @static + * @param {string} a + * @returns {boolean} + */ +showdown.helper.isFunction = function isFunction(a) { + 'use strict'; + var getType = {}; + return a && getType.toString.call(a) === '[object Function]'; +}; + +/** + * ForEach helper function + * @static + * @param {*} obj + * @param {function} callback + */ +showdown.helper.forEach = function forEach(obj, callback) { + 'use strict'; + if (typeof obj.forEach === 'function') { + obj.forEach(callback); + } else { + for (var i = 0; i < obj.length; i++) { + callback(obj[i], i, obj); + } + } +}; + +/** + * isArray helper function + * @static + * @param {*} a + * @returns {boolean} + */ +showdown.helper.isArray = function isArray(a) { + 'use strict'; + return a.constructor === Array; +}; + +/** + * 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 isUndefined(value) { + 'use strict'; + return typeof value === 'undefined'; +}; + +/** + * Standardidize extension name + * @static + * @param {string} s extension name + * @returns {string} + */ +showdown.helper.stdExtName = function (s) { + 'use strict'; + return s.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 escapeCharacters(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; +}; + +/** + * 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; + } + }; +} + +/** + * 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; + + _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'); + } + + 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, ''); + } + + /** + * Dispatch an event + * @private + * @param {string} evtName Event name + * @param {string} text Text + * @param {{}} options Converter Options + * @param {{}} globals + * @returns {string} + */ + 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; + }; + + /** + * 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 + * @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: [] + }; + + // attacklab: Replace ~ with ~T + // This lets us use tilde 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'); + + // attacklab: 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 (nbsp causes trouble in older browsers and some regex flavors) + 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('detab')(text, options, globals); + + // stripBlankLines + text = showdown.subParser('stripBlankLines')(text, options, globals); + + //run languageExtensions + showdown.helper.forEach(langExtensions, function (ext) { + text = showdown.subParser('runExtension')(ext, text, options, globals); + }); + + // run the sub parsers + 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); + + // attacklab: Restore dollar signs + text = text.replace(/~D/g, '$$'); + + // attacklab: Restore tildes + text = text.replace(/~T/g, '~'); + + // Run output modifiers + showdown.helper.forEach(outputModifiers, function (ext) { + text = showdown.subParser('runExtension')(ext, text, options, globals); + }); + + return text; + }; + + /** + * 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 + }; + }; +}; + +/** + * Turn Markdown link shortcuts into XHTML tags. + */ +showdown.subParser('anchors', function (text, options, globals) { + 'use strict'; + + 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, + linkId = m3.toLowerCase(), + url = m4, + title = m7; + + if (!url) { + if (!linkId) { + // lower-case and turn embedded newlines into spaces + 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) { + // Special case for explicit empty url + url = ''; + } else { + return wholeMatch; + } + } + } + + url = showdown.helper.escapeCharacters(url, '*_', false); + var result = ''; + + return result; + }; + + // First, handle reference-style links: [link text] [id] + text = text.replace(/(\[((?:\[[^\]]*]|[^\[\]])*)][ ]?(?:\n[ ]*)?\[(.*?)])()()()()/g, writeAnchorTag); + + // Next, inline-style links: [link text](url "optional title") + text = text.replace(/(\[((?:\[[^\]]*]|[^\[\]])*)]\([ \t]*()?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, + writeAnchorTag); + + // handle reference-style shortcuts: [link text] + // These must come last in case you've also got [link test][1] + // or [link test](/foo) + text = text.replace(/(\[([^\[\]]+)])()()()()()/g, writeAnchorTag); + + // Lastly handle GithubMentions if option is enabled + if (options.ghMentions) { + text = text.replace(/(^|\s)(\\)?(@([a-z\d\-]+))(?=[.!?;,[\]()]|\s|$)/gmi, function (wm, st, escape, mentions, username) { + if (escape === '\\') { + return st + mentions; + } + return st + '' + mentions + ''; + }); + } + + text = globals.converter._dispatch('anchors.after', text, options, globals); + return text; +}); + +showdown.subParser('autoLinks', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('autoLinks.before', text, options, globals); + + var simpleURLRegex = /\b(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+)()(?=\s|$)(?!["<>])/gi, + simpleURLRegex2 = /\b(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+?)([.!?()]?)(?=\s|$)(?!["<>])/gi, + delimUrlRegex = /<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)>/gi, + simpleMailRegex = /(?:^|\s)([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?:$|\s)/gi, + delimMailRegex = /<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi; + + text = text.replace(delimUrlRegex, replaceLink); + text = text.replace(delimMailRegex, replaceMail); + // simpleURLRegex = /\b(((https?|ftp|dict):\/\/|www\.)[-.+~:?#@!$&'()*,;=[\]\w]+)\b/gi, + // Email addresses: + + if (options.simplifiedAutoLink) { + if (options.excludeTrailingPunctuationFromURLs) { + text = text.replace(simpleURLRegex2, replaceLink); + } else { + text = text.replace(simpleURLRegex, replaceLink); + } + text = text.replace(simpleMailRegex, replaceMail); + } + + function replaceLink(wm, link, m2, m3, trailingPunctuation) { + var lnkTxt = link, + append = ''; + if (/^www\./i.test(link)) { + link = link.replace(/^www\./i, 'http://www.'); + } + if (options.excludeTrailingPunctuationFromURLs && trailingPunctuation) { + append = trailingPunctuation; + } + return '' + lnkTxt + '' + append; + } + + function replaceMail(wholeMatch, mail) { + var unescapedStr = showdown.subParser('unescapeSpecialChars')(mail); + return showdown.subParser('encodeEmailAddress')(unescapedStr); + } + + text = globals.converter._dispatch('autoLinks.after', text, options, globals); + + return text; +}); + +/** + * These are all the transformations that form block-level + * tags like paragraphs, headers, and list items. + */ +showdown.subParser('blockGamut', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('blockGamut.before', text, options, globals); + + // we parse blockquotes first so that we can have headings and hrs + // inside blockquotes + text = showdown.subParser('blockQuotes')(text, options, globals); + text = showdown.subParser('headers')(text, options, globals); + + // Do Horizontal Rules: + var key = showdown.subParser('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 = showdown.subParser('lists')(text, options, globals); + text = showdown.subParser('codeBlocks')(text, options, globals); + text = showdown.subParser('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('hashHTMLBlocks')(text, options, globals); + text = showdown.subParser('paragraphs')(text, options, globals); + + text = globals.converter._dispatch('blockGamut.after', text, options, globals); + + return text; +}); + +showdown.subParser('blockQuotes', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('blockQuotes.before', text, options, globals); + + text = text.replace(/((^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+)/gm, function (wholeMatch, m1) { + var bq = m1; + + // attacklab: hack around Konqueror 3.5.4 bug: + // "----------bug".replace(/^-/g,"") == "bug" + bq = bq.replace(/^[ \t]*>[ \t]?/gm, '~0'); // 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('githubCodeBlocks')(bq, options, globals); + bq = showdown.subParser('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('hashBlock')('
\n' + bq + '\n
', options, globals); + }); + + text = globals.converter._dispatch('blockQuotes.after', text, options, globals); + return text; +}); + +/** + * Process Markdown `
` blocks.
+ */
+showdown.subParser('codeBlocks', function (text, options, globals) {
+  'use strict';
+
+  text = globals.converter._dispatch('codeBlocks.before', text, options, globals);
+
+  // 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('outdent')(codeblock);
+    codeblock = showdown.subParser('encodeCode')(codeblock);
+    codeblock = showdown.subParser('detab')(codeblock);
+    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('hashBlock')(codeblock, options, globals) + nextChar; + }); + + // strip sentinel + text = text.replace(/~0/, ''); + + text = globals.converter._dispatch('codeBlocks.after', text, options, globals); + 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('codeSpans', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('codeSpans.before', text, options, globals); + + /* + text = text.replace(/ + (^|[^\\]) // Character before opening ` can't be a backslash + (`+) // $2 = Opening run of ` + ( // $3 = The code block + [^\r]*? + [^`] // attacklab: work around lack of lookbehind + ) + \2 // Matching closer + (?!`) + /gm, function(){...}); + */ + + 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('encodeCode')(c); + return m1 + '' + c + ''; + } + ); + + text = globals.converter._dispatch('codeSpans.after', text, options, globals); + return text; +}); + +/** + * Convert all tabs to spaces + */ +showdown.subParser('detab', function (text) { + 'use strict'; + + // 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, ''); + + return text; + +}); + +/** + * Smart processing for ampersands and angle brackets that need to be encoded. + */ +showdown.subParser('encodeAmpsAndAngles', function (text) { + 'use strict'; + // 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, '<'); + + 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('encodeBackslashEscapes', function (text) { + 'use strict'; + text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback); + text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g, showdown.helper.escapeCharactersCallback); + 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('encodeCode', function (text) { + 'use strict'; + + // Encode all ampersands; HTML entities are not + // entities within a Markdown code span. + text = text.replace(/&/g, '&'); + + // Do the angle bracket song and dance: + text = text.replace(//g, '>'); + + // Now, escape characters that are magic in Markdown: + text = showdown.helper.escapeCharacters(text, '*_{}[]\\', false); + + // jj the line above breaks this: + //--- + //* Item + // 1. Subitem + // special char: * + // --- + + return text; +}); + +/** + * Input: an email address, e.g. "foo@example.com" + * + * Output: the email address as a mailto link, with each character + * of the address encoded as either a decimal or hex entity, in + * the hopes of foiling most address harvesting spam bots. E.g.: + * + * foo + * @example.com + * + * Based on a filter by Matthew Wickline, posted to the BBEdit-Talk + * mailing list: + * + */ +showdown.subParser('encodeEmailAddress', function (addr) { + 'use strict'; + + var encode = [ + function (ch) { + return '&#' + ch.charCodeAt(0) + ';'; + }, + function (ch) { + return '&#x' + ch.charCodeAt(0).toString(16) + ';'; + }, + function (ch) { + return ch; + } + ]; + + addr = 'mailto:' + addr; + + addr = addr.replace(/./g, function (ch) { + if (ch === '@') { + // this *must* be encoded. I insist. + ch = encode[Math.floor(Math.random() * 2)](ch); + } else if (ch !== ':') { + // leave ':' alone (to spot mailto: later) + 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; + }); + + addr = '' + addr + ''; + addr = addr.replace(/">.+:/g, '">'); // strip the mailto: from the visible part + + return addr; +}); + +/** + * Within tags -- meaning between < and > -- encode [\ ` * _] so they + * don't conflict with their use in Markdown for code, italics and strong. + */ +showdown.subParser('escapeSpecialCharsWithinTagAttributes', function (text) { + 'use strict'; + + // Build a regex to find HTML tags and comments. See Friedl's + // "Mastering Regular Expressions", 2nd Ed., pp. 200-201. + 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; +}); + +/** + * 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('githubCodeBlocks', function (text, options, globals) { + 'use strict'; + + // early exit if option is not enabled + 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'; + + // First parse the github code block + codeblock = showdown.subParser('encodeCode')(codeblock); + codeblock = showdown.subParser('detab')(codeblock); + codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines + codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace + + codeblock = '
' + codeblock + end + '
'; + + codeblock = showdown.subParser('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('githubCodeBlocks.after', text, options, globals); +}); + +showdown.subParser('hashBlock', function (text, options, globals) { + 'use strict'; + 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) { + '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('hashHTMLBlocks', function (text, options, globals) { + 'use strict'; + + 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' + ], + 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'; + }; + + for (var i = 0; i < blockTags.length; ++i) { + text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^ {0,3}<' + blockTags[i] + '\\b[^>]*>', '', 'gim'); + } + + // HR SPECIAL CASE + text = text.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, + showdown.subParser('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('hashElement')(text, options, globals)); + + return text; +}); + +/** + * Hash span elements that should not be parsed as markdown + */ +showdown.subParser('hashHTMLSpans', function (text, config, globals) { + 'use strict'; + + var matches = showdown.helper.matchRecursiveRegExp(text, ']*>', '', 'gi'); + + for (var i = 0; i < matches.length; ++i) { + text = text.replace(matches[i][0], '~C' + (globals.gHtmlSpans.push(matches[i][0]) - 1) + 'C'); + } + return text; +}); + +/** + * Unhash HTML spans + */ +showdown.subParser('unhashHTMLSpans', function (text, config, globals) { + 'use strict'; + + for (var i = 0; i < globals.gHtmlSpans.length; ++i) { + text = text.replace('~C' + i + 'C', globals.gHtmlSpans[i]); + } + + return text; +}); + +/** + * Hash span elements that should not be parsed as markdown + */ +showdown.subParser('hashPreCodeTags', function (text, config, globals) { + 'use strict'; + + var repFunc = function (wholeMatch, match, left, right) { + // encode html entities + 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, '^ {0,3}]*>\\s*]*>', '^ {0,3}\\s*
', 'gim'); + return text; +}); + +showdown.subParser('headers', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('headers.before', text, options, globals); + + var prefixHeader = options.prefixHeaderId, + headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart), + ghHeaderId = options.ghCompatibleHeaderId, + + // 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('spanGamut')(m1, options, globals), + hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"', + hLevel = headerLevelStart, + hashBlock = '' + spanGamut + ''; + return showdown.subParser('hashBlock')(hashBlock, options, globals); + }); + + text = text.replace(setextRegexH2, function (matchFound, m1) { + var spanGamut = showdown.subParser('spanGamut')(m1, options, globals), + hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"', + hLevel = headerLevelStart + 1, + hashBlock = '' + spanGamut + ''; + return showdown.subParser('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 span = showdown.subParser('spanGamut')(m2, options, globals), + hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"', + hLevel = headerLevelStart - 1 + m1.length, + header = '' + span + ''; + + return showdown.subParser('hashBlock')(header, options, globals); + }); + + function headerId(m) { + var title, escapedId; + + if (ghHeaderId) { + escapedId = m + .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 { + escapedId = m.replace(/[^\w]/g, '').toLowerCase(); + } + + if (globals.hashLinkCounts[escapedId]) { + title = escapedId + '-' + (globals.hashLinkCounts[escapedId]++); + } else { + title = escapedId; + globals.hashLinkCounts[escapedId] = 1; + } + + // Prefix id to prevent causing inadvertent pre-existing style matches. + 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; +}); + +/** + * Turn Markdown image shortcuts into tags. + */ +showdown.subParser('images', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('images.before', text, options, globals); + + var inlineRegExp = /!\[(.*?)]\s?\([ \t]*()?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(['"])(.*?)\6[ \t]*)?\)/g, + referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[(.*?)]()()()()()/g; + + 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 = ''; + } + + 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); + url = showdown.helper.escapeCharacters(url, '*_', false); + var result = '' + altText + 'x "optional title") + text = text.replace(inlineRegExp, writeImageTag); + + text = globals.converter._dispatch('images.after', text, options, globals); + return text; +}); + +showdown.subParser('italicsAndBold', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('italicsAndBold.before', text, options, globals); + + if (options.literalMidWordUnderscores) { + //underscores + // Since we are consuming a \s character, we need to add it + 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'); + //asterisks + text = text.replace(/(\*\*)(?=\S)([^\r]*?\S[*]*)\1/g, '$2'); + text = text.replace(/(\*)(?=\S)([^\r]*?\S)\1/g, '$2'); + + } else { + // must go first: + 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; +}); + +/** + * Form HTML ordered (numbered) and unordered (bulleted) lists. + */ +showdown.subParser('lists', function (text, options, globals) { + 'use strict'; + text = globals.converter._dispatch('lists.before', text, options, globals); + + /** + * 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 + 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('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; + }); + + // m1 - Leading line or + // Has a double return (multi paragraph) or + // Has sublist + if (m1 || (item.search(/\n{2,}/) > -1)) { + item = showdown.subParser('githubCodeBlocks')(item, options, globals); + item = showdown.subParser('blockGamut')(item, options, globals); + } else { + // Recursion for sub-lists: + item = showdown.subParser('lists')(item, options, globals); + item = item.replace(/\n$/, ''); // chomp(item) + item = showdown.subParser('hashHTMLBlocks')(item, options, globals); + // Colapse double linebreaks + item = item.replace(/\n\n+/g, '\n\n'); + // replace double linebreaks with a placeholder + item = item.replace(/\n\n/g, '~B'); + if (isParagraphed) { + item = showdown.subParser('paragraphs')(item, options, globals); + } else { + item = showdown.subParser('spanGamut')(item, options, globals); + } + item = item.replace(/~B/g, '\n\n'); + } + + // 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; + } + + /** + * 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); + if (pos !== -1) { + // slice + result += '\n<' + listType + '>\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<' + listType + '>\n' + processListItems(txt, !!trimTrailing) + '\n'; + } + })(list); + } else { + result = '\n<' + listType + '>\n' + processListItems(list, !!trimTrailing) + '\n'; + } + + return result; + } + + // 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(/^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm, + function (wholeMatch, list, m2) { + var listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol'; + return parseConsecutiveLists(list, listType, true); + } + ); + } else { + text = text.replace(/(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm, + 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('lists.after', text, options, globals); + return text; +}); + +/** + * Remove one level of line-leading tabs or spaces + */ +showdown.subParser('outdent', function (text) { + 'use strict'; + + // 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, ''); + + return text; +}); + +/** + * + */ +showdown.subParser('paragraphs', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('paragraphs.before', text, options, globals); + // 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); + } else { + str = showdown.subParser('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... + while (grafsOutIt.search(/~(K|G)(\d+)\1/) >= 0) { + 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('encodeCode')(globals.ghCodeBlocks[num].text); + } 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('paragraphs.after', text, options, globals); +}); + +/** + * Run extension + */ +showdown.subParser('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('spanGamut', function (text, options, globals) { + 'use strict'; + + 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); + + // Process anchor and image tags. Images must come first, + // because ![foo][f] looks like an anchor. + text = showdown.subParser('images')(text, options, globals); + text = showdown.subParser('anchors')(text, options, globals); + + // Make links out of things like `` + // Must come after _DoAnchors(), because you can use < and > + // delimiters in inline links like [this](). + 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); + + // Do hard breaks + if (options.simpleLineBreaks) { + // GFM style hard breaks + text = text.replace(/\n/g, '
    \n'); + } else { + // Vanilla hard breaks + text = text.replace(/ +\n/g, '
    \n'); + } + + text = globals.converter._dispatch('spanGamut.after', text, options, globals); + return text; +}); + +showdown.subParser('strikethrough', function (text, options, globals) { + 'use strict'; + + 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; +}); + +/** + * 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+/ + */ +showdown.subParser('stripBlankLines', function (text) { + 'use strict'; + return text.replace(/^[ \t]+$/mg, ''); +}); + +/** + * 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('stripLinkDefinitions', function (text, options, globals) { + 'use strict'; + + var regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=~0))/gm; + + // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug + text += '~0'; + + text = text.replace(regex, function (wholeMatch, linkId, url, width, height, blankLines, title) { + linkId = linkId.toLowerCase(); + globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url); // 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 ''; + }); + + // attacklab: strip sentinel + text = text.replace(/~0/, ''); + + return text; +}); + +showdown.subParser('tables', function (text, options, globals) { + 'use strict'; + + if (!options.tables) { + return text; + } + + var tableRgx = /^ {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', + 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, tableLines = rawTable.split('\n'); + + // strip wrong first and last column if wrapped tables are used + for (i = 0; i < tableLines.length; ++i) { + if (/^ {0,3}\|/.test(tableLines[i])) { + tableLines[i] = tableLines[i].replace(/^ {0,3}\|/, ''); + } + if (/\|[ \t]*$/.test(tableLines[i])) { + tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, ''); + } + } + + 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('tables.after', text, options, globals); + + return text; +}); + +/** + * Swap back in all the special characters we've hidden. + */ +showdown.subParser('unescapeSpecialChars', function (text) { + 'use strict'; + + text = text.replace(/~E(\d+)E/g, function (wholeMatch, m1) { + var charCodeToReplace = parseInt(m1); + return String.fromCharCode(charCodeToReplace); + }); + return text; +}); + +var root = this; + +// CommonJS/nodeJS Loader +if (typeof module !== 'undefined' && module.exports) { + module.exports = showdown; + +// AMD Loader +} else if (typeof define === 'function' && define.amd) { + define(function () { + 'use strict'; + return showdown; + }); + +// Regular Browser loader +} else { + root.showdown = showdown; +} +}).call(this); + +//# sourceMappingURL=showdown.js.map diff --git a/client/grunt-tasks/install-libs.js b/client/grunt-tasks/install-libs.js index b5c671f1730..ee6c7c046c3 100644 --- a/client/grunt-tasks/install-libs.js +++ b/client/grunt-tasks/install-libs.js @@ -24,6 +24,7 @@ module.exports = function( grunt ){ 'bootstrap-tour': [ 'build/js/bootstrap-tour.js', 'bootstrap-tour.js' ], 'jquery.complexify': [ 'jquery.complexify.js', 'jquery.complexify.js' ], + 'showdown': ['dist/showdown.js', 'showdown.js'], // these need to be updated and tested //'jquery-form': [ 'jquery.form.js', 'jquery/jquery.form.js' ], //'jquery-autocomplete': [ 'src/jquery.autocomplete.js', 'jquery/jquery.autocomplete.js' ], diff --git a/config/datatypes_conf.xml.sample b/config/datatypes_conf.xml.sample index 7c18036cfc7..f7ea64b8e65 100644 --- a/config/datatypes_conf.xml.sample +++ b/config/datatypes_conf.xml.sample @@ -114,6 +114,7 @@ + diff --git a/lib/galaxy/datatypes/data.py b/lib/galaxy/datatypes/data.py index 2c6ff80ce84..bce7e29fb6b 100644 --- a/lib/galaxy/datatypes/data.py +++ b/lib/galaxy/datatypes/data.py @@ -363,9 +363,13 @@ class Data( object ): if not os.path.exists( data.file_name ): raise paste.httpexceptions.HTTPNotFound( "File Not Found (%s)." % data.file_name ) max_peek_size = 1000000 # 1 MB - if isinstance(data.datatype, datatypes.text.Html): + if isinstance(data.datatype, datatypes.text.Html) or isinstance(data.datatype, datatypes.text.Markdown): max_peek_size = 10000000 # 10 MB for html preview = util.string_as_bool( preview ) + if trans.response.get_content_type() == "text/markdown": + trans.response.set_content_type( "text/html" ) + return trans.stream_template_mako( "/dataset/markdown.mako", + data=open(data.file_name).read()) if not preview or isinstance(data.datatype, datatypes.images.Image) or os.stat( data.file_name ).st_size < max_peek_size: if trans.app.config.sanitize_all_html and trans.response.get_content_type() == "text/html": # Sanitize anytime we respond with plain text/html content. diff --git a/lib/galaxy/datatypes/text.py b/lib/galaxy/datatypes/text.py index ec55ea4cded..9d7afc44747 100644 --- a/lib/galaxy/datatypes/text.py +++ b/lib/galaxy/datatypes/text.py @@ -57,6 +57,23 @@ class Html( Text ): return True +class Markdown( Text ): + """Class describing a Markdown file""" + file_ext = "md" + + def set_peek( self, dataset, is_multi_byte=False ): + if not dataset.dataset.purged: + dataset.peek = "Markdown file" + dataset.blurb = nice_size( dataset.get_size() ) + else: + dataset.peek = 'file does not exist' + dataset.blurb = 'file purged from disk' + + def get_mime(self): + """Returns the mime type of the datatype""" + return 'text/markdown' + + class Json( Text ): edam_format = "format_3464" file_ext = "json" diff --git a/static/maps/libs/showdown.js.map b/static/maps/libs/showdown.js.map new file mode 100644 index 00000000000..93dfa519c3d --- /dev/null +++ b/static/maps/libs/showdown.js.map @@ -0,0 +1 @@ +{"version":3,"file":"showdown.js","sources":["../../src/libs/showdown.js"],"names":["getDefaultOpts","simple","defaultOptions","omitExtraWLInCodeBlocks","defaultValue","describe","type","noHeaderId","prefixHeaderId","ghCompatibleHeaderId","headerLevelStart","parseImgDimensions","simplifiedAutoLink","excludeTrailingPunctuationFromURLs","literalMidWordUnderscores","strikethrough","tables","tablesHeaderId","ghCodeBlocks","tasklists","smoothLivePreview","smartIndentationFix","description","disableForced4SpacesIndentedSublists","simpleLineBreaks","requireSpaceBeforeHeadingText","ghMentions","JSON","parse","stringify","ret","opt","hasOwnProperty","allOptionsOn","options","validate","extension","name","errMsg","valid","error","showdown","helper","isArray","i","length","baseMsg","ext","isString","toLowerCase","isUndefined","listeners","filter","regex","ln","RegExp","replace","escapeCharactersCallback","wholeMatch","m1","charCodeToEscape","charCodeAt","parsers","extensions","globalOptions","setFlavor","flavor","github","vanilla","allOn","setOption","key","value","this","getOption","getOptions","resetOptions","Error","preset","option","getFlavor","getFlavorOptions","getDefaultOptions","subParser","func","stdExtName","validExtension","getAllExtensions","removeExtension","resetExtensions","validateExtension","console","warn","a","String","isFunction","getType","toString","call","forEach","obj","callback","constructor","Array","s","escapeCharacters","text","charsToEscape","afterBackslash","regexString","rgxFindMatchPos","str","left","right","flags","t","m","start","end","f","g","indexOf","x","l","pos","exec","test","lastIndex","index","match","push","matchRecursiveRegExp","matchPos","results","slice","replaceRecursiveRegExp","replacement","repStr","finalStr","lng","bits","join","msg","alert","log","Converter","converterOptions","_constructor","gOpt","_parseExtension","legacyExtensionLoading","validExt","langExtensions","outputModifiers","listen","rTrimInputText","rsp","rgx","setConvFlavor","_dispatch","evtName","globals","ei","nText","makeHtml","gHtmlBlocks","gHtmlMdBlocks","gHtmlSpans","gUrls","gTitles","gDimensions","gListLevel","hashLinkCounts","converter","addExtension","useExtension","extensionName","splice","ii","language","output","writeAnchorTag","m2","m3","m4","m5","m6","m7","linkText","linkId","url","title","search","result","wm","st","escape","mentions","username","replaceLink","link","trailingPunctuation","lnkTxt","append","replaceMail","mail","unescapedStr","simpleURLRegex","simpleURLRegex2","delimUrlRegex","simpleMailRegex","delimMailRegex","bq","pre","pattern","codeblock","nextChar","c","leadingText","numSpaces","addr","encode","ch","Math","floor","random","r","tag","blockText","blockTags","repFunc","txt","config","matches","headerId","escapedId","ghHeaderId","prefixHeader","isNaN","parseInt","setextRegexH1","setextRegexH2","spanGamut","hID","hLevel","hashBlock","matchFound","atxStyle","span","header","writeImageTag","altText","width","height","gDims","inlineRegExp","referenceRegExp","processListItems","listStr","trimTrailing","isParagraphed","taskbtn","checked","trim","item","bulletStyle","otp","wm2","parseConsecutiveLists","list","listType","olRgx","ulRgx","counterRxg","parseCL","grafs","split","grafsOut","grafsOutIt","codeFlag","delim","$1","num","$2","re","blankLines","parseStyles","sLine","parseHeaders","style","id","tableHeaderId","parseCells","cell","subText","buildTable","headers","cells","tb","tblLgn","tableRgx","rawTable","tableLines","rawHeaders","map","rawStyles","rawCells","styles","shift","row","charCodeToReplace","fromCharCode","root","module","exports","define","amd"],"mappings":"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"} \ No newline at end of file diff --git a/static/scripts/libs/showdown.js b/static/scripts/libs/showdown.js new file mode 100644 index 00000000000..1025be3a3bb --- /dev/null +++ b/static/scripts/libs/showdown.js @@ -0,0 +1,2 @@ +(function(){function a(a){"use strict";var b={omitExtraWLInCodeBlocks:{defaultValue:!1,describe:"Omit the default extra whiteline added to code blocks",type:"boolean"},noHeaderId:{defaultValue:!1,describe:"Turn on/off generated header id",type:"boolean"},prefixHeaderId:{defaultValue:!1,describe:"Specify a prefix to generated header ids",type:"string"},ghCompatibleHeaderId:{defaultValue:!1,describe:"Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)",type:"boolean"},headerLevelStart:{defaultValue:!1,describe:"The header blocks level start",type:"integer"},parseImgDimensions:{defaultValue:!1,describe:"Turn on/off image dimension parsing",type:"boolean"},simplifiedAutoLink:{defaultValue:!1,describe:"Turn on/off GFM autolink style",type:"boolean"},excludeTrailingPunctuationFromURLs:{defaultValue:!1,describe:"Excludes trailing punctuation from links generated with autoLinking",type:"boolean"},literalMidWordUnderscores:{defaultValue:!1,describe:"Parse midword underscores as literal underscores",type:"boolean"},strikethrough:{defaultValue:!1,describe:"Turn on/off strikethrough support",type:"boolean"},tables:{defaultValue:!1,describe:"Turn on/off tables support",type:"boolean"},tablesHeaderId:{defaultValue:!1,describe:"Add an id to table headers",type:"boolean"},ghCodeBlocks:{defaultValue:!0,describe:"Turn on/off GFM fenced code blocks support",type:"boolean"},tasklists:{defaultValue:!1,describe:"Turn on/off GFM tasklist support",type:"boolean"},smoothLivePreview:{defaultValue:!1,describe:"Prevents weird effects in live previews due to incomplete input",type:"boolean"},smartIndentationFix:{defaultValue:!1,description:"Tries to smartly fix indentation in es6 strings",type:"boolean"},disableForced4SpacesIndentedSublists:{defaultValue:!1,description:"Disables the requirement of indenting nested sublists by 4 spaces",type:"boolean"},simpleLineBreaks:{defaultValue:!1,description:"Parses simple line breaks as
    (GFM Style)",type:"boolean"},requireSpaceBeforeHeadingText:{defaultValue:!1,description:"Makes adding a space between `#` and the header text mandatory (GFM Style)",type:"boolean"},ghMentions:{defaultValue:!1,description:"Enables github @mentions",type:"boolean"}};if(a===!1)return JSON.parse(JSON.stringify(b));var c={};for(var d in b)b.hasOwnProperty(d)&&(c[d]=b[d].defaultValue);return c}function b(){"use strict";var b=a(!0),c={};for(var d in b)b.hasOwnProperty(d)&&(c[d]=!0);return c}function c(a,b){"use strict";var c=b?"Error in "+b+" extension->":"Error in unnamed extension",d={valid:!0,error:""};e.helper.isArray(a)||(a=[a]);for(var f=0;f-1,l=new RegExp(b+"|"+c,"g"+j.replace(/g/g,"")),m=new RegExp(b,j.replace(/g/g,"")),n=[];do for(e=0;g=l.exec(a);)if(m.test(g[0]))e++||(f=l.lastIndex,h=f-g[0].length);else if(e&&!--e){i=g.index+g[0].length;var o={left:{start:h,end:f},match:{start:f,end:g.index},right:{start:g.index,end:i},wholeMatch:{start:h,end:i}};if(n.push(o),!k)return n}while(e&&(l.lastIndex=f));return n};e.helper.matchRecursiveRegExp=function(a,b,c,d){"use strict";for(var e=k(a,b,c,d),f=[],g=0;g0){var l=[];0!==h[0].wholeMatch.start&&l.push(a.slice(0,h[0].wholeMatch.start));for(var m=0;j>m;++m)l.push(b(a.slice(h[m].wholeMatch.start,h[m].wholeMatch.end),a.slice(h[m].match.start,h[m].match.end),a.slice(h[m].left.start,h[m].left.end),a.slice(h[m].right.start,h[m].right.end))),j-1>m&&l.push(a.slice(h[m].wholeMatch.end,h[m+1].wholeMatch.start));h[j-1].wholeMatch.end-1))return a;m=""}else m=c.gUrls[l],e.helper.isUndefined(c.gTitles[l])||(n=c.gTitles[l]);m=e.helper.escapeCharacters(m,"*_",!1);var o='"};return a=a.replace(/(\[((?:\[[^\]]*]|[^\[\]])*)][ ]?(?:\n[ ]*)?\[(.*?)])()()()()/g,d),a=a.replace(/(\[((?:\[[^\]]*]|[^\[\]])*)]\([ \t]*()?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,d),a=a.replace(/(\[([^\[\]]+)])()()()()()/g,d),b.ghMentions&&(a=a.replace(/(^|\s)(\\)?(@([a-z\d\-]+))(?=[.!?;,[\]()]|\s|$)/gim,function(a,b,c,d,e){return"\\"===c?b+d:b+''+d+""})),a=c.converter._dispatch("anchors.after",a,b,c)}),e.subParser("autoLinks",function(a,b,c){"use strict";function d(a,c,d,e,f){var g=c,h="";return/^www\./i.test(c)&&(c=c.replace(/^www\./i,"http://www.")),b.excludeTrailingPunctuationFromURLs&&f&&(h=f),''+g+""+h}function f(a,b){var c=e.subParser("unescapeSpecialChars")(b);return e.subParser("encodeEmailAddress")(c)}a=c.converter._dispatch("autoLinks.before",a,b,c);var g=/\b(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+)()(?=\s|$)(?!["<>])/gi,h=/\b(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+?)([.!?()]?)(?=\s|$)(?!["<>])/gi,i=/<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)>/gi,j=/(?:^|\s)([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?:$|\s)/gi,k=/<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;return a=a.replace(i,d),a=a.replace(k,f),b.simplifiedAutoLink&&(a=b.excludeTrailingPunctuationFromURLs?a.replace(h,d):a.replace(g,d),a=a.replace(j,f)),a=c.converter._dispatch("autoLinks.after",a,b,c)}),e.subParser("blockGamut",function(a,b,c){"use strict";a=c.converter._dispatch("blockGamut.before",a,b,c),a=e.subParser("blockQuotes")(a,b,c),a=e.subParser("headers")(a,b,c);var d=e.subParser("hashBlock")("
    ",b,c);return a=a.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm,d),a=a.replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm,d),a=a.replace(/^ {0,2}( ?_){3,}[ \t]*$/gm,d),a=e.subParser("lists")(a,b,c),a=e.subParser("codeBlocks")(a,b,c),a=e.subParser("tables")(a,b,c),a=e.subParser("hashHTMLBlocks")(a,b,c),a=e.subParser("paragraphs")(a,b,c),a=c.converter._dispatch("blockGamut.after",a,b,c)}),e.subParser("blockQuotes",function(a,b,c){"use strict";return a=c.converter._dispatch("blockQuotes.before",a,b,c),a=a.replace(/((^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+)/gm,function(a,d){var f=d;return f=f.replace(/^[ \t]*>[ \t]?/gm,"~0"),f=f.replace(/~0/g,""),f=f.replace(/^[ \t]+$/gm,""),f=e.subParser("githubCodeBlocks")(f,b,c),f=e.subParser("blockGamut")(f,b,c),f=f.replace(/(^|\n)/g,"$1 "),f=f.replace(/(\s*
    [^\r]+?<\/pre>)/gm,function(a,b){var c=b;return c=c.replace(/^  /gm,"~0"),c=c.replace(/~0/g,"")}),e.subParser("hashBlock")("
    \n"+f+"\n
    ",b,c)}),a=c.converter._dispatch("blockQuotes.after",a,b,c)}),e.subParser("codeBlocks",function(a,b,c){"use strict";a=c.converter._dispatch("codeBlocks.before",a,b,c),a+="~0";var d=/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g;return a=a.replace(d,function(a,d,f){var g=d,h=f,i="\n";return g=e.subParser("outdent")(g),g=e.subParser("encodeCode")(g),g=e.subParser("detab")(g),g=g.replace(/^\n+/g,""),g=g.replace(/\n+$/g,""),b.omitExtraWLInCodeBlocks&&(i=""),g="
    "+g+i+"
    ",e.subParser("hashBlock")(g,b,c)+h}),a=a.replace(/~0/,""),a=c.converter._dispatch("codeBlocks.after",a,b,c)}),e.subParser("codeSpans",function(a,b,c){"use strict";return a=c.converter._dispatch("codeSpans.before",a,b,c),"undefined"==typeof a&&(a=""),a=a.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(a,b,c,d){var f=d;return f=f.replace(/^([ \t]*)/g,""),f=f.replace(/[ \t]*$/g,""),f=e.subParser("encodeCode")(f),b+""+f+""}),a=c.converter._dispatch("codeSpans.after",a,b,c)}),e.subParser("detab",function(a){"use strict";return a=a.replace(/\t(?=\t)/g," "),a=a.replace(/\t/g,"~A~B"),a=a.replace(/~B(.+?)~A/g,function(a,b){for(var c=b,d=4-c.length%4,e=0;d>e;e++)c+=" ";return c}),a=a.replace(/~A/g," "),a=a.replace(/~B/g,"")}),e.subParser("encodeAmpsAndAngles",function(a){"use strict";return a=a.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&"),a=a.replace(/<(?![a-z\/?\$!])/gi,"<")}),e.subParser("encodeBackslashEscapes",function(a){"use strict";return a=a.replace(/\\(\\)/g,e.helper.escapeCharactersCallback),a=a.replace(/\\([`*_{}\[\]()>#+-.!])/g,e.helper.escapeCharactersCallback)}),e.subParser("encodeCode",function(a){"use strict";return a=a.replace(/&/g,"&"),a=a.replace(//g,">"),a=e.helper.escapeCharacters(a,"*_{}[]\\",!1)}),e.subParser("encodeEmailAddress",function(a){"use strict";var b=[function(a){return"&#"+a.charCodeAt(0)+";"},function(a){return"&#x"+a.charCodeAt(0).toString(16)+";"},function(a){return a}];return a="mailto:"+a,a=a.replace(/./g,function(a){if("@"===a)a=b[Math.floor(2*Math.random())](a);else if(":"!==a){var c=Math.random();a=c>.9?b[2](a):c>.45?b[1](a):b[0](a)}return a}),a=''+a+"",a=a.replace(/">.+:/g,'">')}),e.subParser("escapeSpecialCharsWithinTagAttributes",function(a){"use strict";var b=/(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|)/gi;return a=a.replace(b,function(a){var b=a.replace(/(.)<\/?code>(?=.)/g,"$1`");return b=e.helper.escapeCharacters(b,"\\`*_",!1)})}),e.subParser("githubCodeBlocks",function(a,b,c){"use strict";return b.ghCodeBlocks?(a=c.converter._dispatch("githubCodeBlocks.before",a,b,c),a+="~0",a=a.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g,function(a,d,f){var g=b.omitExtraWLInCodeBlocks?"":"\n";return f=e.subParser("encodeCode")(f),f=e.subParser("detab")(f),f=f.replace(/^\n+/g,""),f=f.replace(/\n+$/g,""),f="
    "+f+g+"
    ",f=e.subParser("hashBlock")(f,b,c),"\n\n~G"+(c.ghCodeBlocks.push({text:a,codeblock:f})-1)+"G\n\n"}),a=a.replace(/~0/,""),c.converter._dispatch("githubCodeBlocks.after",a,b,c)):a}),e.subParser("hashBlock",function(a,b,c){"use strict";return a=a.replace(/(^\n+|\n+$)/g,""),"\n\n~K"+(c.gHtmlBlocks.push(a)-1)+"K\n\n"}),e.subParser("hashElement",function(a,b,c){"use strict";return function(a,b){var d=b;return d=d.replace(/\n\n/g,"\n"),d=d.replace(/^\n/,""),d=d.replace(/\n+$/g,""),d="\n\n~K"+(c.gHtmlBlocks.push(d)-1)+"K\n\n"}}),e.subParser("hashHTMLBlocks",function(a,b,c){"use strict";for(var d=["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"],f=function(a,b,d,e){var f=a;return-1!==d.search(/\bmarkdown\b/)&&(f=d+c.converter.makeHtml(b)+e),"\n\n~K"+(c.gHtmlBlocks.push(f)-1)+"K\n\n"},g=0;g]*>","","gim");return a=a.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,e.subParser("hashElement")(a,b,c)),a=e.helper.replaceRecursiveRegExp(a,function(a){return"\n\n~K"+(c.gHtmlBlocks.push(a)-1)+"K\n\n"},"^ {0,3}","gm"),a=a.replace(/(?:\n\n)( {0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,e.subParser("hashElement")(a,b,c))}),e.subParser("hashHTMLSpans",function(a,b,c){"use strict";for(var d=e.helper.matchRecursiveRegExp(a,"]*>","","gi"),f=0;f]*>\\s*]*>","^ {0,3}\\s*
    ","gim")}),e.subParser("headers",function(a,b,c){"use strict";function d(a){var b,d;return d=h?a.replace(/ /g,"-").replace(/&/g,"").replace(/~T/g,"").replace(/~D/g,"").replace(/[&+$,\/:;=?@"#{}|^~\[\]`\\*)(%.!'<>]/g,"").toLowerCase():a.replace(/[^\w]/g,"").toLowerCase(),c.hashLinkCounts[d]?b=d+"-"+c.hashLinkCounts[d]++:(b=d,c.hashLinkCounts[d]=1),f===!0&&(f="section"),e.helper.isString(f)?f+b:b}a=c.converter._dispatch("headers.before",a,b,c);var f=b.prefixHeaderId,g=isNaN(parseInt(b.headerLevelStart))?1:parseInt(b.headerLevelStart),h=b.ghCompatibleHeaderId,i=b.smoothLivePreview?/^(.+)[ \t]*\n={2,}[ \t]*\n+/gm:/^(.+)[ \t]*\n=+[ \t]*\n+/gm,j=b.smoothLivePreview?/^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm:/^(.+)[ \t]*\n-+[ \t]*\n+/gm;a=a.replace(i,function(a,f){var h=e.subParser("spanGamut")(f,b,c),i=b.noHeaderId?"":' id="'+d(f)+'"',j=g,k=""+h+"";return e.subParser("hashBlock")(k,b,c)}),a=a.replace(j,function(a,f){var h=e.subParser("spanGamut")(f,b,c),i=b.noHeaderId?"":' id="'+d(f)+'"',j=g+1,k=""+h+"";return e.subParser("hashBlock")(k,b,c)});var k=b.requireSpaceBeforeHeadingText?/^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm:/^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm;return a=a.replace(k,function(a,f,h){var i=e.subParser("spanGamut")(h,b,c),j=b.noHeaderId?"":' id="'+d(h)+'"',k=g-1+f.length,l=""+i+"";return e.subParser("hashBlock")(l,b,c)}),a=c.converter._dispatch("headers.after",a,b,c)}),e.subParser("images",function(a,b,c){"use strict";function d(a,b,d,f,g,h,i,j){var k=c.gUrls,l=c.gTitles,m=c.gDimensions;if(d=d.toLowerCase(),j||(j=""),""===f||null===f){if((""===d||null===d)&&(d=b.toLowerCase().replace(/ ?\n/g," ")),f="#"+d,e.helper.isUndefined(k[d]))return a;f=k[d],e.helper.isUndefined(l[d])||(j=l[d]),e.helper.isUndefined(m[d])||(g=m[d].width,h=m[d].height)}b=b.replace(/"/g,"""),b=e.helper.escapeCharacters(b,"*_",!1),f=e.helper.escapeCharacters(f,"*_",!1);var n=''+b+'?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(['"])(.*?)\6[ \t]*)?\)/g,g=/!\[([^\]]*?)] ?(?:\n *)?\[(.*?)]()()()()()/g;return a=a.replace(g,d),a=a.replace(f,d),a=c.converter._dispatch("images.after",a,b,c)}),e.subParser("italicsAndBold",function(a,b,c){"use strict";return a=c.converter._dispatch("italicsAndBold.before",a,b,c),b.literalMidWordUnderscores?(a=a.replace(/(^|\s|>|\b)__(?=\S)([\s\S]+?)__(?=\b|<|\s|$)/gm,"$1$2"),a=a.replace(/(^|\s|>|\b)_(?=\S)([\s\S]+?)_(?=\b|<|\s|$)/gm,"$1$2"),a=a.replace(/(\*\*)(?=\S)([^\r]*?\S[*]*)\1/g,"$2"),a=a.replace(/(\*)(?=\S)([^\r]*?\S)\1/g,"$2")):(a=a.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,"$2"),a=a.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,"$2")),a=c.converter._dispatch("italicsAndBold.after",a,b,c)}),e.subParser("lists",function(a,b,c){"use strict";function d(a,d){c.gListLevel++,a=a.replace(/\n{2,}$/,"\n"),a+="~0";var f=/(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(~0| {0,3}([*+-]|\d+[.])[ \t]+))/gm,g=/\n[ \t]*\n(?!~0)/.test(a);return b.disableForced4SpacesIndentedSublists&&(f=/(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm),a=a.replace(f,function(a,d,f,h,i,j,k){k=k&&""!==k.trim();var l=e.subParser("outdent")(i,b,c),m="";return j&&b.tasklists&&(m=' class="task-list-item" style="list-style-type: none;"',l=l.replace(/^[ \t]*\[(x|X| )?]/m,function(){var a='-1?(l=e.subParser("githubCodeBlocks")(l,b,c),l=e.subParser("blockGamut")(l,b,c)):(l=e.subParser("lists")(l,b,c),l=l.replace(/\n$/,""),l=e.subParser("hashHTMLBlocks")(l,b,c),l=l.replace(/\n\n+/g,"\n\n"),l=l.replace(/\n\n/g,"~B"),l=g?e.subParser("paragraphs")(l,b,c):e.subParser("spanGamut")(l,b,c),l=l.replace(/~B/g,"\n\n")),l=l.replace("~A",""),l=""+l+"\n"}),a=a.replace(/~0/g,""),c.gListLevel--,d&&(a=a.replace(/\s+$/,"")),a}function f(a,c,e){var f=b.disableForced4SpacesIndentedSublists?/^ ?\d+\.[ \t]/gm:/^ {0,3}\d+\.[ \t]/gm,g=b.disableForced4SpacesIndentedSublists?/^ ?[*+-][ \t]/gm:/^ {0,3}[*+-][ \t]/gm,h="ul"===c?f:g,i="";return-1!==a.search(h)?!function a(b){var j=b.search(h);-1!==j?(i+="\n<"+c+">\n"+d(b.slice(0,j),!!e)+"\n",c="ul"===c?"ol":"ul",h="ul"===c?f:g,a(b.slice(j))):i+="\n<"+c+">\n"+d(b,!!e)+"\n"}(a):i="\n<"+c+">\n"+d(a,!!e)+"\n",i}return a=c.converter._dispatch("lists.before",a,b,c),a+="~0",a=c.gListLevel?a.replace(/^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,function(a,b,c){var d=c.search(/[*+-]/g)>-1?"ul":"ol";return f(b,d,!0)}):a.replace(/(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,function(a,b,c,d){var e=d.search(/[*+-]/g)>-1?"ul":"ol";return f(c,e,!1)}),a=a.replace(/~0/,""),a=c.converter._dispatch("lists.after",a,b,c)}),e.subParser("outdent",function(a){"use strict";return a=a.replace(/^(\t|[ ]{1,4})/gm,"~0"),a=a.replace(/~0/g,"")}),e.subParser("paragraphs",function(a,b,c){"use strict";a=c.converter._dispatch("paragraphs.before",a,b,c),a=a.replace(/^\n+/g,""),a=a.replace(/\n+$/g,"");for(var d=a.split(/\n{2,}/g),f=[],g=d.length,h=0;g>h;h++){var i=d[h];i.search(/~(K|G)(\d+)\1/g)>=0?f.push(i):(i=e.subParser("spanGamut")(i,b,c),i=i.replace(/^([ \t]*)/g,"

    "),i+="

    ",f.push(i))}for(g=f.length,h=0;g>h;h++){for(var j="",k=f[h],l=!1;k.search(/~(K|G)(\d+)\1/)>=0;){var m=RegExp.$1,n=RegExp.$2;j="K"===m?c.gHtmlBlocks[n]:l?e.subParser("encodeCode")(c.ghCodeBlocks[n].text):c.ghCodeBlocks[n].codeblock,j=j.replace(/\$/g,"$$$$"),k=k.replace(/(\n\n)?~(K|G)\d+\2(\n\n)?/,j),/^]*>\s*]*>/.test(k)&&(l=!0)}f[h]=k}return a=f.join("\n"),a=a.replace(/^\n+/g,""),a=a.replace(/\n+$/g,""),c.converter._dispatch("paragraphs.after",a,b,c)}),e.subParser("runExtension",function(a,b,c,d){"use strict";if(a.filter)b=a.filter(b,d.converter,c);else if(a.regex){var e=a.regex;!e instanceof RegExp&&(e=new RegExp(e,"g")),b=b.replace(e,a.replace)}return b}),e.subParser("spanGamut",function(a,b,c){"use strict";return a=c.converter._dispatch("spanGamut.before",a,b,c),a=e.subParser("codeSpans")(a,b,c),a=e.subParser("escapeSpecialCharsWithinTagAttributes")(a,b,c),a=e.subParser("encodeBackslashEscapes")(a,b,c),a=e.subParser("images")(a,b,c),a=e.subParser("anchors")(a,b,c),a=e.subParser("autoLinks")(a,b,c),a=e.subParser("encodeAmpsAndAngles")(a,b,c),a=e.subParser("italicsAndBold")(a,b,c),a=e.subParser("strikethrough")(a,b,c),a=b.simpleLineBreaks?a.replace(/\n/g,"
    \n"):a.replace(/ +\n/g,"
    \n"),a=c.converter._dispatch("spanGamut.after",a,b,c)}),e.subParser("strikethrough",function(a,b,c){"use strict";return b.strikethrough&&(a=c.converter._dispatch("strikethrough.before",a,b,c),a=a.replace(/(?:~T){2}([\s\S]+?)(?:~T){2}/g,"$1"),a=c.converter._dispatch("strikethrough.after",a,b,c)),a}),e.subParser("stripBlankLines",function(a){"use strict";return a.replace(/^[ \t]+$/gm,"")}),e.subParser("stripLinkDefinitions",function(a,b,c){"use strict";var d=/^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=~0))/gm;return a+="~0",a=a.replace(d,function(a,d,f,g,h,i,j){return d=d.toLowerCase(),c.gUrls[d]=e.subParser("encodeAmpsAndAngles")(f),i?i+j:(j&&(c.gTitles[d]=j.replace(/"|'/g,""")),b.parseImgDimensions&&g&&h&&(c.gDimensions[d]={width:g,height:h}),"")}),a=a.replace(/~0/,"")}),e.subParser("tables",function(a,b,c){"use strict";function d(a){return/^:[ \t]*--*$/.test(a)?' style="text-align:left;"':/^--*[ \t]*:[ \t]*$/.test(a)?' style="text-align:right;"':/^:[ \t]*--*[ \t]*:$/.test(a)?' style="text-align:center;"':""}function f(a,d){var f="";return a=a.trim(),b.tableHeaderId&&(f=' id="'+a.replace(/ /g,"_").toLowerCase()+'"'),a=e.subParser("spanGamut")(a,b,c),""+a+"\n"}function g(a,d){var f=e.subParser("spanGamut")(a,b,c);return""+f+"\n"}function h(a,b){for(var c="\n\n\n",d=a.length,e=0;d>e;++e)c+=a[e];for(c+="\n\n\n",e=0;e\n";for(var f=0;d>f;++f)c+=b[e][f];c+="\n"}return c+="\n
    \n"}if(!b.tables)return a;var i=/^ {0,3}\|?.+\|.+\n[ \t]{0,3}\|?[ \t]*:?[ \t]*(?:-|=){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:-|=){2,}[\s\S]+?(?:\n\n|~0)/gm;return a=c.converter._dispatch("tables.before",a,b,c),a=a.replace(i,function(a){var b,c=a.split("\n");for(b=0;b + + +
    + + diff --git a/test/functional/tools/creates_html.xml b/test/functional/tools/creates_html.xml new file mode 100644 index 00000000000..d625ee6e503 --- /dev/null +++ b/test/functional/tools/creates_html.xml @@ -0,0 +1,14 @@ + + + mkdir '$output.extra_files_path'; + cp '$__tool_directory__/creates_html_index.html' '$output'; + cp '$__tool_directory__/creates_html_image.png' '$output.extra_files_path/image.png'; + + + + + + + + + diff --git a/test/functional/tools/creates_html_index.html b/test/functional/tools/creates_html_index.html new file mode 100644 index 00000000000..bf077accbb5 --- /dev/null +++ b/test/functional/tools/creates_html_index.html @@ -0,0 +1,12 @@ + + +

    Hello World!

    +

    Some of this sentence is bold and some is italic.

    +
      +
    • A list element.
    • +
    • Another list element.
    • +
    • Last list element.
    • +
    + An Image + + diff --git a/test/functional/tools/creates_markdown.xml b/test/functional/tools/creates_markdown.xml new file mode 100644 index 00000000000..1ceacbaa8c1 --- /dev/null +++ b/test/functional/tools/creates_markdown.xml @@ -0,0 +1,14 @@ + + + mkdir '$output.extra_files_path'; + cp '$__tool_directory__/creates_markdown_index.md' '$output'; + cp '$__tool_directory__/creates_html_image.png' '$output.extra_files_path/image.png' + + + + + + + + + diff --git a/test/functional/tools/creates_markdown_index.md b/test/functional/tools/creates_markdown_index.md new file mode 100644 index 00000000000..e348afc6785 --- /dev/null +++ b/test/functional/tools/creates_markdown_index.md @@ -0,0 +1,9 @@ +Hello World! + +Some of this sentence is **bold** and some is *italic*. + +* A list element. +* Another list element. +* Last list element. + +![An Image](image.png) diff --git a/test/functional/tools/sample_datatypes_conf.xml b/test/functional/tools/sample_datatypes_conf.xml index 2a80ca5e21b..d4cb8679693 100644 --- a/test/functional/tools/sample_datatypes_conf.xml +++ b/test/functional/tools/sample_datatypes_conf.xml @@ -18,5 +18,7 @@ + + diff --git a/test/functional/tools/samples_tool_conf.xml b/test/functional/tools/samples_tool_conf.xml index ab7ed822054..33d466c9ad6 100644 --- a/test/functional/tools/samples_tool_conf.xml +++ b/test/functional/tools/samples_tool_conf.xml @@ -3,6 +3,8 @@ + +