PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 3.3.8
Pods – Custom Content Types and Fields v3.3.8
trunk 1.14.8 2.7.31.3 2.8.23.3 2.9.19.3 3.0.10.3 3.1.4.1 3.2.0 3.2.1 3.2.1.1 3.2.2 3.2.4 3.2.5 3.2.6 3.2.7 3.2.7.1 3.2.8 3.2.8.1 3.2.8.2 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9
pods / ui / js / codemirror / mode / xml / xml.js
pods / ui / js / codemirror / mode / xml Last commit date
index.html 2 years ago test.js 2 years ago xml.js 2 years ago
xml.js
418 lines
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 // Distributed under an MIT license: https://codemirror.net/5/LICENSE
3
4 (function(mod) {
5 if (typeof exports == "object" && typeof module == "object") // CommonJS
6 mod(require("../../lib/codemirror"));
7 else if (typeof define == "function" && define.amd) // AMD
8 define(["../../lib/codemirror"], mod);
9 else // Plain browser env
10 mod(CodeMirror);
11 })(function(CodeMirror) {
12 "use strict";
13
14 var htmlConfig = {
15 autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
16 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
17 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
18 'track': true, 'wbr': true, 'menuitem': true},
19 implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
20 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
21 'th': true, 'tr': true},
22 contextGrabbers: {
23 'dd': {'dd': true, 'dt': true},
24 'dt': {'dd': true, 'dt': true},
25 'li': {'li': true},
26 'option': {'option': true, 'optgroup': true},
27 'optgroup': {'optgroup': true},
28 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
29 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
30 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
31 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
32 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
33 'rp': {'rp': true, 'rt': true},
34 'rt': {'rp': true, 'rt': true},
35 'tbody': {'tbody': true, 'tfoot': true},
36 'td': {'td': true, 'th': true},
37 'tfoot': {'tbody': true},
38 'th': {'td': true, 'th': true},
39 'thead': {'tbody': true, 'tfoot': true},
40 'tr': {'tr': true}
41 },
42 doNotIndent: {"pre": true},
43 allowUnquoted: true,
44 allowMissing: true,
45 caseFold: true
46 }
47
48 var xmlConfig = {
49 autoSelfClosers: {},
50 implicitlyClosed: {},
51 contextGrabbers: {},
52 doNotIndent: {},
53 allowUnquoted: false,
54 allowMissing: false,
55 allowMissingTagName: false,
56 caseFold: false
57 }
58
59 CodeMirror.defineMode("xml", function(editorConf, config_) {
60 var indentUnit = editorConf.indentUnit
61 var config = {}
62 var defaults = config_.htmlMode ? htmlConfig : xmlConfig
63 for (var prop in defaults) config[prop] = defaults[prop]
64 for (var prop in config_) config[prop] = config_[prop]
65
66 // Return variables for tokenizers
67 var type, setStyle;
68
69 function inText(stream, state) {
70 function chain(parser) {
71 state.tokenize = parser;
72 return parser(stream, state);
73 }
74
75 var ch = stream.next();
76 if (ch == "<") {
77 if (stream.eat("!")) {
78 if (stream.eat("[")) {
79 if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
80 else return null;
81 } else if (stream.match("--")) {
82 return chain(inBlock("comment", "-->"));
83 } else if (stream.match("DOCTYPE", true, true)) {
84 stream.eatWhile(/[\w\._\-]/);
85 return chain(doctype(1));
86 } else {
87 return null;
88 }
89 } else if (stream.eat("?")) {
90 stream.eatWhile(/[\w\._\-]/);
91 state.tokenize = inBlock("meta", "?>");
92 return "meta";
93 } else {
94 type = stream.eat("/") ? "closeTag" : "openTag";
95 state.tokenize = inTag;
96 return "tag bracket";
97 }
98 } else if (ch == "&") {
99 var ok;
100 if (stream.eat("#")) {
101 if (stream.eat("x")) {
102 ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
103 } else {
104 ok = stream.eatWhile(/[\d]/) && stream.eat(";");
105 }
106 } else {
107 ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
108 }
109 return ok ? "atom" : "error";
110 } else {
111 stream.eatWhile(/[^&<]/);
112 return null;
113 }
114 }
115 inText.isInText = true;
116
117 function inTag(stream, state) {
118 var ch = stream.next();
119 if (ch == ">" || (ch == "/" && stream.eat(">"))) {
120 state.tokenize = inText;
121 type = ch == ">" ? "endTag" : "selfcloseTag";
122 return "tag bracket";
123 } else if (ch == "=") {
124 type = "equals";
125 return null;
126 } else if (ch == "<") {
127 state.tokenize = inText;
128 state.state = baseState;
129 state.tagName = state.tagStart = null;
130 var next = state.tokenize(stream, state);
131 return next ? next + " tag error" : "tag error";
132 } else if (/[\'\"]/.test(ch)) {
133 state.tokenize = inAttribute(ch);
134 state.stringStartCol = stream.column();
135 return state.tokenize(stream, state);
136 } else {
137 stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
138 return "word";
139 }
140 }
141
142 function inAttribute(quote) {
143 var closure = function(stream, state) {
144 while (!stream.eol()) {
145 if (stream.next() == quote) {
146 state.tokenize = inTag;
147 break;
148 }
149 }
150 return "string";
151 };
152 closure.isInAttribute = true;
153 return closure;
154 }
155
156 function inBlock(style, terminator) {
157 return function(stream, state) {
158 while (!stream.eol()) {
159 if (stream.match(terminator)) {
160 state.tokenize = inText;
161 break;
162 }
163 stream.next();
164 }
165 return style;
166 }
167 }
168
169 function doctype(depth) {
170 return function(stream, state) {
171 var ch;
172 while ((ch = stream.next()) != null) {
173 if (ch == "<") {
174 state.tokenize = doctype(depth + 1);
175 return state.tokenize(stream, state);
176 } else if (ch == ">") {
177 if (depth == 1) {
178 state.tokenize = inText;
179 break;
180 } else {
181 state.tokenize = doctype(depth - 1);
182 return state.tokenize(stream, state);
183 }
184 }
185 }
186 return "meta";
187 };
188 }
189
190 function lower(tagName) {
191 return tagName && tagName.toLowerCase();
192 }
193
194 function Context(state, tagName, startOfLine) {
195 this.prev = state.context;
196 this.tagName = tagName || "";
197 this.indent = state.indented;
198 this.startOfLine = startOfLine;
199 if (config.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
200 this.noIndent = true;
201 }
202 function popContext(state) {
203 if (state.context) state.context = state.context.prev;
204 }
205 function maybePopContext(state, nextTagName) {
206 var parentTagName;
207 while (true) {
208 if (!state.context) {
209 return;
210 }
211 parentTagName = state.context.tagName;
212 if (!config.contextGrabbers.hasOwnProperty(lower(parentTagName)) ||
213 !config.contextGrabbers[lower(parentTagName)].hasOwnProperty(lower(nextTagName))) {
214 return;
215 }
216 popContext(state);
217 }
218 }
219
220 function baseState(type, stream, state) {
221 if (type == "openTag") {
222 state.tagStart = stream.column();
223 return tagNameState;
224 } else if (type == "closeTag") {
225 return closeTagNameState;
226 } else {
227 return baseState;
228 }
229 }
230 function tagNameState(type, stream, state) {
231 if (type == "word") {
232 state.tagName = stream.current();
233 setStyle = "tag";
234 return attrState;
235 } else if (config.allowMissingTagName && type == "endTag") {
236 setStyle = "tag bracket";
237 return attrState(type, stream, state);
238 } else {
239 setStyle = "error";
240 return tagNameState;
241 }
242 }
243 function closeTagNameState(type, stream, state) {
244 if (type == "word") {
245 var tagName = stream.current();
246 if (state.context && state.context.tagName != tagName &&
247 config.implicitlyClosed.hasOwnProperty(lower(state.context.tagName)))
248 popContext(state);
249 if ((state.context && state.context.tagName == tagName) || config.matchClosing === false) {
250 setStyle = "tag";
251 return closeState;
252 } else {
253 setStyle = "tag error";
254 return closeStateErr;
255 }
256 } else if (config.allowMissingTagName && type == "endTag") {
257 setStyle = "tag bracket";
258 return closeState(type, stream, state);
259 } else {
260 setStyle = "error";
261 return closeStateErr;
262 }
263 }
264
265 function closeState(type, _stream, state) {
266 if (type != "endTag") {
267 setStyle = "error";
268 return closeState;
269 }
270 popContext(state);
271 return baseState;
272 }
273 function closeStateErr(type, stream, state) {
274 setStyle = "error";
275 return closeState(type, stream, state);
276 }
277
278 function attrState(type, _stream, state) {
279 if (type == "word") {
280 setStyle = "attribute";
281 return attrEqState;
282 } else if (type == "endTag" || type == "selfcloseTag") {
283 var tagName = state.tagName, tagStart = state.tagStart;
284 state.tagName = state.tagStart = null;
285 if (type == "selfcloseTag" ||
286 config.autoSelfClosers.hasOwnProperty(lower(tagName))) {
287 maybePopContext(state, tagName);
288 } else {
289 maybePopContext(state, tagName);
290 state.context = new Context(state, tagName, tagStart == state.indented);
291 }
292 return baseState;
293 }
294 setStyle = "error";
295 return attrState;
296 }
297 function attrEqState(type, stream, state) {
298 if (type == "equals") return attrValueState;
299 if (!config.allowMissing) setStyle = "error";
300 return attrState(type, stream, state);
301 }
302 function attrValueState(type, stream, state) {
303 if (type == "string") return attrContinuedState;
304 if (type == "word" && config.allowUnquoted) {setStyle = "string"; return attrState;}
305 setStyle = "error";
306 return attrState(type, stream, state);
307 }
308 function attrContinuedState(type, stream, state) {
309 if (type == "string") return attrContinuedState;
310 return attrState(type, stream, state);
311 }
312
313 return {
314 startState: function(baseIndent) {
315 var state = {tokenize: inText,
316 state: baseState,
317 indented: baseIndent || 0,
318 tagName: null, tagStart: null,
319 context: null}
320 if (baseIndent != null) state.baseIndent = baseIndent
321 return state
322 },
323
324 token: function(stream, state) {
325 if (!state.tagName && stream.sol())
326 state.indented = stream.indentation();
327
328 if (stream.eatSpace()) return null;
329 type = null;
330 var style = state.tokenize(stream, state);
331 if ((style || type) && style != "comment") {
332 setStyle = null;
333 state.state = state.state(type || style, stream, state);
334 if (setStyle)
335 style = setStyle == "error" ? style + " error" : setStyle;
336 }
337 return style;
338 },
339
340 indent: function(state, textAfter, fullLine) {
341 var context = state.context;
342 // Indent multi-line strings (e.g. css).
343 if (state.tokenize.isInAttribute) {
344 if (state.tagStart == state.indented)
345 return state.stringStartCol + 1;
346 else
347 return state.indented + indentUnit;
348 }
349 if (context && context.noIndent) return CodeMirror.Pass;
350 if (state.tokenize != inTag && state.tokenize != inText)
351 return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
352 // Indent the starts of attribute names.
353 if (state.tagName) {
354 if (config.multilineTagIndentPastTag !== false)
355 return state.tagStart + state.tagName.length + 2;
356 else
357 return state.tagStart + indentUnit * (config.multilineTagIndentFactor || 1);
358 }
359 if (config.alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
360 var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
361 if (tagAfter && tagAfter[1]) { // Closing tag spotted
362 while (context) {
363 if (context.tagName == tagAfter[2]) {
364 context = context.prev;
365 break;
366 } else if (config.implicitlyClosed.hasOwnProperty(lower(context.tagName))) {
367 context = context.prev;
368 } else {
369 break;
370 }
371 }
372 } else if (tagAfter) { // Opening tag spotted
373 while (context) {
374 var grabbers = config.contextGrabbers[lower(context.tagName)];
375 if (grabbers && grabbers.hasOwnProperty(lower(tagAfter[2])))
376 context = context.prev;
377 else
378 break;
379 }
380 }
381 while (context && context.prev && !context.startOfLine)
382 context = context.prev;
383 if (context) return context.indent + indentUnit;
384 else return state.baseIndent || 0;
385 },
386
387 electricInput: /<\/[\s\w:]+>$/,
388 blockCommentStart: "<!--",
389 blockCommentEnd: "-->",
390
391 configuration: config.htmlMode ? "html" : "xml",
392 helperType: config.htmlMode ? "html" : "xml",
393
394 skipAttribute: function(state) {
395 if (state.state == attrValueState)
396 state.state = attrState
397 },
398
399 xmlCurrentTag: function(state) {
400 return state.tagName ? {name: state.tagName, close: state.type == "closeTag"} : null
401 },
402
403 xmlCurrentContext: function(state) {
404 var context = []
405 for (var cx = state.context; cx; cx = cx.prev)
406 context.push(cx.tagName)
407 return context.reverse()
408 }
409 };
410 });
411
412 CodeMirror.defineMIME("text/xml", "xml");
413 CodeMirror.defineMIME("application/xml", "xml");
414 if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
415 CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
416
417 });
418