diff --git a/.gitignore b/.gitignore index ff4c7afbdf4..a7bb055c054 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,8 @@ target/ *.iml /.idea/ /.vscode/ + +# artifacts from tools like prettier +node_modules/ +package.json +package-lock.json diff --git a/packages/yew-macro/src/html_tree/html_node.rs b/packages/yew-macro/src/html_tree/html_node.rs index 6b8022ba11a..2ad25d2be68 100644 --- a/packages/yew-macro/src/html_tree/html_node.rs +++ b/packages/yew-macro/src/html_tree/html_node.rs @@ -3,7 +3,7 @@ use quote::{quote, quote_spanned, ToTokens}; use syn::buffer::Cursor; use syn::parse::{Parse, ParseStream, Result}; use syn::spanned::Spanned; -use syn::{Expr, Lit}; +use syn::{Block, Lit, Stmt}; use super::ToNodeIterator; use crate::stringify::Stringify; @@ -11,7 +11,7 @@ use crate::PeekValue; pub enum HtmlNode { Literal(Box), - Expression(Box), + Expression(Vec), } impl Parse for HtmlNode { @@ -23,7 +23,7 @@ impl Parse for HtmlNode { } HtmlNode::Literal(Box::new(lit)) } else { - HtmlNode::Expression(Box::new(input.parse()?)) + HtmlNode::Expression(Block::parse_within(input)?) }; Ok(node) @@ -49,7 +49,17 @@ impl ToTokens for HtmlNode { let sr = lit.stringify(); quote_spanned! {lit.span()=> ::yew::virtual_dom::VText::new(#sr) } } - HtmlNode::Expression(expr) => quote! {#expr}, + HtmlNode::Expression(stmts) => { + if let [expr] = &stmts[..] { + quote! {#expr} + } else { + let mut block = TokenStream::new(); + for stmt in stmts.iter() { + stmt.to_tokens(&mut block) + } + quote_spanned! {block.span()=> {#block}} + } + } }); } } @@ -58,11 +68,23 @@ impl ToNodeIterator for HtmlNode { fn to_node_iterator_stream(&self) -> Option { match self { HtmlNode::Literal(_) => None, - HtmlNode::Expression(expr) => { - // NodeSeq turns both Into and Vec> into IntoIterator - Some(quote_spanned! {expr.span().resolved_at(Span::call_site())=> - ::std::convert::Into::<::yew::utils::NodeSeq<_, _>>::into(#expr) - }) + HtmlNode::Expression(stmts) => { + if let [expr] = &stmts[..] { + Some(quote_spanned! {expr.span().resolved_at(Span::call_site())=> + ::std::convert::Into::<::yew::utils::NodeSeq<_, _>>::into(#expr) + }) + } else { + let mut block = TokenStream::new(); + for stmt in stmts.iter() { + stmt.to_tokens(&mut block) + } + // NodeSeq turns both Into and Vec> into IntoIterator + Some( + quote_spanned! {block.span().resolved_at(Span::call_site())=> + ::std::convert::Into::<::yew::utils::NodeSeq<_, _>>::into({#block}) + }, + ) + } } } } diff --git a/packages/yew-macro/tests/html_macro/block-pass.rs b/packages/yew-macro/tests/html_macro/block-pass.rs index d8f527e6e46..aca8445925c 100644 --- a/packages/yew-macro/tests/html_macro/block-pass.rs +++ b/packages/yew-macro/tests/html_macro/block-pass.rs @@ -62,4 +62,11 @@ fn main() { { for ::std::iter::Iterator::map(0..3, item) } }; + + ::yew::html! { + { + let version = 0.21; + ::std::format!("Yew {version}") + } + }; } diff --git a/website/docs/concepts/function-components/pure-components.mdx b/website/docs/concepts/function-components/pure-components.mdx index ec6285f9ab9..d840d1fcede 100644 --- a/website/docs/concepts/function-components/pure-components.mdx +++ b/website/docs/concepts/function-components/pure-components.mdx @@ -30,7 +30,7 @@ fn HelloWorld(props: &Props) -> Html { :::note If you have an internal pure component that makes no use of hooks and other component machinery, you can often write it instead as a normal function returning `Html` and avoid a bit of overhead for Yew, related to running the component lifecycle. Use -[expression syntax](concepts/html/literals-and-expressions.mdx#expressions) to render them in `html!`. +[code block syntax](concepts/html/literals-and-expressions.mdx#code-blocks) to render them in `html!`. ::: ## Impure components diff --git a/website/docs/concepts/html/literals-and-expressions.mdx b/website/docs/concepts/html/literals-and-expressions.mdx index df1fa4dc3e6..0471de28ff4 100644 --- a/website/docs/concepts/html/literals-and-expressions.mdx +++ b/website/docs/concepts/html/literals-and-expressions.mdx @@ -1,5 +1,5 @@ --- -title: 'Literals and Expressions' +title: 'Literals and Code Blocks' --- ## Literals @@ -27,16 +27,19 @@ html!{ ## Expressions -You can insert expressions in your HTML using `{}` blocks, as long as they resolve to `Html` +You can insert blocks of Rust code in your HTML, as long as they resolve to `Html` ```rust use yew::prelude::*; -let show_link = true; +fn some_computation() -> bool { + true +} html! {
{ + let show_link = some_computation(); if show_link { html! { {"Link"}