{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///node_modules/pagedown/Markdown.Converter.js","webpack:///indico/web/client/js/jquery/markdown.js","webpack:///node_modules/pagedown-editor/node-editor.js","webpack:///node_modules/pagedown/node-pagedown.js","webpack:///node_modules/pagedown/Markdown.Sanitizer.js","webpack:///node_modules/pagedown-editor/Markdown.Editor.js"],"names":["webpackJsonpCallback","data","moduleId","chunkId","chunkIds","moreModules","executeModules","i","resolves","length","Object","prototype","hasOwnProperty","call","installedChunks","push","modules","parentJsonpFunction","shift","deferredModules","apply","checkDeferredModules","result","deferredModule","fulfilled","j","depId","splice","__webpack_require__","s","installedModules","142","exports","module","l","e","Promise","resolve","m","c","d","name","getter","o","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","p","jsonpArray","window","oldJsonpFunction","slice","Markdown","identity","x","returnFalse","HookCollection","SaveHash","chain","hookname","func","original","this","Error","text","args","Array","arguments","set","addNoop","addFalse","Converter","g_urls","g_titles","g_html_blocks","g_list_level","pluginHooks","hooks","_HashHTMLBlocks","replace","hashElement","wholeMatch","m1","blockText","makeHtml","_Detab","preConversion","charCodeToReplace","parseInt","String","fromCharCode","_UnescapeSpecialChars","_RunBlockGamut","m2","m3","m4","m5","toLowerCase","_EncodeAmpsAndAngles","_StripLinkDefinitions","postNormalization","postConversion","blockGamutHookCallback","doNotUnhash","replacement","bq","hashBlock","pre","_DoBlockQuotes","codeblock","nextChar","_EncodeCode","_Outdent","_DoCodeBlocks","_DoLists","_RunSpanGamut","matchFound","h_level","_DoHeaders","preBlockGamut","grafs","split","grafsOut","markerRe","end","str","test","foundAny","id","join","_FormParagraphs","postBlockGamut","_DoItalicsAndBold","handleTrailingParens","replacer","wholematch","plainLinkText","_DoAutoLinks","writeAnchorTag","_DoAnchors","writeImageTag","_DoImages","escapeCharacters_callback","_EncodeBackslashEscapes","regex","tag","escapeCharacters","charAt","_EscapeSpecialCharsWithinTagAttributes","_DoCodeSpans","preSpanGamut","postSpanGamut","m6","m7","undefined","whole_match","link_text","link_id","url","title","search","len","_problemUrlChars","match","offset","charCodeAt","toString","encodeProblemUrlChars","attributeEncode","alt_text","whole_list","list","list_type","_ProcessListItems","runup","_listItemMarkers","ol","ul","list_str","marker","re","RegExp","last_item_had_a_double_newline","item","ends_with_double_newline","contains_double_newline","lookbehind","protocol","link","parens","level","tail","trailingParens","v","spaces","skew","charsToEscape","afterBackslash","regexString","global","pagedown","getPagedownEditor","Editor","getSanitizingConverter","output","sanitizeHtml","html","sanitizeTag","converter","balanceTags","basic_tag_whitelist","a_white","img_white","tagname","tags","tagcount","tagpaired","tagremove","needsRemoval","ctag","ntag","res","util","position","ui","doc","document","nav","navigator","SETTINGS","uaSniffed","userAgent","defaultsStrings","bold","boldexample","italic","italicexample","linkdescription","linkdialog","quote","quoteexample","code","codeexample","image","imagedescription","imagedialog","olist","ulist","litem","heading","headingexample","hr","undo","redo","redomac","help","Chunks","PanelCollection","postfix","buttonBar","getElementById","preview","input","UndoManager","callback","panels","lastState","timer","inputStateObj","undoObj","undoStack","stackPtr","setMode","newMode","noSave","saveState","setTimeout","refreshState","isInitialState","TextareaState","setCommandMode","canUndo","canRedo","restore","focus","currState","handleCtrlYZ","event","handled","ctrlKey","metaKey","altKey","keyCode","charCode","shiftKey","preventDefault","returnValue","handleModeChange","addEvent","handlePaste","onpaste","ondrop","setEventHandlers","stateObj","inputArea","init","isVisible","activeElement","setInputAreaSelectionStartEnd","scrollTop","selectionStart","setInputAreaSelection","selection","range","createTextRange","moveStart","moveEnd","start","select","selectionEnd","ieCachedRange","fixEolChars","createRange","fixedRange","markedRange","inputText","indexOf","lastIndexOf","ieCachedScrollTop","getChunks","chunk","before","substring","startTag","endTag","after","setChunks","PreviewManager","previewRefreshCallback","timeout","elapsedTime","oldInputText","getDocScrollTop","innerHeight","pageYOffset","documentElement","body","makePreviewHtml","prevTime","Date","getTime","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","previewSet","scrollHeight","clientHeight","fullTop","scrollBy","UIManager","undoManager","previewManager","commandManager","helpOptions","getString","inputBox","buttons","buttonRow","createElement","className","xPosition","makeButton","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","fakeButton","CommandManager","markdownConverter","idPostfix","options","strings","identifier","getConverter","that","run","uiManager","onPreviewRefresh","location","href","textOperation","f","refreshPreview","findTags","startRegex","endRegex","chunkObj","extendRegExp","trimWhitespace","remove","beforeReplacer","afterReplacer","skipLines","nLinesBefore","nLinesAfter","findExtraNewlines","regexText","replacementText","$1","elem","getComputedStyle","getPropertyValue","currentStyle","attachEvent","addEventListener","removeEvent","detachEvent","removeEventListener","post","flags","pattern","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","addDefNumber","def","getLink","okayToModify","refOut","isImage","linkEnteredCallback","substr","inQueryString","toUpperCase","encodeURI","trim","insertLinkDialog","insertImageDialog","doAutoindent","commandMgr","fakeSelection","doBlockquote","doCode","newlinesBefore","newlinesAfter","blankLine","leftOver","lines","inChain","good","replaceBlanksInTags","useBracket","markdown","postBlockquoteCreation","blanks","hasTextBefore","nLinesBack","nLinesForward","isNumberedList","nextItemsRegex","bullet","getItemPrefix","prefix","getPrefixedItem","itemText","_","hasDigits","nLinesUp","nLinesDown","doHeading","headerLevel","lastMatch","headerLevelToCreate","headerChar","doHorizontalRule"],"mappings":"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","file":"js/markdown.224ecfd2.bundle.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tfunction webpackJsonpCallback(data) {\n \t\tvar chunkIds = data[0];\n \t\tvar moreModules = data[1];\n \t\tvar executeModules = data[2];\n\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(data);\n\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n\n \t\t// add entry modules from loaded chunk to deferred list\n \t\tdeferredModules.push.apply(deferredModules, executeModules || []);\n\n \t\t// run deferred modules when all chunks ready\n \t\treturn checkDeferredModules();\n \t};\n \tfunction checkDeferredModules() {\n \t\tvar result;\n \t\tfor(var i = 0; i < deferredModules.length; i++) {\n \t\t\tvar deferredModule = deferredModules[i];\n \t\t\tvar fulfilled = true;\n \t\t\tfor(var j = 1; j < deferredModule.length; j++) {\n \t\t\t\tvar depId = deferredModule[j];\n \t\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n \t\t\t}\n \t\t\tif(fulfilled) {\n \t\t\t\tdeferredModules.splice(i--, 1);\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n \t\t\t}\n \t\t}\n\n \t\treturn result;\n \t}\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// undefined = chunk not loaded, null = chunk preloaded/prefetched\n \t// Promise = chunk loading, 0 = chunk loaded\n \tvar installedChunks = {\n \t\t142: 0\n \t};\n\n \tvar deferredModules = [];\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n \t// The chunk loading function for additional chunks\n \t// Since all referenced chunks are already included\n \t// in this file, this function is empty here.\n \t__webpack_require__.e = function requireEnsure() {\n \t\treturn Promise.resolve();\n \t};\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/dist/\";\n\n \tvar jsonpArray = window[\"coreJsonp\"] = window[\"coreJsonp\"] || [];\n \tvar oldJsonpFunction = jsonpArray.push.bind(jsonpArray);\n \tjsonpArray.push = webpackJsonpCallback;\n \tjsonpArray = jsonpArray.slice();\n \tfor(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);\n \tvar parentJsonpFunction = oldJsonpFunction;\n\n\n \t// add entry module to deferred list\n \tdeferredModules.push([1868,0]);\n \t// run deferred modules when ready\n \treturn checkDeferredModules();\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","// This file is part of Indico.\n// Copyright (C) 2002 - 2021 CERN\n//\n// Indico is free software; you can redistribute it and/or\n// modify it under the terms of the MIT License; see the\n// LICENSE file for more details.\n\nimport 'pagedown-editor';\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","exports.Converter = require(\"./Markdown.Converter\").Converter;\nexports.getSanitizingConverter = require(\"./Markdown.Sanitizer\").getSanitizingConverter;\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","// 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"],"sourceRoot":""}