aboutsummaryrefslogtreecommitdiff
path: root/imports/codemirror/mode/xml
diff options
context:
space:
mode:
Diffstat (limited to 'imports/codemirror/mode/xml')
-rwxr-xr-ximports/codemirror/mode/xml/index.html44
-rwxr-xr-ximports/codemirror/mode/xml/xml.js252
2 files changed, 296 insertions, 0 deletions
diff --git a/imports/codemirror/mode/xml/index.html b/imports/codemirror/mode/xml/index.html
new file mode 100755
index 00000000..3b6d6af1
--- /dev/null
+++ b/imports/codemirror/mode/xml/index.html
@@ -0,0 +1,44 @@
1<!doctype html>
2<html>
3 <head>
4 <title>CodeMirror: XML mode</title>
5 <link rel="stylesheet" href="../../lib/codemirror.css">
6 <script src="../../lib/codemirror.js"></script>
7 <script src="xml.js"></script>
8 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
9 <link rel="stylesheet" href="../../doc/docs.css">
10 </head>
11 <body>
12 <h1>CodeMirror: XML mode</h1>
13 <form><textarea id="code" name="code">
14&lt;html style="color: green"&gt;
15 &lt;!-- this is a comment --&gt;
16 &lt;head&gt;
17 &lt;title&gt;HTML Example&lt;/title&gt;
18 &lt;/head&gt;
19 &lt;body&gt;
20 The indentation tries to be &lt;em&gt;somewhat &amp;quot;do what
21 I mean&amp;quot;&lt;/em&gt;... but might not match your style.
22 &lt;/body&gt;
23&lt;/html&gt;
24</textarea></form>
25 <script>
26 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
27 mode: {name: "xml", alignCDATA: true},
28 lineNumbers: true
29 });
30 </script>
31 <p>The XML mode supports two configuration parameters:</p>
32 <dl>
33 <dt><code>htmlMode (boolean)</code></dt>
34 <dd>This switches the mode to parse HTML instead of XML. This
35 means attributes do not have to be quoted, and some elements
36 (such as <code>br</code>) do not require a closing tag.</dd>
37 <dt><code>alignCDATA (boolean)</code></dt>
38 <dd>Setting this to true will force the opening tag of CDATA
39 blocks to not be indented.</dd>
40 </dl>
41
42 <p><strong>MIME types defined:</strong> <code>application/xml</code>, <code>text/html</code>.</p>
43 </body>
44</html>
diff --git a/imports/codemirror/mode/xml/xml.js b/imports/codemirror/mode/xml/xml.js
new file mode 100755
index 00000000..71e0e2b0
--- /dev/null
+++ b/imports/codemirror/mode/xml/xml.js
@@ -0,0 +1,252 @@
1CodeMirror.defineMode("xml", function(config, parserConfig) {
2 var indentUnit = config.indentUnit;
3 var Kludges = parserConfig.htmlMode ? {
4 autoSelfClosers: {"br": true, "img": true, "hr": true, "link": true, "input": true,
5 "meta": true, "col": true, "frame": true, "base": true, "area": true},
6 doNotIndent: {"pre": true},
7 allowUnquoted: true
8 } : {autoSelfClosers: {}, doNotIndent: {}, allowUnquoted: false};
9 var alignCDATA = parserConfig.alignCDATA;
10
11 // Return variables for tokenizers
12 var tagName, type;
13
14 function inText(stream, state) {
15 function chain(parser) {
16 state.tokenize = parser;
17 return parser(stream, state);
18 }
19
20 var ch = stream.next();
21 if (ch == "<") {
22 if (stream.eat("!")) {
23 if (stream.eat("[")) {
24 if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
25 else return null;
26 }
27 else if (stream.match("--")) return chain(inBlock("comment", "-->"));
28 else if (stream.match("DOCTYPE", true, true)) {
29 stream.eatWhile(/[\w\._\-]/);
30 return chain(doctype(1));
31 }
32 else return null;
33 }
34 else if (stream.eat("?")) {
35 stream.eatWhile(/[\w\._\-]/);
36 state.tokenize = inBlock("meta", "?>");
37 return "meta";
38 }
39 else {
40 type = stream.eat("/") ? "closeTag" : "openTag";
41 stream.eatSpace();
42 tagName = "";
43 var c;
44 while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c;
45 state.tokenize = inTag;
46 return "tag";
47 }
48 }
49 else if (ch == "&") {
50 stream.eatWhile(/[^;]/);
51 stream.eat(";");
52 return "atom";
53 }
54 else {
55 stream.eatWhile(/[^&<]/);
56 return null;
57 }
58 }
59
60 function inTag(stream, state) {
61 var ch = stream.next();
62 if (ch == ">" || (ch == "/" && stream.eat(">"))) {
63 state.tokenize = inText;
64 type = ch == ">" ? "endTag" : "selfcloseTag";
65 return "tag";
66 }
67 else if (ch == "=") {
68 type = "equals";
69 return null;
70 }
71 else if (/[\'\"]/.test(ch)) {
72 state.tokenize = inAttribute(ch);
73 return state.tokenize(stream, state);
74 }
75 else {
76 stream.eatWhile(/[^\s\u00a0=<>\"\'\/?]/);
77 return "word";
78 }
79 }
80
81 function inAttribute(quote) {
82 return function(stream, state) {
83 while (!stream.eol()) {
84 if (stream.next() == quote) {
85 state.tokenize = inTag;
86 break;
87 }
88 }
89 return "string";
90 };
91 }
92
93 function inBlock(style, terminator) {
94 return function(stream, state) {
95 while (!stream.eol()) {
96 if (stream.match(terminator)) {
97 state.tokenize = inText;
98 break;
99 }
100 stream.next();
101 }
102 return style;
103 };
104 }
105 function doctype(depth) {
106 return function(stream, state) {
107 var ch;
108 while ((ch = stream.next()) != null) {
109 if (ch == "<") {
110 state.tokenize = doctype(depth + 1);
111 return state.tokenize(stream, state);
112 } else if (ch == ">") {
113 if (depth == 1) {
114 state.tokenize = inText;
115 break;
116 } else {
117 state.tokenize = doctype(depth - 1);
118 return state.tokenize(stream, state);
119 }
120 }
121 }
122 return "meta";
123 };
124 }
125
126 var curState, setStyle;
127 function pass() {
128 for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);
129 }
130 function cont() {
131 pass.apply(null, arguments);
132 return true;
133 }
134
135 function pushContext(tagName, startOfLine) {
136 var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent);
137 curState.context = {
138 prev: curState.context,
139 tagName: tagName,
140 indent: curState.indented,
141 startOfLine: startOfLine,
142 noIndent: noIndent
143 };
144 }
145 function popContext() {
146 if (curState.context) curState.context = curState.context.prev;
147 }
148
149 function element(type) {
150 if (type == "openTag") {
151 curState.tagName = tagName;
152 return cont(attributes, endtag(curState.startOfLine));
153 } else if (type == "closeTag") {
154 var err = false;
155 if (curState.context) {
156 err = curState.context.tagName != tagName;
157 } else {
158 err = true;
159 }
160 if (err) setStyle = "error";
161 return cont(endclosetag(err));
162 }
163 return cont();
164 }
165 function endtag(startOfLine) {
166 return function(type) {
167 if (type == "selfcloseTag" ||
168 (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase())))
169 return cont();
170 if (type == "endTag") {pushContext(curState.tagName, startOfLine); return cont();}
171 return cont();
172 };
173 }
174 function endclosetag(err) {
175 return function(type) {
176 if (err) setStyle = "error";
177 if (type == "endTag") { popContext(); return cont(); }
178 setStyle = "error";
179 return cont(arguments.callee);
180 }
181 }
182
183 function attributes(type) {
184 if (type == "word") {setStyle = "attribute"; return cont(attributes);}
185 if (type == "equals") return cont(attvalue, attributes);
186 if (type == "string") {setStyle = "error"; return cont(attributes);}
187 return pass();
188 }
189 function attvalue(type) {
190 if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();}
191 if (type == "string") return cont(attvaluemaybe);