codemirror-rails 2.22 → 2.23

Sign up to get free protection for your applications and to get access to all the features.
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"};