1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 // Distributed under an MIT license: http://codemirror.net/LICENSE
5 if (typeof exports == "object" && typeof module == "object") // CommonJS
6 mod(require("../../lib/codemirror"));
7 else if (typeof define == "function" && define.amd) // AMD
8 define(["../../lib/codemirror"], mod);
9 else // Plain browser env
11 })(function(CodeMirror) {
14 CodeMirror.defineMode("jinja2", function() {
15 var keywords = ["and", "as", "block", "endblock", "by", "cycle", "debug", "else", "elif",
16 "extends", "filter", "endfilter", "firstof", "for",
17 "endfor", "if", "endif", "ifchanged", "endifchanged",
18 "ifequal", "endifequal", "ifnotequal",
19 "endifnotequal", "in", "include", "load", "not", "now", "or",
20 "parsed", "regroup", "reversed", "spaceless",
21 "endspaceless", "ssi", "templatetag", "openblock",
22 "closeblock", "openvariable", "closevariable",
23 "openbrace", "closebrace", "opencomment",
24 "closecomment", "widthratio", "url", "with", "endwith",
25 "get_current_language", "trans", "endtrans", "noop", "blocktrans",
26 "endblocktrans", "get_available_languages",
27 "get_current_language_bidi", "plural"],
28 operator = /^[+\-*&%=<>!?|~^]/,
30 atom = ["true", "false"],
31 number = /^(\d[+\-\*\/])?\d+(\.\d+)?/;
33 keywords = new RegExp("((" + keywords.join(")|(") + "))\\b");
34 atom = new RegExp("((" + atom.join(")|(") + "))\\b");
36 function tokenBase (stream, state) {
37 var ch = stream.peek();
40 if (state.incomment) {
41 if(!stream.skipTo("#}")) {
44 stream.eatWhile(/\#|}/);
45 state.incomment = false;
49 } else if (state.intag) {
52 state.operator = false;
53 if(stream.match(atom)) {
56 if(stream.match(number)) {
63 if(stream.match(atom)) {
66 if(stream.match(number)) {
72 if(ch == state.instring) {
73 state.instring = false;
77 } else if(ch == "'" || ch == '"') {
81 } else if(stream.match(state.intag + "}") || stream.eat("-") && stream.match(state.intag + "}")) {
84 } else if(stream.match(operator)) {
85 state.operator = true;
87 } else if(stream.match(sign)) {
90 if(stream.eat(" ") || stream.sol()) {
91 if(stream.match(keywords)) {
94 if(stream.match(atom)) {
97 if(stream.match(number)) {
109 } else if (stream.eat("{")) {
110 if (ch = stream.eat("#")) {
111 state.incomment = true;
112 if(!stream.skipTo("#}")) {
115 stream.eatWhile(/\#|}/);
116 state.incomment = false;
120 } else if (ch = stream.eat(/\{|%/)) {
134 startState: function () {
135 return {tokenize: tokenBase};
137 token: function (stream, state) {
138 return state.tokenize(stream, state);