luca 0.8.599 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.rvmrc +1 -0
- data/CHANGELOG +51 -2
- data/README.md +10 -247
- data/ROADMAP +6 -2
- data/app.rb +16 -2
- data/assets/javascripts/dependencies/bootstrap.min.js +7 -1
- data/assets/javascripts/dependencies/codemirror-coffeescript.js +347 -0
- data/assets/javascripts/dependencies/codemirror-css.js +124 -0
- data/assets/javascripts/dependencies/codemirror-html.js +410 -0
- data/assets/javascripts/dependencies/codemirror-javascript.js +361 -0
- data/assets/javascripts/dependencies/codemirror-less.js +232 -0
- data/assets/javascripts/dependencies/codemirror-vim.js +500 -0
- data/assets/javascripts/dependencies/codemirror.js +3076 -0
- data/assets/javascripts/dependencies.coffee +0 -1
- data/assets/javascripts/luca-ui-base.coffee +10 -3
- data/assets/javascripts/luca-ui-bootstrap.js +1 -0
- data/assets/javascripts/luca-ui-development-tools.coffee +9 -0
- data/assets/javascripts/luca-ui.coffee +6 -1
- data/assets/javascripts/sandbox/application.coffee +51 -0
- data/assets/javascripts/sandbox/router.coffee +14 -0
- data/assets/javascripts/sandbox/templates/main.luca +33 -0
- data/assets/javascripts/sandbox/templates/sandbox/navigation.luca +1 -0
- data/assets/javascripts/sandbox/templates/sandbox.luca +1 -0
- data/assets/javascripts/sandbox/views/top_navigation.coffee +4 -0
- data/assets/javascripts/sandbox.coffee +2 -2
- data/assets/stylesheets/bootstrap.min.css +395 -297
- data/assets/stylesheets/codemirror-blackboard.css +25 -0
- data/assets/stylesheets/codemirror-monokai.css +33 -0
- data/assets/stylesheets/codemirror.css +126 -0
- data/assets/stylesheets/luca-ui-bootstrap.css +0 -1
- data/assets/stylesheets/luca-ui-development-tools.css +5 -0
- data/assets/stylesheets/sandbox/sandbox.scss +1 -3
- data/assets/stylesheets/themes/amelia-bootstrap.css +826 -0
- data/assets/stylesheets/themes/slate-bootstrap.css +797 -0
- data/assets/stylesheets/themes/superhero-bootstrap.css +830 -0
- data/lib/luca/code_browser.rb +55 -0
- data/lib/luca/rails/version.rb +1 -1
- data/lib/luca/rails.rb +1 -0
- data/spec/components/fields/checkbox_array_spec.coffee +46 -0
- data/spec/components/form_view_spec.coffee +10 -4
- data/spec/containers/card_view_spec.coffee +7 -0
- data/spec/core/collection_spec.coffee +58 -4
- data/spec/core/container_spec.coffee +6 -6
- data/spec/core/view_spec.coffee +93 -7
- data/spec/framework_spec.coffee +15 -12
- data/src/components/application.coffee +126 -18
- data/src/components/base_toolbar.coffee +2 -2
- data/src/components/collection_loader_view.coffee +1 -2
- data/src/components/collection_view.coffee +77 -0
- data/src/components/controller.coffee +1 -4
- data/src/components/fields/button_field.coffee +1 -1
- data/src/components/fields/checkbox_array.coffee +2 -2
- data/src/components/fields/checkbox_field.coffee +3 -1
- data/src/components/fields/file_upload_field.coffee +1 -1
- data/src/components/fields/hidden_field.coffee +1 -1
- data/src/components/fields/select_field.coffee +1 -1
- data/src/components/fields/text_area_field.coffee +1 -1
- data/src/components/fields/text_field.coffee +10 -6
- data/src/components/fields/type_ahead_field.coffee +18 -5
- data/src/components/form_button_toolbar.coffee +1 -2
- data/src/components/form_view.coffee +44 -62
- data/src/components/grid_view.coffee +27 -20
- data/src/components/load_mask.coffee +3 -0
- data/src/components/nav_bar.coffee +26 -0
- data/src/components/record_manager.coffee +1 -3
- data/src/components/router.coffee +1 -1
- data/src/components/template.coffee +3 -15
- data/src/components/toolbar_dialog.coffee +25 -0
- data/src/containers/card_view.coffee +22 -23
- data/src/containers/column_view.coffee +1 -6
- data/src/containers/modal_view.coffee +20 -71
- data/src/containers/panel_toolbar.coffee +156 -0
- data/src/containers/panel_view.coffee +1 -1
- data/src/containers/split_view.coffee +1 -3
- data/src/containers/tab_view.coffee +29 -29
- data/src/containers/viewport.coffee +38 -3
- data/src/core/collection.coffee +80 -48
- data/src/core/container.coffee +153 -72
- data/src/core/core.coffee +181 -0
- data/src/core/field.coffee +4 -2
- data/src/core/model.coffee +1 -1
- data/src/core/observer.coffee +3 -3
- data/src/core/panel.coffee +143 -0
- data/src/core/registry.coffee +104 -0
- data/src/core/util.coffee +82 -0
- data/src/core/view.coffee +158 -85
- data/src/framework.coffee +112 -178
- data/src/index.coffee +0 -255
- data/src/managers/collection_manager.coffee +1 -0
- data/src/samples/definition.coffee +49 -0
- data/src/stylesheets/base.scss +0 -78
- data/src/stylesheets/components/form_view.scss +8 -3
- data/src/stylesheets/components/grid_view.scss +3 -7
- data/src/stylesheets/components/load_mask.scss +14 -0
- data/src/stylesheets/components/toolbar.scss +0 -15
- data/src/stylesheets/containers/container.scss +14 -2
- data/src/stylesheets/containers/panels.scss +23 -0
- data/src/stylesheets/tools/class_browser.scss +32 -0
- data/src/stylesheets/tools/code_editor.scss +24 -0
- data/src/stylesheets/tools/component_tester.scss +8 -0
- data/src/stylesheets/tools/console.scss +26 -0
- data/src/templates/components/collection_loader_view.luca +1 -1
- data/src/templates/components/form_view.luca +2 -13
- data/src/templates/components/grid_view.luca +0 -2
- data/src/templates/components/load_mask.luca +3 -0
- data/src/templates/components/nav_bar.luca +2 -0
- data/src/templates/containers/tab_view.luca +1 -0
- data/src/templates/fields/text_field.luca +4 -1
- data/src/tools/class_browser.coffee +39 -0
- data/src/tools/code_editor.coffee +258 -0
- data/src/tools/code_mirror_field.coffee +57 -0
- data/src/tools/coffee_script_editor.coffee +60 -0
- data/src/tools/collection_inspector.coffee +4 -0
- data/src/tools/component_tester.coffee +472 -0
- data/src/tools/components/class_browser_detail.coffee +10 -0
- data/src/tools/components/class_browser_list.coffee +74 -0
- data/src/tools/console.coffee +147 -0
- data/src/tools/development_console.coffee +147 -0
- data/src/tools/models/components.coffee +63 -0
- data/src/tools/templates/component_tester/help.luca +14 -0
- data/vendor/assets/javascripts/luca-ui-base.js +1389 -611
- data/vendor/assets/javascripts/luca-ui-bootstrap.js +9 -0
- data/vendor/assets/javascripts/luca-ui-development-tools.js +18719 -0
- data/vendor/assets/javascripts/luca-ui-spec.js +2065 -878
- data/vendor/assets/javascripts/luca-ui.js +1759 -852
- data/vendor/assets/javascripts/luca-ui.min.js +3 -3
- data/vendor/assets/stylesheets/luca-ui-bootstrap.css +494 -440
- data/vendor/assets/stylesheets/luca-ui-development-tools.css +224 -0
- data/vendor/assets/stylesheets/luca-ui-spec.css +99 -140
- data/vendor/assets/stylesheets/luca-ui.css +99 -140
- data/views/index.erb +6 -3
- metadata +60 -18
- data/assets/javascripts/dependencies/jquery-console.js +0 -649
- data/assets/javascripts/development-console.coffee +0 -2
- data/assets/javascripts/sandbox/sandbox.coffee +0 -16
- data/assets/javascripts/sandbox/templates/features/collection_helpers.luca +0 -33
- data/assets/javascripts/sandbox/templates/features/form_demo_code.luca +0 -48
- data/assets/javascripts/sandbox/templates/features/grid_demo_code.luca +0 -24
- data/assets/javascripts/sandbox/templates/features/introduction.luca +0 -11
- data/assets/javascripts/sandbox/templates/features/view_helpers.luca +0 -43
- data/assets/javascripts/sandbox/templates/navigation.luca +0 -8
- data/assets/javascripts/sandbox/views/form_demo.coffee +0 -47
- data/assets/javascripts/sandbox/views/grid_demo.coffee +0 -23
- data/assets/javascripts/sandbox/views/pages/collection_events_sample.coffee +0 -1
- data/assets/javascripts/sandbox/views/pages/pages_controller.coffee +0 -38
- data/src/components/collection_inspector.coffee +0 -2
- data/src/components/development_console.coffee +0 -59
- data/src/stylesheets/components/development_console.scss +0 -47
@@ -0,0 +1,347 @@
|
|
1
|
+
/**
|
2
|
+
* Link to the project's GitHub page:
|
3
|
+
* https://github.com/pickhardt/coffeescript-codemirror-mode
|
4
|
+
*/
|
5
|
+
CodeMirror.defineMode('coffeescript', function(conf) {
|
6
|
+
var ERRORCLASS = 'error';
|
7
|
+
|
8
|
+
function wordRegexp(words) {
|
9
|
+
return new RegExp("^((" + words.join(")|(") + "))\\b");
|
10
|
+
}
|
11
|
+
|
12
|
+
var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!\?]");
|
13
|
+
var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
|
14
|
+
var doubleOperators = new RegExp("^((\->)|(\=>)|(\\+\\+)|(\\+\\=)|(\\-\\-)|(\\-\\=)|(\\*\\*)|(\\*\\=)|(\\/\\/)|(\\/\\=)|(==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//))");
|
15
|
+
var doubleDelimiters = new RegExp("^((\\.\\.)|(\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
|
16
|
+
var tripleDelimiters = new RegExp("^((\\.\\.\\.)|(//=)|(>>=)|(<<=)|(\\*\\*=))");
|
17
|
+
var identifiers = new RegExp("^[_A-Za-z$][_A-Za-z$0-9]*");
|
18
|
+
|
19
|
+
var wordOperators = wordRegexp(['and', 'or', 'not',
|
20
|
+
'is', 'isnt', 'in',
|
21
|
+
'instanceof', 'typeof']);
|
22
|
+
var indentKeywords = ['for', 'while', 'loop', 'if', 'unless', 'else',
|
23
|
+
'switch', 'try', 'catch', 'finally', 'class'];
|
24
|
+
var commonKeywords = ['break', 'by', 'continue', 'debugger', 'delete',
|
25
|
+
'do', 'in', 'of', 'new', 'return', 'then',
|
26
|
+
'this', 'throw', 'when', 'until'];
|
27
|
+
|
28
|
+
var keywords = wordRegexp(indentKeywords.concat(commonKeywords));
|
29
|
+
|
30
|
+
indentKeywords = wordRegexp(indentKeywords);
|
31
|
+
|
32
|
+
|
33
|
+
var stringPrefixes = new RegExp("^('{3}|\"{3}|['\"])");
|
34
|
+
var regexPrefixes = new RegExp("^(/{3}|/)");
|
35
|
+
var commonConstants = ['Infinity', 'NaN', 'undefined', 'null', 'true', 'false', 'on', 'off', 'yes', 'no'];
|
36
|
+
var constants = wordRegexp(commonConstants);
|
37
|
+
|
38
|
+
// Tokenizers
|
39
|
+
function tokenBase(stream, state) {
|
40
|
+
// Handle scope changes
|
41
|
+
if (stream.sol()) {
|
42
|
+
var scopeOffset = state.scopes[0].offset;
|
43
|
+
if (stream.eatSpace()) {
|
44
|
+
var lineOffset = stream.indentation();
|
45
|
+
if (lineOffset > scopeOffset) {
|
46
|
+
return 'indent';
|
47
|
+
} else if (lineOffset < scopeOffset) {
|
48
|
+
return 'dedent';
|
49
|
+
}
|
50
|
+
return null;
|
51
|
+
} else {
|
52
|
+
if (scopeOffset > 0) {
|
53
|
+
dedent(stream, state);
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
if (stream.eatSpace()) {
|
58
|
+
return null;
|
59
|
+
}
|
60
|
+
|
61
|
+
var ch = stream.peek();
|
62
|
+
|
63
|
+
// Handle docco title comment (single line)
|
64
|
+
if (stream.match("####")) {
|
65
|
+
stream.skipToEnd();
|
66
|
+
return 'comment';
|
67
|
+
}
|
68
|
+
|
69
|
+
// Handle multi line comments
|
70
|
+
if (stream.match("###")) {
|
71
|
+
state.tokenize = longComment;
|
72
|
+
return state.tokenize(stream, state);
|
73
|
+
}
|
74
|
+
|
75
|
+
// Single line comment
|
76
|
+
if (ch === '#') {
|
77
|
+
stream.skipToEnd();
|
78
|
+
return 'comment';
|
79
|
+
}
|
80
|
+
|
81
|
+
// Handle number literals
|
82
|
+
if (stream.match(/^-?[0-9\.]/, false)) {
|
83
|
+
var floatLiteral = false;
|
84
|
+
// Floats
|
85
|
+
if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) {
|
86
|
+
floatLiteral = true;
|
87
|
+
}
|
88
|
+
if (stream.match(/^-?\d+\.\d*/)) {
|
89
|
+
floatLiteral = true;
|
90
|
+
}
|
91
|
+
if (stream.match(/^-?\.\d+/)) {
|
92
|
+
floatLiteral = true;
|
93
|
+
}
|
94
|
+
|
95
|
+
if (floatLiteral) {
|
96
|
+
// prevent from getting extra . on 1..
|
97
|
+
if (stream.peek() == "."){
|
98
|
+
stream.backUp(1);
|
99
|
+
}
|
100
|
+
return 'number';
|
101
|
+
}
|
102
|
+
// Integers
|
103
|
+
var intLiteral = false;
|
104
|
+
// Hex
|
105
|
+
if (stream.match(/^-?0x[0-9a-f]+/i)) {
|
106
|
+
intLiteral = true;
|
107
|
+
}
|
108
|
+
// Decimal
|
109
|
+
if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) {
|
110
|
+
intLiteral = true;
|
111
|
+
}
|
112
|
+
// Zero by itself with no other piece of number.
|
113
|
+
if (stream.match(/^-?0(?![\dx])/i)) {
|
114
|
+
intLiteral = true;
|
115
|
+
}
|
116
|
+
if (intLiteral) {
|
117
|
+
return 'number';
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
// Handle strings
|
122
|
+
if (stream.match(stringPrefixes)) {
|
123
|
+
state.tokenize = tokenFactory(stream.current(), 'string');
|
124
|
+
return state.tokenize(stream, state);
|
125
|
+
}
|
126
|
+
// Handle regex literals
|
127
|
+
if (stream.match(regexPrefixes)) {
|
128
|
+
if (stream.current() != '/' || stream.match(/^.*\//, false)) { // prevent highlight of division
|
129
|
+
state.tokenize = tokenFactory(stream.current(), 'string-2');
|
130
|
+
return state.tokenize(stream, state);
|
131
|
+
} else {
|
132
|
+
stream.backUp(1);
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
// Handle operators and delimiters
|
137
|
+
if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
|
138
|
+
return 'punctuation';
|
139
|
+
}
|
140
|
+
if (stream.match(doubleOperators)
|
141
|
+
|| stream.match(singleOperators)
|
142
|
+
|| stream.match(wordOperators)) {
|
143
|
+
return 'operator';
|
144
|
+
}
|
145
|
+
if (stream.match(singleDelimiters)) {
|
146
|
+
return 'punctuation';
|
147
|
+
}
|
148
|
+
|
149
|
+
if (stream.match(constants)) {
|
150
|
+
return 'atom';
|
151
|
+
}
|
152
|
+
|
153
|
+
if (stream.match(keywords)) {
|
154
|
+
return 'keyword';
|
155
|
+
}
|
156
|
+
|
157
|
+
if (stream.match(identifiers)) {
|
158
|
+
return 'variable';
|
159
|
+
}
|
160
|
+
|
161
|
+
// Handle non-detected items
|
162
|
+
stream.next();
|
163
|
+
return ERRORCLASS;
|
164
|
+
}
|
165
|
+
|
166
|
+
function tokenFactory(delimiter, outclass) {
|
167
|
+
var singleline = delimiter.length == 1;
|
168
|
+
return function tokenString(stream, state) {
|
169
|
+
while (!stream.eol()) {
|
170
|
+
stream.eatWhile(/[^'"\/\\]/);
|
171
|
+
if (stream.eat('\\')) {
|
172
|
+
stream.next();
|
173
|
+
if (singleline && stream.eol()) {
|
174
|
+
return outclass;
|
175
|
+
}
|
176
|
+
} else if (stream.match(delimiter)) {
|
177
|
+
state.tokenize = tokenBase;
|
178
|
+
return outclass;
|
179
|
+
} else {
|
180
|
+
stream.eat(/['"\/]/);
|
181
|
+
}
|
182
|
+
}
|
183
|
+
if (singleline) {
|
184
|
+
if (conf.mode.singleLineStringErrors) {
|
185
|
+
outclass = ERRORCLASS
|
186
|
+
} else {
|
187
|
+
state.tokenize = tokenBase;
|
188
|
+
}
|
189
|
+
}
|
190
|
+
return outclass;
|
191
|
+
};
|
192
|
+
}
|
193
|
+
|
194
|
+
function longComment(stream, state) {
|
195
|
+
while (!stream.eol()) {
|
196
|
+
stream.eatWhile(/[^#]/);
|
197
|
+
if (stream.match("###")) {
|
198
|
+
state.tokenize = tokenBase;
|
199
|
+
break;
|
200
|
+
}
|
201
|
+
stream.eatWhile("#");
|
202
|
+
}
|
203
|
+
return "comment"
|
204
|
+
}
|
205
|
+
|
206
|
+
function indent(stream, state, type) {
|
207
|
+
type = type || 'coffee';
|
208
|
+
var indentUnit = 0;
|
209
|
+
if (type === 'coffee') {
|
210
|
+
for (var i = 0; i < state.scopes.length; i++) {
|
211
|
+
if (state.scopes[i].type === 'coffee') {
|
212
|
+
indentUnit = state.scopes[i].offset + conf.indentUnit;
|
213
|
+
break;
|
214
|
+
}
|
215
|
+
}
|
216
|
+
} else {
|
217
|
+
indentUnit = stream.column() + stream.current().length;
|
218
|
+
}
|
219
|
+
state.scopes.unshift({
|
220
|
+
offset: indentUnit,
|
221
|
+
type: type
|
222
|
+
});
|
223
|
+
}
|
224
|
+
|
225
|
+
function dedent(stream, state) {
|
226
|
+
if (state.scopes.length == 1) return;
|
227
|
+
if (state.scopes[0].type === 'coffee') {
|
228
|
+
var _indent = stream.indentation();
|
229
|
+
var _indent_index = -1;
|
230
|
+
for (var i = 0; i < state.scopes.length; ++i) {
|
231
|
+
if (_indent === state.scopes[i].offset) {
|
232
|
+
_indent_index = i;
|
233
|
+
break;
|
234
|
+
}
|
235
|
+
}
|
236
|
+
if (_indent_index === -1) {
|
237
|
+
return true;
|
238
|
+
}
|
239
|
+
while (state.scopes[0].offset !== _indent) {
|
240
|
+
state.scopes.shift();
|
241
|
+
}
|
242
|
+
return false
|
243
|
+
} else {
|
244
|
+
state.scopes.shift();
|
245
|
+
return false;
|
246
|
+
}
|
247
|
+
}
|
248
|
+
|
249
|
+
function tokenLexer(stream, state) {
|
250
|
+
var style = state.tokenize(stream, state);
|
251
|
+
var current = stream.current();
|
252
|
+
|
253
|
+
// Handle '.' connected identifiers
|
254
|
+
if (current === '.') {
|
255
|
+
style = state.tokenize(stream, state);
|
256
|
+
current = stream.current();
|
257
|
+
if (style === 'variable') {
|
258
|
+
return 'variable';
|
259
|
+
} else {
|
260
|
+
return ERRORCLASS;
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
264
|
+
// Handle properties
|
265
|
+
if (current === '@') {
|
266
|
+
stream.eat('@');
|
267
|
+
return 'keyword';
|
268
|
+
}
|
269
|
+
|
270
|
+
// Handle scope changes.
|
271
|
+
if (current === 'return') {
|
272
|
+
state.dedent += 1;
|
273
|
+
}
|
274
|
+
if (((current === '->' || current === '=>') &&
|
275
|
+
!state.lambda &&
|
276
|
+
state.scopes[0].type == 'coffee' &&
|
277
|
+
stream.peek() === '')
|
278
|
+
|| style === 'indent') {
|
279
|
+
indent(stream, state);
|
280
|
+
}
|
281
|
+
var delimiter_index = '[({'.indexOf(current);
|
282
|
+
if (delimiter_index !== -1) {
|
283
|
+
indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1));
|
284
|
+
}
|
285
|
+
if (indentKeywords.exec(current)){
|
286
|
+
indent(stream, state);
|
287
|
+
}
|
288
|
+
if (current == 'then'){
|
289
|
+
dedent(stream, state);
|
290
|
+
}
|
291
|
+
|
292
|
+
|
293
|
+
if (style === 'dedent') {
|
294
|
+
if (dedent(stream, state)) {
|
295
|
+
return ERRORCLASS;
|
296
|
+
}
|
297
|
+
}
|
298
|
+
delimiter_index = '])}'.indexOf(current);
|
299
|
+
if (delimiter_index !== -1) {
|
300
|
+
if (dedent(stream, state)) {
|
301
|
+
return ERRORCLASS;
|
302
|
+
}
|
303
|
+
}
|
304
|
+
if (state.dedent > 0 && stream.eol() && state.scopes[0].type == 'coffee') {
|
305
|
+
if (state.scopes.length > 1) state.scopes.shift();
|
306
|
+
state.dedent -= 1;
|
307
|
+
}
|
308
|
+
|
309
|
+
return style;
|
310
|
+
}
|
311
|
+
|
312
|
+
var external = {
|
313
|
+
startState: function(basecolumn) {
|
314
|
+
return {
|
315
|
+
tokenize: tokenBase,
|
316
|
+
scopes: [{offset:basecolumn || 0, type:'coffee'}],
|
317
|
+
lastToken: null,
|
318
|
+
lambda: false,
|
319
|
+
dedent: 0
|
320
|
+
};
|
321
|
+
},
|
322
|
+
|
323
|
+
token: function(stream, state) {
|
324
|
+
var style = tokenLexer(stream, state);
|
325
|
+
|
326
|
+
state.lastToken = {style:style, content: stream.current()};
|
327
|
+
|
328
|
+
if (stream.eol() && stream.lambda) {
|
329
|
+
state.lambda = false;
|
330
|
+
}
|
331
|
+
|
332
|
+
return style;
|
333
|
+
},
|
334
|
+
|
335
|
+
indent: function(state, textAfter) {
|
336
|
+
if (state.tokenize != tokenBase) {
|
337
|
+
return 0;
|
338
|
+
}
|
339
|
+
|
340
|
+
return state.scopes[0].offset;
|
341
|
+
}
|
342
|
+
|
343
|
+
};
|
344
|
+
return external;
|
345
|
+
});
|
346
|
+
|
347
|
+
CodeMirror.defineMIME('text/x-coffeescript', 'coffeescript');
|
@@ -0,0 +1,124 @@
|
|
1
|
+
CodeMirror.defineMode("css", function(config) {
|
2
|
+
var indentUnit = config.indentUnit, type;
|
3
|
+
function ret(style, tp) {type = tp; return style;}
|
4
|
+
|
5
|
+
function tokenBase(stream, state) {
|
6
|
+
var ch = stream.next();
|
7
|
+
if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("meta", stream.current());}
|
8
|
+
else if (ch == "/" && stream.eat("*")) {
|
9
|
+
state.tokenize = tokenCComment;
|
10
|
+
return tokenCComment(stream, state);
|
11
|
+
}
|
12
|
+
else if (ch == "<" && stream.eat("!")) {
|
13
|
+
state.tokenize = tokenSGMLComment;
|
14
|
+
return tokenSGMLComment(stream, state);
|
15
|
+
}
|
16
|
+
else if (ch == "=") ret(null, "compare");
|
17
|
+
else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare");
|
18
|
+
else if (ch == "\"" || ch == "'") {
|
19
|
+
state.tokenize = tokenString(ch);
|
20
|
+
return state.tokenize(stream, state);
|
21
|
+
}
|
22
|
+
else if (ch == "#") {
|
23
|
+
stream.eatWhile(/[\w\\\-]/);
|
24
|
+
return ret("atom", "hash");
|
25
|
+
}
|
26
|
+
else if (ch == "!") {
|
27
|
+
stream.match(/^\s*\w*/);
|
28
|
+
return ret("keyword", "important");
|
29
|
+
}
|
30
|
+
else if (/\d/.test(ch)) {
|
31
|
+
stream.eatWhile(/[\w.%]/);
|
32
|
+
return ret("number", "unit");
|
33
|
+
}
|
34
|
+
else if (/[,.+>*\/]/.test(ch)) {
|
35
|
+
return ret(null, "select-op");
|
36
|
+
}
|
37
|
+
else if (/[;{}:\[\]]/.test(ch)) {
|
38
|
+
return ret(null, ch);
|
39
|
+
}
|
40
|
+
else {
|
41
|
+
stream.eatWhile(/[\w\\\-]/);
|
42
|
+
return ret("variable", "variable");
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
function tokenCComment(stream, state) {
|
47
|
+
var maybeEnd = false, ch;
|
48
|
+
while ((ch = stream.next()) != null) {
|
49
|
+
if (maybeEnd && ch == "/") {
|
50
|
+
state.tokenize = tokenBase;
|
51
|
+
break;
|
52
|
+
}
|
53
|
+
maybeEnd = (ch == "*");
|
54
|
+
}
|
55
|
+
return ret("comment", "comment");
|
56
|
+
}
|
57
|
+
|
58
|
+
function tokenSGMLComment(stream, state) {
|
59
|
+
var dashes = 0, ch;
|
60
|
+
while ((ch = stream.next()) != null) {
|
61
|
+
if (dashes >= 2 && ch == ">") {
|
62
|
+
state.tokenize = tokenBase;
|
63
|
+
break;
|
64
|
+
}
|
65
|
+
dashes = (ch == "-") ? dashes + 1 : 0;
|
66
|
+
}
|
67
|
+
return ret("comment", "comment");
|
68
|
+
}
|
69
|
+
|
70
|
+
function tokenString(quote) {
|
71
|
+
return function(stream, state) {
|
72
|
+
var escaped = false, ch;
|
73
|
+
while ((ch = stream.next()) != null) {
|
74
|
+
if (ch == quote && !escaped)
|
75
|
+
break;
|
76
|
+
escaped = !escaped && ch == "\\";
|
77
|
+
}
|
78
|
+
if (!escaped) state.tokenize = tokenBase;
|
79
|
+
return ret("string", "string");
|
80
|
+
};
|
81
|
+
}
|
82
|
+
|
83
|
+
return {
|
84
|
+
startState: function(base) {
|
85
|
+
return {tokenize: tokenBase,
|
86
|
+
baseIndent: base || 0,
|
87
|
+
stack: []};
|
88
|
+
},
|
89
|
+
|
90
|
+
token: function(stream, state) {
|
91
|
+
if (stream.eatSpace()) return null;
|
92
|
+
var style = state.tokenize(stream, state);
|
93
|
+
|
94
|
+
var context = state.stack[state.stack.length-1];
|
95
|
+
if (type == "hash" && context != "rule") style = "string-2";
|
96
|
+
else if (style == "variable") {
|
97
|
+
if (context == "rule") style = "number";
|
98
|
+
else if (!context || context == "@media{") style = "tag";
|
99
|
+
}
|
100
|
+
|
101
|
+
if (context == "rule" && /^[\{\};]$/.test(type))
|
102
|
+
state.stack.pop();
|
103
|
+
if (type == "{") {
|
104
|
+
if (context == "@media") state.stack[state.stack.length-1] = "@media{";
|
105
|
+
else state.stack.push("{");
|
106
|
+
}
|
107
|
+
else if (type == "}") state.stack.pop();
|
108
|
+
else if (type == "@media") state.stack.push("@media");
|
109
|
+
else if (context == "{" && type != "comment") state.stack.push("rule");
|
110
|
+
return style;
|
111
|
+
},
|
112
|
+
|
113
|
+
indent: function(state, textAfter) {
|
114
|
+
var n = state.stack.length;
|
115
|
+
if (/^\}/.test(textAfter))
|
116
|
+
n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1;
|
117
|
+
return state.baseIndent + n * indentUnit;
|
118
|
+
},
|
119
|
+
|
120
|
+
electricChars: "}"
|
121
|
+
};
|
122
|
+
});
|
123
|
+
|
124
|
+
CodeMirror.defineMIME("text/css", "css");
|