Blame | Letzte Änderung | Log anzeigen | RSS feed
// 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") // CommonJSmod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"),require("../../addon/mode/overlay"));else if (typeof define == "function" && define.amd) // AMDdefine(["../../lib/codemirror", "../htmlmixed/htmlmixed","../../addon/mode/overlay"], mod);else // Plain browser envmod(CodeMirror);})(function(CodeMirror) {"use strict";CodeMirror.defineMode("django:inner", function() {var keywords = ["block", "endblock", "for", "endfor", "true", "false","loop", "none", "self", "super", "if", "endif", "as","else", "import", "with", "endwith", "without", "context", "ifequal", "endifequal","ifnotequal", "endifnotequal", "extends", "include", "load", "comment","endcomment", "empty", "url", "static", "trans", "blocktrans", "now", "regroup","lorem", "ifchanged", "endifchanged", "firstof", "debug", "cycle", "csrf_token","autoescape", "endautoescape", "spaceless", "ssi", "templatetag","verbatim", "endverbatim", "widthratio"],filters = ["add", "addslashes", "capfirst", "center", "cut", "date","default", "default_if_none", "dictsort","dictsortreversed", "divisibleby", "escape", "escapejs","filesizeformat", "first", "floatformat", "force_escape","get_digit", "iriencode", "join", "last", "length","length_is", "linebreaks", "linebreaksbr", "linenumbers","ljust", "lower", "make_list", "phone2numeric", "pluralize","pprint", "random", "removetags", "rjust", "safe","safeseq", "slice", "slugify", "stringformat", "striptags","time", "timesince", "timeuntil", "title", "truncatechars","truncatechars_html", "truncatewords", "truncatewords_html","unordered_list", "upper", "urlencode", "urlize","urlizetrunc", "wordcount", "wordwrap", "yesno"],operators = ["==", "!=", "<", ">", "<=", ">=", "in", "not", "or", "and"];keywords = new RegExp("^\\b(" + keywords.join("|") + ")\\b");filters = new RegExp("^\\b(" + filters.join("|") + ")\\b");operators = new RegExp("^\\b(" + operators.join("|") + ")\\b");// We have to return "null" instead of null, in order to avoid string// styling as the default, when using Django templates inside HTML// element attributesfunction tokenBase (stream, state) {// Attempt to identify a variable, template or comment tag respectivelyif (stream.match("{{")) {state.tokenize = inVariable;return "tag";} else if (stream.match("{%")) {state.tokenize = inTag;return "tag";} else if (stream.match("{#")) {state.tokenize = inComment;return "comment";}// Ignore completely any stream series that do not match the// Django template opening tags.while (stream.next() != null && !stream.match("{{", false) && !stream.match("{%", false)) {}return null;}// A string can be included in either single or double quotes (this is// the delimeter). Mark everything as a string until the start delimeter// occurs again.function inString (delimeter, previousTokenizer) {return function (stream, state) {if (!state.escapeNext && stream.eat(delimeter)) {state.tokenize = previousTokenizer;} else {if (state.escapeNext) {state.escapeNext = false;}var ch = stream.next();// Take into account the backslash for escaping characters, such as// the string delimeter.if (ch == "\\") {state.escapeNext = true;}}return "string";};}// Apply Django template variable syntax highlightingfunction inVariable (stream, state) {// Attempt to match a dot that precedes a propertyif (state.waitDot) {state.waitDot = false;if (stream.peek() != ".") {return "null";}// Dot folowed by a non-word character should be considered an error.if (stream.match(/\.\W+/)) {return "error";} else if (stream.eat(".")) {state.waitProperty = true;return "null";} else {throw Error ("Unexpected error while waiting for property.");}}// Attempt to match a pipe that precedes a filterif (state.waitPipe) {state.waitPipe = false;if (stream.peek() != "|") {return "null";}// Pipe folowed by a non-word character should be considered an error.if (stream.match(/\.\W+/)) {return "error";} else if (stream.eat("|")) {state.waitFilter = true;return "null";} else {throw Error ("Unexpected error while waiting for filter.");}}// Highlight propertiesif (state.waitProperty) {state.waitProperty = false;if (stream.match(/\b(\w+)\b/)) {state.waitDot = true; // A property can be followed by another propertystate.waitPipe = true; // A property can be followed by a filterreturn "property";}}// Highlight filtersif (state.waitFilter) {state.waitFilter = false;if (stream.match(filters)) {return "variable-2";}}// Ignore all white spacesif (stream.eatSpace()) {state.waitProperty = false;return "null";}// Identify numbersif (stream.match(/\b\d+(\.\d+)?\b/)) {return "number";}// Identify stringsif (stream.match("'")) {state.tokenize = inString("'", state.tokenize);return "string";} else if (stream.match('"')) {state.tokenize = inString('"', state.tokenize);return "string";}// Attempt to find the variableif (stream.match(/\b(\w+)\b/) && !state.foundVariable) {state.waitDot = true;state.waitPipe = true; // A property can be followed by a filterreturn "variable";}// If found closing tag resetif (stream.match("}}")) {state.waitProperty = null;state.waitFilter = null;state.waitDot = null;state.waitPipe = null;state.tokenize = tokenBase;return "tag";}// If nothing was found, advance to the next characterstream.next();return "null";}function inTag (stream, state) {// Attempt to match a dot that precedes a propertyif (state.waitDot) {state.waitDot = false;if (stream.peek() != ".") {return "null";}// Dot folowed by a non-word character should be considered an error.if (stream.match(/\.\W+/)) {return "error";} else if (stream.eat(".")) {state.waitProperty = true;return "null";} else {throw Error ("Unexpected error while waiting for property.");}}// Attempt to match a pipe that precedes a filterif (state.waitPipe) {state.waitPipe = false;if (stream.peek() != "|") {return "null";}// Pipe folowed by a non-word character should be considered an error.if (stream.match(/\.\W+/)) {return "error";} else if (stream.eat("|")) {state.waitFilter = true;return "null";} else {throw Error ("Unexpected error while waiting for filter.");}}// Highlight propertiesif (state.waitProperty) {state.waitProperty = false;if (stream.match(/\b(\w+)\b/)) {state.waitDot = true; // A property can be followed by another propertystate.waitPipe = true; // A property can be followed by a filterreturn "property";}}// Highlight filtersif (state.waitFilter) {state.waitFilter = false;if (stream.match(filters)) {return "variable-2";}}// Ignore all white spacesif (stream.eatSpace()) {state.waitProperty = false;return "null";}// Identify numbersif (stream.match(/\b\d+(\.\d+)?\b/)) {return "number";}// Identify stringsif (stream.match("'")) {state.tokenize = inString("'", state.tokenize);return "string";} else if (stream.match('"')) {state.tokenize = inString('"', state.tokenize);return "string";}// Attempt to match an operatorif (stream.match(operators)) {return "operator";}// Attempt to match a keywordvar keywordMatch = stream.match(keywords);if (keywordMatch) {if (keywordMatch[0] == "comment") {state.blockCommentTag = true;}return "keyword";}// Attempt to match a variableif (stream.match(/\b(\w+)\b/)) {state.waitDot = true;state.waitPipe = true; // A property can be followed by a filterreturn "variable";}// If found closing tag resetif (stream.match("%}")) {state.waitProperty = null;state.waitFilter = null;state.waitDot = null;state.waitPipe = null;// If the tag that closes is a block comment tag, we want to mark the// following code as comment, until the tag closes.if (state.blockCommentTag) {state.blockCommentTag = false; // Release the "lock"state.tokenize = inBlockComment;} else {state.tokenize = tokenBase;}return "tag";}// If nothing was found, advance to the next characterstream.next();return "null";}// Mark everything as comment inside the tag and the tag itself.function inComment (stream, state) {if (stream.match("#}")) {state.tokenize = tokenBase;}return "comment";}// Mark everything as a comment until the `blockcomment` tag closes.function inBlockComment (stream, state) {if (stream.match(/\{%\s*endcomment\s*%\}/, false)) {state.tokenize = inTag;stream.match("{%");return "tag";} else {stream.next();return "comment";}}return {startState: function () {return {tokenize: tokenBase};},token: function (stream, state) {return state.tokenize(stream, state);},blockCommentStart: "{% comment %}",blockCommentEnd: "{% endcomment %}"};});CodeMirror.defineMode("django", function(config) {var htmlBase = CodeMirror.getMode(config, "text/html");var djangoInner = CodeMirror.getMode(config, "django:inner");return CodeMirror.overlayMode(htmlBase, djangoInner);});CodeMirror.defineMIME("text/x-django", "django");});