Commit | Line | Data |
---|---|---|
44f4c339 | 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others |
373d1232 | 2 | // Distributed under an MIT license: https://codemirror.net/LICENSE |
44f4c339 | 3 | |
837afb80 TD |
4 | (function(mod) { |
5 | if (typeof exports == "object" && typeof module == "object") // CommonJS | |
6 | mod(require("../../lib/codemirror")); | |
7 | else if (typeof define == "function" && define.amd) // AMD | |
8 | define(["../../lib/codemirror"], mod); | |
9 | else // Plain browser env | |
10 | mod(CodeMirror); | |
11 | })(function(CodeMirror) { | |
12 | "use strict"; | |
77b7b761 | 13 | |
373d1232 TD |
14 | var listRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/, |
15 | emptyListRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/, | |
44f4c339 | 16 | unorderedListRE = /[*+-]\s/; |
77b7b761 TD |
17 | |
18 | CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) { | |
837afb80 TD |
19 | if (cm.getOption("disableInput")) return CodeMirror.Pass; |
20 | var ranges = cm.listSelections(), replacements = []; | |
21 | for (var i = 0; i < ranges.length; i++) { | |
44f4c339 | 22 | var pos = ranges[i].head; |
704cb1bf MS |
23 | |
24 | // If we're not in Markdown mode, fall back to normal newlineAndIndent | |
44f4c339 | 25 | var eolState = cm.getStateAfter(pos.line); |
704cb1bf MS |
26 | var inner = CodeMirror.innerMode(cm.getMode(), eolState); |
27 | if (inner.mode.name !== "markdown") { | |
28 | cm.execCommand("newlineAndIndent"); | |
29 | return; | |
30 | } else { | |
31 | eolState = inner.state; | |
32 | } | |
33 | ||
44f4c339 AE |
34 | var inList = eolState.list !== false; |
35 | var inQuote = eolState.quote !== 0; | |
77b7b761 | 36 | |
44f4c339 | 37 | var line = cm.getLine(pos.line), match = listRE.exec(line); |
373d1232 TD |
38 | var cursorBeforeBullet = /^\s*$/.test(line.slice(0, pos.ch)); |
39 | if (!ranges[i].empty() || (!inList && !inQuote) || !match || cursorBeforeBullet) { | |
837afb80 TD |
40 | cm.execCommand("newlineAndIndent"); |
41 | return; | |
42 | } | |
44f4c339 | 43 | if (emptyListRE.test(line)) { |
704cb1bf MS |
44 | var endOfQuote = inQuote && />\s*$/.test(line) |
45 | var endOfList = !/>\s*$/.test(line) | |
46 | if (endOfQuote || endOfList) cm.replaceRange("", { | |
44f4c339 AE |
47 | line: pos.line, ch: 0 |
48 | }, { | |
49 | line: pos.line, ch: pos.ch + 1 | |
50 | }); | |
51 | replacements[i] = "\n"; | |
52 | } else { | |
53 | var indent = match[1], after = match[5]; | |
373d1232 TD |
54 | var numbered = !(unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0); |
55 | var bullet = numbered ? (parseInt(match[3], 10) + 1) + match[4] : match[2].replace("x", " "); | |
44f4c339 | 56 | replacements[i] = "\n" + indent + bullet + after; |
373d1232 TD |
57 | |
58 | if (numbered) incrementRemainingMarkdownListNumbers(cm, pos); | |
44f4c339 | 59 | } |
837afb80 | 60 | } |
77b7b761 | 61 | |
837afb80 | 62 | cm.replaceSelections(replacements); |
77b7b761 | 63 | }; |
373d1232 TD |
64 | |
65 | // Auto-updating Markdown list numbers when a new item is added to the | |
66 | // middle of a list | |
67 | function incrementRemainingMarkdownListNumbers(cm, pos) { | |
68 | var startLine = pos.line, lookAhead = 0, skipCount = 0; | |
69 | var startItem = listRE.exec(cm.getLine(startLine)), startIndent = startItem[1]; | |
70 | ||
71 | do { | |
72 | lookAhead += 1; | |
73 | var nextLineNumber = startLine + lookAhead; | |
74 | var nextLine = cm.getLine(nextLineNumber), nextItem = listRE.exec(nextLine); | |
75 | ||
76 | if (nextItem) { | |
77 | var nextIndent = nextItem[1]; | |
78 | var newNumber = (parseInt(startItem[3], 10) + lookAhead - skipCount); | |
79 | var nextNumber = (parseInt(nextItem[3], 10)), itemNumber = nextNumber; | |
80 | ||
81 | if (startIndent === nextIndent && !isNaN(nextNumber)) { | |
82 | if (newNumber === nextNumber) itemNumber = nextNumber + 1; | |
83 | if (newNumber > nextNumber) itemNumber = newNumber + 1; | |
84 | cm.replaceRange( | |
85 | nextLine.replace(listRE, nextIndent + itemNumber + nextItem[4] + nextItem[5]), | |
86 | { | |
87 | line: nextLineNumber, ch: 0 | |
88 | }, { | |
89 | line: nextLineNumber, ch: nextLine.length | |
90 | }); | |
91 | } else { | |
92 | if (startIndent.length > nextIndent.length) return; | |
704cb1bf | 93 | // This doesn't run if the next line immediately indents, as it is |
373d1232 TD |
94 | // not clear of the users intention (new indented item or same level) |
95 | if ((startIndent.length < nextIndent.length) && (lookAhead === 1)) return; | |
96 | skipCount += 1; | |
97 | } | |
98 | } | |
99 | } while (nextItem); | |
100 | } | |
837afb80 | 101 | }); |