codemirror-rails 2.3 → 2.21

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 (71) hide show
  1. data/README.md +0 -16
  2. data/codemirror-rails.gemspec +1 -1
  3. data/lib/codemirror/rails/version.rb +2 -2
  4. data/vendor/assets/javascripts/codemirror.js +323 -687
  5. data/vendor/assets/javascripts/codemirror/modes/clike.js +3 -40
  6. data/vendor/assets/javascripts/codemirror/modes/clojure.js +14 -14
  7. data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +0 -6
  8. data/vendor/assets/javascripts/codemirror/modes/css.js +1 -1
  9. data/vendor/assets/javascripts/codemirror/modes/diff.js +5 -24
  10. data/vendor/assets/javascripts/codemirror/modes/gfm.js +4 -40
  11. data/vendor/assets/javascripts/codemirror/modes/go.js +22 -20
  12. data/vendor/assets/javascripts/codemirror/modes/htmlembedded.js +1 -1
  13. data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +2 -4
  14. data/vendor/assets/javascripts/codemirror/modes/javascript.js +7 -8
  15. data/vendor/assets/javascripts/codemirror/modes/less.js +54 -100
  16. data/vendor/assets/javascripts/codemirror/modes/markdown.js +49 -52
  17. data/vendor/assets/javascripts/codemirror/modes/pascal.js +46 -2
  18. data/vendor/assets/javascripts/codemirror/modes/perl.js +1 -1
  19. data/vendor/assets/javascripts/codemirror/modes/php.js +25 -54
  20. data/vendor/assets/javascripts/codemirror/modes/python.js +16 -14
  21. data/vendor/assets/javascripts/codemirror/modes/rpm-spec.js +1 -1
  22. data/vendor/assets/javascripts/codemirror/modes/rst.js +1 -1
  23. data/vendor/assets/javascripts/codemirror/modes/ruby.js +9 -4
  24. data/vendor/assets/javascripts/codemirror/modes/scheme.js +46 -74
  25. data/vendor/assets/javascripts/codemirror/modes/smalltalk.js +16 -16
  26. data/vendor/assets/javascripts/codemirror/modes/stex.js +6 -21
  27. data/vendor/assets/javascripts/codemirror/modes/tiddlywiki.js +45 -55
  28. data/vendor/assets/javascripts/codemirror/modes/xml.js +14 -79
  29. data/vendor/assets/javascripts/codemirror/{utils/overlay.js → overlay.js} +2 -3
  30. data/vendor/assets/javascripts/codemirror/runmode.js +27 -0
  31. data/vendor/assets/stylesheets/codemirror.css +2 -63
  32. data/vendor/assets/stylesheets/codemirror/modes/tiddlywiki.css +21 -14
  33. data/vendor/assets/stylesheets/codemirror/themes/eclipse.css +1 -1
  34. data/vendor/assets/stylesheets/codemirror/themes/elegant.css +2 -2
  35. data/vendor/assets/stylesheets/codemirror/themes/neat.css +3 -3
  36. data/vendor/assets/stylesheets/codemirror/themes/night.css +1 -1
  37. data/vendor/assets/stylesheets/codemirror/themes/rubyblue.css +2 -2
  38. metadata +6 -39
  39. data/vendor/assets/javascripts/codemirror/keymaps/emacs.js +0 -29
  40. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +0 -766
  41. data/vendor/assets/javascripts/codemirror/modes/ecl.js +0 -203
  42. data/vendor/assets/javascripts/codemirror/modes/erlang.js +0 -251
  43. data/vendor/assets/javascripts/codemirror/modes/pig.js +0 -172
  44. data/vendor/assets/javascripts/codemirror/modes/properties.js +0 -63
  45. data/vendor/assets/javascripts/codemirror/modes/shell.js +0 -103
  46. data/vendor/assets/javascripts/codemirror/modes/smarty.js +0 -148
  47. data/vendor/assets/javascripts/codemirror/modes/tiki.js +0 -316
  48. data/vendor/assets/javascripts/codemirror/modes/vbscript.js +0 -26
  49. data/vendor/assets/javascripts/codemirror/modes/xquery.js +0 -448
  50. data/vendor/assets/javascripts/codemirror/utils/closetag.js +0 -146
  51. data/vendor/assets/javascripts/codemirror/utils/dialog.js +0 -63
  52. data/vendor/assets/javascripts/codemirror/utils/foldcode.js +0 -196
  53. data/vendor/assets/javascripts/codemirror/utils/formatting.js +0 -297
  54. data/vendor/assets/javascripts/codemirror/utils/javascript-hint.js +0 -134
  55. data/vendor/assets/javascripts/codemirror/utils/loadmode.js +0 -51
  56. data/vendor/assets/javascripts/codemirror/utils/match-highlighter.js +0 -44
  57. data/vendor/assets/javascripts/codemirror/utils/multiplex.js +0 -72
  58. data/vendor/assets/javascripts/codemirror/utils/pig-hint.js +0 -123
  59. data/vendor/assets/javascripts/codemirror/utils/runmode.js +0 -49
  60. data/vendor/assets/javascripts/codemirror/utils/search.js +0 -118
  61. data/vendor/assets/javascripts/codemirror/utils/searchcursor.js +0 -117
  62. data/vendor/assets/javascripts/codemirror/utils/simple-hint.js +0 -72
  63. data/vendor/assets/stylesheets/codemirror/modes/tiki.css +0 -26
  64. data/vendor/assets/stylesheets/codemirror/themes/ambiance.css +0 -81
  65. data/vendor/assets/stylesheets/codemirror/themes/blackboard.css +0 -25
  66. data/vendor/assets/stylesheets/codemirror/themes/erlang-dark.css +0 -21
  67. data/vendor/assets/stylesheets/codemirror/themes/lesser-dark.css +0 -44
  68. data/vendor/assets/stylesheets/codemirror/themes/vibrant-ink.css +0 -27
  69. data/vendor/assets/stylesheets/codemirror/themes/xq-dark.css +0 -46
  70. data/vendor/assets/stylesheets/codemirror/utils/dialog.css +0 -23
  71. data/vendor/assets/stylesheets/codemirror/utils/simple-hint.css +0 -16
@@ -1,146 +0,0 @@
1
- /**
2
- * Tag-closer extension for CodeMirror.
3
- *
4
- * This extension adds a "closeTag" utility function that can be used with key bindings to
5
- * insert a matching end tag after the ">" character of a start tag has been typed. It can
6
- * also complete "</" if a matching start tag is found. It will correctly ignore signal
7
- * characters for empty tags, comments, CDATA, etc.
8
- *
9
- * The function depends on internal parser state to identify tags. It is compatible with the
10
- * following CodeMirror modes and will ignore all others:
11
- * - htmlmixed
12
- * - xml
13
- *
14
- * See demos/closetag.html for a usage example.
15
- *
16
- * @author Nathan Williams <nathan@nlwillia.net>
17
- * Contributed under the same license terms as CodeMirror.
18
- */
19
- (function() {
20
- /** Option that allows tag closing behavior to be toggled. Default is true. */
21
- CodeMirror.defaults['closeTagEnabled'] = true;
22
-
23
- /** Array of tag names to add indentation after the start tag for. Default is the list of block-level html tags. */
24
- CodeMirror.defaults['closeTagIndent'] = ['applet', 'blockquote', 'body', 'button', 'div', 'dl', 'fieldset', 'form', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'html', 'iframe', 'layer', 'legend', 'object', 'ol', 'p', 'select', 'table', 'ul'];
25
-
26
- /**
27
- * Call during key processing to close tags. Handles the key event if the tag is closed, otherwise throws CodeMirror.Pass.
28
- * - cm: The editor instance.
29
- * - ch: The character being processed.
30
- * - indent: Optional. Omit or pass true to use the default indentation tag list defined in the 'closeTagIndent' option.
31
- * Pass false to disable indentation. Pass an array to override the default list of tag names.
32
- */
33
- CodeMirror.defineExtension("closeTag", function(cm, ch, indent) {
34
- if (!cm.getOption('closeTagEnabled')) {
35
- throw CodeMirror.Pass;
36
- }
37
-
38
- var mode = cm.getOption('mode');
39
-
40
- if (mode == 'text/html') {
41
-
42
- /*
43
- * Relevant structure of token:
44
- *
45
- * htmlmixed
46
- * className
47
- * state
48
- * htmlState
49
- * type
50
- * context
51
- * tagName
52
- * mode
53
- *
54
- * xml
55
- * className
56
- * state
57
- * tagName
58
- * type
59
- */
60
-
61
- var pos = cm.getCursor();
62
- var tok = cm.getTokenAt(pos);
63
- var state = tok.state;
64
-
65
- if (state.mode && state.mode != 'html') {
66
- throw CodeMirror.Pass; // With htmlmixed, we only care about the html sub-mode.
67
- }
68
-
69
- if (ch == '>') {
70
- var type = state.htmlState ? state.htmlState.type : state.type; // htmlmixed : xml
71
-
72
- if (tok.className == 'tag' && type == 'closeTag') {
73
- throw CodeMirror.Pass; // Don't process the '>' at the end of an end-tag.
74
- }
75
-
76
- cm.replaceSelection('>'); // Mode state won't update until we finish the tag.
77
- pos = {line: pos.line, ch: pos.ch + 1};
78
- cm.setCursor(pos);
79
-
80
- tok = cm.getTokenAt(cm.getCursor());
81
- state = tok.state;
82
- type = state.htmlState ? state.htmlState.type : state.type; // htmlmixed : xml
83
-
84
- if (tok.className == 'tag' && type != 'selfcloseTag') {
85
- var tagName = state.htmlState ? state.htmlState.context.tagName : state.tagName; // htmlmixed : xml
86
- if (tagName.length > 0) {
87
- insertEndTag(cm, indent, pos, tagName);
88
- }
89
- return;
90
- }
91
-
92
- // Undo the '>' insert and allow cm to handle the key instead.
93
- cm.setSelection({line: pos.line, ch: pos.ch - 1}, pos);
94
- cm.replaceSelection("");
95
-
96
- } else if (ch == '/') {
97
- if (tok.className == 'tag' && tok.string == '<') {
98
- var tagName = state.htmlState ? (state.htmlState.context ? state.htmlState.context.tagName : '') : state.context.tagName; // htmlmixed : xml # extra htmlmized check is for '</' edge case
99
- if (tagName.length > 0) {
100
- completeEndTag(cm, pos, tagName);
101
- return;
102
- }
103
- }
104
- }
105
-
106
- }
107
-
108
- throw CodeMirror.Pass; // Bubble if not handled
109
- });
110
-
111
- function insertEndTag(cm, indent, pos, tagName) {
112
- if (shouldIndent(cm, indent, tagName)) {
113
- cm.replaceSelection('\n\n</' + tagName + '>', 'end');
114
- cm.indentLine(pos.line + 1);
115
- cm.indentLine(pos.line + 2);
116
- cm.setCursor({line: pos.line + 1, ch: cm.getLine(pos.line + 1).length});
117
- } else {
118
- cm.replaceSelection('</' + tagName + '>');
119
- cm.setCursor(pos);
120
- }
121
- }
122
-
123
- function shouldIndent(cm, indent, tagName) {
124
- if (typeof indent == 'undefined' || indent == null || indent == true) {
125
- indent = cm.getOption('closeTagIndent');
126
- }
127
- if (!indent) {
128
- indent = [];
129
- }
130
- return indexOf(indent, tagName.toLowerCase()) != -1;
131
- }
132
-
133
- // C&P from codemirror.js...would be nice if this were visible to utilities.
134
- function indexOf(collection, elt) {
135
- if (collection.indexOf) return collection.indexOf(elt);
136
- for (var i = 0, e = collection.length; i < e; ++i)
137
- if (collection[i] == elt) return i;
138
- return -1;
139
- }
140
-
141
- function completeEndTag(cm, pos, tagName) {
142
- cm.replaceSelection('/' + tagName + '>');
143
- cm.setCursor({line: pos.line, ch: pos.ch + tagName.length + 2 });
144
- }
145
-
146
- })();
@@ -1,63 +0,0 @@
1
- // Open simple dialogs on top of an editor. Relies on dialog.css.
2
-
3
- (function() {
4
- function dialogDiv(cm, template) {
5
- var wrap = cm.getWrapperElement();
6
- var dialog = wrap.insertBefore(document.createElement("div"), wrap.firstChild);
7
- dialog.className = "CodeMirror-dialog";
8
- dialog.innerHTML = '<div>' + template + '</div>';
9
- return dialog;
10
- }
11
-
12
- CodeMirror.defineExtension("openDialog", function(template, callback) {
13
- var dialog = dialogDiv(this, template);
14
- var closed = false, me = this;
15
- function close() {
16
- if (closed) return;
17
- closed = true;
18
- dialog.parentNode.removeChild(dialog);
19
- }
20
- var inp = dialog.getElementsByTagName("input")[0];
21
- if (inp) {
22
- CodeMirror.connect(inp, "keydown", function(e) {
23
- if (e.keyCode == 13 || e.keyCode == 27) {
24
- CodeMirror.e_stop(e);
25
- close();
26
- me.focus();
27
- if (e.keyCode == 13) callback(inp.value);
28
- }
29
- });
30
- inp.focus();
31
- CodeMirror.connect(inp, "blur", close);
32
- }
33
- return close;
34
- });
35
-
36
- CodeMirror.defineExtension("openConfirm", function(template, callbacks) {
37
- var dialog = dialogDiv(this, template);
38
- var buttons = dialog.getElementsByTagName("button");
39
- var closed = false, me = this, blurring = 1;
40
- function close() {
41
- if (closed) return;
42
- closed = true;
43
- dialog.parentNode.removeChild(dialog);
44
- me.focus();
45
- }
46
- buttons[0].focus();
47
- for (var i = 0; i < buttons.length; ++i) {
48
- var b = buttons[i];
49
- (function(callback) {
50
- CodeMirror.connect(b, "click", function(e) {
51
- CodeMirror.e_preventDefault(e);
52
- close();
53
- if (callback) callback(me);
54
- });
55
- })(callbacks[i]);
56
- CodeMirror.connect(b, "blur", function() {
57
- --blurring;
58
- setTimeout(function() { if (blurring <= 0) close(); }, 200);
59
- });
60
- CodeMirror.connect(b, "focus", function() { ++blurring; });
61
- }
62
- });
63
- })();
@@ -1,196 +0,0 @@
1
- // the tagRangeFinder function is
2
- // Copyright (C) 2011 by Daniel Glazman <daniel@glazman.org>
3
- // released under the MIT license (../../LICENSE) like the rest of CodeMirror
4
- CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
5
- var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
6
- var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
7
- var xmlNAMERegExp = new RegExp("^[" + nameStartChar + "][" + nameChar + "]*");
8
-
9
- var lineText = cm.getLine(line);
10
- var found = false;
11
- var tag = null;
12
- var pos = 0;
13
- while (!found) {
14
- pos = lineText.indexOf("<", pos);
15
- if (-1 == pos) // no tag on line
16
- return;
17
- if (pos + 1 < lineText.length && lineText[pos + 1] == "/") { // closing tag
18
- pos++;
19
- continue;
20
- }
21
- // ok we weem to have a start tag
22
- if (!lineText.substr(pos + 1).match(xmlNAMERegExp)) { // not a tag name...
23
- pos++;
24
- continue;
25
- }
26
- var gtPos = lineText.indexOf(">", pos + 1);
27
- if (-1 == gtPos) { // end of start tag not in line
28
- var l = line + 1;
29
- var foundGt = false;
30
- var lastLine = cm.lineCount();
31
- while (l < lastLine && !foundGt) {
32
- var lt = cm.getLine(l);
33
- var gt = lt.indexOf(">");
34
- if (-1 != gt) { // found a >
35
- foundGt = true;
36
- var slash = lt.lastIndexOf("/", gt);
37
- if (-1 != slash && slash < gt) {
38
- var str = lineText.substr(slash, gt - slash + 1);
39
- if (!str.match( /\/\s*\>/ )) { // yep, that's the end of empty tag
40
- if (hideEnd === true) l++;
41
- return l;
42
- }
43
- }
44
- }
45
- l++;
46
- }
47
- found = true;
48
- }
49
- else {
50
- var slashPos = lineText.lastIndexOf("/", gtPos);
51
- if (-1 == slashPos) { // cannot be empty tag
52
- found = true;
53
- // don't continue
54
- }
55
- else { // empty tag?
56
- // check if really empty tag
57
- var str = lineText.substr(slashPos, gtPos - slashPos + 1);
58
- if (!str.match( /\/\s*\>/ )) { // finally not empty
59
- found = true;
60
- // don't continue
61
- }
62
- }
63
- }
64
- if (found) {
65
- var subLine = lineText.substr(pos + 1);
66
- tag = subLine.match(xmlNAMERegExp);
67
- if (tag) {
68
- // we have an element name, wooohooo !
69
- tag = tag[0];
70
- // do we have the close tag on same line ???
71
- if (-1 != lineText.indexOf("</" + tag + ">", pos)) // yep
72
- {
73
- found = false;
74
- }
75
- // we don't, so we have a candidate...
76
- }
77
- else
78
- found = false;
79
- }
80
- if (!found)
81
- pos++;
82
- }
83
-
84
- if (found) {
85
- var startTag = "(\\<\\/" + tag + "\\>)|(\\<" + tag + "\\>)|(\\<" + tag + "\\s)|(\\<" + tag + "$)";
86
- var startTagRegExp = new RegExp(startTag, "g");
87
- var endTag = "</" + tag + ">";
88
- var depth = 1;
89
- var l = line + 1;
90
- var lastLine = cm.lineCount();
91
- while (l < lastLine) {
92
- lineText = cm.getLine(l);
93
- var match = lineText.match(startTagRegExp);
94
- if (match) {
95
- for (var i = 0; i < match.length; i++) {
96
- if (match[i] == endTag)
97
- depth--;
98
- else
99
- depth++;
100
- if (!depth) {
101
- if (hideEnd === true) l++;
102
- return l;
103
- }
104
- }
105
- }
106
- l++;
107
- }
108
- return;
109
- }
110
- };
111
-
112
- CodeMirror.braceRangeFinder = function(cm, line, hideEnd) {
113
- var lineText = cm.getLine(line), at = lineText.length, startChar, tokenType;
114
- for (;;) {
115
- var found = lineText.lastIndexOf("{", at);
116
- if (found < 0) break;
117
- tokenType = cm.getTokenAt({line: line, ch: found}).className;
118
- if (!/^(comment|string)/.test(tokenType)) { startChar = found; break; }
119
- at = found - 1;
120
- }
121
- if (startChar == null || lineText.lastIndexOf("}") > startChar) return;
122
- var count = 1, lastLine = cm.lineCount(), end;
123
- outer: for (var i = line + 1; i < lastLine; ++i) {
124
- var text = cm.getLine(i), pos = 0;
125
- for (;;) {
126
- var nextOpen = text.indexOf("{", pos), nextClose = text.indexOf("}", pos);
127
- if (nextOpen < 0) nextOpen = text.length;
128
- if (nextClose < 0) nextClose = text.length;
129
- pos = Math.min(nextOpen, nextClose);
130
- if (pos == text.length) break;
131
- if (cm.getTokenAt({line: i, ch: pos + 1}).className == tokenType) {
132
- if (pos == nextOpen) ++count;
133
- else if (!--count) { end = i; break outer; }
134
- }
135
- ++pos;
136
- }
137
- }
138
- if (end == null || end == line + 1) return;
139
- if (hideEnd === true) end++;
140
- return end;
141
- };
142
-
143
- CodeMirror.indentRangeFinder = function(cm, line) {
144
- var tabSize = cm.getOption("tabSize");
145
- var myIndent = cm.getLineHandle(line).indentation(tabSize), last;
146
- for (var i = line + 1, end = cm.lineCount(); i < end; ++i) {
147
- var handle = cm.getLineHandle(i);
148
- if (!/^\s*$/.test(handle.text)) {
149
- if (handle.indentation(tabSize) <= myIndent) break;
150
- last = i;
151
- }
152
- }
153
- if (!last) return null;
154
- return last + 1;
155
- };
156
-
157
- CodeMirror.newFoldFunction = function(rangeFinder, markText, hideEnd) {
158
- var folded = [];
159
- if (markText == null) markText = '<div style="position: absolute; left: 2px; color:#600">&#x25bc;</div>%N%';
160
-
161
- function isFolded(cm, n) {
162
- for (var i = 0; i < folded.length; ++i) {
163
- var start = cm.lineInfo(folded[i].start);
164
- if (!start) folded.splice(i--, 1);
165
- else if (start.line == n) return {pos: i, region: folded[i]};
166
- }
167
- }
168
-
169
- function expand(cm, region) {
170
- cm.clearMarker(region.start);
171
- for (var i = 0; i < region.hidden.length; ++i)
172
- cm.showLine(region.hidden[i]);
173
- }
174
-
175
- return function(cm, line) {
176
- cm.operation(function() {
177
- var known = isFolded(cm, line);
178
- if (known) {
179
- folded.splice(known.pos, 1);
180
- expand(cm, known.region);
181
- } else {
182
- var end = rangeFinder(cm, line, hideEnd);
183
- if (end == null) return;
184
- var hidden = [];
185
- for (var i = line + 1; i < end; ++i) {
186
- var handle = cm.hideLine(i);
187
- if (handle) hidden.push(handle);
188
- }
189
- var first = cm.setMarker(line, markText);
190
- var region = {start: first, hidden: hidden};
191
- cm.onDeleteLine(first, function() { expand(cm, region); });
192
- folded.push(region);
193
- }
194
- });
195
- };
196
- };
@@ -1,297 +0,0 @@
1
- // ============== Formatting extensions ============================
2
- // A common storage for all mode-specific formatting features
3
- if (!CodeMirror.modeExtensions) CodeMirror.modeExtensions = {};
4
-
5
- // Returns the extension of the editor's current mode
6
- CodeMirror.defineExtension("getModeExt", function () {
7
- var mname = CodeMirror.resolveMode(this.getOption("mode")).name;
8
- var ext = CodeMirror.modeExtensions[mname];
9
- if (!ext) throw new Error("No extensions found for mode " + mname);
10
- return ext;
11
- });
12
-
13
- // If the current mode is 'htmlmixed', returns the extension of a mode located at
14
- // the specified position (can be htmlmixed, css or javascript). Otherwise, simply
15
- // returns the extension of the editor's current mode.
16
- CodeMirror.defineExtension("getModeExtAtPos", function (pos) {
17
- var token = this.getTokenAt(pos);
18
- if (token && token.state && token.state.mode)
19
- return CodeMirror.modeExtensions[token.state.mode == "html" ? "htmlmixed" : token.state.mode];
20
- else
21
- return this.getModeExt();
22
- });
23
-
24
- // Comment/uncomment the specified range
25
- CodeMirror.defineExtension("commentRange", function (isComment, from, to) {
26
- var curMode = this.getModeExtAtPos(this.getCursor());
27
- if (isComment) { // Comment range
28
- var commentedText = this.getRange(from, to);
29
- this.replaceRange(curMode.commentStart + this.getRange(from, to) + curMode.commentEnd
30
- , from, to);
31
- if (from.line == to.line && from.ch == to.ch) { // An empty comment inserted - put cursor inside
32
- this.setCursor(from.line, from.ch + curMode.commentStart.length);
33
- }
34
- }
35
- else { // Uncomment range
36
- var selText = this.getRange(from, to);
37
- var startIndex = selText.indexOf(curMode.commentStart);
38
- var endIndex = selText.lastIndexOf(curMode.commentEnd);
39
- if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {
40
- // Take string till comment start
41
- selText = selText.substr(0, startIndex)
42
- // From comment start till comment end
43
- + selText.substring(startIndex + curMode.commentStart.length, endIndex)
44
- // From comment end till string end
45
- + selText.substr(endIndex + curMode.commentEnd.length);
46
- }
47
- this.replaceRange(selText, from, to);
48
- }
49
- });
50
-
51
- // Applies automatic mode-aware indentation to the specified range
52
- CodeMirror.defineExtension("autoIndentRange", function (from, to) {
53
- var cmInstance = this;
54
- this.operation(function () {
55
- for (var i = from.line; i <= to.line; i++) {
56
- cmInstance.indentLine(i, "smart");
57
- }
58
- });
59
- });
60
-
61
- // Applies automatic formatting to the specified range
62
- CodeMirror.defineExtension("autoFormatRange", function (from, to) {
63
- var absStart = this.indexFromPos(from);
64
- var absEnd = this.indexFromPos(to);
65
- // Insert additional line breaks where necessary according to the
66
- // mode's syntax
67
- var res = this.getModeExt().autoFormatLineBreaks(this.getValue(), absStart, absEnd);
68
- var cmInstance = this;
69
-
70
- // Replace and auto-indent the range
71
- this.operation(function () {
72
- cmInstance.replaceRange(res, from, to);
73
- var startLine = cmInstance.posFromIndex(absStart).line;
74
- var endLine = cmInstance.posFromIndex(absStart + res.length).line;
75
- for (var i = startLine; i <= endLine; i++) {
76
- cmInstance.indentLine(i, "smart");
77
- }
78
- });
79
- });
80
-
81
- // Define extensions for a few modes
82
-
83
- CodeMirror.modeExtensions["css"] = {
84
- commentStart: "/*",
85
- commentEnd: "*/",
86
- wordWrapChars: [";", "\\{", "\\}"],
87
- autoFormatLineBreaks: function (text, startPos, endPos) {
88
- text = text.substring(startPos, endPos);
89
- return text.replace(new RegExp("(;|\\{|\\})([^\r\n])", "g"), "$1\n$2");
90
- }
91
- };
92
-
93
- CodeMirror.modeExtensions["javascript"] = {
94
- commentStart: "/*",
95
- commentEnd: "*/",
96
- wordWrapChars: [";", "\\{", "\\}"],
97
-
98
- getNonBreakableBlocks: function (text) {
99
- var nonBreakableRegexes = [
100
- new RegExp("for\\s*?\\(([\\s\\S]*?)\\)"),
101
- new RegExp("'([\\s\\S]*?)('|$)"),
102
- new RegExp("\"([\\s\\S]*?)(\"|$)"),
103
- new RegExp("//.*([\r\n]|$)")
104
- ];
105
- var nonBreakableBlocks = new Array();
106
- for (var i = 0; i < nonBreakableRegexes.length; i++) {
107
- var curPos = 0;
108
- while (curPos < text.length) {
109
- var m = text.substr(curPos).match(nonBreakableRegexes[i]);
110
- if (m != null) {
111
- nonBreakableBlocks.push({
112
- start: curPos + m.index,
113
- end: curPos + m.index + m[0].length
114
- });
115
- curPos += m.index + Math.max(1, m[0].length);
116
- }
117
- else { // No more matches
118
- break;
119
- }
120
- }
121
- }
122
- nonBreakableBlocks.sort(function (a, b) {
123
- return a.start - b.start;
124
- });
125
-
126
- return nonBreakableBlocks;
127
- },
128
-
129
- autoFormatLineBreaks: function (text, startPos, endPos) {
130
- text = text.substring(startPos, endPos);
131
- var curPos = 0;
132
- var reLinesSplitter = new RegExp("(;|\\{|\\})([^\r\n])", "g");
133
- var nonBreakableBlocks = this.getNonBreakableBlocks(text);
134
- if (nonBreakableBlocks != null) {
135
- var res = "";
136
- for (var i = 0; i < nonBreakableBlocks.length; i++) {
137
- if (nonBreakableBlocks[i].start > curPos) { // Break lines till the block
138
- res += text.substring(curPos, nonBreakableBlocks[i].start).replace(reLinesSplitter, "$1\n$2");
139
- curPos = nonBreakableBlocks[i].start;
140
- }
141
- if (nonBreakableBlocks[i].start <= curPos
142
- && nonBreakableBlocks[i].end >= curPos) { // Skip non-breakable block
143
- res += text.substring(curPos, nonBreakableBlocks[i].end);
144
- curPos = nonBreakableBlocks[i].end;
145
- }
146
- }
147
- if (curPos < text.length - 1) {
148
- res += text.substr(curPos).replace(reLinesSplitter, "$1\n$2");
149
- }
150
- return res;
151
- }
152
- else {
153
- return text.replace(reLinesSplitter, "$1\n$2");
154
- }
155
- }
156
- };
157
-
158
- CodeMirror.modeExtensions["xml"] = {
159
- commentStart: "<!--",
160
- commentEnd: "-->",
161
- wordWrapChars: [">"],
162
-
163
- autoFormatLineBreaks: function (text, startPos, endPos) {
164
- text = text.substring(startPos, endPos);
165
- var lines = text.split("\n");
166
- var reProcessedPortion = new RegExp("(^\\s*?<|^[^<]*?)(.+)(>\\s*?$|[^>]*?$)");
167
- var reOpenBrackets = new RegExp("<", "g");
168
- var reCloseBrackets = new RegExp("(>)([^\r\n])", "g");
169
- for (var i = 0; i < lines.length; i++) {
170
- var mToProcess = lines[i].match(reProcessedPortion);
171
- if (mToProcess != null && mToProcess.length > 3) { // The line starts with whitespaces and ends with whitespaces
172
- lines[i] = mToProcess[1]
173
- + mToProcess[2].replace(reOpenBrackets, "\n$&").replace(reCloseBrackets, "$1\n$2")
174
- + mToProcess[3];
175
- continue;
176
- }
177
- }
178
-
179
- return lines.join("\n");
180
- }
181
- };
182
-
183
- CodeMirror.modeExtensions["htmlmixed"] = {
184
- commentStart: "<!--",
185
- commentEnd: "-->",
186
- wordWrapChars: [">", ";", "\\{", "\\}"],
187
-
188
- getModeInfos: function (text, absPos) {
189
- var modeInfos = new Array();
190
- modeInfos[0] =
191
- {
192
- pos: 0,
193
- modeExt: CodeMirror.modeExtensions["xml"],
194
- modeName: "xml"
195
- };
196
-
197
- var modeMatchers = new Array();
198
- modeMatchers[0] =
199
- {
200
- regex: new RegExp("<style[^>]*>([\\s\\S]*?)(</style[^>]*>|$)", "i"),
201
- modeExt: CodeMirror.modeExtensions["css"],
202
- modeName: "css"
203
- };
204
- modeMatchers[1] =
205
- {
206
- regex: new RegExp("<script[^>]*>([\\s\\S]*?)(</script[^>]*>|$)", "i"),
207
- modeExt: CodeMirror.modeExtensions["javascript"],
208
- modeName: "javascript"
209
- };
210
-
211
- var lastCharPos = (typeof (absPos) !== "undefined" ? absPos : text.length - 1);
212
- // Detect modes for the entire text
213
- for (var i = 0; i < modeMatchers.length; i++) {
214
- var curPos = 0;
215
- while (curPos <= lastCharPos) {
216
- var m = text.substr(curPos).match(modeMatchers[i].regex);
217
- if (m != null) {
218
- if (m.length > 1 && m[1].length > 0) {
219
- // Push block begin pos
220
- var blockBegin = curPos + m.index + m[0].indexOf(m[1]);
221
- modeInfos.push(
222
- {
223
- pos: blockBegin,
224
- modeExt: modeMatchers[i].modeExt,
225
- modeName: modeMatchers[i].modeName
226
- });
227
- // Push block end pos
228
- modeInfos.push(
229
- {
230
- pos: blockBegin + m[1].length,
231
- modeExt: modeInfos[0].modeExt,
232
- modeName: modeInfos[0].modeName
233
- });
234
- curPos += m.index + m[0].length;
235
- continue;
236
- }
237
- else {
238
- curPos += m.index + Math.max(m[0].length, 1);
239
- }
240
- }
241
- else { // No more matches
242
- break;
243
- }
244
- }
245
- }
246
- // Sort mode infos
247
- modeInfos.sort(function sortModeInfo(a, b) {
248
- return a.pos - b.pos;
249
- });
250
-
251
- return modeInfos;
252
- },
253
-
254
- autoFormatLineBreaks: function (text, startPos, endPos) {
255
- var modeInfos = this.getModeInfos(text);
256
- var reBlockStartsWithNewline = new RegExp("^\\s*?\n");
257
- var reBlockEndsWithNewline = new RegExp("\n\\s*?$");
258
- var res = "";
259
- // Use modes info to break lines correspondingly
260
- if (modeInfos.length > 1) { // Deal with multi-mode text
261
- for (var i = 1; i <= modeInfos.length; i++) {
262
- var selStart = modeInfos[i - 1].pos;
263
- var selEnd = (i < modeInfos.length ? modeInfos[i].pos : endPos);
264
-
265
- if (selStart >= endPos) { // The block starts later than the needed fragment
266
- break;
267
- }
268
- if (selStart < startPos) {
269
- if (selEnd <= startPos) { // The block starts earlier than the needed fragment
270
- continue;
271
- }
272
- selStart = startPos;
273
- }
274
- if (selEnd > endPos) {
275
- selEnd = endPos;
276
- }
277
- var textPortion = text.substring(selStart, selEnd);
278
- if (modeInfos[i - 1].modeName != "xml") { // Starting a CSS or JavaScript block
279
- if (!reBlockStartsWithNewline.test(textPortion)
280
- && selStart > 0) { // The block does not start with a line break
281
- textPortion = "\n" + textPortion;
282
- }
283
- if (!reBlockEndsWithNewline.test(textPortion)
284
- && selEnd < text.length - 1) { // The block does not end with a line break
285
- textPortion += "\n";
286
- }
287
- }
288
- res += modeInfos[i - 1].modeExt.autoFormatLineBreaks(textPortion);
289
- }
290
- }
291
- else { // Single-mode text
292
- res = modeInfos[0].modeExt.autoFormatLineBreaks(text.substring(startPos, endPos));
293
- }
294
-
295
- return res;
296
- }
297
- };