From 0c4371343ca95e9963a5d35d5f32240eed0900e9 Mon Sep 17 00:00:00 2001 From: schvv31n Date: Fri, 13 Oct 2023 20:52:36 +0100 Subject: [PATCH 1/3] made blocks parse as blocks, updated docs, excluded npm artifacts in gitignore --- .gitignore | 5 ++++ packages/yew-macro/src/html_tree/html_node.rs | 28 +++++++++++++++---- .../yew-macro/tests/html_macro/block-pass.rs | 7 +++++ .../function-components/pure-components.mdx | 2 +- ...sions.mdx => literals-and-code-blocks.mdx} | 9 ++++-- website/sidebars/docs.js | 2 +- 6 files changed, 42 insertions(+), 11 deletions(-) rename website/docs/concepts/html/{literals-and-expressions.mdx => literals-and-code-blocks.mdx} (87%) 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..3c8dba0d742 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::{Lit, Block, 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,15 @@ 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 +66,19 @@ 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 + 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..7ec10c1b738 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-code-blocks.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-code-blocks.mdx similarity index 87% rename from website/docs/concepts/html/literals-and-expressions.mdx rename to website/docs/concepts/html/literals-and-code-blocks.mdx index df1fa4dc3e6..0471de28ff4 100644 --- a/website/docs/concepts/html/literals-and-expressions.mdx +++ b/website/docs/concepts/html/literals-and-code-blocks.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"} diff --git a/website/sidebars/docs.js b/website/sidebars/docs.js index 6d93cefb22d..429e603617d 100644 --- a/website/sidebars/docs.js +++ b/website/sidebars/docs.js @@ -87,7 +87,7 @@ module.exports = { 'concepts/html/classes', 'concepts/html/fragments', 'concepts/html/lists', - 'concepts/html/literals-and-expressions', + 'concepts/html/literals-and-code-blocks', 'concepts/html/conditional-rendering', ], }, From 6dbdf9a4d7ee402dc48110865903f130a87aefd6 Mon Sep 17 00:00:00 2001 From: schvv31n Date: Fri, 13 Oct 2023 20:58:00 +0100 Subject: [PATCH 2/3] fix formatting --- packages/yew-macro/src/html_tree/html_node.rs | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/packages/yew-macro/src/html_tree/html_node.rs b/packages/yew-macro/src/html_tree/html_node.rs index 3c8dba0d742..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::{Lit, Block, Stmt}; +use syn::{Block, Lit, Stmt}; use super::ToNodeIterator; use crate::stringify::Stringify; @@ -49,14 +49,16 @@ impl ToTokens for HtmlNode { let sr = lit.stringify(); quote_spanned! {lit.span()=> ::yew::virtual_dom::VText::new(#sr) } } - 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) + 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}} } - quote_spanned! {block.span()=> {#block}} } }); } @@ -66,19 +68,23 @@ impl ToNodeIterator for HtmlNode { fn to_node_iterator_stream(&self) -> Option { match self { HtmlNode::Literal(_) => None, - 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) + 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}) + }, + ) } - // 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}) - }) } } } From b58d22eaba0e20116bfe7099ce69238ae74b29e5 Mon Sep 17 00:00:00 2001 From: schvv31n Date: Fri, 13 Oct 2023 21:03:46 +0100 Subject: [PATCH 3/3] renamed a doc file back to its original name --- website/docs/concepts/function-components/pure-components.mdx | 2 +- ...iterals-and-code-blocks.mdx => literals-and-expressions.mdx} | 0 website/sidebars/docs.js | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename website/docs/concepts/html/{literals-and-code-blocks.mdx => literals-and-expressions.mdx} (100%) diff --git a/website/docs/concepts/function-components/pure-components.mdx b/website/docs/concepts/function-components/pure-components.mdx index 7ec10c1b738..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 -[code block syntax](concepts/html/literals-and-code-blocks.mdx#code-blocks) 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-code-blocks.mdx b/website/docs/concepts/html/literals-and-expressions.mdx similarity index 100% rename from website/docs/concepts/html/literals-and-code-blocks.mdx rename to website/docs/concepts/html/literals-and-expressions.mdx diff --git a/website/sidebars/docs.js b/website/sidebars/docs.js index 429e603617d..6d93cefb22d 100644 --- a/website/sidebars/docs.js +++ b/website/sidebars/docs.js @@ -87,7 +87,7 @@ module.exports = { 'concepts/html/classes', 'concepts/html/fragments', 'concepts/html/lists', - 'concepts/html/literals-and-code-blocks', + 'concepts/html/literals-and-expressions', 'concepts/html/conditional-rendering', ], },