codemirror-rails 5.0 → 5.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +104 -64
  4. data/vendor/assets/javascripts/codemirror/addons/dialog/dialog.js +3 -1
  5. data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +144 -121
  6. data/vendor/assets/javascripts/codemirror/addons/fold/foldgutter.js +4 -2
  7. data/vendor/assets/javascripts/codemirror/addons/hint/css-hint.js +4 -0
  8. data/vendor/assets/javascripts/codemirror/addons/hint/sql-hint.js +13 -8
  9. data/vendor/assets/javascripts/codemirror/addons/lint/lint.js +2 -0
  10. data/vendor/assets/javascripts/codemirror/addons/merge/merge.js +40 -0
  11. data/vendor/assets/javascripts/codemirror/addons/mode/multiplex_test.js +33 -0
  12. data/vendor/assets/javascripts/codemirror/addons/scroll/simplescrollbars.js +8 -2
  13. data/vendor/assets/javascripts/codemirror/addons/tern/tern.js +1 -1
  14. data/vendor/assets/javascripts/codemirror/keymaps/sublime.js +13 -0
  15. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +43 -54
  16. data/vendor/assets/javascripts/codemirror/modes/asciiarmor.js +73 -0
  17. data/vendor/assets/javascripts/codemirror/modes/clike.js +2 -1
  18. data/vendor/assets/javascripts/codemirror/modes/clojure.js +1 -0
  19. data/vendor/assets/javascripts/codemirror/modes/cmake.js +97 -0
  20. data/vendor/assets/javascripts/codemirror/modes/commonlisp.js +1 -0
  21. data/vendor/assets/javascripts/codemirror/modes/css.js +1 -0
  22. data/vendor/assets/javascripts/codemirror/modes/groovy.js +1 -0
  23. data/vendor/assets/javascripts/codemirror/modes/htmlembedded.js +18 -76
  24. data/vendor/assets/javascripts/codemirror/modes/javascript.js +5 -0
  25. data/vendor/assets/javascripts/codemirror/modes/kotlin.js +1 -0
  26. data/vendor/assets/javascripts/codemirror/modes/less_test.js +51 -0
  27. data/vendor/assets/javascripts/codemirror/modes/mllike.js +1 -1
  28. data/vendor/assets/javascripts/codemirror/modes/properties.js +1 -1
  29. data/vendor/assets/javascripts/codemirror/modes/python.js +1 -0
  30. data/vendor/assets/javascripts/codemirror/modes/sass.js +1 -1
  31. data/vendor/assets/javascripts/codemirror/modes/scheme.js +1 -0
  32. data/vendor/assets/javascripts/codemirror/modes/scss_test.js +110 -0
  33. data/vendor/assets/javascripts/codemirror/modes/smarty.js +100 -107
  34. data/vendor/assets/javascripts/codemirror/modes/stylus.js +651 -332
  35. data/vendor/assets/javascripts/codemirror/modes/test.js +67 -0
  36. data/vendor/assets/javascripts/codemirror/modes/troff.js +82 -0
  37. data/vendor/assets/javascripts/codemirror/modes/vb.js +6 -5
  38. data/vendor/assets/javascripts/codemirror/modes/verilog.js +53 -53
  39. data/vendor/assets/stylesheets/codemirror.css +11 -8
  40. data/vendor/assets/stylesheets/codemirror/themes/mdn-like.css +1 -1
  41. metadata +9 -3
  42. data/vendor/assets/javascripts/codemirror/modes/smartymixed.js +0 -197
@@ -52,7 +52,7 @@
52
52
  function isFolded(cm, line) {
53
53
  var marks = cm.findMarksAt(Pos(line));
54
54
  for (var i = 0; i < marks.length; ++i)
55
- if (marks[i].__isFold && marks[i].find().from.line == line) return true;
55
+ if (marks[i].__isFold && marks[i].find().from.line == line) return marks[i];
56
56
  }
57
57
 
58
58
  function marker(spec) {
@@ -98,7 +98,9 @@
98
98
  if (!state) return;
99
99
  var opts = state.options;
100
100
  if (gutter != opts.gutter) return;
101
- cm.foldCode(Pos(line, 0), opts.rangeFinder);
101
+ var folded = isFolded(cm, line);
102
+ if (folded) folded.clear();
103
+ else cm.foldCode(Pos(line, 0), opts.rangeFinder);
102
104
  }
103
105
 
104
106
  function onChange(cm) {
@@ -20,6 +20,10 @@
20
20
  var inner = CodeMirror.innerMode(cm.getMode(), token.state);
21
21
  if (inner.mode.name != "css") return;
22
22
 
23
+ if (token.type == "keyword" && "!important".indexOf(token.string) == 0)
24
+ return {list: ["!important"], from: CodeMirror.Pos(cur.line, token.start),
25
+ to: CodeMirror.Pos(cur.line, token.end)};
26
+
23
27
  var start = token.start, end = cur.ch, word = token.string.slice(0, end - start);
24
28
  if (/[^\w$_-]/.test(word)) {
25
29
  word = ""; start = end = cur.ch;
@@ -52,12 +52,9 @@
52
52
  function addMatches(result, search, wordlist, formatter) {
53
53
  for (var word in wordlist) {
54
54
  if (!wordlist.hasOwnProperty(word)) continue;
55
- if (Array.isArray(wordlist)) {
56
- word = wordlist[word];
57
- }
58
- if (match(search, word)) {
59
- result.push(formatter(word));
60
- }
55
+ if (wordlist.slice) word = wordlist[word];
56
+
57
+ if (match(search, word)) result.push(formatter(word));
61
58
  }
62
59
  }
63
60
 
@@ -120,7 +117,7 @@
120
117
  table = findTableByAlias(table, editor);
121
118
 
122
119
  var columns = getItem(tables, table);
123
- if (columns && Array.isArray(tables) && columns.columns)
120
+ if (columns && columns.columns)
124
121
  columns = columns.columns;
125
122
 
126
123
  if (columns) {
@@ -208,9 +205,17 @@
208
205
  CodeMirror.registerHelper("hint", "sql", function(editor, options) {
209
206
  tables = (options && options.tables) || {};
210
207
  var defaultTableName = options && options.defaultTable;
211
- defaultTable = (defaultTableName && getItem(tables, defaultTableName)) || [];
208
+ defaultTable = defaultTableName && getItem(tables, defaultTableName);
212
209
  keywords = keywords || getKeywords(editor);
213
210
 
211
+ if (defaultTableName && !defaultTable)
212
+ defaultTable = findTableByAlias(defaultTableName, editor);
213
+
214
+ defaultTable = defaultTable || [];
215
+
216
+ if (defaultTable.columns)
217
+ defaultTable = defaultTable.columns;
218
+
214
219
  var cur = editor.getCursor();
215
220
  var result = [];
216
221
  var token = editor.getTokenAt(cur), start, end, search;
@@ -163,6 +163,7 @@
163
163
 
164
164
  function onChange(cm) {
165
165
  var state = cm.state.lint;
166
+ if (!state) return;
166
167
  clearTimeout(state.timeout);
167
168
  state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500);
168
169
  }
@@ -188,6 +189,7 @@
188
189
  clearMarks(cm);
189
190
  cm.off("change", onChange);
190
191
  CodeMirror.off(cm.getWrapperElement(), "mouseover", cm.state.lint.onMouseOver);
192
+ clearTimeout(cm.state.lint.timeout);
191
193
  delete cm.state.lint;
192
194
  }
193
195
 
@@ -37,7 +37,9 @@
37
37
  constructor: DiffView,
38
38
  init: function(pane, orig, options) {
39
39
  this.edit = this.mv.edit;
40
+ (this.edit.state.diffViews || (this.edit.state.diffViews = [])).push(this);
40
41
  this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options)));
42
+ this.orig.state.diffViews = [this];
41
43
 
42
44
  this.diff = getDiff(asString(orig), asString(options.value));
43
45
  this.chunks = getChunks(this.diff);
@@ -732,4 +734,42 @@
732
734
  function posMin(a, b) { return (a.line - b.line || a.ch - b.ch) < 0 ? a : b; }
733
735
  function posMax(a, b) { return (a.line - b.line || a.ch - b.ch) > 0 ? a : b; }
734
736
  function posEq(a, b) { return a.line == b.line && a.ch == b.ch; }
737
+
738
+ function findPrevDiff(chunks, start, isOrig) {
739
+ for (var i = chunks.length - 1; i >= 0; i--) {
740
+ var chunk = chunks[i];
741
+ var to = (isOrig ? chunk.origTo : chunk.editTo) - 1;
742
+ if (to < start) return to;
743
+ }
744
+ }
745
+
746
+ function findNextDiff(chunks, start, isOrig) {
747
+ for (var i = 0; i < chunks.length; i++) {
748
+ var chunk = chunks[i];
749
+ var from = (isOrig ? chunk.origFrom : chunk.editFrom);
750
+ if (from > start) return from;
751
+ }
752
+ }
753
+
754
+ function goNearbyDiff(cm, dir) {
755
+ var found = null, views = cm.state.diffViews, line = cm.getCursor().line;
756
+ if (views) for (var i = 0; i < views.length; i++) {
757
+ var dv = views[i], isOrig = cm == dv.orig;
758
+ ensureDiff(dv);
759
+ var pos = dir < 0 ? findPrevDiff(dv.chunks, line, isOrig) : findNextDiff(dv.chunks, line, isOrig);
760
+ if (pos != null && (found == null || (dir < 0 ? pos > found : pos < found)))
761
+ found = pos;
762
+ }
763
+ if (found != null)
764
+ cm.setCursor(found, 0);
765
+ else
766
+ return CodeMirror.Pass;
767
+ }
768
+
769
+ CodeMirror.commands.goNextDiff = function(cm) {
770
+ return goNearbyDiff(cm, 1);
771
+ };
772
+ CodeMirror.commands.goPrevDiff = function(cm) {
773
+ return goNearbyDiff(cm, -1);
774
+ };
735
775
  });
@@ -0,0 +1,33 @@
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function() {
5
+ CodeMirror.defineMode("markdown_with_stex", function(){
6
+ var inner = CodeMirror.getMode({}, "stex");
7
+ var outer = CodeMirror.getMode({}, "markdown");
8
+
9
+ var innerOptions = {
10
+ open: '$',
11
+ close: '$',
12
+ mode: inner,
13
+ delimStyle: 'delim',
14
+ innerStyle: 'inner'
15
+ };
16
+
17
+ return CodeMirror.multiplexingMode(outer, innerOptions);
18
+ });
19
+
20
+ var mode = CodeMirror.getMode({}, "markdown_with_stex");
21
+
22
+ function MT(name) {
23
+ test.mode(
24
+ name,
25
+ mode,
26
+ Array.prototype.slice.call(arguments, 1),
27
+ 'multiplexing');
28
+ }
29
+
30
+ MT(
31
+ "stexInsideMarkdown",
32
+ "[strong **Equation:**] [delim $][inner&tag \\pi][delim $]");
33
+ })();
@@ -69,14 +69,20 @@
69
69
  if (update !== false) this.scroll(pos, this.orientation);
70
70
  };
71
71
 
72
+ var minButtonSize = 10;
73
+
72
74
  Bar.prototype.update = function(scrollSize, clientSize, barSize) {
73
75
  this.screen = clientSize;
74
76
  this.total = scrollSize;
75
77
  this.size = barSize;
76
78
 
77
- // FIXME clip to min size?
79
+ var buttonSize = this.screen * (this.size / this.total);
80
+ if (buttonSize < minButtonSize) {
81
+ this.size -= minButtonSize - buttonSize;
82
+ buttonSize = minButtonSize;
83
+ }
78
84
  this.inner.style[this.orientation == "horizontal" ? "width" : "height"] =
79
- this.screen * (this.size / this.total) + "px";
85
+ buttonSize + "px";
80
86
  this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
81
87
  this.pos * (this.size / this.total) + "px";
82
88
  };
@@ -443,7 +443,7 @@
443
443
  function atInterestingExpression(cm) {
444
444
  var pos = cm.getCursor("end"), tok = cm.getTokenAt(pos);
445
445
  if (tok.start < pos.ch && (tok.type == "comment" || tok.type == "string")) return false;
446
- return /\w/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1));
446
+ return /[\w)\]]/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1));
447
447
  }
448
448
 
449
449
  // Variable renaming
@@ -409,6 +409,19 @@
409
409
 
410
410
  map[cK + ctrl + "Backspace"] = "delLineLeft";
411
411
 
412
+ cmds[map["Backspace"] = "smartBackspace"] = function(cm) {
413
+ if (cm.somethingSelected()) return CodeMirror.Pass;
414
+
415
+ var cursor = cm.getCursor();
416
+ var toStartOfLine = cm.getRange({line: cursor.line, ch: 0}, cursor);
417
+ var column = CodeMirror.countColumn(toStartOfLine, null, cm.getOption("tabSize"));
418
+
419
+ if (!/\S/.test(toStartOfLine) && column % cm.getOption("indentUnit") == 0)
420
+ return cm.indentSelection("subtract");
421
+ else
422
+ return CodeMirror.Pass;
423
+ };
424
+
412
425
  cmds[map[cK + ctrl + "K"] = "delLineRight"] = function(cm) {
413
426
  cm.operation(function() {
414
427
  var ranges = cm.listSelections();
@@ -336,7 +336,11 @@
336
336
  }
337
337
 
338
338
  var numberRegex = /[\d]/;
339
- var wordRegexp = [(/\w/), (/[^\w\s]/)], bigWordRegexp = [(/\S/)];
339
+ var wordCharTest = [CodeMirror.isWordChar, function(ch) {
340
+ return ch && !CodeMirror.isWordChar(ch) && !/\s/.test(ch);
341
+ }], bigWordCharTest = [function(ch) {
342
+ return /\S/.test(ch);
343
+ }];
340
344
  function makeKeyRange(start, size) {
341
345
  var keys = [];
342
346
  for (var i = start; i < start + size; i++) {
@@ -1035,12 +1039,10 @@
1035
1039
  break;
1036
1040
  case 'search':
1037
1041
  this.processSearch(cm, vim, command);
1038
- clearInputState(cm);
1039
1042
  break;
1040
1043
  case 'ex':
1041
1044
  case 'keyToEx':
1042
1045
  this.processEx(cm, vim, command);
1043
- clearInputState(cm);
1044
1046
  break;
1045
1047
  default:
1046
1048
  break;
@@ -1133,6 +1135,7 @@
1133
1135
  updateSearchQuery(cm, query, ignoreCase, smartCase);
1134
1136
  } catch (e) {
1135
1137
  showConfirm(cm, 'Invalid regex: ' + query);
1138
+ clearInputState(cm);
1136
1139
  return;
1137
1140
  }
1138
1141
  commandDispatcher.processMotion(cm, vim, {
@@ -1182,6 +1185,7 @@
1182
1185
  clearSearchHighlight(cm);
1183
1186
  cm.scrollTo(originalScrollPos.left, originalScrollPos.top);
1184
1187
  CodeMirror.e_stop(e);
1188
+ clearInputState(cm);
1185
1189
  close();
1186
1190
  cm.focus();
1187
1191
  }
@@ -1248,6 +1252,7 @@
1248
1252
  vimGlobalState.exCommandHistoryController.pushInput(input);
1249
1253
  vimGlobalState.exCommandHistoryController.reset();
1250
1254
  CodeMirror.e_stop(e);
1255
+ clearInputState(cm);
1251
1256
  close();
1252
1257
  cm.focus();
1253
1258
  }
@@ -2628,9 +2633,6 @@
2628
2633
  function lineLength(cm, lineNum) {
2629
2634
  return cm.getLine(lineNum).length;
2630
2635
  }
2631
- function reverse(s){
2632
- return s.split('').reverse().join('');
2633
- }
2634
2636
  function trim(s) {
2635
2637
  if (s.trim) {
2636
2638
  return s.trim();
@@ -2944,59 +2946,38 @@
2944
2946
 
2945
2947
  // Seek to first word or non-whitespace character, depending on if
2946
2948
  // noSymbol is true.
2947
- var textAfterIdx = line.substring(idx);
2948
- var firstMatchedChar;
2949
- if (noSymbol) {
2950
- firstMatchedChar = textAfterIdx.search(/\w/);
2951
- } else {
2952
- firstMatchedChar = textAfterIdx.search(/\S/);
2949
+ var test = noSymbol ? wordCharTest[0] : bigWordCharTest [0];
2950
+ while (!test(line.charAt(idx))) {
2951
+ idx++;
2952
+ if (idx >= line.length) { return null; }
2953
2953
  }
2954
- if (firstMatchedChar == -1) {
2955
- return null;
2956
- }
2957
- idx += firstMatchedChar;
2958
- textAfterIdx = line.substring(idx);
2959
- var textBeforeIdx = line.substring(0, idx);
2960
2954
 
2961
- var matchRegex;
2962
- // Greedy matchers for the "word" we are trying to expand.
2963
2955
  if (bigWord) {
2964
- matchRegex = /^\S+/;
2956
+ test = bigWordCharTest[0];
2965
2957
  } else {
2966
- if ((/\w/).test(line.charAt(idx))) {
2967
- matchRegex = /^\w+/;
2968
- } else {
2969
- matchRegex = /^[^\w\s]+/;
2958
+ test = wordCharTest[0];
2959
+ if (!test(line.charAt(idx))) {
2960
+ test = wordCharTest[1];
2970
2961
  }
2971
2962
  }
2972
2963
 
2973
- var wordAfterRegex = matchRegex.exec(textAfterIdx);
2974
- var wordStart = idx;
2975
- var wordEnd = idx + wordAfterRegex[0].length;
2976
- // TODO: Find a better way to do this. It will be slow on very long lines.
2977
- var revTextBeforeIdx = reverse(textBeforeIdx);
2978
- var wordBeforeRegex = matchRegex.exec(revTextBeforeIdx);
2979
- if (wordBeforeRegex) {
2980
- wordStart -= wordBeforeRegex[0].length;
2981
- }
2964
+ var end = idx, start = idx;
2965
+ while (test(line.charAt(end)) && end < line.length) { end++; }
2966
+ while (test(line.charAt(start)) && start >= 0) { start--; }
2967
+ start++;
2982
2968
 
2983
2969
  if (inclusive) {
2984
- // If present, trim all whitespace after word.
2985
- // Otherwise, trim all whitespace before word.
2986
- var textAfterWordEnd = line.substring(wordEnd);
2987
- var whitespacesAfterWord = textAfterWordEnd.match(/^\s*/)[0].length;
2988
- if (whitespacesAfterWord > 0) {
2989
- wordEnd += whitespacesAfterWord;
2990
- } else {
2991
- var revTrim = revTextBeforeIdx.length - wordStart;
2992
- var textBeforeWordStart = revTextBeforeIdx.substring(revTrim);
2993
- var whitespacesBeforeWord = textBeforeWordStart.match(/^\s*/)[0].length;
2994
- wordStart -= whitespacesBeforeWord;
2970
+ // If present, include all whitespace after word.
2971
+ // Otherwise, include all whitespace before word, except indentation.
2972
+ var wordEnd = end;
2973
+ while (/\s/.test(line.charAt(end)) && end < line.length) { end++; }
2974
+ if (wordEnd == end) {
2975
+ var wordStart = start;
2976
+ while (/\s/.test(line.charAt(start - 1)) && start > 0) { start--; }
2977
+ if (!start) { start = wordStart; }
2995
2978
  }
2996
2979
  }
2997
-
2998
- return { start: Pos(cur.line, wordStart),
2999
- end: Pos(cur.line, wordEnd) };
2980
+ return { start: Pos(cur.line, start), end: Pos(cur.line, end) };
3000
2981
  }
3001
2982
 
3002
2983
  function recordJumpPosition(cm, oldCur, newCur) {
@@ -3154,7 +3135,7 @@
3154
3135
  var pos = cur.ch;
3155
3136
  var line = cm.getLine(lineNum);
3156
3137
  var dir = forward ? 1 : -1;
3157
- var regexps = bigWord ? bigWordRegexp : wordRegexp;
3138
+ var charTests = bigWord ? bigWordCharTest: wordCharTest;
3158
3139
 
3159
3140
  if (emptyLineIsWord && line == '') {
3160
3141
  lineNum += dir;
@@ -3174,11 +3155,11 @@
3174
3155
  // Find bounds of next word.
3175
3156
  while (pos != stop) {
3176
3157
  var foundWord = false;
3177
- for (var i = 0; i < regexps.length && !foundWord; ++i) {
3178
- if (regexps[i].test(line.charAt(pos))) {
3158
+ for (var i = 0; i < charTests.length && !foundWord; ++i) {
3159
+ if (charTests[i](line.charAt(pos))) {
3179
3160
  wordStart = pos;
3180
3161
  // Advance to end of word.
3181
- while (pos != stop && regexps[i].test(line.charAt(pos))) {
3162
+ while (pos != stop && charTests[i](line.charAt(pos))) {
3182
3163
  pos += dir;
3183
3164
  }
3184
3165
  wordEnd = pos;
@@ -3510,7 +3491,8 @@
3510
3491
  function dialog(cm, template, shortText, onClose, options) {
3511
3492
  if (cm.openDialog) {
3512
3493
  cm.openDialog(template, onClose, { bottom: true, value: options.value,
3513
- onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp });
3494
+ onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp,
3495
+ selectValueOnOpen: false});
3514
3496
  }
3515
3497
  else {
3516
3498
  onClose(prompt(shortText, ''));
@@ -3888,6 +3870,13 @@
3888
3870
  };
3889
3871
  ExCommandDispatcher.prototype = {
3890
3872
  processCommand: function(cm, input, opt_params) {
3873
+ var that = this;
3874
+ cm.operation(function () {
3875
+ cm.curOp.isVimOp = true;
3876
+ that._processCommand(cm, input, opt_params);
3877
+ });
3878
+ },
3879
+ _processCommand: function(cm, input, opt_params) {
3891
3880
  var vim = cm.state.vim;
3892
3881
  var commandHistoryRegister = vimGlobalState.registerController.getRegister(':');
3893
3882
  var previousCommand = commandHistoryRegister.toString();
@@ -4806,7 +4795,7 @@
4806
4795
  var anchor = cm.getCursor('anchor');
4807
4796
  var head = cm.getCursor('head');
4808
4797
  // Enter or exit visual mode to match mouse selection.
4809
- if (vim.visualMode && cursorEqual(head, anchor) && lineLength(cm, head.line) > head.ch) {
4798
+ if (vim.visualMode && !cm.somethingSelected()) {
4810
4799
  exitVisualMode(cm, false);
4811
4800
  } else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) {
4812
4801
  vim.visualMode = true;
@@ -0,0 +1,73 @@
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ function errorIfNotEmpty(stream) {
15
+ var nonWS = stream.match(/^\s*\S/);
16
+ stream.skipToEnd();
17
+ return nonWS ? "error" : null;
18
+ }
19
+
20
+ CodeMirror.defineMode("asciiarmor", function() {
21
+ return {
22
+ token: function(stream, state) {
23
+ var m;
24
+ if (state.state == "top") {
25
+ if (stream.sol() && (m = stream.match(/^-----BEGIN (.*)?-----\s*$/))) {
26
+ state.state = "headers";
27
+ state.type = m[1];
28
+ return "tag";
29
+ }
30
+ return errorIfNotEmpty(stream);
31
+ } else if (state.state == "headers") {
32
+ if (stream.sol() && stream.match(/^\w+:/)) {
33
+ state.state = "header";
34
+ return "atom";
35
+ } else {
36
+ var result = errorIfNotEmpty(stream);
37
+ if (result) state.state = "body";
38
+ return result;
39
+ }
40
+ } else if (state.state == "header") {
41
+ stream.skipToEnd();
42
+ state.state = "headers";
43
+ return "string";
44
+ } else if (state.state == "body") {
45
+ if (stream.sol() && (m = stream.match(/^-----END (.*)?-----\s*$/))) {
46
+ if (m[1] != state.type) return "error";
47
+ state.state = "end";
48
+ return "tag";
49
+ } else {
50
+ if (stream.eatWhile(/[A-Za-z0-9+\/=]/)) {
51
+ return null;
52
+ } else {
53
+ stream.next();
54
+ return "error";
55
+ }
56
+ }
57
+ } else if (state.state == "end") {
58
+ return errorIfNotEmpty(stream);
59
+ }
60
+ },
61
+ blankLine: function(state) {
62
+ if (state.state == "headers") state.state = "body";
63
+ },
64
+ startState: function() {
65
+ return {state: "top", type: null};
66
+ }
67
+ };
68
+ });
69
+
70
+ CodeMirror.defineMIME("application/pgp", "asciiarmor");
71
+ CodeMirror.defineMIME("application/pgp-keys", "asciiarmor");
72
+ CodeMirror.defineMIME("application/pgp-signature", "asciiarmor");
73
+ });