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