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.
Files changed (61) hide show
  1. data/app/assets/javascripts/codemirror/codemirror.js +5104 -0
  2. data/app/assets/javascripts/codemirror/collapserange.js +68 -0
  3. data/app/assets/javascripts/codemirror/css.js +465 -0
  4. data/app/assets/javascripts/codemirror/dialog.js +76 -0
  5. data/app/assets/javascripts/codemirror/editor.js +19 -0
  6. data/app/assets/javascripts/codemirror/foldcode.js +183 -0
  7. data/app/assets/javascripts/codemirror/formatting.js +108 -0
  8. data/app/assets/javascripts/codemirror/htmlmixed.js +84 -0
  9. data/app/assets/javascripts/codemirror/javascript.js +422 -0
  10. data/app/assets/javascripts/codemirror/jquery.js +4 -0
  11. data/app/assets/javascripts/codemirror/loadmode.js +51 -0
  12. data/app/assets/javascripts/codemirror/match-highlighter.js +46 -0
  13. data/app/assets/javascripts/codemirror/matchbrackets.js +63 -0
  14. data/app/assets/javascripts/codemirror/multiplex.js +95 -0
  15. data/app/assets/javascripts/codemirror/overlay.js +59 -0
  16. data/app/assets/javascripts/codemirror/search.js +131 -0
  17. data/app/assets/javascripts/codemirror/searchcursor.js +131 -0
  18. data/app/assets/javascripts/codemirror/xml.js +324 -0
  19. data/app/assets/stylesheets/codemirror/dialog.css +32 -0
  20. data/app/assets/stylesheets/codemirror/style.css +242 -0
  21. data/app/assets/stylesheets/codemirror/theme.css +25 -0
  22. data/app/views/layouts/_html-editor.html.haml +1 -0
  23. data/app/views/layouts/mercury-editor.html.erb +5 -5
  24. data/app/views/utility/mercury_html.html.haml +28 -3
  25. metadata +41 -39
  26. data/app/assets/javascripts/kit/markitup/jquery.markitup.js +0 -634
  27. data/app/assets/javascripts/kit/markitup/settings.js +0 -31
  28. data/app/assets/stylesheets/kit/markitup/html.css +0 -59
  29. data/app/assets/stylesheets/kit/markitup/images/bg-container.png +0 -0
  30. data/app/assets/stylesheets/kit/markitup/images/bg-editor-bbcode.png +0 -0
  31. data/app/assets/stylesheets/kit/markitup/images/bg-editor-dotclear.png +0 -0
  32. data/app/assets/stylesheets/kit/markitup/images/bg-editor-html.png +0 -0
  33. data/app/assets/stylesheets/kit/markitup/images/bg-editor-json.png +0 -0
  34. data/app/assets/stylesheets/kit/markitup/images/bg-editor-markdown.png +0 -0
  35. data/app/assets/stylesheets/kit/markitup/images/bg-editor-textile.png +0 -0
  36. data/app/assets/stylesheets/kit/markitup/images/bg-editor-wiki.png +0 -0
  37. data/app/assets/stylesheets/kit/markitup/images/bg-editor-xml.png +0 -0
  38. data/app/assets/stylesheets/kit/markitup/images/bg-editor.png +0 -0
  39. data/app/assets/stylesheets/kit/markitup/images/bold.png +0 -0
  40. data/app/assets/stylesheets/kit/markitup/images/clean.png +0 -0
  41. data/app/assets/stylesheets/kit/markitup/images/h1.png +0 -0
  42. data/app/assets/stylesheets/kit/markitup/images/h2.png +0 -0
  43. data/app/assets/stylesheets/kit/markitup/images/h3.png +0 -0
  44. data/app/assets/stylesheets/kit/markitup/images/h4.png +0 -0
  45. data/app/assets/stylesheets/kit/markitup/images/h5.png +0 -0
  46. data/app/assets/stylesheets/kit/markitup/images/h6.png +0 -0
  47. data/app/assets/stylesheets/kit/markitup/images/handle.png +0 -0
  48. data/app/assets/stylesheets/kit/markitup/images/image.png +0 -0
  49. data/app/assets/stylesheets/kit/markitup/images/italic.png +0 -0
  50. data/app/assets/stylesheets/kit/markitup/images/link.png +0 -0
  51. data/app/assets/stylesheets/kit/markitup/images/list-bullet.png +0 -0
  52. data/app/assets/stylesheets/kit/markitup/images/list-item.png +0 -0
  53. data/app/assets/stylesheets/kit/markitup/images/list-numeric.png +0 -0
  54. data/app/assets/stylesheets/kit/markitup/images/menu.png +0 -0
  55. data/app/assets/stylesheets/kit/markitup/images/paragraph.png +0 -0
  56. data/app/assets/stylesheets/kit/markitup/images/picture.png +0 -0
  57. data/app/assets/stylesheets/kit/markitup/images/preview.png +0 -0
  58. data/app/assets/stylesheets/kit/markitup/images/stroke.png +0 -0
  59. data/app/assets/stylesheets/kit/markitup/images/submenu.png +0 -0
  60. data/app/assets/stylesheets/kit/markitup/style.css +0 -145
  61. 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");