diff options
| author | Yukai Huang | 2016-10-11 18:39:15 +0800 | 
|---|---|---|
| committer | Yukai Huang | 2016-10-11 18:40:23 +0800 | 
| commit | 6e651c8108783d224c5f40d1bb8047a9ebbeff00 (patch) | |
| tree | c7d501cc6ebb46399c397768b3f58ef05034c522 /public/vendor/codemirror/mode/markdown | |
| parent | 21028c57735028574c769fb6650322eb3f0cb924 (diff) | |
| parent | cd9f8fe36b707ff5a9f8f7be4d55145ddee97f3a (diff) | |
Merge branch 'master' into webpack-frontend
Diffstat (limited to 'public/vendor/codemirror/mode/markdown')
| -rw-r--r-- | public/vendor/codemirror/mode/markdown/markdown_math.js | 864 | 
1 files changed, 864 insertions, 0 deletions
| diff --git a/public/vendor/codemirror/mode/markdown/markdown_math.js b/public/vendor/codemirror/mode/markdown/markdown_math.js new file mode 100644 index 00000000..e46adb79 --- /dev/null +++ b/public/vendor/codemirror/mode/markdown/markdown_math.js @@ -0,0 +1,864 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +(function(mod) { +  if (typeof exports == "object" && typeof module == "object") // CommonJS +    mod(require("../../lib/codemirror"), require("../xml/xml"), require("../meta")); +  else if (typeof define == "function" && define.amd) // AMD +    define(["../../lib/codemirror", "../xml/xml", "../meta"], mod); +  else // Plain browser env +    mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + +CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { + +  var htmlMode = CodeMirror.getMode(cmCfg, "text/html"); +  var htmlModeMissing = htmlMode.name == "null" + +  function getMode(name) { +    if (CodeMirror.findModeByName) { +      var found = CodeMirror.findModeByName(name); +      if (found) name = found.mime || found.mimes[0]; +    } +    var mode = CodeMirror.getMode(cmCfg, name); +    return mode.name == "null" ? null : mode; +  } + +  // Should characters that affect highlighting be highlighted separate? +  // Does not include characters that will be output (such as `1.` and `-` for lists) +  if (modeCfg.highlightFormatting === undefined) +    modeCfg.highlightFormatting = false; + +  // Maximum number of nested blockquotes. Set to 0 for infinite nesting. +  // Excess `>` will emit `error` token. +  if (modeCfg.maxBlockquoteDepth === undefined) +    modeCfg.maxBlockquoteDepth = 0; + +  // Should underscores in words open/close em/strong? +  if (modeCfg.underscoresBreakWords === undefined) +    modeCfg.underscoresBreakWords = true; + +  // Use `fencedCodeBlocks` to configure fenced code blocks. false to +  // disable, string to specify a precise regexp that the fence should +  // match, and true to allow three or more backticks or tildes (as +  // per CommonMark). + +  // Turn on task lists? ("- [ ] " and "- [x] ") +  if (modeCfg.taskLists === undefined) modeCfg.taskLists = false; + +  // Turn on strikethrough syntax +  if (modeCfg.strikethrough === undefined) +    modeCfg.strikethrough = false; + +  // Allow token types to be overridden by user-provided token types. +  if (modeCfg.tokenTypeOverrides === undefined) +    modeCfg.tokenTypeOverrides = {}; + +  var tokenTypes = { +    header: "header", +    code: "comment", +    math: "math", +    quote: "quote", +    list1: "variable-2", +    list2: "variable-3", +    list3: "keyword", +    hr: "hr", +    image: "image", +    imageAltText: "image-alt-text", +    imageMarker: "image-marker", +    formatting: "formatting", +    linkInline: "link", +    linkEmail: "link", +    linkText: "link", +    linkHref: "string", +    em: "em", +    strong: "strong", +    strikethrough: "strikethrough" +  }; + +  for (var tokenType in tokenTypes) { +    if (tokenTypes.hasOwnProperty(tokenType) && modeCfg.tokenTypeOverrides[tokenType]) { +      tokenTypes[tokenType] = modeCfg.tokenTypeOverrides[tokenType]; +    } +  } + +  var hrRE = /^([*\-_])(?:\s*\1){2,}\s*$/ +  ,   ulRE = /^[*\-+]\s+/ +  ,   olRE = /^[0-9]+([.)])\s+/ +  ,   taskListRE = /^\[(x| )\](?=\s)/ // Must follow ulRE or olRE +  ,   atxHeaderRE = modeCfg.allowAtxHeaderWithoutSpace ? /^(#+)/ : /^(#+)(?: |$)/ +  ,   setextHeaderRE = /^ *(?:\={1,}|-{1,})\s*$/ +  ,   textRE = /^[^#!\[\]*_\\<>\$` "'(~]+/ +  ,   fencedCodeRE = new RegExp("^(" + (modeCfg.fencedCodeBlocks === true ? "~~~+|```+" : modeCfg.fencedCodeBlocks) + +                                ")[ \\t]*([\\w+#\-]*)") +  ,   fencedMathRE = new RegExp("^(\$\$)[ \\t]*([\\w+#\-]*)"); + +  function switchInline(stream, state, f) { +    state.f = state.inline = f; +    return f(stream, state); +  } + +  function switchBlock(stream, state, f) { +    state.f = state.block = f; +    return f(stream, state); +  } + +  function lineIsEmpty(line) { +    return !line || !/\S/.test(line.string) +  } + +  // Blocks + +  function blankLine(state) { +    // Reset linkTitle state +    state.linkTitle = false; +    // Reset EM state +    state.em = false; +    // Reset STRONG state +    state.strong = false; +    // Reset strikethrough state +    state.strikethrough = false; +    // Reset state.quote +    state.quote = 0; +    // Reset state.indentedCode +    state.indentedCode = false; +    if (htmlModeMissing && state.f == htmlBlock) { +      state.f = inlineNormal; +      state.block = blockNormal; +    } +    // Reset state.trailingSpace +    state.trailingSpace = 0; +    state.trailingSpaceNewLine = false; +    // Mark this line as blank +    state.prevLine = state.thisLine +    state.thisLine = null +    return null; +  } + +  function blockNormal(stream, state) { + +    var sol = stream.sol(); + +    var prevLineIsList = state.list !== false, +        prevLineIsIndentedCode = state.indentedCode; + +    state.indentedCode = false; + +    if (prevLineIsList) { +      if (state.indentationDiff >= 0) { // Continued list +        if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block +          state.indentation -= state.indentationDiff; +        } +        state.list = null; +      } else if (state.indentation > 0) { +        state.list = null; +      } else { // No longer a list +        state.list = false; +      } +    } + +    var match = null; +    if (state.indentationDiff >= 4) { +      stream.skipToEnd(); +      if (prevLineIsIndentedCode || lineIsEmpty(state.prevLine)) { +        state.indentation -= 4; +        state.indentedCode = true; +        return tokenTypes.code; +      } else { +        return null; +      } +    } else if (stream.eatSpace()) { +      return null; +    } else if ((match = stream.match(atxHeaderRE)) && match[1].length <= 6) { +      state.header = match[1].length; +      if (modeCfg.highlightFormatting) state.formatting = "header"; +      state.f = state.inline; +      return getType(state); +    } else if (!lineIsEmpty(state.prevLine) && !state.quote && !prevLineIsList && +               !prevLineIsIndentedCode && (match = stream.match(setextHeaderRE))) { +      state.header = match[0].charAt(0) == '=' ? 1 : 2; +      if (modeCfg.highlightFormatting) state.formatting = "header"; +      state.f = state.inline; +      return getType(state); +    } else if (stream.eat('>')) { +      state.quote = sol ? 1 : state.quote + 1; +      if (modeCfg.highlightFormatting) state.formatting = "quote"; +      stream.eatSpace(); +      return getType(state); +    } else if (stream.peek() === '[') { +      return switchInline(stream, state, footnoteLink); +    } else if (stream.match(hrRE, true)) { +      state.hr = true; +      return tokenTypes.hr; +    } else if ((lineIsEmpty(state.prevLine) || prevLineIsList) && (stream.match(ulRE, false) || stream.match(olRE, false))) { +      var listType = null; +      if (stream.match(ulRE, true)) { +        listType = 'ul'; +      } else { +        stream.match(olRE, true); +        listType = 'ol'; +      } +      state.indentation = stream.column() + stream.current().length; +      state.list = true; + +      // While this list item's marker's indentation +      // is less than the deepest list item's content's indentation, +      // pop the deepest list item indentation off the stack. +      while (state.listStack && stream.column() < state.listStack[state.listStack.length - 1]) { +        state.listStack.pop(); +      } + +      // Add this list item's content's indentation to the stack +      state.listStack.push(state.indentation); + +      if (modeCfg.taskLists && stream.match(taskListRE, false)) { +        state.taskList = true; +      } +      state.f = state.inline; +      if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType]; +      return getType(state); +    } else if (modeCfg.fencedCodeBlocks && (match = stream.match(fencedCodeRE, true))) { +      state.fencedChars = match[1] +      // try switching mode +      state.localMode = getMode(match[2]); +      if (state.localMode) state.localState = CodeMirror.startState(state.localMode); +      state.f = state.block = local; +      if (modeCfg.highlightFormatting) state.formatting = "code-block"; +      state.code = -1 +      return getType(state); +    } else if (match = stream.match(fencedCodeRE, true)) { +      state.fencedChars = match[1] +      // try switching mode +      state.localMode = getMode(match[2]); +      if (state.localMode) state.localState = CodeMirror.startState(state.localMode); +      state.f = state.block = local; +      state.formatting = "math"; +      state.math = -1 +      return getType(state); +    } + +    return switchInline(stream, state, state.inline); +  } + +  function htmlBlock(stream, state) { +    var style = htmlMode.token(stream, state.htmlState); +    if (!htmlModeMissing) { +      var inner = CodeMirror.innerMode(htmlMode, state.htmlState) +      if ((inner.mode.name == "xml" && inner.state.tagStart === null && +           (!inner.state.context && inner.state.tokenize.isInText)) || +          (state.md_inside && stream.current().indexOf(">") > -1)) { +        state.f = inlineNormal; +        state.block = blockNormal; +        state.htmlState = null; +      } +    } +    return style; +  } + +  function local(stream, state) { +    if (state.fencedChars && stream.match(state.fencedChars, false)) { +      state.localMode = state.localState = null; +      state.f = state.block = leavingLocal; +      return null; +    } else if (state.localMode) { +      return state.localMode.token(stream, state.localState); +    } else { +      stream.skipToEnd(); +      if (state.math === -1) { +        return tokenTypes.math; +      } +      return tokenTypes.code; +    } +  } + +  function leavingLocal(stream, state) { +    stream.match(state.fencedChars); +    state.block = blockNormal; +    state.f = inlineNormal; +    state.fencedChars = null; +    if (state.math === -1) { +      state.formatting = "math"; +      state.math = 1 +      var returnType = getType(state); +      state.math = 0 +      return returnType; +    } +    if (modeCfg.highlightFormatting) state.formatting = "code-block"; +    state.code = 1 +    var returnType = getType(state); +    state.code = 0 +    return returnType; +  } + +  // Inline +  function getType(state) { +    var styles = []; + +    if (state.formatting) { +      styles.push(tokenTypes.formatting); + +      if (typeof state.formatting === "string") state.formatting = [state.formatting]; + +      for (var i = 0; i < state.formatting.length; i++) { +        styles.push(tokenTypes.formatting + "-" + state.formatting[i]); + +        if (state.formatting[i] === "header") { +          styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.header); +        } + +        // Add `formatting-quote` and `formatting-quote-#` for blockquotes +        // Add `error` instead if the maximum blockquote nesting depth is passed +        if (state.formatting[i] === "quote") { +          if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) { +            styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.quote); +          } else { +            styles.push("error"); +          } +        } +      } +    } + +    if (state.taskOpen) { +      styles.push("meta"); +      return styles.length ? styles.join(' ') : null; +    } +    if (state.taskClosed) { +      styles.push("property"); +      return styles.length ? styles.join(' ') : null; +    } + +    if (state.linkHref) { +      styles.push(tokenTypes.linkHref, "url"); +    } else { // Only apply inline styles to non-url text +      if (state.strong) { styles.push(tokenTypes.strong); } +      if (state.em) { styles.push(tokenTypes.em); } +      if (state.strikethrough) { styles.push(tokenTypes.strikethrough); } +      if (state.linkText) { styles.push(tokenTypes.linkText); } +      if (state.code) { styles.push(tokenTypes.code); } +      if (state.math) { styles.push(tokenTypes.math); } +      if (state.image) { styles.push(tokenTypes.image); } +      if (state.imageAltText) { styles.push(tokenTypes.imageAltText, "link"); } +      if (state.imageMarker) { styles.push(tokenTypes.imageMarker); } +    } + +    if (state.header) { styles.push(tokenTypes.header, tokenTypes.header + "-" + state.header); } + +    if (state.quote) { +      styles.push(tokenTypes.quote); + +      // Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth +      if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) { +        styles.push(tokenTypes.quote + "-" + state.quote); +      } else { +        styles.push(tokenTypes.quote + "-" + modeCfg.maxBlockquoteDepth); +      } +    } + +    if (state.list !== false) { +      var listMod = (state.listStack.length - 1) % 3; +      if (!listMod) { +        styles.push(tokenTypes.list1); +      } else if (listMod === 1) { +        styles.push(tokenTypes.list2); +      } else { +        styles.push(tokenTypes.list3); +      } +    } + +    if (state.trailingSpaceNewLine) { +      styles.push("trailing-space-new-line"); +    } else if (state.trailingSpace) { +      styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b")); +    } + +    return styles.length ? styles.join(' ') : null; +  } + +  function handleText(stream, state) { +    if (stream.match(textRE, true)) { +      return getType(state); +    } +    return undefined; +  } + +  function inlineNormal(stream, state) { +    var style = state.text(stream, state); +    if (typeof style !== 'undefined') +      return style; + +    if (state.list) { // List marker (*, +, -, 1., etc) +      state.list = null; +      return getType(state); +    } + +    if (state.taskList) { +      var taskOpen = stream.match(taskListRE, true)[1] !== "x"; +      if (taskOpen) state.taskOpen = true; +      else state.taskClosed = true; +      if (modeCfg.highlightFormatting) state.formatting = "task"; +      state.taskList = false; +      return getType(state); +    } + +    state.taskOpen = false; +    state.taskClosed = false; + +    if (state.header && stream.match(/^#+$/, true)) { +      if (modeCfg.highlightFormatting) state.formatting = "header"; +      return getType(state); +    } + +    // Get sol() value now, before character is consumed +    var sol = stream.sol(); + +    var ch = stream.next(); + +    // Matches link titles present on next line +    if (state.linkTitle) { +      state.linkTitle = false; +      var matchCh = ch; +      if (ch === '(') { +        matchCh = ')'; +      } +      matchCh = (matchCh+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); +      var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh; +      if (stream.match(new RegExp(regex), true)) { +        return tokenTypes.linkHref; +      } +    } + +    // If this block is changed, it may need to be updated in GFM mode +    if (ch === '`') { +      var previousFormatting = state.formatting; +      if (modeCfg.highlightFormatting) state.formatting = "code"; +      stream.eatWhile('`'); +      var count = stream.current().length +      if (state.code == 0) { +        state.code = count +        return getType(state) +      } else if (count == state.code) { // Must be exact +        var t = getType(state) +        state.code = 0 +        return t +      } else { +        state.formatting = previousFormatting +        return getType(state) +      } +    } else if (state.code) { +      return getType(state); +    } + +    // display math correctly +    if (ch === '$') { +      var previousFormatting = state.formatting; +      state.formatting = "math"; +      stream.eatWhile('$'); +      var count = stream.current().length +      if (state.math == 0) { +        state.math = count +        return getType(state) +      } else if (count == state.math) { // Must be exact +        var t = getType(state) +        state.math = 0 +        return t +      } else { +        state.formatting = previousFormatting +        return getType(state) +      } +    } else if (state.math) { +      return getType(state); +    } + +    if (ch === '\\') { +      stream.next(); +      if (modeCfg.highlightFormatting) { +        var type = getType(state); +        var formattingEscape = tokenTypes.formatting + "-escape"; +        return type ? type + " " + formattingEscape : formattingEscape; +      } +    } + +    if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) { +      state.imageMarker = true; +      state.image = true; +      if (modeCfg.highlightFormatting) state.formatting = "image"; +      return getType(state); +    } + +    if (ch === '[' && state.imageMarker) { +      state.imageMarker = false; +      state.imageAltText = true +      if (modeCfg.highlightFormatting) state.formatting = "image"; +      return getType(state); +    } + +    if (ch === ']' && state.imageAltText) { +      if (modeCfg.highlightFormatting) state.formatting = "image"; +      var type = getType(state); +      state.imageAltText = false; +      state.image = false; +      state.inline = state.f = linkHref; +      return type; +    } + +    if (ch === '[' && stream.match(/[^\]]*\](\(.*\)| ?\[.*?\])/, false) && !state.image) { +      state.linkText = true; +      if (modeCfg.highlightFormatting) state.formatting = "link"; +      return getType(state); +    } + +    if (ch === ']' && state.linkText && stream.match(/\(.*?\)| ?\[.*?\]/, false)) { +      if (modeCfg.highlightFormatting) state.formatting = "link"; +      var type = getType(state); +      state.linkText = false; +      state.inline = state.f = linkHref; +      return type; +    } + +    if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) { +      state.f = state.inline = linkInline; +      if (modeCfg.highlightFormatting) state.formatting = "link"; +      var type = getType(state); +      if (type){ +        type += " "; +      } else { +        type = ""; +      } +      return type + tokenTypes.linkInline; +    } + +    if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) { +      state.f = state.inline = linkInline; +      if (modeCfg.highlightFormatting) state.formatting = "link"; +      var type = getType(state); +      if (type){ +        type += " "; +      } else { +        type = ""; +      } +      return type + tokenTypes.linkEmail; +    } + +    if (ch === '<' && stream.match(/^(!--|\w)/, false)) { +      var end = stream.string.indexOf(">", stream.pos); +      if (end != -1) { +        var atts = stream.string.substring(stream.start, end); +        if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) state.md_inside = true; +      } +      stream.backUp(1); +      state.htmlState = CodeMirror.startState(htmlMode); +      return switchBlock(stream, state, htmlBlock); +    } + +    if (ch === '<' && stream.match(/^\/\w*?>/)) { +      state.md_inside = false; +      return "tag"; +    } + +    var ignoreUnderscore = false; +    if (!modeCfg.underscoresBreakWords) { +      if (ch === '_' && stream.peek() !== '_' && stream.match(/(\w)/, false)) { +        var prevPos = stream.pos - 2; +        if (prevPos >= 0) { +          var prevCh = stream.string.charAt(prevPos); +          if (prevCh !== '_' && prevCh.match(/(\w)/, false)) { +            ignoreUnderscore = true; +          } +        } +      } +    } +    if (ch === '*' || (ch === '_' && !ignoreUnderscore)) { +      if (sol && stream.peek() === ' ') { +        // Do nothing, surrounded by newline and space +      } else if (state.strong === ch && stream.eat(ch)) { // Remove STRONG +        if (modeCfg.highlightFormatting) state.formatting = "strong"; +        var t = getType(state); +        state.strong = false; +        return t; +      } else if (!state.strong && stream.eat(ch)) { // Add STRONG +        state.strong = ch; +        if (modeCfg.highlightFormatting) state.formatting = "strong"; +        return getType(state); +      } else if (state.em === ch) { // Remove EM +        if (modeCfg.highlightFormatting) state.formatting = "em"; +        var t = getType(state); +        state.em = false; +        return t; +      } else if (!state.em) { // Add EM +        state.em = ch; +        if (modeCfg.highlightFormatting) state.formatting = "em"; +        return getType(state); +      } +    } else if (ch === ' ') { +      if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces +        if (stream.peek() === ' ') { // Surrounded by spaces, ignore +          return getType(state); +        } else { // Not surrounded by spaces, back up pointer +          stream.backUp(1); +        } +      } +    } + +    if (modeCfg.strikethrough) { +      if (ch === '~' && stream.eatWhile(ch)) { +        if (state.strikethrough) {// Remove strikethrough +          if (modeCfg.highlightFormatting) state.formatting = "strikethrough"; +          var t = getType(state); +          state.strikethrough = false; +          return t; +        } else if (stream.match(/^[^\s]/, false)) {// Add strikethrough +          state.strikethrough = true; +          if (modeCfg.highlightFormatting) state.formatting = "strikethrough"; +          return getType(state); +        } +      } else if (ch === ' ') { +        if (stream.match(/^~~/, true)) { // Probably surrounded by space +          if (stream.peek() === ' ') { // Surrounded by spaces, ignore +            return getType(state); +          } else { // Not surrounded by spaces, back up pointer +            stream.backUp(2); +          } +        } +      } +    } + +    if (ch === ' ') { +      if (stream.match(/ +$/, false)) { +        state.trailingSpace++; +      } else if (state.trailingSpace) { +        state.trailingSpaceNewLine = true; +      } +    } + +    return getType(state); +  } + +  function linkInline(stream, state) { +    var ch = stream.next(); + +    if (ch === ">") { +      state.f = state.inline = inlineNormal; +      if (modeCfg.highlightFormatting) state.formatting = "link"; +      var type = getType(state); +      if (type){ +        type += " "; +      } else { +        type = ""; +      } +      return type + tokenTypes.linkInline; +    } + +    stream.match(/^[^>]+/, true); + +    return tokenTypes.linkInline; +  } + +  function linkHref(stream, state) { +    // Check if space, and return NULL if so (to avoid marking the space) +    if(stream.eatSpace()){ +      return null; +    } +    var ch = stream.next(); +    if (ch === '(' || ch === '[') { +      state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]", 0); +      if (modeCfg.highlightFormatting) state.formatting = "link-string"; +      state.linkHref = true; +      return getType(state); +    } +    return 'error'; +  } + +  var linkRE = { +    ")": /^(?:[^\\\(\)]|\\.|\((?:[^\\\(\)]|\\.)*\))*?(?=\))/, +    "]": /^(?:[^\\\[\]]|\\.|\[(?:[^\\\[\\]]|\\.)*\])*?(?=\])/ +  } + +  function getLinkHrefInside(endChar) { +    return function(stream, state) { +      var ch = stream.next(); + +      if (ch === endChar) { +        state.f = state.inline = inlineNormal; +        if (modeCfg.highlightFormatting) state.formatting = "link-string"; +        var returnState = getType(state); +        state.linkHref = false; +        return returnState; +      } + +      stream.match(linkRE[endChar]) +      state.linkHref = true; +      return getType(state); +    }; +  } + +  function footnoteLink(stream, state) { +    if (stream.match(/^([^\]\\]|\\.)*\]:/, false)) { +      state.f = footnoteLinkInside; +      stream.next(); // Consume [ +      if (modeCfg.highlightFormatting) state.formatting = "link"; +      state.linkText = true; +      return getType(state); +    } +    return switchInline(stream, state, inlineNormal); +  } + +  function footnoteLinkInside(stream, state) { +    if (stream.match(/^\]:/, true)) { +      state.f = state.inline = footnoteUrl; +      if (modeCfg.highlightFormatting) state.formatting = "link"; +      var returnType = getType(state); +      state.linkText = false; +      return returnType; +    } + +    stream.match(/^([^\]\\]|\\.)+/, true); + +    return tokenTypes.linkText; +  } + +  function footnoteUrl(stream, state) { +    // Check if space, and return NULL if so (to avoid marking the space) +    if(stream.eatSpace()){ +      return null; +    } +    // Match URL +    stream.match(/^[^\s]+/, true); +    // Check for link title +    if (stream.peek() === undefined) { // End of line, set flag to check next line +      state.linkTitle = true; +    } else { // More content on line, check if link title +      stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true); +    } +    state.f = state.inline = inlineNormal; +    return tokenTypes.linkHref + " url"; +  } + +  var mode = { +    startState: function() { +      return { +        f: blockNormal, + +        prevLine: null, +        thisLine: null, + +        block: blockNormal, +        htmlState: null, +        indentation: 0, + +        inline: inlineNormal, +        text: handleText, + +        formatting: false, +        linkText: false, +        linkHref: false, +        linkTitle: false, +        code: 0, +        math: 0, +        em: false, +        strong: false, +        header: 0, +        hr: false, +        taskList: false, +        list: false, +        listStack: [], +        quote: 0, +        trailingSpace: 0, +        trailingSpaceNewLine: false, +        strikethrough: false, +        fencedChars: null +      }; +    }, + +    copyState: function(s) { +      return { +        f: s.f, + +        prevLine: s.prevLine, +        thisLine: s.thisLine, + +        block: s.block, +        htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState), +        indentation: s.indentation, + +        localMode: s.localMode, +        localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null, + +        inline: s.inline, +        text: s.text, +        formatting: false, +        linkTitle: s.linkTitle, +        code: s.code, +        math: s.math, +        em: s.em, +        strong: s.strong, +        strikethrough: s.strikethrough, +        header: s.header, +        hr: s.hr, +        taskList: s.taskList, +        list: s.list, +        listStack: s.listStack.slice(0), +        quote: s.quote, +        indentedCode: s.indentedCode, +        trailingSpace: s.trailingSpace, +        trailingSpaceNewLine: s.trailingSpaceNewLine, +        md_inside: s.md_inside, +        fencedChars: s.fencedChars +      }; +    }, + +    token: function(stream, state) { + +      // Reset state.formatting +      state.formatting = false; + +      if (stream != state.thisLine) { +        var forceBlankLine = state.header || state.hr; + +        // Reset state.header and state.hr +        state.header = 0; +        state.hr = false; + +        if (stream.match(/^\s*$/, true) || forceBlankLine) { +          blankLine(state); +          if (!forceBlankLine) return null +          state.prevLine = null +        } + +        state.prevLine = state.thisLine +        state.thisLine = stream + +        // Reset state.taskList +        state.taskList = false; + +        // Reset state.trailingSpace +        state.trailingSpace = 0; +        state.trailingSpaceNewLine = false; + +        state.f = state.block; +        var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, '    ').length; +        state.indentationDiff = Math.min(indentation - state.indentation, 4); +        state.indentation = state.indentation + state.indentationDiff; +        if (indentation > 0) return null; +      } +      return state.f(stream, state); +    }, + +    innerMode: function(state) { +      if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode}; +      if (state.localState) return {state: state.localState, mode: state.localMode}; +      return {state: state, mode: mode}; +    }, + +    blankLine: blankLine, + +    getType: getType, + +    fold: "markdown" +  }; +  return mode; +}, "xml"); + +CodeMirror.defineMIME("text/x-markdown", "markdown"); + +}); | 
