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 (style == "tag" && 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[0].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"); |
---|