Updated codemirror to v4.12.
Did a lot of cleanup to limit the size of the plugin. I kept the emmet plugin.
This commit is contained in:
@@ -16,12 +16,12 @@
|
||||
.cm-s-default .cm-trailing-space-new-line:before {position: absolute; content: "\21B5"; color: #777;}
|
||||
</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><img id=logo src="../../doc/logo.png"></a>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/marijnh/codemirror">Code</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
|
||||
+312
-98
@@ -1,46 +1,39 @@
|
||||
// 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 htmlFound = CodeMirror.modes.hasOwnProperty("xml");
|
||||
var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? {name: "xml", htmlMode: true} : "text/plain");
|
||||
var aliases = {
|
||||
html: "htmlmixed",
|
||||
js: "javascript",
|
||||
json: "application/json",
|
||||
c: "text/x-csrc",
|
||||
"c++": "text/x-c++src",
|
||||
java: "text/x-java",
|
||||
csharp: "text/x-csharp",
|
||||
"c#": "text/x-csharp",
|
||||
scala: "text/x-scala"
|
||||
};
|
||||
|
||||
var getMode = (function () {
|
||||
var i, modes = {}, mimes = {}, mime;
|
||||
|
||||
var list = [];
|
||||
for (var m in CodeMirror.modes)
|
||||
if (CodeMirror.modes.propertyIsEnumerable(m)) list.push(m);
|
||||
for (i = 0; i < list.length; i++) {
|
||||
modes[list[i]] = list[i];
|
||||
}
|
||||
var mimesList = [];
|
||||
for (var m in CodeMirror.mimeModes)
|
||||
if (CodeMirror.mimeModes.propertyIsEnumerable(m))
|
||||
mimesList.push({mime: m, mode: CodeMirror.mimeModes[m]});
|
||||
for (i = 0; i < mimesList.length; i++) {
|
||||
mime = mimesList[i].mime;
|
||||
mimes[mime] = mimesList[i].mime;
|
||||
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;
|
||||
}
|
||||
|
||||
for (var a in aliases) {
|
||||
if (aliases[a] in modes || aliases[a] in mimes)
|
||||
modes[a] = aliases[a];
|
||||
}
|
||||
// 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;
|
||||
|
||||
return function (lang) {
|
||||
return modes[lang] ? CodeMirror.getMode(cmCfg, modes[lang]) : null;
|
||||
};
|
||||
}());
|
||||
// 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)
|
||||
@@ -52,30 +45,36 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
// Turn on task lists? ("- [ ] " and "- [x] ")
|
||||
if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;
|
||||
|
||||
// Turn on strikethrough syntax
|
||||
if (modeCfg.strikethrough === undefined)
|
||||
modeCfg.strikethrough = false;
|
||||
|
||||
var codeDepth = 0;
|
||||
|
||||
var header = 'header'
|
||||
, code = 'comment'
|
||||
, quote1 = 'atom'
|
||||
, quote2 = 'number'
|
||||
, quote = 'quote'
|
||||
, list1 = 'variable-2'
|
||||
, list2 = 'variable-3'
|
||||
, list3 = 'keyword'
|
||||
, hr = 'hr'
|
||||
, image = 'tag'
|
||||
, formatting = 'formatting'
|
||||
, linkinline = 'link'
|
||||
, linkemail = 'link'
|
||||
, linktext = 'link'
|
||||
, linkhref = 'string'
|
||||
, em = 'em'
|
||||
, strong = 'strong';
|
||||
, strong = 'strong'
|
||||
, strikethrough = 'strikethrough';
|
||||
|
||||
var hrRE = /^([*\-=_])(?:\s*\1){2,}\s*$/
|
||||
, ulRE = /^[*\-+]\s+/
|
||||
, olRE = /^[0-9]+\.\s+/
|
||||
, taskListRE = /^\[(x| )\](?=\s)/ // Must follow ulRE or olRE
|
||||
, headerRE = /^(?:\={1,}|-{1,})$/
|
||||
, textRE = /^[^!\[\]*_\\<>` "'(]+/;
|
||||
, atxHeaderRE = /^#+/
|
||||
, setextHeaderRE = /^(?:\={1,}|-{1,})$/
|
||||
, textRE = /^[^#!\[\]*_\\<>` "'(~]+/;
|
||||
|
||||
function switchInline(stream, state, f) {
|
||||
state.f = state.inline = f;
|
||||
@@ -97,6 +96,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
state.em = false;
|
||||
// Reset STRONG state
|
||||
state.strong = false;
|
||||
// Reset strikethrough state
|
||||
state.strikethrough = false;
|
||||
// Reset state.quote
|
||||
state.quote = 0;
|
||||
if (!htmlFound && state.f == htmlBlock) {
|
||||
@@ -113,6 +114,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
|
||||
function blockNormal(stream, state) {
|
||||
|
||||
var sol = stream.sol();
|
||||
|
||||
var prevLineIsList = (state.list !== false);
|
||||
if (state.list !== false && state.indentationDiff >= 0) { // Continued list
|
||||
if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block
|
||||
@@ -127,39 +130,58 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
state.listDepth = 0;
|
||||
}
|
||||
|
||||
var match = null;
|
||||
if (state.indentationDiff >= 4) {
|
||||
state.indentation -= 4;
|
||||
stream.skipToEnd();
|
||||
return code;
|
||||
} else if (stream.eatSpace()) {
|
||||
return null;
|
||||
} else if (stream.peek() === '#' || (state.prevLineHasContent && stream.match(headerRE)) ) {
|
||||
state.header = true;
|
||||
} else if (match = stream.match(atxHeaderRE)) {
|
||||
state.header = match[0].length <= 6 ? match[0].length : 6;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "header";
|
||||
state.f = state.inline;
|
||||
return getType(state);
|
||||
} else if (state.prevLineHasContent && (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.indentation++;
|
||||
state.quote = 1;
|
||||
state.quote = sol ? 1 : state.quote + 1;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "quote";
|
||||
stream.eatSpace();
|
||||
while (stream.eat('>')) {
|
||||
stream.eatSpace();
|
||||
state.quote++;
|
||||
}
|
||||
return getType(state);
|
||||
} else if (stream.peek() === '[') {
|
||||
return switchInline(stream, state, footnoteLink);
|
||||
} else if (stream.match(hrRE, true)) {
|
||||
return hr;
|
||||
} else if ((!state.prevLineHasContent || prevLineIsList) && (stream.match(ulRE, true) || stream.match(olRE, true))) {
|
||||
} else if ((!state.prevLineHasContent || 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 += 4;
|
||||
state.list = true;
|
||||
state.listDepth++;
|
||||
if (modeCfg.taskLists && stream.match(taskListRE, false)) {
|
||||
state.taskList = true;
|
||||
}
|
||||
} else if (modeCfg.fencedCodeBlocks && stream.match(/^```([\w+#]*)/, true)) {
|
||||
state.f = state.inline;
|
||||
if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];
|
||||
return getType(state);
|
||||
} else if (modeCfg.fencedCodeBlocks && stream.match(/^```[ \t]*([\w+#]*)/, true)) {
|
||||
// try switching mode
|
||||
state.localMode = getMode(RegExp.$1);
|
||||
if (state.localMode) state.localState = state.localMode.startState();
|
||||
switchBlock(stream, state, local);
|
||||
return code;
|
||||
state.f = state.block = local;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "code-block";
|
||||
state.code = true;
|
||||
return getType(state);
|
||||
}
|
||||
|
||||
return switchInline(stream, state, state.inline);
|
||||
@@ -167,24 +189,20 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
|
||||
function htmlBlock(stream, state) {
|
||||
var style = htmlMode.token(stream, state.htmlState);
|
||||
if (htmlFound && style === 'tag' && state.htmlState.type !== 'openTag' && !state.htmlState.context) {
|
||||
if ((htmlFound && state.htmlState.tagStart === null && !state.htmlState.context) ||
|
||||
(state.md_inside && stream.current().indexOf(">") > -1)) {
|
||||
state.f = inlineNormal;
|
||||
state.block = blockNormal;
|
||||
}
|
||||
if (state.md_inside && stream.current().indexOf(">")!=-1) {
|
||||
state.f = inlineNormal;
|
||||
state.block = blockNormal;
|
||||
state.htmlState.context = undefined;
|
||||
state.htmlState = null;
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
function local(stream, state) {
|
||||
if (stream.sol() && stream.match(/^```/, true)) {
|
||||
if (stream.sol() && stream.match("```", false)) {
|
||||
state.localMode = state.localState = null;
|
||||
state.f = inlineNormal;
|
||||
state.block = blockNormal;
|
||||
return code;
|
||||
state.f = state.block = leavingLocal;
|
||||
return null;
|
||||
} else if (state.localMode) {
|
||||
return state.localMode.token(stream, state.localState);
|
||||
} else {
|
||||
@@ -193,22 +211,80 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
}
|
||||
}
|
||||
|
||||
function leavingLocal(stream, state) {
|
||||
stream.match("```");
|
||||
state.block = blockNormal;
|
||||
state.f = inlineNormal;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "code-block";
|
||||
state.code = true;
|
||||
var returnType = getType(state);
|
||||
state.code = false;
|
||||
return returnType;
|
||||
}
|
||||
|
||||
// Inline
|
||||
function getType(state) {
|
||||
var styles = [];
|
||||
|
||||
if (state.taskOpen) { return "meta"; }
|
||||
if (state.taskClosed) { return "property"; }
|
||||
if (state.formatting) {
|
||||
styles.push(formatting);
|
||||
|
||||
if (typeof state.formatting === "string") state.formatting = [state.formatting];
|
||||
|
||||
for (var i = 0; i < state.formatting.length; i++) {
|
||||
styles.push(formatting + "-" + state.formatting[i]);
|
||||
|
||||
if (state.formatting[i] === "header") {
|
||||
styles.push(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(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(linkhref);
|
||||
return styles.length ? styles.join(' ') : null;
|
||||
}
|
||||
|
||||
if (state.strong) { styles.push(strong); }
|
||||
if (state.em) { styles.push(em); }
|
||||
if (state.strikethrough) { styles.push(strikethrough); }
|
||||
|
||||
if (state.linkText) { styles.push(linktext); }
|
||||
|
||||
if (state.code) { styles.push(code); }
|
||||
|
||||
if (state.header) { styles.push(header); }
|
||||
if (state.quote) { styles.push(state.quote % 2 ? quote1 : quote2); }
|
||||
if (state.header) { styles.push(header); styles.push(header + "-" + state.header); }
|
||||
|
||||
if (state.quote) {
|
||||
styles.push(quote);
|
||||
|
||||
// Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth
|
||||
if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
|
||||
styles.push(quote + "-" + state.quote);
|
||||
} else {
|
||||
styles.push(quote + "-" + modeCfg.maxBlockquoteDepth);
|
||||
}
|
||||
}
|
||||
|
||||
if (state.list !== false) {
|
||||
var listMod = (state.listDepth - 1) % 3;
|
||||
if (!listMod) {
|
||||
@@ -250,6 +326,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
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);
|
||||
}
|
||||
@@ -257,11 +334,22 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
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();
|
||||
|
||||
if (ch === '\\') {
|
||||
stream.next();
|
||||
return getType(state);
|
||||
if (modeCfg.highlightFormatting) {
|
||||
var type = getType(state);
|
||||
return type ? type + " formatting-escape" : "formatting-escape";
|
||||
}
|
||||
}
|
||||
|
||||
// Matches link titles present on next line
|
||||
@@ -280,6 +368,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
|
||||
// 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";
|
||||
var t = getType(state);
|
||||
var before = stream.pos;
|
||||
stream.eatWhile('`');
|
||||
@@ -293,6 +383,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
state.code = false;
|
||||
return t;
|
||||
}
|
||||
state.formatting = previousFormatting;
|
||||
return getType(state);
|
||||
}
|
||||
} else if (state.code) {
|
||||
@@ -305,12 +396,14 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
return image;
|
||||
}
|
||||
|
||||
if (ch === '[' && stream.match(/.*\](\(| ?\[)/, false)) {
|
||||
if (ch === '[' && stream.match(/.*\](\(.*\)| ?\[.*\])/, false)) {
|
||||
state.linkText = true;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||
return getType(state);
|
||||
}
|
||||
|
||||
if (ch === ']' && state.linkText) {
|
||||
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;
|
||||
@@ -318,21 +411,38 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
}
|
||||
|
||||
if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) {
|
||||
return switchInline(stream, state, inlineElement(linkinline, '>'));
|
||||
state.f = state.inline = linkInline;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||
var type = getType(state);
|
||||
if (type){
|
||||
type += " ";
|
||||
} else {
|
||||
type = "";
|
||||
}
|
||||
return type + linkinline;
|
||||
}
|
||||
|
||||
if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) {
|
||||
return switchInline(stream, state, inlineElement(linkemail, '>'));
|
||||
state.f = state.inline = linkInline;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||
var type = getType(state);
|
||||
if (type){
|
||||
type += " ";
|
||||
} else {
|
||||
type = "";
|
||||
}
|
||||
return type + linkemail;
|
||||
}
|
||||
|
||||
if (ch === '<' && stream.match(/^\w/, false)) {
|
||||
if (stream.string.indexOf(">")!=-1) {
|
||||
if (stream.string.indexOf(">") != -1) {
|
||||
var atts = stream.string.substring(1,stream.string.indexOf(">"));
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -353,19 +463,26 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
}
|
||||
}
|
||||
}
|
||||
var t = getType(state);
|
||||
if (ch === '*' || (ch === '_' && !ignoreUnderscore)) {
|
||||
if (state.strong === ch && stream.eat(ch)) { // Remove STRONG
|
||||
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 === ' ') {
|
||||
@@ -378,6 +495,29 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
}
|
||||
}
|
||||
|
||||
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++;
|
||||
@@ -389,6 +529,26 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
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 + linkinline;
|
||||
}
|
||||
|
||||
stream.match(/^[^>]+/, true);
|
||||
|
||||
return linkinline;
|
||||
}
|
||||
|
||||
function linkHref(stream, state) {
|
||||
// Check if space, and return NULL if so (to avoid marking the space)
|
||||
if(stream.eatSpace()){
|
||||
@@ -396,19 +556,60 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
}
|
||||
var ch = stream.next();
|
||||
if (ch === '(' || ch === '[') {
|
||||
return switchInline(stream, state, inlineElement(linkhref, ch === '(' ? ')' : ']'));
|
||||
state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]");
|
||||
if (modeCfg.highlightFormatting) state.formatting = "link-string";
|
||||
state.linkHref = true;
|
||||
return getType(state);
|
||||
}
|
||||
return 'error';
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (stream.match(inlineRE(endChar), true)) {
|
||||
stream.backUp(1);
|
||||
}
|
||||
|
||||
state.linkHref = true;
|
||||
return getType(state);
|
||||
};
|
||||
}
|
||||
|
||||
function footnoteLink(stream, state) {
|
||||
if (stream.match(/^[^\]]*\]:/, true)) {
|
||||
state.f = footnoteUrl;
|
||||
return linktext;
|
||||
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 linktext;
|
||||
}
|
||||
|
||||
function footnoteUrl(stream, state) {
|
||||
// Check if space, and return NULL if so (to avoid marking the space)
|
||||
if(stream.eatSpace()){
|
||||
@@ -438,16 +639,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
return savedInlineRE[endChar];
|
||||
}
|
||||
|
||||
function inlineElement(type, endChar, next) {
|
||||
next = next || inlineNormal;
|
||||
return function(stream, state) {
|
||||
stream.match(inlineRE(endChar));
|
||||
state.inline = state.f = next;
|
||||
return type;
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
var mode = {
|
||||
startState: function() {
|
||||
return {
|
||||
f: blockNormal,
|
||||
@@ -456,23 +648,26 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
thisLineHasContent: false,
|
||||
|
||||
block: blockNormal,
|
||||
htmlState: CodeMirror.startState(htmlMode),
|
||||
htmlState: null,
|
||||
indentation: 0,
|
||||
|
||||
inline: inlineNormal,
|
||||
text: handleText,
|
||||
|
||||
formatting: false,
|
||||
linkText: false,
|
||||
linkHref: false,
|
||||
linkTitle: false,
|
||||
em: false,
|
||||
strong: false,
|
||||
header: false,
|
||||
header: 0,
|
||||
taskList: false,
|
||||
list: false,
|
||||
listDepth: 0,
|
||||
quote: 0,
|
||||
trailingSpace: 0,
|
||||
trailingSpaceNewLine: false
|
||||
trailingSpaceNewLine: false,
|
||||
strikethrough: false
|
||||
};
|
||||
},
|
||||
|
||||
@@ -484,7 +679,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
thisLineHasContent: s.thisLineHasContent,
|
||||
|
||||
block: s.block,
|
||||
htmlState: CodeMirror.copyState(htmlMode, s.htmlState),
|
||||
htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState),
|
||||
indentation: s.indentation,
|
||||
|
||||
localMode: s.localMode,
|
||||
@@ -492,9 +687,11 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
|
||||
inline: s.inline,
|
||||
text: s.text,
|
||||
formatting: false,
|
||||
linkTitle: s.linkTitle,
|
||||
em: s.em,
|
||||
strong: s.strong,
|
||||
strikethrough: s.strikethrough,
|
||||
header: s.header,
|
||||
taskList: s.taskList,
|
||||
list: s.list,
|
||||
@@ -507,18 +704,25 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
|
||||
// Reset state.formatting
|
||||
state.formatting = false;
|
||||
|
||||
if (stream.sol()) {
|
||||
if (stream.match(/^\s*$/, true)) {
|
||||
var forceBlankLine = !!state.header;
|
||||
|
||||
// Reset state.header
|
||||
state.header = 0;
|
||||
|
||||
if (stream.match(/^\s*$/, true) || forceBlankLine) {
|
||||
state.prevLineHasContent = false;
|
||||
return blankLine(state);
|
||||
blankLine(state);
|
||||
return forceBlankLine ? this.token(stream, state) : null;
|
||||
} else {
|
||||
state.prevLineHasContent = state.thisLineHasContent;
|
||||
state.thisLineHasContent = true;
|
||||
}
|
||||
|
||||
// Reset state.header
|
||||
state.header = false;
|
||||
|
||||
// Reset state.taskList
|
||||
state.taskList = false;
|
||||
|
||||
@@ -541,11 +745,21 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
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
|
||||
};
|
||||
getType: getType,
|
||||
|
||||
fold: "markdown"
|
||||
};
|
||||
return mode;
|
||||
}, "xml");
|
||||
|
||||
CodeMirror.defineMIME("text/x-markdown", "markdown");
|
||||
|
||||
});
|
||||
|
||||
+126
-28
@@ -1,6 +1,60 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function() {
|
||||
var mode = CodeMirror.getMode({tabSize: 4}, "markdown");
|
||||
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
|
||||
var modeHighlightFormatting = CodeMirror.getMode({tabSize: 4}, {name: "markdown", highlightFormatting: true});
|
||||
function FT(name) { test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1)); }
|
||||
|
||||
FT("formatting_emAsterisk",
|
||||
"[em&formatting&formatting-em *][em foo][em&formatting&formatting-em *]");
|
||||
|
||||
FT("formatting_emUnderscore",
|
||||
"[em&formatting&formatting-em _][em foo][em&formatting&formatting-em _]");
|
||||
|
||||
FT("formatting_strongAsterisk",
|
||||
"[strong&formatting&formatting-strong **][strong foo][strong&formatting&formatting-strong **]");
|
||||
|
||||
FT("formatting_strongUnderscore",
|
||||
"[strong&formatting&formatting-strong __][strong foo][strong&formatting&formatting-strong __]");
|
||||
|
||||
FT("formatting_codeBackticks",
|
||||
"[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]");
|
||||
|
||||
FT("formatting_doubleBackticks",
|
||||
"[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]");
|
||||
|
||||
FT("formatting_atxHeader",
|
||||
"[header&header-1&formatting&formatting-header&formatting-header-1 #][header&header-1 foo # bar ][header&header-1&formatting&formatting-header&formatting-header-1 #]");
|
||||
|
||||
FT("formatting_setextHeader",
|
||||
"foo",
|
||||
"[header&header-1&formatting&formatting-header&formatting-header-1 =]");
|
||||
|
||||
FT("formatting_blockquote",
|
||||
"[quote"e-1&formatting&formatting-quote&formatting-quote-1 > ][quote"e-1 foo]");
|
||||
|
||||
FT("formatting_list",
|
||||
"[variable-2&formatting&formatting-list&formatting-list-ul - ][variable-2 foo]");
|
||||
FT("formatting_list",
|
||||
"[variable-2&formatting&formatting-list&formatting-list-ol 1. ][variable-2 foo]");
|
||||
|
||||
FT("formatting_link",
|
||||
"[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string (][string http://example.com/][string&formatting&formatting-link-string )]");
|
||||
|
||||
FT("formatting_linkReference",
|
||||
"[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string [][string bar][string&formatting&formatting-link-string ]]]",
|
||||
"[link&formatting&formatting-link [][link bar][link&formatting&formatting-link ]]:] [string http://example.com/]");
|
||||
|
||||
FT("formatting_linkWeb",
|
||||
"[link&formatting&formatting-link <][link http://example.com/][link&formatting&formatting-link >]");
|
||||
|
||||
FT("formatting_linkEmail",
|
||||
"[link&formatting&formatting-link <][link user@example.com][link&formatting&formatting-link >]");
|
||||
|
||||
FT("formatting_escape",
|
||||
"[formatting-escape \\*]");
|
||||
|
||||
MT("plainText",
|
||||
"foo");
|
||||
@@ -38,6 +92,14 @@
|
||||
" [comment hello]",
|
||||
" [comment world]");
|
||||
|
||||
// Code blocks should end even after extra indented lines
|
||||
MT("codeBlocksWithTrailingIndentedLine",
|
||||
" [comment foo]",
|
||||
" [comment bar]",
|
||||
" [comment baz]",
|
||||
" ",
|
||||
"hello");
|
||||
|
||||
// Code blocks using 1 tab (regardless of CodeMirror.indentWithTabs value)
|
||||
MT("codeBlocksUsing1Tab",
|
||||
"\t[comment foo]");
|
||||
@@ -87,27 +149,31 @@
|
||||
// http://daringfireball.net/projects/markdown/syntax#header
|
||||
|
||||
MT("atxH1",
|
||||
"[header # foo]");
|
||||
"[header&header-1 # foo]");
|
||||
|
||||
MT("atxH2",
|
||||
"[header ## foo]");
|
||||
"[header&header-2 ## foo]");
|
||||
|
||||
MT("atxH3",
|
||||
"[header ### foo]");
|
||||
"[header&header-3 ### foo]");
|
||||
|
||||
MT("atxH4",
|
||||
"[header #### foo]");
|
||||
"[header&header-4 #### foo]");
|
||||
|
||||
MT("atxH5",
|
||||
"[header ##### foo]");
|
||||
"[header&header-5 ##### foo]");
|
||||
|
||||
MT("atxH6",
|
||||
"[header ###### foo]");
|
||||
"[header&header-6 ###### foo]");
|
||||
|
||||
// H6 - 7x '#' should still be H6, per Dingus
|
||||
// http://daringfireball.net/projects/markdown/dingus
|
||||
MT("atxH6NotH7",
|
||||
"[header ####### foo]");
|
||||
"[header&header-6 ####### foo]");
|
||||
|
||||
// Inline styles should be parsed inside headers
|
||||
MT("atxH1inline",
|
||||
"[header&header-1 # foo ][header&header-1&em *bar*]");
|
||||
|
||||
// Setext headers - H1, H2
|
||||
// Per documentation, "Any number of underlining =’s or -’s will work."
|
||||
@@ -119,69 +185,69 @@
|
||||
// Check if single underlining = works
|
||||
MT("setextH1",
|
||||
"foo",
|
||||
"[header =]");
|
||||
"[header&header-1 =]");
|
||||
|
||||
// Check if 3+ ='s work
|
||||
MT("setextH1",
|
||||
"foo",
|
||||
"[header ===]");
|
||||
"[header&header-1 ===]");
|
||||
|
||||
// Check if single underlining - works
|
||||
MT("setextH2",
|
||||
"foo",
|
||||
"[header -]");
|
||||
"[header&header-2 -]");
|
||||
|
||||
// Check if 3+ -'s work
|
||||
MT("setextH2",
|
||||
"foo",
|
||||
"[header ---]");
|
||||
"[header&header-2 ---]");
|
||||
|
||||
// Single-line blockquote with trailing space
|
||||
MT("blockquoteSpace",
|
||||
"[atom > foo]");
|
||||
"[quote"e-1 > foo]");
|
||||
|
||||
// Single-line blockquote
|
||||
MT("blockquoteNoSpace",
|
||||
"[atom >foo]");
|
||||
"[quote"e-1 >foo]");
|
||||
|
||||
// No blank line before blockquote
|
||||
MT("blockquoteNoBlankLine",
|
||||
"foo",
|
||||
"[atom > bar]");
|
||||
"[quote"e-1 > bar]");
|
||||
|
||||
// Nested blockquote
|
||||
MT("blockquoteSpace",
|
||||
"[atom > foo]",
|
||||
"[number > > foo]",
|
||||
"[atom > > > foo]");
|
||||
"[quote"e-1 > foo]",
|
||||
"[quote"e-1 >][quote"e-2 > foo]",
|
||||
"[quote"e-1 >][quote"e-2 >][quote"e-3 > foo]");
|
||||
|
||||
// Single-line blockquote followed by normal paragraph
|
||||
MT("blockquoteThenParagraph",
|
||||
"[atom >foo]",
|
||||
"[quote"e-1 >foo]",
|
||||
"",
|
||||
"bar");
|
||||
|
||||
// Multi-line blockquote (lazy mode)
|
||||
MT("multiBlockquoteLazy",
|
||||
"[atom >foo]",
|
||||
"[atom bar]");
|
||||
"[quote"e-1 >foo]",
|
||||
"[quote"e-1 bar]");
|
||||
|
||||
// Multi-line blockquote followed by normal paragraph (lazy mode)
|
||||
MT("multiBlockquoteLazyThenParagraph",
|
||||
"[atom >foo]",
|
||||
"[atom bar]",
|
||||
"[quote"e-1 >foo]",
|
||||
"[quote"e-1 bar]",
|
||||
"",
|
||||
"hello");
|
||||
|
||||
// Multi-line blockquote (non-lazy mode)
|
||||
MT("multiBlockquote",
|
||||
"[atom >foo]",
|
||||
"[atom >bar]");
|
||||
"[quote"e-1 >foo]",
|
||||
"[quote"e-1 >bar]");
|
||||
|
||||
// Multi-line blockquote followed by normal paragraph (non-lazy mode)
|
||||
MT("multiBlockquoteThenParagraph",
|
||||
"[atom >foo]",
|
||||
"[atom >bar]",
|
||||
"[quote"e-1 >foo]",
|
||||
"[quote"e-1 >bar]",
|
||||
"",
|
||||
"hello");
|
||||
|
||||
@@ -221,6 +287,11 @@
|
||||
"1. bar",
|
||||
"2. hello");
|
||||
|
||||
// List after header
|
||||
MT("listAfterHeader",
|
||||
"[header&header-1 # foo]",
|
||||
"[variable-2 - bar]");
|
||||
|
||||
// Formatting in lists (*)
|
||||
MT("listAsteriskFormatting",
|
||||
"[variable-2 * ][variable-2&em *foo*][variable-2 bar]",
|
||||
@@ -306,7 +377,7 @@
|
||||
"",
|
||||
"[variable-2 * bar]",
|
||||
"",
|
||||
" [variable-2&atom > hello]");
|
||||
" [variable-2"e"e-1 > hello]");
|
||||
|
||||
// Code block
|
||||
MT("blockquoteCode",
|
||||
@@ -364,7 +435,7 @@
|
||||
"",
|
||||
" [variable-3 + bar]",
|
||||
"",
|
||||
" [atom&variable-3 > hello]");
|
||||
" [quote"e-1&variable-3 > hello]");
|
||||
|
||||
MT("listCode",
|
||||
"[variable-2 * foo]",
|
||||
@@ -577,6 +648,10 @@
|
||||
MT("emEscapedBySpaceOut",
|
||||
"foo _ bar[em _hello_]world");
|
||||
|
||||
MT("emEscapedByNewline",
|
||||
"foo",
|
||||
"_ bar[em _hello_]world");
|
||||
|
||||
// Unclosed emphasis characters
|
||||
// Instead of simply marking as EM / STRONG, it would be nice to have an
|
||||
// incomplete flag for EM and STRONG, that is styled slightly different.
|
||||
@@ -643,6 +718,10 @@
|
||||
MT("doubleEscapeHash",
|
||||
"\\\\# foo");
|
||||
|
||||
MT("escapeNewline",
|
||||
"\\",
|
||||
"[em *foo*]");
|
||||
|
||||
|
||||
// Tests to make sure GFM-specific things aren't getting through
|
||||
|
||||
@@ -653,4 +732,23 @@
|
||||
"[comment ```]",
|
||||
"foo",
|
||||
"[comment ```]");
|
||||
|
||||
// Tests that require XML mode
|
||||
|
||||
MT("xmlMode",
|
||||
"[tag&bracket <][tag div][tag&bracket >]",
|
||||
"*foo*",
|
||||
"[tag&bracket <][tag http://github.com][tag&bracket />]",
|
||||
"[tag&bracket </][tag div][tag&bracket >]",
|
||||
"[link <http://github.com/>]");
|
||||
|
||||
MT("xmlModeWithMarkdownInside",
|
||||
"[tag&bracket <][tag div] [attribute markdown]=[string 1][tag&bracket >]",
|
||||
"[em *foo*]",
|
||||
"[link <http://github.com/>]",
|
||||
"[tag </div>]",
|
||||
"[link <http://github.com/>]",
|
||||
"[tag&bracket <][tag div][tag&bracket >]",
|
||||
"[tag&bracket </][tag div][tag&bracket >]");
|
||||
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user