PluginProbe ʕ •ᴥ•ʔ
Admin and Site Enhancements (ASE) / 5.5.2
Admin and Site Enhancements (ASE) v5.5.2
9.1.0 9.0.2 9.0.1 9.0.0 8.9.2 8.9.1 8.9.0 8.8.8 8.8.7 8.8.6 8.8.5 8.8.4 8.8.3 8.8.2 8.8.1 8.8.0 8.7.3 8.7.2 8.7.1 8.2.1 8.2.2 8.2.3 8.3.0 8.3.1 8.3.2 8.4.0 8.4.1 8.4.2 8.5.0 8.5.1 8.5.2 8.6.0 8.6.1 8.6.2 8.7.0 5.0.1 5.0.2 5.0.2.1 5.0.2.2 5.0.2.3 5.0.2.4 5.1.0 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.8.0 5.8.1 6.0.0 6.0.3 6.0.4 6.0.5 6.0.5.1 6.0.6 6.0.7 6.0.8.1 6.1.0 6.1.3 6.2.0 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.2.6 6.2.7 6.3.0 6.3.1 6.3.2 6.4.0 6.5.0 6.5.1 6.6.0 6.7.0 6.8.0 6.8.2 6.8.3 6.9.0 6.9.1 6.9.10 6.9.11 6.9.12 6.9.13.1 6.9.13.2 6.9.2 6.9.3 6.9.4 6.9.5 6.9.6 6.9.7 6.9.8 6.9.9 7.0.0 7.0.2 7.0.2.1 7.0.2.2 7.0.2.3 7.0.3 7.1.0 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2.0 7.2.1 7.3.0 7.3.1 7.3.2 7.3.3 7.4.0 7.4.2 7.4.4 7.4.5 7.4.6 7.4.7 7.4.8 7.5.0 7.5.1 7.5.2 7.5.3 7.5.4 7.6.0 7.6.1 7.6.1.1 7.6.10 7.6.11 7.6.2 7.6.3 7.6.4 7.6.5 7.6.6 7.6.7 7.6.7.1 7.6.8 7.6.9 7.7.0 7.8.0 7.8.1 7.8.10 7.8.11 7.8.12 7.8.13 7.8.14 7.8.15 7.8.16 7.8.17 7.8.18 7.8.2 7.8.3 7.8.4 7.8.5 7.8.5.1 7.8.6 7.8.7 7.8.8 7.8.9 7.9.0 7.9.1 7.9.10 7.9.11 7.9.2 7.9.3 7.9.4 7.9.5 7.9.6 7.9.7 7.9.8 7.9.9 8.0.0 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.0.6 8.0.7 8.0.8 8.1.0 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 trunk 1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 1.9.0 2.0.0 2.1.0 2.2.0 2.3.0 2.4.0 2.5.0 2.6.0 2.7.0 2.8.0 2.8.1 2.8.2 2.8.3 2.9.0 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.2.0 3.3.0 3.4.0 3.5.0 3.6.1 3.7.0 3.8.0 3.9.0 3.9.1 3.9.2 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.1 4.8.2 4.8.3 4.9.0 4.9.1 4.9.2 4.9.3 5.0.0
admin-site-enhancements / assets / js / codemirror / javascript.js
admin-site-enhancements / assets / js / codemirror Last commit date
codemirror.min.js 3 years ago css.js 3 years ago htmlmixed.js 3 years ago javascript.js 3 years ago markdown.js 3 years ago xml.js 3 years ago
javascript.js
960 lines
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 // Distributed under an MIT license: https://codemirror.net/5/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
14 CodeMirror.defineMode("javascript", function(config, parserConfig) {
15 var indentUnit = config.indentUnit;
16 var statementIndent = parserConfig.statementIndent;
17 var jsonldMode = parserConfig.jsonld;
18 var jsonMode = parserConfig.json || jsonldMode;
19 var trackScope = parserConfig.trackScope !== false
20 var isTS = parserConfig.typescript;
21 var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
22
23 // Tokenizer
24
25 var keywords = function(){
26 function kw(type) {return {type: type, style: "keyword"};}
27 var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"), D = kw("keyword d");
28 var operator = kw("operator"), atom = {type: "atom", style: "atom"};
29
30 return {
31 "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
32 "return": D, "break": D, "continue": D, "new": kw("new"), "delete": C, "void": C, "throw": C,
33 "debugger": kw("debugger"), "var": kw("var"), "const": kw("var"), "let": kw("var"),
34 "function": kw("function"), "catch": kw("catch"),
35 "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
36 "in": operator, "typeof": operator, "instanceof": operator,
37 "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
38 "this": kw("this"), "class": kw("class"), "super": kw("atom"),
39 "yield": C, "export": kw("export"), "import": kw("import"), "extends": C,
40 "await": C
41 };
42 }();
43
44 var isOperatorChar = /[+\-*&%=<>!?|~^@]/;
45 var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
46
47 function readRegexp(stream) {
48 var escaped = false, next, inSet = false;
49 while ((next = stream.next()) != null) {
50 if (!escaped) {
51 if (next == "/" && !inSet) return;
52 if (next == "[") inSet = true;
53 else if (inSet && next == "]") inSet = false;
54 }
55 escaped = !escaped && next == "\\";
56 }
57 }
58
59 // Used as scratch variables to communicate multiple values without
60 // consing up tons of objects.
61 var type, content;
62 function ret(tp, style, cont) {
63 type = tp; content = cont;
64 return style;
65 }
66 function tokenBase(stream, state) {
67 var ch = stream.next();
68 if (ch == '"' || ch == "'") {
69 state.tokenize = tokenString(ch);
70 return state.tokenize(stream, state);
71 } else if (ch == "." && stream.match(/^\d[\d_]*(?:[eE][+\-]?[\d_]+)?/)) {
72 return ret("number", "number");
73 } else if (ch == "." && stream.match("..")) {
74 return ret("spread", "meta");
75 } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
76 return ret(ch);
77 } else if (ch == "=" && stream.eat(">")) {
78 return ret("=>", "operator");
79 } else if (ch == "0" && stream.match(/^(?:x[\dA-Fa-f_]+|o[0-7_]+|b[01_]+)n?/)) {
80 return ret("number", "number");
81 } else if (/\d/.test(ch)) {
82 stream.match(/^[\d_]*(?:n|(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)?/);
83 return ret("number", "number");
84 } else if (ch == "/") {
85 if (stream.eat("*")) {
86 state.tokenize = tokenComment;
87 return tokenComment(stream, state);
88 } else if (stream.eat("/")) {
89 stream.skipToEnd();
90 return ret("comment", "comment");
91 } else if (expressionAllowed(stream, state, 1)) {
92 readRegexp(stream);
93 stream.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/);
94 return ret("regexp", "string-2");
95 } else {
96 stream.eat("=");
97 return ret("operator", "operator", stream.current());
98 }
99 } else if (ch == "`") {
100 state.tokenize = tokenQuasi;
101 return tokenQuasi(stream, state);
102 } else if (ch == "#" && stream.peek() == "!") {
103 stream.skipToEnd();
104 return ret("meta", "meta");
105 } else if (ch == "#" && stream.eatWhile(wordRE)) {
106 return ret("variable", "property")
107 } else if (ch == "<" && stream.match("!--") ||
108 (ch == "-" && stream.match("->") && !/\S/.test(stream.string.slice(0, stream.start)))) {
109 stream.skipToEnd()
110 return ret("comment", "comment")
111 } else if (isOperatorChar.test(ch)) {
112 if (ch != ">" || !state.lexical || state.lexical.type != ">") {
113 if (stream.eat("=")) {
114 if (ch == "!" || ch == "=") stream.eat("=")
115 } else if (/[<>*+\-|&?]/.test(ch)) {
116 stream.eat(ch)
117 if (ch == ">") stream.eat(ch)
118 }
119 }
120 if (ch == "?" && stream.eat(".")) return ret(".")
121 return ret("operator", "operator", stream.current());
122 } else if (wordRE.test(ch)) {
123 stream.eatWhile(wordRE);
124 var word = stream.current()
125 if (state.lastType != ".") {
126 if (keywords.propertyIsEnumerable(word)) {
127 var kw = keywords[word]
128 return ret(kw.type, kw.style, word)
129 }
130 if (word == "async" && stream.match(/^(\s|\/\*([^*]|\*(?!\/))*?\*\/)*[\[\(\w]/, false))
131 return ret("async", "keyword", word)
132 }
133 return ret("variable", "variable", word)
134 }
135 }
136
137 function tokenString(quote) {
138 return function(stream, state) {
139 var escaped = false, next;
140 if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
141 state.tokenize = tokenBase;
142 return ret("jsonld-keyword", "meta");
143 }
144 while ((next = stream.next()) != null) {
145 if (next == quote && !escaped) break;
146 escaped = !escaped && next == "\\";
147 }
148 if (!escaped) state.tokenize = tokenBase;
149 return ret("string", "string");
150 };
151 }
152
153 function tokenComment(stream, state) {
154 var maybeEnd = false, ch;
155 while (ch = stream.next()) {
156 if (ch == "/" && maybeEnd) {
157 state.tokenize = tokenBase;
158 break;
159 }
160 maybeEnd = (ch == "*");
161 }
162 return ret("comment", "comment");
163 }
164
165 function tokenQuasi(stream, state) {
166 var escaped = false, next;
167 while ((next = stream.next()) != null) {
168 if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
169 state.tokenize = tokenBase;
170 break;
171 }
172 escaped = !escaped && next == "\\";
173 }
174 return ret("quasi", "string-2", stream.current());
175 }
176
177 var brackets = "([{}])";
178 // This is a crude lookahead trick to try and notice that we're
179 // parsing the argument patterns for a fat-arrow function before we
180 // actually hit the arrow token. It only works if the arrow is on
181 // the same line as the arguments and there's no strange noise
182 // (comments) in between. Fallback is to only notice when we hit the
183 // arrow, and not declare the arguments as locals for the arrow
184 // body.
185 function findFatArrow(stream, state) {
186 if (state.fatArrowAt) state.fatArrowAt = null;
187 var arrow = stream.string.indexOf("=>", stream.start);
188 if (arrow < 0) return;
189
190 if (isTS) { // Try to skip TypeScript return type declarations after the arguments
191 var m = /:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(stream.string.slice(stream.start, arrow))
192 if (m) arrow = m.index
193 }
194
195 var depth = 0, sawSomething = false;
196 for (var pos = arrow - 1; pos >= 0; --pos) {
197 var ch = stream.string.charAt(pos);
198 var bracket = brackets.indexOf(ch);
199 if (bracket >= 0 && bracket < 3) {
200 if (!depth) { ++pos; break; }
201 if (--depth == 0) { if (ch == "(") sawSomething = true; break; }
202 } else if (bracket >= 3 && bracket < 6) {
203 ++depth;
204 } else if (wordRE.test(ch)) {
205 sawSomething = true;
206 } else if (/["'\/`]/.test(ch)) {
207 for (;; --pos) {
208 if (pos == 0) return
209 var next = stream.string.charAt(pos - 1)
210 if (next == ch && stream.string.charAt(pos - 2) != "\\") { pos--; break }
211 }
212 } else if (sawSomething && !depth) {
213 ++pos;
214 break;
215 }
216 }
217 if (sawSomething && !depth) state.fatArrowAt = pos;
218 }
219
220 // Parser
221
222 var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true,
223 "regexp": true, "this": true, "import": true, "jsonld-keyword": true};
224
225 function JSLexical(indented, column, type, align, prev, info) {
226 this.indented = indented;
227 this.column = column;
228 this.type = type;
229 this.prev = prev;
230 this.info = info;
231 if (align != null) this.align = align;
232 }
233
234 function inScope(state, varname) {
235 if (!trackScope) return false
236 for (var v = state.localVars; v; v = v.next)
237 if (v.name == varname) return true;
238 for (var cx = state.context; cx; cx = cx.prev) {
239 for (var v = cx.vars; v; v = v.next)
240 if (v.name == varname) return true;
241 }
242 }
243
244 function parseJS(state, style, type, content, stream) {
245 var cc = state.cc;
246 // Communicate our context to the combinators.
247 // (Less wasteful than consing up a hundred closures on every call.)
248 cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
249
250 if (!state.lexical.hasOwnProperty("align"))
251 state.lexical.align = true;
252
253 while(true) {
254 var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
255 if (combinator(type, content)) {
256 while(cc.length && cc[cc.length - 1].lex)
257 cc.pop()();
258 if (cx.marked) return cx.marked;
259 if (type == "variable" && inScope(state, content)) return "variable-2";
260 return style;
261 }
262 }
263 }
264
265 // Combinator utils
266
267 var cx = {state: null, column: null, marked: null, cc: null};
268 function pass() {
269 for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
270 }
271 function cont() {
272 pass.apply(null, arguments);
273 return true;
274 }
275 function inList(name, list) {
276 for (var v = list; v; v = v.next) if (v.name == name) return true
277 return false;
278 }
279 function register(varname) {
280 var state = cx.state;
281 cx.marked = "def";
282 if (!trackScope) return
283 if (state.context) {
284 if (state.lexical.info == "var" && state.context && state.context.block) {
285 // FIXME function decls are also not block scoped
286 var newContext = registerVarScoped(varname, state.context)
287 if (newContext != null) {
288 state.context = newContext
289 return
290 }
291 } else if (!inList(varname, state.localVars)) {
292 state.localVars = new Var(varname, state.localVars)
293 return
294 }
295 }
296 // Fall through means this is global
297 if (parserConfig.globalVars && !inList(varname, state.globalVars))
298 state.globalVars = new Var(varname, state.globalVars)
299 }
300 function registerVarScoped(varname, context) {
301 if (!context) {
302 return null
303 } else if (context.block) {
304 var inner = registerVarScoped(varname, context.prev)
305 if (!inner) return null
306 if (inner == context.prev) return context
307 return new Context(inner, context.vars, true)
308 } else if (inList(varname, context.vars)) {
309 return context
310 } else {
311 return new Context(context.prev, new Var(varname, context.vars), false)
312 }
313 }
314
315 function isModifier(name) {
316 return name == "public" || name == "private" || name == "protected" || name == "abstract" || name == "readonly"
317 }
318
319 // Combinators
320
321 function Context(prev, vars, block) { this.prev = prev; this.vars = vars; this.block = block }
322 function Var(name, next) { this.name = name; this.next = next }
323
324 var defaultVars = new Var("this", new Var("arguments", null))
325 function pushcontext() {
326 cx.state.context = new Context(cx.state.context, cx.state.localVars, false)
327 cx.state.localVars = defaultVars
328 }
329 function pushblockcontext() {
330 cx.state.context = new Context(cx.state.context, cx.state.localVars, true)
331 cx.state.localVars = null
332 }
333 pushcontext.lex = pushblockcontext.lex = true
334 function popcontext() {
335 cx.state.localVars = cx.state.context.vars
336 cx.state.context = cx.state.context.prev
337 }
338 popcontext.lex = true
339 function pushlex(type, info) {
340 var result = function() {
341 var state = cx.state, indent = state.indented;
342 if (state.lexical.type == "stat") indent = state.lexical.indented;
343 else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
344 indent = outer.indented;
345 state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
346 };
347 result.lex = true;
348 return result;
349 }
350 function poplex() {
351 var state = cx.state;
352 if (state.lexical.prev) {
353 if (state.lexical.type == ")")
354 state.indented = state.lexical.indented;
355 state.lexical = state.lexical.prev;
356 }
357 }
358 poplex.lex = true;
359
360 function expect(wanted) {
361 function exp(type) {
362 if (type == wanted) return cont();
363 else if (wanted == ";" || type == "}" || type == ")" || type == "]") return pass();
364 else return cont(exp);
365 };
366 return exp;
367 }
368
369 function statement(type, value) {
370 if (type == "var") return cont(pushlex("vardef", value), vardef, expect(";"), poplex);
371 if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex);
372 if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
373 if (type == "keyword d") return cx.stream.match(/^\s*$/, false) ? cont() : cont(pushlex("stat"), maybeexpression, expect(";"), poplex);
374 if (type == "debugger") return cont(expect(";"));
375 if (type == "{") return cont(pushlex("}"), pushblockcontext, block, poplex, popcontext);
376 if (type == ";") return cont();
377 if (type == "if") {
378 if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
379 cx.state.cc.pop()();
380 return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse);
381 }
382 if (type == "function") return cont(functiondef);
383 if (type == "for") return cont(pushlex("form"), pushblockcontext, forspec, statement, popcontext, poplex);
384 if (type == "class" || (isTS && value == "interface")) {
385 cx.marked = "keyword"
386 return cont(pushlex("form", type == "class" ? type : value), className, poplex)
387 }
388 if (type == "variable") {
389 if (isTS && value == "declare") {
390 cx.marked = "keyword"
391 return cont(statement)
392 } else if (isTS && (value == "module" || value == "enum" || value == "type") && cx.stream.match(/^\s*\w/, false)) {
393 cx.marked = "keyword"
394 if (value == "enum") return cont(enumdef);
395 else if (value == "type") return cont(typename, expect("operator"), typeexpr, expect(";"));
396 else return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex)
397 } else if (isTS && value == "namespace") {
398 cx.marked = "keyword"
399 return cont(pushlex("form"), expression, statement, poplex)
400 } else if (isTS && value == "abstract") {
401 cx.marked = "keyword"
402 return cont(statement)
403 } else {
404 return cont(pushlex("stat"), maybelabel);
405 }
406 }
407 if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), pushblockcontext,
408 block, poplex, poplex, popcontext);
409 if (type == "case") return cont(expression, expect(":"));
410 if (type == "default") return cont(expect(":"));
411 if (type == "catch") return cont(pushlex("form"), pushcontext, maybeCatchBinding, statement, poplex, popcontext);
412 if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
413 if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
414 if (type == "async") return cont(statement)
415 if (value == "@") return cont(expression, statement)
416 return pass(pushlex("stat"), expression, expect(";"), poplex);
417 }
418 function maybeCatchBinding(type) {
419 if (type == "(") return cont(funarg, expect(")"))
420 }
421 function expression(type, value) {
422 return expressionInner(type, value, false);
423 }
424 function expressionNoComma(type, value) {
425 return expressionInner(type, value, true);
426 }
427 function parenExpr(type) {
428 if (type != "(") return pass()
429 return cont(pushlex(")"), maybeexpression, expect(")"), poplex)
430 }
431 function expressionInner(type, value, noComma) {
432 if (cx.state.fatArrowAt == cx.stream.start) {
433 var body = noComma ? arrowBodyNoComma : arrowBody;
434 if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, expect("=>"), body, popcontext);
435 else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
436 }
437
438 var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
439 if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
440 if (type == "function") return cont(functiondef, maybeop);
441 if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), classExpression, poplex); }
442 if (type == "keyword c" || type == "async") return cont(noComma ? expressionNoComma : expression);
443 if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
444 if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
445 if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
446 if (type == "{") return contCommasep(objprop, "}", null, maybeop);
447 if (type == "quasi") return pass(quasi, maybeop);
448 if (type == "new") return cont(maybeTarget(noComma));
449 return cont();
450 }
451 function maybeexpression(type) {
452 if (type.match(/[;\}\)\],]/)) return pass();
453 return pass(expression);
454 }
455
456 function maybeoperatorComma(type, value) {
457 if (type == ",") return cont(maybeexpression);
458 return maybeoperatorNoComma(type, value, false);
459 }
460 function maybeoperatorNoComma(type, value, noComma) {
461 var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
462 var expr = noComma == false ? expression : expressionNoComma;
463 if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
464 if (type == "operator") {
465 if (/\+\+|--/.test(value) || isTS && value == "!") return cont(me);
466 if (isTS && value == "<" && cx.stream.match(/^([^<>]|<[^<>]*>)*>\s*\(/, false))
467 return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, me);
468 if (value == "?") return cont(expression, expect(":"), expr);
469 return cont(expr);
470 }
471 if (type == "quasi") { return pass(quasi, me); }
472 if (type == ";") return;
473 if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
474 if (type == ".") return cont(property, me);
475 if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
476 if (isTS && value == "as") { cx.marked = "keyword"; return cont(typeexpr, me) }
477 if (type == "regexp") {
478 cx.state.lastType = cx.marked = "operator"
479 cx.stream.backUp(cx.stream.pos - cx.stream.start - 1)
480 return cont(expr)
481 }
482 }
483 function quasi(type, value) {
484 if (type != "quasi") return pass();
485 if (value.slice(value.length - 2) != "${") return cont(quasi);
486 return cont(maybeexpression, continueQuasi);
487 }
488 function continueQuasi(type) {
489 if (type == "}") {
490 cx.marked = "string-2";
491 cx.state.tokenize = tokenQuasi;
492 return cont(quasi);
493 }
494 }
495 function arrowBody(type) {
496 findFatArrow(cx.stream, cx.state);
497 return pass(type == "{" ? statement : expression);
498 }
499 function arrowBodyNoComma(type) {
500 findFatArrow(cx.stream, cx.state);
501 return pass(type == "{" ? statement : expressionNoComma);
502 }
503 function maybeTarget(noComma) {
504 return function(type) {
505 if (type == ".") return cont(noComma ? targetNoComma : target);
506 else if (type == "variable" && isTS) return cont(maybeTypeArgs, noComma ? maybeoperatorNoComma : maybeoperatorComma)
507 else return pass(noComma ? expressionNoComma : expression);
508 };
509 }
510 function target(_, value) {
511 if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); }
512 }
513 function targetNoComma(_, value) {
514 if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); }
515 }
516 function maybelabel(type) {
517 if (type == ":") return cont(poplex, statement);
518 return pass(maybeoperatorComma, expect(";"), poplex);
519 }
520 function property(type) {
521 if (type == "variable") {cx.marked = "property"; return cont();}
522 }
523 function objprop(type, value) {
524 if (type == "async") {
525 cx.marked = "property";
526 return cont(objprop);
527 } else if (type == "variable" || cx.style == "keyword") {
528 cx.marked = "property";
529 if (value == "get" || value == "set") return cont(getterSetter);
530 var m // Work around fat-arrow-detection complication for detecting typescript typed arrow params
531 if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\s*:\s*/, false)))
532 cx.state.fatArrowAt = cx.stream.pos + m[0].length
533 return cont(afterprop);
534 } else if (type == "number" || type == "string") {
535 cx.marked = jsonldMode ? "property" : (cx.style + " property");
536 return cont(afterprop);
537 } else if (type == "jsonld-keyword") {
538 return cont(afterprop);
539 } else if (isTS && isModifier(value)) {
540 cx.marked = "keyword"
541 return cont(objprop)
542 } else if (type == "[") {
543 return cont(expression, maybetype, expect("]"), afterprop);
544 } else if (type == "spread") {
545 return cont(expressionNoComma, afterprop);
546 } else if (value == "*") {
547 cx.marked = "keyword";
548 return cont(objprop);
549 } else if (type == ":") {
550 return pass(afterprop)
551 }
552 }
553 function getterSetter(type) {
554 if (type != "variable") return pass(afterprop);
555 cx.marked = "property";
556 return cont(functiondef);
557 }
558 function afterprop(type) {
559 if (type == ":") return cont(expressionNoComma);
560 if (type == "(") return pass(functiondef);
561 }
562 function commasep(what, end, sep) {
563 function proceed(type, value) {
564 if (sep ? sep.indexOf(type) > -1 : type == ",") {
565 var lex = cx.state.lexical;
566 if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
567 return cont(function(type, value) {
568 if (type == end || value == end) return pass()
569 return pass(what)
570 }, proceed);
571 }
572 if (type == end || value == end) return cont();
573 if (sep && sep.indexOf(";") > -1) return pass(what)
574 return cont(expect(end));
575 }
576 return function(type, value) {
577 if (type == end || value == end) return cont();
578 return pass(what, proceed);
579 };
580 }
581 function contCommasep(what, end, info) {
582 for (var i = 3; i < arguments.length; i++)
583 cx.cc.push(arguments[i]);
584 return cont(pushlex(end, info), commasep(what, end), poplex);
585 }
586 function block(type) {
587 if (type == "}") return cont();
588 return pass(statement, block);
589 }
590 function maybetype(type, value) {
591 if (isTS) {
592 if (type == ":") return cont(typeexpr);
593 if (value == "?") return cont(maybetype);
594 }
595 }
596 function maybetypeOrIn(type, value) {
597 if (isTS && (type == ":" || value == "in")) return cont(typeexpr)
598 }
599 function mayberettype(type) {
600 if (isTS && type == ":") {
601 if (cx.stream.match(/^\s*\w+\s+is\b/, false)) return cont(expression, isKW, typeexpr)
602 else return cont(typeexpr)
603 }
604 }
605 function isKW(_, value) {
606 if (value == "is") {
607 cx.marked = "keyword"
608 return cont()
609 }
610 }
611 function typeexpr(type, value) {
612 if (value == "keyof" || value == "typeof" || value == "infer" || value == "readonly") {
613 cx.marked = "keyword"
614 return cont(value == "typeof" ? expressionNoComma : typeexpr)
615 }
616 if (type == "variable" || value == "void") {
617 cx.marked = "type"
618 return cont(afterType)
619 }
620 if (value == "|" || value == "&") return cont(typeexpr)
621 if (type == "string" || type == "number" || type == "atom") return cont(afterType);
622 if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType)
623 if (type == "{") return cont(pushlex("}"), typeprops, poplex, afterType)
624 if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType, afterType)
625 if (type == "<") return cont(commasep(typeexpr, ">"), typeexpr)
626 if (type == "quasi") { return pass(quasiType, afterType); }
627 }
628 function maybeReturnType(type) {
629 if (type == "=>") return cont(typeexpr)
630 }
631 function typeprops(type) {
632 if (type.match(/[\}\)\]]/)) return cont()
633 if (type == "," || type == ";") return cont(typeprops)
634 return pass(typeprop, typeprops)
635 }
636 function typeprop(type, value) {
637 if (type == "variable" || cx.style == "keyword") {
638 cx.marked = "property"
639 return cont(typeprop)
640 } else if (value == "?" || type == "number" || type == "string") {
641 return cont(typeprop)
642 } else if (type == ":") {
643 return cont(typeexpr)
644 } else if (type == "[") {
645 return cont(expect("variable"), maybetypeOrIn, expect("]"), typeprop)
646 } else if (type == "(") {
647 return pass(functiondecl, typeprop)
648 } else if (!type.match(/[;\}\)\],]/)) {
649 return cont()
650 }
651 }
652 function quasiType(type, value) {
653 if (type != "quasi") return pass();
654 if (value.slice(value.length - 2) != "${") return cont(quasiType);
655 return cont(typeexpr, continueQuasiType);
656 }
657 function continueQuasiType(type) {
658 if (type == "}") {
659 cx.marked = "string-2";
660 cx.state.tokenize = tokenQuasi;
661 return cont(quasiType);
662 }
663 }
664 function typearg(type, value) {
665 if (type == "variable" && cx.stream.match(/^\s*[?:]/, false) || value == "?") return cont(typearg)
666 if (type == ":") return cont(typeexpr)
667 if (type == "spread") return cont(typearg)
668 return pass(typeexpr)
669 }
670 function afterType(type, value) {
671 if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
672 if (value == "|" || type == "." || value == "&") return cont(typeexpr)
673 if (type == "[") return cont(typeexpr, expect("]"), afterType)
674 if (value == "extends" || value == "implements") { cx.marked = "keyword"; return cont(typeexpr) }
675 if (value == "?") return cont(typeexpr, expect(":"), typeexpr)
676 }
677 function maybeTypeArgs(_, value) {
678 if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
679 }
680 function typeparam() {
681 return pass(typeexpr, maybeTypeDefault)
682 }
683 function maybeTypeDefault(_, value) {
684 if (value == "=") return cont(typeexpr)
685 }
686 function vardef(_, value) {
687 if (value == "enum") {cx.marked = "keyword"; return cont(enumdef)}
688 return pass(pattern, maybetype, maybeAssign, vardefCont);
689 }
690 function pattern(type, value) {
691 if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(pattern) }
692 if (type == "variable") { register(value); return cont(); }
693 if (type == "spread") return cont(pattern);
694 if (type == "[") return contCommasep(eltpattern, "]");
695 if (type == "{") return contCommasep(proppattern, "}");
696 }
697 function proppattern(type, value) {
698 if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
699 register(value);
700 return cont(maybeAssign);
701 }
702 if (type == "variable") cx.marked = "property";
703 if (type == "spread") return cont(pattern);
704 if (type == "}") return pass();
705 if (type == "[") return cont(expression, expect(']'), expect(':'), proppattern);
706 return cont(expect(":"), pattern, maybeAssign);
707 }
708 function eltpattern() {
709 return pass(pattern, maybeAssign)
710 }
711 function maybeAssign(_type, value) {
712 if (value == "=") return cont(expressionNoComma);
713 }
714 function vardefCont(type) {
715 if (type == ",") return cont(vardef);
716 }
717 function maybeelse(type, value) {
718 if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
719 }
720 function forspec(type, value) {
721 if (value == "await") return cont(forspec);
722 if (type == "(") return cont(pushlex(")"), forspec1, poplex);
723 }
724 function forspec1(type) {
725 if (type == "var") return cont(vardef, forspec2);
726 if (type == "variable") return cont(forspec2);
727 return pass(forspec2)
728 }
729 function forspec2(type, value) {
730 if (type == ")") return cont()
731 if (type == ";") return cont(forspec2)
732 if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression, forspec2) }
733 return pass(expression, forspec2)
734 }
735 function functiondef(type, value) {
736 if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
737 if (type == "variable") {register(value); return cont(functiondef);}
738 if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, statement, popcontext);
739 if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondef)
740 }
741 function functiondecl(type, value) {
742 if (value == "*") {cx.marked = "keyword"; return cont(functiondecl);}
743 if (type == "variable") {register(value); return cont(functiondecl);}
744 if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, popcontext);
745 if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondecl)
746 }
747 function typename(type, value) {
748 if (type == "keyword" || type == "variable") {
749 cx.marked = "type"
750 return cont(typename)
751 } else if (value == "<") {
752 return cont(pushlex(">"), commasep(typeparam, ">"), poplex)
753 }
754 }
755 function funarg(type, value) {
756 if (value == "@") cont(expression, funarg)
757 if (type == "spread") return cont(funarg);
758 if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(funarg); }
759 if (isTS && type == "this") return cont(maybetype, maybeAssign)
760 return pass(pattern, maybetype, maybeAssign);
761 }
762 function classExpression(type, value) {
763 // Class expressions may have an optional name.
764 if (type == "variable") return className(type, value);
765 return classNameAfter(type, value);
766 }
767 function className(type, value) {
768 if (type == "variable") {register(value); return cont(classNameAfter);}
769 }
770 function classNameAfter(type, value) {
771 if (value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, classNameAfter)
772 if (value == "extends" || value == "implements" || (isTS && type == ",")) {
773 if (value == "implements") cx.marked = "keyword";
774 return cont(isTS ? typeexpr : expression, classNameAfter);
775 }
776 if (type == "{") return cont(pushlex("}"), classBody, poplex);
777 }
778 function classBody(type, value) {
779 if (type == "async" ||
780 (type == "variable" &&
781 (value == "static" || value == "get" || value == "set" || (isTS && isModifier(value))) &&
782 cx.stream.match(/^\s+#?[\w$\xa1-\uffff]/, false))) {
783 cx.marked = "keyword";
784 return cont(classBody);
785 }
786 if (type == "variable" || cx.style == "keyword") {
787 cx.marked = "property";
788 return cont(classfield, classBody);
789 }
790 if (type == "number" || type == "string") return cont(classfield, classBody);
791 if (type == "[")
792 return cont(expression, maybetype, expect("]"), classfield, classBody)
793 if (value == "*") {
794 cx.marked = "keyword";
795 return cont(classBody);
796 }
797 if (isTS && type == "(") return pass(functiondecl, classBody)
798 if (type == ";" || type == ",") return cont(classBody);
799 if (type == "}") return cont();
800 if (value == "@") return cont(expression, classBody)
801 }
802 function classfield(type, value) {
803 if (value == "!") return cont(classfield)
804 if (value == "?") return cont(classfield)
805 if (type == ":") return cont(typeexpr, maybeAssign)
806 if (value == "=") return cont(expressionNoComma)
807 var context = cx.state.lexical.prev, isInterface = context && context.info == "interface"
808 return pass(isInterface ? functiondecl : functiondef)
809 }
810 function afterExport(type, value) {
811 if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
812 if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
813 if (type == "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";"));
814 return pass(statement);
815 }
816 function exportField(type, value) {
817 if (value == "as") { cx.marked = "keyword"; return cont(expect("variable")); }
818 if (type == "variable") return pass(expressionNoComma, exportField);
819 }
820 function afterImport(type) {
821 if (type == "string") return cont();
822 if (type == "(") return pass(expression);
823 if (type == ".") return pass(maybeoperatorComma);
824 return pass(importSpec, maybeMoreImports, maybeFrom);
825 }
826 function importSpec(type, value) {
827 if (type == "{") return contCommasep(importSpec, "}");
828 if (type == "variable") register(value);
829 if (value == "*") cx.marked = "keyword";
830 return cont(maybeAs);
831 }
832 function maybeMoreImports(type) {
833 if (type == ",") return cont(importSpec, maybeMoreImports)
834 }
835 function maybeAs(_type, value) {
836 if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
837 }
838 function maybeFrom(_type, value) {
839 if (value == "from") { cx.marked = "keyword"; return cont(expression); }
840 }
841 function arrayLiteral(type) {
842 if (type == "]") return cont();
843 return pass(commasep(expressionNoComma, "]"));
844 }
845 function enumdef() {
846 return pass(pushlex("form"), pattern, expect("{"), pushlex("}"), commasep(enummember, "}"), poplex, poplex)
847 }
848 function enummember() {
849 return pass(pattern, maybeAssign);
850 }
851
852 function isContinuedStatement(state, textAfter) {
853 return state.lastType == "operator" || state.lastType == "," ||
854 isOperatorChar.test(textAfter.charAt(0)) ||
855 /[,.]/.test(textAfter.charAt(0));
856 }
857
858 function expressionAllowed(stream, state, backUp) {
859 return state.tokenize == tokenBase &&
860 /^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(state.lastType) ||
861 (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))
862 }
863
864 // Interface
865
866 return {
867 startState: function(basecolumn) {
868 var state = {
869 tokenize: tokenBase,
870 lastType: "sof",
871 cc: [],
872 lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
873 localVars: parserConfig.localVars,
874 context: parserConfig.localVars && new Context(null, null, false),
875 indented: basecolumn || 0
876 };
877 if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
878 state.globalVars = parserConfig.globalVars;
879 return state;
880 },
881
882 token: function(stream, state) {
883 if (stream.sol()) {
884 if (!state.lexical.hasOwnProperty("align"))
885 state.lexical.align = false;
886 state.indented = stream.indentation();
887 findFatArrow(stream, state);
888 }
889 if (state.tokenize != tokenComment && stream.eatSpace()) return null;
890 var style = state.tokenize(stream, state);
891 if (type == "comment") return style;
892 state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
893 return parseJS(state, style, type, content, stream);
894 },
895
896 indent: function(state, textAfter) {
897 if (state.tokenize == tokenComment || state.tokenize == tokenQuasi) return CodeMirror.Pass;
898 if (state.tokenize != tokenBase) return 0;
899 var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top
900 // Kludge to prevent 'maybelse' from blocking lexical scope pops
901 if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
902 var c = state.cc[i];
903 if (c == poplex) lexical = lexical.prev;
904 else if (c != maybeelse && c != popcontext) break;
905 }
906 while ((lexical.type == "stat" || lexical.type == "form") &&
907 (firstChar == "}" || ((top = state.cc[state.cc.length - 1]) &&
908 (top == maybeoperatorComma || top == maybeoperatorNoComma) &&
909 !/^[,\.=+\-*:?[\(]/.test(textAfter))))
910 lexical = lexical.prev;
911 if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
912 lexical = lexical.prev;
913 var type = lexical.type, closing = firstChar == type;
914
915 if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info.length + 1 : 0);
916 else if (type == "form" && firstChar == "{") return lexical.indented;
917 else if (type == "form") return lexical.indented + indentUnit;
918 else if (type == "stat")
919 return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
920 else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
921 return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
922 else if (lexical.align) return lexical.column + (closing ? 0 : 1);
923 else return lexical.indented + (closing ? 0 : indentUnit);
924 },
925
926 electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
927 blockCommentStart: jsonMode ? null : "/*",
928 blockCommentEnd: jsonMode ? null : "*/",
929 blockCommentContinue: jsonMode ? null : " * ",
930 lineComment: jsonMode ? null : "//",
931 fold: "brace",
932 closeBrackets: "()[]{}''\"\"``",
933
934 helperType: jsonMode ? "json" : "javascript",
935 jsonldMode: jsonldMode,
936 jsonMode: jsonMode,
937
938 expressionAllowed: expressionAllowed,
939
940 skipExpression: function(state) {
941 parseJS(state, "atom", "atom", "true", new CodeMirror.StringStream("", 2, null))
942 }
943 };
944 });
945
946 CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
947
948 CodeMirror.defineMIME("text/javascript", "javascript");
949 CodeMirror.defineMIME("text/ecmascript", "javascript");
950 CodeMirror.defineMIME("application/javascript", "javascript");
951 CodeMirror.defineMIME("application/x-javascript", "javascript");
952 CodeMirror.defineMIME("application/ecmascript", "javascript");
953 CodeMirror.defineMIME("application/json", { name: "javascript", json: true });
954 CodeMirror.defineMIME("application/x-json", { name: "javascript", json: true });
955 CodeMirror.defineMIME("application/manifest+json", { name: "javascript", json: true })
956 CodeMirror.defineMIME("application/ld+json", { name: "javascript", jsonld: true });
957 CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
958 CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
959
960 });