mirror of
https://github.com/leptos-rs/leptos.git
synced 2025-12-29 07:12:33 -05:00
Compare commits
4 Commits
tracing2
...
eager-clon
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
757413da3c | ||
|
|
3c6b247438 | ||
|
|
45c373ab3e | ||
|
|
dd0ca4754e |
@@ -4,31 +4,30 @@
|
||||
|
||||
The examples in this directory are all built and tested against the current `main` branch.
|
||||
|
||||
To the extent that new features have been released or breaking changes have been made since the previous release, the examples are compatible with the `main` branch and not the current release.
|
||||
To the extent that new features have been released or breaking changes have been made since the previous release, the examples are compatible with the `main` branch but not the current release.
|
||||
|
||||
To see the examples as they were at the time of the `0.5.0` release, [click here](https://github.com/leptos-rs/leptos/tree/v0.5.0/examples).
|
||||
|
||||
## Cargo Make
|
||||
|
||||
[Cargo Make](https://sagiegurari.github.io/cargo-make/) is used to build, test, and run examples.
|
||||
|
||||
Here are the highlights.
|
||||
|
||||
- Extendable custom task files are located in the [cargo-make](./cargo-make/) directory
|
||||
- Running a task will automatically install `cargo` dependencies
|
||||
- Each `Makefile.toml` file must extend the [cargo-make/main.toml](./cargo-make/main.toml) file
|
||||
- [cargo-make](./cargo-make/) files that end in `*-test.toml` configure web testing strategies
|
||||
- Run `cargo make test-report` to learn which examples have web tests
|
||||
|
||||
## Getting Started
|
||||
|
||||
The simplest way to get started with any example is to use the “quick start” command found in the README for each example. Most of the examples use either [`trunk`](https://trunkrs.dev/) (a simple build system and dev server for client-side-rendered apps) or [`cargo-leptos`](https://github.com/leptos-rs/cargo-leptos) (a build system for server-rendered and client-hydrated apps).
|
||||
|
||||
## Using Cargo Make
|
||||
|
||||
You can also run any of the examples using [`cargo-make`](https://github.com/sagiegurari/cargo-make). Note that this is completely optional. We use it for CI, and it can be convenient for running the examples, but is not required.
|
||||
|
||||
Follow these steps to get any example up and running.
|
||||
|
||||
1. `cd` to the example root directory
|
||||
2. Run `cargo make ci` to setup and test the example
|
||||
3. Run `cargo make start` to run the example
|
||||
4. Open the client URL in the console output (<http://127.0.0.1:8080> or <http://127.0.0.1:3000> by default)
|
||||
5. Run `cargo make stop` to end any processes started by `cargo make start`.
|
||||
|
||||
Here are a few additional notes:
|
||||
|
||||
- Extendable custom task files are located in the [cargo-make](./cargo-make/) directory
|
||||
- Running a task will automatically install `cargo` dependencies
|
||||
- Each `Makefile.toml` file must extend the [cargo-make/main.toml](./cargo-make/main.toml) file
|
||||
- [cargo-make](./cargo-make/) files that end in `*-test.toml` configure web testing strategies
|
||||
- Run `cargo make test-report` to learn which examples have web tests
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +1,3 @@
|
||||
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -5,7 +5,3 @@ This example demonstrates how Leptos Errors can work with an Axum backend on a s
|
||||
## Getting Started
|
||||
|
||||
See the [Examples README](../README.md) for setup and run instructions.
|
||||
|
||||
## Quick Start
|
||||
|
||||
Run `cargo leptos watch` to run this example.
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +1,3 @@
|
||||
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -9,6 +9,11 @@ cfg_if! {
|
||||
use crate::app::*;
|
||||
use leptos_actix::{generate_route_list, LeptosRoutes};
|
||||
|
||||
#[get("/style.css")]
|
||||
async fn css() -> impl Responder {
|
||||
actix_files::NamedFile::open_async("./style/output.css").await
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
|
||||
@@ -25,6 +30,7 @@ cfg_if! {
|
||||
let site_root = &leptos_options.site_root;
|
||||
let routes = &routes;
|
||||
App::new()
|
||||
.service(css)
|
||||
.leptos_routes(leptos_options.to_owned(), routes.to_owned(), || view! { <App/> })
|
||||
.service(Files::new("/", site_root))
|
||||
.wrap(middleware::Compress::default())
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -457,7 +457,7 @@ pub type PinnedHtmlStream =
|
||||
/// - [ResponseOptions]
|
||||
/// - [MetaContext](leptos_meta::MetaContext)
|
||||
/// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext)
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
#[tracing::instrument(level = "info", fields(error), skip_all)]
|
||||
pub fn render_app_to_stream<IV>(
|
||||
options: LeptosOptions,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
@@ -483,7 +483,7 @@ where
|
||||
/// The difference between calling this and `render_app_to_stream_with_context()` is that this
|
||||
/// one respects the `SsrMode` on each Route and thus requires `Vec<RouteListing>` for route checking.
|
||||
/// This is useful if you are using `.leptos_routes_with_handler()`
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
#[tracing::instrument(level = "info", fields(error), skip_all)]
|
||||
pub fn render_route<IV>(
|
||||
options: LeptosOptions,
|
||||
paths: Vec<RouteListing>,
|
||||
@@ -558,7 +558,7 @@ where
|
||||
/// - [ResponseOptions]
|
||||
/// - [MetaContext](leptos_meta::MetaContext)
|
||||
/// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext)
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
#[tracing::instrument(level = "info", fields(error), skip_all)]
|
||||
pub fn render_app_to_stream_in_order<IV>(
|
||||
options: LeptosOptions,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
@@ -604,7 +604,7 @@ where
|
||||
/// - [ResponseOptions]
|
||||
/// - [MetaContext](leptos_meta::MetaContext)
|
||||
/// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext)
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
#[tracing::instrument(level = "info", fields(error), skip_all)]
|
||||
pub fn render_app_to_stream_with_context<IV>(
|
||||
options: LeptosOptions,
|
||||
additional_context: impl Fn() + 'static + Clone + Send,
|
||||
@@ -636,7 +636,7 @@ where
|
||||
/// The difference between calling this and `render_app_to_stream_with_context()` is that this
|
||||
/// one respects the `SsrMode` on each Route, and thus requires `Vec<RouteListing>` for route checking.
|
||||
/// This is useful if you are using `.leptos_routes_with_handler()`.
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
#[tracing::instrument(level = "info", fields(error), skip_all)]
|
||||
pub fn render_route_with_context<IV>(
|
||||
options: LeptosOptions,
|
||||
paths: Vec<RouteListing>,
|
||||
@@ -724,7 +724,7 @@ where
|
||||
/// - [ResponseOptions]
|
||||
/// - [MetaContext](leptos_meta::MetaContext)
|
||||
/// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext)
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
#[tracing::instrument(level = "info", fields(error), skip_all)]
|
||||
pub fn render_app_to_stream_with_context_and_replace_blocks<IV>(
|
||||
options: LeptosOptions,
|
||||
additional_context: impl Fn() + 'static + Clone + Send,
|
||||
@@ -787,7 +787,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
#[tracing::instrument(level = "info", fields(error), skip_all)]
|
||||
async fn generate_response(
|
||||
res_options: ResponseOptions,
|
||||
rx: Receiver<String>,
|
||||
@@ -829,7 +829,7 @@ async fn generate_response(
|
||||
}
|
||||
res
|
||||
}
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
#[tracing::instrument(level = "info", fields(error), skip_all)]
|
||||
async fn forward_stream(
|
||||
options: &LeptosOptions,
|
||||
res_options2: ResponseOptions,
|
||||
@@ -890,7 +890,7 @@ async fn forward_stream(
|
||||
/// - [ResponseOptions]
|
||||
/// - [MetaContext](leptos_meta::MetaContext)
|
||||
/// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext)
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
#[tracing::instrument(level = "info", fields(error), skip_all)]
|
||||
pub fn render_app_to_stream_in_order_with_context<IV>(
|
||||
options: LeptosOptions,
|
||||
additional_context: impl Fn() + 'static + Clone + Send,
|
||||
@@ -1026,7 +1026,7 @@ fn provide_contexts(
|
||||
/// - [ResponseOptions]
|
||||
/// - [MetaContext](leptos_meta::MetaContext)
|
||||
/// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext)
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
#[tracing::instrument(level = "info", fields(error), skip_all)]
|
||||
pub fn render_app_async<IV>(
|
||||
options: LeptosOptions,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
@@ -1068,7 +1068,7 @@ where
|
||||
/// - [ResponseOptions]
|
||||
/// - [MetaContext](leptos_meta::MetaContext)
|
||||
/// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext)
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
#[tracing::instrument(level = "info", fields(error), skip_all)]
|
||||
pub fn render_app_async_stream_with_context<IV>(
|
||||
options: LeptosOptions,
|
||||
additional_context: impl Fn() + 'static + Clone + Send,
|
||||
@@ -1204,7 +1204,7 @@ where
|
||||
/// - [ResponseOptions]
|
||||
/// - [MetaContext](leptos_meta::MetaContext)
|
||||
/// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext)
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
#[tracing::instrument(level = "info", fields(error), skip_all)]
|
||||
pub fn render_app_async_with_context<IV>(
|
||||
options: LeptosOptions,
|
||||
additional_context: impl Fn() + 'static + Clone + Send,
|
||||
@@ -1677,7 +1677,7 @@ where
|
||||
LeptosOptions: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
#[tracing::instrument(level = "info", fields(error), skip_all)]
|
||||
fn leptos_routes<IV>(
|
||||
self,
|
||||
options: &S,
|
||||
|
||||
@@ -45,7 +45,7 @@ use leptos_reactive::{
|
||||
/// ```
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
tracing::instrument(level = "trace", skip_all)
|
||||
tracing::instrument(level = "info", skip_all)
|
||||
)]
|
||||
#[component]
|
||||
pub fn AnimatedShow(
|
||||
|
||||
@@ -52,7 +52,7 @@ use std::hash::Hash;
|
||||
/// ```
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
tracing::instrument(level = "trace", skip_all)
|
||||
tracing::instrument(level = "info", skip_all)
|
||||
)]
|
||||
#[component(transparent)]
|
||||
pub fn For<IF, I, T, EF, N, KF, K>(
|
||||
|
||||
@@ -57,8 +57,8 @@
|
||||
//! [`todo_app_sqlite_axum`](https://github.com/leptos-rs/leptos/tree/main/examples/todo_app_sqlite_axum), and
|
||||
//! [`todo_app_sqlite_viz`](https://github.com/leptos-rs/leptos/tree/main/examples/todo_app_sqlite_viz)
|
||||
//! show how to build a full-stack app using server functions and database connections.
|
||||
//! - [`tailwind`](https://github.com/leptos-rs/leptos/tree/main/examples/tailwind_csr) shows how to integrate
|
||||
//! TailwindCSS with `trunk` for CSR.
|
||||
//! - [`tailwind`](https://github.com/leptos-rs/leptos/tree/main/examples/tailwind) shows how to integrate
|
||||
//! TailwindCSS with `cargo-leptos`.
|
||||
//!
|
||||
//! Details on how to run each example can be found in its README.
|
||||
//!
|
||||
|
||||
@@ -11,7 +11,7 @@ use leptos_macro::component;
|
||||
/// Setting `use_shadow` to `true` places the element in a shadow root to isolate styles.
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
tracing::instrument(level = "trace", skip_all)
|
||||
tracing::instrument(level = "info", skip_all)
|
||||
)]
|
||||
#[component]
|
||||
pub fn Portal(
|
||||
|
||||
@@ -28,7 +28,7 @@ use leptos_reactive::{create_memo, signal_prelude::*};
|
||||
/// ```
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
tracing::instrument(level = "trace", skip_all)
|
||||
tracing::instrument(level = "info", skip_all)
|
||||
)]
|
||||
#[component]
|
||||
pub fn Show<W>(
|
||||
|
||||
@@ -57,7 +57,7 @@ use std::rc::Rc;
|
||||
/// ```
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
tracing::instrument(level = "trace", skip_all)
|
||||
tracing::instrument(level = "info", skip_all)
|
||||
)]
|
||||
#[component]
|
||||
pub fn Suspense<V>(
|
||||
|
||||
@@ -64,7 +64,7 @@ use std::{
|
||||
/// ```
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
tracing::instrument(level = "trace", skip_all)
|
||||
tracing::instrument(level = "info", skip_all)
|
||||
)]
|
||||
#[component(transparent)]
|
||||
pub fn Transition(
|
||||
@@ -130,8 +130,7 @@ pub fn Transition(
|
||||
}
|
||||
if is_first_run(first_run, &suspense_context) {
|
||||
let has_local_only = suspense_context.has_local_only()
|
||||
|| cfg!(feature = "csr")
|
||||
|| !HydrationCtx::is_hydrating();
|
||||
|| cfg!(feature = "csr");
|
||||
if (!has_local_only || child_runs.get() > 0)
|
||||
&& !cfg!(feature = "csr")
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ futures = "0.3"
|
||||
getrandom = { version = "0.2", optional = true }
|
||||
html-escape = "0.2"
|
||||
indexmap = "2"
|
||||
itertools = "0.12"
|
||||
itertools = "0.10"
|
||||
js-sys = "0.3"
|
||||
leptos_reactive = { workspace = true }
|
||||
server_fn = { workspace = true }
|
||||
|
||||
@@ -158,7 +158,7 @@ impl From<ComponentRepr> for View {
|
||||
}
|
||||
|
||||
impl IntoView for ComponentRepr {
|
||||
#[cfg_attr(any(debug_assertions, feature = "ssr"), instrument(level = "trace", name = "<Component />", skip_all, fields(name = %self.name)))]
|
||||
#[cfg_attr(any(debug_assertions, feature = "ssr"), instrument(level = "info", name = "<Component />", skip_all, fields(name = %self.name)))]
|
||||
fn into_view(self) -> View {
|
||||
self.into()
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ where
|
||||
{
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", name = "<DynChild />", skip_all)
|
||||
instrument(level = "info", name = "<DynChild />", skip_all)
|
||||
)]
|
||||
#[inline]
|
||||
fn into_view(self) -> View {
|
||||
|
||||
@@ -382,7 +382,7 @@ where
|
||||
{
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", name = "<Each />", skip_all)
|
||||
instrument(level = "info", name = "<Each />", skip_all)
|
||||
)]
|
||||
fn into_view(self) -> crate::View {
|
||||
let Self {
|
||||
|
||||
@@ -15,7 +15,7 @@ where
|
||||
{
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", skip_all,)
|
||||
instrument(level = "info", skip_all,)
|
||||
)]
|
||||
fn into_fragment(self) -> Fragment {
|
||||
self.into_iter().map(|v| v.into_view()).collect()
|
||||
@@ -110,7 +110,7 @@ impl Fragment {
|
||||
}
|
||||
|
||||
impl IntoView for Fragment {
|
||||
#[cfg_attr(debug_assertions, instrument(level = "trace", name = "</>", skip_all, fields(children = self.nodes.len())))]
|
||||
#[cfg_attr(debug_assertions, instrument(level = "info", name = "</>", skip_all, fields(children = self.nodes.len())))]
|
||||
fn into_view(self) -> View {
|
||||
self.into()
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ pub struct Unit;
|
||||
impl IntoView for Unit {
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", name = "<() />", skip_all)
|
||||
instrument(level = "info", name = "<() />", skip_all)
|
||||
)]
|
||||
fn into_view(self) -> crate::View {
|
||||
let component = UnitRepr::default();
|
||||
|
||||
@@ -101,7 +101,7 @@ pub trait Mountable {
|
||||
impl IntoView for () {
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", name = "<() />", skip_all)
|
||||
instrument(level = "info", name = "<() />", skip_all)
|
||||
)]
|
||||
fn into_view(self) -> View {
|
||||
Unit.into_view()
|
||||
@@ -114,7 +114,7 @@ where
|
||||
{
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", name = "Option<T>", skip_all)
|
||||
instrument(level = "info", name = "Option<T>", skip_all)
|
||||
)]
|
||||
fn into_view(self) -> View {
|
||||
if let Some(t) = self {
|
||||
@@ -132,7 +132,7 @@ where
|
||||
{
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", name = "Fn() -> impl IntoView", skip_all)
|
||||
instrument(level = "info", name = "Fn() -> impl IntoView", skip_all)
|
||||
)]
|
||||
#[track_caller]
|
||||
fn into_view(self) -> View {
|
||||
@@ -246,7 +246,7 @@ pub trait CollectView {
|
||||
impl<I: IntoIterator<Item = T>, T: IntoView> CollectView for I {
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", name = "#text", skip_all)
|
||||
instrument(level = "info", name = "#text", skip_all)
|
||||
)]
|
||||
fn collect_view(self) -> View {
|
||||
self.into_iter()
|
||||
@@ -381,7 +381,7 @@ impl Element {
|
||||
}
|
||||
|
||||
impl IntoView for Element {
|
||||
#[cfg_attr(debug_assertions, instrument(level = "trace", name = "<Element />", skip_all, fields(tag = %self.name)))]
|
||||
#[cfg_attr(debug_assertions, instrument(level = "info", name = "<Element />", skip_all, fields(tag = %self.name)))]
|
||||
fn into_view(self) -> View {
|
||||
View::Element(self)
|
||||
}
|
||||
@@ -501,7 +501,7 @@ impl fmt::Debug for Text {
|
||||
}
|
||||
|
||||
impl IntoView for Text {
|
||||
#[cfg_attr(debug_assertions, instrument(level = "trace", name = "#text", skip_all, fields(content = %self.content)))]
|
||||
#[cfg_attr(debug_assertions, instrument(level = "info", name = "#text", skip_all, fields(content = %self.content)))]
|
||||
fn into_view(self) -> View {
|
||||
View::Text(self)
|
||||
}
|
||||
@@ -566,7 +566,7 @@ impl Default for View {
|
||||
}
|
||||
|
||||
impl IntoView for View {
|
||||
#[cfg_attr(debug_assertions, instrument(level = "trace", name = "Node", skip_all, fields(kind = self.kind_name())))]
|
||||
#[cfg_attr(debug_assertions, instrument(level = "info", name = "Node", skip_all, fields(kind = self.kind_name())))]
|
||||
fn into_view(self) -> View {
|
||||
self
|
||||
}
|
||||
@@ -581,7 +581,7 @@ impl IntoView for &View {
|
||||
impl<const N: usize> IntoView for [View; N] {
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", name = "[Node; N]", skip_all)
|
||||
instrument(level = "info", name = "[Node; N]", skip_all)
|
||||
)]
|
||||
fn into_view(self) -> View {
|
||||
Fragment::new(self.into_iter().collect()).into_view()
|
||||
@@ -1135,7 +1135,7 @@ api_planning! {
|
||||
impl IntoView for String {
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", name = "#text", skip_all)
|
||||
instrument(level = "info", name = "#text", skip_all)
|
||||
)]
|
||||
#[inline(always)]
|
||||
fn into_view(self) -> View {
|
||||
@@ -1146,7 +1146,7 @@ impl IntoView for String {
|
||||
impl IntoView for &'static str {
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", name = "#text", skip_all)
|
||||
instrument(level = "info", name = "#text", skip_all)
|
||||
)]
|
||||
#[inline(always)]
|
||||
fn into_view(self) -> View {
|
||||
@@ -1157,7 +1157,7 @@ impl IntoView for &'static str {
|
||||
impl IntoView for Oco<'static, str> {
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", name = "#text", skip_all)
|
||||
instrument(level = "info", name = "#text", skip_all)
|
||||
)]
|
||||
#[inline(always)]
|
||||
fn into_view(self) -> View {
|
||||
@@ -1171,7 +1171,7 @@ where
|
||||
{
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", name = "#text", skip_all)
|
||||
instrument(level = "info", name = "#text", skip_all)
|
||||
)]
|
||||
fn into_view(self) -> View {
|
||||
self.into_iter()
|
||||
@@ -1184,7 +1184,7 @@ where
|
||||
impl IntoView for core::fmt::Arguments<'_> {
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", name = "#text", skip_all)
|
||||
instrument(level = "info", name = "#text", skip_all)
|
||||
)]
|
||||
fn into_view(self) -> View {
|
||||
match self.as_str() {
|
||||
|
||||
@@ -138,6 +138,15 @@ macro_rules! impl_into_attr_boxed {
|
||||
};
|
||||
}
|
||||
|
||||
impl IntoAttribute for Option<Attribute> {
|
||||
#[inline(always)]
|
||||
fn into_attribute(self) -> Attribute {
|
||||
self.unwrap_or(Attribute::Option(None))
|
||||
}
|
||||
|
||||
impl_into_attr_boxed! {}
|
||||
}
|
||||
|
||||
impl IntoAttribute for String {
|
||||
#[inline(always)]
|
||||
fn into_attribute(self) -> Attribute {
|
||||
@@ -192,10 +201,46 @@ impl IntoAttribute for bool {
|
||||
impl_into_attr_boxed! {}
|
||||
}
|
||||
|
||||
impl<T: IntoAttribute> IntoAttribute for Option<T> {
|
||||
impl IntoAttribute for Option<String> {
|
||||
#[inline(always)]
|
||||
fn into_attribute(self) -> Attribute {
|
||||
self.map_or(Attribute::Option(None), IntoAttribute::into_attribute)
|
||||
Attribute::Option(self.map(Oco::Owned))
|
||||
}
|
||||
|
||||
impl_into_attr_boxed! {}
|
||||
}
|
||||
|
||||
impl IntoAttribute for Option<&'static str> {
|
||||
#[inline(always)]
|
||||
fn into_attribute(self) -> Attribute {
|
||||
Attribute::Option(self.map(Oco::Borrowed))
|
||||
}
|
||||
|
||||
impl_into_attr_boxed! {}
|
||||
}
|
||||
|
||||
impl IntoAttribute for Option<Rc<str>> {
|
||||
#[inline(always)]
|
||||
fn into_attribute(self) -> Attribute {
|
||||
Attribute::Option(self.map(Oco::Counted))
|
||||
}
|
||||
|
||||
impl_into_attr_boxed! {}
|
||||
}
|
||||
|
||||
impl IntoAttribute for Option<Cow<'static, str>> {
|
||||
#[inline(always)]
|
||||
fn into_attribute(self) -> Attribute {
|
||||
Attribute::Option(self.map(Oco::from))
|
||||
}
|
||||
|
||||
impl_into_attr_boxed! {}
|
||||
}
|
||||
|
||||
impl IntoAttribute for Option<Oco<'static, str>> {
|
||||
#[inline(always)]
|
||||
fn into_attribute(self) -> Attribute {
|
||||
Attribute::Option(self)
|
||||
}
|
||||
|
||||
impl_into_attr_boxed! {}
|
||||
@@ -265,6 +310,17 @@ macro_rules! attr_type {
|
||||
self.into_attribute()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoAttribute for Option<$attr_type> {
|
||||
fn into_attribute(self) -> Attribute {
|
||||
Attribute::Option(self.map(|n| n.to_string().into()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_attribute_boxed(self: Box<Self>) -> Attribute {
|
||||
self.into_attribute()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -285,6 +341,24 @@ macro_rules! attr_signal_type {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! attr_signal_type_optional {
|
||||
($signal_type:ty) => {
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
impl<T> IntoAttribute for $signal_type
|
||||
where
|
||||
T: Clone,
|
||||
Option<T>: IntoAttribute,
|
||||
{
|
||||
fn into_attribute(self) -> Attribute {
|
||||
let modified_fn = Rc::new(move || self.get().into_attribute());
|
||||
Attribute::Fn(modified_fn)
|
||||
}
|
||||
|
||||
impl_into_attr_boxed! {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
attr_type!(&String);
|
||||
attr_type!(usize);
|
||||
attr_type!(u8);
|
||||
@@ -307,7 +381,7 @@ attr_signal_type!(RwSignal<T>);
|
||||
attr_signal_type!(Memo<T>);
|
||||
attr_signal_type!(Signal<T>);
|
||||
attr_signal_type!(MaybeSignal<T>);
|
||||
attr_signal_type!(MaybeProp<T>);
|
||||
attr_signal_type_optional!(MaybeProp<T>);
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
#[doc(hidden)]
|
||||
|
||||
@@ -69,6 +69,16 @@ impl IntoAttribute for Nonce {
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoAttribute for Option<Nonce> {
|
||||
fn into_attribute(self) -> Attribute {
|
||||
Attribute::Option(self.map(|n| n.0.into()))
|
||||
}
|
||||
|
||||
fn into_attribute_boxed(self: Box<Self>) -> Attribute {
|
||||
Attribute::Option(self.map(|n| n.0.into()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Accesses the nonce that has been generated during the current
|
||||
/// server response. This can be added to inline `<script>` and
|
||||
/// `<style>` tags for compatibility with a Content Security Policy.
|
||||
|
||||
@@ -28,7 +28,7 @@ type PinnedFuture<T> = Pin<Box<dyn Future<Output = T>>>;
|
||||
/// ```
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", skip_all,)
|
||||
instrument(level = "info", skip_all,)
|
||||
)]
|
||||
pub fn render_to_string<F, N>(f: F) -> Oco<'static, str>
|
||||
where
|
||||
@@ -59,7 +59,7 @@ where
|
||||
/// read under that `<Suspense/>` resolve.
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", skip_all,)
|
||||
instrument(level = "info", skip_all,)
|
||||
)]
|
||||
pub fn render_to_stream(
|
||||
view: impl FnOnce() -> View + 'static,
|
||||
@@ -83,7 +83,7 @@ pub fn render_to_stream(
|
||||
/// read under that `<Suspense/>` resolve.
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", skip_all,)
|
||||
instrument(level = "info", skip_all,)
|
||||
)]
|
||||
pub fn render_to_stream_with_prefix(
|
||||
view: impl FnOnce() -> View + 'static,
|
||||
@@ -112,7 +112,7 @@ pub fn render_to_stream_with_prefix(
|
||||
/// read under that `<Suspense/>` resolve.
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", skip_all,)
|
||||
instrument(level = "info", skip_all,)
|
||||
)]
|
||||
pub fn render_to_stream_with_prefix_undisposed(
|
||||
view: impl FnOnce() -> View + 'static,
|
||||
@@ -138,7 +138,7 @@ pub fn render_to_stream_with_prefix_undisposed(
|
||||
/// read under that `<Suspense/>` resolve.
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", skip_all,)
|
||||
instrument(level = "info", skip_all,)
|
||||
)]
|
||||
pub fn render_to_stream_with_prefix_undisposed_with_context(
|
||||
view: impl FnOnce() -> View + 'static,
|
||||
@@ -175,7 +175,7 @@ pub fn render_to_stream_with_prefix_undisposed_with_context(
|
||||
/// read under that `<Suspense/>` resolve.
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", skip_all,)
|
||||
instrument(level = "info", skip_all,)
|
||||
)]
|
||||
pub fn render_to_stream_with_prefix_undisposed_with_context_and_block_replacement(
|
||||
view: impl FnOnce() -> View + 'static,
|
||||
@@ -365,7 +365,7 @@ impl View {
|
||||
/// Consumes the node and renders it into an HTML string.
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", skip_all,)
|
||||
instrument(level = "info", skip_all,)
|
||||
)]
|
||||
pub fn render_to_string(self) -> Oco<'static, str> {
|
||||
#[cfg(all(feature = "web", feature = "ssr"))]
|
||||
|
||||
@@ -17,7 +17,7 @@ use std::collections::VecDeque;
|
||||
|
||||
/// Renders a view to HTML, waiting to return until all `async` [Resource](leptos_reactive::Resource)s
|
||||
/// loaded in `<Suspense/>` elements have finished loading.
|
||||
#[tracing::instrument(level = "trace", skip_all)]
|
||||
#[tracing::instrument(level = "info", skip_all)]
|
||||
pub async fn render_to_string_async(
|
||||
view: impl FnOnce() -> View + 'static,
|
||||
) -> String {
|
||||
@@ -40,7 +40,7 @@ pub async fn render_to_string_async(
|
||||
/// in order:
|
||||
/// 1. HTML from the `view` in order, pausing to wait for each `<Suspense/>`
|
||||
/// 2. any serialized [Resource](leptos_reactive::Resource)s
|
||||
#[tracing::instrument(level = "trace", skip_all)]
|
||||
#[tracing::instrument(level = "info", skip_all)]
|
||||
pub fn render_to_stream_in_order(
|
||||
view: impl FnOnce() -> View + 'static,
|
||||
) -> impl Stream<Item = String> {
|
||||
|
||||
@@ -15,7 +15,7 @@ proc-macro = true
|
||||
attribute-derive = { version = "0.8", features = ["syn-full"] }
|
||||
cfg-if = "1"
|
||||
html-escape = "0.2"
|
||||
itertools = "0.12"
|
||||
itertools = "0.11"
|
||||
prettyplease = "0.2.4"
|
||||
proc-macro-error = { version = "1", default-features = false }
|
||||
proc-macro2 = "1"
|
||||
|
||||
@@ -38,7 +38,7 @@ pub fn TestComponent(
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn TestMutCallback<F>(mut callback: F, value: &'static str) -> impl IntoView
|
||||
fn TestMutCallback<'a, F>(mut callback: F, value: &'a str) -> impl IntoView
|
||||
where
|
||||
F: FnMut(u32) + 'static,
|
||||
{
|
||||
|
||||
@@ -190,7 +190,7 @@ impl ToTokens for Model {
|
||||
#[allow(clippy::let_with_type_underscore)]
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature="ssr"),
|
||||
::leptos::leptos_dom::tracing::instrument(level = "trace", name = #trace_name, skip_all)
|
||||
::leptos::leptos_dom::tracing::instrument(level = "info", name = #trace_name, skip_all)
|
||||
)]
|
||||
},
|
||||
quote! {
|
||||
|
||||
@@ -76,8 +76,7 @@ mod slot;
|
||||
/// # runtime.dispose();
|
||||
/// ```
|
||||
///
|
||||
/// 3. Components (functions annotated with `#[component]`) can be inserted as camel-cased tags. (Generics
|
||||
/// on components are specified as `<Component<T>/>`, not the turbofish `<Component::<T>/>`.)
|
||||
/// 3. Components (functions annotated with `#[component]`) can be inserted as camel-cased tags
|
||||
/// ```rust
|
||||
/// # use leptos::*;
|
||||
/// # let runtime = create_runtime();
|
||||
@@ -603,12 +602,10 @@ pub fn component(args: proc_macro::TokenStream, s: TokenStream) -> TokenStream {
|
||||
false
|
||||
};
|
||||
|
||||
let Ok(mut dummy) = syn::parse::<DummyModel>(s.clone()) else {
|
||||
return s;
|
||||
};
|
||||
let mut dummy = syn::parse::<DummyModel>(s.clone());
|
||||
let parse_result = syn::parse::<component::Model>(s);
|
||||
|
||||
if let (ref mut unexpanded, Ok(model)) = (&mut dummy, parse_result) {
|
||||
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);
|
||||
@@ -618,13 +615,15 @@ pub fn component(args: proc_macro::TokenStream, s: TokenStream) -> TokenStream {
|
||||
#[allow(non_snake_case, dead_code, clippy::too_many_arguments)]
|
||||
#unexpanded
|
||||
}
|
||||
} else {
|
||||
} 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 {
|
||||
quote! {}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
@@ -703,12 +702,10 @@ 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 Ok(mut dummy) = syn::parse::<DummyModel>(s.clone()) else {
|
||||
return s;
|
||||
};
|
||||
let mut dummy = syn::parse::<DummyModel>(s.clone());
|
||||
let parse_result = syn::parse::<component::Model>(s);
|
||||
|
||||
if let (ref mut unexpanded, Ok(model)) = (&mut dummy, parse_result) {
|
||||
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 {
|
||||
@@ -723,13 +720,15 @@ pub fn island(_args: proc_macro::TokenStream, s: TokenStream) -> TokenStream {
|
||||
#[allow(non_snake_case, dead_code, clippy::too_many_arguments)]
|
||||
#unexpanded
|
||||
}
|
||||
} else {
|
||||
} 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 {
|
||||
quote! {}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ use std::any::{Any, TypeId};
|
||||
/// ```
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", skip_all,)
|
||||
instrument(level = "debug", skip_all,)
|
||||
)]
|
||||
#[track_caller]
|
||||
pub fn provide_context<T>(value: T)
|
||||
@@ -230,7 +230,7 @@ where
|
||||
/// ```
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", skip_all,)
|
||||
instrument(level = "debug", skip_all,)
|
||||
)]
|
||||
pub fn use_context<T>() -> Option<T>
|
||||
where
|
||||
|
||||
@@ -341,7 +341,7 @@ where
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(
|
||||
name = "Effect::run()",
|
||||
level = "trace",
|
||||
level = "debug",
|
||||
skip_all,
|
||||
fields(
|
||||
defined_at = %self.defined_at,
|
||||
|
||||
@@ -537,7 +537,7 @@ where
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(
|
||||
name = "Memo::run()",
|
||||
level = "trace",
|
||||
level = "debug",
|
||||
skip_all,
|
||||
fields(
|
||||
defined_at = %self.defined_at,
|
||||
|
||||
@@ -86,7 +86,7 @@ use std::{
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature="ssr"),
|
||||
instrument(
|
||||
level = "trace",
|
||||
level = "debug",
|
||||
skip_all,
|
||||
fields(
|
||||
ty = %std::any::type_name::<T>(),
|
||||
@@ -120,7 +120,7 @@ where
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature="ssr"),
|
||||
instrument(
|
||||
level = "trace",
|
||||
level = "debug",
|
||||
skip_all,
|
||||
fields(
|
||||
ty = %std::any::type_name::<T>(),
|
||||
@@ -169,7 +169,7 @@ where
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature="ssr"),
|
||||
instrument(
|
||||
level = "trace",
|
||||
level = "debug",
|
||||
skip_all,
|
||||
fields(
|
||||
ty = %std::any::type_name::<T>(),
|
||||
@@ -295,7 +295,7 @@ where
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature="ssr"),
|
||||
instrument(
|
||||
level = "trace",
|
||||
level = "debug",
|
||||
skip_all,
|
||||
fields(
|
||||
ty = %std::any::type_name::<T>(),
|
||||
@@ -328,7 +328,7 @@ where
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature="ssr"),
|
||||
instrument(
|
||||
level = "trace",
|
||||
level = "debug",
|
||||
skip_all,
|
||||
fields(
|
||||
ty = %std::any::type_name::<T>(),
|
||||
@@ -500,7 +500,7 @@ where
|
||||
/// (`value.read()` is equivalent to `value.with(T::clone)`.)
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", skip_all,)
|
||||
instrument(level = "debug", skip_all,)
|
||||
)]
|
||||
#[track_caller]
|
||||
#[deprecated = "You can now use .get() on resources."]
|
||||
@@ -520,7 +520,7 @@ where
|
||||
/// [`Resource::read`].
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", skip_all,)
|
||||
instrument(level = "debug", skip_all,)
|
||||
)]
|
||||
#[track_caller]
|
||||
pub fn map<U>(&self, f: impl FnOnce(&T) -> U) -> Option<U> {
|
||||
|
||||
@@ -951,11 +951,12 @@ impl RuntimeId {
|
||||
false
|
||||
};
|
||||
|
||||
let prev_observer = SetObserverOnDrop(runtime.observer.take());
|
||||
let prev_observer =
|
||||
SetObserverOnDrop(self, runtime.observer.take());
|
||||
|
||||
untracked_result = f();
|
||||
|
||||
runtime.observer.set(prev_observer.0);
|
||||
runtime.observer.set(prev_observer.1);
|
||||
std::mem::forget(prev_observer); // avoid Drop
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
@@ -1370,12 +1371,12 @@ impl std::hash::Hash for Runtime {
|
||||
}
|
||||
}
|
||||
|
||||
struct SetObserverOnDrop(Option<NodeId>);
|
||||
struct SetObserverOnDrop(RuntimeId, Option<NodeId>);
|
||||
|
||||
impl Drop for SetObserverOnDrop {
|
||||
fn drop(&mut self) {
|
||||
_ = with_runtime(|rt| {
|
||||
rt.observer.set(self.0);
|
||||
rt.observer.set(self.1);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1392,13 +1393,14 @@ impl Drop for SetObserverOnDrop {
|
||||
)]
|
||||
#[inline(always)]
|
||||
pub fn batch<T>(f: impl FnOnce() -> T) -> T {
|
||||
let runtime_id = Runtime::current();
|
||||
with_runtime(move |runtime| {
|
||||
let batching = SetBatchingOnDrop(runtime.batching.get());
|
||||
let batching = SetBatchingOnDrop(runtime_id, runtime.batching.get());
|
||||
runtime.batching.set(true);
|
||||
|
||||
let val = f();
|
||||
|
||||
runtime.batching.set(batching.0);
|
||||
runtime.batching.set(batching.1);
|
||||
std::mem::forget(batching);
|
||||
|
||||
runtime.run_effects();
|
||||
@@ -1407,12 +1409,12 @@ pub fn batch<T>(f: impl FnOnce() -> T) -> T {
|
||||
.expect("tried to run a batched update in a runtime that has been disposed")
|
||||
}
|
||||
|
||||
struct SetBatchingOnDrop(bool);
|
||||
struct SetBatchingOnDrop(RuntimeId, bool);
|
||||
|
||||
impl Drop for SetBatchingOnDrop {
|
||||
fn drop(&mut self) {
|
||||
_ = with_runtime(|rt| {
|
||||
rt.batching.set(self.0);
|
||||
rt.batching.set(self.1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ wasm-bindgen = { version = "0.2" }
|
||||
wasm-bindgen-futures = { version = "0.4" }
|
||||
lru = { version = "0.11", optional = true }
|
||||
serde_json = "1.0.96"
|
||||
itertools = "0.12.0"
|
||||
itertools = "0.11.0"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3"
|
||||
|
||||
@@ -59,7 +59,7 @@ where
|
||||
/// different color if it’s a link to the page you’re currently on.
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
tracing::instrument(level = "trace", skip_all,)
|
||||
tracing::instrument(level = "info", skip_all,)
|
||||
)]
|
||||
#[component]
|
||||
pub fn A<H>(
|
||||
|
||||
@@ -11,7 +11,7 @@ use web_sys::AnimationEvent;
|
||||
/// that child route is displayed. Renders nothing if there is no nested child.
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
tracing::instrument(level = "trace", skip_all,)
|
||||
tracing::instrument(level = "info", skip_all,)
|
||||
)]
|
||||
#[component]
|
||||
pub fn Outlet() -> impl IntoView {
|
||||
|
||||
@@ -43,7 +43,7 @@ pub enum Method {
|
||||
/// the element it should display, and data that should be loaded alongside the route.
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
tracing::instrument(level = "trace", skip_all,)
|
||||
tracing::instrument(level = "info", skip_all,)
|
||||
)]
|
||||
#[component(transparent)]
|
||||
pub fn Route<E, F, P>(
|
||||
@@ -91,7 +91,7 @@ where
|
||||
/// redirects to `redirect_path` instead of displaying its `view`.
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
tracing::instrument(level = "trace", skip_all,)
|
||||
tracing::instrument(level = "info", skip_all,)
|
||||
)]
|
||||
#[component(transparent)]
|
||||
pub fn ProtectedRoute<P, E, F, C>(
|
||||
@@ -150,7 +150,7 @@ where
|
||||
/// the element it should display, and data that should be loaded alongside the route.
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
tracing::instrument(level = "trace", skip_all,)
|
||||
tracing::instrument(level = "info", skip_all,)
|
||||
)]
|
||||
#[component(transparent)]
|
||||
pub fn StaticRoute<E, F, P, S>(
|
||||
@@ -198,7 +198,7 @@ where
|
||||
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
tracing::instrument(level = "trace", skip_all,)
|
||||
tracing::instrument(level = "info", skip_all,)
|
||||
)]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn define_route(
|
||||
@@ -260,7 +260,7 @@ pub struct RouteContext {
|
||||
impl RouteContext {
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
tracing::instrument(level = "trace", skip_all,)
|
||||
tracing::instrument(level = "info", skip_all,)
|
||||
)]
|
||||
pub(crate) fn new(
|
||||
router: &RouterContext,
|
||||
|
||||
@@ -8,17 +8,11 @@ use cfg_if::cfg_if;
|
||||
use leptos::*;
|
||||
#[cfg(feature = "transition")]
|
||||
use leptos_reactive::use_transition;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
rc::Rc,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
use thiserror::Error;
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
static GLOBAL_ROUTERS_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
/// Provides for client-side and server-side routing. This should usually be somewhere near
|
||||
/// the root of the application.
|
||||
#[component]
|
||||
@@ -57,7 +51,6 @@ pub struct RouterContext {
|
||||
pub(crate) inner: Rc<RouterContextInner>,
|
||||
}
|
||||
pub(crate) struct RouterContextInner {
|
||||
id: usize,
|
||||
pub location: Location,
|
||||
pub base: RouteContext,
|
||||
pub possible_routes: RefCell<Option<Vec<Branch>>>,
|
||||
@@ -172,7 +165,6 @@ impl RouterContext {
|
||||
});
|
||||
|
||||
let inner = Rc::new(RouterContextInner {
|
||||
id: GLOBAL_ROUTERS_COUNT.fetch_add(1, Ordering::SeqCst),
|
||||
base_path: base_path.into_owned(),
|
||||
path_stack: store_value(vec![location.pathname.get_untracked()]),
|
||||
location,
|
||||
@@ -211,10 +203,6 @@ impl RouterContext {
|
||||
self.inner.base.clone()
|
||||
}
|
||||
|
||||
pub(crate) fn id(&self) -> usize {
|
||||
self.inner.id
|
||||
}
|
||||
|
||||
/// A list of all possible routes this router can match.
|
||||
pub fn possible_branches(&self) -> Vec<Branch> {
|
||||
self.inner
|
||||
|
||||
@@ -8,7 +8,6 @@ use crate::{
|
||||
};
|
||||
use leptos::{leptos_dom::HydrationCtx, *};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
cell::{Cell, RefCell},
|
||||
cmp::Reverse,
|
||||
collections::HashMap,
|
||||
@@ -66,7 +65,7 @@ use std::{
|
||||
/// ```
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
tracing::instrument(level = "trace", skip_all,)
|
||||
tracing::instrument(level = "info", skip_all,)
|
||||
)]
|
||||
#[component]
|
||||
pub fn Routes(
|
||||
@@ -77,16 +76,15 @@ pub fn Routes(
|
||||
) -> impl IntoView {
|
||||
let router = use_context::<RouterContext>()
|
||||
.expect("<Routes/> component should be nested within a <Router/>.");
|
||||
let router_id = router.id();
|
||||
|
||||
let base_route = router.base();
|
||||
let base = base.unwrap_or_default();
|
||||
|
||||
Branches::initialize(router_id, &base, children());
|
||||
Branches::initialize(&base, children());
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
if let Some(context) = use_context::<crate::PossibleBranchContext>() {
|
||||
Branches::with(router_id, &base, |branches| {
|
||||
Branches::with(&base, |branches| {
|
||||
*context.0.borrow_mut() = branches.to_vec()
|
||||
});
|
||||
}
|
||||
@@ -95,8 +93,7 @@ pub fn Routes(
|
||||
let current_route = next_route;
|
||||
|
||||
let root_equal = Rc::new(Cell::new(true));
|
||||
let route_states =
|
||||
route_states(router_id, base, &router, current_route, &root_equal);
|
||||
let route_states = route_states(base, &router, current_route, &root_equal);
|
||||
provide_context(route_states);
|
||||
|
||||
let id = HydrationCtx::id();
|
||||
@@ -159,16 +156,15 @@ pub fn AnimatedRoutes(
|
||||
) -> impl IntoView {
|
||||
let router = use_context::<RouterContext>()
|
||||
.expect("<Routes/> component should be nested within a <Router/>.");
|
||||
let router_id = router.id();
|
||||
|
||||
let base_route = router.base();
|
||||
let base = base.unwrap_or_default();
|
||||
|
||||
Branches::initialize(router_id, &base, children());
|
||||
Branches::initialize(&base, children());
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
if let Some(context) = use_context::<crate::PossibleBranchContext>() {
|
||||
Branches::with(router_id, &base, |branches| {
|
||||
Branches::with(&base, |branches| {
|
||||
*context.0.borrow_mut() = branches.to_vec()
|
||||
});
|
||||
}
|
||||
@@ -197,9 +193,8 @@ pub fn AnimatedRoutes(
|
||||
let prev_matches = prev
|
||||
.map(|(_, r)| r)
|
||||
.cloned()
|
||||
.map(|location| get_route_matches(router_id, &base, location));
|
||||
let matches =
|
||||
get_route_matches(router_id, &base, next_route.clone());
|
||||
.map(|location| get_route_matches(&base, location));
|
||||
let matches = get_route_matches(&base, next_route.clone());
|
||||
let same_route = prev_matches
|
||||
.and_then(|p| p.first().as_ref().map(|r| r.route.key.clone()))
|
||||
== matches.first().as_ref().map(|r| r.route.key.clone());
|
||||
@@ -226,8 +221,7 @@ pub fn AnimatedRoutes(
|
||||
let current_route = create_memo(move |_| animation_and_route.get().1);
|
||||
|
||||
let root_equal = Rc::new(Cell::new(true));
|
||||
let route_states =
|
||||
route_states(router_id, base, &router, current_route, &root_equal);
|
||||
let route_states = route_states(base, &router, current_route, &root_equal);
|
||||
|
||||
let root = root_route(base_route, route_states, root_equal);
|
||||
let node_ref = create_node_ref::<html::Div>();
|
||||
@@ -272,13 +266,12 @@ pub fn AnimatedRoutes(
|
||||
|
||||
pub(crate) struct Branches;
|
||||
|
||||
type BranchesCacheKey = (usize, Cow<'static, str>);
|
||||
thread_local! {
|
||||
static BRANCHES: RefCell<HashMap<BranchesCacheKey, Vec<Branch>>> = RefCell::new(HashMap::new());
|
||||
static BRANCHES: RefCell<HashMap<String, Vec<Branch>>> = RefCell::new(HashMap::new());
|
||||
}
|
||||
|
||||
impl Branches {
|
||||
pub fn initialize(router_id: usize, base: &str, children: Fragment) {
|
||||
pub fn initialize(base: &str, children: Fragment) {
|
||||
BRANCHES.with(|branches| {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
@@ -293,7 +286,7 @@ impl Branches {
|
||||
}
|
||||
|
||||
let mut current = branches.borrow_mut();
|
||||
if !current.contains_key(&(router_id, Cow::from(base))) {
|
||||
if !current.contains_key(base) {
|
||||
let mut branches = Vec::new();
|
||||
let children = children
|
||||
.as_children()
|
||||
@@ -323,19 +316,15 @@ impl Branches {
|
||||
true,
|
||||
base,
|
||||
);
|
||||
current.insert((router_id, Cow::Owned(base.into())), branches);
|
||||
current.insert(base.to_string(), branches);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn with<T>(
|
||||
router_id: usize,
|
||||
base: &str,
|
||||
cb: impl FnOnce(&[Branch]) -> T,
|
||||
) -> T {
|
||||
pub fn with<T>(base: &str, cb: impl FnOnce(&[Branch]) -> T) -> T {
|
||||
BRANCHES.with(|branches| {
|
||||
let branches = branches.borrow();
|
||||
let branches = branches.get(&(router_id, Cow::from(base))).expect(
|
||||
let branches = branches.get(base).expect(
|
||||
"Branches::initialize() should be called before \
|
||||
Branches::with()",
|
||||
);
|
||||
@@ -345,16 +334,14 @@ impl Branches {
|
||||
}
|
||||
|
||||
fn route_states(
|
||||
router_id: usize,
|
||||
base: String,
|
||||
router: &RouterContext,
|
||||
current_route: Memo<String>,
|
||||
root_equal: &Rc<Cell<bool>>,
|
||||
) -> Memo<RouterState> {
|
||||
// whenever path changes, update matches
|
||||
let matches = create_memo(move |_| {
|
||||
get_route_matches(router_id, &base, current_route.get())
|
||||
});
|
||||
let matches =
|
||||
create_memo(move |_| get_route_matches(&base, current_route.get()));
|
||||
|
||||
// iterate over the new matches, reusing old routes when they are the same
|
||||
// and replacing them with new routes when they differ
|
||||
@@ -630,7 +617,7 @@ pub(crate) fn create_branch(routes: &[RouteData], index: usize) -> Branch {
|
||||
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
tracing::instrument(level = "trace", skip_all,)
|
||||
tracing::instrument(level = "info", skip_all,)
|
||||
)]
|
||||
fn create_routes(
|
||||
route_def: &RouteDefinition,
|
||||
|
||||
@@ -17,7 +17,6 @@ pub(crate) struct RouteMatch {
|
||||
}
|
||||
|
||||
pub(crate) fn get_route_matches(
|
||||
router_id: usize,
|
||||
base: &str,
|
||||
location: String,
|
||||
) -> Rc<Vec<RouteMatch>> {
|
||||
@@ -25,31 +24,24 @@ pub(crate) fn get_route_matches(
|
||||
{
|
||||
use lru::LruCache;
|
||||
use std::{cell::RefCell, num::NonZeroUsize};
|
||||
type RouteMatchCache = LruCache<(usize, String), Rc<Vec<RouteMatch>>>;
|
||||
thread_local! {
|
||||
static ROUTE_MATCH_CACHE: RefCell<RouteMatchCache> = RefCell::new(LruCache::new(NonZeroUsize::new(32).unwrap()));
|
||||
static ROUTE_MATCH_CACHE: RefCell<LruCache<String, Rc<Vec<RouteMatch>>>> = RefCell::new(LruCache::new(NonZeroUsize::new(32).unwrap()));
|
||||
}
|
||||
|
||||
ROUTE_MATCH_CACHE.with(|cache| {
|
||||
let mut cache = cache.borrow_mut();
|
||||
Rc::clone(
|
||||
cache.get_or_insert((router_id, location.clone()), || {
|
||||
build_route_matches(router_id, base, location)
|
||||
}),
|
||||
)
|
||||
Rc::clone(cache.get_or_insert(location.clone(), || {
|
||||
build_route_matches(base, location)
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
build_route_matches(router_id, base, location)
|
||||
build_route_matches(base, location)
|
||||
}
|
||||
|
||||
fn build_route_matches(
|
||||
router_id: usize,
|
||||
base: &str,
|
||||
location: String,
|
||||
) -> Rc<Vec<RouteMatch>> {
|
||||
Rc::new(Branches::with(router_id, base, |branches| {
|
||||
fn build_route_matches(base: &str, location: String) -> Rc<Vec<RouteMatch>> {
|
||||
Rc::new(Branches::with(base, |branches| {
|
||||
for branch in branches {
|
||||
if let Some(matches) = branch.matcher(&location) {
|
||||
return matches;
|
||||
|
||||
Reference in New Issue
Block a user