LaravelTest

Форк
0
356 строк · 11.5 Кб
1
// CodeMirror, copyright (c) by Marijn Haverbeke and others
2
// Distributed under an MIT license: https://codemirror.net/LICENSE
3

4
(function(mod) {
5
  if (typeof exports == "object" && typeof module == "object") // CommonJS
6
    mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"),
7
        require("../../addon/mode/overlay"));
8
  else if (typeof define == "function" && define.amd) // AMD
9
    define(["../../lib/codemirror", "../htmlmixed/htmlmixed",
10
            "../../addon/mode/overlay"], mod);
11
  else // Plain browser env
12
    mod(CodeMirror);
13
})(function(CodeMirror) {
14
  "use strict";
15

16
  CodeMirror.defineMode("django:inner", function() {
17
    var keywords = ["block", "endblock", "for", "endfor", "true", "false", "filter", "endfilter",
18
                    "loop", "none", "self", "super", "if", "elif", "endif", "as", "else", "import",
19
                    "with", "endwith", "without", "context", "ifequal", "endifequal", "ifnotequal",
20
                    "endifnotequal", "extends", "include", "load", "comment", "endcomment",
21
                    "empty", "url", "static", "trans", "blocktrans", "endblocktrans", "now",
22
                    "regroup", "lorem", "ifchanged", "endifchanged", "firstof", "debug", "cycle",
23
                    "csrf_token", "autoescape", "endautoescape", "spaceless", "endspaceless",
24
                    "ssi", "templatetag", "verbatim", "endverbatim", "widthratio"],
25
        filters = ["add", "addslashes", "capfirst", "center", "cut", "date",
26
                   "default", "default_if_none", "dictsort",
27
                   "dictsortreversed", "divisibleby", "escape", "escapejs",
28
                   "filesizeformat", "first", "floatformat", "force_escape",
29
                   "get_digit", "iriencode", "join", "last", "length",
30
                   "length_is", "linebreaks", "linebreaksbr", "linenumbers",
31
                   "ljust", "lower", "make_list", "phone2numeric", "pluralize",
32
                   "pprint", "random", "removetags", "rjust", "safe",
33
                   "safeseq", "slice", "slugify", "stringformat", "striptags",
34
                   "time", "timesince", "timeuntil", "title", "truncatechars",
35
                   "truncatechars_html", "truncatewords", "truncatewords_html",
36
                   "unordered_list", "upper", "urlencode", "urlize",
37
                   "urlizetrunc", "wordcount", "wordwrap", "yesno"],
38
        operators = ["==", "!=", "<", ">", "<=", ">="],
39
        wordOperators = ["in", "not", "or", "and"];
40

41
    keywords = new RegExp("^\\b(" + keywords.join("|") + ")\\b");
42
    filters = new RegExp("^\\b(" + filters.join("|") + ")\\b");
43
    operators = new RegExp("^\\b(" + operators.join("|") + ")\\b");
44
    wordOperators = new RegExp("^\\b(" + wordOperators.join("|") + ")\\b");
45

46
    // We have to return "null" instead of null, in order to avoid string
47
    // styling as the default, when using Django templates inside HTML
48
    // element attributes
49
    function tokenBase (stream, state) {
50
      // Attempt to identify a variable, template or comment tag respectively
51
      if (stream.match("{{")) {
52
        state.tokenize = inVariable;
53
        return "tag";
54
      } else if (stream.match("{%")) {
55
        state.tokenize = inTag;
56
        return "tag";
57
      } else if (stream.match("{#")) {
58
        state.tokenize = inComment;
59
        return "comment";
60
      }
61

62
      // Ignore completely any stream series that do not match the
63
      // Django template opening tags.
64
      while (stream.next() != null && !stream.match(/\{[{%#]/, false)) {}
65
      return null;
66
    }
67

68
    // A string can be included in either single or double quotes (this is
69
    // the delimiter). Mark everything as a string until the start delimiter
70
    // occurs again.
71
    function inString (delimiter, previousTokenizer) {
72
      return function (stream, state) {
73
        if (!state.escapeNext && stream.eat(delimiter)) {
74
          state.tokenize = previousTokenizer;
75
        } else {
76
          if (state.escapeNext) {
77
            state.escapeNext = false;
78
          }
79

80
          var ch = stream.next();
81

82
          // Take into account the backslash for escaping characters, such as
83
          // the string delimiter.
84
          if (ch == "\\") {
85
            state.escapeNext = true;
86
          }
87
        }
88

89
        return "string";
90
      };
91
    }
92

93
    // Apply Django template variable syntax highlighting
94
    function inVariable (stream, state) {
95
      // Attempt to match a dot that precedes a property
96
      if (state.waitDot) {
97
        state.waitDot = false;
98

99
        if (stream.peek() != ".") {
100
          return "null";
101
        }
102

103
        // Dot followed by a non-word character should be considered an error.
104
        if (stream.match(/\.\W+/)) {
105
          return "error";
106
        } else if (stream.eat(".")) {
107
          state.waitProperty = true;
108
          return "null";
109
        } else {
110
          throw Error ("Unexpected error while waiting for property.");
111
        }
112
      }
113

114
      // Attempt to match a pipe that precedes a filter
115
      if (state.waitPipe) {
116
        state.waitPipe = false;
117

118
        if (stream.peek() != "|") {
119
          return "null";
120
        }
121

122
        // Pipe followed by a non-word character should be considered an error.
123
        if (stream.match(/\.\W+/)) {
124
          return "error";
125
        } else if (stream.eat("|")) {
126
          state.waitFilter = true;
127
          return "null";
128
        } else {
129
          throw Error ("Unexpected error while waiting for filter.");
130
        }
131
      }
132

133
      // Highlight properties
134
      if (state.waitProperty) {
135
        state.waitProperty = false;
136
        if (stream.match(/\b(\w+)\b/)) {
137
          state.waitDot = true;  // A property can be followed by another property
138
          state.waitPipe = true;  // A property can be followed by a filter
139
          return "property";
140
        }
141
      }
142

143
      // Highlight filters
144
      if (state.waitFilter) {
145
          state.waitFilter = false;
146
        if (stream.match(filters)) {
147
          return "variable-2";
148
        }
149
      }
150

151
      // Ignore all white spaces
152
      if (stream.eatSpace()) {
153
        state.waitProperty = false;
154
        return "null";
155
      }
156

157
      // Identify numbers
158
      if (stream.match(/\b\d+(\.\d+)?\b/)) {
159
        return "number";
160
      }
161

162
      // Identify strings
163
      if (stream.match("'")) {
164
        state.tokenize = inString("'", state.tokenize);
165
        return "string";
166
      } else if (stream.match('"')) {
167
        state.tokenize = inString('"', state.tokenize);
168
        return "string";
169
      }
170

171
      // Attempt to find the variable
172
      if (stream.match(/\b(\w+)\b/) && !state.foundVariable) {
173
        state.waitDot = true;
174
        state.waitPipe = true;  // A property can be followed by a filter
175
        return "variable";
176
      }
177

178
      // If found closing tag reset
179
      if (stream.match("}}")) {
180
        state.waitProperty = null;
181
        state.waitFilter = null;
182
        state.waitDot = null;
183
        state.waitPipe = null;
184
        state.tokenize = tokenBase;
185
        return "tag";
186
      }
187

188
      // If nothing was found, advance to the next character
189
      stream.next();
190
      return "null";
191
    }
192

193
    function inTag (stream, state) {
194
      // Attempt to match a dot that precedes a property
195
      if (state.waitDot) {
196
        state.waitDot = false;
197

198
        if (stream.peek() != ".") {
199
          return "null";
200
        }
201

202
        // Dot followed by a non-word character should be considered an error.
203
        if (stream.match(/\.\W+/)) {
204
          return "error";
205
        } else if (stream.eat(".")) {
206
          state.waitProperty = true;
207
          return "null";
208
        } else {
209
          throw Error ("Unexpected error while waiting for property.");
210
        }
211
      }
212

213
      // Attempt to match a pipe that precedes a filter
214
      if (state.waitPipe) {
215
        state.waitPipe = false;
216

217
        if (stream.peek() != "|") {
218
          return "null";
219
        }
220

221
        // Pipe followed by a non-word character should be considered an error.
222
        if (stream.match(/\.\W+/)) {
223
          return "error";
224
        } else if (stream.eat("|")) {
225
          state.waitFilter = true;
226
          return "null";
227
        } else {
228
          throw Error ("Unexpected error while waiting for filter.");
229
        }
230
      }
231

232
      // Highlight properties
233
      if (state.waitProperty) {
234
        state.waitProperty = false;
235
        if (stream.match(/\b(\w+)\b/)) {
236
          state.waitDot = true;  // A property can be followed by another property
237
          state.waitPipe = true;  // A property can be followed by a filter
238
          return "property";
239
        }
240
      }
241

242
      // Highlight filters
243
      if (state.waitFilter) {
244
          state.waitFilter = false;
245
        if (stream.match(filters)) {
246
          return "variable-2";
247
        }
248
      }
249

250
      // Ignore all white spaces
251
      if (stream.eatSpace()) {
252
        state.waitProperty = false;
253
        return "null";
254
      }
255

256
      // Identify numbers
257
      if (stream.match(/\b\d+(\.\d+)?\b/)) {
258
        return "number";
259
      }
260

261
      // Identify strings
262
      if (stream.match("'")) {
263
        state.tokenize = inString("'", state.tokenize);
264
        return "string";
265
      } else if (stream.match('"')) {
266
        state.tokenize = inString('"', state.tokenize);
267
        return "string";
268
      }
269

270
      // Attempt to match an operator
271
      if (stream.match(operators)) {
272
        return "operator";
273
      }
274

275
      // Attempt to match a word operator
276
      if (stream.match(wordOperators)) {
277
        return "keyword";
278
      }
279

280
      // Attempt to match a keyword
281
      var keywordMatch = stream.match(keywords);
282
      if (keywordMatch) {
283
        if (keywordMatch[0] == "comment") {
284
          state.blockCommentTag = true;
285
        }
286
        return "keyword";
287
      }
288

289
      // Attempt to match a variable
290
      if (stream.match(/\b(\w+)\b/)) {
291
        state.waitDot = true;
292
        state.waitPipe = true;  // A property can be followed by a filter
293
        return "variable";
294
      }
295

296
      // If found closing tag reset
297
      if (stream.match("%}")) {
298
        state.waitProperty = null;
299
        state.waitFilter = null;
300
        state.waitDot = null;
301
        state.waitPipe = null;
302
        // If the tag that closes is a block comment tag, we want to mark the
303
        // following code as comment, until the tag closes.
304
        if (state.blockCommentTag) {
305
          state.blockCommentTag = false;  // Release the "lock"
306
          state.tokenize = inBlockComment;
307
        } else {
308
          state.tokenize = tokenBase;
309
        }
310
        return "tag";
311
      }
312

313
      // If nothing was found, advance to the next character
314
      stream.next();
315
      return "null";
316
    }
317

318
    // Mark everything as comment inside the tag and the tag itself.
319
    function inComment (stream, state) {
320
      if (stream.match(/^.*?#\}/)) state.tokenize = tokenBase
321
      else stream.skipToEnd()
322
      return "comment";
323
    }
324

325
    // Mark everything as a comment until the `blockcomment` tag closes.
326
    function inBlockComment (stream, state) {
327
      if (stream.match(/\{%\s*endcomment\s*%\}/, false)) {
328
        state.tokenize = inTag;
329
        stream.match("{%");
330
        return "tag";
331
      } else {
332
        stream.next();
333
        return "comment";
334
      }
335
    }
336

337
    return {
338
      startState: function () {
339
        return {tokenize: tokenBase};
340
      },
341
      token: function (stream, state) {
342
        return state.tokenize(stream, state);
343
      },
344
      blockCommentStart: "{% comment %}",
345
      blockCommentEnd: "{% endcomment %}"
346
    };
347
  });
348

349
  CodeMirror.defineMode("django", function(config) {
350
    var htmlBase = CodeMirror.getMode(config, "text/html");
351
    var djangoInner = CodeMirror.getMode(config, "django:inner");
352
    return CodeMirror.overlayMode(htmlBase, djangoInner);
353
  });
354

355
  CodeMirror.defineMIME("text/x-django", "django");
356
});
357

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.