kit_cms 2.3.8 → 2.3.9
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/app/assets/javascripts/codemirror/codemirror.js +5104 -0
- data/app/assets/javascripts/codemirror/collapserange.js +68 -0
- data/app/assets/javascripts/codemirror/css.js +465 -0
- data/app/assets/javascripts/codemirror/dialog.js +76 -0
- data/app/assets/javascripts/codemirror/editor.js +19 -0
- data/app/assets/javascripts/codemirror/foldcode.js +183 -0
- data/app/assets/javascripts/codemirror/formatting.js +108 -0
- data/app/assets/javascripts/codemirror/htmlmixed.js +84 -0
- data/app/assets/javascripts/codemirror/javascript.js +422 -0
- data/app/assets/javascripts/codemirror/jquery.js +4 -0
- data/app/assets/javascripts/codemirror/loadmode.js +51 -0
- data/app/assets/javascripts/codemirror/match-highlighter.js +46 -0
- data/app/assets/javascripts/codemirror/matchbrackets.js +63 -0
- data/app/assets/javascripts/codemirror/multiplex.js +95 -0
- data/app/assets/javascripts/codemirror/overlay.js +59 -0
- data/app/assets/javascripts/codemirror/search.js +131 -0
- data/app/assets/javascripts/codemirror/searchcursor.js +131 -0
- data/app/assets/javascripts/codemirror/xml.js +324 -0
- data/app/assets/stylesheets/codemirror/dialog.css +32 -0
- data/app/assets/stylesheets/codemirror/style.css +242 -0
- data/app/assets/stylesheets/codemirror/theme.css +25 -0
- data/app/views/layouts/_html-editor.html.haml +1 -0
- data/app/views/layouts/mercury-editor.html.erb +5 -5
- data/app/views/utility/mercury_html.html.haml +28 -3
- metadata +41 -39
- data/app/assets/javascripts/kit/markitup/jquery.markitup.js +0 -634
- data/app/assets/javascripts/kit/markitup/settings.js +0 -31
- data/app/assets/stylesheets/kit/markitup/html.css +0 -59
- data/app/assets/stylesheets/kit/markitup/images/bg-container.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/bg-editor-bbcode.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/bg-editor-dotclear.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/bg-editor-html.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/bg-editor-json.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/bg-editor-markdown.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/bg-editor-textile.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/bg-editor-wiki.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/bg-editor-xml.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/bg-editor.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/bold.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/clean.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/h1.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/h2.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/h3.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/h4.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/h5.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/h6.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/handle.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/image.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/italic.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/link.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/list-bullet.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/list-item.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/list-numeric.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/menu.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/paragraph.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/picture.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/preview.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/stroke.png +0 -0
- data/app/assets/stylesheets/kit/markitup/images/submenu.png +0 -0
- data/app/assets/stylesheets/kit/markitup/style.css +0 -145
- data/lib/kit_cms/version.rb +0 -3
@@ -0,0 +1,76 @@
|
|
1
|
+
// Open simple dialogs on top of an editor. Relies on dialog.css.
|
2
|
+
|
3
|
+
(function() {
|
4
|
+
function dialogDiv(cm, template, bottom) {
|
5
|
+
var wrap = cm.getWrapperElement();
|
6
|
+
var dialog;
|
7
|
+
dialog = wrap.appendChild(document.createElement("div"));
|
8
|
+
if (bottom) {
|
9
|
+
dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom";
|
10
|
+
} else {
|
11
|
+
dialog.className = "CodeMirror-dialog CodeMirror-dialog-top";
|
12
|
+
}
|
13
|
+
dialog.innerHTML = template;
|
14
|
+
return dialog;
|
15
|
+
}
|
16
|
+
|
17
|
+
CodeMirror.defineExtension("openDialog", function(template, callback, options) {
|
18
|
+
var dialog = dialogDiv(this, template, options && options.bottom);
|
19
|
+
var closed = false, me = this;
|
20
|
+
function close() {
|
21
|
+
if (closed) return;
|
22
|
+
closed = true;
|
23
|
+
dialog.parentNode.removeChild(dialog);
|
24
|
+
}
|
25
|
+
var inp = dialog.getElementsByTagName("input")[0], button;
|
26
|
+
if (inp) {
|
27
|
+
CodeMirror.on(inp, "keydown", function(e) {
|
28
|
+
if (e.keyCode == 13 || e.keyCode == 27) {
|
29
|
+
CodeMirror.e_stop(e);
|
30
|
+
close();
|
31
|
+
me.focus();
|
32
|
+
if (e.keyCode == 13) callback(inp.value);
|
33
|
+
}
|
34
|
+
});
|
35
|
+
if (options && options.value) inp.value = options.value;
|
36
|
+
inp.focus();
|
37
|
+
CodeMirror.on(inp, "blur", close);
|
38
|
+
} else if (button = dialog.getElementsByTagName("button")[0]) {
|
39
|
+
CodeMirror.on(button, "click", function() {
|
40
|
+
close();
|
41
|
+
me.focus();
|
42
|
+
});
|
43
|
+
button.focus();
|
44
|
+
CodeMirror.on(button, "blur", close);
|
45
|
+
}
|
46
|
+
return close;
|
47
|
+
});
|
48
|
+
|
49
|
+
CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) {
|
50
|
+
var dialog = dialogDiv(this, template, options && options.bottom);
|
51
|
+
var buttons = dialog.getElementsByTagName("button");
|
52
|
+
var closed = false, me = this, blurring = 1;
|
53
|
+
function close() {
|
54
|
+
if (closed) return;
|
55
|
+
closed = true;
|
56
|
+
dialog.parentNode.removeChild(dialog);
|
57
|
+
me.focus();
|
58
|
+
}
|
59
|
+
buttons[0].focus();
|
60
|
+
for (var i = 0; i < buttons.length; ++i) {
|
61
|
+
var b = buttons[i];
|
62
|
+
(function(callback) {
|
63
|
+
CodeMirror.on(b, "click", function(e) {
|
64
|
+
CodeMirror.e_preventDefault(e);
|
65
|
+
close();
|
66
|
+
if (callback) callback(me);
|
67
|
+
});
|
68
|
+
})(callbacks[i]);
|
69
|
+
CodeMirror.on(b, "blur", function() {
|
70
|
+
--blurring;
|
71
|
+
setTimeout(function() { if (blurring <= 0) close(); }, 200);
|
72
|
+
});
|
73
|
+
CodeMirror.on(b, "focus", function() { ++blurring; });
|
74
|
+
}
|
75
|
+
});
|
76
|
+
})();
|
@@ -0,0 +1,19 @@
|
|
1
|
+
/*
|
2
|
+
*
|
3
|
+
*= require "./codemirror"
|
4
|
+
*= require "./overlay"
|
5
|
+
*= require "./htmlmixed"
|
6
|
+
*= require "./css"
|
7
|
+
*= require "./xml"
|
8
|
+
*= require "./css"
|
9
|
+
*= require "./javascript"
|
10
|
+
*= require "./dialog"
|
11
|
+
*= require "./match-highlighter"
|
12
|
+
*= require "./matchbrackets"
|
13
|
+
*= require "./searchcursor"
|
14
|
+
*= require "./search"
|
15
|
+
*= require "./collapserange"
|
16
|
+
*
|
17
|
+
*/
|
18
|
+
|
19
|
+
|
@@ -0,0 +1,183 @@
|
|
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, start) {
|
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(start.line);
|
10
|
+
var found = false;
|
11
|
+
var tag = null;
|
12
|
+
var pos = start.ch;
|
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 seem 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 = start.line + 1;
|
29
|
+
var foundGt = false;
|
30
|
+
var lastLine = cm.lineCount();
|
31
|
+
while (l < lastLine && !foundGt) {
|
32
|
+
var lt = cm.getLine(l);
|
33
|
+
gtPos = lt.indexOf(">");
|
34
|
+
if (-1 != gtPos) { // found a >
|
35
|
+
foundGt = true;
|
36
|
+
var slash = lt.lastIndexOf("/", gtPos);
|
37
|
+
if (-1 != slash && slash < gtPos) {
|
38
|
+
var str = lineText.substr(slash, gtPos - slash + 1);
|
39
|
+
if (!str.match( /\/\s*\>/ )) // yep, that's the end of empty tag
|
40
|
+
return;
|
41
|
+
}
|
42
|
+
}
|
43
|
+
l++;
|
44
|
+
}
|
45
|
+
found = true;
|
46
|
+
}
|
47
|
+
else {
|
48
|
+
var slashPos = lineText.lastIndexOf("/", gtPos);
|
49
|
+
if (-1 == slashPos) { // cannot be empty tag
|
50
|
+
found = true;
|
51
|
+
// don't continue
|
52
|
+
}
|
53
|
+
else { // empty tag?
|
54
|
+
// check if really empty tag
|
55
|
+
var str = lineText.substr(slashPos, gtPos - slashPos + 1);
|
56
|
+
if (!str.match( /\/\s*\>/ )) { // finally not empty
|
57
|
+
found = true;
|
58
|
+
// don't continue
|
59
|
+
}
|
60
|
+
}
|
61
|
+
}
|
62
|
+
if (found) {
|
63
|
+
var subLine = lineText.substr(pos + 1);
|
64
|
+
tag = subLine.match(xmlNAMERegExp);
|
65
|
+
if (tag) {
|
66
|
+
// we have an element name, wooohooo !
|
67
|
+
tag = tag[0];
|
68
|
+
// do we have the close tag on same line ???
|
69
|
+
if (-1 != lineText.indexOf("</" + tag + ">", pos)) // yep
|
70
|
+
{
|
71
|
+
found = false;
|
72
|
+
}
|
73
|
+
// we don't, so we have a candidate...
|
74
|
+
}
|
75
|
+
else
|
76
|
+
found = false;
|
77
|
+
}
|
78
|
+
if (!found)
|
79
|
+
pos++;
|
80
|
+
}
|
81
|
+
|
82
|
+
if (found) {
|
83
|
+
var startTag = "(\\<\\/" + tag + "\\>)|(\\<" + tag + "\\>)|(\\<" + tag + "\\s)|(\\<" + tag + "$)";
|
84
|
+
var startTagRegExp = new RegExp(startTag);
|
85
|
+
var endTag = "</" + tag + ">";
|
86
|
+
var depth = 1;
|
87
|
+
var l = start.line + 1;
|
88
|
+
var lastLine = cm.lineCount();
|
89
|
+
while (l < lastLine) {
|
90
|
+
lineText = cm.getLine(l);
|
91
|
+
var match = lineText.match(startTagRegExp);
|
92
|
+
if (match) {
|
93
|
+
for (var i = 0; i < match.length; i++) {
|
94
|
+
if (match[i] == endTag)
|
95
|
+
depth--;
|
96
|
+
else
|
97
|
+
depth++;
|
98
|
+
if (!depth) return {from: {line: start.line, ch: gtPos + 1},
|
99
|
+
to: {line: l, ch: match.index}};
|
100
|
+
}
|
101
|
+
}
|
102
|
+
l++;
|
103
|
+
}
|
104
|
+
return;
|
105
|
+
}
|
106
|
+
};
|
107
|
+
|
108
|
+
CodeMirror.braceRangeFinder = function(cm, start) {
|
109
|
+
var line = start.line, lineText = cm.getLine(line);
|
110
|
+
var at = lineText.length, startChar, tokenType;
|
111
|
+
for (;;) {
|
112
|
+
var found = lineText.lastIndexOf("{", at);
|
113
|
+
if (found < start.ch) break;
|
114
|
+
tokenType = cm.getTokenAt({line: line, ch: found}).type;
|
115
|
+
if (!/^(comment|string)/.test(tokenType)) { startChar = found; break; }
|
116
|
+
at = found - 1;
|
117
|
+
}
|
118
|
+
if (startChar == null || lineText.lastIndexOf("}") > startChar) return;
|
119
|
+
var count = 1, lastLine = cm.lineCount(), end, endCh;
|
120
|
+
outer: for (var i = line + 1; i < lastLine; ++i) {
|
121
|
+
var text = cm.getLine(i), pos = 0;
|
122
|
+
for (;;) {
|
123
|
+
var nextOpen = text.indexOf("{", pos), nextClose = text.indexOf("}", pos);
|
124
|
+
if (nextOpen < 0) nextOpen = text.length;
|
125
|
+
if (nextClose < 0) nextClose = text.length;
|
126
|
+
pos = Math.min(nextOpen, nextClose);
|
127
|
+
if (pos == text.length) break;
|
128
|
+
if (cm.getTokenAt({line: i, ch: pos + 1}).type == tokenType) {
|
129
|
+
if (pos == nextOpen) ++count;
|
130
|
+
else if (!--count) { end = i; endCh = pos; break outer; }
|
131
|
+
}
|
132
|
+
++pos;
|
133
|
+
}
|
134
|
+
}
|
135
|
+
if (end == null || end == line + 1) return;
|
136
|
+
return {from: {line: line, ch: startChar + 1},
|
137
|
+
to: {line: end, ch: endCh}};
|
138
|
+
};
|
139
|
+
|
140
|
+
CodeMirror.indentRangeFinder = function(cm, start) {
|
141
|
+
var tabSize = cm.getOption("tabSize"), firstLine = cm.getLine(start.line);
|
142
|
+
var myIndent = CodeMirror.countColumn(firstLine, null, tabSize);
|
143
|
+
for (var i = start.line + 1, end = cm.lineCount(); i < end; ++i) {
|
144
|
+
var curLine = cm.getLine(i);
|
145
|
+
if (CodeMirror.countColumn(curLine, null, tabSize) < myIndent &&
|
146
|
+
CodeMirror.countColumn(cm.getLine(i-1), null, tabSize) > myIndent)
|
147
|
+
return {from: {line: start.line, ch: firstLine.length},
|
148
|
+
to: {line: i, ch: curLine.length}};
|
149
|
+
}
|
150
|
+
};
|
151
|
+
|
152
|
+
CodeMirror.newFoldFunction = function(rangeFinder, widget) {
|
153
|
+
if (widget == null) widget = "\u2194";
|
154
|
+
if (typeof widget == "string") {
|
155
|
+
var text = document.createTextNode(widget);
|
156
|
+
widget = document.createElement("span");
|
157
|
+
widget.appendChild(text);
|
158
|
+
widget.className = "CodeMirror-foldmarker";
|
159
|
+
}
|
160
|
+
|
161
|
+
return function(cm, pos) {
|
162
|
+
if (typeof pos == "number") pos = {line: pos, ch: 0};
|
163
|
+
var range = rangeFinder(cm, pos);
|
164
|
+
if (!range) return;
|
165
|
+
|
166
|
+
var present = cm.findMarksAt(range.from), cleared = 0;
|
167
|
+
for (var i = 0; i < present.length; ++i) {
|
168
|
+
if (present[i].__isFold) {
|
169
|
+
++cleared;
|
170
|
+
present[i].clear();
|
171
|
+
}
|
172
|
+
}
|
173
|
+
if (cleared) return;
|
174
|
+
|
175
|
+
var myWidget = widget.cloneNode(true);
|
176
|
+
CodeMirror.on(myWidget, "mousedown", function() {myRange.clear();});
|
177
|
+
var myRange = cm.markText(range.from, range.to, {
|
178
|
+
replacedWith: myWidget,
|
179
|
+
clearOnEnter: true,
|
180
|
+
__isFold: true
|
181
|
+
});
|
182
|
+
};
|
183
|
+
};
|
@@ -0,0 +1,108 @@
|
|
1
|
+
(function() {
|
2
|
+
|
3
|
+
CodeMirror.extendMode("css", {
|
4
|
+
commentStart: "/*",
|
5
|
+
commentEnd: "*/",
|
6
|
+
newlineAfterToken: function(_type, content) {
|
7
|
+
return /^[;{}]$/.test(content);
|
8
|
+
}
|
9
|
+
});
|
10
|
+
|
11
|
+
CodeMirror.extendMode("javascript", {
|
12
|
+
commentStart: "/*",
|
13
|
+
commentEnd: "*/",
|
14
|
+
// FIXME semicolons inside of for
|
15
|
+
newlineAfterToken: function(_type, content, textAfter, state) {
|
16
|
+
if (this.jsonMode) {
|
17
|
+
return /^[\[,{]$/.test(content) || /^}/.test(textAfter);
|
18
|
+
} else {
|
19
|
+
if (content == ";" && state.lexical && state.lexical.type == ")") return false;
|
20
|
+
return /^[;{}]$/.test(content) && !/^;/.test(textAfter);
|
21
|
+
}
|
22
|
+
}
|
23
|
+
});
|
24
|
+
|
25
|
+
CodeMirror.extendMode("xml", {
|
26
|
+
commentStart: "<!--",
|
27
|
+
commentEnd: "-->",
|
28
|
+
newlineAfterToken: function(type, content, textAfter) {
|
29
|
+
return type == "tag" && />$/.test(content) || /^</.test(textAfter);
|
30
|
+
}
|
31
|
+
});
|
32
|
+
|
33
|
+
// Comment/uncomment the specified range
|
34
|
+
CodeMirror.defineExtension("commentRange", function (isComment, from, to) {
|
35
|
+
var cm = this, curMode = CodeMirror.innerMode(cm.getMode(), cm.getTokenAt(from).state).mode;
|
36
|
+
cm.operation(function() {
|
37
|
+
if (isComment) { // Comment range
|
38
|
+
cm.replaceRange(curMode.commentEnd, to);
|
39
|
+
cm.replaceRange(curMode.commentStart, from);
|
40
|
+
if (from.line == to.line && from.ch == to.ch) // An empty comment inserted - put cursor inside
|
41
|
+
cm.setCursor(from.line, from.ch + curMode.commentStart.length);
|
42
|
+
} else { // Uncomment range
|
43
|
+
var selText = cm.getRange(from, to);
|
44
|
+
var startIndex = selText.indexOf(curMode.commentStart);
|
45
|
+
var endIndex = selText.lastIndexOf(curMode.commentEnd);
|
46
|
+
if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {
|
47
|
+
// Take string till comment start
|
48
|
+
selText = selText.substr(0, startIndex)
|
49
|
+
// From comment start till comment end
|
50
|
+
+ selText.substring(startIndex + curMode.commentStart.length, endIndex)
|
51
|
+
// From comment end till string end
|
52
|
+
+ selText.substr(endIndex + curMode.commentEnd.length);
|
53
|
+
}
|
54
|
+
cm.replaceRange(selText, from, to);
|
55
|
+
}
|
56
|
+
});
|
57
|
+
});
|
58
|
+
|
59
|
+
// Applies automatic mode-aware indentation to the specified range
|
60
|
+
CodeMirror.defineExtension("autoIndentRange", function (from, to) {
|
61
|
+
var cmInstance = this;
|
62
|
+
this.operation(function () {
|
63
|
+
for (var i = from.line; i <= to.line; i++) {
|
64
|
+
cmInstance.indentLine(i, "smart");
|
65
|
+
}
|
66
|
+
});
|
67
|
+
});
|
68
|
+
|
69
|
+
// Applies automatic formatting to the specified range
|
70
|
+
CodeMirror.defineExtension("autoFormatRange", function (from, to) {
|
71
|
+
var cm = this;
|
72
|
+
var outer = cm.getMode(), text = cm.getRange(from, to).split("\n");
|
73
|
+
var state = CodeMirror.copyState(outer, cm.getTokenAt(from).state);
|
74
|
+
var tabSize = cm.getOption("tabSize");
|
75
|
+
|
76
|
+
var out = "", lines = 0, atSol = from.ch == 0;
|
77
|
+
function newline() {
|
78
|
+
out += "\n";
|
79
|
+
atSol = true;
|
80
|
+
++lines;
|
81
|
+
}
|
82
|
+
|
83
|
+
for (var i = 0; i < text.length; ++i) {
|
84
|
+
var stream = new CodeMirror.StringStream(text[i], tabSize);
|
85
|
+
while (!stream.eol()) {
|
86
|
+
var inner = CodeMirror.innerMode(outer, state);
|
87
|
+
var style = outer.token(stream, state), cur = stream.current();
|
88
|
+
stream.start = stream.pos;
|
89
|
+
if (!atSol || /\S/.test(cur)) {
|
90
|
+
out += cur;
|
91
|
+
atSol = false;
|
92
|
+
}
|
93
|
+
if (!atSol && inner.mode.newlineAfterToken &&
|
94
|
+
inner.mode.newlineAfterToken(style, cur, stream.string.slice(stream.pos) || text[i+1] || "", inner.state))
|
95
|
+
newline();
|
96
|
+
}
|
97
|
+
if (!stream.pos && outer.blankLine) outer.blankLine(state);
|
98
|
+
if (!atSol && i < text.length - 1) newline();
|
99
|
+
}
|
100
|
+
|
101
|
+
cm.operation(function () {
|
102
|
+
cm.replaceRange(out, from, to);
|
103
|
+
for (var cur = from.line + 1, end = from.line + lines; cur <= end; ++cur)
|
104
|
+
cm.indentLine(cur, "smart");
|
105
|
+
cm.setSelection(from, cm.getCursor(false));
|
106
|
+
});
|
107
|
+
});
|
108
|
+
})();
|
@@ -0,0 +1,84 @@
|
|
1
|
+
CodeMirror.defineMode("htmlmixed", function(config) {
|
2
|
+
var htmlMode = CodeMirror.getMode(config, {name: "xml", htmlMode: true});
|
3
|
+
var jsMode = CodeMirror.getMode(config, "javascript");
|
4
|
+
var cssMode = CodeMirror.getMode(config, "css");
|
5
|
+
|
6
|
+
function html(stream, state) {
|
7
|
+
var style = htmlMode.token(stream, state.htmlState);
|
8
|
+
if (/(?:^|\s)tag(?:\s|$)/.test(style) && stream.current() == ">" && state.htmlState.context) {
|
9
|
+
if (/^script$/i.test(state.htmlState.context.tagName)) {
|
10
|
+
state.token = javascript;
|
11
|
+
state.localState = jsMode.startState(htmlMode.indent(state.htmlState, ""));
|
12
|
+
}
|
13
|
+
else if (/^style$/i.test(state.htmlState.context.tagName)) {
|
14
|
+
state.token = css;
|
15
|
+
state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
|
16
|
+
}
|
17
|
+
}
|
18
|
+
return style;
|
19
|
+
}
|
20
|
+
function maybeBackup(stream, pat, style) {
|
21
|
+
var cur = stream.current();
|
22
|
+
var close = cur.search(pat), m;
|
23
|
+
if (close > -1) stream.backUp(cur.length - close);
|
24
|
+
else if (m = cur.match(/<\/?$/)) {
|
25
|
+
stream.backUp(cur.length);
|
26
|
+
if (!stream.match(pat, false)) stream.match(cur[0]);
|
27
|
+
}
|
28
|
+
return style;
|
29
|
+
}
|
30
|
+
function javascript(stream, state) {
|
31
|
+
if (stream.match(/^<\/\s*script\s*>/i, false)) {
|
32
|
+
state.token = html;
|
33
|
+
state.localState = null;
|
34
|
+
return html(stream, state);
|
35
|
+
}
|
36
|
+
return maybeBackup(stream, /<\/\s*script\s*>/,
|
37
|
+
jsMode.token(stream, state.localState));
|
38
|
+
}
|
39
|
+
function css(stream, state) {
|
40
|
+
if (stream.match(/^<\/\s*style\s*>/i, false)) {
|
41
|
+
state.token = html;
|
42
|
+
state.localState = null;
|
43
|
+
return html(stream, state);
|
44
|
+
}
|
45
|
+
return maybeBackup(stream, /<\/\s*style\s*>/,
|
46
|
+
cssMode.token(stream, state.localState));
|
47
|
+
}
|
48
|
+
|
49
|
+
return {
|
50
|
+
startState: function() {
|
51
|
+
var state = htmlMode.startState();
|
52
|
+
return {token: html, localState: null, mode: "html", htmlState: state};
|
53
|
+
},
|
54
|
+
|
55
|
+
copyState: function(state) {
|
56
|
+
if (state.localState)
|
57
|
+
var local = CodeMirror.copyState(state.token == css ? cssMode : jsMode, state.localState);
|
58
|
+
return {token: state.token, localState: local, mode: state.mode,
|
59
|
+
htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
|
60
|
+
},
|
61
|
+
|
62
|
+
token: function(stream, state) {
|
63
|
+
return state.token(stream, state);
|
64
|
+
},
|
65
|
+
|
66
|
+
indent: function(state, textAfter) {
|
67
|
+
if (state.token == html || /^\s*<\//.test(textAfter))
|
68
|
+
return htmlMode.indent(state.htmlState, textAfter);
|
69
|
+
else if (state.token == javascript)
|
70
|
+
return jsMode.indent(state.localState, textAfter);
|
71
|
+
else
|
72
|
+
return cssMode.indent(state.localState, textAfter);
|
73
|
+
},
|
74
|
+
|
75
|
+
electricChars: "/{}:",
|
76
|
+
|
77
|
+
innerMode: function(state) {
|
78
|
+
var mode = state.token == html ? htmlMode : state.token == javascript ? jsMode : cssMode;
|
79
|
+
return {state: state.localState || state.htmlState, mode: mode};
|
80
|
+
}
|
81
|
+
};
|
82
|
+
}, "xml", "javascript", "css");
|
83
|
+
|
84
|
+
CodeMirror.defineMIME("text/html", "htmlmixed");
|