mirror of
https://github.com/swc-project/swc.git
synced 2024-12-24 22:22:34 +03:00
feat(html/codegen): Omit end tags (#4770)
This commit is contained in:
parent
f4d828feaf
commit
07c197f51c
@ -136,8 +136,12 @@ where
|
||||
formatting_newline!(self);
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_element(&mut self, n: &Element) -> Result {
|
||||
fn basic_emit_element(
|
||||
&mut self,
|
||||
n: &Element,
|
||||
_parent: Option<&Element>,
|
||||
next: Option<&Child>,
|
||||
) -> Result {
|
||||
write_raw!(self, "<");
|
||||
write_raw!(self, &n.tag_name);
|
||||
|
||||
@ -200,11 +204,69 @@ where
|
||||
..self.ctx
|
||||
};
|
||||
|
||||
self.with_ctx(ctx)
|
||||
.emit_list(&n.children, ListFormat::NotDelimited)?;
|
||||
if self.config.minify {
|
||||
self.with_ctx(ctx)
|
||||
.emit_list_for_tag_omission(n, &n.children)?;
|
||||
} else {
|
||||
self.with_ctx(ctx)
|
||||
.emit_list(&n.children, ListFormat::NotDelimited)?;
|
||||
}
|
||||
}
|
||||
|
||||
if self.is_plaintext {
|
||||
let can_omit_end_tag = self.is_plaintext
|
||||
|| (self.config.minify
|
||||
&& n.namespace == Namespace::HTML
|
||||
&& match &*n.tag_name {
|
||||
// Tag omission in text/html:
|
||||
|
||||
// An li element's end tag can be omitted if the li element is immediately
|
||||
// followed by another li element or if there is no more content in the parent
|
||||
// element.
|
||||
"li" => match next {
|
||||
Some(Child::Element(Element {
|
||||
namespace,
|
||||
tag_name,
|
||||
..
|
||||
})) if *namespace == Namespace::HTML && tag_name == "li" => true,
|
||||
None => true,
|
||||
_ => false,
|
||||
},
|
||||
// A dt element's end tag can be omitted if the dt element is immediately
|
||||
// followed by another dt element or a dd element.
|
||||
"dt" => match next {
|
||||
Some(Child::Element(Element {
|
||||
namespace,
|
||||
tag_name,
|
||||
..
|
||||
})) if *namespace == Namespace::HTML
|
||||
&& (tag_name == "dt" || tag_name == "dd") =>
|
||||
{
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
|
||||
// A dd element's end tag can be omitted if the dd element is immediately
|
||||
// followed by another dd element or a dt element, or if there is no more
|
||||
// content in the parent element.
|
||||
"dd" => match next {
|
||||
Some(Child::Element(Element {
|
||||
namespace,
|
||||
tag_name,
|
||||
..
|
||||
})) if *namespace == Namespace::HTML
|
||||
&& (tag_name == "dd" || tag_name == "dt") =>
|
||||
{
|
||||
true
|
||||
}
|
||||
None => true,
|
||||
_ => false,
|
||||
},
|
||||
|
||||
_ => false,
|
||||
});
|
||||
|
||||
if can_omit_end_tag {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@ -212,6 +274,13 @@ where
|
||||
write_raw!(self, "/");
|
||||
write_raw!(self, &n.tag_name);
|
||||
write_raw!(self, ">");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_element(&mut self, n: &Element) -> Result {
|
||||
self.basic_emit_element(n, None, None)?;
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
@ -565,6 +634,23 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_list_for_tag_omission(&mut self, parent: &Element, nodes: &[Child]) -> Result {
|
||||
for (idx, node) in nodes.iter().enumerate() {
|
||||
match node {
|
||||
Child::Element(element) => {
|
||||
let next = nodes.get(idx + 1);
|
||||
|
||||
self.basic_emit_element(element, Some(parent), next)?;
|
||||
}
|
||||
_ => {
|
||||
emit!(self, node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_delim(&mut self, f: ListFormat) -> Result {
|
||||
match f & ListFormat::DelimitersMask {
|
||||
ListFormat::None => {}
|
||||
|
@ -425,6 +425,7 @@ fn test_indent_type_option(input: PathBuf) {
|
||||
);
|
||||
}
|
||||
|
||||
// TODO minified verification
|
||||
#[testing::fixture("../swc_html_parser/tests/fixture/**/*.html")]
|
||||
fn parser_verify(input: PathBuf) {
|
||||
verify_document(&input, None, None, None, false);
|
||||
|
18
crates/swc_html_codegen/tests/fixture/optional/input.html
Normal file
18
crates/swc_html_codegen/tests/fixture/optional/input.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head><title>Document</title></head><body>
|
||||
<ul><li>test</li></ul>
|
||||
<ul> <li>test</li> </ul>
|
||||
<ul> <li>test</li> <li>test</li> </ul>
|
||||
<ul> <li>test</li> <li>test</li></ul>
|
||||
<ul><li>test</li><li>test</li><li>test</li></ul>
|
||||
<ul><li>test</li><li>test</li> <li>test</li> </ul>
|
||||
|
||||
<article>
|
||||
<h1>FAQ</h1>
|
||||
<dl><dt>What do we want?</dt><dd>Our data.</dd><dt>When do we want it?</dt><dd>Now.</dd><dt>Where is it?</dt><dd>We are not sure.</dd></dl>
|
||||
</article>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
18
crates/swc_html_codegen/tests/fixture/optional/output.html
Normal file
18
crates/swc_html_codegen/tests/fixture/optional/output.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head><title>Document</title></head><body>
|
||||
<ul><li>test</li></ul>
|
||||
<ul> <li>test</li> </ul>
|
||||
<ul> <li>test</li> <li>test</li> </ul>
|
||||
<ul> <li>test</li> <li>test</li></ul>
|
||||
<ul><li>test</li><li>test</li><li>test</li></ul>
|
||||
<ul><li>test</li><li>test</li> <li>test</li> </ul>
|
||||
|
||||
<article>
|
||||
<h1>FAQ</h1>
|
||||
<dl><dt>What do we want?</dt><dd>Our data.</dd><dt>When do we want it?</dt><dd>Now.</dd><dt>Where is it?</dt><dd>We are not sure.</dd></dl>
|
||||
</article>
|
||||
|
||||
|
||||
|
||||
</body></html>
|
@ -0,0 +1,16 @@
|
||||
<!doctype html><html lang=en><head><title>Document</title></head><body>
|
||||
<ul><li>test</ul>
|
||||
<ul> <li>test</li> </ul>
|
||||
<ul> <li>test</li> <li>test</li> </ul>
|
||||
<ul> <li>test</li> <li>test</ul>
|
||||
<ul><li>test<li>test<li>test</ul>
|
||||
<ul><li>test<li>test</li> <li>test</li> </ul>
|
||||
|
||||
<article>
|
||||
<h1>FAQ</h1>
|
||||
<dl><dt>What do we want?<dd>Our data.<dt>When do we want it?<dd>Now.<dt>Where is it?<dd>We are not sure.</dl>
|
||||
</article>
|
||||
|
||||
|
||||
|
||||
</body></html>
|
@ -2,7 +2,7 @@
|
||||
<body>
|
||||
<p>For more information, read <a href=https://stackoverflow.com/questions/17408815/fieldset-resizes-wrong-appears-to-have-unremovable-min-width-min-content/17863685#17863685>this Stack Overflow answer</a>.</p>
|
||||
<p>a</p><div>b</div>
|
||||
<p>a</p><ul><li>item</li></ul>
|
||||
<p>a</p><ol><li>item</li></ol>
|
||||
<p>a</p><ul><li>item</ul>
|
||||
<p>a</p><ol><li>item</ol>
|
||||
|
||||
</body></html>
|
||||
|
Loading…
Reference in New Issue
Block a user