[ Index ]

MailPress 7.2

[ Index ]     [ Classes ]     [ Functions ]     [ Variables ]     [ Constants ]     [ Statistics ]    

title

Body

[close]

/mp-includes/js/codemirror/js/ -> parsexml_genuine.js (source)

   1  /* This file defines an XML parser, with a few kludges to make it
   2   * useable for HTML. autoSelfClosers defines a set of tag names that
   3   * are expected to not have a closing tag, and doNotIndent specifies
   4   * the tags inside of which no indentation should happen (see Config
   5   * object). These can be disabled by passing the editor an object like
   6   * {useHTMLKludges: false} as parserConfig option.
   7   */
   8  
   9  var XMLParser = Editor.Parser = (function() {
  10    var Kludges = {
  11      autoSelfClosers: {"br": true, "img": true, "hr": true, "link": true, "input": true,
  12                        "meta": true, "col": true, "frame": true, "base": true, "area": true},
  13      doNotIndent: {"pre": true, "!cdata": true}
  14    };
  15    var NoKludges = {autoSelfClosers: {}, doNotIndent: {"!cdata": true}};
  16    var UseKludges = Kludges;
  17    var alignCDATA = false;
  18  
  19    // Simple stateful tokenizer for XML documents. Returns a
  20    // MochiKit-style iterator, with a state property that contains a
  21    // function encapsulating the current state. See tokenize.js.
  22    var tokenizeXML = (function() {
  23      function inText(source, setState) {
  24        var ch = source.next();
  25        if (ch == "<") {
  26          if (source.equals("!")) {
  27            source.next();
  28            if (source.equals("[")) {
  29              if (source.lookAhead("[CDATA[", true)) {
  30                setState(inBlock("xml-cdata", "]]>"));
  31                return null;
  32              }
  33              else {
  34                return "xml-text";
  35              }
  36            }
  37            else if (source.lookAhead("--", true)) {
  38              setState(inBlock("xml-comment", "-->"));
  39              return null;
  40            }
  41            else {
  42              return "xml-text";
  43            }
  44          }
  45          else if (source.equals("?")) {
  46            source.next();
  47            source.nextWhileMatches(/[\w\._\-]/);
  48            setState(inBlock("xml-processing", "?>"));
  49            return "xml-processing";
  50          }
  51          else {
  52            if (source.equals("/")) source.next();
  53            setState(inTag);
  54            return "xml-punctuation";
  55          }
  56        }
  57        else if (ch == "&") {
  58          while (!source.endOfLine()) {
  59            if (source.next() == ";")
  60              break;
  61          }
  62          return "xml-entity";
  63        }
  64        else {
  65          source.nextWhileMatches(/[^&<\n]/);
  66          return "xml-text";
  67        }
  68      }
  69  
  70      function inTag(source, setState) {
  71        var ch = source.next();
  72        if (ch == ">") {
  73          setState(inText);
  74          return "xml-punctuation";
  75        }
  76        else if (/[?\/]/.test(ch) && source.equals(">")) {
  77          source.next();
  78          setState(inText);
  79          return "xml-punctuation";
  80        }
  81        else if (ch == "=") {
  82          return "xml-punctuation";
  83        }
  84        else if (/[\'\"]/.test(ch)) {
  85          setState(inAttribute(ch));
  86          return null;
  87        }
  88        else {
  89          source.nextWhileMatches(/[^\s\u00a0=<>\"\'\/?]/);
  90          return "xml-name";
  91        }
  92      }
  93  
  94      function inAttribute(quote) {
  95        return function(source, setState) {
  96          while (!source.endOfLine()) {
  97            if (source.next() == quote) {
  98              setState(inTag);
  99              break;
 100            }
 101          }
 102          return "xml-attribute";
 103        };
 104      }
 105  
 106      function inBlock(style, terminator) {
 107        return function(source, setState) {
 108          while (!source.endOfLine()) {
 109            if (source.lookAhead(terminator, true)) {
 110              setState(inText);
 111              break;
 112            }
 113            source.next();
 114          }
 115          return style;
 116        };
 117      }
 118  
 119      return function(source, startState) {
 120        return tokenizer(source, startState || inText);
 121      };
 122    })();
 123  
 124    // The parser. The structure of this function largely follows that of
 125    // parseJavaScript in parsejavascript.js (there is actually a bit more
 126    // shared code than I'd like), but it is quite a bit simpler.
 127    function parseXML(source) {
 128      var tokens = tokenizeXML(source), token;
 129      var cc = [base];
 130      var tokenNr = 0, indented = 0;
 131      var currentTag = null, context = null;
 132      var consume;
 133      
 134      function push(fs) {
 135        for (var i = fs.length - 1; i >= 0; i--)
 136          cc.push(fs[i]);
 137      }
 138      function cont() {
 139        push(arguments);
 140        consume = true;
 141      }
 142      function pass() {
 143        push(arguments);
 144        consume = false;
 145      }
 146  
 147      function markErr() {
 148        token.style += " xml-error";
 149      }
 150      function expect(text) {
 151        return function(style, content) {
 152          if (content == text) cont();
 153          else {markErr(); cont(arguments.callee);}
 154        };
 155      }
 156  
 157      function pushContext(tagname, startOfLine) {
 158        var noIndent = UseKludges.doNotIndent.hasOwnProperty(tagname) || (context && context.noIndent);
 159        context = {prev: context, name: tagname, indent: indented, startOfLine: startOfLine, noIndent: noIndent};
 160      }
 161      function popContext() {
 162        context = context.prev;
 163      }
 164      function computeIndentation(baseContext) {
 165        return function(nextChars, current) {
 166          var context = baseContext;
 167          if (context && context.noIndent)
 168            return current;
 169          if (alignCDATA && /<!\[CDATA\[/.test(nextChars))
 170            return 0;
 171          if (context && /^<\//.test(nextChars))
 172            context = context.prev;
 173          while (context && !context.startOfLine)
 174            context = context.prev;
 175          if (context)
 176            return context.indent + indentUnit;
 177          else
 178            return 0;
 179        };
 180      }
 181  
 182      function base() {
 183        return pass(element, base);
 184      }
 185      var harmlessTokens = {"xml-text": true, "xml-entity": true, "xml-comment": true, "xml-processing": true};
 186      function element(style, content) {
 187        if (content == "<") cont(tagname, attributes, endtag(tokenNr == 1));
 188        else if (content == "</") cont(closetagname, expect(">"));
 189        else if (style == "xml-cdata") {
 190          if (!context || context.name != "!cdata") pushContext("!cdata");
 191          if (/\]\]>$/.test(content)) popContext();
 192          cont();
 193        }
 194        else if (harmlessTokens.hasOwnProperty(style)) cont();
 195        else {markErr(); cont();}
 196      }
 197      function tagname(style, content) {
 198        if (style == "xml-name") {
 199          currentTag = content.toLowerCase();
 200          token.style = "xml-tagname";
 201          cont();
 202        }
 203        else {
 204          currentTag = null;
 205          pass();
 206        }
 207      }
 208      function closetagname(style, content) {
 209        if (style == "xml-name") {
 210          token.style = "xml-tagname";
 211          if (context && content.toLowerCase() == context.name) popContext();
 212          else markErr();
 213        }
 214        cont();
 215      }
 216      function endtag(startOfLine) {
 217        return function(style, content) {
 218          if (content == "/>" || (content == ">" && UseKludges.autoSelfClosers.hasOwnProperty(currentTag))) cont();
 219          else if (content == ">") {pushContext(currentTag, startOfLine); cont();}
 220          else {markErr(); cont(arguments.callee);}
 221        };
 222      }
 223      function attributes(style) {
 224        if (style == "xml-name") {token.style = "xml-attname"; cont(attribute, attributes);}
 225        else pass();
 226      }
 227      function attribute(style, content) {
 228        if (content == "=") cont(value);
 229        else if (content == ">" || content == "/>") pass(endtag);
 230        else pass();
 231      }
 232      function value(style) {
 233        if (style == "xml-attribute") cont(value);
 234        else pass();
 235      }
 236  
 237      return {
 238        indentation: function() {return indented;},
 239  
 240        next: function(){
 241          token = tokens.next();
 242          if (token.style == "whitespace" && tokenNr == 0)
 243            indented = token.value.length;
 244          else
 245            tokenNr++;
 246          if (token.content == "\n") {
 247            indented = tokenNr = 0;
 248            token.indentation = computeIndentation(context);
 249          }
 250  
 251          if (token.style == "whitespace" || token.type == "xml-comment")
 252            return token;
 253  
 254          while(true){
 255            consume = false;
 256            cc.pop()(token.style, token.content);
 257            if (consume) return token;
 258          }
 259        },
 260  
 261        copy: function(){
 262          var _cc = cc.concat([]), _tokenState = tokens.state, _context = context;
 263          var parser = this;
 264          
 265          return function(input){
 266            cc = _cc.concat([]);
 267            tokenNr = indented = 0;
 268            context = _context;
 269            tokens = tokenizeXML(input, _tokenState);
 270            return parser;
 271          };
 272        }
 273      };
 274    }
 275  
 276    return {
 277      make: parseXML,
 278      electricChars: "/",
 279      configure: function(config) {
 280        if (config.useHTMLKludges != null)
 281          UseKludges = config.useHTMLKludges ? Kludges : NoKludges;
 282        if (config.alignCDATA)
 283          alignCDATA = config.alignCDATA;
 284      }
 285    };
 286  })();


Generated: Tue May 19 15:55:14 2020 Cross-referenced by PHPXref 0.7.1