codemirror-rails 3.20 → 3.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +240 -135
  4. data/vendor/assets/javascripts/codemirror/addons/comment/comment.js +6 -2
  5. data/vendor/assets/javascripts/codemirror/addons/comment/continuecomment.js +1 -1
  6. data/vendor/assets/javascripts/codemirror/addons/dialog/dialog.js +1 -0
  7. data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +5 -3
  8. data/vendor/assets/javascripts/codemirror/addons/edit/closetag.js +10 -6
  9. data/vendor/assets/javascripts/codemirror/addons/edit/continuelist.js +2 -0
  10. data/vendor/assets/javascripts/codemirror/addons/edit/matchbrackets.js +1 -1
  11. data/vendor/assets/javascripts/codemirror/addons/fold/comment-fold.js +3 -1
  12. data/vendor/assets/javascripts/codemirror/addons/fold/foldcode.js +13 -2
  13. data/vendor/assets/javascripts/codemirror/addons/fold/foldgutter.js +1 -1
  14. data/vendor/assets/javascripts/codemirror/addons/fold/indent-fold.js +2 -2
  15. data/vendor/assets/javascripts/codemirror/addons/fold/xml-fold.js +6 -0
  16. data/vendor/assets/javascripts/codemirror/addons/hint/anyword-hint.js +3 -5
  17. data/vendor/assets/javascripts/codemirror/addons/hint/css-hint.js +29 -33
  18. data/vendor/assets/javascripts/codemirror/addons/hint/javascript-hint.js +1 -1
  19. data/vendor/assets/javascripts/codemirror/addons/hint/pig-hint.js +1 -1
  20. data/vendor/assets/javascripts/codemirror/addons/hint/python-hint.js +1 -5
  21. data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +58 -9
  22. data/vendor/assets/javascripts/codemirror/addons/hint/sql-hint.js +58 -17
  23. data/vendor/assets/javascripts/codemirror/addons/hint/xml-hint.js +5 -5
  24. data/vendor/assets/javascripts/codemirror/addons/lint/lint.js +1 -1
  25. data/vendor/assets/javascripts/codemirror/addons/merge/merge.js +6 -1
  26. data/vendor/assets/javascripts/codemirror/addons/mode/multiplex.js +5 -3
  27. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode-standalone.js +26 -11
  28. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.js +1 -1
  29. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.node.js +22 -11
  30. data/vendor/assets/javascripts/codemirror/addons/search/search.js +22 -9
  31. data/vendor/assets/javascripts/codemirror/addons/search/searchcursor.js +48 -24
  32. data/vendor/assets/javascripts/codemirror/addons/selection/active-line.js +15 -9
  33. data/vendor/assets/javascripts/codemirror/addons/tern/tern.js +3 -3
  34. data/vendor/assets/javascripts/codemirror/addons/wrap/hardwrap.js +21 -9
  35. data/vendor/assets/javascripts/codemirror/keymaps/emacs.js +12 -1
  36. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +110 -28
  37. data/vendor/assets/javascripts/codemirror/modes/clike.js +28 -9
  38. data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +3 -4
  39. data/vendor/assets/javascripts/codemirror/modes/css.js +341 -297
  40. data/vendor/assets/javascripts/codemirror/modes/erlang.js +302 -179
  41. data/vendor/assets/javascripts/codemirror/modes/gfm.js +10 -5
  42. data/vendor/assets/javascripts/codemirror/modes/gherkin.js +45 -50
  43. data/vendor/assets/javascripts/codemirror/modes/haml.js +0 -4
  44. data/vendor/assets/javascripts/codemirror/modes/haskell.js +5 -3
  45. data/vendor/assets/javascripts/codemirror/modes/htmlembedded.js +0 -2
  46. data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +0 -2
  47. data/vendor/assets/javascripts/codemirror/modes/javascript.js +43 -30
  48. data/vendor/assets/javascripts/codemirror/modes/jinja2.js +13 -3
  49. data/vendor/assets/javascripts/codemirror/modes/less.js +7 -6
  50. data/vendor/assets/javascripts/codemirror/modes/markdown.js +231 -45
  51. data/vendor/assets/javascripts/codemirror/modes/{ocaml.js → mllike.js} +88 -13
  52. data/vendor/assets/javascripts/codemirror/modes/pegjs.js +5 -9
  53. data/vendor/assets/javascripts/codemirror/modes/php.js +6 -7
  54. data/vendor/assets/javascripts/codemirror/modes/python.js +6 -0
  55. data/vendor/assets/javascripts/codemirror/modes/r.js +5 -1
  56. data/vendor/assets/javascripts/codemirror/modes/rpm-spec.js +1 -1
  57. data/vendor/assets/javascripts/codemirror/modes/ruby.js +3 -1
  58. data/vendor/assets/javascripts/codemirror/modes/smalltalk.js +4 -2
  59. data/vendor/assets/javascripts/codemirror/modes/smartymixed.js +0 -2
  60. data/vendor/assets/javascripts/codemirror/modes/sql.js +5 -4
  61. data/vendor/assets/javascripts/codemirror/modes/xml.js +87 -100
  62. data/vendor/assets/stylesheets/codemirror/themes/mbo.css +1 -1
  63. data/vendor/assets/stylesheets/codemirror/themes/midnight.css +1 -1
  64. data/vendor/assets/stylesheets/codemirror/themes/pastel-on-dark.css +49 -0
  65. data/vendor/assets/stylesheets/codemirror/themes/the-matrix.css +1 -1
  66. metadata +3 -2
@@ -203,18 +203,34 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
203
203
  return "string";
204
204
  }
205
205
 
206
- function mimes(ms, mode) {
207
- for (var i = 0; i < ms.length; ++i) CodeMirror.defineMIME(ms[i], mode);
206
+ function def(mimes, mode) {
207
+ var words = [];
208
+ function add(obj) {
209
+ if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop))
210
+ words.push(prop);
211
+ }
212
+ add(mode.keywords);
213
+ add(mode.builtin);
214
+ add(mode.atoms);
215
+ if (words.length) {
216
+ mode.helperType = mimes[0];
217
+ CodeMirror.registerHelper("hintWords", mimes[0], words);
218
+ }
219
+
220
+ for (var i = 0; i < mimes.length; ++i)
221
+ CodeMirror.defineMIME(mimes[i], mode);
208
222
  }
209
223
 
210
- mimes(["text/x-csrc", "text/x-c", "text/x-chdr"], {
224
+ def(["text/x-csrc", "text/x-c", "text/x-chdr"], {
211
225
  name: "clike",
212
226
  keywords: words(cKeywords),
213
227
  blockKeywords: words("case do else for if switch while struct"),
214
228
  atoms: words("null"),
215
- hooks: {"#": cppHook}
229
+ hooks: {"#": cppHook},
230
+ modeProps: {fold: ["brace", "include"]}
216
231
  });
217
- mimes(["text/x-c++src", "text/x-c++hdr"], {
232
+
233
+ def(["text/x-c++src", "text/x-c++hdr"], {
218
234
  name: "clike",
219
235
  keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
220
236
  "static_cast typeid catch operator template typename class friend private " +
@@ -222,7 +238,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
222
238
  "wchar_t"),
223
239
  blockKeywords: words("catch class do else finally for if struct switch try while"),
224
240
  atoms: words("true false null"),
225
- hooks: {"#": cppHook}
241
+ hooks: {"#": cppHook},
242
+ modeProps: {fold: ["brace", "include"]}
226
243
  });
227
244
  CodeMirror.defineMIME("text/x-java", {
228
245
  name: "clike",
@@ -238,7 +255,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
238
255
  stream.eatWhile(/[\w\$_]/);
239
256
  return "meta";
240
257
  }
241
- }
258
+ },
259
+ modeProps: {fold: ["brace", "import"]}
242
260
  });
243
261
  CodeMirror.defineMIME("text/x-csharp", {
244
262
  name: "clike",
@@ -303,7 +321,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
303
321
  }
304
322
  }
305
323
  });
306
- mimes(["x-shader/x-vertex", "x-shader/x-fragment"], {
324
+ def(["x-shader/x-vertex", "x-shader/x-fragment"], {
307
325
  name: "clike",
308
326
  keywords: words("float int bool void " +
309
327
  "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
@@ -357,6 +375,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
357
375
  "gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " +
358
376
  "gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " +
359
377
  "gl_MaxDrawBuffers"),
360
- hooks: {"#": cppHook}
378
+ hooks: {"#": cppHook},
379
+ modeProps: {fold: ["brace", "include"]}
361
380
  });
362
381
  }());
@@ -119,13 +119,13 @@ CodeMirror.defineMode("coffeescript", function(conf) {
119
119
 
120
120
  // Handle strings
121
121
  if (stream.match(stringPrefixes)) {
122
- state.tokenize = tokenFactory(stream.current(), "string");
122
+ state.tokenize = tokenFactory(stream.current(), false, "string");
123
123
  return state.tokenize(stream, state);
124
124
  }
125
125
  // Handle regex literals
126
126
  if (stream.match(regexPrefixes)) {
127
127
  if (stream.current() != "/" || stream.match(/^.*\//, false)) { // prevent highlight of division
128
- state.tokenize = tokenFactory(stream.current(), "string-2");
128
+ state.tokenize = tokenFactory(stream.current(), true, "string-2");
129
129
  return state.tokenize(stream, state);
130
130
  } else {
131
131
  stream.backUp(1);
@@ -161,8 +161,7 @@ CodeMirror.defineMode("coffeescript", function(conf) {
161
161
  return ERRORCLASS;
162
162
  }
163
163
 
164
- function tokenFactory(delimiter, outclass) {
165
- var singleline = delimiter.length == 1;
164
+ function tokenFactory(delimiter, singleline, outclass) {
166
165
  return function(stream, state) {
167
166
  while (!stream.eol()) {
168
167
  stream.eatWhile(/[^'"\/\\]/);
@@ -3,87 +3,80 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
3
3
 
4
4
  if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
5
5
 
6
- var indentUnit = config.indentUnit || config.tabSize || 2,
7
- hooks = parserConfig.hooks || {},
8
- atMediaTypes = parserConfig.atMediaTypes || {},
9
- atMediaFeatures = parserConfig.atMediaFeatures || {},
6
+ var indentUnit = config.indentUnit,
7
+ tokenHooks = parserConfig.tokenHooks,
8
+ mediaTypes = parserConfig.mediaTypes || {},
9
+ mediaFeatures = parserConfig.mediaFeatures || {},
10
10
  propertyKeywords = parserConfig.propertyKeywords || {},
11
11
  colorKeywords = parserConfig.colorKeywords || {},
12
12
  valueKeywords = parserConfig.valueKeywords || {},
13
- allowNested = !!parserConfig.allowNested,
14
- type = null;
13
+ fontProperties = parserConfig.fontProperties || {},
14
+ allowNested = parserConfig.allowNested;
15
15
 
16
+ var type, override;
16
17
  function ret(style, tp) { type = tp; return style; }
17
18
 
19
+ // Tokenizers
20
+
18
21
  function tokenBase(stream, state) {
19
22
  var ch = stream.next();
20
- if (hooks[ch]) {
21
- // result[0] is style and result[1] is type
22
- var result = hooks[ch](stream, state);
23
+ if (tokenHooks[ch]) {
24
+ var result = tokenHooks[ch](stream, state);
23
25
  if (result !== false) return result;
24
26
  }
25
- if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("def", stream.current());}
26
- else if (ch == "=") ret(null, "compare");
27
- else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare");
28
- else if (ch == "\"" || ch == "'") {
27
+ if (ch == "@") {
28
+ stream.eatWhile(/[\w\\\-]/);
29
+ return ret("def", stream.current());
30
+ } else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
31
+ return ret(null, "compare");
32
+ } else if (ch == "\"" || ch == "'") {
29
33
  state.tokenize = tokenString(ch);
30
34
  return state.tokenize(stream, state);
31
- }
32
- else if (ch == "#") {
35
+ } else if (ch == "#") {
33
36
  stream.eatWhile(/[\w\\\-]/);
34
37
  return ret("atom", "hash");
35
- }
36
- else if (ch == "!") {
38
+ } else if (ch == "!") {
37
39
  stream.match(/^\s*\w*/);
38
40
  return ret("keyword", "important");
39
- }
40
- else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
41
+ } else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
41
42
  stream.eatWhile(/[\w.%]/);
42
43
  return ret("number", "unit");
43
- }
44
- else if (ch === "-") {
45
- if (/\d/.test(stream.peek())) {
44
+ } else if (ch === "-") {
45
+ if (/[\d.]/.test(stream.peek())) {
46
46
  stream.eatWhile(/[\w.%]/);
47
47
  return ret("number", "unit");
48
48
  } else if (stream.match(/^[^-]+-/)) {
49
49
  return ret("meta", "meta");
50
50
  }
51
- }
52
- else if (/[,+>*\/]/.test(ch)) {
51
+ } else if (/[,+>*\/]/.test(ch)) {
53
52
  return ret(null, "select-op");
54
- }
55
- else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
53
+ } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
56
54
  return ret("qualifier", "qualifier");
57
- }
58
- else if (ch == ":") {
59
- return ret("operator", ch);
60
- }
61
- else if (/[;{}\[\]\(\)]/.test(ch)) {
55
+ } else if (/[:;{}\[\]\(\)]/.test(ch)) {
62
56
  return ret(null, ch);
63
- }
64
- else if (ch == "u" && stream.match("rl(")) {
57
+ } else if (ch == "u" && stream.match("rl(")) {
65
58
  stream.backUp(1);
66
59
  state.tokenize = tokenParenthesized;
67
- return ret("property", "variable");
68
- }
69
- else {
60
+ return ret("property", "word");
61
+ } else if (/[\w\\\-]/.test(ch)) {
70
62
  stream.eatWhile(/[\w\\\-]/);
71
- return ret("property", "variable");
63
+ return ret("property", "word");
64
+ } else {
65
+ return ret(null, null);
72
66
  }
73
67
  }
74
68
 
75
- function tokenString(quote, nonInclusive) {
69
+ function tokenString(quote) {
76
70
  return function(stream, state) {
77
71
  var escaped = false, ch;
78
72
  while ((ch = stream.next()) != null) {
79
- if (ch == quote && !escaped)
73
+ if (ch == quote && !escaped) {
74
+ if (quote == ")") stream.backUp(1);
80
75
  break;
76
+ }
81
77
  escaped = !escaped && ch == "\\";
82
78
  }
83
- if (!escaped) {
84
- if (nonInclusive) stream.backUp(1);
85
- state.tokenize = tokenBase;
86
- }
79
+ if (ch == quote || !escaped && quote != ")") state.tokenize = null;
87
80
  return ret("string", "string");
88
81
  };
89
82
  }
@@ -91,218 +84,238 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
91
84
  function tokenParenthesized(stream, state) {
92
85
  stream.next(); // Must be '('
93
86
  if (!stream.match(/\s*[\"\']/, false))
94
- state.tokenize = tokenString(")", true);
87
+ state.tokenize = tokenString(")");
95
88
  else
96
- state.tokenize = tokenBase;
89
+ state.tokenize = null;
97
90
  return ret(null, "(");
98
91
  }
99
92
 
93
+ // Context management
94
+
95
+ function Context(type, indent, prev) {
96
+ this.type = type;
97
+ this.indent = indent;
98
+ this.prev = prev;
99
+ }
100
+
101
+ function pushContext(state, stream, type) {
102
+ state.context = new Context(type, stream.indentation() + indentUnit, state.context);
103
+ return type;
104
+ }
105
+
106
+ function popContext(state) {
107
+ state.context = state.context.prev;
108
+ return state.context.type;
109
+ }
110
+
111
+ function pass(type, stream, state) {
112
+ return states[state.context.type](type, stream, state);
113
+ }
114
+ function popAndPass(type, stream, state, n) {
115
+ for (var i = n || 1; i > 0; i--)
116
+ state.context = state.context.prev;
117
+ return pass(type, stream, state);
118
+ }
119
+
120
+ // Parser
121
+
122
+ function wordAsValue(stream) {
123
+ var word = stream.current().toLowerCase();
124
+ if (valueKeywords.hasOwnProperty(word))
125
+ override = "atom";
126
+ else if (colorKeywords.hasOwnProperty(word))
127
+ override = "keyword";
128
+ else
129
+ override = "variable";
130
+ }
131
+
132
+ var states = {};
133
+
134
+ states.top = function(type, stream, state) {
135
+ if (type == "{") {
136
+ return pushContext(state, stream, "block");
137
+ } else if (type == "}" && state.context.prev) {
138
+ return popContext(state);
139
+ } else if (type == "@media") {
140
+ return pushContext(state, stream, "media");
141
+ } else if (type == "@font-face") {
142
+ return "font_face_before";
143
+ } else if (type && type.charAt(0) == "@") {
144
+ return pushContext(state, stream, "at");
145
+ } else if (type == "hash") {
146
+ override = "builtin";
147
+ } else if (type == "word") {
148
+ override = "tag";
149
+ } else if (type == "variable-definition") {
150
+ return "maybeprop";
151
+ } else if (type == "interpolation") {
152
+ return pushContext(state, stream, "interpolation");
153
+ } else if (type == ":") {
154
+ return "pseudo";
155
+ } else if (allowNested && type == "(") {
156
+ return pushContext(state, stream, "params");
157
+ }
158
+ return state.context.type;
159
+ };
160
+
161
+ states.block = function(type, stream, state) {
162
+ if (type == "word") {
163
+ if (propertyKeywords.hasOwnProperty(stream.current().toLowerCase())) {
164
+ override = "property";
165
+ return "maybeprop";
166
+ } else if (allowNested) {
167
+ override = stream.match(/^\s*:/, false) ? "property" : "tag";
168
+ return "block";
169
+ } else {
170
+ override += " error";
171
+ return "maybeprop";
172
+ }
173
+ } else if (type == "meta") {
174
+ return "block";
175
+ } else if (!allowNested && (type == "hash" || type == "qualifier")) {
176
+ override = "error";
177
+ return "block";
178
+ } else {
179
+ return states.top(type, stream, state);
180
+ }
181
+ };
182
+
183
+ states.maybeprop = function(type, stream, state) {
184
+ if (type == ":") return pushContext(state, stream, "prop");
185
+ return pass(type, stream, state);
186
+ };
187
+
188
+ states.prop = function(type, stream, state) {
189
+ if (type == ";") return popContext(state);
190
+ if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
191
+ if (type == "}" || type == "{") return popAndPass(type, stream, state);
192
+ if (type == "(") return pushContext(state, stream, "parens");
193
+
194
+ if (type == "hash" && !/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) {
195
+ override += " error";
196
+ } else if (type == "word") {
197
+ wordAsValue(stream);
198
+ } else if (type == "interpolation") {
199
+ return pushContext(state, stream, "interpolation");
200
+ }
201
+ return "prop";
202
+ };
203
+
204
+ states.propBlock = function(type, _stream, state) {
205
+ if (type == "}") return popContext(state);
206
+ if (type == "word") { override = "property"; return "maybeprop"; }
207
+ return state.context.type;
208
+ };
209
+
210
+ states.parens = function(type, stream, state) {
211
+ if (type == "{" || type == "}") return popAndPass(type, stream, state);
212
+ if (type == ")") return popContext(state);
213
+ return "parens";
214
+ };
215
+
216
+ states.pseudo = function(type, stream, state) {
217
+ if (type == "word") {
218
+ override = "variable-3";
219
+ return state.context.type;
220
+ }
221
+ return pass(type, stream, state);
222
+ };
223
+
224
+ states.media = function(type, stream, state) {
225
+ if (type == "(") return pushContext(state, stream, "media_parens");
226
+ if (type == "}") return popAndPass(type, stream, state);
227
+ if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
228
+
229
+ if (type == "word") {
230
+ var word = stream.current().toLowerCase();
231
+ if (word == "only" || word == "not" || word == "and")
232
+ override = "keyword";
233
+ else if (mediaTypes.hasOwnProperty(word))
234
+ override = "attribute";
235
+ else if (mediaFeatures.hasOwnProperty(word))
236
+ override = "property";
237
+ else
238
+ override = "error";
239
+ }
240
+ return state.context.type;
241
+ };
242
+
243
+ states.media_parens = function(type, stream, state) {
244
+ if (type == ")") return popContext(state);
245
+ if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
246
+ return states.media(type, stream, state);
247
+ };
248
+
249
+ states.font_face_before = function(type, stream, state) {
250
+ if (type == "{")
251
+ return pushContext(state, stream, "font_face");
252
+ return pass(type, stream, state);
253
+ };
254
+
255
+ states.font_face = function(type, stream, state) {
256
+ if (type == "}") return popContext(state);
257
+ if (type == "word") {
258
+ if (!fontProperties.hasOwnProperty(stream.current().toLowerCase()))
259
+ override = "error";
260
+ else
261
+ override = "property";
262
+ return "maybeprop";
263
+ }
264
+ return "font_face";
265
+ };
266
+
267
+ states.at = function(type, stream, state) {
268
+ if (type == ";") return popContext(state);
269
+ if (type == "{" || type == "}") return popAndPass(type, stream, state);
270
+ if (type == "word") override = "tag";
271
+ else if (type == "hash") override = "builtin";
272
+ return "at";
273
+ };
274
+
275
+ states.interpolation = function(type, stream, state) {
276
+ if (type == "}") return popContext(state);
277
+ if (type == "{" || type == ";") return popAndPass(type, stream, state);
278
+ if (type != "variable") override = "error";
279
+ return "interpolation";
280
+ };
281
+
282
+ states.params = function(type, stream, state) {
283
+ if (type == ")") return popContext(state);
284
+ if (type == "{" || type == "}") return popAndPass(type, stream, state);
285
+ if (type == "word") wordAsValue(stream);
286
+ return "params";
287
+ };
288
+
100
289
  return {
101
290
  startState: function(base) {
102
- return {tokenize: tokenBase,
103
- baseIndent: base || 0,
104
- stack: [],
105
- lastToken: null};
291
+ return {tokenize: null,
292
+ state: "top",
293
+ context: new Context("top", base || 0, null)};
106
294
  },
107
295
 
108
296
  token: function(stream, state) {
109
-
110
- // Use these terms when applicable (see http://www.xanthir.com/blog/b4E50)
111
- //
112
- // rule** or **ruleset:
113
- // A selector + braces combo, or an at-rule.
114
- //
115
- // declaration block:
116
- // A sequence of declarations.
117
- //
118
- // declaration:
119
- // A property + colon + value combo.
120
- //
121
- // property value:
122
- // The entire value of a property.
123
- //
124
- // component value:
125
- // A single piece of a property value. Like the 5px in
126
- // text-shadow: 0 0 5px blue;. Can also refer to things that are
127
- // multiple terms, like the 1-4 terms that make up the background-size
128
- // portion of the background shorthand.
129
- //
130
- // term:
131
- // The basic unit of author-facing CSS, like a single number (5),
132
- // dimension (5px), string ("foo"), or function. Officially defined
133
- // by the CSS 2.1 grammar (look for the 'term' production)
134
- //
135
- //
136
- // simple selector:
137
- // A single atomic selector, like a type selector, an attr selector, a
138
- // class selector, etc.
139
- //
140
- // compound selector:
141
- // One or more simple selectors without a combinator. div.example is
142
- // compound, div > .example is not.
143
- //
144
- // complex selector:
145
- // One or more compound selectors chained with combinators.
146
- //
147
- // combinator:
148
- // The parts of selectors that express relationships. There are four
149
- // currently - the space (descendant combinator), the greater-than
150
- // bracket (child combinator), the plus sign (next sibling combinator),
151
- // and the tilda (following sibling combinator).
152
- //
153
- // sequence of selectors:
154
- // One or more of the named type of selector chained with commas.
155
-
156
- state.tokenize = state.tokenize || tokenBase;
157
- if (state.tokenize == tokenBase && stream.eatSpace()) return null;
158
- var style = state.tokenize(stream, state);
159
- if (style && typeof style != "string") style = ret(style[0], style[1]);
160
-
161
- // Changing style returned based on context
162
- var context = state.stack[state.stack.length-1];
163
- if (style == "variable") {
164
- if (type == "variable-definition") state.stack.push("propertyValue");
165
- return state.lastToken = "variable-2";
166
- } else if (style == "property") {
167
- var word = stream.current().toLowerCase();
168
- if (context == "propertyValue") {
169
- if (valueKeywords.hasOwnProperty(word)) {
170
- style = "string-2";
171
- } else if (colorKeywords.hasOwnProperty(word)) {
172
- style = "keyword";
173
- } else {
174
- style = "variable-2";
175
- }
176
- } else if (context == "rule") {
177
- if (!propertyKeywords.hasOwnProperty(word)) {
178
- style += " error";
179
- }
180
- } else if (context == "block") {
181
- // if a value is present in both property, value, or color, the order
182
- // of preference is property -> color -> value
183
- if (propertyKeywords.hasOwnProperty(word)) {
184
- style = "property";
185
- } else if (colorKeywords.hasOwnProperty(word)) {
186
- style = "keyword";
187
- } else if (valueKeywords.hasOwnProperty(word)) {
188
- style = "string-2";
189
- } else {
190
- style = "tag";
191
- }
192
- } else if (!context || context == "@media{") {
193
- style = "tag";
194
- } else if (context == "@media") {
195
- if (atMediaTypes[stream.current()]) {
196
- style = "attribute"; // Known attribute
197
- } else if (/^(only|not)$/.test(word)) {
198
- style = "keyword";
199
- } else if (word == "and") {
200
- style = "error"; // "and" is only allowed in @mediaType
201
- } else if (atMediaFeatures.hasOwnProperty(word)) {
202
- style = "error"; // Known property, should be in @mediaType(
203
- } else {
204
- // Unknown, expecting keyword or attribute, assuming attribute
205
- style = "attribute error";
206
- }
207
- } else if (context == "@mediaType") {
208
- if (atMediaTypes.hasOwnProperty(word)) {
209
- style = "attribute";
210
- } else if (word == "and") {
211
- style = "operator";
212
- } else if (/^(only|not)$/.test(word)) {
213
- style = "error"; // Only allowed in @media
214
- } else {
215
- // Unknown attribute or property, but expecting property (preceded
216
- // by "and"). Should be in parentheses
217
- style = "error";
218
- }
219
- } else if (context == "@mediaType(") {
220
- if (propertyKeywords.hasOwnProperty(word)) {
221
- // do nothing, remains "property"
222
- } else if (atMediaTypes.hasOwnProperty(word)) {
223
- style = "error"; // Known property, should be in parentheses
224
- } else if (word == "and") {
225
- style = "operator";
226
- } else if (/^(only|not)$/.test(word)) {
227
- style = "error"; // Only allowed in @media
228
- } else {
229
- style += " error";
230
- }
231
- } else if (context == "@import") {
232
- style = "tag";
233
- } else {
234
- style = "error";
235
- }
236
- } else if (style == "atom") {
237
- if(!context || context == "@media{" || context == "block") {
238
- style = "builtin";
239
- } else if (context == "propertyValue") {
240
- if (!/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) {
241
- style += " error";
242
- }
243
- } else {
244
- style = "error";
245
- }
246
- } else if (context == "@media" && type == "{") {
247
- style = "error";
248
- }
249
-
250
- // Push/pop context stack
251
- if (type == "{") {
252
- if (context == "@media" || context == "@mediaType") {
253
- state.stack[state.stack.length-1] = "@media{";
254
- }
255
- else {
256
- var newContext = allowNested ? "block" : "rule";
257
- state.stack.push(newContext);
258
- }
259
- }
260
- else if (type == "}") {
261
- if (context == "interpolation") style = "operator";
262
- // Pop off end of array until { is reached
263
- while(state.stack.length){
264
- var removed = state.stack.pop();
265
- if(removed.indexOf("{") > -1 || removed == "block" || removed == "rule"){
266
- break;
267
- }
268
- }
269
- }
270
- else if (type == "interpolation") state.stack.push("interpolation");
271
- else if (type == "@media") state.stack.push("@media");
272
- else if (type == "@import") state.stack.push("@import");
273
- else if (context == "@media" && /\b(keyword|attribute)\b/.test(style))
274
- state.stack[state.stack.length-1] = "@mediaType";
275
- else if (context == "@mediaType" && stream.current() == ",")
276
- state.stack[state.stack.length-1] = "@media";
277
- else if (type == "(") {
278
- if (context == "@media" || context == "@mediaType") {
279
- // Make sure @mediaType is used to avoid error on {
280
- state.stack[state.stack.length-1] = "@mediaType";
281
- state.stack.push("@mediaType(");
282
- }
283
- else state.stack.push("(");
297
+ if (!state.tokenize && stream.eatSpace()) return null;
298
+ var style = (state.tokenize || tokenBase)(stream, state);
299
+ if (style && typeof style == "object") {
300
+ type = style[1];
301
+ style = style[0];
284
302
  }
285
- else if (type == ")") {
286
- // Pop off end of array until ( is reached
287
- while(state.stack.length){
288
- var removed = state.stack.pop();
289
- if(removed.indexOf("(") > -1){
290
- break;
291
- }
292
- }
293
- }
294
- else if (type == ":" && state.lastToken == "property") state.stack.push("propertyValue");
295
- else if (context == "propertyValue" && type == ";") state.stack.pop();
296
- else if (context == "@import" && type == ";") state.stack.pop();
297
-
298
- return state.lastToken = style;
303
+ override = style;
304
+ state.state = states[state.state](type, stream, state);
305
+ return override;
299
306
  },
300
307
 
301
308
  indent: function(state, textAfter) {
302
- var n = state.stack.length;
303
- if (/^\}/.test(textAfter))
304
- n -= state.stack[n-1] == "propertyValue" ? 2 : 1;
305
- return state.baseIndent + n * indentUnit;
309
+ var cx = state.context, ch = textAfter && textAfter.charAt(0);
310
+ var indent = cx.indent;
311
+ if (cx.prev &&
312
+ (ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "font_face") ||
313
+ ch == ")" && (cx.type == "parens" || cx.type == "params" || cx.type == "media_parens") ||
314
+ ch == "{" && (cx.type == "at" || cx.type == "media"))) {
315
+ indent = cx.indent - indentUnit;
316
+ cx = cx.prev;
317
+ }
318
+ return indent;
306
319
  },
307
320
 
308
321
  electricChars: "}",
@@ -321,12 +334,12 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
321
334
  return keys;
322
335
  }
323
336
 
324
- var atMediaTypes = keySet([
337
+ var mediaTypes_ = [
325
338
  "all", "aural", "braille", "handheld", "print", "projection", "screen",
326
339
  "tty", "tv", "embossed"
327
- ]);
340
+ ], mediaTypes = keySet(mediaTypes_);
328
341
 
329
- var atMediaFeatures = keySet([
342
+ var mediaFeatures_ = [
330
343
  "width", "min-width", "max-width", "height", "min-height", "max-height",
331
344
  "device-width", "min-device-width", "max-device-width", "device-height",
332
345
  "min-device-height", "max-device-height", "aspect-ratio",
@@ -335,9 +348,9 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
335
348
  "max-color", "color-index", "min-color-index", "max-color-index",
336
349
  "monochrome", "min-monochrome", "max-monochrome", "resolution",
337
350
  "min-resolution", "max-resolution", "scan", "grid"
338
- ]);
351
+ ], mediaFeatures = keySet(mediaFeatures_);
339
352
 
340
- var propertyKeywords = keySet([
353
+ var propertyKeywords_ = [
341
354
  "align-content", "align-items", "align-self", "alignment-adjust",
342
355
  "alignment-baseline", "anchor-point", "animation", "animation-delay",
343
356
  "animation-direction", "animation-duration", "animation-iteration-count",
@@ -425,9 +438,9 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
425
438
  "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
426
439
  "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
427
440
  "glyph-orientation-vertical", "kerning", "text-anchor", "writing-mode"
428
- ]);
441
+ ], propertyKeywords = keySet(propertyKeywords_);
429
442
 
430
- var colorKeywords = keySet([
443
+ var colorKeywords_ = [
431
444
  "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
432
445
  "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
433
446
  "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
@@ -454,9 +467,9 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
454
467
  "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
455
468
  "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
456
469
  "whitesmoke", "yellow", "yellowgreen"
457
- ]);
470
+ ], colorKeywords = keySet(colorKeywords_);
458
471
 
459
- var valueKeywords = keySet([
472
+ var valueKeywords_ = [
460
473
  "above", "absolute", "activeborder", "activecaption", "afar",
461
474
  "after-white-space", "ahead", "alias", "all", "all-scroll", "alternate",
462
475
  "always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
@@ -539,7 +552,15 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
539
552
  "visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
540
553
  "window", "windowframe", "windowtext", "x-large", "x-small", "xor",
541
554
  "xx-large", "xx-small"
542
- ]);
555
+ ], valueKeywords = keySet(valueKeywords_);
556
+
557
+ var fontProperties_ = [
558
+ "font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
559
+ "font-stretch", "font-weight", "font-style"
560
+ ], fontProperties = keySet(fontProperties_);
561
+
562
+ var allWords = mediaTypes_.concat(mediaFeatures_).concat(propertyKeywords_).concat(colorKeywords_).concat(valueKeywords_);
563
+ CodeMirror.registerHelper("hintWords", "css", allWords);
543
564
 
544
565
  function tokenCComment(stream, state) {
545
566
  var maybeEnd = false, ch;
@@ -553,67 +574,87 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
553
574
  return ["comment", "comment"];
554
575
  }
555
576
 
577
+ function tokenSGMLComment(stream, state) {
578
+ if (stream.skipTo("-->")) {
579
+ stream.match("-->");
580
+ state.tokenize = null;
581
+ } else {
582
+ stream.skipToEnd();
583
+ }
584
+ return ["comment", "comment"];
585
+ }
586
+
556
587
  CodeMirror.defineMIME("text/css", {
557
- atMediaTypes: atMediaTypes,
558
- atMediaFeatures: atMediaFeatures,
588
+ mediaTypes: mediaTypes,
589
+ mediaFeatures: mediaFeatures,
559
590
  propertyKeywords: propertyKeywords,
560
591
  colorKeywords: colorKeywords,
561
592
  valueKeywords: valueKeywords,
562
- hooks: {
593
+ fontProperties: fontProperties,
594
+ tokenHooks: {
563
595
  "<": function(stream, state) {
564
- function tokenSGMLComment(stream, state) {
565
- var dashes = 0, ch;
566
- while ((ch = stream.next()) != null) {
567
- if (dashes >= 2 && ch == ">") {
568
- state.tokenize = null;
569
- break;
570
- }
571
- dashes = (ch == "-") ? dashes + 1 : 0;
572
- }
573
- return ["comment", "comment"];
574
- }
575
- if (stream.eat("!")) {
576
- state.tokenize = tokenSGMLComment;
577
- return tokenSGMLComment(stream, state);
578
- }
596
+ if (!stream.match("!--")) return false;
597
+ state.tokenize = tokenSGMLComment;
598
+ return tokenSGMLComment(stream, state);
579
599
  },
580
600
  "/": function(stream, state) {
581
- if (stream.eat("*")) {
582
- state.tokenize = tokenCComment;
583
- return tokenCComment(stream, state);
584
- }
585
- return false;
601
+ if (!stream.eat("*")) return false;
602
+ state.tokenize = tokenCComment;
603
+ return tokenCComment(stream, state);
586
604
  }
587
605
  },
588
606
  name: "css"
589
607
  });
590
608
 
591
609
  CodeMirror.defineMIME("text/x-scss", {
592
- atMediaTypes: atMediaTypes,
593
- atMediaFeatures: atMediaFeatures,
610
+ mediaTypes: mediaTypes,
611
+ mediaFeatures: mediaFeatures,
594
612
  propertyKeywords: propertyKeywords,
595
613
  colorKeywords: colorKeywords,
596
614
  valueKeywords: valueKeywords,
615
+ fontProperties: fontProperties,
597
616
  allowNested: true,
598
- hooks: {
617
+ tokenHooks: {
618
+ "/": function(stream, state) {
619
+ if (stream.eat("/")) {
620
+ stream.skipToEnd();
621
+ return ["comment", "comment"];
622
+ } else if (stream.eat("*")) {
623
+ state.tokenize = tokenCComment;
624
+ return tokenCComment(stream, state);
625
+ } else {
626
+ return ["operator", "operator"];
627
+ }
628
+ },
599
629
  ":": function(stream) {
600
- if (stream.match(/\s*{/)) {
630
+ if (stream.match(/\s*{/))
601
631
  return [null, "{"];
602
- }
603
632
  return false;
604
633
  },
605
634
  "$": function(stream) {
606
635
  stream.match(/^[\w-]+/);
607
- if (stream.peek() == ":") {
608
- return ["variable", "variable-definition"];
609
- }
610
- return ["variable", "variable"];
611
- },
612
- ",": function(stream, state) {
613
- if (state.stack[state.stack.length - 1] == "propertyValue" && stream.match(/^ *\$/, false)) {
614
- return ["operator", ";"];
615
- }
636
+ if (stream.match(/^\s*:/, false))
637
+ return ["variable-2", "variable-definition"];
638
+ return ["variable-2", "variable"];
616
639
  },
640
+ "#": function(stream) {
641
+ if (!stream.eat("{")) return false;
642
+ return [null, "interpolation"];
643
+ }
644
+ },
645
+ name: "css",
646
+ helperType: "scss"
647
+ });
648
+
649
+ CodeMirror.defineMIME("text/x-less", {
650
+ mediaTypes: mediaTypes,
651
+ mediaFeatures: mediaFeatures,
652
+ propertyKeywords: propertyKeywords,
653
+ colorKeywords: colorKeywords,
654
+ valueKeywords: valueKeywords,
655
+ fontProperties: fontProperties,
656
+ allowNested: true,
657
+ tokenHooks: {
617
658
  "/": function(stream, state) {
618
659
  if (stream.eat("/")) {
619
660
  stream.skipToEnd();
@@ -625,15 +666,18 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
625
666
  return ["operator", "operator"];
626
667
  }
627
668
  },
628
- "#": function(stream) {
629
- if (stream.eat("{")) {
630
- return ["operator", "interpolation"];
631
- } else {
632
- stream.eatWhile(/[\w\\\-]/);
633
- return ["atom", "hash"];
634
- }
669
+ "@": function(stream) {
670
+ if (stream.match(/^(charset|document|font-face|import|keyframes|media|namespace|page|supports)\b/, false)) return false;
671
+ stream.eatWhile(/[\w\\\-]/);
672
+ if (stream.match(/^\s*:/, false))
673
+ return ["variable-2", "variable-definition"];
674
+ return ["variable-2", "variable"];
675
+ },
676
+ "&": function() {
677
+ return ["atom", "atom"];
635
678
  }
636
679
  },
637
- name: "css"
680
+ name: "css",
681
+ helperType: "less"
638
682
  });
639
683
  })();