{"version":3,"file":"js/markdown.60cad62d.bundle.js","mappings":"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","sources":["webpack:///node_modules/pagedown-editor/Markdown.Editor.js","webpack:///node_modules/pagedown-editor/node-editor.js","webpack:///node_modules/pagedown/Markdown.Converter.js","webpack:///node_modules/pagedown/Markdown.Sanitizer.js","webpack:///node_modules/pagedown/node-pagedown.js"],"sourcesContent":["// needs Markdown.Converter.js at the moment\r\n\r\n(function () {\r\n\r\n var util = {},\r\n position = {},\r\n ui = {},\r\n doc = window.document,\r\n re = window.RegExp,\r\n nav = window.navigator,\r\n SETTINGS = { lineLength: 72 },\r\n\r\n // Used to work around some browser bugs where we can't use feature testing.\r\n uaSniffed = {\r\n isIE: /msie/.test(nav.userAgent.toLowerCase()),\r\n isIE_5or6: /msie 6/.test(nav.userAgent.toLowerCase()) || /msie 5/.test(nav.userAgent.toLowerCase()),\r\n isOpera: /opera/.test(nav.userAgent.toLowerCase())\r\n };\r\n\r\n var defaultsStrings = {\r\n bold: \"Strong Ctrl+B\",\r\n boldexample: \"strong text\",\r\n\r\n italic: \"Emphasis Ctrl+I\",\r\n italicexample: \"emphasized text\",\r\n\r\n link: \"Hyperlink Ctrl+L\",\r\n linkdescription: \"enter link description here\",\r\n linkdialog: \"

Insert Hyperlink

http://example.com/ \\\"optional title\\\"

\",\r\n\r\n quote: \"Blockquote
Ctrl+Q\",\r\n quoteexample: \"Blockquote\",\r\n\r\n code: \"Code Sample
 Ctrl+K\",\r\n        codeexample: \"enter code here\",\r\n\r\n        image: \"Image  Ctrl+G\",\r\n        imagedescription: \"enter image description here\",\r\n        imagedialog: \"

Insert Image

http://example.com/images/diagram.jpg \\\"optional title\\\"

Need
free image hosting?

\",\r\n\r\n olist: \"Numbered List
    Ctrl+O\",\r\n ulist: \"Bulleted List
      Ctrl+U\",\r\n litem: \"List item\",\r\n\r\n heading: \"Heading

      /

      Ctrl+H\",\r\n headingexample: \"Heading\",\r\n\r\n hr: \"Horizontal Rule
      Ctrl+R\",\r\n\r\n undo: \"Undo - Ctrl+Z\",\r\n redo: \"Redo - Ctrl+Y\",\r\n redomac: \"Redo - Ctrl+Shift+Z\",\r\n\r\n help: \"Markdown Editing Help\"\r\n };\r\n\r\n\r\n // -------------------------------------------------------------------\r\n // YOUR CHANGES GO HERE\r\n //\r\n // I've tried to localize the things you are likely to change to\r\n // this area.\r\n // -------------------------------------------------------------------\r\n\r\n // The default text that appears in the dialog input box when entering\r\n // links.\r\n var imageDefaultText = \"http://\";\r\n var linkDefaultText = \"http://\";\r\n\r\n // -------------------------------------------------------------------\r\n // END OF YOUR CHANGES\r\n // -------------------------------------------------------------------\r\n\r\n // options, if given, can have the following properties:\r\n // options.helpButton = { handler: yourEventHandler }\r\n // options.strings = { italicexample: \"slanted text\" }\r\n // `yourEventHandler` is the click handler for the help button.\r\n // If `options.helpButton` isn't given, not help button is created.\r\n // `options.strings` can have any or all of the same properties as\r\n // `defaultStrings` above, so you can just override some string displayed\r\n // to the user on a case-by-case basis, or translate all strings to\r\n // a different language.\r\n //\r\n // For backwards compatibility reasons, the `options` argument can also\r\n // be just the `helpButton` object, and `strings.help` can also be set via\r\n // `helpButton.title`. This should be considered legacy.\r\n //\r\n // The constructed editor object has the methods:\r\n // - getConverter() returns the markdown converter object that was passed to the constructor\r\n // - run() actually starts the editor; should be called after all necessary plugins are registered. Calling this more than once is a no-op.\r\n // - refreshPreview() forces the preview to be updated. This method is only available after run() was called.\r\n Markdown.Editor = function (markdownConverter, idPostfix, options) {\r\n \r\n options = options || {};\r\n\r\n if (typeof options.handler === \"function\") { //backwards compatible behavior\r\n options = { helpButton: options };\r\n }\r\n options.strings = options.strings || {};\r\n if (options.helpButton) {\r\n options.strings.help = options.strings.help || options.helpButton.title;\r\n }\r\n var getString = function (identifier) { return options.strings[identifier] || defaultsStrings[identifier]; }\r\n\r\n idPostfix = idPostfix || \"\";\r\n\r\n var hooks = this.hooks = new Markdown.HookCollection();\r\n hooks.addNoop(\"onPreviewRefresh\"); // called with no arguments after the preview has been refreshed\r\n hooks.addNoop(\"postBlockquoteCreation\"); // called with the user's selection *after* the blockquote was created; should return the actual to-be-inserted text\r\n hooks.addFalse(\"insertLinkDialog\")\r\n hooks.addFalse(\"insertImageDialog\"); /* called with one parameter: a callback to be called with the URL of the image. If the application creates\r\n * its own image insertion dialog, this hook should return true, and the callback should be called with the chosen\r\n * image url (or null if the user cancelled). If this hook returns false, the default dialog will be used.\r\n */\r\n\r\n this.getConverter = function () { return markdownConverter; }\r\n\r\n var that = this,\r\n panels;\r\n\r\n this.run = function () {\r\n if (panels)\r\n return; // already initialized\r\n\r\n panels = new PanelCollection(idPostfix);\r\n var commandManager = new CommandManager(hooks, getString, markdownConverter);\r\n var previewManager = new PreviewManager(markdownConverter, panels, function () { hooks.onPreviewRefresh(); });\r\n var undoManager, uiManager;\r\n\r\n if (!/\\?noundo/.test(doc.location.href)) {\r\n undoManager = new UndoManager(function () {\r\n previewManager.refresh();\r\n if (uiManager) // not available on the first call\r\n uiManager.setUndoRedoButtonStates();\r\n }, panels);\r\n this.textOperation = function (f) {\r\n undoManager.setCommandMode();\r\n f();\r\n that.refreshPreview();\r\n }\r\n }\r\n\r\n uiManager = new UIManager(idPostfix, panels, undoManager, previewManager, commandManager, options.helpButton, getString);\r\n uiManager.setUndoRedoButtonStates();\r\n\r\n var forceRefresh = that.refreshPreview = function () { previewManager.refresh(true); };\r\n\r\n forceRefresh();\r\n };\r\n\r\n }\r\n\r\n // before: contains all the text in the input box BEFORE the selection.\r\n // after: contains all the text in the input box AFTER the selection.\r\n function Chunks() { }\r\n\r\n // startRegex: a regular expression to find the start tag\r\n // endRegex: a regular expresssion to find the end tag\r\n Chunks.prototype.findTags = function (startRegex, endRegex) {\r\n\r\n var chunkObj = this;\r\n var regex;\r\n\r\n if (startRegex) {\r\n\r\n regex = util.extendRegExp(startRegex, \"\", \"$\");\r\n\r\n this.before = this.before.replace(regex,\r\n function (match) {\r\n chunkObj.startTag = chunkObj.startTag + match;\r\n return \"\";\r\n });\r\n\r\n regex = util.extendRegExp(startRegex, \"^\", \"\");\r\n\r\n this.selection = this.selection.replace(regex,\r\n function (match) {\r\n chunkObj.startTag = chunkObj.startTag + match;\r\n return \"\";\r\n });\r\n }\r\n\r\n if (endRegex) {\r\n\r\n regex = util.extendRegExp(endRegex, \"\", \"$\");\r\n\r\n this.selection = this.selection.replace(regex,\r\n function (match) {\r\n chunkObj.endTag = match + chunkObj.endTag;\r\n return \"\";\r\n });\r\n\r\n regex = util.extendRegExp(endRegex, \"^\", \"\");\r\n\r\n this.after = this.after.replace(regex,\r\n function (match) {\r\n chunkObj.endTag = match + chunkObj.endTag;\r\n return \"\";\r\n });\r\n }\r\n };\r\n\r\n // If remove is false, the whitespace is transferred\r\n // to the before/after regions.\r\n //\r\n // If remove is true, the whitespace disappears.\r\n Chunks.prototype.trimWhitespace = function (remove) {\r\n var beforeReplacer, afterReplacer, that = this;\r\n if (remove) {\r\n beforeReplacer = afterReplacer = \"\";\r\n } else {\r\n beforeReplacer = function (s) { that.before += s; return \"\"; }\r\n afterReplacer = function (s) { that.after = s + that.after; return \"\"; }\r\n }\r\n\r\n this.selection = this.selection.replace(/^(\\s*)/, beforeReplacer).replace(/(\\s*)$/, afterReplacer);\r\n };\r\n\r\n\r\n Chunks.prototype.skipLines = function (nLinesBefore, nLinesAfter, findExtraNewlines) {\r\n\r\n if (nLinesBefore === undefined) {\r\n nLinesBefore = 1;\r\n }\r\n\r\n if (nLinesAfter === undefined) {\r\n nLinesAfter = 1;\r\n }\r\n\r\n nLinesBefore++;\r\n nLinesAfter++;\r\n\r\n var regexText;\r\n var replacementText;\r\n\r\n // chrome bug ... documented at: http://meta.stackexchange.com/questions/63307/blockquote-glitch-in-editor-in-chrome-6-and-7/65985#65985\r\n if (navigator.userAgent.match(/Chrome/)) {\r\n \"X\".match(/()./);\r\n }\r\n\r\n this.selection = this.selection.replace(/(^\\n*)/, \"\");\r\n\r\n this.startTag = this.startTag + re.$1;\r\n\r\n this.selection = this.selection.replace(/(\\n*$)/, \"\");\r\n this.endTag = this.endTag + re.$1;\r\n this.startTag = this.startTag.replace(/(^\\n*)/, \"\");\r\n this.before = this.before + re.$1;\r\n this.endTag = this.endTag.replace(/(\\n*$)/, \"\");\r\n this.after = this.after + re.$1;\r\n\r\n if (this.before) {\r\n\r\n regexText = replacementText = \"\";\r\n\r\n while (nLinesBefore--) {\r\n regexText += \"\\\\n?\";\r\n replacementText += \"\\n\";\r\n }\r\n\r\n if (findExtraNewlines) {\r\n regexText = \"\\\\n*\";\r\n }\r\n this.before = this.before.replace(new re(regexText + \"$\", \"\"), replacementText);\r\n }\r\n\r\n if (this.after) {\r\n\r\n regexText = replacementText = \"\";\r\n\r\n while (nLinesAfter--) {\r\n regexText += \"\\\\n?\";\r\n replacementText += \"\\n\";\r\n }\r\n if (findExtraNewlines) {\r\n regexText = \"\\\\n*\";\r\n }\r\n\r\n this.after = this.after.replace(new re(regexText, \"\"), replacementText);\r\n }\r\n };\r\n\r\n // end of Chunks\r\n\r\n // A collection of the important regions on the page.\r\n // Cached so we don't have to keep traversing the DOM.\r\n // Also holds ieCachedRange and ieCachedScrollTop, where necessary; working around\r\n // this issue:\r\n // Internet explorer has problems with CSS sprite buttons that use HTML\r\n // lists. When you click on the background image \"button\", IE will\r\n // select the non-existent link text and discard the selection in the\r\n // textarea. The solution to this is to cache the textarea selection\r\n // on the button's mousedown event and set a flag. In the part of the\r\n // code where we need to grab the selection, we check for the flag\r\n // and, if it's set, use the cached area instead of querying the\r\n // textarea.\r\n //\r\n // This ONLY affects Internet Explorer (tested on versions 6, 7\r\n // and 8) and ONLY on button clicks. Keyboard shortcuts work\r\n // normally since the focus never leaves the textarea.\r\n function PanelCollection(postfix) {\r\n this.buttonBar = doc.getElementById(\"wmd-button-bar\" + postfix);\r\n this.preview = doc.getElementById(\"wmd-preview\" + postfix);\r\n this.input = doc.getElementById(\"wmd-input\" + postfix);\r\n };\r\n\r\n // Returns true if the DOM element is visible, false if it's hidden.\r\n // Checks if display is anything other than none.\r\n util.isVisible = function (elem) {\r\n\r\n if (window.getComputedStyle) {\r\n // Most browsers\r\n return window.getComputedStyle(elem, null).getPropertyValue(\"display\") !== \"none\";\r\n }\r\n else if (elem.currentStyle) {\r\n // IE\r\n return elem.currentStyle[\"display\"] !== \"none\";\r\n }\r\n };\r\n\r\n\r\n // Adds a listener callback to a DOM element which is fired on a specified\r\n // event.\r\n util.addEvent = function (elem, event, listener) {\r\n if (elem.attachEvent) {\r\n // IE only. The \"on\" is mandatory.\r\n elem.attachEvent(\"on\" + event, listener);\r\n }\r\n else {\r\n // Other browsers.\r\n elem.addEventListener(event, listener, false);\r\n }\r\n };\r\n\r\n\r\n // Removes a listener callback from a DOM element which is fired on a specified\r\n // event.\r\n util.removeEvent = function (elem, event, listener) {\r\n if (elem.detachEvent) {\r\n // IE only. The \"on\" is mandatory.\r\n elem.detachEvent(\"on\" + event, listener);\r\n }\r\n else {\r\n // Other browsers.\r\n elem.removeEventListener(event, listener, false);\r\n }\r\n };\r\n\r\n // Converts \\r\\n and \\r to \\n.\r\n util.fixEolChars = function (text) {\r\n text = text.replace(/\\r\\n/g, \"\\n\");\r\n text = text.replace(/\\r/g, \"\\n\");\r\n return text;\r\n };\r\n\r\n // Extends a regular expression. Returns a new RegExp\r\n // using pre + regex + post as the expression.\r\n // Used in a few functions where we have a base\r\n // expression and we want to pre- or append some\r\n // conditions to it (e.g. adding \"$\" to the end).\r\n // The flags are unchanged.\r\n //\r\n // regex is a RegExp, pre and post are strings.\r\n util.extendRegExp = function (regex, pre, post) {\r\n\r\n if (pre === null || pre === undefined) {\r\n pre = \"\";\r\n }\r\n if (post === null || post === undefined) {\r\n post = \"\";\r\n }\r\n\r\n var pattern = regex.toString();\r\n var flags;\r\n\r\n // Replace the flags with empty space and store them.\r\n pattern = pattern.replace(/\\/([gim]*)$/, function (wholeMatch, flagsPart) {\r\n flags = flagsPart;\r\n return \"\";\r\n });\r\n\r\n // Remove the slash delimiters on the regular expression.\r\n pattern = pattern.replace(/(^\\/|\\/$)/g, \"\");\r\n pattern = pre + pattern + post;\r\n\r\n return new re(pattern, flags);\r\n }\r\n\r\n // UNFINISHED\r\n // The assignment in the while loop makes jslint cranky.\r\n // I'll change it to a better loop later.\r\n position.getTop = function (elem, isInner) {\r\n var result = elem.offsetTop;\r\n if (!isInner) {\r\n while (elem = elem.offsetParent) {\r\n result += elem.offsetTop;\r\n }\r\n }\r\n return result;\r\n };\r\n\r\n position.getHeight = function (elem) {\r\n return elem.offsetHeight || elem.scrollHeight;\r\n };\r\n\r\n position.getWidth = function (elem) {\r\n return elem.offsetWidth || elem.scrollWidth;\r\n };\r\n\r\n position.getPageSize = function () {\r\n\r\n var scrollWidth, scrollHeight;\r\n var innerWidth, innerHeight;\r\n\r\n // It's not very clear which blocks work with which browsers.\r\n if (self.innerHeight && self.scrollMaxY) {\r\n scrollWidth = doc.body.scrollWidth;\r\n scrollHeight = self.innerHeight + self.scrollMaxY;\r\n }\r\n else if (doc.body.scrollHeight > doc.body.offsetHeight) {\r\n scrollWidth = doc.body.scrollWidth;\r\n scrollHeight = doc.body.scrollHeight;\r\n }\r\n else {\r\n scrollWidth = doc.body.offsetWidth;\r\n scrollHeight = doc.body.offsetHeight;\r\n }\r\n\r\n if (self.innerHeight) {\r\n // Non-IE browser\r\n innerWidth = self.innerWidth;\r\n innerHeight = self.innerHeight;\r\n }\r\n else if (doc.documentElement && doc.documentElement.clientHeight) {\r\n // Some versions of IE (IE 6 w/ a DOCTYPE declaration)\r\n innerWidth = doc.documentElement.clientWidth;\r\n innerHeight = doc.documentElement.clientHeight;\r\n }\r\n else if (doc.body) {\r\n // Other versions of IE\r\n innerWidth = doc.body.clientWidth;\r\n innerHeight = doc.body.clientHeight;\r\n }\r\n\r\n var maxWidth = Math.max(scrollWidth, innerWidth);\r\n var maxHeight = Math.max(scrollHeight, innerHeight);\r\n return [maxWidth, maxHeight, innerWidth, innerHeight];\r\n };\r\n\r\n // Handles pushing and popping TextareaStates for undo/redo commands.\r\n // I should rename the stack variables to list.\r\n function UndoManager(callback, panels) {\r\n\r\n var undoObj = this;\r\n var undoStack = []; // A stack of undo states\r\n var stackPtr = 0; // The index of the current state\r\n var mode = \"none\";\r\n var lastState; // The last state\r\n var timer; // The setTimeout handle for cancelling the timer\r\n var inputStateObj;\r\n\r\n // Set the mode for later logic steps.\r\n var setMode = function (newMode, noSave) {\r\n if (mode != newMode) {\r\n mode = newMode;\r\n if (!noSave) {\r\n saveState();\r\n }\r\n }\r\n\r\n if (!uaSniffed.isIE || mode != \"moving\") {\r\n timer = setTimeout(refreshState, 1);\r\n }\r\n else {\r\n inputStateObj = null;\r\n }\r\n };\r\n\r\n var refreshState = function (isInitialState) {\r\n inputStateObj = new TextareaState(panels, isInitialState);\r\n timer = undefined;\r\n };\r\n\r\n this.setCommandMode = function () {\r\n mode = \"command\";\r\n saveState();\r\n timer = setTimeout(refreshState, 0);\r\n };\r\n\r\n this.canUndo = function () {\r\n return stackPtr > 1;\r\n };\r\n\r\n this.canRedo = function () {\r\n if (undoStack[stackPtr + 1]) {\r\n return true;\r\n }\r\n return false;\r\n };\r\n\r\n // Removes the last state and restores it.\r\n this.undo = function () {\r\n\r\n if (undoObj.canUndo()) {\r\n if (lastState) {\r\n // What about setting state -1 to null or checking for undefined?\r\n lastState.restore();\r\n lastState = null;\r\n }\r\n else {\r\n undoStack[stackPtr] = new TextareaState(panels);\r\n undoStack[--stackPtr].restore();\r\n\r\n if (callback) {\r\n callback();\r\n }\r\n }\r\n }\r\n\r\n mode = \"none\";\r\n panels.input.focus();\r\n refreshState();\r\n };\r\n\r\n // Redo an action.\r\n this.redo = function () {\r\n\r\n if (undoObj.canRedo()) {\r\n\r\n undoStack[++stackPtr].restore();\r\n\r\n if (callback) {\r\n callback();\r\n }\r\n }\r\n\r\n mode = \"none\";\r\n panels.input.focus();\r\n refreshState();\r\n };\r\n\r\n // Push the input area state to the stack.\r\n var saveState = function () {\r\n var currState = inputStateObj || new TextareaState(panels);\r\n\r\n if (!currState) {\r\n return false;\r\n }\r\n if (mode == \"moving\") {\r\n if (!lastState) {\r\n lastState = currState;\r\n }\r\n return;\r\n }\r\n if (lastState) {\r\n if (undoStack[stackPtr - 1].text != lastState.text) {\r\n undoStack[stackPtr++] = lastState;\r\n }\r\n lastState = null;\r\n }\r\n undoStack[stackPtr++] = currState;\r\n undoStack[stackPtr + 1] = null;\r\n if (callback) {\r\n callback();\r\n }\r\n };\r\n\r\n var handleCtrlYZ = function (event) {\r\n\r\n var handled = false;\r\n\r\n if ((event.ctrlKey || event.metaKey) && !event.altKey) {\r\n\r\n // IE and Opera do not support charCode.\r\n var keyCode = event.charCode || event.keyCode;\r\n var keyCodeChar = String.fromCharCode(keyCode);\r\n\r\n switch (keyCodeChar.toLowerCase()) {\r\n\r\n case \"y\":\r\n undoObj.redo();\r\n handled = true;\r\n break;\r\n\r\n case \"z\":\r\n if (!event.shiftKey) {\r\n undoObj.undo();\r\n }\r\n else {\r\n undoObj.redo();\r\n }\r\n handled = true;\r\n break;\r\n }\r\n }\r\n\r\n if (handled) {\r\n if (event.preventDefault) {\r\n event.preventDefault();\r\n }\r\n if (window.event) {\r\n window.event.returnValue = false;\r\n }\r\n return;\r\n }\r\n };\r\n\r\n // Set the mode depending on what is going on in the input area.\r\n var handleModeChange = function (event) {\r\n\r\n if (!event.ctrlKey && !event.metaKey) {\r\n\r\n var keyCode = event.keyCode;\r\n\r\n if ((keyCode >= 33 && keyCode <= 40) || (keyCode >= 63232 && keyCode <= 63235)) {\r\n // 33 - 40: page up/dn and arrow keys\r\n // 63232 - 63235: page up/dn and arrow keys on safari\r\n setMode(\"moving\");\r\n }\r\n else if (keyCode == 8 || keyCode == 46 || keyCode == 127) {\r\n // 8: backspace\r\n // 46: delete\r\n // 127: delete\r\n setMode(\"deleting\");\r\n }\r\n else if (keyCode == 13) {\r\n // 13: Enter\r\n setMode(\"newlines\");\r\n }\r\n else if (keyCode == 27) {\r\n // 27: escape\r\n setMode(\"escape\");\r\n }\r\n else if ((keyCode < 16 || keyCode > 20) && keyCode != 91) {\r\n // 16-20 are shift, etc.\r\n // 91: left window key\r\n // I think this might be a little messed up since there are\r\n // a lot of nonprinting keys above 20.\r\n setMode(\"typing\");\r\n }\r\n }\r\n };\r\n\r\n var setEventHandlers = function () {\r\n util.addEvent(panels.input, \"keypress\", function (event) {\r\n // keyCode 89: y\r\n // keyCode 90: z\r\n if ((event.ctrlKey || event.metaKey) && !event.altKey && (event.keyCode == 89 || event.keyCode == 90)) {\r\n event.preventDefault();\r\n }\r\n });\r\n\r\n var handlePaste = function () {\r\n if (uaSniffed.isIE || (inputStateObj && inputStateObj.text != panels.input.value)) {\r\n if (timer == undefined) {\r\n mode = \"paste\";\r\n saveState();\r\n refreshState();\r\n }\r\n }\r\n };\r\n\r\n util.addEvent(panels.input, \"keydown\", handleCtrlYZ);\r\n util.addEvent(panels.input, \"keydown\", handleModeChange);\r\n util.addEvent(panels.input, \"mousedown\", function () {\r\n setMode(\"moving\");\r\n });\r\n\r\n panels.input.onpaste = handlePaste;\r\n panels.input.ondrop = handlePaste;\r\n };\r\n\r\n var init = function () {\r\n setEventHandlers();\r\n refreshState(true);\r\n saveState();\r\n };\r\n\r\n init();\r\n }\r\n\r\n // end of UndoManager\r\n\r\n // The input textarea state/contents.\r\n // This is used to implement undo/redo by the undo manager.\r\n function TextareaState(panels, isInitialState) {\r\n\r\n // Aliases\r\n var stateObj = this;\r\n var inputArea = panels.input;\r\n this.init = function () {\r\n if (!util.isVisible(inputArea)) {\r\n return;\r\n }\r\n if (!isInitialState && doc.activeElement && doc.activeElement !== inputArea) { // this happens when tabbing out of the input box\r\n return;\r\n }\r\n\r\n this.setInputAreaSelectionStartEnd();\r\n this.scrollTop = inputArea.scrollTop;\r\n if (!this.text && inputArea.selectionStart || inputArea.selectionStart === 0) {\r\n this.text = inputArea.value;\r\n }\r\n\r\n }\r\n\r\n // Sets the selected text in the input box after we've performed an\r\n // operation.\r\n this.setInputAreaSelection = function () {\r\n\r\n if (!util.isVisible(inputArea)) {\r\n return;\r\n }\r\n\r\n if (inputArea.selectionStart !== undefined && !uaSniffed.isOpera) {\r\n\r\n inputArea.focus();\r\n inputArea.selectionStart = stateObj.start;\r\n inputArea.selectionEnd = stateObj.end;\r\n inputArea.scrollTop = stateObj.scrollTop;\r\n }\r\n else if (doc.selection) {\r\n\r\n if (doc.activeElement && doc.activeElement !== inputArea) {\r\n return;\r\n }\r\n\r\n inputArea.focus();\r\n var range = inputArea.createTextRange();\r\n range.moveStart(\"character\", -inputArea.value.length);\r\n range.moveEnd(\"character\", -inputArea.value.length);\r\n range.moveEnd(\"character\", stateObj.end);\r\n range.moveStart(\"character\", stateObj.start);\r\n range.select();\r\n }\r\n };\r\n\r\n this.setInputAreaSelectionStartEnd = function () {\r\n\r\n if (!panels.ieCachedRange && (inputArea.selectionStart || inputArea.selectionStart === 0)) {\r\n\r\n stateObj.start = inputArea.selectionStart;\r\n stateObj.end = inputArea.selectionEnd;\r\n }\r\n else if (doc.selection) {\r\n\r\n stateObj.text = util.fixEolChars(inputArea.value);\r\n\r\n // IE loses the selection in the textarea when buttons are\r\n // clicked. On IE we cache the selection. Here, if something is cached,\r\n // we take it.\r\n var range = panels.ieCachedRange || doc.selection.createRange();\r\n\r\n var fixedRange = util.fixEolChars(range.text);\r\n var marker = \"\\x07\";\r\n var markedRange = marker + fixedRange + marker;\r\n range.text = markedRange;\r\n var inputText = util.fixEolChars(inputArea.value);\r\n\r\n range.moveStart(\"character\", -markedRange.length);\r\n range.text = fixedRange;\r\n\r\n stateObj.start = inputText.indexOf(marker);\r\n stateObj.end = inputText.lastIndexOf(marker) - marker.length;\r\n\r\n var len = stateObj.text.length - util.fixEolChars(inputArea.value).length;\r\n\r\n if (len) {\r\n range.moveStart(\"character\", -fixedRange.length);\r\n while (len--) {\r\n fixedRange += \"\\n\";\r\n stateObj.end += 1;\r\n }\r\n range.text = fixedRange;\r\n }\r\n\r\n if (panels.ieCachedRange)\r\n stateObj.scrollTop = panels.ieCachedScrollTop; // this is set alongside with ieCachedRange\r\n\r\n panels.ieCachedRange = null;\r\n\r\n this.setInputAreaSelection();\r\n }\r\n };\r\n\r\n // Restore this state into the input area.\r\n this.restore = function () {\r\n\r\n if (stateObj.text != undefined && stateObj.text != inputArea.value) {\r\n inputArea.value = stateObj.text;\r\n }\r\n this.setInputAreaSelection();\r\n inputArea.scrollTop = stateObj.scrollTop;\r\n };\r\n\r\n // Gets a collection of HTML chunks from the inptut textarea.\r\n this.getChunks = function () {\r\n\r\n var chunk = new Chunks();\r\n chunk.before = util.fixEolChars(stateObj.text.substring(0, stateObj.start));\r\n chunk.startTag = \"\";\r\n chunk.selection = util.fixEolChars(stateObj.text.substring(stateObj.start, stateObj.end));\r\n chunk.endTag = \"\";\r\n chunk.after = util.fixEolChars(stateObj.text.substring(stateObj.end));\r\n chunk.scrollTop = stateObj.scrollTop;\r\n\r\n return chunk;\r\n };\r\n\r\n // Sets the TextareaState properties given a chunk of markdown.\r\n this.setChunks = function (chunk) {\r\n\r\n chunk.before = chunk.before + chunk.startTag;\r\n chunk.after = chunk.endTag + chunk.after;\r\n\r\n this.start = chunk.before.length;\r\n this.end = chunk.before.length + chunk.selection.length;\r\n this.text = chunk.before + chunk.selection + chunk.after;\r\n this.scrollTop = chunk.scrollTop;\r\n };\r\n this.init();\r\n };\r\n\r\n function PreviewManager(converter, panels, previewRefreshCallback) {\r\n\r\n var managerObj = this;\r\n var timeout;\r\n var elapsedTime;\r\n var oldInputText;\r\n var maxDelay = 3000;\r\n var startType = \"delayed\"; // The other legal value is \"manual\"\r\n\r\n // Adds event listeners to elements\r\n var setupEvents = function (inputElem, listener) {\r\n\r\n util.addEvent(inputElem, \"input\", listener);\r\n inputElem.onpaste = listener;\r\n inputElem.ondrop = listener;\r\n\r\n util.addEvent(inputElem, \"keypress\", listener);\r\n util.addEvent(inputElem, \"keydown\", listener);\r\n };\r\n\r\n var getDocScrollTop = function () {\r\n\r\n var result = 0;\r\n\r\n if (window.innerHeight) {\r\n result = window.pageYOffset;\r\n }\r\n else\r\n if (doc.documentElement && doc.documentElement.scrollTop) {\r\n result = doc.documentElement.scrollTop;\r\n }\r\n else\r\n if (doc.body) {\r\n result = doc.body.scrollTop;\r\n }\r\n\r\n return result;\r\n };\r\n\r\n var makePreviewHtml = function () {\r\n\r\n // If there is no registered preview panel\r\n // there is nothing to do.\r\n if (!panels.preview)\r\n return;\r\n\r\n\r\n var text = panels.input.value;\r\n if (text && text == oldInputText) {\r\n return; // Input text hasn't changed.\r\n }\r\n else {\r\n oldInputText = text;\r\n }\r\n\r\n var prevTime = new Date().getTime();\r\n\r\n text = converter.makeHtml(text);\r\n\r\n // Calculate the processing time of the HTML creation.\r\n // It's used as the delay time in the event listener.\r\n var currTime = new Date().getTime();\r\n elapsedTime = currTime - prevTime;\r\n\r\n pushPreviewHtml(text);\r\n };\r\n\r\n // setTimeout is already used. Used as an event listener.\r\n var applyTimeout = function () {\r\n\r\n if (timeout) {\r\n clearTimeout(timeout);\r\n timeout = undefined;\r\n }\r\n\r\n if (startType !== \"manual\") {\r\n\r\n var delay = 0;\r\n\r\n if (startType === \"delayed\") {\r\n delay = elapsedTime;\r\n }\r\n\r\n if (delay > maxDelay) {\r\n delay = maxDelay;\r\n }\r\n timeout = setTimeout(makePreviewHtml, delay);\r\n }\r\n };\r\n\r\n var getScaleFactor = function (panel) {\r\n if (panel.scrollHeight <= panel.clientHeight) {\r\n return 1;\r\n }\r\n return panel.scrollTop / (panel.scrollHeight - panel.clientHeight);\r\n };\r\n\r\n var setPanelScrollTops = function () {\r\n if (panels.preview) {\r\n panels.preview.scrollTop = (panels.preview.scrollHeight - panels.preview.clientHeight) * getScaleFactor(panels.preview);\r\n }\r\n };\r\n\r\n this.refresh = function (requiresRefresh) {\r\n\r\n if (requiresRefresh) {\r\n oldInputText = \"\";\r\n makePreviewHtml();\r\n }\r\n else {\r\n applyTimeout();\r\n }\r\n };\r\n\r\n this.processingTime = function () {\r\n return elapsedTime;\r\n };\r\n\r\n var isFirstTimeFilled = true;\r\n\r\n // IE doesn't let you use innerHTML if the element is contained somewhere in a table\r\n // (which is the case for inline editing) -- in that case, detach the element, set the\r\n // value, and reattach. Yes, that *is* ridiculous.\r\n var ieSafePreviewSet = function (text) {\r\n var preview = panels.preview;\r\n var parent = preview.parentNode;\r\n var sibling = preview.nextSibling;\r\n parent.removeChild(preview);\r\n preview.innerHTML = text;\r\n if (!sibling)\r\n parent.appendChild(preview);\r\n else\r\n parent.insertBefore(preview, sibling);\r\n }\r\n\r\n var nonSuckyBrowserPreviewSet = function (text) {\r\n panels.preview.innerHTML = text;\r\n }\r\n\r\n var previewSetter;\r\n\r\n var previewSet = function (text) {\r\n if (previewSetter)\r\n return previewSetter(text);\r\n\r\n try {\r\n nonSuckyBrowserPreviewSet(text);\r\n previewSetter = nonSuckyBrowserPreviewSet;\r\n } catch (e) {\r\n previewSetter = ieSafePreviewSet;\r\n previewSetter(text);\r\n }\r\n };\r\n\r\n var pushPreviewHtml = function (text) {\r\n\r\n var emptyTop = position.getTop(panels.input) - getDocScrollTop();\r\n\r\n if (panels.preview) {\r\n previewSet(text);\r\n previewRefreshCallback();\r\n }\r\n\r\n setPanelScrollTops();\r\n\r\n if (isFirstTimeFilled) {\r\n isFirstTimeFilled = false;\r\n return;\r\n }\r\n\r\n var fullTop = position.getTop(panels.input) - getDocScrollTop();\r\n\r\n if (uaSniffed.isIE) {\r\n setTimeout(function () {\r\n window.scrollBy(0, fullTop - emptyTop);\r\n }, 0);\r\n }\r\n else {\r\n window.scrollBy(0, fullTop - emptyTop);\r\n }\r\n };\r\n\r\n var init = function () {\r\n\r\n setupEvents(panels.input, applyTimeout);\r\n makePreviewHtml();\r\n\r\n if (panels.preview) {\r\n panels.preview.scrollTop = 0;\r\n }\r\n };\r\n\r\n init();\r\n };\r\n\r\n // Creates the background behind the hyperlink text entry box.\r\n // And download dialog\r\n // Most of this has been moved to CSS but the div creation and\r\n // browser-specific hacks remain here.\r\n ui.createBackground = function () {\r\n\r\n var background = doc.createElement(\"div\"),\r\n style = background.style;\r\n \r\n background.className = \"wmd-prompt-background\";\r\n \r\n style.position = \"absolute\";\r\n style.top = \"0\";\r\n\r\n style.zIndex = \"1000\";\r\n\r\n if (uaSniffed.isIE) {\r\n style.filter = \"alpha(opacity=50)\";\r\n }\r\n else {\r\n style.opacity = \"0.5\";\r\n }\r\n\r\n var pageSize = position.getPageSize();\r\n style.height = pageSize[1] + \"px\";\r\n\r\n if (uaSniffed.isIE) {\r\n style.left = doc.documentElement.scrollLeft;\r\n style.width = doc.documentElement.clientWidth;\r\n }\r\n else {\r\n style.left = \"0\";\r\n style.width = \"100%\";\r\n }\r\n\r\n doc.body.appendChild(background);\r\n return background;\r\n };\r\n\r\n // This simulates a modal dialog box and asks for the URL when you\r\n // click the hyperlink or image buttons.\r\n //\r\n // text: The html for the input box.\r\n // defaultInputText: The default value that appears in the input box.\r\n // callback: The function which is executed when the prompt is dismissed, either via OK or Cancel.\r\n // It receives a single argument; either the entered text (if OK was chosen) or null (if Cancel\r\n // was chosen).\r\n ui.prompt = function (text, defaultInputText, callback) {\r\n\r\n // These variables need to be declared at this level since they are used\r\n // in multiple functions.\r\n var dialog; // The dialog box.\r\n var input; // The text box where you enter the hyperlink.\r\n\r\n\r\n if (defaultInputText === undefined) {\r\n defaultInputText = \"\";\r\n }\r\n\r\n // Used as a keydown event handler. Esc dismisses the prompt.\r\n // Key code 27 is ESC.\r\n var checkEscape = function (key) {\r\n var code = (key.charCode || key.keyCode);\r\n if (code === 27) {\r\n if (key.stopPropagation) key.stopPropagation();\r\n close(true);\r\n return false;\r\n }\r\n };\r\n\r\n // Dismisses the hyperlink input box.\r\n // isCancel is true if we don't care about the input text.\r\n // isCancel is false if we are going to keep the text.\r\n var close = function (isCancel) {\r\n util.removeEvent(doc.body, \"keyup\", checkEscape);\r\n var text = input.value;\r\n\r\n if (isCancel) {\r\n text = null;\r\n }\r\n else {\r\n // Fixes common pasting errors.\r\n text = text.replace(/^http:\\/\\/(https?|ftp):\\/\\//, '$1://');\r\n if (!/^(?:https?|ftp):\\/\\//.test(text))\r\n text = 'http://' + text;\r\n }\r\n\r\n dialog.parentNode.removeChild(dialog);\r\n\r\n callback(text);\r\n return false;\r\n };\r\n\r\n\r\n\r\n // Create the text input box form/window.\r\n var createDialog = function () {\r\n\r\n // The main dialog box.\r\n dialog = doc.createElement(\"div\");\r\n dialog.className = \"wmd-prompt-dialog\";\r\n dialog.style.padding = \"10px;\";\r\n dialog.style.position = \"fixed\";\r\n dialog.style.width = \"400px\";\r\n dialog.style.zIndex = \"1001\";\r\n\r\n // The dialog text.\r\n var question = doc.createElement(\"div\");\r\n question.innerHTML = text;\r\n question.style.padding = \"5px\";\r\n dialog.appendChild(question);\r\n\r\n // The web form container for the text box and buttons.\r\n var form = doc.createElement(\"form\"),\r\n style = form.style;\r\n form.onsubmit = function () { return close(false); };\r\n style.padding = \"0\";\r\n style.margin = \"0\";\r\n style.cssFloat = \"left\";\r\n style.width = \"100%\";\r\n style.textAlign = \"center\";\r\n style.position = \"relative\";\r\n dialog.appendChild(form);\r\n\r\n // The input text box\r\n input = doc.createElement(\"input\");\r\n input.type = \"text\";\r\n input.value = defaultInputText;\r\n style = input.style;\r\n style.display = \"block\";\r\n style.width = \"80%\";\r\n style.marginLeft = style.marginRight = \"auto\";\r\n form.appendChild(input);\r\n\r\n // The ok button\r\n var okButton = doc.createElement(\"input\");\r\n okButton.type = \"button\";\r\n okButton.onclick = function () { return close(false); };\r\n okButton.value = \"OK\";\r\n style = okButton.style;\r\n style.margin = \"10px\";\r\n style.display = \"inline\";\r\n style.width = \"7em\";\r\n\r\n\r\n // The cancel button\r\n var cancelButton = doc.createElement(\"input\");\r\n cancelButton.type = \"button\";\r\n cancelButton.onclick = function () { return close(true); };\r\n cancelButton.value = \"Cancel\";\r\n style = cancelButton.style;\r\n style.margin = \"10px\";\r\n style.display = \"inline\";\r\n style.width = \"7em\";\r\n\r\n form.appendChild(okButton);\r\n form.appendChild(cancelButton);\r\n\r\n util.addEvent(doc.body, \"keyup\", checkEscape);\r\n dialog.style.top = \"50%\";\r\n dialog.style.left = \"50%\";\r\n dialog.style.display = \"block\";\r\n if (uaSniffed.isIE_5or6) {\r\n dialog.style.position = \"absolute\";\r\n dialog.style.top = doc.documentElement.scrollTop + 200 + \"px\";\r\n dialog.style.left = \"50%\";\r\n }\r\n doc.body.appendChild(dialog);\r\n\r\n // This has to be done AFTER adding the dialog to the form if you\r\n // want it to be centered.\r\n dialog.style.marginTop = -(position.getHeight(dialog) / 2) + \"px\";\r\n dialog.style.marginLeft = -(position.getWidth(dialog) / 2) + \"px\";\r\n\r\n };\r\n\r\n // Why is this in a zero-length timeout?\r\n // Is it working around a browser bug?\r\n setTimeout(function () {\r\n\r\n createDialog();\r\n\r\n var defTextLen = defaultInputText.length;\r\n if (input.selectionStart !== undefined) {\r\n input.selectionStart = 0;\r\n input.selectionEnd = defTextLen;\r\n }\r\n else if (input.createTextRange) {\r\n var range = input.createTextRange();\r\n range.collapse(false);\r\n range.moveStart(\"character\", -defTextLen);\r\n range.moveEnd(\"character\", defTextLen);\r\n range.select();\r\n }\r\n\r\n input.focus();\r\n }, 0);\r\n };\r\n\r\n function UIManager(postfix, panels, undoManager, previewManager, commandManager, helpOptions, getString) {\r\n\r\n var inputBox = panels.input,\r\n buttons = {}; // buttons.undo, buttons.link, etc. The actual DOM elements.\r\n\r\n makeSpritedButtonRow();\r\n\r\n var keyEvent = \"keydown\";\r\n if (uaSniffed.isOpera) {\r\n keyEvent = \"keypress\";\r\n }\r\n\r\n util.addEvent(inputBox, keyEvent, function (key) {\r\n\r\n // Check to see if we have a button key and, if so execute the callback.\r\n if ((key.ctrlKey || key.metaKey) && !key.altKey && !key.shiftKey) {\r\n\r\n var keyCode = key.charCode || key.keyCode;\r\n var keyCodeStr = String.fromCharCode(keyCode).toLowerCase();\r\n\r\n switch (keyCodeStr) {\r\n case \"b\":\r\n doClick(buttons.bold);\r\n break;\r\n case \"i\":\r\n doClick(buttons.italic);\r\n break;\r\n case \"l\":\r\n doClick(buttons.link);\r\n break;\r\n case \"q\":\r\n doClick(buttons.quote);\r\n break;\r\n case \"k\":\r\n doClick(buttons.code);\r\n break;\r\n case \"g\":\r\n doClick(buttons.image);\r\n break;\r\n case \"o\":\r\n doClick(buttons.olist);\r\n break;\r\n case \"u\":\r\n doClick(buttons.ulist);\r\n break;\r\n case \"h\":\r\n doClick(buttons.heading);\r\n break;\r\n case \"r\":\r\n doClick(buttons.hr);\r\n break;\r\n case \"y\":\r\n doClick(buttons.redo);\r\n break;\r\n case \"z\":\r\n if (key.shiftKey) {\r\n doClick(buttons.redo);\r\n }\r\n else {\r\n doClick(buttons.undo);\r\n }\r\n break;\r\n default:\r\n return;\r\n }\r\n\r\n\r\n if (key.preventDefault) {\r\n key.preventDefault();\r\n }\r\n\r\n if (window.event) {\r\n window.event.returnValue = false;\r\n }\r\n }\r\n });\r\n\r\n // Auto-indent on shift-enter\r\n util.addEvent(inputBox, \"keyup\", function (key) {\r\n if (key.shiftKey && !key.ctrlKey && !key.metaKey) {\r\n var keyCode = key.charCode || key.keyCode;\r\n // Character 13 is Enter\r\n if (keyCode === 13) {\r\n var fakeButton = {};\r\n fakeButton.textOp = bindCommand(\"doAutoindent\");\r\n doClick(fakeButton);\r\n }\r\n }\r\n });\r\n\r\n // special handler because IE clears the context of the textbox on ESC\r\n if (uaSniffed.isIE) {\r\n util.addEvent(inputBox, \"keydown\", function (key) {\r\n var code = key.keyCode;\r\n if (code === 27) {\r\n return false;\r\n }\r\n });\r\n }\r\n\r\n\r\n // Perform the button's action.\r\n function doClick(button) {\r\n\r\n inputBox.focus();\r\n\r\n if (button.textOp) {\r\n\r\n if (undoManager) {\r\n undoManager.setCommandMode();\r\n }\r\n\r\n var state = new TextareaState(panels);\r\n\r\n if (!state) {\r\n return;\r\n }\r\n\r\n var chunks = state.getChunks();\r\n\r\n // Some commands launch a \"modal\" prompt dialog. Javascript\r\n // can't really make a modal dialog box and the WMD code\r\n // will continue to execute while the dialog is displayed.\r\n // This prevents the dialog pattern I'm used to and means\r\n // I can't do something like this:\r\n //\r\n // var link = CreateLinkDialog();\r\n // makeMarkdownLink(link);\r\n //\r\n // Instead of this straightforward method of handling a\r\n // dialog I have to pass any code which would execute\r\n // after the dialog is dismissed (e.g. link creation)\r\n // in a function parameter.\r\n //\r\n // Yes this is awkward and I think it sucks, but there's\r\n // no real workaround. Only the image and link code\r\n // create dialogs and require the function pointers.\r\n var fixupInputArea = function () {\r\n\r\n inputBox.focus();\r\n\r\n if (chunks) {\r\n state.setChunks(chunks);\r\n }\r\n\r\n state.restore();\r\n previewManager.refresh();\r\n };\r\n\r\n var noCleanup = button.textOp(chunks, fixupInputArea);\r\n\r\n if (!noCleanup) {\r\n fixupInputArea();\r\n }\r\n\r\n }\r\n\r\n if (button.execute) {\r\n button.execute(undoManager);\r\n }\r\n };\r\n\r\n function setupButton(button, isEnabled) {\r\n\r\n var normalYShift = \"0px\";\r\n var disabledYShift = \"-20px\";\r\n var highlightYShift = \"-40px\";\r\n var image = button.getElementsByTagName(\"span\")[0];\r\n if (isEnabled) {\r\n image.style.backgroundPosition = button.XShift + \" \" + normalYShift;\r\n button.onmouseover = function () {\r\n image.style.backgroundPosition = this.XShift + \" \" + highlightYShift;\r\n };\r\n\r\n button.onmouseout = function () {\r\n image.style.backgroundPosition = this.XShift + \" \" + normalYShift;\r\n };\r\n\r\n // IE tries to select the background image \"button\" text (it's\r\n // implemented in a list item) so we have to cache the selection\r\n // on mousedown.\r\n if (uaSniffed.isIE) {\r\n button.onmousedown = function () {\r\n if (doc.activeElement && doc.activeElement !== panels.input) { // we're not even in the input box, so there's no selection\r\n return;\r\n }\r\n panels.ieCachedRange = document.selection.createRange();\r\n panels.ieCachedScrollTop = panels.input.scrollTop;\r\n };\r\n }\r\n\r\n if (!button.isHelp) {\r\n button.onclick = function () {\r\n if (this.onmouseout) {\r\n this.onmouseout();\r\n }\r\n doClick(this);\r\n return false;\r\n }\r\n }\r\n }\r\n else {\r\n image.style.backgroundPosition = button.XShift + \" \" + disabledYShift;\r\n button.onmouseover = button.onmouseout = button.onclick = function () { };\r\n }\r\n }\r\n\r\n function bindCommand(method) {\r\n if (typeof method === \"string\")\r\n method = commandManager[method];\r\n return function () { method.apply(commandManager, arguments); }\r\n }\r\n\r\n function makeSpritedButtonRow() {\r\n\r\n var buttonBar = panels.buttonBar;\r\n\r\n var normalYShift = \"0px\";\r\n var disabledYShift = \"-20px\";\r\n var highlightYShift = \"-40px\";\r\n\r\n var buttonRow = document.createElement(\"ul\");\r\n buttonRow.id = \"wmd-button-row\" + postfix;\r\n buttonRow.className = 'wmd-button-row';\r\n buttonRow = buttonBar.appendChild(buttonRow);\r\n var xPosition = 0;\r\n var makeButton = function (id, title, XShift, textOp) {\r\n var button = document.createElement(\"li\");\r\n button.className = \"wmd-button\";\r\n button.style.left = xPosition + \"px\";\r\n xPosition += 25;\r\n var buttonImage = document.createElement(\"span\");\r\n button.id = id + postfix;\r\n button.appendChild(buttonImage);\r\n button.title = title;\r\n button.XShift = XShift;\r\n if (textOp)\r\n button.textOp = textOp;\r\n setupButton(button, true);\r\n buttonRow.appendChild(button);\r\n return button;\r\n };\r\n var makeSpacer = function (num) {\r\n var spacer = document.createElement(\"li\");\r\n spacer.className = \"wmd-spacer wmd-spacer\" + num;\r\n spacer.id = \"wmd-spacer\" + num + postfix;\r\n buttonRow.appendChild(spacer);\r\n xPosition += 25;\r\n }\r\n\r\n buttons.bold = makeButton(\"wmd-bold-button\", getString(\"bold\"), \"0px\", bindCommand(\"doBold\"));\r\n buttons.italic = makeButton(\"wmd-italic-button\", getString(\"italic\"), \"-20px\", bindCommand(\"doItalic\"));\r\n makeSpacer(1);\r\n buttons.link = makeButton(\"wmd-link-button\", getString(\"link\"), \"-40px\", bindCommand(function (chunk, postProcessing) {\r\n return this.doLinkOrImage(chunk, postProcessing, false);\r\n }));\r\n buttons.quote = makeButton(\"wmd-quote-button\", getString(\"quote\"), \"-60px\", bindCommand(\"doBlockquote\"));\r\n buttons.code = makeButton(\"wmd-code-button\", getString(\"code\"), \"-80px\", bindCommand(\"doCode\"));\r\n buttons.image = makeButton(\"wmd-image-button\", getString(\"image\"), \"-100px\", bindCommand(function (chunk, postProcessing) {\r\n return this.doLinkOrImage(chunk, postProcessing, true);\r\n }));\r\n makeSpacer(2);\r\n buttons.olist = makeButton(\"wmd-olist-button\", getString(\"olist\"), \"-120px\", bindCommand(function (chunk, postProcessing) {\r\n this.doList(chunk, postProcessing, true);\r\n }));\r\n buttons.ulist = makeButton(\"wmd-ulist-button\", getString(\"ulist\"), \"-140px\", bindCommand(function (chunk, postProcessing) {\r\n this.doList(chunk, postProcessing, false);\r\n }));\r\n buttons.heading = makeButton(\"wmd-heading-button\", getString(\"heading\"), \"-160px\", bindCommand(\"doHeading\"));\r\n buttons.hr = makeButton(\"wmd-hr-button\", getString(\"hr\"), \"-180px\", bindCommand(\"doHorizontalRule\"));\r\n makeSpacer(3);\r\n buttons.undo = makeButton(\"wmd-undo-button\", getString(\"undo\"), \"-200px\", null);\r\n buttons.undo.execute = function (manager) { if (manager) manager.undo(); };\r\n\r\n var redoTitle = /win/.test(nav.platform.toLowerCase()) ?\r\n getString(\"redo\") :\r\n getString(\"redomac\"); // mac and other non-Windows platforms\r\n\r\n buttons.redo = makeButton(\"wmd-redo-button\", redoTitle, \"-220px\", null);\r\n buttons.redo.execute = function (manager) { if (manager) manager.redo(); };\r\n\r\n if (helpOptions) {\r\n var helpButton = document.createElement(\"li\");\r\n var helpButtonImage = document.createElement(\"span\");\r\n helpButton.appendChild(helpButtonImage);\r\n helpButton.className = \"wmd-button wmd-help-button\";\r\n helpButton.id = \"wmd-help-button\" + postfix;\r\n helpButton.XShift = \"-240px\";\r\n helpButton.isHelp = true;\r\n helpButton.style.right = \"0px\";\r\n helpButton.title = getString(\"help\");\r\n helpButton.onclick = helpOptions.handler;\r\n\r\n setupButton(helpButton, true);\r\n buttonRow.appendChild(helpButton);\r\n buttons.help = helpButton;\r\n }\r\n\r\n setUndoRedoButtonStates();\r\n }\r\n\r\n function setUndoRedoButtonStates() {\r\n if (undoManager) {\r\n setupButton(buttons.undo, undoManager.canUndo());\r\n setupButton(buttons.redo, undoManager.canRedo());\r\n }\r\n };\r\n\r\n this.setUndoRedoButtonStates = setUndoRedoButtonStates;\r\n\r\n }\r\n\r\n function CommandManager(pluginHooks, getString, converter) {\r\n this.hooks = pluginHooks;\r\n this.getString = getString;\r\n this.converter = converter;\r\n }\r\n\r\n var commandProto = CommandManager.prototype;\r\n\r\n // The markdown symbols - 4 spaces = code, > = blockquote, etc.\r\n commandProto.prefixes = \"(?:\\\\s{4,}|\\\\s*>|\\\\s*-\\\\s+|\\\\s*\\\\d+\\\\.|=|\\\\+|-|_|\\\\*|#|\\\\s*\\\\[[^\\n]]+\\\\]:)\";\r\n\r\n // Remove markdown symbols from the chunk selection.\r\n commandProto.unwrap = function (chunk) {\r\n var txt = new re(\"([^\\\\n])\\\\n(?!(\\\\n|\" + this.prefixes + \"))\", \"g\");\r\n chunk.selection = chunk.selection.replace(txt, \"$1 $2\");\r\n };\r\n\r\n commandProto.wrap = function (chunk, len) {\r\n this.unwrap(chunk);\r\n var regex = new re(\"(.{1,\" + len + \"})( +|$\\\\n?)\", \"gm\"),\r\n that = this;\r\n\r\n chunk.selection = chunk.selection.replace(regex, function (line, marked) {\r\n if (new re(\"^\" + that.prefixes, \"\").test(line)) {\r\n return line;\r\n }\r\n return marked + \"\\n\";\r\n });\r\n\r\n chunk.selection = chunk.selection.replace(/\\s+$/, \"\");\r\n };\r\n\r\n commandProto.doBold = function (chunk, postProcessing) {\r\n return this.doBorI(chunk, postProcessing, 2, this.getString(\"boldexample\"));\r\n };\r\n\r\n commandProto.doItalic = function (chunk, postProcessing) {\r\n return this.doBorI(chunk, postProcessing, 1, this.getString(\"italicexample\"));\r\n };\r\n\r\n // chunk: The selected region that will be enclosed with */**\r\n // nStars: 1 for italics, 2 for bold\r\n // insertText: If you just click the button without highlighting text, this gets inserted\r\n commandProto.doBorI = function (chunk, postProcessing, nStars, insertText) {\r\n\r\n // Get rid of whitespace and fixup newlines.\r\n chunk.trimWhitespace();\r\n chunk.selection = chunk.selection.replace(/\\n{2,}/g, \"\\n\");\r\n\r\n // Look for stars before and after. Is the chunk already marked up?\r\n // note that these regex matches cannot fail\r\n var starsBefore = /(\\**$)/.exec(chunk.before)[0];\r\n var starsAfter = /(^\\**)/.exec(chunk.after)[0];\r\n\r\n var prevStars = Math.min(starsBefore.length, starsAfter.length);\r\n\r\n // Remove stars if we have to since the button acts as a toggle.\r\n if ((prevStars >= nStars) && (prevStars != 2 || nStars != 1)) {\r\n chunk.before = chunk.before.replace(re(\"[*]{\" + nStars + \"}$\", \"\"), \"\");\r\n chunk.after = chunk.after.replace(re(\"^[*]{\" + nStars + \"}\", \"\"), \"\");\r\n }\r\n else if (!chunk.selection && starsAfter) {\r\n // It's not really clear why this code is necessary. It just moves\r\n // some arbitrary stuff around.\r\n chunk.after = chunk.after.replace(/^([*_]*)/, \"\");\r\n chunk.before = chunk.before.replace(/(\\s?)$/, \"\");\r\n var whitespace = re.$1;\r\n chunk.before = chunk.before + starsAfter + whitespace;\r\n }\r\n else {\r\n\r\n // In most cases, if you don't have any selected text and click the button\r\n // you'll get a selected, marked up region with the default text inserted.\r\n if (!chunk.selection && !starsAfter) {\r\n chunk.selection = insertText;\r\n }\r\n\r\n // Add the true markup.\r\n var markup = nStars <= 1 ? \"*\" : \"**\"; // shouldn't the test be = ?\r\n chunk.before = chunk.before + markup;\r\n chunk.after = markup + chunk.after;\r\n }\r\n\r\n return;\r\n };\r\n\r\n commandProto.stripLinkDefs = function (text, defsToAdd) {\r\n\r\n text = text.replace(/^[ ]{0,3}\\[(\\d+)\\]:[ \\t]*\\n?[ \\t]*?[ \\t]*\\n?[ \\t]*(?:(\\n*)[\"(](.+?)[\")][ \\t]*)?(?:\\n+|$)/gm,\r\n function (totalMatch, id, link, newlines, title) {\r\n defsToAdd[id] = totalMatch.replace(/\\s*$/, \"\");\r\n if (newlines) {\r\n // Strip the title and return that separately.\r\n defsToAdd[id] = totalMatch.replace(/[\"(](.+?)[\")]$/, \"\");\r\n return newlines + title;\r\n }\r\n return \"\";\r\n });\r\n\r\n return text;\r\n };\r\n\r\n commandProto.addLinkDef = function (chunk, linkDef) {\r\n\r\n var refNumber = 0; // The current reference number\r\n var defsToAdd = {}; //\r\n // Start with a clean slate by removing all previous link definitions.\r\n chunk.before = this.stripLinkDefs(chunk.before, defsToAdd);\r\n chunk.selection = this.stripLinkDefs(chunk.selection, defsToAdd);\r\n chunk.after = this.stripLinkDefs(chunk.after, defsToAdd);\r\n\r\n var defs = \"\";\r\n var regex = /(\\[)((?:\\[[^\\]]*\\]|[^\\[\\]])*)(\\][ ]?(?:\\n[ ]*)?\\[)(\\d+)(\\])/g;\r\n \r\n // The above regex, used to update [foo][13] references after renumbering,\r\n // is much too liberal; it can catch things that are not actually parsed\r\n // as references (notably: code). It's impossible to know which matches are\r\n // real references without performing a markdown conversion, so that's what\r\n // we do. All matches are replaced with a unique reference number, which is\r\n // given a unique link. The uniquifier in both cases is the character offset\r\n // of the match inside the source string. The modified version is then sent\r\n // through the Markdown renderer. Because link reference are stripped during\r\n // rendering, the unique link is present in the rendered version if and only\r\n // if the match at its offset was in fact rendered as a link or image.\r\n var complete = chunk.before + chunk.selection + chunk.after;\r\n var rendered = this.converter.makeHtml(complete);\r\n var testlink = \"http://this-is-a-real-link.biz/\";\r\n \r\n // If our fake link appears in the rendered version *before* we have added it,\r\n // this probably means you're a Meta Stack Exchange user who is deliberately\r\n // trying to break this feature. You can still break this workaround if you\r\n // attach a plugin to the converter that sometimes (!) inserts this link. In\r\n // that case, consider yourself unsupported.\r\n while (rendered.indexOf(testlink) != -1)\r\n testlink += \"nicetry/\";\r\n \r\n var fakedefs = \"\\n\\n\";\r\n\r\n // the regex is tested on the (up to) three chunks separately, and on substrings,\r\n // so in order to have the correct offsets to check against okayToModify(), we\r\n // have to keep track of how many characters are in the original source before\r\n // the substring that we're looking at. Note that doLinkOrImage aligns the selection\r\n // on potential brackets, so there should be no major breakage from the chunk\r\n // separation.\r\n var skippedChars = 0;\r\n\r\n var uniquified = complete.replace(regex, function uniquify(wholeMatch, before, inner, afterInner, id, end, offset) {\r\n skippedChars += offset;\r\n fakedefs += \" [\" + skippedChars + \"]: \" + testlink + skippedChars + \"/unicorn\\n\";\r\n skippedChars += before.length;\r\n inner = inner.replace(regex, uniquify);\r\n skippedChars -= before.length;\r\n var result = before + inner + afterInner + skippedChars + end;\r\n skippedChars -= offset;\r\n return result;\r\n });\r\n \r\n rendered = this.converter.makeHtml(uniquified + fakedefs);\r\n \r\n var okayToModify = function(offset) {\r\n return rendered.indexOf(testlink + offset + \"/unicorn\") !== -1;\r\n }\r\n \r\n var addDefNumber = function (def) {\r\n refNumber++;\r\n def = def.replace(/^[ ]{0,3}\\[(\\d+)\\]:/, \" [\" + refNumber + \"]:\");\r\n defs += \"\\n\" + def;\r\n };\r\n\r\n // note that\r\n // a) the recursive call to getLink cannot go infinite, because by definition\r\n // of regex, inner is always a proper substring of wholeMatch, and\r\n // b) more than one level of nesting is neither supported by the regex\r\n // nor making a lot of sense (the only use case for nesting is a linked image)\r\n var getLink = function (wholeMatch, before, inner, afterInner, id, end, offset) {\r\n if (!okayToModify(skippedChars + offset))\r\n return wholeMatch;\r\n skippedChars += offset + before.length;\r\n inner = inner.replace(regex, getLink);\r\n skippedChars -= offset + before.length;\r\n if (defsToAdd[id]) {\r\n addDefNumber(defsToAdd[id]);\r\n return before + inner + afterInner + refNumber + end;\r\n }\r\n return wholeMatch;\r\n };\r\n\r\n var len = chunk.before.length;\r\n chunk.before = chunk.before.replace(regex, getLink);\r\n skippedChars += len;\r\n \r\n len = chunk.selection.length;\r\n if (linkDef) {\r\n addDefNumber(linkDef);\r\n }\r\n else {\r\n chunk.selection = chunk.selection.replace(regex, getLink);\r\n }\r\n skippedChars += len; \r\n\r\n var refOut = refNumber;\r\n\r\n chunk.after = chunk.after.replace(regex, getLink);\r\n\r\n if (chunk.after) {\r\n chunk.after = chunk.after.replace(/\\n*$/, \"\");\r\n }\r\n if (!chunk.after) {\r\n chunk.selection = chunk.selection.replace(/\\n*$/, \"\");\r\n }\r\n\r\n chunk.after += \"\\n\\n\" + defs;\r\n\r\n return refOut;\r\n };\r\n\r\n // takes the line as entered into the add link/as image dialog and makes\r\n // sure the URL and the optinal title are \"nice\".\r\n function properlyEncoded(linkdef) {\r\n return linkdef.replace(/^\\s*(.*?)(?:\\s+\"(.+)\")?\\s*$/, function (wholematch, link, title) {\r\n \r\n var inQueryString = false;\r\n\r\n // Having `[^\\w\\d-./]` in there is just a shortcut that lets us skip\r\n // the most common characters in URLs. Replacing that it with `.` would not change\r\n // the result, because encodeURI returns those characters unchanged, but it\r\n // would mean lots of unnecessary replacement calls. Having `[` and `]` in that\r\n // section as well means we do *not* enocde square brackets. These characters are\r\n // a strange beast in URLs, but if anything, this causes URLs to be more readable,\r\n // and we leave it to the browser to make sure that these links are handled without\r\n // problems.\r\n link = link.replace(/%(?:[\\da-fA-F]{2})|\\?|\\+|[^\\w\\d-./[\\]]/g, function (match) {\r\n // Valid percent encoding. Could just return it as is, but we follow RFC3986\r\n // Section 2.1 which says \"For consistency, URI producers and normalizers\r\n // should use uppercase hexadecimal digits for all percent-encodings.\"\r\n // Note that we also handle (illegal) stand-alone percent characters by\r\n // replacing them with \"%25\"\r\n if (match.length === 3 && match.charAt(0) == \"%\") {\r\n return match.toUpperCase();\r\n }\r\n switch (match) {\r\n case \"?\":\r\n inQueryString = true;\r\n return \"?\";\r\n break;\r\n \r\n // In the query string, a plus and a space are identical -- normalize.\r\n // Not strictly necessary, but identical behavior to the previous version\r\n // of this function.\r\n case \"+\":\r\n if (inQueryString)\r\n return \"%20\";\r\n break;\r\n }\r\n return encodeURI(match);\r\n })\r\n \r\n if (title) {\r\n title = title.trim ? title.trim() : title.replace(/^\\s*/, \"\").replace(/\\s*$/, \"\");\r\n title = title.replace(/\"/g, \"quot;\").replace(/\\(/g, \"(\").replace(/\\)/g, \")\").replace(//g, \">\");\r\n }\r\n return title ? link + ' \"' + title + '\"' : link;\r\n });\r\n }\r\n\r\n commandProto.doLinkOrImage = function (chunk, postProcessing, isImage) {\r\n\r\n chunk.trimWhitespace();\r\n chunk.findTags(/\\s*!?\\[/, /\\][ ]?(?:\\n[ ]*)?(\\[.*?\\])?/);\r\n var background;\r\n\r\n if (chunk.endTag.length > 1 && chunk.startTag.length > 0) {\r\n\r\n chunk.startTag = chunk.startTag.replace(/!?\\[/, \"\");\r\n chunk.endTag = \"\";\r\n this.addLinkDef(chunk, null);\r\n\r\n }\r\n else {\r\n \r\n // We're moving start and end tag back into the selection, since (as we're in the else block) we're not\r\n // *removing* a link, but *adding* one, so whatever findTags() found is now back to being part of the\r\n // link text. linkEnteredCallback takes care of escaping any brackets.\r\n chunk.selection = chunk.startTag + chunk.selection + chunk.endTag;\r\n chunk.startTag = chunk.endTag = \"\";\r\n\r\n if (/\\n\\n/.test(chunk.selection)) {\r\n this.addLinkDef(chunk, null);\r\n return;\r\n }\r\n var that = this;\r\n // The function to be executed when you enter a link and press OK or Cancel.\r\n // Marks up the link and adds the ref.\r\n var linkEnteredCallback = function (link) {\r\n\r\n background.parentNode.removeChild(background);\r\n\r\n if (link !== null) {\r\n // ( $1\r\n // [^\\\\] anything that's not a backslash\r\n // (?:\\\\\\\\)* an even number (this includes zero) of backslashes\r\n // )\r\n // (?= followed by\r\n // [[\\]] an opening or closing bracket\r\n // )\r\n //\r\n // In other words, a non-escaped bracket. These have to be escaped now to make sure they\r\n // don't count as the end of the link or similar.\r\n // Note that the actual bracket has to be a lookahead, because (in case of to subsequent brackets),\r\n // the bracket in one match may be the \"not a backslash\" character in the next match, so it\r\n // should not be consumed by the first match.\r\n // The \"prepend a space and finally remove it\" steps makes sure there is a \"not a backslash\" at the\r\n // start of the string, so this also works if the selection begins with a bracket. We cannot solve\r\n // this by anchoring with ^, because in the case that the selection starts with two brackets, this\r\n // would mean a zero-width match at the start. Since zero-width matches advance the string position,\r\n // the first bracket could then not act as the \"not a backslash\" for the second.\r\n chunk.selection = (\" \" + chunk.selection).replace(/([^\\\\](?:\\\\\\\\)*)(?=[[\\]])/g, \"$1\\\\\").substr(1);\r\n \r\n var linkDef = \" [999]: \" + properlyEncoded(link);\r\n\r\n var num = that.addLinkDef(chunk, linkDef);\r\n chunk.startTag = isImage ? \"![\" : \"[\";\r\n chunk.endTag = \"][\" + num + \"]\";\r\n\r\n if (!chunk.selection) {\r\n if (isImage) {\r\n chunk.selection = that.getString(\"imagedescription\");\r\n }\r\n else {\r\n chunk.selection = that.getString(\"linkdescription\");\r\n }\r\n }\r\n }\r\n postProcessing();\r\n that.hooks.insertLinkDialog()\r\n };\r\n\r\n background = ui.createBackground();\r\n\r\n if (isImage) {\r\n if (!this.hooks.insertImageDialog(linkEnteredCallback))\r\n ui.prompt(this.getString(\"imagedialog\"), imageDefaultText, linkEnteredCallback);\r\n }\r\n else {\r\n ui.prompt(this.getString(\"linkdialog\"), linkDefaultText, linkEnteredCallback);\r\n }\r\n return true;\r\n }\r\n };\r\n\r\n // When making a list, hitting shift-enter will put your cursor on the next line\r\n // at the current indent level.\r\n commandProto.doAutoindent = function (chunk, postProcessing) {\r\n\r\n var commandMgr = this,\r\n fakeSelection = false;\r\n\r\n chunk.before = chunk.before.replace(/(\\n|^)[ ]{0,3}([*+-]|\\d+[.])[ \\t]*\\n$/, \"\\n\\n\");\r\n chunk.before = chunk.before.replace(/(\\n|^)[ ]{0,3}>[ \\t]*\\n$/, \"\\n\\n\");\r\n chunk.before = chunk.before.replace(/(\\n|^)[ \\t]+\\n$/, \"\\n\\n\");\r\n \r\n // There's no selection, end the cursor wasn't at the end of the line:\r\n // The user wants to split the current list item / code line / blockquote line\r\n // (for the latter it doesn't really matter) in two. Temporarily select the\r\n // (rest of the) line to achieve this.\r\n if (!chunk.selection && !/^[ \\t]*(?:\\n|$)/.test(chunk.after)) {\r\n chunk.after = chunk.after.replace(/^[^\\n]*/, function (wholeMatch) {\r\n chunk.selection = wholeMatch;\r\n return \"\";\r\n });\r\n fakeSelection = true;\r\n }\r\n\r\n if (/(\\n|^)[ ]{0,3}([*+-]|\\d+[.])[ \\t]+.*\\n$/.test(chunk.before)) {\r\n if (commandMgr.doList) {\r\n commandMgr.doList(chunk);\r\n }\r\n }\r\n if (/(\\n|^)[ ]{0,3}>[ \\t]+.*\\n$/.test(chunk.before)) {\r\n if (commandMgr.doBlockquote) {\r\n commandMgr.doBlockquote(chunk);\r\n }\r\n }\r\n if (/(\\n|^)(\\t|[ ]{4,}).*\\n$/.test(chunk.before)) {\r\n if (commandMgr.doCode) {\r\n commandMgr.doCode(chunk);\r\n }\r\n }\r\n \r\n if (fakeSelection) {\r\n chunk.after = chunk.selection + chunk.after;\r\n chunk.selection = \"\";\r\n }\r\n };\r\n\r\n commandProto.doBlockquote = function (chunk, postProcessing) {\r\n\r\n chunk.selection = chunk.selection.replace(/^(\\n*)([^\\r]+?)(\\n*)$/,\r\n function (totalMatch, newlinesBefore, text, newlinesAfter) {\r\n chunk.before += newlinesBefore;\r\n chunk.after = newlinesAfter + chunk.after;\r\n return text;\r\n });\r\n\r\n chunk.before = chunk.before.replace(/(>[ \\t]*)$/,\r\n function (totalMatch, blankLine) {\r\n chunk.selection = blankLine + chunk.selection;\r\n return \"\";\r\n });\r\n\r\n chunk.selection = chunk.selection.replace(/^(\\s|>)+$/, \"\");\r\n chunk.selection = chunk.selection || this.getString(\"quoteexample\");\r\n\r\n // The original code uses a regular expression to find out how much of the\r\n // text *directly before* the selection already was a blockquote:\r\n\r\n /*\r\n if (chunk.before) {\r\n chunk.before = chunk.before.replace(/\\n?$/, \"\\n\");\r\n }\r\n chunk.before = chunk.before.replace(/(((\\n|^)(\\n[ \\t]*)*>(.+\\n)*.*)+(\\n[ \\t]*)*$)/,\r\n function (totalMatch) {\r\n chunk.startTag = totalMatch;\r\n return \"\";\r\n });\r\n */\r\n\r\n // This comes down to:\r\n // Go backwards as many lines a possible, such that each line\r\n // a) starts with \">\", or\r\n // b) is almost empty, except for whitespace, or\r\n // c) is preceeded by an unbroken chain of non-empty lines\r\n // leading up to a line that starts with \">\" and at least one more character\r\n // and in addition\r\n // d) at least one line fulfills a)\r\n //\r\n // Since this is essentially a backwards-moving regex, it's susceptible to\r\n // catstrophic backtracking and can cause the browser to hang;\r\n // see e.g. http://meta.stackexchange.com/questions/9807.\r\n //\r\n // Hence we replaced this by a simple state machine that just goes through the\r\n // lines and checks for a), b), and c).\r\n\r\n var match = \"\",\r\n leftOver = \"\",\r\n line;\r\n if (chunk.before) {\r\n var lines = chunk.before.replace(/\\n$/, \"\").split(\"\\n\");\r\n var inChain = false;\r\n for (var i = 0; i < lines.length; i++) {\r\n var good = false;\r\n line = lines[i];\r\n inChain = inChain && line.length > 0; // c) any non-empty line continues the chain\r\n if (/^>/.test(line)) { // a)\r\n good = true;\r\n if (!inChain && line.length > 1) // c) any line that starts with \">\" and has at least one more character starts the chain\r\n inChain = true;\r\n } else if (/^[ \\t]*$/.test(line)) { // b)\r\n good = true;\r\n } else {\r\n good = inChain; // c) the line is not empty and does not start with \">\", so it matches if and only if we're in the chain\r\n }\r\n if (good) {\r\n match += line + \"\\n\";\r\n } else {\r\n leftOver += match + line;\r\n match = \"\\n\";\r\n }\r\n }\r\n if (!/(^|\\n)>/.test(match)) { // d)\r\n leftOver += match;\r\n match = \"\";\r\n }\r\n }\r\n\r\n chunk.startTag = match;\r\n chunk.before = leftOver;\r\n\r\n // end of change\r\n\r\n if (chunk.after) {\r\n chunk.after = chunk.after.replace(/^\\n?/, \"\\n\");\r\n }\r\n\r\n chunk.after = chunk.after.replace(/^(((\\n|^)(\\n[ \\t]*)*>(.+\\n)*.*)+(\\n[ \\t]*)*)/,\r\n function (totalMatch) {\r\n chunk.endTag = totalMatch;\r\n return \"\";\r\n }\r\n );\r\n\r\n var replaceBlanksInTags = function (useBracket) {\r\n\r\n var replacement = useBracket ? \"> \" : \"\";\r\n\r\n if (chunk.startTag) {\r\n chunk.startTag = chunk.startTag.replace(/\\n((>|\\s)*)\\n$/,\r\n function (totalMatch, markdown) {\r\n return \"\\n\" + markdown.replace(/^[ ]{0,3}>?[ \\t]*$/gm, replacement) + \"\\n\";\r\n });\r\n }\r\n if (chunk.endTag) {\r\n chunk.endTag = chunk.endTag.replace(/^\\n((>|\\s)*)\\n/,\r\n function (totalMatch, markdown) {\r\n return \"\\n\" + markdown.replace(/^[ ]{0,3}>?[ \\t]*$/gm, replacement) + \"\\n\";\r\n });\r\n }\r\n };\r\n\r\n if (/^(?![ ]{0,3}>)/m.test(chunk.selection)) {\r\n this.wrap(chunk, SETTINGS.lineLength - 2);\r\n chunk.selection = chunk.selection.replace(/^/gm, \"> \");\r\n replaceBlanksInTags(true);\r\n chunk.skipLines();\r\n } else {\r\n chunk.selection = chunk.selection.replace(/^[ ]{0,3}> ?/gm, \"\");\r\n this.unwrap(chunk);\r\n replaceBlanksInTags(false);\r\n\r\n if (!/^(\\n|^)[ ]{0,3}>/.test(chunk.selection) && chunk.startTag) {\r\n chunk.startTag = chunk.startTag.replace(/\\n{0,2}$/, \"\\n\\n\");\r\n }\r\n\r\n if (!/(\\n|^)[ ]{0,3}>.*$/.test(chunk.selection) && chunk.endTag) {\r\n chunk.endTag = chunk.endTag.replace(/^\\n{0,2}/, \"\\n\\n\");\r\n }\r\n }\r\n\r\n chunk.selection = this.hooks.postBlockquoteCreation(chunk.selection);\r\n\r\n if (!/\\n/.test(chunk.selection)) {\r\n chunk.selection = chunk.selection.replace(/^(> *)/,\r\n function (wholeMatch, blanks) {\r\n chunk.startTag += blanks;\r\n return \"\";\r\n });\r\n }\r\n };\r\n\r\n commandProto.doCode = function (chunk, postProcessing) {\r\n\r\n var hasTextBefore = /\\S[ ]*$/.test(chunk.before);\r\n var hasTextAfter = /^[ ]*\\S/.test(chunk.after);\r\n\r\n // Use 'four space' markdown if the selection is on its own\r\n // line or is multiline.\r\n if ((!hasTextAfter && !hasTextBefore) || /\\n/.test(chunk.selection)) {\r\n\r\n chunk.before = chunk.before.replace(/[ ]{4}$/,\r\n function (totalMatch) {\r\n chunk.selection = totalMatch + chunk.selection;\r\n return \"\";\r\n });\r\n\r\n var nLinesBack = 1;\r\n var nLinesForward = 1;\r\n\r\n if (/(\\n|^)(\\t|[ ]{4,}).*\\n$/.test(chunk.before)) {\r\n nLinesBack = 0;\r\n }\r\n if (/^\\n(\\t|[ ]{4,})/.test(chunk.after)) {\r\n nLinesForward = 0;\r\n }\r\n\r\n chunk.skipLines(nLinesBack, nLinesForward);\r\n\r\n if (!chunk.selection) {\r\n chunk.startTag = \" \";\r\n chunk.selection = this.getString(\"codeexample\");\r\n }\r\n else {\r\n if (/^[ ]{0,3}\\S/m.test(chunk.selection)) {\r\n if (/\\n/.test(chunk.selection))\r\n chunk.selection = chunk.selection.replace(/^/gm, \" \");\r\n else // if it's not multiline, do not select the four added spaces; this is more consistent with the doList behavior\r\n chunk.before += \" \";\r\n }\r\n else {\r\n chunk.selection = chunk.selection.replace(/^(?:[ ]{4}|[ ]{0,3}\\t)/gm, \"\");\r\n }\r\n }\r\n }\r\n else {\r\n // Use backticks (`) to delimit the code block.\r\n\r\n chunk.trimWhitespace();\r\n chunk.findTags(/`/, /`/);\r\n\r\n if (!chunk.startTag && !chunk.endTag) {\r\n chunk.startTag = chunk.endTag = \"`\";\r\n if (!chunk.selection) {\r\n chunk.selection = this.getString(\"codeexample\");\r\n }\r\n }\r\n else if (chunk.endTag && !chunk.startTag) {\r\n chunk.before += chunk.endTag;\r\n chunk.endTag = \"\";\r\n }\r\n else {\r\n chunk.startTag = chunk.endTag = \"\";\r\n }\r\n }\r\n };\r\n\r\n commandProto.doList = function (chunk, postProcessing, isNumberedList) {\r\n\r\n // These are identical except at the very beginning and end.\r\n // Should probably use the regex extension function to make this clearer.\r\n var previousItemsRegex = /(\\n|^)(([ ]{0,3}([*+-]|\\d+[.])[ \\t]+.*)(\\n.+|\\n{2,}([*+-].*|\\d+[.])[ \\t]+.*|\\n{2,}[ \\t]+\\S.*)*)\\n*$/;\r\n var nextItemsRegex = /^\\n*(([ ]{0,3}([*+-]|\\d+[.])[ \\t]+.*)(\\n.+|\\n{2,}([*+-].*|\\d+[.])[ \\t]+.*|\\n{2,}[ \\t]+\\S.*)*)\\n*/;\r\n\r\n // The default bullet is a dash but others are possible.\r\n // This has nothing to do with the particular HTML bullet,\r\n // it's just a markdown bullet.\r\n var bullet = \"-\";\r\n\r\n // The number in a numbered list.\r\n var num = 1;\r\n\r\n // Get the item prefix - e.g. \" 1. \" for a numbered list, \" - \" for a bulleted list.\r\n var getItemPrefix = function () {\r\n var prefix;\r\n if (isNumberedList) {\r\n prefix = \" \" + num + \". \";\r\n num++;\r\n }\r\n else {\r\n prefix = \" \" + bullet + \" \";\r\n }\r\n return prefix;\r\n };\r\n\r\n // Fixes the prefixes of the other list items.\r\n var getPrefixedItem = function (itemText) {\r\n\r\n // The numbering flag is unset when called by autoindent.\r\n if (isNumberedList === undefined) {\r\n isNumberedList = /^\\s*\\d/.test(itemText);\r\n }\r\n\r\n // Renumber/bullet the list element.\r\n itemText = itemText.replace(/^[ ]{0,3}([*+-]|\\d+[.])\\s/gm,\r\n function (_) {\r\n return getItemPrefix();\r\n });\r\n\r\n return itemText;\r\n };\r\n\r\n chunk.findTags(/(\\n|^)*[ ]{0,3}([*+-]|\\d+[.])\\s+/, null);\r\n\r\n if (chunk.before && !/\\n$/.test(chunk.before) && !/^\\n/.test(chunk.startTag)) {\r\n chunk.before += chunk.startTag;\r\n chunk.startTag = \"\";\r\n }\r\n\r\n if (chunk.startTag) {\r\n\r\n var hasDigits = /\\d+[.]/.test(chunk.startTag);\r\n chunk.startTag = \"\";\r\n chunk.selection = chunk.selection.replace(/\\n[ ]{4}/g, \"\\n\");\r\n this.unwrap(chunk);\r\n chunk.skipLines();\r\n\r\n if (hasDigits) {\r\n // Have to renumber the bullet points if this is a numbered list.\r\n chunk.after = chunk.after.replace(nextItemsRegex, getPrefixedItem);\r\n }\r\n if (isNumberedList == hasDigits) {\r\n return;\r\n }\r\n }\r\n\r\n var nLinesUp = 1;\r\n\r\n chunk.before = chunk.before.replace(previousItemsRegex,\r\n function (itemText) {\r\n if (/^\\s*([*+-])/.test(itemText)) {\r\n bullet = re.$1;\r\n }\r\n nLinesUp = /[^\\n]\\n\\n[^\\n]/.test(itemText) ? 1 : 0;\r\n return getPrefixedItem(itemText);\r\n });\r\n\r\n if (!chunk.selection) {\r\n chunk.selection = this.getString(\"litem\");\r\n }\r\n\r\n var prefix = getItemPrefix();\r\n\r\n var nLinesDown = 1;\r\n\r\n chunk.after = chunk.after.replace(nextItemsRegex,\r\n function (itemText) {\r\n nLinesDown = /[^\\n]\\n\\n[^\\n]/.test(itemText) ? 1 : 0;\r\n return getPrefixedItem(itemText);\r\n });\r\n\r\n chunk.trimWhitespace(true);\r\n chunk.skipLines(nLinesUp, nLinesDown, true);\r\n chunk.startTag = prefix;\r\n var spaces = prefix.replace(/./g, \" \");\r\n this.wrap(chunk, SETTINGS.lineLength - spaces.length);\r\n chunk.selection = chunk.selection.replace(/\\n/g, \"\\n\" + spaces);\r\n\r\n };\r\n\r\n commandProto.doHeading = function (chunk, postProcessing) {\r\n\r\n // Remove leading/trailing whitespace and reduce internal spaces to single spaces.\r\n chunk.selection = chunk.selection.replace(/\\s+/g, \" \");\r\n chunk.selection = chunk.selection.replace(/(^\\s+|\\s+$)/g, \"\");\r\n\r\n // If we clicked the button with no selected text, we just\r\n // make a level 2 hash header around some default text.\r\n if (!chunk.selection) {\r\n chunk.startTag = \"## \";\r\n chunk.selection = this.getString(\"headingexample\");\r\n chunk.endTag = \" ##\";\r\n return;\r\n }\r\n\r\n var headerLevel = 0; // The existing header level of the selected text.\r\n\r\n // Remove any existing hash heading markdown and save the header level.\r\n chunk.findTags(/#+[ ]*/, /[ ]*#+/);\r\n if (/#+/.test(chunk.startTag)) {\r\n headerLevel = re.lastMatch.length;\r\n }\r\n chunk.startTag = chunk.endTag = \"\";\r\n\r\n // Try to get the current header level by looking for - and = in the line\r\n // below the selection.\r\n chunk.findTags(null, /\\s?(-+|=+)/);\r\n if (/=+/.test(chunk.endTag)) {\r\n headerLevel = 1;\r\n }\r\n if (/-+/.test(chunk.endTag)) {\r\n headerLevel = 2;\r\n }\r\n\r\n // Skip to the next line so we can create the header markdown.\r\n chunk.startTag = chunk.endTag = \"\";\r\n chunk.skipLines(1, 1);\r\n\r\n // We make a level 2 header if there is no current header.\r\n // If there is a header level, we substract one from the header level.\r\n // If it's already a level 1 header, it's removed.\r\n var headerLevelToCreate = headerLevel == 0 ? 2 : headerLevel - 1;\r\n\r\n if (headerLevelToCreate > 0) {\r\n\r\n // The button only creates level 1 and 2 underline headers.\r\n // Why not have it iterate over hash header levels? Wouldn't that be easier and cleaner?\r\n var headerChar = headerLevelToCreate >= 2 ? \"-\" : \"=\";\r\n var len = chunk.selection.length;\r\n if (len > SETTINGS.lineLength) {\r\n len = SETTINGS.lineLength;\r\n }\r\n chunk.endTag = \"\\n\";\r\n while (len--) {\r\n chunk.endTag += headerChar;\r\n }\r\n }\r\n };\r\n\r\n commandProto.doHorizontalRule = function (chunk, postProcessing) {\r\n chunk.startTag = \"----------\\n\";\r\n chunk.selection = \"\";\r\n chunk.skipLines(2, 1, true);\r\n }\r\n\r\n\r\n})();\r\n","var pagedown = require(\"pagedown\");\nglobal.window.Markdown = pagedown;\nglobal.window.Markdown.HookCollection = HookCollection;\n\nvar editor = require(\"./Markdown.Editor\");\n\nexports.getPagedownEditor = function() {\n return new Markdown.Editor(pagedown.getSanitizingConverter());\n}\n\nfunction identity(x) { return x; }\nfunction returnFalse(x) { return false; }\nfunction HookCollection() { }\n\nHookCollection.prototype = {\n\n chain: function (hookname, func) {\n var original = this[hookname];\n if (!original)\n throw new Error(\"unknown hook \" + hookname);\n\n if (original === identity)\n this[hookname] = func;\n else\n this[hookname] = function (x) { return func(original(x)); }\n },\n set: function (hookname, func) {\n if (!this[hookname])\n throw new Error(\"unknown hook \" + hookname);\n this[hookname] = func;\n },\n addNoop: function (hookname) {\n this[hookname] = identity;\n },\n addFalse: function (hookname) {\n this[hookname] = returnFalse;\n }\n};\n","var Markdown;\r\n\r\nif (typeof exports === \"object\" && typeof require === \"function\") // we're in a CommonJS (e.g. Node.js) module\r\n Markdown = exports;\r\nelse\r\n Markdown = {};\r\n \r\n// The following text is included for historical reasons, but should\r\n// be taken with a pinch of salt; it's not all true anymore.\r\n\r\n//\r\n// Wherever possible, Showdown is a straight, line-by-line port\r\n// of the Perl version of Markdown.\r\n//\r\n// This is not a normal parser design; it's basically just a\r\n// series of string substitutions. It's hard to read and\r\n// maintain this way, but keeping Showdown close to the original\r\n// design makes it easier to port new features.\r\n//\r\n// More importantly, Showdown behaves like markdown.pl in most\r\n// edge cases. So web applications can do client-side preview\r\n// in Javascript, and then build identical HTML on the server.\r\n//\r\n// This port needs the new RegExp functionality of ECMA 262,\r\n// 3rd Edition (i.e. Javascript 1.5). Most modern web browsers\r\n// should do fine. Even with the new regular expression features,\r\n// We do a lot of work to emulate Perl's regex functionality.\r\n// The tricky changes in this file mostly have the \"attacklab:\"\r\n// label. Major or self-explanatory changes don't.\r\n//\r\n// Smart diff tools like Araxis Merge will be able to match up\r\n// this file with markdown.pl in a useful way. A little tweaking\r\n// helps: in a copy of markdown.pl, replace \"#\" with \"//\" and\r\n// replace \"$text\" with \"text\". Be sure to ignore whitespace\r\n// and line endings.\r\n//\r\n\r\n\r\n//\r\n// Usage:\r\n//\r\n// var text = \"Markdown *rocks*.\";\r\n//\r\n// var converter = new Markdown.Converter();\r\n// var html = converter.makeHtml(text);\r\n//\r\n// alert(html);\r\n//\r\n// Note: move the sample code to the bottom of this\r\n// file before uncommenting it.\r\n//\r\n\r\n(function () {\r\n\r\n function identity(x) { return x; }\r\n function returnFalse(x) { return false; }\r\n\r\n function HookCollection() { }\r\n\r\n HookCollection.prototype = {\r\n\r\n chain: function (hookname, func) {\r\n var original = this[hookname];\r\n if (!original)\r\n throw new Error(\"unknown hook \" + hookname);\r\n\r\n if (original === identity)\r\n this[hookname] = func;\r\n else\r\n this[hookname] = function (text) {\r\n var args = Array.prototype.slice.call(arguments, 0);\r\n args[0] = original.apply(null, args);\r\n return func.apply(null, args);\r\n };\r\n },\r\n set: function (hookname, func) {\r\n if (!this[hookname])\r\n throw new Error(\"unknown hook \" + hookname);\r\n this[hookname] = func;\r\n },\r\n addNoop: function (hookname) {\r\n this[hookname] = identity;\r\n },\r\n addFalse: function (hookname) {\r\n this[hookname] = returnFalse;\r\n }\r\n };\r\n\r\n Markdown.HookCollection = HookCollection;\r\n\r\n // g_urls and g_titles allow arbitrary user-entered strings as keys. This\r\n // caused an exception (and hence stopped the rendering) when the user entered\r\n // e.g. [push] or [__proto__]. Adding a prefix to the actual key prevents this\r\n // (since no builtin property starts with \"s_\"). See\r\n // http://meta.stackoverflow.com/questions/64655/strange-wmd-bug\r\n // (granted, switching from Array() to Object() alone would have left only __proto__\r\n // to be a problem)\r\n function SaveHash() { }\r\n SaveHash.prototype = {\r\n set: function (key, value) {\r\n this[\"s_\" + key] = value;\r\n },\r\n get: function (key) {\r\n return this[\"s_\" + key];\r\n }\r\n };\r\n\r\n Markdown.Converter = function () {\r\n var pluginHooks = this.hooks = new HookCollection();\r\n \r\n // given a URL that was encountered by itself (without markup), should return the link text that's to be given to this link\r\n pluginHooks.addNoop(\"plainLinkText\");\r\n \r\n // called with the orignal text as given to makeHtml. The result of this plugin hook is the actual markdown source that will be cooked\r\n pluginHooks.addNoop(\"preConversion\");\r\n \r\n // called with the text once all normalizations have been completed (tabs to spaces, line endings, etc.), but before any conversions have\r\n pluginHooks.addNoop(\"postNormalization\");\r\n \r\n // Called with the text before / after creating block elements like code blocks and lists. Note that this is called recursively\r\n // with inner content, e.g. it's called with the full text, and then only with the content of a blockquote. The inner\r\n // call will receive outdented text.\r\n pluginHooks.addNoop(\"preBlockGamut\");\r\n pluginHooks.addNoop(\"postBlockGamut\");\r\n \r\n // called with the text of a single block element before / after the span-level conversions (bold, code spans, etc.) have been made\r\n pluginHooks.addNoop(\"preSpanGamut\");\r\n pluginHooks.addNoop(\"postSpanGamut\");\r\n \r\n // called with the final cooked HTML code. The result of this plugin hook is the actual output of makeHtml\r\n pluginHooks.addNoop(\"postConversion\");\r\n\r\n //\r\n // Private state of the converter instance:\r\n //\r\n\r\n // Global hashes, used by various utility routines\r\n var g_urls;\r\n var g_titles;\r\n var g_html_blocks;\r\n\r\n // Used to track when we're inside an ordered or unordered list\r\n // (see _ProcessListItems() for details):\r\n var g_list_level;\r\n\r\n this.makeHtml = function (text) {\r\n\r\n //\r\n // Main function. The order in which other subs are called here is\r\n // essential. Link and image substitutions need to happen before\r\n // _EscapeSpecialCharsWithinTagAttributes(), so that any *'s or _'s in the \r\n // and tags get encoded.\r\n //\r\n\r\n // This will only happen if makeHtml on the same converter instance is called from a plugin hook.\r\n // Don't do that.\r\n if (g_urls)\r\n throw new Error(\"Recursive call to converter.makeHtml\");\r\n \r\n // Create the private state objects.\r\n g_urls = new SaveHash();\r\n g_titles = new SaveHash();\r\n g_html_blocks = [];\r\n g_list_level = 0;\r\n\r\n text = pluginHooks.preConversion(text);\r\n\r\n // attacklab: Replace ~ with ~T\r\n // This lets us use tilde as an escape char to avoid md5 hashes\r\n // The choice of character is arbitray; anything that isn't\r\n // magic in Markdown will work.\r\n text = text.replace(/~/g, \"~T\");\r\n\r\n // attacklab: Replace $ with ~D\r\n // RegExp interprets $ as a special character\r\n // when it's in a replacement string\r\n text = text.replace(/\\$/g, \"~D\");\r\n\r\n // Standardize line endings\r\n text = text.replace(/\\r\\n/g, \"\\n\"); // DOS to Unix\r\n text = text.replace(/\\r/g, \"\\n\"); // Mac to Unix\r\n\r\n // Make sure text begins and ends with a couple of newlines:\r\n text = \"\\n\\n\" + text + \"\\n\\n\";\r\n\r\n // Convert all tabs to spaces.\r\n text = _Detab(text);\r\n\r\n // Strip any lines consisting only of spaces and tabs.\r\n // This makes subsequent regexen easier to write, because we can\r\n // match consecutive blank lines with /\\n+/ instead of something\r\n // contorted like /[ \\t]*\\n+/ .\r\n text = text.replace(/^[ \\t]+$/mg, \"\");\r\n \r\n text = pluginHooks.postNormalization(text);\r\n\r\n // Turn block-level HTML blocks into hash entries\r\n text = _HashHTMLBlocks(text);\r\n\r\n // Strip link definitions, store in hashes.\r\n text = _StripLinkDefinitions(text);\r\n\r\n text = _RunBlockGamut(text);\r\n\r\n text = _UnescapeSpecialChars(text);\r\n\r\n // attacklab: Restore dollar signs\r\n text = text.replace(/~D/g, \"$$\");\r\n\r\n // attacklab: Restore tildes\r\n text = text.replace(/~T/g, \"~\");\r\n\r\n text = pluginHooks.postConversion(text);\r\n\r\n g_html_blocks = g_titles = g_urls = null;\r\n\r\n return text;\r\n };\r\n\r\n function _StripLinkDefinitions(text) {\r\n //\r\n // Strips link definitions from text, stores the URLs and titles in\r\n // hash references.\r\n //\r\n\r\n // Link defs are in the form: ^[id]: url \"optional title\"\r\n\r\n /*\r\n text = text.replace(/\r\n ^[ ]{0,3}\\[(.+)\\]: // id = $1 attacklab: g_tab_width - 1\r\n [ \\t]*\r\n \\n? // maybe *one* newline\r\n [ \\t]*\r\n ? // url = $2\r\n (?=\\s|$) // lookahead for whitespace instead of the lookbehind removed below\r\n [ \\t]*\r\n \\n? // maybe one newline\r\n [ \\t]*\r\n ( // (potential) title = $3\r\n (\\n*) // any lines skipped = $4 attacklab: lookbehind removed\r\n [ \\t]+\r\n [\"(]\r\n (.+?) // title = $5\r\n [\")]\r\n [ \\t]*\r\n )? // title is optional\r\n (?:\\n+|$)\r\n /gm, function(){...});\r\n */\r\n\r\n text = text.replace(/^[ ]{0,3}\\[(.+)\\]:[ \\t]*\\n?[ \\t]*?(?=\\s|$)[ \\t]*\\n?[ \\t]*((\\n*)[\"(](.+?)[\")][ \\t]*)?(?:\\n+)/gm,\r\n function (wholeMatch, m1, m2, m3, m4, m5) {\r\n m1 = m1.toLowerCase();\r\n g_urls.set(m1, _EncodeAmpsAndAngles(m2)); // Link IDs are case-insensitive\r\n if (m4) {\r\n // Oops, found blank lines, so it's not a title.\r\n // Put back the parenthetical statement we stole.\r\n return m3;\r\n } else if (m5) {\r\n g_titles.set(m1, m5.replace(/\"/g, \""\"));\r\n }\r\n\r\n // Completely remove the definition from the text\r\n return \"\";\r\n }\r\n );\r\n\r\n return text;\r\n }\r\n\r\n function _HashHTMLBlocks(text) {\r\n\r\n // Hashify HTML blocks:\r\n // We only want to do this for block-level HTML tags, such as headers,\r\n // lists, and tables. That's because we still want to wrap

      s around\r\n // \"paragraphs\" that are wrapped in non-block-level tags, such as anchors,\r\n // phrase emphasis, and spans. The list of tags we're looking for is\r\n // hard-coded:\r\n var block_tags_a = \"p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del\"\r\n var block_tags_b = \"p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math\"\r\n\r\n // First, look for nested blocks, e.g.:\r\n //

      \r\n //
      \r\n // tags for inner block must be indented.\r\n //
      \r\n //
      \r\n //\r\n // The outermost tags must start at the left margin for this to match, and\r\n // the inner nested divs must be indented.\r\n // We need to do this before the next, more liberal match, because the next\r\n // match will start at the first `
      ` and stop at the first `
      `.\r\n\r\n // attacklab: This regex can be expensive when it fails.\r\n\r\n /*\r\n text = text.replace(/\r\n ( // save in $1\r\n ^ // start of line (with /m)\r\n <($block_tags_a) // start tag = $2\r\n \\b // word break\r\n // attacklab: hack around khtml/pcre bug...\r\n [^\\r]*?\\n // any number of lines, minimally matching\r\n // the matching end tag\r\n [ \\t]* // trailing spaces/tabs\r\n (?=\\n+) // followed by a newline\r\n ) // attacklab: there are sentinel newlines at end of document\r\n /gm,function(){...}};\r\n */\r\n text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\\b[^\\r]*?\\n<\\/\\2>[ \\t]*(?=\\n+))/gm, hashElement);\r\n\r\n //\r\n // Now match more liberally, simply from `\\n` to `\\n`\r\n //\r\n\r\n /*\r\n text = text.replace(/\r\n ( // save in $1\r\n ^ // start of line (with /m)\r\n <($block_tags_b) // start tag = $2\r\n \\b // word break\r\n // attacklab: hack around khtml/pcre bug...\r\n [^\\r]*? // any number of lines, minimally matching\r\n .* // the matching end tag\r\n [ \\t]* // trailing spaces/tabs\r\n (?=\\n+) // followed by a newline\r\n ) // attacklab: there are sentinel newlines at end of document\r\n /gm,function(){...}};\r\n */\r\n text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\\b[^\\r]*?.*<\\/\\2>[ \\t]*(?=\\n+)\\n)/gm, hashElement);\r\n\r\n // Special case just for
      . It was easier to make a special case than\r\n // to make the other regex more complicated. \r\n\r\n /*\r\n text = text.replace(/\r\n \\n // Starting after a blank line\r\n [ ]{0,3}\r\n ( // save in $1\r\n (<(hr) // start tag = $2\r\n \\b // word break\r\n ([^<>])*?\r\n \\/?>) // the matching end tag\r\n [ \\t]*\r\n (?=\\n{2,}) // followed by a blank line\r\n )\r\n /g,hashElement);\r\n */\r\n text = text.replace(/\\n[ ]{0,3}((<(hr)\\b([^<>])*?\\/?>)[ \\t]*(?=\\n{2,}))/g, hashElement);\r\n\r\n // Special case for standalone HTML comments:\r\n\r\n /*\r\n text = text.replace(/\r\n \\n\\n // Starting after a blank line\r\n [ ]{0,3} // attacklab: g_tab_width - 1\r\n ( // save in $1\r\n -]|-[^>])(?:[^-]|-[^-])*)--) // see http://www.w3.org/TR/html-markup/syntax.html#comments and http://meta.stackoverflow.com/q/95256\r\n >\r\n [ \\t]*\r\n (?=\\n{2,}) // followed by a blank line\r\n )\r\n /g,hashElement);\r\n */\r\n text = text.replace(/\\n\\n[ ]{0,3}(-]|-[^>])(?:[^-]|-[^-])*)--)>[ \\t]*(?=\\n{2,}))/g, hashElement);\r\n\r\n // PHP and ASP-style processor instructions ( and <%...%>)\r\n\r\n /*\r\n text = text.replace(/\r\n (?:\r\n \\n\\n // Starting after a blank line\r\n )\r\n ( // save in $1\r\n [ ]{0,3} // attacklab: g_tab_width - 1\r\n (?:\r\n <([?%]) // $2\r\n [^\\r]*?\r\n \\2>\r\n )\r\n [ \\t]*\r\n (?=\\n{2,}) // followed by a blank line\r\n )\r\n /g,hashElement);\r\n */\r\n text = text.replace(/(?:\\n\\n)([ ]{0,3}(?:<([?%])[^\\r]*?\\2>)[ \\t]*(?=\\n{2,}))/g, hashElement);\r\n\r\n return text;\r\n }\r\n\r\n function hashElement(wholeMatch, m1) {\r\n var blockText = m1;\r\n\r\n // Undo double lines\r\n blockText = blockText.replace(/^\\n+/, \"\");\r\n\r\n // strip trailing blank lines\r\n blockText = blockText.replace(/\\n+$/g, \"\");\r\n\r\n // Replace the element text with a marker (\"~KxK\" where x is its key)\r\n blockText = \"\\n\\n~K\" + (g_html_blocks.push(blockText) - 1) + \"K\\n\\n\";\r\n\r\n return blockText;\r\n }\r\n \r\n var blockGamutHookCallback = function (t) { return _RunBlockGamut(t); }\r\n\r\n function _RunBlockGamut(text, doNotUnhash) {\r\n //\r\n // These are all the transformations that form block-level\r\n // tags like paragraphs, headers, and list items.\r\n //\r\n \r\n text = pluginHooks.preBlockGamut(text, blockGamutHookCallback);\r\n \r\n text = _DoHeaders(text);\r\n\r\n // Do Horizontal Rules:\r\n var replacement = \"
      \\n\";\r\n text = text.replace(/^[ ]{0,2}([ ]?\\*[ ]?){3,}[ \\t]*$/gm, replacement);\r\n text = text.replace(/^[ ]{0,2}([ ]?-[ ]?){3,}[ \\t]*$/gm, replacement);\r\n text = text.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \\t]*$/gm, replacement);\r\n\r\n text = _DoLists(text);\r\n text = _DoCodeBlocks(text);\r\n text = _DoBlockQuotes(text);\r\n \r\n text = pluginHooks.postBlockGamut(text, blockGamutHookCallback);\r\n\r\n // We already ran _HashHTMLBlocks() before, in Markdown(), but that\r\n // was to escape raw HTML in the original Markdown source. This time,\r\n // we're escaping the markup we've just created, so that we don't wrap\r\n //

      tags around block-level tags.\r\n text = _HashHTMLBlocks(text);\r\n text = _FormParagraphs(text, doNotUnhash);\r\n\r\n return text;\r\n }\r\n\r\n function _RunSpanGamut(text) {\r\n //\r\n // These are all the transformations that occur *within* block-level\r\n // tags like paragraphs, headers, and list items.\r\n //\r\n\r\n text = pluginHooks.preSpanGamut(text);\r\n \r\n text = _DoCodeSpans(text);\r\n text = _EscapeSpecialCharsWithinTagAttributes(text);\r\n text = _EncodeBackslashEscapes(text);\r\n\r\n // Process anchor and image tags. Images must come first,\r\n // because ![foo][f] looks like an anchor.\r\n text = _DoImages(text);\r\n text = _DoAnchors(text);\r\n\r\n // Make links out of things like ``\r\n // Must come after _DoAnchors(), because you can use < and >\r\n // delimiters in inline links like [this]().\r\n text = _DoAutoLinks(text);\r\n \r\n text = text.replace(/~P/g, \"://\"); // put in place to prevent autolinking; reset now\r\n \r\n text = _EncodeAmpsAndAngles(text);\r\n text = _DoItalicsAndBold(text);\r\n\r\n // Do hard breaks:\r\n text = text.replace(/ +\\n/g, \"
      \\n\");\r\n \r\n text = pluginHooks.postSpanGamut(text);\r\n\r\n return text;\r\n }\r\n\r\n function _EscapeSpecialCharsWithinTagAttributes(text) {\r\n //\r\n // Within tags -- meaning between < and > -- encode [\\ ` * _] so they\r\n // don't conflict with their use in Markdown for code, italics and strong.\r\n //\r\n\r\n // Build a regex to find HTML tags and comments. See Friedl's \r\n // \"Mastering Regular Expressions\", 2nd Ed., pp. 200-201.\r\n\r\n // SE: changed the comment part of the regex\r\n\r\n var regex = /(<[a-z\\/!$](\"[^\"]*\"|'[^']*'|[^'\">])*>|-]|-[^>])(?:[^-]|-[^-])*)--)>)/gi;\r\n\r\n text = text.replace(regex, function (wholeMatch) {\r\n var tag = wholeMatch.replace(/(.)<\\/?code>(?=.)/g, \"$1`\");\r\n tag = escapeCharacters(tag, wholeMatch.charAt(1) == \"!\" ? \"\\\\`*_/\" : \"\\\\`*_\"); // also escape slashes in comments to prevent autolinking there -- http://meta.stackoverflow.com/questions/95987\r\n return tag;\r\n });\r\n\r\n return text;\r\n }\r\n\r\n function _DoAnchors(text) {\r\n //\r\n // Turn Markdown link shortcuts into XHTML
      tags.\r\n //\r\n //\r\n // First, handle reference-style links: [link text] [id]\r\n //\r\n\r\n /*\r\n text = text.replace(/\r\n ( // wrap whole match in $1\r\n \\[\r\n (\r\n (?:\r\n \\[[^\\]]*\\] // allow brackets nested one level\r\n |\r\n [^\\[] // or anything else\r\n )*\r\n )\r\n \\]\r\n\r\n [ ]? // one optional space\r\n (?:\\n[ ]*)? // one optional newline followed by spaces\r\n\r\n \\[\r\n (.*?) // id = $3\r\n \\]\r\n )\r\n ()()()() // pad remaining backreferences\r\n /g, writeAnchorTag);\r\n */\r\n text = text.replace(/(\\[((?:\\[[^\\]]*\\]|[^\\[\\]])*)\\][ ]?(?:\\n[ ]*)?\\[(.*?)\\])()()()()/g, writeAnchorTag);\r\n\r\n //\r\n // Next, inline-style links: [link text](url \"optional title\")\r\n //\r\n\r\n /*\r\n text = text.replace(/\r\n ( // wrap whole match in $1\r\n \\[\r\n (\r\n (?:\r\n \\[[^\\]]*\\] // allow brackets nested one level\r\n |\r\n [^\\[\\]] // or anything else\r\n )*\r\n )\r\n \\]\r\n \\( // literal paren\r\n [ \\t]*\r\n () // no id, so leave $3 empty\r\n ? \r\n [ \\t]*\r\n ( // $5\r\n (['\"]) // quote char = $6\r\n (.*?) // Title = $7\r\n \\6 // matching quote\r\n [ \\t]* // ignore any spaces/tabs between closing quote and )\r\n )? // title is optional\r\n \\)\r\n )\r\n /g, writeAnchorTag);\r\n */\r\n\r\n text = text.replace(/(\\[((?:\\[[^\\]]*\\]|[^\\[\\]])*)\\]\\([ \\t]*()?[ \\t]*((['\"])(.*?)\\6[ \\t]*)?\\))/g, writeAnchorTag);\r\n\r\n //\r\n // Last, handle reference-style shortcuts: [link text]\r\n // These must come last in case you've also got [link test][1]\r\n // or [link test](/foo)\r\n //\r\n\r\n /*\r\n text = text.replace(/\r\n ( // wrap whole match in $1\r\n \\[\r\n ([^\\[\\]]+) // link text = $2; can't contain '[' or ']'\r\n \\]\r\n )\r\n ()()()()() // pad rest of backreferences\r\n /g, writeAnchorTag);\r\n */\r\n text = text.replace(/(\\[([^\\[\\]]+)\\])()()()()()/g, writeAnchorTag);\r\n\r\n return text;\r\n }\r\n\r\n function writeAnchorTag(wholeMatch, m1, m2, m3, m4, m5, m6, m7) {\r\n if (m7 == undefined) m7 = \"\";\r\n var whole_match = m1;\r\n var link_text = m2.replace(/:\\/\\//g, \"~P\"); // to prevent auto-linking withing the link. will be converted back after the auto-linker runs\r\n var link_id = m3.toLowerCase();\r\n var url = m4;\r\n var title = m7;\r\n\r\n if (url == \"\") {\r\n if (link_id == \"\") {\r\n // lower-case and turn embedded newlines into spaces\r\n link_id = link_text.toLowerCase().replace(/ ?\\n/g, \" \");\r\n }\r\n url = \"#\" + link_id;\r\n\r\n if (g_urls.get(link_id) != undefined) {\r\n url = g_urls.get(link_id);\r\n if (g_titles.get(link_id) != undefined) {\r\n title = g_titles.get(link_id);\r\n }\r\n }\r\n else {\r\n if (whole_match.search(/\\(\\s*\\)$/m) > -1) {\r\n // Special case for explicit empty url\r\n url = \"\";\r\n } else {\r\n return whole_match;\r\n }\r\n }\r\n }\r\n url = encodeProblemUrlChars(url);\r\n url = escapeCharacters(url, \"*_\");\r\n var result = \"\" + link_text + \"\";\r\n\r\n return result;\r\n }\r\n\r\n function _DoImages(text) {\r\n //\r\n // Turn Markdown image shortcuts into tags.\r\n //\r\n\r\n //\r\n // First, handle reference-style labeled images: ![alt text][id]\r\n //\r\n\r\n /*\r\n text = text.replace(/\r\n ( // wrap whole match in $1\r\n !\\[\r\n (.*?) // alt text = $2\r\n \\]\r\n\r\n [ ]? // one optional space\r\n (?:\\n[ ]*)? // one optional newline followed by spaces\r\n\r\n \\[\r\n (.*?) // id = $3\r\n \\]\r\n )\r\n ()()()() // pad rest of backreferences\r\n /g, writeImageTag);\r\n */\r\n text = text.replace(/(!\\[(.*?)\\][ ]?(?:\\n[ ]*)?\\[(.*?)\\])()()()()/g, writeImageTag);\r\n\r\n //\r\n // Next, handle inline images: ![alt text](url \"optional title\")\r\n // Don't forget: encode * and _\r\n\r\n /*\r\n text = text.replace(/\r\n ( // wrap whole match in $1\r\n !\\[\r\n (.*?) // alt text = $2\r\n \\]\r\n \\s? // One optional whitespace character\r\n \\( // literal paren\r\n [ \\t]*\r\n () // no id, so leave $3 empty\r\n ? // src url = $4\r\n [ \\t]*\r\n ( // $5\r\n (['\"]) // quote char = $6\r\n (.*?) // title = $7\r\n \\6 // matching quote\r\n [ \\t]*\r\n )? // title is optional\r\n \\)\r\n )\r\n /g, writeImageTag);\r\n */\r\n text = text.replace(/(!\\[(.*?)\\]\\s?\\([ \\t]*()?[ \\t]*((['\"])(.*?)\\6[ \\t]*)?\\))/g, writeImageTag);\r\n\r\n return text;\r\n }\r\n \r\n function attributeEncode(text) {\r\n // unconditionally replace angle brackets here -- what ends up in an attribute (e.g. alt or title)\r\n // never makes sense to have verbatim HTML in it (and the sanitizer would totally break it)\r\n return text.replace(/>/g, \">\").replace(/\";\r\n\r\n return result;\r\n }\r\n\r\n function _DoHeaders(text) {\r\n\r\n // Setext-style headers:\r\n // Header 1\r\n // ========\r\n // \r\n // Header 2\r\n // --------\r\n //\r\n text = text.replace(/^(.+)[ \\t]*\\n=+[ \\t]*\\n+/gm,\r\n function (wholeMatch, m1) { return \"

      \" + _RunSpanGamut(m1) + \"

      \\n\\n\"; }\r\n );\r\n\r\n text = text.replace(/^(.+)[ \\t]*\\n-+[ \\t]*\\n+/gm,\r\n function (matchFound, m1) { return \"

      \" + _RunSpanGamut(m1) + \"

      \\n\\n\"; }\r\n );\r\n\r\n // atx-style headers:\r\n // # Header 1\r\n // ## Header 2\r\n // ## Header 2 with closing hashes ##\r\n // ...\r\n // ###### Header 6\r\n //\r\n\r\n /*\r\n text = text.replace(/\r\n ^(\\#{1,6}) // $1 = string of #'s\r\n [ \\t]*\r\n (.+?) // $2 = Header text\r\n [ \\t]*\r\n \\#* // optional closing #'s (not counted)\r\n \\n+\r\n /gm, function() {...});\r\n */\r\n\r\n text = text.replace(/^(\\#{1,6})[ \\t]*(.+?)[ \\t]*\\#*\\n+/gm,\r\n function (wholeMatch, m1, m2) {\r\n var h_level = m1.length;\r\n return \"\" + _RunSpanGamut(m2) + \"\\n\\n\";\r\n }\r\n );\r\n\r\n return text;\r\n }\r\n\r\n function _DoLists(text) {\r\n //\r\n // Form HTML ordered (numbered) and unordered (bulleted) lists.\r\n //\r\n\r\n // attacklab: add sentinel to hack around khtml/safari bug:\r\n // http://bugs.webkit.org/show_bug.cgi?id=11231\r\n text += \"~0\";\r\n\r\n // Re-usable pattern to match any entirel ul or ol list:\r\n\r\n /*\r\n var whole_list = /\r\n ( // $1 = whole list\r\n ( // $2\r\n [ ]{0,3} // attacklab: g_tab_width - 1\r\n ([*+-]|\\d+[.]) // $3 = first list item marker\r\n [ \\t]+\r\n )\r\n [^\\r]+?\r\n ( // $4\r\n ~0 // sentinel for workaround; should be $\r\n |\r\n \\n{2,}\r\n (?=\\S)\r\n (?! // Negative lookahead for another list item marker\r\n [ \\t]*\r\n (?:[*+-]|\\d+[.])[ \\t]+\r\n )\r\n )\r\n )\r\n /g\r\n */\r\n var whole_list = /^(([ ]{0,3}([*+-]|\\d+[.])[ \\t]+)[^\\r]+?(~0|\\n{2,}(?=\\S)(?![ \\t]*(?:[*+-]|\\d+[.])[ \\t]+)))/gm;\r\n\r\n if (g_list_level) {\r\n text = text.replace(whole_list, function (wholeMatch, m1, m2) {\r\n var list = m1;\r\n var list_type = (m2.search(/[*+-]/g) > -1) ? \"ul\" : \"ol\";\r\n\r\n var result = _ProcessListItems(list, list_type);\r\n\r\n // Trim any trailing whitespace, to put the closing ``\r\n // up on the preceding line, to get it past the current stupid\r\n // HTML block parser. This is a hack to work around the terrible\r\n // hack that is the HTML block parser.\r\n result = result.replace(/\\s+$/, \"\");\r\n result = \"<\" + list_type + \">\" + result + \"\\n\";\r\n return result;\r\n });\r\n } else {\r\n whole_list = /(\\n\\n|^\\n?)(([ ]{0,3}([*+-]|\\d+[.])[ \\t]+)[^\\r]+?(~0|\\n{2,}(?=\\S)(?![ \\t]*(?:[*+-]|\\d+[.])[ \\t]+)))/g;\r\n text = text.replace(whole_list, function (wholeMatch, m1, m2, m3) {\r\n var runup = m1;\r\n var list = m2;\r\n\r\n var list_type = (m3.search(/[*+-]/g) > -1) ? \"ul\" : \"ol\";\r\n var result = _ProcessListItems(list, list_type);\r\n result = runup + \"<\" + list_type + \">\\n\" + result + \"\\n\";\r\n return result;\r\n });\r\n }\r\n\r\n // attacklab: strip sentinel\r\n text = text.replace(/~0/, \"\");\r\n\r\n return text;\r\n }\r\n\r\n var _listItemMarkers = { ol: \"\\\\d+[.]\", ul: \"[*+-]\" };\r\n\r\n function _ProcessListItems(list_str, list_type) {\r\n //\r\n // Process the contents of a single ordered or unordered list, splitting it\r\n // into individual list items.\r\n //\r\n // list_type is either \"ul\" or \"ol\".\r\n\r\n // The $g_list_level global keeps track of when we're inside a list.\r\n // Each time we enter a list, we increment it; when we leave a list,\r\n // we decrement. If it's zero, we're not in a list anymore.\r\n //\r\n // We do this because when we're not inside a list, we want to treat\r\n // something like this:\r\n //\r\n // I recommend upgrading to version\r\n // 8. Oops, now this line is treated\r\n // as a sub-list.\r\n //\r\n // As a single paragraph, despite the fact that the second line starts\r\n // with a digit-period-space sequence.\r\n //\r\n // Whereas when we're inside a list (or sub-list), that line will be\r\n // treated as the start of a sub-list. What a kludge, huh? This is\r\n // an aspect of Markdown's syntax that's hard to parse perfectly\r\n // without resorting to mind-reading. Perhaps the solution is to\r\n // change the syntax rules such that sub-lists must start with a\r\n // starting cardinal number; e.g. \"1.\" or \"a.\".\r\n\r\n g_list_level++;\r\n\r\n // trim trailing blank lines:\r\n list_str = list_str.replace(/\\n{2,}$/, \"\\n\");\r\n\r\n // attacklab: add sentinel to emulate \\z\r\n list_str += \"~0\";\r\n\r\n // In the original attacklab showdown, list_type was not given to this function, and anything\r\n // that matched /[*+-]|\\d+[.]/ would just create the next
    • , causing this mismatch:\r\n //\r\n // Markdown rendered by WMD rendered by MarkdownSharp\r\n // ------------------------------------------------------------------\r\n // 1. first 1. first 1. first\r\n // 2. second 2. second 2. second\r\n // - third 3. third * third\r\n //\r\n // We changed this to behave identical to MarkdownSharp. This is the constructed RegEx,\r\n // with {MARKER} being one of \\d+[.] or [*+-], depending on list_type:\r\n \r\n /*\r\n list_str = list_str.replace(/\r\n (^[ \\t]*) // leading whitespace = $1\r\n ({MARKER}) [ \\t]+ // list marker = $2\r\n ([^\\r]+? // list item text = $3\r\n (\\n+)\r\n )\r\n (?=\r\n (~0 | \\2 ({MARKER}) [ \\t]+)\r\n )\r\n /gm, function(){...});\r\n */\r\n\r\n var marker = _listItemMarkers[list_type];\r\n var re = new RegExp(\"(^[ \\\\t]*)(\" + marker + \")[ \\\\t]+([^\\\\r]+?(\\\\n+))(?=(~0|\\\\1(\" + marker + \")[ \\\\t]+))\", \"gm\");\r\n var last_item_had_a_double_newline = false;\r\n list_str = list_str.replace(re,\r\n function (wholeMatch, m1, m2, m3) {\r\n var item = m3;\r\n var leading_space = m1;\r\n var ends_with_double_newline = /\\n\\n$/.test(item);\r\n var contains_double_newline = ends_with_double_newline || item.search(/\\n{2,}/) > -1;\r\n\r\n if (contains_double_newline || last_item_had_a_double_newline) {\r\n item = _RunBlockGamut(_Outdent(item), /* doNotUnhash = */true);\r\n }\r\n else {\r\n // Recursion for sub-lists:\r\n item = _DoLists(_Outdent(item));\r\n item = item.replace(/\\n$/, \"\"); // chomp(item)\r\n item = _RunSpanGamut(item);\r\n }\r\n last_item_had_a_double_newline = ends_with_double_newline;\r\n return \"
    • \" + item + \"
    • \\n\";\r\n }\r\n );\r\n\r\n // attacklab: strip sentinel\r\n list_str = list_str.replace(/~0/g, \"\");\r\n\r\n g_list_level--;\r\n return list_str;\r\n }\r\n\r\n function _DoCodeBlocks(text) {\r\n //\r\n // Process Markdown `
      ` blocks.\r\n            //  \r\n\r\n            /*\r\n            text = text.replace(/\r\n                (?:\\n\\n|^)\r\n                (                               // $1 = the code block -- one or more lines, starting with a space/tab\r\n                    (?:\r\n                        (?:[ ]{4}|\\t)           // Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width\r\n                        .*\\n+\r\n                    )+\r\n                )\r\n                (\\n*[ ]{0,3}[^ \\t\\n]|(?=~0))    // attacklab: g_tab_width\r\n            /g ,function(){...});\r\n            */\r\n\r\n            // attacklab: sentinel workarounds for lack of \\A and \\Z, safari\\khtml bug\r\n            text += \"~0\";\r\n\r\n            text = text.replace(/(?:\\n\\n|^)((?:(?:[ ]{4}|\\t).*\\n+)+)(\\n*[ ]{0,3}[^ \\t\\n]|(?=~0))/g,\r\n                function (wholeMatch, m1, m2) {\r\n                    var codeblock = m1;\r\n                    var nextChar = m2;\r\n\r\n                    codeblock = _EncodeCode(_Outdent(codeblock));\r\n                    codeblock = _Detab(codeblock);\r\n                    codeblock = codeblock.replace(/^\\n+/g, \"\"); // trim leading newlines\r\n                    codeblock = codeblock.replace(/\\n+$/g, \"\"); // trim trailing whitespace\r\n\r\n                    codeblock = \"
      \" + codeblock + \"\\n
      \";\r\n\r\n return \"\\n\\n\" + codeblock + \"\\n\\n\" + nextChar;\r\n }\r\n );\r\n\r\n // attacklab: strip sentinel\r\n text = text.replace(/~0/, \"\");\r\n\r\n return text;\r\n }\r\n\r\n function hashBlock(text) {\r\n text = text.replace(/(^\\n+|\\n+$)/g, \"\");\r\n return \"\\n\\n~K\" + (g_html_blocks.push(text) - 1) + \"K\\n\\n\";\r\n }\r\n\r\n function _DoCodeSpans(text) {\r\n //\r\n // * Backtick quotes are used for spans.\r\n // \r\n // * You can use multiple backticks as the delimiters if you want to\r\n // include literal backticks in the code span. So, this input:\r\n // \r\n // Just type ``foo `bar` baz`` at the prompt.\r\n // \r\n // Will translate to:\r\n // \r\n //

      Just type foo `bar` baz at the prompt.

      \r\n // \r\n // There's no arbitrary limit to the number of backticks you\r\n // can use as delimters. If you need three consecutive backticks\r\n // in your code, use four for delimiters, etc.\r\n //\r\n // * You can use spaces to get literal backticks at the edges:\r\n // \r\n // ... type `` `bar` `` ...\r\n // \r\n // Turns to:\r\n // \r\n // ... type `bar` ...\r\n //\r\n\r\n /*\r\n text = text.replace(/\r\n (^|[^\\\\]) // Character before opening ` can't be a backslash\r\n (`+) // $2 = Opening run of `\r\n ( // $3 = The code block\r\n [^\\r]*?\r\n [^`] // attacklab: work around lack of lookbehind\r\n )\r\n \\2 // Matching closer\r\n (?!`)\r\n /gm, function(){...});\r\n */\r\n\r\n text = text.replace(/(^|[^\\\\])(`+)([^\\r]*?[^`])\\2(?!`)/gm,\r\n function (wholeMatch, m1, m2, m3, m4) {\r\n var c = m3;\r\n c = c.replace(/^([ \\t]*)/g, \"\"); // leading whitespace\r\n c = c.replace(/[ \\t]*$/g, \"\"); // trailing whitespace\r\n c = _EncodeCode(c);\r\n c = c.replace(/:\\/\\//g, \"~P\"); // to prevent auto-linking. Not necessary in code *blocks*, but in code spans. Will be converted back after the auto-linker runs.\r\n return m1 + \"\" + c + \"\";\r\n }\r\n );\r\n\r\n return text;\r\n }\r\n\r\n function _EncodeCode(text) {\r\n //\r\n // Encode/escape certain characters inside Markdown code runs.\r\n // The point is that in code, these characters are literals,\r\n // and lose their special Markdown meanings.\r\n //\r\n // Encode all ampersands; HTML entities are not\r\n // entities within a Markdown code span.\r\n text = text.replace(/&/g, \"&\");\r\n\r\n // Do the angle bracket song and dance:\r\n text = text.replace(//g, \">\");\r\n\r\n // Now, escape characters that are magic in Markdown:\r\n text = escapeCharacters(text, \"\\*_{}[]\\\\\", false);\r\n\r\n // jj the line above breaks this:\r\n //---\r\n\r\n //* Item\r\n\r\n // 1. Subitem\r\n\r\n // special char: *\r\n //---\r\n\r\n return text;\r\n }\r\n\r\n function _DoItalicsAndBold(text) {\r\n\r\n // must go first:\r\n text = text.replace(/([\\W_]|^)(\\*\\*|__)(?=\\S)([^\\r]*?\\S[\\*_]*)\\2([\\W_]|$)/g,\r\n \"$1$3$4\");\r\n\r\n text = text.replace(/([\\W_]|^)(\\*|_)(?=\\S)([^\\r\\*_]*?\\S)\\2([\\W_]|$)/g,\r\n \"$1$3$4\");\r\n\r\n return text;\r\n }\r\n\r\n function _DoBlockQuotes(text) {\r\n\r\n /*\r\n text = text.replace(/\r\n ( // Wrap whole match in $1\r\n (\r\n ^[ \\t]*>[ \\t]? // '>' at the start of a line\r\n .+\\n // rest of the first line\r\n (.+\\n)* // subsequent consecutive lines\r\n \\n* // blanks\r\n )+\r\n )\r\n /gm, function(){...});\r\n */\r\n\r\n text = text.replace(/((^[ \\t]*>[ \\t]?.+\\n(.+\\n)*\\n*)+)/gm,\r\n function (wholeMatch, m1) {\r\n var bq = m1;\r\n\r\n // attacklab: hack around Konqueror 3.5.4 bug:\r\n // \"----------bug\".replace(/^-/g,\"\") == \"bug\"\r\n\r\n bq = bq.replace(/^[ \\t]*>[ \\t]?/gm, \"~0\"); // trim one level of quoting\r\n\r\n // attacklab: clean up hack\r\n bq = bq.replace(/~0/g, \"\");\r\n\r\n bq = bq.replace(/^[ \\t]+$/gm, \"\"); // trim whitespace-only lines\r\n bq = _RunBlockGamut(bq); // recurse\r\n\r\n bq = bq.replace(/(^|\\n)/g, \"$1 \");\r\n // These leading spaces screw with
       content, so we need to fix that:\r\n                    bq = bq.replace(\r\n                            /(\\s*
      [^\\r]+?<\\/pre>)/gm,\r\n                        function (wholeMatch, m1) {\r\n                            var pre = m1;\r\n                            // attacklab: hack around Konqueror 3.5.4 bug:\r\n                            pre = pre.replace(/^  /mg, \"~0\");\r\n                            pre = pre.replace(/~0/g, \"\");\r\n                            return pre;\r\n                        });\r\n\r\n                    return hashBlock(\"
      \\n\" + bq + \"\\n
      \");\r\n }\r\n );\r\n return text;\r\n }\r\n\r\n function _FormParagraphs(text, doNotUnhash) {\r\n //\r\n // Params:\r\n // $text - string to process with html

      tags\r\n //\r\n\r\n // Strip leading and trailing lines:\r\n text = text.replace(/^\\n+/g, \"\");\r\n text = text.replace(/\\n+$/g, \"\");\r\n\r\n var grafs = text.split(/\\n{2,}/g);\r\n var grafsOut = [];\r\n \r\n var markerRe = /~K(\\d+)K/;\r\n\r\n //\r\n // Wrap

      tags.\r\n //\r\n var end = grafs.length;\r\n for (var i = 0; i < end; i++) {\r\n var str = grafs[i];\r\n\r\n // if this is an HTML marker, copy it\r\n if (markerRe.test(str)) {\r\n grafsOut.push(str);\r\n }\r\n else if (/\\S/.test(str)) {\r\n str = _RunSpanGamut(str);\r\n str = str.replace(/^([ \\t]*)/g, \"

      \");\r\n str += \"

      \"\r\n grafsOut.push(str);\r\n }\r\n\r\n }\r\n //\r\n // Unhashify HTML blocks\r\n //\r\n if (!doNotUnhash) {\r\n end = grafsOut.length;\r\n for (var i = 0; i < end; i++) {\r\n var foundAny = true;\r\n while (foundAny) { // we may need several runs, since the data may be nested\r\n foundAny = false;\r\n grafsOut[i] = grafsOut[i].replace(/~K(\\d+)K/g, function (wholeMatch, id) {\r\n foundAny = true;\r\n return g_html_blocks[id];\r\n });\r\n }\r\n }\r\n }\r\n return grafsOut.join(\"\\n\\n\");\r\n }\r\n\r\n function _EncodeAmpsAndAngles(text) {\r\n // Smart processing for ampersands and angle brackets that need to be encoded.\r\n\r\n // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:\r\n // http://bumppo.net/projects/amputator/\r\n text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\\w+);)/g, \"&\");\r\n\r\n // Encode naked <'s\r\n text = text.replace(/<(?![a-z\\/?!]|~D)/gi, \"<\");\r\n\r\n return text;\r\n }\r\n\r\n function _EncodeBackslashEscapes(text) {\r\n //\r\n // Parameter: String.\r\n // Returns: The string, with after processing the following backslash\r\n // escape sequences.\r\n //\r\n\r\n // attacklab: The polite way to do this is with the new\r\n // escapeCharacters() function:\r\n //\r\n // text = escapeCharacters(text,\"\\\\\",true);\r\n // text = escapeCharacters(text,\"`*_{}[]()>#+-.!\",true);\r\n //\r\n // ...but we're sidestepping its use of the (slow) RegExp constructor\r\n // as an optimization for Firefox. This function gets called a LOT.\r\n\r\n text = text.replace(/\\\\(\\\\)/g, escapeCharacters_callback);\r\n text = text.replace(/\\\\([`*_{}\\[\\]()>#+-.!])/g, escapeCharacters_callback);\r\n return text;\r\n }\r\n \r\n function handleTrailingParens(wholeMatch, lookbehind, protocol, link) {\r\n if (lookbehind)\r\n return wholeMatch;\r\n if (link.charAt(link.length - 1) !== \")\")\r\n return \"<\" + protocol + link + \">\";\r\n var parens = link.match(/[()]/g);\r\n var level = 0;\r\n for (var i = 0; i < parens.length; i++) {\r\n if (parens[i] === \"(\") {\r\n if (level <= 0)\r\n level = 1;\r\n else\r\n level++;\r\n }\r\n else {\r\n level--;\r\n }\r\n }\r\n var tail = \"\";\r\n if (level < 0) {\r\n var re = new RegExp(\"\\\\){1,\" + (-level) + \"}$\");\r\n link = link.replace(re, function (trailingParens) {\r\n tail = trailingParens;\r\n return \"\";\r\n });\r\n }\r\n \r\n return \"<\" + protocol + link + \">\" + tail;\r\n }\r\n\r\n function _DoAutoLinks(text) {\r\n\r\n // note that at this point, all other URL in the text are already hyperlinked as \r\n // *except* for the case\r\n\r\n // automatically add < and > around unadorned raw hyperlinks\r\n // must be preceded by a non-word character (and not by =\" or <) and followed by non-word/EOF character\r\n // simulating the lookbehind in a consuming way is okay here, since a URL can neither and with a \" nor\r\n // with a <, so there is no risk of overlapping matches.\r\n text = text.replace(/(=\"|<)?\\b(https?|ftp)(:\\/\\/[-A-Z0-9+&@#\\/%?=~_|\\[\\]\\(\\)!:,\\.;]*[-A-Z0-9+&@#\\/%=~_|\\[\\])])(?=$|\\W)/gi, handleTrailingParens);\r\n\r\n // autolink anything like \r\n \r\n var replacer = function (wholematch, m1) { return \"\" + pluginHooks.plainLinkText(m1) + \"\"; }\r\n text = text.replace(/<((https?|ftp):[^'\">\\s]+)>/gi, replacer);\r\n\r\n // Email addresses: \r\n /*\r\n text = text.replace(/\r\n <\r\n (?:mailto:)?\r\n (\r\n [-.\\w]+\r\n \\@\r\n [-a-z0-9]+(\\.[-a-z0-9]+)*\\.[a-z]+\r\n )\r\n >\r\n /gi, _DoAutoLinks_callback());\r\n */\r\n\r\n /* disabling email autolinking, since we don't do that on the server, either\r\n text = text.replace(/<(?:mailto:)?([-.\\w]+\\@[-a-z0-9]+(\\.[-a-z0-9]+)*\\.[a-z]+)>/gi,\r\n function(wholeMatch,m1) {\r\n return _EncodeEmailAddress( _UnescapeSpecialChars(m1) );\r\n }\r\n );\r\n */\r\n return text;\r\n }\r\n\r\n function _UnescapeSpecialChars(text) {\r\n //\r\n // Swap back in all the special characters we've hidden.\r\n //\r\n text = text.replace(/~E(\\d+)E/g,\r\n function (wholeMatch, m1) {\r\n var charCodeToReplace = parseInt(m1);\r\n return String.fromCharCode(charCodeToReplace);\r\n }\r\n );\r\n return text;\r\n }\r\n\r\n function _Outdent(text) {\r\n //\r\n // Remove one level of line-leading tabs or spaces\r\n //\r\n\r\n // attacklab: hack around Konqueror 3.5.4 bug:\r\n // \"----------bug\".replace(/^-/g,\"\") == \"bug\"\r\n\r\n text = text.replace(/^(\\t|[ ]{1,4})/gm, \"~0\"); // attacklab: g_tab_width\r\n\r\n // attacklab: clean up hack\r\n text = text.replace(/~0/g, \"\")\r\n\r\n return text;\r\n }\r\n\r\n function _Detab(text) {\r\n if (!/\\t/.test(text))\r\n return text;\r\n\r\n var spaces = [\" \", \" \", \" \", \" \"],\r\n skew = 0,\r\n v;\r\n\r\n return text.replace(/[\\n\\t]/g, function (match, offset) {\r\n if (match === \"\\n\") {\r\n skew = offset + 1;\r\n return match;\r\n }\r\n v = (offset - skew) % 4;\r\n skew = offset + 1;\r\n return spaces[v];\r\n });\r\n }\r\n\r\n //\r\n // attacklab: Utility functions\r\n //\r\n\r\n var _problemUrlChars = /(?:[\"'*()[\\]:]|~D)/g;\r\n\r\n // hex-encodes some unusual \"problem\" chars in URLs to avoid URL detection problems \r\n function encodeProblemUrlChars(url) {\r\n if (!url)\r\n return \"\";\r\n\r\n var len = url.length;\r\n\r\n return url.replace(_problemUrlChars, function (match, offset) {\r\n if (match == \"~D\") // escape for dollar\r\n return \"%24\";\r\n if (match == \":\") {\r\n if (offset == len - 1 || /[0-9\\/]/.test(url.charAt(offset + 1)))\r\n return \":\"\r\n }\r\n return \"%\" + match.charCodeAt(0).toString(16);\r\n });\r\n }\r\n\r\n\r\n function escapeCharacters(text, charsToEscape, afterBackslash) {\r\n // First we have to escape the escape characters so that\r\n // we can build a character class out of them\r\n var regexString = \"([\" + charsToEscape.replace(/([\\[\\]\\\\])/g, \"\\\\$1\") + \"])\";\r\n\r\n if (afterBackslash) {\r\n regexString = \"\\\\\\\\\" + regexString;\r\n }\r\n\r\n var regex = new RegExp(regexString, \"g\");\r\n text = text.replace(regex, escapeCharacters_callback);\r\n\r\n return text;\r\n }\r\n\r\n\r\n function escapeCharacters_callback(wholeMatch, m1) {\r\n var charCodeToEscape = m1.charCodeAt(0);\r\n return \"~E\" + charCodeToEscape + \"E\";\r\n }\r\n\r\n }; // end of the Markdown.Converter constructor\r\n\r\n})();\r\n","(function () {\n var output, Converter;\n if (typeof exports === \"object\" && typeof require === \"function\") { // we're in a CommonJS (e.g. Node.js) module\n output = exports;\n Converter = require(\"./Markdown.Converter\").Converter;\n } else {\n output = window.Markdown;\n Converter = output.Converter;\n }\n \n output.getSanitizingConverter = function () {\n var converter = new Converter();\n converter.hooks.chain(\"postConversion\", sanitizeHtml);\n converter.hooks.chain(\"postConversion\", balanceTags);\n return converter;\n }\n\n function sanitizeHtml(html) {\n return html.replace(/<[^>]*>?/gi, sanitizeTag);\n }\n\n // (tags that can be opened/closed) | (tags that stand alone)\n var basic_tag_whitelist = /^(<\\/?(b|blockquote|code|del|dd|dl|dt|em|h1|h2|h3|i|kbd|li|ol|p|pre|s|sup|sub|strong|strike|ul)>|<(br|hr)\\s?\\/?>)$/i;\n // |\n var a_white = /^(]+\")?\\s?>|<\\/a>)$/i;\n\n // ]*\")?(\\stitle=\"[^\"<>]*\")?\\s?\\/?>)$/i;\n\n function sanitizeTag(tag) {\n if (tag.match(basic_tag_whitelist) || tag.match(a_white) || tag.match(img_white))\n return tag;\n else\n return \"\";\n }\n\n /// \n /// attempt to balance HTML tags in the html string\n /// by removing any unmatched opening or closing tags\n /// IMPORTANT: we *assume* HTML has *already* been \n /// sanitized and is safe/sane before balancing!\n /// \n /// adapted from CODESNIPPET: A8591DBA-D1D3-11DE-947C-BA5556D89593\n /// \n function balanceTags(html) {\n\n if (html == \"\")\n return \"\";\n\n var re = /<\\/?\\w+[^>]*(\\s|$|>)/g;\n // convert everything to lower case; this makes\n // our case insensitive comparisons easier\n var tags = html.toLowerCase().match(re);\n\n // no HTML tags present? nothing to do; exit now\n var tagcount = (tags || []).length;\n if (tagcount == 0)\n return html;\n\n var tagname, tag;\n var ignoredtags = \"



    • \";\n var match;\n var tagpaired = [];\n var tagremove = [];\n var needsRemoval = false;\n\n // loop through matched tags in forward order\n for (var ctag = 0; ctag < tagcount; ctag++) {\n tagname = tags[ctag].replace(/<\\/?(\\w+).*/, \"$1\");\n // skip any already paired tags\n // and skip tags in our ignore list; assume they're self-closed\n if (tagpaired[ctag] || ignoredtags.search(\"<\" + tagname + \">\") > -1)\n continue;\n\n tag = tags[ctag];\n match = -1;\n\n if (!/^<\\//.test(tag)) {\n // this is an opening tag\n // search forwards (next tags), look for closing tags\n for (var ntag = ctag + 1; ntag < tagcount; ntag++) {\n if (!tagpaired[ntag] && tags[ntag] == \"\") {\n match = ntag;\n break;\n }\n }\n }\n\n if (match == -1)\n needsRemoval = tagremove[ctag] = true; // mark for removal\n else\n tagpaired[match] = true; // mark paired\n }\n\n if (!needsRemoval)\n return html;\n\n // delete all orphaned tags from the string\n\n var ctag = 0;\n html = html.replace(re, function (match) {\n var res = tagremove[ctag] ? \"\" : match;\n ctag++;\n return res;\n });\n return html;\n }\n})();\n","exports.Converter = require(\"./Markdown.Converter\").Converter;\nexports.getSanitizingConverter = require(\"./Markdown.Sanitizer\").getSanitizingConverter;\n"],"names":["util","position","ui","doc","window","document","re","RegExp","nav","navigator","SETTINGS","uaSniffed","isIE","test","userAgent","toLowerCase","isIE_5or6","isOpera","defaultsStrings","bold","boldexample","italic","italicexample","link","linkdescription","linkdialog","quote","quoteexample","code","codeexample","image","imagedescription","imagedialog","olist","ulist","litem","heading","headingexample","hr","undo","redo","redomac","help","Chunks","PanelCollection","postfix","this","buttonBar","getElementById","preview","input","UndoManager","callback","panels","lastState","timer","inputStateObj","undoObj","undoStack","stackPtr","mode","setMode","newMode","noSave","saveState","setTimeout","refreshState","isInitialState","TextareaState","undefined","setCommandMode","canUndo","canRedo","restore","focus","currState","text","handleCtrlYZ","event","handled","ctrlKey","metaKey","altKey","keyCode","charCode","String","fromCharCode","shiftKey","preventDefault","returnValue","handleModeChange","addEvent","handlePaste","value","onpaste","ondrop","setEventHandlers","stateObj","inputArea","init","isVisible","activeElement","setInputAreaSelectionStartEnd","scrollTop","selectionStart","setInputAreaSelection","selection","range","createTextRange","moveStart","length","moveEnd","end","start","select","selectionEnd","ieCachedRange","fixEolChars","createRange","fixedRange","marker","markedRange","inputText","indexOf","lastIndexOf","len","ieCachedScrollTop","getChunks","chunk","before","substring","startTag","endTag","after","setChunks","PreviewManager","converter","previewRefreshCallback","timeout","elapsedTime","oldInputText","getDocScrollTop","result","innerHeight","pageYOffset","documentElement","body","makePreviewHtml","prevTime","Date","getTime","makeHtml","currTime","pushPreviewHtml","applyTimeout","clearTimeout","delay","refresh","requiresRefresh","processingTime","previewSetter","inputElem","listener","isFirstTimeFilled","ieSafePreviewSet","parent","parentNode","sibling","nextSibling","removeChild","innerHTML","insertBefore","appendChild","nonSuckyBrowserPreviewSet","panel","emptyTop","getTop","e","previewSet","scrollHeight","clientHeight","fullTop","scrollBy","UIManager","undoManager","previewManager","commandManager","helpOptions","getString","inputBox","buttons","buttonRow","createElement","id","className","xPosition","makeButton","title","XShift","textOp","button","style","left","buttonImage","setupButton","makeSpacer","num","spacer","bindCommand","postProcessing","doLinkOrImage","doList","execute","manager","redoTitle","platform","helpButton","helpButtonImage","isHelp","right","onclick","handler","setUndoRedoButtonStates","makeSpritedButtonRow","keyEvent","doClick","state","chunks","fixupInputArea","isEnabled","getElementsByTagName","backgroundPosition","onmouseover","onmouseout","onmousedown","method","apply","arguments","key","fakeButton","CommandManager","pluginHooks","hooks","Markdown","Editor","markdownConverter","idPostfix","options","strings","identifier","HookCollection","addNoop","addFalse","getConverter","that","run","uiManager","onPreviewRefresh","location","href","textOperation","f","refreshPreview","prototype","findTags","startRegex","endRegex","regex","chunkObj","extendRegExp","replace","match","trimWhitespace","remove","beforeReplacer","afterReplacer","s","skipLines","nLinesBefore","nLinesAfter","findExtraNewlines","regexText","replacementText","$1","elem","getComputedStyle","getPropertyValue","currentStyle","attachEvent","addEventListener","removeEvent","detachEvent","removeEventListener","pre","post","flags","pattern","toString","wholeMatch","flagsPart","isInner","offsetTop","offsetParent","getHeight","offsetHeight","getWidth","offsetWidth","scrollWidth","getPageSize","innerWidth","self","scrollMaxY","clientWidth","Math","max","createBackground","background","top","zIndex","filter","opacity","pageSize","height","scrollLeft","width","prompt","defaultInputText","dialog","checkEscape","stopPropagation","close","isCancel","padding","question","form","onsubmit","margin","cssFloat","textAlign","type","display","marginLeft","marginRight","okButton","cancelButton","marginTop","createDialog","defTextLen","collapse","commandProto","prefixes","unwrap","txt","wrap","line","marked","doBold","doBorI","doItalic","nStars","insertText","starsBefore","exec","starsAfter","prevStars","min","whitespace","markup","stripLinkDefs","defsToAdd","totalMatch","newlines","addLinkDef","linkDef","refNumber","defs","complete","rendered","testlink","fakedefs","skippedChars","uniquified","uniquify","inner","afterInner","offset","addDefNumber","def","getLink","okayToModify","refOut","isImage","linkEnteredCallback","substr","wholematch","inQueryString","charAt","toUpperCase","encodeURI","trim","insertLinkDialog","insertImageDialog","doAutoindent","commandMgr","fakeSelection","doBlockquote","doCode","newlinesBefore","newlinesAfter","blankLine","leftOver","lines","split","inChain","i","good","replaceBlanksInTags","useBracket","replacement","markdown","postBlockquoteCreation","blanks","hasTextBefore","nLinesBack","nLinesForward","isNumberedList","nextItemsRegex","bullet","getItemPrefix","prefix","getPrefixedItem","itemText","_","hasDigits","nLinesUp","nLinesDown","spaces","doHeading","headerLevel","lastMatch","headerLevelToCreate","headerChar","doHorizontalRule","pagedown","g","identity","x","returnFalse","chain","hookname","func","original","Error","set","exports","SaveHash","args","Array","slice","call","get","Converter","g_urls","g_titles","g_html_blocks","g_list_level","_HashHTMLBlocks","hashElement","m1","blockText","push","_Detab","preConversion","charCodeToReplace","parseInt","_UnescapeSpecialChars","_RunBlockGamut","m2","m3","m4","m5","_EncodeAmpsAndAngles","_StripLinkDefinitions","postNormalization","postConversion","blockGamutHookCallback","t","doNotUnhash","bq","hashBlock","_DoBlockQuotes","codeblock","nextChar","_EncodeCode","_Outdent","_DoCodeBlocks","_DoLists","_RunSpanGamut","matchFound","h_level","_DoHeaders","preBlockGamut","grafs","grafsOut","markerRe","str","foundAny","join","_FormParagraphs","postBlockGamut","_DoItalicsAndBold","handleTrailingParens","replacer","plainLinkText","_DoAutoLinks","writeAnchorTag","_DoAnchors","writeImageTag","_DoImages","escapeCharacters_callback","_EncodeBackslashEscapes","tag","escapeCharacters","_EscapeSpecialCharsWithinTagAttributes","c","_DoCodeSpans","preSpanGamut","postSpanGamut","m6","m7","whole_match","link_text","link_id","url","search","_problemUrlChars","charCodeAt","encodeProblemUrlChars","attributeEncode","alt_text","whole_list","list","list_type","_ProcessListItems","runup","_listItemMarkers","ol","ul","list_str","last_item_had_a_double_newline","item","ends_with_double_newline","contains_double_newline","lookbehind","protocol","parens","level","tail","trailingParens","v","skew","charsToEscape","afterBackslash","regexString","output","sanitizeHtml","html","sanitizeTag","getSanitizingConverter","balanceTags","basic_tag_whitelist","a_white","img_white","tagname","tags","tagcount","tagpaired","tagremove","needsRemoval","ctag","ntag","res"],"sourceRoot":""}