codemirror-rails 2.22 → 2.23

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 (31) hide show
  1. data/lib/codemirror/rails/version.rb +2 -2
  2. data/vendor/assets/javascripts/codemirror.js +164 -83
  3. data/vendor/assets/javascripts/codemirror/modes/clojure.js +13 -13
  4. data/vendor/assets/javascripts/codemirror/modes/css.js +1 -1
  5. data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +1 -1
  6. data/vendor/assets/javascripts/codemirror/modes/javascript.js +3 -3
  7. data/vendor/assets/javascripts/codemirror/modes/less.js +86 -57
  8. data/vendor/assets/javascripts/codemirror/modes/markdown.js +29 -60
  9. data/vendor/assets/javascripts/codemirror/modes/properties.js +17 -11
  10. data/vendor/assets/javascripts/codemirror/modes/smarty.js +148 -0
  11. data/vendor/assets/javascripts/codemirror/modes/stex.js +15 -2
  12. data/vendor/assets/javascripts/codemirror/modes/tiddlywiki.js +41 -31
  13. data/vendor/assets/javascripts/codemirror/modes/vbscript.js +26 -0
  14. data/vendor/assets/javascripts/codemirror/modes/xml.js +2 -1
  15. data/vendor/assets/javascripts/codemirror/modes/xquery.js +448 -0
  16. data/vendor/assets/javascripts/codemirror/utils/closetag.js +174 -0
  17. data/vendor/assets/javascripts/codemirror/utils/foldcode.js +1 -1
  18. data/vendor/assets/javascripts/codemirror/utils/formatting.js +1 -1
  19. data/vendor/assets/javascripts/codemirror/utils/javascript-hint.js +4 -2
  20. data/vendor/assets/javascripts/codemirror/utils/simple-hint.js +6 -0
  21. data/vendor/assets/stylesheets/codemirror.css +2 -0
  22. data/vendor/assets/stylesheets/codemirror/modes/tiddlywiki.css +1 -1
  23. data/vendor/assets/stylesheets/codemirror/themes/eclipse.css +1 -1
  24. data/vendor/assets/stylesheets/codemirror/themes/elegant.css +2 -2
  25. data/vendor/assets/stylesheets/codemirror/themes/lesser-dark.css +45 -0
  26. data/vendor/assets/stylesheets/codemirror/themes/neat.css +3 -3
  27. data/vendor/assets/stylesheets/codemirror/themes/rubyblue.css +1 -1
  28. data/vendor/assets/stylesheets/codemirror/themes/xq-dark.css +46 -0
  29. metadata +10 -6
  30. data/vendor/assets/javascripts/codemirror/modes/rpm-spec.css +0 -5
  31. data/vendor/assets/stylesheets/codemirror/modes/properties.css +0 -3
@@ -1,6 +1,6 @@
1
1
  module Codemirror
2
2
  module Rails
3
- VERSION = '2.22'
4
- CODEMIRROR_VERSION = '2.22'
3
+ VERSION = '2.23'
4
+ CODEMIRROR_VERSION = '2.23'
5
5
  end
6
6
  end
@@ -1,4 +1,4 @@
1
- // CodeMirror version 2.22
1
+ // CodeMirror version 2.23
2
2
  //
3
3
  // All functions that need access to the editor's state live inside
4
4
  // the CodeMirror function. Below that, at the bottom of the file,
@@ -15,9 +15,8 @@ var CodeMirror = (function() {
15
15
  if (defaults.hasOwnProperty(opt))
16
16
  options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];
17
17
 
18
- var targetDocument = options["document"];
19
18
  // The element in which the editor lives.
20
- var wrapper = targetDocument.createElement("div");
19
+ var wrapper = document.createElement("div");
21
20
  wrapper.className = "CodeMirror" + (options.lineWrapping ? " CodeMirror-wrap" : "");
22
21
  // This mess creates the base DOM structure for the editor.
23
22
  wrapper.innerHTML =
@@ -48,7 +47,10 @@ var CodeMirror = (function() {
48
47
  if (!webkit) lineSpace.draggable = true;
49
48
  lineSpace.style.outline = "none";
50
49
  if (options.tabindex != null) input.tabIndex = options.tabindex;
50
+ if (options.autofocus) focusInput();
51
51
  if (!options.gutter && !options.lineNumbers) gutter.style.display = "none";
52
+ // Needed to handle Tab key in KHTML
53
+ if (khtml) inputDiv.style.height = "1px", inputDiv.style.position = "absolute";
52
54
 
53
55
  // Check for problem with IE innerHTML not working when we have a
54
56
  // P (or similar) parent node.
@@ -81,12 +83,13 @@ var CodeMirror = (function() {
81
83
  gutterDirty, callbacks;
82
84
  // Current visible range (may be bigger than the view window).
83
85
  var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0;
84
- // bracketHighlighted is used to remember that a backet has been
86
+ // bracketHighlighted is used to remember that a bracket has been
85
87
  // marked.
86
88
  var bracketHighlighted;
87
89
  // Tracks the maximum line length so that the horizontal scrollbar
88
90
  // can be kept static when scrolling.
89
91
  var maxLine = "", maxWidth;
92
+ var tabCache = {};
90
93
 
91
94
  // Initialize the content.
92
95
  operation(function(){setValue(options.value || ""); updateInput = false;})();
@@ -124,10 +127,16 @@ var CodeMirror = (function() {
124
127
  if (!options.readOnly) replaceSelection("");
125
128
  }));
126
129
 
130
+ // Needed to handle Tab key in KHTML
131
+ if (khtml) connect(code, "mouseup", function() {
132
+ if (document.activeElement == input) input.blur();
133
+ focusInput();
134
+ });
135
+
127
136
  // IE throws unspecified error in certain cases, when
128
137
  // trying to access activeElement before onload
129
- var hasFocus; try { hasFocus = (targetDocument.activeElement == input); } catch(e) { }
130
- if (hasFocus) setTimeout(onFocus, 20);
138
+ var hasFocus; try { hasFocus = (document.activeElement == input); } catch(e) { }
139
+ if (hasFocus || options.autofocus) setTimeout(onFocus, 20);
131
140
  else onBlur();
132
141
 
133
142
  function isLine(l) {return l >= 0 && l < doc.size;}
@@ -178,17 +187,23 @@ var CodeMirror = (function() {
178
187
  line = clipLine(line == null ? doc.size - 1: line);
179
188
  return getStateBefore(line + 1);
180
189
  },
181
- cursorCoords: function(start){
190
+ cursorCoords: function(start, mode) {
182
191
  if (start == null) start = sel.inverted;
183
- return pageCoords(start ? sel.from : sel.to);
192
+ return this.charCoords(start ? sel.from : sel.to, mode);
193
+ },
194
+ charCoords: function(pos, mode) {
195
+ pos = clipPos(pos);
196
+ if (mode == "local") return localCoords(pos, false);
197
+ if (mode == "div") return localCoords(pos, true);
198
+ return pageCoords(pos);
184
199
  },
185
- charCoords: function(pos){return pageCoords(clipPos(pos));},
186
200
  coordsChar: function(coords) {
187
201
  var off = eltOffset(lineSpace);
188
202
  return coordsChar(coords.x - off.left, coords.y - off.top);
189
203
  },
190
204
  markText: operation(markText),
191
205
  setBookmark: setBookmark,
206
+ findMarksAt: findMarksAt,
192
207
  setMarker: operation(addGutterMarker),
193
208
  clearMarker: operation(removeGutterMarker),
194
209
  setLineClass: operation(setLineClass),
@@ -256,6 +271,7 @@ var CodeMirror = (function() {
256
271
  replaceRange: operation(replaceRange),
257
272
  getRange: function(from, to) {return getRange(clipPos(from), clipPos(to));},
258
273
 
274
+ triggerOnKeyDown: operation(onKeyDown),
259
275
  execCommand: function(cmd) {return commands[cmd](instance);},
260
276
  // Stuff used by commands, probably not much use to outside code.
261
277
  moveH: operation(moveH),
@@ -373,7 +389,7 @@ var CodeMirror = (function() {
373
389
  !posLess(start, sel.from) && !posLess(sel.to, start)) {
374
390
  // Let the drag handler handle this.
375
391
  if (webkit) lineSpace.draggable = true;
376
- var up = connect(targetDocument, "mouseup", operation(function(e2) {
392
+ var up = connect(document, "mouseup", operation(function(e2) {
377
393
  if (webkit) lineSpace.draggable = false;
378
394
  draggingText = false;
379
395
  up();
@@ -384,6 +400,8 @@ var CodeMirror = (function() {
384
400
  }
385
401
  }), true);
386
402
  draggingText = true;
403
+ // IE's approach to draggable
404
+ if (lineSpace.dragDrop) lineSpace.dragDrop();
387
405
  return;
388
406
  }
389
407
  e_preventDefault(e);
@@ -402,12 +420,7 @@ var CodeMirror = (function() {
402
420
  }
403
421
  }
404
422
 
405
- var move = connect(targetDocument, "mousemove", operation(function(e) {
406
- clearTimeout(going);
407
- e_preventDefault(e);
408
- extend(e);
409
- }), true);
410
- var up = connect(targetDocument, "mouseup", operation(function(e) {
423
+ function done(e) {
411
424
  clearTimeout(going);
412
425
  var cur = posFromMouse(e);
413
426
  if (cur) setSelectionUser(start, cur);
@@ -415,7 +428,14 @@ var CodeMirror = (function() {
415
428
  focusInput();
416
429
  updateInput = true;
417
430
  move(); up();
431
+ }
432
+ var move = connect(document, "mousemove", operation(function(e) {
433
+ clearTimeout(going);
434
+ e_preventDefault(e);
435
+ if (!ie && !e_button(e)) done(e);
436
+ else extend(e);
418
437
  }), true);
438
+ var up = connect(document, "mouseup", operation(done), true);
419
439
  }
420
440
  function onDoubleClick(e) {
421
441
  for (var n = e_target(e); n != wrapper; n = n.parentNode)
@@ -464,11 +484,14 @@ var CodeMirror = (function() {
464
484
  }
465
485
  function onDragStart(e) {
466
486
  var txt = getSelection();
467
- // Disabled until further notice. Doesn't work on most browsers,
468
- // and crashes Safari (issue #332).
469
- //htmlEscape(txt);
470
- //e.dataTransfer.setDragImage(escapeElement, 0, 0);
471
487
  e.dataTransfer.setData("Text", txt);
488
+
489
+ // Use dummy image instead of default browsers image.
490
+ if (gecko || chrome) {
491
+ var img = document.createElement('img');
492
+ img.scr = 'data:image/gif;base64,R0lGODdhAgACAIAAAAAAAP///ywAAAAAAgACAAACAoRRADs='; //1x1 image
493
+ e.dataTransfer.setDragImage(img, 0, 0);
494
+ }
472
495
  }
473
496
 
474
497
  function doHandleBinding(bound, dropShift) {
@@ -506,13 +529,19 @@ var CodeMirror = (function() {
506
529
  if (e_prop(e, "ctrlKey")) name = "Ctrl-" + name;
507
530
  if (e_prop(e, "metaKey")) name = "Cmd-" + name;
508
531
 
509
- if (e_prop(e, "shiftKey"))
532
+ if (e_prop(e, "shiftKey")) {
510
533
  handled = lookupKey("Shift-" + name, options.extraKeys, options.keyMap,
511
- function(b) {return doHandleBinding(b, true);});
512
- if (!handled)
534
+ function(b) {return doHandleBinding(b, true);})
535
+ || lookupKey(name, options.extraKeys, options.keyMap, function(b) {
536
+ if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(b);
537
+ });
538
+ } else {
513
539
  handled = lookupKey(name, options.extraKeys, options.keyMap, doHandleBinding);
514
-
515
- if (handled) e_preventDefault(e);
540
+ }
541
+ if (handled) {
542
+ e_preventDefault(e);
543
+ if (ie) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
544
+ }
516
545
  return handled;
517
546
  }
518
547
  function handleCharBinding(e, ch) {
@@ -545,7 +574,7 @@ var CodeMirror = (function() {
545
574
  if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
546
575
  var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode");
547
576
  if (window.opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
548
- if (window.opera && !e.which && handleKeyBinding(e)) return;
577
+ if (((window.opera && !e.which) || khtml) && handleKeyBinding(e)) return;
549
578
  var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
550
579
  if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) {
551
580
  if (mode.electricChars.indexOf(ch) > -1)
@@ -837,11 +866,11 @@ var CodeMirror = (function() {
837
866
  return scrollIntoView(x, cursor.y, x, cursor.yBot);
838
867
  }
839
868
  function scrollIntoView(x1, y1, x2, y2) {
840
- var pl = paddingLeft(), pt = paddingTop(), lh = textHeight();
869
+ var pl = paddingLeft(), pt = paddingTop();
841
870
  y1 += pt; y2 += pt; x1 += pl; x2 += pl;
842
871
  var screen = scroller.clientHeight, screentop = scroller.scrollTop, scrolled = false, result = true;
843
- if (y1 < screentop) {scroller.scrollTop = Math.max(0, y1 - 2*lh); scrolled = true;}
844
- else if (y2 > screentop + screen) {scroller.scrollTop = y2 + lh - screen; scrolled = true;}
872
+ if (y1 < screentop) {scroller.scrollTop = Math.max(0, y1); scrolled = true;}
873
+ else if (y2 > screentop + screen) {scroller.scrollTop = y2 - screen; scrolled = true;}
845
874
 
846
875
  var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft;
847
876
  var gutterw = options.fixedGutter ? gutter.clientWidth : 0;
@@ -921,7 +950,7 @@ var CodeMirror = (function() {
921
950
  throw new Error("BAD PATCH! " + JSON.stringify(intact) + " size=" + (showingTo - showingFrom) +
922
951
  " nodes=" + lineDiv.childNodes.length);
923
952
 
924
- if (options.lineWrapping) {
953
+ function checkHeights() {
925
954
  maxWidth = scroller.clientWidth;
926
955
  var curNode = lineDiv.firstChild, heightChanged = false;
927
956
  doc.iter(showingFrom, showingTo, function(line) {
@@ -936,6 +965,11 @@ var CodeMirror = (function() {
936
965
  });
937
966
  if (heightChanged)
938
967
  code.style.height = (doc.height * th + 2 * paddingTop()) + "px";
968
+ return heightChanged;
969
+ }
970
+
971
+ if (options.lineWrapping) {
972
+ checkHeights();
939
973
  } else {
940
974
  if (maxWidth == null) maxWidth = stringWidth(maxLine);
941
975
  if (maxWidth > scroller.clientWidth) {
@@ -947,8 +981,12 @@ var CodeMirror = (function() {
947
981
  lineSpace.style.width = code.style.width = "";
948
982
  }
949
983
  }
984
+
950
985
  gutter.style.display = gutterDisplay;
951
- if (different || gutterDirty) updateGutter();
986
+ if (different || gutterDirty) {
987
+ // If the gutter grew in size, re-check heights. If those changed, re-draw gutter.
988
+ updateGutter() && options.lineWrapping && checkHeights() && updateGutter();
989
+ }
952
990
  updateSelection();
953
991
  if (!suppressCallback && options.onUpdate) options.onUpdate(instance);
954
992
  return true;
@@ -996,16 +1034,17 @@ var CodeMirror = (function() {
996
1034
  }
997
1035
  // This pass fills in the lines that actually changed.
998
1036
  var nextIntact = intact.shift(), curNode = lineDiv.firstChild, j = from;
999
- var scratch = targetDocument.createElement("div"), newElt;
1037
+ var scratch = document.createElement("div");
1000
1038
  doc.iter(from, to, function(line) {
1001
1039
  if (nextIntact && nextIntact.to == j) nextIntact = intact.shift();
1002
1040
  if (!nextIntact || nextIntact.from > j) {
1003
1041
  if (line.hidden) var html = scratch.innerHTML = "<pre></pre>";
1004
1042
  else {
1005
- var html = '<pre>' + line.getHTML(makeTab) + '</pre>';
1043
+ var html = '<pre' + (line.className ? ' class="' + line.className + '"' : '') + '>'
1044
+ + line.getHTML(makeTab) + '</pre>';
1006
1045
  // Kludge to make sure the styled element lies behind the selection (by z-index)
1007
- if (line.className)
1008
- html = '<div style="position: relative"><pre class="' + line.className +
1046
+ if (line.bgClassName)
1047
+ html = '<div style="position: relative"><pre class="' + line.bgClassName +
1009
1048
  '" style="position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -2">&#160;</pre>' + html + "</div>";
1010
1049
  }
1011
1050
  scratch.innerHTML = html;
@@ -1021,7 +1060,7 @@ var CodeMirror = (function() {
1021
1060
  if (!options.gutter && !options.lineNumbers) return;
1022
1061
  var hText = mover.offsetHeight, hEditor = scroller.clientHeight;
1023
1062
  gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + "px";
1024
- var html = [], i = showingFrom;
1063
+ var html = [], i = showingFrom, normalNode;
1025
1064
  doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) {
1026
1065
  if (line.hidden) {
1027
1066
  html.push("<pre></pre>");
@@ -1035,17 +1074,24 @@ var CodeMirror = (function() {
1035
1074
  html.push((marker && marker.style ? '<pre class="' + marker.style + '">' : "<pre>"), text);
1036
1075
  for (var j = 1; j < line.height; ++j) html.push("<br/>&#160;");
1037
1076
  html.push("</pre>");
1077
+ if (!marker) normalNode = i;
1038
1078
  }
1039
1079
  ++i;
1040
1080
  });
1041
1081
  gutter.style.display = "none";
1042
1082
  gutterText.innerHTML = html.join("");
1043
- var minwidth = String(doc.size).length, firstNode = gutterText.firstChild, val = eltText(firstNode), pad = "";
1044
- while (val.length + pad.length < minwidth) pad += "\u00a0";
1045
- if (pad) firstNode.insertBefore(targetDocument.createTextNode(pad), firstNode.firstChild);
1083
+ // Make sure scrolling doesn't cause number gutter size to pop
1084
+ if (normalNode != null) {
1085
+ var node = gutterText.childNodes[normalNode - showingFrom];
1086
+ var minwidth = String(doc.size).length, val = eltText(node), pad = "";
1087
+ while (val.length + pad.length < minwidth) pad += "\u00a0";
1088
+ if (pad) node.insertBefore(document.createTextNode(pad), node.firstChild);
1089
+ }
1046
1090
  gutter.style.display = "";
1091
+ var resized = Math.abs((parseInt(lineSpace.style.marginLeft) || 0) - gutter.offsetWidth) > 2;
1047
1092
  lineSpace.style.marginLeft = gutter.offsetWidth + "px";
1048
1093
  gutterDirty = false;
1094
+ return resized;
1049
1095
  }
1050
1096
  function updateSelection() {
1051
1097
  var collapsed = posEq(sel.from, sel.to);
@@ -1066,16 +1112,18 @@ var CodeMirror = (function() {
1066
1112
  html += '<div class="CodeMirror-selected" style="position: absolute; left: ' + left +
1067
1113
  'px; top: ' + top + 'px; right: ' + right + 'px; height: ' + height + 'px"></div>';
1068
1114
  }
1115
+ var clientWidth = lineSpace.clientWidth || lineSpace.offsetWidth;
1116
+ var clientHeight = lineSpace.clientHeight || lineSpace.offsetHeight;
1069
1117
  if (sel.from.ch && fromPos.y >= 0) {
1070
- var right = sameLine ? lineSpace.clientWidth - toPos.x : 0;
1118
+ var right = sameLine ? clientWidth - toPos.x : 0;
1071
1119
  add(fromPos.x, fromPos.y, right, th);
1072
1120
  }
1073
1121
  var middleStart = Math.max(0, fromPos.y + (sel.from.ch ? th : 0));
1074
- var middleHeight = Math.min(toPos.y, lineSpace.clientHeight) - middleStart;
1122
+ var middleHeight = Math.min(toPos.y, clientHeight) - middleStart;
1075
1123
  if (middleHeight > 0.2 * th)
1076
1124
  add(0, middleStart, 0, middleHeight);
1077
- if ((!sameLine || !sel.from.ch) && toPos.y < lineSpace.clientHeight - .5 * th)
1078
- add(0, toPos.y, lineSpace.clientWidth - toPos.x, th);
1125
+ if ((!sameLine || !sel.from.ch) && toPos.y < clientHeight - .5 * th)
1126
+ add(0, toPos.y, clientWidth - toPos.x, th);
1079
1127
  selectionDiv.innerHTML = html;
1080
1128
  cursor.style.display = "none";
1081
1129
  selectionDiv.style.display = "";
@@ -1105,7 +1153,12 @@ var CodeMirror = (function() {
1105
1153
  if (posLess(to, from)) {var tmp = to; to = from; from = tmp;}
1106
1154
 
1107
1155
  // Skip over hidden lines.
1108
- if (from.line != oldFrom) from = skipHidden(from, oldFrom, sel.from.ch);
1156
+ if (from.line != oldFrom) {
1157
+ var from1 = skipHidden(from, oldFrom, sel.from.ch);
1158
+ // If there is no non-hidden line left, force visibility on current line
1159
+ if (!from1) setLineHidden(from.line, false);
1160
+ else from = from1;
1161
+ }
1109
1162
  if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch);
1110
1163
 
1111
1164
  if (posEq(from, to)) sel.inverted = false;
@@ -1114,7 +1167,7 @@ var CodeMirror = (function() {
1114
1167
 
1115
1168
  if (options.autoClearEmptyLines && posEq(sel.from, sel.to)) {
1116
1169
  var head = sel.inverted ? from : to;
1117
- if (head.line != sel.from.line) {
1170
+ if (head.line != sel.from.line && sel.from.line < doc.size) {
1118
1171
  var oldLine = getLine(sel.from.line);
1119
1172
  if (/^\s+$/.test(oldLine.text))
1120
1173
  setTimeout(operation(function() {
@@ -1209,6 +1262,7 @@ var CodeMirror = (function() {
1209
1262
  if (unit == "page") dist = Math.min(scroller.clientHeight, window.innerHeight || document.documentElement.clientHeight);
1210
1263
  else if (unit == "line") dist = textHeight();
1211
1264
  var target = coordsChar(pos.x, pos.y + dist * dir + 2);
1265
+ if (unit == "page") scroller.scrollTop += localCoords(target, true).y - pos.y;
1212
1266
  setCursor(target.line, target.ch, true);
1213
1267
  goalColumn = pos.x;
1214
1268
  }
@@ -1295,9 +1349,10 @@ var CodeMirror = (function() {
1295
1349
  changes.push({from: 0, to: doc.size});
1296
1350
  }
1297
1351
  function makeTab(col) {
1298
- var w = options.tabSize - col % options.tabSize;
1352
+ var w = options.tabSize - col % options.tabSize, cached = tabCache[w];
1353
+ if (cached) return cached;
1299
1354
  for (var str = '<span class="cm-tab">', i = 0; i < w; ++i) str += " ";
1300
- return {html: str + "</span>", width: w};
1355
+ return (tabCache[w] = {html: str + "</span>", width: w});
1301
1356
  }
1302
1357
  function themeChanged() {
1303
1358
  scroller.className = scroller.className.replace(/\s*cm-s-\w+/g, "") +
@@ -1313,7 +1368,7 @@ var CodeMirror = (function() {
1313
1368
  var lineN = lineNo(line);
1314
1369
  min = Math.min(min, lineN); max = Math.max(max, lineN);
1315
1370
  for (var j = 0; j < mk.length; ++j)
1316
- if (mk[j].set == this.set) mk.splice(j--, 1);
1371
+ if (mk[j].marker == this) mk.splice(j--, 1);
1317
1372
  }
1318
1373
  if (min != Infinity)
1319
1374
  changes.push({from: min, to: max + 1});
@@ -1324,7 +1379,7 @@ var CodeMirror = (function() {
1324
1379
  var line = this.set[i], mk = line.marked;
1325
1380
  for (var j = 0; j < mk.length; ++j) {
1326
1381
  var mark = mk[j];
1327
- if (mark.set == this.set) {
1382
+ if (mark.marker == this) {
1328
1383
  if (mark.from != null || mark.to != null) {
1329
1384
  var found = lineNo(line);
1330
1385
  if (found != null) {
@@ -1341,8 +1396,9 @@ var CodeMirror = (function() {
1341
1396
  function markText(from, to, className) {
1342
1397
  from = clipPos(from); to = clipPos(to);
1343
1398
  var tm = new TextMarker();
1399
+ if (!posLess(from, to)) return tm;
1344
1400
  function add(line, from, to, className) {
1345
- getLine(line).addMark(new MarkedText(from, to, className, tm.set));
1401
+ getLine(line).addMark(new MarkedText(from, to, className, tm));
1346
1402
  }
1347
1403
  if (from.line == to.line) add(from.line, from.ch, to.ch, className);
1348
1404
  else {
@@ -1362,6 +1418,19 @@ var CodeMirror = (function() {
1362
1418
  return bm;
1363
1419
  }
1364
1420
 
1421
+ function findMarksAt(pos) {
1422
+ pos = clipPos(pos);
1423
+ var markers = [], marked = getLine(pos.line).marked;
1424
+ if (!marked) return markers;
1425
+ for (var i = 0, e = marked.length; i < e; ++i) {
1426
+ var m = marked[i];
1427
+ if ((m.from == null || m.from <= pos.ch) &&
1428
+ (m.to == null || m.to >= pos.ch))
1429
+ markers.push(m.marker || m);
1430
+ }
1431
+ return markers;
1432
+ }
1433
+
1365
1434
  function addGutterMarker(line, text, className) {
1366
1435
  if (typeof line == "number") line = getLine(clipLine(line));
1367
1436
  line.gutterMarker = {text: text, style: className};
@@ -1383,10 +1452,11 @@ var CodeMirror = (function() {
1383
1452
  else return null;
1384
1453
  return line;
1385
1454
  }
1386
- function setLineClass(handle, className) {
1455
+ function setLineClass(handle, className, bgClassName) {
1387
1456
  return changeLine(handle, function(line) {
1388
- if (line.className != className) {
1457
+ if (line.className != className || line.bgClassName != bgClassName) {
1389
1458
  line.className = className;
1459
+ line.bgClassName = bgClassName;
1390
1460
  return true;
1391
1461
  }
1392
1462
  });
@@ -1400,6 +1470,8 @@ var CodeMirror = (function() {
1400
1470
  if (hidden && (fline == no || tline == no)) {
1401
1471
  var from = fline == no ? skipHidden({line: fline, ch: 0}, fline, 0) : sel.from;
1402
1472
  var to = tline == no ? skipHidden({line: tline, ch: 0}, tline, 0) : sel.to;
1473
+ // Can't hide the last visible line, we'd have no place to put the cursor
1474
+ if (!to) return;
1403
1475
  setSelection(from, to);
1404
1476
  }
1405
1477
  return (gutterDirty = true);
@@ -1420,7 +1492,7 @@ var CodeMirror = (function() {
1420
1492
  }
1421
1493
  var marker = line.gutterMarker;
1422
1494
  return {line: n, handle: line, text: line.text, markerText: marker && marker.text,
1423
- markerClass: marker && marker.style, lineClass: line.className};
1495
+ markerClass: marker && marker.style, lineClass: line.className, bgClass: line.bgClassName};
1424
1496
  }
1425
1497
 
1426
1498
  function stringWidth(str) {
@@ -1464,7 +1536,7 @@ var CodeMirror = (function() {
1464
1536
  var extra = "";
1465
1537
  // Include extra text at the end to make sure the measured line is wrapped in the right way.
1466
1538
  if (options.lineWrapping) {
1467
- var end = line.text.indexOf(" ", ch + 2);
1539
+ var end = line.text.indexOf(" ", ch + 6);
1468
1540
  extra = htmlEscape(line.text.slice(ch + 1, end < 0 ? line.text.length : end + (ie ? 5 : 0)));
1469
1541
  }
1470
1542
  measure.innerHTML = "<pre>" + line.getHTML(makeTab, ch) +
@@ -1823,7 +1895,7 @@ var CodeMirror = (function() {
1823
1895
  pollInterval: 100,
1824
1896
  undoDepth: 40,
1825
1897
  tabindex: null,
1826
- document: window.document
1898
+ autofocus: null
1827
1899
  };
1828
1900
 
1829
1901
  var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
@@ -1831,7 +1903,7 @@ var CodeMirror = (function() {
1831
1903
  var win = /Win/.test(navigator.platform);
1832
1904
 
1833
1905
  // Known modes, by name and by MIME
1834
- var modes = {}, mimeModes = {};
1906
+ var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
1835
1907
  CodeMirror.defineMode = function(name, mode) {
1836
1908
  if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
1837
1909
  modes[name] = mode;
@@ -1842,6 +1914,8 @@ var CodeMirror = (function() {
1842
1914
  CodeMirror.resolveMode = function(spec) {
1843
1915
  if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
1844
1916
  spec = mimeModes[spec];
1917
+ else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec))
1918
+ return CodeMirror.resolveMode("application/xml");
1845
1919
  if (typeof spec == "string") return {name: spec};
1846
1920
  else return spec || {name: "null"};
1847
1921
  };
@@ -1926,7 +2000,7 @@ var CodeMirror = (function() {
1926
2000
  keyMap.basic = {
1927
2001
  "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
1928
2002
  "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
1929
- "Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "indentMore", "Shift-Tab": "indentLess",
2003
+ "Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "insertTab", "Shift-Tab": "indentAuto",
1930
2004
  "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
1931
2005
  };
1932
2006
  // Note that the save and find-related commands aren't defined by
@@ -1937,6 +2011,7 @@ var CodeMirror = (function() {
1937
2011
  "Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
1938
2012
  "Ctrl-Backspace": "delWordLeft", "Ctrl-Delete": "delWordRight", "Ctrl-S": "save", "Ctrl-F": "find",
1939
2013
  "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
2014
+ "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
1940
2015
  fallthrough: "basic"
1941
2016
  };
1942
2017
  keyMap.macDefault = {
@@ -1945,6 +2020,7 @@ var CodeMirror = (function() {
1945
2020
  "Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordLeft",
1946
2021
  "Ctrl-Alt-Backspace": "delWordRight", "Alt-Delete": "delWordRight", "Cmd-S": "save", "Cmd-F": "find",
1947
2022
  "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
2023
+ "Cmd-[": "indentLess", "Cmd-]": "indentMore",
1948
2024
  fallthrough: ["basic", "emacsy"]
1949
2025
  };
1950
2026
  keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
@@ -1987,6 +2063,8 @@ var CodeMirror = (function() {
1987
2063
  options.value = textarea.value;
1988
2064
  if (!options.tabindex && textarea.tabindex)
1989
2065
  options.tabindex = textarea.tabindex;
2066
+ if (options.autofocus == null && textarea.getAttribute("autofocus") != null)
2067
+ options.autofocus = true;
1990
2068
 
1991
2069
  function save() {textarea.value = instance.getValue();}
1992
2070
  if (textarea.form) {
@@ -2098,34 +2176,34 @@ var CodeMirror = (function() {
2098
2176
  };
2099
2177
  CodeMirror.StringStream = StringStream;
2100
2178
 
2101
- function MarkedText(from, to, className, set) {
2102
- this.from = from; this.to = to; this.style = className; this.set = set;
2179
+ function MarkedText(from, to, className, marker) {
2180
+ this.from = from; this.to = to; this.style = className; this.marker = marker;
2103
2181
  }
2104
2182
  MarkedText.prototype = {
2105
- attach: function(line) { this.set.push(line); },
2183
+ attach: function(line) { this.marker.set.push(line); },
2106
2184
  detach: function(line) {
2107
- var ix = indexOf(this.set, line);
2108
- if (ix > -1) this.set.splice(ix, 1);
2185
+ var ix = indexOf(this.marker.set, line);
2186
+ if (ix > -1) this.marker.set.splice(ix, 1);
2109
2187
  },
2110
2188
  split: function(pos, lenBefore) {
2111
2189
  if (this.to <= pos && this.to != null) return null;
2112
2190
  var from = this.from < pos || this.from == null ? null : this.from - pos + lenBefore;
2113
2191
  var to = this.to == null ? null : this.to - pos + lenBefore;
2114
- return new MarkedText(from, to, this.style, this.set);
2192
+ return new MarkedText(from, to, this.style, this.marker);
2115
2193
  },
2116
- dup: function() { return new MarkedText(null, null, this.style, this.set); },
2194
+ dup: function() { return new MarkedText(null, null, this.style, this.marker); },
2117
2195
  clipTo: function(fromOpen, from, toOpen, to, diff) {
2118
- if (this.from != null && this.from >= from)
2119
- this.from = Math.max(to, this.from) + diff;
2120
- if (this.to != null && this.to > from)
2121
- this.to = to < this.to ? this.to + diff : from;
2122
2196
  if (fromOpen && to > this.from && (to < this.to || this.to == null))
2123
2197
  this.from = null;
2198
+ else if (this.from != null && this.from >= from)
2199
+ this.from = Math.max(to, this.from) + diff;
2124
2200
  if (toOpen && (from < this.to || this.to == null) && (from > this.from || this.from == null))
2125
2201
  this.to = null;
2202
+ else if (this.to != null && this.to > from)
2203
+ this.to = to < this.to ? this.to + diff : from;
2126
2204
  },
2127
2205
  isDead: function() { return this.from != null && this.to != null && this.from >= this.to; },
2128
- sameSet: function(x) { return this.set == x.set; }
2206
+ sameSet: function(x) { return this.marker == x.marker; }
2129
2207
  };
2130
2208
 
2131
2209
  function Bookmark(pos) {
@@ -2168,7 +2246,7 @@ var CodeMirror = (function() {
2168
2246
  this.styles = styles || [text, null];
2169
2247
  this.text = text;
2170
2248
  this.height = 1;
2171
- this.marked = this.gutterMarker = this.className = this.handlers = null;
2249
+ this.marked = this.gutterMarker = this.className = this.bgClassName = this.handlers = null;
2172
2250
  this.stateAfter = this.parent = this.hidden = null;
2173
2251
  }
2174
2252
  Line.inheritMarks = function(text, orig) {
@@ -2214,6 +2292,7 @@ var CodeMirror = (function() {
2214
2292
  if (newmark) {
2215
2293
  if (!taken.marked) taken.marked = [];
2216
2294
  taken.marked.push(newmark); newmark.attach(taken);
2295
+ if (newmark == mark) mk.splice(i--, 1);
2217
2296
  }
2218
2297
  }
2219
2298
  }
@@ -2637,10 +2716,10 @@ var CodeMirror = (function() {
2637
2716
  if (start < last.start) {
2638
2717
  for (var i = last.start - start - 1; i >= 0; --i)
2639
2718
  last.old.unshift(old[i]);
2640
- last.added += last.start - start;
2719
+ oldoff = Math.min(0, added - old.length);
2720
+ last.added += last.start - start + oldoff;
2641
2721
  last.start = start;
2642
- }
2643
- else if (last.start < start) {
2722
+ } else if (last.start < start) {
2644
2723
  oldoff = start - last.start;
2645
2724
  added += oldoff;
2646
2725
  }
@@ -2707,19 +2786,21 @@ var CodeMirror = (function() {
2707
2786
 
2708
2787
  var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
2709
2788
 
2710
- // Detect drag-and-drop
2711
- var dragAndDrop = function() {
2712
- // IE8 has ondragstart and ondrop properties, but doesn't seem to
2713
- // actually support ondragstart the way it's supposed to work.
2714
- if (/MSIE [1-8]\b/.test(navigator.userAgent)) return false;
2715
- var div = document.createElement('div');
2716
- return "draggable" in div;
2717
- }();
2718
-
2719
2789
  var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
2720
2790
  var ie = /MSIE \d/.test(navigator.userAgent);
2721
2791
  var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent);
2722
2792
  var webkit = /WebKit\//.test(navigator.userAgent);
2793
+ var chrome = /Chrome\//.test(navigator.userAgent);
2794
+ var khtml = /KHTML\//.test(navigator.userAgent);
2795
+
2796
+ // Detect drag-and-drop
2797
+ var dragAndDrop = function() {
2798
+ // There is *some* kind of drag-and-drop support in IE6-8, but I
2799
+ // couldn't get it to work yet.
2800
+ if (ie_lt9) return false;
2801
+ var div = document.createElement('div');
2802
+ return "draggable" in div || "dragDrop" in div;
2803
+ }();
2723
2804
 
2724
2805
  var lineSep = "\n";
2725
2806
  // Feature-detect whether newlines in textareas are converted to \r\n
@@ -2873,7 +2954,7 @@ var CodeMirror = (function() {
2873
2954
  var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
2874
2955
  19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
2875
2956
  36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
2876
- 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 186: ";", 187: "=", 188: ",",
2957
+ 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 127: "Delete", 186: ";", 187: "=", 188: ",",
2877
2958
  189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 221: "]", 222: "'", 63276: "PageUp",
2878
2959
  63277: "PageDown", 63275: "End", 63273: "Home", 63234: "Left", 63232: "Up", 63235: "Right",
2879
2960
  63233: "Down", 63302: "Insert", 63272: "Delete"};