codemirror-rails 3.14 → 3.15

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