shop.balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

xml.js (11607B)


      1 CodeMirror.defineMode("xml", function(config, parserConfig) {
      2   var indentUnit = config.indentUnit;
      3   var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;
      4   var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag || true;
      5 
      6   var Kludges = parserConfig.htmlMode ? {
      7     autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
      8                       'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
      9                       'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
     10                       'track': true, 'wbr': true},
     11     implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
     12                        'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
     13                        'th': true, 'tr': true},
     14     contextGrabbers: {
     15       'dd': {'dd': true, 'dt': true},
     16       'dt': {'dd': true, 'dt': true},
     17       'li': {'li': true},
     18       'option': {'option': true, 'optgroup': true},
     19       'optgroup': {'optgroup': true},
     20       'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
     21             'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
     22             'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
     23             'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
     24             'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
     25       'rp': {'rp': true, 'rt': true},
     26       'rt': {'rp': true, 'rt': true},
     27       'tbody': {'tbody': true, 'tfoot': true},
     28       'td': {'td': true, 'th': true},
     29       'tfoot': {'tbody': true},
     30       'th': {'td': true, 'th': true},
     31       'thead': {'tbody': true, 'tfoot': true},
     32       'tr': {'tr': true}
     33     },
     34     doNotIndent: {"pre": true},
     35     allowUnquoted: true,
     36     allowMissing: true
     37   } : {
     38     autoSelfClosers: {},
     39     implicitlyClosed: {},
     40     contextGrabbers: {},
     41     doNotIndent: {},
     42     allowUnquoted: false,
     43     allowMissing: false
     44   };
     45   var alignCDATA = parserConfig.alignCDATA;
     46 
     47   // Return variables for tokenizers
     48   var tagName, type;
     49 
     50   function inText(stream, state) {
     51     function chain(parser) {
     52       state.tokenize = parser;
     53       return parser(stream, state);
     54     }
     55 
     56     var ch = stream.next();
     57     if (ch == "<") {
     58       if (stream.eat("!")) {
     59         if (stream.eat("[")) {
     60           if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
     61           else return null;
     62         } else if (stream.match("--")) {
     63           return chain(inBlock("comment", "-->"));
     64         } else if (stream.match("DOCTYPE", true, true)) {
     65           stream.eatWhile(/[\w\._\-]/);
     66           return chain(doctype(1));
     67         } else {
     68           return null;
     69         }
     70       } else if (stream.eat("?")) {
     71         stream.eatWhile(/[\w\._\-]/);
     72         state.tokenize = inBlock("meta", "?>");
     73         return "meta";
     74       } else {
     75         var isClose = stream.eat("/");
     76         tagName = "";
     77         var c;
     78         while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c;
     79         if (!tagName) return "tag error";
     80         type = isClose ? "closeTag" : "openTag";
     81         state.tokenize = inTag;
     82         return "tag";
     83       }
     84     } else if (ch == "&") {
     85       var ok;
     86       if (stream.eat("#")) {
     87         if (stream.eat("x")) {
     88           ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
     89         } else {
     90           ok = stream.eatWhile(/[\d]/) && stream.eat(";");
     91         }
     92       } else {
     93         ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
     94       }
     95       return ok ? "atom" : "error";
     96     } else {
     97       stream.eatWhile(/[^&<]/);
     98       return null;
     99     }
    100   }
    101 
    102   function inTag(stream, state) {
    103     var ch = stream.next();
    104     if (ch == ">" || (ch == "/" && stream.eat(">"))) {
    105       state.tokenize = inText;
    106       type = ch == ">" ? "endTag" : "selfcloseTag";
    107       return "tag";
    108     } else if (ch == "=") {
    109       type = "equals";
    110       return null;
    111     } else if (ch == "<") {
    112       state.tokenize = inText;
    113       var next = state.tokenize(stream, state);
    114       return next ? next + " error" : "error";
    115     } else if (/[\'\"]/.test(ch)) {
    116       state.tokenize = inAttribute(ch);
    117       state.stringStartCol = stream.column();
    118       return state.tokenize(stream, state);
    119     } else {
    120       stream.eatWhile(/[^\s\u00a0=<>\"\']/);
    121       return "word";
    122     }
    123   }
    124 
    125   function inAttribute(quote) {
    126     var closure = function(stream, state) {
    127       while (!stream.eol()) {
    128         if (stream.next() == quote) {
    129           state.tokenize = inTag;
    130           break;
    131         }
    132       }
    133       return "string";
    134     };
    135     closure.isInAttribute = true;
    136     return closure;
    137   }
    138 
    139   function inBlock(style, terminator) {
    140     return function(stream, state) {
    141       while (!stream.eol()) {
    142         if (stream.match(terminator)) {
    143           state.tokenize = inText;
    144           break;
    145         }
    146         stream.next();
    147       }
    148       return style;
    149     };
    150   }
    151   function doctype(depth) {
    152     return function(stream, state) {
    153       var ch;
    154       while ((ch = stream.next()) != null) {
    155         if (ch == "<") {
    156           state.tokenize = doctype(depth + 1);
    157           return state.tokenize(stream, state);
    158         } else if (ch == ">") {
    159           if (depth == 1) {
    160             state.tokenize = inText;
    161             break;
    162           } else {
    163             state.tokenize = doctype(depth - 1);
    164             return state.tokenize(stream, state);
    165           }
    166         }
    167       }
    168       return "meta";
    169     };
    170   }
    171 
    172   var curState, curStream, setStyle;
    173   function pass() {
    174     for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);
    175   }
    176   function cont() {
    177     pass.apply(null, arguments);
    178     return true;
    179   }
    180 
    181   function pushContext(tagName, startOfLine) {
    182     var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent);
    183     curState.context = {
    184       prev: curState.context,
    185       tagName: tagName,
    186       indent: curState.indented,
    187       startOfLine: startOfLine,
    188       noIndent: noIndent
    189     };
    190   }
    191   function popContext() {
    192     if (curState.context) curState.context = curState.context.prev;
    193   }
    194 
    195   function element(type) {
    196     if (type == "openTag") {
    197       curState.tagName = tagName;
    198       curState.tagStart = curStream.column();
    199       return cont(attributes, endtag(curState.startOfLine));
    200     } else if (type == "closeTag") {
    201       var err = false;
    202       if (curState.context) {
    203         if (curState.context.tagName != tagName) {
    204           if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) {
    205             popContext();
    206           }
    207           err = !curState.context || curState.context.tagName != tagName;
    208         }
    209       } else {
    210         err = true;
    211       }
    212       if (err) setStyle = "error";
    213       return cont(endclosetag(err));
    214     }
    215     return cont();
    216   }
    217   function endtag(startOfLine) {
    218     return function(type) {
    219       var tagName = curState.tagName;
    220       curState.tagName = curState.tagStart = null;
    221       if (type == "selfcloseTag" ||
    222           (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(tagName.toLowerCase()))) {
    223         maybePopContext(tagName.toLowerCase());
    224         return cont();
    225       }
    226       if (type == "endTag") {
    227         maybePopContext(tagName.toLowerCase());
    228         pushContext(tagName, startOfLine);
    229         return cont();
    230       }
    231       return cont();
    232     };
    233   }
    234   function endclosetag(err) {
    235     return function(type) {
    236       if (err) setStyle = "error";
    237       if (type == "endTag") { popContext(); return cont(); }
    238       setStyle = "error";
    239       return cont(arguments.callee);
    240     };
    241   }
    242   function maybePopContext(nextTagName) {
    243     var parentTagName;
    244     while (true) {
    245       if (!curState.context) {
    246         return;
    247       }
    248       parentTagName = curState.context.tagName.toLowerCase();
    249       if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
    250           !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
    251         return;
    252       }
    253       popContext();
    254     }
    255   }
    256 
    257   function attributes(type) {
    258     if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);}
    259     if (type == "endTag" || type == "selfcloseTag") return pass();
    260     setStyle = "error";
    261     return cont(attributes);
    262   }
    263   function attribute(type) {
    264     if (type == "equals") return cont(attvalue, attributes);
    265     if (!Kludges.allowMissing) setStyle = "error";
    266     else if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);}
    267     return (type == "endTag" || type == "selfcloseTag") ? pass() : cont();
    268   }
    269   function attvalue(type) {
    270     if (type == "string") return cont(attvaluemaybe);
    271     if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();}
    272     setStyle = "error";
    273     return (type == "endTag" || type == "selfCloseTag") ? pass() : cont();
    274   }
    275   function attvaluemaybe(type) {
    276     if (type == "string") return cont(attvaluemaybe);
    277     else return pass();
    278   }
    279 
    280   return {
    281     startState: function() {
    282       return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, tagStart: null, context: null};
    283     },
    284 
    285     token: function(stream, state) {
    286       if (!state.tagName && stream.sol()) {
    287         state.startOfLine = true;
    288         state.indented = stream.indentation();
    289       }
    290       if (stream.eatSpace()) return null;
    291 
    292       setStyle = type = tagName = null;
    293       var style = state.tokenize(stream, state);
    294       state.type = type;
    295       if ((style || type) && style != "comment") {
    296         curState = state; curStream = stream;
    297         while (true) {
    298           var comb = state.cc.pop() || element;
    299           if (comb(type || style)) break;
    300         }
    301       }
    302       state.startOfLine = false;
    303       if (setStyle)
    304         style = setStyle == "error" ? style + " error" : setStyle;
    305       return style;
    306     },
    307 
    308     indent: function(state, textAfter, fullLine) {
    309       var context = state.context;
    310       // Indent multi-line strings (e.g. css).
    311       if (state.tokenize.isInAttribute) {
    312         return state.stringStartCol + 1;
    313       }
    314       if ((state.tokenize != inTag && state.tokenize != inText) ||
    315           context && context.noIndent)
    316         return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
    317       // Indent the starts of attribute names.
    318       if (state.tagName) {
    319         if (multilineTagIndentPastTag)
    320           return state.tagStart + state.tagName.length + 2;
    321         else
    322           return state.tagStart + indentUnit * multilineTagIndentFactor;
    323       }
    324       if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
    325       if (context && /^<\//.test(textAfter))
    326         context = context.prev;
    327       while (context && !context.startOfLine)
    328         context = context.prev;
    329       if (context) return context.indent + indentUnit;
    330       else return 0;
    331     },
    332 
    333     electricChars: "/",
    334     blockCommentStart: "<!--",
    335     blockCommentEnd: "-->",
    336 
    337     configuration: parserConfig.htmlMode ? "html" : "xml",
    338     helperType: parserConfig.htmlMode ? "html" : "xml"
    339   };
    340 });
    341 
    342 CodeMirror.defineMIME("text/xml", "xml");
    343 CodeMirror.defineMIME("application/xml", "xml");
    344 if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
    345   CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});