htmlmixed.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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. function html(stream, state) {
  6. var style = htmlMode.token(stream, state.htmlState);
  7. if (/(?:^|\s)tag(?:\s|$)/.test(style) && stream.current() == ">" && state.htmlState.context) {
  8. if (/^script$/i.test(state.htmlState.context.tagName)) {
  9. state.token = javascript;
  10. state.localState = jsMode.startState(htmlMode.indent(state.htmlState, ""));
  11. }
  12. else if (/^style$/i.test(state.htmlState.context.tagName)) {
  13. state.token = css;
  14. state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
  15. }
  16. }
  17. return style;
  18. }
  19. function maybeBackup(stream, pat, style) {
  20. var cur = stream.current();
  21. var close = cur.search(pat), m;
  22. if (close > -1) stream.backUp(cur.length - close);
  23. else if (m = cur.match(/<\/?$/)) {
  24. stream.backUp(cur.length);
  25. if (!stream.match(pat, false)) stream.match(cur[0]);
  26. }
  27. return style;
  28. }
  29. function javascript(stream, state) {
  30. if (stream.match(/^<\/\s*script\s*>/i, false)) {
  31. state.token = html;
  32. state.localState = null;
  33. return html(stream, state);
  34. }
  35. return maybeBackup(stream, /<\/\s*script\s*>/,
  36. jsMode.token(stream, state.localState));
  37. }
  38. function css(stream, state) {
  39. if (stream.match(/^<\/\s*style\s*>/i, false)) {
  40. state.token = html;
  41. state.localState = null;
  42. return html(stream, state);
  43. }
  44. return maybeBackup(stream, /<\/\s*style\s*>/,
  45. cssMode.token(stream, state.localState));
  46. }
  47. return {
  48. startState: function() {
  49. var state = htmlMode.startState();
  50. return {token: html, localState: null, mode: "html", htmlState: state};
  51. },
  52. copyState: function(state) {
  53. if (state.localState)
  54. var local = CodeMirror.copyState(state.token == css ? cssMode : jsMode, state.localState);
  55. return {token: state.token, localState: local, mode: state.mode,
  56. htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
  57. },
  58. token: function(stream, state) {
  59. return state.token(stream, state);
  60. },
  61. indent: function(state, textAfter) {
  62. if (state.token == html || /^\s*<\//.test(textAfter))
  63. return htmlMode.indent(state.htmlState, textAfter);
  64. else if (state.token == javascript)
  65. return jsMode.indent(state.localState, textAfter);
  66. else
  67. return cssMode.indent(state.localState, textAfter);
  68. },
  69. electricChars: "/{}:",
  70. innerMode: function(state) {
  71. var mode = state.token == html ? htmlMode : state.token == javascript ? jsMode : cssMode;
  72. return {state: state.localState || state.htmlState, mode: mode};
  73. }
  74. };
  75. }, "xml", "javascript", "css");
  76. CodeMirror.defineMIME("text/html", "htmlmixed");