-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds a fairly basic configuration suited for markdown. We can do syntax highlighting for more languages in embedded code blocks by including more modes, but it's already 7 separate source files -- we probably need to package it up if we want more (or dynamically load them). Closes #76
- Loading branch information
Showing
11 changed files
with
12,052 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// CodeMirror, copyright (c) by Marijn Haverbeke and others | ||
// Distributed under an MIT license: https://codemirror.net/LICENSE | ||
|
||
(function(mod) { | ||
if (typeof exports == "object" && typeof module == "object") // CommonJS | ||
mod(require("../../lib/codemirror")); | ||
else if (typeof define == "function" && define.amd) // AMD | ||
define(["../../lib/codemirror"], mod); | ||
else // Plain browser env | ||
mod(CodeMirror); | ||
})(function(CodeMirror) { | ||
"use strict"; | ||
|
||
var listRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/, | ||
emptyListRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/, | ||
unorderedListRE = /[*+-]\s/; | ||
|
||
CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) { | ||
if (cm.getOption("disableInput")) return CodeMirror.Pass; | ||
var ranges = cm.listSelections(), replacements = []; | ||
for (var i = 0; i < ranges.length; i++) { | ||
var pos = ranges[i].head; | ||
|
||
// If we're not in Markdown mode, fall back to normal newlineAndIndent | ||
var eolState = cm.getStateAfter(pos.line); | ||
var inner = CodeMirror.innerMode(cm.getMode(), eolState); | ||
if (inner.mode.name !== "markdown") { | ||
cm.execCommand("newlineAndIndent"); | ||
return; | ||
} else { | ||
eolState = inner.state; | ||
} | ||
|
||
var inList = eolState.list !== false; | ||
var inQuote = eolState.quote !== 0; | ||
|
||
var line = cm.getLine(pos.line), match = listRE.exec(line); | ||
var cursorBeforeBullet = /^\s*$/.test(line.slice(0, pos.ch)); | ||
if (!ranges[i].empty() || (!inList && !inQuote) || !match || cursorBeforeBullet) { | ||
cm.execCommand("newlineAndIndent"); | ||
return; | ||
} | ||
if (emptyListRE.test(line)) { | ||
var endOfQuote = inQuote && />\s*$/.test(line) | ||
var endOfList = !/>\s*$/.test(line) | ||
if (endOfQuote || endOfList) cm.replaceRange("", { | ||
line: pos.line, ch: 0 | ||
}, { | ||
line: pos.line, ch: pos.ch + 1 | ||
}); | ||
replacements[i] = "\n"; | ||
} else { | ||
var indent = match[1], after = match[5]; | ||
var numbered = !(unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0); | ||
var bullet = numbered ? (parseInt(match[3], 10) + 1) + match[4] : match[2].replace("x", " "); | ||
replacements[i] = "\n" + indent + bullet + after; | ||
|
||
if (numbered) incrementRemainingMarkdownListNumbers(cm, pos); | ||
} | ||
} | ||
|
||
cm.replaceSelections(replacements); | ||
}; | ||
|
||
// Auto-updating Markdown list numbers when a new item is added to the | ||
// middle of a list | ||
function incrementRemainingMarkdownListNumbers(cm, pos) { | ||
var startLine = pos.line, lookAhead = 0, skipCount = 0; | ||
var startItem = listRE.exec(cm.getLine(startLine)), startIndent = startItem[1]; | ||
|
||
do { | ||
lookAhead += 1; | ||
var nextLineNumber = startLine + lookAhead; | ||
var nextLine = cm.getLine(nextLineNumber), nextItem = listRE.exec(nextLine); | ||
|
||
if (nextItem) { | ||
var nextIndent = nextItem[1]; | ||
var newNumber = (parseInt(startItem[3], 10) + lookAhead - skipCount); | ||
var nextNumber = (parseInt(nextItem[3], 10)), itemNumber = nextNumber; | ||
|
||
if (startIndent === nextIndent && !isNaN(nextNumber)) { | ||
if (newNumber === nextNumber) itemNumber = nextNumber + 1; | ||
if (newNumber > nextNumber) itemNumber = newNumber + 1; | ||
cm.replaceRange( | ||
nextLine.replace(listRE, nextIndent + itemNumber + nextItem[4] + nextItem[5]), | ||
{ | ||
line: nextLineNumber, ch: 0 | ||
}, { | ||
line: nextLineNumber, ch: nextLine.length | ||
}); | ||
} else { | ||
if (startIndent.length > nextIndent.length) return; | ||
// This doesn't run if the next line immediately indents, as it is | ||
// not clear of the users intention (new indented item or same level) | ||
if ((startIndent.length < nextIndent.length) && (lookAhead === 1)) return; | ||
skipCount += 1; | ||
} | ||
} | ||
} while (nextItem); | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// CodeMirror, copyright (c) by Marijn Haverbeke and others | ||
// Distributed under an MIT license: https://codemirror.net/LICENSE | ||
|
||
// Utility function that allows modes to be combined. The mode given | ||
// as the base argument takes care of most of the normal mode | ||
// functionality, but a second (typically simple) mode is used, which | ||
// can override the style of text. Both modes get to parse all of the | ||
// text, but when both assign a non-null style to a piece of code, the | ||
// overlay wins, unless the combine argument was true and not overridden, | ||
// or state.overlay.combineTokens was true, in which case the styles are | ||
// combined. | ||
|
||
(function(mod) { | ||
if (typeof exports == "object" && typeof module == "object") // CommonJS | ||
mod(require("../../lib/codemirror")); | ||
else if (typeof define == "function" && define.amd) // AMD | ||
define(["../../lib/codemirror"], mod); | ||
else // Plain browser env | ||
mod(CodeMirror); | ||
})(function(CodeMirror) { | ||
"use strict"; | ||
|
||
CodeMirror.overlayMode = function(base, overlay, combine) { | ||
return { | ||
startState: function() { | ||
return { | ||
base: CodeMirror.startState(base), | ||
overlay: CodeMirror.startState(overlay), | ||
basePos: 0, baseCur: null, | ||
overlayPos: 0, overlayCur: null, | ||
streamSeen: null | ||
}; | ||
}, | ||
copyState: function(state) { | ||
return { | ||
base: CodeMirror.copyState(base, state.base), | ||
overlay: CodeMirror.copyState(overlay, state.overlay), | ||
basePos: state.basePos, baseCur: null, | ||
overlayPos: state.overlayPos, overlayCur: null | ||
}; | ||
}, | ||
|
||
token: function(stream, state) { | ||
if (stream != state.streamSeen || | ||
Math.min(state.basePos, state.overlayPos) < stream.start) { | ||
state.streamSeen = stream; | ||
state.basePos = state.overlayPos = stream.start; | ||
} | ||
|
||
if (stream.start == state.basePos) { | ||
state.baseCur = base.token(stream, state.base); | ||
state.basePos = stream.pos; | ||
} | ||
if (stream.start == state.overlayPos) { | ||
stream.pos = stream.start; | ||
state.overlayCur = overlay.token(stream, state.overlay); | ||
state.overlayPos = stream.pos; | ||
} | ||
stream.pos = Math.min(state.basePos, state.overlayPos); | ||
|
||
// state.overlay.combineTokens always takes precedence over combine, | ||
// unless set to null | ||
if (state.overlayCur == null) return state.baseCur; | ||
else if (state.baseCur != null && | ||
state.overlay.combineTokens || | ||
combine && state.overlay.combineTokens == null) | ||
return state.baseCur + " " + state.overlayCur; | ||
else return state.overlayCur; | ||
}, | ||
|
||
indent: base.indent && function(state, textAfter, line) { | ||
return base.indent(state.base, textAfter, line); | ||
}, | ||
electricChars: base.electricChars, | ||
|
||
innerMode: function(state) { return {state: state.base, mode: base}; }, | ||
|
||
blankLine: function(state) { | ||
var baseToken, overlayToken; | ||
if (base.blankLine) baseToken = base.blankLine(state.base); | ||
if (overlay.blankLine) overlayToken = overlay.blankLine(state.overlay); | ||
|
||
return overlayToken == null ? | ||
baseToken : | ||
(combine && baseToken != null ? baseToken + " " + overlayToken : overlayToken); | ||
} | ||
}; | ||
}; | ||
|
||
}); |
Oops, something went wrong.