PageSourceSearch

https://glasshunt.co/mode/javascript/javascript.js

js glasshunt.co collected 2026-10-09 00:42:07 UTC 28,897 bytes, 762 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.