codemirror-rails 2.21.1 → 2.22

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 (37) hide show
  1. data/README.md +8 -0
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +160 -86
  4. data/vendor/assets/javascripts/codemirror/modes/clike.js +2 -2
  5. data/vendor/assets/javascripts/codemirror/modes/clojure.js +1 -1
  6. data/vendor/assets/javascripts/codemirror/modes/ecl.js +203 -0
  7. data/vendor/assets/javascripts/codemirror/modes/gfm.js +1 -1
  8. data/vendor/assets/javascripts/codemirror/modes/go.js +20 -22
  9. data/vendor/assets/javascripts/codemirror/modes/less.js +5 -2
  10. data/vendor/assets/javascripts/codemirror/modes/markdown.js +58 -24
  11. data/vendor/assets/javascripts/codemirror/modes/pascal.js +2 -46
  12. data/vendor/assets/javascripts/codemirror/modes/perl.js +1 -1
  13. data/vendor/assets/javascripts/codemirror/modes/php.js +53 -24
  14. data/vendor/assets/javascripts/codemirror/modes/properties.js +57 -0
  15. data/vendor/assets/javascripts/codemirror/modes/rpm-spec.css +5 -0
  16. data/vendor/assets/javascripts/codemirror/modes/rpm-spec.js +1 -1
  17. data/vendor/assets/javascripts/codemirror/modes/ruby.js +1 -1
  18. data/vendor/assets/javascripts/codemirror/modes/smalltalk.js +16 -16
  19. data/vendor/assets/javascripts/codemirror/modes/verilog.js +194 -194
  20. data/vendor/assets/javascripts/codemirror/modes/xml.js +15 -8
  21. data/vendor/assets/javascripts/codemirror/utils/dialog.js +63 -0
  22. data/vendor/assets/javascripts/codemirror/utils/foldcode.js +186 -0
  23. data/vendor/assets/javascripts/codemirror/utils/formatting.js +294 -0
  24. data/vendor/assets/javascripts/codemirror/utils/javascript-hint.js +132 -0
  25. data/vendor/assets/javascripts/codemirror/utils/match-highlighter.js +44 -0
  26. data/vendor/assets/javascripts/codemirror/{overlay.js → utils/overlay.js} +0 -0
  27. data/vendor/assets/javascripts/codemirror/utils/runmode.js +49 -0
  28. data/vendor/assets/javascripts/codemirror/utils/search.js +114 -0
  29. data/vendor/assets/javascripts/codemirror/utils/searchcursor.js +117 -0
  30. data/vendor/assets/javascripts/codemirror/utils/simple-hint.js +66 -0
  31. data/vendor/assets/stylesheets/codemirror.css +3 -0
  32. data/vendor/assets/stylesheets/codemirror/modes/properties.css +3 -0
  33. data/vendor/assets/stylesheets/codemirror/themes/rubyblue.css +1 -1
  34. data/vendor/assets/stylesheets/codemirror/utils/dialog.css +23 -0
  35. data/vendor/assets/stylesheets/codemirror/utils/simple-hint.css +16 -0
  36. metadata +20 -6
  37. data/vendor/assets/javascripts/codemirror/runmode.js +0 -27
data/README.md CHANGED
@@ -35,6 +35,14 @@ Additional syntax modes can be added to your application.js:
35
35
  //= require codemirror/modes/ruby
36
36
  ```
37
37
 
38
+ ### Adding a util
39
+
40
+ Additional reusable util components can be added in your application.js:
41
+
42
+ ```js
43
+ //= require codemirror/utils/dialog
44
+ ```
45
+
38
46
  ### Adding a keymap
39
47
 
40
48
  Additional keymap bindings can be added to your application.js:
@@ -1,6 +1,6 @@
1
1
  module Codemirror
2
2
  module Rails
3
- VERSION = '2.21.1'
4
- CODEMIRROR_VERSION = '2.21'
3
+ VERSION = '2.22'
4
+ CODEMIRROR_VERSION = '2.22'
5
5
  end
6
6
  end
@@ -1,4 +1,4 @@
1
- // CodeMirror version 2.21
1
+ // CodeMirror version 2.22
2
2
  //
3
3
  // All functions that need access to the editor's state live inside
4
4
  // the CodeMirror function. Below that, at the bottom of the file,
@@ -6,7 +6,7 @@
6
6
 
7
7
  // CodeMirror is the only global var we claim
8
8
  var CodeMirror = (function() {
9
- // This is the function that produces an editor instance. It's
9
+ // This is the function that produces an editor instance. Its
10
10
  // closure is used to store the editor state.
11
11
  function CodeMirror(place, givenOptions) {
12
12
  // Determine effective options based on given values and defaults.
@@ -30,7 +30,7 @@ var CodeMirror = (function() {
30
30
  '<div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div>' +
31
31
  // Provides positioning relative to (visible) text origin
32
32
  '<div class="CodeMirror-lines"><div style="position: relative; z-index: 0">' +
33
- '<div style="position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden; outline: 5px auto none"></div>' +
33
+ '<div style="position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden;"></div>' +
34
34
  '<pre class="CodeMirror-cursor">&#160;</pre>' + // Absolutely positioned blinky cursor
35
35
  '<div style="position: relative; z-index: -1"></div><div></div>' + // DIVs containing the selection and the actual code
36
36
  '</div></div></div></div></div>';
@@ -86,7 +86,7 @@ var CodeMirror = (function() {
86
86
  var bracketHighlighted;
87
87
  // Tracks the maximum line length so that the horizontal scrollbar
88
88
  // can be kept static when scrolling.
89
- var maxLine = "", maxWidth, tabText = computeTabText();
89
+ var maxLine = "", maxWidth;
90
90
 
91
91
  // Initialize the content.
92
92
  operation(function(){setValue(options.value || ""); updateInput = false;})();
@@ -141,7 +141,7 @@ var CodeMirror = (function() {
141
141
  setValue: operation(setValue),
142
142
  getSelection: getSelection,
143
143
  replaceSelection: operation(replaceSelection),
144
- focus: function(){focusInput(); onFocus(); fastPoll();},
144
+ focus: function(){window.focus(); focusInput(); onFocus(); fastPoll();},
145
145
  setOption: function(option, value) {
146
146
  var oldVal = options[option];
147
147
  options[option] = value;
@@ -150,9 +150,11 @@ var CodeMirror = (function() {
150
150
  else if (option == "readOnly" && !value) {resetInput(true);}
151
151
  else if (option == "theme") themeChanged();
152
152
  else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
153
- else if (option == "tabSize") operation(tabsChanged)();
154
- if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme")
153
+ else if (option == "tabSize") updateDisplay(true);
154
+ if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme") {
155
+ gutterChanged();
155
156
  updateDisplay(true);
157
+ }
156
158
  },
157
159
  getOption: function(option) {return options[option];},
158
160
  undo: operation(undo),
@@ -259,7 +261,15 @@ var CodeMirror = (function() {
259
261
  moveH: operation(moveH),
260
262
  deleteH: operation(deleteH),
261
263
  moveV: operation(moveV),
262
- toggleOverwrite: function() {overwrite = !overwrite;},
264
+ toggleOverwrite: function() {
265
+ if(overwrite){
266
+ overwrite = false;
267
+ cursor.className = cursor.className.replace(" CodeMirror-overwrite", "");
268
+ } else {
269
+ overwrite = true;
270
+ cursor.className += " CodeMirror-overwrite";
271
+ }
272
+ },
263
273
 
264
274
  posFromIndex: function(off) {
265
275
  var lineNo = 0, ch;
@@ -280,8 +290,8 @@ var CodeMirror = (function() {
280
290
  return index;
281
291
  },
282
292
  scrollTo: function(x, y) {
283
- if (x != null) scroller.scrollTop = x;
284
- if (y != null) scroller.scrollLeft = y;
293
+ if (x != null) scroller.scrollLeft = x;
294
+ if (y != null) scroller.scrollTop = y;
285
295
  updateDisplay([]);
286
296
  },
287
297
 
@@ -454,51 +464,69 @@ var CodeMirror = (function() {
454
464
  }
455
465
  function onDragStart(e) {
456
466
  var txt = getSelection();
457
- // This will reset escapeElement
458
- htmlEscape(txt);
459
- e.dataTransfer.setDragImage(escapeElement, 0, 0);
467
+ // Disabled until further notice. Doesn't work on most browsers,
468
+ // and crashes Safari (issue #332).
469
+ //htmlEscape(txt);
470
+ //e.dataTransfer.setDragImage(escapeElement, 0, 0);
460
471
  e.dataTransfer.setData("Text", txt);
461
472
  }
462
- function handleKeyBinding(e) {
463
- var name = keyNames[e_prop(e, "keyCode")], next = keyMap[options.keyMap].auto, bound, dropShift;
464
- function handleNext() {
465
- return next.call ? next.call(null, instance) : next;
466
- }
467
- if (name == null || e.altGraphKey) {
468
- if (next) options.keyMap = handleNext();
469
- return null;
470
- }
471
- if (e_prop(e, "altKey")) name = "Alt-" + name;
472
- if (e_prop(e, "ctrlKey")) name = "Ctrl-" + name;
473
- if (e_prop(e, "metaKey")) name = "Cmd-" + name;
474
- if (e_prop(e, "shiftKey") &&
475
- (bound = lookupKey("Shift-" + name, options.extraKeys, options.keyMap))) {
476
- dropShift = true;
477
- } else {
478
- bound = lookupKey(name, options.extraKeys, options.keyMap);
479
- }
473
+
474
+ function doHandleBinding(bound, dropShift) {
480
475
  if (typeof bound == "string") {
481
- if (commands.propertyIsEnumerable(bound)) bound = commands[bound];
482
- else bound = null;
476
+ bound = commands[bound];
477
+ if (!bound) return false;
483
478
  }
484
- if (next && (bound || !isModifierKey(e))) options.keyMap = handleNext();
485
- if (!bound) return false;
486
479
  var prevShift = shiftSelecting;
487
480
  try {
488
481
  if (options.readOnly) suppressEdits = true;
489
482
  if (dropShift) shiftSelecting = null;
490
483
  bound(instance);
484
+ } catch(e) {
485
+ if (e != Pass) throw e;
486
+ return false;
491
487
  } finally {
492
488
  shiftSelecting = prevShift;
493
489
  suppressEdits = false;
494
490
  }
495
- e_preventDefault(e);
496
491
  return true;
497
492
  }
498
- var lastStoppedKey = null;
493
+ function handleKeyBinding(e) {
494
+ // Handle auto keymap transitions
495
+ var startMap = getKeyMap(options.keyMap), next = startMap.auto;
496
+ clearTimeout(maybeTransition);
497
+ if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
498
+ if (getKeyMap(options.keyMap) == startMap) {
499
+ options.keyMap = (next.call ? next.call(null, instance) : next);
500
+ }
501
+ }, 50);
502
+
503
+ var name = keyNames[e_prop(e, "keyCode")], handled = false;
504
+ if (name == null || e.altGraphKey) return false;
505
+ if (e_prop(e, "altKey")) name = "Alt-" + name;
506
+ if (e_prop(e, "ctrlKey")) name = "Ctrl-" + name;
507
+ if (e_prop(e, "metaKey")) name = "Cmd-" + name;
508
+
509
+ if (e_prop(e, "shiftKey"))
510
+ handled = lookupKey("Shift-" + name, options.extraKeys, options.keyMap,
511
+ function(b) {return doHandleBinding(b, true);});
512
+ if (!handled)
513
+ handled = lookupKey(name, options.extraKeys, options.keyMap, doHandleBinding);
514
+
515
+ if (handled) e_preventDefault(e);
516
+ return handled;
517
+ }
518
+ function handleCharBinding(e, ch) {
519
+ var handled = lookupKey("'" + ch + "'", options.extraKeys,
520
+ options.keyMap, doHandleBinding);
521
+ if (handled) e_preventDefault(e);
522
+ return handled;
523
+ }
524
+
525
+ var lastStoppedKey = null, maybeTransition;
499
526
  function onKeyDown(e) {
500
527
  if (!focused) onFocus();
501
528
  if (ie && e.keyCode == 27) { e.returnValue = false; }
529
+ if (pollingFast) { if (readInput()) pollingFast = false; }
502
530
  if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
503
531
  var code = e_prop(e, "keyCode");
504
532
  // IE does strange things with escape.
@@ -513,15 +541,17 @@ var CodeMirror = (function() {
513
541
  }
514
542
  }
515
543
  function onKeyPress(e) {
544
+ if (pollingFast) readInput();
545
+ if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
516
546
  var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode");
517
547
  if (window.opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
518
- if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
519
548
  if (window.opera && !e.which && handleKeyBinding(e)) return;
549
+ var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
520
550
  if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) {
521
- var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
522
551
  if (mode.electricChars.indexOf(ch) > -1)
523
552
  setTimeout(operation(function() {indentLine(sel.to.line, "smart");}), 75);
524
553
  }
554
+ if (handleCharBinding(e, ch)) return;
525
555
  fastPoll();
526
556
  }
527
557
  function onKeyUp(e) {
@@ -567,9 +597,10 @@ var CodeMirror = (function() {
567
597
  }
568
598
  updateLinesNoUndo(from, to, newText, selFrom, selTo);
569
599
  }
570
- function unredoHelper(from, to, dir) {
571
- var set = from.pop(), len = set ? set.length : 0, out = [];
572
- for (var i = dir > 0 ? 0 : len - 1, e = dir > 0 ? len : -1; i != e; i += dir) {
600
+ function unredoHelper(from, to) {
601
+ if (!from.length) return;
602
+ var set = from.pop(), out = [];
603
+ for (var i = set.length - 1; i >= 0; i -= 1) {
573
604
  var change = set[i];
574
605
  var replaced = [], end = change.start + change.added;
575
606
  doc.iter(change.start, end, function(line) { replaced.push(line.text); });
@@ -581,8 +612,8 @@ var CodeMirror = (function() {
581
612
  updateInput = true;
582
613
  to.push(out);
583
614
  }
584
- function undo() {unredoHelper(history.done, history.undone, -1);}
585
- function redo() {unredoHelper(history.undone, history.done, 1);}
615
+ function undo() {unredoHelper(history.done, history.undone);}
616
+ function redo() {unredoHelper(history.undone, history.done);}
586
617
 
587
618
  function updateLinesNoUndo(from, to, newText, selFrom, selTo) {
588
619
  if (suppressEdits) return;
@@ -784,7 +815,7 @@ var CodeMirror = (function() {
784
815
  if (!posEq(sel.from, sel.to)) {
785
816
  prevInput = "";
786
817
  input.value = getSelection();
787
- input.select();
818
+ selectInput(input);
788
819
  } else if (user) prevInput = input.value = "";
789
820
  }
790
821
 
@@ -971,7 +1002,7 @@ var CodeMirror = (function() {
971
1002
  if (!nextIntact || nextIntact.from > j) {
972
1003
  if (line.hidden) var html = scratch.innerHTML = "<pre></pre>";
973
1004
  else {
974
- var html = '<pre>' + line.getHTML(tabText) + '</pre>';
1005
+ var html = '<pre>' + line.getHTML(makeTab) + '</pre>';
975
1006
  // Kludge to make sure the styled element lies behind the selection (by z-index)
976
1007
  if (line.className)
977
1008
  html = '<div style="position: relative"><pre class="' + line.className +
@@ -1081,6 +1112,20 @@ var CodeMirror = (function() {
1081
1112
  else if (posEq(from, sel.to)) sel.inverted = false;
1082
1113
  else if (posEq(to, sel.from)) sel.inverted = true;
1083
1114
 
1115
+ if (options.autoClearEmptyLines && posEq(sel.from, sel.to)) {
1116
+ var head = sel.inverted ? from : to;
1117
+ if (head.line != sel.from.line) {
1118
+ var oldLine = getLine(sel.from.line);
1119
+ if (/^\s+$/.test(oldLine.text))
1120
+ setTimeout(operation(function() {
1121
+ if (oldLine.parent && /^\s+$/.test(oldLine.text)) {
1122
+ var no = lineNo(oldLine);
1123
+ replaceRange("", {line: no, ch: 0}, {line: no, ch: oldLine.text.length});
1124
+ }
1125
+ }, 10));
1126
+ }
1127
+ }
1128
+
1084
1129
  sel.from = from; sel.to = to;
1085
1130
  selectionChanged = true;
1086
1131
  }
@@ -1176,7 +1221,7 @@ var CodeMirror = (function() {
1176
1221
  setSelectionUser({line: pos.line, ch: start}, {line: pos.line, ch: end});
1177
1222
  }
1178
1223
  function selectLine(line) {
1179
- setSelectionUser({line: line, ch: 0}, {line: line, ch: getLine(line).text.length});
1224
+ setSelectionUser({line: line, ch: 0}, clipPos({line: line + 1, ch: 0}));
1180
1225
  }
1181
1226
  function indentSelected(mode) {
1182
1227
  if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode);
@@ -1249,13 +1294,10 @@ var CodeMirror = (function() {
1249
1294
  }
1250
1295
  changes.push({from: 0, to: doc.size});
1251
1296
  }
1252
- function computeTabText() {
1253
- for (var str = '<span class="cm-tab">', i = 0; i < options.tabSize; ++i) str += " ";
1254
- return str + "</span>";
1255
- }
1256
- function tabsChanged() {
1257
- tabText = computeTabText();
1258
- updateDisplay(true);
1297
+ function makeTab(col) {
1298
+ var w = options.tabSize - col % options.tabSize;
1299
+ for (var str = '<span class="cm-tab">', i = 0; i < w; ++i) str += " ";
1300
+ return {html: str + "</span>", width: w};
1259
1301
  }
1260
1302
  function themeChanged() {
1261
1303
  scroller.className = scroller.className.replace(/\s*cm-s-\w+/g, "") +
@@ -1392,7 +1434,7 @@ var CodeMirror = (function() {
1392
1434
  if (x <= 0) return 0;
1393
1435
  var lineObj = getLine(line), text = lineObj.text;
1394
1436
  function getX(len) {
1395
- measure.innerHTML = "<pre><span>" + lineObj.getHTML(tabText, len) + "</span></pre>";
1437
+ measure.innerHTML = "<pre><span>" + lineObj.getHTML(makeTab, len) + "</span></pre>";
1396
1438
  return measure.firstChild.firstChild.offsetWidth;
1397
1439
  }
1398
1440
  var from = 0, fromX = 0, to = text.length, toX;
@@ -1425,7 +1467,7 @@ var CodeMirror = (function() {
1425
1467
  var end = line.text.indexOf(" ", ch + 2);
1426
1468
  extra = htmlEscape(line.text.slice(ch + 1, end < 0 ? line.text.length : end + (ie ? 5 : 0)));
1427
1469
  }
1428
- measure.innerHTML = "<pre>" + line.getHTML(tabText, ch) +
1470
+ measure.innerHTML = "<pre>" + line.getHTML(makeTab, ch) +
1429
1471
  '<span id="CodeMirror-temp-' + tempId + '">' + htmlEscape(line.text.charAt(ch) || " ") + "</span>" +
1430
1472
  extra + "</pre>";
1431
1473
  var elt = document.getElementById("CodeMirror-temp-" + tempId);
@@ -1528,7 +1570,7 @@ var CodeMirror = (function() {
1528
1570
  return coordsChar(x - offL.left, y - offL.top);
1529
1571
  }
1530
1572
  function onContextMenu(e) {
1531
- var pos = posFromMouse(e);
1573
+ var pos = posFromMouse(e), scrollPos = scroller.scrollTop;
1532
1574
  if (!pos || window.opera) return; // Opera is difficult.
1533
1575
  if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
1534
1576
  operation(setCursor)(pos.line, pos.ch);
@@ -1541,12 +1583,13 @@ var CodeMirror = (function() {
1541
1583
  leaveInputAlone = true;
1542
1584
  var val = input.value = getSelection();
1543
1585
  focusInput();
1544
- input.select();
1586
+ selectInput(input);
1545
1587
  function rehide() {
1546
1588
  var newVal = splitLines(input.value).join("\n");
1547
1589
  if (newVal != val) operation(replaceSelection)(newVal, "end");
1548
1590
  inputDiv.style.position = "relative";
1549
1591
  input.style.cssText = oldCSS;
1592
+ if (ie_lt9) scroller.scrollTop = scrollPos;
1550
1593
  leaveInputAlone = false;
1551
1594
  resetInput(true);
1552
1595
  slowPoll();
@@ -1558,8 +1601,7 @@ var CodeMirror = (function() {
1558
1601
  mouseup();
1559
1602
  setTimeout(rehide, 20);
1560
1603
  }, true);
1561
- }
1562
- else {
1604
+ } else {
1563
1605
  setTimeout(rehide, 50);
1564
1606
  }
1565
1607
  }
@@ -1761,6 +1803,7 @@ var CodeMirror = (function() {
1761
1803
  keyMap: "default",
1762
1804
  extraKeys: null,
1763
1805
  electricChars: true,
1806
+ autoClearEmptyLines: false,
1764
1807
  onKeyEvent: null,
1765
1808
  lineWrapping: false,
1766
1809
  lineNumbers: false,
@@ -1796,19 +1839,20 @@ var CodeMirror = (function() {
1796
1839
  CodeMirror.defineMIME = function(mime, spec) {
1797
1840
  mimeModes[mime] = spec;
1798
1841
  };
1799
- CodeMirror.getMode = function(options, spec) {
1842
+ CodeMirror.resolveMode = function(spec) {
1800
1843
  if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
1801
1844
  spec = mimeModes[spec];
1802
- if (typeof spec == "string")
1803
- var mname = spec, config = {};
1804
- else if (spec != null)
1805
- var mname = spec.name, config = spec;
1806
- var mfactory = modes[mname];
1845
+ if (typeof spec == "string") return {name: spec};
1846
+ else return spec || {name: "null"};
1847
+ };
1848
+ CodeMirror.getMode = function(options, spec) {
1849
+ var spec = CodeMirror.resolveMode(spec);
1850
+ var mfactory = modes[spec.name];
1807
1851
  if (!mfactory) {
1808
- if (window.console) console.warn("No mode " + mname + " found, falling back to plain text.");
1852
+ if (window.console) console.warn("No mode " + spec.name + " found, falling back to plain text.");
1809
1853
  return CodeMirror.getMode(options, "text/plain");
1810
1854
  }
1811
- return mfactory(options, config || {});
1855
+ return mfactory(options, spec);
1812
1856
  };
1813
1857
  CodeMirror.listModes = function() {
1814
1858
  var list = [];
@@ -1911,20 +1955,27 @@ var CodeMirror = (function() {
1911
1955
  "Alt-D": "delWordRight", "Alt-Backspace": "delWordLeft", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
1912
1956
  };
1913
1957
 
1914
- function lookupKey(name, extraMap, map) {
1915
- function lookup(name, map, ft) {
1958
+ function getKeyMap(val) {
1959
+ if (typeof val == "string") return keyMap[val];
1960
+ else return val;
1961
+ }
1962
+ function lookupKey(name, extraMap, map, handle) {
1963
+ function lookup(map) {
1964
+ map = getKeyMap(map);
1916
1965
  var found = map[name];
1917
- if (found != null) return found;
1918
- if (ft == null) ft = map.fallthrough;
1919
- if (ft == null) return map.catchall;
1920
- if (typeof ft == "string") return lookup(name, keyMap[ft]);
1921
- for (var i = 0, e = ft.length; i < e; ++i) {
1922
- found = lookup(name, keyMap[ft[i]]);
1923
- if (found != null) return found;
1924
- }
1925
- return null;
1926
- }
1927
- return extraMap ? lookup(name, extraMap, map) : lookup(name, keyMap[map]);
1966
+ if (found != null && handle(found)) return true;
1967
+ if (map.catchall) return handle(map.catchall);
1968
+ var fallthrough = map.fallthrough;
1969
+ if (fallthrough == null) return false;
1970
+ if (Object.prototype.toString.call(fallthrough) != "[object Array]")
1971
+ return lookup(fallthrough);
1972
+ for (var i = 0, e = fallthrough.length; i < e; ++i) {
1973
+ if (lookup(fallthrough[i])) return true;
1974
+ }
1975
+ return false;
1976
+ }
1977
+ if (extraMap && lookup(extraMap)) return true;
1978
+ return lookup(map);
1928
1979
  }
1929
1980
  function isModifierKey(event) {
1930
1981
  var name = keyNames[e_prop(event, "keyCode")];
@@ -2272,15 +2323,35 @@ var CodeMirror = (function() {
2272
2323
  indentation: function(tabSize) {return countColumn(this.text, null, tabSize);},
2273
2324
  // Produces an HTML fragment for the line, taking selection,
2274
2325
  // marking, and highlighting into account.
2275
- getHTML: function(tabText, endAt) {
2276
- var html = [], first = true;
2326
+ getHTML: function(makeTab, endAt) {
2327
+ var html = [], first = true, col = 0;
2277
2328
  function span(text, style) {
2278
2329
  if (!text) return;
2279
2330
  // Work around a bug where, in some compat modes, IE ignores leading spaces
2280
2331
  if (first && ie && text.charAt(0) == " ") text = "\u00a0" + text.slice(1);
2281
2332
  first = false;
2282
- if (style) html.push('<span class="', style, '">', htmlEscape(text).replace(/\t/g, tabText), "</span>");
2283
- else html.push(htmlEscape(text).replace(/\t/g, tabText));
2333
+ if (text.indexOf("\t") == -1) {
2334
+ col += text.length;
2335
+ var escaped = htmlEscape(text);
2336
+ } else {
2337
+ var escaped = "";
2338
+ for (var pos = 0;;) {
2339
+ var idx = text.indexOf("\t", pos);
2340
+ if (idx == -1) {
2341
+ escaped += htmlEscape(text.slice(pos));
2342
+ col += text.length - pos;
2343
+ break;
2344
+ } else {
2345
+ col += idx - pos;
2346
+ var tab = makeTab(col);
2347
+ escaped += htmlEscape(text.slice(pos, idx)) + tab.html;
2348
+ col += tab.width;
2349
+ pos = idx + 1;
2350
+ }
2351
+ }
2352
+ }
2353
+ if (style) html.push('<span class="', style, '">', escaped, "</span>");
2354
+ else html.push(escaped);
2284
2355
  }
2285
2356
  var st = this.styles, allText = this.text, marked = this.marked;
2286
2357
  var len = allText.length;
@@ -2559,7 +2630,7 @@ var CodeMirror = (function() {
2559
2630
  var dtime = time - this.time;
2560
2631
  if (dtime > 400 || !last) {
2561
2632
  this.done.push([{start: start, added: added, old: old}]);
2562
- } else if (last.start > start + added || last.start + last.added < start - last.added + last.old.length) {
2633
+ } else if (last.start > start + old.length || last.start + last.added < start - last.added + last.old.length) {
2563
2634
  cur.push({start: start, added: added, old: old});
2564
2635
  } else {
2565
2636
  var oldoff = 0;
@@ -2634,6 +2705,8 @@ var CodeMirror = (function() {
2634
2705
  function Delayed() {this.id = null;}
2635
2706
  Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
2636
2707
 
2708
+ var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
2709
+
2637
2710
  // Detect drag-and-drop
2638
2711
  var dragAndDrop = function() {
2639
2712
  // IE8 has ondragstart and ondrop properties, but doesn't seem to
@@ -2645,6 +2718,7 @@ var CodeMirror = (function() {
2645
2718
 
2646
2719
  var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
2647
2720
  var ie = /MSIE \d/.test(navigator.userAgent);
2721
+ var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent);
2648
2722
  var webkit = /WebKit\//.test(navigator.userAgent);
2649
2723
 
2650
2724
  var lineSep = "\n";