codemirror-rails 3.19 → 3.20
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/codemirror/rails/version.rb +2 -2
- data/vendor/assets/javascripts/codemirror.js +61 -27
- data/vendor/assets/javascripts/codemirror/addons/dialog/dialog.js +42 -1
- data/vendor/assets/javascripts/codemirror/addons/display/fullscreen.js +2 -1
- data/vendor/assets/javascripts/codemirror/addons/display/placeholder.js +0 -6
- data/vendor/assets/javascripts/codemirror/addons/edit/closetag.js +13 -11
- data/vendor/assets/javascripts/codemirror/addons/edit/matchbrackets.js +2 -1
- data/vendor/assets/javascripts/codemirror/addons/fold/foldgutter.js +4 -4
- data/vendor/assets/javascripts/codemirror/addons/fold/indent-fold.js +25 -21
- data/vendor/assets/javascripts/codemirror/addons/hint/javascript-hint.js +1 -0
- data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +20 -8
- data/vendor/assets/javascripts/codemirror/addons/tern/tern.js +7 -7
- data/vendor/assets/javascripts/codemirror/keymaps/vim.js +3 -4
- data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +13 -8
- data/vendor/assets/javascripts/codemirror/modes/css.js +3 -3
- data/vendor/assets/javascripts/codemirror/modes/go.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/haskell.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/javascript.js +216 -79
- data/vendor/assets/javascripts/codemirror/modes/julia.js +262 -0
- data/vendor/assets/javascripts/codemirror/modes/less.js +4 -2
- data/vendor/assets/javascripts/codemirror/modes/markdown.js +16 -7
- data/vendor/assets/javascripts/codemirror/modes/pegjs.js +103 -0
- data/vendor/assets/javascripts/codemirror/modes/pig.js +1 -1
- data/vendor/assets/stylesheets/codemirror/themes/ambiance.css +1 -1
- data/vendor/assets/stylesheets/codemirror/themes/mbo.css +3 -1
- metadata +3 -1
@@ -1,26 +1,30 @@
|
|
1
1
|
CodeMirror.registerHelper("fold", "indent", function(cm, start) {
|
2
|
-
var
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
if (
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
2
|
+
var tabSize = cm.getOption("tabSize"), firstLine = cm.getLine(start.line);
|
3
|
+
if (!/\S/.test(firstLine)) return;
|
4
|
+
var getIndent = function(lineNum) {
|
5
|
+
return CodeMirror.countColumn(lineNum, null, tabSize);
|
6
|
+
};
|
7
|
+
var myIndent = getIndent(firstLine);
|
8
|
+
var lastLineInFold = null;
|
9
|
+
// Go through lines until we find a line that definitely doesn't belong in
|
10
|
+
// the block we're folding, or to the end.
|
11
|
+
for (var i = start.line + 1, end = cm.lastLine(); i <= end; ++i) {
|
12
|
+
var curLine = cm.getLine(i);
|
13
|
+
var curIndent = getIndent(curLine);
|
14
|
+
if (curIndent > myIndent) {
|
15
|
+
// Lines with a greater indent are considered part of the block.
|
16
|
+
lastLineInFold = i;
|
17
|
+
} else if (!/\S/.test(curLine)) {
|
18
|
+
// Empty lines might be breaks within the block we're trying to fold.
|
19
|
+
} else {
|
20
|
+
// A non-empty line at an indent equal to or less than ours marks the
|
21
|
+
// start of another block.
|
22
|
+
break;
|
22
23
|
}
|
23
24
|
}
|
25
|
+
if (lastLineInFold) return {
|
26
|
+
from: CodeMirror.Pos(start.line, firstLine.length),
|
27
|
+
to: CodeMirror.Pos(lastLineInFold, cm.getLine(lastLineInFold).length)
|
28
|
+
};
|
24
29
|
});
|
25
|
-
|
26
30
|
CodeMirror.indentRangeFinder = CodeMirror.fold.indent; // deprecated
|
@@ -21,6 +21,7 @@
|
|
21
21
|
function scriptHint(editor, keywords, getToken, options) {
|
22
22
|
// Find the token at the cursor
|
23
23
|
var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
|
24
|
+
if (/\b(?:string|comment)\b/.test(token.type)) return;
|
24
25
|
token.state = CodeMirror.innerMode(editor.getMode(), token.state).state;
|
25
26
|
|
26
27
|
// If it's not a 'word-style' token, ignore the token.
|
@@ -1,6 +1,9 @@
|
|
1
1
|
(function() {
|
2
2
|
"use strict";
|
3
3
|
|
4
|
+
var HINT_ELEMENT_CLASS = "CodeMirror-hint";
|
5
|
+
var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
|
6
|
+
|
4
7
|
CodeMirror.showHint = function(cm, getHints, options) {
|
5
8
|
// We want a single cursor position.
|
6
9
|
if (cm.somethingSelected()) return;
|
@@ -140,6 +143,13 @@
|
|
140
143
|
return ourMap;
|
141
144
|
}
|
142
145
|
|
146
|
+
function getHintElement(stopAt, el) {
|
147
|
+
while (el && el != stopAt) {
|
148
|
+
if (el.nodeName.toUpperCase() === "LI") return el;
|
149
|
+
el = el.parentNode;
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
143
153
|
function Widget(completion, data) {
|
144
154
|
this.completion = completion;
|
145
155
|
this.data = data;
|
@@ -147,12 +157,12 @@
|
|
147
157
|
|
148
158
|
var hints = this.hints = document.createElement("ul");
|
149
159
|
hints.className = "CodeMirror-hints";
|
150
|
-
this.selectedHint = 0;
|
160
|
+
this.selectedHint = options.getDefaultSelection ? options.getDefaultSelection(cm,options,data) : 0;
|
151
161
|
|
152
162
|
var completions = data.list;
|
153
163
|
for (var i = 0; i < completions.length; ++i) {
|
154
164
|
var elt = hints.appendChild(document.createElement("li")), cur = completions[i];
|
155
|
-
var className =
|
165
|
+
var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
|
156
166
|
if (cur.className != null) className = cur.className + " " + className;
|
157
167
|
elt.className = className;
|
158
168
|
if (cur.render) cur.render(elt, data, cur);
|
@@ -216,13 +226,15 @@
|
|
216
226
|
});
|
217
227
|
|
218
228
|
CodeMirror.on(hints, "dblclick", function(e) {
|
219
|
-
var t = e.target || e.srcElement;
|
220
|
-
if (t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
|
229
|
+
var t = getHintElement(hints, e.target || e.srcElement);
|
230
|
+
if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
|
221
231
|
});
|
232
|
+
|
222
233
|
CodeMirror.on(hints, "click", function(e) {
|
223
|
-
var t = e.target || e.srcElement;
|
224
|
-
if (t.hintId != null) widget.changeActive(t.hintId);
|
234
|
+
var t = getHintElement(hints, e.target || e.srcElement);
|
235
|
+
if (t && t.hintId != null) widget.changeActive(t.hintId);
|
225
236
|
});
|
237
|
+
|
226
238
|
CodeMirror.on(hints, "mousedown", function() {
|
227
239
|
setTimeout(function(){cm.focus();}, 20);
|
228
240
|
});
|
@@ -257,9 +269,9 @@
|
|
257
269
|
i = avoidWrap ? 0 : this.data.list.length - 1;
|
258
270
|
if (this.selectedHint == i) return;
|
259
271
|
var node = this.hints.childNodes[this.selectedHint];
|
260
|
-
node.className = node.className.replace("
|
272
|
+
node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
|
261
273
|
node = this.hints.childNodes[this.selectedHint = i];
|
262
|
-
node.className += "
|
274
|
+
node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
|
263
275
|
if (node.offsetTop < this.hints.scrollTop)
|
264
276
|
this.hints.scrollTop = node.offsetTop - 3;
|
265
277
|
else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
|
@@ -96,7 +96,7 @@
|
|
96
96
|
|
97
97
|
getHint: function(cm, c) { return hint(this, cm, c); },
|
98
98
|
|
99
|
-
showType: function(cm) { showType(this, cm); },
|
99
|
+
showType: function(cm, pos) { showType(this, cm, pos); },
|
100
100
|
|
101
101
|
updateArgHints: function(cm) { updateArgHints(this, cm); },
|
102
102
|
|
@@ -106,10 +106,10 @@
|
|
106
106
|
|
107
107
|
rename: function(cm) { rename(this, cm); },
|
108
108
|
|
109
|
-
request: function (cm, query, c) {
|
109
|
+
request: function (cm, query, c, pos) {
|
110
110
|
var self = this;
|
111
111
|
var doc = findDoc(this, cm.getDoc());
|
112
|
-
var request = buildRequest(this, doc, query);
|
112
|
+
var request = buildRequest(this, doc, query, pos);
|
113
113
|
|
114
114
|
this.server.request(request, function (error, data) {
|
115
115
|
if (!error && self.options.responseFilter)
|
@@ -221,7 +221,7 @@
|
|
221
221
|
|
222
222
|
// Type queries
|
223
223
|
|
224
|
-
function showType(ts, cm) {
|
224
|
+
function showType(ts, cm, pos) {
|
225
225
|
ts.request(cm, "type", function(error, data) {
|
226
226
|
if (error) return showError(ts, cm, error);
|
227
227
|
if (ts.options.typeTip) {
|
@@ -236,7 +236,7 @@
|
|
236
236
|
}
|
237
237
|
}
|
238
238
|
tempTooltip(cm, tip);
|
239
|
-
});
|
239
|
+
}, pos);
|
240
240
|
}
|
241
241
|
|
242
242
|
// Maintaining argument hints
|
@@ -450,13 +450,13 @@
|
|
450
450
|
|
451
451
|
// Generic request-building helper
|
452
452
|
|
453
|
-
function buildRequest(ts, doc, query) {
|
453
|
+
function buildRequest(ts, doc, query, pos) {
|
454
454
|
var files = [], offsetLines = 0, allowFragments = !query.fullDocs;
|
455
455
|
if (!allowFragments) delete query.fullDocs;
|
456
456
|
if (typeof query == "string") query = {type: query};
|
457
457
|
query.lineCharPositions = true;
|
458
458
|
if (query.end == null) {
|
459
|
-
query.end = doc.doc.getCursor("end");
|
459
|
+
query.end = pos || doc.doc.getCursor("end");
|
460
460
|
if (doc.doc.somethingSelected())
|
461
461
|
query.start = doc.doc.getCursor("start");
|
462
462
|
}
|
@@ -2726,10 +2726,9 @@
|
|
2726
2726
|
return regexp;
|
2727
2727
|
}
|
2728
2728
|
function showConfirm(cm, text) {
|
2729
|
-
if (cm.
|
2730
|
-
cm.
|
2731
|
-
|
2732
|
-
{bottom: true});
|
2729
|
+
if (cm.openNotification) {
|
2730
|
+
cm.openNotification('<span style="color: red">' + text + '</span>',
|
2731
|
+
{bottom: true, duration: 5000});
|
2733
2732
|
} else {
|
2734
2733
|
alert(text);
|
2735
2734
|
}
|
@@ -213,6 +213,8 @@ CodeMirror.defineMode("coffeescript", function(conf) {
|
|
213
213
|
if (type !== "coffee") {
|
214
214
|
align = null;
|
215
215
|
alignOffset = stream.column() + stream.current().length;
|
216
|
+
} else if (state.scope.align) {
|
217
|
+
state.scope.align = false;
|
216
218
|
}
|
217
219
|
state.scope = {
|
218
220
|
offset: offset,
|
@@ -268,7 +270,6 @@ CodeMirror.defineMode("coffeescript", function(conf) {
|
|
268
270
|
}
|
269
271
|
if (((current === "->" || current === "=>") &&
|
270
272
|
!state.lambda &&
|
271
|
-
state.scope.type == "coffee" &&
|
272
273
|
!stream.peek())
|
273
274
|
|| style === "indent") {
|
274
275
|
indent(stream, state);
|
@@ -292,9 +293,10 @@ CodeMirror.defineMode("coffeescript", function(conf) {
|
|
292
293
|
}
|
293
294
|
delimiter_index = "])}".indexOf(current);
|
294
295
|
if (delimiter_index !== -1) {
|
295
|
-
|
296
|
-
|
297
|
-
|
296
|
+
while (state.scope.type == "coffee" && state.scope.prev)
|
297
|
+
state.scope = state.scope.prev;
|
298
|
+
if (state.scope.type == current)
|
299
|
+
state.scope = state.scope.prev;
|
298
300
|
}
|
299
301
|
if (state.dedent > 0 && stream.eol() && state.scope.type == "coffee") {
|
300
302
|
if (state.scope.prev) state.scope = state.scope.prev;
|
@@ -333,11 +335,14 @@ CodeMirror.defineMode("coffeescript", function(conf) {
|
|
333
335
|
|
334
336
|
indent: function(state, text) {
|
335
337
|
if (state.tokenize != tokenBase) return 0;
|
336
|
-
var
|
337
|
-
|
338
|
-
|
338
|
+
var scope = state.scope;
|
339
|
+
var closer = text && "])}".indexOf(text.charAt(0)) > -1;
|
340
|
+
if (closer) while (scope.type == "coffee" && scope.prev) scope = scope.prev;
|
341
|
+
var closes = closer && scope.type === text.charAt(0);
|
342
|
+
if (scope.align)
|
343
|
+
return scope.alignOffset - (closes ? 1 : 0);
|
339
344
|
else
|
340
|
-
return (closes ?
|
345
|
+
return (closes ? scope.prev : scope).offset;
|
341
346
|
},
|
342
347
|
|
343
348
|
lineComment: "#",
|
@@ -262,7 +262,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|
262
262
|
// Pop off end of array until { is reached
|
263
263
|
while(state.stack.length){
|
264
264
|
var removed = state.stack.pop();
|
265
|
-
if(removed.indexOf("{") > -1){
|
265
|
+
if(removed.indexOf("{") > -1 || removed == "block" || removed == "rule"){
|
266
266
|
break;
|
267
267
|
}
|
268
268
|
}
|
@@ -609,8 +609,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|
609
609
|
}
|
610
610
|
return ["variable", "variable"];
|
611
611
|
},
|
612
|
-
",": function(
|
613
|
-
if (state.stack[state.stack.length - 1] == "propertyValue") {
|
612
|
+
",": function(stream, state) {
|
613
|
+
if (state.stack[state.stack.length - 1] == "propertyValue" && stream.match(/^ *\$/, false)) {
|
614
614
|
return ["operator", ";"];
|
615
615
|
}
|
616
616
|
},
|
@@ -237,7 +237,7 @@ CodeMirror.defineMode("haskell", function(_config, modeConfig) {
|
|
237
237
|
token: function(stream, state) {
|
238
238
|
var t = state.f(stream, function(s) { state.f = s; });
|
239
239
|
var w = stream.current();
|
240
|
-
return (w
|
240
|
+
return wellKnownWords.hasOwnProperty(w) ? wellKnownWords[w] : t;
|
241
241
|
},
|
242
242
|
|
243
243
|
blockCommentStart: "{-",
|
@@ -44,7 +44,7 @@ CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
|
|
44
44
|
if (close > -1) stream.backUp(cur.length - close);
|
45
45
|
else if (m = cur.match(/<\/?$/)) {
|
46
46
|
stream.backUp(cur.length);
|
47
|
-
if (!stream.match(pat, false)) stream.match(cur
|
47
|
+
if (!stream.match(pat, false)) stream.match(cur);
|
48
48
|
}
|
49
49
|
return style;
|
50
50
|
}
|
@@ -21,7 +21,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
21
21
|
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
|
22
22
|
"in": operator, "typeof": operator, "instanceof": operator,
|
23
23
|
"true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
|
24
|
-
"this": kw("this")
|
24
|
+
"this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"),
|
25
|
+
"yield": C, "export": kw("export"), "import": kw("import"), "extends": C
|
25
26
|
};
|
26
27
|
|
27
28
|
// Extend the 'normal' keywords with the TypeScript language extensions
|
@@ -30,7 +31,6 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
30
31
|
var tsKeywords = {
|
31
32
|
// object-like things
|
32
33
|
"interface": kw("interface"),
|
33
|
-
"class": kw("class"),
|
34
34
|
"extends": kw("extends"),
|
35
35
|
"constructor": kw("constructor"),
|
36
36
|
|
@@ -40,8 +40,6 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
40
40
|
"protected": kw("protected"),
|
41
41
|
"static": kw("static"),
|
42
42
|
|
43
|
-
"super": kw("super"),
|
44
|
-
|
45
43
|
// types
|
46
44
|
"string": type, "number": type, "bool": type, "any": type
|
47
45
|
};
|
@@ -56,11 +54,6 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
56
54
|
|
57
55
|
var isOperatorChar = /[+\-*&%=<>!?|~^]/;
|
58
56
|
|
59
|
-
function chain(stream, state, f) {
|
60
|
-
state.tokenize = f;
|
61
|
-
return f(stream, state);
|
62
|
-
}
|
63
|
-
|
64
57
|
function nextUntilUnescaped(stream, end) {
|
65
58
|
var escaped = false, next;
|
66
59
|
while ((next = stream.next()) != null) {
|
@@ -78,50 +71,51 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
78
71
|
type = tp; content = cont;
|
79
72
|
return style;
|
80
73
|
}
|
81
|
-
function
|
74
|
+
function tokenBase(stream, state) {
|
82
75
|
var ch = stream.next();
|
83
|
-
if (ch == '"' || ch == "'")
|
84
|
-
|
85
|
-
|
76
|
+
if (ch == '"' || ch == "'") {
|
77
|
+
state.tokenize = tokenString(ch);
|
78
|
+
return state.tokenize(stream, state);
|
79
|
+
} else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
|
86
80
|
return ret("number", "number");
|
87
|
-
else if (
|
81
|
+
} else if (ch == "." && stream.match("..")) {
|
82
|
+
return ret("spread", "meta");
|
83
|
+
} else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
|
88
84
|
return ret(ch);
|
89
|
-
else if (ch == "
|
85
|
+
} else if (ch == "=" && stream.eat(">")) {
|
86
|
+
return ret("=>");
|
87
|
+
} else if (ch == "0" && stream.eat(/x/i)) {
|
90
88
|
stream.eatWhile(/[\da-f]/i);
|
91
89
|
return ret("number", "number");
|
92
|
-
}
|
93
|
-
else if (/\d/.test(ch)) {
|
90
|
+
} else if (/\d/.test(ch)) {
|
94
91
|
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
|
95
92
|
return ret("number", "number");
|
96
|
-
}
|
97
|
-
else if (ch == "/") {
|
93
|
+
} else if (ch == "/") {
|
98
94
|
if (stream.eat("*")) {
|
99
|
-
|
100
|
-
|
101
|
-
else if (stream.eat("/")) {
|
95
|
+
state.tokenize = tokenComment;
|
96
|
+
return tokenComment(stream, state);
|
97
|
+
} else if (stream.eat("/")) {
|
102
98
|
stream.skipToEnd();
|
103
99
|
return ret("comment", "comment");
|
104
|
-
}
|
105
|
-
|
106
|
-
/^[\[{}\(,;:]$/.test(state.lastType)) {
|
100
|
+
} else if (state.lastType == "operator" || state.lastType == "keyword c" ||
|
101
|
+
state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
|
107
102
|
nextUntilUnescaped(stream, "/");
|
108
103
|
stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
|
109
104
|
return ret("regexp", "string-2");
|
110
|
-
}
|
111
|
-
else {
|
105
|
+
} else {
|
112
106
|
stream.eatWhile(isOperatorChar);
|
113
107
|
return ret("operator", null, stream.current());
|
114
108
|
}
|
115
|
-
}
|
116
|
-
|
109
|
+
} else if (ch == "`") {
|
110
|
+
state.tokenize = tokenQuasi;
|
111
|
+
return tokenQuasi(stream, state);
|
112
|
+
} else if (ch == "#") {
|
117
113
|
stream.skipToEnd();
|
118
114
|
return ret("error", "error");
|
119
|
-
}
|
120
|
-
else if (isOperatorChar.test(ch)) {
|
115
|
+
} else if (isOperatorChar.test(ch)) {
|
121
116
|
stream.eatWhile(isOperatorChar);
|
122
117
|
return ret("operator", null, stream.current());
|
123
|
-
}
|
124
|
-
else {
|
118
|
+
} else {
|
125
119
|
stream.eatWhile(/[\w\$_]/);
|
126
120
|
var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
|
127
121
|
return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
|
@@ -129,19 +123,19 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
129
123
|
}
|
130
124
|
}
|
131
125
|
|
132
|
-
function
|
126
|
+
function tokenString(quote) {
|
133
127
|
return function(stream, state) {
|
134
128
|
if (!nextUntilUnescaped(stream, quote))
|
135
|
-
state.tokenize =
|
129
|
+
state.tokenize = tokenBase;
|
136
130
|
return ret("string", "string");
|
137
131
|
};
|
138
132
|
}
|
139
133
|
|
140
|
-
function
|
134
|
+
function tokenComment(stream, state) {
|
141
135
|
var maybeEnd = false, ch;
|
142
136
|
while (ch = stream.next()) {
|
143
137
|
if (ch == "/" && maybeEnd) {
|
144
|
-
state.tokenize =
|
138
|
+
state.tokenize = tokenBase;
|
145
139
|
break;
|
146
140
|
}
|
147
141
|
maybeEnd = (ch == "*");
|
@@ -149,6 +143,50 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
149
143
|
return ret("comment", "comment");
|
150
144
|
}
|
151
145
|
|
146
|
+
function tokenQuasi(stream, state) {
|
147
|
+
var escaped = false, next;
|
148
|
+
while ((next = stream.next()) != null) {
|
149
|
+
if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
|
150
|
+
state.tokenize = tokenBase;
|
151
|
+
break;
|
152
|
+
}
|
153
|
+
escaped = !escaped && next == "\\";
|
154
|
+
}
|
155
|
+
return ret("quasi", "string-2", stream.current());
|
156
|
+
}
|
157
|
+
|
158
|
+
var brackets = "([{}])";
|
159
|
+
// This is a crude lookahead trick to try and notice that we're
|
160
|
+
// parsing the argument patterns for a fat-arrow function before we
|
161
|
+
// actually hit the arrow token. It only works if the arrow is on
|
162
|
+
// the same line as the arguments and there's no strange noise
|
163
|
+
// (comments) in between. Fallback is to only notice when we hit the
|
164
|
+
// arrow, and not declare the arguments as locals for the arrow
|
165
|
+
// body.
|
166
|
+
function findFatArrow(stream, state) {
|
167
|
+
if (state.fatArrowAt) state.fatArrowAt = null;
|
168
|
+
var arrow = stream.string.indexOf("=>", stream.start);
|
169
|
+
if (arrow < 0) return;
|
170
|
+
|
171
|
+
var depth = 0, sawSomething = false;
|
172
|
+
for (var pos = arrow - 1; pos >= 0; --pos) {
|
173
|
+
var ch = stream.string.charAt(pos);
|
174
|
+
var bracket = brackets.indexOf(ch);
|
175
|
+
if (bracket >= 0 && bracket < 3) {
|
176
|
+
if (!depth) { ++pos; break; }
|
177
|
+
if (--depth == 0) break;
|
178
|
+
} else if (bracket >= 3 && bracket < 6) {
|
179
|
+
++depth;
|
180
|
+
} else if (/[$\w]/.test(ch)) {
|
181
|
+
sawSomething = true;
|
182
|
+
} else if (sawSomething && !depth) {
|
183
|
+
++pos;
|
184
|
+
break;
|
185
|
+
}
|
186
|
+
}
|
187
|
+
if (sawSomething && !depth) state.fatArrowAt = pos;
|
188
|
+
}
|
189
|
+
|
152
190
|
// Parser
|
153
191
|
|
154
192
|
var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true};
|
@@ -165,6 +203,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
165
203
|
function inScope(state, varname) {
|
166
204
|
for (var v = state.localVars; v; v = v.next)
|
167
205
|
if (v.name == varname) return true;
|
206
|
+
for (var cx = state.context; cx; cx = cx.prev) {
|
207
|
+
for (var v = cx.vars; v; v = v.next)
|
208
|
+
if (v.name == varname) return true;
|
209
|
+
}
|
168
210
|
}
|
169
211
|
|
170
212
|
function parseJS(state, style, type, content, stream) {
|
@@ -211,7 +253,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
211
253
|
state.localVars = {name: varname, next: state.localVars};
|
212
254
|
} else {
|
213
255
|
if (inList(state.globalVars)) return;
|
214
|
-
|
256
|
+
if (parserConfig.globalVars)
|
257
|
+
state.globalVars = {name: varname, next: state.globalVars};
|
215
258
|
}
|
216
259
|
}
|
217
260
|
|
@@ -253,16 +296,15 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
253
296
|
};
|
254
297
|
}
|
255
298
|
|
256
|
-
function statement(type) {
|
257
|
-
if (type == "var") return cont(pushlex("vardef"),
|
299
|
+
function statement(type, value) {
|
300
|
+
if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
|
258
301
|
if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
|
259
302
|
if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
|
260
303
|
if (type == "{") return cont(pushlex("}"), block, poplex);
|
261
304
|
if (type == ";") return cont();
|
262
305
|
if (type == "if") return cont(pushlex("form"), expression, statement, poplex, maybeelse);
|
263
306
|
if (type == "function") return cont(functiondef);
|
264
|
-
if (type == "for") return cont(pushlex("form"),
|
265
|
-
poplex, statement, poplex);
|
307
|
+
if (type == "for") return cont(pushlex("form"), forspec, poplex, statement, poplex);
|
266
308
|
if (type == "variable") return cont(pushlex("stat"), maybelabel);
|
267
309
|
if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
|
268
310
|
block, poplex, poplex);
|
@@ -270,6 +312,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
270
312
|
if (type == "default") return cont(expect(":"));
|
271
313
|
if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
|
272
314
|
statement, poplex, popcontext);
|
315
|
+
if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex);
|
316
|
+
if (type == "class") return cont(pushlex("form"), className, objlit, poplex);
|
317
|
+
if (type == "export") return cont(pushlex("form"), afterExport, poplex);
|
318
|
+
if (type == "import") return cont(pushlex("form"), afterImport, poplex);
|
273
319
|
return pass(pushlex("stat"), expression, expect(";"), poplex);
|
274
320
|
}
|
275
321
|
function expression(type) {
|
@@ -279,14 +325,20 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
279
325
|
return expressionInner(type, true);
|
280
326
|
}
|
281
327
|
function expressionInner(type, noComma) {
|
328
|
+
if (cx.state.fatArrowAt == cx.stream.start) {
|
329
|
+
var body = noComma ? arrowBodyNoComma : arrowBody;
|
330
|
+
if (type == "(") return cont(pushcontext, commasep(pattern, ")"), expect("=>"), body, popcontext);
|
331
|
+
else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
|
332
|
+
}
|
333
|
+
|
282
334
|
var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
|
283
335
|
if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
|
284
336
|
if (type == "function") return cont(functiondef);
|
285
337
|
if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
|
286
|
-
if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
|
287
|
-
if (type == "operator") return cont(noComma ? expressionNoComma : expression);
|
288
|
-
if (type == "[") return cont(pushlex("]"),
|
289
|
-
if (type == "{") return cont(
|
338
|
+
if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
|
339
|
+
if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
|
340
|
+
if (type == "[") return cont(pushlex("]"), expressionNoComma, maybeArrayComprehension, poplex, maybeop);
|
341
|
+
if (type == "{") return cont(commasep(objprop, "}"), maybeop);
|
290
342
|
return cont();
|
291
343
|
}
|
292
344
|
function maybeexpression(type) {
|
@@ -305,16 +357,40 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
305
357
|
function maybeoperatorNoComma(type, value, noComma) {
|
306
358
|
var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
|
307
359
|
var expr = noComma == false ? expression : expressionNoComma;
|
360
|
+
if (value == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
|
308
361
|
if (type == "operator") {
|
309
362
|
if (/\+\+|--/.test(value)) return cont(me);
|
310
363
|
if (value == "?") return cont(expression, expect(":"), expr);
|
311
364
|
return cont(expr);
|
312
365
|
}
|
366
|
+
if (type == "quasi") { cx.cc.push(me); return quasi(value); }
|
313
367
|
if (type == ";") return;
|
314
|
-
if (type == "(") return cont(
|
368
|
+
if (type == "(") return cont(commasep(expressionNoComma, ")", "call"), me);
|
315
369
|
if (type == ".") return cont(property, me);
|
316
370
|
if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
|
317
371
|
}
|
372
|
+
function quasi(value) {
|
373
|
+
if (!value) debugger;
|
374
|
+
if (value.slice(value.length - 2) != "${") return cont();
|
375
|
+
return cont(expression, continueQuasi);
|
376
|
+
}
|
377
|
+
function continueQuasi(type) {
|
378
|
+
if (type == "}") {
|
379
|
+
cx.marked = "string-2";
|
380
|
+
cx.state.tokenize = tokenQuasi;
|
381
|
+
return cont();
|
382
|
+
}
|
383
|
+
}
|
384
|
+
function arrowBody(type) {
|
385
|
+
findFatArrow(cx.stream, cx.state);
|
386
|
+
if (type == "{") return pass(statement);
|
387
|
+
return pass(expression);
|
388
|
+
}
|
389
|
+
function arrowBodyNoComma(type) {
|
390
|
+
findFatArrow(cx.stream, cx.state);
|
391
|
+
if (type == "{") return pass(statement);
|
392
|
+
return pass(expressionNoComma);
|
393
|
+
}
|
318
394
|
function maybelabel(type) {
|
319
395
|
if (type == ":") return cont(poplex, statement);
|
320
396
|
return pass(maybeoperatorComma, expect(";"), poplex);
|
@@ -328,16 +404,21 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
328
404
|
if (value == "get" || value == "set") return cont(getterSetter);
|
329
405
|
} else if (type == "number" || type == "string") {
|
330
406
|
cx.marked = type + " property";
|
407
|
+
} else if (type == "[") {
|
408
|
+
return cont(expression, expect("]"), afterprop);
|
331
409
|
}
|
332
|
-
if (atomicTypes.hasOwnProperty(type)) return cont(
|
410
|
+
if (atomicTypes.hasOwnProperty(type)) return cont(afterprop);
|
333
411
|
}
|
334
412
|
function getterSetter(type) {
|
335
|
-
if (type
|
336
|
-
if (type != "variable") return cont(expect(":"), expression);
|
413
|
+
if (type != "variable") return pass(afterprop);
|
337
414
|
cx.marked = "property";
|
338
415
|
return cont(functiondef);
|
339
416
|
}
|
340
|
-
function
|
417
|
+
function afterprop(type) {
|
418
|
+
if (type == ":") return cont(expressionNoComma);
|
419
|
+
if (type == "(") return pass(functiondef);
|
420
|
+
}
|
421
|
+
function commasep(what, end, info) {
|
341
422
|
function proceed(type) {
|
342
423
|
if (type == ",") {
|
343
424
|
var lex = cx.state.lexical;
|
@@ -349,7 +430,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
349
430
|
}
|
350
431
|
return function(type) {
|
351
432
|
if (type == end) return cont();
|
352
|
-
|
433
|
+
if (info === false) return pass(what, proceed);
|
434
|
+
return pass(pushlex(end, info), what, proceed, poplex);
|
353
435
|
};
|
354
436
|
}
|
355
437
|
function block(type) {
|
@@ -357,67 +439,121 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
357
439
|
return pass(statement, block);
|
358
440
|
}
|
359
441
|
function maybetype(type) {
|
360
|
-
if (type == ":") return cont(typedef);
|
361
|
-
return pass();
|
442
|
+
if (isTS && type == ":") return cont(typedef);
|
362
443
|
}
|
363
444
|
function typedef(type) {
|
364
445
|
if (type == "variable"){cx.marked = "variable-3"; return cont();}
|
365
|
-
return pass();
|
366
446
|
}
|
367
|
-
function
|
368
|
-
|
447
|
+
function vardef() {
|
448
|
+
return pass(pattern, maybetype, maybeAssign, vardefCont);
|
449
|
+
}
|
450
|
+
function pattern(type, value) {
|
451
|
+
if (type == "variable") { register(value); return cont(); }
|
452
|
+
if (type == "[") return cont(commasep(pattern, "]"));
|
453
|
+
if (type == "{") return cont(commasep(proppattern, "}"));
|
454
|
+
}
|
455
|
+
function proppattern(type, value) {
|
456
|
+
if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
|
369
457
|
register(value);
|
370
|
-
return
|
458
|
+
return cont(maybeAssign);
|
371
459
|
}
|
372
|
-
|
460
|
+
if (type == "variable") cx.marked = "property";
|
461
|
+
return cont(expect(":"), pattern, maybeAssign);
|
462
|
+
}
|
463
|
+
function maybeAssign(_type, value) {
|
464
|
+
if (value == "=") return cont(expressionNoComma);
|
373
465
|
}
|
374
|
-
function
|
375
|
-
if (
|
376
|
-
if (type == ",") return cont(vardef1);
|
466
|
+
function vardefCont(type) {
|
467
|
+
if (type == ",") return cont(vardef);
|
377
468
|
}
|
378
469
|
function maybeelse(type, value) {
|
379
470
|
if (type == "keyword b" && value == "else") return cont(pushlex("form"), statement, poplex);
|
380
471
|
}
|
472
|
+
function forspec(type) {
|
473
|
+
if (type == "(") return cont(pushlex(")"), forspec1, expect(")"));
|
474
|
+
}
|
381
475
|
function forspec1(type) {
|
382
|
-
if (type == "var") return cont(
|
476
|
+
if (type == "var") return cont(vardef, expect(";"), forspec2);
|
383
477
|
if (type == ";") return cont(forspec2);
|
384
|
-
if (type == "variable") return cont(
|
478
|
+
if (type == "variable") return cont(formaybeinof);
|
385
479
|
return pass(expression, expect(";"), forspec2);
|
386
480
|
}
|
387
|
-
function
|
388
|
-
if (value == "in") return cont(expression);
|
481
|
+
function formaybeinof(_type, value) {
|
482
|
+
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
|
389
483
|
return cont(maybeoperatorComma, forspec2);
|
390
484
|
}
|
391
485
|
function forspec2(type, value) {
|
392
486
|
if (type == ";") return cont(forspec3);
|
393
|
-
if (value == "in") return cont(expression);
|
487
|
+
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
|
394
488
|
return pass(expression, expect(";"), forspec3);
|
395
489
|
}
|
396
490
|
function forspec3(type) {
|
397
491
|
if (type != ")") cont(expression);
|
398
492
|
}
|
399
493
|
function functiondef(type, value) {
|
494
|
+
if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
|
400
495
|
if (type == "variable") {register(value); return cont(functiondef);}
|
401
|
-
if (type == "(") return cont(
|
496
|
+
if (type == "(") return cont(pushcontext, commasep(funarg, ")"), statement, popcontext);
|
497
|
+
}
|
498
|
+
function funarg(type) {
|
499
|
+
if (type == "spread") return cont(funarg);
|
500
|
+
return pass(pattern, maybetype);
|
501
|
+
}
|
502
|
+
function className(type, value) {
|
503
|
+
if (type == "variable") {register(value); return cont(classNameAfter);}
|
504
|
+
}
|
505
|
+
function classNameAfter(_type, value) {
|
506
|
+
if (value == "extends") return cont(expression);
|
507
|
+
}
|
508
|
+
function objlit(type) {
|
509
|
+
if (type == "{") return cont(commasep(objprop, "}"));
|
510
|
+
}
|
511
|
+
function afterModule(type, value) {
|
512
|
+
if (type == "string") return cont(statement);
|
513
|
+
if (type == "variable") { register(value); return cont(maybeFrom); }
|
514
|
+
}
|
515
|
+
function afterExport(_type, value) {
|
516
|
+
if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
|
517
|
+
if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
|
518
|
+
return pass(statement);
|
519
|
+
}
|
520
|
+
function afterImport(type) {
|
521
|
+
if (type == "string") return cont();
|
522
|
+
return pass(importSpec, maybeFrom);
|
523
|
+
}
|
524
|
+
function importSpec(type, value) {
|
525
|
+
if (type == "{") return cont(commasep(importSpec, "}"));
|
526
|
+
if (type == "variable") register(value);
|
527
|
+
return cont();
|
528
|
+
}
|
529
|
+
function maybeFrom(_type, value) {
|
530
|
+
if (value == "from") { cx.marked = "keyword"; return cont(expression); }
|
531
|
+
}
|
532
|
+
function maybeArrayComprehension(type) {
|
533
|
+
if (type == "for") return pass(comprehension);
|
534
|
+
if (type == ",") return cont(commasep(expressionNoComma, "]", false));
|
535
|
+
return pass(commasep(expressionNoComma, "]", false));
|
402
536
|
}
|
403
|
-
function
|
404
|
-
if (type == "
|
537
|
+
function comprehension(type) {
|
538
|
+
if (type == "for") return cont(forspec, comprehension);
|
539
|
+
if (type == "if") return cont(expression, comprehension);
|
405
540
|
}
|
406
541
|
|
407
542
|
// Interface
|
408
543
|
|
409
544
|
return {
|
410
545
|
startState: function(basecolumn) {
|
411
|
-
|
412
|
-
tokenize:
|
413
|
-
lastType:
|
546
|
+
var state = {
|
547
|
+
tokenize: tokenBase,
|
548
|
+
lastType: "sof",
|
414
549
|
cc: [],
|
415
550
|
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
|
416
551
|
localVars: parserConfig.localVars,
|
417
|
-
globalVars: parserConfig.globalVars,
|
418
552
|
context: parserConfig.localVars && {vars: parserConfig.localVars},
|
419
553
|
indented: 0
|
420
554
|
};
|
555
|
+
if (parserConfig.globalVars) state.globalVars = parserConfig.globalVars;
|
556
|
+
return state;
|
421
557
|
},
|
422
558
|
|
423
559
|
token: function(stream, state) {
|
@@ -425,8 +561,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
425
561
|
if (!state.lexical.hasOwnProperty("align"))
|
426
562
|
state.lexical.align = false;
|
427
563
|
state.indented = stream.indentation();
|
564
|
+
findFatArrow(stream, state);
|
428
565
|
}
|
429
|
-
if (state.tokenize !=
|
566
|
+
if (state.tokenize != tokenComment && stream.eatSpace()) return null;
|
430
567
|
var style = state.tokenize(stream, state);
|
431
568
|
if (type == "comment") return style;
|
432
569
|
state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
|
@@ -434,21 +571,21 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|
434
571
|
},
|
435
572
|
|
436
573
|
indent: function(state, textAfter) {
|
437
|
-
if (state.tokenize ==
|
438
|
-
if (state.tokenize !=
|
574
|
+
if (state.tokenize == tokenComment) return CodeMirror.Pass;
|
575
|
+
if (state.tokenize != tokenBase) return 0;
|
439
576
|
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
|
440
577
|
// Kludge to prevent 'maybelse' from blocking lexical scope pops
|
441
578
|
for (var i = state.cc.length - 1; i >= 0; --i) {
|
442
579
|
var c = state.cc[i];
|
443
580
|
if (c == poplex) lexical = lexical.prev;
|
444
|
-
else if (c != maybeelse
|
581
|
+
else if (c != maybeelse) break;
|
445
582
|
}
|
446
583
|
if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
|
447
584
|
if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
|
448
585
|
lexical = lexical.prev;
|
449
586
|
var type = lexical.type, closing = firstChar == type;
|
450
587
|
|
451
|
-
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ?
|
588
|
+
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0);
|
452
589
|
else if (type == "form" && firstChar == "{") return lexical.indented;
|
453
590
|
else if (type == "form") return lexical.indented + indentUnit;
|
454
591
|
else if (type == "stat")
|