PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 2.9.19.4
Pods – Custom Content Types and Fields v2.9.19.4
2.7.31.4 2.8.23.5 2.9.19.5 3.0.10.5 3.1.4.3 3.2.8.4 3.3.9.2 2.8.23.4 2.9.19.4 3.0.10.4 3.1.4.2 3.2.8.3 3.3.9.1 trunk 1.14.8 2.7.31.3 2.8.23.3 2.9.19.3 3.0.10.3 3.1.4.1 3.2.0 3.2.1 3.2.1.1 3.2.2 3.2.4 3.2.5 3.2.6 3.2.7 3.2.7.1 3.2.8 3.2.8.1 3.2.8.2 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9
pods / ui / js / codemirror / mode / javascript / javascript.js
pods / ui / js / codemirror / mode / javascript Last commit date
javascript.js 2 weeks ago
javascript.js
685 lines
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 // Distributed under an MIT license: http://codemirror.net/LICENSE
3
4 // TODO actually recognize syntax of TypeScript constructs
5
6 (function(mod) {
7 if (typeof exports == "object" && typeof module == "object") // CommonJS
8 mod(require("../../lib/codemirror"));
9 else if (typeof define == "function" && define.amd) // AMD
10 define(["../../lib/codemirror"], mod);
11 else // Plain browser env
12 mod(CodeMirror);
13 })(function(CodeMirror) {
14 "use strict";
15
16 CodeMirror.defineMode("javascript", function(config, parserConfig) {
17 var indentUnit = config.indentUnit;
18 var statementIndent = parserConfig.statementIndent;
19 var jsonldMode = parserConfig.jsonld;
20 var jsonMode = parserConfig.json || jsonldMode;
21 var isTS = parserConfig.typescript;
22 var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
23
24 // Tokenizer
25
26 var keywords = function(){
27 function kw(type) {return {type: type, style: "keyword"};}
28 var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
29 var operator = kw("operator"), atom = {type: "atom", style: "atom"};
30
31 var jsKeywords = {
32 "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
33 "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C,
34 "var": kw("var"), "const": kw("var"), "let": kw("var"),
35 "function": kw("function"), "catch": kw("catch"),
36 "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
37 "in": operator, "typeof": operator, "instanceof": operator,
38 "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
39 "this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"),
40 "yield": C, "export": kw("export"), "import": kw("import"), "extends": C
41 };
42
43 // Extend the 'normal' keywords with the TypeScript language extensions
44 if (isTS) {
45 var type = {type: "variable", style: "variable-3"};
46 var tsKeywords = {
47 // object-like things
48 "interface": kw("interface"),
49 "extends": kw("extends"),
50 "constructor": kw("constructor"),
51
52 // scope modifiers
53 "public": kw("public"),
54 "private": kw("private"),
55 "protected": kw("protected"),
56 "static": kw("static"),
57
58 // types
59 "string": type, "number": type, "bool": type, "any": type
60 };
61
62 for (var attr in tsKeywords) {
63 jsKeywords[attr] = tsKeywords[attr];
64 }
65 }
66
67 return jsKeywords;
68 }();
69
70 var isOperatorChar = /[+\-*&%=<>!?|~^]/;
71 var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
72
73 function readRegexp(stream) {
74 var escaped = false, next, inSet = false;
75 while ((next = stream.next()) != null) {
76 if (!escaped) {
77 if (next == "/" && !inSet) return;
78 if (next == "[") inSet = true;
79 else if (inSet && next == "]") inSet = false;
80 }
81 escaped = !escaped && next == "\\";
82 }
83 }
84
85 // Used as scratch variables to communicate multiple values without
86 // consing up tons of objects.
87 var type, content;
88 function ret(tp, style, cont) {
89 type = tp; content = cont;
90 return style;
91 }
92 function tokenBase(stream, state) {
93 var ch = stream.next();
94 if (ch == '"' || ch == "'") {
95 state.tokenize = tokenString(ch);
96 return state.tokenize(stream, state);
97 } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
98 return ret("number", "number");
99 } else if (ch == "." && stream.match("..")) {
100 return ret("spread", "meta");
101 } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
102 return ret(ch);
103 } else if (ch == "=" && stream.eat(">")) {
104 return ret("=>", "operator");
105 } else if (ch == "0" && stream.eat(/x/i)) {
106 stream.eatWhile(/[\da-f]/i);
107 return ret("number", "number");
108 } else if (/\d/.test(ch)) {
109 stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
110 return ret("number", "number");
111 } else if (ch == "/") {
112 if (stream.eat("*")) {
113 state.tokenize = tokenComment;
114 return tokenComment(stream, state);
115 } else if (stream.eat("/")) {
116 stream.skipToEnd();
117 return ret("comment", "comment");
118 } else if (state.lastType == "operator" || state.lastType == "keyword c" ||
119 state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
120 readRegexp(stream);
121 stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
122 return ret("regexp", "string-2");
123 } else {
124 stream.eatWhile(isOperatorChar);
125 return ret("operator", "operator", stream.current());
126 }
127 } else if (ch == "`") {
128 state.tokenize = tokenQuasi;
129 return tokenQuasi(stream, state);
130 } else if (ch == "#") {
131 stream.skipToEnd();
132 return ret("error", "error");
133 } else if (isOperatorChar.test(ch)) {
134 stream.eatWhile(isOperatorChar);
135 return ret("operator", "operator", stream.current());
136 } else if (wordRE.test(ch)) {
137 stream.eatWhile(wordRE);
138 var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
139 return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
140 ret("variable", "variable", word);
141 }
142 }
143
144 function tokenString(quote) {
145 return function(stream, state) {
146 var escaped = false, next;
147 if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
148 state.tokenize = tokenBase;
149 return ret("jsonld-keyword", "meta");
150 }
151 while ((next = stream.next()) != null) {
152 if (next == quote && !escaped) break;
153 escaped = !escaped && next == "\\";
154 }
155 if (!escaped) state.tokenize = tokenBase;
156 return ret("string", "string");
157 };
158 }
159
160 function tokenComment(stream, state) {
161 var maybeEnd = false, ch;
162 while (ch = stream.next()) {
163 if (ch == "/" && maybeEnd) {
164 state.tokenize = tokenBase;
165 break;
166 }
167 maybeEnd = (ch == "*");
168 }
169 return ret("comment", "comment");
170 }
171
172 function tokenQuasi(stream, state) {
173 var escaped = false, next;
174 while ((next = stream.next()) != null) {
175 if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
176 state.tokenize = tokenBase;
177 break;
178 }
179 escaped = !escaped && next == "\\";
180 }
181 return ret("quasi", "string-2", stream.current());
182 }
183
184 var brackets = "([{}])";
185 // This is a crude lookahead trick to try and notice that we're
186 // parsing the argument patterns for a fat-arrow function before we
187 // actually hit the arrow token. It only works if the arrow is on
188 // the same line as the arguments and there's no strange noise
189 // (comments) in between. Fallback is to only notice when we hit the
190 // arrow, and not declare the arguments as locals for the arrow
191 // body.
192 function findFatArrow(stream, state) {
193 if (state.fatArrowAt) state.fatArrowAt = null;
194 var arrow = stream.string.indexOf("=>", stream.start);
195 if (arrow < 0) return;
196
197 var depth = 0, sawSomething = false;
198 for (var pos = arrow - 1; pos >= 0; --pos) {
199 var ch = stream.string.charAt(pos);
200 var bracket = brackets.indexOf(ch);
201 if (bracket >= 0 && bracket < 3) {
202 if (!depth) { ++pos; break; }
203 if (--depth == 0) break;
204 } else if (bracket >= 3 && bracket < 6) {
205 ++depth;
206 } else if (wordRE.test(ch)) {
207 sawSomething = true;
208 } else if (sawSomething && !depth) {
209 ++pos;
210 break;
211 }
212 }
213 if (sawSomething && !depth) state.fatArrowAt = pos;
214 }
215
216 // Parser
217
218 var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
219
220 function JSLexical(indented, column, type, align, prev, info) {
221 this.indented = indented;
222 this.column = column;
223 this.type = type;
224 this.prev = prev;
225 this.info = info;
226 if (align != null) this.align = align;
227 }
228
229 function inScope(state, varname) {
230 for (var v = state.localVars; v; v = v.next)
231 if (v.name == varname) return true;
232 for (var cx = state.context; cx; cx = cx.prev) {
233 for (var v = cx.vars; v; v = v.next)
234 if (v.name == varname) return true;
235 }
236 }
237
238 function parseJS(state, style, type, content, stream) {
239 var cc = state.cc;
240 // Communicate our context to the combinators.
241 // (Less wasteful than consing up a hundred closures on every call.)
242 cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
243
244 if (!state.lexical.hasOwnProperty("align"))
245 state.lexical.align = true;
246
247 while(true) {
248 var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
249 if (combinator(type, content)) {
250 while(cc.length && cc[cc.length - 1].lex)
251 cc.pop()();
252 if (cx.marked) return cx.marked;
253 if (type == "variable" && inScope(state, content)) return "variable-2";
254 return style;
255 }
256 }
257 }
258
259 // Combinator utils
260
261 var cx = {state: null, column: null, marked: null, cc: null};
262 function pass() {
263 for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
264 }
265 function cont() {
266 pass.apply(null, arguments);
267 return true;
268 }
269 function register(varname) {
270 function inList(list) {
271 for (var v = list; v; v = v.next)
272 if (v.name == varname) return true;
273 return false;
274 }
275 var state = cx.state;
276 if (state.context) {
277 cx.marked = "def";
278 if (inList(state.localVars)) return;
279 state.localVars = {name: varname, next: state.localVars};
280 } else {
281 if (inList(state.globalVars)) return;
282 if (parserConfig.globalVars)
283 state.globalVars = {name: varname, next: state.globalVars};
284 }
285 }
286
287 // Combinators
288
289 var defaultVars = {name: "this", next: {name: "arguments"}};
290 function pushcontext() {
291 cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
292 cx.state.localVars = defaultVars;
293 }
294 function popcontext() {
295 cx.state.localVars = cx.state.context.vars;
296 cx.state.context = cx.state.context.prev;
297 }
298 function pushlex(type, info) {
299 var result = function() {
300 var state = cx.state, indent = state.indented;
301 if (state.lexical.type == "stat") indent = state.lexical.indented;
302 else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
303 indent = outer.indented;
304 state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
305 };
306 result.lex = true;
307 return result;
308 }
309 function poplex() {
310 var state = cx.state;
311 if (state.lexical.prev) {
312 if (state.lexical.type == ")")
313 state.indented = state.lexical.indented;
314 state.lexical = state.lexical.prev;
315 }
316 }
317 poplex.lex = true;
318
319 function expect(wanted) {
320 function exp(type) {
321 if (type == wanted) return cont();
322 else if (wanted == ";") return pass();
323 else return cont(exp);
324 };
325 return exp;
326 }
327
328 function statement(type, value) {
329 if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
330 if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
331 if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
332 if (type == "{") return cont(pushlex("}"), block, poplex);
333 if (type == ";") return cont();
334 if (type == "if") {
335 if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
336 cx.state.cc.pop()();
337 return cont(pushlex("form"), expression, statement, poplex, maybeelse);
338 }
339 if (type == "function") return cont(functiondef);
340 if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
341 if (type == "variable") return cont(pushlex("stat"), maybelabel);
342 if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
343 block, poplex, poplex);
344 if (type == "case") return cont(expression, expect(":"));
345 if (type == "default") return cont(expect(":"));
346 if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
347 statement, poplex, popcontext);
348 if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex);
349 if (type == "class") return cont(pushlex("form"), className, poplex);
350 if (type == "export") return cont(pushlex("form"), afterExport, poplex);
351 if (type == "import") return cont(pushlex("form"), afterImport, poplex);
352 return pass(pushlex("stat"), expression, expect(";"), poplex);
353 }
354 function expression(type) {
355 return expressionInner(type, false);
356 }
357 function expressionNoComma(type) {
358 return expressionInner(type, true);
359 }
360 function expressionInner(type, noComma) {
361 if (cx.state.fatArrowAt == cx.stream.start) {
362 var body = noComma ? arrowBodyNoComma : arrowBody;
363 if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext);
364 else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
365 }
366
367 var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
368 if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
369 if (type == "function") return cont(functiondef, maybeop);
370 if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
371 if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
372 if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
373 if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
374 if (type == "{") return contCommasep(objprop, "}", null, maybeop);
375 if (type == "quasi") { return pass(quasi, maybeop); }
376 return cont();
377 }
378 function maybeexpression(type) {
379 if (type.match(/[;\}\)\],]/)) return pass();
380 return pass(expression);
381 }
382 function maybeexpressionNoComma(type) {
383 if (type.match(/[;\}\)\],]/)) return pass();
384 return pass(expressionNoComma);
385 }
386
387 function maybeoperatorComma(type, value) {
388 if (type == ",") return cont(expression);
389 return maybeoperatorNoComma(type, value, false);
390 }
391 function maybeoperatorNoComma(type, value, noComma) {
392 var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
393 var expr = noComma == false ? expression : expressionNoComma;
394 if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
395 if (type == "operator") {
396 if (/\+\+|--/.test(value)) return cont(me);
397 if (value == "?") return cont(expression, expect(":"), expr);
398 return cont(expr);
399 }
400 if (type == "quasi") { return pass(quasi, me); }
401 if (type == ";") return;
402 if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
403 if (type == ".") return cont(property, me);
404 if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
405 }
406 function quasi(type, value) {
407 if (type != "quasi") return pass();
408 if (value.slice(value.length - 2) != "${") return cont(quasi);
409 return cont(expression, continueQuasi);
410 }
411 function continueQuasi(type) {
412 if (type == "}") {
413 cx.marked = "string-2";
414 cx.state.tokenize = tokenQuasi;
415 return cont(quasi);
416 }
417 }
418 function arrowBody(type) {
419 findFatArrow(cx.stream, cx.state);
420 return pass(type == "{" ? statement : expression);
421 }
422 function arrowBodyNoComma(type) {
423 findFatArrow(cx.stream, cx.state);
424 return pass(type == "{" ? statement : expressionNoComma);
425 }
426 function maybelabel(type) {
427 if (type == ":") return cont(poplex, statement);
428 return pass(maybeoperatorComma, expect(";"), poplex);
429 }
430 function property(type) {
431 if (type == "variable") {cx.marked = "property"; return cont();}
432 }
433 function objprop(type, value) {
434 if (type == "variable" || cx.style == "keyword") {
435 cx.marked = "property";
436 if (value == "get" || value == "set") return cont(getterSetter);
437 return cont(afterprop);
438 } else if (type == "number" || type == "string") {
439 cx.marked = jsonldMode ? "property" : (cx.style + " property");
440 return cont(afterprop);
441 } else if (type == "jsonld-keyword") {
442 return cont(afterprop);
443 } else if (type == "[") {
444 return cont(expression, expect("]"), afterprop);
445 }
446 }
447 function getterSetter(type) {
448 if (type != "variable") return pass(afterprop);
449 cx.marked = "property";
450 return cont(functiondef);
451 }
452 function afterprop(type) {
453 if (type == ":") return cont(expressionNoComma);
454 if (type == "(") return pass(functiondef);
455 }
456 function commasep(what, end) {
457 function proceed(type) {
458 if (type == ",") {
459 var lex = cx.state.lexical;
460 if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
461 return cont(what, proceed);
462 }
463 if (type == end) return cont();
464 return cont(expect(end));
465 }
466 return function(type) {
467 if (type == end) return cont();
468 return pass(what, proceed);
469 };
470 }
471 function contCommasep(what, end, info) {
472 for (var i = 3; i < arguments.length; i++)
473 cx.cc.push(arguments[i]);
474 return cont(pushlex(end, info), commasep(what, end), poplex);
475 }
476 function block(type) {
477 if (type == "}") return cont();
478 return pass(statement, block);
479 }
480 function maybetype(type) {
481 if (isTS && type == ":") return cont(typedef);
482 }
483 function typedef(type) {
484 if (type == "variable"){cx.marked = "variable-3"; return cont();}
485 }
486 function vardef() {
487 return pass(pattern, maybetype, maybeAssign, vardefCont);
488 }
489 function pattern(type, value) {
490 if (type == "variable") { register(value); return cont(); }
491 if (type == "[") return contCommasep(pattern, "]");
492 if (type == "{") return contCommasep(proppattern, "}");
493 }
494 function proppattern(type, value) {
495 if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
496 register(value);
497 return cont(maybeAssign);
498 }
499 if (type == "variable") cx.marked = "property";
500 return cont(expect(":"), pattern, maybeAssign);
501 }
502 function maybeAssign(_type, value) {
503 if (value == "=") return cont(expressionNoComma);
504 }
505 function vardefCont(type) {
506 if (type == ",") return cont(vardef);
507 }
508 function maybeelse(type, value) {
509 if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
510 }
511 function forspec(type) {
512 if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
513 }
514 function forspec1(type) {
515 if (type == "var") return cont(vardef, expect(";"), forspec2);
516 if (type == ";") return cont(forspec2);
517 if (type == "variable") return cont(formaybeinof);
518 return pass(expression, expect(";"), forspec2);
519 }
520 function formaybeinof(_type, value) {
521 if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
522 return cont(maybeoperatorComma, forspec2);
523 }
524 function forspec2(type, value) {
525 if (type == ";") return cont(forspec3);
526 if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
527 return pass(expression, expect(";"), forspec3);
528 }
529 function forspec3(type) {
530 if (type != ")") cont(expression);
531 }
532 function functiondef(type, value) {
533 if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
534 if (type == "variable") {register(value); return cont(functiondef);}
535 if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext);
536 }
537 function funarg(type) {
538 if (type == "spread") return cont(funarg);
539 return pass(pattern, maybetype);
540 }
541 function className(type, value) {
542 if (type == "variable") {register(value); return cont(classNameAfter);}
543 }
544 function classNameAfter(type, value) {
545 if (value == "extends") return cont(expression, classNameAfter);
546 if (type == "{") return cont(pushlex("}"), classBody, poplex);
547 }
548 function classBody(type, value) {
549 if (type == "variable" || cx.style == "keyword") {
550 cx.marked = "property";
551 if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody);
552 return cont(functiondef, classBody);
553 }
554 if (value == "*") {
555 cx.marked = "keyword";
556 return cont(classBody);
557 }
558 if (type == ";") return cont(classBody);
559 if (type == "}") return cont();
560 }
561 function classGetterSetter(type) {
562 if (type != "variable") return pass();
563 cx.marked = "property";
564 return cont();
565 }
566 function afterModule(type, value) {
567 if (type == "string") return cont(statement);
568 if (type == "variable") { register(value); return cont(maybeFrom); }
569 }
570 function afterExport(_type, value) {
571 if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
572 if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
573 return pass(statement);
574 }
575 function afterImport(type) {
576 if (type == "string") return cont();
577 return pass(importSpec, maybeFrom);
578 }
579 function importSpec(type, value) {
580 if (type == "{") return contCommasep(importSpec, "}");
581 if (type == "variable") register(value);
582 return cont();
583 }
584 function maybeFrom(_type, value) {
585 if (value == "from") { cx.marked = "keyword"; return cont(expression); }
586 }
587 function arrayLiteral(type) {
588 if (type == "]") return cont();
589 return pass(expressionNoComma, maybeArrayComprehension);
590 }
591 function maybeArrayComprehension(type) {
592 if (type == "for") return pass(comprehension, expect("]"));
593 if (type == ",") return cont(commasep(maybeexpressionNoComma, "]"));
594 return pass(commasep(expressionNoComma, "]"));
595 }
596 function comprehension(type) {
597 if (type == "for") return cont(forspec, comprehension);
598 if (type == "if") return cont(expression, comprehension);
599 }
600
601 // Interface
602
603 return {
604 startState: function(basecolumn) {
605 var state = {
606 tokenize: tokenBase,
607 lastType: "sof",
608 cc: [],
609 lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
610 localVars: parserConfig.localVars,
611 context: parserConfig.localVars && {vars: parserConfig.localVars},
612 indented: 0
613 };
614 if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
615 state.globalVars = parserConfig.globalVars;
616 return state;
617 },
618
619 token: function(stream, state) {
620 if (stream.sol()) {
621 if (!state.lexical.hasOwnProperty("align"))
622 state.lexical.align = false;
623 state.indented = stream.indentation();
624 findFatArrow(stream, state);
625 }
626 if (state.tokenize != tokenComment && stream.eatSpace()) return null;
627 var style = state.tokenize(stream, state);
628 if (type == "comment") return style;
629 state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
630 return parseJS(state, style, type, content, stream);
631 },
632
633 indent: function(state, textAfter) {
634 if (state.tokenize == tokenComment) return CodeMirror.Pass;
635 if (state.tokenize != tokenBase) return 0;
636 var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
637 // Kludge to prevent 'maybelse' from blocking lexical scope pops
638 if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
639 var c = state.cc[i];
640 if (c == poplex) lexical = lexical.prev;
641 else if (c != maybeelse) break;
642 }
643 if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
644 if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
645 lexical = lexical.prev;
646 var type = lexical.type, closing = firstChar == type;
647
648 if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0);
649 else if (type == "form" && firstChar == "{") return lexical.indented;
650 else if (type == "form") return lexical.indented + indentUnit;
651 else if (type == "stat")
652 return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? statementIndent || indentUnit : 0);
653 else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
654 return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
655 else if (lexical.align) return lexical.column + (closing ? 0 : 1);
656 else return lexical.indented + (closing ? 0 : indentUnit);
657 },
658
659 electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
660 blockCommentStart: jsonMode ? null : "/*",
661 blockCommentEnd: jsonMode ? null : "*/",
662 lineComment: jsonMode ? null : "//",
663 fold: "brace",
664
665 helperType: jsonMode ? "json" : "javascript",
666 jsonldMode: jsonldMode,
667 jsonMode: jsonMode
668 };
669 });
670
671 CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
672
673 CodeMirror.defineMIME("text/javascript", "javascript");
674 CodeMirror.defineMIME("text/ecmascript", "javascript");
675 CodeMirror.defineMIME("application/javascript", "javascript");
676 CodeMirror.defineMIME("application/x-javascript", "javascript");
677 CodeMirror.defineMIME("application/ecmascript", "javascript");
678 CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
679 CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
680 CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
681 CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
682 CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
683
684 });
685