codemirror-rails 3.14 → 3.15

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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +178 -94
  4. data/vendor/assets/javascripts/codemirror/addons/comment/comment.js +3 -3
  5. data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +3 -1
  6. data/vendor/assets/javascripts/codemirror/addons/edit/matchtags.js +51 -0
  7. data/vendor/assets/javascripts/codemirror/addons/fold/brace-fold.js +9 -6
  8. data/vendor/assets/javascripts/codemirror/addons/fold/foldcode.js +9 -4
  9. data/vendor/assets/javascripts/codemirror/addons/fold/foldgutter.js +122 -0
  10. data/vendor/assets/javascripts/codemirror/addons/fold/indent-fold.js +3 -2
  11. data/vendor/assets/javascripts/codemirror/addons/fold/xml-fold.js +24 -17
  12. data/vendor/assets/javascripts/codemirror/addons/hint/anyword-hint.js +34 -0
  13. data/vendor/assets/javascripts/codemirror/addons/hint/html-hint.js +5 -3
  14. data/vendor/assets/javascripts/codemirror/addons/hint/javascript-hint.js +7 -3
  15. data/vendor/assets/javascripts/codemirror/addons/hint/pig-hint.js +4 -2
  16. data/vendor/assets/javascripts/codemirror/addons/hint/python-hint.js +4 -2
  17. data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +6 -2
  18. data/vendor/assets/javascripts/codemirror/addons/hint/xml-hint.js +5 -2
  19. data/vendor/assets/javascripts/codemirror/addons/lint/coffeescript-lint.js +3 -2
  20. data/vendor/assets/javascripts/codemirror/addons/lint/javascript-lint.js +3 -6
  21. data/vendor/assets/javascripts/codemirror/addons/lint/json-lint.js +3 -2
  22. data/vendor/assets/javascripts/codemirror/addons/lint/lint.js +12 -6
  23. data/vendor/assets/javascripts/codemirror/addons/merge/dep/diff_match_patch.js +50 -0
  24. data/vendor/assets/javascripts/codemirror/addons/merge/merge.js +40 -24
  25. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode-standalone.js +3 -1
  26. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.node.js +3 -1
  27. data/vendor/assets/javascripts/codemirror/addons/search/match-highlighter.js +11 -9
  28. data/vendor/assets/javascripts/codemirror/addons/selection/active-line.js +1 -1
  29. data/vendor/assets/javascripts/codemirror/addons/tern/tern.js +608 -0
  30. data/vendor/assets/javascripts/codemirror/addons/tern/worker.js +39 -0
  31. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +120 -101
  32. data/vendor/assets/javascripts/codemirror/modes/clike.js +2 -1
  33. data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +2 -1
  34. data/vendor/assets/javascripts/codemirror/modes/css.js +33 -16
  35. data/vendor/assets/javascripts/codemirror/modes/groovy.js +2 -1
  36. data/vendor/assets/javascripts/codemirror/modes/jade.js +90 -0
  37. data/vendor/assets/javascripts/codemirror/modes/javascript.js +21 -18
  38. data/vendor/assets/javascripts/codemirror/modes/markdown.js +26 -1
  39. data/vendor/assets/javascripts/codemirror/modes/nginx.js +163 -0
  40. data/vendor/assets/javascripts/codemirror/modes/python.js +19 -2
  41. data/vendor/assets/javascripts/codemirror/modes/rst.js +30 -19
  42. data/vendor/assets/javascripts/codemirror/modes/ruby.js +4 -4
  43. data/vendor/assets/javascripts/codemirror/modes/rust.js +2 -1
  44. data/vendor/assets/javascripts/codemirror/modes/scss_test.js +1 -1
  45. data/vendor/assets/javascripts/codemirror/modes/smalltalk.js +12 -2
  46. data/vendor/assets/javascripts/codemirror/modes/smartymixed.js +170 -0
  47. data/vendor/assets/javascripts/codemirror/modes/sparql.js +4 -2
  48. data/vendor/assets/javascripts/codemirror/modes/vbscript.js +330 -22
  49. data/vendor/assets/javascripts/codemirror/modes/xml.js +18 -3
  50. data/vendor/assets/stylesheets/codemirror.css +10 -0
  51. data/vendor/assets/stylesheets/codemirror/addons/merge/merge.css +39 -29
  52. data/vendor/assets/stylesheets/codemirror/addons/tern/tern.css +85 -0
  53. data/vendor/assets/stylesheets/codemirror/themes/3024-day.css +33 -0
  54. data/vendor/assets/stylesheets/codemirror/themes/3024-night.css +33 -0
  55. data/vendor/assets/stylesheets/codemirror/themes/base16-dark.css +33 -0
  56. data/vendor/assets/stylesheets/codemirror/themes/base16-light.css +33 -0
  57. data/vendor/assets/stylesheets/codemirror/themes/lesser-dark.css +1 -1
  58. data/vendor/assets/stylesheets/codemirror/themes/midnight.css +5 -14
  59. data/vendor/assets/stylesheets/codemirror/themes/tomorrow-night-eighties.css +33 -0
  60. data/vendor/assets/stylesheets/codemirror/themes/vibrant-ink.css +2 -2
  61. metadata +17 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e8db830325f2938ade6c18b47a5812733158244e
4
- data.tar.gz: 018e82750853a395756b30bb752221b248239a7e
3
+ metadata.gz: b87d64cb7ae54051ff568e14699010de59f830b4
4
+ data.tar.gz: c1b9dfa59056dc0e7fa7a2dc097478013c95e6d1
5
5
  SHA512:
6
- metadata.gz: 7897de28740b56bdecf9c8ba8571ac11eb74ff6224690d9aa689bd9488f2dbb8a750e0d31548df25b045ad212b977e880c5b440db371566cdfa76c6b535d4575
7
- data.tar.gz: d9c73bfaf3cdca3cd320997bcff2759e3216afe96f2c2b979c7c5838c8ecb00a7c29f0ef094587a58d7874c990eea73540e7666f01127bacc653764de778c69c
6
+ metadata.gz: 7ca0fdfede9a60eb79b632a66bf0afb91627cf98d610a45d822a0fca46e44bcf9af84fb5ba61d3316af5cb0f8e83ed713877e2c22e06f109cfa9615d04ed740d
7
+ data.tar.gz: a489edc67eec3593cfc023f7e039b5d41b76ad7f7d7b1d54495ae348c87f704b7abb15073cf37870140595f5fbe7d35212fe30d18c592fbbf9d89c21ee9c9433
@@ -1,6 +1,6 @@
1
1
  module Codemirror
2
2
  module Rails
3
- VERSION = '3.14'
4
- CODEMIRROR_VERSION = '3.14'
3
+ VERSION = '3.15'
4
+ CODEMIRROR_VERSION = '3.15'
5
5
  end
6
6
  end
@@ -1,4 +1,4 @@
1
- // CodeMirror version 3.14
1
+ // CodeMirror version 3.15
2
2
  //
3
3
  // CodeMirror is the only global var we claim
4
4
  window.CodeMirror = (function() {
@@ -30,6 +30,7 @@ window.CodeMirror = (function() {
30
30
 
31
31
  var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
32
32
  if (opera_version) opera_version = Number(opera_version[1]);
33
+ if (opera_version && opera_version >= 15) { opera = false; webkit = true; }
33
34
  // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
34
35
  var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));
35
36
  var captureMiddleClick = gecko || (ie && !ie_lt9);
@@ -403,11 +404,12 @@ window.CodeMirror = (function() {
403
404
 
404
405
  // DISPLAY DRAWING
405
406
 
406
- function updateDisplay(cm, changes, viewPort) {
407
+ function updateDisplay(cm, changes, viewPort, forced) {
407
408
  var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
408
409
  var visible = visibleLines(cm.display, cm.doc, viewPort);
409
410
  for (;;) {
410
- if (!updateDisplayInner(cm, changes, visible)) break;
411
+ if (!updateDisplayInner(cm, changes, visible, forced)) break;
412
+ forced = false;
411
413
  updated = true;
412
414
  updateSelection(cm);
413
415
  updateScrollbars(cm);
@@ -433,7 +435,7 @@ window.CodeMirror = (function() {
433
435
  // Uses a set of changes plus the current scroll position to
434
436
  // determine which DOM updates have to be made, and makes the
435
437
  // updates.
436
- function updateDisplayInner(cm, changes, visible) {
438
+ function updateDisplayInner(cm, changes, visible, forced) {
437
439
  var display = cm.display, doc = cm.doc;
438
440
  if (!display.wrapper.clientWidth) {
439
441
  display.showingFrom = display.showingTo = doc.first;
@@ -442,7 +444,7 @@ window.CodeMirror = (function() {
442
444
  }
443
445
 
444
446
  // Bail out if the visible area is already rendered and nothing changed.
445
- if (changes.length == 0 &&
447
+ if (!forced && changes.length == 0 &&
446
448
  visible.from > display.showingFrom && visible.to < display.showingTo)
447
449
  return;
448
450
 
@@ -495,7 +497,7 @@ window.CodeMirror = (function() {
495
497
  if (range.from >= range.to) intact.splice(i--, 1);
496
498
  else intactLines += range.to - range.from;
497
499
  }
498
- if (intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
500
+ if (!forced && intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
499
501
  updateViewOffset(cm);
500
502
  return;
501
503
  }
@@ -520,6 +522,14 @@ window.CodeMirror = (function() {
520
522
  }
521
523
  display.showingFrom = from; display.showingTo = to;
522
524
 
525
+ updateHeightsInViewport(cm);
526
+ updateViewOffset(cm);
527
+
528
+ return true;
529
+ }
530
+
531
+ function updateHeightsInViewport(cm) {
532
+ var display = cm.display;
523
533
  var prevBottom = display.lineDiv.offsetTop;
524
534
  for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
525
535
  if (ie_lt8) {
@@ -539,9 +549,6 @@ window.CodeMirror = (function() {
539
549
  widgets[i].height = widgets[i].node.offsetHeight;
540
550
  }
541
551
  }
542
- updateViewOffset(cm);
543
-
544
- return true;
545
552
  }
546
553
 
547
554
  function updateViewOffset(cm) {
@@ -670,10 +677,10 @@ window.CodeMirror = (function() {
670
677
  if (!/\bCodeMirror-linewidget\b/.test(n.className)) {
671
678
  reuse.removeChild(n);
672
679
  } else {
673
- for (var i = 0, first = true; i < line.widgets.length; ++i) {
680
+ for (var i = 0; i < line.widgets.length; ++i) {
674
681
  var widget = line.widgets[i];
675
- if (!widget.above) { insertBefore = n; first = false; }
676
682
  if (widget.node == n.firstChild) {
683
+ if (!widget.above && !insertBefore) insertBefore = n;
677
684
  positionLineWidget(widget, n, reuse, dims);
678
685
  ++widgetsSeen;
679
686
  break;
@@ -966,11 +973,13 @@ window.CodeMirror = (function() {
966
973
  if (r) break;
967
974
  if (dir < 0 && pos == 0) dir = 1;
968
975
  }
969
- var rightV = (pos < ch || bias == "right") && r.topRight != null;
976
+ bias = pos > ch ? "left" : pos < ch ? "right" : bias;
977
+ if (bias == "left" && r.leftSide) r = r.leftSide;
978
+ else if (bias == "right" && r.rightSide) r = r.rightSide;
970
979
  return {left: pos < ch ? r.right : r.left,
971
980
  right: pos > ch ? r.left : r.right,
972
- top: rightV ? r.topRight : r.top,
973
- bottom: rightV ? r.bottomRight : r.bottom};
981
+ top: r.top,
982
+ bottom: r.bottom};
974
983
  }
975
984
 
976
985
  function findCachedMeasurement(cm, line) {
@@ -1007,7 +1016,7 @@ window.CodeMirror = (function() {
1007
1016
 
1008
1017
  function measureLineInner(cm, line) {
1009
1018
  var display = cm.display, measure = emptyArray(line.text.length);
1010
- var pre = lineContent(cm, line, measure);
1019
+ var pre = lineContent(cm, line, measure, true);
1011
1020
 
1012
1021
  // IE does not cache element positions of inline elements between
1013
1022
  // calls to getBoundingClientRect. This makes the loop below,
@@ -1043,48 +1052,50 @@ window.CodeMirror = (function() {
1043
1052
  if (ie_lt9 && display.measure.first != pre)
1044
1053
  removeChildrenAndAdd(display.measure, pre);
1045
1054
 
1046
- function categorizeVSpan(top, bot) {
1055
+ function measureRect(rect) {
1056
+ var top = rect.top - outer.top, bot = rect.bottom - outer.top;
1047
1057
  if (bot > maxBot) bot = maxBot;
1048
1058
  if (top < 0) top = 0;
1049
- for (var j = 0; j < vranges.length; j += 2) {
1050
- var rtop = vranges[j], rbot = vranges[j+1];
1059
+ for (var i = vranges.length - 2; i >= 0; i -= 2) {
1060
+ var rtop = vranges[i], rbot = vranges[i+1];
1051
1061
  if (rtop > bot || rbot < top) continue;
1052
1062
  if (rtop <= top && rbot >= bot ||
1053
1063
  top <= rtop && bot >= rbot ||
1054
1064
  Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {
1055
- vranges[j] = Math.min(top, rtop);
1056
- vranges[j+1] = Math.max(bot, rbot);
1057
- return j;
1065
+ vranges[i] = Math.min(top, rtop);
1066
+ vranges[i+1] = Math.max(bot, rbot);
1067
+ break;
1058
1068
  }
1059
1069
  }
1060
- vranges.push(top, bot);
1061
- return j;
1070
+ if (i < 0) { i = vranges.length; vranges.push(top, bot); }
1071
+ return {left: rect.left - outer.left,
1072
+ right: rect.right - outer.left,
1073
+ top: i, bottom: null};
1074
+ }
1075
+ function finishRect(rect) {
1076
+ rect.bottom = vranges[rect.top+1];
1077
+ rect.top = vranges[rect.top];
1062
1078
  }
1063
1079
 
1064
1080
  for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
1065
- var size, node = cur;
1081
+ var node = cur, rect = null;
1066
1082
  // A widget might wrap, needs special care
1067
1083
  if (/\bCodeMirror-widget\b/.test(cur.className) && cur.getClientRects) {
1068
1084
  if (cur.firstChild.nodeType == 1) node = cur.firstChild;
1069
- var rects = node.getClientRects(), rLeft = rects[0], rRight = rects[rects.length - 1];
1085
+ var rects = node.getClientRects();
1070
1086
  if (rects.length > 1) {
1071
- var vCatLeft = categorizeVSpan(rLeft.top - outer.top, rLeft.bottom - outer.top);
1072
- var vCatRight = categorizeVSpan(rRight.top - outer.top, rRight.bottom - outer.top);
1073
- data[i] = {left: rLeft.left - outer.left, right: rRight.right - outer.left,
1074
- top: vCatLeft, topRight: vCatRight};
1075
- continue;
1087
+ rect = data[i] = measureRect(rects[0]);
1088
+ rect.rightSide = measureRect(rects[rects.length - 1]);
1076
1089
  }
1077
1090
  }
1078
- size = getRect(node);
1079
- var vCat = categorizeVSpan(size.top - outer.top, size.bottom - outer.top);
1080
- var right = size.right;
1081
- if (cur.measureRight) right = getRect(cur.measureRight).left;
1082
- data[i] = {left: size.left - outer.left, right: right - outer.left, top: vCat};
1091
+ if (!rect) rect = data[i] = measureRect(getRect(node));
1092
+ if (cur.measureRight) rect.right = getRect(cur.measureRight).left;
1093
+ if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide));
1083
1094
  }
1084
1095
  for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
1085
- var vr = cur.top, vrRight = cur.topRight;
1086
- cur.top = vranges[vr]; cur.bottom = vranges[vr+1];
1087
- if (vrRight != null) { cur.topRight = vranges[vrRight]; cur.bottomRight = vranges[vrRight+1]; }
1096
+ finishRect(cur);
1097
+ if (cur.leftSide) finishRect(cur.leftSide);
1098
+ if (cur.rightSide) finishRect(cur.rightSide);
1088
1099
  }
1089
1100
  return data;
1090
1101
  }
@@ -1098,7 +1109,7 @@ window.CodeMirror = (function() {
1098
1109
  var cached = !hasBadSpan && findCachedMeasurement(cm, line);
1099
1110
  if (cached) return measureChar(cm, line, line.text.length, cached.measure, "right").right;
1100
1111
 
1101
- var pre = lineContent(cm, line);
1112
+ var pre = lineContent(cm, line, null, true);
1102
1113
  var end = pre.appendChild(zeroWidthElement(cm.display.measure));
1103
1114
  removeChildrenAndAdd(cm.display.measure, pre);
1104
1115
  return getRect(end).right - getRect(cm.display.lineDiv).left;
@@ -1302,6 +1313,7 @@ window.CodeMirror = (function() {
1302
1313
  // An array of ranges of lines that have to be updated. See
1303
1314
  // updateDisplay.
1304
1315
  changes: [],
1316
+ forceUpdate: false,
1305
1317
  updateInput: null,
1306
1318
  userSelChange: null,
1307
1319
  textChanged: null,
@@ -1334,8 +1346,8 @@ window.CodeMirror = (function() {
1334
1346
  var coords = cursorCoords(cm, doc.sel.head);
1335
1347
  newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
1336
1348
  }
1337
- if (op.changes.length || newScrollPos && newScrollPos.scrollTop != null) {
1338
- updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop);
1349
+ if (op.changes.length || op.forceUpdate || newScrollPos && newScrollPos.scrollTop != null) {
1350
+ updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop, op.forceUpdate);
1339
1351
  if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;
1340
1352
  }
1341
1353
  if (!updated && op.selectionChanged) updateSelection(cm);
@@ -2105,6 +2117,7 @@ window.CodeMirror = (function() {
2105
2117
 
2106
2118
  var detectingSelectAll;
2107
2119
  function onContextMenu(cm, e) {
2120
+ if (signalDOMEvent(cm, e, "contextmenu")) return;
2108
2121
  var display = cm.display, sel = cm.doc.sel;
2109
2122
  if (eventInWidget(display, e)) return;
2110
2123
 
@@ -2755,7 +2768,7 @@ window.CodeMirror = (function() {
2755
2768
  function findWordAt(line, pos) {
2756
2769
  var start = pos.ch, end = pos.ch;
2757
2770
  if (line) {
2758
- if (pos.xRel < 0 || end == line.length) --start; else ++end;
2771
+ if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
2759
2772
  var startChar = line.charAt(start);
2760
2773
  var check = isWordChar(startChar) ? isWordChar
2761
2774
  : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
@@ -2796,7 +2809,7 @@ window.CodeMirror = (function() {
2796
2809
  removeKeyMap: function(map) {
2797
2810
  var maps = this.state.keyMaps;
2798
2811
  for (var i = 0; i < maps.length; ++i)
2799
- if ((typeof map == "string" ? maps[i].name : maps[i]) == map) {
2812
+ if (maps[i] == map || (typeof maps[i] != "string" && maps[i].name == map)) {
2800
2813
  maps.splice(i, 1);
2801
2814
  return true;
2802
2815
  }
@@ -2860,6 +2873,7 @@ window.CodeMirror = (function() {
2860
2873
  pos = clipPos(this.doc, pos);
2861
2874
  var styles = getLineStyles(this, getLine(this.doc, pos.line));
2862
2875
  var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
2876
+ if (ch == 0) return styles[2];
2863
2877
  for (;;) {
2864
2878
  var mid = (before + after) >> 1;
2865
2879
  if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
@@ -2868,6 +2882,20 @@ window.CodeMirror = (function() {
2868
2882
  }
2869
2883
  },
2870
2884
 
2885
+ getModeAt: function(pos) {
2886
+ var mode = this.doc.mode;
2887
+ if (!mode.innerMode) return mode;
2888
+ return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;
2889
+ },
2890
+
2891
+ getHelper: function(pos, type) {
2892
+ if (!helpers.hasOwnProperty(type)) return;
2893
+ var help = helpers[type], mode = this.getModeAt(pos);
2894
+ return mode[type] && help[mode[type]] ||
2895
+ mode.helperType && help[mode.helperType] ||
2896
+ help[mode.name];
2897
+ },
2898
+
2871
2899
  getStateAfter: function(line, precise) {
2872
2900
  var doc = this.doc;
2873
2901
  line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
@@ -3097,17 +3125,16 @@ window.CodeMirror = (function() {
3097
3125
  updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);
3098
3126
  }),
3099
3127
 
3100
- setSize: function(width, height) {
3128
+ setSize: operation(null, function(width, height) {
3101
3129
  function interpret(val) {
3102
3130
  return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
3103
3131
  }
3104
3132
  if (width != null) this.display.wrapper.style.width = interpret(width);
3105
3133
  if (height != null) this.display.wrapper.style.height = interpret(height);
3106
- this.refresh();
3107
- },
3108
-
3109
- on: function(type, f) {on(this, type, f);},
3110
- off: function(type, f) {off(this, type, f);},
3134
+ if (this.options.lineWrapping)
3135
+ this.display.measureLineCache.length = this.display.measureLineCachePos = 0;
3136
+ this.curOp.forceUpdate = true;
3137
+ }),
3111
3138
 
3112
3139
  operation: function(f){return runInOp(this, f);},
3113
3140
 
@@ -3132,6 +3159,7 @@ window.CodeMirror = (function() {
3132
3159
  getScrollerElement: function(){return this.display.scroller;},
3133
3160
  getGutterElement: function(){return this.display.gutters;}
3134
3161
  };
3162
+ eventMixin(CodeMirror);
3135
3163
 
3136
3164
  // OPTION DEFAULTS
3137
3165
 
@@ -3256,7 +3284,7 @@ window.CodeMirror = (function() {
3256
3284
  };
3257
3285
 
3258
3286
  CodeMirror.getMode = function(options, spec) {
3259
- spec = CodeMirror.resolveMode(spec);
3287
+ var spec = CodeMirror.resolveMode(spec);
3260
3288
  var mfactory = modes[spec.name];
3261
3289
  if (!mfactory) return CodeMirror.getMode(options, "text/plain");
3262
3290
  var modeObj = mfactory(options, spec);
@@ -3269,6 +3297,7 @@ window.CodeMirror = (function() {
3269
3297
  }
3270
3298
  }
3271
3299
  modeObj.name = spec.name;
3300
+
3272
3301
  return modeObj;
3273
3302
  };
3274
3303
 
@@ -3296,6 +3325,16 @@ window.CodeMirror = (function() {
3296
3325
  var initHooks = [];
3297
3326
  CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
3298
3327
 
3328
+ var helpers = CodeMirror.helpers = {};
3329
+ CodeMirror.registerHelper = function(type, name, value) {
3330
+ if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {};
3331
+ helpers[type][name] = value;
3332
+ };
3333
+
3334
+ // UTILITIES
3335
+
3336
+ CodeMirror.isWordChar = isWordChar;
3337
+
3299
3338
  // MODE STATE HANDLING
3300
3339
 
3301
3340
  // Utility functions for working with state. Exported because modes
@@ -3321,6 +3360,7 @@ window.CodeMirror = (function() {
3321
3360
  CodeMirror.innerMode = function(mode, state) {
3322
3361
  while (mode.innerMode) {
3323
3362
  var info = mode.innerMode(state);
3363
+ if (!info || info.mode == mode) break;
3324
3364
  state = info.state;
3325
3365
  mode = info.mode;
3326
3366
  }
@@ -3633,11 +3673,16 @@ window.CodeMirror = (function() {
3633
3673
  this.doc = doc;
3634
3674
  }
3635
3675
  CodeMirror.TextMarker = TextMarker;
3676
+ eventMixin(TextMarker);
3636
3677
 
3637
3678
  TextMarker.prototype.clear = function() {
3638
3679
  if (this.explicitlyCleared) return;
3639
3680
  var cm = this.doc.cm, withOp = cm && !cm.curOp;
3640
3681
  if (withOp) startOperation(cm);
3682
+ if (hasHandler(this, "clear")) {
3683
+ var found = this.find();
3684
+ if (found) signalLater(this, "clear", found.from, found.to);
3685
+ }
3641
3686
  var min = null, max = null;
3642
3687
  for (var i = 0; i < this.lines.length; ++i) {
3643
3688
  var line = this.lines[i];
@@ -3666,7 +3711,6 @@ window.CodeMirror = (function() {
3666
3711
  if (cm) reCheckSelection(cm);
3667
3712
  }
3668
3713
  if (withOp) endOperation(cm);
3669
- signalLater(this, "clear");
3670
3714
  };
3671
3715
 
3672
3716
  TextMarker.prototype.find = function() {
@@ -3694,7 +3738,9 @@ window.CodeMirror = (function() {
3694
3738
  if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight);
3695
3739
  break;
3696
3740
  }
3697
- runInOp(cm, function() { cm.curOp.selectionChanged = true; });
3741
+ runInOp(cm, function() {
3742
+ cm.curOp.selectionChanged = cm.curOp.forceUpdate = cm.curOp.updateMaxLine = true;
3743
+ });
3698
3744
  }
3699
3745
  };
3700
3746
 
@@ -3767,7 +3813,7 @@ window.CodeMirror = (function() {
3767
3813
  }
3768
3814
  if (cm) {
3769
3815
  if (updateMaxLine) cm.curOp.updateMaxLine = true;
3770
- if (marker.className || marker.startStyle || marker.endStyle || marker.collapsed)
3816
+ if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.collapsed)
3771
3817
  regChange(cm, from.line, to.line + 1);
3772
3818
  if (marker.atomic) reCheckSelection(cm);
3773
3819
  }
@@ -3785,6 +3831,7 @@ window.CodeMirror = (function() {
3785
3831
  }
3786
3832
  }
3787
3833
  CodeMirror.SharedTextMarker = SharedTextMarker;
3834
+ eventMixin(SharedTextMarker);
3788
3835
 
3789
3836
  SharedTextMarker.prototype.clear = function() {
3790
3837
  if (this.explicitlyCleared) return;
@@ -4037,11 +4084,12 @@ window.CodeMirror = (function() {
4037
4084
  // LINE WIDGETS
4038
4085
 
4039
4086
  var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {
4040
- for (var opt in options) if (options.hasOwnProperty(opt))
4087
+ if (options) for (var opt in options) if (options.hasOwnProperty(opt))
4041
4088
  this[opt] = options[opt];
4042
4089
  this.cm = cm;
4043
4090
  this.node = node;
4044
4091
  };
4092
+ eventMixin(LineWidget);
4045
4093
  function widgetOperation(f) {
4046
4094
  return function() {
4047
4095
  var withOp = !this.cm.curOp;
@@ -4056,7 +4104,9 @@ window.CodeMirror = (function() {
4056
4104
  if (no == null || !ws) return;
4057
4105
  for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
4058
4106
  if (!ws.length) this.line.widgets = null;
4107
+ var aboveVisible = heightAtLine(this.cm, this.line) < this.cm.doc.scrollTop;
4059
4108
  updateLineHeight(this.line, Math.max(0, this.line.height - widgetHeight(this)));
4109
+ if (aboveVisible) addToScrollPos(this.cm, 0, -this.height);
4060
4110
  regChange(this.cm, no, no + 1);
4061
4111
  });
4062
4112
  LineWidget.prototype.changed = widgetOperation(function() {
@@ -4080,10 +4130,12 @@ window.CodeMirror = (function() {
4080
4130
  var widget = new LineWidget(cm, node, options);
4081
4131
  if (widget.noHScroll) cm.display.alignWidgets = true;
4082
4132
  changeLine(cm, handle, function(line) {
4083
- (line.widgets || (line.widgets = [])).push(widget);
4133
+ var widgets = line.widgets || (line.widgets = []);
4134
+ if (widget.insertAt == null) widgets.push(widget);
4135
+ else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
4084
4136
  widget.line = line;
4085
4137
  if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) {
4086
- var aboveVisible = heightAtLine(cm, line) < cm.display.scroller.scrollTop;
4138
+ var aboveVisible = heightAtLine(cm, line) < cm.doc.scrollTop;
4087
4139
  updateLineHeight(line, line.height + widgetHeight(widget));
4088
4140
  if (aboveVisible) addToScrollPos(cm, 0, widget.height);
4089
4141
  }
@@ -4096,12 +4148,12 @@ window.CodeMirror = (function() {
4096
4148
 
4097
4149
  // Line objects. These hold state related to a line, including
4098
4150
  // highlighting info (the styles array).
4099
- function makeLine(text, markedSpans, estimateHeight) {
4100
- var line = {text: text};
4101
- attachMarkedSpans(line, markedSpans);
4102
- line.height = estimateHeight ? estimateHeight(line) : 1;
4103
- return line;
4104
- }
4151
+ var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {
4152
+ this.text = text;
4153
+ attachMarkedSpans(this, markedSpans);
4154
+ this.height = estimateHeight ? estimateHeight(this) : 1;
4155
+ };
4156
+ eventMixin(Line);
4105
4157
 
4106
4158
  function updateLine(line, text, markedSpans, estimateHeight) {
4107
4159
  line.text = text;
@@ -4207,13 +4259,14 @@ window.CodeMirror = (function() {
4207
4259
  (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-"));
4208
4260
  }
4209
4261
 
4210
- function lineContent(cm, realLine, measure) {
4262
+ function lineContent(cm, realLine, measure, copyWidgets) {
4211
4263
  var merged, line = realLine, empty = true;
4212
4264
  while (merged = collapsedSpanAtStart(line))
4213
4265
  line = getLine(cm.doc, merged.find().from.line);
4214
4266
 
4215
- var builder = {pre: elt("pre"), col: 0, pos: 0, display: !measure,
4216
- measure: null, measuredSomething: false, cm: cm};
4267
+ var builder = {pre: elt("pre"), col: 0, pos: 0,
4268
+ measure: null, measuredSomething: false, cm: cm,
4269
+ copyWidgets: copyWidgets};
4217
4270
  if (line.textClass) builder.pre.className = line.textClass;
4218
4271
 
4219
4272
  do {
@@ -4256,7 +4309,7 @@ window.CodeMirror = (function() {
4256
4309
  }
4257
4310
 
4258
4311
  var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g;
4259
- function buildToken(builder, text, style, startStyle, endStyle) {
4312
+ function buildToken(builder, text, style, startStyle, endStyle, title) {
4260
4313
  if (!text) return;
4261
4314
  if (!tokenSpecialChars.test(text)) {
4262
4315
  builder.col += text.length;
@@ -4289,7 +4342,9 @@ window.CodeMirror = (function() {
4289
4342
  var fullStyle = style || "";
4290
4343
  if (startStyle) fullStyle += startStyle;
4291
4344
  if (endStyle) fullStyle += endStyle;
4292
- return builder.pre.appendChild(elt("span", [content], fullStyle));
4345
+ var token = elt("span", [content], fullStyle);
4346
+ if (title) token.title = title;
4347
+ return builder.pre.appendChild(token);
4293
4348
  }
4294
4349
  builder.pre.appendChild(content);
4295
4350
  }
@@ -4304,9 +4359,11 @@ window.CodeMirror = (function() {
4304
4359
  } else if (i && wrapping && spanAffectsWrapping(text, i)) {
4305
4360
  builder.pre.appendChild(elt("wbr"));
4306
4361
  }
4362
+ var old = builder.measure[builder.pos];
4307
4363
  var span = builder.measure[builder.pos] =
4308
4364
  buildToken(builder, ch, style,
4309
4365
  start && startStyle, i == text.length - 1 && endStyle);
4366
+ if (old) span.leftSide = old.leftSide || old;
4310
4367
  // In IE single-space nodes wrap differently than spaces
4311
4368
  // embedded in larger text nodes, except when set to
4312
4369
  // white-space: normal (issue #1268).
@@ -4325,20 +4382,28 @@ window.CodeMirror = (function() {
4325
4382
  out += " ";
4326
4383
  return out;
4327
4384
  }
4328
- return function(builder, text, style, startStyle, endStyle) {
4329
- return inner(builder, text.replace(/ {3,}/, split), style, startStyle, endStyle);
4385
+ return function(builder, text, style, startStyle, endStyle, title) {
4386
+ return inner(builder, text.replace(/ {3,}/, split), style, startStyle, endStyle, title);
4330
4387
  };
4331
4388
  }
4332
4389
 
4333
- function buildCollapsedSpan(builder, size, widget) {
4390
+ function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
4391
+ var widget = !ignoreWidget && marker.replacedWith;
4334
4392
  if (widget) {
4335
- if (!builder.display) widget = widget.cloneNode(true);
4393
+ if (builder.copyWidgets) widget = widget.cloneNode(true);
4394
+ builder.pre.appendChild(widget);
4336
4395
  if (builder.measure) {
4337
- builder.measure[builder.pos] = size ? widget
4338
- : builder.pre.appendChild(zeroWidthElement(builder.cm.display.measure));
4396
+ if (size) {
4397
+ builder.measure[builder.pos] = widget;
4398
+ } else {
4399
+ var elt = builder.measure[builder.pos] = zeroWidthElement(builder.cm.display.measure);
4400
+ if (marker.type != "bookmark" || marker.insertLeft)
4401
+ builder.pre.insertBefore(elt, widget);
4402
+ else
4403
+ builder.pre.appendChild(elt);
4404
+ }
4339
4405
  builder.measuredSomething = true;
4340
4406
  }
4341
- builder.pre.appendChild(widget);
4342
4407
  }
4343
4408
  builder.pos += size;
4344
4409
  }
@@ -4354,10 +4419,10 @@ window.CodeMirror = (function() {
4354
4419
  }
4355
4420
 
4356
4421
  var len = allText.length, pos = 0, i = 1, text = "", style;
4357
- var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed;
4422
+ var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
4358
4423
  for (;;) {
4359
4424
  if (nextChange == pos) { // Update current marker set
4360
- spanStyle = spanEndStyle = spanStartStyle = "";
4425
+ spanStyle = spanEndStyle = spanStartStyle = title = "";
4361
4426
  collapsed = null; nextChange = Infinity;
4362
4427
  var foundBookmark = null;
4363
4428
  for (var j = 0; j < spans.length; ++j) {
@@ -4367,17 +4432,17 @@ window.CodeMirror = (function() {
4367
4432
  if (m.className) spanStyle += " " + m.className;
4368
4433
  if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
4369
4434
  if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
4435
+ if (m.title && !title) title = m.title;
4370
4436
  if (m.collapsed && (!collapsed || collapsed.marker.size < m.size))
4371
4437
  collapsed = sp;
4372
4438
  } else if (sp.from > pos && nextChange > sp.from) {
4373
4439
  nextChange = sp.from;
4374
4440
  }
4375
- if (m.type == "bookmark" && sp.from == pos && m.replacedWith)
4376
- foundBookmark = m.replacedWith;
4441
+ if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmark = m;
4377
4442
  }
4378
4443
  if (collapsed && (collapsed.from || 0) == pos) {
4379
4444
  buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,
4380
- collapsed.from != null && collapsed.marker.replacedWith);
4445
+ collapsed.marker, collapsed.from == null);
4381
4446
  if (collapsed.to == null) return collapsed.marker.find();
4382
4447
  }
4383
4448
  if (foundBookmark && !collapsed) buildCollapsedSpan(builder, 0, foundBookmark);
@@ -4391,7 +4456,7 @@ window.CodeMirror = (function() {
4391
4456
  if (!collapsed) {
4392
4457
  var tokenText = end > upto ? text.slice(0, upto - pos) : text;
4393
4458
  builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
4394
- spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "");
4459
+ spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title);
4395
4460
  }
4396
4461
  if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
4397
4462
  pos = end;
@@ -4421,7 +4486,7 @@ window.CodeMirror = (function() {
4421
4486
  // This is a whole-line replace. Treated specially to make
4422
4487
  // sure line objects move the way they are supposed to.
4423
4488
  for (var i = 0, e = text.length - 1, added = []; i < e; ++i)
4424
- added.push(makeLine(text[i], spansFor(i), estimateHeight));
4489
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
4425
4490
  update(lastLine, lastLine.text, lastSpans);
4426
4491
  if (nlines) doc.remove(from.line, nlines);
4427
4492
  if (added.length) doc.insert(from.line, added);
@@ -4430,8 +4495,8 @@ window.CodeMirror = (function() {
4430
4495
  update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
4431
4496
  } else {
4432
4497
  for (var added = [], i = 1, e = text.length - 1; i < e; ++i)
4433
- added.push(makeLine(text[i], spansFor(i), estimateHeight));
4434
- added.push(makeLine(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
4498
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
4499
+ added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
4435
4500
  update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
4436
4501
  doc.insert(from.line + 1, added);
4437
4502
  }
@@ -4442,7 +4507,7 @@ window.CodeMirror = (function() {
4442
4507
  update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
4443
4508
  update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
4444
4509
  for (var i = 1, e = text.length - 1, added = []; i < e; ++i)
4445
- added.push(makeLine(text[i], spansFor(i), estimateHeight));
4510
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
4446
4511
  if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
4447
4512
  doc.insert(from.line + 1, added);
4448
4513
  }
@@ -4585,7 +4650,7 @@ window.CodeMirror = (function() {
4585
4650
  if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
4586
4651
  if (firstLine == null) firstLine = 0;
4587
4652
 
4588
- BranchChunk.call(this, [new LeafChunk([makeLine("", null)])]);
4653
+ BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
4589
4654
  this.first = firstLine;
4590
4655
  this.scrollTop = this.scrollLeft = 0;
4591
4656
  this.cantEdit = false;
@@ -4650,6 +4715,11 @@ window.CodeMirror = (function() {
4650
4715
  getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
4651
4716
  getLineNumber: function(line) {return lineNo(line);},
4652
4717
 
4718
+ getLineHandleVisualStart: function(line) {
4719
+ if (typeof line == "number") line = getLine(this, line);
4720
+ return visualLine(this, line);
4721
+ },
4722
+
4653
4723
  lineCount: function() {return this.size;},
4654
4724
  firstLine: function() {return this.first;},
4655
4725
  lastLine: function() {return this.first + this.size - 1;},
@@ -4820,6 +4890,8 @@ window.CodeMirror = (function() {
4820
4890
  return function() {return method.apply(this.doc, arguments);};
4821
4891
  })(Doc.prototype[prop]);
4822
4892
 
4893
+ eventMixin(Doc);
4894
+
4823
4895
  function linkedDocs(doc, f, sharedHistOnly) {
4824
4896
  function propagate(doc, skip, sharedHist) {
4825
4897
  if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
@@ -4963,7 +5035,8 @@ window.CodeMirror = (function() {
4963
5035
  }
4964
5036
 
4965
5037
  function historyChangeFromChange(doc, change) {
4966
- var histChange = {from: change.from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
5038
+ var from = { line: change.from.line, ch: change.from.ch };
5039
+ var histChange = {from: from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
4967
5040
  attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
4968
5041
  linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
4969
5042
  return histChange;
@@ -5183,9 +5256,9 @@ window.CodeMirror = (function() {
5183
5256
  delayedCallbacks.push(bnd(arr[i]));
5184
5257
  }
5185
5258
 
5186
- function signalDOMEvent(cm, e) {
5187
- signal(cm, e.type, cm, e);
5188
- return e_defaultPrevented(e);
5259
+ function signalDOMEvent(cm, e, override) {
5260
+ signal(cm, override || e.type, cm, e);
5261
+ return e_defaultPrevented(e) || e.codemirrorIgnore;
5189
5262
  }
5190
5263
 
5191
5264
  function fireDelayed() {
@@ -5202,6 +5275,11 @@ window.CodeMirror = (function() {
5202
5275
 
5203
5276
  CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal;
5204
5277
 
5278
+ function eventMixin(ctor) {
5279
+ ctor.prototype.on = function(type, f) {on(this, type, f);};
5280
+ ctor.prototype.off = function(type, f) {off(this, type, f);};
5281
+ }
5282
+
5205
5283
  // MISC UTILITIES
5206
5284
 
5207
5285
  // Number of pixels added to scroller and sizer to hide scrollbar
@@ -5353,10 +5431,12 @@ window.CodeMirror = (function() {
5353
5431
  spanAffectsWrapping = function(str, i) {
5354
5432
  return /\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(str.slice(i - 1, i + 1));
5355
5433
  };
5356
- else if (webkit)
5434
+ else if (webkit && !/Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent))
5357
5435
  spanAffectsWrapping = function(str, i) {
5358
- if (i > 1 && str.charCodeAt(i - 1) == 45 && /\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i)))
5359
- return true;
5436
+ if (i > 1 && str.charCodeAt(i - 1) == 45) {
5437
+ if (/\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i))) return true;
5438
+ if (i > 2 && /[\d\.,]/.test(str.charAt(i - 2)) && /[\d\.,]/.test(str.charAt(i))) return false;
5439
+ }
5360
5440
  return /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));
5361
5441
  };
5362
5442
 
@@ -5443,11 +5523,15 @@ window.CodeMirror = (function() {
5443
5523
 
5444
5524
  function iterateBidiSections(order, from, to, f) {
5445
5525
  if (!order) return f(from, to, "ltr");
5526
+ var found = false;
5446
5527
  for (var i = 0; i < order.length; ++i) {
5447
5528
  var part = order[i];
5448
- if (part.from < to && part.to > from || from == to && part.to == from)
5529
+ if (part.from < to && part.to > from || from == to && part.to == from) {
5449
5530
  f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
5531
+ found = true;
5532
+ }
5450
5533
  }
5534
+ if (!found) f(from, to, "ltr");
5451
5535
  }
5452
5536
 
5453
5537
  function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
@@ -5709,7 +5793,7 @@ window.CodeMirror = (function() {
5709
5793
 
5710
5794
  // THE END
5711
5795
 
5712
- CodeMirror.version = "3.14.0";
5796
+ CodeMirror.version = "3.15.0";
5713
5797
 
5714
5798
  return CodeMirror;
5715
5799
  })();