codemirror-rails 5.1 → 5.2

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +92 -39
  4. data/vendor/assets/javascripts/codemirror/addons/display/panel.js +22 -4
  5. data/vendor/assets/javascripts/codemirror/addons/edit/continuelist.js +5 -5
  6. data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +63 -65
  7. data/vendor/assets/javascripts/codemirror/addons/lint/javascript-lint.js +1 -1
  8. data/vendor/assets/javascripts/codemirror/addons/mode/multiplex.js +14 -9
  9. data/vendor/assets/javascripts/codemirror/addons/scroll/annotatescrollbar.js +19 -4
  10. data/vendor/assets/javascripts/codemirror/addons/search/matchesonscrollbar.js +3 -1
  11. data/vendor/assets/javascripts/codemirror/addons/search/search.js +7 -4
  12. data/vendor/assets/javascripts/codemirror/addons/search/searchcursor.js +2 -2
  13. data/vendor/assets/javascripts/codemirror/keymaps/sublime.js +1 -1
  14. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +117 -23
  15. data/vendor/assets/javascripts/codemirror/modes/clike.js +1 -1
  16. data/vendor/assets/javascripts/codemirror/modes/css.js +3 -1
  17. data/vendor/assets/javascripts/codemirror/modes/django.js +307 -24
  18. data/vendor/assets/javascripts/codemirror/modes/handlebars.js +53 -0
  19. data/vendor/assets/javascripts/codemirror/modes/javascript.js +5 -1
  20. data/vendor/assets/javascripts/codemirror/modes/less_test.js +3 -0
  21. data/vendor/assets/javascripts/codemirror/modes/markdown.js +15 -13
  22. data/vendor/assets/javascripts/codemirror/modes/mumps.js +148 -0
  23. data/vendor/assets/javascripts/codemirror/modes/python.js +2 -4
  24. data/vendor/assets/javascripts/codemirror/modes/scss_test.js +1 -1
  25. data/vendor/assets/javascripts/codemirror/modes/smarty.js +17 -6
  26. data/vendor/assets/javascripts/codemirror/modes/soy.js +3 -3
  27. data/vendor/assets/javascripts/codemirror/modes/sql.js +4 -4
  28. data/vendor/assets/javascripts/codemirror/modes/stylus.js +8 -3
  29. data/vendor/assets/javascripts/codemirror/modes/z80.js +34 -18
  30. data/vendor/assets/stylesheets/codemirror.css +2 -0
  31. data/vendor/assets/stylesheets/codemirror/themes/liquibyte.css +95 -0
  32. data/vendor/assets/stylesheets/codemirror/themes/monokai.css +1 -1
  33. data/vendor/assets/stylesheets/codemirror/themes/solarized.css +1 -1
  34. metadata +4 -1
@@ -185,7 +185,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
185
185
  return obj;
186
186
  }
187
187
  var cKeywords = "auto if break int case long char register continue return default short do sizeof " +
188
- "double static else struct entry switch extern typedef float union for unsigned " +
188
+ "double static else struct switch extern typedef float union for unsigned " +
189
189
  "goto while enum void const signed volatile";
190
190
 
191
191
  function cppHook(stream, state) {
@@ -328,7 +328,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
328
328
  states.interpolation = function(type, stream, state) {
329
329
  if (type == "}") return popContext(state);
330
330
  if (type == "{" || type == ";") return popAndPass(type, stream, state);
331
- if (type != "variable") override = "error";
331
+ if (type == "word") override = "variable";
332
+ else if (type != "variable") override = "error";
332
333
  return "interpolation";
333
334
  };
334
335
 
@@ -750,6 +751,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
750
751
  }
751
752
  },
752
753
  "@": function(stream) {
754
+ if (stream.eat("{")) return [null, "interpolation"];
753
755
  if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false;
754
756
  stream.eatWhile(/[\w\\\-]/);
755
757
  if (stream.match(/^\s*:/, false))
@@ -14,46 +14,329 @@
14
14
  "use strict";
15
15
 
16
16
  CodeMirror.defineMode("django:inner", function() {
17
- var keywords = ["block", "endblock", "for", "endfor", "in", "true", "false",
18
- "loop", "none", "self", "super", "if", "endif", "as", "not", "and",
17
+ var keywords = ["block", "endblock", "for", "endfor", "true", "false",
18
+ "loop", "none", "self", "super", "if", "endif", "as",
19
19
  "else", "import", "with", "endwith", "without", "context", "ifequal", "endifequal",
20
- "ifnotequal", "endifnotequal", "extends", "include", "load", "length", "comment",
21
- "endcomment", "empty"];
22
- keywords = new RegExp("^((" + keywords.join(")|(") + "))\\b");
20
+ "ifnotequal", "endifnotequal", "extends", "include", "load", "comment",
21
+ "endcomment", "empty", "url", "static", "trans", "blocktrans", "now", "regroup",
22
+ "lorem", "ifchanged", "endifchanged", "firstof", "debug", "cycle", "csrf_token",
23
+ "autoescape", "endautoescape", "spaceless", "ssi", "templatetag",
24
+ "verbatim", "endverbatim", "widthratio"],
25
+ filters = ["add", "addslashes", "capfirst", "center", "cut", "date",
26
+ "default", "default_if_none", "dictsort",
27
+ "dictsortreversed", "divisibleby", "escape", "escapejs",
28
+ "filesizeformat", "first", "floatformat", "force_escape",
29
+ "get_digit", "iriencode", "join", "last", "length",
30
+ "length_is", "linebreaks", "linebreaksbr", "linenumbers",
31
+ "ljust", "lower", "make_list", "phone2numeric", "pluralize",
32
+ "pprint", "random", "removetags", "rjust", "safe",
33
+ "safeseq", "slice", "slugify", "stringformat", "striptags",
34
+ "time", "timesince", "timeuntil", "title", "truncatechars",
35
+ "truncatechars_html", "truncatewords", "truncatewords_html",
36
+ "unordered_list", "upper", "urlencode", "urlize",
37
+ "urlizetrunc", "wordcount", "wordwrap", "yesno"],
38
+ operators = ["==", "!=", "<", ">", "<=", ">=", "in", "not", "or", "and"];
23
39
 
40
+ keywords = new RegExp("^\\b(" + keywords.join("|") + ")\\b");
41
+ filters = new RegExp("^\\b(" + filters.join("|") + ")\\b");
42
+ operators = new RegExp("^\\b(" + operators.join("|") + ")\\b");
43
+
44
+ // We have to return "null" instead of null, in order to avoid string
45
+ // styling as the default, when using Django templates inside HTML
46
+ // element attributes
24
47
  function tokenBase (stream, state) {
25
- stream.eatWhile(/[^\{]/);
26
- var ch = stream.next();
27
- if (ch == "{") {
28
- if (ch = stream.eat(/\{|%|#/)) {
29
- state.tokenize = inTag(ch);
30
- return "tag";
48
+ // Attempt to identify a variable, template or comment tag respectively
49
+ if (stream.match("{{")) {
50
+ state.tokenize = inVariable;
51
+ return "tag";
52
+ } else if (stream.match("{%")) {
53
+ state.tokenize = inTag;
54
+ return "tag";
55
+ } else if (stream.match("{#")) {
56
+ state.tokenize = inComment;
57
+ return "comment";
58
+ }
59
+
60
+ // Ignore completely any stream series that do not match the
61
+ // Django template opening tags.
62
+ while (stream.next() != null && !stream.match("{{", false) && !stream.match("{%", false)) {}
63
+ return null;
64
+ }
65
+
66
+ // A string can be included in either single or double quotes (this is
67
+ // the delimeter). Mark everything as a string until the start delimeter
68
+ // occurs again.
69
+ function inString (delimeter, previousTokenizer) {
70
+ return function (stream, state) {
71
+ if (!state.escapeNext && stream.eat(delimeter)) {
72
+ state.tokenize = previousTokenizer;
73
+ } else {
74
+ if (state.escapeNext) {
75
+ state.escapeNext = false;
76
+ }
77
+
78
+ var ch = stream.next();
79
+
80
+ // Take into account the backslash for escaping characters, such as
81
+ // the string delimeter.
82
+ if (ch == "\\") {
83
+ state.escapeNext = true;
84
+ }
85
+ }
86
+
87
+ return "string";
88
+ };
89
+ }
90
+
91
+ // Apply Django template variable syntax highlighting
92
+ function inVariable (stream, state) {
93
+ // Attempt to match a dot that precedes a property
94
+ if (state.waitDot) {
95
+ state.waitDot = false;
96
+
97
+ if (stream.peek() != ".") {
98
+ return "null";
99
+ }
100
+
101
+ // Dot folowed by a non-word character should be considered an error.
102
+ if (stream.match(/\.\W+/)) {
103
+ return "error";
104
+ } else if (stream.eat(".")) {
105
+ state.waitProperty = true;
106
+ return "null";
107
+ } else {
108
+ throw Error ("Unexpected error while waiting for property.");
109
+ }
110
+ }
111
+
112
+ // Attempt to match a pipe that precedes a filter
113
+ if (state.waitPipe) {
114
+ state.waitPipe = false;
115
+
116
+ if (stream.peek() != "|") {
117
+ return "null";
118
+ }
119
+
120
+ // Pipe folowed by a non-word character should be considered an error.
121
+ if (stream.match(/\.\W+/)) {
122
+ return "error";
123
+ } else if (stream.eat("|")) {
124
+ state.waitFilter = true;
125
+ return "null";
126
+ } else {
127
+ throw Error ("Unexpected error while waiting for filter.");
128
+ }
129
+ }
130
+
131
+ // Highlight properties
132
+ if (state.waitProperty) {
133
+ state.waitProperty = false;
134
+ if (stream.match(/\b(\w+)\b/)) {
135
+ state.waitDot = true; // A property can be followed by another property
136
+ state.waitPipe = true; // A property can be followed by a filter
137
+ return "property";
31
138
  }
32
139
  }
140
+
141
+ // Highlight filters
142
+ if (state.waitFilter) {
143
+ state.waitFilter = false;
144
+ if (stream.match(filters)) {
145
+ return "variable-2";
146
+ }
147
+ }
148
+
149
+ // Ignore all white spaces
150
+ if (stream.eatSpace()) {
151
+ state.waitProperty = false;
152
+ return "null";
153
+ }
154
+
155
+ // Identify numbers
156
+ if (stream.match(/\b\d+(\.\d+)?\b/)) {
157
+ return "number";
158
+ }
159
+
160
+ // Identify strings
161
+ if (stream.match("'")) {
162
+ state.tokenize = inString("'", state.tokenize);
163
+ return "string";
164
+ } else if (stream.match('"')) {
165
+ state.tokenize = inString('"', state.tokenize);
166
+ return "string";
167
+ }
168
+
169
+ // Attempt to find the variable
170
+ if (stream.match(/\b(\w+)\b/) && !state.foundVariable) {
171
+ state.waitDot = true;
172
+ state.waitPipe = true; // A property can be followed by a filter
173
+ return "variable";
174
+ }
175
+
176
+ // If found closing tag reset
177
+ if (stream.match("}}")) {
178
+ state.waitProperty = null;
179
+ state.waitFilter = null;
180
+ state.waitDot = null;
181
+ state.waitPipe = null;
182
+ state.tokenize = tokenBase;
183
+ return "tag";
184
+ }
185
+
186
+ // If nothing was found, advance to the next character
187
+ stream.next();
188
+ return "null";
33
189
  }
34
- function inTag (close) {
35
- if (close == "{") {
36
- close = "}";
190
+
191
+ function inTag (stream, state) {
192
+ // Attempt to match a dot that precedes a property
193
+ if (state.waitDot) {
194
+ state.waitDot = false;
195
+
196
+ if (stream.peek() != ".") {
197
+ return "null";
198
+ }
199
+
200
+ // Dot folowed by a non-word character should be considered an error.
201
+ if (stream.match(/\.\W+/)) {
202
+ return "error";
203
+ } else if (stream.eat(".")) {
204
+ state.waitProperty = true;
205
+ return "null";
206
+ } else {
207
+ throw Error ("Unexpected error while waiting for property.");
208
+ }
37
209
  }
38
- return function (stream, state) {
39
- var ch = stream.next();
40
- if ((ch == close) && stream.eat("}")) {
41
- state.tokenize = tokenBase;
42
- return "tag";
210
+
211
+ // Attempt to match a pipe that precedes a filter
212
+ if (state.waitPipe) {
213
+ state.waitPipe = false;
214
+
215
+ if (stream.peek() != "|") {
216
+ return "null";
43
217
  }
44
- if (stream.match(keywords)) {
45
- return "keyword";
218
+
219
+ // Pipe folowed by a non-word character should be considered an error.
220
+ if (stream.match(/\.\W+/)) {
221
+ return "error";
222
+ } else if (stream.eat("|")) {
223
+ state.waitFilter = true;
224
+ return "null";
225
+ } else {
226
+ throw Error ("Unexpected error while waiting for filter.");
46
227
  }
47
- return close == "#" ? "comment" : "string";
48
- };
228
+ }
229
+
230
+ // Highlight properties
231
+ if (state.waitProperty) {
232
+ state.waitProperty = false;
233
+ if (stream.match(/\b(\w+)\b/)) {
234
+ state.waitDot = true; // A property can be followed by another property
235
+ state.waitPipe = true; // A property can be followed by a filter
236
+ return "property";
237
+ }
238
+ }
239
+
240
+ // Highlight filters
241
+ if (state.waitFilter) {
242
+ state.waitFilter = false;
243
+ if (stream.match(filters)) {
244
+ return "variable-2";
245
+ }
246
+ }
247
+
248
+ // Ignore all white spaces
249
+ if (stream.eatSpace()) {
250
+ state.waitProperty = false;
251
+ return "null";
252
+ }
253
+
254
+ // Identify numbers
255
+ if (stream.match(/\b\d+(\.\d+)?\b/)) {
256
+ return "number";
257
+ }
258
+
259
+ // Identify strings
260
+ if (stream.match("'")) {
261
+ state.tokenize = inString("'", state.tokenize);
262
+ return "string";
263
+ } else if (stream.match('"')) {
264
+ state.tokenize = inString('"', state.tokenize);
265
+ return "string";
266
+ }
267
+
268
+ // Attempt to match an operator
269
+ if (stream.match(operators)) {
270
+ return "operator";
271
+ }
272
+
273
+ // Attempt to match a keyword
274
+ var keywordMatch = stream.match(keywords);
275
+ if (keywordMatch) {
276
+ if (keywordMatch[0] == "comment") {
277
+ state.blockCommentTag = true;
278
+ }
279
+ return "keyword";
280
+ }
281
+
282
+ // Attempt to match a variable
283
+ if (stream.match(/\b(\w+)\b/)) {
284
+ state.waitDot = true;
285
+ state.waitPipe = true; // A property can be followed by a filter
286
+ return "variable";
287
+ }
288
+
289
+ // If found closing tag reset
290
+ if (stream.match("%}")) {
291
+ state.waitProperty = null;
292
+ state.waitFilter = null;
293
+ state.waitDot = null;
294
+ state.waitPipe = null;
295
+ // If the tag that closes is a block comment tag, we want to mark the
296
+ // following code as comment, until the tag closes.
297
+ if (state.blockCommentTag) {
298
+ state.blockCommentTag = false; // Release the "lock"
299
+ state.tokenize = inBlockComment;
300
+ } else {
301
+ state.tokenize = tokenBase;
302
+ }
303
+ return "tag";
304
+ }
305
+
306
+ // If nothing was found, advance to the next character
307
+ stream.next();
308
+ return "null";
309
+ }
310
+
311
+ // Mark everything as comment inside the tag and the tag itself.
312
+ function inComment (stream, state) {
313
+ if (stream.match("#}")) {
314
+ state.tokenize = tokenBase;
315
+ }
316
+ return "comment";
317
+ }
318
+
319
+ // Mark everything as a comment until the `blockcomment` tag closes.
320
+ function inBlockComment (stream, state) {
321
+ if (stream.match(/\{%\s*endcomment\s*%\}/, false)) {
322
+ state.tokenize = inTag;
323
+ stream.match("{%");
324
+ return "tag";
325
+ } else {
326
+ stream.next();
327
+ return "comment";
328
+ }
49
329
  }
330
+
50
331
  return {
51
332
  startState: function () {
52
333
  return {tokenize: tokenBase};
53
334
  },
54
335
  token: function (stream, state) {
55
336
  return state.tokenize(stream, state);
56
- }
337
+ },
338
+ blockCommentStart: "{% comment %}",
339
+ blockCommentEnd: "{% endcomment %}"
57
340
  };
58
341
  });
59
342
 
@@ -0,0 +1,53 @@
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"), require("../../addon/mode/simple"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror", "../../addon/mode/simple"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ CodeMirror.defineSimpleMode("handlebars", {
15
+ start: [
16
+ { regex: /\{\{!--/, push: "dash_comment", token: "comment" },
17
+ { regex: /\{\{!/, push: "comment", token: "comment" },
18
+ { regex: /\{\{/, push: "handlebars", token: "tag" }
19
+ ],
20
+ handlebars: [
21
+ { regex: /\}\}/, pop: true, token: "tag" },
22
+
23
+ // Double and single quotes
24
+ { regex: /"(?:[^\\]|\\.)*?"/, token: "string" },
25
+ { regex: /'(?:[^\\]|\\.)*?'/, token: "string" },
26
+
27
+ // Handlebars keywords
28
+ { regex: />|[#\/]([A-Za-z_]\w*)/, token: "keyword" },
29
+ { regex: /(?:else|this)\b/, token: "keyword" },
30
+
31
+ // Numeral
32
+ { regex: /\d+/i, token: "number" },
33
+
34
+ // Atoms like = and .
35
+ { regex: /=|~|@|true|false/, token: "atom" },
36
+
37
+ // Paths
38
+ { regex: /(?:\.\.\/)*(?:[A-Za-z_][\w\.]*)+/, token: "variable-2" }
39
+ ],
40
+ dash_comment: [
41
+ { regex: /--\}\}/, pop: true, token: "comment" },
42
+
43
+ // Commented code
44
+ { regex: /./, token: "comment"}
45
+ ],
46
+ comment: [
47
+ { regex: /\}\}/, pop: true, token: "comment" },
48
+ { regex: /./, token: "comment" }
49
+ ]
50
+ });
51
+
52
+ CodeMirror.defineMIME("text/x-handlebars-template", "handlebars");
53
+ });
@@ -585,7 +585,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
585
585
  function importSpec(type, value) {
586
586
  if (type == "{") return contCommasep(importSpec, "}");
587
587
  if (type == "variable") register(value);
588
- return cont();
588
+ if (value == "*") cx.marked = "keyword";
589
+ return cont(maybeAs);
590
+ }
591
+ function maybeAs(_type, value) {
592
+ if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
589
593
  }
590
594
  function maybeFrom(_type, value) {
591
595
  if (value == "from") { cx.marked = "keyword"; return cont(expression); }