diff options
Diffstat (limited to 'plugins/LocalFilesEditor/codemirror/mode/xml')
-rw-r--r-- | plugins/LocalFilesEditor/codemirror/mode/xml/index.html | 42 | ||||
-rw-r--r-- | plugins/LocalFilesEditor/codemirror/mode/xml/xml.css | 7 | ||||
-rw-r--r-- | plugins/LocalFilesEditor/codemirror/mode/xml/xml.js | 206 |
3 files changed, 255 insertions, 0 deletions
diff --git a/plugins/LocalFilesEditor/codemirror/mode/xml/index.html b/plugins/LocalFilesEditor/codemirror/mode/xml/index.html new file mode 100644 index 000000000..5ad7c63fe --- /dev/null +++ b/plugins/LocalFilesEditor/codemirror/mode/xml/index.html @@ -0,0 +1,42 @@ +<!doctype html> +<html> + <head> + <title>CodeMirror 2: XML mode</title> + <link rel="stylesheet" href="../../lib/codemirror.css"> + <script src="../../lib/codemirror.js"></script> + <script src="xml.js"></script> + <link rel="stylesheet" href="xml.css"> + <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> + <link rel="stylesheet" href="../../css/docs.css"> + </head> + <body> + <h1>CodeMirror 2: XML mode</h1> + <form><textarea id="code" name="code"> +<html style="color: green"> + <!-- this is a comment --> + <head> + <title>HTML Example</title> + </head> + <body> + The indentation tries to be <em>somewhat &quot;do what + I mean&quot;</em>... but might not match your style. + </body> +</html> +</textarea></form> + <script> + var editor = CodeMirror.fromTextArea(document.getElementById("code"), {mode: {name: "xml", htmlMode: true}}); + </script> + <p>The XML mode supports two configuration parameters:</p> + <dl> + <dt><code>htmlMode (boolean)</code></dt> + <dd>This switches the mode to parse HTML instead of XML. This + means attributes do not have to be quoted, and some elements + (such as <code>br</code>) do not require a closing tag.</dd> + <dt><code>alignCDATA (boolean)</code></dt> + <dd>Setting this to true will force the opening tag of CDATA + blocks to not be indented.</dd> + </dl> + + <p><strong>MIME types defined:</strong> <code>application/xml</code>, <code>text/html</code>.</p> + </body> +</html> diff --git a/plugins/LocalFilesEditor/codemirror/mode/xml/xml.css b/plugins/LocalFilesEditor/codemirror/mode/xml/xml.css new file mode 100644 index 000000000..86845faa6 --- /dev/null +++ b/plugins/LocalFilesEditor/codemirror/mode/xml/xml.css @@ -0,0 +1,7 @@ +span.xml-tag {color: #a0b;} +span.xml-attribute {color: #281;} +span.xml-attname {color: #00f;} +span.xml-comment {color: #a70;} +span.xml-cdata {color: #48a;} +span.xml-processing {color: #999;} +span.xml-entity {color: #a22;} diff --git a/plugins/LocalFilesEditor/codemirror/mode/xml/xml.js b/plugins/LocalFilesEditor/codemirror/mode/xml/xml.js new file mode 100644 index 000000000..21da47b22 --- /dev/null +++ b/plugins/LocalFilesEditor/codemirror/mode/xml/xml.js @@ -0,0 +1,206 @@ +CodeMirror.defineMode("xml", function(config, parserConfig) { + var indentUnit = config.indentUnit; + var Kludges = parserConfig.htmlMode ? { + autoSelfClosers: {"br": true, "img": true, "hr": true, "link": true, "input": true, + "meta": true, "col": true, "frame": true, "base": true, "area": true}, + doNotIndent: {"pre": true, "!cdata": true}, + allowUnquoted: true + } : {autoSelfClosers: {}, doNotIndent: {"!cdata": true}, allowUnquoted: false}; + var alignCDATA = parserConfig.alignCDATA; + + // Return variables for tokenizers + var tagName, type; + + function inText(stream, state) { + function chain(parser) { + state.tokenize = parser; + return parser(stream, state); + } + + var ch = stream.next(); + if (ch == "<") { + if (stream.eat("!")) { + if (stream.eat("[")) { + if (stream.match("[CDATA[")) return chain(inBlock("xml-cdata", "]]>")); + else return null; + } + else if (stream.match("--")) return chain(inBlock("xml-comment", "-->")); + else if (stream.match("DOCTYPE")) { + stream.eatWhile(/[\w\._\-]/); + return chain(inBlock("xml-doctype", ">")); + } + else return null; + } + else if (stream.eat("?")) { + stream.eatWhile(/[\w\._\-]/); + state.tokenize = inBlock("xml-processing", "?>"); + return "xml-processing"; + } + else { + type = stream.eat("/") ? "closeTag" : "openTag"; + stream.eatSpace(); + tagName = ""; + var c; + while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c; + state.tokenize = inTag; + return "xml-tag"; + } + } + else if (ch == "&") { + stream.eatWhile(/[^;]/); + stream.eat(";"); + return "xml-entity"; + } + else { + stream.eatWhile(/[^&<]/); + return null; + } + } + + function inTag(stream, state) { + var ch = stream.next(); + if (ch == ">" || (ch == "/" && stream.eat(">"))) { + state.tokenize = inText; + type = ch == ">" ? "endTag" : "selfcloseTag"; + return "xml-tag"; + } + else if (ch == "=") { + type = "equals"; + return null; + } + else if (/[\'\"]/.test(ch)) { + state.tokenize = inAttribute(ch); + return state.tokenize(stream, state); + } + else { + stream.eatWhile(/[^\s\u00a0=<>\"\'\/?]/); + return "xml-word"; + } + } + + function inAttribute(quote) { + return function(stream, state) { + while (!stream.eol()) { + if (stream.next() == quote) { + state.tokenize = inTag; + break; + } + } + return "xml-attribute"; + }; + } + + function inBlock(style, terminator) { + return function(stream, state) { + while (!stream.eol()) { + if (stream.match(terminator)) { + state.tokenize = inText; + break; + } + stream.next(); + } + return style; + }; + } + + var curState, setStyle; + function pass() { + for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]); + } + function cont() { + pass.apply(null, arguments); + return true; + } + + function pushContext(tagName, startOfLine) { + var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent); + curState.context = { + prev: curState.context, + tagName: tagName, + indent: curState.indented, + startOfLine: startOfLine, + noIndent: noIndent + }; + } + function popContext() { + if (curState.context) curState.context = curState.context.prev; + } + + function element(type) { + if (type == "openTag") {curState.tagName = tagName; return cont(attributes, endtag(curState.startOfLine));} + else if (type == "closeTag") {popContext(); return cont(endclosetag);} + else if (type == "xml-cdata") { + if (!curState.context || curState.context.name != "!cdata") pushContext("!cdata"); + if (curState.tokenize == inText) popContext(); + return cont(); + } + else return cont(); + } + function endtag(startOfLine) { + return function(type) { + if (type == "selfcloseTag" || + (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))) + return cont(); + if (type == "endTag") {pushContext(curState.tagName, startOfLine); return cont();} + return cont(); + }; + } + function endclosetag(type) { + if (type == "endTag") return cont(); + return pass(); + } + + function attributes(type) { + if (type == "xml-word") {setStyle = "xml-attname"; return cont(attributes);} + if (type == "equals") return cont(attvalue, attributes); + return pass(); + } + function attvalue(type) { + if (type == "xml-word" && Kludges.allowUnquoted) {setStyle = "xml-attribute"; return cont();} + if (type == "xml-attribute") return cont(); + return pass(); + } + + return { + startState: function() { + return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null}; + }, + + token: function(stream, state) { + if (stream.sol()) { + state.startOfLine = true; + state.indented = stream.indentation(); + } + if (stream.eatSpace()) return null; + + setStyle = type = tagName = null; + var style = state.tokenize(stream, state); + if ((style || type) && style != "xml-comment") { + curState = state; + while (true) { + var comb = state.cc.pop() || element; + if (comb(type || style)) break; + } + } + state.startOfLine = false; + return setStyle || style; + }, + + indent: function(state, textAfter) { + var context = state.context; + if (context && context.noIndent) return 0; + if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0; + if (context && /^<\//.test(textAfter)) + context = context.prev; + while (context && !context.startOfLine) + context = context.prev; + if (context) return context.indent + indentUnit; + else return 0; + }, + + electricChars: "/" + }; +}); + +CodeMirror.defineMIME("application/xml", "xml"); +CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true}); |