[ Index ]

MailPress 7.2

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

title

Body

[close]

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


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