codemirror-rails 0.2.0 → 0.2.1

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.
data/README.md CHANGED
@@ -7,10 +7,3 @@ Rails 3 project.
7
7
  ```
8
8
  rails generate codemirror:install
9
9
  ```
10
-
11
- TODO:
12
-
13
- * Suppport for the Rails 3.1+ asset pipline
14
- * Optionally install additional modes (currently only plain text)
15
- * View helpers?
16
- * JS initialization example for a basic CodeMirror textarea
@@ -1,6 +1,6 @@
1
1
  module Codemirror
2
2
  module Rails
3
- VERSION = '0.2.0'
4
- CODEMIRROR_VERSION = '2.11'
3
+ VERSION = '0.2.1'
4
+ CODEMIRROR_VERSION = '2.12'
5
5
  end
6
6
  end
@@ -72,7 +72,7 @@ var CodeMirror = (function() {
72
72
  var editing, bracketHighlighted;
73
73
  // Tracks the maximum line length so that the horizontal scrollbar
74
74
  // can be kept static when scrolling.
75
- var maxLine = "";
75
+ var maxLine = "", maxWidth;
76
76
 
77
77
  // Initialize the content.
78
78
  operation(function(){setValue(options.value || ""); updateInput = false;})();
@@ -92,8 +92,8 @@ var CodeMirror = (function() {
92
92
  connect(input, "focus", onFocus);
93
93
  connect(input, "blur", onBlur);
94
94
 
95
- connect(scroller, "dragenter", function(e){e.stop();});
96
- connect(scroller, "dragover", function(e){e.stop();});
95
+ connect(scroller, "dragenter", e_stop);
96
+ connect(scroller, "dragover", e_stop);
97
97
  connect(scroller, "drop", operation(onDrop));
98
98
  connect(scroller, "paste", function(){focusInput(); fastPoll();});
99
99
  connect(input, "paste", function(){fastPoll();});
@@ -161,10 +161,13 @@ var CodeMirror = (function() {
161
161
  code.appendChild(node);
162
162
  node.style.left = left + "px";
163
163
  if (where == "over") top = pos.y;
164
- else if (where == "fit") {
165
- var vspace = lines.length * lineHeight(), hspace = code.clientWidth - paddingLeft();
166
- top = pos.y + node.offsetHeight > vspace ? vspace - node.offsetHeight : pos.y;
167
- if (left + node.offsetWidth > hspace) left = hspace - node.offsetWidth;
164
+ else if (where == "near") {
165
+ var vspace = Math.max(scroller.offsetHeight, lines.length * lineHeight()),
166
+ hspace = Math.max(code.clientWidth, lineSpace.clientWidth) - paddingLeft();
167
+ if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight)
168
+ top = pos.y - node.offsetHeight;
169
+ if (left + node.offsetWidth > hspace)
170
+ left = hspace - node.offsetWidth;
168
171
  }
169
172
  node.style.top = (top + paddingTop()) + "px";
170
173
  node.style.left = (left + paddingLeft()) + "px";
@@ -215,17 +218,21 @@ var CodeMirror = (function() {
215
218
  }
216
219
 
217
220
  function onMouseDown(e) {
221
+ // Check whether this is a click in a widget
222
+ for (var n = e_target(e); n != wrapper; n = n.parentNode)
223
+ if (n.parentNode == code && n != mover) return;
218
224
  var ld = lastDoubleClick; lastDoubleClick = null;
219
225
  // First, see if this is a click in the gutter
220
- for (var n = e.target(); n != wrapper; n = n.parentNode)
226
+ for (var n = e_target(e); n != wrapper; n = n.parentNode)
221
227
  if (n.parentNode == gutterText) {
222
228
  if (options.onGutterClick)
223
229
  options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom);
224
- return e.stop();
230
+ return e_preventDefault(e);
225
231
  }
226
232
 
227
233
  var start = posFromMouse(e);
228
- switch (e.button()) {
234
+
235
+ switch (e_button(e)) {
229
236
  case 3:
230
237
  if (gecko && !mac) onContextMenu(e);
231
238
  return;
@@ -236,10 +243,10 @@ var CodeMirror = (function() {
236
243
  // For button 1, if it was clicked inside the editor
237
244
  // (posFromMouse returning non-null), we have to adjust the
238
245
  // selection.
239
- if (!start) {if (e.target() == scroller) e.stop(); return;}
246
+ if (!start) {if (e_target(e) == scroller) e_preventDefault(e); return;}
240
247
 
241
248
  if (!focused) onFocus();
242
- e.stop();
249
+ e_preventDefault(e);
243
250
  if (ld && +new Date - ld < 400) return selectLine(start.line);
244
251
 
245
252
  setCursor(start.line, start.ch, true);
@@ -266,14 +273,14 @@ var CodeMirror = (function() {
266
273
 
267
274
  var move = connect(targetDocument, "mousemove", operation(function(e) {
268
275
  clearTimeout(going);
269
- e.stop();
276
+ e_preventDefault(e);
270
277
  extend(e);
271
278
  }), true);
272
279
  var up = connect(targetDocument, "mouseup", operation(function(e) {
273
280
  clearTimeout(going);
274
281
  var cur = posFromMouse(e);
275
282
  if (cur) setSelectionUser(start, cur);
276
- e.stop();
283
+ e_preventDefault(e);
277
284
  end();
278
285
  }), true);
279
286
  }
@@ -281,12 +288,12 @@ var CodeMirror = (function() {
281
288
  var pos = posFromMouse(e);
282
289
  if (!pos) return;
283
290
  selectWordAt(pos);
284
- e.stop();
291
+ e_preventDefault(e);
285
292
  lastDoubleClick = +new Date;
286
293
  }
287
294
  function onDrop(e) {
288
- e.e.preventDefault();
289
- var pos = posFromMouse(e, true), files = e.e.dataTransfer.files;
295
+ e.preventDefault();
296
+ var pos = posFromMouse(e, true), files = e.dataTransfer.files;
290
297
  if (!pos || options.readOnly) return;
291
298
  if (files && files.length && window.FileReader && window.File) {
292
299
  function loadFile(file, i) {
@@ -302,7 +309,7 @@ var CodeMirror = (function() {
302
309
  }
303
310
  else {
304
311
  try {
305
- var text = e.e.dataTransfer.getData("Text");
312
+ var text = e.dataTransfer.getData("Text");
306
313
  if (text) replaceRange(text, pos, pos);
307
314
  }
308
315
  catch(e){}
@@ -311,27 +318,27 @@ var CodeMirror = (function() {
311
318
  function onKeyDown(e) {
312
319
  if (!focused) onFocus();
313
320
 
314
- var code = e.e.keyCode;
321
+ var code = e.keyCode;
315
322
  // IE does strange things with escape.
316
- if (ie && code == 27) { e.e.returnValue = false; }
323
+ if (ie && code == 27) { e.returnValue = false; }
317
324
  // Tries to detect ctrl on non-mac, cmd on mac.
318
- var mod = (mac ? e.e.metaKey : e.e.ctrlKey) && !e.e.altKey, anyMod = e.e.ctrlKey || e.e.altKey || e.e.metaKey;
319
- if (code == 16 || e.e.shiftKey) shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from);
325
+ var mod = (mac ? e.metaKey : e.ctrlKey) && !e.altKey, anyMod = e.ctrlKey || e.altKey || e.metaKey;
326
+ if (code == 16 || e.shiftKey) shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from);
320
327
  else shiftSelecting = null;
321
328
  // First give onKeyEvent option a chance to handle this.
322
- if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e.e))) return;
329
+ if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
323
330
 
324
- if (code == 33 || code == 34) {scrollPage(code == 34); return e.stop();} // page up/down
331
+ if (code == 33 || code == 34) {scrollPage(code == 34); return e_preventDefault(e);} // page up/down
325
332
  if (mod && ((code == 36 || code == 35) || // ctrl-home/end
326
333
  mac && (code == 38 || code == 40))) { // cmd-up/down
327
- scrollEnd(code == 36 || code == 38); return e.stop();
334
+ scrollEnd(code == 36 || code == 38); return e_preventDefault(e);
328
335
  }
329
- if (mod && code == 65) {selectAll(); return e.stop();} // ctrl-a
336
+ if (mod && code == 65) {selectAll(); return e_preventDefault(e);} // ctrl-a
330
337
  if (!options.readOnly) {
331
338
  if (!anyMod && code == 13) {return;} // enter
332
- if (!anyMod && code == 9 && handleTab(e.e.shiftKey)) return e.stop(); // tab
333
- if (mod && code == 90) {undo(); return e.stop();} // ctrl-z
334
- if (mod && ((e.e.shiftKey && code == 90) || code == 89)) {redo(); return e.stop();} // ctrl-shift-z, ctrl-y
339
+ if (!anyMod && code == 9 && handleTab(e.shiftKey)) return e_preventDefault(e); // tab
340
+ if (mod && code == 90) {undo(); return e_preventDefault(e);} // ctrl-z
341
+ if (mod && ((e.shiftKey && code == 90) || code == 89)) {redo(); return e_preventDefault(e);} // ctrl-shift-z, ctrl-y
335
342
  }
336
343
 
337
344
  // Key id to use in the movementKeys map. We also pass it to
@@ -351,24 +358,24 @@ var CodeMirror = (function() {
351
358
  fastPoll(curKeyId);
352
359
  }
353
360
  function onKeyUp(e) {
354
- if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e.e))) return;
361
+ if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
355
362
  if (reducedSelection) {
356
363
  reducedSelection = null;
357
364
  updateInput = true;
358
365
  }
359
- if (e.e.keyCode == 16) shiftSelecting = null;
366
+ if (e.keyCode == 16) shiftSelecting = null;
360
367
  }
361
368
  function onKeyPress(e) {
362
- if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e.e))) return;
369
+ if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
363
370
  if (options.electricChars && mode.electricChars) {
364
- var ch = String.fromCharCode(e.e.charCode == null ? e.e.keyCode : e.e.charCode);
371
+ var ch = String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode);
365
372
  if (mode.electricChars.indexOf(ch) > -1)
366
373
  setTimeout(operation(function() {indentLine(sel.to.line, "smart");}), 50);
367
374
  }
368
- var code = e.e.keyCode;
375
+ var code = e.keyCode;
369
376
  // Re-stop tab and enter. Necessary on some browsers.
370
- if (code == 13) {if (!options.readOnly) handleEnter(); e.stop();}
371
- else if (!e.e.ctrlKey && !e.e.altKey && !e.e.metaKey && code == 9 && options.tabMode != "default") e.stop();
377
+ if (code == 13) {if (!options.readOnly) handleEnter(); e_preventDefault(e);}
378
+ else if (!e.ctrlKey && !e.altKey && !e.metaKey && code == 9 && options.tabMode != "default") e_preventDefault(e);
372
379
  else fastPoll(curKeyId);
373
380
  }
374
381
 
@@ -414,6 +421,7 @@ var CodeMirror = (function() {
414
421
  var pos = clipPos({line: change.start + change.old.length - 1,
415
422
  ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])});
416
423
  updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: lines[end-1].text.length}, change.old, pos, pos);
424
+ updateInput = true;
417
425
  }
418
426
  }
419
427
  function undo() {unredoHelper(history.done, history.undone);}
@@ -455,12 +463,12 @@ var CodeMirror = (function() {
455
463
  for (var i = from.line, e = i + newText.length; i < e; ++i) {
456
464
  var l = lines[i].text;
457
465
  if (l.length > maxLineLength) {
458
- maxLine = l; maxLineLength = l.length;
466
+ maxLine = l; maxLineLength = l.length; maxWidth = null;
459
467
  recomputeMaxLength = false;
460
468
  }
461
469
  }
462
470
  if (recomputeMaxLength) {
463
- maxLineLength = 0; maxLine = "";
471
+ maxLineLength = 0; maxLine = ""; maxWidth = null;
464
472
  for (var i = 0, e = lines.length; i < e; ++i) {
465
473
  var l = lines[i].text;
466
474
  if (l.length > maxLineLength) {
@@ -570,7 +578,7 @@ var CodeMirror = (function() {
570
578
  // to the data in the editing variable, and updates the editor
571
579
  // content or cursor if something changed.
572
580
  function readInput() {
573
- if (leaveInputAlone) return;
581
+ if (leaveInputAlone || !focused) return;
574
582
  var changed = false, text = input.value, sr = selRange(input);
575
583
  if (!sr) return false;
576
584
  var changed = editing.text != text, rs = reducedSelection;
@@ -761,10 +769,15 @@ var CodeMirror = (function() {
761
769
  updateGutter();
762
770
  }
763
771
 
764
- var textWidth = stringWidth(maxLine);
765
- lineSpace.style.width = textWidth > scroller.clientWidth ? textWidth + "px" : "";
766
- // Needed to prevent odd wrapping/hiding of widgets placed in here.
767
- code.style.width = (lineSpace.offsetWidth + lineSpace.offsetLeft) + "px";
772
+ if (maxWidth == null) maxWidth = stringWidth(maxLine);
773
+ if (maxWidth > scroller.clientWidth) {
774
+ lineSpace.style.width = maxWidth + "px";
775
+ // Needed to prevent odd wrapping/hiding of widgets placed in here.
776
+ code.style.width = "";
777
+ code.style.width = scroller.scrollWidth + "px";
778
+ } else {
779
+ lineSpace.style.width = code.style.width = "";
780
+ }
768
781
 
769
782
  // Since this is all rather error prone, it is honoured with the
770
783
  // only assertion in the whole file.
@@ -959,8 +972,8 @@ var CodeMirror = (function() {
959
972
  function handleTab(shift) {
960
973
  function indentSelected(mode) {
961
974
  if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode);
962
- var e = sel.to.line - (sel.to.ch ? 1 : 0);
963
- for (var i = sel.from.line; i < e; ++i) indentLine(i, mode);
975
+ var e = sel.to.line - (sel.to.ch ? 0 : 1);
976
+ for (var i = sel.from.line; i <= e; ++i) indentLine(i, mode);
964
977
  }
965
978
  shiftSelecting = null;
966
979
  switch (options.tabMode) {
@@ -1159,7 +1172,7 @@ var CodeMirror = (function() {
1159
1172
  function posFromMouse(e, liberal) {
1160
1173
  var offW = eltOffset(scroller, true), x, y;
1161
1174
  // Fails unpredictably on IE[67] when mouse is dragged around quickly.
1162
- try { x = e.e.clientX; y = e.e.clientY; } catch (e) { return null; }
1175
+ try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
1163
1176
  // This is a mess of a heuristic to try and determine whether a
1164
1177
  // scroll-bar was clicked or not, and to return null if one was
1165
1178
  // (and !liberal).
@@ -1177,8 +1190,8 @@ var CodeMirror = (function() {
1177
1190
 
1178
1191
  var oldCSS = input.style.cssText;
1179
1192
  inputDiv.style.position = "absolute";
1180
- input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.pageY() - 1) +
1181
- "px; left: " + (e.pageX() - 1) + "px; z-index: 1000; background: white; " +
1193
+ input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e_pageY(e) - 1) +
1194
+ "px; left: " + (e_pageX(e) - 1) + "px; z-index: 1000; background: white; " +
1182
1195
  "border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
1183
1196
  leaveInputAlone = true;
1184
1197
  var val = input.value = getSelection();
@@ -1195,7 +1208,7 @@ var CodeMirror = (function() {
1195
1208
  }
1196
1209
 
1197
1210
  if (gecko) {
1198
- e.stop();
1211
+ e_stop(e);
1199
1212
  var mouseup = connect(window, "mouseup", function() {
1200
1213
  mouseup();
1201
1214
  setTimeout(rehide, 20);
@@ -1286,7 +1299,7 @@ var CodeMirror = (function() {
1286
1299
  line.highlight(mode, state);
1287
1300
  line.stateAfter = copyState(mode, state);
1288
1301
  }
1289
- if (!lines[n].stateAfter) work.push(n);
1302
+ if (n < lines.length && !lines[n].stateAfter) work.push(n);
1290
1303
  return state;
1291
1304
  }
1292
1305
  function highlightLines(start, end) {
@@ -1314,7 +1327,7 @@ var CodeMirror = (function() {
1314
1327
  if (+new Date > end) {
1315
1328
  work.push(i);
1316
1329
  startWorker(options.workDelay);
1317
- changes.push({from: task, to: i});
1330
+ changes.push({from: task, to: i + 1});
1318
1331
  return;
1319
1332
  }
1320
1333
  var changed = line.highlight(mode, state);
@@ -1326,7 +1339,7 @@ var CodeMirror = (function() {
1326
1339
  else if (++unchanged > 3) break;
1327
1340
  }
1328
1341
  }
1329
- changes.push({from: task, to: i});
1342
+ changes.push({from: task, to: i + 1});
1330
1343
  }
1331
1344
  if (foundWork && options.onHighlightComplete)
1332
1345
  options.onHighlightComplete(instance);
@@ -1784,7 +1797,7 @@ var CodeMirror = (function() {
1784
1797
  html.push(this.className ? '<pre class="' + this.className + '">': "<pre>");
1785
1798
  function span(text, style) {
1786
1799
  if (!text) return;
1787
- if (style) html.push('<span class="cm-', style, '">', htmlEscape(text), "</span>");
1800
+ if (style) html.push('<span class="', style, '">', htmlEscape(text), "</span>");
1788
1801
  else html.push(htmlEscape(text));
1789
1802
  }
1790
1803
  var st = this.styles, allText = this.text, marked = this.marked;
@@ -1799,7 +1812,7 @@ var CodeMirror = (function() {
1799
1812
  var str = st[i], l = str.length;
1800
1813
  if (ch + l > len) str = str.slice(0, len - ch);
1801
1814
  ch += l;
1802
- span(str, st[i+1]);
1815
+ span(str, "cm-" + st[i+1]);
1803
1816
  }
1804
1817
  else {
1805
1818
  var pos = 0, i = 0, text = "", style, sg = 0;
@@ -1831,12 +1844,12 @@ var CodeMirror = (function() {
1831
1844
  }
1832
1845
  for (;;) {
1833
1846
  var end = pos + text.length;
1834
- var apliedStyle = style;
1835
- if (extraStyle) apliedStyle = style ? style + extraStyle : extraStyle;
1836
- span(end > upto ? text.slice(0, upto - pos) : text, apliedStyle);
1847
+ var appliedStyle = style;
1848
+ if (extraStyle) appliedStyle = style ? style + extraStyle : extraStyle;
1849
+ span(end > upto ? text.slice(0, upto - pos) : text, appliedStyle);
1837
1850
  if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
1838
1851
  pos = end;
1839
- text = st[i++]; style = st[i++];
1852
+ text = st[i++]; style = "cm-" + st[i++];
1840
1853
  }
1841
1854
  }
1842
1855
  if (sfrom != null && sto == null) span(" ", "CodeMirror-selected");
@@ -1894,44 +1907,44 @@ var CodeMirror = (function() {
1894
1907
  }
1895
1908
  };
1896
1909
 
1897
- // Event stopping compatibility wrapper.
1898
- function stopEvent() {
1899
- if (this.preventDefault) {this.preventDefault(); this.stopPropagation();}
1900
- else {this.returnValue = false; this.cancelBubble = true;}
1901
- }
1910
+ function stopMethod() {e_stop(this);}
1902
1911
  // Ensure an event has a stop method.
1903
1912
  function addStop(event) {
1904
- if (!event.stop) event.stop = stopEvent;
1913
+ if (!event.stop) event.stop = stopMethod;
1905
1914
  return event;
1906
1915
  }
1907
1916
 
1908
- // Event wrapper, exposing the few operations we need.
1909
- function Event(orig) {this.e = orig;}
1910
- Event.prototype = {
1911
- stop: function() {stopEvent.call(this.e);},
1912
- target: function() {return this.e.target || this.e.srcElement;},
1913
- button: function() {
1914
- if (this.e.which) return this.e.which;
1915
- else if (this.e.button & 1) return 1;
1916
- else if (this.e.button & 2) return 3;
1917
- else if (this.e.button & 4) return 2;
1918
- },
1919
- pageX: function() {
1920
- if (this.e.pageX != null) return this.e.pageX;
1921
- var doc = this.target().ownerDocument;
1922
- return this.e.clientX + doc.body.scrollLeft + doc.documentElement.scrollLeft;
1923
- },
1924
- pageY: function() {
1925
- if (this.e.pageY != null) return this.e.pageY;
1926
- var doc = this.target().ownerDocument;
1927
- return this.e.clientY + doc.body.scrollTop + doc.documentElement.scrollTop;
1928
- }
1929
- };
1917
+ function e_preventDefault(e) {
1918
+ if (e.preventDefault) e.preventDefault();
1919
+ else e.returnValue = false;
1920
+ }
1921
+ function e_stopPropagation(e) {
1922
+ if (e.stopPropagation) e.stopPropagation();
1923
+ else e.cancelBubble = true;
1924
+ }
1925
+ function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
1926
+ function e_target(e) {return e.target || e.srcElement;}
1927
+ function e_button(e) {
1928
+ if (e.which) return e.which;
1929
+ else if (e.button & 1) return 1;
1930
+ else if (e.button & 2) return 3;
1931
+ else if (e.button & 4) return 2;
1932
+ }
1933
+ function e_pageX(e) {
1934
+ if (e.pageX != null) return e.pageX;
1935
+ var doc = e_target(e).ownerDocument;
1936
+ return e.clientX + doc.body.scrollLeft + doc.documentElement.scrollLeft;
1937
+ }
1938
+ function e_pageY(e) {
1939
+ if (e.pageY != null) return e.pageY;
1940
+ var doc = e_target(e).ownerDocument;
1941
+ return e.clientY + doc.body.scrollTop + doc.documentElement.scrollTop;
1942
+ }
1930
1943
 
1931
1944
  // Event handler registration. If disconnect is true, it'll return a
1932
1945
  // function that unregisters the handler.
1933
1946
  function connect(node, type, handler, disconnect) {
1934
- function wrapHandler(event) {handler(new Event(event || window.event));}
1947
+ function wrapHandler(event) {handler(event || window.event);}
1935
1948
  if (typeof node.addEventListener == "function") {
1936
1949
  node.addEventListener(type, wrapHandler, false);
1937
1950
  if (disconnect) return function() {node.removeEventListener(type, wrapHandler, false);};
@@ -2013,10 +2026,10 @@ var CodeMirror = (function() {
2013
2026
  function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
2014
2027
  function copyPos(x) {return {line: x.line, ch: x.ch};}
2015
2028
 
2029
+ var escapeElement = document.createElement("div");
2016
2030
  function htmlEscape(str) {
2017
- return str.replace(/[<>&]/g, function(str) {
2018
- return str == "&" ? "&amp;" : str == "<" ? "&lt;" : "&gt;";
2019
- });
2031
+ escapeElement.innerText = escapeElement.textContent = str;
2032
+ return escapeElement.innerHTML;
2020
2033
  }
2021
2034
  CodeMirror.htmlEscape = htmlEscape;
2022
2035
 
@@ -2127,4 +2140,5 @@ var CodeMirror = (function() {
2127
2140
  CodeMirror.defineMIME("text/plain", "null");
2128
2141
 
2129
2142
  return CodeMirror;
2130
- })();
2143
+ })()
2144
+ ;
@@ -1,6 +1,7 @@
1
1
  CodeMirror.defineMode("clike", function(config, parserConfig) {
2
2
  var indentUnit = config.indentUnit,
3
3
  keywords = parserConfig.keywords || {},
4
+ blockKeywords = parserConfig.blockKeywords || {},
4
5
  atoms = parserConfig.atoms || {},
5
6
  hooks = parserConfig.hooks || {},
6
7
  multiLineStrings = parserConfig.multiLineStrings;
@@ -42,7 +43,10 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
42
43
  }
43
44
  stream.eatWhile(/[\w\$_]/);
44
45
  var cur = stream.current();
45
- if (keywords.propertyIsEnumerable(cur)) return "keyword";
46
+ if (keywords.propertyIsEnumerable(cur)) {
47
+ if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
48
+ return "keyword";
49
+ }
46
50
  if (atoms.propertyIsEnumerable(cur)) return "atom";
47
51
  return "word";
48
52
  }
@@ -79,11 +83,13 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
79
83
  this.align = align;
80
84
  this.prev = prev;
81
85
  }
82
-
83
86
  function pushContext(state, col, type) {
84
87
  return state.context = new Context(state.indented, col, type, null, state.context);
85
88
  }
86
89
  function popContext(state) {
90
+ var t = state.context.type;
91
+ if (t == ")" || t == "]" || t == "}")
92
+ state.indented = state.context.indented;
87
93
  return state.context = state.context.prev;
88
94
  }
89
95
 
@@ -109,7 +115,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
109
115
  if (stream.eatSpace()) return null;
110
116
  curPunc = null;
111
117
  var style = (state.tokenize || tokenBase)(stream, state);
112
- if (style == "comment") return style;
118
+ if (style == "comment" || style == "meta") return style;
113
119
  if (ctx.align == null) ctx.align = true;
114
120
 
115
121
  if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
@@ -117,12 +123,13 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
117
123
  else if (curPunc == "[") pushContext(state, stream.column(), "]");
118
124
  else if (curPunc == "(") pushContext(state, stream.column(), ")");
119
125
  else if (curPunc == "}") {
120
- if (ctx.type == "statement") ctx = popContext(state);
126
+ while (ctx.type == "statement") ctx = popContext(state);
121
127
  if (ctx.type == "}") ctx = popContext(state);
122
- if (ctx.type == "statement") ctx = popContext(state);
128
+ while (ctx.type == "statement") ctx = popContext(state);
123
129
  }
124
130
  else if (curPunc == ctx.type) popContext(state);
125
- else if (ctx.type == "}" || ctx.type == "top") pushContext(state, stream.column(), "statement");
131
+ else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
132
+ pushContext(state, stream.column(), "statement");
126
133
  state.startOfLine = false;
127
134
  return style;
128
135
  },
@@ -170,6 +177,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
170
177
  CodeMirror.defineMIME("text/x-csrc", {
171
178
  name: "clike",
172
179
  keywords: words(cKeywords),
180
+ blockKeywords: words("case do else for if switch while struct"),
173
181
  atoms: words("null"),
174
182
  hooks: {"#": cppHook}
175
183
  });
@@ -179,6 +187,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
179
187
  "static_cast typeid catch operator template typename class friend private " +
180
188
  "this using const_cast inline public throw virtual delete mutable protected " +
181
189
  "wchar_t"),
190
+ blockKeywords: words("catch class do else finally for if struct switch try while"),
182
191
  atoms: words("true false null"),
183
192
  hooks: {"#": cppHook}
184
193
  });
@@ -189,6 +198,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
189
198
  "instanceof int interface long native new package private protected public " +
190
199
  "return short static strictfp super switch synchronized this throw throws transient " +
191
200
  "try void volatile while"),
201
+ blockKeywords: words("catch class do else finally for if switch try while"),
192
202
  atoms: words("true false null"),
193
203
  hooks: {
194
204
  "@": function(stream, state) {
@@ -206,6 +216,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
206
216
  " sizeof stackalloc static string struct switch this throw try typeof uint ulong unchecked" +
207
217
  " unsafe ushort using virtual void volatile while add alias ascending descending dynamic from get" +
208
218
  " global group into join let orderby partial remove select set value var yield"),
219
+ blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
209
220
  atoms: words("true false null"),
210
221
  hooks: {
211
222
  "@": function(stream, state) {
@@ -218,4 +229,19 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
218
229
  }
219
230
  }
220
231
  });
232
+ CodeMirror.defineMIME("text/x-groovy", {
233
+ name: "clike",
234
+ keywords: words("abstract as assert boolean break byte case catch char class const continue def default " +
235
+ "do double else enum extends final finally float for goto if implements import " +
236
+ "in instanceof int interface long native new package property private protected public " +
237
+ "return short static strictfp super switch synchronized this throw throws transient " +
238
+ "try void volatile while"),
239
+ atoms: words("true false null"),
240
+ hooks: {
241
+ "@": function(stream, state) {
242
+ stream.eatWhile(/[\w\$_]/);
243
+ return "meta";
244
+ }
245
+ }
246
+ });
221
247
  }());
@@ -51,11 +51,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
51
51
  return ret(ch);
52
52
  else if (ch == "0" && stream.eat(/x/i)) {
53
53
  stream.eatWhile(/[\da-f]/i);
54
- return ret("number", "atom");
54
+ return ret("number", "number");
55
55
  }
56
56
  else if (/\d/.test(ch)) {
57
57
  stream.match(/^\d*(?:\.\d*)?(?:e[+\-]?\d+)?/);
58
- return ret("number", "atom");
58
+ return ret("number", "number");
59
59
  }
60
60
  else if (ch == "/") {
61
61
  if (stream.eat("*")) {
@@ -4,11 +4,6 @@
4
4
  for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
5
5
  return obj;
6
6
  }
7
- var phpKeywords =
8
- keywords("abstract and array as break case catch cfunction class clone const continue declare " +
9
- "default do else elseif enddeclare endfor endforeach endif endswitch endwhile extends " +
10
- "final for foreach function global goto if implements interface instanceof namespace " +
11
- "new or private protected public static switch throw try use var while xor return");
12
7
  function heredoc(delim) {
13
8
  return function(stream, state) {
14
9
  if (stream.match(delim)) state.tokenize = null;
@@ -18,7 +13,11 @@
18
13
  }
19
14
  var phpConfig = {
20
15
  name: "clike",
21
- keywords: phpKeywords,
16
+ keywords: keywords("abstract and array as break case catch cfunction class clone const continue declare " +
17
+ "default do else elseif enddeclare endfor endforeach endif endswitch endwhile extends " +
18
+ "final for foreach function global goto if implements interface instanceof namespace " +
19
+ "new or private protected public static switch throw try use var while xor return"),
20
+ blockKeywords: keywords("catch do else elseif for foreach if switch try while"),
22
21
  atoms: keywords("true false null"),
23
22
  multiLineStrings: true,
24
23
  hooks: {
@@ -0,0 +1,143 @@
1
+ CodeMirror.defineMode("sparql", function(config) {
2
+ var indentUnit = config.indentUnit;
3
+ var curPunc;
4
+
5
+ function wordRegexp(words) {
6
+ return new RegExp("^(?:" + words.join("|") + ")$", "i");
7
+ }
8
+ var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri",
9
+ "isblank", "isliteral", "union", "a"]);
10
+ var keywords = wordRegexp(["base", "prefix", "select", "distinct", "reduced", "construct", "describe",
11
+ "ask", "from", "named", "where", "order", "limit", "offset", "filter", "optional",
12
+ "graph", "by", "asc", "desc"]);
13
+ var operatorChars = /[*+\-<>=&|]/;
14
+
15
+ function tokenBase(stream, state) {
16
+ var ch = stream.next();
17
+ curPunc = null;
18
+ if (ch == "$" || ch == "?") {
19
+ stream.match(/^[\w\d]*/);
20
+ return "variable-2";
21
+ }
22
+ else if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) {
23
+ stream.match(/^[^\s\u00a0>]*>?/);
24
+ return "atom";
25
+ }
26
+ else if (ch == "\"" || ch == "'") {
27
+ state.tokenize = tokenLiteral(ch);
28
+ return state.tokenize(stream, state);
29
+ }
30
+ else if (/[{}\(\),\.;\[\]]/.test(ch)) {
31
+ curPunc = ch;
32
+ return null;
33
+ }
34
+ else if (ch == "#") {
35
+ stream.skipToEnd();
36
+ return "comment";
37
+ }
38
+ else if (operatorChars.test(ch)) {
39
+ stream.eatWhile(operatorChars);
40
+ return null;
41
+ }
42
+ else if (ch == ":") {
43
+ stream.eatWhile(/[\w\d\._\-]/);
44
+ return "atom";
45
+ }
46
+ else {
47
+ stream.eatWhile(/[_\w\d]/);
48
+ if (stream.eat(":")) {
49
+ stream.eatWhile(/[\w\d_\-]/);
50
+ return "atom";
51
+ }
52
+ var word = stream.current(), type;
53
+ if (ops.test(word))
54
+ return null;
55
+ else if (keywords.test(word))
56
+ return "keyword";
57
+ else
58
+ return "variable";
59
+ }
60
+ }
61
+
62
+ function tokenLiteral(quote) {
63
+ return function(stream, state) {
64
+ var escaped = false, ch;
65
+ while ((ch = stream.next()) != null) {
66
+ if (ch == quote && !escaped) {
67
+ state.tokenize = tokenBase;
68
+ break;
69
+ }
70
+ escaped = !escaped && ch == "\\";
71
+ }
72
+ return "string";
73
+ };
74
+ }
75
+
76
+ function pushContext(state, type, col) {
77
+ state.context = {prev: state.context, indent: state.indent, col: col, type: type};
78
+ }
79
+ function popContext(state) {
80
+ state.indent = state.context.indent;
81
+ state.context = state.context.prev;
82
+ }
83
+
84
+ return {
85
+ startState: function(base) {
86
+ return {tokenize: tokenBase,
87
+ context: null,
88
+ indent: 0,
89
+ col: 0};
90
+ },
91
+
92
+ token: function(stream, state) {
93
+ if (stream.sol()) {
94
+ if (state.context && state.context.align == null) state.context.align = false;
95
+ state.indent = stream.indentation();
96
+ }
97
+ if (stream.eatSpace()) return null;
98
+ var style = state.tokenize(stream, state);
99
+
100
+ if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") {
101
+ state.context.align = true;
102
+ }
103
+
104
+ if (curPunc == "(") pushContext(state, ")", stream.column());
105
+ else if (curPunc == "[") pushContext(state, "]", stream.column());
106
+ else if (curPunc == "{") pushContext(state, "}", stream.column());
107
+ else if (/[\]\}\)]/.test(curPunc)) {
108
+ while (state.context && state.context.type == "pattern") popContext(state);
109
+ if (state.context && curPunc == state.context.type) popContext(state);
110
+ }
111
+ else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state);
112
+ else if (/atom|string|variable/.test(style) && state.context) {
113
+ if (/[\}\]]/.test(state.context.type))
114
+ pushContext(state, "pattern", stream.column());
115
+ else if (state.context.type == "pattern" && !state.context.align) {
116
+ state.context.align = true;
117
+ state.context.col = stream.column();
118
+ }
119
+ }
120
+
121
+ return style;
122
+ },
123
+
124
+ indent: function(state, textAfter) {
125
+ var firstChar = textAfter && textAfter.charAt(0);
126
+ var context = state.context;
127
+ if (/[\]\}]/.test(firstChar))
128
+ while (context && context.type == "pattern") context = context.prev;
129
+
130
+ var closing = context && firstChar == context.type;
131
+ if (!context)
132
+ return 0;
133
+ else if (context.type == "pattern")
134
+ return context.col;
135
+ else if (context.align)
136
+ return context.col + (closing ? 0 : 1);
137
+ else
138
+ return context.indent + (closing ? 0 : indentUnit);
139
+ }
140
+ };
141
+ });
142
+
143
+ CodeMirror.defineMIME("application/x-sparql-query", "sparql");
@@ -25,7 +25,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
25
25
  else return null;
26
26
  }
27
27
  else if (stream.match("--")) return chain(inBlock("comment", "-->"));
28
- else if (stream.match("DOCTYPE")) {
28
+ else if (stream.match("DOCTYPE", true, true)) {
29
29
  stream.eatWhile(/[\w\._\-]/);
30
30
  return chain(inBlock("meta", ">"));
31
31
  }
@@ -170,9 +170,13 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
170
170
  }
171
171
  function attvalue(type) {
172
172
  if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();}
173
- if (type == "string") return cont();
173
+ if (type == "string") return cont(attvaluemaybe);
174
174
  return pass();
175
175
  }
176
+ function attvaluemaybe(type) {
177
+ if (type == "string") return cont(attvaluemaybe);
178
+ else return pass();
179
+ }
176
180
 
177
181
  return {
178
182
  startState: function() {
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: 0.2.0
4
+ version: 0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-07-06 00:00:00.000000000 -04:00
12
+ date: 2011-07-25 00:00:00.000000000 -04:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
  description: This gem provides CodeMirror assets for your Rails 3 application.
@@ -19,6 +19,7 @@ extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
21
  - ./codemirror-rails-0.1.2.gem
22
+ - ./codemirror-rails-0.2.0.gem
22
23
  - ./codemirror-rails.gemspec
23
24
  - ./doc/CodeMirror-LICENSE
24
25
  - ./lib/codemirror/rails/railtie.rb
@@ -41,6 +42,7 @@ files:
41
42
  - ./vendor/assets/javascripts/codemirror/modes/rst.js
42
43
  - ./vendor/assets/javascripts/codemirror/modes/scheme.js
43
44
  - ./vendor/assets/javascripts/codemirror/modes/smalltalk.js
45
+ - ./vendor/assets/javascripts/codemirror/modes/sparql.js
44
46
  - ./vendor/assets/javascripts/codemirror/modes/stex.js
45
47
  - ./vendor/assets/javascripts/codemirror/modes/xml.js
46
48
  - ./vendor/assets/javascripts/codemirror/modes/yaml.js