mumuki-laboratory 5.0.1 → 5.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mumuki/laboratory/version.rb +1 -1
  3. data/vendor/assets/javascripts/analytics.js +4 -0
  4. data/vendor/assets/javascripts/codemirror-modes/assembly_x86.js +967 -0
  5. data/vendor/assets/javascripts/codemirror-modes/autocomplete.js +44 -0
  6. data/vendor/assets/javascripts/codemirror-modes/clike.min.js +1 -0
  7. data/vendor/assets/javascripts/codemirror-modes/closebrackets.min.js +1 -0
  8. data/vendor/assets/javascripts/codemirror-modes/css-hint.min.js +1 -0
  9. data/vendor/assets/javascripts/codemirror-modes/css.min.js +1 -0
  10. data/vendor/assets/javascripts/codemirror-modes/elixir.js +1284 -0
  11. data/vendor/assets/javascripts/codemirror-modes/gobstones-autocomplete.js +4 -0
  12. data/vendor/assets/javascripts/codemirror-modes/gobstones.js +1046 -0
  13. data/vendor/assets/javascripts/codemirror-modes/haskell-autocomplete.js +1 -0
  14. data/vendor/assets/javascripts/codemirror-modes/haskell.min.js +1 -0
  15. data/vendor/assets/javascripts/codemirror-modes/html-hint.min.js +1 -0
  16. data/vendor/assets/javascripts/codemirror-modes/htmlmixed.min.js +1 -0
  17. data/vendor/assets/javascripts/codemirror-modes/javascript-hint.min.js +1 -0
  18. data/vendor/assets/javascripts/codemirror-modes/javascript.min.js +1 -0
  19. data/vendor/assets/javascripts/codemirror-modes/markdown.min.js +1 -0
  20. data/vendor/assets/javascripts/codemirror-modes/matchbrackets.min.js +1 -0
  21. data/vendor/assets/javascripts/codemirror-modes/placeholder.min.js +1 -0
  22. data/vendor/assets/javascripts/codemirror-modes/prolog-autocomplete.js +1 -0
  23. data/vendor/assets/javascripts/codemirror-modes/prolog.js +1089 -0
  24. data/vendor/assets/javascripts/codemirror-modes/python.min.js +1 -0
  25. data/vendor/assets/javascripts/codemirror-modes/ruby-autocomplete.js +3 -0
  26. data/vendor/assets/javascripts/codemirror-modes/ruby.min.js +1 -0
  27. data/vendor/assets/javascripts/codemirror-modes/shell.min.js +1 -0
  28. data/vendor/assets/javascripts/codemirror-modes/show-hint.min.js +1 -0
  29. data/vendor/assets/javascripts/codemirror-modes/sql-hint.min.js +1 -0
  30. data/vendor/assets/javascripts/codemirror-modes/sql.min.js +1 -0
  31. data/vendor/assets/javascripts/codemirror-modes/wollok-autocomplete.js +3 -0
  32. data/vendor/assets/javascripts/codemirror-modes/wollok.js +1035 -0
  33. data/vendor/assets/javascripts/codemirror-modes/xml-hint.min.js +1 -0
  34. data/vendor/assets/javascripts/codemirror-modes/xml.min.js +1 -0
  35. data/vendor/assets/javascripts/codemirror.min.js +1 -0
  36. data/vendor/assets/javascripts/hotjar.js +8 -0
  37. data/vendor/assets/javascripts/jquery-console.js +845 -0
  38. data/vendor/assets/javascripts/webcomponents-lite.js +12 -0
  39. data/vendor/assets/stylesheets/codemirror/codemirror.min.css +2 -0
  40. data/vendor/assets/stylesheets/codemirror/show-hint.min.css +2 -0
  41. metadata +39 -1
@@ -0,0 +1,4 @@
1
+ registerAutocomplete('gobstones', (
2
+ 'program procedure function if else switch repeat while not return ' +
3
+ 'False True Poner Colocar Sacar Retirar Mover Verde Rojo Vermelho Azul Negro Preto Norte Sur Sul Este Leste Oeste'
4
+ ).split(' '));
@@ -0,0 +1,1046 @@
1
+ // Parts from Ace; see <https://raw.githubusercontent.com/ajaxorg/ace/master/LICENSE>
2
+ CodeMirror.defineMode("gobstones", function(cmCfg, modeCfg) {
3
+
4
+ // Fake define() function.
5
+ var moduleHolder = Object.create(null);
6
+
7
+ // Given a module path as a string, create the canonical version
8
+ // (no leading ./, no ending .js).
9
+ var canonicalPath = function(path) {
10
+ return path.replace(/\.\//, '').replace(/\.js$/, '');
11
+ };
12
+
13
+ // We intentionally add the `path` argument to `define()`.
14
+ var define = function(path, init) {
15
+ var exports = Object.create(null);
16
+ init(require, exports); // module (3rd parameter) isn't supported.
17
+ moduleHolder[canonicalPath(path)] = exports;
18
+ };
19
+
20
+ // path: string of the location of the JS file.
21
+ var require = function(path) { return moduleHolder[canonicalPath(path)]; };
22
+
23
+ // All dependencies here.
24
+ define("../lib/oop.js", function(require, exports, module) {
25
+ "use strict";
26
+
27
+ exports.inherits = function(ctor, superCtor) {
28
+ ctor.super_ = superCtor;
29
+ ctor.prototype = Object.create(superCtor.prototype, {
30
+ constructor: {
31
+ value: ctor,
32
+ enumerable: false,
33
+ writable: true,
34
+ configurable: true
35
+ }
36
+ });
37
+ };
38
+
39
+ exports.mixin = function(obj, mixin) {
40
+ for (var key in mixin) {
41
+ obj[key] = mixin[key];
42
+ }
43
+ return obj;
44
+ };
45
+
46
+ exports.implement = function(proto, mixin) {
47
+ exports.mixin(proto, mixin);
48
+ };
49
+
50
+ });
51
+
52
+
53
+ define("../lib/lang.js", function(require, exports, module) {
54
+ "use strict";
55
+
56
+ exports.last = function(a) {
57
+ return a[a.length - 1];
58
+ };
59
+
60
+ exports.stringReverse = function(string) {
61
+ return string.split("").reverse().join("");
62
+ };
63
+
64
+ exports.stringRepeat = function (string, count) {
65
+ var result = '';
66
+ while (count > 0) {
67
+ if (count & 1)
68
+ result += string;
69
+
70
+ if (count >>= 1)
71
+ string += string;
72
+ }
73
+ return result;
74
+ };
75
+
76
+ var trimBeginRegexp = /^\s\s*/;
77
+ var trimEndRegexp = /\s\s*$/;
78
+
79
+ exports.stringTrimLeft = function (string) {
80
+ return string.replace(trimBeginRegexp, '');
81
+ };
82
+
83
+ exports.stringTrimRight = function (string) {
84
+ return string.replace(trimEndRegexp, '');
85
+ };
86
+
87
+ exports.copyObject = function(obj) {
88
+ var copy = {};
89
+ for (var key in obj) {
90
+ copy[key] = obj[key];
91
+ }
92
+ return copy;
93
+ };
94
+
95
+ exports.copyArray = function(array){
96
+ var copy = [];
97
+ for (var i=0, l=array.length; i<l; i++) {
98
+ if (array[i] && typeof array[i] == "object")
99
+ copy[i] = this.copyObject(array[i]);
100
+ else
101
+ copy[i] = array[i];
102
+ }
103
+ return copy;
104
+ };
105
+
106
+ exports.deepCopy = function deepCopy(obj) {
107
+ if (typeof obj !== "object" || !obj)
108
+ return obj;
109
+ var copy;
110
+ if (Array.isArray(obj)) {
111
+ copy = [];
112
+ for (var key = 0; key < obj.length; key++) {
113
+ copy[key] = deepCopy(obj[key]);
114
+ }
115
+ return copy;
116
+ }
117
+ if (Object.prototype.toString.call(obj) !== "[object Object]")
118
+ return obj;
119
+
120
+ copy = {};
121
+ for (var key in obj)
122
+ copy[key] = deepCopy(obj[key]);
123
+ return copy;
124
+ };
125
+
126
+ exports.arrayToMap = function(arr) {
127
+ var map = {};
128
+ for (var i=0; i<arr.length; i++) {
129
+ map[arr[i]] = 1;
130
+ }
131
+ return map;
132
+
133
+ };
134
+
135
+ exports.createMap = function(props) {
136
+ var map = Object.create(null);
137
+ for (var i in props) {
138
+ map[i] = props[i];
139
+ }
140
+ return map;
141
+ };
142
+
143
+ /*
144
+ * splice out of 'array' anything that === 'value'
145
+ */
146
+ exports.arrayRemove = function(array, value) {
147
+ for (var i = 0; i <= array.length; i++) {
148
+ if (value === array[i]) {
149
+ array.splice(i, 1);
150
+ }
151
+ }
152
+ };
153
+
154
+ exports.escapeRegExp = function(str) {
155
+ return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
156
+ };
157
+
158
+ exports.escapeHTML = function(str) {
159
+ return str.replace(/&/g, "&#38;").replace(/"/g, "&#34;").replace(/'/g, "&#39;").replace(/</g, "&#60;");
160
+ };
161
+
162
+ exports.getMatchOffsets = function(string, regExp) {
163
+ var matches = [];
164
+
165
+ string.replace(regExp, function(str) {
166
+ matches.push({
167
+ offset: arguments[arguments.length-2],
168
+ length: str.length
169
+ });
170
+ });
171
+
172
+ return matches;
173
+ };
174
+
175
+ /* deprecated */
176
+ exports.deferredCall = function(fcn) {
177
+ var timer = null;
178
+ var callback = function() {
179
+ timer = null;
180
+ fcn();
181
+ };
182
+
183
+ var deferred = function(timeout) {
184
+ deferred.cancel();
185
+ timer = setTimeout(callback, timeout || 0);
186
+ return deferred;
187
+ };
188
+
189
+ deferred.schedule = deferred;
190
+
191
+ deferred.call = function() {
192
+ this.cancel();
193
+ fcn();
194
+ return deferred;
195
+ };
196
+
197
+ deferred.cancel = function() {
198
+ clearTimeout(timer);
199
+ timer = null;
200
+ return deferred;
201
+ };
202
+
203
+ deferred.isPending = function() {
204
+ return timer;
205
+ };
206
+
207
+ return deferred;
208
+ };
209
+
210
+
211
+ exports.delayedCall = function(fcn, defaultTimeout) {
212
+ var timer = null;
213
+ var callback = function() {
214
+ timer = null;
215
+ fcn();
216
+ };
217
+
218
+ var _self = function(timeout) {
219
+ if (timer == null)
220
+ timer = setTimeout(callback, timeout || defaultTimeout);
221
+ };
222
+
223
+ _self.delay = function(timeout) {
224
+ timer && clearTimeout(timer);
225
+ timer = setTimeout(callback, timeout || defaultTimeout);
226
+ };
227
+ _self.schedule = _self;
228
+
229
+ _self.call = function() {
230
+ this.cancel();
231
+ fcn();
232
+ };
233
+
234
+ _self.cancel = function() {
235
+ timer && clearTimeout(timer);
236
+ timer = null;
237
+ };
238
+
239
+ _self.isPending = function() {
240
+ return timer;
241
+ };
242
+
243
+ return _self;
244
+ };
245
+ });
246
+
247
+
248
+ define("./text_highlight_rules.js", function(require, exports, module) {
249
+ "use strict";
250
+
251
+ var lang = require("../lib/lang");
252
+
253
+ var TextHighlightRules = function() {
254
+
255
+ // regexp must not have capturing parentheses
256
+ // regexps are ordered -> the first match is used
257
+
258
+ this.$rules = {
259
+ "start" : [{
260
+ token : "empty_line",
261
+ regex : '^$'
262
+ }, {
263
+ defaultToken : "text"
264
+ }]
265
+ };
266
+ };
267
+
268
+ (function() {
269
+
270
+ this.addRules = function(rules, prefix) {
271
+ if (!prefix) {
272
+ for (var key in rules)
273
+ this.$rules[key] = rules[key];
274
+ return;
275
+ }
276
+ for (var key in rules) {
277
+ var state = rules[key];
278
+ for (var i = 0; i < state.length; i++) {
279
+ var rule = state[i];
280
+ if (rule.next || rule.onMatch) {
281
+ if (typeof rule.next == "string") {
282
+ if (rule.next.indexOf(prefix) !== 0)
283
+ rule.next = prefix + rule.next;
284
+ }
285
+ if (rule.nextState && rule.nextState.indexOf(prefix) !== 0)
286
+ rule.nextState = prefix + rule.nextState;
287
+ }
288
+ }
289
+ this.$rules[prefix + key] = state;
290
+ }
291
+ };
292
+
293
+ this.getRules = function() {
294
+ return this.$rules;
295
+ };
296
+
297
+ this.embedRules = function (HighlightRules, prefix, escapeRules, states, append) {
298
+ var embedRules = typeof HighlightRules == "function"
299
+ ? new HighlightRules().getRules()
300
+ : HighlightRules;
301
+ if (states) {
302
+ for (var i = 0; i < states.length; i++)
303
+ states[i] = prefix + states[i];
304
+ } else {
305
+ states = [];
306
+ for (var key in embedRules)
307
+ states.push(prefix + key);
308
+ }
309
+
310
+ this.addRules(embedRules, prefix);
311
+
312
+ if (escapeRules) {
313
+ var addRules = Array.prototype[append ? "push" : "unshift"];
314
+ for (var i = 0; i < states.length; i++)
315
+ addRules.apply(this.$rules[states[i]], lang.deepCopy(escapeRules));
316
+ }
317
+
318
+ if (!this.$embeds)
319
+ this.$embeds = [];
320
+ this.$embeds.push(prefix);
321
+ };
322
+
323
+ this.getEmbeds = function() {
324
+ return this.$embeds;
325
+ };
326
+
327
+ var pushState = function(currentState, stack) {
328
+ if (currentState != "start" || stack.length)
329
+ stack.unshift(this.nextState, currentState);
330
+ return this.nextState;
331
+ };
332
+ var popState = function(currentState, stack) {
333
+ // if (stack[0] === currentState)
334
+ stack.shift();
335
+ return stack.shift() || "start";
336
+ };
337
+
338
+ this.normalizeRules = function() {
339
+ var id = 0;
340
+ var rules = this.$rules;
341
+ function processState(key) {
342
+ var state = rules[key];
343
+ state.processed = true;
344
+ for (var i = 0; i < state.length; i++) {
345
+ var rule = state[i];
346
+ var toInsert = null;
347
+ if (Array.isArray(rule)) {
348
+ toInsert = rule;
349
+ rule = {};
350
+ }
351
+ if (!rule.regex && rule.start) {
352
+ rule.regex = rule.start;
353
+ if (!rule.next)
354
+ rule.next = [];
355
+ rule.next.push({
356
+ defaultToken: rule.token
357
+ }, {
358
+ token: rule.token + ".end",
359
+ regex: rule.end || rule.start,
360
+ next: "pop"
361
+ });
362
+ rule.token = rule.token + ".start";
363
+ rule.push = true;
364
+ }
365
+ var next = rule.next || rule.push;
366
+ if (next && Array.isArray(next)) {
367
+ var stateName = rule.stateName;
368
+ if (!stateName) {
369
+ stateName = rule.token;
370
+ if (typeof stateName != "string")
371
+ stateName = stateName[0] || "";
372
+ if (rules[stateName])
373
+ stateName += id++;
374
+ }
375
+ rules[stateName] = next;
376
+ rule.next = stateName;
377
+ processState(stateName);
378
+ } else if (next == "pop") {
379
+ rule.next = popState;
380
+ }
381
+
382
+ if (rule.push) {
383
+ rule.nextState = rule.next || rule.push;
384
+ rule.next = pushState;
385
+ delete rule.push;
386
+ }
387
+
388
+ if (rule.rules) {
389
+ for (var r in rule.rules) {
390
+ if (rules[r]) {
391
+ if (rules[r].push)
392
+ rules[r].push.apply(rules[r], rule.rules[r]);
393
+ } else {
394
+ rules[r] = rule.rules[r];
395
+ }
396
+ }
397
+ }
398
+ var includeName = typeof rule == "string" ? rule : rule.include;
399
+ if (includeName) {
400
+ if (Array.isArray(includeName))
401
+ toInsert = includeName.map(function(x) { return rules[x]; });
402
+ else
403
+ toInsert = rules[includeName];
404
+ }
405
+
406
+ if (toInsert) {
407
+ var args = [i, 1].concat(toInsert);
408
+ if (rule.noEscape)
409
+ args = args.filter(function(x) {return !x.next;});
410
+ state.splice.apply(state, args);
411
+ // skip included rules since they are already processed
412
+ //i += args.length - 3;
413
+ i--;
414
+ }
415
+
416
+ if (rule.keywordMap) {
417
+ rule.token = this.createKeywordMapper(
418
+ rule.keywordMap, rule.defaultToken || "text", rule.caseInsensitive
419
+ );
420
+ delete rule.defaultToken;
421
+ }
422
+ }
423
+ }
424
+ Object.keys(rules).forEach(processState, this);
425
+ };
426
+
427
+ this.createKeywordMapper = function(map, defaultToken, ignoreCase, splitChar) {
428
+ var keywords = Object.create(null);
429
+ Object.keys(map).forEach(function(className) {
430
+ var a = map[className];
431
+ if (ignoreCase)
432
+ a = a.toLowerCase();
433
+ var list = a.split(splitChar || "|");
434
+ for (var i = list.length; i--; )
435
+ keywords[list[i]] = className;
436
+ });
437
+ // in old versions of opera keywords["__proto__"] sets prototype
438
+ // even on objects with __proto__=null
439
+ if (Object.getPrototypeOf(keywords)) {
440
+ keywords.__proto__ = null;
441
+ }
442
+ this.$keywordList = Object.keys(keywords);
443
+ map = null;
444
+ return ignoreCase
445
+ ? function(value) {return keywords[value.toLowerCase()] || defaultToken; }
446
+ : function(value) {return keywords[value] || defaultToken; };
447
+ };
448
+
449
+ this.getKeywords = function() {
450
+ return this.$keywords;
451
+ };
452
+
453
+ }).call(TextHighlightRules.prototype);
454
+
455
+ exports.TextHighlightRules = TextHighlightRules;
456
+ });
457
+
458
+
459
+ define("./doc_comment_highlight_rules.js", function(require, exports, module) {
460
+ "use strict";
461
+
462
+ var oop = require("../lib/oop");
463
+ var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
464
+
465
+ var DocCommentHighlightRules = function() {
466
+ this.$rules = {
467
+ "start" : [ {
468
+ token : "comment.doc.tag",
469
+ regex : "@[\\w\\d_]+" // TODO: fix email addresses
470
+ },
471
+ DocCommentHighlightRules.getTagRule(),
472
+ {
473
+ defaultToken : "comment.doc",
474
+ caseInsensitive: true
475
+ }]
476
+ };
477
+ };
478
+
479
+ oop.inherits(DocCommentHighlightRules, TextHighlightRules);
480
+
481
+ DocCommentHighlightRules.getTagRule = function(start) {
482
+ return {
483
+ token : "comment.doc.tag.storage.type",
484
+ regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
485
+ };
486
+ };
487
+
488
+ DocCommentHighlightRules.getStartRule = function(start) {
489
+ return {
490
+ token : "comment.doc", // doc comment
491
+ regex : "\\/\\*(?=\\*)",
492
+ next : start
493
+ };
494
+ };
495
+
496
+ DocCommentHighlightRules.getEndRule = function (start) {
497
+ return {
498
+ token : "comment.doc", // closing comment
499
+ regex : "\\*\\/",
500
+ next : start
501
+ };
502
+ };
503
+
504
+
505
+ exports.DocCommentHighlightRules = DocCommentHighlightRules;
506
+
507
+ });
508
+
509
+
510
+ define("gobstones_highlight_rules", function(require, exports, module) {
511
+ "use strict";
512
+
513
+ var oop = require("../lib/oop");
514
+ var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
515
+ var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
516
+
517
+ var GobstonesHighlightRules = function() {
518
+
519
+ var keywords = (
520
+ "program|procedure|function|interactive|if|then|else|switch|repeat|while|foreach|in|not|div|mod|Skip|return"
521
+ );
522
+
523
+ var buildinConstants = (
524
+ "Verde|Rojo|Vermelho|Azul|Negro|Preto|Norte|Sur|Sul|Este|Leste|Oeste|False|True"
525
+ );
526
+
527
+
528
+ var langClasses = (
529
+ "Poner|Colocar|Sacar|Retirar|Mover|IrAlBorde|IrABorda|VaciarTablero|" +
530
+ "nroBolitas|nroPedras|hayBolitas|haPedras|puedeMover|podeMover|siguiente|seguinte|previo|opuesto|oposto|minBool|maxBool|" +
531
+ "minDir|maxDir|minColor|minCor|maxColor|maxCor"
532
+ );
533
+
534
+ var keywordMapper = this.createKeywordMapper({
535
+ "keyword": keywords,
536
+ "constant.language": buildinConstants,
537
+ "support.function": langClasses,
538
+ "support.type": ''
539
+ }, "identifier");
540
+
541
+ // regexp must not have capturing parentheses. Use (?:) instead.
542
+ // regexps are ordered -> the first match is used
543
+
544
+ this.$rules = {
545
+ "start" : [
546
+ {
547
+ token : "comment",
548
+ regex : "\\/\\/.*$"
549
+ },
550
+ {
551
+ token : "comment",
552
+ regex : "\\-\\-.*$"
553
+ },
554
+ {
555
+ token : "comment",
556
+ regex : "#.*$"
557
+ },
558
+ DocCommentHighlightRules.getStartRule("doc-start"),
559
+ {
560
+ token : "comment", // multi line comment
561
+ regex : "\\/\\*",
562
+ next : "comment"
563
+ }, {
564
+
565
+ token : "string", // single line
566
+ regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
567
+ }, {
568
+ token : "string", // single line
569
+ regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
570
+ }, {
571
+ token : "constant.numeric", // hex
572
+ regex : /0(?:[xX][0-9a-fA-F][0-9a-fA-F_]*|[bB][01][01_]*)[LlSsDdFfYy]?\b/
573
+ }, {
574
+ token : "constant.numeric", // float
575
+ regex : /[+-]?\d[\d_]*(?:(?:\.[\d_]*)?(?:[eE][+-]?[\d_]+)?)?[LlSsDdFfYy]?\b/
576
+ }, {
577
+ token : "constant.language.boolean",
578
+ regex : "(?:True|False)\\b"
579
+ }, {
580
+ token : "keyword.operator",
581
+ regex : ":=|\\.\\.|,|;|\\|\\||\\/\\/|\\+|\\-|\\^|\\*|>|<|>=|=>|==|&&"
582
+ }, {
583
+ token : keywordMapper,
584
+ // TODO: Unicode escape sequences
585
+ // TODO: Unicode identifiers
586
+ regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
587
+ }, {
588
+ token : "lparen",
589
+ regex : "[[({]"
590
+ }, {
591
+ token : "rparen",
592
+ regex : "[\\])}]"
593
+ }, {
594
+ token : "text",
595
+ regex : "\\s+"
596
+ }
597
+ ],
598
+ "comment" : [
599
+ {
600
+ token : "comment", // closing comment
601
+ regex : "\\*\\/",
602
+ next : "start"
603
+ }, {
604
+ defaultToken : "comment"
605
+ }
606
+ ]
607
+ };
608
+
609
+ this.embedRules(DocCommentHighlightRules, "doc-",
610
+ [ DocCommentHighlightRules.getEndRule("start") ]);
611
+ };
612
+
613
+ oop.inherits(GobstonesHighlightRules, TextHighlightRules);
614
+
615
+ exports.GobstonesHighlightRules = GobstonesHighlightRules;
616
+ });
617
+
618
+
619
+
620
+ // Ace highlight rules function imported below.
621
+ var HighlightRules = require("gobstones_highlight_rules").GobstonesHighlightRules;
622
+
623
+
624
+
625
+ // Ace's Syntax Tokenizer.
626
+
627
+ // tokenizing lines longer than this makes editor very slow
628
+ var MAX_TOKEN_COUNT = 1000;
629
+ var Tokenizer = function(rules) {
630
+ this.states = rules;
631
+
632
+ this.regExps = {};
633
+ this.matchMappings = {};
634
+ for (var key in this.states) {
635
+ var state = this.states[key];
636
+ var ruleRegExps = [];
637
+ var matchTotal = 0;
638
+ var mapping = this.matchMappings[key] = {defaultToken: "text"};
639
+ var flag = "g";
640
+
641
+ var splitterRurles = [];
642
+ for (var i = 0; i < state.length; i++) {
643
+ var rule = state[i];
644
+ if (rule.defaultToken)
645
+ mapping.defaultToken = rule.defaultToken;
646
+ if (rule.caseInsensitive)
647
+ flag = "gi";
648
+ if (rule.regex == null)
649
+ continue;
650
+
651
+ if (rule.regex instanceof RegExp)
652
+ rule.regex = rule.regex.toString().slice(1, -1);
653
+
654
+ // Count number of matching groups. 2 extra groups from the full match
655
+ // And the catch-all on the end (used to force a match);
656
+ var adjustedregex = rule.regex;
657
+ var matchcount = new RegExp("(?:(" + adjustedregex + ")|(.))").exec("a").length - 2;
658
+ if (Array.isArray(rule.token)) {
659
+ if (rule.token.length == 1 || matchcount == 1) {
660
+ rule.token = rule.token[0];
661
+ } else if (matchcount - 1 != rule.token.length) {
662
+ throw new Error("number of classes and regexp groups in '" +
663
+ rule.token + "'\n'" + rule.regex + "' doesn't match\n"
664
+ + (matchcount - 1) + "!=" + rule.token.length);
665
+ } else {
666
+ rule.tokenArray = rule.token;
667
+ rule.token = null;
668
+ rule.onMatch = this.$arrayTokens;
669
+ }
670
+ } else if (typeof rule.token == "function" && !rule.onMatch) {
671
+ if (matchcount > 1)
672
+ rule.onMatch = this.$applyToken;
673
+ else
674
+ rule.onMatch = rule.token;
675
+ }
676
+
677
+ if (matchcount > 1) {
678
+ if (/\\\d/.test(rule.regex)) {
679
+ // Replace any backreferences and offset appropriately.
680
+ adjustedregex = rule.regex.replace(/\\([0-9]+)/g, function(match, digit) {
681
+ return "\\" + (parseInt(digit, 10) + matchTotal + 1);
682
+ });
683
+ } else {
684
+ matchcount = 1;
685
+ adjustedregex = this.removeCapturingGroups(rule.regex);
686
+ }
687
+ if (!rule.splitRegex && typeof rule.token != "string")
688
+ splitterRurles.push(rule); // flag will be known only at the very end
689
+ }
690
+
691
+ mapping[matchTotal] = i;
692
+ matchTotal += matchcount;
693
+
694
+ ruleRegExps.push(adjustedregex);
695
+
696
+ // makes property access faster
697
+ if (!rule.onMatch)
698
+ rule.onMatch = null;
699
+ }
700
+
701
+ splitterRurles.forEach(function(rule) {
702
+ rule.splitRegex = this.createSplitterRegexp(rule.regex, flag);
703
+ }, this);
704
+
705
+ this.regExps[key] = new RegExp("(" + ruleRegExps.join(")|(") + ")|($)", flag);
706
+ }
707
+ };
708
+
709
+ (function() {
710
+ this.$setMaxTokenCount = function(m) {
711
+ MAX_TOKEN_COUNT = m | 0;
712
+ };
713
+
714
+ this.$applyToken = function(str) {
715
+ var values = this.splitRegex.exec(str).slice(1);
716
+ var types = this.token.apply(this, values);
717
+
718
+ // required for compatibility with old modes
719
+ if (typeof types === "string")
720
+ return [{type: types, value: str}];
721
+
722
+ var tokens = [];
723
+ for (var i = 0, l = types.length; i < l; i++) {
724
+ if (values[i])
725
+ tokens[tokens.length] = {
726
+ type: types[i],
727
+ value: values[i]
728
+ };
729
+ }
730
+ return tokens;
731
+ },
732
+
733
+ this.$arrayTokens = function(str) {
734
+ if (!str)
735
+ return [];
736
+ var values = this.splitRegex.exec(str);
737
+ if (!values)
738
+ return "text";
739
+ var tokens = [];
740
+ var types = this.tokenArray;
741
+ for (var i = 0, l = types.length; i < l; i++) {
742
+ if (values[i + 1])
743
+ tokens[tokens.length] = {
744
+ type: types[i],
745
+ value: values[i + 1]
746
+ };
747
+ }
748
+ return tokens;
749
+ };
750
+
751
+ this.removeCapturingGroups = function(src) {
752
+ var r = src.replace(
753
+ /\[(?:\\.|[^\]])*?\]|\\.|\(\?[:=!]|(\()/g,
754
+ function(x, y) {return y ? "(?:" : x;}
755
+ );
756
+ return r;
757
+ };
758
+
759
+ this.createSplitterRegexp = function(src, flag) {
760
+ if (src.indexOf("(?=") != -1) {
761
+ var stack = 0;
762
+ var inChClass = false;
763
+ var lastCapture = {};
764
+ src.replace(/(\\.)|(\((?:\?[=!])?)|(\))|([\[\]])/g, function(
765
+ m, esc, parenOpen, parenClose, square, index
766
+ ) {
767
+ if (inChClass) {
768
+ inChClass = square != "]";
769
+ } else if (square) {
770
+ inChClass = true;
771
+ } else if (parenClose) {
772
+ if (stack == lastCapture.stack) {
773
+ lastCapture.end = index+1;
774
+ lastCapture.stack = -1;
775
+ }
776
+ stack--;
777
+ } else if (parenOpen) {
778
+ stack++;
779
+ if (parenOpen.length != 1) {
780
+ lastCapture.stack = stack
781
+ lastCapture.start = index;
782
+ }
783
+ }
784
+ return m;
785
+ });
786
+
787
+ if (lastCapture.end != null && /^\)*$/.test(src.substr(lastCapture.end)))
788
+ src = src.substring(0, lastCapture.start) + src.substr(lastCapture.end);
789
+ }
790
+ return new RegExp(src, (flag||"").replace("g", ""));
791
+ };
792
+
793
+ /**
794
+ * Returns an object containing two properties: `tokens`, which contains all the tokens; and `state`, the current state.
795
+ * @returns {Object}
796
+ **/
797
+ this.getLineTokens = function(line, startState) {
798
+ if (startState && typeof startState != "string") {
799
+ var stack = startState.slice(0);
800
+ startState = stack[0];
801
+ } else
802
+ var stack = [];
803
+
804
+ var currentState = startState || "start";
805
+ var state = this.states[currentState];
806
+ if (!state) {
807
+ currentState = "start";
808
+ state = this.states[currentState];
809
+ }
810
+ var mapping = this.matchMappings[currentState];
811
+ var re = this.regExps[currentState];
812
+ re.lastIndex = 0;
813
+
814
+ var match, tokens = [];
815
+ var lastIndex = 0;
816
+
817
+ var token = {type: null, value: ""};
818
+
819
+ while (match = re.exec(line)) {
820
+ var type = mapping.defaultToken;
821
+ var rule = null;
822
+ var value = match[0];
823
+ var index = re.lastIndex;
824
+
825
+ if (index - value.length > lastIndex) {
826
+ var skipped = line.substring(lastIndex, index - value.length);
827
+ if (token.type == type) {
828
+ token.value += skipped;
829
+ } else {
830
+ if (token.type)
831
+ tokens.push(token);
832
+ token = {type: type, value: skipped};
833
+ }
834
+ }
835
+
836
+ for (var i = 0; i < match.length-2; i++) {
837
+ if (match[i + 1] === undefined)
838
+ continue;
839
+
840
+ rule = state[mapping[i]];
841
+
842
+ if (rule.onMatch)
843
+ type = rule.onMatch(value, currentState, stack);
844
+ else
845
+ type = rule.token;
846
+
847
+ if (rule.next) {
848
+ if (typeof rule.next == "string")
849
+ currentState = rule.next;
850
+ else
851
+ currentState = rule.next(currentState, stack);
852
+
853
+ state = this.states[currentState];
854
+ if (!state) {
855
+ window.console && console.error && console.error(currentState, "doesn't exist");
856
+ currentState = "start";
857
+ state = this.states[currentState];
858
+ }
859
+ mapping = this.matchMappings[currentState];
860
+ lastIndex = index;
861
+ re = this.regExps[currentState];
862
+ re.lastIndex = index;
863
+ }
864
+ break;
865
+ }
866
+
867
+ if (value) {
868
+ if (typeof type == "string") {
869
+ if ((!rule || rule.merge !== false) && token.type === type) {
870
+ token.value += value;
871
+ } else {
872
+ if (token.type)
873
+ tokens.push(token);
874
+ token = {type: type, value: value};
875
+ }
876
+ } else if (type) {
877
+ if (token.type)
878
+ tokens.push(token);
879
+ token = {type: null, value: ""};
880
+ for (var i = 0; i < type.length; i++)
881
+ tokens.push(type[i]);
882
+ }
883
+ }
884
+
885
+ if (lastIndex == line.length)
886
+ break;
887
+
888
+ lastIndex = index;
889
+
890
+ if (tokens.length > MAX_TOKEN_COUNT) {
891
+ // chrome doens't show contents of text nodes with very long text
892
+ while (lastIndex < line.length) {
893
+ if (token.type)
894
+ tokens.push(token);
895
+ token = {
896
+ value: line.substring(lastIndex, lastIndex += 2000),
897
+ type: "overflow"
898
+ };
899
+ }
900
+ currentState = "start";
901
+ stack = [];
902
+ break;
903
+ }
904
+ }
905
+
906
+ if (token.type)
907
+ tokens.push(token);
908
+
909
+ if (stack.length > 1) {
910
+ if (stack[0] !== currentState)
911
+ stack.unshift(currentState);
912
+ }
913
+ return {
914
+ tokens : tokens,
915
+ state : stack.length ? stack : currentState
916
+ };
917
+ };
918
+
919
+ }).call(Tokenizer.prototype);
920
+
921
+ // Token conversion.
922
+ // See <https://github.com/ajaxorg/ace/wiki/Creating-or-Extending-an-Edit-Mode#common-tokens>
923
+ // This is not an exact match nor the best match that can be made.
924
+ var tokenFromAceToken = {
925
+ empty: null,
926
+ text: null,
927
+
928
+ // Keyword
929
+ keyword: 'keyword',
930
+ control: 'keyword',
931
+ operator: 'operator',
932
+
933
+ // Constants
934
+ constant: 'atom',
935
+ numeric: 'number',
936
+ character: 'atom',
937
+ escape: 'atom',
938
+
939
+ // Variables
940
+ variable: 'variable',
941
+ parameter: 'variable-3',
942
+ language: 'variable-2', // Python's `self` uses that.
943
+
944
+ // Comments
945
+ comment: 'comment',
946
+ line: 'comment',
947
+ 'double-slash': 'comment',
948
+ 'double-dash': 'comment',
949
+ 'number-sign': 'comment',
950
+ percentage: 'comment',
951
+ block: 'comment',
952
+ documentation: 'comment',
953
+
954
+ // String
955
+ string: 'string',
956
+ quoted: 'string',
957
+ single: 'string',
958
+ double: 'string',
959
+ triple: 'string',
960
+ unquoted: 'string',
961
+ interpolated: 'string',
962
+ regexp: 'string-2',
963
+
964
+ meta: 'meta',
965
+ literal: 'qualifier',
966
+ support: 'builtin',
967
+
968
+ // Markup
969
+ markup: 'tag',
970
+ underline: 'link',
971
+ link: 'link',
972
+ bold: 'strong',
973
+ heading: 'header',
974
+ italic: 'em',
975
+ list: 'variable-2',
976
+ numbered: 'variable-2',
977
+ unnumbered: 'variable-2',
978
+ quote: 'quote',
979
+ raw: 'variable-2', // Markdown's raw block uses that.
980
+
981
+ // Invalid
982
+ invalid: 'error',
983
+ illegal: 'invalidchar',
984
+ deprecated: 'error'
985
+ };
986
+
987
+ // Takes a list of Ace tokens, returns a (string) CodeMirror token.
988
+ var cmTokenFromAceTokens = function(tokens) {
989
+ var token = null;
990
+ for (var i = 0; i < tokens.length; i++) {
991
+ // Find the most specific token.
992
+ if (tokenFromAceToken[tokens[i]] !== undefined) {
993
+ token = tokenFromAceToken[tokens[i]];
994
+ }
995
+ }
996
+ return token;
997
+ };
998
+
999
+ // Consume a token from plannedTokens.
1000
+ var consumeToken = function(stream, state) {
1001
+ var plannedToken = state.plannedTokens.shift();
1002
+ if (plannedToken === undefined) {
1003
+ return null;
1004
+ }
1005
+ stream.match(plannedToken.value);
1006
+ var tokens = plannedToken.type.split('.');
1007
+ return cmTokenFromAceTokens(tokens);
1008
+ };
1009
+
1010
+ var matchToken = function(stream, state) {
1011
+ // Anormal start: we already have planned tokens to consume.
1012
+ if (state.plannedTokens.length > 0) {
1013
+ return consumeToken(stream, state);
1014
+ }
1015
+
1016
+ // Normal start.
1017
+ var currentState = state.current;
1018
+ var currentLine = stream.match(/.*$/, false)[0];
1019
+ var tokenized = tokenizer.getLineTokens(currentLine, currentState);
1020
+ // We got a {tokens, state} object.
1021
+ // Each token is a {value, type} object.
1022
+ state.plannedTokens = tokenized.tokens;
1023
+ state.current = tokenized.state;
1024
+
1025
+ // Consume a token.
1026
+ return consumeToken(stream, state);
1027
+ }
1028
+
1029
+ // Initialize all state.
1030
+ var aceHighlightRules = new HighlightRules();
1031
+ var tokenizer = new Tokenizer(aceHighlightRules.$rules);
1032
+
1033
+ return {
1034
+ startState: function() {
1035
+ return {
1036
+ current: 'start',
1037
+ // List of {value, type}, with type being an Ace token string.
1038
+ plannedTokens: []
1039
+ };
1040
+ },
1041
+ blankLine: function(state) { matchToken('', state); },
1042
+ token: matchToken
1043
+ };
1044
+ });
1045
+
1046
+ CodeMirror.defineMIME("text/x-gobstones", "gobstones");