8889841cindex.html000066600000005604150513762770006567 0ustar00 CodeMirror: HTML mixed mode

HTML mixed mode

The HTML mixed mode depends on the XML, JavaScript, and CSS modes.

It takes an optional mode configuration option, scriptTypes, which can be used to add custom behavior for specific <script type="..."> tags. If given, it should hold an array of {matches, mode} objects, where matches is a string or regexp that matches the script type, and mode is either null, for script types that should stay in HTML mode, or a mode spec corresponding to the mode that should be used for the script.

MIME types defined: text/html (redefined, only takes effect if you load this parser after the XML parser).

htmlmixed.js000066600000010031150513762770007111 0ustar00CodeMirror.defineMode("htmlmixed", function(config, parserConfig) { var htmlMode = CodeMirror.getMode(config, {name: "xml", htmlMode: true}); var cssMode = CodeMirror.getMode(config, "css"); var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes; scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i, mode: CodeMirror.getMode(config, "javascript")}); if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) { var conf = scriptTypesConf[i]; scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)}); } scriptTypes.push({matches: /./, mode: CodeMirror.getMode(config, "text/plain")}); function html(stream, state) { var tagName = state.htmlState.tagName; var style = htmlMode.token(stream, state.htmlState); if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") { // Script block: mode to change to depends on type attribute var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i); scriptType = scriptType ? scriptType[1] : ""; if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1); for (var i = 0; i < scriptTypes.length; ++i) { var tp = scriptTypes[i]; if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) { if (tp.mode) { state.token = script; state.localMode = tp.mode; state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, "")); } break; } } } else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") { state.token = css; state.localMode = cssMode; state.localState = cssMode.startState(htmlMode.indent(state.htmlState, "")); } return style; } function maybeBackup(stream, pat, style) { var cur = stream.current(); var close = cur.search(pat), m; if (close > -1) stream.backUp(cur.length - close); else if (m = cur.match(/<\/?$/)) { stream.backUp(cur.length); if (!stream.match(pat, false)) stream.match(cur); } return style; } function script(stream, state) { if (stream.match(/^<\/\s*script\s*>/i, false)) { state.token = html; state.localState = state.localMode = null; return html(stream, state); } return maybeBackup(stream, /<\/\s*script\s*>/, state.localMode.token(stream, state.localState)); } function css(stream, state) { if (stream.match(/^<\/\s*style\s*>/i, false)) { state.token = html; state.localState = state.localMode = null; return html(stream, state); } return maybeBackup(stream, /<\/\s*style\s*>/, cssMode.token(stream, state.localState)); } return { startState: function() { var state = htmlMode.startState(); return {token: html, localMode: null, localState: null, htmlState: state}; }, copyState: function(state) { if (state.localState) var local = CodeMirror.copyState(state.localMode, state.localState); return {token: state.token, localMode: state.localMode, localState: local, htmlState: CodeMirror.copyState(htmlMode, state.htmlState)}; }, token: function(stream, state) { return state.token(stream, state); }, indent: function(state, textAfter) { if (!state.localMode || /^\s*<\//.test(textAfter)) return htmlMode.indent(state.htmlState, textAfter); else if (state.localMode.indent) return state.localMode.indent(state.localState, textAfter); else return CodeMirror.Pass; }, innerMode: function(state) { return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode}; } }; }, "xml", "javascript", "css"); CodeMirror.defineMIME("text/html", "htmlmixed");