@lezer/html
Version:
lezer-based HTML grammar
398 lines (254 loc) • 8.34 kB
Plain Text
# 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&'>
==>
Document(Element(SelfClosingTag(StartTag, TagName,
Attribute(AttributeName, Is, AttributeValue),
Attribute(AttributeName, Is, AttributeValue(EntityReference)),
EndTag)))
# Entities
<a attr="one&two">&C</a>
==>
Document(Element(OpenTag(StartTag,TagName,
Attribute(AttributeName,Is,AttributeValue(EntityReference)),EndTag),
EntityReference,CharacterReference,
CloseTag(StartCloseTag,TagName,EndTag)))
# Doctype
<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)),Text,Comment,Text,Comment)
# 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: <</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)))
# Allows self-closing in foreign elements
<div><svg><circle/></svg></div>
==>
Document(Element(OpenTag(StartTag,TagName,EndTag),
Element(OpenTag(StartTag,TagName,EndTag),
Element(SelfClosingTag(StartTag,TagName,SelfClosingEndTag)),
CloseTag(StartCloseTag,TagName,EndTag)),
CloseTag(StartCloseTag,TagName,EndTag)))
# Parses multiple unfinished tags in a row
<div
<div
<div
==>
Document(Element(OpenTag(StartTag,TagName,⚠),
Element(OpenTag(StartTag,TagName,⚠),
Element(OpenTag(StartTag,TagName,⚠),⚠),⚠),⚠))
# Allows self-closing on special tags {"dialect": "selfClosing"}
<body>
<br/>
<textarea/>
<script/>
<style/>
</body>
==>
Document(Element(
OpenTag(StartTag,TagName,EndTag),
Text,
Element(SelfClosingTag(StartTag,TagName,SelfClosingEndTag)),
Text,
Element(SelfClosingTag(StartTag,TagName,SelfClosingEndTag)),
Text,
Element(SelfClosingTag(StartTag,TagName,SelfClosingEndTag)),
Text,
Element(SelfClosingTag(StartTag,TagName,SelfClosingEndTag)),
Text,
CloseTag(StartCloseTag,TagName,EndTag)))