1 // TODO actually recognize syntax of TypeScript constructs
4 if (typeof exports
== "object" && typeof module
== "object") // CommonJS
5 mod(require("../../lib/codemirror"));
6 else if (typeof define
== "function" && define
.amd
) // AMD
7 define(["../../lib/codemirror"], mod
);
8 else // Plain browser env
10 })(function(CodeMirror
) {
13 CodeMirror
.defineMode("javascript", function(config
, parserConfig
) {
14 var indentUnit
= config
.indentUnit
;
15 var statementIndent
= parserConfig
.statementIndent
;
16 var jsonldMode
= parserConfig
.jsonld
;
17 var jsonMode
= parserConfig
.json
|| jsonldMode
;
18 var isTS
= parserConfig
.typescript
;
22 var keywords = function(){
23 function kw(type
) {return {type
: type
, style
: "keyword"};}
24 var A
= kw("keyword a"), B
= kw("keyword b"), C
= kw("keyword c");
25 var operator
= kw("operator"), atom
= {type
: "atom", style
: "atom"};
28 "if": kw("if"), "while": A
, "with": A
, "else": B
, "do": B
, "try": B
, "finally": B
,
29 "return": C
, "break": C
, "continue": C
, "new": C
, "delete": C
, "throw": C
, "debugger": C
,
30 "var": kw("var"), "const": kw("var"), "let": kw("var"),
31 "function": kw("function"), "catch": kw("catch"),
32 "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
33 "in": operator
, "typeof": operator
, "instanceof": operator
,
34 "true": atom
, "false": atom
, "null": atom
, "undefined": atom
, "NaN": atom
, "Infinity": atom
,
35 "this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"),
36 "yield": C
, "export": kw("export"), "import": kw("import"), "extends": C
39 // Extend the 'normal' keywords with the TypeScript language extensions
41 var type
= {type
: "variable", style
: "variable-3"};
44 "interface": kw("interface"),
45 "extends": kw("extends"),
46 "constructor": kw("constructor"),
49 "public": kw("public"),
50 "private": kw("private"),
51 "protected": kw("protected"),
52 "static": kw("static"),
55 "string": type
, "number": type
, "bool": type
, "any": type
58 for (var attr
in tsKeywords
) {
59 jsKeywords
[attr
] = tsKeywords
[attr
];
66 var isOperatorChar
= /[+\-*&%=<>!?|~^]/;
67 var isJsonldKeyword
= /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
69 function readRegexp(stream
) {
70 var escaped
= false, next
, inSet
= false;
71 while ((next
= stream
.next()) != null) {
73 if (next
== "/" && !inSet
) return;
74 if (next
== "[") inSet
= true;
75 else if (inSet
&& next
== "]") inSet
= false;
77 escaped
= !escaped
&& next
== "\\";
81 // Used as scratch variables to communicate multiple values without
82 // consing up tons of objects.
84 function ret(tp
, style
, cont
) {
85 type
= tp
; content
= cont
;
88 function tokenBase(stream
, state
) {
89 var ch
= stream
.next();
90 if (ch
== '"' || ch
== "'") {
91 state
.tokenize
= tokenString(ch
);
92 return state
.tokenize(stream
, state
);
93 } else if (ch
== "." && stream
.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
94 return ret("number", "number");
95 } else if (ch
== "." && stream
.match("..")) {
96 return ret("spread", "meta");
97 } else if (/[\[\]{}\(\),;\:\.]/.test(ch
)) {
99 } else if (ch
== "=" && stream
.eat(">")) {
100 return ret("=>", "operator");
101 } else if (ch
== "0" && stream
.eat(/x
/i
)) {
102 stream
.eatWhile(/[\da-f]/i);
103 return ret("number", "number");
104 } else if (/\d/.test(ch
)) {
105 stream
.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
106 return ret("number", "number");
107 } else if (ch
== "/") {
108 if (stream
.eat("*")) {
109 state
.tokenize
= tokenComment
;
110 return tokenComment(stream
, state
);
111 } else if (stream
.eat("/")) {
113 return ret("comment", "comment");
114 } else if (state
.lastType
== "operator" || state
.lastType
== "keyword c" ||
115 state
.lastType
== "sof" || /^[\[{}\(,;:]$/.test(state
.lastType
)) {
117 stream
.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
118 return ret("regexp", "string-2");
120 stream
.eatWhile(isOperatorChar
);
121 return ret("operator", "operator", stream
.current());
123 } else if (ch
== "`") {
124 state
.tokenize
= tokenQuasi
;
125 return tokenQuasi(stream
, state
);
126 } else if (ch
== "#") {
128 return ret("error", "error");
129 } else if (isOperatorChar
.test(ch
)) {
130 stream
.eatWhile(isOperatorChar
);
131 return ret("operator", "operator", stream
.current());
133 stream
.eatWhile(/[\w\$_]/);
134 var word
= stream
.current(), known
= keywords
.propertyIsEnumerable(word
) && keywords
[word
];
135 return (known
&& state
.lastType
!= ".") ? ret(known
.type
, known
.style
, word
) :
136 ret("variable", "variable", word
);
140 function tokenString(quote
) {
141 return function(stream
, state
) {
142 var escaped
= false, next
;
143 if (jsonldMode
&& stream
.peek() == "@" && stream
.match(isJsonldKeyword
)){
144 state
.tokenize
= tokenBase
;
145 return ret("jsonld-keyword", "meta");
147 while ((next
= stream
.next()) != null) {
148 if (next
== quote
&& !escaped
) break;
149 escaped
= !escaped
&& next
== "\\";
151 if (!escaped
) state
.tokenize
= tokenBase
;
152 return ret("string", "string");
156 function tokenComment(stream
, state
) {
157 var maybeEnd
= false, ch
;
158 while (ch
= stream
.next()) {
159 if (ch
== "/" && maybeEnd
) {
160 state
.tokenize
= tokenBase
;
163 maybeEnd
= (ch
== "*");
165 return ret("comment", "comment");
168 function tokenQuasi(stream
, state
) {
169 var escaped
= false, next
;
170 while ((next
= stream
.next()) != null) {
171 if (!escaped
&& (next
== "`" || next
== "$" && stream
.eat("{"))) {
172 state
.tokenize
= tokenBase
;
175 escaped
= !escaped
&& next
== "\\";
177 return ret("quasi", "string-2", stream
.current());
180 var brackets
= "([{}])";
181 // This is a crude lookahead trick to try and notice that we're
182 // parsing the argument patterns for a fat-arrow function before we
183 // actually hit the arrow token. It only works if the arrow is on
184 // the same line as the arguments and there's no strange noise
185 // (comments) in between. Fallback is to only notice when we hit the
186 // arrow, and not declare the arguments as locals for the arrow
188 function findFatArrow(stream
, state
) {
189 if (state
.fatArrowAt
) state
.fatArrowAt
= null;
190 var arrow
= stream
.string
.indexOf("=>", stream
.start
);
191 if (arrow
< 0) return;
193 var depth
= 0, sawSomething
= false;
194 for (var pos
= arrow
- 1; pos
>= 0; --pos
) {
195 var ch
= stream
.string
.charAt(pos
);
196 var bracket
= brackets
.indexOf(ch
);
197 if (bracket
>= 0 && bracket
< 3) {
198 if (!depth
) { ++pos
; break; }
199 if (--depth
== 0) break;
200 } else if (bracket
>= 3 && bracket
< 6) {
202 } else if (/[$\w]/.test(ch
)) {
204 } else if (sawSomething
&& !depth
) {
209 if (sawSomething
&& !depth
) state
.fatArrowAt
= pos
;
214 var atomicTypes
= {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
216 function JSLexical(indented
, column
, type
, align
, prev
, info
) {
217 this.indented
= indented
;
218 this.column
= column
;
222 if (align
!= null) this.align
= align
;
225 function inScope(state
, varname
) {
226 for (var v
= state
.localVars
; v
; v
= v
.next
)
227 if (v
.name
== varname
) return true;
228 for (var cx
= state
.context
; cx
; cx
= cx
.prev
) {
229 for (var v
= cx
.vars
; v
; v
= v
.next
)
230 if (v
.name
== varname
) return true;
234 function parseJS(state
, style
, type
, content
, stream
) {
236 // Communicate our context to the combinators.
237 // (Less wasteful than consing up a hundred closures on every call.)
238 cx
.state
= state
; cx
.stream
= stream
; cx
.marked
= null, cx
.cc
= cc
;
240 if (!state
.lexical
.hasOwnProperty("align"))
241 state
.lexical
.align
= true;
244 var combinator
= cc
.length
? cc
.pop() : jsonMode
? expression
: statement
;
245 if (combinator(type
, content
)) {
246 while(cc
.length
&& cc
[cc
.length
- 1].lex
)
248 if (cx
.marked
) return cx
.marked
;
249 if (type
== "variable" && inScope(state
, content
)) return "variable-2";
257 var cx
= {state
: null, column
: null, marked
: null, cc
: null};
259 for (var i
= arguments
.length
- 1; i
>= 0; i
--) cx
.cc
.push(arguments
[i
]);
262 pass
.apply(null, arguments
);
265 function register(varname
) {
266 function inList(list
) {
267 for (var v
= list
; v
; v
= v
.next
)
268 if (v
.name
== varname
) return true;
271 var state
= cx
.state
;
274 if (inList(state
.localVars
)) return;
275 state
.localVars
= {name
: varname
, next
: state
.localVars
};
277 if (inList(state
.globalVars
)) return;
278 if (parserConfig
.globalVars
)
279 state
.globalVars
= {name
: varname
, next
: state
.globalVars
};
285 var defaultVars
= {name
: "this", next
: {name
: "arguments"}};
286 function pushcontext() {
287 cx
.state
.context
= {prev
: cx
.state
.context
, vars
: cx
.state
.localVars
};
288 cx
.state
.localVars
= defaultVars
;
290 function popcontext() {
291 cx
.state
.localVars
= cx
.state
.context
.vars
;
292 cx
.state
.context
= cx
.state
.context
.prev
;
294 function pushlex(type
, info
) {
295 var result = function() {
296 var state
= cx
.state
, indent
= state
.indented
;
297 if (state
.lexical
.type
== "stat") indent
= state
.lexical
.indented
;
298 state
.lexical
= new JSLexical(indent
, cx
.stream
.column(), type
, null, state
.lexical
, info
);
304 var state
= cx
.state
;
305 if (state
.lexical
.prev
) {
306 if (state
.lexical
.type
== ")")
307 state
.indented
= state
.lexical
.indented
;
308 state
.lexical
= state
.lexical
.prev
;
313 function expect(wanted
) {
315 if (type
== wanted
) return cont();
316 else if (wanted
== ";") return pass();
317 else return cont(exp
);
322 function statement(type
, value
) {
323 if (type
== "var") return cont(pushlex("vardef", value
.length
), vardef
, expect(";"), poplex
);
324 if (type
== "keyword a") return cont(pushlex("form"), expression
, statement
, poplex
);
325 if (type
== "keyword b") return cont(pushlex("form"), statement
, poplex
);
326 if (type
== "{") return cont(pushlex("}"), block
, poplex
);
327 if (type
== ";") return cont();
328 if (type
== "if") return cont(pushlex("form"), expression
, statement
, poplex
, maybeelse
);
329 if (type
== "function") return cont(functiondef
);
330 if (type
== "for") return cont(pushlex("form"), forspec
, statement
, poplex
);
331 if (type
== "variable") return cont(pushlex("stat"), maybelabel
);
332 if (type
== "switch") return cont(pushlex("form"), expression
, pushlex("}", "switch"), expect("{"),
333 block
, poplex
, poplex
);
334 if (type
== "case") return cont(expression
, expect(":"));
335 if (type
== "default") return cont(expect(":"));
336 if (type
== "catch") return cont(pushlex("form"), pushcontext
, expect("("), funarg
, expect(")"),
337 statement
, poplex
, popcontext
);
338 if (type
== "module") return cont(pushlex("form"), pushcontext
, afterModule
, popcontext
, poplex
);
339 if (type
== "class") return cont(pushlex("form"), className
, objlit
, poplex
);
340 if (type
== "export") return cont(pushlex("form"), afterExport
, poplex
);
341 if (type
== "import") return cont(pushlex("form"), afterImport
, poplex
);
342 return pass(pushlex("stat"), expression
, expect(";"), poplex
);
344 function expression(type
) {
345 return expressionInner(type
, false);
347 function expressionNoComma(type
) {
348 return expressionInner(type
, true);
350 function expressionInner(type
, noComma
) {
351 if (cx
.state
.fatArrowAt
== cx
.stream
.start
) {
352 var body
= noComma
? arrowBodyNoComma
: arrowBody
;
353 if (type
== "(") return cont(pushcontext
, pushlex(")"), commasep(pattern
, ")"), poplex
, expect("=>"), body
, popcontext
);
354 else if (type
== "variable") return pass(pushcontext
, pattern
, expect("=>"), body
, popcontext
);
357 var maybeop
= noComma
? maybeoperatorNoComma
: maybeoperatorComma
;
358 if (atomicTypes
.hasOwnProperty(type
)) return cont(maybeop
);
359 if (type
== "function") return cont(functiondef
);
360 if (type
== "keyword c") return cont(noComma
? maybeexpressionNoComma
: maybeexpression
);
361 if (type
== "(") return cont(pushlex(")"), maybeexpression
, comprehension
, expect(")"), poplex
, maybeop
);
362 if (type
== "operator" || type
== "spread") return cont(noComma
? expressionNoComma
: expression
);
363 if (type
== "[") return cont(pushlex("]"), arrayLiteral
, poplex
, maybeop
);
364 if (type
== "{") return contCommasep(objprop
, "}", null, maybeop
);
367 function maybeexpression(type
) {
368 if (type
.match(/[;\}\)\],]/)) return pass();
369 return pass(expression
);
371 function maybeexpressionNoComma(type
) {
372 if (type
.match(/[;\}\)\],]/)) return pass();
373 return pass(expressionNoComma
);
376 function maybeoperatorComma(type
, value
) {
377 if (type
== ",") return cont(expression
);
378 return maybeoperatorNoComma(type
, value
, false);
380 function maybeoperatorNoComma(type
, value
, noComma
) {
381 var me
= noComma
== false ? maybeoperatorComma
: maybeoperatorNoComma
;
382 var expr
= noComma
== false ? expression
: expressionNoComma
;
383 if (value
== "=>") return cont(pushcontext
, noComma
? arrowBodyNoComma
: arrowBody
, popcontext
);
384 if (type
== "operator") {
385 if (/\+\+|--/.test(value
)) return cont(me
);
386 if (value
== "?") return cont(expression
, expect(":"), expr
);
389 if (type
== "quasi") { cx
.cc
.push(me
); return quasi(value
); }
390 if (type
== ";") return;
391 if (type
== "(") return contCommasep(expressionNoComma
, ")", "call", me
);
392 if (type
== ".") return cont(property
, me
);
393 if (type
== "[") return cont(pushlex("]"), maybeexpression
, expect("]"), poplex
, me
);
395 function quasi(value
) {
396 if (value
.slice(value
.length
- 2) != "${") return cont();
397 return cont(expression
, continueQuasi
);
399 function continueQuasi(type
) {
401 cx
.marked
= "string-2";
402 cx
.state
.tokenize
= tokenQuasi
;
406 function arrowBody(type
) {
407 findFatArrow(cx
.stream
, cx
.state
);
408 if (type
== "{") return pass(statement
);
409 return pass(expression
);
411 function arrowBodyNoComma(type
) {
412 findFatArrow(cx
.stream
, cx
.state
);
413 if (type
== "{") return pass(statement
);
414 return pass(expressionNoComma
);
416 function maybelabel(type
) {
417 if (type
== ":") return cont(poplex
, statement
);
418 return pass(maybeoperatorComma
, expect(";"), poplex
);
420 function property(type
) {
421 if (type
== "variable") {cx
.marked
= "property"; return cont();}
423 function objprop(type
, value
) {
424 if (type
== "variable") {
425 cx
.marked
= "property";
426 if (value
== "get" || value
== "set") return cont(getterSetter
);
427 } else if (type
== "number" || type
== "string") {
428 cx
.marked
= jsonldMode
? "property" : (type
+ " property");
429 } else if (type
== "[") {
430 return cont(expression
, expect("]"), afterprop
);
432 if (atomicTypes
.hasOwnProperty(type
)) return cont(afterprop
);
434 function getterSetter(type
) {
435 if (type
!= "variable") return pass(afterprop
);
436 cx
.marked
= "property";
437 return cont(functiondef
);
439 function afterprop(type
) {
440 if (type
== ":") return cont(expressionNoComma
);
441 if (type
== "(") return pass(functiondef
);
443 function commasep(what
, end
) {
444 function proceed(type
) {
446 var lex
= cx
.state
.lexical
;
447 if (lex
.info
== "call") lex
.pos
= (lex
.pos
|| 0) + 1;
448 return cont(what
, proceed
);
450 if (type
== end
) return cont();
451 return cont(expect(end
));
453 return function(type
) {
454 if (type
== end
) return cont();
455 return pass(what
, proceed
);
458 function contCommasep(what
, end
, info
) {
459 for (var i
= 3; i
< arguments
.length
; i
++)
460 cx
.cc
.push(arguments
[i
]);
461 return cont(pushlex(end
, info
), commasep(what
, end
), poplex
);
463 function block(type
) {
464 if (type
== "}") return cont();
465 return pass(statement
, block
);
467 function maybetype(type
) {
468 if (isTS
&& type
== ":") return cont(typedef
);
470 function typedef(type
) {
471 if (type
== "variable"){cx
.marked
= "variable-3"; return cont();}
474 return pass(pattern
, maybetype
, maybeAssign
, vardefCont
);
476 function pattern(type
, value
) {
477 if (type
== "variable") { register(value
); return cont(); }
478 if (type
== "[") return contCommasep(pattern
, "]");
479 if (type
== "{") return contCommasep(proppattern
, "}");
481 function proppattern(type
, value
) {
482 if (type
== "variable" && !cx
.stream
.match(/^\s*:/, false)) {
484 return cont(maybeAssign
);
486 if (type
== "variable") cx
.marked
= "property";
487 return cont(expect(":"), pattern
, maybeAssign
);
489 function maybeAssign(_type
, value
) {
490 if (value
== "=") return cont(expressionNoComma
);
492 function vardefCont(type
) {
493 if (type
== ",") return cont(vardef
);
495 function maybeelse(type
, value
) {
496 if (type
== "keyword b" && value
== "else") return cont(pushlex("form"), statement
, poplex
);
498 function forspec(type
) {
499 if (type
== "(") return cont(pushlex(")"), forspec1
, expect(")"), poplex
);
501 function forspec1(type
) {
502 if (type
== "var") return cont(vardef
, expect(";"), forspec2
);
503 if (type
== ";") return cont(forspec2
);
504 if (type
== "variable") return cont(formaybeinof
);
505 return pass(expression
, expect(";"), forspec2
);
507 function formaybeinof(_type
, value
) {
508 if (value
== "in" || value
== "of") { cx
.marked
= "keyword"; return cont(expression
); }
509 return cont(maybeoperatorComma
, forspec2
);
511 function forspec2(type
, value
) {
512 if (type
== ";") return cont(forspec3
);
513 if (value
== "in" || value
== "of") { cx
.marked
= "keyword"; return cont(expression
); }
514 return pass(expression
, expect(";"), forspec3
);
516 function forspec3(type
) {
517 if (type
!= ")") cont(expression
);
519 function functiondef(type
, value
) {
520 if (value
== "*") {cx
.marked
= "keyword"; return cont(functiondef
);}
521 if (type
== "variable") {register(value
); return cont(functiondef
);}
522 if (type
== "(") return cont(pushcontext
, pushlex(")"), commasep(funarg
, ")"), poplex
, statement
, popcontext
);
524 function funarg(type
) {
525 if (type
== "spread") return cont(funarg
);
526 return pass(pattern
, maybetype
);
528 function className(type
, value
) {
529 if (type
== "variable") {register(value
); return cont(classNameAfter
);}
531 function classNameAfter(_type
, value
) {
532 if (value
== "extends") return cont(expression
);
534 function objlit(type
) {
535 if (type
== "{") return contCommasep(objprop
, "}");
537 function afterModule(type
, value
) {
538 if (type
== "string") return cont(statement
);
539 if (type
== "variable") { register(value
); return cont(maybeFrom
); }
541 function afterExport(_type
, value
) {
542 if (value
== "*") { cx
.marked
= "keyword"; return cont(maybeFrom
, expect(";")); }
543 if (value
== "default") { cx
.marked
= "keyword"; return cont(expression
, expect(";")); }
544 return pass(statement
);
546 function afterImport(type
) {
547 if (type
== "string") return cont();
548 return pass(importSpec
, maybeFrom
);
550 function importSpec(type
, value
) {
551 if (type
== "{") return contCommasep(importSpec
, "}");
552 if (type
== "variable") register(value
);
555 function maybeFrom(_type
, value
) {
556 if (value
== "from") { cx
.marked
= "keyword"; return cont(expression
); }
558 function arrayLiteral(type
) {
559 if (type
== "]") return cont();
560 return pass(expressionNoComma
, maybeArrayComprehension
);
562 function maybeArrayComprehension(type
) {
563 if (type
== "for") return pass(comprehension
, expect("]"));
564 if (type
== ",") return cont(commasep(expressionNoComma
, "]"));
565 return pass(commasep(expressionNoComma
, "]"));
567 function comprehension(type
) {
568 if (type
== "for") return cont(forspec
, comprehension
);
569 if (type
== "if") return cont(expression
, comprehension
);
575 startState: function(basecolumn
) {
580 lexical
: new JSLexical((basecolumn
|| 0) - indentUnit
, 0, "block", false),
581 localVars
: parserConfig
.localVars
,
582 context
: parserConfig
.localVars
&& {vars
: parserConfig
.localVars
},
585 if (parserConfig
.globalVars
&& typeof parserConfig
.globalVars
== "object")
586 state
.globalVars
= parserConfig
.globalVars
;
590 token: function(stream
, state
) {
592 if (!state
.lexical
.hasOwnProperty("align"))
593 state
.lexical
.align
= false;
594 state
.indented
= stream
.indentation();
595 findFatArrow(stream
, state
);
597 if (state
.tokenize
!= tokenComment
&& stream
.eatSpace()) return null;
598 var style
= state
.tokenize(stream
, state
);
599 if (type
== "comment") return style
;
600 state
.lastType
= type
== "operator" && (content
== "++" || content
== "--") ? "incdec" : type
;
601 return parseJS(state
, style
, type
, content
, stream
);
604 indent: function(state
, textAfter
) {
605 if (state
.tokenize
== tokenComment
) return CodeMirror
.Pass
;
606 if (state
.tokenize
!= tokenBase
) return 0;
607 var firstChar
= textAfter
&& textAfter
.charAt(0), lexical
= state
.lexical
;
608 // Kludge to prevent 'maybelse' from blocking lexical scope pops
609 for (var i
= state
.cc
.length
- 1; i
>= 0; --i
) {
611 if (c
== poplex
) lexical
= lexical
.prev
;
612 else if (c
!= maybeelse
) break;
614 if (lexical
.type
== "stat" && firstChar
== "}") lexical
= lexical
.prev
;
615 if (statementIndent
&& lexical
.type
== ")" && lexical
.prev
.type
== "stat")
616 lexical
= lexical
.prev
;
617 var type
= lexical
.type
, closing
= firstChar
== type
;
619 if (type
== "vardef") return lexical
.indented
+ (state
.lastType
== "operator" || state
.lastType
== "," ? lexical
.info
+ 1 : 0);
620 else if (type
== "form" && firstChar
== "{") return lexical
.indented
;
621 else if (type
== "form") return lexical
.indented
+ indentUnit
;
622 else if (type
== "stat")
623 return lexical
.indented
+ (state
.lastType
== "operator" || state
.lastType
== "," ? statementIndent
|| indentUnit
: 0);
624 else if (lexical
.info
== "switch" && !closing
&& parserConfig
.doubleIndentSwitch
!= false)
625 return lexical
.indented
+ (/^(?:case|default)\b/.test(textAfter
) ? indentUnit
: 2 * indentUnit
);
626 else if (lexical
.align
) return lexical
.column
+ (closing
? 0 : 1);
627 else return lexical
.indented
+ (closing
? 0 : indentUnit
);
630 electricChars
: ":{}",
631 blockCommentStart
: jsonMode
? null : "/*",
632 blockCommentEnd
: jsonMode
? null : "*/",
633 lineComment
: jsonMode
? null : "//",
636 helperType
: jsonMode
? "json" : "javascript",
637 jsonldMode
: jsonldMode
,
642 CodeMirror
.defineMIME("text/javascript", "javascript");
643 CodeMirror
.defineMIME("text/ecmascript", "javascript");
644 CodeMirror
.defineMIME("application/javascript", "javascript");
645 CodeMirror
.defineMIME("application/ecmascript", "javascript");
646 CodeMirror
.defineMIME("application/json", {name
: "javascript", json
: true});
647 CodeMirror
.defineMIME("application/x-json", {name
: "javascript", json
: true});
648 CodeMirror
.defineMIME("application/ld+json", {name
: "javascript", jsonld
: true});
649 CodeMirror
.defineMIME("text/typescript", { name
: "javascript", typescript
: true });
650 CodeMirror
.defineMIME("application/typescript", { name
: "javascript", typescript
: true });