codemirror-rails 3.19 → 3.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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")
|