codemirror-rails 0.2.0 → 0.2.1

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