Require braces around element bodies

This commit is contained in:
Chris Wong 2018-06-16 21:33:23 +12:00
parent b9279f7f3f
commit 41aea5f92c
4 changed files with 34 additions and 27 deletions
maud/tests
maud_extras
maud_macros/src

View file

@ -50,12 +50,6 @@ fn simple_elements() {
assert_eq!(s, "<p><b>pickle</b>barrel<i>kumquat</i></p>"); assert_eq!(s, "<p><b>pickle</b>barrel<i>kumquat</i></p>");
} }
#[test]
fn nesting_elements() {
let s = html!(html body div p sup "butts").into_string();
assert_eq!(s, "<html><body><div><p><sup>butts</sup></p></div></body></html>");
}
#[test] #[test]
fn empty_elements() { fn empty_elements() {
let s = html!("pinkie" br; "pie").into_string(); let s = html!("pinkie" br; "pie").into_string();
@ -73,7 +67,7 @@ fn simple_attributes() {
let s = html! { let s = html! {
link rel="stylesheet" href="styles.css"; link rel="stylesheet" href="styles.css";
section id="midriff" { section id="midriff" {
p class="hotpink" "Hello!" p class="hotpink" { "Hello!" }
} }
}.into_string(); }.into_string();
assert_eq!(s, concat!( assert_eq!(s, concat!(
@ -83,7 +77,7 @@ fn simple_attributes() {
#[test] #[test]
fn empty_attributes() { fn empty_attributes() {
let s = html!(div readonly? input type="checkbox" checked?;).into_string(); let s = html!(div readonly? { input type="checkbox" checked?; }).into_string();
assert_eq!(s, r#"<div readonly><input type="checkbox" checked></div>"#); assert_eq!(s, r#"<div readonly><input type="checkbox" checked></div>"#);
} }
@ -112,7 +106,7 @@ fn toggle_empty_attributes_braces() {
#[test] #[test]
fn colons_in_names() { fn colons_in_names() {
let s = html!(pon-pon:controls-alpha a on:click="yay()" "Yay!").into_string(); let s = html!(pon-pon:controls-alpha { a on:click="yay()" { "Yay!" } }).into_string();
assert_eq!(s, concat!( assert_eq!(s, concat!(
r#"<pon-pon:controls-alpha>"#, r#"<pon-pon:controls-alpha>"#,
r#"<a on:click="yay()">Yay!</a>"#, r#"<a on:click="yay()">Yay!</a>"#,
@ -151,14 +145,14 @@ fn classes_shorthand() {
#[test] #[test]
fn hyphens_in_class_names() { fn hyphens_in_class_names() {
let s = html!(p.rocks-these.are--my--rocks "yes").into_string(); let s = html!(p.rocks-these.are--my--rocks { "yes" }).into_string();
assert_eq!(s, r#"<p class="rocks-these are--my--rocks">yes</p>"#); assert_eq!(s, r#"<p class="rocks-these are--my--rocks">yes</p>"#);
} }
#[test] #[test]
fn toggle_classes() { fn toggle_classes() {
fn test(is_cupcake: bool, is_muffin: bool) -> Markup { fn test(is_cupcake: bool, is_muffin: bool) -> Markup {
html!(p.cupcake[is_cupcake].muffin[is_muffin] "Testing!") html!(p.cupcake[is_cupcake].muffin[is_muffin] { "Testing!" })
} }
assert_eq!(test(true, true).into_string(), r#"<p class="cupcake muffin">Testing!</p>"#); assert_eq!(test(true, true).into_string(), r#"<p class="cupcake muffin">Testing!</p>"#);
assert_eq!(test(false, true).into_string(), r#"<p class=" muffin">Testing!</p>"#); assert_eq!(test(false, true).into_string(), r#"<p class=" muffin">Testing!</p>"#);
@ -169,14 +163,14 @@ fn toggle_classes() {
#[test] #[test]
fn toggle_classes_braces() { fn toggle_classes_braces() {
struct Maud { rocks: bool } struct Maud { rocks: bool }
let s = html!(p.rocks[Maud { rocks: true }.rocks] "Awesome!").into_string(); let s = html!(p.rocks[Maud { rocks: true }.rocks] { "Awesome!" }).into_string();
assert_eq!(s, r#"<p class="rocks">Awesome!</p>"#); assert_eq!(s, r#"<p class="rocks">Awesome!</p>"#);
} }
#[test] #[test]
fn mixed_classes() { fn mixed_classes() {
fn test(is_muffin: bool) -> Markup { fn test(is_muffin: bool) -> Markup {
html!(p.cupcake.muffin[is_muffin].lamington "Testing!") html!(p.cupcake.muffin[is_muffin].lamington { "Testing!" })
} }
assert_eq!(test(true).into_string(), r#"<p class="cupcake lamington muffin">Testing!</p>"#); assert_eq!(test(true).into_string(), r#"<p class="cupcake lamington muffin">Testing!</p>"#);
assert_eq!(test(false).into_string(), r#"<p class="cupcake lamington">Testing!</p>"#); assert_eq!(test(false).into_string(), r#"<p class="cupcake lamington">Testing!</p>"#);

View file

@ -44,8 +44,10 @@ fn if_let() {
fn while_expr() { fn while_expr() {
let mut numbers = (0..3).into_iter().peekable(); let mut numbers = (0..3).into_iter().peekable();
let s = html! { let s = html! {
ul @while numbers.peek().is_some() { ul {
li (numbers.next().unwrap()) @while numbers.peek().is_some() {
li { (numbers.next().unwrap()) }
}
} }
}.into_string(); }.into_string();
assert_eq!(s, "<ul><li>0</li><li>1</li><li>2</li></ul>"); assert_eq!(s, "<ul><li>0</li><li>1</li><li>2</li></ul>");
@ -56,8 +58,10 @@ fn while_let_expr() {
let mut numbers = (0..3).into_iter(); let mut numbers = (0..3).into_iter();
#[cfg_attr(feature = "cargo-clippy", allow(while_let_on_iterator))] #[cfg_attr(feature = "cargo-clippy", allow(while_let_on_iterator))]
let s = html! { let s = html! {
ul @while let Some(n) = numbers.next() { ul {
li (n) @while let Some(n) = numbers.next() {
li { (n) }
}
} }
}.into_string(); }.into_string();
assert_eq!(s, "<ul><li>0</li><li>1</li><li>2</li></ul>"); assert_eq!(s, "<ul><li>0</li><li>1</li><li>2</li></ul>");
@ -67,8 +71,10 @@ fn while_let_expr() {
fn for_expr() { fn for_expr() {
let ponies = ["Apple Bloom", "Scootaloo", "Sweetie Belle"]; let ponies = ["Apple Bloom", "Scootaloo", "Sweetie Belle"];
let s = html! { let s = html! {
ul @for pony in &ponies { ul {
li (pony) @for pony in &ponies {
li { (pony) }
}
} }
}.into_string(); }.into_string();
assert_eq!(s, concat!( assert_eq!(s, concat!(
@ -85,7 +91,7 @@ fn match_expr() {
let s = html! { let s = html! {
@match input { @match input {
Some(value) => { Some(value) => {
div (value) div { (value) }
}, },
None => { None => {
"oh noes" "oh noes"
@ -102,7 +108,7 @@ fn match_expr_without_delims() {
let s = html! { let s = html! {
@match input { @match input {
Some(value) => (value), Some(value) => (value),
None => span "oh noes", None => span { "oh noes" },
} }
}.into_string(); }.into_string();
assert_eq!(s, output); assert_eq!(s, output);

View file

@ -112,7 +112,7 @@ pub struct Title<T: AsRef<str>>(pub T);
impl<T: AsRef<str>> Render for Title<T> { impl<T: AsRef<str>> Render for Title<T> {
fn render(&self) -> Markup { fn render(&self) -> Markup {
html! { html! {
title (self.0.as_ref()) title { (self.0.as_ref()) }
} }
} }
} }

View file

@ -422,11 +422,18 @@ impl Parser {
_ => { _ => {
match self.markup()? { match self.markup()? {
ast::Markup::Block(block) => ast::ElementBody::Block { block }, ast::Markup::Block(block) => ast::ElementBody::Block { block },
markup => ast::ElementBody::Block { markup => {
block: ast::Block { let markup_span = markup.span();
markups: vec![markup], markup_span
outer_span: Span::call_site(), .error("element body must be wrapped in braces")
}, .help("see https://github.com/lfairy/maud/pull/137 for details")
.emit();
ast::ElementBody::Block {
block: ast::Block {
markups: vec![markup],
outer_span: markup_span,
},
}
}, },
} }
}, },