From 954cc7c4c3bc8e963e0f8fc6ef5b7f57df924392 Mon Sep 17 00:00:00 2001 From: gkhk Date: Mon, 2 Oct 2023 01:38:24 +0200 Subject: [PATCH] fix: Correct handling of empty non self-closing elements Previously empty element tags were causing other elements to be incorrectly rendered inside them. This commit fixes the issue by ensuring that empty non self-closing tags are handeld correctly. Closes #42 --- render/src/simple_element.rs | 24 +++++++++++------------- render_macros/src/element.rs | 14 +++++++++++--- render_tests/src/lib.rs | 12 ++++++++++++ 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/render/src/simple_element.rs b/render/src/simple_element.rs index 4cc0e22..27c77ea 100644 --- a/render/src/simple_element.rs +++ b/render/src/simple_element.rs @@ -13,6 +13,7 @@ pub struct SimpleElement<'a, T: Render> { pub tag_name: &'a str, pub attributes: Attributes<'a>, pub contents: Option, + pub self_closing: bool, } fn write_attributes<'a, W: Write>(maybe_attributes: Attributes<'a>, writer: &mut W) -> Result { @@ -31,19 +32,16 @@ fn write_attributes<'a, W: Write>(maybe_attributes: Attributes<'a>, writer: &mut impl Render for SimpleElement<'_, T> { fn render_into(self, writer: &mut W) -> Result { - match self.contents { - None => { - write!(writer, "<{}", self.tag_name)?; - write_attributes(self.attributes, writer)?; - write!(writer, "/>") - } - Some(renderable) => { - write!(writer, "<{}", self.tag_name)?; - write_attributes(self.attributes, writer)?; - write!(writer, ">")?; - renderable.render_into(writer)?; - write!(writer, "", self.tag_name) - } + if self.self_closing { + write!(writer, "<{}", self.tag_name)?; + write_attributes(self.attributes, writer)?; + write!(writer, "/>") + } else { + write!(writer, "<{}", self.tag_name)?; + write_attributes(self.attributes, writer)?; + write!(writer, ">")?; + self.contents.render_into(writer)?; + write!(writer, "", self.tag_name) } } } diff --git a/render_macros/src/element.rs b/render_macros/src/element.rs index 161919b..77e8d34 100644 --- a/render_macros/src/element.rs +++ b/render_macros/src/element.rs @@ -8,16 +8,21 @@ pub struct Element { name: syn::Path, attributes: ElementAttributes, children: Children, + self_closing: bool, } impl Parse for Element { fn parse(input: ParseStream) -> Result { let open_tag = input.parse::()?; - - let children = if open_tag.self_closing { + let self_closing = open_tag.self_closing; + let children = if self_closing { Children::default() } else { - let children = input.parse::()?; + let children = if input.peek2(syn::Token![/]) { + Children::default() + } else { + input.parse::()? + }; let closing_tag = input.parse::()?; closing_tag.validate(&open_tag); children @@ -27,6 +32,7 @@ impl Parse for Element { name: open_tag.name, attributes: open_tag.attributes, children, + self_closing, }) } } @@ -54,11 +60,13 @@ impl ToTokens for Element { } else { let attrs = self.attributes.for_simple_element(); let children_tuple = self.children.as_option_of_tuples_tokens(); + let self_closing = self.self_closing; quote! { ::render::SimpleElement { tag_name: stringify!(#name), attributes: #attrs, contents: #children_tuple, + self_closing: #self_closing, } } }; diff --git a/render_tests/src/lib.rs b/render_tests/src/lib.rs index 873e576..abc30a4 100644 --- a/render_tests/src/lib.rs +++ b/render_tests/src/lib.rs @@ -77,6 +77,18 @@ fn element_ordering() { ); } +#[test] +fn childless_non_selfclosing_tag() { + use pretty_assertions::assert_eq; + use render::html; + + let actual = html! { + + }; + + assert_eq!(actual, ""); +} + #[test] fn some_none() { use pretty_assertions::assert_eq;