mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-27 00:56:20 +00:00
96d4a3ecf7
Due to historical reasons, the code is in subfolder "1". With SVN removal, we place the code back and remove the annoying "1" folder.
760 lines
22 KiB
JavaScript
760 lines
22 KiB
JavaScript
// 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")));
|
|
else if (typeof define == "function" && define.amd) // AMD
|
|
define(["../../lib/codemirror", "../xml/xml"], 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;
|
|
}
|
|
|
|
for (var a in aliases) {
|
|
if (aliases[a] in modes || aliases[a] in mimes)
|
|
modes[a] = aliases[a];
|
|
}
|
|
|
|
return function (lang) {
|
|
return modes[lang] ? CodeMirror.getMode(cmCfg, modes[lang]) : null;
|
|
};
|
|
}());
|
|
|
|
// 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;
|
|
|
|
// Turn on fenced code blocks? ("```" to start/end)
|
|
if (modeCfg.fencedCodeBlocks === undefined) modeCfg.fencedCodeBlocks = false;
|
|
|
|
// Turn on task lists? ("- [ ] " and "- [x] ")
|
|
if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;
|
|
|
|
var codeDepth = 0;
|
|
|
|
var header = 'header'
|
|
, code = 'comment'
|
|
, 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';
|
|
|
|
var hrRE = /^([*\-=_])(?:\s*\1){2,}\s*$/
|
|
, ulRE = /^[*\-+]\s+/
|
|
, olRE = /^[0-9]+\.\s+/
|
|
, taskListRE = /^\[(x| )\](?=\s)/ // Must follow ulRE or olRE
|
|
, atxHeaderRE = /^#+/
|
|
, setextHeaderRE = /^(?:\={1,}|-{1,})$/
|
|
, textRE = /^[^#!\[\]*_\\<>` "'(]+/;
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
// Blocks
|
|
|
|
function blankLine(state) {
|
|
// Reset linkTitle state
|
|
state.linkTitle = false;
|
|
// Reset EM state
|
|
state.em = false;
|
|
// Reset STRONG state
|
|
state.strong = false;
|
|
// Reset state.quote
|
|
state.quote = 0;
|
|
if (!htmlFound && state.f == htmlBlock) {
|
|
state.f = inlineNormal;
|
|
state.block = blockNormal;
|
|
}
|
|
// Reset state.trailingSpace
|
|
state.trailingSpace = 0;
|
|
state.trailingSpaceNewLine = false;
|
|
// Mark this line as blank
|
|
state.thisLineHasContent = false;
|
|
return null;
|
|
}
|
|
|
|
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
|
|
state.indentation -= state.indentationDiff;
|
|
}
|
|
state.list = null;
|
|
} else if (state.list !== false && state.indentation > 0) {
|
|
state.list = null;
|
|
state.listDepth = Math.floor(state.indentation / 4);
|
|
} else if (state.list !== false) { // No longer a list
|
|
state.list = false;
|
|
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 (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 = 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)) {
|
|
return hr;
|
|
} 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;
|
|
}
|
|
state.f = state.inline;
|
|
if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];
|
|
return getType(state);
|
|
} else if (modeCfg.fencedCodeBlocks && stream.match(/^```([\w+#]*)/, true)) {
|
|
// try switching mode
|
|
state.localMode = getMode(RegExp.$1);
|
|
if (state.localMode) state.localState = state.localMode.startState();
|
|
switchBlock(stream, state, local);
|
|
if (modeCfg.highlightFormatting) state.formatting = "code-block";
|
|
state.code = true;
|
|
return getType(state);
|
|
}
|
|
|
|
return switchInline(stream, state, state.inline);
|
|
}
|
|
|
|
function htmlBlock(stream, state) {
|
|
var style = htmlMode.token(stream, state.htmlState);
|
|
if ((htmlFound && state.htmlState.tagStart === null && !state.htmlState.context) ||
|
|
(state.md_inside && stream.current().indexOf(">") > -1)) {
|
|
state.f = inlineNormal;
|
|
state.block = blockNormal;
|
|
state.htmlState = null;
|
|
}
|
|
return style;
|
|
}
|
|
|
|
function local(stream, state) {
|
|
if (stream.sol() && stream.match(/^```/, true)) {
|
|
state.localMode = state.localState = null;
|
|
state.f = inlineNormal;
|
|
state.block = blockNormal;
|
|
if (modeCfg.highlightFormatting) state.formatting = "code-block";
|
|
state.code = true;
|
|
var returnType = getType(state);
|
|
state.code = false;
|
|
return returnType;
|
|
} else if (state.localMode) {
|
|
return state.localMode.token(stream, state.localState);
|
|
} else {
|
|
stream.skipToEnd();
|
|
return code;
|
|
}
|
|
}
|
|
|
|
// Inline
|
|
function getType(state) {
|
|
var styles = [];
|
|
|
|
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.linkText) { styles.push(linktext); }
|
|
|
|
if (state.code) { styles.push(code); }
|
|
|
|
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) {
|
|
styles.push(list1);
|
|
} else if (listMod === 1) {
|
|
styles.push(list2);
|
|
} else {
|
|
styles.push(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();
|
|
|
|
if (ch === '\\') {
|
|
stream.next();
|
|
if (modeCfg.highlightFormatting) {
|
|
var type = getType(state);
|
|
return type ? type + " formatting-escape" : "formatting-escape";
|
|
}
|
|
}
|
|
|
|
// 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 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";
|
|
var t = getType(state);
|
|
var before = stream.pos;
|
|
stream.eatWhile('`');
|
|
var difference = 1 + stream.pos - before;
|
|
if (!state.code) {
|
|
codeDepth = difference;
|
|
state.code = true;
|
|
return getType(state);
|
|
} else {
|
|
if (difference === codeDepth) { // Must be exact
|
|
state.code = false;
|
|
return t;
|
|
}
|
|
state.formatting = previousFormatting;
|
|
return getType(state);
|
|
}
|
|
} else if (state.code) {
|
|
return getType(state);
|
|
}
|
|
|
|
if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
|
|
stream.match(/\[[^\]]*\]/);
|
|
state.inline = state.f = linkHref;
|
|
return image;
|
|
}
|
|
|
|
if (ch === '[' && stream.match(/.*\](\(| ?\[)/, false)) {
|
|
state.linkText = true;
|
|
if (modeCfg.highlightFormatting) state.formatting = "link";
|
|
return getType(state);
|
|
}
|
|
|
|
if (ch === ']' && state.linkText) {
|
|
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 + 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 + linkemail;
|
|
}
|
|
|
|
if (ch === '<' && stream.match(/^\w/, false)) {
|
|
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);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// by vfleaking, ignore _
|
|
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 === ' ') {
|
|
// by vfleaking, ignore _
|
|
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 (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 + 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()){
|
|
return null;
|
|
}
|
|
var ch = stream.next();
|
|
if (ch === '(' || 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(/^[^\]]*\]:/, 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()){
|
|
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 linkhref;
|
|
}
|
|
|
|
var savedInlineRE = [];
|
|
function inlineRE(endChar) {
|
|
if (!savedInlineRE[endChar]) {
|
|
// Escape endChar for RegExp (taken from http://stackoverflow.com/a/494122/526741)
|
|
endChar = (endChar+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
|
|
// Match any non-endChar, escaped character, as well as the closing
|
|
// endChar.
|
|
savedInlineRE[endChar] = new RegExp('^(?:[^\\\\]|\\\\.)*?(' + endChar + ')');
|
|
}
|
|
return savedInlineRE[endChar];
|
|
}
|
|
|
|
var mode = {
|
|
startState: function() {
|
|
return {
|
|
f: blockNormal,
|
|
|
|
prevLineHasContent: false,
|
|
thisLineHasContent: false,
|
|
|
|
block: blockNormal,
|
|
htmlState: null,
|
|
indentation: 0,
|
|
|
|
inline: inlineNormal,
|
|
text: handleText,
|
|
|
|
formatting: false,
|
|
linkText: false,
|
|
linkHref: false,
|
|
linkTitle: false,
|
|
em: false,
|
|
strong: false,
|
|
header: 0,
|
|
taskList: false,
|
|
list: false,
|
|
listDepth: 0,
|
|
quote: 0,
|
|
trailingSpace: 0,
|
|
trailingSpaceNewLine: false
|
|
};
|
|
},
|
|
|
|
copyState: function(s) {
|
|
return {
|
|
f: s.f,
|
|
|
|
prevLineHasContent: s.prevLineHasContent,
|
|
thisLineHasContent: s.thisLineHasContent,
|
|
|
|
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,
|
|
em: s.em,
|
|
strong: s.strong,
|
|
header: s.header,
|
|
taskList: s.taskList,
|
|
list: s.list,
|
|
listDepth: s.listDepth,
|
|
quote: s.quote,
|
|
trailingSpace: s.trailingSpace,
|
|
trailingSpaceNewLine: s.trailingSpaceNewLine,
|
|
md_inside: s.md_inside
|
|
};
|
|
},
|
|
|
|
token: function(stream, state) {
|
|
|
|
// Reset state.formatting
|
|
state.formatting = false;
|
|
|
|
if (stream.sol()) {
|
|
var forceBlankLine = stream.match(/^\s*$/, true) || state.header;
|
|
|
|
// Reset state.header
|
|
state.header = 0;
|
|
|
|
if (forceBlankLine) {
|
|
state.prevLineHasContent = false;
|
|
return blankLine(state);
|
|
} else {
|
|
state.prevLineHasContent = state.thisLineHasContent;
|
|
state.thisLineHasContent = true;
|
|
}
|
|
|
|
// Reset state.taskList
|
|
state.taskList = false;
|
|
|
|
// Reset state.code
|
|
state.code = 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;
|
|
var difference = Math.floor((indentation - state.indentation) / 4) * 4;
|
|
if (difference > 4) difference = 4;
|
|
var adjustedIndentation = state.indentation + difference;
|
|
state.indentationDiff = adjustedIndentation - state.indentation;
|
|
state.indentation = adjustedIndentation;
|
|
if (indentation > 0) return null;
|
|
}
|
|
var result = state.f(stream, state);
|
|
if (stream.start == stream.pos) return this.token(stream, state);
|
|
else return result;
|
|
},
|
|
|
|
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");
|
|
|
|
});
|