PageSourceSearch

https://algospot.com/static/codemirror/mode/markdown/markdown.js

js algospot.com collected 2026-10-04 19:36:09 UTC 25,770 bytes, 819 lines download raw bytes

1// CodeMirror, copyright (c) by Marijn Haverbeke and others
2// Distributed under an MIT license: http://codemirror.net/LICENSE
3
4(function(mod) {
5  if (typeof exports == "object" && typeof module == "object") // CommonJS
6    mod(require("../../lib/codemirror"), require("../xml/xml"), require("../meta"));
7  else if (typeof define == "function" && define.amd) // AMD
8    define(["../../lib/codemirror", "../xml/xml", "../meta"], mod);
9  else // Plain browser env
10    mod(CodeMirror);
11})(function(CodeMirror) {
12"use strict";
13
14CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
15
16  var htmlMode = CodeMirror.getMode(cmCfg, "text/html");
17  var htmlModeMissing = htmlMode.name == "null"
18
19  function getMode(name) {
20    if (CodeMirror.findModeByName) {
21      var found = CodeMirror.findModeByName(name);
22      if (found) name = found.mime || found.mimes[0];
23    }
24    var mode = CodeMirror.getMode(cmCfg, name);
25    return mode.name == "null" ? null : mode;
26  }
27
28  // Should characters that affect highlighting be highlighted separate?
29  // Does not include characters that will be output (such as `1.` and `-` for lists)
30  if (modeCfg.highlightFormatting === undefined)
31    modeCfg.highlightFormatting = false;
32
33  // Maximum number of nested blockquotes. Set to 0 for infinite nesting.
34  // Excess `>` will emit `error` token.
35  if (modeCfg.maxBlockquoteDepth === undefined)
36    modeCfg.maxBlockquoteDepth = 0;
37
38  // Should underscores in words open/close em/strong?
39  if (modeCfg.underscoresBreakWords === undefined)
40    modeCfg.underscoresBreakWords = true;
41
42  // Use `fencedCodeBlocks` to configure fenced code blocks. false to
43  // disable, string to specify a precise regexp that the fence should
44  // match, and true to allow three or more backticks or tildes (as
45  // per CommonMark).
46
47  // Turn on task lists? ("- [ ] " and "- [x] ")
48  if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;
49
50  // Turn on strikethrough syntax
51  if (modeCfg.strikethrough === undefined)
52    modeCfg.strikethrough = false;
53
54  // Allow token types to be overridden by user-provided token types.
55  if (modeCfg.tokenTypeOverrides === undefined)
56    modeCfg.tokenTypeOverrides = {};
57
58  var tokenTypes = {
59    header: "header",
60    code: "comment",
61    quote: "quote",
62    list1: "variable-2",
63    list2: "variable-3",
64    list3: "keyword",
65    hr: "hr",
66    image: "image",
67    imageAltText: "image-alt-text",
68    imageMarker: "image-marker",
69    formatting: "formatting",
70    linkInline: "link",
71    linkEmail: "link",
72    linkText: "link",
73    linkHref: "string",
74    em: "em",
75    strong: "strong",
76    strikethrough: "strikethrough"
77  };
78
79  for (var tokenType in tokenTypes) {
80    if (tokenTypes.hasOwnProperty(tokenType) && modeCfg.tokenTypeOverrides[tokenType]) {
81      tokenTypes[tokenType] = modeCfg.tokenTypeOverrides[tokenType];
82    }
83  }
84
85  var hrRE = /^([*\-_])(?:\s*\1){2,}\s*$/
86  ,   ulRE = /^[*\-+]\s+/
87  ,   olRE = /^[0-9]+([.)])\s+/
88  ,   taskListRE = /^\[(x| )\](?=\s)/ // Must follow ulRE or olRE
89  ,   atxHeaderRE = modeCfg.allowAtxHeaderWithoutSpace ? /^(#+)/ : /^(#+)(?: |$)/
90  ,   setextHeaderRE = /^ *(?:\={1,}|-{1,})\s*$/
91  ,   textRE = /^[^#!\[\]*_\\<>` "'(~]+/
92  ,   fencedCodeRE = new RegExp("^(" + (modeCfg.fencedCodeBlocks === true ? "~~~+|```+" : modeCfg.fencedCodeBlocks) +
93                                ")[ \\t]*([\\w+#\-]*)");
94
95  function switchInline(stream, state, f) {
96    state.f = state.inline = f;
97    return f(stream, state);
98  }
99
100  function switchBlock(stream, state, f) {
101    state.f = state.block = f;
102    return f(stream, state);
103  }
104
105  function lineIsEmpty(line) {
106    return !line || !/\S/.test(line.string)
107  }
108
109  // Blocks
110
111  function blankLine(state) {
112    // Reset linkTitle state
113    state.linkTitle = false;
114    // Reset EM state
115    state.em = false;
116    // Reset STRONG state
117    state.strong = false;
118    // Reset strikethrough state
119    state.strikethrough = false;
120    // Reset state.quote
121    state.quote = 0;
122    // Reset state.indentedCode
123    state.indentedCode = false;
124    if (htmlModeMissing && state.f == htmlBlock) {
125      state.f = inlineNormal;
126      state.block = blockNormal;
127    }
128    // Reset state.trailingSpace
129    state.trailingSpace = 0;
130    state.trailingSpaceNewLine = false;
131    // Mark this line as blank
132    state.prevLine = state.thisLine
133    state.thisLine = null
134    return null;
135  }
136
137  function blockNormal(stream, state) {
138
139    var sol = stream.sol();
140
141    var prevLineIsList = state.list !== false,
142        prevLineIsIndentedCode = state.indentedCode;
143
144    state.indentedCode = false;
145
146    if (prevLineIsList) {
147      if (state.indentationDiff >= 0) { // Continued list
148        if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block
149          state.indentation -= state.indentationDiff;
150        }
151        state.list = null;
152      } else if (state.indentation > 0) {
153        state.list = null;
154      } else { // No longer a list
155        state.list = false;
156      }
157    }
158
159    var match = null;
160    if (state.indentationDiff >= 4) {
161      stream.skipToEnd();
162      if (prevLineIsIndentedCode || lineIsEmpty(state.prevLine)) {
163        state.indentation -= 4;
164        state.indentedCode = true;
165        return tokenTypes.code;
166      } else {
167        return null;
168      }
169    } else if (stream.eatSpace()) {
170      return null;
171    } else if ((match = stream.match(atxHeaderRE)) && match[1].length <= 6) {
172      state.header = match[1].length;
173      if (modeCfg.highlightFormatting) state.formatting = "header";
174      state.f = state.inline;
175      return getType(state);
176    } else if (!lineIsEmpty(state.prevLine) && !state.quote && !prevLineIsList &&
177               !prevLineIsIndentedCode && (match = stream.match(setextHeaderRE))) {
178      state.header = match[0].charAt(0) == '=' ? 1 : 2;
179      if (modeCfg.highlightFormatting) state.formatting = "header";
180      state.f = state.inline;
181      return getType(state);
182    } else if (stream.eat('>')) {
183      state.quote = sol ? 1 : state.quote + 1;
184      if (modeCfg.highlightFormatting) state.formatting = "quote";
185      stream.eatSpace();
186      return getType(state);
187    } else if (stream.peek() === '[') {
188      return switchInline(stream, state, footnoteLink);
189    } else if (stream.match(hrRE, true)) {
190      state.hr = true;
191      return tokenTypes.hr;
192    } else if ((lineIsEmpty(state.prevLine) || prevLineIsList) && (stream.match(ulRE, false) || stream.match(olRE, false))) {
193      var listType = null;
194      if (stream.match(ulRE, true)) {
195        listType = 'ul';
196      } else {
197        stream.match(olRE, true);
198        listType = 'ol';
199      }
200      state.indentation = stream.column() + stream.current().length;
201      state.list = true;
202
203      // While this list item's marker's indentation
204      // is less than the deepest list item's content's indentation,
205      // pop the deepest list item indentation off the stack.
206      while (state.listStack && stream.column() < state.listStack[state.listStack.length - 1]) {
207        state.listStack.pop();
208      }
209
210      // Add this list item's content's indentation to the stack
211      state.listStack.push(state.indentation);
212
213      if (modeCfg.taskLists && stream.match(taskListRE, false)) {
214        state.taskList = true;
215      }
216      state.f = state.inline;
217      if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];
218      return getType(state);
219    } else if (modeCfg.fencedCodeBlocks && (match = stream.match(fencedCodeRE, true))) {
220      state.fencedChars = match[1]
221      // try switching mode
222      state.localMode = getMode(match[2]);
223      if (state.localMode) state.localState = CodeMirror.startState(state.localMode);
224      state.f = state.block = local;
225      if (modeCfg.highlightFormatting) state.formatting = "code-block";
226      state.code = -1
227      return getType(state);
228    }
229
230    return switchInline(stream, state, state.inline);
231  }
232
233  function htmlBlock(stream, state) {
234    var style = htmlMode.token(stream, state.htmlState);
235    if (!htmlModeMissing) {
236      var inner = CodeMirror.innerMode(htmlMode, state.htmlState)
237      if ((inner.mode.name == "xml" && inner.state.tagStart === null &&
238           (!inner.state.context && inner.state.tokenize.isInText)) ||
239          (state.md_inside && stream.current().indexOf(">") > -1)) {
240        state.f = inlineNormal;
241        state.block = blockNormal;
242        state.htmlState = null;
243      }
244    }
245    return style;
246  }
247
248  function local(stream, state) {
249    if (state.fencedChars && stream.match(state.fencedChars, false)) {
250      state.localMode = state.localState = null;
251      state.f = state.block = leavingLocal;
252      return null;
253    } else if (state.localMode) {
254      return state.localMode.token(stream, state.localState);
255    } else {
256      stream.skipToEnd();
257      return tokenTypes.code;
258    }
259  }
260
261  function leavingLocal(stream, state) {
262    stream.match(state.fencedChars);
263    state.block = blockNormal;
264    state.f = inlineNormal;
265    state.fencedChars = null;
266    if (modeCfg.highlightFormatting) state.formatting = "code-block";
267    state.code = 1
268    var returnType = getType(state);
269    state.code = 0
270    return returnType;
271  }
272
273  // Inline
274  function getType(state) {
275    var styles = [];
276
277    if (state.formatting) {
278      styles.push(tokenTypes.formatting);
279
280      if (typeof state.formatting === "string") state.formatting = [state.formatting];
281
282      for (var i = 0; i < state.formatting.length; i++) {
283        styles.push(tokenTypes.formatting + "-" + state.formatting[i]);
284
285        if (state.formatting[i] === "header") {
286          styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.header);
287        }
288
289        // Add `formatting-quote` and `formatting-quote-#` for blockquotes
290        // Add `error` instead if the maximum blockquote nesting depth is passed
291        if (state.formatting[i] === "quote") {
292          if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
293            styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.quote);
294          } else {
295            styles.push("error");
296          }
297        }
298      }
299    }
300
301    if (state.taskOpen) {
302      styles.push("meta");
303      return styles.length ? styles.join(' ') : null;
304    }
305    if (state.taskClosed) {
306      styles.push("property");
307      return styles.length ? styles.join(' ') : null;
308    }
309
310    if (state.linkHref) {
311      styles.push(tokenTypes.linkHref, "url");
312    } else { // Only apply inline styles to non-url text
313      if (state.strong) { styles.push(tokenTypes.strong); }
314      if (state.em) { styles.push(tokenTypes.em); }
315      if (state.strikethrough) { styles.push(tokenTypes.strikethrough); }
316      if (state.linkText) { styles.push(tokenTypes.linkText); }
317      if (state.code) { styles.push(tokenTypes.code); }
318      if (state.image) { styles.push(tokenTypes.image); }
319      if (state.imageAltText) { styles.push(tokenTypes.imageAltText, "link"); }
320      if (state.imageMarker) { styles.push(tokenTypes.imageMarker); }
321    }
322
323    if (state.header) { styles.push(tokenTypes.header, tokenTypes.header + "-" + state.header); }
324
325    if (state.quote) {
326      styles.push(tokenTypes.quote);
327
328      // Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth
329      if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
330        styles.push(tokenTypes.quote + "-" + state.quote);
331      } else {
332        styles.push(tokenTypes.quote + "-" + modeCfg.maxBlockquoteDepth);
333      }
334    }
335
336    if (state.list !== false) {
337      var listMod = (state.listStack.length - 1) % 3;
338      if (!listMod) {
339        styles.push(tokenTypes.list1);
340      } else if (listMod === 1) {
341        styles.push(tokenTypes.list2);
342      } else {
343        styles.push(tokenTypes.list3);
344      }
345    }
346
347    if (state.trailingSpaceNewLine) {
348      styles.push("trailing-space-new-line");
349    } else if (state.trailingSpace) {
350      styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b"));
351    }
352
353    return styles.length ? styles.join(' ') : null;
354  }
355
356  function handleText(stream, state) {
357    if (stream.match(textRE, true)) {
358      return getType(state);
359    }
360    return undefined;
361  }
362
363  function inlineNormal(stream, state) {
364    var style = state.text(stream, state);
365    if (typeof style !== 'undefined')
366      return style;
367
368    if (state.list) { // List marker (*, +, -, 1., etc)
369      state.list = null;
370      return getType(state);
371    }
372
373    if (state.taskList) {
374      var taskOpen = stream.match(taskListRE, true)[1] !== "x";
375      if (taskOpen) state.taskOpen = true;
376      else state.taskClosed = true;
377      if (modeCfg.highlightFormatting) state.formatting = "task";
378      state.taskList = false;
379      return getType(state);
380    }
381
382    state.taskOpen = false;
383    state.taskClosed = false;
384
385    if (state.header && stream.match(/^#+$/, true)) {
386      if (modeCfg.highlightFormatting) state.formatting = "header";
387      return getType(state);
388    }
389
390    // Get sol() value now, before character is consumed
391    var sol = stream.sol();
392
393    var ch = stream.next();
394
395    // Matches link titles present on next line
396    if (state.linkTitle) {
397      state.linkTitle = false;
398      var matchCh = ch;
399      if (ch === '(') {
400        matchCh = ')';
401      }
402      matchCh = (matchCh+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
403      var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh;
404      if (stream.match(new RegExp(regex), true)) {
405        return tokenTypes.linkHref;
406      }
407    }
408
409    // If this block is changed, it may need to be updated in GFM mode
410    if (ch === '`') {
411      var previousFormatting = state.formatting;
412      if (modeCfg.highlightFormatting) state.formatting = "code";
413      stream.eatWhile('`');
414      var count = stream.current().length
415      if (state.code == 0) {
416        state.code = count
417        return getType(state)
418      } else if (count == state.code) { // Must be exact
419        var t = getType(state)
420        state.code = 0
421        return t
422      } else {
423        state.formatting = previousFormatting
424        return getType(state)
425      }
426    } else if (state.code) {
427      return getType(state);
428    }
429
430    if (ch === '\\') {
431      stream.next();
432      if (modeCfg.highlightFormatting) {
433        var type = getType(state);
434        var formattingEscape = tokenTypes.formatting + "-escape";
435        return type ? type + " " + formattingEscape : formattingEscape;
436      }
437    }
438
439    if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
440      state.imageMarker = true;
441      state.image = true;
442      if (modeCfg.highlightFormatting) state.formatting = "image";
443      return getType(state);
444    }
445
446    if (ch === '[' && state.imageMarker) {
447      state.imageMarker = false;
448      state.imageAltText = true
449      if (modeCfg.highlightFormatting) state.formatting = "image";
450      return getType(state);
451    }
452
453    if (ch === ']' && state.imageAltText) {
454      if (modeCfg.highlightFormatting) state.formatting = "image";
455      var type = getType(state);
456      state.imageAltText = false;
457      state.image = false;
458      state.inline = state.f = linkHref;
459      return type;
460    }
461
462    if (ch === '[' && stream.match(/[^\]]*\](\(.*\)| ?\[.*?\])/, false) && !state.image) {
463      state.linkText = true;
464      if (modeCfg.highlightFormatting) state.formatting = "link";
465      return getType(state);
466    }
467
468    if (ch === ']' && state.linkText && stream.match(/\(.*?\)| ?\[.*?\]/, false)) {
469      if (modeCfg.highlightFormatting) state.formatting = "link";
470      var type = getType(state);
471      state.linkText = false;
472      state.inline = state.f = linkHref;
473      return type;
474    }
475
476    if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) {
477      state.f = state.inline = linkInline;
478      if (modeCfg.highlightFormatting) state.formatting = "link";
479      var type = getType(state);
480      if (type){
481        type += " ";
482      } else {
483        type = "";
484      }
485      return type + tokenTypes.linkInline;
486    }
487
488    if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) {
489      state.f = state.inline = linkInline;
490      if (modeCfg.highlightFormatting) state.formatting = "link";
491      var type = getType(state);
492      if (type){
493        type += " ";
494      } else {
495        type = "";
496      }
497      return type + tokenTypes.linkEmail;
498    }
499
500    if (ch === '<' && stream.match(/^(!--|\w)/, false)) {
501      var end = stream.string.indexOf(">", stream.pos);
502      if (end != -1) {
503        var atts = stream.string.substring(stream.start, end);
504        if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) state.md_inside = true;
505      }
506      stream.backUp(1);
507      state.htmlState = CodeMirror.startState(htmlMode);
508      return switchBlock(stream, state, htmlBlock);
509    }
510
511    if (ch === '<' && stream.match(/^\/\w*?>/)) {
512      state.md_inside = false;
513      return "tag";
514    }
515
516    var ignoreUnderscore = false;
517    if (!modeCfg.underscoresBreakWords) {
518      if (ch === '_' && stream.peek() !== '_' && stream.match(/(\w)/, false)) {
519        var prevPos = stream.pos - 2;
520        if (prevPos >= 0) {
521          var prevCh = stream.string.charAt(prevPos);
522          if (prevCh !== '_' && prevCh.match(/(\w)/, false)) {
523            ignoreUnderscore = true;
524          }
525        }
526      }
527    }
528    if (ch === '*' || (ch === '_' && !ignoreUnderscore)) {
529      if (sol && stream.peek() === ' ') {
530        // Do nothing, surrounded by newline and space
531      } else if (state.strong === ch && stream.eat(ch)) { // Remove STRONG
532        if (modeCfg.highlightFormatting) state.formatting = "strong";
533        var t = getType(state);
534        state.strong = false;
535        return t;
536      } else if (!state.strong && stream.eat(ch)) { // Add STRONG
537        state.strong = ch;
538        if (modeCfg.highlightFormatting) state.formatting = "strong";
539        return getType(state);
540      } else if (state.em === ch) { // Remove EM
541        if (modeCfg.highlightFormatting) state.formatting = "em";
542        var t = getType(state);
543        state.em = false;
544        return t;
545      } else if (!state.em) { // Add EM
546        state.em = ch;
547        if (modeCfg.highlightFormatting) state.formatting = "em";
548        return getType(state);
549      }
550    } else if (ch === ' ') {
551      if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces
552        if (stream.peek() === ' ') { // Surrounded by spaces, ignore
553          return getType(state);
554        } else { // Not surrounded by spaces, back up pointer
555          stream.backUp(1);
556        }
557      }
558    }
559
560    if (modeCfg.strikethrough) {
561      if (ch === '~' && stream.eatWhile(ch)) {
562        if (state.strikethrough) {// Remove strikethrough
563          if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
564          var t = getType(state);
565          state.strikethrough = false;
566          return t;
567        } else if (stream.match(/^[^\s]/, false)) {// Add strikethrough
568          state.strikethrough = true;
569          if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
570          return getType(state);
571        }
572      } else if (ch === ' ') {
573        if (stream.match(/^~~/, true)) { // Probably surrounded by space
574          if (stream.peek() === ' ') { // Surrounded by spaces, ignore
575            return getType(state);
576          } else { // Not surrounded by spaces, back up pointer
577            stream.backUp(2);
578          }
579        }
580      }
581    }
582
583    if (ch === ' ') {
584      if (stream.match(/ +$/, false)) {
585        state.trailingSpace++;
586      } else if (state.trailingSpace) {
587        state.trailingSpaceNewLine = true;
588      }
589    }
590
591    return getType(state);
592  }
593
594  function linkInline(stream, state) {
595    var ch = stream.next();
596
597    if (ch === ">") {
598      state.f = state.inline = inlineNormal;
599      if (modeCfg.highlightFormatting) state.formatting = "link";
600      var type = getType(state);
601      if (type){
602        type += " ";
603      } else {
604        type = "";
605      }
606      return type + tokenTypes.linkInline;
607    }
608
609    stream.match(/^[^>]+/, true);
610
611    return tokenTypes.linkInline;
612  }
613
614  function linkHref(stream, state) {
615    // Check if space, and return NULL if so (to avoid marking the space)
616    if(stream.eatSpace()){
617      return null;
618    }
619    var ch = stream.next();
620    if (ch === '(' || ch === '[') {
621      state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]", 0);
622      if (modeCfg.highlightFormatting) state.formatting = "link-string";
623      state.linkHref = true;
624      return getType(state);
625    }
626    return 'error';
627  }
628
629  var linkRE = {
630    ")": /^(?:[^\\\(\)]|\\.|\((?:[^\\\(\)]|\\.)*\))*?(?=\))/,
631    "]": /^(?:[^\\\[\]]|\\.|\[(?:[^\\\[\\]]|\\.)*\])*?(?=\])/
632  }
633
634  function getLinkHrefInside(endChar) {
635    return function(stream, state) {
636      var ch = stream.next();
637
638      if (ch === endChar) {
639        state.f = state.inline = inlineNormal;
640        if (modeCfg.highlightFormatting) state.formatting = "link-string";
641        var returnState = getType(state);
642        state.linkHref = false;
643        return returnState;
644      }
645
646      stream.match(linkRE[endChar])
647      state.linkHref = true;
648      return getType(state);
649    };
650  }
651
652  function footnoteLink(stream, state) {
653    if (stream.match(/^([^\]\\]|\\.)*\]:/, false)) {
654      state.f = footnoteLinkInside;
655      stream.next(); // Consume [
656      if (modeCfg.highlightFormatting) state.formatting = "link";
657      state.linkText = true;
658      return getType(state);
659    }
660    return switchInline(stream, state, inlineNormal);
661  }
662
663  function footnoteLinkInside(stream, state) {
664    if (stream.match(/^\]:/, true)) {
665      state.f = state.inline = footnoteUrl;
666      if (modeCfg.highlightFormatting) state.formatting = "link";
667      var returnType = getType(state);
668      state.linkText = false;
669      return returnType;
670    }
671
672    stream.match(/^([^\]\\]|\\.)+/, true);
673
674    return tokenTypes.linkText;
675  }
676
677  function footnoteUrl(stream, state) {
678    // Check if space, and return NULL if so (to avoid marking the space)
679    if(stream.eatSpace()){
680      return null;
681    }
682    // Match URL
683    stream.match(/^[^\s]+/, true);
684    // Check for link title
685    if (stream.peek() === undefined) { // End of line, set flag to check next line
686      state.linkTitle = true;
687    } else { // More content on line, check if link title
688      stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true);
689    }
690    state.f = state.inline = inlineNormal;
691    return tokenTypes.linkHref + " url";
692  }
693
694  var mode = {
695    startState: function() {
696      return {
697        f: blockNormal,
698
699        prevLine: null,
700        thisLine: null,
701
702        block: blockNormal,
703        htmlState: null,
704        indentation: 0,
705
706        inline: inlineNormal,
707        text: handleText,
708
709        formatting: false,
710        linkText: false,
711        linkHref: false,
712        linkTitle: false,
713        code: 0,
714        em: false,
715        strong: false,
716        header: 0,
717        hr: false,
718        taskList: false,
719        list: false,
720        listStack: [],
721        quote: 0,
722        trailingSpace: 0,
723        trailingSpaceNewLine: false,
724        strikethrough: false,
725        fencedChars: null
726      };
727    },
728
729    copyState: function(s) {
730      return {
731        f: s.f,
732
733        prevLine: s.prevLine,
734        thisLine: s.thisLine,
735
736        block: s.block,
737        htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState),
738        indentation: s.indentation,
739
740        localMode: s.localMode,
741        localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null,
742
743        inline: s.inline,
744        text: s.text,
745        formatting: false,
746        linkTitle: s.linkTitle,
747        code: s.code,
748        em: s.em,
749        strong: s.strong,
750        strikethrough: s.strikethrough,
751        header: s.header,
752        hr: s.hr,
753        taskList: s.taskList,
754        list: s.list,
755        listStack: s.listStack.slice(0),
756        quote: s.quote,
757        indentedCode: s.indentedCode,
758        trailingSpace: s.trailingSpace,
759        trailingSpaceNewLine: s.trailingSpaceNewLine,
760        md_inside: s.md_inside,
761        fencedChars: s.fencedChars
762      };
763    },
764
765    token: function(stream, state) {
766
767      // Reset state.formatting
768      state.formatting = false;
769
770      if (stream != state.thisLine) {
771        var forceBlankLine = state.header || state.hr;
772
773        // Reset state.header and state.hr
774        state.header = 0;
775        state.hr = false;
776
777        if (stream.match(/^\s*$/, true) || forceBlankLine) {
778          blankLine(state);
779          if (!forceBlankLine) return null
780          state.prevLine = null
781        }
782
783        state.prevLine = state.thisLine
784        state.thisLine = stream
785
786        // Reset state.taskList
787        state.taskList = false;
788
789        // Reset state.trailingSpace
790        state.trailingSpace = 0;
791        state.trailingSpaceNewLine = false;
792
793        state.f = state.block;
794        var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, '    ').length;
795        state.indentationDiff = Math.min(indentation - state.indentation, 4);
796        state.indentation = state.indentation + state.indentationDiff;
797        if (indentation > 0) return null;
798      }
799      return state.f(stream, state);
800    },
801
802    innerMode: function(state) {
803      if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode};
804      if (state.localState) return {state: state.localState, mode: state.localMode};
805      return {state: state, mode: mode};
806    },
807
808    blankLine: blankLine,
809
810    getType: getType,
811
812    fold: "markdown"
813  };
814  return mode;
815}, "xml");
816
817CodeMirror.defineMIME("text/x-markdown", "markdown");
818
819});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.