codemirror-rails 3.20 → 3.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +240 -135
  4. data/vendor/assets/javascripts/codemirror/addons/comment/comment.js +6 -2
  5. data/vendor/assets/javascripts/codemirror/addons/comment/continuecomment.js +1 -1
  6. data/vendor/assets/javascripts/codemirror/addons/dialog/dialog.js +1 -0
  7. data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +5 -3
  8. data/vendor/assets/javascripts/codemirror/addons/edit/closetag.js +10 -6
  9. data/vendor/assets/javascripts/codemirror/addons/edit/continuelist.js +2 -0
  10. data/vendor/assets/javascripts/codemirror/addons/edit/matchbrackets.js +1 -1
  11. data/vendor/assets/javascripts/codemirror/addons/fold/comment-fold.js +3 -1
  12. data/vendor/assets/javascripts/codemirror/addons/fold/foldcode.js +13 -2
  13. data/vendor/assets/javascripts/codemirror/addons/fold/foldgutter.js +1 -1
  14. data/vendor/assets/javascripts/codemirror/addons/fold/indent-fold.js +2 -2
  15. data/vendor/assets/javascripts/codemirror/addons/fold/xml-fold.js +6 -0
  16. data/vendor/assets/javascripts/codemirror/addons/hint/anyword-hint.js +3 -5
  17. data/vendor/assets/javascripts/codemirror/addons/hint/css-hint.js +29 -33
  18. data/vendor/assets/javascripts/codemirror/addons/hint/javascript-hint.js +1 -1
  19. data/vendor/assets/javascripts/codemirror/addons/hint/pig-hint.js +1 -1
  20. data/vendor/assets/javascripts/codemirror/addons/hint/python-hint.js +1 -5
  21. data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +58 -9
  22. data/vendor/assets/javascripts/codemirror/addons/hint/sql-hint.js +58 -17
  23. data/vendor/assets/javascripts/codemirror/addons/hint/xml-hint.js +5 -5
  24. data/vendor/assets/javascripts/codemirror/addons/lint/lint.js +1 -1
  25. data/vendor/assets/javascripts/codemirror/addons/merge/merge.js +6 -1
  26. data/vendor/assets/javascripts/codemirror/addons/mode/multiplex.js +5 -3
  27. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode-standalone.js +26 -11
  28. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.js +1 -1
  29. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.node.js +22 -11
  30. data/vendor/assets/javascripts/codemirror/addons/search/search.js +22 -9
  31. data/vendor/assets/javascripts/codemirror/addons/search/searchcursor.js +48 -24
  32. data/vendor/assets/javascripts/codemirror/addons/selection/active-line.js +15 -9
  33. data/vendor/assets/javascripts/codemirror/addons/tern/tern.js +3 -3
  34. data/vendor/assets/javascripts/codemirror/addons/wrap/hardwrap.js +21 -9
  35. data/vendor/assets/javascripts/codemirror/keymaps/emacs.js +12 -1
  36. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +110 -28
  37. data/vendor/assets/javascripts/codemirror/modes/clike.js +28 -9
  38. data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +3 -4
  39. data/vendor/assets/javascripts/codemirror/modes/css.js +341 -297
  40. data/vendor/assets/javascripts/codemirror/modes/erlang.js +302 -179
  41. data/vendor/assets/javascripts/codemirror/modes/gfm.js +10 -5
  42. data/vendor/assets/javascripts/codemirror/modes/gherkin.js +45 -50
  43. data/vendor/assets/javascripts/codemirror/modes/haml.js +0 -4
  44. data/vendor/assets/javascripts/codemirror/modes/haskell.js +5 -3
  45. data/vendor/assets/javascripts/codemirror/modes/htmlembedded.js +0 -2
  46. data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +0 -2
  47. data/vendor/assets/javascripts/codemirror/modes/javascript.js +43 -30
  48. data/vendor/assets/javascripts/codemirror/modes/jinja2.js +13 -3
  49. data/vendor/assets/javascripts/codemirror/modes/less.js +7 -6
  50. data/vendor/assets/javascripts/codemirror/modes/markdown.js +231 -45
  51. data/vendor/assets/javascripts/codemirror/modes/{ocaml.js → mllike.js} +88 -13
  52. data/vendor/assets/javascripts/codemirror/modes/pegjs.js +5 -9
  53. data/vendor/assets/javascripts/codemirror/modes/php.js +6 -7
  54. data/vendor/assets/javascripts/codemirror/modes/python.js +6 -0
  55. data/vendor/assets/javascripts/codemirror/modes/r.js +5 -1
  56. data/vendor/assets/javascripts/codemirror/modes/rpm-spec.js +1 -1
  57. data/vendor/assets/javascripts/codemirror/modes/ruby.js +3 -1
  58. data/vendor/assets/javascripts/codemirror/modes/smalltalk.js +4 -2
  59. data/vendor/assets/javascripts/codemirror/modes/smartymixed.js +0 -2
  60. data/vendor/assets/javascripts/codemirror/modes/sql.js +5 -4
  61. data/vendor/assets/javascripts/codemirror/modes/xml.js +87 -100
  62. data/vendor/assets/stylesheets/codemirror/themes/mbo.css +1 -1
  63. data/vendor/assets/stylesheets/codemirror/themes/midnight.css +1 -1
  64. data/vendor/assets/stylesheets/codemirror/themes/pastel-on-dark.css +49 -0
  65. data/vendor/assets/stylesheets/codemirror/themes/the-matrix.css +1 -1
  66. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f4d274479004f7971f3fb00405bcee8d1a2efbef
4
- data.tar.gz: 58da8b05ad13207494ca43d926fcb370271b7b63
3
+ metadata.gz: 8680d4179ae33590e39ba128f1345d74e83722db
4
+ data.tar.gz: 2cda7f5da857f741036521f93736630ede8ec6dc
5
5
  SHA512:
6
- metadata.gz: d771bf91908c86f73f91f92a053385a90bfa921fa8a2237b4bc3058d11db7860e5769d44ffe1a549f8f8718681ea1e179847cfafe0813c9df137e72f208b9c68
7
- data.tar.gz: a9eeeab433dfc80ea5aa91de38ec46eda1749909838c7190f40b30f8985e82abc692dc258050b856ceea8eaad41cf3aabe3cf95fcf7c8982baa185b722f130c5
6
+ metadata.gz: 8690cdf5554a8108e8c60956b196c91b121e3939e919ad030e0e76981f5bd0d126907049db5b2bef7014bca84b73ce2b36975eb7ce5e50dcc93e9e2296f77e50
7
+ data.tar.gz: a1afa46266825c3491100c691a11ec0ab1b21c3f9f9c4ac3901f5acd5f485a06b7e87f8a87636d84f6a058b039c5c5d50a1da6bbf5b16dcec3125c731b53df33
@@ -1,6 +1,6 @@
1
1
  module Codemirror
2
2
  module Rails
3
- VERSION = '3.20'
4
- CODEMIRROR_VERSION = '3.20'
3
+ VERSION = '3.21'
4
+ CODEMIRROR_VERSION = '3.21'
5
5
  end
6
6
  end
@@ -10,10 +10,11 @@ window.CodeMirror = (function() {
10
10
  // IE11 currently doesn't count as 'ie', since it has almost none of
11
11
  // the same bugs as earlier versions. Use ie_gt10 to handle
12
12
  // incompatibilities in that version.
13
- var ie = /MSIE \d/.test(navigator.userAgent);
14
- var ie_lt8 = ie && (document.documentMode == null || document.documentMode < 8);
15
- var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
13
+ var old_ie = /MSIE \d/.test(navigator.userAgent);
14
+ var ie_lt8 = old_ie && (document.documentMode == null || document.documentMode < 8);
15
+ var ie_lt9 = old_ie && (document.documentMode == null || document.documentMode < 9);
16
16
  var ie_gt10 = /Trident\/([7-9]|\d{2,})\./.test(navigator.userAgent);
17
+ var ie = old_ie || ie_gt10;
17
18
  var webkit = /WebKit\//.test(navigator.userAgent);
18
19
  var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
19
20
  var chrome = /Chrome\//.test(navigator.userAgent);
@@ -35,7 +36,7 @@ window.CodeMirror = (function() {
35
36
  if (opera_version && opera_version >= 15) { opera = false; webkit = true; }
36
37
  // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
37
38
  var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));
38
- var captureMiddleClick = gecko || (ie && !ie_lt9);
39
+ var captureMiddleClick = gecko || (old_ie && !ie_lt9);
39
40
 
40
41
  // Optimize some code when these features are not used
41
42
  var sawReadOnlySpans = false, sawCollapsedSpans = false;
@@ -61,7 +62,8 @@ window.CodeMirror = (function() {
61
62
  overlays: [],
62
63
  modeGen: 0,
63
64
  overwrite: false, focused: false,
64
- suppressEdits: false, pasteIncoming: false,
65
+ suppressEdits: false,
66
+ pasteIncoming: false, cutIncoming: false,
65
67
  draggingText: false,
66
68
  highlight: new Delayed()};
67
69
 
@@ -75,7 +77,7 @@ window.CodeMirror = (function() {
75
77
 
76
78
  // Override magic textarea content restore that IE sometimes does
77
79
  // on our hidden textarea on reload
78
- if (ie) setTimeout(bind(resetInput, this, true), 20);
80
+ if (old_ie) setTimeout(bind(resetInput, this, true), 20);
79
81
 
80
82
  registerEventHandlers(this);
81
83
  // IE throws unspecified error in certain cases, when
@@ -195,6 +197,10 @@ window.CodeMirror = (function() {
195
197
 
196
198
  function loadMode(cm) {
197
199
  cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
200
+ resetModeState(cm);
201
+ }
202
+
203
+ function resetModeState(cm) {
198
204
  cm.doc.iter(function(line) {
199
205
  if (line.stateAfter) line.stateAfter = null;
200
206
  if (line.styles) line.styles = null;
@@ -244,7 +250,6 @@ window.CodeMirror = (function() {
244
250
  var map = keyMap[cm.options.keyMap], style = map.style;
245
251
  cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
246
252
  (style ? " cm-keymap-" + style : "");
247
- cm.state.disableInput = map.disableInput;
248
253
  }
249
254
 
250
255
  function themeChanged(cm) {
@@ -450,7 +455,7 @@ window.CodeMirror = (function() {
450
455
  // updates.
451
456
  function updateDisplayInner(cm, changes, visible, forced) {
452
457
  var display = cm.display, doc = cm.doc;
453
- if (!display.wrapper.clientWidth) {
458
+ if (!display.wrapper.offsetWidth) {
454
459
  display.showingFrom = display.showingTo = doc.first;
455
460
  display.viewOffset = 0;
456
461
  return;
@@ -535,6 +540,7 @@ window.CodeMirror = (function() {
535
540
  }
536
541
  display.showingFrom = from; display.showingTo = to;
537
542
 
543
+ display.gutters.style.height = "";
538
544
  updateHeightsInViewport(cm);
539
545
  updateViewOffset(cm);
540
546
 
@@ -717,9 +723,9 @@ window.CodeMirror = (function() {
717
723
  if (bgClass)
718
724
  wrap.insertBefore(elt("div", null, bgClass + " CodeMirror-linebackground"), wrap.firstChild);
719
725
  if (cm.options.lineNumbers || markers) {
720
- var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " +
726
+ var gutterWrap = wrap.insertBefore(elt("div", null, "CodeMirror-gutter-wrapper", "position: absolute; left: " +
721
727
  (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),
722
- wrap.firstChild);
728
+ lineElement);
723
729
  if (cm.options.fixedGutter) (wrap.alignable || (wrap.alignable = [])).push(gutterWrap);
724
730
  if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
725
731
  wrap.lineNumber = gutterWrap.appendChild(
@@ -1053,7 +1059,7 @@ window.CodeMirror = (function() {
1053
1059
  // doesn't work when wrapping is on, but in that case the
1054
1060
  // situation is slightly better, since IE does cache line-wrapping
1055
1061
  // information and only recomputes per-line.
1056
- if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) {
1062
+ if (old_ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) {
1057
1063
  var fragment = document.createDocumentFragment();
1058
1064
  var chunk = 10, n = pre.childNodes.length;
1059
1065
  for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) {
@@ -1113,7 +1119,7 @@ window.CodeMirror = (function() {
1113
1119
  }
1114
1120
  }
1115
1121
  if (!rect) rect = data[i] = measureRect(getRect(node));
1116
- if (cur.measureRight) rect.right = getRect(cur.measureRight).left;
1122
+ if (cur.measureRight) rect.right = getRect(cur.measureRight).left - outer.left;
1117
1123
  if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide));
1118
1124
  }
1119
1125
  removeChildren(cm.display.measure);
@@ -1289,7 +1295,7 @@ window.CodeMirror = (function() {
1289
1295
  if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
1290
1296
  var ch = x < fromX || x - fromX <= toX - x ? from : to;
1291
1297
  var xDiff = x - (ch == from ? fromX : toX);
1292
- while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
1298
+ while (isExtendingChar(lineObj.text.charAt(ch))) ++ch;
1293
1299
  var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
1294
1300
  xDiff < 0 ? -1 : xDiff ? 1 : 0);
1295
1301
  return pos;
@@ -1481,7 +1487,7 @@ window.CodeMirror = (function() {
1481
1487
  // supported or compatible enough yet to rely on.)
1482
1488
  function readInput(cm) {
1483
1489
  var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
1484
- if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false;
1490
+ if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.options.disableInput) return false;
1485
1491
  if (cm.state.pasteIncoming && cm.state.fakedLastChar) {
1486
1492
  input.value = input.value.substring(0, input.value.length - 1);
1487
1493
  cm.state.fakedLastChar = false;
@@ -1499,22 +1505,32 @@ window.CodeMirror = (function() {
1499
1505
  var same = 0, l = Math.min(prevInput.length, text.length);
1500
1506
  while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
1501
1507
  var from = sel.from, to = sel.to;
1508
+ var inserted = text.slice(same);
1502
1509
  if (same < prevInput.length)
1503
1510
  from = Pos(from.line, from.ch - (prevInput.length - same));
1504
1511
  else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming)
1505
- to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same)));
1512
+ to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + inserted.length));
1506
1513
 
1507
1514
  var updateInput = cm.curOp.updateInput;
1508
- var changeEvent = {from: from, to: to, text: splitLines(text.slice(same)),
1509
- origin: cm.state.pasteIncoming ? "paste" : "+input"};
1515
+ var changeEvent = {from: from, to: to, text: splitLines(inserted),
1516
+ origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"};
1510
1517
  makeChange(cm.doc, changeEvent, "end");
1511
1518
  cm.curOp.updateInput = updateInput;
1512
1519
  signalLater(cm, "inputRead", cm, changeEvent);
1520
+ if (inserted && !cm.state.pasteIncoming && cm.options.electricChars &&
1521
+ cm.options.smartIndent && sel.head.ch < 100) {
1522
+ var electric = cm.getModeAt(sel.head).electricChars;
1523
+ if (electric) for (var i = 0; i < electric.length; i++)
1524
+ if (inserted.indexOf(electric.charAt(i)) > -1) {
1525
+ indentLine(cm, sel.head.line, "smart");
1526
+ break;
1527
+ }
1528
+ }
1513
1529
 
1514
1530
  if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = "";
1515
1531
  else cm.display.prevInput = text;
1516
1532
  if (withOp) endOperation(cm);
1517
- cm.state.pasteIncoming = false;
1533
+ cm.state.pasteIncoming = cm.state.cutIncoming = false;
1518
1534
  return true;
1519
1535
  }
1520
1536
 
@@ -1549,7 +1565,7 @@ window.CodeMirror = (function() {
1549
1565
  function registerEventHandlers(cm) {
1550
1566
  var d = cm.display;
1551
1567
  on(d.scroller, "mousedown", operation(cm, onMouseDown));
1552
- if (ie)
1568
+ if (old_ie)
1553
1569
  on(d.scroller, "dblclick", operation(cm, function(e) {
1554
1570
  if (signalDOMEvent(cm, e)) return;
1555
1571
  var pos = posFromMouse(cm, e);
@@ -1655,21 +1671,22 @@ window.CodeMirror = (function() {
1655
1671
  fastPoll(cm);
1656
1672
  });
1657
1673
 
1658
- function prepareCopy() {
1674
+ function prepareCopy(e) {
1659
1675
  if (d.inaccurateSelection) {
1660
1676
  d.prevInput = "";
1661
1677
  d.inaccurateSelection = false;
1662
1678
  d.input.value = cm.getSelection();
1663
1679
  selectInput(d.input);
1664
1680
  }
1681
+ if (e.type == "cut") cm.state.cutIncoming = true;
1665
1682
  }
1666
1683
  on(d.input, "cut", prepareCopy);
1667
1684
  on(d.input, "copy", prepareCopy);
1668
1685
 
1669
1686
  // Needed to handle Tab key in KHTML
1670
1687
  if (khtml) on(d.sizer, "mouseup", function() {
1671
- if (document.activeElement == d.input) d.input.blur();
1672
- focusInput(cm);
1688
+ if (document.activeElement == d.input) d.input.blur();
1689
+ focusInput(cm);
1673
1690
  });
1674
1691
  }
1675
1692
 
@@ -1753,6 +1770,9 @@ window.CodeMirror = (function() {
1753
1770
  e_preventDefault(e2);
1754
1771
  extendSelection(cm.doc, start);
1755
1772
  focusInput(cm);
1773
+ // Work around unexplainable focus problem in IE9 (#2127)
1774
+ if (old_ie && !ie_lt9)
1775
+ setTimeout(function() {document.body.focus(); focusInput(cm);}, 20);
1756
1776
  }
1757
1777
  });
1758
1778
  // Let the drag handler handle this.
@@ -1827,7 +1847,7 @@ window.CodeMirror = (function() {
1827
1847
  }
1828
1848
 
1829
1849
  var move = operation(cm, function(e) {
1830
- if (!ie && !e_button(e)) done(e);
1850
+ if (!old_ie && !e_button(e)) done(e);
1831
1851
  else extend(e);
1832
1852
  });
1833
1853
  var up = operation(cm, done);
@@ -1972,7 +1992,7 @@ window.CodeMirror = (function() {
1972
1992
  // know one. These don't have to be accurate -- the result of them
1973
1993
  // being wrong would just be a slight flicker on the first wheel
1974
1994
  // scroll (if it is large enough).
1975
- if (ie) wheelPixelsPerUnit = -.53;
1995
+ if (old_ie) wheelPixelsPerUnit = -.53;
1976
1996
  else if (gecko) wheelPixelsPerUnit = 15;
1977
1997
  else if (chrome) wheelPixelsPerUnit = -.7;
1978
1998
  else if (safari) wheelPixelsPerUnit = -1/3;
@@ -2126,7 +2146,7 @@ window.CodeMirror = (function() {
2126
2146
  var cm = this;
2127
2147
  if (!cm.state.focused) onFocus(cm);
2128
2148
  if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2129
- if (ie && e.keyCode == 27) e.returnValue = false;
2149
+ if (old_ie && e.keyCode == 27) e.returnValue = false;
2130
2150
  var code = e.keyCode;
2131
2151
  // IE does strange things with escape.
2132
2152
  cm.doc.sel.shift = code == 16 || e.shiftKey;
@@ -2147,10 +2167,6 @@ window.CodeMirror = (function() {
2147
2167
  if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
2148
2168
  if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
2149
2169
  var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
2150
- if (this.options.electricChars && this.doc.mode.electricChars &&
2151
- this.options.smartIndent && !isReadOnly(this) &&
2152
- this.doc.mode.electricChars.indexOf(ch) > -1)
2153
- setTimeout(operation(cm, function() {indentLine(cm, cm.doc.sel.to.line, "smart");}), 75);
2154
2170
  if (handleCharBinding(cm, e, ch)) return;
2155
2171
  if (ie && !ie_lt9) cm.display.inputHasSelection = null;
2156
2172
  fastPoll(cm);
@@ -2199,7 +2215,7 @@ window.CodeMirror = (function() {
2199
2215
  var oldCSS = display.input.style.cssText;
2200
2216
  display.inputDiv.style.position = "absolute";
2201
2217
  display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
2202
- "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; outline: none;" +
2218
+ "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: transparent; outline: none;" +
2203
2219
  "border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);";
2204
2220
  focusInput(cm);
2205
2221
  resetInput(cm, true);
@@ -2221,10 +2237,10 @@ window.CodeMirror = (function() {
2221
2237
 
2222
2238
  // Try to detect the user choosing select-all
2223
2239
  if (display.input.selectionStart != null) {
2224
- if (!ie || ie_lt9) prepareSelectAllHack();
2240
+ if (!old_ie || ie_lt9) prepareSelectAllHack();
2225
2241
  clearTimeout(detectingSelectAll);
2226
2242
  var i = 0, poll = function(){
2227
- if (display.prevInput == " " && display.input.selectionStart == 0)
2243
+ if (display.prevInput == "\u200b" && display.input.selectionStart == 0)
2228
2244
  operation(cm, commands.selectAll)(cm);
2229
2245
  else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
2230
2246
  else resetInput(cm);
@@ -2233,7 +2249,7 @@ window.CodeMirror = (function() {
2233
2249
  }
2234
2250
  }
2235
2251
 
2236
- if (ie && !ie_lt9) prepareSelectAllHack();
2252
+ if (old_ie && !ie_lt9) prepareSelectAllHack();
2237
2253
  if (captureMiddleClick) {
2238
2254
  e_stop(e);
2239
2255
  var mouseup = function() {
@@ -2506,6 +2522,7 @@ window.CodeMirror = (function() {
2506
2522
 
2507
2523
  function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
2508
2524
  function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
2525
+ function cmp(a, b) {return a.line - b.line || a.ch - b.ch;}
2509
2526
  function copyPos(x) {return Pos(x.line, x.ch);}
2510
2527
 
2511
2528
  // SELECTION
@@ -2650,14 +2667,13 @@ window.CodeMirror = (function() {
2650
2667
  if (coords.top + box.top < 0) doScroll = true;
2651
2668
  else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
2652
2669
  if (doScroll != null && !phantom) {
2653
- var hidden = display.cursor.style.display == "none";
2654
- if (hidden) {
2655
- display.cursor.style.display = "";
2656
- display.cursor.style.left = coords.left + "px";
2657
- display.cursor.style.top = (coords.top - display.viewOffset) + "px";
2658
- }
2659
- display.cursor.scrollIntoView(doScroll);
2660
- if (hidden) display.cursor.style.display = "none";
2670
+ var scrollNode = elt("div", "\u200b", null, "position: absolute; top: " +
2671
+ (coords.top - display.viewOffset) + "px; height: " +
2672
+ (coords.bottom - coords.top + scrollerCutOff) + "px; left: " +
2673
+ coords.left + "px; width: 2px;");
2674
+ cm.display.lineSpace.appendChild(scrollNode);
2675
+ scrollNode.scrollIntoView(doScroll);
2676
+ cm.display.lineSpace.removeChild(scrollNode);
2661
2677
  }
2662
2678
  }
2663
2679
 
@@ -2740,7 +2756,10 @@ window.CodeMirror = (function() {
2740
2756
  var tabSize = cm.options.tabSize;
2741
2757
  var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
2742
2758
  var curSpaceString = line.text.match(/^\s*/)[0], indentation;
2743
- if (how == "smart") {
2759
+ if (!aggressive && !/\S/.test(line.text)) {
2760
+ indentation = 0;
2761
+ how = "not";
2762
+ } else if (how == "smart") {
2744
2763
  indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
2745
2764
  if (indentation == Pass) {
2746
2765
  if (!aggressive) return;
@@ -2922,7 +2941,7 @@ window.CodeMirror = (function() {
2922
2941
  }),
2923
2942
  indentSelection: operation(null, function(how) {
2924
2943
  var sel = this.doc.sel;
2925
- if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how);
2944
+ if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how, true);
2926
2945
  var e = sel.to.line - (sel.to.ch ? 0 : 1);
2927
2946
  for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how);
2928
2947
  }),
@@ -2967,11 +2986,31 @@ window.CodeMirror = (function() {
2967
2986
  },
2968
2987
 
2969
2988
  getHelper: function(pos, type) {
2970
- if (!helpers.hasOwnProperty(type)) return;
2989
+ return this.getHelpers(pos, type)[0];
2990
+ },
2991
+
2992
+ getHelpers: function(pos, type) {
2993
+ var found = [];
2994
+ if (!helpers.hasOwnProperty(type)) return helpers;
2971
2995
  var help = helpers[type], mode = this.getModeAt(pos);
2972
- return mode[type] && help[mode[type]] ||
2973
- mode.helperType && help[mode.helperType] ||
2974
- help[mode.name];
2996
+ if (typeof mode[type] == "string") {
2997
+ if (help[mode[type]]) found.push(help[mode[type]]);
2998
+ } else if (mode[type]) {
2999
+ for (var i = 0; i < mode[type].length; i++) {
3000
+ var val = help[mode[type][i]];
3001
+ if (val) found.push(val);
3002
+ }
3003
+ } else if (mode.helperType && help[mode.helperType]) {
3004
+ found.push(help[mode.helperType]);
3005
+ } else if (help[mode.name]) {
3006
+ found.push(help[mode.name]);
3007
+ }
3008
+ for (var i = 0; i < help._global.length; i++) {
3009
+ var cur = help._global[i];
3010
+ if (cur.pred(mode, this) && indexOf(found, cur.val) == -1)
3011
+ found.push(cur.val);
3012
+ }
3013
+ return found;
2975
3014
  },
2976
3015
 
2977
3016
  getStateAfter: function(line, precise) {
@@ -3118,7 +3157,10 @@ window.CodeMirror = (function() {
3118
3157
 
3119
3158
  triggerOnKeyDown: operation(null, onKeyDown),
3120
3159
 
3121
- execCommand: function(cmd) {return commands[cmd](this);},
3160
+ execCommand: function(cmd) {
3161
+ if (commands.hasOwnProperty(cmd))
3162
+ return commands[cmd](this);
3163
+ },
3122
3164
 
3123
3165
  findPosH: function(from, amount, unit, visually) {
3124
3166
  var dir = 1;
@@ -3160,14 +3202,18 @@ window.CodeMirror = (function() {
3160
3202
  },
3161
3203
 
3162
3204
  moveV: operation(null, function(dir, unit) {
3163
- var sel = this.doc.sel;
3164
- var pos = cursorCoords(this, sel.head, "div");
3165
- if (sel.goalColumn != null) pos.left = sel.goalColumn;
3166
- var target = findPosV(this, pos, dir, unit);
3167
-
3168
- if (unit == "page") addToScrollPos(this, 0, charCoords(this, target, "div").top - pos.top);
3205
+ var sel = this.doc.sel, target, goal;
3206
+ if (sel.shift || sel.extend || posEq(sel.from, sel.to)) {
3207
+ var pos = cursorCoords(this, sel.head, "div");
3208
+ if (sel.goalColumn != null) pos.left = sel.goalColumn;
3209
+ target = findPosV(this, pos, dir, unit);
3210
+ if (unit == "page") addToScrollPos(this, 0, charCoords(this, target, "div").top - pos.top);
3211
+ goal = pos.left;
3212
+ } else {
3213
+ target = dir < 0 ? sel.from : sel.to;
3214
+ }
3169
3215
  extendSelection(this.doc, target, target, dir);
3170
- sel.goalColumn = pos.left;
3216
+ if (goal != null) sel.goalColumn = goal;
3171
3217
  }),
3172
3218
 
3173
3219
  toggleOverwrite: function(value) {
@@ -3277,7 +3323,7 @@ window.CodeMirror = (function() {
3277
3323
  option("indentWithTabs", false);
3278
3324
  option("smartIndent", true);
3279
3325
  option("tabSize", 4, function(cm) {
3280
- loadMode(cm);
3326
+ resetModeState(cm);
3281
3327
  clearCaches(cm);
3282
3328
  regChange(cm);
3283
3329
  }, true);
@@ -3330,6 +3376,7 @@ window.CodeMirror = (function() {
3330
3376
  if (!val) resetInput(cm, true);
3331
3377
  }
3332
3378
  });
3379
+ option("disableInput", false, function(cm, val) {if (!val) resetInput(cm, true);}, true);
3333
3380
  option("dragDrop", true);
3334
3381
 
3335
3382
  option("cursorBlinkRate", 530);
@@ -3337,12 +3384,13 @@ window.CodeMirror = (function() {
3337
3384
  option("cursorHeight", 1);
3338
3385
  option("workTime", 100);
3339
3386
  option("workDelay", 100);
3340
- option("flattenSpans", true);
3387
+ option("flattenSpans", true, resetModeState, true);
3388
+ option("addModeClass", false, resetModeState, true);
3341
3389
  option("pollInterval", 100);
3342
3390
  option("undoDepth", 40, function(cm, val){cm.doc.history.undoDepth = val;});
3343
3391
  option("historyEventDelay", 500);
3344
3392
  option("viewportMargin", 10, function(cm){cm.refresh();}, true);
3345
- option("maxHighlightLength", 10000, function(cm){loadMode(cm); cm.refresh();}, true);
3393
+ option("maxHighlightLength", 10000, resetModeState, true);
3346
3394
  option("crudeMeasuringFrom", 10000);
3347
3395
  option("moveInputWithCursor", true, function(cm, val) {
3348
3396
  if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0;
@@ -3399,6 +3447,9 @@ window.CodeMirror = (function() {
3399
3447
  }
3400
3448
  }
3401
3449
  modeObj.name = spec.name;
3450
+ if (spec.helperType) modeObj.helperType = spec.helperType;
3451
+ if (spec.modeProps) for (var prop in spec.modeProps)
3452
+ modeObj[prop] = spec.modeProps[prop];
3402
3453
 
3403
3454
  return modeObj;
3404
3455
  };
@@ -3429,9 +3480,13 @@ window.CodeMirror = (function() {
3429
3480
 
3430
3481
  var helpers = CodeMirror.helpers = {};
3431
3482
  CodeMirror.registerHelper = function(type, name, value) {
3432
- if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {};
3483
+ if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []};
3433
3484
  helpers[type][name] = value;
3434
3485
  };
3486
+ CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
3487
+ CodeMirror.registerHelper(type, name, value);
3488
+ helpers[type]._global.push({pred: predicate, val: value});
3489
+ };
3435
3490
 
3436
3491
  // UTILITIES
3437
3492
 
@@ -3536,7 +3591,9 @@ window.CodeMirror = (function() {
3536
3591
  indentAuto: function(cm) {cm.indentSelection("smart");},
3537
3592
  indentMore: function(cm) {cm.indentSelection("add");},
3538
3593
  indentLess: function(cm) {cm.indentSelection("subtract");},
3539
- insertTab: function(cm) {cm.replaceSelection("\t", "end", "+input");},
3594
+ insertTab: function(cm) {
3595
+ cm.replaceSelection("\t", "end", "+input");
3596
+ },
3540
3597
  defaultTab: function(cm) {
3541
3598
  if (cm.somethingSelected()) cm.indentSelection("add");
3542
3599
  else cm.replaceSelection("\t", "end", "+input");
@@ -3709,11 +3766,12 @@ window.CodeMirror = (function() {
3709
3766
  this.string = string;
3710
3767
  this.tabSize = tabSize || 8;
3711
3768
  this.lastColumnPos = this.lastColumnValue = 0;
3769
+ this.lineStart = 0;
3712
3770
  }
3713
3771
 
3714
3772
  StringStream.prototype = {
3715
3773
  eol: function() {return this.pos >= this.string.length;},
3716
- sol: function() {return this.pos == 0;},
3774
+ sol: function() {return this.pos == this.lineStart;},
3717
3775
  peek: function() {return this.string.charAt(this.pos) || undefined;},
3718
3776
  next: function() {
3719
3777
  if (this.pos < this.string.length)
@@ -3746,9 +3804,12 @@ window.CodeMirror = (function() {
3746
3804
  this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
3747
3805
  this.lastColumnPos = this.start;
3748
3806
  }
3749
- return this.lastColumnValue;
3807
+ return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
3808
+ },
3809
+ indentation: function() {
3810
+ return countColumn(this.string, null, this.tabSize) -
3811
+ (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
3750
3812
  },
3751
- indentation: function() {return countColumn(this.string, null, this.tabSize);},
3752
3813
  match: function(pattern, consume, caseInsensitive) {
3753
3814
  if (typeof pattern == "string") {
3754
3815
  var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
@@ -3764,7 +3825,12 @@ window.CodeMirror = (function() {
3764
3825
  return match;
3765
3826
  }
3766
3827
  },
3767
- current: function(){return this.string.slice(this.start, this.pos);}
3828
+ current: function(){return this.string.slice(this.start, this.pos);},
3829
+ hideFirstChars: function(n, inner) {
3830
+ this.lineStart += n;
3831
+ try { return inner(); }
3832
+ finally { this.lineStart -= n; }
3833
+ }
3768
3834
  };
3769
3835
  CodeMirror.StringStream = StringStream;
3770
3836
 
@@ -3816,7 +3882,7 @@ window.CodeMirror = (function() {
3816
3882
  if (withOp) endOperation(cm);
3817
3883
  };
3818
3884
 
3819
- TextMarker.prototype.find = function() {
3885
+ TextMarker.prototype.find = function(bothSides) {
3820
3886
  var from, to;
3821
3887
  for (var i = 0; i < this.lines.length; ++i) {
3822
3888
  var line = this.lines[i];
@@ -3827,7 +3893,7 @@ window.CodeMirror = (function() {
3827
3893
  if (span.to != null) to = Pos(found, span.to);
3828
3894
  }
3829
3895
  }
3830
- if (this.type == "bookmark") return from;
3896
+ if (this.type == "bookmark" && !bothSides) return from;
3831
3897
  return from && {from: from, to: to};
3832
3898
  };
3833
3899
 
@@ -3864,39 +3930,40 @@ window.CodeMirror = (function() {
3864
3930
  }
3865
3931
  };
3866
3932
 
3933
+ var nextMarkerId = 0;
3934
+
3867
3935
  function markText(doc, from, to, options, type) {
3868
3936
  if (options && options.shared) return markTextShared(doc, from, to, options, type);
3869
3937
  if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
3870
3938
 
3871
3939
  var marker = new TextMarker(doc, type);
3872
- if (posLess(to, from) || posEq(from, to) && type == "range" &&
3873
- !(options.inclusiveLeft && options.inclusiveRight))
3874
- return marker;
3875
3940
  if (options) copyObj(options, marker);
3941
+ if (posLess(to, from) || posEq(from, to) && marker.clearWhenEmpty !== false)
3942
+ return marker;
3876
3943
  if (marker.replacedWith) {
3877
3944
  marker.collapsed = true;
3878
3945
  marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget");
3879
3946
  if (!options.handleMouseEvents) marker.replacedWith.ignoreEvents = true;
3880
3947
  }
3881
- if (marker.collapsed) sawCollapsedSpans = true;
3948
+ if (marker.collapsed) {
3949
+ if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||
3950
+ from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))
3951
+ throw new Error("Inserting collapsed marker partially overlapping an existing one");
3952
+ sawCollapsedSpans = true;
3953
+ }
3882
3954
 
3883
3955
  if (marker.addToHistory)
3884
3956
  addToHistory(doc, {from: from, to: to, origin: "markText"},
3885
3957
  {head: doc.sel.head, anchor: doc.sel.anchor}, NaN);
3886
3958
 
3887
- var curLine = from.line, size = 0, collapsedAtStart, collapsedAtEnd, cm = doc.cm, updateMaxLine;
3959
+ var curLine = from.line, cm = doc.cm, updateMaxLine;
3888
3960
  doc.iter(curLine, to.line + 1, function(line) {
3889
3961
  if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.display.maxLine)
3890
3962
  updateMaxLine = true;
3891
3963
  var span = {from: null, to: null, marker: marker};
3892
- size += line.text.length;
3893
- if (curLine == from.line) {span.from = from.ch; size -= from.ch;}
3894
- if (curLine == to.line) {span.to = to.ch; size -= line.text.length - to.ch;}
3895
- if (marker.collapsed) {
3896
- if (curLine == to.line) collapsedAtEnd = collapsedSpanAt(line, to.ch);
3897
- if (curLine == from.line) collapsedAtStart = collapsedSpanAt(line, from.ch);
3898
- else updateLineHeight(line, 0);
3899
- }
3964
+ if (curLine == from.line) span.from = from.ch;
3965
+ if (curLine == to.line) span.to = to.ch;
3966
+ if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0);
3900
3967
  addMarkedSpan(line, span);
3901
3968
  ++curLine;
3902
3969
  });
@@ -3912,9 +3979,7 @@ window.CodeMirror = (function() {
3912
3979
  doc.clearHistory();
3913
3980
  }
3914
3981
  if (marker.collapsed) {
3915
- if (collapsedAtStart != collapsedAtEnd)
3916
- throw new Error("Inserting collapsed marker overlapping an existing one");
3917
- marker.size = size;
3982
+ marker.id = ++nextMarkerId;
3918
3983
  marker.atomic = true;
3919
3984
  }
3920
3985
  if (cm) {
@@ -3987,9 +4052,7 @@ window.CodeMirror = (function() {
3987
4052
  if (old) for (var i = 0, nw; i < old.length; ++i) {
3988
4053
  var span = old[i], marker = span.marker;
3989
4054
  var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
3990
- if (startsBefore ||
3991
- (marker.inclusiveLeft && marker.inclusiveRight || marker.type == "bookmark") &&
3992
- span.from == startCh && (!isInsert || !span.marker.insertLeft)) {
4055
+ if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) {
3993
4056
  var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
3994
4057
  (nw || (nw = [])).push({from: span.from,
3995
4058
  to: endsAfter ? null : span.to,
@@ -4003,7 +4066,7 @@ window.CodeMirror = (function() {
4003
4066
  if (old) for (var i = 0, nw; i < old.length; ++i) {
4004
4067
  var span = old[i], marker = span.marker;
4005
4068
  var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
4006
- if (endsAfter || marker.type == "bookmark" && span.from == endCh && (!isInsert || span.marker.insertLeft)) {
4069
+ if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) {
4007
4070
  var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
4008
4071
  (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,
4009
4072
  to: span.to == null ? null : span.to - endCh,
@@ -4053,13 +4116,9 @@ window.CodeMirror = (function() {
4053
4116
  }
4054
4117
  }
4055
4118
  }
4056
- if (sameLine && first) {
4057
- // Make sure we didn't create any zero-length spans
4058
- for (var i = 0; i < first.length; ++i)
4059
- if (first[i].from != null && first[i].from == first[i].to && first[i].marker.type != "bookmark")
4060
- first.splice(i--, 1);
4061
- if (!first.length) first = null;
4062
- }
4119
+ // Make sure we didn't create any zero-length spans
4120
+ if (first) first = clearEmptySpans(first);
4121
+ if (last && last != first) last = clearEmptySpans(last);
4063
4122
 
4064
4123
  var newMarkers = [first];
4065
4124
  if (!sameLine) {
@@ -4076,6 +4135,16 @@ window.CodeMirror = (function() {
4076
4135
  return newMarkers;
4077
4136
  }
4078
4137
 
4138
+ function clearEmptySpans(spans) {
4139
+ for (var i = 0; i < spans.length; ++i) {
4140
+ var span = spans[i];
4141
+ if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)
4142
+ spans.splice(i--, 1);
4143
+ }
4144
+ if (!spans.length) return null;
4145
+ return spans;
4146
+ }
4147
+
4079
4148
  function mergeOldSpans(doc, change) {
4080
4149
  var old = getOldSpans(doc, change);
4081
4150
  var stretched = stretchSpansOverChange(doc, change);
@@ -4126,20 +4195,48 @@ window.CodeMirror = (function() {
4126
4195
  return parts;
4127
4196
  }
4128
4197
 
4129
- function collapsedSpanAt(line, ch) {
4198
+ function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; }
4199
+ function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; }
4200
+
4201
+ function compareCollapsedMarkers(a, b) {
4202
+ var lenDiff = a.lines.length - b.lines.length;
4203
+ if (lenDiff != 0) return lenDiff;
4204
+ var aPos = a.find(), bPos = b.find();
4205
+ var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b);
4206
+ if (fromCmp) return -fromCmp;
4207
+ var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b);
4208
+ if (toCmp) return toCmp;
4209
+ return b.id - a.id;
4210
+ }
4211
+
4212
+ function collapsedSpanAtSide(line, start) {
4130
4213
  var sps = sawCollapsedSpans && line.markedSpans, found;
4131
4214
  if (sps) for (var sp, i = 0; i < sps.length; ++i) {
4132
4215
  sp = sps[i];
4133
- if (!sp.marker.collapsed) continue;
4134
- if ((sp.from == null || sp.from < ch) &&
4135
- (sp.to == null || sp.to > ch) &&
4136
- (!found || found.width < sp.marker.width))
4216
+ if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
4217
+ (!found || compareCollapsedMarkers(found, sp.marker) < 0))
4137
4218
  found = sp.marker;
4138
4219
  }
4139
4220
  return found;
4140
4221
  }
4141
- function collapsedSpanAtStart(line) { return collapsedSpanAt(line, -1); }
4142
- function collapsedSpanAtEnd(line) { return collapsedSpanAt(line, line.text.length + 1); }
4222
+ function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); }
4223
+ function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); }
4224
+
4225
+ function conflictingCollapsedRange(doc, lineNo, from, to, marker) {
4226
+ var line = getLine(doc, lineNo);
4227
+ var sps = sawCollapsedSpans && line.markedSpans;
4228
+ if (sps) for (var i = 0; i < sps.length; ++i) {
4229
+ var sp = sps[i];
4230
+ if (!sp.marker.collapsed) continue;
4231
+ var found = sp.marker.find(true);
4232
+ var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);
4233
+ var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);
4234
+ if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue;
4235
+ if (fromCmp <= 0 && (cmp(found.to, from) || extraRight(sp.marker) - extraLeft(marker)) > 0 ||
4236
+ fromCmp >= 0 && (cmp(found.from, to) || extraLeft(sp.marker) - extraRight(marker)) < 0)
4237
+ return true;
4238
+ }
4239
+ }
4143
4240
 
4144
4241
  function visualLine(doc, line) {
4145
4242
  var merged;
@@ -4169,6 +4266,7 @@ window.CodeMirror = (function() {
4169
4266
  for (var sp, i = 0; i < line.markedSpans.length; ++i) {
4170
4267
  sp = line.markedSpans[i];
4171
4268
  if (sp.marker.collapsed && !sp.marker.replacedWith && sp.from == span.to &&
4269
+ (sp.to == null || sp.to != span.from) &&
4172
4270
  (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
4173
4271
  lineIsHiddenInner(doc, line, sp)) return true;
4174
4272
  }
@@ -4298,6 +4396,10 @@ window.CodeMirror = (function() {
4298
4396
  } else {
4299
4397
  style = mode.token(stream, state);
4300
4398
  }
4399
+ if (cm.options.addModeClass) {
4400
+ var mName = CodeMirror.innerMode(mode, state).mode.name;
4401
+ if (mName) style = "m-" + (style ? mName + " " + style : mName);
4402
+ }
4301
4403
  if (!flattenSpans || curStyle != style) {
4302
4404
  if (curStart < stream.start) f(stream.start, curStyle);
4303
4405
  curStart = stream.start; curStyle = style;
@@ -4369,7 +4471,7 @@ window.CodeMirror = (function() {
4369
4471
  }
4370
4472
  }
4371
4473
 
4372
- var styleToClassCache = {};
4474
+ var styleToClassCache = {}, styleToClassCacheWithMode = {};
4373
4475
  function interpretTokenStyle(style, builder) {
4374
4476
  if (!style) return null;
4375
4477
  for (;;) {
@@ -4382,8 +4484,9 @@ window.CodeMirror = (function() {
4382
4484
  else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(builder[prop]))
4383
4485
  builder[prop] += " " + lineClass[2];
4384
4486
  }
4385
- return styleToClassCache[style] ||
4386
- (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-"));
4487
+ var cache = builder.cm.options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;
4488
+ return cache[style] ||
4489
+ (cache[style] = "cm-" + style.replace(/ +/g, " cm-"));
4387
4490
  }
4388
4491
 
4389
4492
  function buildLineContent(cm, realLine, measure, copyWidgets) {
@@ -4400,7 +4503,7 @@ window.CodeMirror = (function() {
4400
4503
  builder.measure = line == realLine && measure;
4401
4504
  builder.pos = 0;
4402
4505
  builder.addToken = builder.measure ? buildTokenMeasure : buildToken;
4403
- if ((ie || webkit) && cm.getOption("lineWrapping"))
4506
+ if ((old_ie || webkit) && cm.getOption("lineWrapping"))
4404
4507
  builder.addToken = buildTokenSplitSpaces(builder.addToken);
4405
4508
  var next = insertLineContent(line, builder, getLineStyles(cm, line));
4406
4509
  if (measure && line == realLine && !builder.measuredSomething) {
@@ -4419,7 +4522,7 @@ window.CodeMirror = (function() {
4419
4522
  // Work around problem with the reported dimensions of single-char
4420
4523
  // direction spans on IE (issue #1129). See also the comment in
4421
4524
  // cursorCoords.
4422
- if (measure && (ie || ie_gt10) && (order = getOrder(line))) {
4525
+ if (measure && ie && (order = getOrder(line))) {
4423
4526
  var l = order.length - 1;
4424
4527
  if (order[l].from == order[l].to) --l;
4425
4528
  var last = order[l], prev = order[l - 1];
@@ -4486,13 +4589,12 @@ window.CodeMirror = (function() {
4486
4589
  function buildTokenMeasure(builder, text, style, startStyle, endStyle) {
4487
4590
  var wrapping = builder.cm.options.lineWrapping;
4488
4591
  for (var i = 0; i < text.length; ++i) {
4489
- var ch = text.charAt(i), start = i == 0;
4490
- if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) {
4491
- ch = text.slice(i, i + 2);
4492
- ++i;
4493
- } else if (i && wrapping && spanAffectsWrapping(text, i)) {
4592
+ var start = i == 0, to = i + 1;
4593
+ while (to < text.length && isExtendingChar(text.charAt(to))) ++to;
4594
+ var ch = text.slice(i, to);
4595
+ i = to - 1;
4596
+ if (i && wrapping && spanAffectsWrapping(text, i))
4494
4597
  builder.pre.appendChild(elt("wbr"));
4495
- }
4496
4598
  var old = builder.measure[builder.pos];
4497
4599
  var span = builder.measure[builder.pos] =
4498
4600
  buildToken(builder, ch, style,
@@ -4501,7 +4603,7 @@ window.CodeMirror = (function() {
4501
4603
  // In IE single-space nodes wrap differently than spaces
4502
4604
  // embedded in larger text nodes, except when set to
4503
4605
  // white-space: normal (issue #1268).
4504
- if (ie && wrapping && ch == " " && i && !/\s/.test(text.charAt(i - 1)) &&
4606
+ if (old_ie && wrapping && ch == " " && i && !/\s/.test(text.charAt(i - 1)) &&
4505
4607
  i < text.length - 1 && !/\s/.test(text.charAt(i + 1)))
4506
4608
  span.style.whiteSpace = "normal";
4507
4609
  builder.pos += ch.length;
@@ -4569,7 +4671,7 @@ window.CodeMirror = (function() {
4569
4671
  if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
4570
4672
  if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
4571
4673
  if (m.title && !title) title = m.title;
4572
- if (m.collapsed && (!collapsed || collapsed.marker.size < m.size))
4674
+ if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
4573
4675
  collapsed = sp;
4574
4676
  } else if (sp.from > pos && nextChange > sp.from) {
4575
4677
  nextChange = sp.from;
@@ -4902,10 +5004,11 @@ window.CodeMirror = (function() {
4902
5004
  clearHistory: function() {this.history = makeHistory(this.history.maxGeneration);},
4903
5005
 
4904
5006
  markClean: function() {
4905
- this.cleanGeneration = this.changeGeneration();
5007
+ this.cleanGeneration = this.changeGeneration(true);
4906
5008
  },
4907
- changeGeneration: function() {
4908
- this.history.lastOp = this.history.lastOrigin = null;
5009
+ changeGeneration: function(forceSplit) {
5010
+ if (forceSplit)
5011
+ this.history.lastOp = this.history.lastOrigin = null;
4909
5012
  return this.history.generation;
4910
5013
  },
4911
5014
  isClean: function (gen) {
@@ -4927,7 +5030,8 @@ window.CodeMirror = (function() {
4927
5030
  },
4928
5031
  setBookmark: function(pos, options) {
4929
5032
  var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
4930
- insertLeft: options && options.insertLeft};
5033
+ insertLeft: options && options.insertLeft,
5034
+ clearWhenEmpty: false};
4931
5035
  pos = clipPos(this, pos);
4932
5036
  return markText(this, pos, pos, realOpts, "bookmark");
4933
5037
  },
@@ -5208,10 +5312,10 @@ window.CodeMirror = (function() {
5208
5312
  anchorBefore: doc.sel.anchor, headBefore: doc.sel.head,
5209
5313
  anchorAfter: selAfter.anchor, headAfter: selAfter.head};
5210
5314
  hist.done.push(cur);
5211
- hist.generation = ++hist.maxGeneration;
5212
5315
  while (hist.done.length > hist.undoDepth)
5213
5316
  hist.done.shift();
5214
5317
  }
5318
+ hist.generation = ++hist.maxGeneration;
5215
5319
  hist.lastTime = time;
5216
5320
  hist.lastOp = opId;
5217
5321
  hist.lastOrigin = change.origin;
@@ -5507,7 +5611,8 @@ window.CodeMirror = (function() {
5507
5611
  return true;
5508
5612
  }
5509
5613
 
5510
- var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\u1DC0–\u1DFF\u20D0–\u20FF\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff\uFE20–\uFE2F]/;
5614
+ var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;
5615
+ function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); }
5511
5616
 
5512
5617
  // DOM UTILITIES
5513
5618
 
@@ -5580,7 +5685,7 @@ window.CodeMirror = (function() {
5580
5685
  if (/\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i))) return true;
5581
5686
  if (i > 2 && /[\d\.,]/.test(str.charAt(i - 2)) && /[\d\.,]/.test(str.charAt(i))) return false;
5582
5687
  }
5583
- return /[~!#%&*)=+}\]\\|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));
5688
+ return /[~!#%&*)=+}\]\\|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|\u2026[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));
5584
5689
  };
5585
5690
 
5586
5691
  var knownScrollbarWidth;
@@ -5648,14 +5753,14 @@ window.CodeMirror = (function() {
5648
5753
  var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
5649
5754
  19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
5650
5755
  36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
5651
- 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete",
5652
- 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
5653
- 221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home",
5654
- 63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"};
5756
+ 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", 107: "=", 109: "-", 127: "Delete",
5757
+ 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
5758
+ 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
5759
+ 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"};
5655
5760
  CodeMirror.keyNames = keyNames;
5656
5761
  (function() {
5657
5762
  // Number keys
5658
- for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i);
5763
+ for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i);
5659
5764
  // Alphabetic keys
5660
5765
  for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
5661
5766
  // Function keys
@@ -5712,29 +5817,29 @@ window.CodeMirror = (function() {
5712
5817
  }
5713
5818
  var bidiOther;
5714
5819
  function getBidiPartAt(order, pos) {
5820
+ bidiOther = null;
5715
5821
  for (var i = 0, found; i < order.length; ++i) {
5716
5822
  var cur = order[i];
5717
- if (cur.from < pos && cur.to > pos) { bidiOther = null; return i; }
5718
- if (cur.from == pos || cur.to == pos) {
5823
+ if (cur.from < pos && cur.to > pos) return i;
5824
+ if ((cur.from == pos || cur.to == pos)) {
5719
5825
  if (found == null) {
5720
5826
  found = i;
5721
5827
  } else if (compareBidiLevel(order, cur.level, order[found].level)) {
5722
- bidiOther = found;
5828
+ if (cur.from != cur.to) bidiOther = found;
5723
5829
  return i;
5724
5830
  } else {
5725
- bidiOther = i;
5831
+ if (cur.from != cur.to) bidiOther = i;
5726
5832
  return found;
5727
5833
  }
5728
5834
  }
5729
5835
  }
5730
- bidiOther = null;
5731
5836
  return found;
5732
5837
  }
5733
5838
 
5734
5839
  function moveInLine(line, pos, dir, byUnit) {
5735
5840
  if (!byUnit) return pos + dir;
5736
5841
  do pos += dir;
5737
- while (pos > 0 && isExtendingChar.test(line.text.charAt(pos)));
5842
+ while (pos > 0 && isExtendingChar(line.text.charAt(pos)));
5738
5843
  return pos;
5739
5844
  }
5740
5845
 
@@ -5769,7 +5874,7 @@ window.CodeMirror = (function() {
5769
5874
 
5770
5875
  function moveLogically(line, start, dir, byUnit) {
5771
5876
  var target = start + dir;
5772
- if (byUnit) while (target > 0 && isExtendingChar.test(line.text.charAt(target))) target += dir;
5877
+ if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir;
5773
5878
  return target < 0 || target > line.text.length ? null : target;
5774
5879
  }
5775
5880
 
@@ -5861,7 +5966,7 @@ window.CodeMirror = (function() {
5861
5966
  if (type == ",") types[i] = "N";
5862
5967
  else if (type == "%") {
5863
5968
  for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
5864
- var replace = (i && types[i-1] == "!") || (end < len - 1 && types[end] == "1") ? "1" : "N";
5969
+ var replace = (i && types[i-1] == "!") || (end < len && types[end] == "1") ? "1" : "N";
5865
5970
  for (var j = i; j < end; ++j) types[j] = replace;
5866
5971
  i = end - 1;
5867
5972
  }
@@ -5886,7 +5991,7 @@ window.CodeMirror = (function() {
5886
5991
  if (isNeutral.test(types[i])) {
5887
5992
  for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
5888
5993
  var before = (i ? types[i-1] : outerType) == "L";
5889
- var after = (end < len - 1 ? types[end] : outerType) == "L";
5994
+ var after = (end < len ? types[end] : outerType) == "L";
5890
5995
  var replace = before || after ? "L" : "R";
5891
5996
  for (var j = i; j < end; ++j) types[j] = replace;
5892
5997
  i = end - 1;
@@ -5936,7 +6041,7 @@ window.CodeMirror = (function() {
5936
6041
 
5937
6042
  // THE END
5938
6043
 
5939
- CodeMirror.version = "3.20.0";
6044
+ CodeMirror.version = "3.21.0";
5940
6045
 
5941
6046
  return CodeMirror;
5942
6047
  })();