| OLD | NEW |
| 1 // CodeMirror, copyright (c) by Marijn Haverbeke and others | 1 // CodeMirror, copyright (c) by Marijn Haverbeke and others |
| 2 // Distributed under an MIT license: http://codemirror.net/LICENSE | 2 // Distributed under an MIT license: http://codemirror.net/LICENSE |
| 3 | 3 |
| 4 // TODO actually recognize syntax of TypeScript constructs | 4 // TODO actually recognize syntax of TypeScript constructs |
| 5 | 5 |
| 6 (function(mod) { | 6 (function(mod) { |
| 7 if (typeof exports == "object" && typeof module == "object") // CommonJS | 7 if (typeof exports == "object" && typeof module == "object") // CommonJS |
| 8 mod(require("../../lib/codemirror")); | 8 mod(require("../../lib/codemirror")); |
| 9 else if (typeof define == "function" && define.amd) // AMD | 9 else if (typeof define == "function" && define.amd) // AMD |
| 10 define(["../../lib/codemirror"], mod); | 10 define(["../../lib/codemirror"], mod); |
| 11 else // Plain browser env | 11 else // Plain browser env |
| 12 mod(CodeMirror); | 12 mod(CodeMirror); |
| 13 })(function(CodeMirror) { | 13 })(function(CodeMirror) { |
| 14 "use strict"; | 14 "use strict"; |
| 15 | 15 |
| 16 CodeMirror.defineMode("javascript", function(config, parserConfig) { | 16 CodeMirror.defineMode("javascript", function(config, parserConfig) { |
| 17 var indentUnit = config.indentUnit; | 17 var indentUnit = config.indentUnit; |
| 18 var statementIndent = parserConfig.statementIndent; | 18 var statementIndent = parserConfig.statementIndent; |
| 19 var jsonldMode = parserConfig.jsonld; | 19 var jsonldMode = parserConfig.jsonld; |
| 20 var jsonMode = parserConfig.json || jsonldMode; | 20 var jsonMode = parserConfig.json || jsonldMode; |
| 21 var isTS = parserConfig.typescript; | 21 var isTS = parserConfig.typescript; |
| 22 var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/; |
| 22 | 23 |
| 23 // Tokenizer | 24 // Tokenizer |
| 24 | 25 |
| 25 var keywords = function(){ | 26 var keywords = function(){ |
| 26 function kw(type) {return {type: type, style: "keyword"};} | 27 function kw(type) {return {type: type, style: "keyword"};} |
| 27 var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); | 28 var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); |
| 28 var operator = kw("operator"), atom = {type: "atom", style: "atom"}; | 29 var operator = kw("operator"), atom = {type: "atom", style: "atom"}; |
| 29 | 30 |
| 30 var jsKeywords = { | 31 var jsKeywords = { |
| 31 "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "fina
lly": B, | 32 "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "fina
lly": B, |
| 32 "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C,
"debugger": C, | 33 "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C,
"debugger": C, |
| 33 "var": kw("var"), "const": kw("var"), "let": kw("var"), | 34 "var": kw("var"), "const": kw("var"), "let": kw("var"), |
| 34 "function": kw("function"), "catch": kw("catch"), | 35 "function": kw("function"), "catch": kw("catch"), |
| 35 "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": k
w("default"), | 36 "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": k
w("default"), |
| 36 "in": operator, "typeof": operator, "instanceof": operator, | 37 "in": operator, "typeof": operator, "instanceof": operator, |
| 37 "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom,
"Infinity": atom, | 38 "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom,
"Infinity": atom, |
| 38 "this": kw("this"), "module": kw("module"), "class": kw("class"), "super":
kw("atom"), | 39 "this": kw("this"), "class": kw("class"), "super": kw("atom"), |
| 39 "yield": C, "export": kw("export"), "import": kw("import"), "extends": C | 40 "yield": C, "export": kw("export"), "import": kw("import"), "extends": C |
| 40 }; | 41 }; |
| 41 | 42 |
| 42 // Extend the 'normal' keywords with the TypeScript language extensions | 43 // Extend the 'normal' keywords with the TypeScript language extensions |
| 43 if (isTS) { | 44 if (isTS) { |
| 44 var type = {type: "variable", style: "variable-3"}; | 45 var type = {type: "variable", style: "variable-3"}; |
| 45 var tsKeywords = { | 46 var tsKeywords = { |
| 46 // object-like things | 47 // object-like things |
| 47 "interface": kw("interface"), | 48 "interface": kw("interface"), |
| 48 "extends": kw("extends"), | 49 "extends": kw("extends"), |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 } else if (ch == "/") { | 111 } else if (ch == "/") { |
| 111 if (stream.eat("*")) { | 112 if (stream.eat("*")) { |
| 112 state.tokenize = tokenComment; | 113 state.tokenize = tokenComment; |
| 113 return tokenComment(stream, state); | 114 return tokenComment(stream, state); |
| 114 } else if (stream.eat("/")) { | 115 } else if (stream.eat("/")) { |
| 115 stream.skipToEnd(); | 116 stream.skipToEnd(); |
| 116 return ret("comment", "comment"); | 117 return ret("comment", "comment"); |
| 117 } else if (state.lastType == "operator" || state.lastType == "keyword c" |
| | 118 } else if (state.lastType == "operator" || state.lastType == "keyword c" |
| |
| 118 state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType))
{ | 119 state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType))
{ |
| 119 readRegexp(stream); | 120 readRegexp(stream); |
| 120 stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla | 121 stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/); |
| 121 return ret("regexp", "string-2"); | 122 return ret("regexp", "string-2"); |
| 122 } else { | 123 } else { |
| 123 stream.eatWhile(isOperatorChar); | 124 stream.eatWhile(isOperatorChar); |
| 124 return ret("operator", "operator", stream.current()); | 125 return ret("operator", "operator", stream.current()); |
| 125 } | 126 } |
| 126 } else if (ch == "`") { | 127 } else if (ch == "`") { |
| 127 state.tokenize = tokenQuasi; | 128 state.tokenize = tokenQuasi; |
| 128 return tokenQuasi(stream, state); | 129 return tokenQuasi(stream, state); |
| 129 } else if (ch == "#") { | 130 } else if (ch == "#") { |
| 130 stream.skipToEnd(); | 131 stream.skipToEnd(); |
| 131 return ret("error", "error"); | 132 return ret("error", "error"); |
| 132 } else if (isOperatorChar.test(ch)) { | 133 } else if (isOperatorChar.test(ch)) { |
| 133 stream.eatWhile(isOperatorChar); | 134 stream.eatWhile(isOperatorChar); |
| 134 return ret("operator", "operator", stream.current()); | 135 return ret("operator", "operator", stream.current()); |
| 135 } else { | 136 } else if (wordRE.test(ch)) { |
| 136 stream.eatWhile(/[\w\$_]/); | 137 stream.eatWhile(wordRE); |
| 137 var word = stream.current(), known = keywords.propertyIsEnumerable(word) &
& keywords[word]; | 138 var word = stream.current(), known = keywords.propertyIsEnumerable(word) &
& keywords[word]; |
| 138 return (known && state.lastType != ".") ? ret(known.type, known.style, wor
d) : | 139 return (known && state.lastType != ".") ? ret(known.type, known.style, wor
d) : |
| 139 ret("variable", "variable", word); | 140 ret("variable", "variable", word); |
| 140 } | 141 } |
| 141 } | 142 } |
| 142 | 143 |
| 143 function tokenString(quote) { | 144 function tokenString(quote) { |
| 144 return function(stream, state) { | 145 return function(stream, state) { |
| 145 var escaped = false, next; | 146 var escaped = false, next; |
| 146 if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){ | 147 if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){ |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 | 196 |
| 196 var depth = 0, sawSomething = false; | 197 var depth = 0, sawSomething = false; |
| 197 for (var pos = arrow - 1; pos >= 0; --pos) { | 198 for (var pos = arrow - 1; pos >= 0; --pos) { |
| 198 var ch = stream.string.charAt(pos); | 199 var ch = stream.string.charAt(pos); |
| 199 var bracket = brackets.indexOf(ch); | 200 var bracket = brackets.indexOf(ch); |
| 200 if (bracket >= 0 && bracket < 3) { | 201 if (bracket >= 0 && bracket < 3) { |
| 201 if (!depth) { ++pos; break; } | 202 if (!depth) { ++pos; break; } |
| 202 if (--depth == 0) break; | 203 if (--depth == 0) break; |
| 203 } else if (bracket >= 3 && bracket < 6) { | 204 } else if (bracket >= 3 && bracket < 6) { |
| 204 ++depth; | 205 ++depth; |
| 205 } else if (/[$\w]/.test(ch)) { | 206 } else if (wordRE.test(ch)) { |
| 206 sawSomething = true; | 207 sawSomething = true; |
| 208 } else if (/["'\/]/.test(ch)) { |
| 209 return; |
| 207 } else if (sawSomething && !depth) { | 210 } else if (sawSomething && !depth) { |
| 208 ++pos; | 211 ++pos; |
| 209 break; | 212 break; |
| 210 } | 213 } |
| 211 } | 214 } |
| 212 if (sawSomething && !depth) state.fatArrowAt = pos; | 215 if (sawSomething && !depth) state.fatArrowAt = pos; |
| 213 } | 216 } |
| 214 | 217 |
| 215 // Parser | 218 // Parser |
| 216 | 219 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 cx.state.localVars = defaultVars; | 294 cx.state.localVars = defaultVars; |
| 292 } | 295 } |
| 293 function popcontext() { | 296 function popcontext() { |
| 294 cx.state.localVars = cx.state.context.vars; | 297 cx.state.localVars = cx.state.context.vars; |
| 295 cx.state.context = cx.state.context.prev; | 298 cx.state.context = cx.state.context.prev; |
| 296 } | 299 } |
| 297 function pushlex(type, info) { | 300 function pushlex(type, info) { |
| 298 var result = function() { | 301 var result = function() { |
| 299 var state = cx.state, indent = state.indented; | 302 var state = cx.state, indent = state.indented; |
| 300 if (state.lexical.type == "stat") indent = state.lexical.indented; | 303 if (state.lexical.type == "stat") indent = state.lexical.indented; |
| 304 else for (var outer = state.lexical; outer && outer.type == ")" && outer.a
lign; outer = outer.prev) |
| 305 indent = outer.indented; |
| 301 state.lexical = new JSLexical(indent, cx.stream.column(), type, null, stat
e.lexical, info); | 306 state.lexical = new JSLexical(indent, cx.stream.column(), type, null, stat
e.lexical, info); |
| 302 }; | 307 }; |
| 303 result.lex = true; | 308 result.lex = true; |
| 304 return result; | 309 return result; |
| 305 } | 310 } |
| 306 function poplex() { | 311 function poplex() { |
| 307 var state = cx.state; | 312 var state = cx.state; |
| 308 if (state.lexical.prev) { | 313 if (state.lexical.prev) { |
| 309 if (state.lexical.type == ")") | 314 if (state.lexical.type == ")") |
| 310 state.indented = state.lexical.indented; | 315 state.indented = state.lexical.indented; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 335 } | 340 } |
| 336 if (type == "function") return cont(functiondef); | 341 if (type == "function") return cont(functiondef); |
| 337 if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); | 342 if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); |
| 338 if (type == "variable") return cont(pushlex("stat"), maybelabel); | 343 if (type == "variable") return cont(pushlex("stat"), maybelabel); |
| 339 if (type == "switch") return cont(pushlex("form"), expression, pushlex("}",
"switch"), expect("{"), | 344 if (type == "switch") return cont(pushlex("form"), expression, pushlex("}",
"switch"), expect("{"), |
| 340 block, poplex, poplex); | 345 block, poplex, poplex); |
| 341 if (type == "case") return cont(expression, expect(":")); | 346 if (type == "case") return cont(expression, expect(":")); |
| 342 if (type == "default") return cont(expect(":")); | 347 if (type == "default") return cont(expect(":")); |
| 343 if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("),
funarg, expect(")"), | 348 if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("),
funarg, expect(")"), |
| 344 statement, poplex, popcontext); | 349 statement, poplex, popcontext); |
| 345 if (type == "module") return cont(pushlex("form"), pushcontext, afterModule,
popcontext, poplex); | |
| 346 if (type == "class") return cont(pushlex("form"), className, poplex); | 350 if (type == "class") return cont(pushlex("form"), className, poplex); |
| 347 if (type == "export") return cont(pushlex("form"), afterExport, poplex); | 351 if (type == "export") return cont(pushlex("form"), afterExport, poplex); |
| 348 if (type == "import") return cont(pushlex("form"), afterImport, poplex); | 352 if (type == "import") return cont(pushlex("form"), afterImport, poplex); |
| 349 return pass(pushlex("stat"), expression, expect(";"), poplex); | 353 return pass(pushlex("stat"), expression, expect(";"), poplex); |
| 350 } | 354 } |
| 351 function expression(type) { | 355 function expression(type) { |
| 352 return expressionInner(type, false); | 356 return expressionInner(type, false); |
| 353 } | 357 } |
| 354 function expressionNoComma(type) { | 358 function expressionNoComma(type) { |
| 355 return expressionInner(type, true); | 359 return expressionInner(type, true); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 381 return pass(expressionNoComma); | 385 return pass(expressionNoComma); |
| 382 } | 386 } |
| 383 | 387 |
| 384 function maybeoperatorComma(type, value) { | 388 function maybeoperatorComma(type, value) { |
| 385 if (type == ",") return cont(expression); | 389 if (type == ",") return cont(expression); |
| 386 return maybeoperatorNoComma(type, value, false); | 390 return maybeoperatorNoComma(type, value, false); |
| 387 } | 391 } |
| 388 function maybeoperatorNoComma(type, value, noComma) { | 392 function maybeoperatorNoComma(type, value, noComma) { |
| 389 var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma; | 393 var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma; |
| 390 var expr = noComma == false ? expression : expressionNoComma; | 394 var expr = noComma == false ? expression : expressionNoComma; |
| 391 if (value == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arr
owBody, popcontext); | 395 if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arro
wBody, popcontext); |
| 392 if (type == "operator") { | 396 if (type == "operator") { |
| 393 if (/\+\+|--/.test(value)) return cont(me); | 397 if (/\+\+|--/.test(value)) return cont(me); |
| 394 if (value == "?") return cont(expression, expect(":"), expr); | 398 if (value == "?") return cont(expression, expect(":"), expr); |
| 395 return cont(expr); | 399 return cont(expr); |
| 396 } | 400 } |
| 397 if (type == "quasi") { return pass(quasi, me); } | 401 if (type == "quasi") { return pass(quasi, me); } |
| 398 if (type == ";") return; | 402 if (type == ";") return; |
| 399 if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); | 403 if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); |
| 400 if (type == ".") return cont(property, me); | 404 if (type == ".") return cont(property, me); |
| 401 if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), pop
lex, me); | 405 if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), pop
lex, me); |
| 402 } | 406 } |
| 403 function quasi(type, value) { | 407 function quasi(type, value) { |
| 404 if (type != "quasi") return pass(); | 408 if (type != "quasi") return pass(); |
| 405 if (value.slice(value.length - 2) != "${") return cont(quasi); | 409 if (value.slice(value.length - 2) != "${") return cont(quasi); |
| 406 return cont(expression, continueQuasi); | 410 return cont(expression, continueQuasi); |
| 407 } | 411 } |
| 408 function continueQuasi(type) { | 412 function continueQuasi(type) { |
| 409 if (type == "}") { | 413 if (type == "}") { |
| 410 cx.marked = "string-2"; | 414 cx.marked = "string-2"; |
| 411 cx.state.tokenize = tokenQuasi; | 415 cx.state.tokenize = tokenQuasi; |
| 412 return cont(quasi); | 416 return cont(quasi); |
| 413 } | 417 } |
| 414 } | 418 } |
| 415 function arrowBody(type) { | 419 function arrowBody(type) { |
| 416 findFatArrow(cx.stream, cx.state); | 420 findFatArrow(cx.stream, cx.state); |
| 417 if (type == "{") return pass(statement); | 421 return pass(type == "{" ? statement : expression); |
| 418 return pass(expression); | |
| 419 } | 422 } |
| 420 function arrowBodyNoComma(type) { | 423 function arrowBodyNoComma(type) { |
| 421 findFatArrow(cx.stream, cx.state); | 424 findFatArrow(cx.stream, cx.state); |
| 422 if (type == "{") return pass(statement); | 425 return pass(type == "{" ? statement : expressionNoComma); |
| 423 return pass(expressionNoComma); | |
| 424 } | 426 } |
| 425 function maybelabel(type) { | 427 function maybelabel(type) { |
| 426 if (type == ":") return cont(poplex, statement); | 428 if (type == ":") return cont(poplex, statement); |
| 427 return pass(maybeoperatorComma, expect(";"), poplex); | 429 return pass(maybeoperatorComma, expect(";"), poplex); |
| 428 } | 430 } |
| 429 function property(type) { | 431 function property(type) { |
| 430 if (type == "variable") {cx.marked = "property"; return cont();} | 432 if (type == "variable") {cx.marked = "property"; return cont();} |
| 431 } | 433 } |
| 432 function objprop(type, value) { | 434 function objprop(type, value) { |
| 433 if (type == "variable" || cx.style == "keyword") { | 435 if (type == "variable" || cx.style == "keyword") { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 cx.cc.push(arguments[i]); | 474 cx.cc.push(arguments[i]); |
| 473 return cont(pushlex(end, info), commasep(what, end), poplex); | 475 return cont(pushlex(end, info), commasep(what, end), poplex); |
| 474 } | 476 } |
| 475 function block(type) { | 477 function block(type) { |
| 476 if (type == "}") return cont(); | 478 if (type == "}") return cont(); |
| 477 return pass(statement, block); | 479 return pass(statement, block); |
| 478 } | 480 } |
| 479 function maybetype(type) { | 481 function maybetype(type) { |
| 480 if (isTS && type == ":") return cont(typedef); | 482 if (isTS && type == ":") return cont(typedef); |
| 481 } | 483 } |
| 484 function maybedefault(_, value) { |
| 485 if (value == "=") return cont(expressionNoComma); |
| 486 } |
| 482 function typedef(type) { | 487 function typedef(type) { |
| 483 if (type == "variable"){cx.marked = "variable-3"; return cont();} | 488 if (type == "variable") {cx.marked = "variable-3"; return cont();} |
| 484 } | 489 } |
| 485 function vardef() { | 490 function vardef() { |
| 486 return pass(pattern, maybetype, maybeAssign, vardefCont); | 491 return pass(pattern, maybetype, maybeAssign, vardefCont); |
| 487 } | 492 } |
| 488 function pattern(type, value) { | 493 function pattern(type, value) { |
| 489 if (type == "variable") { register(value); return cont(); } | 494 if (type == "variable") { register(value); return cont(); } |
| 490 if (type == "[") return contCommasep(pattern, "]"); | 495 if (type == "[") return contCommasep(pattern, "]"); |
| 491 if (type == "{") return contCommasep(proppattern, "}"); | 496 if (type == "{") return contCommasep(proppattern, "}"); |
| 492 } | 497 } |
| 493 function proppattern(type, value) { | 498 function proppattern(type, value) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 function forspec3(type) { | 533 function forspec3(type) { |
| 529 if (type != ")") cont(expression); | 534 if (type != ")") cont(expression); |
| 530 } | 535 } |
| 531 function functiondef(type, value) { | 536 function functiondef(type, value) { |
| 532 if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} | 537 if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} |
| 533 if (type == "variable") {register(value); return cont(functiondef);} | 538 if (type == "variable") {register(value); return cont(functiondef);} |
| 534 if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"
), poplex, statement, popcontext); | 539 if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"
), poplex, statement, popcontext); |
| 535 } | 540 } |
| 536 function funarg(type) { | 541 function funarg(type) { |
| 537 if (type == "spread") return cont(funarg); | 542 if (type == "spread") return cont(funarg); |
| 538 return pass(pattern, maybetype); | 543 return pass(pattern, maybetype, maybedefault); |
| 539 } | 544 } |
| 540 function className(type, value) { | 545 function className(type, value) { |
| 541 if (type == "variable") {register(value); return cont(classNameAfter);} | 546 if (type == "variable") {register(value); return cont(classNameAfter);} |
| 542 } | 547 } |
| 543 function classNameAfter(type, value) { | 548 function classNameAfter(type, value) { |
| 544 if (value == "extends") return cont(expression, classNameAfter); | 549 if (value == "extends") return cont(expression, classNameAfter); |
| 545 if (type == "{") return cont(pushlex("}"), classBody, poplex); | 550 if (type == "{") return cont(pushlex("}"), classBody, poplex); |
| 546 } | 551 } |
| 547 function classBody(type, value) { | 552 function classBody(type, value) { |
| 548 if (type == "variable" || cx.style == "keyword") { | 553 if (type == "variable" || cx.style == "keyword") { |
| 554 if (value == "static") { |
| 555 cx.marked = "keyword"; |
| 556 return cont(classBody); |
| 557 } |
| 549 cx.marked = "property"; | 558 cx.marked = "property"; |
| 550 if (value == "get" || value == "set") return cont(classGetterSetter, funct
iondef, classBody); | 559 if (value == "get" || value == "set") return cont(classGetterSetter, funct
iondef, classBody); |
| 551 return cont(functiondef, classBody); | 560 return cont(functiondef, classBody); |
| 552 } | 561 } |
| 553 if (value == "*") { | 562 if (value == "*") { |
| 554 cx.marked = "keyword"; | 563 cx.marked = "keyword"; |
| 555 return cont(classBody); | 564 return cont(classBody); |
| 556 } | 565 } |
| 557 if (type == ";") return cont(classBody); | 566 if (type == ";") return cont(classBody); |
| 558 if (type == "}") return cont(); | 567 if (type == "}") return cont(); |
| 559 } | 568 } |
| 560 function classGetterSetter(type) { | 569 function classGetterSetter(type) { |
| 561 if (type != "variable") return pass(); | 570 if (type != "variable") return pass(); |
| 562 cx.marked = "property"; | 571 cx.marked = "property"; |
| 563 return cont(); | 572 return cont(); |
| 564 } | 573 } |
| 565 function afterModule(type, value) { | |
| 566 if (type == "string") return cont(statement); | |
| 567 if (type == "variable") { register(value); return cont(maybeFrom); } | |
| 568 } | |
| 569 function afterExport(_type, value) { | 574 function afterExport(_type, value) { |
| 570 if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";"
)); } | 575 if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";"
)); } |
| 571 if (value == "default") { cx.marked = "keyword"; return cont(expression, exp
ect(";")); } | 576 if (value == "default") { cx.marked = "keyword"; return cont(expression, exp
ect(";")); } |
| 572 return pass(statement); | 577 return pass(statement); |
| 573 } | 578 } |
| 574 function afterImport(type) { | 579 function afterImport(type) { |
| 575 if (type == "string") return cont(); | 580 if (type == "string") return cont(); |
| 576 return pass(importSpec, maybeFrom); | 581 return pass(importSpec, maybeFrom); |
| 577 } | 582 } |
| 578 function importSpec(type, value) { | 583 function importSpec(type, value) { |
| 579 if (type == "{") return contCommasep(importSpec, "}"); | 584 if (type == "{") return contCommasep(importSpec, "}"); |
| 580 if (type == "variable") register(value); | 585 if (type == "variable") register(value); |
| 581 return cont(); | 586 if (value == "*") cx.marked = "keyword"; |
| 587 return cont(maybeAs); |
| 588 } |
| 589 function maybeAs(_type, value) { |
| 590 if (value == "as") { cx.marked = "keyword"; return cont(importSpec); } |
| 582 } | 591 } |
| 583 function maybeFrom(_type, value) { | 592 function maybeFrom(_type, value) { |
| 584 if (value == "from") { cx.marked = "keyword"; return cont(expression); } | 593 if (value == "from") { cx.marked = "keyword"; return cont(expression); } |
| 585 } | 594 } |
| 586 function arrayLiteral(type) { | 595 function arrayLiteral(type) { |
| 587 if (type == "]") return cont(); | 596 if (type == "]") return cont(); |
| 588 return pass(expressionNoComma, maybeArrayComprehension); | 597 return pass(expressionNoComma, maybeArrayComprehension); |
| 589 } | 598 } |
| 590 function maybeArrayComprehension(type) { | 599 function maybeArrayComprehension(type) { |
| 591 if (type == "for") return pass(comprehension, expect("]")); | 600 if (type == "for") return pass(comprehension, expect("]")); |
| 592 if (type == ",") return cont(commasep(expressionNoComma, "]")); | 601 if (type == ",") return cont(commasep(maybeexpressionNoComma, "]")); |
| 593 return pass(commasep(expressionNoComma, "]")); | 602 return pass(commasep(expressionNoComma, "]")); |
| 594 } | 603 } |
| 595 function comprehension(type) { | 604 function comprehension(type) { |
| 596 if (type == "for") return cont(forspec, comprehension); | 605 if (type == "for") return cont(forspec, comprehension); |
| 597 if (type == "if") return cont(expression, comprehension); | 606 if (type == "if") return cont(expression, comprehension); |
| 598 } | 607 } |
| 599 | 608 |
| 609 function isContinuedStatement(state, textAfter) { |
| 610 return state.lastType == "operator" || state.lastType == "," || |
| 611 isOperatorChar.test(textAfter.charAt(0)) || |
| 612 /[,.]/.test(textAfter.charAt(0)); |
| 613 } |
| 614 |
| 600 // Interface | 615 // Interface |
| 601 | 616 |
| 602 return { | 617 return { |
| 603 startState: function(basecolumn) { | 618 startState: function(basecolumn) { |
| 604 var state = { | 619 var state = { |
| 605 tokenize: tokenBase, | 620 tokenize: tokenBase, |
| 606 lastType: "sof", | 621 lastType: "sof", |
| 607 cc: [], | 622 cc: [], |
| 608 lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false
), | 623 lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false
), |
| 609 localVars: parserConfig.localVars, | 624 localVars: parserConfig.localVars, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 } | 656 } |
| 642 if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev; | 657 if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev; |
| 643 if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat") | 658 if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat") |
| 644 lexical = lexical.prev; | 659 lexical = lexical.prev; |
| 645 var type = lexical.type, closing = firstChar == type; | 660 var type = lexical.type, closing = firstChar == type; |
| 646 | 661 |
| 647 if (type == "vardef") return lexical.indented + (state.lastType == "operat
or" || state.lastType == "," ? lexical.info + 1 : 0); | 662 if (type == "vardef") return lexical.indented + (state.lastType == "operat
or" || state.lastType == "," ? lexical.info + 1 : 0); |
| 648 else if (type == "form" && firstChar == "{") return lexical.indented; | 663 else if (type == "form" && firstChar == "{") return lexical.indented; |
| 649 else if (type == "form") return lexical.indented + indentUnit; | 664 else if (type == "form") return lexical.indented + indentUnit; |
| 650 else if (type == "stat") | 665 else if (type == "stat") |
| 651 return lexical.indented + (state.lastType == "operator" || state.lastTyp
e == "," ? statementIndent || indentUnit : 0); | 666 return lexical.indented + (isContinuedStatement(state, textAfter) ? stat
ementIndent || indentUnit : 0); |
| 652 else if (lexical.info == "switch" && !closing && parserConfig.doubleIndent
Switch != false) | 667 else if (lexical.info == "switch" && !closing && parserConfig.doubleIndent
Switch != false) |
| 653 return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? inden
tUnit : 2 * indentUnit); | 668 return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? inden
tUnit : 2 * indentUnit); |
| 654 else if (lexical.align) return lexical.column + (closing ? 0 : 1); | 669 else if (lexical.align) return lexical.column + (closing ? 0 : 1); |
| 655 else return lexical.indented + (closing ? 0 : indentUnit); | 670 else return lexical.indented + (closing ? 0 : indentUnit); |
| 656 }, | 671 }, |
| 657 | 672 |
| 658 electricChars: ":{}", | 673 electricInput: /^\s*(?:case .*?:|default:|\{|\})$/, |
| 659 blockCommentStart: jsonMode ? null : "/*", | 674 blockCommentStart: jsonMode ? null : "/*", |
| 660 blockCommentEnd: jsonMode ? null : "*/", | 675 blockCommentEnd: jsonMode ? null : "*/", |
| 661 lineComment: jsonMode ? null : "//", | 676 lineComment: jsonMode ? null : "//", |
| 662 fold: "brace", | 677 fold: "brace", |
| 678 closeBrackets: "()[]{}''\"\"``", |
| 663 | 679 |
| 664 helperType: jsonMode ? "json" : "javascript", | 680 helperType: jsonMode ? "json" : "javascript", |
| 665 jsonldMode: jsonldMode, | 681 jsonldMode: jsonldMode, |
| 666 jsonMode: jsonMode | 682 jsonMode: jsonMode |
| 667 }; | 683 }; |
| 668 }); | 684 }); |
| 669 | 685 |
| 670 CodeMirror.registerHelper("wordChars", "javascript", /[\\w$]/); | 686 CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/); |
| 671 | 687 |
| 672 CodeMirror.defineMIME("text/javascript", "javascript"); | 688 CodeMirror.defineMIME("text/javascript", "javascript"); |
| 673 CodeMirror.defineMIME("text/ecmascript", "javascript"); | 689 CodeMirror.defineMIME("text/ecmascript", "javascript"); |
| 674 CodeMirror.defineMIME("application/javascript", "javascript"); | 690 CodeMirror.defineMIME("application/javascript", "javascript"); |
| 675 CodeMirror.defineMIME("application/x-javascript", "javascript"); | 691 CodeMirror.defineMIME("application/x-javascript", "javascript"); |
| 676 CodeMirror.defineMIME("application/ecmascript", "javascript"); | 692 CodeMirror.defineMIME("application/ecmascript", "javascript"); |
| 677 CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); | 693 CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); |
| 678 CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true}); | 694 CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true}); |
| 679 CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true})
; | 695 CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true})
; |
| 680 CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true
}); | 696 CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true
}); |
| 681 CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript
: true }); | 697 CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript
: true }); |
| 682 | 698 |
| 683 }); | 699 }); |
| OLD | NEW |