PluginProbe ʕ •ᴥ•ʔ
YITH WooCommerce Wishlist / 3.18.0
YITH WooCommerce Wishlist v3.18.0
trunk 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.2.10 2.2.11 2.2.12 2.2.13 2.2.14 2.2.15 2.2.16 2.2.17 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 3.0.0 3.0.1 3.0.10 3.0.11 3.0.12 3.0.13 3.0.14 3.0.15 3.0.16 3.0.17 3.0.18 3.0.19 3.0.2 3.0.20 3.0.21 3.0.22 3.0.23 3.0.25 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.10.0 3.11.0 3.12.0 3.13.0 3.14.0 3.15.0 3.16.0 3.17.0 3.18.0 3.19.0 3.2.0 3.20.0 3.21.0 3.22.0 3.23.0 3.24.0 3.25.0 3.26.0 3.27.0 3.28.0 3.29.0 3.3.0 3.30.0 3.31.0 3.32.0 3.33.0 3.34.0 3.35.0 3.36.0 3.37.0 3.38.0 3.4.0 3.5.0 3.6.0 3.7.0 3.8.0 3.9.0 4.0.0 4.0.1 4.1.0 4.10.0 4.10.1 4.10.2 4.11.0 4.12.0 4.13.0 4.14.0 4.15.0 4.2.0 4.3.0 4.4.0 4.5.0 4.6.0 4.7.0 4.8.0 4.9.0
yith-woocommerce-wishlist / plugin-fw / assets / js / codemirror / javascript.js
yith-woocommerce-wishlist / plugin-fw / assets / js / codemirror Last commit date
codemirror.js 4 years ago javascript.js 9 years ago
javascript.js
631 lines
1 // TODO actually recognize syntax of TypeScript constructs
2
3 CodeMirror.defineMode("javascript", function(config, parserConfig) {
4 var indentUnit = config.indentUnit;
5 var statementIndent = parserConfig.statementIndent;
6 var jsonMode = parserConfig.json;
7 var isTS = parserConfig.typescript;
8
9 // Tokenizer
10
11 var keywords = function(){
12 function kw(type) {return {type: type, style: "keyword"};}
13 var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
14 var operator = kw("operator"), atom = {type: "atom", style: "atom"};
15
16 var jsKeywords = {
17 "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
18 "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C,
19 "var": kw("var"), "const": kw("var"), "let": kw("var"),
20 "function": kw("function"), "catch": kw("catch"),
21 "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
22 "in": operator, "typeof": operator, "instanceof": operator,
23 "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
24 "this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"),
25 "yield": C, "export": kw("export"), "import": kw("import"), "extends": C
26 };
27
28 // Extend the 'normal' keywords with the TypeScript language extensions
29 if (isTS) {
30 var type = {type: "variable", style: "variable-3"};
31 var tsKeywords = {
32 // object-like things
33 "interface": kw("interface"),
34 "extends": kw("extends"),
35 "constructor": kw("constructor"),
36
37 // scope modifiers
38 "public": kw("public"),
39 "private": kw("private"),
40 "protected": kw("protected"),
41 "static": kw("static"),
42
43 // types
44 "string": type, "number": type, "bool": type, "any": type
45 };
46
47 for (var attr in tsKeywords) {
48 jsKeywords[attr] = tsKeywords[attr];
49 }
50 }
51
52 return jsKeywords;
53 }();
54
55 var isOperatorChar = /[+\-*&%=<>!?|~^]/;
56
57 function readRegexp(stream) {
58 var escaped = false, next, inSet = false;
59 while ((next = stream.next()) != null) {
60 if (!escaped) {
61 if (next == "/" && !inSet) return;
62 if (next == "[") inSet = true;
63 else if (inSet && next == "]") inSet = false;
64 }
65 escaped = !escaped && next == "\\";
66 }
67 }
68
69 // Used as scratch variables to communicate multiple values without
70 // consing up tons of objects.
71 var type, content;
72 function ret(tp, style, cont) {
73 type = tp; content = cont;
74 return style;
75 }
76 function tokenBase(stream, state) {
77 var ch = stream.next();
78 if (ch == '"' || ch == "'") {
79 state.tokenize = tokenString(ch);
80 return state.tokenize(stream, state);
81 } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
82 return ret("number", "number");
83 } else if (ch == "." && stream.match("..")) {
84 return ret("spread", "meta");
85 } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
86 return ret(ch);
87 } else if (ch == "=" && stream.eat(">")) {
88 return ret("=>", "operator");
89 } else if (ch == "0" && stream.eat(/x/i)) {
90 stream.eatWhile(/[\da-f]/i);
91 return ret("number", "number");
92 } else if (/\d/.test(ch)) {
93 stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
94 return ret("number", "number");
95 } else if (ch == "/") {
96 if (stream.eat("*")) {
97 state.tokenize = tokenComment;
98 return tokenComment(stream, state);
99 } else if (stream.eat("/")) {
100 stream.skipToEnd();
101 return ret("comment", "comment");
102 } else if (state.lastType == "operator" || state.lastType == "keyword c" ||
103 state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
104 readRegexp(stream);
105 stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
106 return ret("regexp", "string-2");
107 } else {
108 stream.eatWhile(isOperatorChar);
109 return ret("operator", "operator", stream.current());
110 }
111 } else if (ch == "`") {
112 state.tokenize = tokenQuasi;
113 return tokenQuasi(stream, state);
114 } else if (ch == "#") {
115 stream.skipToEnd();
116 return ret("error", "error");
117 } else if (isOperatorChar.test(ch)) {
118 stream.eatWhile(isOperatorChar);
119 return ret("operator", "operator", stream.current());
120 } else {
121 stream.eatWhile(/[\w\$_]/);
122 var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
123 return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
124 ret("variable", "variable", word);
125 }
126 }
127
128 function tokenString(quote) {
129 return function(stream, state) {
130 var escaped = false, next;
131 while ((next = stream.next()) != null) {
132 if (next == quote && !escaped) break;
133 escaped = !escaped && next == "\\";
134 }
135 if (!escaped) state.tokenize = tokenBase;
136 return ret("string", "string");
137 };
138 }
139
140 function tokenComment(stream, state) {
141 var maybeEnd = false, ch;
142 while (ch = stream.next()) {
143 if (ch == "/" && maybeEnd) {
144 state.tokenize = tokenBase;
145 break;
146 }
147 maybeEnd = (ch == "*");
148 }
149 return ret("comment", "comment");
150 }
151
152 function tokenQuasi(stream, state) {
153 var escaped = false, next;
154 while ((next = stream.next()) != null) {
155 if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
156 state.tokenize = tokenBase;
157 break;
158 }
159 escaped = !escaped && next == "\\";
160 }
161 return ret("quasi", "string-2", stream.current());
162 }
163
164 var brackets = "([{}])";
165 // This is a crude lookahead trick to try and notice that we're
166 // parsing the argument patterns for a fat-arrow function before we
167 // actually hit the arrow token. It only works if the arrow is on
168 // the same line as the arguments and there's no strange noise
169 // (comments) in between. Fallback is to only notice when we hit the
170 // arrow, and not declare the arguments as locals for the arrow
171 // body.
172 function findFatArrow(stream, state) {
173 if (state.fatArrowAt) state.fatArrowAt = null;
174 var arrow = stream.string.indexOf("=>", stream.start);
175 if (arrow < 0) return;
176
177 var depth = 0, sawSomething = false;
178 for (var pos = arrow - 1; pos >= 0; --pos) {
179 var ch = stream.string.charAt(pos);
180 var bracket = brackets.indexOf(ch);
181 if (bracket >= 0 && bracket < 3) {
182 if (!depth) { ++pos; break; }
183 if (--depth == 0) break;
184 } else if (bracket >= 3 && bracket < 6) {
185 ++depth;
186 } else if (/[$\w]/.test(ch)) {
187 sawSomething = true;
188 } else if (sawSomething && !depth) {
189 ++pos;
190 break;
191 }
192 }
193 if (sawSomething && !depth) state.fatArrowAt = pos;
194 }
195
196 // Parser
197
198 var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true};
199
200 function JSLexical(indented, column, type, align, prev, info) {
201 this.indented = indented;
202 this.column = column;
203 this.type = type;
204 this.prev = prev;
205 this.info = info;
206 if (align != null) this.align = align;
207 }
208
209 function inScope(state, varname) {
210 for (var v = state.localVars; v; v = v.next)
211 if (v.name == varname) return true;
212 for (var cx = state.context; cx; cx = cx.prev) {
213 for (var v = cx.vars; v; v = v.next)
214 if (v.name == varname) return true;
215 }
216 }
217
218 function parseJS(state, style, type, content, stream) {
219 var cc = state.cc;
220 // Communicate our context to the combinators.
221 // (Less wasteful than consing up a hundred closures on every call.)
222 cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
223
224 if (!state.lexical.hasOwnProperty("align"))
225 state.lexical.align = true;
226
227 while(true) {
228 var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
229 if (combinator(type, content)) {
230 while(cc.length && cc[cc.length - 1].lex)
231 cc.pop()();
232 if (cx.marked) return cx.marked;
233 if (type == "variable" && inScope(state, content)) return "variable-2";
234 return style;
235 }
236 }
237 }
238
239 // Combinator utils
240
241 var cx = {state: null, column: null, marked: null, cc: null};
242 function pass() {
243 for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
244 }
245 function cont() {
246 pass.apply(null, arguments);
247 return true;
248 }
249 function register(varname) {
250 function inList(list) {
251 for (var v = list; v; v = v.next)
252 if (v.name == varname) return true;
253 return false;
254 }
255 var state = cx.state;
256 if (state.context) {
257 cx.marked = "def";
258 if (inList(state.localVars)) return;
259 state.localVars = {name: varname, next: state.localVars};
260 } else {
261 if (inList(state.globalVars)) return;
262 if (parserConfig.globalVars)
263 state.globalVars = {name: varname, next: state.globalVars};
264 }
265 }
266
267 // Combinators
268
269 var defaultVars = {name: "this", next: {name: "arguments"}};
270 function pushcontext() {
271 cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
272 cx.state.localVars = defaultVars;
273 }
274 function popcontext() {
275 cx.state.localVars = cx.state.context.vars;
276 cx.state.context = cx.state.context.prev;
277 }
278 function pushlex(type, info) {
279 var result = function() {
280 var state = cx.state, indent = state.indented;
281 if (state.lexical.type == "stat") indent = state.lexical.indented;
282 state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
283 };
284 result.lex = true;
285 return result;
286 }
287 function poplex() {
288 var state = cx.state;
289 if (state.lexical.prev) {
290 if (state.lexical.type == ")")
291 state.indented = state.lexical.indented;
292 state.lexical = state.lexical.prev;
293 }
294 }
295 poplex.lex = true;
296
297 function expect(wanted) {
298 return function(type) {
299 if (type == wanted) return cont();
300 else if (wanted == ";") return pass();
301 else return cont(arguments.callee);
302 };
303 }
304
305 function statement(type, value) {
306 if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
307 if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
308 if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
309 if (type == "{") return cont(pushlex("}"), block, poplex);
310 if (type == ";") return cont();
311 if (type == "if") return cont(pushlex("form"), expression, statement, poplex, maybeelse);
312 if (type == "function") return cont(functiondef);
313 if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
314 if (type == "variable") return cont(pushlex("stat"), maybelabel);
315 if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
316 block, poplex, poplex);
317 if (type == "case") return cont(expression, expect(":"));
318 if (type == "default") return cont(expect(":"));
319 if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
320 statement, poplex, popcontext);
321 if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex);
322 if (type == "class") return cont(pushlex("form"), className, objlit, poplex);
323 if (type == "export") return cont(pushlex("form"), afterExport, poplex);
324 if (type == "import") return cont(pushlex("form"), afterImport, poplex);
325 return pass(pushlex("stat"), expression, expect(";"), poplex);
326 }
327 function expression(type) {
328 return expressionInner(type, false);
329 }
330 function expressionNoComma(type) {
331 return expressionInner(type, true);
332 }
333 function expressionInner(type, noComma) {
334 if (cx.state.fatArrowAt == cx.stream.start) {
335 var body = noComma ? arrowBodyNoComma : arrowBody;
336 if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext);
337 else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
338 }
339
340 var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
341 if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
342 if (type == "function") return cont(functiondef);
343 if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
344 if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
345 if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
346 if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
347 if (type == "{") return contCommasep(objprop, "}", null, maybeop);
348 return cont();
349 }
350 function maybeexpression(type) {
351 if (type.match(/[;\}\)\],]/)) return pass();
352 return pass(expression);
353 }
354 function maybeexpressionNoComma(type) {
355 if (type.match(/[;\}\)\],]/)) return pass();
356 return pass(expressionNoComma);
357 }
358
359 function maybeoperatorComma(type, value) {
360 if (type == ",") return cont(expression);
361 return maybeoperatorNoComma(type, value, false);
362 }
363 function maybeoperatorNoComma(type, value, noComma) {
364 var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
365 var expr = noComma == false ? expression : expressionNoComma;
366 if (value == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
367 if (type == "operator") {
368 if (/\+\+|--/.test(value)) return cont(me);
369 if (value == "?") return cont(expression, expect(":"), expr);
370 return cont(expr);
371 }
372 if (type == "quasi") { cx.cc.push(me); return quasi(value); }
373 if (type == ";") return;
374 if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
375 if (type == ".") return cont(property, me);
376 if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
377 }
378 function quasi(value) {
379 if (value.slice(value.length - 2) != "${") return cont();
380 return cont(expression, continueQuasi);
381 }
382 function continueQuasi(type) {
383 if (type == "}") {
384 cx.marked = "string-2";
385 cx.state.tokenize = tokenQuasi;
386 return cont();
387 }
388 }
389 function arrowBody(type) {
390 findFatArrow(cx.stream, cx.state);
391 if (type == "{") return pass(statement);
392 return pass(expression);
393 }
394 function arrowBodyNoComma(type) {
395 findFatArrow(cx.stream, cx.state);
396 if (type == "{") return pass(statement);
397 return pass(expressionNoComma);
398 }
399 function maybelabel(type) {
400 if (type == ":") return cont(poplex, statement);
401 return pass(maybeoperatorComma, expect(";"), poplex);
402 }
403 function property(type) {
404 if (type == "variable") {cx.marked = "property"; return cont();}
405 }
406 function objprop(type, value) {
407 if (type == "variable") {
408 cx.marked = "property";
409 if (value == "get" || value == "set") return cont(getterSetter);
410 } else if (type == "number" || type == "string") {
411 cx.marked = type + " property";
412 } else if (type == "[") {
413 return cont(expression, expect("]"), afterprop);
414 }
415 if (atomicTypes.hasOwnProperty(type)) return cont(afterprop);
416 }
417 function getterSetter(type) {
418 if (type != "variable") return pass(afterprop);
419 cx.marked = "property";
420 return cont(functiondef);
421 }
422 function afterprop(type) {
423 if (type == ":") return cont(expressionNoComma);
424 if (type == "(") return pass(functiondef);
425 }
426 function commasep(what, end) {
427 function proceed(type) {
428 if (type == ",") {
429 var lex = cx.state.lexical;
430 if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
431 return cont(what, proceed);
432 }
433 if (type == end) return cont();
434 return cont(expect(end));
435 }
436 return function(type) {
437 if (type == end) return cont();
438 return pass(what, proceed);
439 };
440 }
441 function contCommasep(what, end, info) {
442 for (var i = 3; i < arguments.length; i++)
443 cx.cc.push(arguments[i]);
444 return cont(pushlex(end, info), commasep(what, end), poplex);
445 }
446 function block(type) {
447 if (type == "}") return cont();
448 return pass(statement, block);
449 }
450 function maybetype(type) {
451 if (isTS && type == ":") return cont(typedef);
452 }
453 function typedef(type) {
454 if (type == "variable"){cx.marked = "variable-3"; return cont();}
455 }
456 function vardef() {
457 return pass(pattern, maybetype, maybeAssign, vardefCont);
458 }
459 function pattern(type, value) {
460 if (type == "variable") { register(value); return cont(); }
461 if (type == "[") return contCommasep(pattern, "]");
462 if (type == "{") return contCommasep(proppattern, "}");
463 }
464 function proppattern(type, value) {
465 if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
466 register(value);
467 return cont(maybeAssign);
468 }
469 if (type == "variable") cx.marked = "property";
470 return cont(expect(":"), pattern, maybeAssign);
471 }
472 function maybeAssign(_type, value) {
473 if (value == "=") return cont(expressionNoComma);
474 }
475 function vardefCont(type) {
476 if (type == ",") return cont(vardef);
477 }
478 function maybeelse(type, value) {
479 if (type == "keyword b" && value == "else") return cont(pushlex("form"), statement, poplex);
480 }
481 function forspec(type) {
482 if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
483 }
484 function forspec1(type) {
485 if (type == "var") return cont(vardef, expect(";"), forspec2);
486 if (type == ";") return cont(forspec2);
487 if (type == "variable") return cont(formaybeinof);
488 return pass(expression, expect(";"), forspec2);
489 }
490 function formaybeinof(_type, value) {
491 if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
492 return cont(maybeoperatorComma, forspec2);
493 }
494 function forspec2(type, value) {
495 if (type == ";") return cont(forspec3);
496 if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
497 return pass(expression, expect(";"), forspec3);
498 }
499 function forspec3(type) {
500 if (type != ")") cont(expression);
501 }
502 function functiondef(type, value) {
503 if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
504 if (type == "variable") {register(value); return cont(functiondef);}
505 if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext);
506 }
507 function funarg(type) {
508 if (type == "spread") return cont(funarg);
509 return pass(pattern, maybetype);
510 }
511 function className(type, value) {
512 if (type == "variable") {register(value); return cont(classNameAfter);}
513 }
514 function classNameAfter(_type, value) {
515 if (value == "extends") return cont(expression);
516 }
517 function objlit(type) {
518 if (type == "{") return contCommasep(objprop, "}");
519 }
520 function afterModule(type, value) {
521 if (type == "string") return cont(statement);
522 if (type == "variable") { register(value); return cont(maybeFrom); }
523 }
524 function afterExport(_type, value) {
525 if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
526 if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
527 return pass(statement);
528 }
529 function afterImport(type) {
530 if (type == "string") return cont();
531 return pass(importSpec, maybeFrom);
532 }
533 function importSpec(type, value) {
534 if (type == "{") return contCommasep(importSpec, "}");
535 if (type == "variable") register(value);
536 return cont();
537 }
538 function maybeFrom(_type, value) {
539 if (value == "from") { cx.marked = "keyword"; return cont(expression); }
540 }
541 function arrayLiteral(type) {
542 if (type == "]") return cont();
543 return pass(expressionNoComma, maybeArrayComprehension);
544 }
545 function maybeArrayComprehension(type) {
546 if (type == "for") return pass(comprehension, expect("]"));
547 if (type == ",") return cont(commasep(expressionNoComma, "]"));
548 return pass(commasep(expressionNoComma, "]"));
549 }
550 function comprehension(type) {
551 if (type == "for") return cont(forspec, comprehension);
552 if (type == "if") return cont(expression, comprehension);
553 }
554
555 // Interface
556
557 return {
558 startState: function(basecolumn) {
559 var state = {
560 tokenize: tokenBase,
561 lastType: "sof",
562 cc: [],
563 lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
564 localVars: parserConfig.localVars,
565 context: parserConfig.localVars && {vars: parserConfig.localVars},
566 indented: 0
567 };
568 if (parserConfig.globalVars) state.globalVars = parserConfig.globalVars;
569 return state;
570 },
571
572 token: function(stream, state) {
573 if (stream.sol()) {
574 if (!state.lexical.hasOwnProperty("align"))
575 state.lexical.align = false;
576 state.indented = stream.indentation();
577 findFatArrow(stream, state);
578 }
579 if (state.tokenize != tokenComment && stream.eatSpace()) return null;
580 var style = state.tokenize(stream, state);
581 if (type == "comment") return style;
582 state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
583 return parseJS(state, style, type, content, stream);
584 },
585
586 indent: function(state, textAfter) {
587 if (state.tokenize == tokenComment) return CodeMirror.Pass;
588 if (state.tokenize != tokenBase) return 0;
589 var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
590 // Kludge to prevent 'maybelse' from blocking lexical scope pops
591 for (var i = state.cc.length - 1; i >= 0; --i) {
592 var c = state.cc[i];
593 if (c == poplex) lexical = lexical.prev;
594 else if (c != maybeelse) break;
595 }
596 if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
597 if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
598 lexical = lexical.prev;
599 var type = lexical.type, closing = firstChar == type;
600
601 if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0);
602 else if (type == "form" && firstChar == "{") return lexical.indented;
603 else if (type == "form") return lexical.indented + indentUnit;
604 else if (type == "stat")
605 return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? statementIndent || indentUnit : 0);
606 else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
607 return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
608 else if (lexical.align) return lexical.column + (closing ? 0 : 1);
609 else return lexical.indented + (closing ? 0 : indentUnit);
610 },
611
612 electricChars: ":{}",
613 blockCommentStart: jsonMode ? null : "/*",
614 blockCommentEnd: jsonMode ? null : "*/",
615 lineComment: jsonMode ? null : "//",
616 fold: "brace",
617
618 helperType: jsonMode ? "json" : "javascript",
619 jsonMode: jsonMode
620 };
621 });
622
623 CodeMirror.defineMIME("text/javascript", "javascript");
624 CodeMirror.defineMIME("text/ecmascript", "javascript");
625 CodeMirror.defineMIME("application/javascript", "javascript");
626 CodeMirror.defineMIME("application/ecmascript", "javascript");
627 CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
628 CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
629 CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
630 CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
631