PageSourceSearch

https://labelstud.io/js/playground/xml.js

js labelstud.io collected 2026-10-02 04:06:22 UTC 13,691 bytes, 456 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.