codemirror-rails 5.0 → 5.1

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