File modules/editor/codemirror/mode/htmlmixed/htmlmixed.js
Last commit: Sun Dec 17 01:14:09 2017 +0100 Jan Dankert Integration eines weiteren Code-Editors: Codemirror. Demnächst müssen wir hier mal aufräumen und andere Editoren rauswerfen.
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 var defaultTags = { 15 script: [ 16 ["lang", /(javascript|babel)/i, "javascript"], 17 ["type", /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^module$|^$/i, "javascript"], 18 ["type", /./, "text/plain"], 19 [null, null, "javascript"] 20 ], 21 style: [ 22 ["lang", /^css$/i, "css"], 23 ["type", /^(text\/)?(x-)?(stylesheet|css)$/i, "css"], 24 ["type", /./, "text/plain"], 25 [null, null, "css"] 26 ] 27 }; 28 29 function maybeBackup(stream, pat, style) { 30 var cur = stream.current(), close = cur.search(pat); 31 if (close > -1) { 32 stream.backUp(cur.length - close); 33 } else if (cur.match(/<\/?$/)) { 34 stream.backUp(cur.length); 35 if (!stream.match(pat, false)) stream.match(cur); 36 } 37 return style; 38 } 39 40 var attrRegexpCache = {}; 41 function getAttrRegexp(attr) { 42 var regexp = attrRegexpCache[attr]; 43 if (regexp) return regexp; 44 return attrRegexpCache[attr] = new RegExp("\\s+" + attr + "\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*"); 45 } 46 47 function getAttrValue(text, attr) { 48 var match = text.match(getAttrRegexp(attr)) 49 return match ? /^\s*(.*?)\s*$/.exec(match[2])[1] : "" 50 } 51 52 function getTagRegexp(tagName, anchored) { 53 return new RegExp((anchored ? "^" : "") + "<\/\s*" + tagName + "\s*>", "i"); 54 } 55 56 function addTags(from, to) { 57 for (var tag in from) { 58 var dest = to[tag] || (to[tag] = []); 59 var source = from[tag]; 60 for (var i = source.length - 1; i >= 0; i--) 61 dest.unshift(source[i]) 62 } 63 } 64 65 function findMatchingMode(tagInfo, tagText) { 66 for (var i = 0; i < tagInfo.length; i++) { 67 var spec = tagInfo[i]; 68 if (!spec[0] || spec[1].test(getAttrValue(tagText, spec[0]))) return spec[2]; 69 } 70 } 71 72 CodeMirror.defineMode("htmlmixed", function (config, parserConfig) { 73 var htmlMode = CodeMirror.getMode(config, { 74 name: "xml", 75 htmlMode: true, 76 multilineTagIndentFactor: parserConfig.multilineTagIndentFactor, 77 multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag 78 }); 79 80 var tags = {}; 81 var configTags = parserConfig && parserConfig.tags, configScript = parserConfig && parserConfig.scriptTypes; 82 addTags(defaultTags, tags); 83 if (configTags) addTags(configTags, tags); 84 if (configScript) for (var i = configScript.length - 1; i >= 0; i--) 85 tags.script.unshift(["type", configScript[i].matches, configScript[i].mode]) 86 87 function html(stream, state) { 88 var style = htmlMode.token(stream, state.htmlState), tag = /\btag\b/.test(style), tagName 89 if (tag && !/[<>\s\/]/.test(stream.current()) && 90 (tagName = state.htmlState.tagName && state.htmlState.tagName.toLowerCase()) && 91 tags.hasOwnProperty(tagName)) { 92 state.inTag = tagName + " " 93 } else if (state.inTag && tag && />$/.test(stream.current())) { 94 var inTag = /^([\S]+) (.*)/.exec(state.inTag) 95 state.inTag = null 96 var modeSpec = stream.current() == ">" && findMatchingMode(tags[inTag[1]], inTag[2]) 97 var mode = CodeMirror.getMode(config, modeSpec) 98 var endTagA = getTagRegexp(inTag[1], true), endTag = getTagRegexp(inTag[1], false); 99 state.token = function (stream, state) { 100 if (stream.match(endTagA, false)) { 101 state.token = html; 102 state.localState = state.localMode = null; 103 return null; 104 } 105 return maybeBackup(stream, endTag, state.localMode.token(stream, state.localState)); 106 }; 107 state.localMode = mode; 108 state.localState = CodeMirror.startState(mode, htmlMode.indent(state.htmlState, "")); 109 } else if (state.inTag) { 110 state.inTag += stream.current() 111 if (stream.eol()) state.inTag += " " 112 } 113 return style; 114 }; 115 116 return { 117 startState: function () { 118 var state = CodeMirror.startState(htmlMode); 119 return {token: html, inTag: null, localMode: null, localState: null, htmlState: state}; 120 }, 121 122 copyState: function (state) { 123 var local; 124 if (state.localState) { 125 local = CodeMirror.copyState(state.localMode, state.localState); 126 } 127 return {token: state.token, inTag: state.inTag, 128 localMode: state.localMode, localState: local, 129 htmlState: CodeMirror.copyState(htmlMode, state.htmlState)}; 130 }, 131 132 token: function (stream, state) { 133 return state.token(stream, state); 134 }, 135 136 indent: function (state, textAfter, line) { 137 if (!state.localMode || /^\s*<\//.test(textAfter)) 138 return htmlMode.indent(state.htmlState, textAfter); 139 else if (state.localMode.indent) 140 return state.localMode.indent(state.localState, textAfter, line); 141 else 142 return CodeMirror.Pass; 143 }, 144 145 innerMode: function (state) { 146 return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode}; 147 } 148 }; 149 }, "xml", "javascript", "css"); 150 151 CodeMirror.defineMIME("text/html", "htmlmixed"); 152 });
Downloadmodules/editor/codemirror/mode/htmlmixed/htmlmixed.js
History Sun, 17 Dec 2017 01:14:09 +0100 Jan Dankert Integration eines weiteren Code-Editors: Codemirror. Demnächst müssen wir hier mal aufräumen und andere Editoren rauswerfen.