From 80e8d49a4407a52aab8003111fd902c608872127 Mon Sep 17 00:00:00 2001 From: blorbb <88137137+blorbb@users.noreply.github.com> Date: Thu, 1 Aug 2024 22:02:27 +1000 Subject: [PATCH 1/8] rstml 0.12 and enforce braces in attribute values --- leptos/src/for_loop.rs | 2 +- leptos/src/hydration/mod.rs | 10 ++-- leptos/tests/ssr.rs | 14 ++--- leptos_hot_reload/Cargo.toml | 2 +- leptos_hot_reload/src/parsing.rs | 4 +- leptos_macro/Cargo.toml | 2 +- leptos_macro/src/lib.rs | 11 +++- leptos_macro/src/view/component_builder.rs | 6 +-- leptos_macro/src/view/mod.rs | 63 ++++++++++++++-------- leptos_macro/src/view/slot_helper.rs | 10 ++-- router/src/components.rs | 2 +- router/src/link.rs | 8 +-- 12 files changed, 81 insertions(+), 53 deletions(-) diff --git a/leptos/src/for_loop.rs b/leptos/src/for_loop.rs index ad33383541..34d8b47c03 100644 --- a/leptos/src/for_loop.rs +++ b/leptos/src/for_loop.rs @@ -88,7 +88,7 @@ mod tests { let values = RwSignal::new(vec![1, 2, 3, 4, 5]); let list: HtmlElement<_, _, _, Dom> = view! { <ol> - <For each=move || values.get() key=|i| *i let:i> + <For each={move || values.get()} key={|i| *i} let:i> <li>{i}</li> </For> </ol> diff --git a/leptos/src/hydration/mod.rs b/leptos/src/hydration/mod.rs index b6fe9b3734..cd0febc91e 100644 --- a/leptos/src/hydration/mod.rs +++ b/leptos/src/hydration/mod.rs @@ -25,7 +25,7 @@ pub fn AutoReload( }; let script = include_str!("reload_script.js"); - view! { <script nonce=nonce>{format!("{script}({reload_port:?}, {protocol})")}</script> } + view! { <script nonce={nonce}>{format!("{script}({reload_port:?}, {protocol})")}</script> } }) } @@ -54,15 +54,15 @@ pub fn HydrationScripts( }; view! { - <link rel="modulepreload" href=format!("/{pkg_path}/{output_name}.js") nonce=nonce.clone()/> + <link rel="modulepreload" href={format!("/{pkg_path}/{output_name}.js")} nonce={nonce.clone()}/> <link rel="preload" - href=format!("/{pkg_path}/{wasm_output_name}.wasm") + href={format!("/{pkg_path}/{wasm_output_name}.wasm")} r#as="fetch" r#type="application/wasm" - crossorigin=nonce.clone().unwrap_or_default() + crossorigin={nonce.clone().unwrap_or_default()} /> - <script type="module" nonce=nonce> + <script type="module" nonce={nonce}> {format!("{script}({pkg_path:?}, {output_name:?}, {wasm_output_name:?})")} </script> } diff --git a/leptos/tests/ssr.rs b/leptos/tests/ssr.rs index 43bd15747a..2f18c7f4f4 100644 --- a/leptos/tests/ssr.rs +++ b/leptos/tests/ssr.rs @@ -7,9 +7,9 @@ fn simple_ssr_test() { let (value, set_value) = signal(0); let rendered: HtmlElement<_, _, _, Dom> = view! { <div> - <button on:click=move |_| set_value.update(|value| *value -= 1)>"-1"</button> + <button on:click={move |_| set_value.update(|value| *value -= 1)}>"-1"</button> <span>"Value: " {move || value.get().to_string()} "!"</span> - <button on:click=move |_| set_value.update(|value| *value += 1)>"+1"</button> + <button on:click={move |_| set_value.update(|value| *value += 1)}>"+1"</button> </div> }; @@ -29,9 +29,9 @@ fn ssr_test_with_components() { let (value, set_value) = signal(initial_value); view! { <div> - <button on:click=move |_| set_value.update(|value| *value -= 1)>"-1"</button> + <button on:click={move |_| set_value.update(|value| *value -= 1)}>"-1"</button> <span>"Value: " {move || value.get().to_string()} "!"</span> - <button on:click=move |_| set_value.update(|value| *value += 1)>"+1"</button> + <button on:click={move |_| set_value.update(|value| *value += 1)}>"+1"</button> </div> } } @@ -60,9 +60,9 @@ fn ssr_test_with_snake_case_components() { let (value, set_value) = signal(initial_value); view! { <div> - <button on:click=move |_| set_value.update(|value| *value -= 1)>"-1"</button> + <button on:click={move |_| set_value.update(|value| *value -= 1)}>"-1"</button> <span>"Value: " {move || value.get().to_string()} "!"</span> - <button on:click=move |_| set_value.update(|value| *value += 1)>"+1"</button> + <button on:click={move |_| set_value.update(|value| *value += 1)}>"+1"</button> </div> } } @@ -106,7 +106,7 @@ fn ssr_with_styles() { let styles = "myclass"; let rendered: HtmlElement<_, _, _, Dom> = view! { class=styles, <div> - <button class="btn" on:click=move |_| set_value.update(|value| *value -= 1)> + <button class="btn" on:click={move |_| set_value.update(|value| *value -= 1)}> "-1" </button> </div> diff --git a/leptos_hot_reload/Cargo.toml b/leptos_hot_reload/Cargo.toml index 429098cc5b..82f4e22a85 100644 --- a/leptos_hot_reload/Cargo.toml +++ b/leptos_hot_reload/Cargo.toml @@ -20,7 +20,7 @@ syn = { version = "2", features = [ "printing", ] } quote = "1" -rstml = "0.11.2" +rstml = "0.12.0" proc-macro2 = { version = "1", features = ["span-locations", "nightly"] } parking_lot = "0.12" walkdir = "2" diff --git a/leptos_hot_reload/src/parsing.rs b/leptos_hot_reload/src/parsing.rs index 697b0d5387..e14f80196b 100644 --- a/leptos_hot_reload/src/parsing.rs +++ b/leptos_hot_reload/src/parsing.rs @@ -1,4 +1,4 @@ -use rstml::node::{NodeElement, NodeName}; +use rstml::node::{CustomNode, NodeElement, NodeName}; /// Converts `syn::Block` to simple expression /// @@ -65,6 +65,6 @@ pub fn is_component_tag_name(name: &NodeName) -> bool { } #[must_use] -pub fn is_component_node(node: &NodeElement) -> bool { +pub fn is_component_node(node: &NodeElement<impl CustomNode>) -> bool { is_component_tag_name(node.name()) } diff --git a/leptos_macro/Cargo.toml b/leptos_macro/Cargo.toml index 9fd3c60e13..760246435e 100644 --- a/leptos_macro/Cargo.toml +++ b/leptos_macro/Cargo.toml @@ -22,7 +22,7 @@ proc-macro-error = { version = "1", default-features = false } proc-macro2 = "1" quote = "1" syn = { version = "2", features = ["full"] } -rstml = "0.11.2" +rstml = "0.12.0" leptos_hot_reload = { workspace = true } server_fn_macro = { workspace = true } convert_case = "0.6.0" diff --git a/leptos_macro/src/lib.rs b/leptos_macro/src/lib.rs index cdb18eec0f..28ece8ec9f 100644 --- a/leptos_macro/src/lib.rs +++ b/leptos_macro/src/lib.rs @@ -303,10 +303,17 @@ pub fn view(tokens: TokenStream) -> TokenStream { let (nodes, errors) = parser.parse_recoverable(tokens).split_vec(); let errors = errors.into_iter().map(|e| e.emit_as_expr_tokens()); let nodes_output = view::render_view(&nodes, global_class.as_ref(), None); + + // The allow lint needs to be put here instead of at the expansion of + // view::attribute_value(). Adding this next to the expanded expression + // seems to break rust-analyzer, but it works when the allow is put here. quote! { { - #(#errors;)* - #nodes_output + #[allow(unused_braces)] + { + #(#errors;)* + #nodes_output + } } } .into() diff --git a/leptos_macro/src/view/component_builder.rs b/leptos_macro/src/view/component_builder.rs index 77ab9ebdd6..ca052602fe 100644 --- a/leptos_macro/src/view/component_builder.rs +++ b/leptos_macro/src/view/component_builder.rs @@ -3,13 +3,13 @@ use crate::view::attribute_absolute; use proc_macro2::{Ident, TokenStream, TokenTree}; use quote::{format_ident, quote, quote_spanned}; use rstml::node::{ - KeyedAttributeValue, NodeAttribute, NodeBlock, NodeElement, NodeName, + CustomNode, KeyedAttributeValue, NodeAttribute, NodeBlock, NodeElement, NodeName }; use std::collections::HashMap; use syn::{spanned::Spanned, Expr, ExprPath, ExprRange, RangeLimits, Stmt}; pub(crate) fn component_to_tokens( - node: &NodeElement, + node: &NodeElement<impl CustomNode>, global_class: Option<&TokenTree>, ) -> TokenStream { let name = node.name(); @@ -155,7 +155,7 @@ pub(crate) fn component_to_tokens( } })) } else if let NodeAttribute::Attribute(node) = attr { - attribute_absolute(node, idx >= spread_marker) + attribute_absolute(&node, idx >= spread_marker) } else { None } diff --git a/leptos_macro/src/view/mod.rs b/leptos_macro/src/view/mod.rs index e4698d00c6..0c6dc25637 100644 --- a/leptos_macro/src/view/mod.rs +++ b/leptos_macro/src/view/mod.rs @@ -11,8 +11,8 @@ use proc_macro2::{Ident, Span, TokenStream, TokenTree}; use proc_macro_error::abort; use quote::{quote, quote_spanned, ToTokens}; use rstml::node::{ - KeyedAttribute, Node, NodeAttribute, NodeBlock, NodeElement, NodeName, - NodeNameFragment, + CustomNode, KVAttributeValue, KeyedAttribute, Node, NodeAttribute, + NodeBlock, NodeElement, NodeName, NodeNameFragment, }; use std::collections::HashMap; use syn::{spanned::Spanned, Expr, ExprRange, Lit, LitStr, RangeLimits, Stmt}; @@ -55,7 +55,7 @@ pub fn render_view( } fn element_children_to_tokens( - nodes: &[Node], + nodes: &[Node<impl CustomNode>], parent_type: TagType, parent_slots: Option<&mut HashMap<String, Vec<TokenStream>>>, global_class: Option<&TokenTree>, @@ -83,7 +83,7 @@ fn element_children_to_tokens( } fn fragment_to_tokens( - nodes: &[Node], + nodes: &[Node<impl CustomNode>], parent_type: TagType, parent_slots: Option<&mut HashMap<String, Vec<TokenStream>>>, global_class: Option<&TokenTree>, @@ -108,7 +108,7 @@ fn fragment_to_tokens( } fn children_to_tokens( - nodes: &[Node], + nodes: &[Node<impl CustomNode>], parent_type: TagType, parent_slots: Option<&mut HashMap<String, Vec<TokenStream>>>, global_class: Option<&TokenTree>, @@ -152,7 +152,7 @@ fn children_to_tokens( } fn node_to_tokens( - node: &Node, + node: &Node<impl CustomNode>, parent_type: TagType, parent_slots: Option<&mut HashMap<String, Vec<TokenStream>>>, global_class: Option<&TokenTree>, @@ -185,6 +185,7 @@ fn node_to_tokens( global_class, view_marker, ), + Node::Custom(node) => Some(node.to_token_stream()), } } @@ -202,7 +203,7 @@ fn text_to_tokens(text: &LitStr) -> TokenStream { } pub(crate) fn element_to_tokens( - node: &NodeElement, + node: &NodeElement<impl CustomNode>, mut parent_type: TagType, parent_slots: Option<&mut HashMap<String, Vec<TokenStream>>>, global_class: Option<&TokenTree>, @@ -244,7 +245,7 @@ pub(crate) fn element_to_tokens( } } NodeAttribute::Attribute(node) => { - if let Some(content) = attribute_absolute(node, true) { + if let Some(content) = attribute_absolute(&node, true) { attributes.push(content); } } @@ -357,7 +358,7 @@ pub(crate) fn element_to_tokens( } } -fn is_spread_marker(node: &NodeElement) -> bool { +fn is_spread_marker(node: &NodeElement<impl CustomNode>) -> bool { match node.name() { NodeName::Block(block) => matches!( block.stmts.first(), @@ -715,7 +716,7 @@ fn is_custom_element(tag: &str) -> bool { tag.contains('-') } -fn is_self_closing(node: &NodeElement) -> bool { +fn is_self_closing(node: &NodeElement<impl CustomNode>) -> bool { // self-closing tags // https://developer.mozilla.org/en-US/docs/Glossary/Empty_element [ @@ -863,20 +864,40 @@ fn attribute_name(name: &NodeName) -> TokenStream { } fn attribute_value(attr: &KeyedAttribute) -> TokenStream { - match attr.value() { - Some(value) => { - if let Expr::Lit(lit) = value { - if cfg!(feature = "nightly") { - if let Lit::Str(str) = &lit.lit { - return quote! { - ::leptos::tachys::view::static_types::Static::<#str> - }; + match attr.possible_value.to_value() { + None => quote! { true }, + Some(value) => match &value.value { + KVAttributeValue::Expr(expr) => { + // value must be a block or literal + if !matches!(expr, Expr::Block(_) | Expr::Lit(_)) { + emit_error!( + expr.span(), + "attribute values must be surrounded by braces or be literals"; + help = "wrap the expression in braces: {{{}}}", expr.to_token_stream(), + ) + } + + if let Expr::Lit(lit) = expr { + if cfg!(feature = "nightly") { + if let Lit::Str(str) = &lit.lit { + return quote! { + ::leptos::tachys::view::static_types::Static::<#str> + }; + } } } + + quote! { + {#expr} + } } - quote! { #value } - } - None => quote! { true }, + // any value in braces: expand as-is to give proper r-a support + KVAttributeValue::InvalidBraced(block) => { + quote! { + #block + } + } + }, } } diff --git a/leptos_macro/src/view/slot_helper.rs b/leptos_macro/src/view/slot_helper.rs index bcaf6d3ea2..823bb081d9 100644 --- a/leptos_macro/src/view/slot_helper.rs +++ b/leptos_macro/src/view/slot_helper.rs @@ -2,12 +2,12 @@ use super::{convert_to_snake_case, ident_from_tag_name}; use crate::view::{fragment_to_tokens, TagType}; use proc_macro2::{Ident, TokenStream, TokenTree}; use quote::{format_ident, quote, quote_spanned}; -use rstml::node::{KeyedAttribute, NodeAttribute, NodeElement}; +use rstml::node::{CustomNode, KeyedAttribute, NodeAttribute, NodeElement}; use std::collections::HashMap; use syn::spanned::Spanned; pub(crate) fn slot_to_tokens( - node: &NodeElement, + node: &NodeElement<impl CustomNode>, slot: &KeyedAttribute, parent_slots: Option<&mut HashMap<String, Vec<TokenStream>>>, global_class: Option<&TokenTree>, @@ -32,7 +32,7 @@ pub(crate) fn slot_to_tokens( let attrs = node.attributes().iter().filter_map(|node| { if let NodeAttribute::Attribute(node) = node { - if is_slot(node) { + if is_slot(&node) { None } else { Some(node) @@ -214,10 +214,10 @@ pub(crate) fn is_slot(node: &KeyedAttribute) -> bool { key == "slot" || key.starts_with("slot:") } -pub(crate) fn get_slot(node: &NodeElement) -> Option<&KeyedAttribute> { +pub(crate) fn get_slot(node: &NodeElement<impl CustomNode>) -> Option<&KeyedAttribute> { node.attributes().iter().find_map(|node| { if let NodeAttribute::Attribute(node) = node { - if is_slot(node) { + if is_slot(&node) { Some(node) } else { None diff --git a/router/src/components.rs b/router/src/components.rs index abed6b49a0..ca580b2f74 100644 --- a/router/src/components.rs +++ b/router/src/components.rs @@ -521,7 +521,7 @@ pub fn RoutingProgress( view! { <Show when=move || is_showing.get() fallback=|| ()> - <progress min="0" max="100" value=move || progress.get()></progress> + <progress min="0" max="100" value={move || progress.get()}></progress> </Show> } } diff --git a/router/src/link.rs b/router/src/link.rs index c524af2b5b..e925450f15 100644 --- a/router/src/link.rs +++ b/router/src/link.rs @@ -115,10 +115,10 @@ where view! { <a - href=move || href.get().unwrap_or_default() - target=target - prop:state=state.map(|s| s.to_js_value()) - prop:replace=replace + href={move || href.get().unwrap_or_default()} + target={target} + prop:state={state.map(|s| s.to_js_value())} + prop:replace={replace} aria-current={ let is_active = is_active.clone(); move || if is_active.get() { Some("page") } else { None } From 23ad91b67a2f7268f319c979fbf5e65eef486bdc Mon Sep 17 00:00:00 2001 From: blorbb <88137137+blorbb@users.noreply.github.com> Date: Sat, 3 Aug 2024 22:05:26 +1000 Subject: [PATCH 2/8] run leptosfmt on examples + manual fixes --- benchmarks/src/ssr.rs | 22 +-- benchmarks/src/todomvc/leptos.rs | 65 ++++---- benchmarks/src/todomvc/mod.rs | 18 +-- benchmarks/src/todomvc/tachys.rs | 56 +++---- .../action-form-error-handling/src/app.rs | 12 +- .../action-form-error-handling/src/main.rs | 12 +- examples/counter/src/lib.rs | 6 +- examples/counter/src/main.rs | 2 +- examples/counter/tests/web.rs | 4 +- examples/counter_isomorphic/src/counters.rs | 42 ++--- examples/counter_isomorphic/src/main.rs | 10 +- examples/counter_url_query/src/lib.rs | 11 +- examples/counter_url_query/src/main.rs | 2 +- examples/counters/src/lib.rs | 30 ++-- examples/directives/src/lib.rs | 6 +- examples/directives/src/main.rs | 2 +- examples/error_boundary/src/lib.rs | 8 +- examples/errors_axum/src/error_template.rs | 13 +- examples/errors_axum/src/landing.rs | 49 +++--- examples/fetch/src/lib.rs | 10 +- examples/hackernews/src/lib.rs | 18 +-- examples/hackernews/src/main.rs | 17 ++- examples/hackernews/src/routes/nav.rs | 7 +- examples/hackernews/src/routes/stories.rs | 143 ++++++++++------- examples/hackernews/src/routes/story.rs | 125 ++++++++------- examples/hackernews/src/routes/users.rs | 62 +++++--- .../hackernews_axum/src/error_template.rs | 27 ++-- examples/hackernews_axum/src/lib.rs | 32 ++-- examples/hackernews_axum/src/routes/nav.rs | 7 +- .../hackernews_axum/src/routes/stories.rs | 143 ++++++++++------- examples/hackernews_axum/src/routes/story.rs | 125 ++++++++------- examples/hackernews_axum/src/routes/users.rs | 62 +++++--- examples/hackernews_islands_axum/src/lib.rs | 30 ++-- .../hackernews_islands_axum/src/routes/nav.rs | 7 +- .../src/routes/stories.rs | 143 ++++++++++------- .../src/routes/story.rs | 79 +++++----- .../src/routes/users.rs | 62 +++++--- examples/hackernews_js_fetch/src/lib.rs | 34 ++--- .../hackernews_js_fetch/src/routes/stories.rs | 38 ++--- .../hackernews_js_fetch/src/routes/story.rs | 30 ++-- .../hackernews_js_fetch/src/routes/users.rs | 14 +- examples/islands/src/app.rs | 34 ++--- examples/islands_router/src/app.rs | 28 ++-- examples/js-framework-benchmark/src/lib.rs | 47 +++--- examples/parent_child/src/lib.rs | 24 +-- examples/portal/src/lib.rs | 20 ++- examples/router/src/lib.rs | 49 +++--- examples/server_fns_axum/src/app.rs | 107 ++++++------- .../server_fns_axum/src/error_template.rs | 8 +- examples/slots/src/lib.rs | 16 +- examples/spread/src/lib.rs | 24 +-- examples/ssr_modes/src/app.rs | 43 +++--- examples/ssr_modes/src/main.rs | 17 ++- examples/ssr_modes_axum/src/app.rs | 117 +++++++------- examples/stores/src/lib.rs | 40 ++--- examples/suspense_tests/src/app.rs | 144 +++++++++--------- examples/suspense_tests/src/main.rs | 10 +- examples/tailwind_actix/src/app.rs | 20 +-- examples/tailwind_actix/src/main.rs | 17 ++- examples/tailwind_axum/src/app.rs | 34 +++-- examples/tailwind_csr/src/app.rs | 20 +-- examples/timer/src/lib.rs | 13 +- examples/todo_app_sqlite/src/main.rs | 10 +- examples/todo_app_sqlite/src/todo.rs | 16 +- examples/todo_app_sqlite_axum/src/todo.rs | 35 +++-- .../todo_app_sqlite_csr/src/error_template.rs | 33 ++-- examples/todo_app_sqlite_csr/src/fallback.rs | 14 +- examples/todo_app_sqlite_csr/src/todo.rs | 35 +++-- examples/todomvc/src/lib.rs | 52 +++---- integrations/actix/tests/extract_routes.rs | 30 ++-- leptos/src/animated_show.rs | 4 +- leptos/src/await_.rs | 2 +- leptos/src/hydration/mod.rs | 6 +- leptos/tests/ssr.rs | 12 +- leptos_dom/examples/hydration-test/src/lib.rs | 12 +- .../examples/hydration-test/src/main.rs | 2 +- leptos_dom/examples/test-bench/src/main.rs | 72 ++++----- leptos_dom/examples/view-tests/src/main.rs | 124 ++++++++++----- leptos_macro/example/src/lib.rs | 8 +- leptos_macro/tests/ui/component_absolute.rs | 4 +- projects/bevy3d_ui/src/main.rs | 2 +- projects/bevy3d_ui/src/routes/demo1.rs | 10 +- projects/bevy3d_ui/src/routes/mod.rs | 14 +- projects/counter_dwarf_debug/src/lib.rs | 8 +- projects/counter_dwarf_debug/src/main.rs | 7 +- .../client/src/components/credentials.rs | 26 ++-- .../client/src/components/navbar.rs | 15 +- .../client/src/lib.rs | 30 ++-- .../client/src/main.rs | 2 +- .../client/src/pages/home.rs | 7 +- .../client/src/pages/login.rs | 6 +- .../client/src/pages/register.rs | 14 +- .../meilisearch-searchbar/src/fallback.rs | 2 +- projects/meilisearch-searchbar/src/lib.rs | 66 +++++--- projects/nginx-mpmc/app-1/src/app.rs | 50 +++--- .../nginx-mpmc/app-1/src/error_template.rs | 12 +- projects/nginx-mpmc/app-2/src/app.rs | 29 ++-- .../nginx-mpmc/app-2/src/error_template.rs | 12 +- .../openapi-openai-api-swagger-ui/src/app.rs | 112 +++++++------- .../src/error_template.rs | 12 +- .../ory-kratos/app/src/auth/kratos_error.rs | 15 +- .../ory-kratos/app/src/auth/kratos_html.rs | 72 +++++---- projects/ory-kratos/app/src/auth/login.rs | 108 +++++++------ projects/ory-kratos/app/src/auth/logout.rs | 8 +- projects/ory-kratos/app/src/auth/recovery.rs | 107 +++++++------ .../ory-kratos/app/src/auth/registration.rs | 129 +++++++++------- projects/ory-kratos/app/src/auth/session.rs | 10 +- projects/ory-kratos/app/src/auth/settings.rs | 101 +++++++----- .../ory-kratos/app/src/auth/verification.rs | 100 +++++++----- projects/ory-kratos/app/src/error_template.rs | 12 +- projects/ory-kratos/app/src/lib.rs | 52 ++++--- .../ory-kratos/app/src/posts/create_posts.rs | 14 +- projects/ory-kratos/app/src/posts/post.rs | 36 ++--- .../ory-kratos/app/src/posts/posts_page.rs | 52 ++++--- projects/ory-kratos/server/src/fileserv.rs | 2 +- .../session_auth_axum/src/error_template.rs | 8 +- projects/session_auth_axum/src/fallback.rs | 2 +- projects/session_auth_axum/src/todo.rs | 70 ++++----- projects/sitemap_axum/src/app.rs | 19 +-- projects/sitemap_axum/src/error_template.rs | 12 +- projects/sso_auth_axum/src/error_template.rs | 26 ++-- projects/sso_auth_axum/src/lib.rs | 28 ++-- projects/sso_auth_axum/src/main.rs | 2 +- projects/sso_auth_axum/src/sign_in_sign_up.rs | 57 ++++--- .../src-orig/src/fallback.rs | 2 +- .../tauri-from-scratch/src-orig/src/lib.rs | 13 +- router/src/components.rs | 6 +- 127 files changed, 2411 insertions(+), 1976 deletions(-) diff --git a/benchmarks/src/ssr.rs b/benchmarks/src/ssr.rs index 159eef8cd1..bcc699d9f2 100644 --- a/benchmarks/src/ssr.rs +++ b/benchmarks/src/ssr.rs @@ -11,20 +11,24 @@ fn leptos_ssr_bench(b: &mut Bencher) { let (value, set_value) = create_signal(initial); view! { <div> - <button on:click=move |_| set_value.update(|value| *value -= 1)>"-1"</button> + <button on:click={move |_| { + set_value.update(|value| *value -= 1) + }}>"-1"</button> <span>"Value: " {move || value().to_string()} "!"</span> - <button on:click=move |_| set_value.update(|value| *value += 1)>"+1"</button> + <button on:click={move |_| { + set_value.update(|value| *value += 1) + }}>"+1"</button> </div> } } - let rendered = view! { + let rendered = view! { <main> <h1>"Welcome to our benchmark page."</h1> <p>"Here's some introductory text."</p> - <Counter initial=1/> - <Counter initial=2/> - <Counter initial=3/> + <Counter initial=1 /> + <Counter initial=2 /> + <Counter initial=3 /> </main> }.into_view().render_to_string(); @@ -51,14 +55,14 @@ fn tachys_ssr_bench(b: &mut Bencher) { let (value, set_value) = create_signal(initial); view! { <div> - <button on:click=move |_| set_value.update(|value| *value -= 1)>"-1"</button> + <button on:click={move |_| set_value.update(|value| *value -= 1)}>"-1"</button> <span>"Value: " {move || value().to_string()} "!"</span> - <button on:click=move |_| set_value.update(|value| *value += 1)>"+1"</button> + <button on:click={move |_| set_value.update(|value| *value += 1)}>"+1"</button> </div> } } - let rendered = view! { + let rendered = view! { <main> <h1>"Welcome to our benchmark page."</h1> <p>"Here's some introductory text."</p> diff --git a/benchmarks/src/todomvc/leptos.rs b/benchmarks/src/todomvc/leptos.rs index aed57ed8df..17c853a6bc 100644 --- a/benchmarks/src/todomvc/leptos.rs +++ b/benchmarks/src/todomvc/leptos.rs @@ -167,7 +167,7 @@ pub fn TodoMVC(todos: Todos) -> impl IntoView { } }); - view! { + view! { <main> <section class="todoapp"> <header class="header"> @@ -176,32 +176,34 @@ pub fn TodoMVC(todos: Todos) -> impl IntoView { class="new-todo" placeholder="What needs to be done?" autofocus="" - on:keydown=add_todo + on:keydown={add_todo} /> </header> - <section class="main" class:hidden=move || todos.with(|t| t.is_empty())> + <section class="main" class:hidden={move || todos.with(|t| t.is_empty())}> <input id="toggle-all" class="toggle-all" type="checkbox" - prop:checked=move || todos.with(|t| t.remaining() > 0) - on:input=move |_| set_todos.update(|t| t.toggle_all()) + prop:checked={move || todos.with(|t| t.remaining() > 0)} + on:input={move |_| set_todos.update(|t| t.toggle_all())} /> <label for="toggle-all">"Mark all as complete"</label> <ul class="todo-list"> <For - each=filtered_todos - key=|todo| todo.id - children=move |todo: Todo| { - view! { <Todo todo=todo.clone()/> } - } + each={filtered_todos} + key={|todo| todo.id} + children={move |todo: Todo| { + view! { <Todo todo={todo.clone()} /> } + }} /> </ul> </section> - <footer class="footer" class:hidden=move || todos.with(|t| t.is_empty())> + <footer class="footer" class:hidden={move || todos.with(|t| t.is_empty())}> <span class="todo-count"> <strong>{move || todos.with(|t| t.remaining().to_string())}</strong> - {move || if todos.with(|t| t.remaining()) == 1 { " item" } else { " items" }} + {move || { + if todos.with(|t| t.remaining()) == 1 { " item" } else { " items" } + }} " left" </span> <ul class="filters"> @@ -209,26 +211,29 @@ pub fn TodoMVC(todos: Todos) -> impl IntoView { <a href="#/" class="selected" - class:selected=move || mode() == Mode::All + class:selected={move || mode() == Mode::All} > "All" </a> </li> <li> - <a href="#/active" class:selected=move || mode() == Mode::Active> + <a href="#/active" class:selected={move || mode() == Mode::Active}> "Active" </a> </li> <li> - <a href="#/completed" class:selected=move || mode() == Mode::Completed> + <a + href="#/completed" + class:selected={move || mode() == Mode::Completed} + > "Completed" </a> </li> </ul> <button class="clear-completed hidden" - class:hidden=move || todos.with(|t| t.completed() == 0) - on:click=move |_| set_todos.update(|t| t.clear_completed()) + class:hidden={move || todos.with(|t| t.completed() == 0)} + on:click={move |_| set_todos.update(|t| t.clear_completed())} > "Clear completed" </button> @@ -259,33 +264,35 @@ pub fn Todo(todo: Todo) -> impl IntoView { set_editing(false); }; - view! { - <li class="todo" class:editing=editing class:completed=move || (todo.completed)()> + view! { + <li class="todo" class:editing={editing} class:completed={move || (todo.completed)()}> <div class="view"> - <input class="toggle" type="checkbox" prop:checked=move || (todo.completed)()/> - <label on:dblclick=move |_| set_editing(true)>{move || todo.title.get()}</label> + <input class="toggle" type="checkbox" prop:checked={move || (todo.completed)()} /> + <label on:dblclick={move |_| set_editing(true)}>{move || todo.title.get()}</label> <button class="destroy" - on:click=move |_| set_todos.update(|t| t.remove(todo.id)) + on:click={move |_| set_todos.update(|t| t.remove(todo.id))} ></button> </div> {move || { editing() .then(|| { - view! { + view! { <input class="edit" - class:hidden=move || !(editing)() - prop:value=move || todo.title.get() - on:focusout=move |ev| save(&event_target_value(&ev)) - on:keyup=move |ev| { - let key_code = ev.unchecked_ref::<web_sys::KeyboardEvent>().key_code(); + class:hidden={move || !(editing)()} + prop:value={move || todo.title.get()} + on:focusout={move |ev| save(&event_target_value(&ev))} + on:keyup={move |ev| { + let key_code = ev + .unchecked_ref::<web_sys::KeyboardEvent>() + .key_code(); if key_code == ENTER_KEY { save(&event_target_value(&ev)); } else if key_code == ESCAPE_KEY { set_editing(false); } - } + }} /> } }) diff --git a/benchmarks/src/todomvc/mod.rs b/benchmarks/src/todomvc/mod.rs index 35536c12ab..0db37084e5 100644 --- a/benchmarks/src/todomvc/mod.rs +++ b/benchmarks/src/todomvc/mod.rs @@ -14,7 +14,7 @@ fn leptos_todomvc_ssr(b: &mut Bencher) { use crate::todomvc::leptos::*; let html = ::leptos::ssr::render_to_string(|| { - view! { <TodoMVC todos=Todos::new()/> } + view! { <TodoMVC todos={Todos::new()} /> } }); assert!(html.len() > 1); }); @@ -45,10 +45,7 @@ fn sycamore_todomvc_ssr(b: &mut Bencher) { b.iter(|| { _ = create_scope(|cx| { let rendered = render_to_string(|cx| { - view! { - cx, - App() - } + view! { cx, App() } }); assert!(rendered.len() > 1); @@ -77,9 +74,7 @@ fn leptos_todomvc_ssr_with_1000(b: &mut Bencher) { use ::leptos::*; let html = ::leptos::ssr::render_to_string(|| { - view! { - <TodoMVC todos=Todos::new_with_1000()/> - } + view! { <TodoMVC todos={Todos::new_with_1000()} /> } }); assert!(html.len() > 1); }); @@ -107,10 +102,7 @@ fn sycamore_todomvc_ssr_with_1000(b: &mut Bencher) { b.iter(|| { _ = create_scope(|cx| { let rendered = render_to_string(|cx| { - view! { - cx, - AppWith1000() - } + view! { cx, AppWith1000() } }); assert!(rendered.len() > 1); @@ -140,7 +132,7 @@ fn tera_todomvc_ssr(b: &mut Bencher) { use crate::todomvc::leptos::*; let html = ::leptos::ssr::render_to_string(|| { - view! { <TodoMVC todos=Todos::new()/> } + view! { <TodoMVC todos={Todos::new()} /> } }); assert!(html.len() > 1); }); diff --git a/benchmarks/src/todomvc/tachys.rs b/benchmarks/src/todomvc/tachys.rs index c8a6fb31b4..1d0fa81be2 100644 --- a/benchmarks/src/todomvc/tachys.rs +++ b/benchmarks/src/todomvc/tachys.rs @@ -182,31 +182,27 @@ pub fn TodoMVC(todos: Todos) -> impl Render<Dom> + RenderHtml<Dom> { <section class="todoapp"> <header class="header"> <h1>"todos"</h1> - <input - class="new-todo" - placeholder="What needs to be done?" - autofocus - /> + <input class="new-todo" placeholder="What needs to be done?" autofocus /> </header> - <section class="main" class:hidden=move || todos.with(|t| t.is_empty())> + <section class="main" class:hidden={move || todos.with(|t| t.is_empty())}> <input id="toggle-all" class="toggle-all" r#type="checkbox" - //prop:checked=move || todos.with(|t| t.remaining() > 0) - on:input=move |_| set_todos.update(|t| t.toggle_all()) + // prop:checked=move || todos.with(|t| t.remaining() > 0) + on:input={move |_| set_todos.update(|t| t.toggle_all())} /> <label r#for="toggle-all">"Mark all as complete"</label> <ul class="todo-list"> - {move || { - keyed(filtered_todos.get(), |todo| todo.id, Todo) - }} + {move || { keyed(filtered_todos.get(), |todo| todo.id, Todo) }} </ul> </section> - <footer class="footer" class:hidden=move || todos.with(|t| t.is_empty())> + <footer class="footer" class:hidden={move || todos.with(|t| t.is_empty())}> <span class="todo-count"> <strong>{move || todos.with(|t| t.remaining().to_string())}</strong> - {move || if todos.with(|t| t.remaining()) == 1 { " item" } else { " items" }} + {move || { + if todos.with(|t| t.remaining()) == 1 { " item" } else { " items" } + }} " left" </span> <ul class="filters"> @@ -214,26 +210,29 @@ pub fn TodoMVC(todos: Todos) -> impl Render<Dom> + RenderHtml<Dom> { <a href="#/" class="selected" - class:selected=move || mode() == Mode::All + class:selected={move || mode() == Mode::All} > "All" </a> </li> <li> - <a href="#/active" class:selected=move || mode() == Mode::Active> + <a href="#/active" class:selected={move || mode() == Mode::Active}> "Active" </a> </li> <li> - <a href="#/completed" class:selected=move || mode() == Mode::Completed> + <a + href="#/completed" + class:selected={move || mode() == Mode::Completed} + > "Completed" </a> </li> </ul> <button class="clear-completed hidden" - class:hidden=move || todos.with(|t| t.completed() == 0) - on:click=move |_| set_todos.update(|t| t.clear_completed()) + class:hidden={move || todos.with(|t| t.completed() == 0)} + on:click={move |_| set_todos.update(|t| t.clear_completed())} > "Clear completed" </button> @@ -264,26 +263,7 @@ pub fn Todo(todo: Todo) -> impl Render<Dom> + RenderHtml<Dom> { }; view! { - <li class="todo" class:editing=editing class:completed=move || (todo.completed)()> - /* <div class="view"> - <input class="toggle" r#type="checkbox"/> - <label on:dblclick=move |_| set_editing(true)>{move || todo.title.get()}</label> - <button - class="destroy" - on:click=move |_| set_todos.update(|t| t.remove(todo.id)) - ></button> - </div> - {move || { - editing() - .then(|| { - view! { - <input - class="edit" - class:hidden=move || !(editing)() - /> - } - }) - }} */ + <li class="todo" class:editing={editing} class:completed={move || (todo.completed)()}> </li> } } diff --git a/examples/action-form-error-handling/src/app.rs b/examples/action-form-error-handling/src/app.rs index fd380f48e1..811b07eca2 100644 --- a/examples/action-form-error-handling/src/app.rs +++ b/examples/action-form-error-handling/src/app.rs @@ -10,8 +10,8 @@ pub fn App() -> impl IntoView { // content for this welcome page <Router> <main id="app"> - <FlatRoutes fallback=NotFound> - <Route path=StaticSegment("") view=HomePage/> + <FlatRoutes fallback={NotFound}> + <Route path={StaticSegment("")} view={HomePage} /> </FlatRoutes> </main> </Router> @@ -48,12 +48,10 @@ fn HomePage() -> impl IntoView { view! { <h1>"Test the action form!"</h1> - <ErrorBoundary fallback=move |error| { - move || format!("{:#?}", error.get()) - }> + <ErrorBoundary fallback={move |error| { move || format!("{:#?}", error.get()) }}> <pre>{value}</pre> - <ActionForm action=do_something_action attr:class="form"> - <label>"Should error: "<input type="checkbox" name="should_error"/></label> + <ActionForm action={do_something_action} attr:class="form"> + <label>"Should error: "<input type="checkbox" name="should_error" /></label> <button type="submit">Submit</button> </ActionForm> </ErrorBoundary> diff --git a/examples/action-form-error-handling/src/main.rs b/examples/action-form-error-handling/src/main.rs index 244cf1e827..da7f775fcb 100644 --- a/examples/action-form-error-handling/src/main.rs +++ b/examples/action-form-error-handling/src/main.rs @@ -27,20 +27,20 @@ async fn main() -> std::io::Result<()> { use leptos::prelude::*; view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> + <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> - <AutoReload options=leptos_options.clone()/> - <HydrationScripts options=leptos_options.clone()/> - <MetaTags/> + <AutoReload options={leptos_options.clone()} /> + <HydrationScripts options={leptos_options.clone()} /> + <MetaTags /> </head> <body> - <App/> + <App /> </body> </html> } diff --git a/examples/counter/src/lib.rs b/examples/counter/src/lib.rs index 5f9b488257..1b7c54b5e0 100644 --- a/examples/counter/src/lib.rs +++ b/examples/counter/src/lib.rs @@ -14,10 +14,10 @@ pub fn SimpleCounter( view! { <div> - <button on:click=move |_| set_value.set(0)>"Clear"</button> - <button on:click=move |_| *set_value.write() -= step>"-1"</button> + <button on:click={move |_| set_value.set(0)}>"Clear"</button> + <button on:click={move |_| *set_value.write() -= step}>"-1"</button> <span>"Value: " {value} "!"</span> - <button on:click=move |_| set_value.update(|value| *value += step)>"+1"</button> + <button on:click={move |_| set_value.update(|value| *value += step)}>"+1"</button> </div> } } diff --git a/examples/counter/src/main.rs b/examples/counter/src/main.rs index 6cdabd06c8..bc7f6eb02a 100644 --- a/examples/counter/src/main.rs +++ b/examples/counter/src/main.rs @@ -5,6 +5,6 @@ pub fn main() { _ = console_log::init_with_level(log::Level::Debug); console_error_panic_hook::set_once(); mount_to_body(|| { - view! { <SimpleCounter initial_value=0 step=1/> } + view! { <SimpleCounter initial_value=0 step=1 /> } }) } diff --git a/examples/counter/tests/web.rs b/examples/counter/tests/web.rs index a4f92da5a0..eef5da370b 100644 --- a/examples/counter/tests/web.rs +++ b/examples/counter/tests/web.rs @@ -17,7 +17,7 @@ async fn clear() { // note that we start at the initial value of 10 let _dispose = mount_to( test_wrapper.clone().unchecked_into(), - || view! { <SimpleCounter initial_value=10 step=1/> }, + || view! { <SimpleCounter initial_value=10 step=1 /> }, ); // now we extract the buttons by iterating over the DOM @@ -85,7 +85,7 @@ async fn inc() { let _dispose = mount_to( test_wrapper.clone().unchecked_into(), - || view! { <SimpleCounter initial_value=0 step=1/> }, + || view! { <SimpleCounter initial_value=0 step=1 /> }, ); // You can do testing with vanilla DOM operations diff --git a/examples/counter_isomorphic/src/counters.rs b/examples/counter_isomorphic/src/counters.rs index 4a77636eb9..7c1276ebd8 100644 --- a/examples/counter_isomorphic/src/counters.rs +++ b/examples/counter_isomorphic/src/counters.rs @@ -75,10 +75,10 @@ pub fn Counters() -> impl IntoView { </ul> </nav> <main> - <FlatRoutes fallback=|| "Not found."> - <Route path=StaticSegment("") view=Counter/> - <Route path=StaticSegment("form") view=FormCounter/> - <Route path=StaticSegment("multi") view=MultiuserCounter/> + <FlatRoutes fallback={|| "Not found."}> + <Route path={StaticSegment("")} view={Counter} /> + <Route path={StaticSegment("form")} view={FormCounter} /> + <Route path={StaticSegment("multi")} view={MultiuserCounter} /> </FlatRoutes> </main> </Router> @@ -111,12 +111,12 @@ pub fn Counter() -> impl IntoView { <p> "This counter sets the value on the server and automatically reloads the new value." </p> - <ErrorBoundary fallback=|errors| move || format!("Error: {:#?}", errors.get())> + <ErrorBoundary fallback={|errors| move || format!("Error: {:#?}", errors.get())}> <div> - <button on:click=move |_| clear.dispatch(())>"Clear"</button> - <button on:click=move |_| dec.dispatch(())>"-1"</button> + <button on:click={move |_| clear.dispatch(())}>"Clear"</button> + <button on:click={move |_| dec.dispatch(())}>"-1"</button> <span>"Value: " <Suspense>{counter} "!"</Suspense></span> - <button on:click=move |_| inc.dispatch(())>"+1"</button> + <button on:click={move |_| inc.dispatch(())}>"+1"</button> </div> </ErrorBoundary> </div> @@ -154,21 +154,21 @@ pub fn FormCounter() -> impl IntoView { <div> // calling a server function is the same as POSTing to its API URL // so we can just do that with a form and button - <ActionForm action=clear> - <input type="submit" value="Clear"/> + <ActionForm action={clear}> + <input type="submit" value="Clear" /> </ActionForm> // We can submit named arguments to the server functions // by including them as input values with the same name - <ActionForm action=adjust> - <input type="hidden" name="delta" value="-1"/> - <input type="hidden" name="msg" value="form value down"/> - <input type="submit" value="-1"/> + <ActionForm action={adjust}> + <input type="hidden" name="delta" value="-1" /> + <input type="hidden" name="msg" value="form value down" /> + <input type="submit" value="-1" /> </ActionForm> <span>"Value: " <Suspense>{value} "!"</Suspense></span> - <ActionForm action=adjust> - <input type="hidden" name="delta" value="1"/> - <input type="hidden" name="msg" value="form value up"/> - <input type="submit" value="+1"/> + <ActionForm action={adjust}> + <input type="hidden" name="delta" value="1" /> + <input type="hidden" name="msg" value="form value up" /> + <input type="submit" value="+1" /> </ActionForm> </div> </div> @@ -224,12 +224,12 @@ pub fn MultiuserCounter() -> impl IntoView { "This one uses server-sent events (SSE) to live-update when other users make changes." </p> <div> - <button on:click=move |_| clear.dispatch(())>"Clear"</button> - <button on:click=move |_| dec.dispatch(())>"-1"</button> + <button on:click={move |_| clear.dispatch(())}>"Clear"</button> + <button on:click={move |_| dec.dispatch(())}>"-1"</button> <span> "Multiplayer Value: " {move || multiplayer_value.get().unwrap_or_default()} </span> - <button on:click=move |_| inc.dispatch(())>"+1"</button> + <button on:click={move |_| inc.dispatch(())}>"+1"</button> </div> </div> } diff --git a/examples/counter_isomorphic/src/main.rs b/examples/counter_isomorphic/src/main.rs index 1a08d51d18..b9db5955ba 100644 --- a/examples/counter_isomorphic/src/main.rs +++ b/examples/counter_isomorphic/src/main.rs @@ -46,19 +46,19 @@ async fn main() -> std::io::Result<()> { let leptos_options = leptos_options.clone(); move || { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> + <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> - <AutoReload options=leptos_options.clone()/> - <HydrationScripts options=leptos_options.clone()/> + <AutoReload options={leptos_options.clone()} /> + <HydrationScripts options={leptos_options.clone()} /> </head> <body> - <Counters/> + <Counters /> </body> </html> } diff --git a/examples/counter_url_query/src/lib.rs b/examples/counter_url_query/src/lib.rs index 8e16305427..fef76dfcf8 100644 --- a/examples/counter_url_query/src/lib.rs +++ b/examples/counter_url_query/src/lib.rs @@ -23,17 +23,14 @@ pub fn SimpleQueryCounter() -> impl IntoView { view! { <div> - <button on:click=clear>"Clear"</button> - <button on:click=decrement>"-1"</button> + <button on:click={clear}>"Clear"</button> + <button on:click={decrement}>"-1"</button> <span>"Value: " {move || count.get().unwrap_or(0)} "!"</span> - <button on:click=increment>"+1"</button> + <button on:click={increment}>"+1"</button> <br /> - <input - prop:value=move || msg.get().unwrap_or_default() - on:input=update_msg - /> + <input prop:value={move || msg.get().unwrap_or_default()} on:input={update_msg} /> </div> } } diff --git a/examples/counter_url_query/src/main.rs b/examples/counter_url_query/src/main.rs index 81e515a790..1d1e5264ff 100644 --- a/examples/counter_url_query/src/main.rs +++ b/examples/counter_url_query/src/main.rs @@ -7,7 +7,7 @@ pub fn main() { leptos::mount::mount_to_body(|| { view! { <Router> - <SimpleQueryCounter/> + <SimpleQueryCounter /> </Router> } }) diff --git a/examples/counters/src/lib.rs b/examples/counters/src/lib.rs index e6be7e9c10..e087d0b5a7 100644 --- a/examples/counters/src/lib.rs +++ b/examples/counters/src/lib.rs @@ -39,9 +39,9 @@ pub fn Counters() -> impl IntoView { view! { <div> - <button on:click=add_counter>"Add Counter"</button> - <button on:click=add_many_counters>{format!("Add {MANY_COUNTERS} Counters")}</button> - <button on:click=clear_counters>"Clear Counters"</button> + <button on:click={add_counter}>"Add Counter"</button> + <button on:click={add_many_counters}>{format!("Add {MANY_COUNTERS} Counters")}</button> + <button on:click={clear_counters}>"Clear Counters"</button> <p> "Total: " <span> @@ -54,11 +54,11 @@ pub fn Counters() -> impl IntoView { </p> <ul> <For - each=move || counters.get() - key=|counter| counter.0 - children=move |(id, value)| { - view! { <Counter id value/> } - } + each={move || counters.get()} + key={|counter| counter.0} + children={move |(id, value)| { + view! { <Counter id value /> } + }} /> </ul> @@ -73,21 +73,21 @@ fn Counter(id: usize, value: ArcRwSignal<i32>) -> impl IntoView { view! { <li> - <button on:click=move |_| value.update(move |value| *value -= 1)>"-1"</button> + <button on:click={move |_| value.update(move |value| *value -= 1)}>"-1"</button> <input type="text" - prop:value=value - on:input:target=move |ev| { + prop:value={value} + on:input:target={move |ev| { value.set(ev.target().value().parse::<i32>().unwrap_or_default()) - } + }} /> <span>{value}</span> - <button on:click=move |_| value.update(move |value| *value += 1)>"+1"</button> - <button on:click=move |_| { + <button on:click={move |_| value.update(move |value| *value += 1)}>"+1"</button> + <button on:click={move |_| { set_counters .update(move |counters| counters.retain(|(counter_id, _)| counter_id != &id)) - }>"x"</button> + }}>"x"</button> </li> } } diff --git a/examples/directives/src/lib.rs b/examples/directives/src/lib.rs index 737e37f4f5..9bd4739ede 100644 --- a/examples/directives/src/lib.rs +++ b/examples/directives/src/lib.rs @@ -82,7 +82,11 @@ pub fn App() -> impl IntoView { let data = "Hello World!"; view! { - <a href="#" use:copy_to_clipboard=data>"Copy \"" {data} "\" to clipboard"</a> + <a href="#" use:copy_to_clipboard={data}> + "Copy \"" + {data} + "\" to clipboard" + </a> // automatically applies the directive to every root element in `SomeComponent` <SomeComponent use:highlight /> // no value will default to `().into()` diff --git a/examples/directives/src/main.rs b/examples/directives/src/main.rs index cfc58cd616..ed65037bc9 100644 --- a/examples/directives/src/main.rs +++ b/examples/directives/src/main.rs @@ -4,5 +4,5 @@ use leptos::prelude::*; fn main() { _ = console_log::init_with_level(log::Level::Debug); console_error_panic_hook::set_once(); - mount_to_body(|| view! { <App/> }) + mount_to_body(|| view! { <App /> }) } diff --git a/examples/error_boundary/src/lib.rs b/examples/error_boundary/src/lib.rs index 0838706aec..bb3a222c20 100644 --- a/examples/error_boundary/src/lib.rs +++ b/examples/error_boundary/src/lib.rs @@ -10,15 +10,15 @@ pub fn App() -> impl IntoView { "Type an integer (or something that's not an integer!)" <input type="number" - value=move || value.get().unwrap_or_default() + value={move || value.get().unwrap_or_default()} // when input changes, try to parse a number from the input - on:input:target=move |ev| set_value.set(ev.target().value().parse::<i32>()) + on:input:target={move |ev| set_value.set(ev.target().value().parse::<i32>())} /> // If an `Err(_) has been rendered inside the <ErrorBoundary/>, // the fallback will be displayed. Otherwise, the children of the // <ErrorBoundary/> will be displayed. // the fallback receives a signal containing current errors - <ErrorBoundary fallback=|errors| { + <ErrorBoundary fallback={|errors| { let errors = errors.clone(); view! { <div class="error"> @@ -37,7 +37,7 @@ pub fn App() -> impl IntoView { </ul> </div> } - }> + }}> <p> "You entered " diff --git a/examples/errors_axum/src/error_template.rs b/examples/errors_axum/src/error_template.rs index d59ef4d887..bd87882753 100644 --- a/examples/errors_axum/src/error_template.rs +++ b/examples/errors_axum/src/error_template.rs @@ -31,19 +31,14 @@ pub fn ErrorTemplate( } view! { - <h1>{move || { - if errors.read().len() > 1 { - "Errors" - } else { - "Error" - }}} - </h1> + <h1>{move || { if errors.read().len() > 1 { "Errors" } else { "Error" } }}</h1> {move || { - errors.get() + errors + .get() .into_iter() .map(|error| { let error_string = error.to_string(); - let error_code= error.status_code(); + let error_code = error.status_code(); view! { <h2>{error_code.to_string()}</h2> <p>"Error: " {error_string}</p> diff --git a/examples/errors_axum/src/landing.rs b/examples/errors_axum/src/landing.rs index 4fe0d0f768..88aa5c0b21 100644 --- a/examples/errors_axum/src/landing.rs +++ b/examples/errors_axum/src/landing.rs @@ -18,17 +18,17 @@ pub async fn cause_internal_server_error() -> Result<(), ServerFnError> { pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1"/> - <AutoReload options=options.clone() /> - <HydrationScripts options/> - <MetaTags/> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <AutoReload options={options.clone()} /> + <HydrationScripts options /> + <MetaTags /> </head> <body> - <App/> + <App /> </body> </html> } @@ -38,22 +38,19 @@ pub fn shell(options: LeptosOptions) -> impl IntoView { pub fn App() -> impl IntoView { provide_meta_context(); view! { - <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico"/> - <Stylesheet id="leptos" href="/pkg/errors_axum.css"/> + <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico" /> + <Stylesheet id="leptos" href="/pkg/errors_axum.css" /> <Router> <header> <h1>"Error Examples:"</h1> </header> <main> - <Routes fallback=|| { + <Routes fallback={|| { let mut errors = Errors::default(); errors.insert_with_default_key(AppError::NotFound); - view! { - <ErrorTemplate errors/> - } - .into_view() - }> - <Route path=StaticSegment("") view=ExampleErrors/> + view! { <ErrorTemplate errors /> }.into_view() + }}> + <Route path={StaticSegment("")} view={ExampleErrors} /> </Routes> </main> </Router> @@ -67,23 +64,27 @@ pub fn ExampleErrors() -> impl IntoView { view! { <p> - "These links will load 404 pages since they do not exist. Verify with browser development tools: " <br/> - <a href="/404">"This links to a page that does not exist"</a><br/> - <a href="/404" target="_blank">"Same link, but in a new tab"</a> + "These links will load 404 pages since they do not exist. Verify with browser development tools: " + <br /> <a href="/404">"This links to a page that does not exist"</a><br /> + <a href="/404" target="_blank"> + "Same link, but in a new tab" + </a> </p> <p> "After pressing this button check browser network tools. Can be used even when WASM is blocked:" </p> - <ActionForm action=generate_internal_error> - <input name="error1" type="submit" value="Generate Internal Server Error"/> + <ActionForm action={generate_internal_error}> + <input name="error1" type="submit" value="Generate Internal Server Error" /> </ActionForm> - <p>"The following <div> will always contain an error and cause this page to produce status 500. Check browser dev tools. "</p> + <p> + "The following <div> will always contain an error and cause this page to produce status 500. Check browser dev tools. " + </p> <div> // note that the error boundaries could be placed above in the Router or lower down // in a particular route. The generated errors on the entire page contribute to the // final status code sent by the server when producing ssr pages. - <ErrorBoundary fallback=|errors| view!{ <ErrorTemplate errors/>}> - <ReturnsError/> + <ErrorBoundary fallback={|errors| view! { <ErrorTemplate errors /> }}> + <ReturnsError /> </ErrorBoundary> </div> } diff --git a/examples/fetch/src/lib.rs b/examples/fetch/src/lib.rs index 52a200458c..2cfbc55ae1 100644 --- a/examples/fetch/src/lib.rs +++ b/examples/fetch/src/lib.rs @@ -74,15 +74,15 @@ pub fn fetch_example() -> impl IntoView { "How many cats would you like?" <input type="number" - prop:value=move || cat_count.get().to_string() - on:input:target=move |ev| { + prop:value={move || cat_count.get().to_string()} + on:input:target={move |ev| { let val = ev.target().value().parse::<CatCount>().unwrap_or(0); set_cat_count.set(val); - } + }} /> </label> - <Transition fallback=|| view! { <div>"Loading..."</div> } {..spreadable}> + <Transition fallback={|| view! { <div>"Loading..."</div> }} {..spreadable}> <ErrorBoundary fallback> <ul> {move || Suspend::new(async move { @@ -92,7 +92,7 @@ pub fn fetch_example() -> impl IntoView { .map(|s| { view! { <li> - <img src=s.clone()/> + <img src={s.clone()} /> </li> } }) diff --git a/examples/hackernews/src/lib.rs b/examples/hackernews/src/lib.rs index 4d391ea825..c40438d65a 100644 --- a/examples/hackernews/src/lib.rs +++ b/examples/hackernews/src/lib.rs @@ -15,22 +15,22 @@ pub fn App() -> impl IntoView { let (is_routing, set_is_routing) = signal(false); view! { - <Stylesheet id="leptos" href="/pkg/hackernews.css"/> - <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico"/> - <Meta name="description" content="Leptos implementation of a HackerNews demo."/> + <Stylesheet id="leptos" href="/pkg/hackernews.css" /> + <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico" /> + <Meta name="description" content="Leptos implementation of a HackerNews demo." /> <Router set_is_routing> // shows a progress bar while async data are loading <div class="routing-progress"> - <RoutingProgress is_routing max_time=Duration::from_millis(250)/> + <RoutingProgress is_routing max_time={Duration::from_millis(250)} /> </div> <Nav /> <main> - <FlatRoutes fallback=|| "Not found."> - <Route path=(StaticSegment("users"), ParamSegment("id")) view=User/> - <Route path=(StaticSegment("stories"), ParamSegment("id")) view=Story/> - <Route path=ParamSegment("stories") view=Stories/> + <FlatRoutes fallback={|| "Not found."}> + <Route path={(StaticSegment("users"), ParamSegment("id"))} view={User} /> + <Route path={(StaticSegment("stories"), ParamSegment("id"))} view={Story} /> + <Route path={ParamSegment("stories")} view={Stories} /> // TODO allow optional params without duplication - <Route path=StaticSegment("") view=Stories/> + <Route path={StaticSegment("")} view={Stories} /> </FlatRoutes> </main> </Router> diff --git a/examples/hackernews/src/main.rs b/examples/hackernews/src/main.rs index c02b7994e2..3ccfb670ef 100644 --- a/examples/hackernews/src/main.rs +++ b/examples/hackernews/src/main.rs @@ -41,17 +41,20 @@ async fn main() -> std::io::Result<()> { use leptos::prelude::*; view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1"/> - <AutoReload options=leptos_options.clone() /> - <HydrationScripts options=leptos_options.clone()/> - <MetaTags/> + <meta charset="utf-8" /> + <meta + name="viewport" + content="width=device-width, initial-scale=1" + /> + <AutoReload options={leptos_options.clone()} /> + <HydrationScripts options={leptos_options.clone()} /> + <MetaTags /> </head> <body> - <App/> + <App /> </body> </html> } diff --git a/examples/hackernews/src/routes/nav.rs b/examples/hackernews/src/routes/nav.rs index cbc9a77781..aee41f0743 100644 --- a/examples/hackernews/src/routes/nav.rs +++ b/examples/hackernews/src/routes/nav.rs @@ -21,7 +21,12 @@ pub fn Nav() -> impl IntoView { <A href="/job"> <strong>"Jobs"</strong> </A> - <a class="github" href="http://github.com/leptos-rs/leptos" target="_blank" rel="noreferrer"> + <a + class="github" + href="http://github.com/leptos-rs/leptos" + target="_blank" + rel="noreferrer" + > "Built with Leptos" </a> </nav> diff --git a/examples/hackernews/src/routes/stories.rs b/examples/hackernews/src/routes/stories.rs index eb2586b3a1..4c777db165 100644 --- a/examples/hackernews/src/routes/stories.rs +++ b/examples/hackernews/src/routes/stories.rs @@ -50,30 +50,41 @@ pub fn Stories() -> impl IntoView { <div class="news-view"> <div class="news-list-nav"> <span> - {move || if page() > 1 { - Either::Left(view! { - <a class="page-link" - href=move || format!("/{}?page={}", story_type(), page() - 1) - aria-label="Previous Page" - > - "< prev" - </a> - }) - } else { - Either::Right(view! { - <span class="page-link disabled" aria-hidden="true"> - "< prev" - </span> - }) + {move || { + if page() > 1 { + Either::Left( + view! { + <a + class="page-link" + href={move || { + format!("/{}?page={}", story_type(), page() - 1) + }} + aria-label="Previous Page" + > + "< prev" + </a> + }, + ) + } else { + Either::Right( + view! { + <span class="page-link disabled" aria-hidden="true"> + "< prev" + </span> + }, + ) + } }} </span> <span>"page " {page}</span> <Suspense> - <span class="page-link" - class:disabled=hide_more_link - aria-hidden=hide_more_link + <span + class="page-link" + class:disabled={hide_more_link} + aria-hidden={hide_more_link} > - <a href=move || format!("/{}?page={}", story_type(), page() + 1) + <a + href={move || format!("/{}?page={}", story_type(), page() + 1)} aria-label="Next Page" > "more >" @@ -83,21 +94,17 @@ pub fn Stories() -> impl IntoView { </div> <main class="news-list"> <div> - <Transition - fallback=move || view! { <p>"Loading..."</p> } - set_pending - > - <Show when=move || stories.read().as_ref().map(Option::is_none).unwrap_or(false)> - > - <p>"Error loading stories."</p> - </Show> + <Transition fallback={move || view! { <p>"Loading..."</p> }} set_pending> + <Show when={move || { + stories.read().as_ref().map(Option::is_none).unwrap_or(false) + }}>> <p>"Error loading stories."</p></Show> <ul> <For - each=move || stories.get().unwrap_or_default().unwrap_or_default() - key=|story| story.id + each={move || stories.get().unwrap_or_default().unwrap_or_default()} + key={|story| story.id} let:story > - <Story story/> + <Story story /> </For> </ul> </Transition> @@ -110,49 +117,67 @@ pub fn Stories() -> impl IntoView { #[component] fn Story(story: api::Story) -> impl IntoView { view! { - <li class="news-item"> + <li class="news-item"> <span class="score">{story.points}</span> <span class="title"> {if !story.url.starts_with("item?id=") { - Either::Left(view! { - <span> - <a href=story.url target="_blank" rel="noreferrer"> - {story.title.clone()} - </a> - <span class="host">"("{story.domain}")"</span> - </span> - }) + Either::Left( + view! { + <span> + <a href={story.url} target="_blank" rel="noreferrer"> + {story.title.clone()} + </a> + <span class="host">"("{story.domain}")"</span> + </span> + }, + ) } else { let title = story.title.clone(); - Either::Right(view! { <A href=format!("/stories/{}", story.id)>{title}</A> }) + Either::Right(view! { <A href={format!("/stories/{}", story.id)}>{title}</A> }) }} </span> <br /> <span class="meta"> {if story.story_type != "job" { - Either::Left(view! { - <span> - {"by "} - {story.user.map(|user| view ! { <A href=format!("/users/{user}")>{user.clone()}</A>})} - {format!(" {} | ", story.time_ago)} - <A href=format!("/stories/{}", story.id)> - {if story.comments_count.unwrap_or_default() > 0 { - format!("{} comments", story.comments_count.unwrap_or_default()) - } else { - "discuss".into() - }} - </A> - </span> - }) + Either::Left( + view! { + <span> + {"by "} + {story + .user + .map(|user| { + view! { + <A href={format!("/users/{user}")}>{user.clone()}</A> + } + })} {format!(" {} | ", story.time_ago)} + <A href={format!( + "/stories/{}", + story.id, + )}> + {if story.comments_count.unwrap_or_default() > 0 { + format!( + "{} comments", + story.comments_count.unwrap_or_default(), + ) + } else { + "discuss".into() + }} + </A> + </span> + }, + ) } else { let title = story.title.clone(); - Either::Right(view! { <A href=format!("/item/{}", story.id)>{title}</A> }) + Either::Right(view! { <A href={format!("/item/{}", story.id)}>{title}</A> }) }} </span> - {(story.story_type != "link").then(|| view! { - " " - <span class="label">{story.story_type}</span> - })} + {(story.story_type != "link") + .then(|| { + view! { + " " + <span class="label">{story.story_type}</span> + } + })} </li> } } diff --git a/examples/hackernews/src/routes/story.rs b/examples/hackernews/src/routes/story.rs index b8c9dae4ce..d26fdf1c53 100644 --- a/examples/hackernews/src/routes/story.rs +++ b/examples/hackernews/src/routes/story.rs @@ -25,21 +25,24 @@ pub fn Story() -> impl IntoView { None => Either::Left("Story not found."), Some(story) => { Either::Right(view! { - <Meta name="description" content=story.title.clone()/> + <Meta name="description" content={story.title.clone()} /> <div class="item-view"> <div class="item-view-header"> - <a href=story.url target="_blank"> - <h1>{story.title}</h1> - </a> - <span class="host"> - "("{story.domain}")" - </span> - {story.user.map(|user| view! { <p class="meta"> - {story.points} - " points | by " - <A href=format!("/users/{user}")>{user.clone()}</A> - {format!(" {}", story.time_ago)} - </p>})} + <a href={story.url} target="_blank"> + <h1>{story.title}</h1> + </a> + <span class="host">"("{story.domain}")"</span> + {story + .user + .map(|user| { + view! { + <p class="meta"> + {story.points} " points | by " + <A href={format!("/users/{user}")}>{user.clone()}</A> + {format!(" {}", story.time_ago)} + </p> + } + })} </div> <div class="item-view-comments"> <p class="item-view-comments-header"> @@ -51,8 +54,8 @@ pub fn Story() -> impl IntoView { </p> <ul class="comment-children"> <For - each=move || story.comments.clone().unwrap_or_default() - key=|comment| comment.id + each={move || story.comments.clone().unwrap_or_default()} + key={|comment| comment.id} let:comment > <Comment comment /> @@ -72,43 +75,61 @@ pub fn Comment(comment: api::Comment) -> impl IntoView { view! { <li class="comment"> - <div class="by"> - <A href=format!("/users/{}", comment.user.clone().unwrap_or_default())>{comment.user.clone()}</A> - {format!(" {}", comment.time_ago)} - </div> - <div class="text" inner_html=comment.content></div> - {(!comment.comments.is_empty()).then(|| { - view! { - <div> - <div class="toggle" class:open=open> - <a on:click=move |_| set_open.update(|n| *n = !*n)> - { - let comments_len = comment.comments.len(); - move || if open.get() { - "[-]".into() - } else { - format!("[+] {}{} collapsed", comments_len, pluralize(comments_len)) - } - } - </a> - </div> - {move || open.get().then({ - let comments = comment.comments.clone(); - move || view! { - <ul class="comment-children"> - <For - each=move || comments.clone() - key=|comment| comment.id - let:comment - > - <Comment comment /> - </For> - </ul> - } - })} - </div> - } - })} + <div class="by"> + <A href={format!( + "/users/{}", + comment.user.clone().unwrap_or_default(), + )}>{comment.user.clone()}</A> + {format!(" {}", comment.time_ago)} + </div> + <div class="text" inner_html={comment.content}></div> + {(!comment.comments.is_empty()) + .then(|| { + view! { + <div> + <div class="toggle" class:open={open}> + <a on:click={move |_| { + set_open.update(|n| *n = !*n) + }}> + { + let comments_len = comment.comments.len(); + move || { + if open.get() { + "[-]".into() + } else { + format!( + "[+] {}{} collapsed", + comments_len, + pluralize(comments_len), + ) + } + } + } + </a> + </div> + {move || { + open + .get() + .then({ + let comments = comment.comments.clone(); + move || { + view! { + <ul class="comment-children"> + <For + each={move || comments.clone()} + key={|comment| comment.id} + let:comment + > + <Comment comment /> + </For> + </ul> + } + } + }) + }} + </div> + } + })} </li> }.into_any() } diff --git a/examples/hackernews/src/routes/users.rs b/examples/hackernews/src/routes/users.rs index 177c1fed1f..07a57266e4 100644 --- a/examples/hackernews/src/routes/users.rs +++ b/examples/hackernews/src/routes/users.rs @@ -18,29 +18,45 @@ pub fn User() -> impl IntoView { ); view! { <div class="user-view"> - <Suspense fallback=|| view! { "Loading..." }> - {move || Suspend::new(async move { match user.await.clone() { - None => Either::Left(view! { <h1>"User not found."</h1> }), - Some(user) => Either::Right(view! { - <div> - <h1>"User: " {user.id.clone()}</h1> - <ul class="meta"> - <li> - <span class="label">"Created: "</span> {user.created} - </li> - <li> - <span class="label">"Karma: "</span> {user.karma} - </li> - <li inner_html={user.about} class="about"></li> - </ul> - <p class="links"> - <a href=format!("https://news.ycombinator.com/submitted?id={}", user.id)>"submissions"</a> - " | " - <a href=format!("https://news.ycombinator.com/threads?id={}", user.id)>"comments"</a> - </p> - </div> - }) - }})} + <Suspense fallback={|| { + view! { "Loading..." } + }}> + {move || Suspend::new(async move { + match user.await.clone() { + None => Either::Left(view! { <h1>"User not found."</h1> }), + Some(user) => { + Either::Right( + view! { + <div> + <h1>"User: " {user.id.clone()}</h1> + <ul class="meta"> + <li> + <span class="label">"Created: "</span> + {user.created} + </li> + <li> + <span class="label">"Karma: "</span> + {user.karma} + </li> + <li inner_html={user.about} class="about"></li> + </ul> + <p class="links"> + <a href={format!( + "https://news.ycombinator.com/submitted?id={}", + user.id, + )}>"submissions"</a> + " | " + <a href={format!( + "https://news.ycombinator.com/threads?id={}", + user.id, + )}>"comments"</a> + </p> + </div> + }, + ) + } + } + })} </Suspense> </div> } diff --git a/examples/hackernews_axum/src/error_template.rs b/examples/hackernews_axum/src/error_template.rs index a164c47a06..d0f6cf0253 100644 --- a/examples/hackernews_axum/src/error_template.rs +++ b/examples/hackernews_axum/src/error_template.rs @@ -8,21 +8,18 @@ pub fn error_template(errors: Option<RwSignal<Errors>>) -> View { }; view! { - <h1>"Errors"</h1> - <For - // a function that returns the items we're iterating over; a signal is fine - each=move || errors.get() - // a unique key for each item as a reference - key=|(key, _)| key.clone() - // renders each item to a view - children=move | (_, error)| { - let error_string = error.to_string(); - view! { - - <p>"Error: " {error_string}</p> - } - } - /> + <h1>"Errors"</h1> + <For + // a function that returns the items we're iterating over; a signal is fine + each={move || errors.get()} + // a unique key for each item as a reference + key={|(key, _)| key.clone()} + // renders each item to a view + children={move |(_, error)| { + let error_string = error.to_string(); + view! { <p>"Error: " {error_string}</p> } + }} + /> } .into_view() } diff --git a/examples/hackernews_axum/src/lib.rs b/examples/hackernews_axum/src/lib.rs index 6e5b11b996..e02cc60867 100644 --- a/examples/hackernews_axum/src/lib.rs +++ b/examples/hackernews_axum/src/lib.rs @@ -11,17 +11,17 @@ use std::time::Duration; pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1"/> - <AutoReload options=options.clone() /> - <HydrationScripts options/> - <MetaTags/> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <AutoReload options={options.clone()} /> + <HydrationScripts options /> + <MetaTags /> </head> <body> - <App/> + <App /> </body> </html> } @@ -33,22 +33,22 @@ pub fn App() -> impl IntoView { let (is_routing, set_is_routing) = signal(false); view! { - <Stylesheet id="leptos" href="/pkg/hackernews_axum.css"/> - <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico"/> - <Meta name="description" content="Leptos implementation of a HackerNews demo."/> + <Stylesheet id="leptos" href="/pkg/hackernews_axum.css" /> + <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico" /> + <Meta name="description" content="Leptos implementation of a HackerNews demo." /> <Router set_is_routing> // shows a progress bar while async data are loading <div class="routing-progress"> - <RoutingProgress is_routing max_time=Duration::from_millis(250)/> + <RoutingProgress is_routing max_time={Duration::from_millis(250)} /> </div> <Nav /> <main> - <FlatRoutes fallback=|| "Not found."> - <Route path=(StaticSegment("users"), ParamSegment("id")) view=User/> - <Route path=(StaticSegment("stories"), ParamSegment("id")) view=Story/> - <Route path=ParamSegment("stories") view=Stories/> + <FlatRoutes fallback={|| "Not found."}> + <Route path={(StaticSegment("users"), ParamSegment("id"))} view={User} /> + <Route path={(StaticSegment("stories"), ParamSegment("id"))} view={Story} /> + <Route path={ParamSegment("stories")} view={Stories} /> // TODO allow optional params without duplication - <Route path=StaticSegment("") view=Stories/> + <Route path={StaticSegment("")} view={Stories} /> </FlatRoutes> </main> </Router> diff --git a/examples/hackernews_axum/src/routes/nav.rs b/examples/hackernews_axum/src/routes/nav.rs index cbc9a77781..aee41f0743 100644 --- a/examples/hackernews_axum/src/routes/nav.rs +++ b/examples/hackernews_axum/src/routes/nav.rs @@ -21,7 +21,12 @@ pub fn Nav() -> impl IntoView { <A href="/job"> <strong>"Jobs"</strong> </A> - <a class="github" href="http://github.com/leptos-rs/leptos" target="_blank" rel="noreferrer"> + <a + class="github" + href="http://github.com/leptos-rs/leptos" + target="_blank" + rel="noreferrer" + > "Built with Leptos" </a> </nav> diff --git a/examples/hackernews_axum/src/routes/stories.rs b/examples/hackernews_axum/src/routes/stories.rs index eb2586b3a1..4c777db165 100644 --- a/examples/hackernews_axum/src/routes/stories.rs +++ b/examples/hackernews_axum/src/routes/stories.rs @@ -50,30 +50,41 @@ pub fn Stories() -> impl IntoView { <div class="news-view"> <div class="news-list-nav"> <span> - {move || if page() > 1 { - Either::Left(view! { - <a class="page-link" - href=move || format!("/{}?page={}", story_type(), page() - 1) - aria-label="Previous Page" - > - "< prev" - </a> - }) - } else { - Either::Right(view! { - <span class="page-link disabled" aria-hidden="true"> - "< prev" - </span> - }) + {move || { + if page() > 1 { + Either::Left( + view! { + <a + class="page-link" + href={move || { + format!("/{}?page={}", story_type(), page() - 1) + }} + aria-label="Previous Page" + > + "< prev" + </a> + }, + ) + } else { + Either::Right( + view! { + <span class="page-link disabled" aria-hidden="true"> + "< prev" + </span> + }, + ) + } }} </span> <span>"page " {page}</span> <Suspense> - <span class="page-link" - class:disabled=hide_more_link - aria-hidden=hide_more_link + <span + class="page-link" + class:disabled={hide_more_link} + aria-hidden={hide_more_link} > - <a href=move || format!("/{}?page={}", story_type(), page() + 1) + <a + href={move || format!("/{}?page={}", story_type(), page() + 1)} aria-label="Next Page" > "more >" @@ -83,21 +94,17 @@ pub fn Stories() -> impl IntoView { </div> <main class="news-list"> <div> - <Transition - fallback=move || view! { <p>"Loading..."</p> } - set_pending - > - <Show when=move || stories.read().as_ref().map(Option::is_none).unwrap_or(false)> - > - <p>"Error loading stories."</p> - </Show> + <Transition fallback={move || view! { <p>"Loading..."</p> }} set_pending> + <Show when={move || { + stories.read().as_ref().map(Option::is_none).unwrap_or(false) + }}>> <p>"Error loading stories."</p></Show> <ul> <For - each=move || stories.get().unwrap_or_default().unwrap_or_default() - key=|story| story.id + each={move || stories.get().unwrap_or_default().unwrap_or_default()} + key={|story| story.id} let:story > - <Story story/> + <Story story /> </For> </ul> </Transition> @@ -110,49 +117,67 @@ pub fn Stories() -> impl IntoView { #[component] fn Story(story: api::Story) -> impl IntoView { view! { - <li class="news-item"> + <li class="news-item"> <span class="score">{story.points}</span> <span class="title"> {if !story.url.starts_with("item?id=") { - Either::Left(view! { - <span> - <a href=story.url target="_blank" rel="noreferrer"> - {story.title.clone()} - </a> - <span class="host">"("{story.domain}")"</span> - </span> - }) + Either::Left( + view! { + <span> + <a href={story.url} target="_blank" rel="noreferrer"> + {story.title.clone()} + </a> + <span class="host">"("{story.domain}")"</span> + </span> + }, + ) } else { let title = story.title.clone(); - Either::Right(view! { <A href=format!("/stories/{}", story.id)>{title}</A> }) + Either::Right(view! { <A href={format!("/stories/{}", story.id)}>{title}</A> }) }} </span> <br /> <span class="meta"> {if story.story_type != "job" { - Either::Left(view! { - <span> - {"by "} - {story.user.map(|user| view ! { <A href=format!("/users/{user}")>{user.clone()}</A>})} - {format!(" {} | ", story.time_ago)} - <A href=format!("/stories/{}", story.id)> - {if story.comments_count.unwrap_or_default() > 0 { - format!("{} comments", story.comments_count.unwrap_or_default()) - } else { - "discuss".into() - }} - </A> - </span> - }) + Either::Left( + view! { + <span> + {"by "} + {story + .user + .map(|user| { + view! { + <A href={format!("/users/{user}")}>{user.clone()}</A> + } + })} {format!(" {} | ", story.time_ago)} + <A href={format!( + "/stories/{}", + story.id, + )}> + {if story.comments_count.unwrap_or_default() > 0 { + format!( + "{} comments", + story.comments_count.unwrap_or_default(), + ) + } else { + "discuss".into() + }} + </A> + </span> + }, + ) } else { let title = story.title.clone(); - Either::Right(view! { <A href=format!("/item/{}", story.id)>{title}</A> }) + Either::Right(view! { <A href={format!("/item/{}", story.id)}>{title}</A> }) }} </span> - {(story.story_type != "link").then(|| view! { - " " - <span class="label">{story.story_type}</span> - })} + {(story.story_type != "link") + .then(|| { + view! { + " " + <span class="label">{story.story_type}</span> + } + })} </li> } } diff --git a/examples/hackernews_axum/src/routes/story.rs b/examples/hackernews_axum/src/routes/story.rs index b8c9dae4ce..d26fdf1c53 100644 --- a/examples/hackernews_axum/src/routes/story.rs +++ b/examples/hackernews_axum/src/routes/story.rs @@ -25,21 +25,24 @@ pub fn Story() -> impl IntoView { None => Either::Left("Story not found."), Some(story) => { Either::Right(view! { - <Meta name="description" content=story.title.clone()/> + <Meta name="description" content={story.title.clone()} /> <div class="item-view"> <div class="item-view-header"> - <a href=story.url target="_blank"> - <h1>{story.title}</h1> - </a> - <span class="host"> - "("{story.domain}")" - </span> - {story.user.map(|user| view! { <p class="meta"> - {story.points} - " points | by " - <A href=format!("/users/{user}")>{user.clone()}</A> - {format!(" {}", story.time_ago)} - </p>})} + <a href={story.url} target="_blank"> + <h1>{story.title}</h1> + </a> + <span class="host">"("{story.domain}")"</span> + {story + .user + .map(|user| { + view! { + <p class="meta"> + {story.points} " points | by " + <A href={format!("/users/{user}")}>{user.clone()}</A> + {format!(" {}", story.time_ago)} + </p> + } + })} </div> <div class="item-view-comments"> <p class="item-view-comments-header"> @@ -51,8 +54,8 @@ pub fn Story() -> impl IntoView { </p> <ul class="comment-children"> <For - each=move || story.comments.clone().unwrap_or_default() - key=|comment| comment.id + each={move || story.comments.clone().unwrap_or_default()} + key={|comment| comment.id} let:comment > <Comment comment /> @@ -72,43 +75,61 @@ pub fn Comment(comment: api::Comment) -> impl IntoView { view! { <li class="comment"> - <div class="by"> - <A href=format!("/users/{}", comment.user.clone().unwrap_or_default())>{comment.user.clone()}</A> - {format!(" {}", comment.time_ago)} - </div> - <div class="text" inner_html=comment.content></div> - {(!comment.comments.is_empty()).then(|| { - view! { - <div> - <div class="toggle" class:open=open> - <a on:click=move |_| set_open.update(|n| *n = !*n)> - { - let comments_len = comment.comments.len(); - move || if open.get() { - "[-]".into() - } else { - format!("[+] {}{} collapsed", comments_len, pluralize(comments_len)) - } - } - </a> - </div> - {move || open.get().then({ - let comments = comment.comments.clone(); - move || view! { - <ul class="comment-children"> - <For - each=move || comments.clone() - key=|comment| comment.id - let:comment - > - <Comment comment /> - </For> - </ul> - } - })} - </div> - } - })} + <div class="by"> + <A href={format!( + "/users/{}", + comment.user.clone().unwrap_or_default(), + )}>{comment.user.clone()}</A> + {format!(" {}", comment.time_ago)} + </div> + <div class="text" inner_html={comment.content}></div> + {(!comment.comments.is_empty()) + .then(|| { + view! { + <div> + <div class="toggle" class:open={open}> + <a on:click={move |_| { + set_open.update(|n| *n = !*n) + }}> + { + let comments_len = comment.comments.len(); + move || { + if open.get() { + "[-]".into() + } else { + format!( + "[+] {}{} collapsed", + comments_len, + pluralize(comments_len), + ) + } + } + } + </a> + </div> + {move || { + open + .get() + .then({ + let comments = comment.comments.clone(); + move || { + view! { + <ul class="comment-children"> + <For + each={move || comments.clone()} + key={|comment| comment.id} + let:comment + > + <Comment comment /> + </For> + </ul> + } + } + }) + }} + </div> + } + })} </li> }.into_any() } diff --git a/examples/hackernews_axum/src/routes/users.rs b/examples/hackernews_axum/src/routes/users.rs index 177c1fed1f..07a57266e4 100644 --- a/examples/hackernews_axum/src/routes/users.rs +++ b/examples/hackernews_axum/src/routes/users.rs @@ -18,29 +18,45 @@ pub fn User() -> impl IntoView { ); view! { <div class="user-view"> - <Suspense fallback=|| view! { "Loading..." }> - {move || Suspend::new(async move { match user.await.clone() { - None => Either::Left(view! { <h1>"User not found."</h1> }), - Some(user) => Either::Right(view! { - <div> - <h1>"User: " {user.id.clone()}</h1> - <ul class="meta"> - <li> - <span class="label">"Created: "</span> {user.created} - </li> - <li> - <span class="label">"Karma: "</span> {user.karma} - </li> - <li inner_html={user.about} class="about"></li> - </ul> - <p class="links"> - <a href=format!("https://news.ycombinator.com/submitted?id={}", user.id)>"submissions"</a> - " | " - <a href=format!("https://news.ycombinator.com/threads?id={}", user.id)>"comments"</a> - </p> - </div> - }) - }})} + <Suspense fallback={|| { + view! { "Loading..." } + }}> + {move || Suspend::new(async move { + match user.await.clone() { + None => Either::Left(view! { <h1>"User not found."</h1> }), + Some(user) => { + Either::Right( + view! { + <div> + <h1>"User: " {user.id.clone()}</h1> + <ul class="meta"> + <li> + <span class="label">"Created: "</span> + {user.created} + </li> + <li> + <span class="label">"Karma: "</span> + {user.karma} + </li> + <li inner_html={user.about} class="about"></li> + </ul> + <p class="links"> + <a href={format!( + "https://news.ycombinator.com/submitted?id={}", + user.id, + )}>"submissions"</a> + " | " + <a href={format!( + "https://news.ycombinator.com/threads?id={}", + user.id, + )}>"comments"</a> + </p> + </div> + }, + ) + } + } + })} </Suspense> </div> } diff --git a/examples/hackernews_islands_axum/src/lib.rs b/examples/hackernews_islands_axum/src/lib.rs index 260e4849a4..5d708703ee 100644 --- a/examples/hackernews_islands_axum/src/lib.rs +++ b/examples/hackernews_islands_axum/src/lib.rs @@ -12,17 +12,17 @@ pub mod fallback; pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1"/> - <AutoReload options=options.clone() /> - <HydrationScripts options islands=true/> - <MetaTags/> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <AutoReload options={options.clone()} /> + <HydrationScripts options islands=true /> + <MetaTags /> </head> <body> - <App/> + <App /> </body> </html> } @@ -33,18 +33,18 @@ pub fn App() -> impl IntoView { provide_meta_context(); view! { - <Stylesheet id="leptos" href="/pkg/hackernews.css"/> - <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico"/> - <Meta name="description" content="Leptos implementation of a HackerNews demo."/> + <Stylesheet id="leptos" href="/pkg/hackernews.css" /> + <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico" /> + <Meta name="description" content="Leptos implementation of a HackerNews demo." /> <Router> <Nav /> <main> - <FlatRoutes fallback=|| "Not found."> - <Route path=(StaticSegment("users"), ParamSegment("id")) view=User/> - <Route path=(StaticSegment("stories"), ParamSegment("id")) view=Story/> - <Route path=ParamSegment("stories") view=Stories/> + <FlatRoutes fallback={|| "Not found."}> + <Route path={(StaticSegment("users"), ParamSegment("id"))} view={User} /> + <Route path={(StaticSegment("stories"), ParamSegment("id"))} view={Story} /> + <Route path={ParamSegment("stories")} view={Stories} /> // TODO allow optional params without duplication - <Route path=StaticSegment("") view=Stories/> + <Route path={StaticSegment("")} view={Stories} /> </FlatRoutes> </main> </Router> diff --git a/examples/hackernews_islands_axum/src/routes/nav.rs b/examples/hackernews_islands_axum/src/routes/nav.rs index cbc9a77781..aee41f0743 100644 --- a/examples/hackernews_islands_axum/src/routes/nav.rs +++ b/examples/hackernews_islands_axum/src/routes/nav.rs @@ -21,7 +21,12 @@ pub fn Nav() -> impl IntoView { <A href="/job"> <strong>"Jobs"</strong> </A> - <a class="github" href="http://github.com/leptos-rs/leptos" target="_blank" rel="noreferrer"> + <a + class="github" + href="http://github.com/leptos-rs/leptos" + target="_blank" + rel="noreferrer" + > "Built with Leptos" </a> </nav> diff --git a/examples/hackernews_islands_axum/src/routes/stories.rs b/examples/hackernews_islands_axum/src/routes/stories.rs index 8e60c1b91b..06f9647ac1 100644 --- a/examples/hackernews_islands_axum/src/routes/stories.rs +++ b/examples/hackernews_islands_axum/src/routes/stories.rs @@ -61,30 +61,41 @@ pub fn Stories() -> impl IntoView { <div class="news-view"> <div class="news-list-nav"> <span> - {move || if page() > 1 { - Either::Left(view! { - <a class="page-link" - href=move || format!("/{}?page={}", story_type(), page() - 1) - aria-label="Previous Page" - > - "< prev" - </a> - }) - } else { - Either::Right(view! { - <span class="page-link disabled" aria-hidden="true"> - "< prev" - </span> - }) + {move || { + if page() > 1 { + Either::Left( + view! { + <a + class="page-link" + href={move || { + format!("/{}?page={}", story_type(), page() - 1) + }} + aria-label="Previous Page" + > + "< prev" + </a> + }, + ) + } else { + Either::Right( + view! { + <span class="page-link disabled" aria-hidden="true"> + "< prev" + </span> + }, + ) + } }} </span> <span>"page " {page}</span> <Suspense> - <span class="page-link" - class:disabled=hide_more_link - aria-hidden=hide_more_link + <span + class="page-link" + class:disabled={hide_more_link} + aria-hidden={hide_more_link} > - <a href=move || format!("/{}?page={}", story_type(), page() + 1) + <a + href={move || format!("/{}?page={}", story_type(), page() + 1)} aria-label="Next Page" > "more >" @@ -94,21 +105,17 @@ pub fn Stories() -> impl IntoView { </div> <main class="news-list"> <div> - <Transition - fallback=move || view! { <p>"Loading..."</p> } - set_pending - > - <Show when=move || stories.read().as_ref().map(Option::is_none).unwrap_or(false)> - > - <p>"Error loading stories."</p> - </Show> + <Transition fallback={move || view! { <p>"Loading..."</p> }} set_pending> + <Show when={move || { + stories.read().as_ref().map(Option::is_none).unwrap_or(false) + }}>> <p>"Error loading stories."</p></Show> <ul> <For - each=move || stories.get().unwrap_or_default().unwrap_or_default() - key=|story| story.id + each={move || stories.get().unwrap_or_default().unwrap_or_default()} + key={|story| story.id} let:story > - <Story story/> + <Story story /> </For> </ul> </Transition> @@ -121,49 +128,67 @@ pub fn Stories() -> impl IntoView { #[component] fn Story(story: api::Story) -> impl IntoView { view! { - <li class="news-item"> + <li class="news-item"> <span class="score">{story.points}</span> <span class="title"> {if !story.url.starts_with("item?id=") { - Either::Left(view! { - <span> - <a href=story.url target="_blank" rel="noreferrer"> - {story.title.clone()} - </a> - <span class="host">"("{story.domain}")"</span> - </span> - }) + Either::Left( + view! { + <span> + <a href={story.url} target="_blank" rel="noreferrer"> + {story.title.clone()} + </a> + <span class="host">"("{story.domain}")"</span> + </span> + }, + ) } else { let title = story.title.clone(); - Either::Right(view! { <A href=format!("/stories/{}", story.id)>{title}</A> }) + Either::Right(view! { <A href={format!("/stories/{}", story.id)}>{title}</A> }) }} </span> <br /> <span class="meta"> {if story.story_type != "job" { - Either::Left(view! { - <span> - {"by "} - {story.user.map(|user| view ! { <A href=format!("/users/{user}")>{user.clone()}</A>})} - {format!(" {} | ", story.time_ago)} - <A href=format!("/stories/{}", story.id)> - {if story.comments_count.unwrap_or_default() > 0 { - format!("{} comments", story.comments_count.unwrap_or_default()) - } else { - "discuss".into() - }} - </A> - </span> - }) + Either::Left( + view! { + <span> + {"by "} + {story + .user + .map(|user| { + view! { + <A href={format!("/users/{user}")}>{user.clone()}</A> + } + })} {format!(" {} | ", story.time_ago)} + <A href={format!( + "/stories/{}", + story.id, + )}> + {if story.comments_count.unwrap_or_default() > 0 { + format!( + "{} comments", + story.comments_count.unwrap_or_default(), + ) + } else { + "discuss".into() + }} + </A> + </span> + }, + ) } else { let title = story.title.clone(); - Either::Right(view! { <A href=format!("/item/{}", story.id)>{title}</A> }) + Either::Right(view! { <A href={format!("/item/{}", story.id)}>{title}</A> }) }} </span> - {(story.story_type != "link").then(|| view! { - " " - <span class="label">{story.story_type}</span> - })} + {(story.story_type != "link") + .then(|| { + view! { + " " + <span class="label">{story.story_type}</span> + } + })} </li> } } diff --git a/examples/hackernews_islands_axum/src/routes/story.rs b/examples/hackernews_islands_axum/src/routes/story.rs index 75e12357a2..0b863bb0df 100644 --- a/examples/hackernews_islands_axum/src/routes/story.rs +++ b/examples/hackernews_islands_axum/src/routes/story.rs @@ -31,21 +31,24 @@ pub fn Story() -> impl IntoView { None => Either::Left("Story not found."), Some(story) => { Either::Right(view! { - <Meta name="description" content=story.title.clone()/> + <Meta name="description" content={story.title.clone()} /> <div class="item-view"> <div class="item-view-header"> - <a href=story.url target="_blank"> - <h1>{story.title}</h1> - </a> - <span class="host"> - "("{story.domain}")" - </span> - {story.user.map(|user| view! { <p class="meta"> - {story.points} - " points | by " - <A href=format!("/users/{user}")>{user.clone()}</A> - {format!(" {}", story.time_ago)} - </p>})} + <a href={story.url} target="_blank"> + <h1>{story.title}</h1> + </a> + <span class="host">"("{story.domain}")"</span> + {story + .user + .map(|user| { + view! { + <p class="meta"> + {story.points} " points | by " + <A href={format!("/users/{user}")}>{user.clone()}</A> + {format!(" {}", story.time_ago)} + </p> + } + })} </div> <div class="item-view-comments"> <p class="item-view-comments-header"> @@ -57,8 +60,8 @@ pub fn Story() -> impl IntoView { </p> <ul class="comment-children"> <For - each=move || story.comments.clone().unwrap_or_default() - key=|comment| comment.id + each={move || story.comments.clone().unwrap_or_default()} + key={|comment| comment.id} let:comment > <Comment comment /> @@ -77,19 +80,25 @@ pub fn Comment(comment: api::Comment) -> impl IntoView { view! { <li class="comment"> <div class="by"> - <A href=format!("/users/{}", comment.user.clone().unwrap_or_default())>{comment.user.clone()}</A> + <A href={format!( + "/users/{}", + comment.user.clone().unwrap_or_default(), + )}>{comment.user.clone()}</A> {format!(" {}", comment.time_ago)} </div> - <div class="text" inner_html=comment.content></div> - {(!comment.comments.is_empty()).then(|| { - view! { - <Toggle> - {comment.comments.into_iter() - .map(|comment: api::Comment| view! { <Comment comment /> }) - .collect_view()} - </Toggle> - } - })} + <div class="text" inner_html={comment.content}></div> + {(!comment.comments.is_empty()) + .then(|| { + view! { + <Toggle> + {comment + .comments + .into_iter() + .map(|comment: api::Comment| view! { <Comment comment /> }) + .collect_view()} + </Toggle> + } + })} </li> } } @@ -98,22 +107,14 @@ pub fn Comment(comment: api::Comment) -> impl IntoView { pub fn Toggle(children: Children) -> impl IntoView { let (open, set_open) = signal(true); view! { - <div class="toggle" class:open=open> - <a on:click=move |_| set_open.update(|n| *n = !*n)> - {move || if open.get() { - "[-]" - } else { - "[+] comments collapsed" - }} - </a> + <div class="toggle" class:open={open}> + <a on:click={move |_| { + set_open.update(|n| *n = !*n) + }}>{move || if open.get() { "[-]" } else { "[+] comments collapsed" }}</a> </div> <ul class="comment-children" - style:display=move || if open.get() { - "block" - } else { - "none" - } + style:display={move || if open.get() { "block" } else { "none" }} > {children()} </ul> diff --git a/examples/hackernews_islands_axum/src/routes/users.rs b/examples/hackernews_islands_axum/src/routes/users.rs index a367771e23..acdcc26410 100644 --- a/examples/hackernews_islands_axum/src/routes/users.rs +++ b/examples/hackernews_islands_axum/src/routes/users.rs @@ -25,29 +25,45 @@ pub fn User() -> impl IntoView { ); view! { <div class="user-view"> - <Suspense fallback=|| view! { "Loading..." }> - {move || Suspend::new(async move { match user.await.ok().flatten() { - None => Either::Left(view! { <h1>"User not found."</h1> }), - Some(user) => Either::Right(view! { - <div> - <h1>"User: " {user.id.clone()}</h1> - <ul class="meta"> - <li> - <span class="label">"Created: "</span> {user.created} - </li> - <li> - <span class="label">"Karma: "</span> {user.karma} - </li> - <li inner_html={user.about} class="about"></li> - </ul> - <p class="links"> - <a href=format!("https://news.ycombinator.com/submitted?id={}", user.id)>"submissions"</a> - " | " - <a href=format!("https://news.ycombinator.com/threads?id={}", user.id)>"comments"</a> - </p> - </div> - }) - }})} + <Suspense fallback={|| { + view! { "Loading..." } + }}> + {move || Suspend::new(async move { + match user.await.ok().flatten() { + None => Either::Left(view! { <h1>"User not found."</h1> }), + Some(user) => { + Either::Right( + view! { + <div> + <h1>"User: " {user.id.clone()}</h1> + <ul class="meta"> + <li> + <span class="label">"Created: "</span> + {user.created} + </li> + <li> + <span class="label">"Karma: "</span> + {user.karma} + </li> + <li inner_html={user.about} class="about"></li> + </ul> + <p class="links"> + <a href={format!( + "https://news.ycombinator.com/submitted?id={}", + user.id, + )}>"submissions"</a> + " | " + <a href={format!( + "https://news.ycombinator.com/threads?id={}", + user.id, + )}>"comments"</a> + </p> + </div> + }, + ) + } + } + })} </Suspense> </div> } diff --git a/examples/hackernews_js_fetch/src/lib.rs b/examples/hackernews_js_fetch/src/lib.rs index c365687e7e..81707a9806 100644 --- a/examples/hackernews_js_fetch/src/lib.rs +++ b/examples/hackernews_js_fetch/src/lib.rs @@ -11,17 +11,17 @@ use std::time::Duration; pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1"/> - <AutoReload options=options.clone()/> - <HydrationScripts options/> - <MetaTags/> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <AutoReload options={options.clone()} /> + <HydrationScripts options /> + <MetaTags /> </head> <body> - <App/> + <App /> </body> </html> } @@ -33,22 +33,22 @@ pub fn App() -> impl IntoView { let (is_routing, set_is_routing) = signal(false); view! { - <Stylesheet id="leptos" href="/public/style.css"/> - <Link rel="shortcut icon" type_="image/ico" href="/public/favicon.ico"/> - <Meta name="description" content="Leptos implementation of a HackerNews demo."/> + <Stylesheet id="leptos" href="/public/style.css" /> + <Link rel="shortcut icon" type_="image/ico" href="/public/favicon.ico" /> + <Meta name="description" content="Leptos implementation of a HackerNews demo." /> <Router set_is_routing> // shows a progress bar while async data are loading <div class="routing-progress"> - <RoutingProgress is_routing max_time=Duration::from_millis(250)/> + <RoutingProgress is_routing max_time={Duration::from_millis(250)} /> </div> - <Nav/> + <Nav /> <main> - <FlatRoutes fallback=|| "Not found."> - <Route path=(StaticSegment("users"), ParamSegment("id")) view=User/> - <Route path=(StaticSegment("stories"), ParamSegment("id")) view=Story/> - <Route path=ParamSegment("stories") view=Stories/> + <FlatRoutes fallback={|| "Not found."}> + <Route path={(StaticSegment("users"), ParamSegment("id"))} view={User} /> + <Route path={(StaticSegment("stories"), ParamSegment("id"))} view={Story} /> + <Route path={ParamSegment("stories")} view={Stories} /> // TODO allow optional params without duplication - <Route path=StaticSegment("") view=Stories/> + <Route path={StaticSegment("")} view={Stories} /> </FlatRoutes> </main> </Router> diff --git a/examples/hackernews_js_fetch/src/routes/stories.rs b/examples/hackernews_js_fetch/src/routes/stories.rs index fdbff488e6..349da36b20 100644 --- a/examples/hackernews_js_fetch/src/routes/stories.rs +++ b/examples/hackernews_js_fetch/src/routes/stories.rs @@ -59,9 +59,9 @@ pub fn Stories() -> impl IntoView { view! { <a class="page-link" - href=move || { + href={move || { format!("/{}?page={}", story_type(), page() - 1) - } + }} aria-label="Previous Page" > "< prev" @@ -80,9 +80,13 @@ pub fn Stories() -> impl IntoView { }} </span> <span>"page " {page}</span> - <span class="page-link" class:disabled=hide_more_link aria-hidden=hide_more_link> + <span + class="page-link" + class:disabled={hide_more_link} + aria-hidden={hide_more_link} + > <a - href=move || format!("/{}?page={}", story_type(), page() + 1) + href={move || format!("/{}?page={}", story_type(), page() + 1)} aria-label="Next Page" > "more >" @@ -91,17 +95,17 @@ pub fn Stories() -> impl IntoView { </div> <main class="news-list"> <div> - <Transition fallback=move || view! { <p>"Loading..."</p> } set_pending> - <Show when=move || { + <Transition fallback={move || view! { <p>"Loading..."</p> }} set_pending> + <Show when={move || { stories.read().as_ref().map(Option::is_none).unwrap_or(false) - }>> <p>"Error loading stories."</p></Show> + }}>> <p>"Error loading stories."</p></Show> <ul> <For - each=move || stories.get().unwrap_or_default().unwrap_or_default() - key=|story| story.id + each={move || stories.get().unwrap_or_default().unwrap_or_default()} + key={|story| story.id} let:story > - <Story story/> + <Story story /> </For> </ul> </Transition> @@ -121,7 +125,7 @@ fn Story(story: api::Story) -> impl IntoView { Either::Left( view! { <span> - <a href=story.url target="_blank" rel="noreferrer"> + <a href={story.url} target="_blank" rel="noreferrer"> {story.title.clone()} </a> <span class="host">"("{story.domain}")"</span> @@ -130,10 +134,10 @@ fn Story(story: api::Story) -> impl IntoView { ) } else { let title = story.title.clone(); - Either::Right(view! { <A href=format!("/stories/{}", story.id)>{title}</A> }) + Either::Right(view! { <A href={format!("/stories/{}", story.id)}>{title}</A> }) }} </span> - <br/> + <br /> <span class="meta"> {if story.story_type != "job" { Either::Left( @@ -144,13 +148,13 @@ fn Story(story: api::Story) -> impl IntoView { .user .map(|user| { view! { - <A href=format!("/users/{user}")>{user.clone()}</A> + <A href={format!("/users/{user}")}>{user.clone()}</A> } })} {format!(" {} | ", story.time_ago)} - <A href=format!( + <A href={format!( "/stories/{}", story.id, - )> + )}> {if story.comments_count.unwrap_or_default() > 0 { format!( "{} comments", @@ -165,7 +169,7 @@ fn Story(story: api::Story) -> impl IntoView { ) } else { let title = story.title.clone(); - Either::Right(view! { <A href=format!("/item/{}", story.id)>{title}</A> }) + Either::Right(view! { <A href={format!("/item/{}", story.id)}>{title}</A> }) }} </span> {(story.story_type != "link") diff --git a/examples/hackernews_js_fetch/src/routes/story.rs b/examples/hackernews_js_fetch/src/routes/story.rs index 2fff740211..babca7ecc3 100644 --- a/examples/hackernews_js_fetch/src/routes/story.rs +++ b/examples/hackernews_js_fetch/src/routes/story.rs @@ -28,10 +28,10 @@ pub fn Story() -> impl IntoView { None => Either::Left("Story not found."), Some(story) => { Either::Right(view! { - <Meta name="description" content=story.title.clone()/> + <Meta name="description" content={story.title.clone()} /> <div class="item-view"> <div class="item-view-header"> - <a href=story.url target="_blank"> + <a href={story.url} target="_blank"> <h1>{story.title}</h1> </a> <span class="host">"("{story.domain}")"</span> @@ -41,7 +41,7 @@ pub fn Story() -> impl IntoView { view! { <p class="meta"> {story.points} " points | by " - <A href=format!("/users/{user}")>{user.clone()}</A> + <A href={format!("/users/{user}")}>{user.clone()}</A> {format!(" {}", story.time_ago)} </p> } @@ -57,11 +57,11 @@ pub fn Story() -> impl IntoView { </p> <ul class="comment-children"> <For - each=move || story.comments.clone().unwrap_or_default() - key=|comment| comment.id + each={move || story.comments.clone().unwrap_or_default()} + key={|comment| comment.id} let:comment > - <Comment comment/> + <Comment comment /> </For> </ul> </div> @@ -79,21 +79,21 @@ pub fn Comment(comment: api::Comment) -> impl IntoView { view! { <li class="comment"> <div class="by"> - <A href=format!( + <A href={format!( "/users/{}", comment.user.clone().unwrap_or_default(), - )>{comment.user.clone()}</A> + )}>{comment.user.clone()}</A> {format!(" {}", comment.time_ago)} </div> - <div class="text" inner_html=comment.content></div> + <div class="text" inner_html={comment.content}></div> {(!comment.comments.is_empty()) .then(|| { view! { <div> - <div class="toggle" class:open=open> - <a on:click=move |_| { + <div class="toggle" class:open={open}> + <a on:click={move |_| { set_open.update(|n| *n = !*n) - }> + }}> { let comments_len = comment.comments.len(); move || { @@ -118,11 +118,11 @@ pub fn Comment(comment: api::Comment) -> impl IntoView { view! { <ul class="comment-children"> <For - each=move || comments.clone() - key=|comment| comment.id + each={move || comments.clone()} + key={|comment| comment.id} let:comment > - <Comment comment/> + <Comment comment /> </For> </ul> } diff --git a/examples/hackernews_js_fetch/src/routes/users.rs b/examples/hackernews_js_fetch/src/routes/users.rs index 160deb411b..cbd6d80598 100644 --- a/examples/hackernews_js_fetch/src/routes/users.rs +++ b/examples/hackernews_js_fetch/src/routes/users.rs @@ -20,9 +20,9 @@ pub fn User() -> impl IntoView { ); view! { <div class="user-view"> - <Suspense fallback=|| { + <Suspense fallback={|| { view! { "Loading..." } - }> + }}> {move || Suspend::new(async move { match user.await.clone() { None => Either::Left(view! { <h1>"User not found."</h1> }), @@ -40,18 +40,18 @@ pub fn User() -> impl IntoView { <span class="label">"Karma: "</span> {user.karma} </li> - <li inner_html=user.about class="about"></li> + <li inner_html={user.about} class="about"></li> </ul> <p class="links"> - <a href=format!( + <a href={format!( "https://news.ycombinator.com/submitted?id={}", user.id, - )>"submissions"</a> + )}>"submissions"</a> " | " - <a href=format!( + <a href={format!( "https://news.ycombinator.com/threads?id={}", user.id, - )>"comments"</a> + )}>"comments"</a> </p> </div> }, diff --git a/examples/islands/src/app.rs b/examples/islands/src/app.rs index 9b37d27bcf..deaa9e8686 100644 --- a/examples/islands/src/app.rs +++ b/examples/islands/src/app.rs @@ -2,18 +2,18 @@ use leptos::prelude::*; pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1"/> - <AutoReload options=options.clone()/> - <HydrationScripts options=options islands=true/> - <link rel="stylesheet" id="leptos" href="/pkg/islands.css"/> - <link rel="shortcut icon" type="image/ico" href="/favicon.ico"/> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <AutoReload options={options.clone()} /> + <HydrationScripts options={options} islands=true /> + <link rel="stylesheet" id="leptos" href="/pkg/islands.css" /> + <link rel="shortcut icon" type="image/ico" href="/favicon.ico" /> </head> <body> - <App/> + <App /> </body> </html> } @@ -27,9 +27,9 @@ pub fn App() -> impl IntoView { </header> <main> <OuterIsland> - <InnerIsland/> - <InnerIsland/> - <InnerIsland/> + <InnerIsland /> + <InnerIsland /> + <InnerIsland /> </OuterIsland> </main> } @@ -41,9 +41,9 @@ pub fn OuterIsland(children: Children) -> impl IntoView { view! { <div class="outer-island"> <h2>"Outer Island"</h2> - <button on:click=|_| leptos::logging::log!("clicked button in island!")> - "Click me" - </button> + <button on:click={|_| { + leptos::logging::log!("clicked button in island!") + }}>"Click me"</button> {children()} </div> } @@ -54,8 +54,8 @@ pub fn InnerIsland() -> impl IntoView { let val = use_context::<i32>(); view! { <h2>"Inner Island"</h2> - <button on:click=move |_| leptos::logging::log!("value should be Some(42) -- it's {val:?}")> - "Click me (inner)" - </button> + <button on:click={move |_| { + leptos::logging::log!("value should be Some(42) -- it's {val:?}") + }}>"Click me (inner)"</button> } } diff --git a/examples/islands_router/src/app.rs b/examples/islands_router/src/app.rs index a38cef001f..5e9da42bd3 100644 --- a/examples/islands_router/src/app.rs +++ b/examples/islands_router/src/app.rs @@ -6,18 +6,18 @@ use leptos_router::{ pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1"/> - <AutoReload options=options.clone()/> - <HydrationScripts options=options islands=true/> - <link rel="stylesheet" id="leptos" href="/pkg/islands.css"/> - <link rel="shortcut icon" type="image/ico" href="/favicon.ico"/> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <AutoReload options={options.clone()} /> + <HydrationScripts options={options} islands=true /> + <link rel="stylesheet" id="leptos" href="/pkg/islands.css" /> + <link rel="shortcut icon" type="image/ico" href="/favicon.ico" /> </head> <body> - <App/> + <App /> </body> </html> } @@ -37,11 +37,11 @@ pub fn App() -> impl IntoView { </nav> <main> <p> - <label>"Home Checkbox" <input type="checkbox"/></label> + <label>"Home Checkbox" <input type="checkbox" /></label> </p> - <FlatRoutes fallback=|| "Not found."> - <Route path=StaticSegment("") view=PageA/> - <Route path=StaticSegment("b") view=PageB/> + <FlatRoutes fallback={|| "Not found."}> + <Route path={StaticSegment("")} view={PageA} /> + <Route path={StaticSegment("b")} view={PageB} /> </FlatRoutes> </main> </Router> @@ -50,10 +50,10 @@ pub fn App() -> impl IntoView { #[component] pub fn PageA() -> impl IntoView { - view! { <label>"Page A" <input type="checkbox"/></label> } + view! { <label>"Page A" <input type="checkbox" /></label> } } #[component] pub fn PageB() -> impl IntoView { - view! { <label>"Page B" <input type="checkbox"/></label> } + view! { <label>"Page B" <input type="checkbox" /></label> } } diff --git a/examples/js-framework-benchmark/src/lib.rs b/examples/js-framework-benchmark/src/lib.rs index 2985ef040c..c6b5b135a7 100644 --- a/examples/js-framework-benchmark/src/lib.rs +++ b/examples/js-framework-benchmark/src/lib.rs @@ -87,7 +87,7 @@ fn Button( ) -> impl IntoView { view! { <div class="col-sm-6 smallpad"> - <button id=id class="btn btn-primary btn-block" type="button"> + <button id={id} class="btn btn-primary btn-block" type="button"> {text} </button> </div> @@ -149,12 +149,12 @@ pub fn App() -> impl IntoView { </div> <div class="col-md-6"> <div class="row"> - <Button id="run" text="Create 1,000 rows" on:click=run/> - <Button id="runlots" text="Create 10,000 rows" on:click=run_lots/> - <Button id="add" text="Append 1,000 rows" on:click=add/> - <Button id="update" text="Update every 10th row" on:click=update/> - <Button id="clear" text="Clear" on:click=clear/> - <Button id="swaprows" text="Swap Rows" on:click=swap_rows/> + <Button id="run" text="Create 1,000 rows" on:click={run} /> + <Button id="runlots" text="Create 10,000 rows" on:click={run_lots} /> + <Button id="add" text="Append 1,000 rows" on:click={add} /> + <Button id="update" text="Update every 10th row" on:click={update} /> + <Button id="clear" text="Clear" on:click={clear} /> + <Button id="swaprows" text="Swap Rows" on:click={swap_rows} /> </div> </div> </div> @@ -164,19 +164,32 @@ pub fn App() -> impl IntoView { <For each={move || data.get()} key={|row| row.id} - children=move |row: RowData| { + children={move |row: RowData| { let row_id = row.id; let label = row.label; let is_selected = is_selected.clone(); - ViewTemplate::new(view! { - <tr class:danger={move || is_selected.selected(Some(row_id))}> - <td class="col-md-1">{row_id.to_string()}</td> - <td class="col-md-4"><a on:click=move |_| set_selected.set(Some(row_id))>{move || label.get()}</a></td> - <td class="col-md-1"><a on:click=move |_| remove(row_id)><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></a></td> - <td class="col-md-6"/> - </tr> - }) - } + ViewTemplate::new( + view! { + <tr class:danger={move || is_selected.selected(Some(row_id))}> + <td class="col-md-1">{row_id.to_string()}</td> + <td class="col-md-4"> + <a on:click={move |_| { + set_selected.set(Some(row_id)) + }}>{move || label.get()}</a> + </td> + <td class="col-md-1"> + <a on:click={move |_| remove(row_id)}> + <span + class="glyphicon glyphicon-remove" + aria-hidden="true" + ></span> + </a> + </td> + <td class="col-md-6" /> + </tr> + }, + ) + }} /> </tbody> </table> diff --git a/examples/parent_child/src/lib.rs b/examples/parent_child/src/lib.rs index 4db490f983..1a07458b2c 100644 --- a/examples/parent_child/src/lib.rs +++ b/examples/parent_child/src/lib.rs @@ -30,27 +30,27 @@ pub fn App() -> impl IntoView { <main> <p // class: attributes take F: Fn() => bool, and these signals all implement Fn() - class:red=red - class:right=right - class:italics=italics - class:smallcaps=smallcaps + class:red={red} + class:right={right} + class:italics={italics} + class:smallcaps={smallcaps} > "Lorem ipsum sit dolor amet." </p> // Button A: pass the signal setter - <ButtonA setter=set_red/> + <ButtonA setter={set_red} /> // Button B: pass a closure - <ButtonB on_click=move |_| set_right.update(|value| *value = !*value)/> + <ButtonB on_click={move |_| set_right.update(|value| *value = !*value)} /> // Button C: use a regular event listener // setting an event listener on a component like this applies it // to each of the top-level elements the component returns - <ButtonC on:click=move |_| set_italics.update(|value| *value = !*value)/> + <ButtonC on:click={move |_| set_italics.update(|value| *value = !*value)} /> // Button D gets its setter from context rather than props - <ButtonD/> + <ButtonD /> </main> } } @@ -61,7 +61,7 @@ pub fn ButtonA( /// Signal that will be toggled when the button is clicked. setter: WriteSignal<bool>, ) -> impl IntoView { - view! { <button on:click=move |_| setter.update(|value| *value = !*value)>"Toggle Red"</button> } + view! { <button on:click={move |_| setter.update(|value| *value = !*value)}>"Toggle Red"</button> } } /// Button B receives a closure @@ -70,7 +70,7 @@ pub fn ButtonB( /// Callback that will be invoked when the button is clicked. on_click: impl FnMut(MouseEvent) + 'static, ) -> impl IntoView { - view! { <button on:click=on_click>"Toggle Right"</button> } + view! { <button on:click={on_click}>"Toggle Right"</button> } } /// Button C is a dummy: it renders a button but doesn't handle @@ -87,8 +87,8 @@ pub fn ButtonD() -> impl IntoView { let setter = use_context::<SmallcapsContext>().unwrap().0; view! { - <button on:click=move |_| { + <button on:click={move |_| { setter.update(|value| *value = !*value) - }>"Toggle Small Caps"</button> + }}>"Toggle Small Caps"</button> } } diff --git a/examples/portal/src/lib.rs b/examples/portal/src/lib.rs index 0530879247..8636785aa4 100644 --- a/examples/portal/src/lib.rs +++ b/examples/portal/src/lib.rs @@ -9,23 +9,31 @@ pub fn App() -> impl IntoView { view! { <div> - <button id="btn-show" on:click=move |_| set_show_overlay.set(true)> + <button id="btn-show" on:click={move |_| set_show_overlay.set(true)}> Show Overlay </button> - <Show when=move || show_overlay.get() fallback=|| ()> + <Show when={move || show_overlay.get()} fallback={|| ()}> <div>Show</div> - <Portal mount=document().get_element_by_id("app").unwrap()> + <Portal mount={document().get_element_by_id("app").unwrap()}> <div style="position: fixed; z-index: 10; width: 100vw; height: 100vh; top: 0; left: 0; background: rgba(0, 0, 0, 0.8); color: white;"> <p>This is in the body element</p> - <button id="btn-hide" on:click=move |_| set_show_overlay.set(false)> + <button id="btn-hide" on:click={move |_| set_show_overlay.set(false)}> Close Overlay </button> - <button id="btn-toggle" on:click=move |_| set_show_inside_overlay.set(!show_inside_overlay.get())> + <button + id="btn-toggle" + on:click={move |_| { + set_show_inside_overlay.set(!show_inside_overlay.get()) + }} + > Toggle inner </button> - <Show when=move || show_inside_overlay.get() fallback=|| view! { "Hidden" }> + <Show + when={move || show_inside_overlay.get()} + fallback={|| view! { "Hidden" }} + > Visible </Show> </div> diff --git a/examples/router/src/lib.rs b/examples/router/src/lib.rs index 214874cc4e..fb0516ef54 100644 --- a/examples/router/src/lib.rs +++ b/examples/router/src/lib.rs @@ -39,23 +39,26 @@ pub fn RouterExample() -> impl IntoView { <A href="/about">"About"</A> <A href="/settings">"Settings"</A> <A href="/redirect-home">"Redirect to Home"</A> - <button on:click=move |_| { + <button on:click={move |_| { set_logged_in.update(|n| *n = !*n) - }>{move || if logged_in.get() { "Log Out" } else { "Log In" }}</button> + }}>{move || if logged_in.get() { "Log Out" } else { "Log In" }}</button> </nav> <main> - <Routes fallback=|| "This page could not be found."> + <Routes fallback={|| "This page could not be found."}> // paths can be created using the path!() macro, or provided as types like // StaticSegment("about") - <Route path=path!("about") view=About/> + <Route path={path!("about")} view={About} /> <ProtectedRoute - path=path!("settings") - condition=move || Some(logged_in.get()) - redirect_path=|| "/" - view=Settings + path={path!("settings")} + condition={move || Some(logged_in.get())} + redirect_path={|| "/"} + view={Settings} /> - <Route path=path!("redirect-home") view=|| view! { <Redirect path="/"/> }/> - <ContactRoutes/> + <Route + path={path!("redirect-home")} + view={|| view! { <Redirect path="/" /> }} + /> + <ContactRoutes /> </Routes> </main> </Router> @@ -67,9 +70,9 @@ pub fn RouterExample() -> impl IntoView { #[component] pub fn ContactRoutes() -> impl MatchNestedRoutes<Dom> + Clone { view! { - <ParentRoute path=path!("") view=ContactList> - <Route path=path!("/") view=|| "Select a contact."/> - <Route path=path!("/:id") view=Contact/> + <ParentRoute path={path!("")} view={ContactList}> + <Route path={path!("/")} view={|| "Select a contact."} /> + <Route path={path!("/:id")} view={Contact} /> </ParentRoute> } } @@ -99,7 +102,7 @@ pub fn ContactList() -> impl IntoView { .map(|contact| { view! { <li> - <A href=contact.id.to_string()> + <A href={contact.id.to_string()}> <span>{contact.first_name} " " {contact.last_name}</span> </A> </li> @@ -112,10 +115,10 @@ pub fn ContactList() -> impl IntoView { view! { <div class="contact-list"> <h1>"Contacts"</h1> - <Suspense fallback=move || view! { <p>"Loading contacts..."</p> }> + <Suspense fallback={move || view! { <p>"Loading contacts..."</p> }}> <ul>{contacts}</ul> </Suspense> - <Outlet/> + <Outlet /> </div> } } @@ -159,7 +162,7 @@ pub fn Contact() -> impl IntoView { Some(contact) => Either::Right(view! { <section class="card"> <h1>{contact.first_name} " " {contact.last_name}</h1> - <p>{contact.address_1} <br/> {contact.address_2}</p> + <p>{contact.address_1} <br /> {contact.address_2}</p> </section> }), } @@ -168,9 +171,9 @@ pub fn Contact() -> impl IntoView { view! { <div class="contact"> - <Transition fallback=move || { + <Transition fallback={move || { view! { <p>"Loading..."</p> } - }>{contact_display}</Transition> + }}>{contact_display}</Transition> </div> } } @@ -196,7 +199,7 @@ pub fn About() -> impl IntoView { // you should ordinarily use a link instead, // both semantically and so your link will work before WASM loads view! { - <button on:click=move |_| navigate("/", Default::default())>"Home"</button> + <button on:click={move |_| navigate("/", Default::default())}>"Home"</button> <h1>"About"</h1> <p> "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." @@ -217,10 +220,10 @@ pub fn Settings() -> impl IntoView { <Form action=""> <fieldset> <legend>"Name"</legend> - <input type="text" name="first_name" placeholder="First"/> - <input type="text" name="last_name" placeholder="Last"/> + <input type="text" name="first_name" placeholder="First" /> + <input type="text" name="last_name" placeholder="Last" /> </fieldset> - <input type="submit"/> + <input type="submit" /> <p> "This uses the " <code>"<Form/>"</code> " component, which enhances forms by using client-side navigation for " diff --git a/examples/server_fns_axum/src/app.rs b/examples/server_fns_axum/src/app.rs index b29d4f4e23..30b8cbf9a4 100644 --- a/examples/server_fns_axum/src/app.rs +++ b/examples/server_fns_axum/src/app.rs @@ -23,19 +23,19 @@ use web_sys::{FormData, HtmlFormElement, SubmitEvent}; pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1"/> - <AutoReload options=options.clone()/> - <HydrationScripts options/> - <meta name="color-scheme" content="dark light"/> - <link rel="shortcut icon" type="image/ico" href="/favicon.ico"/> - <link rel="stylesheet" id="leptos" href="/pkg/server_fns_axum.css"/> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <AutoReload options={options.clone()} /> + <HydrationScripts options /> + <meta name="color-scheme" content="dark light" /> + <link rel="shortcut icon" type="image/ico" href="/favicon.ico" /> + <link rel="stylesheet" id="leptos" href="/pkg/server_fns_axum.css" /> </head> <body> - <App/> + <App /> </body> </html> } @@ -48,7 +48,7 @@ pub fn App() -> impl IntoView { <h1>"Server Function Demo"</h1> </header> <main> - <HomePage/> + <HomePage /> </main> } } @@ -57,19 +57,19 @@ pub fn App() -> impl IntoView { pub fn HomePage() -> impl IntoView { view! { <h2>"Some Simple Server Functions"</h2> - <SpawnLocal/> - <WithAnAction/> - <WithActionForm/> + <SpawnLocal /> + <WithAnAction /> + <WithActionForm /> <h2>"Custom Error Types"</h2> - <CustomErrorTypes/> + <CustomErrorTypes /> <h2>"Alternative Encodings"</h2> - <ServerFnArgumentExample/> - <RkyvExample/> - <FileUpload/> - <FileUploadWithProgress/> - <FileWatcher/> - <CustomEncoding/> - <CustomClientExample/> + <ServerFnArgumentExample /> + <RkyvExample /> + <FileUpload /> + <FileUploadWithProgress /> + <FileWatcher /> + <CustomEncoding /> + <CustomClientExample /> } } @@ -105,14 +105,14 @@ pub fn SpawnLocal() -> impl IntoView { " in an event listener. " "Clicking this button should alert with the uppercase version of the input." </p> - <input node_ref=input_ref placeholder="Type something here."/> - <button on:click=move |_| { + <input node_ref={input_ref} placeholder="Type something here." /> + <button on:click={move |_| { let value = input_ref.get().unwrap().value(); spawn_local(async move { let uppercase_text = shouting_text(value).await.unwrap_or_else(|e| e.to_string()); set_shout_result.set(uppercase_text); }); - }> + }}> {shout_result} </button> @@ -184,11 +184,11 @@ pub fn WithAnAction() -> impl IntoView { "Some server functions are conceptually \"mutations,\", which change something on the server. " "These often work well as actions." </p> - <input node_ref=input_ref placeholder="Type something here."/> - <button on:click=move |_| { + <input node_ref={input_ref} placeholder="Type something here." /> + <button on:click={move |_| { let text = input_ref.get().unwrap().value(); action.dispatch(text.into()); - }> + }}> Submit </button> @@ -274,16 +274,16 @@ pub fn ServerFnArgumentExample() -> impl IntoView { <ul> <li>Specific server function <strong>paths</strong></li> <li>Mixing and matching input and output <strong>encodings</strong></li> - <li>Adding custom <strong>middleware</strong> on a per-server-fn basis</li> + <li>Adding custom <strong>middleware</strong>on a per-server-fn basis</li> </ul> - <input node_ref=input_ref placeholder="Type something here."/> - <button on:click=move |_| { + <input node_ref={input_ref} placeholder="Type something here." /> + <button on:click={move |_| { let value = input_ref.get().unwrap().value(); spawn_local(async move { let length = length_of_input(value).await.unwrap_or(0); set_result.set(length); }); - }> + }}> Click to see length </button> @@ -314,12 +314,12 @@ pub fn RkyvExample() -> impl IntoView { let rkyv_result = Resource::new(move || input.get(), rkyv_example); view! { - <h3>Using <code>rkyv</code> encoding</h3> - <input node_ref=input_ref placeholder="Type something here."/> - <button on:click=move |_| { + <h3>Using <code>rkyv</code>encoding</h3> + <input node_ref={input_ref} placeholder="Type something here." /> + <button on:click={move |_| { let value = input_ref.get().unwrap().value(); set_input.set(value); - }> + }}> Click to capitalize </button> @@ -369,18 +369,19 @@ pub fn FileUpload() -> impl IntoView { view! { <h3>File Upload</h3> <p>Uploading files is fairly easy using multipart form data.</p> - <form on:submit=move |ev: SubmitEvent| { + <form on:submit={move |ev: SubmitEvent| { ev.prevent_default(); let target = ev.target().unwrap().unchecked_into::<HtmlFormElement>(); let form_data = FormData::new_with_form(&target).unwrap(); upload_action.dispatch_local(form_data); - }> - <input type="file" name="file_to_upload"/> - <input type="submit"/> + }}> + <input type="file" name="file_to_upload" /> + <input type="submit" /> </form> <p> {move || { - if upload_action.input_local().read().is_none() && upload_action.value().read().is_none() + if upload_action.input_local().read().is_none() + && upload_action.value().read().is_none() { "Upload a file.".to_string() } else if upload_action.pending().get() { @@ -548,9 +549,9 @@ pub fn FileUploadWithProgress() -> impl IntoView { <h3>File Upload with Progress</h3> <p>A file upload with progress can be handled with two separate server functions.</p> <aside>See the doc comment on the component for an explanation.</aside> - <form on:submit=on_submit> - <input type="file" name="file_to_upload"/> - <input type="submit"/> + <form on:submit={on_submit}> + <input type="file" name="file_to_upload" /> + <input type="submit" /> </form> {move || filename.get().map(|filename| view! { <p>Uploading {filename}</p> })} {move || { @@ -558,8 +559,8 @@ pub fn FileUploadWithProgress() -> impl IntoView { .map(|max| { view! { <progress - max=max - value=move || current.get().unwrap_or_default() + max={max} + value={move || current.get().unwrap_or_default()} ></progress> } }) @@ -687,14 +688,14 @@ pub fn CustomErrorTypes() -> impl IntoView { "Try typing a message that is between 5 and 15 characters of ASCII text below. Then try breaking \ the rules!" </p> - <input node_ref=input_ref placeholder="Type something here."/> - <button on:click=move |_| { + <input node_ref={input_ref} placeholder="Type something here." /> + <button on:click={move |_| { let value = input_ref.get().unwrap().value(); spawn_local(async move { let data = ascii_uppercase(value).await; set_result.set(Some(data)); }); - }> + }}> "Submit" </button> @@ -808,14 +809,14 @@ pub fn CustomEncoding() -> impl IntoView { <p> "This example creates a custom encoding that sends server fn data using TOML. Why? Well... why not?" </p> - <input node_ref=input_ref placeholder="Type something here."/> - <button on:click=move |_| { + <input node_ref={input_ref} placeholder="Type something here." /> + <button on:click={move |_| { let value = input_ref.get().unwrap().value(); spawn_local(async move { let new_value = why_not(value, ", but in TOML!!!".to_string()).await.unwrap(); set_result.set(new_value.0.modified); }); - }> + }}> Submit </button> @@ -875,8 +876,8 @@ pub fn CustomClientExample() -> impl IntoView { <p> Check the network request in your browser devtools to see how this client adds a custom header. </p> - <button on:click=|_| spawn_local(async { + <button on:click={|_| spawn_local(async { fn_with_custom_client().await.unwrap() - })>Click me</button> + })}>Click me</button> } } diff --git a/examples/server_fns_axum/src/error_template.rs b/examples/server_fns_axum/src/error_template.rs index a60429af46..10adfef4db 100644 --- a/examples/server_fns_axum/src/error_template.rs +++ b/examples/server_fns_axum/src/error_template.rs @@ -40,18 +40,18 @@ pub fn ErrorTemplate( <h1>"Errors"</h1> <For // a function that returns the items we're iterating over; a signal is fine - each=move || { errors.clone().into_iter().enumerate() } + each={move || { errors.clone().into_iter().enumerate() }} // a unique key for each item as a reference - key=|(index, _error)| *index + key={|(index, _error)| *index} // renders each item to a view - children=move |error| { + children={move |error| { let error_string = error.1.to_string(); let error_code = error.1.status_code(); view! { <h2>{error_code.to_string()}</h2> <p>"Error: " {error_string}</p> } - } + }} /> } } diff --git a/examples/slots/src/lib.rs b/examples/slots/src/lib.rs index aa39dfe876..60362bb554 100644 --- a/examples/slots/src/lib.rs +++ b/examples/slots/src/lib.rs @@ -48,14 +48,20 @@ pub fn App() -> impl IntoView { let is_div7 = MaybeSignal::derive(move || count.get() % 7 == 0); view! { - <button on:click=move |_| set_count.update(|value| *value += 1)>"+1"</button> - " "{count}" is " - <SlotIf cond=is_even> + <button on:click={move |_| set_count.update(|value| *value += 1)}>"+1"</button> + " " + {count} + " is " + <SlotIf cond={is_even}> // The slot name can be emitted if it would match the slot struct name (in snake case). <Then slot>"even"</Then> // Props are passed just like on normal components. - <ElseIf slot cond=is_div5>"divisible by 5"</ElseIf> - <ElseIf slot cond=is_div7>"divisible by 7"</ElseIf> + <ElseIf slot cond={is_div5}> + "divisible by 5" + </ElseIf> + <ElseIf slot cond={is_div7}> + "divisible by 7" + </ElseIf> <Fallback slot>"odd"</Fallback> </SlotIf> } diff --git a/examples/spread/src/lib.rs b/examples/spread/src/lib.rs index 4acf639876..5fdc12a000 100644 --- a/examples/spread/src/lib.rs +++ b/examples/spread/src/lib.rs @@ -10,17 +10,17 @@ pub fn SpreadingExample() -> impl IntoView { // you can easily create sets of spreadable attributes by using the <{..} ___/> syntax // this is expanded to a tuple of attributes; it has no meaning on its own, but can be spread // onto an HTML element or component - let attrs_only = view! { <{..} class="foo"/> }; - let event_handlers_only = view! { <{..} on:click=move |_| { - alert("event_handlers_only clicked"); - }/> }; - let combined = view! { <{..} class="bar" on:click=move |_| alert("combined clicked") /> }; + let attrs_only = view! { <{..} class="foo" /> }; + let event_handlers_only = view! { + <{..} on:click={move |_| { + alert("event_handlers_only clicked"); + }} /> + }; + let combined = view! { <{..} class="bar" on:click={move |_| alert("combined clicked")} /> }; let partial_attrs = view! { <{..} id="snood" class="baz" data-foo="bar" /> }; - let partial_event_handlers = view! { <{..} on:click=move |_| alert("partial_event_handlers clicked") /> }; - let spread_onto_component = view! { - <{..} aria-label="a component with attribute spreading"/> - }; + let partial_event_handlers = view! { <{..} on:click={move |_| alert("partial_event_handlers clicked")} /> }; + let spread_onto_component = view! { <{..} aria-label="a component with attribute spreading" /> }; /* with the correct imports, you can use a tuple/builder syntax as well let attrs_only = class("foo"); @@ -53,7 +53,7 @@ pub fn SpreadingExample() -> impl IntoView { "<div {..partial_attrs} {..partial_event_handlers} />" </div> - <hr/> + <hr /> <p> "The .. is not required to spread; you can pass any valid attribute in a block by itself." @@ -68,7 +68,7 @@ pub fn SpreadingExample() -> impl IntoView { "<div {partial_attrs} {partial_event_handlers} />" </div> - <hr/> + <hr /> // attributes that are spread onto a component will be applied to *all* elements returned as part of // the component's view. to apply attributes to a subset of the component, pass them via a component prop @@ -77,7 +77,7 @@ pub fn SpreadingExample() -> impl IntoView { class:foo=true style:font-weight="bold" prop:cool=42 - on:click=move |_| alert("clicked ComponentThatTakesSpread") + on:click={move |_| alert("clicked ComponentThatTakesSpread")} // props are passed as they usually are on components some_prop=13 // to pass a plain HTML attribute, prefix it with attr: diff --git a/examples/ssr_modes/src/app.rs b/examples/ssr_modes/src/app.rs index c60afaca9b..60c36716cf 100644 --- a/examples/ssr_modes/src/app.rs +++ b/examples/ssr_modes/src/app.rs @@ -17,26 +17,26 @@ pub fn App() -> impl IntoView { let fallback = || view! { "Page not found." }.into_view(); view! { - <Stylesheet id="leptos" href="/pkg/ssr_modes.css"/> - <Title text="Welcome to Leptos"/> - <Meta name="color-scheme" content="dark light"/> + <Stylesheet id="leptos" href="/pkg/ssr_modes.css" /> + <Title text="Welcome to Leptos" /> + <Meta name="color-scheme" content="dark light" /> <Router> <main> <FlatRoutes fallback> // We’ll load the home page with out-of-order streaming and <Suspense/> - <Route path=StaticSegment("") view=HomePage/> + <Route path={StaticSegment("")} view={HomePage} /> // We'll load the posts with async rendering, so they can set // the title and metadata *after* loading the data <Route - path=(StaticSegment("post"), ParamSegment("id")) - view=Post - ssr=SsrMode::Async + path={(StaticSegment("post"), ParamSegment("id"))} + view={Post} + ssr={SsrMode::Async} /> <Route - path=(StaticSegment("post_in_order"), ParamSegment("id")) - view=Post - ssr=SsrMode::InOrder + path={(StaticSegment("post_in_order"), ParamSegment("id"))} + view={Post} + ssr={SsrMode::InOrder} /> </FlatRoutes> </main> @@ -63,16 +63,19 @@ fn HomePage() -> impl IntoView { view! { <h1>"My Great Blog"</h1> - <Suspense fallback=move || view! { <p>"Loading posts..."</p> }> + <Suspense fallback={move || view! { <p>"Loading posts..."</p> }}> <p>"number of posts: " {Suspend::new(async move { posts2.await })}</p> </Suspense> - <Suspense fallback=move || view! { <p>"Loading posts..."</p> }> + <Suspense fallback={move || view! { <p>"Loading posts..."</p> }}> <ul> - <For each=posts key=|post| post.id let:post> + <For each={posts} key={|post| post.id} let:post> <li> - <a href=format!("/post/{}", post.id)>{post.title.clone()}</a> + <a href={format!("/post/{}", post.id)}>{post.title.clone()}</a> "|" - <a href=format!("/post_in_order/{}", post.id)>{post.title} "(in order)"</a> + <a href={format!( + "/post_in_order/{}", + post.id, + )}>{post.title} "(in order)"</a> </li> </For> </ul> @@ -114,8 +117,8 @@ fn Post() -> impl IntoView { // since we're using async rendering for this page, // this metadata should be included in the actual HTML <head> // when it's first served - <Title text=post.title/> - <Meta name="description" content=post.content/> + <Title text={post.title} /> + <Meta name="description" content={post.content} /> }), _ => Err(PostError::ServerError), } @@ -123,8 +126,8 @@ fn Post() -> impl IntoView { view! { <em>"The world's best content."</em> - <Suspense fallback=move || view! { <p>"Loading post..."</p> }> - <ErrorBoundary fallback=|errors| { + <Suspense fallback={move || view! { <p>"Loading post..."</p> }}> + <ErrorBoundary fallback={|errors| { view! { <div class="error"> <h1>"Something went wrong."</h1> @@ -140,7 +143,7 @@ fn Post() -> impl IntoView { </ul> </div> } - }>{post_view}</ErrorBoundary> + }}>{post_view}</ErrorBoundary> </Suspense> } } diff --git a/examples/ssr_modes/src/main.rs b/examples/ssr_modes/src/main.rs index 7a24ec2e43..479b9944d7 100644 --- a/examples/ssr_modes/src/main.rs +++ b/examples/ssr_modes/src/main.rs @@ -24,17 +24,20 @@ async fn main() -> std::io::Result<()> { use leptos::prelude::*; view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1"/> - <AutoReload options=leptos_options.clone() /> - <HydrationScripts options=leptos_options.clone()/> - <MetaTags/> + <meta charset="utf-8" /> + <meta + name="viewport" + content="width=device-width, initial-scale=1" + /> + <AutoReload options={leptos_options.clone()} /> + <HydrationScripts options={leptos_options.clone()} /> + <MetaTags /> </head> <body> - <App/> + <App /> </body> </html> } diff --git a/examples/ssr_modes_axum/src/app.rs b/examples/ssr_modes_axum/src/app.rs index 60926d9f0a..d4a5c11b97 100644 --- a/examples/ssr_modes_axum/src/app.rs +++ b/examples/ssr_modes_axum/src/app.rs @@ -15,17 +15,17 @@ use thiserror::Error; pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1"/> - <AutoReload options=options.clone() /> - <HydrationScripts options/> - <MetaTags/> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <AutoReload options={options.clone()} /> + <HydrationScripts options /> + <MetaTags /> </head> <body> - <App/> + <App /> </body> </html> } @@ -55,23 +55,30 @@ pub fn App() -> impl IntoView { Resource::new(move || toggle_admin.version().get(), |_| is_admin()); view! { - <Stylesheet id="leptos" href="/pkg/ssr_modes.css"/> - <Title text="Welcome to Leptos"/> - <Meta name="color-scheme" content="dark light"/> + <Stylesheet id="leptos" href="/pkg/ssr_modes.css" /> + <Title text="Welcome to Leptos" /> + <Meta name="color-scheme" content="dark light" /> <Router> <nav> <a href="/">"Home"</a> <a href="/admin">"Admin"</a> <Transition> - <ActionForm action=toggle_admin> - <input type="hidden" name="is_admin" - value=move || (!is_admin.get().and_then(|n| n.ok()).unwrap_or_default()).to_string() + <ActionForm action={toggle_admin}> + <input + type="hidden" + name="is_admin" + value={move || { + (!is_admin.get().and_then(|n| n.ok()).unwrap_or_default()) + .to_string() + }} /> <button> - {move || if is_admin.get().and_then(Result::ok).unwrap_or_default() { - "Log Out" - } else { - "Log In" + {move || { + if is_admin.get().and_then(Result::ok).unwrap_or_default() { + "Log Out" + } else { + "Log In" + } }} </button> </ActionForm> @@ -80,30 +87,30 @@ pub fn App() -> impl IntoView { <main> <FlatRoutes fallback> // We’ll load the home page with out-of-order streaming and <Suspense/> - <Route path=StaticSegment("") view=HomePage/> + <Route path={StaticSegment("")} view={HomePage} /> // We'll load the posts with async rendering, so they can set // the title and metadata *after* loading the data <Route - path=(StaticSegment("post"), ParamSegment("id")) - view=Post - ssr=SsrMode::Async + path={(StaticSegment("post"), ParamSegment("id"))} + view={Post} + ssr={SsrMode::Async} /> <Route - path=(StaticSegment("post_in_order"), ParamSegment("id")) - view=Post - ssr=SsrMode::InOrder + path={(StaticSegment("post_in_order"), ParamSegment("id"))} + view={Post} + ssr={SsrMode::InOrder} /> <Route - path=(StaticSegment("post_partially_blocked"), ParamSegment("id")) - view=Post + path={(StaticSegment("post_partially_blocked"), ParamSegment("id"))} + view={Post} /> <ProtectedRoute - path=StaticSegment("admin") - view=Admin - ssr=SsrMode::Async - condition=move || is_admin.get().map(|n| n.unwrap_or(false)) - redirect_path=|| "/" + path={StaticSegment("admin")} + view={Admin} + ssr={SsrMode::Async} + condition={move || is_admin.get().map(|n| n.unwrap_or(false))} + redirect_path={|| "/"} /> </FlatRoutes> </main> @@ -130,18 +137,24 @@ fn HomePage() -> impl IntoView { view! { <h1>"My Great Blog"</h1> - <Suspense fallback=move || view! { <p>"Loading posts..."</p> }> + <Suspense fallback={move || view! { <p>"Loading posts..."</p> }}> <p>"number of posts: " {Suspend::new(async move { posts2.await })}</p> </Suspense> - <Suspense fallback=move || view! { <p>"Loading posts..."</p> }> + <Suspense fallback={move || view! { <p>"Loading posts..."</p> }}> <ul> - <For each=posts key=|post| post.id let:post> + <For each={posts} key={|post| post.id} let:post> <li> - <a href=format!("/post/{}", post.id)>{post.title.clone()}</a> + <a href={format!("/post/{}", post.id)}>{post.title.clone()}</a> "|" - <a href=format!("/post_in_order/{}", post.id)>{post.title.clone()} "(in order)"</a> + <a href={format!( + "/post_in_order/{}", + post.id, + )}>{post.title.clone()} "(in order)"</a> "|" - <a href=format!("/post_partially_blocked/{}", post.id)>{post.title} "(partially blocked)"</a> + <a href={format!( + "/post_partially_blocked/{}", + post.id, + )}>{post.title} "(partially blocked)"</a> </li> </For> </ul> @@ -192,8 +205,8 @@ fn Post() -> impl IntoView { // since we're using async rendering for this page, // this metadata should be included in the actual HTML <head> // when it's first served - <Title text=post.title/> - <Meta name="description" content=post.content/> + <Title text={post.title} /> + <Meta name="description" content={post.content} /> }) } _ => Err(PostError::ServerError), @@ -204,12 +217,10 @@ fn Post() -> impl IntoView { Ok(comments) => Ok(view! { <h1>"Comments"</h1> <ul> - {comments.into_iter() - .map(|comment| view! { - <li>{comment}</li> - }) - .collect_view() - } + {comments + .into_iter() + .map(|comment| view! { <li>{comment}</li> }) + .collect_view()} </ul> }), _ => Err(PostError::ServerError), @@ -218,8 +229,8 @@ fn Post() -> impl IntoView { view! { <em>"The world's best content."</em> - <Suspense fallback=move || view! { <p>"Loading post..."</p> }> - <ErrorBoundary fallback=|errors| { + <Suspense fallback={move || view! { <p>"Loading post..."</p> }}> + <ErrorBoundary fallback={|errors| { view! { <div class="error"> <h1>"Something went wrong."</h1> @@ -235,19 +246,17 @@ fn Post() -> impl IntoView { </ul> </div> } - }>{post_view}</ErrorBoundary> - </Suspense> - <Suspense fallback=move || view! { <p>"Loading comments..."</p> }> - {comments_view} + }}>{post_view}</ErrorBoundary> </Suspense> + <Suspense fallback={move || { + view! { <p>"Loading comments..."</p> } + }}>{comments_view}</Suspense> } } #[component] pub fn Admin() -> impl IntoView { - view! { - <p>"You can only see this page if you're logged in."</p> - } + view! { <p>"You can only see this page if you're logged in."</p> } } // Dummy API diff --git a/examples/stores/src/lib.rs b/examples/stores/src/lib.rs index 1827ae74f4..1639c50c4c 100644 --- a/examples/stores/src/lib.rs +++ b/examples/stores/src/lib.rs @@ -54,18 +54,18 @@ pub fn App() -> impl IntoView { .todos() .iter() .enumerate() - .map(|(idx, todo)| view! { <TodoRow store idx todo/> }) + .map(|(idx, todo)| view! { <TodoRow store idx todo /> }) .collect_view() }; view! { <p>"Hello, " {move || store.user().get()}</p> - <form on:submit=move |ev| { + <form on:submit={move |ev| { ev.prevent_default(); store.todos().write().push(Todo::new(input_ref.get().unwrap().value())); - }> - <label>"Add a Todo" <input type="text" node_ref=input_ref/></label> - <input type="submit"/> + }}> + <label>"Add a Todo" <input type="text" node_ref={input_ref} /></label> + <input type="submit" /> </form> <ol>{rows}</ol> <div style="display: flex"></div> @@ -85,46 +85,46 @@ fn TodoRow( view! { <li - style:text-decoration=move || { + style:text-decoration={move || { completed.get().then_some("line-through").unwrap_or_default() - } + }} - class:foo=move || completed.get() + class:foo={move || completed.get()} > <p - class:hidden=move || editing.get() - on:click=move |_| { + class:hidden={move || editing.get()} + on:click={move |_| { editing.update(|n| *n = !*n); - } + }} > {move || title.get()} </p> <input - class:hidden=move || !(editing.get()) + class:hidden={move || !(editing.get())} type="text" - prop:value=move || title.get() - on:change=move |ev| { + prop:value={move || title.get()} + on:change={move |ev| { title.set(event_target_value(&ev)); editing.set(false); - } + }} - on:blur=move |_| editing.set(false) + on:blur={move |_| editing.set(false)} autofocus /> <input type="checkbox" - prop:checked=move || completed.get() - on:click=move |_| { completed.update(|n| *n = !*n) } + prop:checked={move || completed.get()} + on:click={move |_| { completed.update(|n| *n = !*n) }} /> - <button on:click=move |_| { + <button on:click={move |_| { store .todos() .update(|todos| { todos.remove(idx); }); - }>"X"</button> + }}>"X"</button> </li> } } diff --git a/examples/suspense_tests/src/app.rs b/examples/suspense_tests/src/app.rs index 07cab868c6..04eb445ea3 100644 --- a/examples/suspense_tests/src/app.rs +++ b/examples/suspense_tests/src/app.rs @@ -43,72 +43,72 @@ pub fn App() -> impl IntoView { <A href="/async">"Async"</A> </nav> <main> - <Routes fallback=|| "Page not found."> + <Routes fallback={|| "Page not found."}> <Route - path=StaticSegment("") - view=|| view! { <Redirect path="/out-of-order"/> } + path={StaticSegment("")} + view={|| view! { <Redirect path="/out-of-order" /> }} /> // out-of-order <ParentRoute - path=StaticSegment("out-of-order") - view=|| { + path={StaticSegment("out-of-order")} + view={|| { view! { - <SecondaryNav/> + <SecondaryNav /> <h1>"Out-of-Order"</h1> - <Outlet/> + <Outlet /> } - } + }} > - <Route path=StaticSegment("") view=Nested/> - <Route path=StaticSegment("inside") view=NestedResourceInside/> - <Route path=StaticSegment("single") view=Single/> - <Route path=StaticSegment("parallel") view=Parallel/> - <Route path=StaticSegment("inside-component") view=InsideComponent/> - <Route path=StaticSegment("local") view=LocalResource/> - <Route path=StaticSegment("none") view=None/> + <Route path={StaticSegment("")} view={Nested} /> + <Route path={StaticSegment("inside")} view={NestedResourceInside} /> + <Route path={StaticSegment("single")} view={Single} /> + <Route path={StaticSegment("parallel")} view={Parallel} /> + <Route path={StaticSegment("inside-component")} view={InsideComponent} /> + <Route path={StaticSegment("local")} view={LocalResource} /> + <Route path={StaticSegment("none")} view={None} /> </ParentRoute> // in-order <ParentRoute - path=StaticSegment("in-order") - ssr=SsrMode::InOrder - view=|| { + path={StaticSegment("in-order")} + ssr={SsrMode::InOrder} + view={|| { view! { - <SecondaryNav/> + <SecondaryNav /> <h1>"In-Order"</h1> - <Outlet/> + <Outlet /> } - } + }} > - <Route path=StaticSegment("") view=Nested/> - <Route path=StaticSegment("inside") view=NestedResourceInside/> - <Route path=StaticSegment("single") view=Single/> - <Route path=StaticSegment("parallel") view=Parallel/> - <Route path=StaticSegment("inside-component") view=InsideComponent/> - <Route path=StaticSegment("local") view=LocalResource/> - <Route path=StaticSegment("none") view=None/> + <Route path={StaticSegment("")} view={Nested} /> + <Route path={StaticSegment("inside")} view={NestedResourceInside} /> + <Route path={StaticSegment("single")} view={Single} /> + <Route path={StaticSegment("parallel")} view={Parallel} /> + <Route path={StaticSegment("inside-component")} view={InsideComponent} /> + <Route path={StaticSegment("local")} view={LocalResource} /> + <Route path={StaticSegment("none")} view={None} /> </ParentRoute> // async <ParentRoute - path=StaticSegment("async") - ssr=SsrMode::Async - view=|| { + path={StaticSegment("async")} + ssr={SsrMode::Async} + view={|| { view! { - <SecondaryNav/> + <SecondaryNav /> <h1>"Async"</h1> - <Outlet/> + <Outlet /> } - } + }} > - <Route path=StaticSegment("") view=Nested/> - <Route path=StaticSegment("inside") view=NestedResourceInside/> - <Route path=StaticSegment("single") view=Single/> - <Route path=StaticSegment("parallel") view=Parallel/> - <Route path=StaticSegment("inside-component") view=InsideComponent/> - <Route path=StaticSegment("local") view=LocalResource/> - <Route path=StaticSegment("none") view=None/> + <Route path={StaticSegment("")} view={Nested} /> + <Route path={StaticSegment("inside")} view={NestedResourceInside} /> + <Route path={StaticSegment("single")} view={Single} /> + <Route path={StaticSegment("parallel")} view={Parallel} /> + <Route path={StaticSegment("inside-component")} view={InsideComponent} /> + <Route path={StaticSegment("local")} view={LocalResource} /> + <Route path={StaticSegment("none")} view={None} /> </ParentRoute> </Routes> </main> @@ -143,24 +143,24 @@ fn Nested() -> impl IntoView { view! { <div> - <Suspense fallback=|| { + <Suspense fallback={|| { "Loading 1..." - }> + }}> {move || { one_second.get().map(|_| view! { <p id="loaded-1">"One Second: Loaded 1!"</p> }) }} - <Suspense fallback=|| { + <Suspense fallback={|| { "Loading 2..." - }> + }}> {move || { two_second .get() .map(|_| { view! { <p id="loaded-2">"Two Second: Loaded 2!"</p> - <button on:click=move |_| { + <button on:click={move |_| { set_count.update(|n| *n += 1) - }>{count}</button> + }}>{count}</button> } }) }} @@ -178,9 +178,9 @@ fn NestedResourceInside() -> impl IntoView { view! { <div> - <Suspense fallback=|| { + <Suspense fallback={|| { "Loading 1..." - }> + }}> {Suspend::new(async move { _ = one_second.await; let two_second = Resource::new( @@ -189,12 +189,14 @@ fn NestedResourceInside() -> impl IntoView { ); view! { <p id="loaded-1">"One Second: Loaded 1!"</p> - <Suspense fallback=|| "Loading 2..."> + <Suspense fallback={|| "Loading 2..."}> <span id="loaded-2"> "Loaded 2 (created inside first suspense)!: " {Suspend::new(async move { format!("{:?}", two_second.await) })} </span> - <button on:click=move |_| set_count.update(|n| *n += 1)>{count}</button> + <button on:click={move |_| { + set_count.update(|n| *n += 1) + }}>{count}</button> </Suspense> } })} @@ -212,26 +214,26 @@ fn Parallel() -> impl IntoView { view! { <div> - <Suspense fallback=|| { + <Suspense fallback={|| { "Loading 1..." - }> + }}> {move || { one_second .get() .map(move |_| { view! { <p id="loaded-1">"One Second: Loaded 1!"</p> - <button on:click=move |_| { + <button on:click={move |_| { set_count.update(|n| *n += 1) - }>{count}</button> + }}>{count}</button> } }) }} </Suspense> - <Suspense fallback=|| { + <Suspense fallback={|| { "Loading 2..." - }> + }}> {move || { two_second .get() @@ -240,7 +242,7 @@ fn Parallel() -> impl IntoView { <p id="loaded-2">"Two Second: Loaded 2!"</p> <button id="second-count" - on:click=move |_| set_count.update(|n| *n += 1) + on:click={move |_| set_count.update(|n| *n += 1)} > {count} </button> @@ -260,9 +262,9 @@ fn Single() -> impl IntoView { view! { <div> - <Suspense fallback=|| { + <Suspense fallback={|| { "Loading 1..." - }> + }}> {move || { one_second.get().map(|_| view! { <p id="loaded-1">"One Second: Loaded 1!"</p> }) }} @@ -270,7 +272,7 @@ fn Single() -> impl IntoView { </Suspense> <p id="following-message">"Children following Suspense should hydrate properly."</p> <div> - <button on:click=move |_| set_count.update(|n| *n += 1)>{count}</button> + <button on:click={move |_| set_count.update(|n| *n += 1)}>{count}</button> </div> </div> } @@ -283,10 +285,10 @@ fn InsideComponent() -> impl IntoView { view! { <div> <p id="inside-message">"Suspense inside another component should work."</p> - <InsideComponentChild/> + <InsideComponentChild /> <p id="following-message">"Children following Suspense should hydrate properly."</p> <div> - <button on:click=move |_| set_count.update(|n| *n += 1)>{count}</button> + <button on:click={move |_| set_count.update(|n| *n += 1)}>{count}</button> </div> </div> } @@ -296,9 +298,9 @@ fn InsideComponent() -> impl IntoView { fn InsideComponentChild() -> impl IntoView { let one_second = Resource::new(|| WAIT_ONE_SECOND, first_wait_fn); view! { - <Suspense fallback=|| { + <Suspense fallback={|| { "Loading 1..." - }> + }}> {move || { one_second.get().map(|_| view! { <p id="loaded-1">"One Second: Loaded 1!"</p> }) }} @@ -315,9 +317,9 @@ fn LocalResource() -> impl IntoView { view! { <div> - <Suspense fallback=|| { + <Suspense fallback={|| { "Loading 1..." - }> + }}> {move || { one_second.get().map(|_| view! { <p id="loaded-1">"One Second: Loaded 1!"</p> }) }} @@ -331,7 +333,7 @@ fn LocalResource() -> impl IntoView { </Suspense> <p id="following-message">"Children following Suspense should hydrate properly."</p> <div> - <button on:click=move |_| set_count.update(|n| *n += 1)>{count}</button> + <button on:click={move |_| set_count.update(|n| *n += 1)}>{count}</button> </div> </div> } @@ -343,13 +345,13 @@ fn None() -> impl IntoView { view! { <div> - <Suspense fallback=|| "Loading 1..."> + <Suspense fallback={|| "Loading 1..."}> <p id="inside-message">"Children inside Suspense should hydrate properly."</p> - <button on:click=move |_| set_count.update(|n| *n += 1)>{count}</button> + <button on:click={move |_| set_count.update(|n| *n += 1)}>{count}</button> </Suspense> <p id="following-message">"Children following Suspense should hydrate properly."</p> <div> - <button id="second-count" on:click=move |_| set_count.update(|n| *n += 1)> + <button id="second-count" on:click={move |_| set_count.update(|n| *n += 1)}> {count} </button> </div> diff --git a/examples/suspense_tests/src/main.rs b/examples/suspense_tests/src/main.rs index 0cd0067bb6..7f25304098 100644 --- a/examples/suspense_tests/src/main.rs +++ b/examples/suspense_tests/src/main.rs @@ -24,19 +24,19 @@ async fn main() -> std::io::Result<()> { use leptos::prelude::*; view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> + <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> - <AutoReload options=leptos_options.clone()/> - <HydrationScripts options=leptos_options.clone()/> + <AutoReload options={leptos_options.clone()} /> + <HydrationScripts options={leptos_options.clone()} /> </head> <body> - <App/> + <App /> </body> </html> } diff --git a/examples/tailwind_actix/src/app.rs b/examples/tailwind_actix/src/app.rs index 58832c0465..10a7bd06cc 100644 --- a/examples/tailwind_actix/src/app.rs +++ b/examples/tailwind_actix/src/app.rs @@ -10,11 +10,11 @@ pub fn App() -> impl IntoView { provide_meta_context(); view! { - <Stylesheet id="leptos" href="/pkg/tailwind_actix.css"/> - <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico"/> + <Stylesheet id="leptos" href="/pkg/tailwind_actix.css" /> + <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico" /> <Router> - <FlatRoutes fallback=|| "Page not found."> - <Route path=StaticSegment("") view=Home/> + <FlatRoutes fallback={|| "Page not found."}> + <Route path={StaticSegment("")} view={Home} /> </FlatRoutes> </Router> } @@ -27,16 +27,16 @@ fn Home() -> impl IntoView { view! { <main class="my-0 mx-auto max-w-3xl text-center"> <h2 class="p-6 text-4xl">"Welcome to Leptos with Tailwind"</h2> - <p class="px-10 pb-10 text-left">"Tailwind will scan your Rust files for Tailwind class names and compile them into a CSS file."</p> + <p class="px-10 pb-10 text-left"> + "Tailwind will scan your Rust files for Tailwind class names and compile them into a CSS file." + </p> <button class="bg-amber-600 hover:bg-sky-700 px-5 py-3 text-white rounded-lg" - on:click=move |_| set_count.update(|count| *count += 1) + on:click={move |_| set_count.update(|count| *count += 1)} > "Something's here | " - {move || if count.get() == 0 { - "Click me!".to_string() - } else { - count.get().to_string() + {move || { + if count.get() == 0 { "Click me!".to_string() } else { count.get().to_string() } }} " | Some more text" </button> diff --git a/examples/tailwind_actix/src/main.rs b/examples/tailwind_actix/src/main.rs index 3d6e671802..d16cb3967c 100644 --- a/examples/tailwind_actix/src/main.rs +++ b/examples/tailwind_actix/src/main.rs @@ -25,17 +25,20 @@ async fn main() -> std::io::Result<()> { use leptos::prelude::*; view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1"/> - <AutoReload options=leptos_options.clone() /> - <HydrationScripts options=leptos_options.clone()/> - <MetaTags/> + <meta charset="utf-8" /> + <meta + name="viewport" + content="width=device-width, initial-scale=1" + /> + <AutoReload options={leptos_options.clone()} /> + <HydrationScripts options={leptos_options.clone()} /> + <MetaTags /> </head> <body> - <App/> + <App /> </body> </html> } diff --git a/examples/tailwind_axum/src/app.rs b/examples/tailwind_axum/src/app.rs index 37bbb685cc..a66aea8ada 100644 --- a/examples/tailwind_axum/src/app.rs +++ b/examples/tailwind_axum/src/app.rs @@ -7,19 +7,19 @@ use leptos_router::{ pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1"/> - <AutoReload options=options.clone() /> - <HydrationScripts options/> - <link rel="stylesheet" id="leptos" href="/pkg/leptos_tailwind.css"/> - <link rel="shortcut icon" type="image/ico" href="/favicon.ico"/> - <MetaTags/> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <AutoReload options={options.clone()} /> + <HydrationScripts options /> + <link rel="stylesheet" id="leptos" href="/pkg/leptos_tailwind.css" /> + <link rel="shortcut icon" type="image/ico" href="/favicon.ico" /> + <MetaTags /> </head> <body> - <App/> + <App /> </body> </html> } @@ -31,8 +31,8 @@ pub fn App() -> impl IntoView { view! { <Router> - <FlatRoutes fallback=|| "Page not found."> - <Route path=StaticSegment("") view=Home/> + <FlatRoutes fallback={|| "Page not found."}> + <Route path={StaticSegment("")} view={Home} /> </FlatRoutes> </Router> } @@ -44,17 +44,23 @@ fn Home() -> impl IntoView { // thanks to https://tailwindcomponents.com/component/blue-buttons-example for the showcase layout view! { - <Title text="Leptos + Tailwindcss"/> + <Title text="Leptos + Tailwindcss" /> <main> <div class="bg-gradient-to-tl from-blue-800 to-blue-500 text-white font-mono flex flex-col min-h-screen"> <div class="flex flex-row-reverse flex-wrap m-auto"> - <button on:click=move |_| set_value.update(|value| *value += 1) class="rounded px-3 py-2 m-1 border-b-4 border-l-2 shadow-lg bg-blue-700 border-blue-800 text-white"> + <button + on:click={move |_| set_value.update(|value| *value += 1)} + class="rounded px-3 py-2 m-1 border-b-4 border-l-2 shadow-lg bg-blue-700 border-blue-800 text-white" + > "+" </button> <button class="rounded px-3 py-2 m-1 border-b-4 border-l-2 shadow-lg bg-blue-800 border-blue-900 text-white"> {value} </button> - <button on:click=move |_| set_value.update(|value| *value -= 1) class="rounded px-3 py-2 m-1 border-b-4 border-l-2 shadow-lg bg-blue-700 border-blue-800 text-white"> + <button + on:click={move |_| set_value.update(|value| *value -= 1)} + class="rounded px-3 py-2 m-1 border-b-4 border-l-2 shadow-lg bg-blue-700 border-blue-800 text-white" + > "-" </button> </div> diff --git a/examples/tailwind_csr/src/app.rs b/examples/tailwind_csr/src/app.rs index e584f2bf67..d9de420383 100644 --- a/examples/tailwind_csr/src/app.rs +++ b/examples/tailwind_csr/src/app.rs @@ -10,11 +10,11 @@ pub fn App() -> impl IntoView { provide_meta_context(); view! { - <Stylesheet id="leptos" href="/style/output.css"/> - <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico"/> + <Stylesheet id="leptos" href="/style/output.css" /> + <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico" /> <Router> - <Routes fallback=|| "Page not found."> - <Route path=StaticSegment("") view=Home/> + <Routes fallback={|| "Page not found."}> + <Route path={StaticSegment("")} view={Home} /> </Routes> </Router> } @@ -27,16 +27,16 @@ fn Home() -> impl IntoView { view! { <div class="my-0 mx-auto max-w-3xl text-center"> <h2 class="p-6 text-4xl">"Welcome to Leptos with Tailwind"</h2> - <p class="px-10 pb-10 text-left">"Tailwind will scan your Rust files for Tailwind class names and compile them into a CSS file."</p> + <p class="px-10 pb-10 text-left"> + "Tailwind will scan your Rust files for Tailwind class names and compile them into a CSS file." + </p> <button class="bg-amber-600 hover:bg-sky-700 px-5 py-3 text-white rounded-lg" - on:click=move |_| set_count.update(|count| *count += 1) + on:click={move |_| set_count.update(|count| *count += 1)} > "Something's here | " - {move || if count.get() == 0 { - "Click me!".to_string() - } else { - count.get().to_string() + {move || { + if count.get() == 0 { "Click me!".to_string() } else { count.get().to_string() } }} " | Some more text" </button> diff --git a/examples/timer/src/lib.rs b/examples/timer/src/lib.rs index 48ac44b9e8..7bec45f15f 100644 --- a/examples/timer/src/lib.rs +++ b/examples/timer/src/lib.rs @@ -24,11 +24,14 @@ pub fn TimerDemo() -> impl IntoView { <div>{count_a}</div> <div>"Count B (dynamic interval, currently " {interval} " ms)"</div> <div>{count_b}</div> - <input prop:value=interval on:input:target=move |ev| { - if let Ok(value) = ev.target().value().parse::<u64>() { - interval.set(value); - } - }/> + <input + prop:value={interval} + on:input:target={move |ev| { + if let Ok(value) = ev.target().value().parse::<u64>() { + interval.set(value); + } + }} + /> </div> } } diff --git a/examples/todo_app_sqlite/src/main.rs b/examples/todo_app_sqlite/src/main.rs index 61953f90d0..271f082f36 100644 --- a/examples/todo_app_sqlite/src/main.rs +++ b/examples/todo_app_sqlite/src/main.rs @@ -42,19 +42,19 @@ async fn main() -> std::io::Result<()> { use leptos::prelude::*; view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> + <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> - <AutoReload options=leptos_options.clone()/> - <HydrationScripts options=leptos_options.clone()/> + <AutoReload options={leptos_options.clone()} /> + <HydrationScripts options={leptos_options.clone()} /> </head> <body> - <TodoApp/> + <TodoApp /> </body> </html> } diff --git a/examples/todo_app_sqlite/src/todo.rs b/examples/todo_app_sqlite/src/todo.rs index d60b896da9..2eb4f595d6 100644 --- a/examples/todo_app_sqlite/src/todo.rs +++ b/examples/todo_app_sqlite/src/todo.rs @@ -89,7 +89,7 @@ pub fn TodoApp() -> impl IntoView { <h1>"My Tasks"</h1> </header> <main> - <Todos/> + <Todos /> </main> } } @@ -127,9 +127,9 @@ pub fn Todos() -> impl IntoView { let id = todo.id; view! { <li> - {todo.title.clone()} <ActionForm action=delete_todo> - <input type="hidden" name="id" value=id/> - <input type="submit" value="X"/> + {todo.title.clone()} <ActionForm action={delete_todo}> + <input type="hidden" name="id" value={id} /> + <input type="submit" value="X" /> </ActionForm> </li> } @@ -142,12 +142,12 @@ pub fn Todos() -> impl IntoView { }; view! { - <MultiActionForm action=add_todo> - <label>"Add a Todo" <input type="text" name="title"/></label> - <input type="submit" value="Add"/> + <MultiActionForm action={add_todo}> + <label>"Add a Todo" <input type="text" name="title" /></label> + <input type="submit" value="Add" /> </MultiActionForm> <div> - <Transition fallback=move || view! { <p>"Loading..."</p> }> + <Transition fallback={move || view! { <p>"Loading..."</p> }}> // TODO: ErrorBoundary here seems to break Suspense in Actix // <ErrorBoundary fallback=|errors| view! { <p>"Error: " {move || format!("{:?}", errors.get())}</p> }> <ul> diff --git a/examples/todo_app_sqlite_axum/src/todo.rs b/examples/todo_app_sqlite_axum/src/todo.rs index 8e0a393d04..0ac94185b4 100644 --- a/examples/todo_app_sqlite_axum/src/todo.rs +++ b/examples/todo_app_sqlite_axum/src/todo.rs @@ -6,18 +6,18 @@ use server_fn::ServerFnError; pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1"/> - <AutoReload options=options.clone() /> - <HydrationScripts options/> - <link rel="stylesheet" id="leptos" href="/pkg/todo_app_sqlite_axum.css"/> - <link rel="shortcut icon" type="image/ico" href="/favicon.ico"/> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <AutoReload options={options.clone()} /> + <HydrationScripts options /> + <link rel="stylesheet" id="leptos" href="/pkg/todo_app_sqlite_axum.css" /> + <link rel="shortcut icon" type="image/ico" href="/favicon.ico" /> </head> <body> - <TodoApp/> + <TodoApp /> </body> </html> } @@ -110,7 +110,7 @@ pub fn TodoApp() -> impl IntoView { <h1>"My Tasks"</h1> </header> <main> - <Todos/> + <Todos /> </main> } } @@ -148,10 +148,9 @@ pub fn Todos() -> impl IntoView { let id = todo.id; view! { <li> - {todo.title.clone()} - <ActionForm action=delete_todo> - <input type="hidden" name="id" value=id/> - <input type="submit" value="X"/> + {todo.title.clone()} <ActionForm action={delete_todo}> + <input type="hidden" name="id" value={id} /> + <input type="submit" value="X" /> </ActionForm> </li> } @@ -164,13 +163,13 @@ pub fn Todos() -> impl IntoView { }; view! { - <MultiActionForm action=add_todo> - <label>"Add a Todo" <input type="text" name="title"/></label> - <input type="submit" value="Add"/> + <MultiActionForm action={add_todo}> + <label>"Add a Todo" <input type="text" name="title" /></label> + <input type="submit" value="Add" /> </MultiActionForm> <div> - <Transition fallback=move || view! { <p>"Loading..."</p> }> - <ErrorBoundary fallback=|errors| view! { <ErrorTemplate errors/> }> + <Transition fallback={move || view! { <p>"Loading..."</p> }}> + <ErrorBoundary fallback={|errors| view! { <ErrorTemplate errors /> }}> <ul> {existing_todos} {move || { diff --git a/examples/todo_app_sqlite_csr/src/error_template.rs b/examples/todo_app_sqlite_csr/src/error_template.rs index 924173e908..337ad40a00 100644 --- a/examples/todo_app_sqlite_csr/src/error_template.rs +++ b/examples/todo_app_sqlite_csr/src/error_template.rs @@ -37,22 +37,21 @@ pub fn ErrorTemplate( } view! { - <h1>"Errors"</h1> - <For - // a function that returns the items we're iterating over; a signal is fine - each= move || {errors.clone().into_iter().enumerate()} - // a unique key for each item as a reference - key=|(index, _error)| *index - // renders each item to a view - children=move |error| { - let error_string = error.1.to_string(); - let error_code= error.1.status_code(); - view! { - - <h2>{error_code.to_string()}</h2> - <p>"Error: " {error_string}</p> - } - } - /> + <h1>"Errors"</h1> + <For + // a function that returns the items we're iterating over; a signal is fine + each={move || { errors.clone().into_iter().enumerate() }} + // a unique key for each item as a reference + key={|(index, _error)| *index} + // renders each item to a view + children={move |error| { + let error_string = error.1.to_string(); + let error_code = error.1.status_code(); + view! { + <h2>{error_code.to_string()}</h2> + <p>"Error: " {error_string}</p> + } + }} + /> } } diff --git a/examples/todo_app_sqlite_csr/src/fallback.rs b/examples/todo_app_sqlite_csr/src/fallback.rs index bdceccf834..b1b7032742 100644 --- a/examples/todo_app_sqlite_csr/src/fallback.rs +++ b/examples/todo_app_sqlite_csr/src/fallback.rs @@ -23,15 +23,15 @@ pub async fn file_or_index_handler( res.into_response() } else { Html(view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1"/> - <AutoReload options=options.clone() /> - <HydrationScripts options=options.clone()/> - <link rel="stylesheet" id="leptos" href="/pkg/todo_app_sqlite_csr.css"/> - <link rel="shortcut icon" type="image/ico" href="/favicon.ico"/> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <AutoReload options={options.clone()} /> + <HydrationScripts options={options.clone()} /> + <link rel="stylesheet" id="leptos" href="/pkg/todo_app_sqlite_csr.css" /> + <link rel="shortcut icon" type="image/ico" href="/favicon.ico" /> </head> <body></body> </html> diff --git a/examples/todo_app_sqlite_csr/src/todo.rs b/examples/todo_app_sqlite_csr/src/todo.rs index 9a74ae2bbc..f93f3a48ec 100644 --- a/examples/todo_app_sqlite_csr/src/todo.rs +++ b/examples/todo_app_sqlite_csr/src/todo.rs @@ -6,18 +6,18 @@ use server_fn::ServerFnError; pub fn shell(leptos_options: &LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1"/> - <AutoReload options=leptos_options.clone() /> - <HydrationScripts options=leptos_options.clone()/> - <link rel="stylesheet" id="leptos" href="/pkg/todo_app_sqlite_csr.css"/> - <link rel="shortcut icon" type="image/ico" href="/favicon.ico"/> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <AutoReload options={leptos_options.clone()} /> + <HydrationScripts options={leptos_options.clone()} /> + <link rel="stylesheet" id="leptos" href="/pkg/todo_app_sqlite_csr.css" /> + <link rel="shortcut icon" type="image/ico" href="/favicon.ico" /> </head> <body> - <TodoApp/> + <TodoApp /> </body> </html> } @@ -110,7 +110,7 @@ pub fn TodoApp() -> impl IntoView { <h1>"My Tasks"</h1> </header> <main> - <Todos/> + <Todos /> </main> } } @@ -148,10 +148,9 @@ pub fn Todos() -> impl IntoView { let id = todo.id; view! { <li> - {todo.title.clone()} - <ActionForm action=delete_todo> - <input type="hidden" name="id" value=id/> - <input type="submit" value="X"/> + {todo.title.clone()} <ActionForm action={delete_todo}> + <input type="hidden" name="id" value={id} /> + <input type="submit" value="X" /> </ActionForm> </li> } @@ -164,13 +163,13 @@ pub fn Todos() -> impl IntoView { }; view! { - <MultiActionForm action=add_todo> - <label>"Add a Todo" <input type="text" name="title"/></label> - <input type="submit" value="Add"/> + <MultiActionForm action={add_todo}> + <label>"Add a Todo" <input type="text" name="title" /></label> + <input type="submit" value="Add" /> </MultiActionForm> <div> - <Transition fallback=move || view! { <p>"Loading..."</p> }> - <ErrorBoundary fallback=|errors| view! { <ErrorTemplate errors/> }> + <Transition fallback={move || view! { <p>"Loading..."</p> }}> + <ErrorBoundary fallback={|errors| view! { <ErrorTemplate errors /> }}> <ul> {existing_todos} {move || { diff --git a/examples/todomvc/src/lib.rs b/examples/todomvc/src/lib.rs index 2dd8b6a013..08c387fd66 100644 --- a/examples/todomvc/src/lib.rs +++ b/examples/todomvc/src/lib.rs @@ -224,26 +224,26 @@ pub fn TodoMVC() -> impl IntoView { class="new-todo" placeholder="What needs to be done?" autofocus - on:keydown=add_todo - node_ref=input_ref + on:keydown={add_todo} + node_ref={input_ref} /> </header> - <section class="main" class:hidden=move || todos.with(|t| t.is_empty())> + <section class="main" class:hidden={move || todos.with(|t| t.is_empty())}> <input id="toggle-all" class="toggle-all" type="checkbox" - prop:checked=move || todos.with(|t| t.remaining() > 0) - on:input=move |_| todos.with(|t| t.toggle_all()) + prop:checked={move || todos.with(|t| t.remaining() > 0)} + on:input={move |_| todos.with(|t| t.toggle_all())} /> <label for="toggle-all">"Mark all as complete"</label> <ul class="todo-list"> - <For each=filtered_todos key=|todo| todo.id let:todo> - <Todo todo/> + <For each={filtered_todos} key={|todo| todo.id} let:todo> + <Todo todo /> </For> </ul> </section> - <footer class="footer" class:hidden=move || todos.with(|t| t.is_empty())> + <footer class="footer" class:hidden={move || todos.with(|t| t.is_empty())}> <span class="todo-count"> <strong>{move || todos.with(|t| t.remaining().to_string())}</strong> {move || { @@ -257,20 +257,20 @@ pub fn TodoMVC() -> impl IntoView { <a href="#/" class="selected" - class:selected=move || mode.get() == Mode::All + class:selected={move || mode.get() == Mode::All} > "All" </a> </li> <li> - <a href="#/active" class:selected=move || mode.get() == Mode::Active> + <a href="#/active" class:selected={move || mode.get() == Mode::Active}> "Active" </a> </li> <li> <a href="#/completed" - class:selected=move || mode.get() == Mode::Completed + class:selected={move || mode.get() == Mode::Completed} > "Completed" </a> @@ -278,8 +278,8 @@ pub fn TodoMVC() -> impl IntoView { </ul> <button class="clear-completed hidden" - class:hidden=move || todos.with(|t| t.completed() == 0) - on:click=move |_| set_todos.update(|t| t.clear_completed()) + class:hidden={move || todos.with(|t| t.completed() == 0)} + on:click={move |_| set_todos.update(|t| t.clear_completed())} > "Clear completed" </button> @@ -313,27 +313,27 @@ pub fn Todo(todo: Todo) -> impl IntoView { }; view! { - <li class="todo" class:editing=editing class:completed=move || todo.completed.get()> + <li class="todo" class:editing={editing} class:completed={move || todo.completed.get()}> <div class="view"> <input - node_ref=todo_input + node_ref={todo_input} class="toggle" type="checkbox" - prop:checked=move || todo.completed.get() - on:input:target=move |ev| { + prop:checked={move || todo.completed.get()} + on:input:target={move |ev| { todo.completed.set(ev.target().checked()); - } + }} /> - <label on:dblclick=move |_| { + <label on:dblclick={move |_| { set_editing.set(true); if let Some(input) = todo_input.get() { _ = input.focus(); } - }>{move || todo.title.get()}</label> + }}>{move || todo.title.get()}</label> <button class="destroy" - on:click=move |_| set_todos.update(|t| t.remove(todo.id)) + on:click={move |_| set_todos.update(|t| t.remove(todo.id))} ></button> </div> {move || { @@ -343,17 +343,17 @@ pub fn Todo(todo: Todo) -> impl IntoView { view! { <input class="edit" - class:hidden=move || !editing.get() - prop:value=move || todo.title.get() - on:focusout:target=move |ev| save(&ev.target().value()) - on:keyup:target=move |ev| { + class:hidden={move || !editing.get()} + prop:value={move || todo.title.get()} + on:focusout:target={move |ev| save(&ev.target().value())} + on:keyup:target={move |ev| { let key_code = ev.key_code(); if key_code == ENTER_KEY { save(&ev.target().value()); } else if key_code == ESCAPE_KEY { set_editing.set(false); } - } + }} /> } }) diff --git a/integrations/actix/tests/extract_routes.rs b/integrations/actix/tests/extract_routes.rs index 67765b187e..ded613f4c2 100644 --- a/integrations/actix/tests/extract_routes.rs +++ b/integrations/actix/tests/extract_routes.rs @@ -8,11 +8,11 @@ fn DefaultApp() -> impl IntoView { view! { <Router> <Routes> - <Route path="/foo" view/> - <Route path="/bar/" view/> - <Route path="/baz/:id" view/> - <Route path="/baz/:name/" view/> - <Route path="/baz/*any" view/> + <Route path="/foo" view /> + <Route path="/bar/" view /> + <Route path="/baz/:id" view /> + <Route path="/baz/:name/" view /> + <Route path="/baz/*any" view /> </Routes> </Router> } @@ -44,11 +44,11 @@ fn ExactApp() -> impl IntoView { view! { <Router trailing_slash> <Routes> - <Route path="/foo" view/> - <Route path="/bar/" view/> - <Route path="/baz/:id" view/> - <Route path="/baz/:name/" view/> - <Route path="/baz/*any" view/> + <Route path="/foo" view /> + <Route path="/bar/" view /> + <Route path="/baz/:id" view /> + <Route path="/baz/:name/" view /> + <Route path="/baz/*any" view /> </Routes> </Router> } @@ -86,11 +86,11 @@ fn RedirectApp() -> impl IntoView { view! { <Router trailing_slash> <Routes> - <Route path="/foo" view/> - <Route path="/bar/" view/> - <Route path="/baz/:id" view/> - <Route path="/baz/:name/" view/> - <Route path="/baz/*any" view/> + <Route path="/foo" view /> + <Route path="/bar/" view /> + <Route path="/baz/:id" view /> + <Route path="/baz/:name/" view /> + <Route path="/baz/*any" view /> </Routes> </Router> } diff --git a/leptos/src/animated_show.rs b/leptos/src/animated_show.rs index 8a4db98c84..dfb003fc1e 100644 --- a/leptos/src/animated_show.rs +++ b/leptos/src/animated_show.rs @@ -99,8 +99,8 @@ pub fn AnimatedShow( }); view! { - <Show when=move || show.get() fallback=|| ()> - <div class=move || cls.get()>{children()}</div> + <Show when={move || show.get()} fallback={|| ()}> + <div class={move || cls.get()}>{children()}</div> </Show> } } diff --git a/leptos/src/await_.rs b/leptos/src/await_.rs index a98063b956..1b80ebfb31 100644 --- a/leptos/src/await_.rs +++ b/leptos/src/await_.rs @@ -115,7 +115,7 @@ where let view = store_value(children); view! { - <Suspense fallback=|| ()> + <Suspense fallback={|| ()}> {move || res.map(|data| view.with_value(|view| view(data)))} </Suspense> } diff --git a/leptos/src/hydration/mod.rs b/leptos/src/hydration/mod.rs index cd0febc91e..3ea7252e12 100644 --- a/leptos/src/hydration/mod.rs +++ b/leptos/src/hydration/mod.rs @@ -54,7 +54,11 @@ pub fn HydrationScripts( }; view! { - <link rel="modulepreload" href={format!("/{pkg_path}/{output_name}.js")} nonce={nonce.clone()}/> + <link + rel="modulepreload" + href={format!("/{pkg_path}/{output_name}.js")} + nonce={nonce.clone()} + /> <link rel="preload" href={format!("/{pkg_path}/{wasm_output_name}.wasm")} diff --git a/leptos/tests/ssr.rs b/leptos/tests/ssr.rs index 2f18c7f4f4..e0daafdf6d 100644 --- a/leptos/tests/ssr.rs +++ b/leptos/tests/ssr.rs @@ -38,8 +38,8 @@ fn ssr_test_with_components() { let rendered: HtmlElement<_, _, _, Dom> = view! { <div class="counters"> - <Counter initial_value=1/> - <Counter initial_value=2/> + <Counter initial_value=1 /> + <Counter initial_value=2 /> </div> }; @@ -68,8 +68,8 @@ fn ssr_test_with_snake_case_components() { } let rendered: HtmlElement<_, _, _, Dom> = view! { <div class="counters"> - <SnakeCaseCounter initial_value=1/> - <SnakeCaseCounter initial_value=2/> + <SnakeCaseCounter initial_value=1 /> + <SnakeCaseCounter initial_value=2 /> </div> }; @@ -89,9 +89,9 @@ fn test_classes() { let rendered: HtmlElement<_, _, _, Dom> = view! { <div class="my big" - class:a=move || { value.get() > 10 } + class:a={move || { value.get() > 10 }} class:red=true - class:car=move || { value.get() > 1 } + class:car={move || { value.get() > 1 }} ></div> }; diff --git a/leptos_dom/examples/hydration-test/src/lib.rs b/leptos_dom/examples/hydration-test/src/lib.rs index 62bbfc495c..01d755f1f6 100644 --- a/leptos_dom/examples/hydration-test/src/lib.rs +++ b/leptos_dom/examples/hydration-test/src/lib.rs @@ -21,14 +21,12 @@ pub fn App() -> impl IntoView { ); view! { - <div> <div> - "This is some text" + <div>"This is some text"</div> + // <Suspense fallback=move || view! { <p>"Loading..."</p> }> + {move || pending_thing.read().map(|n| view! { <ComponentA /> })} + // </Suspense> </div> - // <Suspense fallback=move || view! { <p>"Loading..."</p> }> - {move || pending_thing.read().map(|n| view! { <ComponentA/> })} - // </Suspense> - </div> } } @@ -65,6 +63,6 @@ pub fn hydrate() { gloo::console::debug!("starting WASM"); leptos::mount_to_body(move || { - view! { <App/> } + view! { <App /> } }); } diff --git a/leptos_dom/examples/hydration-test/src/main.rs b/leptos_dom/examples/hydration-test/src/main.rs index 40bd4b4ae0..fea604450f 100644 --- a/leptos_dom/examples/hydration-test/src/main.rs +++ b/leptos_dom/examples/hydration-test/src/main.rs @@ -30,7 +30,7 @@ async fn main() -> std::io::Result<()> { HttpResponse::Ok().content_type("text/html").streaming( futures::stream::once(async move { head.clone() }) .chain(render_to_stream( - || view! { <App/> }.into_view(), + || view! { <App /> }.into_view(), )) .chain(futures::stream::once(async { tail.to_string() })) .inspect(|html| println!("{html}")) diff --git a/leptos_dom/examples/test-bench/src/main.rs b/leptos_dom/examples/test-bench/src/main.rs index 0df8c42c85..c5071de8fe 100644 --- a/leptos_dom/examples/test-bench/src/main.rs +++ b/leptos_dom/examples/test-bench/src/main.rs @@ -30,31 +30,31 @@ fn view_fn() -> impl IntoView { view! { <h2>"Passing Tests"</h2> <ul> - <Test from=[1] to=[]/> - <Test from=[1, 2] to=[3, 2] then=vec![2]/> - <Test from=[1, 2] to=[]/> - <Test from=[1, 2, 3] to=[]/> - <hr/> - <Test from=[] to=[1]/> - <Test from=[1, 2] to=[1]/> - <Test from=[2, 1] to=[1]/> - <hr/> - <Test from=[1, 2, 3] to=[1, 2]/> - <Test from=[2] to=[1, 2]/> - <Test from=[1] to=[1, 2]/> - <Test from=[] to=[1, 2, 3]/> - <Test from=[2] to=[1, 2, 3]/> - <Test from=[1] to=[1, 2, 3]/> - <Test from=[1, 3, 2] to=[1, 2, 3]/> - <Test from=[2, 1, 3] to=[1, 2, 3]/> - <Test from=[3] to=[1, 2, 3]/> - <Test from=[3, 1] to=[1, 2, 3]/> - <Test from=[3, 2, 1] to=[1, 2, 3]/> - <hr/> - <Test from=[1, 4, 2, 3] to=[1, 2, 3, 4]/> - <hr/> - <Test from=[1, 4, 3, 2, 5] to=[1, 2, 3, 4, 5]/> - <Test from=[4, 5, 3, 1, 2] to=[1, 2, 3, 4, 5]/> + <Test from={[1]} to={[]} /> + <Test from={[1, 2]} to={[3, 2]} then={vec![2]} /> + <Test from={[1, 2]} to={[]} /> + <Test from={[1, 2, 3]} to={[]} /> + <hr /> + <Test from={[]} to={[1]} /> + <Test from={[1, 2]} to={[1]} /> + <Test from={[2, 1]} to={[1]} /> + <hr /> + <Test from={[1, 2, 3]} to={[1, 2]} /> + <Test from={[2]} to={[1, 2]} /> + <Test from={[1]} to={[1, 2]} /> + <Test from={[]} to={[1, 2, 3]} /> + <Test from={[2]} to={[1, 2, 3]} /> + <Test from={[1]} to={[1, 2, 3]} /> + <Test from={[1, 3, 2]} to={[1, 2, 3]} /> + <Test from={[2, 1, 3]} to={[1, 2, 3]} /> + <Test from={[3]} to={[1, 2, 3]} /> + <Test from={[3, 1]} to={[1, 2, 3]} /> + <Test from={[3, 2, 1]} to={[1, 2, 3]} /> + <hr /> + <Test from={[1, 4, 2, 3]} to={[1, 2, 3, 4]} /> + <hr /> + <Test from={[1, 4, 3, 2, 5]} to={[1, 2, 3, 4, 5]} /> + <Test from={[4, 5, 3, 1, 2]} to={[1, 2, 3, 4, 5]} /> </ul> } } @@ -91,30 +91,30 @@ where view! { <li> - "from: [" {move || { - from - .iter() + "from: [" + {move || { + from.iter() .map(ToString::to_string) .intersperse(", ".to_string()) .collect::<String>() - }} "]" <br/> "to: [" { + }} "]" <br /> "to: [" + { let then = then.clone(); move || { - then - .clone() + then.clone() .unwrap_or(to.iter().copied().collect()) .iter() .map(ToString::to_string) .intersperse(", ".to_string()) .collect::<String>() } - } "]" <br/> "result: [" + } "]" <br /> "result: [" <For - each=list - key=|i| *i - view=|i| { + each={list} + key={|i| *i} + view={|i| { view! { <span>{i} ", "</span> } - } + }} /> "]" </li> } diff --git a/leptos_dom/examples/view-tests/src/main.rs b/leptos_dom/examples/view-tests/src/main.rs index b328729ea1..7d8df46b94 100644 --- a/leptos_dom/examples/view-tests/src/main.rs +++ b/leptos_dom/examples/view-tests/src/main.rs @@ -3,7 +3,7 @@ use leptos::prelude::*; pub fn main() { _ = console_log::init_with_level(log::Level::Debug); console_error_panic_hook::set_once(); - mount_to_body(|| view! { <Tests/> }) + mount_to_body(|| view! { <Tests /> }) } #[component] @@ -16,19 +16,20 @@ fn SelfUpdatingEffect() -> Element { } }); - view! { - <h1>"Hello " {move || a().to_string()}</h1> - } + view! { <h1>"Hello " {move || a().to_string()}</h1> } } #[component] fn Tests() -> Element { view! { - <div> - <div><SelfUpdatingEffect/></div> - <div><BlockOrders/></div> - //<div><TemplateConsumer/></div> + <div> + <SelfUpdatingEffect /> + </div> + <div> + <BlockOrders /> + </div> + // <div><TemplateConsumer/></div> </div> } } @@ -40,49 +41,102 @@ fn BlockOrders() -> Element { let c = "C"; view! { - <div> <div>"A"</div> <div>{a}</div> - <div><span>"A"</span></div> - <div><span>{a}</span></div> - <hr/> + <div> + <span>"A"</span> + </div> + <div> + <span>{a}</span> + </div> + <hr /> <div>"A" {b}</div> <div>{a} "B"</div> <div>{a} {b}</div> <div>{"A"} {"B"}</div> - <div><span style="color: red">{a}</span> {b}</div> - <hr/> + <div> + <span style="color: red">{a}</span> + {b} + </div> + <hr /> <div>{a} "B" {c}</div> <div>"A" {b} "C"</div> <div>{a} {b} "C"</div> <div>{a} {b} {c}</div> <div>"A" {b} {c}</div> - <hr/> + <hr /> <div>"A" {b} <span style="color: red">"C"</span></div> <div>"A" {b} <span style="color: red">{c}</span></div> <div>"A" <span style="color: red">"B"</span> "C"</div> <div>"A" <span style="color: red">"B"</span> {c}</div> <div>{a} <span style="color: red">{b}</span> {c}</div> <div>"A" {b} <span style="color: red">{c}</span></div> - <div><span style="color: red">"A"</span> {b} {c}</div> - <div><span style="color: red">{a}</span> "B" {c}</div> - <div><span style="color: red">"A"</span> {b} "C"</div> - <hr/> - <div><span style="color: red">"A"</span> <span style="color: blue">{b}</span> {c}</div> - <div><span style="color: red">{a}</span> "B" <span style="color: blue">{c}</span></div> - <div><span style="color: red">"A"</span> {b} <span style="color: blue">"C"</span></div> - <hr/> - <div><A/></div> - <div>"A" <B/></div> - <div>{a} <B/></div> - <div><A/> "B"</div> - <div><A/> {b}</div> - <div><A/><B/></div> - <hr/> - <div><A/> "B" <C/></div> - <div><A/> {b} <C/></div> - <div><A/> {b} "C"</div> + <div> + <span style="color: red">"A"</span> + {b} + {c} + </div> + <div> + <span style="color: red">{a}</span> + "B" + {c} + </div> + <div> + <span style="color: red">"A"</span> + {b} + "C" + </div> + <hr /> + <div> + <span style="color: red">"A"</span> + <span style="color: blue">{b}</span> + {c} + </div> + <div> + <span style="color: red">{a}</span> + "B" + <span style="color: blue">{c}</span> + </div> + <div> + <span style="color: red">"A"</span> + {b} + <span style="color: blue">"C"</span> + </div> + <hr /> + <div> + <A /> + </div> + <div>"A" <B /></div> + <div>{a} <B /></div> + <div> + <A /> + "B" + </div> + <div> + <A /> + {b} + </div> + <div> + <A /> + <B /> + </div> + <hr /> + <div> + <A /> + "B" + <C /> + </div> + <div> + <A /> + {b} + <C /> + </div> + <div> + <A /> + {b} + "C" + </div> </div> } } @@ -104,7 +158,7 @@ fn C() -> Element { #[component] fn TemplateConsumer() -> Element { - let tpl = view! { <TemplateExample/> }; + let tpl = view! { <TemplateExample /> }; let cloned_tpl = tpl .unchecked_ref::<web_sys::HtmlTemplateElement>() .content() @@ -112,7 +166,6 @@ fn TemplateConsumer() -> Element { .expect("couldn't clone template node"); view! { - <div id="template"> /* <h1>"Template Consumer"</h1> {cloned_tpl} */ @@ -123,7 +176,6 @@ fn TemplateConsumer() -> Element { #[component] fn TemplateExample() -> Element { view! { - <template> <div>"Template contents"</div> </template> diff --git a/leptos_macro/example/src/lib.rs b/leptos_macro/example/src/lib.rs index dfb5da868c..fc25495d96 100644 --- a/leptos_macro/example/src/lib.rs +++ b/leptos_macro/example/src/lib.rs @@ -44,11 +44,9 @@ where { let value = value.to_owned(); view! { - <button on:click=move |_| { + <button on:click={move |_| { callback(5); - }> - {value} - </button> - <TestComponent key="test"/> + }}>{value}</button> + <TestComponent key="test" /> } } diff --git a/leptos_macro/tests/ui/component_absolute.rs b/leptos_macro/tests/ui/component_absolute.rs index fe629cfa0f..8fb44a3763 100644 --- a/leptos_macro/tests/ui/component_absolute.rs +++ b/leptos_macro/tests/ui/component_absolute.rs @@ -43,9 +43,7 @@ fn default_with_invalid_value( #[::leptos::component] pub fn using_the_view_macro() -> impl ::leptos::IntoView { - ::leptos::view! { - "ok" - } + leptos::view! { "ok" } } fn main() {} diff --git a/projects/bevy3d_ui/src/main.rs b/projects/bevy3d_ui/src/main.rs index d35c07344a..383899eff1 100644 --- a/projects/bevy3d_ui/src/main.rs +++ b/projects/bevy3d_ui/src/main.rs @@ -7,5 +7,5 @@ pub fn main() { // Bevy will output a lot of debug info to the console when this is enabled. //_ = console_log::init_with_level(log::Level::Debug); console_error_panic_hook::set_once(); - mount_to_body(|| view! { <RootPage/> }) + mount_to_body(|| view! { <RootPage /> }) } diff --git a/projects/bevy3d_ui/src/routes/demo1.rs b/projects/bevy3d_ui/src/routes/demo1.rs index 6c49894e00..a55a0cf704 100644 --- a/projects/bevy3d_ui/src/routes/demo1.rs +++ b/projects/bevy3d_ui/src/routes/demo1.rs @@ -27,24 +27,24 @@ pub fn Demo1() -> impl IntoView { view! { <div> - <button on:click=move |_| set_value.set(0)>"Clear"</button> - <button on:click=move |_| { + <button on:click={move |_| set_value.set(0)}>"Clear"</button> + <button on:click={move |_| { set_value.update(|value| *value -= step); let newpos = (step as f32) / 10.0; sender_sig .get() .send(ClientInEvents::CounterEvt(CounterEvtData { value: -newpos })) .expect("could not send event"); - }>"-1"</button> + }}>"-1"</button> <span>"Value: " {value} "!"</span> - <button on:click=move |_| { + <button on:click={move |_| { set_value.update(|value| *value += step); let newpos = step as f32 / 10.0; sender_sig .get() .send(ClientInEvents::CounterEvt(CounterEvtData { value: newpos })) .expect("could not send event"); - }>"+1"</button> + }}>"+1"</button> </div> <canvas id="bevy" width="800" height="600"></canvas> diff --git a/projects/bevy3d_ui/src/routes/mod.rs b/projects/bevy3d_ui/src/routes/mod.rs index 77cc30b616..1f642dceb4 100644 --- a/projects/bevy3d_ui/src/routes/mod.rs +++ b/projects/bevy3d_ui/src/routes/mod.rs @@ -9,15 +9,15 @@ pub fn RootPage() -> impl IntoView { provide_meta_context(); view! { - <Meta name="charset" content="UTF-8"/> - <Meta name="description" content="Leptonic CSR template"/> - <Meta name="viewport" content="width=device-width, initial-scale=1.0"/> - <Meta name="theme-color" content="#e66956"/> - <Stylesheet href="https://fonts.googleapis.com/css?family=Roboto&display=swap"/> - <Title text="Leptos Bevy3D Example"/> + <Meta name="charset" content="UTF-8" /> + <Meta name="description" content="Leptonic CSR template" /> + <Meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <Meta name="theme-color" content="#e66956" /> + <Stylesheet href="https://fonts.googleapis.com/css?family=Roboto&display=swap" /> + <Title text="Leptos Bevy3D Example" /> <Router> <Routes> - <Route path="" view=|| view! { <Demo1/> }/> + <Route path="" view={|| view! { <Demo1 /> }} /> </Routes> </Router> } diff --git a/projects/counter_dwarf_debug/src/lib.rs b/projects/counter_dwarf_debug/src/lib.rs index 8f63a97a60..d7e6bf5797 100644 --- a/projects/counter_dwarf_debug/src/lib.rs +++ b/projects/counter_dwarf_debug/src/lib.rs @@ -14,15 +14,15 @@ pub fn SimpleCounter( view! { <div> - <button on:click=move |_| set_value.set(0)>"Clear"</button> - <button on:click=move |_| set_value.update(|value| *value -= step)>"-1"</button> + <button on:click={move |_| set_value.set(0)}>"Clear"</button> + <button on:click={move |_| set_value.update(|value| *value -= step)}>"-1"</button> <span>"Value: " {value} "!"</span> - <button on:click=move |_| { + <button on:click={move |_| { // Test Panic //panic!("Test Panic"); // In order to breakpoint the below, the code needs to be on it's own line set_value.update(|value| *value += step) - } + }} >"+1"</button> </div> } diff --git a/projects/counter_dwarf_debug/src/main.rs b/projects/counter_dwarf_debug/src/main.rs index 7a15224d3e..fc3c87f06b 100644 --- a/projects/counter_dwarf_debug/src/main.rs +++ b/projects/counter_dwarf_debug/src/main.rs @@ -5,11 +5,6 @@ pub fn main() { _ = console_log::init_with_level(log::Level::Debug); console_error_panic_hook::set_once(); mount_to_body(|| { - view! { - <SimpleCounter - initial_value=0 - step=1 - /> - } + view! { <SimpleCounter initial_value=0 step=1 /> } }) } diff --git a/projects/login_with_token_csr_only/client/src/components/credentials.rs b/projects/login_with_token_csr_only/client/src/components/credentials.rs index 003d8dbe99..2c6193dc85 100644 --- a/projects/login_with_token_csr_only/client/src/components/credentials.rs +++ b/projects/login_with_token_csr_only/client/src/components/credentials.rs @@ -19,7 +19,7 @@ pub fn CredentialsForm( }); view! { - <form on:submit=|ev| ev.prevent_default()> + <form on:submit={|ev| ev.prevent_default()}> <p>{title}</p> {move || { error @@ -32,22 +32,22 @@ pub fn CredentialsForm( type="email" required placeholder="Email address" - prop:disabled=move || disabled.get() - on:keyup=move |ev: ev::KeyboardEvent| { + prop:disabled={move || disabled.get()} + on:keyup={move |ev: ev::KeyboardEvent| { let val = event_target_value(&ev); set_email.update(|v| *v = val); - } - on:change=move |ev| { + }} + on:change={move |ev| { let val = event_target_value(&ev); set_email.update(|v| *v = val); - } + }} /> <input type="password" required placeholder="Password" - prop:disabled=move || disabled.get() - on:keyup=move |ev: ev::KeyboardEvent| { + prop:disabled={move || disabled.get()} + on:keyup={move |ev: ev::KeyboardEvent| { match &*ev.key() { "Enter" => { dispatch_action(); @@ -57,15 +57,15 @@ pub fn CredentialsForm( set_password.update(|p| *p = val); } } - } - on:change=move |ev| { + }} + on:change={move |ev| { let val = event_target_value(&ev); set_password.update(|p| *p = val); - } + }} /> <button - prop:disabled=move || button_is_disabled.get() - on:click=move |_| dispatch_action() + prop:disabled={move || button_is_disabled.get()} + on:click={move |_| dispatch_action()} > {action_label} </button> diff --git a/projects/login_with_token_csr_only/client/src/components/navbar.rs b/projects/login_with_token_csr_only/client/src/components/navbar.rs index fbe1973185..d3f3b5fab9 100644 --- a/projects/login_with_token_csr_only/client/src/components/navbar.rs +++ b/projects/login_with_token_csr_only/client/src/components/navbar.rs @@ -10,19 +10,16 @@ pub fn NavBar( view! { <nav> <Show - when=move || logged_in.get() - fallback=|| { + when={move || logged_in.get()} + fallback={|| { view! { - <A href=Page::Login.path()>"Login"</A> + <A href={Page::Login.path()}>"Login"</A> " | " - <A href=Page::Register.path()>"Register"</A> + <A href={Page::Register.path()}>"Register"</A> } - } + }} > - <a - href="#" - on:click=move |_| on_logout.call(()) - > + <a href="#" on:click={move |_| on_logout.call(())}> "Logout" </a> </Show> diff --git a/projects/login_with_token_csr_only/client/src/lib.rs b/projects/login_with_token_csr_only/client/src/lib.rs index 7b1773ff96..cae98d87c9 100644 --- a/projects/login_with_token_csr_only/client/src/lib.rs +++ b/projects/login_with_token_csr_only/client/src/lib.rs @@ -96,37 +96,37 @@ pub fn App() -> impl IntoView { view! { <Router> - <NavBar logged_in on_logout/> + <NavBar logged_in on_logout /> <main> <Routes> <Route - path=Page::Home.path() - view=move || { - view! { <Home user_info=user_info.into()/> } - } + path={Page::Home.path()} + view={move || { + view! { <Home user_info={user_info.into()} /> } + }} /> <Route - path=Page::Login.path() - view=move || { + path={Page::Login.path()} + view={move || { view! { <Login - api=unauthorized_api - on_success=move |api| { + api={unauthorized_api} + on_success={move |api| { log::info!("Successfully logged in"); authorized_api.update(|v| *v = Some(api)); let navigate = use_navigate(); navigate(Page::Home.path(), Default::default()); fetch_user_info.dispatch(()); - } + }} /> } - } + }} /> <Route - path=Page::Register.path() - view=move || { - view! { <Register api=unauthorized_api/> } - } + path={Page::Register.path()} + view={move || { + view! { <Register api={unauthorized_api} /> } + }} /> </Routes> </main> diff --git a/projects/login_with_token_csr_only/client/src/main.rs b/projects/login_with_token_csr_only/client/src/main.rs index d1f06c2928..e151f7f404 100644 --- a/projects/login_with_token_csr_only/client/src/main.rs +++ b/projects/login_with_token_csr_only/client/src/main.rs @@ -4,5 +4,5 @@ use leptos::prelude::*; pub fn main() { _ = console_log::init_with_level(log::Level::Debug); console_error_panic_hook::set_once(); - mount_to_body(|| view! { <App/> }) + mount_to_body(|| view! { <App /> }) } diff --git a/projects/login_with_token_csr_only/client/src/pages/home.rs b/projects/login_with_token_csr_only/client/src/pages/home.rs index 4276d4e46a..b07d00ad0f 100644 --- a/projects/login_with_token_csr_only/client/src/pages/home.rs +++ b/projects/login_with_token_csr_only/client/src/pages/home.rs @@ -8,14 +8,11 @@ pub fn Home(user_info: Signal<Option<UserInfo>>) -> impl IntoView { view! { <h2>"Leptos Login example"</h2> {move || match user_info.get() { - Some(info) => { - view! { <p>"You are logged in with " {info.email} "."</p> } - .into_view() - } + Some(info) => view! { <p>"You are logged in with " {info.email} "."</p> }.into_view(), None => { view! { <p>"You are not logged in."</p> - <A href=Page::Login.path()>"Login now."</A> + <A href={Page::Login.path()}>"Login now."</A> } .into_view() } diff --git a/projects/login_with_token_csr_only/client/src/pages/login.rs b/projects/login_with_token_csr_only/client/src/pages/login.rs index bbf47c590e..7e22b5d88e 100644 --- a/projects/login_with_token_csr_only/client/src/pages/login.rs +++ b/projects/login_with_token_csr_only/client/src/pages/login.rs @@ -53,11 +53,11 @@ pub fn Login( <CredentialsForm title="Please login to your account" action_label="Login" - action=login_action - error=login_error.into() + action={login_action} + error={login_error.into()} disabled /> <p>"Don't have an account?"</p> - <A href=Page::Register.path()>"Register"</A> + <A href={Page::Register.path()}>"Register"</A> } } diff --git a/projects/login_with_token_csr_only/client/src/pages/register.rs b/projects/login_with_token_csr_only/client/src/pages/register.rs index e9b8735deb..9cb44b9576 100644 --- a/projects/login_with_token_csr_only/client/src/pages/register.rs +++ b/projects/login_with_token_csr_only/client/src/pages/register.rs @@ -49,23 +49,23 @@ pub fn Register(api: UnauthorizedApi) -> impl IntoView { view! { <Show - when=move || register_response.get().is_some() - fallback=move || { + when={move || register_response.get().is_some()} + fallback={move || { view! { <CredentialsForm title="Please enter the desired credentials" action_label="Register" - action=register_action - error=register_error.into() + action={register_action} + error={register_error.into()} disabled /> <p>"Your already have an account?"</p> - <A href=Page::Login.path()>"Login"</A> + <A href={Page::Login.path()}>"Login"</A> } - } + }} > <p>"You have successfully registered."</p> - <p>"You can now " <A href=Page::Login.path()>"login"</A> " with your new account."</p> + <p>"You can now " <A href={Page::Login.path()}>"login"</A> " with your new account."</p> </Show> } } diff --git a/projects/meilisearch-searchbar/src/fallback.rs b/projects/meilisearch-searchbar/src/fallback.rs index ee9851fdda..f5303d955b 100644 --- a/projects/meilisearch-searchbar/src/fallback.rs +++ b/projects/meilisearch-searchbar/src/fallback.rs @@ -22,7 +22,7 @@ pub async fn file_and_error_handler( } else { let handler = leptos_axum::render_app_to_stream( options.to_owned(), - || view! {"Error! Error! Error!"}, + || view! { "Error! Error! Error!" }, ); handler(req).await.into_response() } diff --git a/projects/meilisearch-searchbar/src/lib.rs b/projects/meilisearch-searchbar/src/lib.rs index 730253c2cf..3294abecbf 100644 --- a/projects/meilisearch-searchbar/src/lib.rs +++ b/projects/meilisearch-searchbar/src/lib.rs @@ -21,15 +21,23 @@ pub fn App() -> impl IntoView { let search_results = create_rw_signal(Vec::<StockRow>::new()); provide_context(search_results); view! { - <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico"/> - <Meta name="description" content="Leptos implementation of a Meilisearch backed Searchbar."/> + <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico" /> + <Meta + name="description" + content="Leptos implementation of a Meilisearch backed Searchbar." + /> <Router> <main> <Routes> - <Route path="/" view=||view!{ - <SearchBar/> - <SearchResults/> - }/> + <Route + path="/" + view={|| { + view! { + <SearchBar /> + <SearchResults /> + } + }} + /> </Routes> </main> </Router> @@ -92,10 +100,13 @@ pub fn SearchBar() -> impl IntoView { view! { <div> <label for="search">Search</label> - <input id="search" on:input=move|e|{ - let query = event_target_value(&e); - search_query.dispatch(SearchQuery{query}); - }/> + <input + id="search" + on:input={move |e| { + let query = event_target_value(&e); + search_query.dispatch(SearchQuery { query }); + }} + /> </div> } } @@ -105,17 +116,30 @@ pub fn SearchResults() -> impl IntoView { let read_search_results = expect_context::<RwSignal<Vec<StockRow>>>().read_only(); view! { <ul> - <For - each=read_search_results - key=|row| row.name.clone() - children=move |StockRow{name,last,high,low,absolute_change,percentage_change,volume,..}: StockRow| { - view! { - <li> - {format!("{name}; last: {last}; high: {high}; low: {low}; chg.: {absolute_change}; chg...:{percentage_change}; volume:{volume}")} - </li> - } - } - /> + <For + each={read_search_results} + key={|row| row.name.clone()} + children={move | + StockRow { + name, + last, + high, + low, + absolute_change, + percentage_change, + volume, + .. + }: StockRow| + { + view! { + <li> + {format!( + "{name}; last: {last}; high: {high}; low: {low}; chg.: {absolute_change}; chg...:{percentage_change}; volume:{volume}", + )} + </li> + } + }} + /> </ul> } } diff --git a/projects/nginx-mpmc/app-1/src/app.rs b/projects/nginx-mpmc/app-1/src/app.rs index 70899e115e..e114ff38da 100644 --- a/projects/nginx-mpmc/app-1/src/app.rs +++ b/projects/nginx-mpmc/app-1/src/app.rs @@ -9,27 +9,22 @@ pub fn App() -> impl IntoView { provide_meta_context(); view! { - - // injects a stylesheet into the document <head> // id=leptos means cargo-leptos will hot-reload this stylesheet <Stylesheet id="leptos" href="/pkg/app-1.css"/> // sets the document title - <Title text="Welcome to Leptos"/> + <Title text="Welcome to Leptos" /> // content for this welcome page - <Router fallback=|| { + <Router fallback={|| { let mut outside_errors = Errors::default(); outside_errors.insert_with_default_key(AppError::NotFound); - view! { - <ErrorTemplate outside_errors/> - } - .into_view() - }> + view! { <ErrorTemplate outside_errors /> }.into_view() + }}> <main> <Routes> - <Route path="" view=HomePage/> + <Route path="" view={HomePage} /> </Routes> </main> </Router> @@ -58,22 +53,29 @@ fn HomePage() -> impl IntoView { create_effect(move|_|{if let Some(Ok(msg)) = hello_2_action.value().get(){value_2.set(msg)}}); view! { - <h1> App 1</h1> + <h1>App 1</h1> <div>Suspense</div> - <Suspense fallback=move || view! { <p>"Loading (Suspense Fallback)..."</p> }> - {move || { - hello_1.get().map(|data| match data { - Err(_) => view! { <pre>"Error"</pre> }.into_view(), - Ok(hello) => hello.into_view(), - }) - } - } - </Suspense> - <div> action response from server 1 </div> - <button on:click=move|_|hello_1_action.dispatch(SharedServerFunction{})>request from shared server 1</button> + <Suspense fallback={move || { + view! { <p>"Loading (Suspense Fallback)..."</p> } + }}> + {move || { + hello_1 + .get() + .map(|data| match data { + Err(_) => view! { <pre>"Error"</pre> }.into_view(), + Ok(hello) => hello.into_view(), + }) + }} + </Suspense> + <div>action response from server 1</div> + <button on:click={move |_| { + hello_1_action.dispatch(SharedServerFunction {}) + }}>request from shared server 1</button> {move || value_1.get()} - <div> action response from server 2 </div> - <button on:click=move|_|hello_2_action.dispatch(SharedServerFunction2{})>request from shared server 2</button> + <div>action response from server 2</div> + <button on:click={move |_| { + hello_2_action.dispatch(SharedServerFunction2 {}) + }}>request from shared server 2</button> {move || value_2.get()} } } diff --git a/projects/nginx-mpmc/app-1/src/error_template.rs b/projects/nginx-mpmc/app-1/src/error_template.rs index 1e0508da5c..3d50323307 100644 --- a/projects/nginx-mpmc/app-1/src/error_template.rs +++ b/projects/nginx-mpmc/app-1/src/error_template.rs @@ -52,21 +52,21 @@ pub fn ErrorTemplate( } view! { - <h1>{if errors.len() > 1 {"Errors"} else {"Error"}}</h1> + <h1>{if errors.len() > 1 { "Errors" } else { "Error" }}</h1> <For // a function that returns the items we're iterating over; a signal is fine - each= move || {errors.clone().into_iter().enumerate()} + each={move || { errors.clone().into_iter().enumerate() }} // a unique key for each item as a reference - key=|(index, _error)| *index + key={|(index, _error)| *index} // renders each item to a view - children=move |error| { + children={move |error| { let error_string = error.1.to_string(); - let error_code= error.1.status_code(); + let error_code = error.1.status_code(); view! { <h2>{error_code.to_string()}</h2> <p>"Error: " {error_string}</p> } - } + }} /> } } diff --git a/projects/nginx-mpmc/app-2/src/app.rs b/projects/nginx-mpmc/app-2/src/app.rs index 6374941fc8..a4b710278e 100644 --- a/projects/nginx-mpmc/app-2/src/app.rs +++ b/projects/nginx-mpmc/app-2/src/app.rs @@ -9,27 +9,22 @@ pub fn App() -> impl IntoView { provide_meta_context(); view! { - - // injects a stylesheet into the document <head> // id=leptos means cargo-leptos will hot-reload this stylesheet <Stylesheet id="leptos" href="/pkg2/app-2.css"/> // sets the document title - <Title text="Welcome to Leptos"/> + <Title text="Welcome to Leptos" /> // content for this welcome page - <Router fallback=|| { + <Router fallback={|| { let mut outside_errors = Errors::default(); outside_errors.insert_with_default_key(AppError::NotFound); - view! { - <ErrorTemplate outside_errors/> - } - .into_view() - }> + view! { <ErrorTemplate outside_errors /> }.into_view() + }}> <main> <Routes> - <Route path="app2" view=HomePage/> + <Route path="app2" view={HomePage} /> </Routes> </main> </Router> @@ -53,12 +48,16 @@ fn HomePage() -> impl IntoView { create_effect(move|_|{if let Some(Ok(msg)) = hello_2_action.value().get(){value_2.set(msg)}}); view! { - <h1> App 2</h1> - <div> action response from server 1 </div> - <button on:click=move|_|hello_1_action.dispatch(SharedServerFunction{})>request from shared server 1</button> + <h1>App 2</h1> + <div>action response from server 1</div> + <button on:click={move |_| { + hello_1_action.dispatch(SharedServerFunction {}) + }}>request from shared server 1</button> {move || value_1.get()} - <div> action response from server 2 </div> - <button on:click=move|_|hello_2_action.dispatch(SharedServerFunction2{})>request from shared server 2</button> + <div>action response from server 2</div> + <button on:click={move |_| { + hello_2_action.dispatch(SharedServerFunction2 {}) + }}>request from shared server 2</button> {move || value_2.get()} } } diff --git a/projects/nginx-mpmc/app-2/src/error_template.rs b/projects/nginx-mpmc/app-2/src/error_template.rs index 1e0508da5c..3d50323307 100644 --- a/projects/nginx-mpmc/app-2/src/error_template.rs +++ b/projects/nginx-mpmc/app-2/src/error_template.rs @@ -52,21 +52,21 @@ pub fn ErrorTemplate( } view! { - <h1>{if errors.len() > 1 {"Errors"} else {"Error"}}</h1> + <h1>{if errors.len() > 1 { "Errors" } else { "Error" }}</h1> <For // a function that returns the items we're iterating over; a signal is fine - each= move || {errors.clone().into_iter().enumerate()} + each={move || { errors.clone().into_iter().enumerate() }} // a unique key for each item as a reference - key=|(index, _error)| *index + key={|(index, _error)| *index} // renders each item to a view - children=move |error| { + children={move |error| { let error_string = error.1.to_string(); - let error_code= error.1.status_code(); + let error_code = error.1.status_code(); view! { <h2>{error_code.to_string()}</h2> <p>"Error: " {error_string}</p> } - } + }} /> } } diff --git a/projects/openapi-openai-api-swagger-ui/src/app.rs b/projects/openapi-openai-api-swagger-ui/src/app.rs index f09398be4a..feb1263805 100644 --- a/projects/openapi-openai-api-swagger-ui/src/app.rs +++ b/projects/openapi-openai-api-swagger-ui/src/app.rs @@ -9,27 +9,22 @@ pub fn App() -> impl IntoView { provide_meta_context(); view! { - - // injects a stylesheet into the document <head> // id=leptos means cargo-leptos will hot-reload this stylesheet <Stylesheet id="leptos" href="/pkg/openapi-swagger-ui.css"/> // sets the document title - <Title text="Welcome to Leptos"/> + <Title text="Welcome to Leptos" /> // content for this welcome page - <Router fallback=|| { + <Router fallback={|| { let mut outside_errors = Errors::default(); outside_errors.insert_with_default_key(AppError::NotFound); - view! { - <ErrorTemplate outside_errors/> - } - .into_view() - }> + view! { <ErrorTemplate outside_errors /> }.into_view() + }}> <main> <Routes> - <Route path="" view=HomePage/> + <Route path="" view={HomePage} /> </Routes> </main> </Router> @@ -41,22 +36,28 @@ pub fn App() -> impl IntoView { fn HomePage() -> impl IntoView { let hello = Action::<HelloWorld,_>::server(); view! { - <button on:click = move |_| hello.dispatch(HelloWorld{say_whut:SayHello{say:true}})> - "hello world" - </button> - - - <ErrorBoundary - fallback=|err| view! { <p>{format!("{err:#?}")}</p>}> - { - move || hello.value().get().map(|h|match h { - Ok(h) => h.into_view(), - err => err.into_view() + <button on:click={move |_| { + hello + .dispatch(HelloWorld { + say_whut: SayHello { say: true }, }) - } + }}>"hello world"</button> + + <ErrorBoundary fallback={|err| { + view! { <p>{format!("{err:#?}")}</p> } + }}> + {move || { + hello + .value() + .get() + .map(|h| match h { + Ok(h) => h.into_view(), + err => err.into_view(), + }) + }} </ErrorBoundary> - <AiSayHello/> + <AiSayHello /> } } @@ -130,45 +131,36 @@ pub async fn ai_msg(msg:String) -> Result<AiServerCall,ServerFnError> { pub fn AiSayHello() -> impl IntoView { let ai_msg = Action::<AiMsg, _>::server(); let result = create_rw_signal(Vec::new()); - view!{ - <ActionForm action=ai_msg> - <label> "Tell the AI what function to call." - <input name="msg"/> - </label> - <input type="submit"/> + view! { + <ActionForm action={ai_msg}> + <label>"Tell the AI what function to call." <input name="msg" /></label> + <input type="submit" /> </ActionForm> <div> - { - move || if let Some(Ok(AiServerCall{path,args})) = ai_msg.value().get() { - spawn_local(async move { - let text = - reqwest::Client::new() - .post(format!("http://127.0.0.1:3000/api/{}",path)) - .header("content-type","application/json") - .body(args) - .send() - .await - .unwrap() - .text() - .await - .unwrap(); - result.update(|list| - list.push( - text - ) - ); - }); - } - } - <For - each=move || result.get() - key=|_| uuid::Uuid::new_v4() - children=move |s:String| { - view! { - <p>{s}</p> - } - } - /> + {move || { + if let Some(Ok(AiServerCall { path, args })) = ai_msg.value().get() { + spawn_local(async move { + let text = reqwest::Client::new() + .post(format!("http://127.0.0.1:3000/api/{}", path)) + .header("content-type", "application/json") + .body(args) + .send() + .await + .unwrap() + .text() + .await + .unwrap(); + result.update(|list| list.push(text)); + }); + } + }} + <For + each={move || result.get()} + key={|_| uuid::Uuid::new_v4()} + children={move |s: String| { + view! { <p>{s}</p> } + }} + /> </div> } } \ No newline at end of file diff --git a/projects/openapi-openai-api-swagger-ui/src/error_template.rs b/projects/openapi-openai-api-swagger-ui/src/error_template.rs index 1e0508da5c..3d50323307 100644 --- a/projects/openapi-openai-api-swagger-ui/src/error_template.rs +++ b/projects/openapi-openai-api-swagger-ui/src/error_template.rs @@ -52,21 +52,21 @@ pub fn ErrorTemplate( } view! { - <h1>{if errors.len() > 1 {"Errors"} else {"Error"}}</h1> + <h1>{if errors.len() > 1 { "Errors" } else { "Error" }}</h1> <For // a function that returns the items we're iterating over; a signal is fine - each= move || {errors.clone().into_iter().enumerate()} + each={move || { errors.clone().into_iter().enumerate() }} // a unique key for each item as a reference - key=|(index, _error)| *index + key={|(index, _error)| *index} // renders each item to a view - children=move |error| { + children={move |error| { let error_string = error.1.to_string(); - let error_code= error.1.status_code(); + let error_code = error.1.status_code(); view! { <h2>{error_code.to_string()}</h2> <p>"Error: " {error_string}</p> } - } + }} /> } } diff --git a/projects/ory-kratos/app/src/auth/kratos_error.rs b/projects/ory-kratos/app/src/auth/kratos_error.rs index e04866933d..8af8c9026e 100644 --- a/projects/ory-kratos/app/src/auth/kratos_error.rs +++ b/projects/ory-kratos/app/src/auth/kratos_error.rs @@ -27,8 +27,13 @@ impl KratosError { impl IntoView for KratosError { fn into_view(self) -> View { - view!{ - <div>{self.code.map(|code|code.to_string()).unwrap_or("No Code included in error message".to_string())}</div> + view! { + <div> + {self + .code + .map(|code| code.to_string()) + .unwrap_or("No Code included in error message".to_string())} + </div> <div>{self.message.unwrap_or("No message in Kratos Error".to_string())}</div> <div>{self.reason.unwrap_or("No reason included in Kratos Error".to_string())}</div> <div>{self.debug.unwrap_or("No debug included in Kratos Error".to_string())}</div> @@ -63,9 +68,9 @@ pub fn KratosErrorPage() -> impl IntoView { let id = move || use_query_map().get().get("id").cloned().unwrap_or_default(); let fetch_error_resource = create_resource(move || id(), |id| fetch_error(id)); view! { - <Suspense fallback=||"Error loading...".into_view()> - <ErrorBoundary fallback=|errors|view!{<ErrorTemplate errors/>}> - { move || + <Suspense fallback={||"Error loading...".into_view()}> + <ErrorBoundary fallback={|errors| view!{<ErrorTemplate errors/>}}> + {move || fetch_error_resource.get().map(|resp| match resp { // kratos error isn't an error type, it's just a ui/data representation of a kratos error. Ok(kratos_error) => kratos_error.into_view(), diff --git a/projects/ory-kratos/app/src/auth/kratos_html.rs b/projects/ory-kratos/app/src/auth/kratos_html.rs index e563ac703c..9b81a8ab9d 100644 --- a/projects/ory-kratos/app/src/auth/kratos_html.rs +++ b/projects/ory-kratos/app/src/auth/kratos_html.rs @@ -12,16 +12,18 @@ pub fn kratos_html(node: UiNode, body: RwSignal<HashMap<String, String>>) -> imp // each node MAY have messages (i.e password is bad, email is wrong form etc) let messages_html = view! { <For - // a function that returns the items we're iterating over; a signal is fine - each=move || node.messages.clone() - // a unique key for each item - key=|ui_text| ui_text.id - // renders each item to a view - children=move |UiText { text,_type,.. }: UiText| { - // colored red, because we assume _type == error... - view!{<p style="color:red;">{text}</p>} - } - /> + // a function that returns the items we're iterating over; a signal is fine + each={move || node.messages.clone()} + // a unique key for each item + key={|ui_text| ui_text.id} + // renders each item to a view + children={move |UiText { text, _type, .. }: UiText| { + view! { + // colored red, because we assume _type == error... + <p style="color:red;">{text}</p> + } + }} + /> }; let node_html = match *node.attributes { @@ -63,8 +65,8 @@ pub fn kratos_html(node: UiNode, body: RwSignal<HashMap<String, String>>) -> imp view! { // will be something like value="password" name="method" // or value="oidc" name="method" - <input type="hidden" value=value name=name/> - <input type="submit" value=label/> + <input type="hidden" value={value} name={name} /> + <input type="submit" value={label} /> } .into_view() } else if _type != UiNodeAttributesTypeEnum::Hidden { @@ -72,19 +74,25 @@ pub fn kratos_html(node: UiNode, body: RwSignal<HashMap<String, String>>) -> imp view! { <label> - <span>{&label}</span> - <input name=name - id=id - // we use replace here and in autocomplete because serde_json adds double quotes for some reason? - type=_type_str.replace("\"","") - value=move||body.get().get(&name_clone_2).cloned().unwrap_or_default() - autocomplete=autocomplete.replace("\"","") - disabled=disabled - required=required placeholder=label - on:input=move |ev|{ - let name = name_clone.clone(); - body.update(|map|{_=map.insert(name,event_target_value(&ev));}) - } + <span>{&label}</span> + <input + name={name} + id={id} + // we use replace here and in autocomplete because serde_json adds double quotes for some reason? + type={_type_str.replace("\"", "")} + value={move || { + body.get().get(&name_clone_2).cloned().unwrap_or_default() + }} + autocomplete={autocomplete.replace("\"", "")} + disabled={disabled} + required={required} + placeholder={label} + on:input={move |ev| { + let name = name_clone.clone(); + body.update(|map| { + _ = map.insert(name, event_target_value(&ev)); + }) + }} /> </label> } @@ -94,20 +102,24 @@ pub fn kratos_html(node: UiNode, body: RwSignal<HashMap<String, String>>) -> imp _ = map.insert(name.clone(), value.clone()); }); // this expects the identifier to be an email, but it could be telephone etc so code is extra fragile - view! {<input type="hidden" value=value name=name /> }.into_view() + view! { <input type="hidden" value={value} name={name} /> }.into_view() } } UiNodeAttributes::UiNodeAnchorAttributes { href, id, title } => { let inner = title.text; - view! {<a href=href id=id>{inner}</a>}.into_view() + view! { + <a href={href} id={id}> + {inner} + </a> + }.into_view() } UiNodeAttributes::UiNodeImageAttributes { height, id, src, width, - } => view! {<img src=src height=height width=width id=id/>}.into_view(), - UiNodeAttributes::UiNodeScriptAttributes { .. } => view! {script not supported}.into_view(), + } => view! { <img src={src} height={height} width={width} id={id} /> }.into_view(), + UiNodeAttributes::UiNodeScriptAttributes { .. } => view! { script not supported }.into_view(), UiNodeAttributes::UiNodeTextAttributes { id, text: @@ -120,7 +132,7 @@ pub fn kratos_html(node: UiNode, body: RwSignal<HashMap<String, String>>) -> imp // This could be, info, error, success. i.e context for msg responses on bad input etc _type, }, - } => view! {<p id=id>{text}</p>}.into_view(), + } => view! { <p id={id}>{text}</p> }.into_view(), }; view! { {node_html} diff --git a/projects/ory-kratos/app/src/auth/login.rs b/projects/ory-kratos/app/src/auth/login.rs index 1d0b760fb0..f2c84e2869 100644 --- a/projects/ory-kratos/app/src/auth/login.rs +++ b/projects/ory-kratos/app/src/auth/login.rs @@ -168,50 +168,70 @@ pub fn LoginPage() -> impl IntoView { }); let body = create_rw_signal(HashMap::new()); view! { - <Suspense fallback=||view!{Loading Login Details}> - <ErrorBoundary fallback=|errors|view!{<ErrorTemplate errors/>}> - { - move || - login_flow.get().map(|resp| - match resp { - Ok(resp) => { - match resp { - LoginResponse::Flow(ViewableLoginFlow(LoginFlow{ui:box UiContainer{nodes,action,messages,..},..})) => { - let form_inner_html = nodes.into_iter().map(|node|kratos_html(node,body)).collect_view(); - body.update(move|map|{_=map.insert(String::from("action"),action);}); - view!{ - <form id=ids::LOGIN_FORM_ID - on:submit=move|e|{ - e.prevent_default(); - e.stop_propagation(); - login.dispatch(Login{body:body.get_untracked()}); - }> - {form_inner_html} - {messages.map(|messages|{ - view!{ - <For - each=move || messages.clone().into_iter() - key=|text| text.id - children=move |text: UiText| { - view! { - <p id=text.id>{text.text}</p> - } - } - /> - } - }).unwrap_or_default()} - </form> - }.into_view() - }, - LoginResponse::Success => { - view!{<Redirect path="/"/>}.into_view() + <Suspense fallback={|| view! { Loading Login Details }}> + <ErrorBoundary fallback={|errors| { + view! { <ErrorTemplate errors /> } + }}> + {move || { + login_flow + .get() + .map(|resp| match resp { + Ok(resp) => { + match resp { + LoginResponse::Flow( + ViewableLoginFlow( + LoginFlow { + ui: box UiContainer { nodes, action, messages, .. }, + .. + }, + ), + ) => { + let form_inner_html = nodes + .into_iter() + .map(|node| kratos_html(node, body)) + .collect_view(); + body.update(move |map| { + _ = map.insert(String::from("action"), action); + }); + view! { + <form + id={ids::LOGIN_FORM_ID} + on:submit={move |e| { + e.prevent_default(); + e.stop_propagation(); + login + .dispatch(Login { + body: body.get_untracked(), + }); + }} + > + {form_inner_html} + {messages + .map(|messages| { + view! { + <For + each={move || messages.clone().into_iter()} + key={|text| text.id} + children={move |text: UiText| { + view! { <p id={text.id}>{text.text}</p> } + }} + /> + } + }) + .unwrap_or_default()} + </form> + } + .into_view() + } + LoginResponse::Success => { + view! { <Redirect path="/" /> }.into_view() + } + } } - } - } - err => err.into_view(), - }) - } - </ErrorBoundary> - </Suspense> + err => err.into_view(), + }) + }} + </ErrorBoundary> + </Suspense> } } diff --git a/projects/ory-kratos/app/src/auth/logout.rs b/projects/ory-kratos/app/src/auth/logout.rs index 4d9b5fe693..a82d13c050 100644 --- a/projects/ory-kratos/app/src/auth/logout.rs +++ b/projects/ory-kratos/app/src/auth/logout.rs @@ -83,11 +83,11 @@ pub async fn logout() -> Result<(), ServerFnError> { pub fn LogoutButton() -> impl IntoView { let logout = Action::<Logout, _>::server(); view! { - <button id=ids::LOGOUT_BUTTON_ID on:click=move|_|logout.dispatch(Logout{})> + <button id={ids::LOGOUT_BUTTON_ID} on:click={move |_| logout.dispatch(Logout {})}> Logout - <ErrorBoundary fallback=|errors|view!{<ErrorTemplate errors/>}> - { move || logout.value().get().map(|resp|resp.into_view())} - </ErrorBoundary> + <ErrorBoundary fallback={|errors| { + view! { <ErrorTemplate errors /> } + }}>{move || logout.value().get().map(|resp| resp.into_view())}</ErrorBoundary> </button> } } diff --git a/projects/ory-kratos/app/src/auth/recovery.rs b/projects/ory-kratos/app/src/auth/recovery.rs index e615a7bb5a..7efb36bc20 100644 --- a/projects/ory-kratos/app/src/auth/recovery.rs +++ b/projects/ory-kratos/app/src/auth/recovery.rs @@ -31,7 +31,7 @@ impl IntoView for ViewableContinueWith { ContinueWith::ContinueWithRecoveryUi { flow } => todo!(), ContinueWith::ContinueWithSettingsUi { flow: box ContinueWithSettingsUiFlow { id }, - } => view! {<Redirect path=format!("/settings?flow={id}")/>}.into_view(), + } => view! { <Redirect path={format!("/settings?flow={id}")} /> }.into_view(), ContinueWith::ContinueWithVerificationUi { flow } => todo!(), } } else { @@ -174,53 +174,74 @@ pub fn RecoveryPage() -> impl IntoView { }); let body = create_rw_signal(HashMap::new()); view! { - <Suspense fallback=||view!{}> - <ErrorBoundary fallback=|errors|view!{<ErrorTemplate errors/>}> - { - move || - recovery_flow.get().map(|resp| - match resp { - Ok(ViewableRecoveryFlow(RecoveryFlow{ - continue_with, - ui:box UiContainer{nodes,action,messages,..},..})) => { + <Suspense fallback={|| view! {}}> + <ErrorBoundary fallback={|errors| { + view! { <ErrorTemplate errors /> } + }}> + {move || { + recovery_flow + .get() + .map(|resp| match resp { + Ok( + ViewableRecoveryFlow( + RecoveryFlow { + continue_with, + ui: box UiContainer { nodes, action, messages, .. }, + .. + }, + ), + ) => { if let Some(continue_with) = continue_with { return ViewableContinueWith(continue_with).into_view(); } - let form_inner_html = nodes.into_iter().map(|node|kratos_html(node,body)).collect_view(); - body.update(move|map|{_=map.insert(String::from("action"),action);}); - view!{ - <form id=ids::RECOVERY_FORM_ID - on:submit=move|e|{ - if body.get().get(&String::from("code")).is_some() { - // if we have a code we need to drop the email which will be stored from earlier. - // if we include the email then ory kratos server will not try to validate the code. - // but instead send another recovery email. - body.update(move|map|{_=map.remove(&String::from("email"));}); - } - e.prevent_default(); - e.stop_propagation(); - recovery.dispatch(ProcessRecovery{body:body.get_untracked()}); - }> - {form_inner_html} - {messages.map(|messages|{ - view!{ - <For - each=move || messages.clone().into_iter() - key=|text| text.id - children=move |text: UiText| { - view! { - <p id=text.id>{text.text}</p> - } + let form_inner_html = nodes + .into_iter() + .map(|node| kratos_html(node, body)) + .collect_view(); + body.update(move |map| { + _ = map.insert(String::from("action"), action); + }); + view! { + <form + id={ids::RECOVERY_FORM_ID} + on:submit={move |e| { + if body.get().get(&String::from("code")).is_some() { + // if we have a code we need to drop the email which will be stored from earlier. + // if we include the email then ory kratos server will not try to validate the code. + // but instead send another recovery email. + body.update(move |map| { + _ = map.remove(&String::from("email")); + }); + } + e.prevent_default(); + e.stop_propagation(); + recovery + .dispatch(ProcessRecovery { + body: body.get_untracked(), + }); + }} + > + {form_inner_html} + {messages + .map(|messages| { + view! { + <For + each={move || messages.clone().into_iter()} + key={|text| text.id} + children={move |text: UiText| { + view! { <p id={text.id}>{text.text}</p> } + }} + /> } - /> - } - }).unwrap_or_default()} + }) + .unwrap_or_default()} </form> - }.into_view() - }, - err => err.into_view(), - }) - } + } + .into_view() + } + err => err.into_view(), + }) + }} </ErrorBoundary> </Suspense> } diff --git a/projects/ory-kratos/app/src/auth/registration.rs b/projects/ory-kratos/app/src/auth/registration.rs index dbcb33a5a3..255673a08c 100644 --- a/projects/ory-kratos/app/src/auth/registration.rs +++ b/projects/ory-kratos/app/src/auth/registration.rs @@ -202,61 +202,82 @@ pub fn RegistrationPage() -> impl IntoView { let body = create_rw_signal(HashMap::new()); view! { // we'll render the fallback when the user hits the page for the first time - <Suspense fallback=||view!{Loading Registration Details}> - // if we get any errors, from either server functions we've merged we'll render them here. - <ErrorBoundary fallback=|errors|view!{<ErrorTemplate errors/>}> - { - move || - // this is the resource XOR the results of the register action. - registration_flow.get().map(|resp|{ - match resp { - // TODO add Oauth using the flow args (see type docs) - Ok(resp) => { - match resp { - RegistrationResponse::Flow(ViewableRegistrationFlow(RegistrationFlow{ui:box UiContainer{nodes,action,messages,..},..})) - => { - let form_inner_html = nodes.into_iter().map(|node|kratos_html(node,body)).collect_view(); - body.update(move|map|{_=map.insert(String::from("action"),action);}); + <Suspense fallback={|| view! { Loading Registration Details }}> + // if we get any errors, from either server functions we've merged we'll render them here. + <ErrorBoundary fallback={|errors| { + view! { <ErrorTemplate errors /> } + }}> + {move || { + // this is the resource XOR the results of the register action. + registration_flow + .get() + .map(|resp| { + match resp { + // TODO add Oauth using the flow args (see type docs) + Ok(resp) => { + match resp { + RegistrationResponse::Flow( + ViewableRegistrationFlow( + RegistrationFlow { + ui: box UiContainer { nodes, action, messages, .. }, + .. + }, + ), + ) => { + let form_inner_html = nodes + .into_iter() + .map(|node| kratos_html(node, body)) + .collect_view(); + body.update(move |map| { + _ = map.insert(String::from("action"), action); + }); + view! { + <form - view!{ - <form - - on:submit=move|e|{ - e.prevent_default(); - e.stop_propagation(); - register.dispatch(Register{body:body.get_untracked()}); - } - id=ids::REGISTRATION_FORM_ID - > - {form_inner_html} - // kratos_html renders messages for each node and these are the messages attached to the entire form. - {messages.map(|messages|{ - view!{ - <For - each=move || messages.clone().into_iter() - key=|text| text.id - children=move |text: UiText| { - view! { - <p id=text.id>{text.text}</p> - } - } - /> + on:submit={move |e| { + e.prevent_default(); + e.stop_propagation(); + register + .dispatch(Register { + body: body.get_untracked(), + }); + }} + id={ids::REGISTRATION_FORM_ID} + > + {form_inner_html} + // kratos_html renders messages for each node and these are the messages attached to the entire form. + {messages + .map(|messages| { + view! { + <For + each={move || messages.clone().into_iter()} + key={|text| text.id} + children={move |text: UiText| { + view! { <p id={text.id}>{text.text}</p> } + }} + /> + } + }) + .unwrap_or_default()} + </form> + } + .into_view() } - }).unwrap_or_default()} - </form> - }.into_view() - - }, - RegistrationResponse::Success => { - view!{<div id=ids::VERIFY_EMAIL_DIV_ID>"Check Email for Verification"</div>}.into_view() - } - } - }, - err => err.into_view(), - } - }) - } - </ErrorBoundary> - </Suspense> + RegistrationResponse::Success => { + view! { + <div id={ids::VERIFY_EMAIL_DIV_ID}> + "Check Email for Verification" + </div> + } + .into_view() + } + } + } + err => err.into_view(), + } + }) + }} + </ErrorBoundary> + </Suspense> } } diff --git a/projects/ory-kratos/app/src/auth/session.rs b/projects/ory-kratos/app/src/auth/session.rs index 483777eb08..7243d7444c 100644 --- a/projects/ory-kratos/app/src/auth/session.rs +++ b/projects/ory-kratos/app/src/auth/session.rs @@ -21,11 +21,13 @@ pub async fn session_who_am_i() -> Result<ViewableSession, ServerFnError> { pub fn HasSession() -> impl IntoView { let check_session = Action::<SessionWhoAmI, _>::server(); view! { - <button on:click=move|_|check_session.dispatch(SessionWhoAmI{})> + <button on:click={move |_| { + check_session.dispatch(SessionWhoAmI {}) + }}> Check Session Status - <ErrorBoundary fallback=|errors|view!{<ErrorTemplate errors/>}> - { move || check_session.value().get().map(|sesh|sesh.into_view()) } - </ErrorBoundary> + <ErrorBoundary fallback={|errors| { + view! { <ErrorTemplate errors /> } + }}>{move || check_session.value().get().map(|sesh| sesh.into_view())}</ErrorBoundary> </button> } } diff --git a/projects/ory-kratos/app/src/auth/settings.rs b/projects/ory-kratos/app/src/auth/settings.rs index 043d3fab51..6655abdfe0 100644 --- a/projects/ory-kratos/app/src/auth/settings.rs +++ b/projects/ory-kratos/app/src/auth/settings.rs @@ -291,45 +291,66 @@ pub fn SettingsPage() -> impl IntoView { }); let body = create_rw_signal(HashMap::new()); view! { - <Suspense fallback=||"loading settings...".into_view()> - <ErrorBoundary fallback=|errors|view!{<ErrorTemplate errors/>}> - { - move || flow.get().map(|resp| - match resp { - Ok( - ViewableSettingsFlow(SettingsFlow{id,ui:box UiContainer{nodes,action,messages,..},..}) - ) => { - let form_inner_html = nodes.into_iter().map(|node|kratos_html(node,body)).collect_view(); - body.update(move|map|{_=map.insert(String::from("action"),action);}); - let id = create_rw_signal(id); - view!{ - <form id=ids::SETTINGS_FORM_ID - on:submit=move|e|{ - e.prevent_default(); - e.stop_propagation(); - update_settings_action.dispatch(UpdateSettings{flow_id:id.get_untracked(),body:body.get_untracked()}); - }> - {form_inner_html} - {messages.map(|messages|{ - view!{ - <For - each=move || messages.clone().into_iter() - key=|text| text.id - children=move |text: UiText| { - view! { - <p id=text.id>{text.text}</p> - } - } - /> - } - }).unwrap_or_default()} - </form> - }.into_view() - }, - err => err.into_view() - }) - } + <Suspense fallback={|| "loading settings...".into_view()}> + <ErrorBoundary fallback={|errors| { + view! { <ErrorTemplate errors /> } + }}> + {move || { + flow + .get() + .map(|resp| match resp { + Ok( + ViewableSettingsFlow( + SettingsFlow { + id, + ui: box UiContainer { nodes, action, messages, .. }, + .. + }, + ), + ) => { + let form_inner_html = nodes + .into_iter() + .map(|node| kratos_html(node, body)) + .collect_view(); + body.update(move |map| { + _ = map.insert(String::from("action"), action); + }); + let id = create_rw_signal(id); + view! { + <form + id={ids::SETTINGS_FORM_ID} + on:submit={move |e| { + e.prevent_default(); + e.stop_propagation(); + update_settings_action + .dispatch(UpdateSettings { + flow_id: id.get_untracked(), + body: body.get_untracked(), + }); + }} + > + {form_inner_html} + {messages + .map(|messages| { + view! { + <For + each={move || messages.clone().into_iter()} + key={|text| text.id} + children={move |text: UiText| { + view! { <p id={text.id}>{text.text}</p> } + }} + /> + } + }) + .unwrap_or_default()} + </form> + } + .into_view() + } + err => err.into_view(), + }) + }} </ErrorBoundary> - </Suspense> - } + </Suspense> + } } diff --git a/projects/ory-kratos/app/src/auth/verification.rs b/projects/ory-kratos/app/src/auth/verification.rs index cf44ebc9bf..ed2d024b58 100644 --- a/projects/ory-kratos/app/src/auth/verification.rs +++ b/projects/ory-kratos/app/src/auth/verification.rs @@ -118,45 +118,67 @@ pub fn VerificationPage() -> impl IntoView { }); let body = create_rw_signal(HashMap::new()); view! { - <Suspense fallback=||view!{Loading Verification Details}> - <ErrorBoundary fallback=|errors|format!("ERRORS: {:?}",errors.get_untracked()).into_view()> - { - move || - verification_flow.get().map(|resp|{ - match resp { - Ok(Some(ViewableVerificationFlow(VerificationFlow{ui:box UiContainer{nodes,messages,action,..},..}))) => { - let form_inner_html = nodes.into_iter().map(|node|kratos_html(node,body)).collect_view(); - body.update(|map|{_=map.insert(String::from("action"),action);}); - view!{ - <form on:submit=move|e|{ - e.prevent_default(); - e.stop_propagation(); - verify.dispatch(Verify{body:body.get_untracked()}); - } - id=ids::VERIFICATION_FORM_ID - > - {form_inner_html} - {messages.map(|messages|{ - view!{ - <For - each=move || messages.clone().into_iter() - key=|text| text.id - children=move |text: UiText| { - view! { - <p id=text.id>{text.text}</p> - } - } - /> + <Suspense fallback={|| view! { Loading Verification Details }}> + <ErrorBoundary fallback={|errors| { + format!("ERRORS: {:?}", errors.get_untracked()).into_view() + }}> + {move || { + verification_flow + .get() + .map(|resp| { + match resp { + Ok( + Some( + ViewableVerificationFlow( + VerificationFlow { + ui: box UiContainer { nodes, messages, action, .. }, + .. + }, + ), + ), + ) => { + let form_inner_html = nodes + .into_iter() + .map(|node| kratos_html(node, body)) + .collect_view(); + body.update(|map| { + _ = map.insert(String::from("action"), action); + }); + view! { + <form + on:submit={move |e| { + e.prevent_default(); + e.stop_propagation(); + verify + .dispatch(Verify { + body: body.get_untracked(), + }); + }} + id={ids::VERIFICATION_FORM_ID} + > + {form_inner_html} + {messages + .map(|messages| { + view! { + <For + each={move || messages.clone().into_iter()} + key={|text| text.id} + children={move |text: UiText| { + view! { <p id={text.id}>{text.text}</p> } + }} + /> + } + }) + .unwrap_or_default()} + </form> } - }).unwrap_or_default()} - </form> - }.into_view() - }, - err => err.into_view(), - } - }) - } - </ErrorBoundary> - </Suspense> + .into_view() + } + err => err.into_view(), + } + }) + }} + </ErrorBoundary> + </Suspense> } } diff --git a/projects/ory-kratos/app/src/error_template.rs b/projects/ory-kratos/app/src/error_template.rs index aa2ed962e2..9fb4226311 100644 --- a/projects/ory-kratos/app/src/error_template.rs +++ b/projects/ory-kratos/app/src/error_template.rs @@ -65,19 +65,19 @@ pub fn ErrorTemplate( <h1>{if errors.len() > 1 { "Errors" } else { "Error" }}</h1> <For // a function that returns the items we're iterating over; a signal is fine - each=move || { errors.clone().into_iter().enumerate() } + each={move || { errors.clone().into_iter().enumerate() }} // a unique key for each item as a reference - key=|(index, _error)| *index + key={|(index, _error)| *index} // renders each item to a view - children=move |error| { + children={move |error| { let error_string = error.1.to_string(); let error_code = error.1.status_code(); view! { <h2>{error_code.to_string()}</h2> - <p >"Error: " {error_string}</p> + <p>"Error: " {error_string}</p> } - } + }} /> - <p id=ids::ERROR_ERROR_ID>{basic_err_msg}</p> + <p id={ids::ERROR_ERROR_ID}>{basic_err_msg}</p> } } diff --git a/projects/ory-kratos/app/src/lib.rs b/projects/ory-kratos/app/src/lib.rs index 6d32b4d8b5..4bf1aaadde 100644 --- a/projects/ory-kratos/app/src/lib.rs +++ b/projects/ory-kratos/app/src/lib.rs @@ -22,26 +22,26 @@ pub fn App() -> impl IntoView { provide_meta_context(); view! { - <Stylesheet id="leptos" href="/pkg/ory-auth-example.css"/> + <Stylesheet id="leptos" href="/pkg/ory-auth-example.css" /> // sets the document title - <Title text="Welcome to Leptos"/> + <Title text="Welcome to Leptos" /> // content for this welcome page - <Router fallback=|| { + <Router fallback={|| { let mut outside_errors = Errors::default(); outside_errors.insert_with_default_key(AppError::NotFound); - view! { <ErrorTemplate outside_errors/> }.into_view() - }> + view! { <ErrorTemplate outside_errors /> }.into_view() + }}> <main> <Routes> - <Route path="" view=HomePage/> - <Route path=ids::REGISTER_ROUTE view=RegistrationPage/> - <Route path=ids::VERIFICATION_ROUTE view=VerificationPage/> - <Route path=ids::LOGIN_ROUTE view=LoginPage/> - <Route path=ids::KRATOS_ERROR_ROUTE view=KratosErrorPage/> - <Route path=ids::RECOVERY_ROUTE view=RecoveryPage/> - <Route path=ids::SETTINGS_ROUTE view=SettingsPage/> + <Route path="" view={HomePage} /> + <Route path={ids::REGISTER_ROUTE} view={RegistrationPage} /> + <Route path={ids::VERIFICATION_ROUTE} view={VerificationPage} /> + <Route path={ids::LOGIN_ROUTE} view={LoginPage} /> + <Route path={ids::KRATOS_ERROR_ROUTE} view={KratosErrorPage} /> + <Route path={ids::RECOVERY_ROUTE} view={RecoveryPage} /> + <Route path={ids::SETTINGS_ROUTE} view={SettingsPage} /> </Routes> </main> </Router> @@ -55,29 +55,39 @@ fn HomePage() -> impl IntoView { view! { <h1>"Welcome to Leptos!"</h1> <div> - <a href=ids::REGISTER_ROUTE id=ids::REGISTER_BUTTON_ID>Register</a> + <a href={ids::REGISTER_ROUTE} id={ids::REGISTER_BUTTON_ID}> + Register + </a> </div> <div> - <a href=ids::LOGIN_ROUTE id=ids::LOGIN_BUTTON_ID>"Login"</a> + <a href={ids::LOGIN_ROUTE} id={ids::LOGIN_BUTTON_ID}> + "Login" + </a> </div> <div> - <LogoutButton/> + <LogoutButton /> </div> <div> - <button id=ids::CLEAR_COOKIES_BUTTON_ID - on:click=move|_|clear_cookies.dispatch(ClearCookies{})>Clear cookies </button> + <button + id={ids::CLEAR_COOKIES_BUTTON_ID} + on:click={move |_| clear_cookies.dispatch(ClearCookies {})} + > + Clear cookies + </button> </div> <div> - <HasSession/> + <HasSession /> </div> <div> - <PostPage/> + <PostPage /> </div> <div> - <a href=ids::RECOVERY_ROUTE id=ids::RECOVER_EMAIL_BUTTON_ID>"Recovery Email"</a> + <a href={ids::RECOVERY_ROUTE} id={ids::RECOVER_EMAIL_BUTTON_ID}> + "Recovery Email" + </a> </div> <div> - <a href=ids::SETTINGS_ROUTE>"Settings"</a> + <a href={ids::SETTINGS_ROUTE}>"Settings"</a> </div> } } diff --git a/projects/ory-kratos/app/src/posts/create_posts.rs b/projects/ory-kratos/app/src/posts/create_posts.rs index e15bec8856..10fe484c0f 100644 --- a/projects/ory-kratos/app/src/posts/create_posts.rs +++ b/projects/ory-kratos/app/src/posts/create_posts.rs @@ -21,14 +21,14 @@ pub async fn post_post(content: String) -> Result<(), ServerFnError> { pub fn CreatePost() -> impl IntoView { let post_post = Action::<PostPost, _>::server(); view! { - <ActionForm action=post_post> - <textarea type="text" name="content" id=ids::POST_POST_TEXT_AREA_ID/> - <input type="submit" value="Post Post" id=ids::POST_POST_SUBMIT_ID/> + <ActionForm action={post_post}> + <textarea type="text" name="content" id={ids::POST_POST_TEXT_AREA_ID} /> + <input type="submit" value="Post Post" id={ids::POST_POST_SUBMIT_ID} /> </ActionForm> - <Suspense fallback=move||view!{}> - <ErrorBoundary fallback=|errors|view!{<ErrorTemplate errors/>}> - { move || post_post.value().get()} - </ErrorBoundary> + <Suspense fallback={move || view! {}}> + <ErrorBoundary fallback={|errors| { + view! { <ErrorTemplate errors /> } + }}>{move || post_post.value().get()}</ErrorBoundary> </Suspense> } } diff --git a/projects/ory-kratos/app/src/posts/post.rs b/projects/ory-kratos/app/src/posts/post.rs index 6946eb31e8..5eb36ad2c8 100644 --- a/projects/ory-kratos/app/src/posts/post.rs +++ b/projects/ory-kratos/app/src/posts/post.rs @@ -10,8 +10,8 @@ pub fn Post(post: PostData) -> impl IntoView { } = post; view! { <div>{content}</div> - <AddEditor post_id=post_id.clone()/> - <EditPost post_id=post_id.clone()/> + <AddEditor post_id={post_id.clone()} /> + <EditPost post_id={post_id.clone()} /> } } @@ -52,17 +52,17 @@ pub async fn server_add_editor(post_id: String, email: String) -> Result<(), Ser pub fn AddEditor(post_id: String) -> impl IntoView { let add_editor = Action::<ServerAddEditor, _>::server(); view! { - <ActionForm action=add_editor> + <ActionForm action={add_editor}> <label value="Add Editor Email"> - <input type="text" name="email" id=ids::POST_ADD_EDITOR_INPUT_ID/> - <input type="hidden" name="post_id" value=post_id/> + <input type="text" name="email" id={ids::POST_ADD_EDITOR_INPUT_ID} /> + <input type="hidden" name="post_id" value={post_id} /> </label> - <input type="submit" id=ids::POST_ADD_EDITOR_SUBMIT_ID/> + <input type="submit" id={ids::POST_ADD_EDITOR_SUBMIT_ID} /> </ActionForm> - <Suspense fallback=||view!{}> - <ErrorBoundary fallback=|errors|view!{<ErrorTemplate errors/>}> - { move || add_editor.value().get()} - </ErrorBoundary> + <Suspense fallback={|| view! {}}> + <ErrorBoundary fallback={|errors| { + view! { <ErrorTemplate errors /> } + }}>{move || add_editor.value().get()}</ErrorBoundary> </Suspense> } } @@ -90,17 +90,17 @@ pub async fn server_edit_post(post_id: String, content: String) -> Result<(), Se pub fn EditPost(post_id: String) -> impl IntoView { let edit_post = Action::<ServerEditPost, _>::server(); view! { - <ActionForm action=edit_post> + <ActionForm action={edit_post}> <label value="New Content:"> - <textarea name="content" id=ids::POST_EDIT_TEXT_AREA_ID/> - <input type="hidden" name="post_id" value=post_id/> + <textarea name="content" id={ids::POST_EDIT_TEXT_AREA_ID} /> + <input type="hidden" name="post_id" value={post_id} /> </label> - <input type="submit" id=ids::POST_EDIT_SUBMIT_ID/> + <input type="submit" id={ids::POST_EDIT_SUBMIT_ID} /> </ActionForm> - <Suspense fallback=||view!{}> - <ErrorBoundary fallback=|errors|view!{<ErrorTemplate errors/>}> - { move || edit_post.value().get()} - </ErrorBoundary> + <Suspense fallback={|| view! {}}> + <ErrorBoundary fallback={|errors| { + view! { <ErrorTemplate errors /> } + }}>{move || edit_post.value().get()}</ErrorBoundary> </Suspense> } } diff --git a/projects/ory-kratos/app/src/posts/posts_page.rs b/projects/ory-kratos/app/src/posts/posts_page.rs index 3f5c9d05ea..0c58641287 100644 --- a/projects/ory-kratos/app/src/posts/posts_page.rs +++ b/projects/ory-kratos/app/src/posts/posts_page.rs @@ -11,7 +11,7 @@ pub struct PostData { } impl IntoView for PostData { fn into_view(self) -> View { - view! {<Post post=self/>} + view! { <Post post={self} /> } } } @@ -35,8 +35,8 @@ pub async fn get_post_list() -> Result<Vec<PostData>, ServerFnError> { #[component] pub fn PostPage() -> impl IntoView { view! { - <PostsList/> - <CreatePost/> + <PostsList /> + <CreatePost /> } } @@ -45,25 +45,35 @@ pub fn PostsList() -> impl IntoView { let list_posts = Action::<GetPostList, _>::server(); view! { - <button on:click=move|_|list_posts.dispatch(GetPostList{}) id=ids::POST_SHOW_LIST_BUTTON_ID>Show List</button> - <Suspense fallback=||"Post list loading...".into_view()> - <ErrorBoundary fallback=|errors|view!{<ErrorTemplate errors/>}> - { - move || list_posts.value().get().map(|resp| - match resp { - Ok(list) => view!{ - <For - each=move || list.clone() - key=|_| uuid::Uuid::new_v4() - children=move |post: PostData| { - post.into_view() + <button + on:click={move |_| list_posts.dispatch(GetPostList {})} + id={ids::POST_SHOW_LIST_BUTTON_ID} + > + Show List + </button> + <Suspense fallback={|| "Post list loading...".into_view()}> + <ErrorBoundary fallback={|errors| { + view! { <ErrorTemplate errors /> } + }}> + {move || { + list_posts + .value() + .get() + .map(|resp| match resp { + Ok(list) => { + view! { + <For + each={move || list.clone()} + key={|_| uuid::Uuid::new_v4()} + children={move |post: PostData| { post.into_view() }} + /> + } + .into_view() } - /> - }.into_view(), - err => err.into_view() - }) - } - </ErrorBoundary> + err => err.into_view(), + }) + }} + </ErrorBoundary> </Suspense> } } diff --git a/projects/ory-kratos/server/src/fileserv.rs b/projects/ory-kratos/server/src/fileserv.rs index 06f0d937af..a1fdb31dfd 100644 --- a/projects/ory-kratos/server/src/fileserv.rs +++ b/projects/ory-kratos/server/src/fileserv.rs @@ -22,7 +22,7 @@ pub async fn file_and_error_handler( res.into_response() } else { let handler = - leptos_axum::render_app_to_stream(options.to_owned(), move || view! { <App/> }); + leptos_axum::render_app_to_stream(options.to_owned(), move || view! { <App /> }); handler(req).await.into_response() } } diff --git a/projects/session_auth_axum/src/error_template.rs b/projects/session_auth_axum/src/error_template.rs index a60429af46..10adfef4db 100644 --- a/projects/session_auth_axum/src/error_template.rs +++ b/projects/session_auth_axum/src/error_template.rs @@ -40,18 +40,18 @@ pub fn ErrorTemplate( <h1>"Errors"</h1> <For // a function that returns the items we're iterating over; a signal is fine - each=move || { errors.clone().into_iter().enumerate() } + each={move || { errors.clone().into_iter().enumerate() }} // a unique key for each item as a reference - key=|(index, _error)| *index + key={|(index, _error)| *index} // renders each item to a view - children=move |error| { + children={move |error| { let error_string = error.1.to_string(); let error_code = error.1.status_code(); view! { <h2>{error_code.to_string()}</h2> <p>"Error: " {error_string}</p> } - } + }} /> } } diff --git a/projects/session_auth_axum/src/fallback.rs b/projects/session_auth_axum/src/fallback.rs index 66b2a5ffe0..7838e8c9f1 100644 --- a/projects/session_auth_axum/src/fallback.rs +++ b/projects/session_auth_axum/src/fallback.rs @@ -24,7 +24,7 @@ pub async fn file_and_error_handler( errors.insert_with_default_key(TodoAppError::NotFound); let handler = leptos_axum::render_app_to_stream( options.to_owned(), - move || view! {<ErrorTemplate outside_errors=errors.clone()/>}, + move || view! { <ErrorTemplate outside_errors={errors.clone()} /> }, ); handler(req).await.into_response() } diff --git a/projects/session_auth_axum/src/todo.rs b/projects/session_auth_axum/src/todo.rs index a2f91401dd..bef3ce20fc 100644 --- a/projects/session_auth_axum/src/todo.rs +++ b/projects/session_auth_axum/src/todo.rs @@ -128,16 +128,16 @@ pub fn TodoApp() -> impl IntoView { provide_meta_context(); view! { - <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico"/> - <Stylesheet id="leptos" href="/pkg/session_auth_axum.css"/> + <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico" /> + <Stylesheet id="leptos" href="/pkg/session_auth_axum.css" /> <Router> <header> <A href="/"> <h1>"My Tasks"</h1> </A> - <Transition fallback=move || { + <Transition fallback={move || { view! { <span>"Loading..."</span> } - }> + }}> {move || { user.get() .map(|user| match user { @@ -176,21 +176,21 @@ pub fn TodoApp() -> impl IntoView { </Transition> </header> - <hr/> + <hr /> <main> <Routes> // Route - <Route path="" view=Todos/> - <Route path="signup" view=move || view! { <Signup action=signup/> }/> - <Route path="login" view=move || view! { <Login action=login/> }/> + <Route path="" view={Todos} /> + <Route path="signup" view={move || view! { <Signup action={signup} /> }} /> + <Route path="login" view={move || view! { <Login action={login} /> }} /> <Route path="settings" - view=move || { + view={move || { view! { <h1>"Settings"</h1> - <Logout action=logout/> + <Logout action={logout} /> } - } + }} /> </Routes> @@ -213,14 +213,14 @@ pub fn Todos() -> impl IntoView { view! { <div> - <MultiActionForm action=add_todo> - <label>"Add a Todo" <input type="text" name="title"/></label> - <input type="submit" value="Add"/> + <MultiActionForm action={add_todo}> + <label>"Add a Todo" <input type="text" name="title" /></label> + <input type="submit" value="Add" /> </MultiActionForm> - <Transition fallback=move || view! { <p>"Loading..."</p> }> - <ErrorBoundary fallback=|errors| { - view! { <ErrorTemplate errors=errors/> } - }> + <Transition fallback={move || view! { <p>"Loading..."</p> }}> + <ErrorBoundary fallback={|errors| { + view! { <ErrorTemplate errors={errors} /> } + }}> {move || { let existing_todos = { move || { @@ -244,9 +244,9 @@ pub fn Todos() -> impl IntoView { <li> {todo.title} ": Created at " {todo.created_at} " by " {todo.user.unwrap_or_default().username} - <ActionForm action=delete_todo> - <input type="hidden" name="id" value=todo.id/> - <input type="submit" value="X"/> + <ActionForm action={delete_todo}> + <input type="hidden" name="id" value={todo.id} /> + <input type="submit" value="X" /> </ActionForm> </li> } @@ -286,7 +286,7 @@ pub fn Login( action: Action<Login, Result<(), ServerFnError>>, ) -> impl IntoView { view! { - <ActionForm action=action> + <ActionForm action={action}> <h1>"Log In"</h1> <label> "User ID:" @@ -298,17 +298,17 @@ pub fn Login( class="auth-input" /> </label> - <br/> + <br /> <label> "Password:" - <input type="password" placeholder="Password" name="password" class="auth-input"/> + <input type="password" placeholder="Password" name="password" class="auth-input" /> </label> - <br/> + <br /> <label> - <input type="checkbox" name="remember" class="auth-input"/> + <input type="checkbox" name="remember" class="auth-input" /> "Remember me?" </label> - <br/> + <br /> <button type="submit" class="button"> "Log In" </button> @@ -321,7 +321,7 @@ pub fn Signup( action: Action<Signup, Result<(), ServerFnError>>, ) -> impl IntoView { view! { - <ActionForm action=action> + <ActionForm action={action}> <h1>"Sign Up"</h1> <label> "User ID:" @@ -333,12 +333,12 @@ pub fn Signup( class="auth-input" /> </label> - <br/> + <br /> <label> "Password:" - <input type="password" placeholder="Password" name="password" class="auth-input"/> + <input type="password" placeholder="Password" name="password" class="auth-input" /> </label> - <br/> + <br /> <label> "Confirm Password:" <input @@ -348,12 +348,12 @@ pub fn Signup( class="auth-input" /> </label> - <br/> + <br /> <label> - "Remember me?" <input type="checkbox" name="remember" class="auth-input"/> + "Remember me?" <input type="checkbox" name="remember" class="auth-input" /> </label> - <br/> + <br /> <button type="submit" class="button"> "Sign Up" </button> @@ -367,7 +367,7 @@ pub fn Logout( ) -> impl IntoView { view! { <div id="loginbox"> - <ActionForm action=action> + <ActionForm action={action}> <button type="submit" class="button"> "Log Out" </button> diff --git a/projects/sitemap_axum/src/app.rs b/projects/sitemap_axum/src/app.rs index 2a7dbbf17f..847936b077 100644 --- a/projects/sitemap_axum/src/app.rs +++ b/projects/sitemap_axum/src/app.rs @@ -9,27 +9,22 @@ pub fn App() -> impl IntoView { provide_meta_context(); view! { - - // injects a stylesheet into the document <head> // id=leptos means cargo-leptos will hot-reload this stylesheet <Stylesheet id="leptos" href="/pkg/sitemap-axum.css"/> // sets the document title - <Title text="Welcome to Leptos"/> + <Title text="Welcome to Leptos" /> // content for this welcome page - <Router fallback=|| { + <Router fallback={|| { let mut outside_errors = Errors::default(); outside_errors.insert_with_default_key(AppError::NotFound); - view! { - <ErrorTemplate outside_errors/> - } - .into_view() - }> + view! { <ErrorTemplate outside_errors /> }.into_view() + }}> <main> <Routes> - <Route path="" view=HomePage/> + <Route path="" view={HomePage} /> </Routes> </main> </Router> @@ -43,6 +38,8 @@ fn HomePage() -> impl IntoView { <h1>"Welcome to Leptos!"</h1> // Typically, you won't route to these files manually - a crawler of sorts will take care of that <a href="http://localhost:3000/sitemap-index.xml">"Generate dynamic sitemap"</a> - <a style="padding-left: 1em;" href="http://localhost:3000/sitemap-static.xml">"Go to static sitemap"</a> + <a style="padding-left: 1em;" href="http://localhost:3000/sitemap-static.xml"> + "Go to static sitemap" + </a> } } diff --git a/projects/sitemap_axum/src/error_template.rs b/projects/sitemap_axum/src/error_template.rs index 1e0508da5c..3d50323307 100644 --- a/projects/sitemap_axum/src/error_template.rs +++ b/projects/sitemap_axum/src/error_template.rs @@ -52,21 +52,21 @@ pub fn ErrorTemplate( } view! { - <h1>{if errors.len() > 1 {"Errors"} else {"Error"}}</h1> + <h1>{if errors.len() > 1 { "Errors" } else { "Error" }}</h1> <For // a function that returns the items we're iterating over; a signal is fine - each= move || {errors.clone().into_iter().enumerate()} + each={move || { errors.clone().into_iter().enumerate() }} // a unique key for each item as a reference - key=|(index, _error)| *index + key={|(index, _error)| *index} // renders each item to a view - children=move |error| { + children={move |error| { let error_string = error.1.to_string(); - let error_code= error.1.status_code(); + let error_code = error.1.status_code(); view! { <h2>{error_code.to_string()}</h2> <p>"Error: " {error_string}</p> } - } + }} /> } } diff --git a/projects/sso_auth_axum/src/error_template.rs b/projects/sso_auth_axum/src/error_template.rs index f9b32330d0..6f297c7616 100644 --- a/projects/sso_auth_axum/src/error_template.rs +++ b/projects/sso_auth_axum/src/error_template.rs @@ -4,20 +4,18 @@ use leptos::{view, Errors, For, IntoView, RwSignal, SignalGet, View}; // here than just displaying them pub fn error_template(errors: RwSignal<Errors>) -> View { view! { - <h1>"Errors"</h1> - <For - // a function that returns the items we're iterating over; a signal is fine - each=move || errors.get() - // a unique key for each item as a reference - key=|(key, _)| key.clone() - // renders each item to a view - children= move | (_, error)| { - let error_string = error.to_string(); - view! { - <p>"Error: " {error_string}</p> - } - } - /> + <h1>"Errors"</h1> + <For + // a function that returns the items we're iterating over; a signal is fine + each={move || errors.get()} + // a unique key for each item as a reference + key={|(key, _)| key.clone()} + // renders each item to a view + children={move |(_, error)| { + let error_string = error.to_string(); + view! { <p>"Error: " {error_string}</p> } + }} + /> } .into_view() } diff --git a/projects/sso_auth_axum/src/lib.rs b/projects/sso_auth_axum/src/lib.rs index 96fc134a61..17a4e5d52f 100644 --- a/projects/sso_auth_axum/src/lib.rs +++ b/projects/sso_auth_axum/src/lib.rs @@ -120,21 +120,27 @@ pub fn App() -> impl IntoView { }); view! { - <Stylesheet id="leptos" href="/pkg/sso_auth_axum.css"/> - <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico"/> - <Title text="SSO Auth Axum"/> + <Stylesheet id="leptos" href="/pkg/sso_auth_axum.css" /> + <Link rel="shortcut icon" type_="image/ico" href="/favicon.ico" /> + <Title text="SSO Auth Axum" /> <Router> <main> <Routes> - <Route path="" view=move || { - view!{ - {display_email} - <Show when=move || email.get().is_some() fallback=||view!{<SignIn/>}> - <LogOut/> - </Show> + <Route + path="" + view={move || { + view! { + {display_email} + <Show + when={move || email.get().is_some()} + fallback={|| view! { <SignIn /> }} + > + <LogOut /> + </Show> } - }/> - <Route path="g_auth" view=||view!{<HandleGAuth/>}/> + }} + /> + <Route path="g_auth" view={|| view! { <HandleGAuth /> }} /> </Routes> </main> </Router> diff --git a/projects/sso_auth_axum/src/main.rs b/projects/sso_auth_axum/src/main.rs index 3b7701fb02..9e9fabedce 100644 --- a/projects/sso_auth_axum/src/main.rs +++ b/projects/sso_auth_axum/src/main.rs @@ -50,7 +50,7 @@ pub async fn leptos_routes_handler( provide_context(auth_session.clone()); provide_context(app_state.pool.clone()); }, - move || view! { <sso_auth_axum::App/> }, + move || view! { <sso_auth_axum::App /> }, ); handler(request).await.into_response() diff --git a/projects/sso_auth_axum/src/sign_in_sign_up.rs b/projects/sso_auth_axum/src/sign_in_sign_up.rs index fda2451996..f728029b02 100644 --- a/projects/sso_auth_axum/src/sign_in_sign_up.rs +++ b/projects/sso_auth_axum/src/sign_in_sign_up.rs @@ -54,23 +54,42 @@ pub fn SignIn() -> impl IntoView { }); view! { - <div style=" - display:flex; - flex-direction: column; - justify-content: center; - align-items: center; - "> - <div> {"Sign Up Sign In"} </div> - <button style="display:flex;" on:click=move|_| g_auth.dispatch(GoogleSso{})> - <svg style="width:2rem;" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" xmlns:xlink="http://www.w3.org/1999/xlink" style="display: block;"> - <path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"></path> - <path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"></path> - <path fill="#FBBC05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"></path> - <path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"></path> - <path fill="none" d="M0 0h48v48H0z"></path> - </svg> - <span style="margin-left:0.5rem;">"Sign in with Google"</span> - </button> + <div style=" + display:flex; + flex-direction: column; + justify-content: center; + align-items: center; + "> + <div>{"Sign Up Sign In"}</div> + <button style="display:flex;" on:click={move |_| g_auth.dispatch(GoogleSso {})}> + <svg + style="width:2rem;" + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewBox="0 0 48 48" + xmlns:xlink="http://www.w3.org/1999/xlink" + style="display: block;" + > + <path + fill="#EA4335" + d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z" + ></path> + <path + fill="#4285F4" + d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z" + ></path> + <path + fill="#FBBC05" + d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z" + ></path> + <path + fill="#34A853" + d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z" + ></path> + <path fill="none" d="M0 0h48v48H0z"></path> + </svg> + <span style="margin-left:0.5rem;">"Sign in with Google"</span> + </button> </div> } } @@ -205,7 +224,5 @@ pub async fn logout() -> Result<(), ServerFnError> { #[component] pub fn LogOut() -> impl IntoView { let log_out = create_server_action::<Logout>(); - view! { - <button on:click=move|_|log_out.dispatch(Logout{})>{"log out"}</button> - } + view! { <button on:click={move |_| log_out.dispatch(Logout {})}>{"log out"}</button> } } diff --git a/projects/tauri-from-scratch/src-orig/src/fallback.rs b/projects/tauri-from-scratch/src-orig/src/fallback.rs index d89836c0d8..1df0fa3ded 100644 --- a/projects/tauri-from-scratch/src-orig/src/fallback.rs +++ b/projects/tauri-from-scratch/src-orig/src/fallback.rs @@ -19,7 +19,7 @@ pub async fn file_and_error_handler( if res.status() == StatusCode::OK { res.into_response() } else { - let handler = leptos_axum::render_app_to_stream(options.to_owned(), move || view! {404}); + let handler = leptos_axum::render_app_to_stream(options.to_owned(), move || view! { 404 }); handler(req).await.into_response() } } diff --git a/projects/tauri-from-scratch/src-orig/src/lib.rs b/projects/tauri-from-scratch/src-orig/src/lib.rs index e97d3824fb..914b0d2f36 100644 --- a/projects/tauri-from-scratch/src-orig/src/lib.rs +++ b/projects/tauri-from-scratch/src-orig/src/lib.rs @@ -20,14 +20,11 @@ pub fn App() -> impl IntoView { } } }); - view! {<button - on:click=move |_| { - action.dispatch(HelloWorldServer{}); - } - >"Hello world."</button> - { - move || vals.get() - } + view! { + <button on:click={move |_| { + action.dispatch(HelloWorldServer {}); + }}>"Hello world."</button> + {move || vals.get()} } } cfg_if::cfg_if! { diff --git a/router/src/components.rs b/router/src/components.rs index ca580b2f74..184044088b 100644 --- a/router/src/components.rs +++ b/router/src/components.rs @@ -334,7 +334,7 @@ where match condition() { Some(true) => Either::Left(view()), #[allow(clippy::unit_arg)] - Some(false) => Either::Right(view! { <Redirect path=redirect_path()/> }), + Some(false) => Either::Right(view! { <Redirect path={redirect_path()} /> }), None => Either::Right(()), } }} @@ -379,7 +379,7 @@ where match condition() { Some(true) => Either::Left(view()), #[allow(clippy::unit_arg)] - Some(false) => Either::Right(view! { <Redirect path=redirect_path()/> }), + Some(false) => Either::Right(view! { <Redirect path={redirect_path()} /> }), None => Either::Right(()), } }} @@ -520,7 +520,7 @@ pub fn RoutingProgress( )); view! { - <Show when=move || is_showing.get() fallback=|| ()> + <Show when={move || is_showing.get()} fallback={|| ()}> <progress min="0" max="100" value={move || progress.get()}></progress> </Show> } From 3bd8bcbbe248a46c8f8b4dbb58d7fef395293fe5 Mon Sep 17 00:00:00 2001 From: blorbb <88137137+blorbb@users.noreply.github.com> Date: Sat, 3 Aug 2024 22:20:56 +1000 Subject: [PATCH 3/8] add braces to example attribute values --- leptos/src/animated_show.rs | 6 +++--- leptos/src/await_.rs | 10 +++++----- leptos/src/callback.rs | 2 +- leptos/src/error_boundary.rs | 4 ++-- leptos/src/for_loop.rs | 8 ++++---- leptos/src/form.rs | 2 +- leptos/src/lib.rs | 2 +- leptos/src/nonce.rs | 12 ++++++------ leptos/src/suspense_component.rs | 2 +- leptos/src/transition.rs | 2 +- leptos_dom/src/helpers.rs | 2 +- leptos_macro/src/lib.rs | 28 ++++++++++++++-------------- meta/src/body.rs | 2 +- router/src/hooks.rs | 6 +++--- 14 files changed, 44 insertions(+), 44 deletions(-) diff --git a/leptos/src/animated_show.rs b/leptos/src/animated_show.rs index dfb003fc1e..bb1936a770 100644 --- a/leptos/src/animated_show.rs +++ b/leptos/src/animated_show.rs @@ -24,8 +24,8 @@ use leptos_reactive::{ /// view! { /// <div /// class="hover-me" -/// on:mouseenter=move |_| show.set(true) -/// on:mouseleave=move |_| show.set(false) +/// on:mouseenter={move |_| show.set(true)} +/// on:mouseleave={move |_| show.set(false)} /// > /// "Hover Me" /// </div> @@ -34,7 +34,7 @@ use leptos_reactive::{ /// when=show /// show_class="fade-in-1000" /// hide_class="fade-out-1000" -/// hide_delay=Duration::from_millis(1000) +/// hide_delay={Duration::from_millis(1000)} /// > /// <div class="here-i-am"> /// "Here I Am!" diff --git a/leptos/src/await_.rs b/leptos/src/await_.rs index 1b80ebfb31..3e3ca03733 100644 --- a/leptos/src/await_.rs +++ b/leptos/src/await_.rs @@ -27,7 +27,7 @@ use leptos_reactive::{ /// /// view! { /// <Await -/// future=|| fetch_monkeys(3) +/// future={|| fetch_monkeys(3)} /// let:data /// > /// <p>{*data} " little monkeys, jumping on the bed."</p> @@ -66,7 +66,7 @@ pub fn Await<T, Fut, FF, VF, V>( /// # } /// view! { /// <Await - /// future=|| fetch_monkeys(3) + /// future={|| fetch_monkeys(3)} /// let:data /// > /// <p>{*data} " little monkeys, jumping on the bed."</p> @@ -86,10 +86,10 @@ pub fn Await<T, Fut, FF, VF, V>( /// # } /// view! { /// <Await - /// future=|| fetch_monkeys(3) - /// children=|data| view! { + /// future={|| fetch_monkeys(3)} + /// children={|data| view! { /// <p>{*data} " little monkeys, jumping on the bed."</p> - /// } + /// }} /// /> /// } /// # ; diff --git a/leptos/src/callback.rs b/leptos/src/callback.rs index 6a4973ab5d..31a9e103df 100644 --- a/leptos/src/callback.rs +++ b/leptos/src/callback.rs @@ -163,7 +163,7 @@ impl<In, Out> Fn<(In,)> for UnsyncCallback<In, Out> { /// /// fn test() -> impl IntoView { /// view! { -/// <MyComponent render_number=move |x: i32| x.to_string()/> +/// <MyComponent render_number={move |x: i32| x.to_string()} /> /// } /// } /// ``` diff --git a/leptos/src/error_boundary.rs b/leptos/src/error_boundary.rs index 6445445e1d..0bca746aab 100644 --- a/leptos/src/error_boundary.rs +++ b/leptos/src/error_boundary.rs @@ -36,9 +36,9 @@ use throw_error::{Error, ErrorHook, ErrorId}; /// move |ev| set_value.set(event_target_value(&ev).parse::<i32>()); /// /// view! { -/// <input type="text" on:input=on_input/> +/// <input type="text" on:input={on_input}/> /// <ErrorBoundary -/// fallback=move |_| view! { <p class="error">"Enter a valid number."</p>} +/// fallback={move |_| view! { <p class="error">"Enter a valid number."</p>}} /// > /// <p>"Value is: " {move || value.get()}</p> /// </ErrorBoundary> diff --git a/leptos/src/for_loop.rs b/leptos/src/for_loop.rs index 34d8b47c03..e5c3d2f94e 100644 --- a/leptos/src/for_loop.rs +++ b/leptos/src/for_loop.rs @@ -26,15 +26,15 @@ use tachys::{reactive_graph::OwnedView, view::keyed::keyed}; /// <div> /// <For /// // a function that returns the items we're iterating over; a signal is fine -/// each=move || counters.get() +/// each={move || counters.get()} /// // a unique key for each item -/// key=|counter| counter.id +/// key={|counter| counter.id} /// // renders each item to a view -/// children=move |counter: Counter| { +/// children={move |counter: Counter| { /// view! { /// <button>"Value: " {move || counter.count.get()}</button> /// } -/// } +/// }} /// /> /// </div> /// } diff --git a/leptos/src/form.rs b/leptos/src/form.rs index 59f6f1349e..7523e432fe 100644 --- a/leptos/src/form.rs +++ b/leptos/src/form.rs @@ -48,7 +48,7 @@ use web_sys::{ /// let submit = ServerAction::<VeryImportantFn>::new(); /// /// view! { -/// <ActionForm action=submit> +/// <ActionForm action={submit}> /// <input type="text" name="hefty_arg[first_name]" value="leptos"/> /// <input /// type="text" diff --git a/leptos/src/lib.rs b/leptos/src/lib.rs index 2aad22f8ad..91f6aa0303 100644 --- a/leptos/src/lib.rs +++ b/leptos/src/lib.rs @@ -423,7 +423,7 @@ extern crate self as leptos; /// #[prop(optional, into)] class: Option<AttributeValue>, /// ) -> impl IntoView { /// view! { -/// <h1 class=class>{text}</h1> +/// <h1 class={class}>{text}</h1> /// } /// } /// ``` diff --git a/leptos/src/nonce.rs b/leptos/src/nonce.rs index 48b8e02b73..50beb4ce57 100644 --- a/leptos/src/nonce.rs +++ b/leptos/src/nonce.rs @@ -28,7 +28,7 @@ use tachys::{html::attribute::AttributeValue, renderer::Renderer}; /// // use `leptos_meta` to insert a <meta> tag with the CSP /// <Meta /// http_equiv="Content-Security-Policy" -/// content=move || { +/// content={move || { /// // this will insert the CSP with nonce on the server, be empty on client /// use_nonce() /// .map(|nonce| { @@ -38,10 +38,10 @@ use tachys::{html::attribute::AttributeValue, renderer::Renderer}; /// ) /// }) /// .unwrap_or_default() -/// } +/// }} /// /> /// // manually insert nonce during SSR on inline script -/// <script nonce=use_nonce()>"console.log('Hello, world!');"</script> +/// <script nonce={use_nonce()}>"console.log('Hello, world!');"</script> /// // leptos_meta <Style/> and <Script/> automatically insert the nonce /// <Style>"body { color: blue; }"</Style> /// <p>"Test"</p> @@ -128,7 +128,7 @@ where /// // use `leptos_meta` to insert a <meta> tag with the CSP /// <Meta /// http_equiv="Content-Security-Policy" -/// content=move || { +/// content={move || { /// // this will insert the CSP with nonce on the server, be empty on client /// use_nonce() /// .map(|nonce| { @@ -138,10 +138,10 @@ where /// ) /// }) /// .unwrap_or_default() -/// } +/// }} /// /> /// // manually insert nonce during SSR on inline script -/// <script nonce=use_nonce()>"console.log('Hello, world!');"</script> +/// <script nonce={use_nonce()}>"console.log('Hello, world!');"</script> /// // leptos_meta <Style/> and <Script/> automatically insert the nonce /// <Style>"body { color: blue; }"</Style> /// <p>"Test"</p> diff --git a/leptos/src/suspense_component.rs b/leptos/src/suspense_component.rs index 69ade92636..8923f0dd9e 100644 --- a/leptos/src/suspense_component.rs +++ b/leptos/src/suspense_component.rs @@ -55,7 +55,7 @@ use throw_error::ErrorHookFuture; /// /// view! { /// <div> -/// <Suspense fallback=move || view! { <p>"Loading (Suspense Fallback)..."</p> }> +/// <Suspense fallback={move || view! { <p>"Loading (Suspense Fallback)..."</p> }}> /// // you can access a resource synchronously /// {move || { /// cats.get().map(|data| { diff --git a/leptos/src/transition.rs b/leptos/src/transition.rs index 733760824f..22e6d47686 100644 --- a/leptos/src/transition.rs +++ b/leptos/src/transition.rs @@ -39,7 +39,7 @@ use tachys::reactive_graph::OwnedView; /// /// view! { /// <div> -/// <Transition fallback=move || view! { <p>"Loading (Suspense Fallback)..."</p> }> +/// <Transition fallback={move || view! { <p>"Loading (Suspense Fallback)..."</p> }}> /// // you can access a resource synchronously /// {move || { /// cats.get().map(|data| { diff --git a/leptos_dom/src/helpers.rs b/leptos_dom/src/helpers.rs index 8936d95a2b..a1782d1d7d 100644 --- a/leptos_dom/src/helpers.rs +++ b/leptos_dom/src/helpers.rs @@ -328,7 +328,7 @@ pub fn set_timeout_with_handle( /// }); /// /// view! { -/// <button on:click=on_click>"Click me"</button> +/// <button on:click={on_click}>"Click me"</button> /// } /// } /// ``` diff --git a/leptos_macro/src/lib.rs b/leptos_macro/src/lib.rs index 28ece8ec9f..281f4a494d 100644 --- a/leptos_macro/src/lib.rs +++ b/leptos_macro/src/lib.rs @@ -96,9 +96,9 @@ mod slot; /// # use leptos::prelude::*; /// # fn test() -> impl IntoView { /// view! { -/// <button on:click=|ev| { +/// <button on:click={|ev| { /// log::debug!("click event: {ev:#?}"); -/// }> +/// }}> /// "Click me" /// </button> /// } @@ -119,7 +119,7 @@ mod slot; /// name="user_name" /// value={move || name.get()} // this only sets the default value! /// prop:value={move || name.get()} // here's how you update values. Sorry, I didn’t invent the DOM. -/// on:click=move |ev| set_name.set(event_target_value(&ev)) // `event_target_value` is a useful little Leptos helper +/// on:click={move |ev| set_name.set(event_target_value(&ev))} // `event_target_value` is a useful little Leptos helper /// /> /// } /// # } @@ -153,7 +153,7 @@ mod slot; /// # } /// ``` /// -/// However, you can pass arbitrary class names using the syntax `class=("name", value)`. +/// However, you can pass arbitrary class names using the syntax `class={("name", value)}`. /// ```rust /// # use leptos::prelude::*; /// # fn test() -> impl IntoView { @@ -161,7 +161,7 @@ mod slot; /// // this allows you to use CSS frameworks that include complex class names /// view! { /// <div -/// class=("is-[this_-_really]-necessary-42", move || count.get() < 3) +/// class={("is-[this_-_really]-necessary-42", move || count.get() < 3)} /// > /// "Now you see me, now you don’t." /// </div> @@ -169,7 +169,7 @@ mod slot; /// # } /// ``` /// -/// 8. Individual styles can also be set with `style:` or `style=("property-name", value)` syntax. +/// 8. Individual styles can also be set with `style:` or `style={("property-name", value)}` syntax. /// ```rust /// # use leptos::prelude::*; /// @@ -179,9 +179,9 @@ mod slot; /// view! { /// <div /// style="position: absolute" -/// style:left=move || format!("{}px", x.get()) -/// style:top=move || format!("{}px", y.get()) -/// style=("background-color", move || format!("rgb({}, {}, 100)", x.get(), y.get())) +/// style:left={move || format!("{}px", x.get())} +/// style:top={move || format!("{}px", y.get())} +/// style={("background-color", move || format!("rgb({}, {}, 100)", x.get(), y.get()))} /// > /// "Moves when coordinates change" /// </div> @@ -199,7 +199,7 @@ mod slot; /// /// let (value, set_value) = signal(0); /// let my_input = NodeRef::<Input>::new(); -/// view! { <input type="text" node_ref=my_input/> } +/// view! { <input type="text" node_ref={my_input}/> } /// // `my_input` now contains an `Element` that we can use anywhere /// # ; /// # }; @@ -229,7 +229,7 @@ mod slot; /// # fn test() -> impl IntoView { /// let html = "<p>This HTML will be injected.</p>"; /// view! { -/// <div inner_html=html/> +/// <div inner_html={html}/> /// } /// # } /// ``` @@ -249,10 +249,10 @@ mod slot; /// /// view! { /// <div> -/// <button on:click=clear>"Clear"</button> -/// <button on:click=decrement>"-1"</button> +/// <button on:click={clear}>"Clear"</button> +/// <button on:click={decrement}>"-1"</button> /// <span>"Value: " {move || value.get().to_string()} "!"</span> -/// <button on:click=increment>"+1"</button> +/// <button on:click={increment}>"+1"</button> /// </div> /// } /// } diff --git a/meta/src/body.rs b/meta/src/body.rs index 263fc995ff..5f8f9ef947 100644 --- a/meta/src/body.rs +++ b/meta/src/body.rs @@ -40,7 +40,7 @@ use leptos::{ /// /// view! { /// <main> -/// <Body {..} class=body_class id="body"/> +/// <Body {..} class={body_class} id="body"/> /// </main> /// } /// } diff --git a/router/src/hooks.rs b/router/src/hooks.rs index eed0892777..933650c6ce 100644 --- a/router/src/hooks.rs +++ b/router/src/hooks.rs @@ -67,10 +67,10 @@ where /// /// view! { /// <div> -/// <button on:click=clear>"Clear"</button> -/// <button on:click=decrement>"-1"</button> +/// <button on:click={clear}>"Clear"</button> +/// <button on:click={decrement}>"-1"</button> /// <span>"Value: " {move || count.get().unwrap_or(0)} "!"</span> -/// <button on:click=increment>"+1"</button> +/// <button on:click={increment}>"+1"</button> /// </div> /// } /// } From 78f2864c373745c625de15dad4b5336361a33b30 Mon Sep 17 00:00:00 2001 From: blorbb <88137137+blorbb@users.noreply.github.com> Date: Mon, 5 Aug 2024 09:29:01 +1000 Subject: [PATCH 4/8] fmt + clippy --- leptos_macro/src/view/component_builder.rs | 5 +++-- leptos_macro/src/view/mod.rs | 2 +- leptos_macro/src/view/slot_helper.rs | 8 +++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/leptos_macro/src/view/component_builder.rs b/leptos_macro/src/view/component_builder.rs index ca052602fe..606fe8e8be 100644 --- a/leptos_macro/src/view/component_builder.rs +++ b/leptos_macro/src/view/component_builder.rs @@ -3,7 +3,8 @@ use crate::view::attribute_absolute; use proc_macro2::{Ident, TokenStream, TokenTree}; use quote::{format_ident, quote, quote_spanned}; use rstml::node::{ - CustomNode, KeyedAttributeValue, NodeAttribute, NodeBlock, NodeElement, NodeName + CustomNode, KeyedAttributeValue, NodeAttribute, NodeBlock, NodeElement, + NodeName, }; use std::collections::HashMap; use syn::{spanned::Spanned, Expr, ExprPath, ExprRange, RangeLimits, Stmt}; @@ -155,7 +156,7 @@ pub(crate) fn component_to_tokens( } })) } else if let NodeAttribute::Attribute(node) = attr { - attribute_absolute(&node, idx >= spread_marker) + attribute_absolute(node, idx >= spread_marker) } else { None } diff --git a/leptos_macro/src/view/mod.rs b/leptos_macro/src/view/mod.rs index 6b8197054e..96998b0c42 100644 --- a/leptos_macro/src/view/mod.rs +++ b/leptos_macro/src/view/mod.rs @@ -245,7 +245,7 @@ pub(crate) fn element_to_tokens( } } NodeAttribute::Attribute(node) => { - if let Some(content) = attribute_absolute(&node, true) { + if let Some(content) = attribute_absolute(node, true) { attributes.push(content); } } diff --git a/leptos_macro/src/view/slot_helper.rs b/leptos_macro/src/view/slot_helper.rs index 823bb081d9..1f63b79b6e 100644 --- a/leptos_macro/src/view/slot_helper.rs +++ b/leptos_macro/src/view/slot_helper.rs @@ -32,7 +32,7 @@ pub(crate) fn slot_to_tokens( let attrs = node.attributes().iter().filter_map(|node| { if let NodeAttribute::Attribute(node) = node { - if is_slot(&node) { + if is_slot(node) { None } else { Some(node) @@ -214,10 +214,12 @@ pub(crate) fn is_slot(node: &KeyedAttribute) -> bool { key == "slot" || key.starts_with("slot:") } -pub(crate) fn get_slot(node: &NodeElement<impl CustomNode>) -> Option<&KeyedAttribute> { +pub(crate) fn get_slot( + node: &NodeElement<impl CustomNode>, +) -> Option<&KeyedAttribute> { node.attributes().iter().find_map(|node| { if let NodeAttribute::Attribute(node) = node { - if is_slot(&node) { + if is_slot(node) { Some(node) } else { None From 51a6cd9a40bfed4526ed25adfeb63cf5f3059490 Mon Sep 17 00:00:00 2001 From: blorbb <88137137+blorbb@users.noreply.github.com> Date: Mon, 5 Aug 2024 09:46:53 +1000 Subject: [PATCH 5/8] fix unformatted trailing whitespace --- examples/action-form-error-handling/src/main.rs | 2 +- examples/counter_isomorphic/src/main.rs | 2 +- examples/errors_axum/src/landing.rs | 2 +- examples/hackernews/src/main.rs | 2 +- examples/hackernews_axum/src/lib.rs | 2 +- examples/hackernews_islands_axum/src/lib.rs | 2 +- examples/hackernews_js_fetch/src/lib.rs | 2 +- examples/islands/src/app.rs | 2 +- examples/islands_router/src/app.rs | 2 +- examples/server_fns_axum/src/app.rs | 2 +- examples/ssr_modes/src/main.rs | 2 +- examples/ssr_modes_axum/src/app.rs | 2 +- examples/suspense_tests/src/main.rs | 2 +- examples/tailwind_actix/src/main.rs | 2 +- examples/tailwind_axum/src/app.rs | 2 +- examples/todo_app_sqlite/src/main.rs | 2 +- examples/todo_app_sqlite_axum/src/todo.rs | 2 +- examples/todo_app_sqlite_csr/src/fallback.rs | 2 +- examples/todo_app_sqlite_csr/src/todo.rs | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/examples/action-form-error-handling/src/main.rs b/examples/action-form-error-handling/src/main.rs index da7f775fcb..5ea0b51d58 100644 --- a/examples/action-form-error-handling/src/main.rs +++ b/examples/action-form-error-handling/src/main.rs @@ -27,7 +27,7 @@ async fn main() -> std::io::Result<()> { use leptos::prelude::*; view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/counter_isomorphic/src/main.rs b/examples/counter_isomorphic/src/main.rs index b9db5955ba..413939c2f6 100644 --- a/examples/counter_isomorphic/src/main.rs +++ b/examples/counter_isomorphic/src/main.rs @@ -46,7 +46,7 @@ async fn main() -> std::io::Result<()> { let leptos_options = leptos_options.clone(); move || { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/errors_axum/src/landing.rs b/examples/errors_axum/src/landing.rs index 88aa5c0b21..76a1a18038 100644 --- a/examples/errors_axum/src/landing.rs +++ b/examples/errors_axum/src/landing.rs @@ -18,7 +18,7 @@ pub async fn cause_internal_server_error() -> Result<(), ServerFnError> { pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/hackernews/src/main.rs b/examples/hackernews/src/main.rs index 3ccfb670ef..da6d4815f5 100644 --- a/examples/hackernews/src/main.rs +++ b/examples/hackernews/src/main.rs @@ -41,7 +41,7 @@ async fn main() -> std::io::Result<()> { use leptos::prelude::*; view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/hackernews_axum/src/lib.rs b/examples/hackernews_axum/src/lib.rs index e02cc60867..5fa898a83d 100644 --- a/examples/hackernews_axum/src/lib.rs +++ b/examples/hackernews_axum/src/lib.rs @@ -11,7 +11,7 @@ use std::time::Duration; pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/hackernews_islands_axum/src/lib.rs b/examples/hackernews_islands_axum/src/lib.rs index 5d708703ee..5eeeb6a0a8 100644 --- a/examples/hackernews_islands_axum/src/lib.rs +++ b/examples/hackernews_islands_axum/src/lib.rs @@ -12,7 +12,7 @@ pub mod fallback; pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/hackernews_js_fetch/src/lib.rs b/examples/hackernews_js_fetch/src/lib.rs index 81707a9806..8740bd458b 100644 --- a/examples/hackernews_js_fetch/src/lib.rs +++ b/examples/hackernews_js_fetch/src/lib.rs @@ -11,7 +11,7 @@ use std::time::Duration; pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/islands/src/app.rs b/examples/islands/src/app.rs index deaa9e8686..7a90d9a13e 100644 --- a/examples/islands/src/app.rs +++ b/examples/islands/src/app.rs @@ -2,7 +2,7 @@ use leptos::prelude::*; pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/islands_router/src/app.rs b/examples/islands_router/src/app.rs index 5e9da42bd3..74d6a0ff81 100644 --- a/examples/islands_router/src/app.rs +++ b/examples/islands_router/src/app.rs @@ -6,7 +6,7 @@ use leptos_router::{ pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/server_fns_axum/src/app.rs b/examples/server_fns_axum/src/app.rs index 30b8cbf9a4..8032506af6 100644 --- a/examples/server_fns_axum/src/app.rs +++ b/examples/server_fns_axum/src/app.rs @@ -23,7 +23,7 @@ use web_sys::{FormData, HtmlFormElement, SubmitEvent}; pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/ssr_modes/src/main.rs b/examples/ssr_modes/src/main.rs index 479b9944d7..79deb73587 100644 --- a/examples/ssr_modes/src/main.rs +++ b/examples/ssr_modes/src/main.rs @@ -24,7 +24,7 @@ async fn main() -> std::io::Result<()> { use leptos::prelude::*; view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/ssr_modes_axum/src/app.rs b/examples/ssr_modes_axum/src/app.rs index d4a5c11b97..9c4c38ded6 100644 --- a/examples/ssr_modes_axum/src/app.rs +++ b/examples/ssr_modes_axum/src/app.rs @@ -15,7 +15,7 @@ use thiserror::Error; pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/suspense_tests/src/main.rs b/examples/suspense_tests/src/main.rs index 7f25304098..2a74c1e214 100644 --- a/examples/suspense_tests/src/main.rs +++ b/examples/suspense_tests/src/main.rs @@ -24,7 +24,7 @@ async fn main() -> std::io::Result<()> { use leptos::prelude::*; view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/tailwind_actix/src/main.rs b/examples/tailwind_actix/src/main.rs index d16cb3967c..1370550ed2 100644 --- a/examples/tailwind_actix/src/main.rs +++ b/examples/tailwind_actix/src/main.rs @@ -25,7 +25,7 @@ async fn main() -> std::io::Result<()> { use leptos::prelude::*; view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/tailwind_axum/src/app.rs b/examples/tailwind_axum/src/app.rs index a66aea8ada..50c8a2e3a0 100644 --- a/examples/tailwind_axum/src/app.rs +++ b/examples/tailwind_axum/src/app.rs @@ -7,7 +7,7 @@ use leptos_router::{ pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/todo_app_sqlite/src/main.rs b/examples/todo_app_sqlite/src/main.rs index 271f082f36..9b148d9d26 100644 --- a/examples/todo_app_sqlite/src/main.rs +++ b/examples/todo_app_sqlite/src/main.rs @@ -42,7 +42,7 @@ async fn main() -> std::io::Result<()> { use leptos::prelude::*; view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/todo_app_sqlite_axum/src/todo.rs b/examples/todo_app_sqlite_axum/src/todo.rs index 0ac94185b4..a4ef9c163a 100644 --- a/examples/todo_app_sqlite_axum/src/todo.rs +++ b/examples/todo_app_sqlite_axum/src/todo.rs @@ -6,7 +6,7 @@ use server_fn::ServerFnError; pub fn shell(options: LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/todo_app_sqlite_csr/src/fallback.rs b/examples/todo_app_sqlite_csr/src/fallback.rs index b1b7032742..1941ff8e47 100644 --- a/examples/todo_app_sqlite_csr/src/fallback.rs +++ b/examples/todo_app_sqlite_csr/src/fallback.rs @@ -23,7 +23,7 @@ pub async fn file_or_index_handler( res.into_response() } else { Html(view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/examples/todo_app_sqlite_csr/src/todo.rs b/examples/todo_app_sqlite_csr/src/todo.rs index f93f3a48ec..445a0fe265 100644 --- a/examples/todo_app_sqlite_csr/src/todo.rs +++ b/examples/todo_app_sqlite_csr/src/todo.rs @@ -6,7 +6,7 @@ use server_fn::ServerFnError; pub fn shell(leptos_options: &LeptosOptions) -> impl IntoView { view! { - <!DOCTYPE html> + <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> From 3038ec67590b13fbbf5bbc2d72ce560e42b85017 Mon Sep 17 00:00:00 2001 From: blorbb <88137137+blorbb@users.noreply.github.com> Date: Mon, 5 Aug 2024 09:47:32 +1000 Subject: [PATCH 6/8] fix doc test missing braces --- leptos/src/lib.rs | 6 +++--- leptos_macro/src/lib.rs | 4 ++-- meta/src/lib.rs | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/leptos/src/lib.rs b/leptos/src/lib.rs index 91f6aa0303..7d9dca73b2 100644 --- a/leptos/src/lib.rs +++ b/leptos/src/lib.rs @@ -114,10 +114,10 @@ //! view! { //! //! <div> -//! <button on:click=clear>"Clear"</button> -//! <button on:click=decrement>"-1"</button> +//! <button on:click={clear}>"Clear"</button> +//! <button on:click={decrement}>"-1"</button> //! <span>"Value: " {value} "!"</span> -//! <button on:click=increment>"+1"</button> +//! <button on:click={increment}>"+1"</button> //! </div> //! } //! } diff --git a/leptos_macro/src/lib.rs b/leptos_macro/src/lib.rs index 281f4a494d..7d597cbf47 100644 --- a/leptos_macro/src/lib.rs +++ b/leptos_macro/src/lib.rs @@ -648,7 +648,7 @@ fn component_macro(s: TokenStream, island: bool) -> TokenStream { /// fn App() -> impl IntoView { /// view! { /// <ComponentWithSlot> -/// <SlotWithChildren slot:slot on:click=move |_| {}> +/// <SlotWithChildren slot:slot on:click={|_| {}}> /// <h1>"Hello, World!"</h1> /// </SlotWithChildren> /// </ComponentWithSlot> @@ -675,7 +675,7 @@ fn component_macro(s: TokenStream, island: bool) -> TokenStream { /// view! { /// <ComponentWithSlot> /// <SlotWithChildren slot:slot> -/// <div on:click=move |_| {}> +/// <div on:click={|_| {}}> /// <h1>"Hello, World!"</h1> /// </div> /// </SlotWithChildren> diff --git a/meta/src/lib.rs b/meta/src/lib.rs index d0f25d3d79..666a926405 100644 --- a/meta/src/lib.rs +++ b/meta/src/lib.rs @@ -24,14 +24,14 @@ //! view! { //! <Title //! // reactively sets document.title when `name` changes -//! text=move || name.get() +//! text={move || name.get()} //! // applies the `formatter` function to the `text` value -//! formatter=|text| format!("“{text}” is your name") +//! formatter={|text| format!("“{text}” is your name")} //! /> //! <main> //! <input -//! prop:value=move || name.get() -//! on:input=move |ev| set_name.set(event_target_value(&ev)) +//! prop:value={move || name.get()} +//! on:input={move |ev| set_name.set(event_target_value(&ev))} //! /> //! </main> //! } From b721f4865ad4dffe90009edcc52e9abd3be46027 Mon Sep 17 00:00:00 2001 From: blorbb <88137137+blorbb@users.noreply.github.com> Date: Mon, 5 Aug 2024 10:36:28 +1000 Subject: [PATCH 7/8] format example --- examples/spread/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/spread/src/lib.rs b/examples/spread/src/lib.rs index 5fdc12a000..c29251fbb0 100644 --- a/examples/spread/src/lib.rs +++ b/examples/spread/src/lib.rs @@ -20,7 +20,8 @@ pub fn SpreadingExample() -> impl IntoView { let partial_attrs = view! { <{..} id="snood" class="baz" data-foo="bar" /> }; let partial_event_handlers = view! { <{..} on:click={move |_| alert("partial_event_handlers clicked")} /> }; - let spread_onto_component = view! { <{..} aria-label="a component with attribute spreading" /> }; + let spread_onto_component = + view! { <{..} aria-label="a component with attribute spreading" /> }; /* with the correct imports, you can use a tuple/builder syntax as well let attrs_only = class("foo"); From c4553d6ee628d5535d74a32f7d65bd26b2ff185a Mon Sep 17 00:00:00 2001 From: Greg Johnston <greg.johnston@gmail.com> Date: Wed, 14 Aug 2024 08:02:04 -0400 Subject: [PATCH 8/8] cargo fmt --- leptos_macro/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leptos_macro/src/lib.rs b/leptos_macro/src/lib.rs index 9d74f2c716..68b43da895 100644 --- a/leptos_macro/src/lib.rs +++ b/leptos_macro/src/lib.rs @@ -308,7 +308,7 @@ pub fn view(tokens: TokenStream) -> TokenStream { global_class.as_ref(), normalized_call_site(proc_macro::Span::call_site()), ); - + // The allow lint needs to be put here instead of at the expansion of // view::attribute_value(). Adding this next to the expanded expression // seems to break rust-analyzer, but it works when the allow is put here.