diff --git a/maud/tests/basic_syntax.rs b/maud/tests/basic_syntax.rs index a31cd39..d5dfcec 100644 --- a/maud/tests/basic_syntax.rs +++ b/maud/tests/basic_syntax.rs @@ -93,6 +93,13 @@ fn toggle_empty_attributes() { r#"<input>"#)); } +#[test] +fn toggle_empty_attributes_braces() { + let s = html!(input checked?[Maud { rocks: true }.rocks] /).into_string(); + let foo = 42; + assert_eq!(s, r#"<input checked>"#); +} + #[test] fn colons_in_names() { let s = html!(pon-pon:controls-alpha a on:click="yay()" "Yay!").into_string(); diff --git a/maud_macros/src/parse.rs b/maud_macros/src/parse.rs index 6c60071..64e8fec 100644 --- a/maud_macros/src/parse.rs +++ b/maud_macros/src/parse.rs @@ -408,16 +408,28 @@ impl Parser { self.commit(attempt); match self.peek() { // Toggle the attribute based on a boolean expression - Some(TokenTree { kind: TokenNode::Group(Delimiter::Bracket, cond), span: delim_span }) => { + Some(TokenTree { + kind: TokenNode::Group(Delimiter::Bracket, cond), + span: delim_span, + }) => { self.advance(); render.push(TokenTree { kind: TokenNode::Term(Term::intern("if")), span: question_span, }); - render.push(TokenTree { - kind: TokenNode::Group(Delimiter::None, cond), - span: delim_span, - }); + // If the condition contains an opening brace `{`, + // wrap it in parentheses to avoid parse errors + if cond.clone().into_iter().any(|token| match token.kind { + TokenNode::Group(Delimiter::Brace, _) => true, + _ => false, + }) { + render.push(TokenTree { + kind: TokenNode::Group(Delimiter::Parenthesis, cond), + span: delim_span, + }); + } else { + render.push(cond); + } let body = { let mut render = render.fork(); render.attribute_empty(&name);