| 776 |
lars |
1 |
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
|
2 |
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
|
3 |
|
|
|
4 |
(function(mod) {
|
|
|
5 |
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
|
6 |
mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css"));
|
|
|
7 |
else if (typeof define == "function" && define.amd) // AMD
|
|
|
8 |
define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod);
|
|
|
9 |
else // Plain browser env
|
|
|
10 |
mod(CodeMirror);
|
|
|
11 |
})(function(CodeMirror) {
|
|
|
12 |
"use strict";
|
|
|
13 |
|
|
|
14 |
CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
|
|
|
15 |
var htmlMode = CodeMirror.getMode(config, {name: "xml",
|
|
|
16 |
htmlMode: true,
|
|
|
17 |
multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
|
|
|
18 |
multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag});
|
|
|
19 |
var cssMode = CodeMirror.getMode(config, "css");
|
|
|
20 |
|
|
|
21 |
var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes;
|
|
|
22 |
scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i,
|
|
|
23 |
mode: CodeMirror.getMode(config, "javascript")});
|
|
|
24 |
if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) {
|
|
|
25 |
var conf = scriptTypesConf[i];
|
|
|
26 |
scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)});
|
|
|
27 |
}
|
|
|
28 |
scriptTypes.push({matches: /./,
|
|
|
29 |
mode: CodeMirror.getMode(config, "text/plain")});
|
|
|
30 |
|
|
|
31 |
function html(stream, state) {
|
|
|
32 |
var tagName = state.htmlState.tagName;
|
|
|
33 |
if (tagName) tagName = tagName.toLowerCase();
|
|
|
34 |
var style = htmlMode.token(stream, state.htmlState);
|
|
|
35 |
if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") {
|
|
|
36 |
// Script block: mode to change to depends on type attribute
|
|
|
37 |
var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i);
|
|
|
38 |
scriptType = scriptType ? scriptType[1] : "";
|
|
|
39 |
if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1);
|
|
|
40 |
for (var i = 0; i < scriptTypes.length; ++i) {
|
|
|
41 |
var tp = scriptTypes[i];
|
|
|
42 |
if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) {
|
|
|
43 |
if (tp.mode) {
|
|
|
44 |
state.token = script;
|
|
|
45 |
state.localMode = tp.mode;
|
|
|
46 |
state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, ""));
|
|
|
47 |
}
|
|
|
48 |
break;
|
|
|
49 |
}
|
|
|
50 |
}
|
|
|
51 |
} else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") {
|
|
|
52 |
state.token = css;
|
|
|
53 |
state.localMode = cssMode;
|
|
|
54 |
state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
|
|
|
55 |
}
|
|
|
56 |
return style;
|
|
|
57 |
}
|
|
|
58 |
function maybeBackup(stream, pat, style) {
|
|
|
59 |
var cur = stream.current();
|
|
|
60 |
var close = cur.search(pat);
|
|
|
61 |
if (close > -1) stream.backUp(cur.length - close);
|
|
|
62 |
else if (cur.match(/<\/?$/)) {
|
|
|
63 |
stream.backUp(cur.length);
|
|
|
64 |
if (!stream.match(pat, false)) stream.match(cur);
|
|
|
65 |
}
|
|
|
66 |
return style;
|
|
|
67 |
}
|
|
|
68 |
function script(stream, state) {
|
|
|
69 |
if (stream.match(/^<\/\s*script\s*>/i, false)) {
|
|
|
70 |
state.token = html;
|
|
|
71 |
state.localState = state.localMode = null;
|
|
|
72 |
return null;
|
|
|
73 |
}
|
|
|
74 |
return maybeBackup(stream, /<\/\s*script\s*>/,
|
|
|
75 |
state.localMode.token(stream, state.localState));
|
|
|
76 |
}
|
|
|
77 |
function css(stream, state) {
|
|
|
78 |
if (stream.match(/^<\/\s*style\s*>/i, false)) {
|
|
|
79 |
state.token = html;
|
|
|
80 |
state.localState = state.localMode = null;
|
|
|
81 |
return null;
|
|
|
82 |
}
|
|
|
83 |
return maybeBackup(stream, /<\/\s*style\s*>/,
|
|
|
84 |
cssMode.token(stream, state.localState));
|
|
|
85 |
}
|
|
|
86 |
|
|
|
87 |
return {
|
|
|
88 |
startState: function() {
|
|
|
89 |
var state = htmlMode.startState();
|
|
|
90 |
return {token: html, localMode: null, localState: null, htmlState: state};
|
|
|
91 |
},
|
|
|
92 |
|
|
|
93 |
copyState: function(state) {
|
|
|
94 |
if (state.localState)
|
|
|
95 |
var local = CodeMirror.copyState(state.localMode, state.localState);
|
|
|
96 |
return {token: state.token, localMode: state.localMode, localState: local,
|
|
|
97 |
htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
|
|
|
98 |
},
|
|
|
99 |
|
|
|
100 |
token: function(stream, state) {
|
|
|
101 |
return state.token(stream, state);
|
|
|
102 |
},
|
|
|
103 |
|
|
|
104 |
indent: function(state, textAfter) {
|
|
|
105 |
if (!state.localMode || /^\s*<\//.test(textAfter))
|
|
|
106 |
return htmlMode.indent(state.htmlState, textAfter);
|
|
|
107 |
else if (state.localMode.indent)
|
|
|
108 |
return state.localMode.indent(state.localState, textAfter);
|
|
|
109 |
else
|
|
|
110 |
return CodeMirror.Pass;
|
|
|
111 |
},
|
|
|
112 |
|
|
|
113 |
innerMode: function(state) {
|
|
|
114 |
return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
|
|
|
115 |
}
|
|
|
116 |
};
|
|
|
117 |
}, "xml", "javascript", "css");
|
|
|
118 |
|
|
|
119 |
CodeMirror.defineMIME("text/html", "htmlmixed");
|
|
|
120 |
|
|
|
121 |
});
|