mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-12-23 18:01:51 +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.
324 lines
8.5 KiB
JavaScript
324 lines
8.5 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"));
|
|
else if (typeof define == "function" && define.amd) // AMD
|
|
define(["../../lib/codemirror"], mod);
|
|
else // Plain browser env
|
|
mod(CodeMirror);
|
|
})(function(CodeMirror) {
|
|
"use strict";
|
|
|
|
CodeMirror.defineMode('tiki', function(config) {
|
|
function inBlock(style, terminator, returnTokenizer) {
|
|
return function(stream, state) {
|
|
while (!stream.eol()) {
|
|
if (stream.match(terminator)) {
|
|
state.tokenize = inText;
|
|
break;
|
|
}
|
|
stream.next();
|
|
}
|
|
|
|
if (returnTokenizer) state.tokenize = returnTokenizer;
|
|
|
|
return style;
|
|
};
|
|
}
|
|
|
|
function inLine(style) {
|
|
return function(stream, state) {
|
|
while(!stream.eol()) {
|
|
stream.next();
|
|
}
|
|
state.tokenize = inText;
|
|
return style;
|
|
};
|
|
}
|
|
|
|
function inText(stream, state) {
|
|
function chain(parser) {
|
|
state.tokenize = parser;
|
|
return parser(stream, state);
|
|
}
|
|
|
|
var sol = stream.sol();
|
|
var ch = stream.next();
|
|
|
|
//non start of line
|
|
switch (ch) { //switch is generally much faster than if, so it is used here
|
|
case "{": //plugin
|
|
stream.eat("/");
|
|
stream.eatSpace();
|
|
var tagName = "";
|
|
var c;
|
|
while ((c = stream.eat(/[^\s\u00a0=\"\'\/?(}]/))) tagName += c;
|
|
state.tokenize = inPlugin;
|
|
return "tag";
|
|
break;
|
|
case "_": //bold
|
|
if (stream.eat("_")) {
|
|
return chain(inBlock("strong", "__", inText));
|
|
}
|
|
break;
|
|
case "'": //italics
|
|
if (stream.eat("'")) {
|
|
// Italic text
|
|
return chain(inBlock("em", "''", inText));
|
|
}
|
|
break;
|
|
case "(":// Wiki Link
|
|
if (stream.eat("(")) {
|
|
return chain(inBlock("variable-2", "))", inText));
|
|
}
|
|
break;
|
|
case "[":// Weblink
|
|
return chain(inBlock("variable-3", "]", inText));
|
|
break;
|
|
case "|": //table
|
|
if (stream.eat("|")) {
|
|
return chain(inBlock("comment", "||"));
|
|
}
|
|
break;
|
|
case "-":
|
|
if (stream.eat("=")) {//titleBar
|
|
return chain(inBlock("header string", "=-", inText));
|
|
} else if (stream.eat("-")) {//deleted
|
|
return chain(inBlock("error tw-deleted", "--", inText));
|
|
}
|
|
break;
|
|
case "=": //underline
|
|
if (stream.match("==")) {
|
|
return chain(inBlock("tw-underline", "===", inText));
|
|
}
|
|
break;
|
|
case ":":
|
|
if (stream.eat(":")) {
|
|
return chain(inBlock("comment", "::"));
|
|
}
|
|
break;
|
|
case "^": //box
|
|
return chain(inBlock("tw-box", "^"));
|
|
break;
|
|
case "~": //np
|
|
if (stream.match("np~")) {
|
|
return chain(inBlock("meta", "~/np~"));
|
|
}
|
|
break;
|
|
}
|
|
|
|
//start of line types
|
|
if (sol) {
|
|
switch (ch) {
|
|
case "!": //header at start of line
|
|
if (stream.match('!!!!!')) {
|
|
return chain(inLine("header string"));
|
|
} else if (stream.match('!!!!')) {
|
|
return chain(inLine("header string"));
|
|
} else if (stream.match('!!!')) {
|
|
return chain(inLine("header string"));
|
|
} else if (stream.match('!!')) {
|
|
return chain(inLine("header string"));
|
|
} else {
|
|
return chain(inLine("header string"));
|
|
}
|
|
break;
|
|
case "*": //unordered list line item, or <li /> at start of line
|
|
case "#": //ordered list line item, or <li /> at start of line
|
|
case "+": //ordered list line item, or <li /> at start of line
|
|
return chain(inLine("tw-listitem bracket"));
|
|
break;
|
|
}
|
|
}
|
|
|
|
//stream.eatWhile(/[&{]/); was eating up plugins, turned off to act less like html and more like tiki
|
|
return null;
|
|
}
|
|
|
|
var indentUnit = config.indentUnit;
|
|
|
|
// Return variables for tokenizers
|
|
var pluginName, type;
|
|
function inPlugin(stream, state) {
|
|
var ch = stream.next();
|
|
var peek = stream.peek();
|
|
|
|
if (ch == "}") {
|
|
state.tokenize = inText;
|
|
//type = ch == ")" ? "endPlugin" : "selfclosePlugin"; inPlugin
|
|
return "tag";
|
|
} else if (ch == "(" || ch == ")") {
|
|
return "bracket";
|
|
} else if (ch == "=") {
|
|
type = "equals";
|
|
|
|
if (peek == ">") {
|
|
ch = stream.next();
|
|
peek = stream.peek();
|
|
}
|
|
|
|
//here we detect values directly after equal character with no quotes
|
|
if (!/[\'\"]/.test(peek)) {
|
|
state.tokenize = inAttributeNoQuote();
|
|
}
|
|
//end detect values
|
|
|
|
return "operator";
|
|
} else if (/[\'\"]/.test(ch)) {
|
|
state.tokenize = inAttribute(ch);
|
|
return state.tokenize(stream, state);
|
|
} else {
|
|
stream.eatWhile(/[^\s\u00a0=\"\'\/?]/);
|
|
return "keyword";
|
|
}
|
|
}
|
|
|
|
function inAttribute(quote) {
|
|
return function(stream, state) {
|
|
while (!stream.eol()) {
|
|
if (stream.next() == quote) {
|
|
state.tokenize = inPlugin;
|
|
break;
|
|
}
|
|
}
|
|
return "string";
|
|
};
|
|
}
|
|
|
|
function inAttributeNoQuote() {
|
|
return function(stream, state) {
|
|
while (!stream.eol()) {
|
|
var ch = stream.next();
|
|
var peek = stream.peek();
|
|
if (ch == " " || ch == "," || /[ )}]/.test(peek)) {
|
|
state.tokenize = inPlugin;
|
|
break;
|
|
}
|
|
}
|
|
return "string";
|
|
};
|
|
}
|
|
|
|
var curState, setStyle;
|
|
function pass() {
|
|
for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);
|
|
}
|
|
|
|
function cont() {
|
|
pass.apply(null, arguments);
|
|
return true;
|
|
}
|
|
|
|
function pushContext(pluginName, startOfLine) {
|
|
var noIndent = curState.context && curState.context.noIndent;
|
|
curState.context = {
|
|
prev: curState.context,
|
|
pluginName: pluginName,
|
|
indent: curState.indented,
|
|
startOfLine: startOfLine,
|
|
noIndent: noIndent
|
|
};
|
|
}
|
|
|
|
function popContext() {
|
|
if (curState.context) curState.context = curState.context.prev;
|
|
}
|
|
|
|
function element(type) {
|
|
if (type == "openPlugin") {curState.pluginName = pluginName; return cont(attributes, endplugin(curState.startOfLine));}
|
|
else if (type == "closePlugin") {
|
|
var err = false;
|
|
if (curState.context) {
|
|
err = curState.context.pluginName != pluginName;
|
|
popContext();
|
|
} else {
|
|
err = true;
|
|
}
|
|
if (err) setStyle = "error";
|
|
return cont(endcloseplugin(err));
|
|
}
|
|
else if (type == "string") {
|
|
if (!curState.context || curState.context.name != "!cdata") pushContext("!cdata");
|
|
if (curState.tokenize == inText) popContext();
|
|
return cont();
|
|
}
|
|
else return cont();
|
|
}
|
|
|
|
function endplugin(startOfLine) {
|
|
return function(type) {
|
|
if (
|
|
type == "selfclosePlugin" ||
|
|
type == "endPlugin"
|
|
)
|
|
return cont();
|
|
if (type == "endPlugin") {pushContext(curState.pluginName, startOfLine); return cont();}
|
|
return cont();
|
|
};
|
|
}
|
|
|
|
function endcloseplugin(err) {
|
|
return function(type) {
|
|
if (err) setStyle = "error";
|
|
if (type == "endPlugin") return cont();
|
|
return pass();
|
|
};
|
|
}
|
|
|
|
function attributes(type) {
|
|
if (type == "keyword") {setStyle = "attribute"; return cont(attributes);}
|
|
if (type == "equals") return cont(attvalue, attributes);
|
|
return pass();
|
|
}
|
|
function attvalue(type) {
|
|
if (type == "keyword") {setStyle = "string"; return cont();}
|
|
if (type == "string") return cont(attvaluemaybe);
|
|
return pass();
|
|
}
|
|
function attvaluemaybe(type) {
|
|
if (type == "string") return cont(attvaluemaybe);
|
|
else return pass();
|
|
}
|
|
return {
|
|
startState: function() {
|
|
return {tokenize: inText, cc: [], indented: 0, startOfLine: true, pluginName: null, context: null};
|
|
},
|
|
token: function(stream, state) {
|
|
if (stream.sol()) {
|
|
state.startOfLine = true;
|
|
state.indented = stream.indentation();
|
|
}
|
|
if (stream.eatSpace()) return null;
|
|
|
|
setStyle = type = pluginName = null;
|
|
var style = state.tokenize(stream, state);
|
|
if ((style || type) && style != "comment") {
|
|
curState = state;
|
|
while (true) {
|
|
var comb = state.cc.pop() || element;
|
|
if (comb(type || style)) break;
|
|
}
|
|
}
|
|
state.startOfLine = false;
|
|
return setStyle || style;
|
|
},
|
|
indent: function(state, textAfter) {
|
|
var context = state.context;
|
|
if (context && context.noIndent) return 0;
|
|
if (context && /^{\//.test(textAfter))
|
|
context = context.prev;
|
|
while (context && !context.startOfLine)
|
|
context = context.prev;
|
|
if (context) return context.indent + indentUnit;
|
|
else return 0;
|
|
},
|
|
electricChars: "/"
|
|
};
|
|
});
|
|
|
|
CodeMirror.defineMIME("text/tiki", "tiki");
|
|
|
|
});
|