codemirror-rails 3.20 → 3.21

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 (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
  })();