# Regular tag

<foo>bar</foo>

==>

Document(Element(OpenTag(StartTag,TagName,EndTag),Text,CloseTag(StartCloseTag,TagName,EndTag)))

# Nested tag

<a><b>c</b><br></a>

==>

Document(Element(OpenTag(StartTag,TagName,EndTag),
  Element(OpenTag(StartTag,TagName,EndTag),Text,CloseTag(StartCloseTag,TagName,EndTag)),
  Element(SelfClosingTag(StartTag,TagName,EndTag)),
CloseTag(StartCloseTag,TagName,EndTag)))

# Attribute

<br foo="bar">

==>

Document(Element(SelfClosingTag(StartTag,TagName,Attribute(AttributeName,Is,AttributeValue),EndTag)))

# Multiple attributes

<a x="one" y="two" z="three"></a>

==>

Document(Element(OpenTag(StartTag,TagName,
  Attribute(AttributeName,Is,AttributeValue),
  Attribute(AttributeName,Is,AttributeValue),
  Attribute(AttributeName,Is,AttributeValue),EndTag),
CloseTag(StartCloseTag,TagName,EndTag)))

# Value-less attributes

<a x y="one" z></a>

==>

Document(Element(OpenTag(StartTag,TagName,
  Attribute(AttributeName),
  Attribute(AttributeName,Is,AttributeValue),
  Attribute(AttributeName),EndTag),
CloseTag(StartCloseTag,TagName,EndTag)))

# Unquoted attributes

<a x=one y z=two></a>

==>

Document(Element(OpenTag(StartTag,TagName,
  Attribute(AttributeName,Is,UnquotedAttributeValue),
  Attribute(AttributeName),
  Attribute(AttributeName,Is,UnquotedAttributeValue),EndTag),
CloseTag(StartCloseTag,TagName,EndTag)))

# Unquoted attributes with slashes

<link as=font crossorigin=anonymous href=/fonts/google-sans/regular/latin.woff2 rel=preload>

==>

Document(Element(SelfClosingTag(StartTag,TagName,
  Attribute(AttributeName,Is,UnquotedAttributeValue),
  Attribute(AttributeName,Is,UnquotedAttributeValue),
  Attribute(AttributeName,Is,UnquotedAttributeValue),
  Attribute(AttributeName,Is,UnquotedAttributeValue),
EndTag)))

# Single-quoted attributes

<link x='one' z='two&amp;'>

==>

Document(Element(SelfClosingTag(StartTag, TagName,
  Attribute(AttributeName, Is, AttributeValue),
  Attribute(AttributeName, Is, AttributeValue(EntityReference)),
EndTag)))

# Entities

<a attr="one&amp;two">&amp;&#67;</a>

==>

Document(Element(OpenTag(StartTag,TagName,
  Attribute(AttributeName,Is,AttributeValue(EntityReference)),EndTag),
  EntityReference,CharacterReference,
CloseTag(StartCloseTag,TagName,EndTag)))

# Doctype

<!doctype html>
<doc></doc>

==>

Document(DoctypeDecl,Text,Element(OpenTag(StartTag,TagName,EndTag),CloseTag(StartCloseTag,TagName,EndTag)))

# Processing instructions

<?foo?><bar><?baz?></bar>

==>

Document(ProcessingInst,Element(OpenTag(StartTag,TagName,EndTag),ProcessingInst,CloseTag(StartCloseTag,TagName,EndTag)))

# Comments

<!-- top comment -->
<element><!-- inner comment --> text</element>

==>

Document(Comment,Text,Element(OpenTag(StartTag,TagName,EndTag),Comment,Text,CloseTag(StartCloseTag,TagName,EndTag)))

# Mismatched tag

<a></b>

==>

Document(Element(OpenTag(StartTag,TagName,EndTag),MismatchedCloseTag(StartCloseTag,TagName,EndTag)))

# Unclosed tag

<a>

==>

Document(Element(OpenTag(StartTag,TagName,EndTag)))

# Ignore pseudo-xml self-closers

<br/>

==>

Document(Element(SelfClosingTag(StartTag,TagName,EndTag)))

# Unclosed implicitly closed tag

<p>

==>

Document(Element(OpenTag(StartTag,TagName,EndTag)))

# Nested mismatched tag

<a><b><c></c></x></a>

==>

Document(Element(OpenTag(StartTag,TagName,EndTag),
  Element(OpenTag(StartTag,TagName,EndTag),
    Element(OpenTag(StartTag,TagName,EndTag),CloseTag(StartCloseTag,TagName,EndTag)),
    MismatchedCloseTag(StartCloseTag,TagName,EndTag),
    ⚠),
  CloseTag(StartCloseTag,TagName,EndTag)))

# Mismatched tag with whitespace

<doc>
  <
    foo bar="10">
    blah
  </oof>
</doc>

==>

Document(Element(OpenTag(StartTag,TagName,EndTag),
  Text,
  Element(OpenTag(StartTag,TagName,Attribute(AttributeName,Is,AttributeValue),EndTag),
    Text,
    MismatchedCloseTag(StartCloseTag,TagName,EndTag),
    Text, ⚠),
  CloseTag(StartCloseTag,TagName,EndTag)))

# Incomplete close tag

<html><body></</html>

==>

Document(Element(OpenTag(StartTag,TagName,EndTag),
  Element(OpenTag(StartTag,TagName,EndTag), IncompleteCloseTag, ⚠),
  CloseTag(StartCloseTag,TagName,EndTag)))

# Re-synchronize close tags

<a><b><c></x></c></a>

==>

Document(Element(OpenTag(StartTag,TagName,EndTag),
  Element(OpenTag(StartTag,TagName,EndTag),
    Element(OpenTag(StartTag,TagName,EndTag),
      MismatchedCloseTag(StartCloseTag,TagName,EndTag),
      CloseTag(StartCloseTag,TagName,EndTag)),
    ⚠),
  CloseTag(StartCloseTag,TagName,EndTag)))

# Top-level mismatched close tag

<a></a></a>

==>

Document(
  Element(OpenTag(StartTag,TagName,EndTag),CloseTag(StartCloseTag,TagName,EndTag)),
  MismatchedCloseTag(StartCloseTag,TagName,EndTag))

# Self-closing tags

<a><img src=blah></a>

==>

Document(Element(OpenTag(StartTag,TagName,EndTag),
  Element(SelfClosingTag(StartTag,TagName,Attribute(AttributeName,Is,UnquotedAttributeValue),EndTag)),
CloseTag(StartCloseTag,TagName,EndTag)))

# Implicitly closed

<dl><dd>Hello</dl>

==>

Document(Element(OpenTag(StartTag,TagName,EndTag),
  Element(OpenTag(StartTag,TagName,EndTag),Text),
CloseTag(StartCloseTag,TagName,EndTag)))

# Closed by sibling

<div>
  <p>Foo
  <p>Bar
</div>

==>

Document(Element(OpenTag(StartTag,TagName,EndTag),
  Text,
  Element(OpenTag(StartTag,TagName,EndTag),Text),
  Element(OpenTag(StartTag,TagName,EndTag),Text),
CloseTag(StartCloseTag,TagName,EndTag)))

# Closed by sibling at top

<p>Foo
<p>Bar

==>

Document(Element(OpenTag(StartTag,TagName,EndTag),Text),Element(OpenTag(StartTag,TagName,EndTag),Text))

# Textarea

<p>Enter something: <textarea code-lang=javascript>function foo() {
  return "</bar>"
}</textarea>

==>

Document(Element(OpenTag(StartTag,TagName,EndTag),
  Text,
  Element(OpenTag(StartTag,TagName,Attribute(AttributeName,Is,UnquotedAttributeValue),EndTag),
    TextareaText,
  CloseTag(StartCloseTag,TagName,EndTag))))

# Script

<script>This is not an entity: &lt;</script>

==>

Document(Element(OpenTag(StartTag,TagName,EndTag),ScriptText,CloseTag(StartCloseTag,TagName,EndTag)))

# Allows whitespace in tags

<
  body
    foo=bar
  >hi</
 body
 >

==>

Document(Element(
  OpenTag(StartTag,TagName,Attribute(AttributeName,Is,UnquotedAttributeValue),EndTag),
  Text,
  CloseTag(StartCloseTag,TagName,EndTag)))

# Doesn't get confused by a stray ampersand

<html>a&b</html>

==>

Document(Element(OpenTag(StartTag,TagName,EndTag),Text,InvalidEntity,Text,CloseTag(StartCloseTag,TagName,EndTag)))

# Can ignore mismatches {"dialect": "noMatch"}

<div>foo</p>

==>

Document(Element(OpenTag(StartTag,TagName,EndTag),Text,CloseTag(StartCloseTag,TagName,EndTag)))

# Can handle lone close tags {"dialect": "noMatch"}

</strong>

==>

Document(CloseTag(StartCloseTag,TagName,EndTag))

# Parses ampersands in attributes

<img src="foo&bar">

==>

Document(Element(SelfClosingTag(StartTag, TagName, Attribute(AttributeName, Is, AttributeValue(InvalidEntity)), EndTag)))

# Supports self-closing dialect {"dialect": "selfClosing"}

<section><image id=i2 /></section>

==>

Document(Element(
  OpenTag(StartTag,TagName,EndTag),
  Element(SelfClosingTag(StartTag,TagName,Attribute(AttributeName,Is,UnquotedAttributeValue),SelfClosingEndTag)),
  CloseTag(StartCloseTag,TagName,EndTag)))
