diff --git a/Cargo.toml b/Cargo.toml index ddba0fe060..9e8b73ceb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,22 +26,22 @@ members = [ exclude = ["benchmarks", "examples"] [workspace.package] -version = "0.5.2" +version = "0.5.3" [workspace.dependencies] -leptos = { path = "./leptos", version = "0.5.2" } -leptos_dom = { path = "./leptos_dom", version = "0.5.2" } -leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.5.2" } -leptos_macro = { path = "./leptos_macro", version = "0.5.2" } -leptos_reactive = { path = "./leptos_reactive", version = "0.5.2" } -leptos_server = { path = "./leptos_server", version = "0.5.2" } -server_fn = { path = "./server_fn", version = "0.5.2" } -server_fn_macro = { path = "./server_fn_macro", version = "0.5.2" } -server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", version = "0.5.2" } -leptos_config = { path = "./leptos_config", version = "0.5.2" } -leptos_router = { path = "./router", version = "0.5.2" } -leptos_meta = { path = "./meta", version = "0.5.2" } -leptos_integration_utils = { path = "./integrations/utils", version = "0.5.2" } +leptos = { path = "./leptos", version = "0.5.3" } +leptos_dom = { path = "./leptos_dom", version = "0.5.3" } +leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.5.3" } +leptos_macro = { path = "./leptos_macro", version = "0.5.3" } +leptos_reactive = { path = "./leptos_reactive", version = "0.5.3" } +leptos_server = { path = "./leptos_server", version = "0.5.3" } +server_fn = { path = "./server_fn", version = "0.5.3" } +server_fn_macro = { path = "./server_fn_macro", version = "0.5.3" } +server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", version = "0.5.3" } +leptos_config = { path = "./leptos_config", version = "0.5.3" } +leptos_router = { path = "./router", version = "0.5.3" } +leptos_meta = { path = "./meta", version = "0.5.3" } +leptos_integration_utils = { path = "./integrations/utils", version = "0.5.3" } [profile.release] codegen-units = 1 diff --git a/examples/animated_show/README.md b/examples/animated_show/README.md index a4cfb65bce..fe966c9ded 100644 --- a/examples/animated_show/README.md +++ b/examples/animated_show/README.md @@ -8,3 +8,7 @@ CSS. ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/examples/counter/README.md b/examples/counter/README.md index 04812db84f..70d6662cec 100644 --- a/examples/counter/README.md +++ b/examples/counter/README.md @@ -5,3 +5,7 @@ This example creates a simple counter in a client side rendered app with Rust an ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/examples/counter_isomorphic/README.md b/examples/counter_isomorphic/README.md index 26c7a0c86a..1a196bcd44 100644 --- a/examples/counter_isomorphic/README.md +++ b/examples/counter_isomorphic/README.md @@ -5,3 +5,7 @@ This example demonstrates how to use a function isomorphically, to run a server ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `cargo leptos watch` to run this example. diff --git a/examples/counter_url_query/README.md b/examples/counter_url_query/README.md index c62839087e..031d27bb73 100644 --- a/examples/counter_url_query/README.md +++ b/examples/counter_url_query/README.md @@ -5,3 +5,7 @@ This example creates a simple counter whose state is persisted and synced in the ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/examples/counter_without_macros/README.md b/examples/counter_without_macros/README.md index 2ea983cff3..f37c0259bd 100644 --- a/examples/counter_without_macros/README.md +++ b/examples/counter_without_macros/README.md @@ -5,3 +5,7 @@ This example is the same like the `counter` but it's written without using macro ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/examples/counters/README.md b/examples/counters/README.md index 35305e4320..bfd9d00b24 100644 --- a/examples/counters/README.md +++ b/examples/counters/README.md @@ -5,3 +5,7 @@ This example showcases a basic leptos app with many counters. It is a good examp ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/examples/counters_stable/README.md b/examples/counters_stable/README.md index a015cb6db4..f009121d87 100644 --- a/examples/counters_stable/README.md +++ b/examples/counters_stable/README.md @@ -5,3 +5,7 @@ This example showcases a basic Leptos app with many counters. It is a good examp ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/examples/directives/README.md b/examples/directives/README.md index 9ad496184f..b7906beaf2 100644 --- a/examples/directives/README.md +++ b/examples/directives/README.md @@ -1,7 +1,11 @@ # Leptos Directives Example -This example showcases a basic leptos app that shows how to write and use directives. +This example showcases a basic leptos app that shows how to write and use directives. ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/examples/error_boundary/README.md b/examples/error_boundary/README.md index 10e62be952..eda9fe563c 100644 --- a/examples/error_boundary/README.md +++ b/examples/error_boundary/README.md @@ -9,3 +9,7 @@ See the [Examples README](../README.md) for setup and run instructions. ## Testing This project is configured to run start and stop of processes for integration tests wihtout the use of Cargo Leptos or Node. + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/examples/fetch/README.md b/examples/fetch/README.md index dd43ccba20..85e920b580 100644 --- a/examples/fetch/README.md +++ b/examples/fetch/README.md @@ -4,4 +4,8 @@ This example shows how to fetch data from the client in WebAssembly. ## Getting Started -See the [Examples README](../README.md) for setup and run instructions. \ No newline at end of file +See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/examples/hackernews/README.md b/examples/hackernews/README.md index 89d2126914..785389d680 100644 --- a/examples/hackernews/README.md +++ b/examples/hackernews/README.md @@ -5,3 +5,7 @@ This example creates a basic clone of the Hacker News site. It showcases Leptos' ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` or `cargo leptos watch` to run this example. diff --git a/examples/hackernews_axum/README.md b/examples/hackernews_axum/README.md index 1d5a297255..4c64435bee 100644 --- a/examples/hackernews_axum/README.md +++ b/examples/hackernews_axum/README.md @@ -5,3 +5,7 @@ This example creates a basic clone of the Hacker News site. It showcases Leptos' ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` or `cargo leptos watch` to run this example. diff --git a/examples/hackernews_islands_axum/README.md b/examples/hackernews_islands_axum/README.md index 1d5a297255..0d546362ef 100644 --- a/examples/hackernews_islands_axum/README.md +++ b/examples/hackernews_islands_axum/README.md @@ -5,3 +5,7 @@ This example creates a basic clone of the Hacker News site. It showcases Leptos' ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `cargo leptos watch` to run this example. diff --git a/examples/js-framework-benchmark/README.md b/examples/js-framework-benchmark/README.md index a75dc430ef..71c228c0d7 100644 --- a/examples/js-framework-benchmark/README.md +++ b/examples/js-framework-benchmark/README.md @@ -6,3 +6,7 @@ This example creates a large table with randomized entries, it also shows usage ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/examples/parent_child/README.md b/examples/parent_child/README.md index 8bf987f341..ea18c65c3b 100644 --- a/examples/parent_child/README.md +++ b/examples/parent_child/README.md @@ -12,3 +12,7 @@ This example highlights four different ways that child components can communicat ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/examples/portal/README.md b/examples/portal/README.md index 287d85ea33..e487b2f442 100644 --- a/examples/portal/README.md +++ b/examples/portal/README.md @@ -5,3 +5,7 @@ This example showcases a basic leptos app with a portal. ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/examples/router/README.md b/examples/router/README.md index 7450774be9..9a90ed3150 100644 --- a/examples/router/README.md +++ b/examples/router/README.md @@ -5,3 +5,7 @@ This example demonstrates how Leptos’s router works for client side routing. ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/examples/session_auth_axum/README.md b/examples/session_auth_axum/README.md index 02ff829d3c..b0b841c0f9 100644 --- a/examples/session_auth_axum/README.md +++ b/examples/session_auth_axum/README.md @@ -5,3 +5,7 @@ This example creates a basic todo app with an Axum backend that uses Leptos' ser ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `cargo leptos watch` to run this example. diff --git a/examples/slots/README.md b/examples/slots/README.md index c48f10be75..e81eb7bad0 100644 --- a/examples/slots/README.md +++ b/examples/slots/README.md @@ -5,3 +5,7 @@ This example shows how to use Slots in Leptos. ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/examples/ssr_modes/README.md b/examples/ssr_modes/README.md index eb0325b8cd..08efb5b1b9 100644 --- a/examples/ssr_modes/README.md +++ b/examples/ssr_modes/README.md @@ -9,18 +9,25 @@ See the [Examples README](../README.md) for setup and run instructions. ## Server-Side Rendering Modes 1. **Synchronous**: Serve an HTML shell that includes `fallback` for any `Suspense`. Load data on the client, replacing `fallback` once they're loaded. - - *Pros*: App shell appears very quickly: great TTFB (time to first byte). - - *Cons*: Resources load relatively slowly; you need to wait for JS + Wasm to load before even making a request. + + - _Pros_: App shell appears very quickly: great TTFB (time to first byte). + - _Cons_: Resources load relatively slowly; you need to wait for JS + Wasm to load before even making a request. 2. **Out-of-order streaming**: Serve an HTML shell that includes `fallback` for any `Suspense`. Load data on the **server**, streaming it down to the client as it resolves, and streaming down HTML for `Suspense` nodes. - - *Pros*: Combines the best of **synchronous** and **`async`**, with a very fast shell and resources that begin loading on the server. - - *Cons*: Requires JS for suspended fragments to appear in correct order. Weaker meta tag support when it depends on data that's under suspense (has already streamed down ``) + + - _Pros_: Combines the best of **synchronous** and **`async`**, with a very fast shell and resources that begin loading on the server. + - _Cons_: Requires JS for suspended fragments to appear in correct order. Weaker meta tag support when it depends on data that's under suspense (has already streamed down ``) 3. **In-order streaming**: Walk through the tree, returning HTML synchronously as in synchronous rendering and out-of-order streaming until you hit a `Suspense`. At that point, wait for all its data to load, then render it, then the rest of the tree. - - *Pros*: Does not require JS for HTML to appear in correct order. - - *Cons*: Loads the shell more slowly than out-of-order streaming or synchronous rendering because it needs to pause at every `Suspense`. Cannot begin hydration until the entire page has loaded, so earlier pieces - of the page will not be interactive until the suspended chunks have loaded. + + - _Pros_: Does not require JS for HTML to appear in correct order. + - _Cons_: Loads the shell more slowly than out-of-order streaming or synchronous rendering because it needs to pause at every `Suspense`. Cannot begin hydration until the entire page has loaded, so earlier pieces + of the page will not be interactive until the suspended chunks have loaded. 4. **`async`**: Load all resources on the server. Wait until all data are loaded, and render HTML in one sweep. - - *Pros*: Better handling for meta tags (because you know async data even before you render the ``). Faster complete load than **synchronous** because async resources begin loading on server. - - *Cons*: Slower load time/TTFB: you need to wait for all async resources to load before displaying anything on the client. + - _Pros_: Better handling for meta tags (because you know async data even before you render the ``). Faster complete load than **synchronous** because async resources begin loading on server. + - _Cons_: Slower load time/TTFB: you need to wait for all async resources to load before displaying anything on the client. + +## Quick Start + +Run `cargo leptos watch` to run this example. diff --git a/examples/ssr_modes_axum/README.md b/examples/ssr_modes_axum/README.md index c6edb14106..1f96e481b8 100644 --- a/examples/ssr_modes_axum/README.md +++ b/examples/ssr_modes_axum/README.md @@ -9,19 +9,25 @@ See the [Examples README](../README.md) for setup and run instructions. ## Server-Side Rendering Modes 1. **Synchronous**: Serve an HTML shell that includes `fallback` for any `Suspense`. Load data on the client, replacing `fallback` once they're loaded. - - *Pros*: App shell appears very quickly: great TTFB (time to first byte). - - *Cons*: Resources load relatively slowly; you need to wait for JS + Wasm to load before even making a request. + + - _Pros_: App shell appears very quickly: great TTFB (time to first byte). + - _Cons_: Resources load relatively slowly; you need to wait for JS + Wasm to load before even making a request. 2. **Out-of-order streaming**: Serve an HTML shell that includes `fallback` for any `Suspense`. Load data on the **server**, streaming it down to the client as it resolves, and streaming down HTML for `Suspense` nodes. - - *Pros*: Combines the best of **synchronous** and **`async`**, with a very fast shell and resources that begin loading on the server. - - *Cons*: Requires JS for suspended fragments to appear in correct order. Weaker meta tag support when it depends on data that's under suspense (has already streamed down ``) + + - _Pros_: Combines the best of **synchronous** and **`async`**, with a very fast shell and resources that begin loading on the server. + - _Cons_: Requires JS for suspended fragments to appear in correct order. Weaker meta tag support when it depends on data that's under suspense (has already streamed down ``) 3. **In-order streaming**: Walk through the tree, returning HTML synchronously as in synchronous rendering and out-of-order streaming until you hit a `Suspense`. At that point, wait for all its data to load, then render it, then the rest of the tree. - - *Pros*: Does not require JS for HTML to appear in correct order. - - *Cons*: Loads the shell more slowly than out-of-order streaming or synchronous rendering because it needs to pause at every `Suspense`. Cannot begin hydration until the entire page has loaded, so earlier pieces - of the page will not be interactive until the suspended chunks have loaded. + + - _Pros_: Does not require JS for HTML to appear in correct order. + - _Cons_: Loads the shell more slowly than out-of-order streaming or synchronous rendering because it needs to pause at every `Suspense`. Cannot begin hydration until the entire page has loaded, so earlier pieces + of the page will not be interactive until the suspended chunks have loaded. 4. **`async`**: Load all resources on the server. Wait until all data are loaded, and render HTML in one sweep. - - *Pros*: Better handling for meta tags (because you know async data even before you render the ``). Faster complete load than **synchronous** because async resources begin loading on server. - - *Cons*: Slower load time/TTFB: you need to wait for all async resources to load before displaying anything on the client. + - _Pros_: Better handling for meta tags (because you know async data even before you render the ``). Faster complete load than **synchronous** because async resources begin loading on server. + - _Cons_: Slower load time/TTFB: you need to wait for all async resources to load before displaying anything on the client. + +## Quick Start +Run `cargo leptos watch` to run this example. diff --git a/examples/suspense_tests/README.md b/examples/suspense_tests/README.md index ea8188d492..e4c184d0ba 100644 --- a/examples/suspense_tests/README.md +++ b/examples/suspense_tests/README.md @@ -9,3 +9,7 @@ See the [Examples README](../README.md) for setup and run instructions. ## Test Strategy See the [E2E README](./e2e/README.md) to learn about the web testing strategy for this project. + +## Quick Start + +Run `cargo leptos watch` to run this example. diff --git a/examples/tailwind_axum/README.md b/examples/tailwind_axum/README.md index 4dc8bfdd37..ea2f705f7c 100644 --- a/examples/tailwind_axum/README.md +++ b/examples/tailwind_axum/README.md @@ -5,3 +5,7 @@ This is a template demonstrating how to integrate [TailwindCSS](https://tailwind ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `cargo leptos watch` to run this example. diff --git a/examples/tailwind_csr/README.md b/examples/tailwind_csr/README.md index 2a975d1a7b..fa5951fd11 100644 --- a/examples/tailwind_csr/README.md +++ b/examples/tailwind_csr/README.md @@ -51,3 +51,7 @@ Allow vscode Ports forward: 3000, 3001. ### Attribution Many thanks to GreatGreg for putting together this guide. You can find the original, with added details, [here](https://github.com/leptos-rs/leptos/discussions/125). + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/examples/timer/README.md b/examples/timer/README.md index 7bbc25c29a..a5b7b76533 100644 --- a/examples/timer/README.md +++ b/examples/timer/README.md @@ -5,3 +5,7 @@ This example creates a simple timer based on `setInterval` in a client side rend ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/examples/todo_app_sqlite/README.md b/examples/todo_app_sqlite/README.md index aebf885ece..1a2ceade58 100644 --- a/examples/todo_app_sqlite/README.md +++ b/examples/todo_app_sqlite/README.md @@ -13,3 +13,7 @@ See the [E2E README](./e2e/README.md) for more information about the testing str ## Rendering See the [SSR Notes](../SSR_NOTES.md) for more information about Server Side Rendering. + +## Quick Start + +Run `cargo leptos watch` to run this example. diff --git a/examples/todo_app_sqlite_axum/README.md b/examples/todo_app_sqlite_axum/README.md index 48e8ec23da..b4f1639c47 100644 --- a/examples/todo_app_sqlite_axum/README.md +++ b/examples/todo_app_sqlite_axum/README.md @@ -13,3 +13,7 @@ See the [E2E README](./e2e/README.md) for more information about the testing str ## Rendering See the [SSR Notes](../SSR_NOTES.md) for more information about Server Side Rendering. + +## Quick Start + +Run `cargo leptos watch` to run this example. diff --git a/examples/todo_app_sqlite_csr/README.md b/examples/todo_app_sqlite_csr/README.md index 53b7929f13..46a5f753f1 100644 --- a/examples/todo_app_sqlite_csr/README.md +++ b/examples/todo_app_sqlite_csr/README.md @@ -13,3 +13,7 @@ See the [E2E README](./e2e/README.md) for more information about the testing str ## Rendering See the [SSR Notes](../SSR_NOTES.md) for more information about Server Side Rendering. + +## Quick Start + +Run `cargo leptos watch` to run this example. diff --git a/examples/todo_app_sqlite_viz/README.md b/examples/todo_app_sqlite_viz/README.md index ba5c021731..d17a34644d 100644 --- a/examples/todo_app_sqlite_viz/README.md +++ b/examples/todo_app_sqlite_viz/README.md @@ -9,3 +9,7 @@ See the [Examples README](../README.md) for setup and run instructions. ## Rendering See the [SSR Notes](../SSR_NOTES.md) for more information about Server Side Rendering. + +## Quick Start + +Run `cargo leptos watch` to run this example. diff --git a/examples/todomvc/README.md b/examples/todomvc/README.md index 73ff173531..3b3eca5006 100644 --- a/examples/todomvc/README.md +++ b/examples/todomvc/README.md @@ -5,3 +5,7 @@ This is a Leptos implementation of the TodoMVC example common to many frameworks ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `trunk serve --open` to run this example. diff --git a/integrations/axum/src/lib.rs b/integrations/axum/src/lib.rs index f910757ba0..a7d8ec0207 100644 --- a/integrations/axum/src/lib.rs +++ b/integrations/axum/src/lib.rs @@ -7,7 +7,7 @@ //! To run in this environment, you need to disable the default feature set and enable //! the `wasm` feature on `leptos_axum` in your `Cargo.toml`. //! ```toml -//! leptos_axum = { version = "0.5.2", default-features = false, features = ["wasm"] } +//! leptos_axum = { version = "0.5.3", default-features = false, features = ["wasm"] } //! ``` //! //! ## Features diff --git a/leptos_dom/Cargo.toml b/leptos_dom/Cargo.toml index 51a2dce056..1c2a7fd1fa 100644 --- a/leptos_dom/Cargo.toml +++ b/leptos_dom/Cargo.toml @@ -172,7 +172,8 @@ ssr = ["leptos_reactive/ssr"] nightly = ["leptos_reactive/nightly"] nonce = ["dep:base64", "dep:getrandom", "dep:rand"] experimental-islands = ["leptos_reactive/experimental-islands"] +trace-component-props = [] [package.metadata.cargo-all-features] -denylist = ["nightly"] +denylist = ["nightly", "trace-component-props"] skip_feature_sets = [["web", "ssr"]] diff --git a/leptos_dom/src/macro_helpers/mod.rs b/leptos_dom/src/macro_helpers/mod.rs index a032f95bad..1508af9e3c 100644 --- a/leptos_dom/src/macro_helpers/mod.rs +++ b/leptos_dom/src/macro_helpers/mod.rs @@ -2,6 +2,7 @@ mod into_attribute; mod into_class; mod into_property; mod into_style; +#[cfg(feature = "trace-component-props")] #[doc(hidden)] pub mod tracing_property; pub use into_attribute::*; diff --git a/leptos_macro/Cargo.toml b/leptos_macro/Cargo.toml index 0618fc215e..b6987ba718 100644 --- a/leptos_macro/Cargo.toml +++ b/leptos_macro/Cargo.toml @@ -43,7 +43,8 @@ ssr = ["server_fn_macro/ssr"] nightly = ["server_fn_macro/nightly"] tracing = [] experimental-islands = [] +trace-component-props = [] [package.metadata.cargo-all-features] -denylist = ["nightly", "tracing"] +denylist = ["nightly", "tracing", "trace-component-props"] skip_feature_sets = [["csr", "hydrate"], ["hydrate", "csr"], ["hydrate", "ssr"]] diff --git a/leptos_macro/src/component.rs b/leptos_macro/src/component.rs index a713a6da72..5aa779db04 100644 --- a/leptos_macro/src/component.rs +++ b/leptos_macro/src/component.rs @@ -118,8 +118,6 @@ impl ToTokens for Model { let no_props = props.is_empty(); - let mut body = body.to_owned(); - // check for components that end ; if !is_transparent { let ends_semi = @@ -139,7 +137,6 @@ impl ToTokens for Model { } } - body.sig.ident = format_ident!("__{}", body.sig.ident); #[allow(clippy::redundant_clone)] // false positive let body_name = body.sig.ident.clone(); @@ -203,7 +200,7 @@ impl ToTokens for Model { #[cfg(debug_assertions)] let _guard = span.entered(); }, - if no_props { + if no_props || !cfg!(feature = "trace-component-props") { quote! {} } else { quote! { @@ -234,6 +231,7 @@ impl ToTokens for Model { quote! {} }; + let body_name = unmodified_fn_name_from_fn_name(&body_name); let body_expr = if *is_island { quote! { ::leptos::SharedContext::with_hydration(move || { @@ -367,7 +365,6 @@ impl ToTokens for Model { .collect::(); let body = quote! { - #body #destructure_props #tracing_span_expr #component @@ -547,10 +544,10 @@ impl Model { /// used to improve IDEs and rust-analyzer's auto-completion behavior in case /// of a syntax error. pub struct DummyModel { - attrs: Vec, - vis: Visibility, - sig: Signature, - body: TokenStream, + pub attrs: Vec, + pub vis: Visibility, + pub sig: Signature, + pub body: TokenStream, } impl Parse for DummyModel { @@ -588,7 +585,21 @@ impl ToTokens for DummyModel { let mut sig = sig.clone(); sig.inputs.iter_mut().for_each(|arg| { if let FnArg::Typed(ty) = arg { - ty.attrs.clear(); + ty.attrs.retain(|attr| match &attr.meta { + Meta::List(list) => list + .path + .segments + .first() + .map(|n| n.ident != "prop") + .unwrap_or(true), + Meta::NameValue(name_value) => name_value + .path + .segments + .first() + .map(|n| n.ident != "doc") + .unwrap_or(true), + _ => true, + }); } }); sig @@ -1162,3 +1173,7 @@ fn is_valid_into_view_return_type(ty: &ReturnType) -> bool { .iter() .any(|test| ty == test) } + +pub fn unmodified_fn_name_from_fn_name(ident: &Ident) -> Ident { + Ident::new(&format!("__{ident}"), ident.span()) +} diff --git a/leptos_macro/src/lib.rs b/leptos_macro/src/lib.rs index a9cd6e259c..46b7526ebf 100644 --- a/leptos_macro/src/lib.rs +++ b/leptos_macro/src/lib.rs @@ -4,11 +4,12 @@ #[macro_use] extern crate proc_macro_error; +use component::DummyModel; use proc_macro::TokenStream; use proc_macro2::{Span, TokenTree}; use quote::ToTokens; use rstml::{node::KeyedAttribute, parse}; -use syn::parse_macro_input; +use syn::{parse_macro_input, spanned::Spanned, token::Pub, Visibility}; #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub(crate) enum Mode { @@ -31,6 +32,7 @@ impl Default for Mode { mod params; mod view; +use crate::component::unmodified_fn_name_from_fn_name; use view::{client_template::render_template, render_view}; mod component; mod server; @@ -598,21 +600,30 @@ pub fn component(args: proc_macro::TokenStream, s: TokenStream) -> TokenStream { false }; - let parse_result = syn::parse::(s.clone()); + let mut dummy = syn::parse::(s.clone()); + let parse_result = syn::parse::(s); - if let Ok(model) = parse_result { - model - .is_transparent(is_transparent) - .into_token_stream() - .into() + if let (Ok(ref mut unexpanded), Ok(model)) = (&mut dummy, parse_result) { + let expanded = model.is_transparent(is_transparent).into_token_stream(); + unexpanded.sig.ident = + unmodified_fn_name_from_fn_name(&unexpanded.sig.ident); + quote! { + #expanded + #[doc(hidden)] + #[allow(non_snake_case, dead_code, clippy::too_many_arguments)] + #unexpanded + } + } else if let Ok(mut dummy) = dummy { + dummy.sig.ident = unmodified_fn_name_from_fn_name(&dummy.sig.ident); + quote! { + #[doc(hidden)] + #[allow(non_snake_case, dead_code, clippy::too_many_arguments)] + #dummy + } } else { - // When the input syntax is invalid, e.g. while typing, we let - // the dummy model output tokens similar to the input, which improves - // IDEs and rust-analyzer's auto-complete capabilities. - parse_macro_input!(s as component::DummyModel) - .into_token_stream() - .into() + quote! {} } + .into() } /// Defines a component as an interactive island when you are using the @@ -688,28 +699,36 @@ pub fn component(args: proc_macro::TokenStream, s: TokenStream) -> TokenStream { /// ``` #[proc_macro_error::proc_macro_error] #[proc_macro_attribute] -pub fn island(args: proc_macro::TokenStream, s: TokenStream) -> TokenStream { - let is_transparent = if !args.is_empty() { - let transparent = parse_macro_input!(args as syn::Ident); +pub fn island(_args: proc_macro::TokenStream, s: TokenStream) -> TokenStream { + let mut dummy = syn::parse::(s.clone()); + let parse_result = syn::parse::(s); - if transparent != "transparent" { - abort!( - transparent, - "only `transparent` is supported"; - help = "try `#[island(transparent)]` or `#[island]`" - ); + if let (Ok(ref mut unexpanded), Ok(model)) = (&mut dummy, parse_result) { + let expanded = model.is_island().into_token_stream(); + if !matches!(unexpanded.vis, Visibility::Public(_)) { + unexpanded.vis = Visibility::Public(Pub { + span: unexpanded.vis.span(), + }) + } + unexpanded.sig.ident = + unmodified_fn_name_from_fn_name(&unexpanded.sig.ident); + quote! { + #expanded + #[doc(hidden)] + #[allow(non_snake_case, dead_code, clippy::too_many_arguments)] + #unexpanded + } + } else if let Ok(mut dummy) = dummy { + dummy.sig.ident = unmodified_fn_name_from_fn_name(&dummy.sig.ident); + quote! { + #[doc(hidden)] + #[allow(non_snake_case, dead_code, clippy::too_many_arguments)] + #dummy } - - true } else { - false - }; - - parse_macro_input!(s as component::Model) - .is_transparent(is_transparent) - .is_island() - .into_token_stream() - .into() + quote! {} + } + .into() } /// Annotates a struct so that it can be used with your Component as a `slot`. diff --git a/leptos_macro/tests/ui/component.rs b/leptos_macro/tests/ui/component.rs index d5ecf2cc3c..262bcc0e77 100644 --- a/leptos_macro/tests/ui/component.rs +++ b/leptos_macro/tests/ui/component.rs @@ -13,7 +13,6 @@ fn unknown_prop_option(#[prop(hello)] test: bool) -> impl IntoView { #[component] fn optional_and_optional_no_strip( - , #[prop(optional, optional_no_strip)] conflicting: bool, ) -> impl IntoView { _ = conflicting; @@ -21,7 +20,6 @@ fn optional_and_optional_no_strip( #[component] fn optional_and_strip_option( - , #[prop(optional, strip_option)] conflicting: bool, ) -> impl IntoView { _ = conflicting; @@ -29,23 +27,18 @@ fn optional_and_strip_option( #[component] fn optional_no_strip_and_strip_option( - , #[prop(optional_no_strip, strip_option)] conflicting: bool, ) -> impl IntoView { _ = conflicting; } #[component] -fn default_without_value( - , - #[prop(default)] default: bool, -) -> impl IntoView { +fn default_without_value(#[prop(default)] default: bool) -> impl IntoView { _ = default; } #[component] fn default_with_invalid_value( - , #[prop(default= |)] default: bool, ) -> impl IntoView { _ = default; diff --git a/leptos_macro/tests/ui/component.stderr b/leptos_macro/tests/ui/component.stderr index 37563cdae2..7a425f79ba 100644 --- a/leptos_macro/tests/ui/component.stderr +++ b/leptos_macro/tests/ui/component.stderr @@ -1,33 +1,3 @@ -error: expected parameter name, found `,` - --> tests/ui/component.rs:16:5 - | -16 | , - | ^ expected parameter name - -error: expected parameter name, found `,` - --> tests/ui/component.rs:24:5 - | -24 | , - | ^ expected parameter name - -error: expected parameter name, found `,` - --> tests/ui/component.rs:32:5 - | -32 | , - | ^ expected parameter name - -error: expected parameter name, found `,` - --> tests/ui/component.rs:40:5 - | -40 | , - | ^ expected parameter name - -error: expected parameter name, found `,` - --> tests/ui/component.rs:48:5 - | -48 | , - | ^ expected parameter name - error: return type is incorrect --> tests/ui/component.rs:4:1 | @@ -50,32 +20,34 @@ error: supported fields are `optional`, `optional_no_strip`, `strip_option`, `de 10 | fn unknown_prop_option(#[prop(hello)] test: bool) -> impl IntoView { | ^^^^^ -error: expected one of: identifier, `::`, `<`, `_`, literal, `const`, `ref`, `mut`, `&`, parentheses, square brackets, `..`, `const` - --> tests/ui/component.rs:16:5 +error: `optional` conflicts with mutually exclusive `optional_no_strip` + --> tests/ui/component.rs:16:12 | -16 | , - | ^ +16 | #[prop(optional, optional_no_strip)] conflicting: bool, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: expected one of: identifier, `::`, `<`, `_`, literal, `const`, `ref`, `mut`, `&`, parentheses, square brackets, `..`, `const` - --> tests/ui/component.rs:24:5 +error: `optional` conflicts with mutually exclusive `strip_option` + --> tests/ui/component.rs:23:12 | -24 | , - | ^ +23 | #[prop(optional, strip_option)] conflicting: bool, + | ^^^^^^^^^^^^^^^^^^^^^^ -error: expected one of: identifier, `::`, `<`, `_`, literal, `const`, `ref`, `mut`, `&`, parentheses, square brackets, `..`, `const` - --> tests/ui/component.rs:32:5 +error: `optional_no_strip` conflicts with mutually exclusive `strip_option` + --> tests/ui/component.rs:30:12 | -32 | , - | ^ +30 | #[prop(optional_no_strip, strip_option)] conflicting: bool, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: expected one of: identifier, `::`, `<`, `_`, literal, `const`, `ref`, `mut`, `&`, parentheses, square brackets, `..`, `const` - --> tests/ui/component.rs:40:5 +error: unexpected end of input, expected assignment `=` + --> tests/ui/component.rs:36:40 | -40 | , - | ^ +36 | fn default_without_value(#[prop(default)] default: bool) -> impl IntoView { + | ^ + +error: unexpected end of input, expected one of: identifier, `::`, `<`, `_`, literal, `const`, `ref`, `mut`, `&`, parentheses, square brackets, `..`, `const` -error: expected one of: identifier, `::`, `<`, `_`, literal, `const`, `ref`, `mut`, `&`, parentheses, square brackets, `..`, `const` - --> tests/ui/component.rs:48:5 + = help: try `#[prop(default=5 * 10)]` + --> tests/ui/component.rs:42:22 | -48 | , - | ^ +42 | #[prop(default= |)] default: bool, + | ^ diff --git a/meta/Cargo.toml b/meta/Cargo.toml index bc60edb7c3..22f653012b 100644 --- a/meta/Cargo.toml +++ b/meta/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leptos_meta" -version = "0.5.2" +version = "0.5.3" edition = "2021" authors = ["Greg Johnston"] license = "MIT" diff --git a/router/Cargo.toml b/router/Cargo.toml index e871378182..5fa91bb07c 100644 --- a/router/Cargo.toml +++ b/router/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leptos_router" -version = "0.5.2" +version = "0.5.3" edition = "2021" authors = ["Greg Johnston"] license = "MIT"