18403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// Copyright (c) 2011, Mike Samuel
28403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// All rights reserved.
38403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel//
48403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// Redistribution and use in source and binary forms, with or without
58403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// modification, are permitted provided that the following conditions
68403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// are met:
78403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel//
88403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// Redistributions of source code must retain the above copyright
98403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// notice, this list of conditions and the following disclaimer.
108403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// Redistributions in binary form must reproduce the above copyright
118403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// notice, this list of conditions and the following disclaimer in the
128403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// documentation and/or other materials provided with the distribution.
138403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// Neither the name of the OWASP nor the names of its contributors may
148403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// be used to endorse or promote products derived from this software
158403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// without specific prior written permission.
168403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
178403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
188403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
198403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
208403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
218403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
228403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
238403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
248403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
258403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
268403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
278403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// POSSIBILITY OF SUCH DAMAGE.
288403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel
295c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.compackage org.owasp.html;
305c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com
315c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.comimport java.util.List;
325c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com
331ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuelimport javax.annotation.Nullable;
3427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuelimport javax.annotation.concurrent.Immutable;
3527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel
365c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.comimport com.google.common.collect.ImmutableMap;
375c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.comimport com.google.common.collect.Lists;
385c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com
394e867904c8295537803c1c8a076e130df5674b58mikesamuel/**
404e867904c8295537803c1c8a076e130df5674b58mikesamuel * Wraps an HTML stream event receiver to fill in missing close tags.
414e867904c8295537803c1c8a076e130df5674b58mikesamuel * If the balancer is given the HTML {@code <p>1<p>2}, the wrapped receiver will
424e867904c8295537803c1c8a076e130df5674b58mikesamuel * see events equivalent to {@code <p>1</p><p>2</p>}.
434e867904c8295537803c1c8a076e130df5674b58mikesamuel *
444e867904c8295537803c1c8a076e130df5674b58mikesamuel * @author Mike Samuel <mikesamuel@gmail.com>
454e867904c8295537803c1c8a076e130df5674b58mikesamuel */
465c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com@TCB
474e867904c8295537803c1c8a076e130df5674b58mikesamuelpublic class TagBalancingHtmlStreamEventReceiver
484e867904c8295537803c1c8a076e130df5674b58mikesamuel    implements HtmlStreamEventReceiver {
495c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com  private final HtmlStreamEventReceiver underlying;
503f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel  private int nestingLimit = Integer.MAX_VALUE;
5127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel  private final List<ElementContainmentInfo> openElements
5227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      = Lists.newArrayList();
535c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com
544e867904c8295537803c1c8a076e130df5674b58mikesamuel  public TagBalancingHtmlStreamEventReceiver(
554e867904c8295537803c1c8a076e130df5674b58mikesamuel      HtmlStreamEventReceiver underlying) {
565c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com    this.underlying = underlying;
575c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com  }
585c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com
593f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel  public void setNestingLimit(int limit) {
603f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel    if (openElements.size() > limit) {
613f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel      throw new IllegalStateException();
623f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel    }
633f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel    this.nestingLimit = limit;
643f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel  }
653f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel
665c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com  public void openDocument() {
675c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com    underlying.openDocument();
685c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com  }
695c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com
705c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com  public void closeDocument() {
713f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel    for (int i = Math.min(nestingLimit, openElements.size()); --i >= 0;) {
723f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel      underlying.closeTag(openElements.get(i).elementName);
735c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com    }
7427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    openElements.clear();
755c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com    underlying.closeDocument();
765c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com  }
775c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com
785c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com  public void openTag(String elementName, List<String> attrs) {
795c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com    String canonElementName = HtmlLexer.canonicalName(elementName);
8027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    ElementContainmentInfo elInfo = ELEMENT_CONTAINMENT_RELATIONSHIPS.get(
8127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel        canonElementName);
8227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    // Treat unrecognized tags as void, but emit closing tags in closeTag().
8327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    if (elInfo == null) {
843f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel      if (openElements.size() < nestingLimit) {
853f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel        underlying.openTag(elementName, attrs);
863f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel      }
8727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      return;
8827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    }
8927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel
9063dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel    prepareForContent(elInfo);
9163dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel
9263dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel    if (openElements.size() < nestingLimit) {
9363dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel      underlying.openTag(elInfo.elementName, attrs);
9463dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel    }
9563dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel    if (!elInfo.isVoid) {
9663dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel      openElements.add(elInfo);
9763dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel    }
9863dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel  }
9963dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel
10063dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel  private void prepareForContent(ElementContainmentInfo elInfo) {
1011ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel    int nOpen = openElements.size();
1021ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel    if (nOpen != 0) {
1031ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel      ElementContainmentInfo top = openElements.get(nOpen - 1);
1041ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel      if ((top.contents & elInfo.types) == 0) {
1051ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel        ElementContainmentInfo blockContainerChild = top.blockContainerChild;
1061ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel        // Open implied elements, such as list-items and table cells & rows.
1071ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel        if (blockContainerChild != null
1081ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel            && (blockContainerChild.contents & elInfo.types) != 0) {
1091ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel          underlying.openTag(
1101ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel              blockContainerChild.elementName, Lists.<String>newArrayList());
1111ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel          openElements.add(blockContainerChild);
1121ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel          top = blockContainerChild;
1131ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel          ++nOpen;
1141ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel        }
1153f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel      }
1161ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel
1171ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel      // Close all the elements that cannot contain the element to open.
1181ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel      List<ElementContainmentInfo> toResumeInReverse = null;
1191ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel      while (true) {
1201ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel        if ((top.contents & elInfo.types) != 0) { break; }
1211ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel        if (openElements.size() < nestingLimit) {
1221ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel          underlying.closeTag(top.elementName);
1231ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel        }
1241ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel        openElements.remove(--nOpen);
1251ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel        if (top.resumable) {
1261ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel          if (toResumeInReverse == null) {
1271ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel            toResumeInReverse = Lists.newArrayList();
1281ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel          }
1291ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel          toResumeInReverse.add(top);
1305c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com        }
1311ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel        if (nOpen == 0) { break; }
1321ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel        top = openElements.get(nOpen - 1);
13327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      }
13427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel
1351ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel      if (toResumeInReverse != null) {
1361ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel        resume(toResumeInReverse);
1371ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel      }
1383f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel    }
1395c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com  }
1405c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com
1415c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com  public void closeTag(String elementName) {
1425c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com    String canonElementName = HtmlLexer.canonicalName(elementName);
14327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    ElementContainmentInfo elInfo = ELEMENT_CONTAINMENT_RELATIONSHIPS.get(
14427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel        canonElementName);
14527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    if (elInfo == null) {  // Allow unrecognized end tags through.
1463f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel      if (openElements.size() < nestingLimit) {
1473f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel        underlying.closeTag(elementName);
1483f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel      }
14927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      return;
15027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    }
15127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    int index = openElements.lastIndexOf(elInfo);
152783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    // Let any of </h1>, </h2>, ... close other header tags.
153783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    if (isHeaderElementName(canonElementName)) {
154783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel      for (int i = openElements.size(), limit = index + 1; -- i >= limit;) {
155783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel        ElementContainmentInfo openEl = openElements.get(i);
156783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel        if (isHeaderElementName(openEl.elementName)) {
157783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          elInfo = openEl;
158783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          index = i;
159783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          canonElementName = openEl.elementName;
160783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          break;
16163dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel        }
16263dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel      }
163783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    }
164783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    if (index < 0) {
165783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel      return;  // Don't close unopened tags.
166783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    }
167783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel
168783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    // Ensure that index is in the scope of closeable elements.
169783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    // This approximates the "has an element in *** scope" predicates defined at
170783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html
171783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    // #has-an-element-in-the-specific-scope
172783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    int blockingScopes = elInfo.blockedByScopes;
173783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    for (int i = openElements.size(); --i > index;) {
174783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel      if ((openElements.get(i).inScopes & blockingScopes) != 0) {
175783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel        return;
17663dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel      }
17763dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel    }
178783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel
1795c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com    int last = openElements.size();
18027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    // Close all the elements that cannot contain the element to open.
18127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    List<ElementContainmentInfo> toResumeInReverse = null;
1825c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com    while (--last > index) {
18327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      ElementContainmentInfo unclosed = openElements.remove(last);
1843f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel      if (last + 1 < nestingLimit) {
1853f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel        underlying.closeTag(unclosed.elementName);
1863f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel      }
18727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      if (unclosed.resumable) {
18827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel        if (toResumeInReverse == null) {
18927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          toResumeInReverse = Lists.newArrayList();
19027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel        }
19127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel        toResumeInReverse.add(unclosed);
19227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      }
1935c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com    }
1943f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel    if (openElements.size() < nestingLimit) {
19563dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel      underlying.closeTag(elInfo.elementName);
1963f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel    }
1975c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com    openElements.remove(index);
19827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    if (toResumeInReverse != null) {
1993f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel      resume(toResumeInReverse);
2003f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel    }
2013f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel  }
2023f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel
2033f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel  private void resume(List<ElementContainmentInfo> toResumeInReverse) {
2043f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel    for (ElementContainmentInfo toResume : toResumeInReverse) {
2053f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel      // TODO: If resuming of things other than plain formatting tags like <b>
2063f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel      // and <i>, then we need to store the attributes for resumable tags so
2073f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel      // that we can resume with the appropriate attributes.
2083f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel      if (openElements.size() < nestingLimit) {
20927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel        underlying.openTag(toResume.elementName, Lists.<String>newArrayList());
21027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      }
2113f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel      openElements.add(toResume);
21227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    }
2135c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com  }
2145c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com
215550c8d3230c152db7156b266d089512b72ac0024mikesamuel  private static final long HTML_SPACE_CHAR_BITMASK =
216550c8d3230c152db7156b266d089512b72ac0024mikesamuel      (1L << ' ')
217550c8d3230c152db7156b266d089512b72ac0024mikesamuel    | (1L << '\t')
218550c8d3230c152db7156b266d089512b72ac0024mikesamuel    | (1L << '\n')
219550c8d3230c152db7156b266d089512b72ac0024mikesamuel    | (1L << '\u000c')
220550c8d3230c152db7156b266d089512b72ac0024mikesamuel    | (1L << '\r');
22163dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel
222550c8d3230c152db7156b266d089512b72ac0024mikesamuel  public static boolean isInterElementWhitespace(String text) {
22363dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel    int n = text.length();
22463dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel    for (int i = 0; i < n; ++i) {
22563dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel      int ch = text.charAt(i);
226550c8d3230c152db7156b266d089512b72ac0024mikesamuel      if (ch > 0x20 || (HTML_SPACE_CHAR_BITMASK & (1L << ch)) == 0) {
227550c8d3230c152db7156b266d089512b72ac0024mikesamuel        return false;
22863dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel      }
22963dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel    }
230550c8d3230c152db7156b266d089512b72ac0024mikesamuel    return true;
231550c8d3230c152db7156b266d089512b72ac0024mikesamuel  }
232550c8d3230c152db7156b266d089512b72ac0024mikesamuel
233550c8d3230c152db7156b266d089512b72ac0024mikesamuel  public void text(String text) {
234550c8d3230c152db7156b266d089512b72ac0024mikesamuel    if (!isInterElementWhitespace(text)) {
235550c8d3230c152db7156b266d089512b72ac0024mikesamuel      prepareForContent(ElementContainmentRelationships.CHARACTER_DATA_ONLY);
236550c8d3230c152db7156b266d089512b72ac0024mikesamuel    }
23763dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel
2383f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel    if (openElements.size() < nestingLimit) {
2393f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel      underlying.text(text);
2403f54e49f2181c52ca40d99fbe738b2484ba91528mikesamuel    }
2415c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com  }
2425c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com
24363dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel  private static boolean isHeaderElementName(String canonElementName) {
24463dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel    return canonElementName.length() == 2 && canonElementName.charAt(0) == 'h'
24563dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel        && canonElementName.charAt(1) <= '9';
24663dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel  }
24763dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel
2485c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com
24927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel  @Immutable
2501ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel  private static final class ElementContainmentInfo {
25127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    final String elementName;
25227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    /**
25327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel     * True if the adoption agency algorithm allows an element to be resumed
25427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel     * after a mis-nested end tag closes it.
25527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel     * E.g. in {@code <b>Foo<i>Bar</b>Baz</i>} the {@code <i>} element is
25627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel     * resumed after the {@code <b>} element is closed.
25727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel     */
25827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    final boolean resumable;
25927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    /** A set of bits of element groups into which the element falls. */
26027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    final int types;
26127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    /** The type of elements that an element can contain. */
26227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    final int contents;
26327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    /** True if the element has no content -- not even text content. */
26427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    final boolean isVoid;
2651ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel    /** A legal child of this node that can contain block content. */
2661ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel    final @Nullable ElementContainmentInfo blockContainerChild;
267783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    /** A bit set of close tag scopes that block this element's close tags. */
268783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    final int blockedByScopes;
269783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    /** A bit set of scopes groups into which this element falls. */
270783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    final int inScopes;
27127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel
27227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    ElementContainmentInfo(
2731ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel        String elementName, boolean resumable, int types, int contents,
274783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel        @Nullable ElementContainmentInfo blockContainerChild,
275783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel        int inScopes) {
27627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      this.elementName = elementName;
27727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      this.resumable = resumable;
27827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      this.types = types;
27927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      this.contents = contents;
28027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      this.isVoid = contents == 0
28127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          && HtmlTextEscapingMode.isVoidElement(elementName);
2821ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel      this.blockContainerChild = blockContainerChild;
283783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel      this.blockedByScopes =
284783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          ElementContainmentRelationships.CloseTagScope.ALL & ~inScopes;
285783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel      this.inScopes = inScopes;
28627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    }
28727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel
28827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    @Override public String toString() {
28927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      return "<" + elementName + ">";
29027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    }
29127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel  }
29227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel
29379b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel  static final ImmutableMap<String, ElementContainmentInfo>
29479b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel      ELEMENT_CONTAINMENT_RELATIONSHIPS
29527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      = new ElementContainmentRelationships().toMap();
29627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel
29727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel  private static class ElementContainmentRelationships {
29827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    private enum ElementGroup {
29927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      BLOCK,
30027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      INLINE,
30127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      INLINE_MINUS_A,
30227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      MIXED,
30327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      TABLE_CONTENT,
30427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      HEAD_CONTENT,
30527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      TOP_CONTENT,
30627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      AREA_ELEMENT,
30727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      FORM_ELEMENT,
30827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      LEGEND_ELEMENT,
30927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      LI_ELEMENT,
31027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      DL_PART,
31127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      P_ELEMENT,
31227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      OPTIONS_ELEMENT,
31327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      OPTION_ELEMENT,
31427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      PARAM_ELEMENT,
31527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      TABLE_ELEMENT,
31627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      TR_ELEMENT,
31727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      TD_ELEMENT,
31827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      COL_ELEMENT,
31963dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel      CHARACTER_DATA,
32027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      ;
32127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    }
32227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel
323783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    /**
324783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel     * An identifier for one of the "has a *** element in scope" predicates
325783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel     * used by HTML5 to decide when a close tag implicitly closes tags above
326783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel     * the target element on the open element stack.
327783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel     */
328783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    private enum CloseTagScope {
329783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel      COMMON,
330783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel      BUTTON,
331783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel      LIST_ITEM,
332783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel      TABLE,
333783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel      ;
334783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel
335783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel      static final int ALL = (1 << values().length) - 1;
336783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    }
337783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel
33827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    private static int elementGroupBits(ElementGroup a) {
33927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      return 1 << a.ordinal();
34027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    }
34127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel
34227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    private static int elementGroupBits(
34327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel        ElementGroup a, ElementGroup b) {
34427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      return (1 << a.ordinal()) | (1 << b.ordinal());
34527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    }
34627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel
34727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    private static int elementGroupBits(
34827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel        ElementGroup a, ElementGroup b, ElementGroup c) {
34927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      return (1 << a.ordinal()) | (1 << b.ordinal()) | (1 << c.ordinal());
35027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    }
35127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel
35227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    private static int elementGroupBits(
35327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel        ElementGroup... bits) {
35427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      int bitField = 0;
35527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      for (ElementGroup bit : bits) {
35627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel        bitField |= (1 << bit.ordinal());
35727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      }
35827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      return bitField;
35927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    }
36027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel
361783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    private static int scopeBits(CloseTagScope a) {
362783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel      return 1 << a.ordinal();
363783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    }
364783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel
365783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    private static int scopeBits(
366783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel        CloseTagScope a, CloseTagScope b, CloseTagScope c) {
367783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel      return (1 << a.ordinal()) | (1 << b.ordinal()) | (1 << c.ordinal());
368783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    }
369783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel
37027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    private ImmutableMap.Builder<String, ElementContainmentInfo> definitions
37127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel        = ImmutableMap.builder();
37227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel
3731ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel    private ElementContainmentInfo defineElement(
37427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel        String elementName, boolean resumable, int types, int contentTypes) {
3751ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel      return defineElement(elementName, resumable, types, contentTypes, null);
3761ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel    }
3771ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel
3781ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel    private ElementContainmentInfo defineElement(
3791ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel        String elementName, boolean resumable, int types, int contentTypes,
380783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel        int inScopes) {
381783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel      return defineElement(
382783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          elementName, resumable, types, contentTypes, null, inScopes);
383783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    }
384783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel
385783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    private ElementContainmentInfo defineElement(
386783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel        String elementName, boolean resumable, int types, int contentTypes,
3871ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel        @Nullable ElementContainmentInfo blockContainer) {
388783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel      return defineElement(
389783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          elementName, resumable, types, contentTypes, blockContainer, 0);
390783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    }
391783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel
392783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel    private ElementContainmentInfo defineElement(
393783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel        String elementName, boolean resumable, int types, int contentTypes,
394783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel        @Nullable ElementContainmentInfo blockContainer, int inScopes) {
3951ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel      ElementContainmentInfo info = new ElementContainmentInfo(
396783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          elementName, resumable, types, contentTypes, blockContainer,
397783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          inScopes);
3981ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel      definitions.put(elementName, info);
3991ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel      return info;
40027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    }
40127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel
40227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    private ImmutableMap<String, ElementContainmentInfo> toMap() {
40327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      return definitions.build();
40427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    }
40527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel
40627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    {
40727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
40827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "a", false, elementGroupBits(
40927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
41027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
41127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE_MINUS_A
41227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
41327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
41427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "abbr", true, elementGroupBits(
41527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
41627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
41727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
41827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
41927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
42027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "acronym", true, elementGroupBits(
42127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
42227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
42327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
42427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
42527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
42627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "address", false, elementGroupBits(
42727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
42827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
42927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.P_ELEMENT
43027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
43127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
43227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "applet", false, elementGroupBits(
43327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
43427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
43527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE,
43627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.PARAM_ELEMENT
437783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          ), scopeBits(
438783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel              CloseTagScope.COMMON, CloseTagScope.BUTTON,
439783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel              CloseTagScope.LIST_ITEM
44027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
44127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
44227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "area", false, elementGroupBits(ElementGroup.AREA_ELEMENT), 0);
44327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
44427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "audio", false, elementGroupBits(
44527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
44627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), 0);
44727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
44827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "b", true, elementGroupBits(
44927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
45027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
45127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
45227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
45327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
45427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "base", false, elementGroupBits(ElementGroup.HEAD_CONTENT), 0);
45527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
45627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "basefont", false, elementGroupBits(
45727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
45827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), 0);
45927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
46027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "bdi", true, elementGroupBits(
46127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
46227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
46327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
46427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
46527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
46627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "bdo", true, elementGroupBits(
46727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
46827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
46927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
47027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
47127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
47227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "big", true, elementGroupBits(
47327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
47427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
47527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
47627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
47727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
47827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "blink", true, elementGroupBits(
47927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
48027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
48127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
48227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
48327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
48427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "blockquote", false, elementGroupBits(
48527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
48627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
48727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE
48827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
48927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
49027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "body", false, elementGroupBits(
49127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TOP_CONTENT
49227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
49327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE
49427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
49527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
49627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "br", false, elementGroupBits(
49727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
49827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), 0);
49927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
50027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "button", false, elementGroupBits(
50127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
50227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
50327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE
504783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          ), scopeBits(CloseTagScope.BUTTON));
50527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
50627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "canvas", false, elementGroupBits(
50727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
50827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
50927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
51027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
51127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
51227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "caption", false, elementGroupBits(
51327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TABLE_CONTENT
51427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
51527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
516783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          ), scopeBits(
517783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel              CloseTagScope.COMMON, CloseTagScope.BUTTON,
518783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel              CloseTagScope.LIST_ITEM
51927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
52027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
52127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "center", false, elementGroupBits(
52227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
52327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
52427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE
52527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
52627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
52727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "cite", true, elementGroupBits(
52827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
52927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
53027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
53127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
53227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
53327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "code", true, elementGroupBits(
53427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
53527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
53627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
53727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
53827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
53927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "col", false, elementGroupBits(
54027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TABLE_CONTENT, ElementGroup.COL_ELEMENT
54127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), 0);
54227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
54327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "colgroup", false, elementGroupBits(
54427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TABLE_CONTENT
54527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
54627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.COL_ELEMENT
54727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
5481ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel      ElementContainmentInfo DD = defineElement(
54927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "dd", false, elementGroupBits(
55027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.DL_PART
55127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
55227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE
55327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
55427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
55527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "del", true, elementGroupBits(
55627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE,
55727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.MIXED
55827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
55927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE
56027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
56127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
56227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "dfn", true, elementGroupBits(
56327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
56427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
56527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
56627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
56727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
56827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "dir", false, elementGroupBits(
56927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
57027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
57127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.LI_ELEMENT
57227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
57327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
57427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "div", false, elementGroupBits(
57527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
57627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
57727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE
57827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
57927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
58027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "dl", false, elementGroupBits(
58127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
58227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
58327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.DL_PART
5841ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel          ),
5851ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel          DD);
58627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
58727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "dt", false, elementGroupBits(
58827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.DL_PART
58927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
59027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
59127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
59227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
59327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "em", true, elementGroupBits(
59427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
59527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
59627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
59727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
59827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
59927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "fieldset", false, elementGroupBits(
60027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
60127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
60227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE,
60327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.LEGEND_ELEMENT
60427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
60527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
60627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "font", false, elementGroupBits(
60727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
60827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
60927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
61027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
61127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
61227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "form", false, elementGroupBits(
61327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.FORM_ELEMENT
61427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
61527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE,
61627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE_MINUS_A, ElementGroup.TR_ELEMENT,
61727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TD_ELEMENT
61827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
61927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
62027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "h1", false, elementGroupBits(
62127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
62227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
62327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
62427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
62527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
62627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "h2", false, elementGroupBits(
62727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
62827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
62927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
63027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
63127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
63227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "h3", false, elementGroupBits(
63327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
63427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
63527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
63627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
63727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
63827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "h4", false, elementGroupBits(
63927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
64027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
64127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
64227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
64327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
64427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "h5", false, elementGroupBits(
64527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
64627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
64727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
64827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
64927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
65027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "h6", false, elementGroupBits(
65127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
65227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
65327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
65427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
65527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
65627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "head", false, elementGroupBits(
65727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TOP_CONTENT
65827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
65927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.HEAD_CONTENT
66027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
66127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
66227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "hr", false, elementGroupBits(ElementGroup.BLOCK), 0);
66327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
664783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          "html", false, 0, elementGroupBits(ElementGroup.TOP_CONTENT),
665783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          CloseTagScope.ALL);
66627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
66727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "i", true, elementGroupBits(
66827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
66927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
67027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
67127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
67227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
67327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "iframe", false, elementGroupBits(
67427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
67527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
67627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE
67727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
67827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
67927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "img", false, elementGroupBits(
68027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
68127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), 0);
68227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
68327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "input", false, elementGroupBits(
68427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
68527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), 0);
68627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
68727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "ins", true, elementGroupBits(
68827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE
68927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
69027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE
69127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
69227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
69327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "isindex", false, elementGroupBits(ElementGroup.INLINE), 0);
69427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
69527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "kbd", true, elementGroupBits(
69627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
69727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
69827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
69927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
70027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
70127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "label", false, elementGroupBits(
70227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
70327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
70427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
70527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
70627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
70727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "legend", false, elementGroupBits(
70827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.LEGEND_ELEMENT
70927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
71027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
71127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
7121ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel      ElementContainmentInfo LI = defineElement(
71327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "li", false, elementGroupBits(
71427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.LI_ELEMENT
71527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
71627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE
71727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
71827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
71927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "link", false, elementGroupBits(
72027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.HEAD_CONTENT
72127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), 0);
72227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
72327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "listing", false, elementGroupBits(
72427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
72527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
72627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
72727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
72827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
72927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "map", false, elementGroupBits(
73027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
73127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
73227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.AREA_ELEMENT
73327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
73427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
73527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "meta", false, elementGroupBits(ElementGroup.HEAD_CONTENT), 0);
73627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
73727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "nobr", false, elementGroupBits(
73827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
73927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
74027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
74127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
74227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
74327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "noframes", false, elementGroupBits(
74427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.TOP_CONTENT
74527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
74627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE,
74727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TOP_CONTENT
74827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
74927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
75027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "noscript", false, elementGroupBits(
75127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
75227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
75327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE
75427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
75527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
75627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "object", false, elementGroupBits(
75727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A,
75827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.HEAD_CONTENT
75927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
76027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE,
76127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.PARAM_ELEMENT
762783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          ), scopeBits(
763783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel              CloseTagScope.COMMON, CloseTagScope.BUTTON,
764783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel              CloseTagScope.LIST_ITEM
76527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
76627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
76727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "ol", false, elementGroupBits(
76827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
76927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
77027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.LI_ELEMENT
7711ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel          ),
772783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          LI,
773783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          scopeBits(CloseTagScope.LIST_ITEM));
77427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
77527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "optgroup", false, elementGroupBits(
77627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.OPTIONS_ELEMENT
77727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
77827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.OPTIONS_ELEMENT
77927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
78027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
78127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "option", false, elementGroupBits(
78227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.OPTIONS_ELEMENT, ElementGroup.OPTION_ELEMENT
7834c1e3417997042b0b485cbf71344a0210dfaba04mikesamuel          ), elementGroupBits(
7844c1e3417997042b0b485cbf71344a0210dfaba04mikesamuel              ElementGroup.CHARACTER_DATA
7854c1e3417997042b0b485cbf71344a0210dfaba04mikesamuel          ));
78627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
78727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "p", false, elementGroupBits(
78827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.P_ELEMENT
78927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
79027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.TABLE_ELEMENT
79127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
79227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
79327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "param", false, elementGroupBits(ElementGroup.PARAM_ELEMENT), 0);
79427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
79527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "pre", false, elementGroupBits(
79627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
79727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
79827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
79927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
80027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
80127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "q", true, elementGroupBits(
80227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
80327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
80427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
80527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
80627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
80727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "s", true, elementGroupBits(
80827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
80927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
81027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
81127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
81227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
81327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "samp", true, elementGroupBits(
81427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
81527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
81627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
81727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
81827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
81927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "script", false, elementGroupBits(
82027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE,
82127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE_MINUS_A, ElementGroup.MIXED,
82227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TABLE_CONTENT, ElementGroup.HEAD_CONTENT,
82327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TOP_CONTENT, ElementGroup.AREA_ELEMENT,
82427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.FORM_ELEMENT, ElementGroup.LEGEND_ELEMENT,
82527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.LI_ELEMENT, ElementGroup.DL_PART,
82627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.P_ELEMENT, ElementGroup.OPTIONS_ELEMENT,
82727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.OPTION_ELEMENT, ElementGroup.PARAM_ELEMENT,
82827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TABLE_ELEMENT, ElementGroup.TR_ELEMENT,
82927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TD_ELEMENT, ElementGroup.COL_ELEMENT
83063dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel          ), elementGroupBits(
83163dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel              ElementGroup.CHARACTER_DATA));
83227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
83327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "select", false, elementGroupBits(
83427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
83527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
83627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.OPTIONS_ELEMENT
83727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
83827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
83927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "small", true, elementGroupBits(
84027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
84127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
84227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
84327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
84427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
84527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "span", false, elementGroupBits(
84627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
84727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
84827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
84927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
85027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
85127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "strike", true, elementGroupBits(
85227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
85327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
85427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
85527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
85627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
85727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "strong", true, elementGroupBits(
85827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
85927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
86027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
86127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
86227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
86327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "style", false, elementGroupBits(
86427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.HEAD_CONTENT
86563dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel          ), elementGroupBits(
86663dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel              ElementGroup.CHARACTER_DATA
86763dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel          ));
86827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
86927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "sub", true, elementGroupBits(
87027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
87127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
87227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
87327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
87427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
87527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "sup", true, elementGroupBits(
87627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
87727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
87827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
87927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
88027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
88127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "table", false, elementGroupBits(
88227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.TABLE_ELEMENT
88327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
88427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TABLE_CONTENT, ElementGroup.FORM_ELEMENT
885783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          ), CloseTagScope.ALL);
88627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
88727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "tbody", false, elementGroupBits(
88827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TABLE_CONTENT
88927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
89027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TR_ELEMENT
89127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
8921ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel      ElementContainmentInfo TD = defineElement(
89327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "td", false, elementGroupBits(
89427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TD_ELEMENT
89527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
89627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE
897783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          ), scopeBits(
898783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel              CloseTagScope.COMMON, CloseTagScope.BUTTON,
899783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel              CloseTagScope.LIST_ITEM
90027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
90127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
90227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "textarea", false,
90327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          // No, a textarea cannot be inside a link.
90463dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel          elementGroupBits(ElementGroup.INLINE),
90563dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel          elementGroupBits(ElementGroup.CHARACTER_DATA));
90627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
90727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "tfoot", false, elementGroupBits(
90827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TABLE_CONTENT
90927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
91027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.FORM_ELEMENT, ElementGroup.TR_ELEMENT,
91127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TD_ELEMENT
91227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
91327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
91427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "th", false, elementGroupBits(
91527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TD_ELEMENT
91627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
91727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK, ElementGroup.INLINE
918783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          ), scopeBits(
919783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel              CloseTagScope.COMMON, CloseTagScope.BUTTON,
920783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel              CloseTagScope.LIST_ITEM
92127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
92227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
92327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "thead", false, elementGroupBits(
92427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TABLE_CONTENT
92527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
92627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.FORM_ELEMENT, ElementGroup.TR_ELEMENT,
92727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TD_ELEMENT
92827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
92927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
93063dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel          "title", false, elementGroupBits(ElementGroup.HEAD_CONTENT),
93163dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel          elementGroupBits(ElementGroup.CHARACTER_DATA));
93227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
93327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "tr", false, elementGroupBits(
93427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.TABLE_CONTENT, ElementGroup.TR_ELEMENT
93527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
93627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.FORM_ELEMENT, ElementGroup.TD_ELEMENT
9371ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel          ),
9381ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel          TD);
93927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
94027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "tt", true, elementGroupBits(
94127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
94227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
94327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
94427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
94527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
94627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "u", true, elementGroupBits(
94727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
94827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
94927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
95027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
95127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
95227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "ul", false, elementGroupBits(
95327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
95427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
95527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.LI_ELEMENT
9561ecbdce5dd203e7aca2b93650ca3afce17dbc095mikesamuel          ),
957783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          LI,
958783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel          scopeBits(CloseTagScope.LIST_ITEM));
95927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
96027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "var", false, elementGroupBits(
96127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
96227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
96327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
96427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
96527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
96627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "video", false, elementGroupBits(
96727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
96827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), 0);
96927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
97027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "wbr", false, elementGroupBits(
97127b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A
97227b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), 0);
97327b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel      defineElement(
97427b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          "xmp", false, elementGroupBits(
97527b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.BLOCK
97627b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ), elementGroupBits(
97727b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel              ElementGroup.INLINE
97827b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel          ));
97927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel
98027b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel    }
98163dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel
982a1b4378ade2caa7a029abba418a37ed7b94e7a7fmikesamuel    private static final ElementContainmentInfo CHARACTER_DATA_ONLY
98363dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel        = new ElementContainmentInfo(
98463dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel            "#text", false,
98563dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel            elementGroupBits(
98663dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel                ElementGroup.INLINE, ElementGroup.INLINE_MINUS_A,
98763dba946a9a0b3af438ca08b6824e653e5ca58c5mikesamuel                ElementGroup.BLOCK, ElementGroup.CHARACTER_DATA),
988783908cf042927b900d42383d30ec1fb8ee83d1fmikesamuel            0, null, 0);
98927b4be957534ebb90e21ac8d31bf722e4c9273bfmikesamuel  }
99079b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel
99179b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel  static boolean allowsPlainTextualContent(String canonElementName) {
99279b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel    ElementContainmentInfo info =
99379b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel       ELEMENT_CONTAINMENT_RELATIONSHIPS.get(canonElementName);
994ce5bde40e2e126de05105f09f1f965a5c70aaa94mikesamuel    if (info == null
995ce5bde40e2e126de05105f09f1f965a5c70aaa94mikesamuel        || ((info.contents
996a1b4378ade2caa7a029abba418a37ed7b94e7a7fmikesamuel             & ElementContainmentRelationships.CHARACTER_DATA_ONLY.types)
997ce5bde40e2e126de05105f09f1f965a5c70aaa94mikesamuel            != 0)) {
99879b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel      switch (HtmlTextEscapingMode.getModeForTag(canonElementName)) {
99979b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel        case PCDATA:     return true;
100079b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel        case RCDATA:     return true;
100179b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel        case PLAIN_TEXT: return true;
100279b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel        case VOID:       return false;
100379b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel        case CDATA:
100479b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel        case CDATA_SOMETIMES:
100579b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel          return "xmp".equals(canonElementName)
100679b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel              || "listing".equals(canonElementName);
100779b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel      }
100879b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel    }
100979b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel    return false;
101079b4c29af1261d95c663bdf0003b70cb0eb8000emikesamuel  }
10115c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com}
1012