mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-15 04:48:41 +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.
194 lines
6.3 KiB
JavaScript
194 lines
6.3 KiB
JavaScript
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
|
|
/**
|
|
* @file smartymixed.js
|
|
* @brief Smarty Mixed Codemirror mode (Smarty + Mixed HTML)
|
|
* @author Ruslan Osmanov <rrosmanov at gmail dot com>
|
|
* @version 3.0
|
|
* @date 05.07.2013
|
|
*/
|
|
|
|
// Warning: Don't base other modes on this one. This here is a
|
|
// terrible way to write a mixed mode.
|
|
|
|
(function(mod) {
|
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../smarty/smarty"));
|
|
else if (typeof define == "function" && define.amd) // AMD
|
|
define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../smarty/smarty"], mod);
|
|
else // Plain browser env
|
|
mod(CodeMirror);
|
|
})(function(CodeMirror) {
|
|
"use strict";
|
|
|
|
CodeMirror.defineMode("smartymixed", function(config) {
|
|
var htmlMixedMode = CodeMirror.getMode(config, "htmlmixed");
|
|
var smartyMode = CodeMirror.getMode(config, "smarty");
|
|
|
|
var settings = {
|
|
rightDelimiter: '}',
|
|
leftDelimiter: '{'
|
|
};
|
|
|
|
if (config.hasOwnProperty("leftDelimiter")) {
|
|
settings.leftDelimiter = config.leftDelimiter;
|
|
}
|
|
if (config.hasOwnProperty("rightDelimiter")) {
|
|
settings.rightDelimiter = config.rightDelimiter;
|
|
}
|
|
|
|
function reEsc(str) { return str.replace(/[^\s\w]/g, "\\$&"); }
|
|
|
|
var reLeft = reEsc(settings.leftDelimiter), reRight = reEsc(settings.rightDelimiter);
|
|
var regs = {
|
|
smartyComment: new RegExp("^" + reRight + "\\*"),
|
|
literalOpen: new RegExp(reLeft + "literal" + reRight),
|
|
literalClose: new RegExp(reLeft + "\/literal" + reRight),
|
|
hasLeftDelimeter: new RegExp(".*" + reLeft),
|
|
htmlHasLeftDelimeter: new RegExp("[^<>]*" + reLeft)
|
|
};
|
|
|
|
var helpers = {
|
|
chain: function(stream, state, parser) {
|
|
state.tokenize = parser;
|
|
return parser(stream, state);
|
|
},
|
|
|
|
cleanChain: function(stream, state, parser) {
|
|
state.tokenize = null;
|
|
state.localState = null;
|
|
state.localMode = null;
|
|
return (typeof parser == "string") ? (parser ? parser : null) : parser(stream, state);
|
|
},
|
|
|
|
maybeBackup: function(stream, pat, style) {
|
|
var cur = stream.current();
|
|
var close = cur.search(pat),
|
|
m;
|
|
if (close > - 1) stream.backUp(cur.length - close);
|
|
else if (m = cur.match(/<\/?$/)) {
|
|
stream.backUp(cur.length);
|
|
if (!stream.match(pat, false)) stream.match(cur[0]);
|
|
}
|
|
return style;
|
|
}
|
|
};
|
|
|
|
var parsers = {
|
|
html: function(stream, state) {
|
|
if (!state.inLiteral && stream.match(regs.htmlHasLeftDelimeter, false) && state.htmlMixedState.htmlState.tagName === null) {
|
|
state.tokenize = parsers.smarty;
|
|
state.localMode = smartyMode;
|
|
state.localState = smartyMode.startState(htmlMixedMode.indent(state.htmlMixedState, ""));
|
|
return helpers.maybeBackup(stream, settings.leftDelimiter, smartyMode.token(stream, state.localState));
|
|
} else if (!state.inLiteral && stream.match(settings.leftDelimiter, false)) {
|
|
state.tokenize = parsers.smarty;
|
|
state.localMode = smartyMode;
|
|
state.localState = smartyMode.startState(htmlMixedMode.indent(state.htmlMixedState, ""));
|
|
return helpers.maybeBackup(stream, settings.leftDelimiter, smartyMode.token(stream, state.localState));
|
|
}
|
|
return htmlMixedMode.token(stream, state.htmlMixedState);
|
|
},
|
|
|
|
smarty: function(stream, state) {
|
|
if (stream.match(settings.leftDelimiter, false)) {
|
|
if (stream.match(regs.smartyComment, false)) {
|
|
return helpers.chain(stream, state, parsers.inBlock("comment", "*" + settings.rightDelimiter));
|
|
}
|
|
} else if (stream.match(settings.rightDelimiter, false)) {
|
|
stream.eat(settings.rightDelimiter);
|
|
state.tokenize = parsers.html;
|
|
state.localMode = htmlMixedMode;
|
|
state.localState = state.htmlMixedState;
|
|
return "tag";
|
|
}
|
|
|
|
return helpers.maybeBackup(stream, settings.rightDelimiter, smartyMode.token(stream, state.localState));
|
|
},
|
|
|
|
inBlock: function(style, terminator) {
|
|
return function(stream, state) {
|
|
while (!stream.eol()) {
|
|
if (stream.match(terminator)) {
|
|
helpers.cleanChain(stream, state, "");
|
|
break;
|
|
}
|
|
stream.next();
|
|
}
|
|
return style;
|
|
};
|
|
}
|
|
};
|
|
|
|
return {
|
|
startState: function() {
|
|
var state = htmlMixedMode.startState();
|
|
return {
|
|
token: parsers.html,
|
|
localMode: null,
|
|
localState: null,
|
|
htmlMixedState: state,
|
|
tokenize: null,
|
|
inLiteral: false
|
|
};
|
|
},
|
|
|
|
copyState: function(state) {
|
|
var local = null, tok = (state.tokenize || state.token);
|
|
if (state.localState) {
|
|
local = CodeMirror.copyState((tok != parsers.html ? smartyMode : htmlMixedMode), state.localState);
|
|
}
|
|
return {
|
|
token: state.token,
|
|
tokenize: state.tokenize,
|
|
localMode: state.localMode,
|
|
localState: local,
|
|
htmlMixedState: CodeMirror.copyState(htmlMixedMode, state.htmlMixedState),
|
|
inLiteral: state.inLiteral
|
|
};
|
|
},
|
|
|
|
token: function(stream, state) {
|
|
if (stream.match(settings.leftDelimiter, false)) {
|
|
if (!state.inLiteral && stream.match(regs.literalOpen, true)) {
|
|
state.inLiteral = true;
|
|
return "keyword";
|
|
} else if (state.inLiteral && stream.match(regs.literalClose, true)) {
|
|
state.inLiteral = false;
|
|
return "keyword";
|
|
}
|
|
}
|
|
if (state.inLiteral && state.localState != state.htmlMixedState) {
|
|
state.tokenize = parsers.html;
|
|
state.localMode = htmlMixedMode;
|
|
state.localState = state.htmlMixedState;
|
|
}
|
|
|
|
var style = (state.tokenize || state.token)(stream, state);
|
|
return style;
|
|
},
|
|
|
|
indent: function(state, textAfter) {
|
|
if (state.localMode == smartyMode
|
|
|| (state.inLiteral && !state.localMode)
|
|
|| regs.hasLeftDelimeter.test(textAfter)) {
|
|
return CodeMirror.Pass;
|
|
}
|
|
return htmlMixedMode.indent(state.htmlMixedState, textAfter);
|
|
},
|
|
|
|
innerMode: function(state) {
|
|
return {
|
|
state: state.localState || state.htmlMixedState,
|
|
mode: state.localMode || htmlMixedMode
|
|
};
|
|
}
|
|
};
|
|
}, "htmlmixed", "smarty");
|
|
|
|
CodeMirror.defineMIME("text/x-smarty", "smartymixed");
|
|
// vim: et ts=2 sts=2 sw=2
|
|
|
|
});
|