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.
- data/README.md +0 -16
- data/codemirror-rails.gemspec +1 -1
- data/lib/codemirror/rails/version.rb +2 -2
- data/vendor/assets/javascripts/codemirror.js +323 -687
- data/vendor/assets/javascripts/codemirror/modes/clike.js +3 -40
- data/vendor/assets/javascripts/codemirror/modes/clojure.js +14 -14
- data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +0 -6
- data/vendor/assets/javascripts/codemirror/modes/css.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/diff.js +5 -24
- data/vendor/assets/javascripts/codemirror/modes/gfm.js +4 -40
- data/vendor/assets/javascripts/codemirror/modes/go.js +22 -20
- data/vendor/assets/javascripts/codemirror/modes/htmlembedded.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +2 -4
- data/vendor/assets/javascripts/codemirror/modes/javascript.js +7 -8
- data/vendor/assets/javascripts/codemirror/modes/less.js +54 -100
- data/vendor/assets/javascripts/codemirror/modes/markdown.js +49 -52
- data/vendor/assets/javascripts/codemirror/modes/pascal.js +46 -2
- data/vendor/assets/javascripts/codemirror/modes/perl.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/php.js +25 -54
- data/vendor/assets/javascripts/codemirror/modes/python.js +16 -14
- data/vendor/assets/javascripts/codemirror/modes/rpm-spec.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/rst.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/ruby.js +9 -4
- data/vendor/assets/javascripts/codemirror/modes/scheme.js +46 -74
- data/vendor/assets/javascripts/codemirror/modes/smalltalk.js +16 -16
- data/vendor/assets/javascripts/codemirror/modes/stex.js +6 -21
- data/vendor/assets/javascripts/codemirror/modes/tiddlywiki.js +45 -55
- data/vendor/assets/javascripts/codemirror/modes/xml.js +14 -79
- data/vendor/assets/javascripts/codemirror/{utils/overlay.js → overlay.js} +2 -3
- data/vendor/assets/javascripts/codemirror/runmode.js +27 -0
- data/vendor/assets/stylesheets/codemirror.css +2 -63
- data/vendor/assets/stylesheets/codemirror/modes/tiddlywiki.css +21 -14
- data/vendor/assets/stylesheets/codemirror/themes/eclipse.css +1 -1
- data/vendor/assets/stylesheets/codemirror/themes/elegant.css +2 -2
- data/vendor/assets/stylesheets/codemirror/themes/neat.css +3 -3
- data/vendor/assets/stylesheets/codemirror/themes/night.css +1 -1
- data/vendor/assets/stylesheets/codemirror/themes/rubyblue.css +2 -2
- metadata +6 -39
- data/vendor/assets/javascripts/codemirror/keymaps/emacs.js +0 -29
- data/vendor/assets/javascripts/codemirror/keymaps/vim.js +0 -766
- data/vendor/assets/javascripts/codemirror/modes/ecl.js +0 -203
- data/vendor/assets/javascripts/codemirror/modes/erlang.js +0 -251
- data/vendor/assets/javascripts/codemirror/modes/pig.js +0 -172
- data/vendor/assets/javascripts/codemirror/modes/properties.js +0 -63
- data/vendor/assets/javascripts/codemirror/modes/shell.js +0 -103
- data/vendor/assets/javascripts/codemirror/modes/smarty.js +0 -148
- data/vendor/assets/javascripts/codemirror/modes/tiki.js +0 -316
- data/vendor/assets/javascripts/codemirror/modes/vbscript.js +0 -26
- data/vendor/assets/javascripts/codemirror/modes/xquery.js +0 -448
- data/vendor/assets/javascripts/codemirror/utils/closetag.js +0 -146
- data/vendor/assets/javascripts/codemirror/utils/dialog.js +0 -63
- data/vendor/assets/javascripts/codemirror/utils/foldcode.js +0 -196
- data/vendor/assets/javascripts/codemirror/utils/formatting.js +0 -297
- data/vendor/assets/javascripts/codemirror/utils/javascript-hint.js +0 -134
- data/vendor/assets/javascripts/codemirror/utils/loadmode.js +0 -51
- data/vendor/assets/javascripts/codemirror/utils/match-highlighter.js +0 -44
- data/vendor/assets/javascripts/codemirror/utils/multiplex.js +0 -72
- data/vendor/assets/javascripts/codemirror/utils/pig-hint.js +0 -123
- data/vendor/assets/javascripts/codemirror/utils/runmode.js +0 -49
- data/vendor/assets/javascripts/codemirror/utils/search.js +0 -118
- data/vendor/assets/javascripts/codemirror/utils/searchcursor.js +0 -117
- data/vendor/assets/javascripts/codemirror/utils/simple-hint.js +0 -72
- data/vendor/assets/stylesheets/codemirror/modes/tiki.css +0 -26
- data/vendor/assets/stylesheets/codemirror/themes/ambiance.css +0 -81
- data/vendor/assets/stylesheets/codemirror/themes/blackboard.css +0 -25
- data/vendor/assets/stylesheets/codemirror/themes/erlang-dark.css +0 -21
- data/vendor/assets/stylesheets/codemirror/themes/lesser-dark.css +0 -44
- data/vendor/assets/stylesheets/codemirror/themes/vibrant-ink.css +0 -27
- data/vendor/assets/stylesheets/codemirror/themes/xq-dark.css +0 -46
- data/vendor/assets/stylesheets/codemirror/utils/dialog.css +0 -23
- 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">▼</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
|
-
};
|