codemirror-rails 2.34 → 2.35

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.
@@ -1,6 +1,6 @@
1
1
  module Codemirror
2
2
  module Rails
3
- VERSION = '2.34'
4
- CODEMIRROR_VERSION = '2.34'
3
+ VERSION = '2.35'
4
+ CODEMIRROR_VERSION = '2.35'
5
5
  end
6
6
  end
@@ -1,5 +1,5 @@
1
- // CodeMirror version 2.34
2
-
1
+ // CodeMirror version 2.35
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,
5
5
  // some utilities are defined.
@@ -77,7 +77,7 @@ window.CodeMirror = (function() {
77
77
  // Selection-related flags. shiftSelecting obviously tracks
78
78
  // whether the user is holding shift.
79
79
  var shiftSelecting, lastClick, lastDoubleClick, lastScrollTop = 0, draggingText,
80
- overwrite = false, suppressEdits = false;
80
+ overwrite = false, suppressEdits = false, pasteIncoming = false;
81
81
  // Variables used by startOperation/endOperation to track what
82
82
  // happened during the operation.
83
83
  var updateInput, userSelChange, changes, textChanged, selectionChanged,
@@ -130,7 +130,7 @@ window.CodeMirror = (function() {
130
130
  connect(scroller, "drop", operation(onDrop));
131
131
  }
132
132
  connect(scroller, "paste", function(){focusInput(); fastPoll();});
133
- connect(input, "paste", fastPoll);
133
+ connect(input, "paste", function(){pasteIncoming = true; fastPoll();});
134
134
  connect(input, "cut", operation(function(){
135
135
  if (!options.readOnly) replaceSelection("");
136
136
  }));
@@ -169,6 +169,7 @@ window.CodeMirror = (function() {
169
169
  else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
170
170
  else if (option == "tabSize") updateDisplay(true);
171
171
  else if (option == "keyMap") keyMapChanged();
172
+ else if (option == "tabindex") input.tabIndex = value;
172
173
  if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" ||
173
174
  option == "theme" || option == "lineNumberFormatter") {
174
175
  gutterChanged();
@@ -956,12 +957,13 @@ window.CodeMirror = (function() {
956
957
  while (same < l && prevInput[same] == text[same]) ++same;
957
958
  if (same < prevInput.length)
958
959
  sel.from = {line: sel.from.line, ch: sel.from.ch - (prevInput.length - same)};
959
- else if (overwrite && posEq(sel.from, sel.to))
960
+ else if (overwrite && posEq(sel.from, sel.to) && !pasteIncoming)
960
961
  sel.to = {line: sel.to.line, ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same))};
961
962
  replaceSelection(text.slice(same), "end");
962
963
  if (text.length > 1000) { input.value = prevInput = ""; }
963
964
  else prevInput = text;
964
965
  if (!nestedOperation) endOperation();
966
+ pasteIncoming = false;
965
967
  return true;
966
968
  }
967
969
  function resetInput(user) {
@@ -1418,7 +1420,7 @@ window.CodeMirror = (function() {
1418
1420
  var startChar = line.charAt(start);
1419
1421
  var check = isWordChar(startChar) ? isWordChar :
1420
1422
  /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} :
1421
- function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
1423
+ function(ch) {return !/\s/.test(ch) && isWordChar(ch);};
1422
1424
  while (start > 0 && check(line.charAt(start - 1))) --start;
1423
1425
  while (end < line.length && check(line.charAt(end))) ++end;
1424
1426
  }
@@ -1462,6 +1464,7 @@ window.CodeMirror = (function() {
1462
1464
 
1463
1465
  if (indentString != curSpaceString)
1464
1466
  replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length});
1467
+ line.stateAfter = null;
1465
1468
  }
1466
1469
 
1467
1470
  function loadMode() {
@@ -1507,18 +1510,17 @@ window.CodeMirror = (function() {
1507
1510
 
1508
1511
  function TextMarker(type, style) { this.lines = []; this.type = type; if (style) this.style = style; }
1509
1512
  TextMarker.prototype.clear = operation(function() {
1510
- var min = Infinity, max = -Infinity;
1513
+ var min, max;
1511
1514
  for (var i = 0; i < this.lines.length; ++i) {
1512
1515
  var line = this.lines[i];
1513
- var span = getMarkedSpanFor(line.markedSpans, this, true);
1514
- if (span.from != null || span.to != null) {
1515
- var lineN = lineNo(line);
1516
- min = Math.min(min, lineN); max = Math.max(max, lineN);
1517
- }
1516
+ var span = getMarkedSpanFor(line.markedSpans, this);
1517
+ if (span.from != null) min = lineNo(line);
1518
+ if (span.to != null) max = lineNo(line);
1519
+ line.markedSpans = removeMarkedSpan(line.markedSpans, span);
1518
1520
  }
1519
- if (min != Infinity)
1520
- changes.push({from: min, to: max + 1});
1521
+ if (min != null) changes.push({from: min, to: max + 1});
1521
1522
  this.lines.length = 0;
1523
+ this.explicitlyCleared = true;
1522
1524
  });
1523
1525
  TextMarker.prototype.find = function() {
1524
1526
  var from, to;
@@ -1545,7 +1547,7 @@ window.CodeMirror = (function() {
1545
1547
  var span = {from: curLine == from.line ? from.ch : null,
1546
1548
  to: curLine == to.line ? to.ch : null,
1547
1549
  marker: marker};
1548
- (line.markedSpans || (line.markedSpans = [])).push(span);
1550
+ line.markedSpans = (line.markedSpans || []).concat([span]);
1549
1551
  marker.lines.push(line);
1550
1552
  ++curLine;
1551
1553
  });
@@ -1556,8 +1558,9 @@ window.CodeMirror = (function() {
1556
1558
  function setBookmark(pos) {
1557
1559
  pos = clipPos(pos);
1558
1560
  var marker = new TextMarker("bookmark"), line = getLine(pos.line);
1561
+ history.addChange(pos.line, 1, [newHL(line.text, line.markedSpans)], true);
1559
1562
  var span = {from: pos.ch, to: pos.ch, marker: marker};
1560
- (line.markedSpans || (line.markedSpans = [])).push(span);
1563
+ line.markedSpans = (line.markedSpans || []).concat([span]);
1561
1564
  marker.lines.push(line);
1562
1565
  return marker;
1563
1566
  }
@@ -1646,8 +1649,6 @@ window.CodeMirror = (function() {
1646
1649
 
1647
1650
  function measureLine(line, ch) {
1648
1651
  if (ch == 0) return {top: 0, left: 0};
1649
- var wbr = options.lineWrapping && ch < line.text.length &&
1650
- spanAffectsWrapping.test(line.text.slice(ch - 1, ch + 1));
1651
1652
  var pre = lineContent(line, ch);
1652
1653
  removeChildrenAndAdd(measure, pre);
1653
1654
  var anchor = pre.anchor;
@@ -1980,6 +1981,7 @@ window.CodeMirror = (function() {
1980
1981
  if (extensions.propertyIsEnumerable(ext) &&
1981
1982
  !instance.propertyIsEnumerable(ext))
1982
1983
  instance[ext] = extensions[ext];
1984
+ for (var i = 0; i < initHooks.length; ++i) initHooks[i](instance);
1983
1985
  return instance;
1984
1986
  } // (end of function CodeMirror)
1985
1987
 
@@ -2077,6 +2079,9 @@ window.CodeMirror = (function() {
2077
2079
  extensions[name] = func;
2078
2080
  };
2079
2081
 
2082
+ var initHooks = [];
2083
+ CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
2084
+
2080
2085
  var modeExtensions = CodeMirror.modeExtensions = {};
2081
2086
  CodeMirror.extendMode = function(mode, properties) {
2082
2087
  var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
@@ -2206,6 +2211,7 @@ window.CodeMirror = (function() {
2206
2211
  var name = keyNames[e_prop(event, "keyCode")];
2207
2212
  return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
2208
2213
  }
2214
+ CodeMirror.isModifierKey = isModifierKey;
2209
2215
 
2210
2216
  CodeMirror.fromTextArea = function(textarea, options) {
2211
2217
  if (!options) options = {};
@@ -2355,16 +2361,20 @@ window.CodeMirror = (function() {
2355
2361
  this.from = from; this.to = to; this.marker = marker;
2356
2362
  }
2357
2363
 
2358
- function getMarkedSpanFor(spans, marker, del) {
2364
+ function getMarkedSpanFor(spans, marker) {
2359
2365
  if (spans) for (var i = 0; i < spans.length; ++i) {
2360
2366
  var span = spans[i];
2361
- if (span.marker == marker) {
2362
- if (del) spans.splice(i, 1);
2363
- return span;
2364
- }
2367
+ if (span.marker == marker) return span;
2365
2368
  }
2366
2369
  }
2367
2370
 
2371
+ function removeMarkedSpan(spans, span) {
2372
+ var r;
2373
+ for (var i = 0; i < spans.length; ++i)
2374
+ if (spans[i] != span) (r || (r = [])).push(spans[i]);
2375
+ return r;
2376
+ }
2377
+
2368
2378
  function markedSpansBefore(old, startCh, endCh) {
2369
2379
  if (old) for (var i = 0, nw; i < old.length; ++i) {
2370
2380
  var span = old[i], marker = span.marker;
@@ -2448,7 +2458,15 @@ window.CodeMirror = (function() {
2448
2458
  // hl stands for history-line, a data structure that can be either a
2449
2459
  // string (line without markers) or a {text, markedSpans} object.
2450
2460
  function hlText(val) { return typeof val == "string" ? val : val.text; }
2451
- function hlSpans(val) { return typeof val == "string" ? null : val.markedSpans; }
2461
+ function hlSpans(val) {
2462
+ if (typeof val == "string") return null;
2463
+ var spans = val.markedSpans, out = null;
2464
+ for (var i = 0; i < spans.length; ++i) {
2465
+ if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
2466
+ else if (out) out.push(spans[i]);
2467
+ }
2468
+ return !out ? spans : out.length ? out : null;
2469
+ }
2452
2470
  function newHL(text, spans) { return spans ? {text: text, markedSpans: spans} : text; }
2453
2471
 
2454
2472
  function detachMarkedSpans(line) {
@@ -2584,13 +2602,17 @@ window.CodeMirror = (function() {
2584
2602
  span = function(html, text, style) {
2585
2603
  var l = text.length;
2586
2604
  if (wrapAt >= outPos && wrapAt < outPos + l) {
2587
- if (wrapAt > outPos) {
2588
- span_(html, text.slice(0, wrapAt - outPos), style);
2605
+ var cut = wrapAt - outPos;
2606
+ if (cut) {
2607
+ span_(html, text.slice(0, cut), style);
2589
2608
  // See comment at the definition of spanAffectsWrapping
2590
- if (compensateForWrapping) html.appendChild(elt("wbr"));
2609
+ if (compensateForWrapping) {
2610
+ var view = text.slice(cut - 1, cut + 1);
2611
+ if (spanAffectsWrapping.test(view)) html.appendChild(elt("wbr"));
2612
+ else if (!ie_lt8 && /\w\w/.test(view)) html.appendChild(document.createTextNode("\u200d"));
2613
+ }
2591
2614
  }
2592
2615
  html.appendChild(anchor);
2593
- var cut = wrapAt - outPos;
2594
2616
  span_(anchor, opera ? text.slice(cut, cut + 1) : text.slice(cut), style);
2595
2617
  if (opera) span_(html, text.slice(cut + 1), style);
2596
2618
  wrapAt--;
@@ -2874,7 +2896,7 @@ window.CodeMirror = (function() {
2874
2896
  var time = +new Date, cur = lst(this.done), last = cur && lst(cur);
2875
2897
  var dtime = time - this.time;
2876
2898
 
2877
- if (this.compound && cur && !this.closed) {
2899
+ if (cur && !this.closed && this.compound) {
2878
2900
  cur.push({start: start, added: added, old: old});
2879
2901
  } else if (dtime > 400 || !last || this.closed ||
2880
2902
  last.start > start + old.length || last.start + last.added < start) {
@@ -3081,7 +3103,7 @@ window.CodeMirror = (function() {
3081
3103
  return -1;
3082
3104
  }
3083
3105
  function isWordChar(ch) {
3084
- return /\w/.test(ch) || ch.toUpperCase() != ch.toLowerCase();
3106
+ return /\w/.test(ch) || ch.toUpperCase() != ch.toLowerCase() || /[\u4E00-\u9FA5]/.test(ch);
3085
3107
  }
3086
3108
 
3087
3109
  // See if "".split is the broken IE version, if so, provide an
@@ -3137,7 +3159,7 @@ window.CodeMirror = (function() {
3137
3159
  for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
3138
3160
  })();
3139
3161
 
3140
- CodeMirror.version = "2.34";
3162
+ CodeMirror.version = "2.35";
3141
3163
 
3142
3164
  return CodeMirror;
3143
3165
  })();
@@ -318,13 +318,12 @@
318
318
  };
319
319
 
320
320
  // standard mode switching
321
- iterList(["d", "t", "T", "f", "F", "c", "r"],
322
- function (ch) {
323
- CodeMirror.keyMap.vim[toCombo(ch)] = function (cm) {
324
- cm.setOption("keyMap", "vim-prefix-" + ch);
325
- emptyBuffer();
326
- };
327
- });
321
+ iterList(["d", "t", "T", "f", "F", "c", "r"], function (ch) {
322
+ CodeMirror.keyMap.vim[toCombo(ch)] = function (cm) {
323
+ cm.setOption("keyMap", "vim-prefix-" + ch);
324
+ emptyBuffer();
325
+ };
326
+ });
328
327
 
329
328
  function addCountBindings(keyMap) {
330
329
  // Add bindings for number keys
@@ -645,7 +644,7 @@
645
644
  };
646
645
 
647
646
  // Map our movement actions each operator and non-operational movement
648
- motionList.forEach(function(key, index, array) {
647
+ iterList(motionList, function(key, index, array) {
649
648
  CodeMirror.keyMap['vim-prefix-d'][key] = function(cm) {
650
649
  // Get our selected range
651
650
  var start = cm.getCursor();
@@ -695,7 +694,7 @@
695
694
  });
696
695
 
697
696
  var nums = [1,2,3,4,5,6,7,8,9];
698
- nums.forEach(function(key, index, array) {
697
+ iterList(nums, function(key, index, array) {
699
698
  CodeMirror.keyMap['vim'][key] = function (cm) {
700
699
  reptTimes = (reptTimes * 10) + key;
701
700
  };
@@ -713,7 +712,7 @@
713
712
  // Create our keymaps for each operator and make xa and xi where x is an operator
714
713
  // change to the corrosponding keymap
715
714
  var operators = ['d', 'y', 'c'];
716
- operators.forEach(function(key, index, array) {
715
+ iterList(operators, function(key, index, array) {
717
716
  CodeMirror.keyMap['vim-prefix-'+key+'a'] = {
718
717
  auto: 'vim', nofallthrough: true, style: "fat-cursor"
719
718
  };
@@ -140,6 +140,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
140
140
  },
141
141
 
142
142
  indent: function(state, textAfter) {
143
+ if (state.tokenize == tokenComment) return CodeMirror.Pass;
143
144
  if (state.tokenize != tokenBase && state.tokenize != null) return 0;
144
145
  var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
145
146
  if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
@@ -228,7 +228,7 @@ CodeMirror.defineMode("css", function(config) {
228
228
  else if (/[,+>*\/]/.test(ch)) {
229
229
  return ret(null, "select-op");
230
230
  }
231
- else if (ch == "." && stream.match(/^\w+/)) {
231
+ else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
232
232
  return ret("qualifier", type);
233
233
  }
234
234
  else if (ch == ":") {
@@ -1,150 +1,94 @@
1
1
  CodeMirror.defineMode("gfm", function(config, parserConfig) {
2
- var mdMode = CodeMirror.getMode(config, "markdown");
3
- var aliases = {
4
- html: "htmlmixed",
5
- js: "javascript",
6
- json: "application/json",
7
- c: "text/x-csrc",
8
- "c++": "text/x-c++src",
9
- java: "text/x-java",
10
- csharp: "text/x-csharp",
11
- "c#": "text/x-csharp"
12
- };
13
-
14
- // make this lazy so that we don't need to load GFM last
15
- var getMode = (function () {
16
- var i, modes = {}, mimes = {}, mime;
17
-
18
- var list = CodeMirror.listModes();
19
- for (i = 0; i < list.length; i++) {
20
- modes[list[i]] = list[i];
21
- }
22
- var mimesList = CodeMirror.listMIMEs();
23
- for (i = 0; i < mimesList.length; i++) {
24
- mime = mimesList[i].mime;
25
- mimes[mime] = mimesList[i].mime;
26
- }
27
-
28
- for (var a in aliases) {
29
- if (aliases[a] in modes || aliases[a] in mimes)
30
- modes[a] = aliases[a];
31
- }
32
-
33
- return function (lang) {
34
- return modes[lang] ? CodeMirror.getMode(config, modes[lang]) : null;
35
- };
36
- }());
37
-
38
- function markdown(stream, state) {
39
- // intercept fenced code blocks
40
- if (stream.sol() && stream.match(/^```([\w+#]*)/)) {
41
- // try switching mode
42
- state.localMode = getMode(RegExp.$1);
43
- if (state.localMode)
44
- state.localState = state.localMode.startState();
45
-
46
- state.token = local;
47
- return 'code';
48
- }
49
-
50
- return mdMode.token(stream, state.mdState);
51
- }
52
-
53
- function local(stream, state) {
54
- if (stream.sol() && stream.match(/^```/)) {
55
- state.localMode = state.localState = null;
56
- state.token = markdown;
57
- return 'code';
58
- }
59
- else if (state.localMode) {
60
- return state.localMode.token(stream, state.localState);
61
- } else {
62
- stream.skipToEnd();
63
- return 'code';
64
- }
65
- }
66
-
67
- // custom handleText to prevent emphasis in the middle of a word
68
- // and add autolinking
69
- function handleText(stream, mdState) {
70
- var match;
71
- if (stream.match(/^\w+:\/\/\S+/)) {
72
- return 'link';
73
- }
74
- if (stream.match(/^[^\[*\\<>` _][^\[*\\<>` ]*[^\[*\\<>` _]/)) {
75
- return mdMode.getType(mdState);
76
- }
77
- if (match = stream.match(/^[^\[*\\<>` ]+/)) {
78
- var word = match[0];
79
- if (word[0] === '_' && word[word.length-1] === '_') {
80
- stream.backUp(word.length);
81
- return undefined;
82
- }
83
- return mdMode.getType(mdState);
84
- }
85
- if (stream.eatSpace()) {
86
- return null;
87
- }
2
+ var codeDepth = 0;
3
+ function blankLine(state) {
4
+ state.code = false;
5
+ return null;
88
6
  }
89
-
90
- return {
7
+ var gfmOverlay = {
91
8
  startState: function() {
92
- var mdState = mdMode.startState();
93
- mdState.text = handleText;
94
- return {token: markdown, mode: "markdown", mdState: mdState,
95
- localMode: null, localState: null};
9
+ return {
10
+ code: false,
11
+ codeBlock: false,
12
+ ateSpace: false
13
+ };
96
14
  },
97
-
98
- copyState: function(state) {
99
- return {token: state.token, mdState: CodeMirror.copyState(mdMode, state.mdState),
100
- localMode: state.localMode,
101
- localState: state.localMode ? CodeMirror.copyState(state.localMode, state.localState) : null};
15
+ copyState: function(s) {
16
+ return {
17
+ code: s.code,
18
+ codeBlock: s.codeBlock,
19
+ ateSpace: s.ateSpace
20
+ };
102
21
  },
103
-
104
22
  token: function(stream, state) {
105
- /* Parse GFM double bracket links */
106
- var ch;
107
- if ((ch = stream.peek()) != undefined && ch == '[') {
108
- stream.next(); // Advance the stream
109
-
110
- /* Only handle double bracket links */
111
- if ((ch = stream.peek()) == undefined || ch != '[') {
112
- stream.backUp(1);
113
- return state.token(stream, state);
114
- }
115
-
116
- while ((ch = stream.next()) != undefined && ch != ']') {}
117
-
118
- if (ch == ']' && (ch = stream.next()) != undefined && ch == ']')
119
- return 'link';
120
-
121
- /* If we did not find the second ']' */
122
- stream.backUp(1);
123
- }
124
-
125
- /* Match GFM latex formulas, as well as latex formulas within '$' */
126
- if (stream.match(/^\$[^\$]+\$/)) {
127
- return "string";
23
+ // Hack to prevent formatting override inside code blocks (block and inline)
24
+ if (state.codeBlock) {
25
+ if (stream.match(/^```/)) {
26
+ state.codeBlock = false;
27
+ return null;
128
28
  }
129
-
130
- if (stream.match(/^\\\((.*?)\\\)/)) {
131
- return "string";
132
- }
133
-
134
- if (stream.match(/^\$\$[^\$]+\$\$/)) {
135
- return "string";
29
+ stream.skipToEnd();
30
+ return null;
31
+ }
32
+ if (stream.sol()) {
33
+ state.code = false;
34
+ }
35
+ if (stream.sol() && stream.match(/^```/)) {
36
+ stream.skipToEnd();
37
+ state.codeBlock = true;
38
+ return null;
39
+ }
40
+ // If this block is changed, it may need to be updated in Markdown mode
41
+ if (stream.peek() === '`') {
42
+ stream.next();
43
+ var before = stream.pos;
44
+ stream.eatWhile('`');
45
+ var difference = 1 + stream.pos - before;
46
+ if (!state.code) {
47
+ codeDepth = difference;
48
+ state.code = true;
49
+ } else {
50
+ if (difference === codeDepth) { // Must be exact
51
+ state.code = false;
52
+ }
136
53
  }
137
-
138
- if (stream.match(/^\\\[(.*?)\\\]/)) {
139
- return "string";
54
+ return null;
55
+ } else if (state.code) {
56
+ stream.next();
57
+ return null;
58
+ }
59
+ // Check if space. If so, links can be formatted later on
60
+ if (stream.eatSpace()) {
61
+ state.ateSpace = true;
62
+ return null;
63
+ }
64
+ if (stream.sol() || state.ateSpace) {
65
+ state.ateSpace = false;
66
+ if(stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+@)?(?:[a-f0-9]{7,40}\b)/)) {
67
+ // User/Project@SHA
68
+ // User@SHA
69
+ // SHA
70
+ return "link";
71
+ } else if (stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+)?#[0-9]+\b/)) {
72
+ // User/Project#Num
73
+ // User#Num
74
+ // #Num
75
+ return "link";
140
76
  }
141
-
142
- return state.token(stream, state);
77
+ }
78
+ if (stream.match(/^((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/i)) {
79
+ // URLs
80
+ // Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls
81
+ return "link";
82
+ }
83
+ stream.next();
84
+ return null;
143
85
  },
144
-
145
- innerMode: function(state) {
146
- if (state.token == markdown) return {state: state.mdState, mode: mdMode};
147
- else return {state: state.localState, mode: state.localMode};
148
- }
86
+ blankLine: blankLine
149
87
  };
150
- }, "markdown");
88
+ CodeMirror.defineMIME("gfmBase", {
89
+ name: "markdown",
90
+ underscoresBreakWords: false,
91
+ fencedCodeBlocks: true
92
+ });
93
+ return CodeMirror.overlayMode(CodeMirror.getMode(config, "gfmBase"), gfmOverlay);
94
+ });
@@ -70,3 +70,4 @@ CodeMirror.defineMode("htmlembedded", function(config, parserConfig) {
70
70
  CodeMirror.defineMIME("application/x-ejs", { name: "htmlembedded", scriptingModeSpec:"javascript"});
71
71
  CodeMirror.defineMIME("application/x-aspx", { name: "htmlembedded", scriptingModeSpec:"text/x-csharp"});
72
72
  CodeMirror.defineMIME("application/x-jsp", { name: "htmlembedded", scriptingModeSpec:"text/x-java"});
73
+ CodeMirror.defineMIME("application/x-erb", { name: "htmlembedded", scriptingModeSpec:"ruby"});
@@ -1,6 +1,9 @@
1
+ // TODO actually recognize syntax of TypeScript constructs
2
+
1
3
  CodeMirror.defineMode("javascript", function(config, parserConfig) {
2
4
  var indentUnit = config.indentUnit;
3
5
  var jsonMode = parserConfig.json;
6
+ var isTS = parserConfig.typescript;
4
7
 
5
8
  // Tokenizer
6
9
 
@@ -8,7 +11,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
8
11
  function kw(type) {return {type: type, style: "keyword"};}
9
12
  var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
10
13
  var operator = kw("operator"), atom = {type: "atom", style: "atom"};
11
- return {
14
+
15
+ var jsKeywords = {
12
16
  "if": A, "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
13
17
  "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C,
14
18
  "var": kw("var"), "const": kw("var"), "let": kw("var"),
@@ -17,6 +21,35 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
17
21
  "in": operator, "typeof": operator, "instanceof": operator,
18
22
  "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom
19
23
  };
24
+
25
+ // Extend the 'normal' keywords with the TypeScript language extensions
26
+ if (isTS) {
27
+ var type = {type: "variable", style: "variable-3"};
28
+ var tsKeywords = {
29
+ // object-like things
30
+ "interface": kw("interface"),
31
+ "class": kw("class"),
32
+ "extends": kw("extends"),
33
+ "constructor": kw("constructor"),
34
+
35
+ // scope modifiers
36
+ "public": kw("public"),
37
+ "private": kw("private"),
38
+ "protected": kw("protected"),
39
+ "static": kw("static"),
40
+
41
+ "super": kw("super"),
42
+
43
+ // types
44
+ "string": type, "number": type, "bool": type, "any": type
45
+ };
46
+
47
+ for (var attr in tsKeywords) {
48
+ jsKeywords[attr] = tsKeywords[attr];
49
+ }
50
+ }
51
+
52
+ return jsKeywords;
20
53
  }();
21
54
 
22
55
  var isOperatorChar = /[+\-*&%=<>!?|]/;
@@ -66,7 +99,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
66
99
  stream.skipToEnd();
67
100
  return ret("comment", "comment");
68
101
  }
69
- else if (state.reAllowed) {
102
+ else if (state.lastType == "operator" || state.lastType == "keyword c" ||
103
+ /^[\[{}\(,;:]$/.test(state.lastType)) {
70
104
  nextUntilUnescaped(stream, "/");
71
105
  stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
72
106
  return ret("regexp", "string-2");
@@ -87,7 +121,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
87
121
  else {
88
122
  stream.eatWhile(/[\w\$_]/);
89
123
  var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
90
- return (known && state.kwAllowed) ? ret(known.type, known.style, word) :
124
+ return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
91
125
  ret("variable", "variable", word);
92
126
  }
93
127
  }
@@ -275,19 +309,30 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
275
309
  if (type == "}") return cont();
276
310
  return pass(statement, block);
277
311
  }
312
+ function maybetype(type) {
313
+ if (type == ":") return cont(typedef);
314
+ return pass();
315
+ }
316
+ function typedef(type) {
317
+ if (type == "variable"){cx.marked = "variable-3"; return cont();}
318
+ return pass();
319
+ }
278
320
  function vardef1(type, value) {
279
- if (type == "variable"){register(value); return cont(vardef2);}
280
- return cont();
321
+ if (type == "variable") {
322
+ register(value);
323
+ return isTS ? cont(maybetype, vardef2) : cont(vardef2);
324
+ }
325
+ return pass();
281
326
  }
282
327
  function vardef2(type, value) {
283
328
  if (value == "=") return cont(expression, vardef2);
284
329
  if (type == ",") return cont(vardef1);
285
330
  }
286
331
  function forspec1(type) {
287
- if (type == "var") return cont(vardef1, forspec2);
288
- if (type == ";") return pass(forspec2);
332
+ if (type == "var") return cont(vardef1, expect(";"), forspec2);
333
+ if (type == ";") return cont(forspec2);
289
334
  if (type == "variable") return cont(formaybein);
290
- return pass(forspec2);
335
+ return cont(forspec2);
291
336
  }
292
337
  function formaybein(type, value) {
293
338
  if (value == "in") return cont(expression);
@@ -306,7 +351,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
306
351
  if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext);
307
352
  }
308
353
  function funarg(type, value) {
309
- if (type == "variable") {register(value); return cont();}
354
+ if (type == "variable") {register(value); return isTS ? cont(maybetype) : cont();}
310
355
  }
311
356
 
312
357
  // Interface
@@ -315,8 +360,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
315
360
  startState: function(basecolumn) {
316
361
  return {
317
362
  tokenize: jsTokenBase,
318
- reAllowed: true,
319
- kwAllowed: true,
363
+ lastType: null,
320
364
  cc: [],
321
365
  lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
322
366
  localVars: parserConfig.localVars,
@@ -334,19 +378,21 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
334
378
  if (stream.eatSpace()) return null;
335
379
  var style = state.tokenize(stream, state);
336
380
  if (type == "comment") return style;
337
- state.reAllowed = !!(type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/));
338
- state.kwAllowed = type != '.';
381
+ state.lastType = type;
339
382
  return parseJS(state, style, type, content, stream);
340
383
  },
341
384
 
342
385
  indent: function(state, textAfter) {
386
+ if (state.tokenize == jsTokenComment) return CodeMirror.Pass;
343
387
  if (state.tokenize != jsTokenBase) return 0;
344
388
  var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
345
389
  if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
346
390
  var type = lexical.type, closing = firstChar == type;
347
- if (type == "vardef") return lexical.indented + 4;
391
+ if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? 4 : 0);
348
392
  else if (type == "form" && firstChar == "{") return lexical.indented;
349
- else if (type == "stat" || type == "form") return lexical.indented + indentUnit;
393
+ else if (type == "form") return lexical.indented + indentUnit;
394
+ else if (type == "stat")
395
+ return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? indentUnit : 0);
350
396
  else if (lexical.info == "switch" && !closing)
351
397
  return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
352
398
  else if (lexical.align) return lexical.column + (closing ? 0 : 1);
@@ -359,3 +405,5 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
359
405
 
360
406
  CodeMirror.defineMIME("text/javascript", "javascript");
361
407
  CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
408
+ CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
409
+ CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
@@ -64,7 +64,7 @@ CodeMirror.defineMode("lua", function(config, parserConfig) {
64
64
  function normal(stream, state) {
65
65
  var ch = stream.next();
66
66
  if (ch == "-" && stream.eat("-")) {
67
- if (stream.eat("["))
67
+ if (stream.eat("[") && stream.eat("["))
68
68
  return (state.cur = bracketed(readBracket(stream), "comment"))(stream, state);
69
69
  stream.skipToEnd();
70
70
  return "comment";
@@ -2,6 +2,46 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
2
2
 
3
3
  var htmlFound = CodeMirror.mimeModes.hasOwnProperty("text/html");
4
4
  var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? "text/html" : "text/plain");
5
+ var aliases = {
6
+ html: "htmlmixed",
7
+ js: "javascript",
8
+ json: "application/json",
9
+ c: "text/x-csrc",
10
+ "c++": "text/x-c++src",
11
+ java: "text/x-java",
12
+ csharp: "text/x-csharp",
13
+ "c#": "text/x-csharp"
14
+ };
15
+
16
+ var getMode = (function () {
17
+ var i, modes = {}, mimes = {}, mime;
18
+
19
+ var list = CodeMirror.listModes();
20
+ for (i = 0; i < list.length; i++) {
21
+ modes[list[i]] = list[i];
22
+ }
23
+ var mimesList = CodeMirror.listMIMEs();
24
+ for (i = 0; i < mimesList.length; i++) {
25
+ mime = mimesList[i].mime;
26
+ mimes[mime] = mimesList[i].mime;
27
+ }
28
+
29
+ for (var a in aliases) {
30
+ if (aliases[a] in modes || aliases[a] in mimes)
31
+ modes[a] = aliases[a];
32
+ }
33
+
34
+ return function (lang) {
35
+ return modes[lang] ? CodeMirror.getMode(cmCfg, modes[lang]) : null;
36
+ };
37
+ }());
38
+
39
+ // Should underscores in words open/close em/strong?
40
+ if (modeCfg.underscoresBreakWords === undefined)
41
+ modeCfg.underscoresBreakWords = true;
42
+
43
+ // Turn on fenced code blocks? ("```" to start/end)
44
+ if (modeCfg.fencedCodeBlocks === undefined) modeCfg.fencedCodeBlocks = false;
5
45
 
6
46
  var codeDepth = 0;
7
47
  var prevLineHasContent = false
@@ -12,6 +52,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
12
52
  , quote = 'quote'
13
53
  , list = 'string'
14
54
  , hr = 'hr'
55
+ , image = 'tag'
15
56
  , linkinline = 'link'
16
57
  , linkemail = 'link'
17
58
  , linktext = 'link'
@@ -24,7 +65,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
24
65
  , ulRE = /^[*\-+]\s+/
25
66
  , olRE = /^[0-9]+\.\s+/
26
67
  , headerRE = /^(?:\={1,}|-{1,})$/
27
- , textRE = /^[^\[*_\\<>` "'(]+/;
68
+ , textRE = /^[^!\[\]*_\\<>` "'(]+/;
28
69
 
29
70
  function switchInline(stream, state, f) {
30
71
  state.f = state.inline = f;
@@ -42,8 +83,6 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
42
83
  function blankLine(state) {
43
84
  // Reset linkTitle state
44
85
  state.linkTitle = false;
45
- // Reset CODE state
46
- state.code = false;
47
86
  // Reset EM state
48
87
  state.em = false;
49
88
  // Reset STRONG state
@@ -58,7 +97,6 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
58
97
  }
59
98
 
60
99
  function blockNormal(stream, state) {
61
- var match;
62
100
 
63
101
  if (state.list !== false && state.indentationDiff >= 0) { // Continued list
64
102
  if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block
@@ -84,9 +122,15 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
84
122
  return switchInline(stream, state, footnoteLink);
85
123
  } else if (stream.match(hrRE, true)) {
86
124
  return hr;
87
- } else if (match = stream.match(ulRE, true) || stream.match(olRE, true)) {
125
+ } else if (stream.match(ulRE, true) || stream.match(olRE, true)) {
88
126
  state.indentation += 4;
89
127
  state.list = true;
128
+ } else if (modeCfg.fencedCodeBlocks && stream.match(/^```([\w+#]*)/, true)) {
129
+ // try switching mode
130
+ state.localMode = getMode(RegExp.$1);
131
+ if (state.localMode) state.localState = state.localMode.startState();
132
+ switchBlock(stream, state, local);
133
+ return code;
90
134
  }
91
135
 
92
136
  return switchInline(stream, state, state.inline);
@@ -106,6 +150,30 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
106
150
  return style;
107
151
  }
108
152
 
153
+ function local(stream, state) {
154
+ if (stream.sol() && stream.match(/^```/, true)) {
155
+ state.localMode = state.localState = null;
156
+ state.f = inlineNormal;
157
+ state.block = blockNormal;
158
+ return code;
159
+ } else if (state.localMode) {
160
+ return state.localMode.token(stream, state.localState);
161
+ } else {
162
+ stream.skipToEnd();
163
+ return code;
164
+ }
165
+ }
166
+
167
+ function codeBlock(stream, state) {
168
+ if(stream.match(codeBlockRE, true)){
169
+ state.f = inlineNormal;
170
+ state.block = blockNormal;
171
+ switchInline(stream, state, state.inline);
172
+ return code;
173
+ }
174
+ stream.skipToEnd();
175
+ return code;
176
+ }
109
177
 
110
178
  // Inline
111
179
  function getType(state) {
@@ -114,6 +182,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
114
182
  if (state.strong) { styles.push(state.em ? emstrong : strong); }
115
183
  else if (state.em) { styles.push(em); }
116
184
 
185
+ if (state.linkText) { styles.push(linktext); }
186
+
117
187
  if (state.code) { styles.push(code); }
118
188
 
119
189
  if (state.header) { styles.push(header); }
@@ -161,6 +231,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
161
231
  }
162
232
  }
163
233
 
234
+ // If this block is changed, it may need to be updated in GFM mode
164
235
  if (ch === '`') {
165
236
  var t = getType(state);
166
237
  var before = stream.pos;
@@ -181,8 +252,22 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
181
252
  return getType(state);
182
253
  }
183
254
 
184
- if (ch === '[' && stream.match(/.*\] ?(?:\(|\[)/, false)) {
185
- return switchInline(stream, state, linkText);
255
+ if (ch === '!' && stream.match(/\[.*\] ?(?:\(|\[)/, false)) {
256
+ stream.match(/\[.*\]/);
257
+ state.inline = state.f = linkHref;
258
+ return image;
259
+ }
260
+
261
+ if (ch === '[' && stream.match(/.*\](\(| ?\[)/, false)) {
262
+ state.linkText = true;
263
+ return getType(state);
264
+ }
265
+
266
+ if (ch === ']' && state.linkText) {
267
+ var type = getType(state);
268
+ state.linkText = false;
269
+ state.inline = state.f = linkHref;
270
+ return type;
186
271
  }
187
272
 
188
273
  if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, true)) {
@@ -210,8 +295,20 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
210
295
  return "tag";
211
296
  }
212
297
 
298
+ var ignoreUnderscore = false;
299
+ if (!modeCfg.underscoresBreakWords) {
300
+ if (ch === '_' && stream.peek() !== '_' && stream.match(/(\w)/, false)) {
301
+ var prevPos = stream.pos - 2;
302
+ if (prevPos >= 0) {
303
+ var prevCh = stream.string.charAt(prevPos);
304
+ if (prevCh !== '_' && prevCh.match(/(\w)/, false)) {
305
+ ignoreUnderscore = true;
306
+ }
307
+ }
308
+ }
309
+ }
213
310
  var t = getType(state);
214
- if (ch === '*' || ch === '_') {
311
+ if (ch === '*' || (ch === '_' && !ignoreUnderscore)) {
215
312
  if (state.strong === ch && stream.eat(ch)) { // Remove STRONG
216
313
  state.strong = false;
217
314
  return t;
@@ -238,18 +335,6 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
238
335
  return getType(state);
239
336
  }
240
337
 
241
- function linkText(stream, state) {
242
- while (!stream.eol()) {
243
- var ch = stream.next();
244
- if (ch === '\\') stream.next();
245
- if (ch === ']') {
246
- state.inline = state.f = linkHref;
247
- return linktext;
248
- }
249
- }
250
- return linktext;
251
- }
252
-
253
338
  function linkHref(stream, state) {
254
339
  // Check if space, and return NULL if so (to avoid marking the space)
255
340
  if(stream.eatSpace()){
@@ -287,15 +372,16 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
287
372
  return linkhref;
288
373
  }
289
374
 
375
+ var savedInlineRE = [];
290
376
  function inlineRE(endChar) {
291
- if (!inlineRE[endChar]) {
377
+ if (!savedInlineRE[endChar]) {
292
378
  // Escape endChar for RegExp (taken from http://stackoverflow.com/a/494122/526741)
293
379
  endChar = (endChar+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
294
380
  // Match any non-endChar, escaped character, as well as the closing
295
381
  // endChar.
296
- inlineRE[endChar] = new RegExp('^(?:[^\\\\]+?|\\\\.)*?(' + endChar + ')');
382
+ savedInlineRE[endChar] = new RegExp('^(?:[^\\\\]|\\\\.)*?(' + endChar + ')');
297
383
  }
298
- return inlineRE[endChar];
384
+ return savedInlineRE[endChar];
299
385
  }
300
386
 
301
387
  function inlineElement(type, endChar, next) {
@@ -309,6 +395,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
309
395
 
310
396
  return {
311
397
  startState: function() {
398
+ prevLineHasContent = false;
399
+ thisLineHasContent = false;
312
400
  return {
313
401
  f: blockNormal,
314
402
 
@@ -318,6 +406,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
318
406
 
319
407
  inline: inlineNormal,
320
408
  text: handleText,
409
+
410
+ linkText: false,
321
411
  linkTitle: false,
322
412
  em: false,
323
413
  strong: false,
@@ -334,6 +424,9 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
334
424
  block: s.block,
335
425
  htmlState: CodeMirror.copyState(htmlMode, s.htmlState),
336
426
  indentation: s.indentation,
427
+
428
+ localMode: s.localMode,
429
+ localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null,
337
430
 
338
431
  inline: s.inline,
339
432
  text: s.text,
@@ -362,9 +455,15 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
362
455
 
363
456
  // Reset state.header
364
457
  state.header = false;
458
+
459
+ // Reset state.code
460
+ state.code = false;
365
461
 
366
462
  state.f = state.block;
367
463
  var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, ' ').length;
464
+ var difference = Math.floor((indentation - state.indentation) / 4) * 4;
465
+ if (difference > 4) difference = 4;
466
+ indentation = state.indentation + difference;
368
467
  state.indentationDiff = indentation - state.indentation;
369
468
  state.indentation = indentation;
370
469
  if (indentation > 0) { return null; }
@@ -49,6 +49,11 @@ CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, comb
49
49
  },
50
50
  electricChars: base.electricChars,
51
51
 
52
- innerMode: function(state) { return {state: state.base, mode: base}; }
52
+ innerMode: function(state) { return {state: state.base, mode: base}; },
53
+
54
+ blankLine: function(state) {
55
+ if (base.blankLine) base.blankLine(state.base);
56
+ if (overlay.blankLine) overlay.blankLine(state.overlay);
57
+ }
53
58
  };
54
59
  };
@@ -1,6 +1,6 @@
1
1
  CodeMirror.runMode = function(string, modespec, callback, options) {
2
2
  function esc(str) {
3
- return str.replace(/[<&]/, function(ch) { return ch == "<" ? "&lt;" : "&amp;"; });
3
+ return str.replace(/[<&]/g, function(ch) { return ch == "<" ? "&lt;" : "&amp;"; });
4
4
  }
5
5
 
6
6
  var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
@@ -17,14 +17,14 @@
17
17
  query.lastIndex = 0;
18
18
  var line = cm.getLine(pos.line).slice(0, pos.ch), match = query.exec(line), start = 0;
19
19
  while (match) {
20
- start += match.index;
21
- line = line.slice(match.index);
20
+ start += match.index + 1;
21
+ line = line.slice(start);
22
22
  query.lastIndex = 0;
23
23
  var newmatch = query.exec(line);
24
24
  if (newmatch) match = newmatch;
25
25
  else break;
26
- start++;
27
26
  }
27
+ start--;
28
28
  } else {
29
29
  query.lastIndex = pos.ch;
30
30
  var line = cm.getLine(pos.line), match = query.exec(line),
@@ -25,7 +25,10 @@
25
25
  editor.replaceRange(str, result.from, result.to);
26
26
  }
27
27
  // When there is only one completion, use it directly.
28
- if (completions.length == 1) {insert(completions[0]); return true;}
28
+ if (options.completeSingle && completions.length == 1) {
29
+ insert(completions[0]);
30
+ return true;
31
+ }
29
32
 
30
33
  // Build the select widget
31
34
  var complete = document.createElement("div");
@@ -41,7 +44,7 @@
41
44
  }
42
45
  sel.firstChild.selected = true;
43
46
  sel.size = Math.min(10, completions.length);
44
- var pos = editor.cursorCoords();
47
+ var pos = options.alignWithWord ? editor.charCoords(result.from) : editor.cursorCoords();
45
48
  complete.style.left = pos.x + "px";
46
49
  complete.style.top = pos.yBot + "px";
47
50
  document.body.appendChild(complete);
@@ -71,7 +74,7 @@
71
74
  if (code == 13) {CodeMirror.e_stop(event); pick();}
72
75
  // Escape
73
76
  else if (code == 27) {CodeMirror.e_stop(event); close(); editor.focus();}
74
- else if (code != 38 && code != 40 && code != 33 && code != 34) {
77
+ else if (code != 38 && code != 40 && code != 33 && code != 34 && !CodeMirror.isModifierKey(event)) {
75
78
  close(); editor.focus();
76
79
  // Pass the event to the CodeMirror instance so that it can handle things like backspace properly.
77
80
  editor.triggerOnKeyDown(event);
@@ -92,6 +95,8 @@
92
95
  };
93
96
  CodeMirror.simpleHint.defaults = {
94
97
  closeOnBackspace: true,
95
- closeOnTokenChange: false
98
+ closeOnTokenChange: false,
99
+ completeSingle: true,
100
+ alignWithWord: true
96
101
  };
97
102
  })();
@@ -80,6 +80,7 @@
80
80
  word-wrap: normal;
81
81
  line-height: inherit;
82
82
  color: inherit;
83
+ overflow: visible;
83
84
  }
84
85
 
85
86
  .CodeMirror-wrap pre {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codemirror-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: '2.34'
4
+ version: '2.35'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-13 00:00:00.000000000Z
12
+ date: 2012-10-27 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties
16
- requirement: &2165230860 !ruby/object:Gem::Requirement
16
+ requirement: &2165649660 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2165230860
24
+ version_requirements: *2165649660
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rails
27
- requirement: &2165230340 !ruby/object:Gem::Requirement
27
+ requirement: &2165648920 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '3.0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *2165230340
35
+ version_requirements: *2165648920
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: sqlite3
38
- requirement: &2165229960 !ruby/object:Gem::Requirement
38
+ requirement: &2165647960 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2165229960
46
+ version_requirements: *2165647960
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: minitest
49
- requirement: &2165229320 !ruby/object:Gem::Requirement
49
+ requirement: &2165647440 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2165229320
57
+ version_requirements: *2165647440
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: capybara
60
- requirement: &2165228760 !ruby/object:Gem::Requirement
60
+ requirement: &2165647020 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *2165228760
68
+ version_requirements: *2165647020
69
69
  description: This gem provides CodeMirror assets for your Rails 3 application.
70
70
  email: nathan@fixler.org
71
71
  executables: []