mumuki-laboratory 5.0.1 → 5.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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");