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