luca 0.8.599 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. data/.gitignore +3 -0
  2. data/.rvmrc +1 -0
  3. data/CHANGELOG +51 -2
  4. data/README.md +10 -247
  5. data/ROADMAP +6 -2
  6. data/app.rb +16 -2
  7. data/assets/javascripts/dependencies/bootstrap.min.js +7 -1
  8. data/assets/javascripts/dependencies/codemirror-coffeescript.js +347 -0
  9. data/assets/javascripts/dependencies/codemirror-css.js +124 -0
  10. data/assets/javascripts/dependencies/codemirror-html.js +410 -0
  11. data/assets/javascripts/dependencies/codemirror-javascript.js +361 -0
  12. data/assets/javascripts/dependencies/codemirror-less.js +232 -0
  13. data/assets/javascripts/dependencies/codemirror-vim.js +500 -0
  14. data/assets/javascripts/dependencies/codemirror.js +3076 -0
  15. data/assets/javascripts/dependencies.coffee +0 -1
  16. data/assets/javascripts/luca-ui-base.coffee +10 -3
  17. data/assets/javascripts/luca-ui-bootstrap.js +1 -0
  18. data/assets/javascripts/luca-ui-development-tools.coffee +9 -0
  19. data/assets/javascripts/luca-ui.coffee +6 -1
  20. data/assets/javascripts/sandbox/application.coffee +51 -0
  21. data/assets/javascripts/sandbox/router.coffee +14 -0
  22. data/assets/javascripts/sandbox/templates/main.luca +33 -0
  23. data/assets/javascripts/sandbox/templates/sandbox/navigation.luca +1 -0
  24. data/assets/javascripts/sandbox/templates/sandbox.luca +1 -0
  25. data/assets/javascripts/sandbox/views/top_navigation.coffee +4 -0
  26. data/assets/javascripts/sandbox.coffee +2 -2
  27. data/assets/stylesheets/bootstrap.min.css +395 -297
  28. data/assets/stylesheets/codemirror-blackboard.css +25 -0
  29. data/assets/stylesheets/codemirror-monokai.css +33 -0
  30. data/assets/stylesheets/codemirror.css +126 -0
  31. data/assets/stylesheets/luca-ui-bootstrap.css +0 -1
  32. data/assets/stylesheets/luca-ui-development-tools.css +5 -0
  33. data/assets/stylesheets/sandbox/sandbox.scss +1 -3
  34. data/assets/stylesheets/themes/amelia-bootstrap.css +826 -0
  35. data/assets/stylesheets/themes/slate-bootstrap.css +797 -0
  36. data/assets/stylesheets/themes/superhero-bootstrap.css +830 -0
  37. data/lib/luca/code_browser.rb +55 -0
  38. data/lib/luca/rails/version.rb +1 -1
  39. data/lib/luca/rails.rb +1 -0
  40. data/spec/components/fields/checkbox_array_spec.coffee +46 -0
  41. data/spec/components/form_view_spec.coffee +10 -4
  42. data/spec/containers/card_view_spec.coffee +7 -0
  43. data/spec/core/collection_spec.coffee +58 -4
  44. data/spec/core/container_spec.coffee +6 -6
  45. data/spec/core/view_spec.coffee +93 -7
  46. data/spec/framework_spec.coffee +15 -12
  47. data/src/components/application.coffee +126 -18
  48. data/src/components/base_toolbar.coffee +2 -2
  49. data/src/components/collection_loader_view.coffee +1 -2
  50. data/src/components/collection_view.coffee +77 -0
  51. data/src/components/controller.coffee +1 -4
  52. data/src/components/fields/button_field.coffee +1 -1
  53. data/src/components/fields/checkbox_array.coffee +2 -2
  54. data/src/components/fields/checkbox_field.coffee +3 -1
  55. data/src/components/fields/file_upload_field.coffee +1 -1
  56. data/src/components/fields/hidden_field.coffee +1 -1
  57. data/src/components/fields/select_field.coffee +1 -1
  58. data/src/components/fields/text_area_field.coffee +1 -1
  59. data/src/components/fields/text_field.coffee +10 -6
  60. data/src/components/fields/type_ahead_field.coffee +18 -5
  61. data/src/components/form_button_toolbar.coffee +1 -2
  62. data/src/components/form_view.coffee +44 -62
  63. data/src/components/grid_view.coffee +27 -20
  64. data/src/components/load_mask.coffee +3 -0
  65. data/src/components/nav_bar.coffee +26 -0
  66. data/src/components/record_manager.coffee +1 -3
  67. data/src/components/router.coffee +1 -1
  68. data/src/components/template.coffee +3 -15
  69. data/src/components/toolbar_dialog.coffee +25 -0
  70. data/src/containers/card_view.coffee +22 -23
  71. data/src/containers/column_view.coffee +1 -6
  72. data/src/containers/modal_view.coffee +20 -71
  73. data/src/containers/panel_toolbar.coffee +156 -0
  74. data/src/containers/panel_view.coffee +1 -1
  75. data/src/containers/split_view.coffee +1 -3
  76. data/src/containers/tab_view.coffee +29 -29
  77. data/src/containers/viewport.coffee +38 -3
  78. data/src/core/collection.coffee +80 -48
  79. data/src/core/container.coffee +153 -72
  80. data/src/core/core.coffee +181 -0
  81. data/src/core/field.coffee +4 -2
  82. data/src/core/model.coffee +1 -1
  83. data/src/core/observer.coffee +3 -3
  84. data/src/core/panel.coffee +143 -0
  85. data/src/core/registry.coffee +104 -0
  86. data/src/core/util.coffee +82 -0
  87. data/src/core/view.coffee +158 -85
  88. data/src/framework.coffee +112 -178
  89. data/src/index.coffee +0 -255
  90. data/src/managers/collection_manager.coffee +1 -0
  91. data/src/samples/definition.coffee +49 -0
  92. data/src/stylesheets/base.scss +0 -78
  93. data/src/stylesheets/components/form_view.scss +8 -3
  94. data/src/stylesheets/components/grid_view.scss +3 -7
  95. data/src/stylesheets/components/load_mask.scss +14 -0
  96. data/src/stylesheets/components/toolbar.scss +0 -15
  97. data/src/stylesheets/containers/container.scss +14 -2
  98. data/src/stylesheets/containers/panels.scss +23 -0
  99. data/src/stylesheets/tools/class_browser.scss +32 -0
  100. data/src/stylesheets/tools/code_editor.scss +24 -0
  101. data/src/stylesheets/tools/component_tester.scss +8 -0
  102. data/src/stylesheets/tools/console.scss +26 -0
  103. data/src/templates/components/collection_loader_view.luca +1 -1
  104. data/src/templates/components/form_view.luca +2 -13
  105. data/src/templates/components/grid_view.luca +0 -2
  106. data/src/templates/components/load_mask.luca +3 -0
  107. data/src/templates/components/nav_bar.luca +2 -0
  108. data/src/templates/containers/tab_view.luca +1 -0
  109. data/src/templates/fields/text_field.luca +4 -1
  110. data/src/tools/class_browser.coffee +39 -0
  111. data/src/tools/code_editor.coffee +258 -0
  112. data/src/tools/code_mirror_field.coffee +57 -0
  113. data/src/tools/coffee_script_editor.coffee +60 -0
  114. data/src/tools/collection_inspector.coffee +4 -0
  115. data/src/tools/component_tester.coffee +472 -0
  116. data/src/tools/components/class_browser_detail.coffee +10 -0
  117. data/src/tools/components/class_browser_list.coffee +74 -0
  118. data/src/tools/console.coffee +147 -0
  119. data/src/tools/development_console.coffee +147 -0
  120. data/src/tools/models/components.coffee +63 -0
  121. data/src/tools/templates/component_tester/help.luca +14 -0
  122. data/vendor/assets/javascripts/luca-ui-base.js +1389 -611
  123. data/vendor/assets/javascripts/luca-ui-bootstrap.js +9 -0
  124. data/vendor/assets/javascripts/luca-ui-development-tools.js +18719 -0
  125. data/vendor/assets/javascripts/luca-ui-spec.js +2065 -878
  126. data/vendor/assets/javascripts/luca-ui.js +1759 -852
  127. data/vendor/assets/javascripts/luca-ui.min.js +3 -3
  128. data/vendor/assets/stylesheets/luca-ui-bootstrap.css +494 -440
  129. data/vendor/assets/stylesheets/luca-ui-development-tools.css +224 -0
  130. data/vendor/assets/stylesheets/luca-ui-spec.css +99 -140
  131. data/vendor/assets/stylesheets/luca-ui.css +99 -140
  132. data/views/index.erb +6 -3
  133. metadata +60 -18
  134. data/assets/javascripts/dependencies/jquery-console.js +0 -649
  135. data/assets/javascripts/development-console.coffee +0 -2
  136. data/assets/javascripts/sandbox/sandbox.coffee +0 -16
  137. data/assets/javascripts/sandbox/templates/features/collection_helpers.luca +0 -33
  138. data/assets/javascripts/sandbox/templates/features/form_demo_code.luca +0 -48
  139. data/assets/javascripts/sandbox/templates/features/grid_demo_code.luca +0 -24
  140. data/assets/javascripts/sandbox/templates/features/introduction.luca +0 -11
  141. data/assets/javascripts/sandbox/templates/features/view_helpers.luca +0 -43
  142. data/assets/javascripts/sandbox/templates/navigation.luca +0 -8
  143. data/assets/javascripts/sandbox/views/form_demo.coffee +0 -47
  144. data/assets/javascripts/sandbox/views/grid_demo.coffee +0 -23
  145. data/assets/javascripts/sandbox/views/pages/collection_events_sample.coffee +0 -1
  146. data/assets/javascripts/sandbox/views/pages/pages_controller.coffee +0 -38
  147. data/src/components/collection_inspector.coffee +0 -2
  148. data/src/components/development_console.coffee +0 -59
  149. data/src/stylesheets/components/development_console.scss +0 -47
@@ -0,0 +1,361 @@
1
+ CodeMirror.defineMode("javascript", function(config, parserConfig) {
2
+ var indentUnit = config.indentUnit;
3
+ var jsonMode = parserConfig.json;
4
+
5
+ // Tokenizer
6
+
7
+ var keywords = function(){
8
+ function kw(type) {return {type: type, style: "keyword"};}
9
+ var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
10
+ var operator = kw("operator"), atom = {type: "atom", style: "atom"};
11
+ return {
12
+ "if": A, "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
13
+ "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C,
14
+ "var": kw("var"), "const": kw("var"), "let": kw("var"),
15
+ "function": kw("function"), "catch": kw("catch"),
16
+ "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
17
+ "in": operator, "typeof": operator, "instanceof": operator,
18
+ "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom
19
+ };
20
+ }();
21
+
22
+ var isOperatorChar = /[+\-*&%=<>!?|]/;
23
+
24
+ function chain(stream, state, f) {
25
+ state.tokenize = f;
26
+ return f(stream, state);
27
+ }
28
+
29
+ function nextUntilUnescaped(stream, end) {
30
+ var escaped = false, next;
31
+ while ((next = stream.next()) != null) {
32
+ if (next == end && !escaped)
33
+ return false;
34
+ escaped = !escaped && next == "\\";
35
+ }
36
+ return escaped;
37
+ }
38
+
39
+ // Used as scratch variables to communicate multiple values without
40
+ // consing up tons of objects.
41
+ var type, content;
42
+ function ret(tp, style, cont) {
43
+ type = tp; content = cont;
44
+ return style;
45
+ }
46
+
47
+ function jsTokenBase(stream, state) {
48
+ var ch = stream.next();
49
+ if (ch == '"' || ch == "'")
50
+ return chain(stream, state, jsTokenString(ch));
51
+ else if (/[\[\]{}\(\),;\:\.]/.test(ch))
52
+ return ret(ch);
53
+ else if (ch == "0" && stream.eat(/x/i)) {
54
+ stream.eatWhile(/[\da-f]/i);
55
+ return ret("number", "number");
56
+ }
57
+ else if (/\d/.test(ch)) {
58
+ stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
59
+ return ret("number", "number");
60
+ }
61
+ else if (ch == "/") {
62
+ if (stream.eat("*")) {
63
+ return chain(stream, state, jsTokenComment);
64
+ }
65
+ else if (stream.eat("/")) {
66
+ stream.skipToEnd();
67
+ return ret("comment", "comment");
68
+ }
69
+ else if (state.reAllowed) {
70
+ nextUntilUnescaped(stream, "/");
71
+ stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
72
+ return ret("regexp", "string-2");
73
+ }
74
+ else {
75
+ stream.eatWhile(isOperatorChar);
76
+ return ret("operator", null, stream.current());
77
+ }
78
+ }
79
+ else if (ch == "#") {
80
+ stream.skipToEnd();
81
+ return ret("error", "error");
82
+ }
83
+ else if (isOperatorChar.test(ch)) {
84
+ stream.eatWhile(isOperatorChar);
85
+ return ret("operator", null, stream.current());
86
+ }
87
+ else {
88
+ stream.eatWhile(/[\w\$_]/);
89
+ var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
90
+ return (known && state.kwAllowed) ? ret(known.type, known.style, word) :
91
+ ret("variable", "variable", word);
92
+ }
93
+ }
94
+
95
+ function jsTokenString(quote) {
96
+ return function(stream, state) {
97
+ if (!nextUntilUnescaped(stream, quote))
98
+ state.tokenize = jsTokenBase;
99
+ return ret("string", "string");
100
+ };
101
+ }
102
+
103
+ function jsTokenComment(stream, state) {
104
+ var maybeEnd = false, ch;
105
+ while (ch = stream.next()) {
106
+ if (ch == "/" && maybeEnd) {
107
+ state.tokenize = jsTokenBase;
108
+ break;
109
+ }
110
+ maybeEnd = (ch == "*");
111
+ }
112
+ return ret("comment", "comment");
113
+ }
114
+
115
+ // Parser
116
+
117
+ var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true};
118
+
119
+ function JSLexical(indented, column, type, align, prev, info) {
120
+ this.indented = indented;
121
+ this.column = column;
122
+ this.type = type;
123
+ this.prev = prev;
124
+ this.info = info;
125
+ if (align != null) this.align = align;
126
+ }
127
+
128
+ function inScope(state, varname) {
129
+ for (var v = state.localVars; v; v = v.next)
130
+ if (v.name == varname) return true;
131
+ }
132
+
133
+ function parseJS(state, style, type, content, stream) {
134
+ var cc = state.cc;
135
+ // Communicate our context to the combinators.
136
+ // (Less wasteful than consing up a hundred closures on every call.)
137
+ cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
138
+
139
+ if (!state.lexical.hasOwnProperty("align"))
140
+ state.lexical.align = true;
141
+
142
+ while(true) {
143
+ var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
144
+ if (combinator(type, content)) {
145
+ while(cc.length && cc[cc.length - 1].lex)
146
+ cc.pop()();
147
+ if (cx.marked) return cx.marked;
148
+ if (type == "variable" && inScope(state, content)) return "variable-2";
149
+ return style;
150
+ }
151
+ }
152
+ }
153
+
154
+ // Combinator utils
155
+
156
+ var cx = {state: null, column: null, marked: null, cc: null};
157
+ function pass() {
158
+ for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
159
+ }
160
+ function cont() {
161
+ pass.apply(null, arguments);
162
+ return true;
163
+ }
164
+ function register(varname) {
165
+ var state = cx.state;
166
+ if (state.context) {
167
+ cx.marked = "def";
168
+ for (var v = state.localVars; v; v = v.next)
169
+ if (v.name == varname) return;
170
+ state.localVars = {name: varname, next: state.localVars};
171
+ }
172
+ }
173
+
174
+ // Combinators
175
+
176
+ var defaultVars = {name: "this", next: {name: "arguments"}};
177
+ function pushcontext() {
178
+ if (!cx.state.context) cx.state.localVars = defaultVars;
179
+ cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
180
+ }
181
+ function popcontext() {
182
+ cx.state.localVars = cx.state.context.vars;
183
+ cx.state.context = cx.state.context.prev;
184
+ }
185
+ function pushlex(type, info) {
186
+ var result = function() {
187
+ var state = cx.state;
188
+ state.lexical = new JSLexical(state.indented, cx.stream.column(), type, null, state.lexical, info)
189
+ };
190
+ result.lex = true;
191
+ return result;
192
+ }
193
+ function poplex() {
194
+ var state = cx.state;
195
+ if (state.lexical.prev) {
196
+ if (state.lexical.type == ")")
197
+ state.indented = state.lexical.indented;
198
+ state.lexical = state.lexical.prev;
199
+ }
200
+ }
201
+ poplex.lex = true;
202
+
203
+ function expect(wanted) {
204
+ return function expecting(type) {
205
+ if (type == wanted) return cont();
206
+ else if (wanted == ";") return pass();
207
+ else return cont(arguments.callee);
208
+ };
209
+ }
210
+
211
+ function statement(type) {
212
+ if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex);
213
+ if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
214
+ if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
215
+ if (type == "{") return cont(pushlex("}"), block, poplex);
216
+ if (type == ";") return cont();
217
+ if (type == "function") return cont(functiondef);
218
+ if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"),
219
+ poplex, statement, poplex);
220
+ if (type == "variable") return cont(pushlex("stat"), maybelabel);
221
+ if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
222
+ block, poplex, poplex);
223
+ if (type == "case") return cont(expression, expect(":"));
224
+ if (type == "default") return cont(expect(":"));
225
+ if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
226
+ statement, poplex, popcontext);
227
+ return pass(pushlex("stat"), expression, expect(";"), poplex);
228
+ }
229
+ function expression(type) {
230
+ if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);
231
+ if (type == "function") return cont(functiondef);
232
+ if (type == "keyword c") return cont(maybeexpression);
233
+ if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator);
234
+ if (type == "operator") return cont(expression);
235
+ if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator);
236
+ if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator);
237
+ return cont();
238
+ }
239
+ function maybeexpression(type) {
240
+ if (type.match(/[;\}\)\],]/)) return pass();
241
+ return pass(expression);
242
+ }
243
+
244
+ function maybeoperator(type, value) {
245
+ if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
246
+ if (type == "operator" || type == ":") return cont(expression);
247
+ if (type == ";") return;
248
+ if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
249
+ if (type == ".") return cont(property, maybeoperator);
250
+ if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator);
251
+ }
252
+ function maybelabel(type) {
253
+ if (type == ":") return cont(poplex, statement);
254
+ return pass(maybeoperator, expect(";"), poplex);
255
+ }
256
+ function property(type) {
257
+ if (type == "variable") {cx.marked = "property"; return cont();}
258
+ }
259
+ function objprop(type) {
260
+ if (type == "variable") cx.marked = "property";
261
+ if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression);
262
+ }
263
+ function commasep(what, end) {
264
+ function proceed(type) {
265
+ if (type == ",") return cont(what, proceed);
266
+ if (type == end) return cont();
267
+ return cont(expect(end));
268
+ }
269
+ return function commaSeparated(type) {
270
+ if (type == end) return cont();
271
+ else return pass(what, proceed);
272
+ };
273
+ }
274
+ function block(type) {
275
+ if (type == "}") return cont();
276
+ return pass(statement, block);
277
+ }
278
+ function vardef1(type, value) {
279
+ if (type == "variable"){register(value); return cont(vardef2);}
280
+ return cont();
281
+ }
282
+ function vardef2(type, value) {
283
+ if (value == "=") return cont(expression, vardef2);
284
+ if (type == ",") return cont(vardef1);
285
+ }
286
+ function forspec1(type) {
287
+ if (type == "var") return cont(vardef1, forspec2);
288
+ if (type == ";") return pass(forspec2);
289
+ if (type == "variable") return cont(formaybein);
290
+ return pass(forspec2);
291
+ }
292
+ function formaybein(type, value) {
293
+ if (value == "in") return cont(expression);
294
+ return cont(maybeoperator, forspec2);
295
+ }
296
+ function forspec2(type, value) {
297
+ if (type == ";") return cont(forspec3);
298
+ if (value == "in") return cont(expression);
299
+ return cont(expression, expect(";"), forspec3);
300
+ }
301
+ function forspec3(type) {
302
+ if (type != ")") cont(expression);
303
+ }
304
+ function functiondef(type, value) {
305
+ if (type == "variable") {register(value); return cont(functiondef);}
306
+ if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext);
307
+ }
308
+ function funarg(type, value) {
309
+ if (type == "variable") {register(value); return cont();}
310
+ }
311
+
312
+ // Interface
313
+
314
+ return {
315
+ startState: function(basecolumn) {
316
+ return {
317
+ tokenize: jsTokenBase,
318
+ reAllowed: true,
319
+ kwAllowed: true,
320
+ cc: [],
321
+ lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
322
+ localVars: parserConfig.localVars,
323
+ context: parserConfig.localVars && {vars: parserConfig.localVars},
324
+ indented: 0
325
+ };
326
+ },
327
+
328
+ token: function(stream, state) {
329
+ if (stream.sol()) {
330
+ if (!state.lexical.hasOwnProperty("align"))
331
+ state.lexical.align = false;
332
+ state.indented = stream.indentation();
333
+ }
334
+ if (stream.eatSpace()) return null;
335
+ var style = state.tokenize(stream, state);
336
+ if (type == "comment") return style;
337
+ state.reAllowed = !!(type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/));
338
+ state.kwAllowed = type != '.';
339
+ return parseJS(state, style, type, content, stream);
340
+ },
341
+
342
+ indent: function(state, textAfter) {
343
+ if (state.tokenize != jsTokenBase) return 0;
344
+ var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
345
+ if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
346
+ var type = lexical.type, closing = firstChar == type;
347
+ if (type == "vardef") return lexical.indented + 4;
348
+ else if (type == "form" && firstChar == "{") return lexical.indented;
349
+ else if (type == "stat" || type == "form") return lexical.indented + indentUnit;
350
+ else if (lexical.info == "switch" && !closing)
351
+ return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
352
+ else if (lexical.align) return lexical.column + (closing ? 0 : 1);
353
+ else return lexical.indented + (closing ? 0 : indentUnit);
354
+ },
355
+
356
+ electricChars: ":{}"
357
+ };
358
+ });
359
+
360
+ CodeMirror.defineMIME("text/javascript", "javascript");
361
+ CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
@@ -0,0 +1,232 @@
1
+ /*
2
+ LESS mode - http://www.lesscss.org/
3
+ Ported to CodeMirror by Peter Kroon
4
+ */
5
+
6
+ CodeMirror.defineMode("css", function(config) {
7
+ var indentUnit = config.indentUnit, type;
8
+ function ret(style, tp) {type = tp; return style;}
9
+ //html5 tags
10
+ var tags = ["a","abbr","acronym","address","applet","area","article","aside","audio","b","base","basefont","bdi","bdo","big","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","command","datalist","dd","del","details","dfn","dir","div","dl","dt","em","embed","fieldset","figcaption","figure","font","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","keygen","kbd","label","legend","li","link","map","mark","menu","meta","meter","nav","noframes","noscript","object","ol","optgroup","option","output","p","param","pre","progress","q","rp","rt","ruby","s","samp","script","section","select","small","source","span","strike","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","title","tr","track","tt","u","ul","var","video","wbr"];
11
+
12
+ function inTagsArray(val){
13
+ for(var i=0; i<tags.length; i++){
14
+ if(val === tags[i]){
15
+ return true;
16
+ }
17
+ }
18
+ }
19
+
20
+ function tokenBase(stream, state) {
21
+ var ch = stream.next();
22
+
23
+ if (ch == "@") {stream.eatWhile(/[\w\-]/); return ret("meta", stream.current());}
24
+ else if (ch == "/" && stream.eat("*")) {
25
+ state.tokenize = tokenCComment;
26
+ return tokenCComment(stream, state);
27
+ }
28
+ else if (ch == "<" && stream.eat("!")) {
29
+ state.tokenize = tokenSGMLComment;
30
+ return tokenSGMLComment(stream, state);
31
+ }
32
+ else if (ch == "=") ret(null, "compare");
33
+ else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare");
34
+ else if (ch == "\"" || ch == "'") {
35
+ state.tokenize = tokenString(ch);
36
+ return state.tokenize(stream, state);
37
+ }
38
+ else if (ch == "/") { // lesscss e.g.: .png will not be parsed as a class
39
+ if(stream.eat("/")){
40
+ state.tokenize = tokenSComment
41
+ return tokenSComment(stream, state);
42
+ }else{
43
+ stream.eatWhile(/[\a-zA-Z0-9\-_.\s]/);
44
+ if(/\/|\)|#/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == ")")))return ret("string", "string");//let url(/images/logo.png) without quotes return as string
45
+ return ret("number", "unit");
46
+ }
47
+ }
48
+ else if (ch == "!") {
49
+ stream.match(/^\s*\w*/);
50
+ return ret("keyword", "important");
51
+ }
52
+ else if (/\d/.test(ch)) {
53
+ stream.eatWhile(/[\w.%]/);
54
+ return ret("number", "unit");
55
+ }
56
+ else if (/[,+<>*\/]/.test(ch)) {//removed . dot character original was [,.+>*\/]
57
+ return ret(null, "select-op");
58
+ }
59
+ else if (/[;{}:\[\]()]/.test(ch)) { //added () char for lesscss original was [;{}:\[\]]
60
+ if(ch == ":"){
61
+ stream.eatWhile(/[active|hover|link|visited]/);
62
+ if( stream.current().match(/active|hover|link|visited/)){
63
+ return ret("tag", "tag");
64
+ }else{
65
+ return ret(null, ch);
66
+ }
67
+ }else{
68
+ return ret(null, ch);
69
+ }
70
+ }
71
+ else if (ch == ".") { // lesscss
72
+ stream.eatWhile(/[\a-zA-Z0-9\-_]/);
73
+ return ret("tag", "tag");
74
+ }
75
+ else if (ch == "#") { // lesscss
76
+ //we don't eat white-space, we want the hex color and or id only
77
+ stream.eatWhile(/[A-Za-z0-9]/);
78
+ //check if there is a proper hex color length e.g. #eee || #eeeEEE
79
+ if(stream.current().length ===4 || stream.current().length ===7){
80
+ if(stream.current().match(/[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/,false) != null){//is there a valid hex color value present in the current stream
81
+ //when not a valid hex value, parse as id
82
+ if(stream.current().substring(1) != stream.current().match(/[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/,false))return ret("atom", "tag");
83
+ //eat white-space
84
+ stream.eatSpace();
85
+ //when hex value declaration doesn't end with [;,] but is does with a slash/cc comment treat it as an id, just like the other hex values that don't end with[;,]
86
+ if( /[\/<>.(){!$%^&*_\-\\?=+\|#'~`]/.test(stream.peek()) )return ret("atom", "tag");
87
+ //#time { color: #aaa }
88
+ else if(stream.peek() == "}" )return ret("number", "unit");
89
+ //we have a valid hex color value, parse as id whenever an element/class is defined after the hex(id) value e.g. #eee aaa || #eee .aaa
90
+ else if( /[a-zA-Z\\]/.test(stream.peek()) )return ret("atom", "tag");
91
+ //when a hex value is on the end of a line, parse as id
92
+ else if(stream.eol())return ret("atom", "tag");
93
+ //default
94
+ else return ret("number", "unit");
95
+ }else{//when not a valid hexvalue in the current stream e.g. #footer
96
+ stream.eatWhile(/[\w\\\-]/);
97
+ return ret("atom", "tag");
98
+ }
99
+ }else{
100
+ stream.eatWhile(/[\w\\\-]/);
101
+ return ret("atom", "tag");
102
+ }
103
+ }
104
+ else if (ch == "&") {
105
+ stream.eatWhile(/[\w\-]/);
106
+ return ret(null, ch);
107
+ }
108
+ else {
109
+ stream.eatWhile(/[\w\\\-_%.{]/);
110
+ if(stream.current().match(/http|https/) != null){
111
+ stream.eatWhile(/[\w\\\-_%.{:\/]/);
112
+ return ret("string", "string");
113
+ }else if(stream.peek() == "<" || stream.peek() == ">"){
114
+ return ret("tag", "tag");
115
+ }else if( stream.peek().match(/\(/) != null ){// lessc
116
+ return ret(null, ch);
117
+ }else if (stream.peek() == "/" && state.stack[state.stack.length-1] != undefined){ // url(dir/center/image.png)
118
+ return ret("string", "string");
119
+ }else if( stream.current().match(/\-\d|\-.\d/) ){ // lesscss match e.g.: -5px -0.4 etc... only colorize the minus sign
120
+ //stream.backUp(stream.current().length-1); //commment out these 2 comment if you want the minus sign to be parsed as null -500px
121
+ //return ret(null, ch);
122
+ return ret("number", "unit");
123
+ }else if( inTagsArray(stream.current()) ){ // lesscss match html tags
124
+ return ret("tag", "tag");
125
+ }else if( /\/|[\s\)]/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == "/")) && stream.current().indexOf(".") !== -1){
126
+ if(stream.current().substring(stream.current().length-1,stream.current().length) == "{"){
127
+ stream.backUp(1);
128
+ return ret("tag", "tag");
129
+ }//end if
130
+ if( (stream.eatSpace() && stream.peek().match(/[{<>.a-zA-Z]/) != null) || stream.eol() )return ret("tag", "tag");//e.g. button.icon-plus
131
+ return ret("string", "string");//let url(/images/logo.png) without quotes return as string
132
+ }else if( stream.eol() ){
133
+ if(stream.current().substring(stream.current().length-1,stream.current().length) == "{")stream.backUp(1);
134
+ return ret("tag", "tag");
135
+ }else{
136
+ return ret("variable", "variable");
137
+ }
138
+ }
139
+
140
+ }
141
+
142
+ function tokenSComment(stream, state) {// SComment = Slash comment
143
+ stream.skipToEnd();
144
+ state.tokenize = tokenBase;
145
+ return ret("comment", "comment");
146
+ }
147
+
148
+ function tokenCComment(stream, state) {
149
+ var maybeEnd = false, ch;
150
+ while ((ch = stream.next()) != null) {
151
+ if (maybeEnd && ch == "/") {
152
+ state.tokenize = tokenBase;
153
+ break;
154
+ }
155
+ maybeEnd = (ch == "*");
156
+ }
157
+ return ret("comment", "comment");
158
+ }
159
+
160
+ function tokenSGMLComment(stream, state) {
161
+ var dashes = 0, ch;
162
+ while ((ch = stream.next()) != null) {
163
+ if (dashes >= 2 && ch == ">") {
164
+ state.tokenize = tokenBase;
165
+ break;
166
+ }
167
+ dashes = (ch == "-") ? dashes + 1 : 0;
168
+ }
169
+ return ret("comment", "comment");
170
+ }
171
+
172
+ function tokenString(quote) {
173
+ return function(stream, state) {
174
+ var escaped = false, ch;
175
+ while ((ch = stream.next()) != null) {
176
+ if (ch == quote && !escaped)
177
+ break;
178
+ escaped = !escaped && ch == "\\";
179
+ }
180
+ if (!escaped) state.tokenize = tokenBase;
181
+ return ret("string", "string");
182
+ };
183
+ }
184
+
185
+ return {
186
+ startState: function(base) {
187
+ return {tokenize: tokenBase,
188
+ baseIndent: base || 0,
189
+ stack: []};
190
+ },
191
+
192
+ token: function(stream, state) {
193
+ if (stream.eatSpace()) return null;
194
+ var style = state.tokenize(stream, state);
195
+
196
+ var context = state.stack[state.stack.length-1];
197
+ if (type == "hash" && context == "rule") style = "atom";
198
+ else if (style == "variable") {
199
+ if (context == "rule") style = null; //"tag"
200
+ else if (!context || context == "@media{"){
201
+ style = stream.current() == "when" ? "variable" :
202
+ stream.string.match(/#/g) != undefined ? null :
203
+ /[\s,|\s\)]/.test(stream.peek()) ? "tag" : null;
204
+ }
205
+ }
206
+
207
+ if (context == "rule" && /^[\{\};]$/.test(type))
208
+ state.stack.pop();
209
+ if (type == "{") {
210
+ if (context == "@media") state.stack[state.stack.length-1] = "@media{";
211
+ else state.stack.push("{");
212
+ }
213
+ else if (type == "}") state.stack.pop();
214
+ else if (type == "@media") state.stack.push("@media");
215
+ else if (context == "{" && type != "comment") state.stack.push("rule");
216
+ return style;
217
+ },
218
+
219
+ indent: function(state, textAfter) {
220
+ var n = state.stack.length;
221
+ if (/^\}/.test(textAfter))
222
+ n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1;
223
+ return state.baseIndent + n * indentUnit;
224
+ },
225
+
226
+ electricChars: "}"
227
+ };
228
+ });
229
+
230
+ CodeMirror.defineMIME("text/x-less", "less");
231
+ if (!CodeMirror.mimeModes.hasOwnProperty("text/css"))
232
+ CodeMirror.defineMIME("text/css", "less");