From b0a2c89a6183412b1af30a8f06b45976c519e4ac Mon Sep 17 00:00:00 2001 From: Fisch03 Date: Wed, 24 Apr 2024 02:55:28 +0200 Subject: [PATCH] benches, improve docs a lot --- docs/fishnet/all.html | 2 +- docs/fishnet/attr.component.html | 2 +- docs/fishnet/component/fake_macros/index.html | 1 - .../component/fake_macros/macro.state.html | 14 +- .../fake_macros/macro.state_init.html | 14 +- .../component/fake_macros/sidebar-items.js | 1 - docs/fishnet/component/index.html | 4 +- .../component/prelude/attr.component.html | 2 +- docs/fishnet/component/prelude/index.html | 2 +- docs/fishnet/component/prelude/macro.c.html | 2 +- .../fishnet/component/prelude/macro.html.html | 6 +- .../component/prelude/macro.script.html | 8 +- .../component/prelude/macro.state!.html | 11 + .../component/prelude/macro.state.html | 3 + .../component/prelude/macro.state_init!.html | 11 + .../component/prelude/macro.state_init.html | 3 + .../component/prelude/macro.style.html | 30 ++- .../prelude/routing/struct.Router.html | 10 +- .../component/prelude/sidebar-items.js | 2 +- docs/fishnet/component/sidebar-items.js | 2 +- docs/fishnet/component/struct.Component.html | 18 +- .../component/struct.ComponentState.html | 12 +- .../component/type.ComponentRunner.html | 2 +- docs/fishnet/css/index.html | 2 +- docs/fishnet/css/struct.Stylesheet.html | 4 +- docs/fishnet/index.html | 21 +- docs/fishnet/macro.c.html | 2 +- docs/fishnet/macro.script.html | 8 +- docs/fishnet/macro.style.html | 30 ++- docs/fishnet/page/index.html | 2 + .../page/render_context/fn.enter_page.html | 5 + .../fn.enter_temporary_render.html | 8 + .../page/render_context/fn.exit_page.html | 5 + .../fn.exit_temporary_render.html | 5 + .../page/render_context/fn.global_store.html | 2 + .../render_context/fn.render_component.html | 13 + docs/fishnet/page/render_context/index.html | 12 + .../page/render_context/sidebar-items.js | 1 + .../render_context/struct.GlobalStore.html | 25 ++ .../struct.GlobalStoreEntry.html | 21 ++ .../render_context/struct.RenderResult.html | 28 +++ docs/fishnet/page/sidebar-items.js | 1 + .../struct.BuiltPage.html} | 9 +- docs/fishnet/page/struct.Page.html | 35 ++- docs/fishnet/page/trait.RouterPageExt.html | 18 ++ docs/fishnet/sidebar-items.js | 2 +- docs/fishnet/struct.Website.html | 4 +- docs/search-index.js | 2 +- docs/search.desc/fishnet/fishnet-desc-0-.js | 2 +- docs/src/fishnet/component.rs.html | 4 +- docs/src/fishnet/component/prelude.rs.html | 10 +- docs/src/fishnet/css.rs.html | 2 + docs/src/fishnet/lib.rs.html | 14 +- docs/src/fishnet/page.rs.html | 10 +- docs/src/fishnet/page/render_context.rs.html | 184 +++++++++++--- docs/trait.impl/core/fmt/trait.Debug.js | 2 +- docs/trait.impl/core/marker/trait.Freeze.js | 2 +- docs/trait.impl/core/marker/trait.Send.js | 2 +- docs/trait.impl/core/marker/trait.Sync.js | 2 +- docs/trait.impl/core/marker/trait.Unpin.js | 2 +- .../panic/unwind_safe/trait.RefUnwindSafe.js | 2 +- .../panic/unwind_safe/trait.UnwindSafe.js | 2 +- .../fishnet/page/trait.RouterPageExt.js | 3 + fishnet-macros/src/lib.rs | 2 - fishnet/benches/rendering.rs | 227 +++++++++++++++--- fishnet/src/component.rs | 1 + fishnet/src/component/prelude.rs | 8 +- fishnet/src/css.rs | 1 + fishnet/src/lib.rs | 6 +- fishnet/src/page/render_context.rs | 120 ++++++--- fishnet/tests/test_component.rs | 2 +- 71 files changed, 798 insertions(+), 239 deletions(-) delete mode 100644 docs/fishnet/component/fake_macros/index.html delete mode 100644 docs/fishnet/component/fake_macros/sidebar-items.js create mode 100644 docs/fishnet/component/prelude/macro.state!.html create mode 100644 docs/fishnet/component/prelude/macro.state.html create mode 100644 docs/fishnet/component/prelude/macro.state_init!.html create mode 100644 docs/fishnet/component/prelude/macro.state_init.html create mode 100644 docs/fishnet/page/index.html create mode 100644 docs/fishnet/page/render_context/fn.enter_page.html create mode 100644 docs/fishnet/page/render_context/fn.enter_temporary_render.html create mode 100644 docs/fishnet/page/render_context/fn.exit_page.html create mode 100644 docs/fishnet/page/render_context/fn.exit_temporary_render.html create mode 100644 docs/fishnet/page/render_context/fn.global_store.html create mode 100644 docs/fishnet/page/render_context/fn.render_component.html create mode 100644 docs/fishnet/page/render_context/index.html create mode 100644 docs/fishnet/page/render_context/sidebar-items.js create mode 100644 docs/fishnet/page/render_context/struct.GlobalStore.html create mode 100644 docs/fishnet/page/render_context/struct.GlobalStoreEntry.html create mode 100644 docs/fishnet/page/render_context/struct.RenderResult.html create mode 100644 docs/fishnet/page/sidebar-items.js rename docs/fishnet/{struct.Page.html => page/struct.BuiltPage.html} (57%) create mode 100644 docs/fishnet/page/trait.RouterPageExt.html create mode 100644 docs/trait.impl/fishnet/page/trait.RouterPageExt.js diff --git a/docs/fishnet/all.html b/docs/fishnet/all.html index ded0868..ff32d91 100644 --- a/docs/fishnet/all.html +++ b/docs/fishnet/all.html @@ -1 +1 @@ -List of all items in this crate

List of all items

Structs

Enums

Traits

Macros

Attribute Macros

Functions

Type Aliases

\ No newline at end of file +List of all items in this crate

List of all items

Structs

Enums

Traits

Macros

Attribute Macros

Functions

Type Aliases

\ No newline at end of file diff --git a/docs/fishnet/attr.component.html b/docs/fishnet/attr.component.html index 09cf80b..acaa5b9 100644 --- a/docs/fishnet/attr.component.html +++ b/docs/fishnet/attr.component.html @@ -2,7 +2,7 @@

it is highly recommended to use this instead of constructing a Component manually.

you use this to decorate any async function that returns a Markup and it will be turned into a Component for you. you can use the style! and script! macros anywhere in the function to add css and javascript to the component. -there are two macros to add state to the component - state! and state_init!. state +there are two macros to add state to the component - state! and state_init!. state takes in a type and uses the std::default::Default implementation to create the initial state. if you want some more control like initializing the state from function parameters, you can use the state_init! macro instead.

diff --git a/docs/fishnet/component/fake_macros/index.html b/docs/fishnet/component/fake_macros/index.html deleted file mode 100644 index 986cf5e..0000000 --- a/docs/fishnet/component/fake_macros/index.html +++ /dev/null @@ -1 +0,0 @@ -fishnet::component::fake_macros - Rust

Module fishnet::component::fake_macros

source ·

Macros§

\ No newline at end of file diff --git a/docs/fishnet/component/fake_macros/macro.state.html b/docs/fishnet/component/fake_macros/macro.state.html index 4557530..d8fa19d 100644 --- a/docs/fishnet/component/fake_macros/macro.state.html +++ b/docs/fishnet/component/fake_macros/macro.state.html @@ -1,3 +1,11 @@ -state in fishnet::component::fake_macros - Rust

Macro fishnet::component::fake_macros::state

source ·
macro_rules! state {
-    ($($tt:tt)*) => { ... };
-}
\ No newline at end of file + + + + + Redirection + + +

Redirecting to ../../../fishnet/component/prelude/macro.state.html...

+ + + \ No newline at end of file diff --git a/docs/fishnet/component/fake_macros/macro.state_init.html b/docs/fishnet/component/fake_macros/macro.state_init.html index 8c294fd..4f52999 100644 --- a/docs/fishnet/component/fake_macros/macro.state_init.html +++ b/docs/fishnet/component/fake_macros/macro.state_init.html @@ -1,3 +1,11 @@ -state_init in fishnet::component::fake_macros - Rust

Macro fishnet::component::fake_macros::state_init

source ·
macro_rules! state_init {
-    ($($tt:tt)*) => { ... };
-}
\ No newline at end of file + + + + + Redirection + + +

Redirecting to ../../../fishnet/component/prelude/macro.state_init.html...

+ + + \ No newline at end of file diff --git a/docs/fishnet/component/fake_macros/sidebar-items.js b/docs/fishnet/component/fake_macros/sidebar-items.js deleted file mode 100644 index 1399e84..0000000 --- a/docs/fishnet/component/fake_macros/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"macro":["state","state_init"]}; \ No newline at end of file diff --git a/docs/fishnet/component/index.html b/docs/fishnet/component/index.html index 096b68e..ba6ec3f 100644 --- a/docs/fishnet/component/index.html +++ b/docs/fishnet/component/index.html @@ -1,2 +1,2 @@ -fishnet::component - Rust

Module fishnet::component

source ·
Expand description

reusable components for building web pages (aka the main thing)

-

Modules§

Structs§

Traits§

Type Aliases§

\ No newline at end of file +fishnet::component - Rust

Module fishnet::component

source ·
Expand description

reusable components for building web pages (aka the main thing)

+

Modules§

  • commonly used imports for building components.

Structs§

Traits§

Type Aliases§

\ No newline at end of file diff --git a/docs/fishnet/component/prelude/attr.component.html b/docs/fishnet/component/prelude/attr.component.html index 6b84b53..fc02e13 100644 --- a/docs/fishnet/component/prelude/attr.component.html +++ b/docs/fishnet/component/prelude/attr.component.html @@ -2,7 +2,7 @@

it is highly recommended to use this instead of constructing a Component manually.

you use this to decorate any async function that returns a Markup and it will be turned into a Component for you. you can use the style! and script! macros anywhere in the function to add css and javascript to the component. -there are two macros to add state to the component - state! and state_init!. state +there are two macros to add state to the component - state! and state_init!. state takes in a type and uses the std::default::Default implementation to create the initial state. if you want some more control like initializing the state from function parameters, you can use the state_init! macro instead.

diff --git a/docs/fishnet/component/prelude/index.html b/docs/fishnet/component/prelude/index.html index ba4a0d8..f378106 100644 --- a/docs/fishnet/component/prelude/index.html +++ b/docs/fishnet/component/prelude/index.html @@ -1,5 +1,5 @@ fishnet::component::prelude - Rust

Module fishnet::component::prelude

source ·
Expand description

commonly used imports for building components.

-

Re-exports§

Modules§

  • Routing between [Service]s and handlers.

Macros§

  • add components to the page.
  • macro for generating a StyleFragment from css.
  • add js to the page from outside a component.
  • add css to the page from outside a component.

Structs§

  • A thread-safe reference-counting pointer. ‘Arc’ stands for ‘Atomically +

    Re-exports§

    Modules§

    • Routing between [Service]s and handlers.

    Macros§

    Structs§

    • A thread-safe reference-counting pointer. ‘Arc’ stands for ‘Atomically Reference Counted’.
    • Extractor and response for extensions.
    • An asynchronous Mutex-like type.

    Traits§

    • An extension trait for Futures that provides a variety of convenient adapters.
    • Represents a type that can be rendered as HTML.

    Type Aliases§

    • An owned dynamically typed Future for use in cases where you can’t statically type your result or need to add some indirection.
    • A block of markup is a string that does not need to be escaped.

    Attribute Macros§

\ No newline at end of file diff --git a/docs/fishnet/component/prelude/macro.c.html b/docs/fishnet/component/prelude/macro.c.html index ef49032..554474f 100644 --- a/docs/fishnet/component/prelude/macro.c.html +++ b/docs/fishnet/component/prelude/macro.c.html @@ -1,4 +1,4 @@ -c in fishnet::component::prelude - Rust

Macro fishnet::component::prelude::c

source ·
macro_rules! c {
+c in fishnet::component::prelude - Rust

Macro fishnet::component::prelude::c

source ·
macro_rules! c {
     ($component:expr) => { ... };
 }
Expand description

add components to the page.

This is done by wrapping the component in a c! macro. The component will then be diff --git a/docs/fishnet/component/prelude/macro.html.html b/docs/fishnet/component/prelude/macro.html.html index e5b2110..ec54b27 100644 --- a/docs/fishnet/component/prelude/macro.html.html +++ b/docs/fishnet/component/prelude/macro.html.html @@ -1 +1,5 @@ -html in fishnet::component::prelude - Rust

Macro fishnet::component::prelude::html

source ·
html!() { /* proc-macro */ }
\ No newline at end of file +html in fishnet::component::prelude - Rust

Macro fishnet::component::prelude::html

source ·
html!() { /* proc-macro */ }
Expand description

macro for generating Markup from html.

+

this is just a reexport of the html! macro from the maud crate.

+

note: due to the way this macro works, you will still need to add maud as a dependency to your project. +it’s just here for convenience.

+
\ No newline at end of file diff --git a/docs/fishnet/component/prelude/macro.script.html b/docs/fishnet/component/prelude/macro.script.html index 6c3a78e..888adb2 100644 --- a/docs/fishnet/component/prelude/macro.script.html +++ b/docs/fishnet/component/prelude/macro.script.html @@ -1,8 +1,8 @@ -script in fishnet::component::prelude - Rust

Macro fishnet::component::prelude::script

source ·
macro_rules! script {
+script in fishnet::component::prelude - Rust

Macro fishnet::component::prelude::script

source ·
macro_rules! script {
     ($js:literal) => { ... };
-}
Expand description

add js to the page from outside a component.

-

this is helpful for adding styling to functions that just return Markup. -you have to call this from within a page render or the js will not be added to the page.

+}
Expand description

add js to the page

+

differently to the css! macro, this will work identically whether you are within a +component or not. you still have to be within a page render though or it will do nothing.

§usage

use fishnet::{script, html, Markup};
 async fn render_something() -> Markup {
diff --git a/docs/fishnet/component/prelude/macro.state!.html b/docs/fishnet/component/prelude/macro.state!.html
new file mode 100644
index 0000000..9029a35
--- /dev/null
+++ b/docs/fishnet/component/prelude/macro.state!.html
@@ -0,0 +1,11 @@
+
+
+
+    
+    Redirection
+
+
+    

Redirecting to macro.state.html...

+ + + \ No newline at end of file diff --git a/docs/fishnet/component/prelude/macro.state.html b/docs/fishnet/component/prelude/macro.state.html new file mode 100644 index 0000000..cd842de --- /dev/null +++ b/docs/fishnet/component/prelude/macro.state.html @@ -0,0 +1,3 @@ +state in fishnet::component::prelude - Rust

Macro fishnet::component::prelude::state

source ·
macro_rules! state {
+    ($($tt:tt)*) => { ... };
+}
\ No newline at end of file diff --git a/docs/fishnet/component/prelude/macro.state_init!.html b/docs/fishnet/component/prelude/macro.state_init!.html new file mode 100644 index 0000000..05a81f3 --- /dev/null +++ b/docs/fishnet/component/prelude/macro.state_init!.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to macro.state_init.html...

+ + + \ No newline at end of file diff --git a/docs/fishnet/component/prelude/macro.state_init.html b/docs/fishnet/component/prelude/macro.state_init.html new file mode 100644 index 0000000..8eeacaa --- /dev/null +++ b/docs/fishnet/component/prelude/macro.state_init.html @@ -0,0 +1,3 @@ +state_init in fishnet::component::prelude - Rust

Macro fishnet::component::prelude::state_init

source ·
macro_rules! state_init {
+    ($($tt:tt)*) => { ... };
+}
\ No newline at end of file diff --git a/docs/fishnet/component/prelude/macro.style.html b/docs/fishnet/component/prelude/macro.style.html index 594e674..9cdd952 100644 --- a/docs/fishnet/component/prelude/macro.style.html +++ b/docs/fishnet/component/prelude/macro.style.html @@ -1,16 +1,34 @@ -style in fishnet::component::prelude - Rust

Macro fishnet::component::prelude::style

source ·
macro_rules! style {
+style in fishnet::component::prelude - Rust

Macro fishnet::component::prelude::style

source ·
macro_rules! style {
+    ($css: expr) => { ... };
     ($tl_class: literal, $css:expr) => { ... };
-}
Expand description

add css to the page from outside a component.

-

this is helpful for adding styling to functions that just return Markup. -you have to call this from within a page render or the css will not be added to the page.

-

§usage

+}
Expand description

add css to the page

+

you have to call this from within a page render or it will not work.

+

there are two ways to use this macro:

+

§from within a component

+
use fishnet::component::prelude::*;
+
+#[component]
+async fn my_component() {
+    style!(css!{
+        color: red;
+    });
+
+    html! {
+        "hello world!"
+    }
+}
+

§from outside a component

+

additionally to providing the style, you also have to name the top level class yourself as the +first argument.

+

this is helpful for adding styling to functions that just return Markup.

+
use fishnet::{style, html, Markup, css};
 
 async fn render_something() -> Markup {
     style!("my_class", css!{
         color: red;
     });
-     
+    
     html!{
         div class="my_class" {
             "hello world!"
diff --git a/docs/fishnet/component/prelude/routing/struct.Router.html b/docs/fishnet/component/prelude/routing/struct.Router.html
index 51a10df..e9a1943 100644
--- a/docs/fishnet/component/prelude/routing/struct.Router.html
+++ b/docs/fishnet/component/prelude/routing/struct.Router.html
@@ -1,4 +1,4 @@
-Router in fishnet::component::prelude::routing - Rust

Struct fishnet::component::prelude::routing::Router

pub struct Router<S = ()> { /* private fields */ }
Expand description

The router type for composing handlers and services.

+Router in fishnet::component::prelude::routing - Rust

Struct fishnet::component::prelude::routing::Router

pub struct Router<S = ()> { /* private fields */ }
Expand description

The router type for composing handlers and services.

Implementations§

§

impl<S> Router<S>
where S: Clone + Send + Sync + 'static,

pub fn new() -> Router<S>

Create a new Router.

Unless you add additional routes this will respond with 404 Not Found to @@ -784,7 +784,13 @@

unix domain socket example for an example of how to use this to collect UDS connection info.

Trait Implementations§

§

impl<S> Clone for Router<S>

§

fn clone(&self) -> Router<S>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl<S> Debug for Router<S>

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl<S> Default for Router<S>
where - S: Clone + Send + Sync + 'static,

§

fn default() -> Router<S>

Returns the “default value” for a type. Read more
§

impl Service<IncomingStream<'_>> for Router

§

type Response = Router

Responses given by the service.
§

type Error = Infallible

Errors produced by the service.
§

type Future = Ready<Result<<Router as Service<IncomingStream<'_>>>::Response, <Router as Service<IncomingStream<'_>>>::Error>>

The future response value.
§

fn poll_ready( + S: Clone + Send + Sync + 'static,

§

fn default() -> Router<S>

Returns the “default value” for a type. Read more
source§

impl RouterPageExt for Router

source§

fn attach_page<'life0, 'async_trait>( + self, + path: &'life0 str, + page: Page +) -> Pin<Box<dyn Future<Output = Self> + Send + 'async_trait>>
where + Self: 'async_trait, + 'life0: 'async_trait,

Attach the given page to the router. This involves building the page and adding multiple routes for the api, scripts and content.
§

impl Service<IncomingStream<'_>> for Router

§

type Response = Router

Responses given by the service.
§

type Error = Infallible

Errors produced by the service.
§

type Future = Ready<Result<<Router as Service<IncomingStream<'_>>>::Response, <Router as Service<IncomingStream<'_>>>::Error>>

The future response value.
§

fn poll_ready( &mut self, _cx: &mut Context<'_> ) -> Poll<Result<(), <Router as Service<IncomingStream<'_>>>::Error>>

Returns Poll::Ready(Ok(())) when the service is able to process requests. Read more
§

fn call( diff --git a/docs/fishnet/component/prelude/sidebar-items.js b/docs/fishnet/component/prelude/sidebar-items.js index 33d949f..cc2cec3 100644 --- a/docs/fishnet/component/prelude/sidebar-items.js +++ b/docs/fishnet/component/prelude/sidebar-items.js @@ -1 +1 @@ -window.SIDEBAR_ITEMS = {"attr":["component","dyn_component"],"macro":["c","css","html","script","style"],"mod":["routing"],"struct":["Arc","Extension","Mutex"],"trait":["FutureExt","Render"],"type":["BoxFuture","Markup"]}; \ No newline at end of file +window.SIDEBAR_ITEMS = {"attr":["component","dyn_component"],"macro":["c","css","html","script","state","state_init","style"],"mod":["routing"],"struct":["Arc","Extension","Mutex"],"trait":["FutureExt","Render"],"type":["BoxFuture","Markup"]}; \ No newline at end of file diff --git a/docs/fishnet/component/sidebar-items.js b/docs/fishnet/component/sidebar-items.js index 5a055cb..655a0fe 100644 --- a/docs/fishnet/component/sidebar-items.js +++ b/docs/fishnet/component/sidebar-items.js @@ -1 +1 @@ -window.SIDEBAR_ITEMS = {"mod":["fake_macros","prelude"],"struct":["BuiltComponent","Component","ComponentBuildResult","ComponentState"],"trait":["BuildableComponent"],"type":["ComponentRunner"]}; \ No newline at end of file +window.SIDEBAR_ITEMS = {"mod":["prelude"],"struct":["BuiltComponent","Component","ComponentBuildResult","ComponentState"],"trait":["BuildableComponent"],"type":["ComponentRunner"]}; \ No newline at end of file diff --git a/docs/fishnet/component/struct.Component.html b/docs/fishnet/component/struct.Component.html index 45c4c1e..46cf64d 100644 --- a/docs/fishnet/component/struct.Component.html +++ b/docs/fishnet/component/struct.Component.html @@ -1,17 +1,17 @@ -Component in fishnet::component - Rust

Struct fishnet::component::Component

source ·
pub struct Component<R, S, ST>
where - ST: Clone + Send + Sync,
{ /* private fields */ }

Implementations§

source§

impl Component<NoRenderer, NoState, ()>

source

pub fn new(name: &str, id: &str) -> Component<NoRenderer, NoState, ()>

source§

impl<R, S, ST> Component<R, S, ST>
where - ST: Clone + Send + Sync,

source

pub fn name(&self) -> &str

source

pub fn add_script(self, script: ScriptType) -> Self

source

pub fn style(self, style: StyleFragment<'static>) -> Self

source

pub fn route(self, path: &str, route: MethodRouter) -> Component<R, S, ST>

source

pub fn nest_service<T>(self, path: &str, service: T) -> Self
where +Component in fishnet::component - Rust

Struct fishnet::component::Component

source ·
pub struct Component<R, S, ST>
where + ST: Clone + Send + Sync,
{ /* private fields */ }

Implementations§

source§

impl Component<NoRenderer, NoState, ()>

source

pub fn new(name: &str, id: &str) -> Component<NoRenderer, NoState, ()>

source§

impl<R, S, ST> Component<R, S, ST>
where + ST: Clone + Send + Sync,

source

pub fn name(&self) -> &str

source

pub fn add_script(self, script: ScriptType) -> Self

source

pub fn style(self, style: StyleFragment<'static>) -> Self

source

pub fn route(self, path: &str, route: MethodRouter) -> Component<R, S, ST>

source

pub fn nest_service<T>(self, path: &str, service: T) -> Self
where T: Service<Request<Body>, Error = Infallible> + Clone + Send + 'static, T::Response: IntoResponse, - T::Future: Send + 'static,

source§

impl<S, ST> Component<NoRenderer, S, ST>
where + T::Future: Send + 'static,

source§

impl<S, ST> Component<NoRenderer, S, ST>
where ST: Clone + Send + Sync, - S: Send + Sync + 'static,

source

pub fn render<C>(self, renderer: C) -> impl BuildableComponent
where + S: Send + Sync + 'static,

source

pub fn render<C>(self, renderer: C) -> impl BuildableComponent
where ST: Clone + Send + Sync + 'static, - C: Fn(ComponentState<ST>) -> BoxFuture<'static, Markup> + Send + Sync + 'static,

source

pub fn render_dynamic<C>(self, renderer: C) -> impl BuildableComponent
where + C: Fn(ComponentState<ST>) -> BoxFuture<'static, Markup> + Send + Sync + 'static,

source

pub fn render_dynamic<C>(self, renderer: C) -> impl BuildableComponent
where ST: Clone + Send + Sync + 'static, - C: Fn(ComponentState<ST>) -> BoxFuture<'static, Markup> + Send + Sync + 'static,

source§

impl<R> Component<R, FixedNoState, ()>

source

pub fn with_runner<F>(self, runner: ComponentRunner<()>) -> Self

source§

impl<R, ST> Component<R, HasState, ST>
where - ST: Clone + Send + Sync + 'static,

source

pub fn with_runner<F>(self, runner: F) -> Self
where - F: FnOnce(ComponentState<ST>) -> BoxFuture<'static, ()> + Send + Sync + 'static,

source§

impl<R> Component<R, NoState, ()>

source

pub fn with_state<ST>(self, state: ST) -> Component<NoRenderer, HasState, ST>
where + C: Fn(ComponentState<ST>) -> BoxFuture<'static, Markup> + Send + Sync + 'static,

source§

impl<R> Component<R, FixedNoState, ()>

source

pub fn with_runner<F>(self, runner: ComponentRunner<()>) -> Self

source§

impl<R, ST> Component<R, HasState, ST>
where + ST: Clone + Send + Sync + 'static,

source

pub fn with_runner<F>(self, runner: F) -> Self
where + F: FnOnce(ComponentState<ST>) -> BoxFuture<'static, ()> + Send + Sync + 'static,

source§

impl<R> Component<R, NoState, ()>

source

pub fn with_state<ST>(self, state: ST) -> Component<NoRenderer, HasState, ST>
where ST: Clone + Send + Sync + 'static,

Add state to the component. Since the state will be passed around a lot, it should be cheap to clone. This usually means wrapping it in an Arc or similar.

diff --git a/docs/fishnet/component/struct.ComponentState.html b/docs/fishnet/component/struct.ComponentState.html index d42555d..a4788d5 100644 --- a/docs/fishnet/component/struct.ComponentState.html +++ b/docs/fishnet/component/struct.ComponentState.html @@ -1,9 +1,9 @@ -ComponentState in fishnet::component - Rust

Struct fishnet::component::ComponentState

source ·
pub struct ComponentState<ST>
where - ST: Clone + Send + Sync,
{ /* private fields */ }

Implementations§

source§

impl<ST> ComponentState<ST>
where - ST: Clone + Send + Sync,

source

pub fn endpoint(&self) -> &str

Trait Implementations§

source§

impl<ST> Clone for ComponentState<ST>
where - ST: Clone + Send + Sync + Clone,

source§

fn clone(&self) -> ComponentState<ST>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<ST> Debug for ComponentState<ST>
where - ST: Clone + Send + Sync + Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<ST> Deref for ComponentState<ST>
where - ST: Clone + Send + Sync,

§

type Target = ST

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.

Auto Trait Implementations§

§

impl<ST> Freeze for ComponentState<ST>
where +ComponentState in fishnet::component - Rust

Struct fishnet::component::ComponentState

source ·
pub struct ComponentState<ST>
where + ST: Clone + Send + Sync,
{ /* private fields */ }

Implementations§

source§

impl<ST> ComponentState<ST>
where + ST: Clone + Send + Sync,

source

pub fn endpoint(&self) -> &str

Trait Implementations§

source§

impl<ST> Clone for ComponentState<ST>
where + ST: Clone + Send + Sync + Clone,

source§

fn clone(&self) -> ComponentState<ST>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<ST> Debug for ComponentState<ST>
where + ST: Clone + Send + Sync + Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<ST> Deref for ComponentState<ST>
where + ST: Clone + Send + Sync,

§

type Target = ST

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.

Auto Trait Implementations§

§

impl<ST> Freeze for ComponentState<ST>
where ST: Freeze,

§

impl<ST> RefUnwindSafe for ComponentState<ST>
where ST: RefUnwindSafe,

§

impl<ST> Send for ComponentState<ST>

§

impl<ST> Sync for ComponentState<ST>

§

impl<ST> Unpin for ComponentState<ST>
where ST: Unpin,

§

impl<ST> UnwindSafe for ComponentState<ST>
where diff --git a/docs/fishnet/component/type.ComponentRunner.html b/docs/fishnet/component/type.ComponentRunner.html index 0b9dfc2..d418b6e 100644 --- a/docs/fishnet/component/type.ComponentRunner.html +++ b/docs/fishnet/component/type.ComponentRunner.html @@ -1 +1 @@ -ComponentRunner in fishnet::component - Rust

Type Alias fishnet::component::ComponentRunner

source ·
pub type ComponentRunner<ST> = Box<dyn FnOnce(ComponentState<ST>) -> BoxFuture<'static, ()> + Send + Sync + 'static>;

Aliased Type§

struct ComponentRunner<ST>(/* private fields */);
\ No newline at end of file +ComponentRunner in fishnet::component - Rust

Type Alias fishnet::component::ComponentRunner

source ·
pub type ComponentRunner<ST> = Box<dyn FnOnce(ComponentState<ST>) -> BoxFuture<'static, ()> + Send + Sync + 'static>;

Aliased Type§

struct ComponentRunner<ST>(/* private fields */);
\ No newline at end of file diff --git a/docs/fishnet/css/index.html b/docs/fishnet/css/index.html index d38325e..6d20233 100644 --- a/docs/fishnet/css/index.html +++ b/docs/fishnet/css/index.html @@ -1,2 +1,2 @@ -fishnet::css - Rust

Module fishnet::css

source ·
Expand description

data structures and functions for dealing with css

+fishnet::css - Rust

Module fishnet::css

source ·
Expand description

data structures and functions for dealing with css

Structs§

\ No newline at end of file diff --git a/docs/fishnet/css/struct.Stylesheet.html b/docs/fishnet/css/struct.Stylesheet.html index cf96569..2636509 100644 --- a/docs/fishnet/css/struct.Stylesheet.html +++ b/docs/fishnet/css/struct.Stylesheet.html @@ -1,7 +1,7 @@ -Stylesheet in fishnet::css - Rust

Struct fishnet::css::Stylesheet

source ·
pub struct Stylesheet { /* private fields */ }
Expand description

a full css stylesheet

+Stylesheet in fishnet::css - Rust

Struct fishnet::css::Stylesheet

source ·
pub struct Stylesheet { /* private fields */ }
Expand description

a full css stylesheet

a stylesheet is basically just a collection of RenderedStyles. however it caches all its renders, so you can only add to it and never remove things.

-

Implementations§

source§

impl Stylesheet

source

pub fn new() -> Self

source

pub fn add(&mut self, rendered: &RenderedStyle)

source

pub fn render(&mut self) -> String

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where +

Implementations§

source§

impl Stylesheet

source

pub fn new() -> Self

source

pub fn add(&mut self, rendered: &RenderedStyle)

source

pub fn render(&mut self) -> String

Trait Implementations§

source§

impl Debug for Stylesheet

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

diff --git a/docs/fishnet/index.html b/docs/fishnet/index.html index 396b9c4..282a008 100644 --- a/docs/fishnet/index.html +++ b/docs/fishnet/index.html @@ -1,4 +1,4 @@ -fishnet - Rust

Crate fishnet

source ·
Expand description

fishnet is a opinionated, performant web framework for small projects and personal websites where htmx is a first class citizen.

+fishnet - Rust

Crate fishnet

source ·
Expand description

fishnet is a opinionated, performant web framework for small projects and personal websites where htmx is a first class citizen.

§overview

fishnet aims to provide abstractions for splitting your page into components, while trying to stay as close as possible to the served content. no virtual dom, giant javascript bundles or complex build steps. @@ -10,7 +10,7 @@

§overview

  • and most importantly: you are fine with using a library that probably isn’t going to get a lot of maintenance.
  • §getting started

    §creating a page

    -

    to get started with fishnet, you need to create a new Website and add a Page to it. +

    to get started with fishnet, you need to create a new Website and add a Page to it. you can then use the html! (see the maud documentation for more info) macro to create the content of the page.

    use futures::future::FutureExt;
    @@ -79,10 +79,10 @@ 

    §u

    let’s break down what’s happening here: the my_awesome_button function is decorated with #[component]. this makes it a component. inside, we first need to create a new component state to save the parameters -for future use. this is done using either the state! or state_init! macros. the -state! macro will just take in the type of the state and use its +for future use. this is done using either the state! or state_init! macros. the +state! macro will just take in the type of the state and use its Default implementation to initialize it. if you want to use the -functions parameters to initialize the state, you need to use the state_init macro. you can +functions parameters to initialize the state, you need to use the state_init macro. you can put an arbitrary code block in it and its return value will be used as the components state. this is the only place where you can access the function parameters!

    on the page itself, we use the c! macro to add the component to the page. this handles all the behind the scenes work of building and rendering the component, and caching it for future use. @@ -151,11 +151,14 @@

    §htmx

    #[component] fn awesome_htmx_btn() { + #[route("/", POST)] - async fn click_endpoint(state: Extension<_>) -> Markup { + async fn click_endpoint(state: Extension<ComponentState<()>>) -> Markup { html! { "hiiii!!" } } + // just leave the state empty + let state = state!(()); html! { button hx-post=(state.endpoint()) hx-swap="outerHTML" { "click me" @@ -204,8 +207,8 @@

    §styling

    > div is perfectly valid. it selects all the divs that are direct children of the component. this also means that a selector like * will only affect the components children. -

    if you want to style a specific child component, its class name will always be derived from the -type you put into the component! macro (e.g. “SomeChild” becomes +

    if you want to style a specific child component, its css class name will always be derived from the +components function name when using the component macro (e.g. “some_child” becomes “some-child”). this also means that conflicts can occur if you use the same name multiple times, choose your names wisely…

    §javascript

    @@ -215,4 +218,4 @@

    §javascriptExternal file. All loaded scripts will be bundled into one and minified if you use the optional minify-js crate feature (note that this will use esbuild internally, so you need to have go installed on your system.)

    -

    Modules§

    • reusable components for building web pages (aka the main thing)
    • data structures and functions for dealing with css
    • data structures and functions for dealing with js

    Macros§

    Structs§

    • A page represents a visitable route on the website.
    • A simple website builder. A Website consists of multiple Pages and can additionally serve static files.

    Type Aliases§

    • A block of markup is a string that does not need to be escaped.

    Attribute Macros§

    \ No newline at end of file +

    Re-exports§

    Modules§

    • reusable components for building web pages (aka the main thing)
    • data structures and functions for dealing with css
    • data structures and functions for dealing with js
    • A visitable page on the Website.

    Macros§

    Structs§

    • A simple website builder. A Website consists of multiple Pages and can additionally serve static files.

    Type Aliases§

    • A block of markup is a string that does not need to be escaped.

    Attribute Macros§

    \ No newline at end of file diff --git a/docs/fishnet/macro.c.html b/docs/fishnet/macro.c.html index b94ab77..7d51f04 100644 --- a/docs/fishnet/macro.c.html +++ b/docs/fishnet/macro.c.html @@ -1,4 +1,4 @@ -c in fishnet - Rust

    Macro fishnet::c

    source ·
    macro_rules! c {
    +c in fishnet - Rust

    Macro fishnet::c

    source ·
    macro_rules! c {
         ($component:expr) => { ... };
     }
    Expand description

    add components to the page.

    This is done by wrapping the component in a c! macro. The component will then be diff --git a/docs/fishnet/macro.script.html b/docs/fishnet/macro.script.html index 0564e3f..26cd5e0 100644 --- a/docs/fishnet/macro.script.html +++ b/docs/fishnet/macro.script.html @@ -1,8 +1,8 @@ -script in fishnet - Rust

    Macro fishnet::script

    source ·
    macro_rules! script {
    +script in fishnet - Rust

    Macro fishnet::script

    source ·
    macro_rules! script {
         ($js:literal) => { ... };
    -}
    Expand description

    add js to the page from outside a component.

    -

    this is helpful for adding styling to functions that just return Markup. -you have to call this from within a page render or the js will not be added to the page.

    +}
    Expand description

    add js to the page

    +

    differently to the css! macro, this will work identically whether you are within a +component or not. you still have to be within a page render though or it will do nothing.

    §usage

    use fishnet::{script, html, Markup};
     async fn render_something() -> Markup {
    diff --git a/docs/fishnet/macro.style.html b/docs/fishnet/macro.style.html
    index 90b2f9d..b11a1c3 100644
    --- a/docs/fishnet/macro.style.html
    +++ b/docs/fishnet/macro.style.html
    @@ -1,16 +1,34 @@
    -style in fishnet - Rust

    Macro fishnet::style

    source ·
    macro_rules! style {
    +style in fishnet - Rust

    Macro fishnet::style

    source ·
    macro_rules! style {
    +    ($css: expr) => { ... };
         ($tl_class: literal, $css:expr) => { ... };
    -}
    Expand description

    add css to the page from outside a component.

    -

    this is helpful for adding styling to functions that just return Markup. -you have to call this from within a page render or the css will not be added to the page.

    -

    §usage

    +}
    Expand description

    add css to the page

    +

    you have to call this from within a page render or it will not work.

    +

    there are two ways to use this macro:

    +

    §from within a component

    +
    use fishnet::component::prelude::*;
    +
    +#[component]
    +async fn my_component() {
    +    style!(css!{
    +        color: red;
    +    });
    +
    +    html! {
    +        "hello world!"
    +    }
    +}
    +

    §from outside a component

    +

    additionally to providing the style, you also have to name the top level class yourself as the +first argument.

    +

    this is helpful for adding styling to functions that just return Markup.

    +
    use fishnet::{style, html, Markup, css};
     
     async fn render_something() -> Markup {
         style!("my_class", css!{
             color: red;
         });
    -     
    +    
         html!{
             div class="my_class" {
                 "hello world!"
    diff --git a/docs/fishnet/page/index.html b/docs/fishnet/page/index.html
    new file mode 100644
    index 0000000..cea29fd
    --- /dev/null
    +++ b/docs/fishnet/page/index.html
    @@ -0,0 +1,2 @@
    +fishnet::page - Rust

    Module fishnet::page

    source ·
    Expand description

    A visitable page on the Website.

    +

    Modules§

    Structs§

    Traits§

    \ No newline at end of file diff --git a/docs/fishnet/page/render_context/fn.enter_page.html b/docs/fishnet/page/render_context/fn.enter_page.html new file mode 100644 index 0000000..1117769 --- /dev/null +++ b/docs/fishnet/page/render_context/fn.enter_page.html @@ -0,0 +1,5 @@ +enter_page in fishnet::page::render_context - Rust

    Function fishnet::page::render_context::enter_page

    source ·
    pub async fn enter_page(page: &mut BuiltPage)
    Expand description

    Enter a page render context.

    +

    This should be called before rendering any components. +After the rendering is complete, exit_page should be called to acquire the results. +Calling enter_page while another page is being rendered results in the loss of the previous page’s render results!

    +
    \ No newline at end of file diff --git a/docs/fishnet/page/render_context/fn.enter_temporary_render.html b/docs/fishnet/page/render_context/fn.enter_temporary_render.html new file mode 100644 index 0000000..1d9cf34 --- /dev/null +++ b/docs/fishnet/page/render_context/fn.enter_temporary_render.html @@ -0,0 +1,8 @@ +enter_temporary_render in fishnet::page::render_context - Rust

    Function fishnet::page::render_context::enter_temporary_render

    source ·
    pub async fn enter_temporary_render()
    Expand description

    Enter a temporary render context.

    +

    While in a temporary render context, rendered components will not be saved to the page’s component store. +Furthermore, it will be recorded, whether any dynamic components were rendered during the temporary render. +This can be used to “test-render” a static component to see if it contains any dynamic children.

    +

    Temporary render contexts can be exited using exit_temporary_render, and can be multiple +levels deep. it is up to you to ensure that you always exit every render you enter.

    +

    You usually don’t need to call this function yourself.

    +
    \ No newline at end of file diff --git a/docs/fishnet/page/render_context/fn.exit_page.html b/docs/fishnet/page/render_context/fn.exit_page.html new file mode 100644 index 0000000..14cc119 --- /dev/null +++ b/docs/fishnet/page/render_context/fn.exit_page.html @@ -0,0 +1,5 @@ +exit_page in fishnet::page::render_context - Rust

    Function fishnet::page::render_context::exit_page

    source ·
    pub async fn exit_page() -> RenderResult
    Expand description

    Exit a page render context.

    +

    This should be called after rendering all components. It will return the RenderResult containing all the scripts and runners that were collected during the rendering.

    +

    §Panics

    +

    Panics if no page is currently being rendered. (i.e. enter_page was not called before)

    +
    \ No newline at end of file diff --git a/docs/fishnet/page/render_context/fn.exit_temporary_render.html b/docs/fishnet/page/render_context/fn.exit_temporary_render.html new file mode 100644 index 0000000..be77a66 --- /dev/null +++ b/docs/fishnet/page/render_context/fn.exit_temporary_render.html @@ -0,0 +1,5 @@ +exit_temporary_render in fishnet::page::render_context - Rust

    Function fishnet::page::render_context::exit_temporary_render

    source ·
    pub async fn exit_temporary_render() -> bool
    Expand description

    Exit a temporary render context.

    +

    Returns true if the temporary render started via enter_temporary_render was static (i.e. no dynamic components were rendered). +If not within a (temporary) render context, this function will always return true.

    +

    You usually don’t need to call this function yourself.

    +
    \ No newline at end of file diff --git a/docs/fishnet/page/render_context/fn.global_store.html b/docs/fishnet/page/render_context/fn.global_store.html new file mode 100644 index 0000000..bcfbef6 --- /dev/null +++ b/docs/fishnet/page/render_context/fn.global_store.html @@ -0,0 +1,2 @@ +global_store in fishnet::page::render_context - Rust

    Function fishnet::page::render_context::global_store

    source ·
    pub fn global_store() -> &'static GlobalStore
    Expand description

    acquire access to the GlobalStore.

    +
    \ No newline at end of file diff --git a/docs/fishnet/page/render_context/fn.render_component.html b/docs/fishnet/page/render_context/fn.render_component.html new file mode 100644 index 0000000..70021d2 --- /dev/null +++ b/docs/fishnet/page/render_context/fn.render_component.html @@ -0,0 +1,13 @@ +render_component in fishnet::page::render_context - Rust

    Function fishnet::page::render_context::render_component

    source ·
    pub async fn render_component<F, C>(
    +    context_id: &str,
    +    lazy_component: F
    +) -> Markup
    where + F: FnOnce() -> C, + C: BuildableComponent,
    Expand description

    Render a component into the current page render context.

    +

    This function should only be called while a page is being rendered. +It is highly recommended to use the c! macro instead of calling this function directly, since it will handle the context id generation automatically.

    +
      +
    • context_id - A unique identifier for the render. This should be kept consistent for the same component across renders.
    • +
    • lazy_component - A closure that returns the component to render. It will only be called if the component is not already rendered for the current page.
    • +
    +
    \ No newline at end of file diff --git a/docs/fishnet/page/render_context/index.html b/docs/fishnet/page/render_context/index.html new file mode 100644 index 0000000..f5ec2ec --- /dev/null +++ b/docs/fishnet/page/render_context/index.html @@ -0,0 +1,12 @@ +fishnet::page::render_context - Rust

    Module fishnet::page::render_context

    source ·
    Expand description

    managing resources during a render

    +

    the render context is used under the hood whenever you use macros that add things to the +page (e.g. c!, style!, script!, …).

    +

    before a page renders its contents, it attaches itself to the render context via enter_page. during the +render when a resource is about to be added, it is first checked whether it already exists on +the render context. if yes, it is not added again and just reused. otherwise it is newly +constructed. after the render is finished, the page can use exit_page to get a list of all +the newly constructed things during the render and then process them further (e.g. add routes +from new components, minify added scripts, …)

    +

    you usually don’t need to call anything from in here manually unless you want to have finer +control over resources (like dynamically adding resources to the page)

    +

    Structs§

    Functions§

    \ No newline at end of file diff --git a/docs/fishnet/page/render_context/sidebar-items.js b/docs/fishnet/page/render_context/sidebar-items.js new file mode 100644 index 0000000..77fc4e4 --- /dev/null +++ b/docs/fishnet/page/render_context/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["enter_page","enter_temporary_render","exit_page","exit_temporary_render","global_store","render_component"],"struct":["GlobalStore","GlobalStoreEntry","RenderResult"]}; \ No newline at end of file diff --git a/docs/fishnet/page/render_context/struct.GlobalStore.html b/docs/fishnet/page/render_context/struct.GlobalStore.html new file mode 100644 index 0000000..e15eafa --- /dev/null +++ b/docs/fishnet/page/render_context/struct.GlobalStore.html @@ -0,0 +1,25 @@ +GlobalStore in fishnet::page::render_context - Rust

    Struct fishnet::page::render_context::GlobalStore

    source ·
    pub struct GlobalStore(/* private fields */);
    Expand description

    collection of resources that are page independent

    +

    Implementations§

    source§

    impl GlobalStore

    source

    pub async fn add<F>(&self, id: &str, globals: F)
    where + F: FnOnce() -> GlobalStoreEntry,

    add a GlobalStoreEntry to the store

    +

    does nothing if there already is a entry under the given id. +otherwise the globals closure is executed to create a new entry

    +

    this will also notify the currently active render context about the newly added resource +(which usually means that it gets added to the rendered page)

    +
    source

    pub async fn get<'a>(&'a self, id: &str) -> Option<Arc<GlobalStoreEntry>>

    get a GlobalStoreEntry from its id.

    +

    Trait Implementations§

    source§

    impl Debug for GlobalStore

    source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    source§

    impl<T> Any for T
    where + T: 'static + ?Sized,

    source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    source§

    impl<T> Borrow<T> for T
    where + T: ?Sized,

    source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    source§

    impl<T> BorrowMut<T> for T
    where + T: ?Sized,

    source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    source§

    impl<T> From<T> for T

    source§

    fn from(t: T) -> T

    Returns the argument unchanged.

    +
    §

    impl<T> Instrument for T

    §

    fn instrument(self, span: Span) -> Instrumented<Self>

    Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
    §

    fn in_current_span(self) -> Instrumented<Self>

    Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
    source§

    impl<T, U> Into<U> for T
    where + U: From<T>,

    source§

    fn into(self) -> U

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    source§

    impl<T, U> TryFrom<U> for T
    where + U: Into<T>,

    §

    type Error = Infallible

    The type returned in the event of a conversion error.
    source§

    fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

    Performs the conversion.
    source§

    impl<T, U> TryInto<U> for T
    where + U: TryFrom<T>,

    §

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.
    source§

    fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

    Performs the conversion.
    §

    impl<T> WithSubscriber for T

    §

    fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
    where + S: Into<Dispatch>,

    Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
    §

    fn with_current_subscriber(self) -> WithDispatch<Self>

    Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
    §

    impl<A, B, T> HttpServerConnExec<A, B> for T
    where + B: Body,

    \ No newline at end of file diff --git a/docs/fishnet/page/render_context/struct.GlobalStoreEntry.html b/docs/fishnet/page/render_context/struct.GlobalStoreEntry.html new file mode 100644 index 0000000..41bdc30 --- /dev/null +++ b/docs/fishnet/page/render_context/struct.GlobalStoreEntry.html @@ -0,0 +1,21 @@ +GlobalStoreEntry in fishnet::page::render_context - Rust

    Struct fishnet::page::render_context::GlobalStoreEntry

    source ·
    pub struct GlobalStoreEntry {
    +    pub scripts: Vec<ScriptType>,
    +    pub style: Option<RenderedStyle>,
    +}
    Expand description

    a single global (page independent) resource

    +

    Fields§

    §scripts: Vec<ScriptType>§style: Option<RenderedStyle>

    Trait Implementations§

    source§

    impl Debug for GlobalStoreEntry

    source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    source§

    impl<T> Any for T
    where + T: 'static + ?Sized,

    source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    source§

    impl<T> Borrow<T> for T
    where + T: ?Sized,

    source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    source§

    impl<T> BorrowMut<T> for T
    where + T: ?Sized,

    source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    source§

    impl<T> From<T> for T

    source§

    fn from(t: T) -> T

    Returns the argument unchanged.

    +
    §

    impl<T> Instrument for T

    §

    fn instrument(self, span: Span) -> Instrumented<Self>

    Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
    §

    fn in_current_span(self) -> Instrumented<Self>

    Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
    source§

    impl<T, U> Into<U> for T
    where + U: From<T>,

    source§

    fn into(self) -> U

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    source§

    impl<T, U> TryFrom<U> for T
    where + U: Into<T>,

    §

    type Error = Infallible

    The type returned in the event of a conversion error.
    source§

    fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

    Performs the conversion.
    source§

    impl<T, U> TryInto<U> for T
    where + U: TryFrom<T>,

    §

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.
    source§

    fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

    Performs the conversion.
    §

    impl<T> WithSubscriber for T

    §

    fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
    where + S: Into<Dispatch>,

    Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
    §

    fn with_current_subscriber(self) -> WithDispatch<Self>

    Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
    §

    impl<A, B, T> HttpServerConnExec<A, B> for T
    where + B: Body,

    \ No newline at end of file diff --git a/docs/fishnet/page/render_context/struct.RenderResult.html b/docs/fishnet/page/render_context/struct.RenderResult.html new file mode 100644 index 0000000..121f953 --- /dev/null +++ b/docs/fishnet/page/render_context/struct.RenderResult.html @@ -0,0 +1,28 @@ +RenderResult in fishnet::page::render_context - Rust

    Struct fishnet::page::render_context::RenderResult

    source ·
    pub struct RenderResult {
    +    pub runners: Vec<BoxFuture<'static, ()>>,
    +    pub routers: Vec<(ComponentRoute, Router)>,
    +    pub new_components: HashSet<String>,
    +}
    Expand description

    The result of a page render.

    +

    Contains all the scripts, runners and routers that were collected during the rendering.

    +
      +
    • scripts - A list of scripts that should be included in the page.
    • +
    • runners - A list of runners that should be executed.
    • +
    • routers - A list of routers that should be accessible from the page at the given routes
    • +
    +

    Fields§

    §runners: Vec<BoxFuture<'static, ()>>§routers: Vec<(ComponentRoute, Router)>§new_components: HashSet<String>

    Auto Trait Implementations§

    Blanket Implementations§

    source§

    impl<T> Any for T
    where + T: 'static + ?Sized,

    source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    source§

    impl<T> Borrow<T> for T
    where + T: ?Sized,

    source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    source§

    impl<T> BorrowMut<T> for T
    where + T: ?Sized,

    source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    source§

    impl<T> From<T> for T

    source§

    fn from(t: T) -> T

    Returns the argument unchanged.

    +
    §

    impl<T> Instrument for T

    §

    fn instrument(self, span: Span) -> Instrumented<Self>

    Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
    §

    fn in_current_span(self) -> Instrumented<Self>

    Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
    source§

    impl<T, U> Into<U> for T
    where + U: From<T>,

    source§

    fn into(self) -> U

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    source§

    impl<T, U> TryFrom<U> for T
    where + U: Into<T>,

    §

    type Error = Infallible

    The type returned in the event of a conversion error.
    source§

    fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

    Performs the conversion.
    source§

    impl<T, U> TryInto<U> for T
    where + U: TryFrom<T>,

    §

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.
    source§

    fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

    Performs the conversion.
    §

    impl<T> WithSubscriber for T

    §

    fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
    where + S: Into<Dispatch>,

    Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
    §

    fn with_current_subscriber(self) -> WithDispatch<Self>

    Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
    §

    impl<A, B, T> HttpServerConnExec<A, B> for T
    where + B: Body,

    \ No newline at end of file diff --git a/docs/fishnet/page/sidebar-items.js b/docs/fishnet/page/sidebar-items.js new file mode 100644 index 0000000..b6e1bb8 --- /dev/null +++ b/docs/fishnet/page/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"mod":["render_context"],"struct":["BuiltPage","Page"],"trait":["RouterPageExt"]}; \ No newline at end of file diff --git a/docs/fishnet/struct.Page.html b/docs/fishnet/page/struct.BuiltPage.html similarity index 57% rename from docs/fishnet/struct.Page.html rename to docs/fishnet/page/struct.BuiltPage.html index a816184..3caad4e 100644 --- a/docs/fishnet/struct.Page.html +++ b/docs/fishnet/page/struct.BuiltPage.html @@ -1,11 +1,4 @@ -Page in fishnet - Rust

    Struct fishnet::Page

    source ·
    pub struct Page { /* private fields */ }
    Expand description

    A page represents a visitable route on the website.

    -

    It manages rendering of the content, preparing scripts and running components.

    -

    Implementations§

    source§

    impl Page

    source

    pub fn new(name: &str) -> Self

    Create a new page.

    -

    The name is only used for logging purposes.

    -
    source

    pub fn with_head(self, head: Markup) -> Self

    source

    pub fn with_body<C>(self, content_renderer: C) -> Self
    where - C: Fn() -> BoxFuture<'static, Markup> + Send + Sync + 'static,

    Add content to the page.

    -

    This function takes in a closure that returns a rendered page.

    -

    Auto Trait Implementations§

    §

    impl Freeze for Page

    §

    impl !RefUnwindSafe for Page

    §

    impl Send for Page

    §

    impl Sync for Page

    §

    impl Unpin for Page

    §

    impl !UnwindSafe for Page

    Blanket Implementations§

    source§

    impl<T> Any for T
    where +BuiltPage in fishnet::page - Rust

    Struct fishnet::page::BuiltPage

    source ·
    pub struct BuiltPage { /* private fields */ }

    Implementations§

    source§

    impl BuiltPage

    source

    pub async fn new(page: Page, path: &str) -> (Arc<Mutex<BuiltPage>>, Router)

    source

    pub async fn render(page: Extension<Arc<Mutex<Self>>>) -> Markup

    Auto Trait Implementations§

    Blanket Implementations§

    source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    source§

    impl<T> BorrowMut<T> for T
    where T: ?Sized,

    source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    source§

    impl<T> From<T> for T

    source§

    fn from(t: T) -> T

    Returns the argument unchanged.

    diff --git a/docs/fishnet/page/struct.Page.html b/docs/fishnet/page/struct.Page.html index 8f1e0a5..381b7ad 100644 --- a/docs/fishnet/page/struct.Page.html +++ b/docs/fishnet/page/struct.Page.html @@ -1,11 +1,24 @@ - - - - - Redirection - - -

    Redirecting to ../../fishnet/struct.Page.html...

    - - - \ No newline at end of file +Page in fishnet::page - Rust

    Struct fishnet::page::Page

    source ·
    pub struct Page { /* private fields */ }
    Expand description

    A page represents a visitable route on the website.

    +

    It manages rendering of the content, preparing scripts and running components.

    +

    Implementations§

    source§

    impl Page

    source

    pub fn new(name: &str) -> Self

    Create a new page.

    +

    The name is only used for logging purposes.

    +
    source

    pub fn with_head(self, head: Markup) -> Self

    source

    pub fn with_body<C>(self, content_renderer: C) -> Self
    where + C: Fn() -> BoxFuture<'static, Markup> + Send + Sync + 'static,

    Add content to the page.

    +

    This function takes in a closure that returns a rendered page.

    +

    Auto Trait Implementations§

    §

    impl Freeze for Page

    §

    impl !RefUnwindSafe for Page

    §

    impl Send for Page

    §

    impl Sync for Page

    §

    impl Unpin for Page

    §

    impl !UnwindSafe for Page

    Blanket Implementations§

    source§

    impl<T> Any for T
    where + T: 'static + ?Sized,

    source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    source§

    impl<T> Borrow<T> for T
    where + T: ?Sized,

    source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    source§

    impl<T> BorrowMut<T> for T
    where + T: ?Sized,

    source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    source§

    impl<T> From<T> for T

    source§

    fn from(t: T) -> T

    Returns the argument unchanged.

    +
    §

    impl<T> Instrument for T

    §

    fn instrument(self, span: Span) -> Instrumented<Self>

    Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
    §

    fn in_current_span(self) -> Instrumented<Self>

    Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
    source§

    impl<T, U> Into<U> for T
    where + U: From<T>,

    source§

    fn into(self) -> U

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    source§

    impl<T, U> TryFrom<U> for T
    where + U: Into<T>,

    §

    type Error = Infallible

    The type returned in the event of a conversion error.
    source§

    fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

    Performs the conversion.
    source§

    impl<T, U> TryInto<U> for T
    where + U: TryFrom<T>,

    §

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.
    source§

    fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

    Performs the conversion.
    §

    impl<T> WithSubscriber for T

    §

    fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
    where + S: Into<Dispatch>,

    Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
    §

    fn with_current_subscriber(self) -> WithDispatch<Self>

    Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
    §

    impl<A, B, T> HttpServerConnExec<A, B> for T
    where + B: Body,

    \ No newline at end of file diff --git a/docs/fishnet/page/trait.RouterPageExt.html b/docs/fishnet/page/trait.RouterPageExt.html new file mode 100644 index 0000000..6ea902f --- /dev/null +++ b/docs/fishnet/page/trait.RouterPageExt.html @@ -0,0 +1,18 @@ +RouterPageExt in fishnet::page - Rust

    Trait fishnet::page::RouterPageExt

    source ·
    pub trait RouterPageExt {
    +    // Required method
    +    fn attach_page<'life0, 'async_trait>(
    +        self,
    +        path: &'life0 str,
    +        page: Page
    +    ) -> Pin<Box<dyn Future<Output = Self> + Send + 'async_trait>>
    +       where Self: 'async_trait,
    +             'life0: 'async_trait;
    +}
    Expand description

    Allows attaching a page to a router.

    +

    Required Methods§

    source

    fn attach_page<'life0, 'async_trait>( + self, + path: &'life0 str, + page: Page +) -> Pin<Box<dyn Future<Output = Self> + Send + 'async_trait>>
    where + Self: 'async_trait, + 'life0: 'async_trait,

    Attach the given page to the router. This involves building the page and adding multiple routes for the api, scripts and content.

    +

    Object Safety§

    This trait is not object safe.

    Implementors§

    \ No newline at end of file diff --git a/docs/fishnet/sidebar-items.js b/docs/fishnet/sidebar-items.js index 1bc4609..b03c1a7 100644 --- a/docs/fishnet/sidebar-items.js +++ b/docs/fishnet/sidebar-items.js @@ -1 +1 @@ -window.SIDEBAR_ITEMS = {"attr":["component","dyn_component"],"macro":["c","css","html","script","state","state_init","style"],"mod":["component","css","js"],"struct":["Page","Website"],"type":["Markup"]}; \ No newline at end of file +window.SIDEBAR_ITEMS = {"attr":["component","dyn_component"],"macro":["c","css","html","script","state","state_init","style"],"mod":["component","css","js","page"],"struct":["Website"],"type":["Markup"]}; \ No newline at end of file diff --git a/docs/fishnet/struct.Website.html b/docs/fishnet/struct.Website.html index d56e962..aae702e 100644 --- a/docs/fishnet/struct.Website.html +++ b/docs/fishnet/struct.Website.html @@ -1,6 +1,6 @@ -Website in fishnet - Rust

    Struct fishnet::Website

    source ·
    pub struct Website { /* private fields */ }
    Expand description

    A simple website builder. A Website consists of multiple Pages and can additionally serve static files.

    +Website in fishnet - Rust

    Struct fishnet::Website

    source ·
    pub struct Website { /* private fields */ }
    Expand description

    A simple website builder. A Website consists of multiple Pages and can additionally serve static files.

    Implementations§

    source§

    impl Website

    source

    pub fn new() -> Self

    Create a new website.

    -
    source

    pub async fn add_page(self, path: &str, page: Page) -> Self

    Add a page to the website.

    +
    source

    pub async fn add_page(self, path: &str, page: Page) -> Self

    Add a page to the website.

    This will first initiate a build of the page and afterwards attach the page to the Website at the given path.

    source

    pub fn compression(self, enable: bool) -> Self

    Enable or disable compression for the website.

    source

    pub fn serve_dir(self, path: &str) -> Self

    Serve a directory as static files.

    diff --git a/docs/search-index.js b/docs/search-index.js index 365aad9..af851e4 100644 --- a/docs/search-index.js +++ b/docs/search-index.js @@ -1,5 +1,5 @@ var searchIndex = new Map(JSON.parse('[\ -["fishnet",{"t":"IFFNNNNNQCXNCQXNNQNNCNNQNNQQQNNNNNNNNKFFFIFNNNNNNNNNMONNNNNNCNNNNNNNNMNNNNNNMNNNNCNNNNOONNNNNNNNNNNNNNNNNNQQFIEEFKIFKENNNNNNNNNNNNNNNNNNQNNNNNNNNNEXXNEQQNNNNNNNNNNNNNNNNXNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNQNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNCQNNNNNNNNQNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNTTTFFFTTTTFFFFTHHNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNHNHNNNNNNNNNNNNNNNNNNNNNNNNNNCHNHNNHNHNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNCNNNNHNHNHNHNNHNHNNNNNNNNNNNNHNHNHNHNNNNNNNNNNNHNHNNNNNNNNNNNNNNNNNNNNNNNNNFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNFHHHHHHHHHHHHHHHHHHHHFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNPPFGNNNNNNNNNNNNNNNNNNHNNNNNNN","n":["Markup","Page","Website","add_page","borrow","borrow","borrow_mut","borrow_mut","c","component","component","compression","css","css","dyn_component","from","from","html","into","into","js","new","new","script","serve","serve_dir","state","state_init","style","try_from","try_from","try_into","try_into","type_id","type_id","with_body","with_head","BuildableComponent","BuiltComponent","Component","ComponentBuildResult","ComponentRunner","ComponentState","add_script","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build","built_component","clone","clone","clone_into","clone_into","deref","endpoint","fake_macros","fmt","fmt","from","from","from","from","from_ref","from_ref","id","id","into","into","into","into","is_dynamic","name","name","name","nest_service","new","prelude","render","render","render_dynamic","route","router","runner","style","to_owned","to_owned","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","with_runner","with_runner","with_state","state","state_init","Arc","BoxFuture","BuildableComponent","ComponentState","Extension","FutureExt","Markup","Mutex","Render","ScriptType","allocator","as_fd","as_ptr","as_raw_fd","as_ref","assume_init","assume_init","blocking_lock","blocking_lock_owned","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","boxed","boxed_local","c","call","catch_unwind","cause","clone","clone","clone_into","clone_into","clone_span","cmp","component","component","component","const_new","css","css","css","current_span","decrement_strong_count","decrement_strong_count_in","default","default","default","deref","deref","deref_mut","description","downcast","downcast_raw","downcast_unchecked","downgrade","drop","drop_span","dyn_component","enabled","enter","eq","event","event_enabled","exit","flatten","flatten_stream","flush","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_iter","from_raw","from_raw_in","from_ref","from_ref","from_request","from_request_parts","fuse","ge","get_mut","get_mut","get_mut_unchecked","gt","hash","html","increment_strong_count","increment_strong_count_in","inspect","into","into","into","into_inner","into_inner","into_make_service","into_make_service_with_connect_info","into_raw","into_response","into_response_parts","into_service","into_stream","is_read_vectored","is_write_vectored","layer","le","left_future","lock","lock_owned","lt","make_mut","map","map_into","max_level_hint","ne","never_error","new","new","new_cyclic","new_in","new_span","new_uninit","new_uninit_in","new_uninit_slice","new_uninit_slice_in","new_zeroed","new_zeroed_in","new_zeroed_slice","new_zeroed_slice_in","now_or_never","partial_cmp","pin","pin_in","poll_unpin","provide","ptr_eq","read","read_buf","read_to_end","read_to_string","read_vectored","record","record_follows_from","register_callsite","remote_handle","render","render_to","render_to","right_future","routing","script","seek","shared","source","spawn_local_obj","spawn_obj","status","status_local","strong_count","style","then","to_owned","to_owned","to_string","try_close","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_lock","try_lock_owned","try_new","try_new_in","try_new_uninit","try_new_uninit_in","try_new_zeroed","try_new_zeroed_in","try_pin","try_pin_in","try_unwrap","type_id","type_id","type_id","unit_error","unwrap","unwrap_or_clone","view","weak_count","write","write_vectored","DELETE","GET","HEAD","IntoMakeService","MethodFilter","MethodRouter","OPTIONS","PATCH","POST","PUT","Route","Router","RouterAsService","RouterIntoService","TRACE","any","any_service","as_service","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","call","call","call","call","call","call","call","call","call","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","default","default","delete","delete","delete_service","delete_service","eq","fallback","fallback","fallback_service","fallback_service","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from_ref","from_ref","from_ref","from_ref","from_ref","from_ref","future","get","get","get_service","get_service","handle_error","head","head","head_service","head_service","into","into","into","into","into","into","into","into_make_service","into_make_service","into_make_service","into_make_service","into_make_service","into_make_service","into_make_service","into_make_service","into_make_service","into_make_service_with_connect_info","into_make_service_with_connect_info","into_make_service_with_connect_info","into_make_service_with_connect_info","into_make_service_with_connect_info","into_make_service_with_connect_info","into_make_service_with_connect_info","into_make_service_with_connect_info","into_make_service_with_connect_info","into_service","into_service","layer","layer","make_service","make_service","make_service","merge","merge","method_routing","nest","nest_service","new","new","on","on","on_service","on_service","options","options","options_service","options_service","or","patch","patch","patch_service","patch_service","poll_ready","poll_ready","poll_ready","poll_ready","poll_ready","poll_ready","poll_ready","poll_ready","poll_ready","poll_ready","poll_ready","post","post","post_service","post_service","put","put","put_service","put_service","route","route_layer","route_layer","route_service","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","trace","trace","trace_service","trace_service","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","with_state","with_state","InfallibleRouteFuture","IntoMakeServiceFuture","RouteFuture","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","fmt","from","from","from","into","into","into","into_future","into_future","into_future","poll","poll","poll","try_from","try_from","try_from","try_into","try_into","try_into","try_poll","try_poll","type_id","type_id","type_id","MethodRouter","any","any_service","delete","delete_service","get","get_service","head","head_service","on","on_service","options","options_service","patch","patch_service","post","post_service","put","put_service","trace","trace_service","RenderedStyle","StyleFragment","Stylesheet","add","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","clone","clone_into","fmt","from","from","from","from_ref","into","into","into","new","new","render","render","to_owned","try_from","try_from","try_from","try_into","try_into","try_into","type_id","type_id","type_id","External","Inline","ScriptString","ScriptType","as_str","borrow","borrow","borrow_mut","borrow_mut","clone","clone_into","consume","eq","fmt","fmt","from","from","from","from_ref","hash","into","into","minify_script","to_owned","try_from","try_from","try_into","try_into","type_id","type_id"],"q":[[0,"fishnet"],[37,"fishnet::component"],[106,"fishnet::component::fake_macros"],[108,"fishnet::component::prelude"],[326,"fishnet::component::prelude::routing"],[529,"fishnet::component::prelude::routing::future"],[562,"fishnet::component::prelude::routing::method_routing"],[583,"fishnet::css"],[617,"fishnet::js"],[647,"core::result"],[648,"core::any"],[649,"core::ops::function"],[650,"core::marker"],[651,"core::marker"],[652,"core::future::future"],[653,"alloc::boxed"],[654,"core::pin"],[655,"core::fmt"],[656,"core::fmt"],[657,"http::request"],[658,"core::convert"],[659,"tower_service"],[660,"core::ops::function"],[661,"std::os::fd::owned"],[662,"std::os::fd::owned"],[663,"core::mem::maybe_uninit"],[664,"tokio::sync::mutex"],[665,"tokio::sync::mutex"],[666,"core::error"],[667,"core::option"],[668,"tracing_core::span"],[669,"tracing_core::subscriber"],[670,"core::cmp"],[671,"core::cmp"],[672,"core::any"],[673,"tracing_core::metadata"],[674,"core::cmp"],[675,"futures_util::future::future"],[676,"futures_util::future::future"],[677,"std::io::error"],[678,"core::fmt"],[679,"alloc::ffi::c_str"],[680,"core::ffi::c_str"],[681,"alloc::string"],[682,"std::path"],[683,"std::ffi::os_str"],[684,"alloc::borrow"],[685,"alloc::borrow"],[686,"http::request"],[687,"core::cmp"],[688,"core::hash"],[689,"axum::extract::connect_info"],[690,"http::response"],[691,"axum_core::response::into_response_parts"],[692,"futures_util::future::future"],[693,"futures_util::future::future"],[694,"core::task::poll"],[695,"core::error"],[696,"std::io"],[697,"tracing_core::span"],[698,"futures_util::future::future::remote_handle"],[699,"std::io"],[700,"futures_task::future_obj"],[701,"futures_task::spawn"],[702,"futures_task::spawn"],[703,"std::io"],[704,"bytes::bytes"],[705,"http_body"],[706,"axum::serve"],[707,"tower_layer"],[708,"core::convert"],[709,"axum::routing::method_filter"]],"i":[0,0,0,1,3,1,3,1,0,0,0,1,0,0,0,3,1,0,3,1,0,3,1,0,1,1,0,0,0,3,1,3,1,3,1,3,3,0,0,0,0,0,0,15,150,15,22,23,150,15,22,23,18,150,22,23,22,23,23,23,0,22,23,150,15,22,23,22,23,18,22,150,15,22,23,22,18,15,22,15,15,0,15,22,15,15,150,150,15,22,23,150,15,22,23,150,15,22,23,150,15,22,23,15,15,15,0,0,0,0,0,0,0,0,0,0,0,0,36,36,36,36,36,36,36,45,45,52,36,36,45,52,36,45,48,48,0,52,48,36,52,36,52,36,36,36,0,0,0,45,0,0,0,36,36,36,52,36,45,52,36,52,36,36,36,36,36,36,36,0,36,36,36,36,36,36,48,48,36,52,36,36,36,45,52,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,45,45,45,36,36,36,52,36,52,52,48,36,36,45,36,36,36,0,36,36,48,52,36,45,36,45,52,52,36,52,52,52,48,36,36,52,36,48,45,45,36,36,48,48,36,36,48,36,45,36,36,36,36,36,36,36,36,36,36,36,48,36,36,36,48,36,36,36,36,36,36,36,36,36,36,48,114,114,36,48,0,0,36,48,36,36,36,36,36,36,0,48,52,36,36,36,52,36,36,45,52,36,45,45,45,36,36,36,36,36,36,36,36,36,52,36,45,48,36,36,36,36,36,36,139,139,139,0,0,0,139,139,139,139,0,0,0,0,139,0,0,131,32,137,131,132,138,92,139,32,137,131,132,138,92,139,32,32,32,137,131,131,132,138,92,32,137,131,138,92,139,32,137,131,138,92,139,32,131,0,32,0,32,139,32,131,32,131,32,137,131,132,138,92,139,32,137,131,132,138,92,139,32,137,131,138,92,139,0,0,32,0,32,32,0,32,0,32,32,137,131,132,138,92,139,32,32,32,137,131,131,132,138,92,32,32,32,137,131,131,132,138,92,32,131,32,131,32,131,92,32,131,0,131,131,32,131,0,32,0,32,0,32,0,32,139,0,32,0,32,32,32,32,137,131,131,131,132,138,92,92,0,32,0,32,0,32,0,32,131,32,131,131,32,137,131,138,92,139,0,32,0,32,32,137,131,132,138,92,139,139,32,137,131,132,138,92,139,32,137,131,132,138,92,139,32,131,0,0,0,144,145,146,144,145,146,144,144,145,146,144,145,146,144,145,146,144,145,146,144,145,146,144,145,146,144,145,144,145,146,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,147,33,147,148,33,147,148,148,148,148,33,147,148,148,33,147,148,33,147,33,147,148,33,147,148,33,147,148,33,147,148,16,16,0,0,149,16,149,16,149,149,149,149,16,16,149,16,149,149,149,16,16,149,0,149,16,149,16,149,16,149],"f":"```{{bdf}b}{ce{}{}}000```{{bh}b}```{cc{}}0`22`{df}{{}b}`{{bj}l}{{bd}b}```{c{{n{e}}}{}{}}000{cA`{}}0{{fc}f{{Ah{}{{Ab{{Af{Ad}}}}}}AjAl}}{{fAd}f}``````{{{An{ceg}}B`}{{An{ceg}}}{}{}{BbAjAl}};;;;;;;;{{Bdd}{{Bj{{Bh{Bf}}}}}}`{BlBl}{{{Bn{c}}}{{Bn{c}}}{BbAjAlBb}}{{ce}l{}{}}0{{{Bn{c}}}e{BbAjAl}{}}{{{Bn{c}}}d{BbAjAl}}`{{BlC`}Cb}{{{Bn{c}}C`}Cb{BbAjAlCd}}{cc{}}00000{Bdd}{Bld}{ce{}{}}000{Blh}3{{{An{ceg}}}d{}{}{BbAjAl}}3{{{An{ceg}}di}{{An{ceg}}}{}{}{BbAjAl}{{Cn{{Ch{Cf}}}{{Cj{Cl}}}}BbAj}}{{dd}{{An{``l}}}}`{{{An{`ce}}g}{{`{Bd}}}{AjAl}{BbAjAlBbAjAl}{{Ah{{Bn{e}}}{{Ab{{Af{Ad}}}}}}AjAl}}{BlAd}1{{{An{ceg}}dD`}{{An{ceg}}}{}{}{BbAjAl}}``{{{An{ceg}}Db}{{An{ceg}}}{}{}{BbAjAl}}88{c{{n{e}}}{}{}}0000000{cA`{}}000{{{An{c`e}}g}{{An{c`e}}}{}{BbAjAl}{{Dd{{Bn{e}}}{{Ab{{Af{l}}}}}}AjAl}}{{{An{c`l}}{Df{l}}}{{An{c`l}}}{}}{{{An{c`l}}e}{{An{``e}}}{}{BbAjAl}}````````````{{{Dh{ce}}}e{}Dj}{{{Dh{c}}}Dl{DnE`}}{{{Dh{ce}}}{}E`Dj}{{{Dh{c}}}EbEd}{{{Dh{ce}}}cE`Dj}{{{Dh{{Eh{{Ef{c}}}}e}}}{{Dh{{Eh{c}}e}}}{}Dj}{{{Dh{{Ef{c}}e}}}{{Dh{ce}}}{}Dj}{{{Ej{c}}}{{El{c}}}E`}{{{Dh{{Ej{c}}}}}{{En{c}}}E`}{ce{}{}}050000{F`{{Bj{{Bh{Bf}}}}}}0`{{c{Ch{Cf}}e}{}{}{}}{F`{{Fb{F`}}}}{{{Dh{c}}}{{Ff{Fd}}}{FdE`}}{{{Fh{c}}}{{Fh{c}}}Bb}{{{Dh{ce}}}{{Dh{ce}}}E`{DjBb}}{{ce}l{}{}}0{{{Dh{c}}Fj}Fj{FlE`}}{{{Dh{ce}}{Dh{ce}}}Fn{G`E`}Dj}```{c{{Ej{c}}}E`}```{{{Dh{c}}}Gb{FlE`}}{{}l}{clDj}{{}{{Fh{c}}}Gd}{{}{{Dh{c}}}Gd}{{}{{Ej{c}}}Gd}{{{Fh{c}}}{}{}}{{{Dh{ce}}}cE`Dj}1{{{Dh{c}}}d{FdE`}}{{{Dh{Gfc}}}{{n{{Dh{ec}}{Dh{Gfc}}}}}Dj{GfAjAl}}{{{Dh{c}}A`}{{Ff{l}}}{FlE`}}{{{Dh{Gfc}}}{{Dh{ec}}}Dj{GfAjAl}}{{{Dh{ce}}}{{Gh{ce}}}E`{BbDj}}{{{Dh{ce}}}lE`Dj}{{{Dh{c}}Fj}l{FlE`}}`{{{Dh{c}}Gj}h{FlE`}}1{{{Dh{ce}}{Dh{ce}}}h{GlE`}Dj}{{{Dh{c}}Gn}l{FlE`}}{{{Dh{c}}Gn}h{FlE`}}4{F`{{H`{F`}}}}{F`{{Hb{F`}}}}{{{Dh{Hd}}}{{n{lHf}}}}{{{Fh{c}}C`}{{n{lHh}}}Cd}{{{Dh{ce}}C`}{{n{lHh}}}{CdE`}Dj}{{{Dh{ce}}C`}{{n{lHh}}}E`Dj}{{{Dh{ce}}C`}{{n{lHh}}}{HjE`}Dj}{{{Ej{c}}C`}{{n{lHh}}}{CdE`}}{cc{}}{Hlc{}}{{{Hn{c}}}{{Dh{{Eh{c}}}}}{}}{{{Eh{c}}}{{Dh{{Eh{c}}}}}Bb}{{{I`{ce}}}{{Dh{{Eh{c}}e}}}{}{DjBb}}{{{Dh{d}}}{{Dh{{Eh{Ib}}}}}}5{Id{{Dh{If}}}}{Ih{{Dh{d}}}}{{{Bh{ce}}}{{Dh{ce}}}E`Dj}{If{{Dh{If}}}}{Ij{{Dh{Ij}}}}{Il{{Dh{Il}}}}{{{In{c}}}{{Dh{c}}}{J`E`}}{d{{Dh{d}}}}{Jb{{Dh{Ij}}}}{c{{Dh{c}}}{}}{Jd{{Dh{Il}}}}{c{{Ej{c}}}{}}{Hlc{}}{cc{}}{e{{Dh{{Eh{c}}}}}{}{{Jh{}{{Jf{c}}}}}}{{}{{Dh{c}}}E`}{c{{Dh{ec}}}DjE`}33{{{Ch{Cf}}c}{{Bj{{Bh{Bf}}}}}{}}{{Jjc}{{Bj{{Bh{Bf}}}}}{AjAl}}{F`{{Jl{F`}}}}{{{Dh{ce}}{Dh{ce}}}h{JnE`}Dj}{{{Dh{ce}}}{{Ff{c}}}E`Dj}{{{Ej{c}}}cE`}{{{Dh{ce}}}cE`Dj}3{{{Dh{ce}}g}l{K`E`}DjKb}`{{}l}{cl{BbDj}}{{F`e}{{Kd{F`e}}}{}{{Dd{c}}}}{ce{}{}}00{{{Dh{ce}}}{{Ff{c}}}{}Dj}7{c{{Kh{{Kf{egl}}}}}{}{}{}}{c{{Kj{{Kf{egl}}i}}}{}{}{}{}}{{{Dh{ce}}}{}E`Dj}{{{Fh{c}}}{{Kl{Cf}}}{BbAjAl}}{{{Fh{c}}Kn}{{n{Kn}}}{BbAjAl}}{c{{Kf{egl}}}{}{}{}}{F`{{L`{F`}}}}{{{Dh{Hd}}}h}0{{{Fh{c}}e}{}{BbAjAl}{}}{{{Dh{ce}}{Dh{ce}}}h{JnE`}Dj}{F`{{Lb{F`e}}}{}{{Bf{}{{Ab{c}}}}}}{{{Ej{c}}}{{El{c}}}E`}{{{Dh{{Ej{c}}}}}{{En{c}}}E`}3{{{Dh{ce}}}cBb{DjBb}}{{F`g}{{Ld{F`g}}}{}{}{{Dd{c}{{Ab{e}}}}}}{F`{{Lf{F`c}}}{}}{{{Dh{c}}}{{Ff{Lh}}}{FlE`}}{{{Dh{ce}}{Dh{ce}}}h{GlE`}Dj}{F`{{Lj{F`}}}}{c{{Dh{c}}}{}}{c{{Ej{c}}}E`}{e{{Dh{c}}}{}{{Dd{{Gh{c}}}{{Ab{c}}}}}}{{ce}{{Dh{ce}}}{}Dj}{{{Dh{c}}Ll}Fj{FlE`}}{{}{{Dh{{Ef{c}}}}}{}}{c{{Dh{{Ef{e}}c}}}Dj{}}{Ln{{Dh{{Eh{{Ef{c}}}}}}}{}}{{Lnc}{{Dh{{Eh{{Ef{e}}}}c}}}Dj{}}3210{F`{{Ff{c}}}{}}{{{Dh{ce}}{Dh{ce}}}{{Ff{Fn}}}{JnE`}Dj}{c{{Bj{{Dh{c}}}}}{}}{{ce}{{Bj{{Dh{ce}}}}}{}Dj}{{F`M`}{{Mb{c}}}{}}{{{Dh{c}}Md}l{FdE`}}{{{Dh{ce}}{Dh{ce}}}hE`Dj}{{{Dh{Hd}}{Eh{Ib}}}{{n{LnHf}}}}{{{Dh{Hd}}Mf}{{n{lHf}}}}{{{Dh{Hd}}{I`{Ib}}}{{n{LnHf}}}}{{{Dh{Hd}}Ih}{{n{LnHf}}}}{{{Dh{Hd}}{Eh{Mh}}}{{n{LnHf}}}}{{{Dh{c}}FjMj}l{FlE`}}{{{Dh{c}}FjFj}l{FlE`}}{{{Dh{c}}Gj}Ml{FlE`}}{F`{{Nb{{Mn{F`}}{N`{c}}}}}{}}{Nd{{Nf{Ih}}}}{{NdIh}l}{{{Dh{c}}Ih}l{NdE`}}{F`{{Lb{eF`}}}{}{{Bf{}{{Ab{c}}}}}}``{{{Dh{Hd}}Nh}{{n{NjHf}}}}{F`{{Nl{F`}}}}{{{Dh{c}}}{{Ff{Fd}}}{FdE`}}{{{Dh{c}}{Nn{l}}}{{n{lO`}}}{ObE`}}{{{Dh{c}}{Od{l}}}{{n{lO`}}}{OfE`}}{{{Dh{c}}}{{n{lO`}}}{OfE`}}{{{Dh{c}}}{{n{lO`}}}{ObE`}}{{{Dh{ce}}}LnE`Dj}`{{F`g}{{Oh{F`eg}}}{}Bf{{Dd{c}{{Ab{e}}}}}}{ce{}{}}0{cIh{}}{{{Dh{c}}Fj}h{FlE`}}{c{{n{e}}}{}{}}0{{{Dh{{Eh{c}}e}}}{{n{{Dh{{Hn{c}}e}}}}}{}Dj}1111{{{Ej{c}}}{{n{{El{c}}Oj}}}E`}{{{Dh{{Ej{c}}}}}{{n{{En{c}}Oj}}}E`}{c{{n{{Dh{c}}Ol}}}{}}{{ce}{{n{{Dh{ce}}Ol}}}{}Dj}{{}{{n{{Dh{{Ef{c}}}}Ol}}}{}}{c{{n{{Dh{{Ef{e}}c}}Ol}}}Dj{}}10{c{{n{{Bj{{Dh{c}}}}Ol}}}{}}{{ce}{{n{{Bj{{Dh{ce}}}}Ol}}}{}Dj}{{{Dh{ce}}}{{n{c{Dh{ce}}}}}{}Dj}{cA`{}}00{F`{{On{F`}}}}{{{Dh{{A@`{c}}}}}{{n{cl}}}Aj}{{{Dh{ce}}}cBb{DjBb}}{{{Dh{{A@`{c}}}}g}{{n{el}}}Aj{}{{Dd{c}{{Ab{e}}}}}}{{{Dh{ce}}}LnE`Dj}{{{Dh{Hd}}{Eh{Ib}}}{{n{LnHf}}}}{{{Dh{Hd}}{Eh{A@b}}}{{n{LnHf}}}}```````````````{g{{D`{e}}}{}{BbAjAl}{{A@d{ce}}}}{c{{D`{e}}}{{Cn{{Ch{Cf}}}}BbAj}Bb}{{{A@f{c}}}{{A@h{ec}}}{BbAjAl}{}}{ce{}{}}0000000000000{{{D`{lc}}{Ch{e}}}{}{}{{A@n{}{{A@j{A@l}}}}Aj}}{{D`AA`}}{{{D`{c}}{Ch{Cf}}c}{}Bb}{{{AAb{c}}{Ch{e}}}{}{}{{A@n{}{{A@j{A@l}}}}Aj}}{{A@fAA`}}{{A@f{Ch{c}}}{}{{A@n{}{{A@j{A@l}}}}Aj}}{{{A@h{c}}{Ch{c}}}{}{{A@n{}{{A@j{A@l}}}}Aj}}{{{AAd{c}}{Ch{c}}}{}{{A@n{}{{A@j{A@l}}}}Aj}}{{{Kh{c}}e}{}Bb{}}{{{D`{ce}}}{{D`{ce}}}{}{}}{{{AAb{c}}}{{AAb{c}}}{}}{{{A@f{c}}}{{A@f{c}}}{}}{{{AAd{ce}}}{{AAd{ce}}}{}{}}{{{Kh{c}}}{{Kh{c}}}Bb}{AAfAAf}{{ce}l{}{}}00000{{}{{D`{ce}}}Bb{}}{{}{{A@f{c}}}{BbAjAl}}{g{{D`{e}}}{}{BbAjAl}{{A@d{ce}}}}{{{D`{c}}g}{{D`{c}}}{AjAlBb}{}{{A@d{ec}}}}{c{{D`{e}}}{{Cn{{Ch{Cf}}}}BbAj}Bb}{{{D`{ce}}g}{{D`{ce}}}Bb{}{{Cn{{Ch{Cf}}}{{Cj{e}}}}BbAj}}{{AAfAAf}h}3{{{A@f{c}}g}{{A@f{c}}}{BbAjAl}{}{{A@d{ec}}}}2{{{A@f{c}}e}{{A@f{c}}}{BbAjAl}{{Cn{{Ch{Cf}}}{{Cj{Cl}}}}BbAj}}{{{D`{ce}}C`}{{n{lHh}}}{}{}}{{{AAb{c}}C`}{{n{lHh}}}{}}{{{A@f{c}}C`}{{n{lHh}}}{}}{{{A@h{ce}}C`}{{n{lHh}}}{}Cd}{{{AAd{ce}}C`}{{n{lHh}}}{}Cd}{{{Kh{c}}C`}{{n{lHh}}}Cd}{{AAfC`}{{n{lHh}}}}{cc{}}000000000000`>=<;{{{D`{ce}}g}{{D`{c}}}Bb{}{BbAjAl}}?>=<{ce{}{}}000000{c{{Kh{e}}}{}{}}{D`{{Kh{D`}}}}{c{{Kh{{Kf{egl}}}}}{}{}{}}22{A@f{{Kh{A@f}}}}333{D`{{Kj{D`c}}}{}}{c{{Kj{eg}}}{}{}{}}{c{{Kj{{Kf{egl}}i}}}{}{}{}{}}11{A@f{{Kj{A@fc}}}{}}222{c{{Kf{egl}}}{}{}{}}{{{A@f{c}}}{{AAd{ec}}}{BbAjAl}{}}{{{D`{ce}}g}{{D`{ci}}}Bb{}{{AAh{{AAb{e}}}}BbAj}{}}{{{A@f{c}}e}{{A@f{c}}}{BbAjAl}{{AAh{AAb}}BbAj}}{{ce}{}{}{}}00{{{D`{ce}}{D`{ce}}}{{D`{ce}}}Bb{}}{{{A@f{c}}e}{{A@f{c}}}{BbAjAl}{{AAj{{A@f{c}}}}}}`{{{A@f{c}}d{A@f{c}}}{{A@f{c}}}{BbAjAl}}{{{A@f{c}}de}{{A@f{c}}}{BbAjAl}{{Cn{{Ch{Cf}}}{{Cj{Cl}}}}BbAj}}{{}{{D`{ce}}}Bb{}}{{}{{A@f{c}}}{BbAjAl}}{{AAfg}{{D`{e}}}{}{BbAjAl}{{A@d{ce}}}}{{{D`{c}}AAfg}{{D`{c}}}{AjAlBb}{}{{A@d{ec}}}}{{AAfc}{{D`{e}}}{{Cn{{Ch{Cf}}}}BbAj}Bb}{{{D`{ce}}AAfg}{{D`{ce}}}Bb{}{{Cn{{Ch{Cf}}}{{Cj{e}}}}BbAj}}{g{{D`{e}}}{}{BbAjAl}{{A@d{ce}}}}{{{D`{c}}g}{{D`{c}}}{AjAlBb}{}{{A@d{ec}}}}{c{{D`{e}}}{{Cn{{Ch{Cf}}}}BbAj}Bb}{{{D`{ce}}g}{{D`{ce}}}Bb{}{{Cn{{Ch{Cf}}}{{Cj{e}}}}BbAj}}{{AAfAAf}AAf}4321{{D`M`}{{Mb{{n{l}}}}}}{{{D`{lc}}M`}{{Mb{{n{l}}}}}{}}{{cM`}{{Mb{{n{l}}}}}{}}{{{AAb{c}}M`}{{Mb{{n{l}}}}}{}}1{{A@fM`}{{Mb{{n{l}}}}}}0{{{A@h{c}}M`}{{Mb{{n{l}}}}}{{A@n{}{{A@j{A@l}}}}Aj}}{{{AAd{c}}M`}{{Mb{{n{l}}}}}{{A@n{}{{A@j{A@l}}}}Aj}}{{{Kh{c}}M`}{{Mb{{n{l}}}}}Bb}5<;:9<;:9{{{A@f{c}}d{D`{c}}}{{A@f{c}}}{BbAjAl}}{{{D`{ce}}g}{{D`{ce}}}Bb{}{{AAh{{AAb{e}}}}BbAj}}{{{A@f{c}}e}{{A@f{c}}}{BbAjAl}{{AAh{AAb}}BbAj}}{{{A@f{c}}de}{{A@f{c}}}{BbAjAl}{{Cn{{Ch{Cf}}}{{Cj{Cl}}}}BbAj}}{ce{}{}}00000{g{{D`{e}}}{}{BbAjAl}{{A@d{ce}}}}{{{D`{c}}g}{{D`{c}}}{AjAlBb}{}{{A@d{ec}}}}{c{{D`{e}}}{{Cn{{Ch{Cf}}}}BbAj}Bb}{{{D`{ce}}g}{{D`{ce}}}Bb{}{{Cn{{Ch{Cf}}}{{Cj{e}}}}BbAj}}{c{{n{e}}}{}{}}000000{AAl{{n{AAfAAn}}}}1111111{cA`{}}000000{{{D`{ce}}c}{{D`{ge}}}Bb{}{}}{{{A@f{c}}c}{{A@f{e}}}{BbAjAl}{}}```999999{{{AB`{c}}C`}{{n{lHh}}}{}}{cc{}}00;;;{c{}{}}00{{{Bj{{AB`{c}}}}M`}Mb{}}{{{Bj{{ABb{c}}}}M`}Mb{}}{{{Bj{ABd}}M`}Mb}::::::{{{Bj{c}}M`}Mb{}}0999`?=?=?=?={{AAfg}{{D`{e}}}{}{BbAjAl}{{A@d{ce}}}}{{AAfc}{{D`{e}}}{{Cn{{Ch{Cf}}}}BbAj}Bb}{g{{D`{e}}}{}{BbAjAl}{{A@d{ce}}}}{c{{D`{e}}}{{Cn{{Ch{Cf}}}}BbAj}Bb}10101010```{{ABfABh}l}{ce{}{}}00000{ABhABh}{{ce}l{}{}}{{ABhC`}Cb}>>>>333{{d{Eh{{Nb{dd}}}}}Db}{{}ABf}{{Dbd}ABh}{ABfIh}7{c{{n{e}}}{}{}}00000{cA`{}}00````{ABjd}::::{ABjABj}9{ABjIh}{{B`B`}h}{{B`C`}Cb}{{ABjC`}Cb}{cc{}}{B`ABj}11{{B`c}lKb}{ce{}{}}080;;;;::","D":"BFb","p":[[5,"Website",0],[1,"str"],[5,"Page",0],[1,"bool"],[1,"u16"],[1,"unit"],[6,"Result",647],[5,"TypeId",648],[17,"Output"],[8,"Markup",0],[8,"BoxFuture",108],[10,"Fn",649],[10,"Send",650],[10,"Sync",650],[5,"Component",37],[6,"ScriptType",617],[10,"Clone",651],[10,"BuildableComponent",37],[10,"Future",652],[5,"Box",653],[5,"Pin",654],[5,"BuiltComponent",37],[5,"ComponentState",37],[5,"Formatter",655],[8,"Result",655],[10,"Debug",655],[5,"Body",656],[5,"Request",657],[17,"Error"],[6,"Infallible",658],[10,"Service",659],[5,"MethodRouter",326],[5,"StyleFragment",583],[10,"FnOnce",649],[8,"ComponentRunner",37],[5,"Arc",108],[10,"Allocator",660],[5,"BorrowedFd",661],[10,"AsFd",661],[10,"Sized",650],[1,"i32"],[10,"AsRawFd",662],[20,"MaybeUninit",663],[1,"slice"],[5,"Mutex",108],[5,"MutexGuard",664],[5,"OwnedMutexGuard",664],[10,"FutureExt",108],[5,"CatchUnwind",665],[10,"Error",666],[6,"Option",667],[5,"Extension",108],[5,"Id",668],[10,"Subscriber",669],[6,"Ordering",670],[10,"Ord",670],[5,"Current",668],[10,"Default",671],[10,"Any",648],[5,"Weak",672],[5,"Metadata",673],[10,"PartialEq",670],[5,"Event",674],[5,"Flatten",675],[5,"FlattenStream",675],[5,"File",676],[5,"Error",677],[5,"Error",655],[10,"Display",655],[1,"never"],[1,"array"],[5,"Vec",678],[1,"u8"],[5,"CString",679],[5,"CStr",680],[5,"String",681],[5,"Path",682],[5,"OsStr",683],[6,"Cow",684],[10,"ToOwned",684],[5,"PathBuf",682],[5,"OsString",683],[17,"Item"],[10,"IntoIterator",685],[5,"Parts",657],[5,"Fuse",686],[10,"PartialOrd",670],[10,"Hash",687],[10,"Hasher",687],[5,"Inspect",675],[5,"HandlerService",688],[5,"IntoMakeService",326],[5,"IntoMakeServiceWithConnectInfo",689],[5,"Response",690],[5,"ResponseParts",691],[5,"IntoStream",675],[6,"Either",692],[5,"Map",675],[5,"MapInto",675],[5,"LevelFilter",673],[5,"NeverError",675],[5,"Attributes",668],[1,"usize"],[5,"Context",693],[6,"Poll",694],[5,"Request",666],[5,"BorrowedCursor",695],[5,"IoSliceMut",696],[5,"Record",668],[5,"Interest",669],[5,"Remote",697],[5,"RemoteHandle",697],[1,"tuple"],[10,"Render",108],[5,"PreEscaped",698],[6,"SeekFrom",696],[1,"u64"],[5,"Shared",699],[5,"LocalFutureObj",700],[5,"SpawnError",701],[10,"LocalSpawn",701],[5,"FutureObj",700],[10,"Spawn",701],[5,"Then",675],[5,"TryLockError",664],[5,"AllocError",660],[5,"UnitError",675],[5,"RwLock",702],[5,"IoSlice",696],[10,"Handler",703],[5,"Router",326],[5,"RouterAsService",326],[17,"Data"],[5,"Bytes",704],[10,"Body",705],[5,"IncomingStream",706],[5,"Route",326],[5,"RouterIntoService",326],[5,"MethodFilter",326],[10,"Layer",707],[10,"Into",658],[5,"Method",708],[5,"NoMatchingMethodFilter",709],[5,"IntoMakeServiceFuture",529],[5,"RouteFuture",529],[5,"InfallibleRouteFuture",529],[5,"Stylesheet",583],[5,"RenderedStyle",583],[5,"ScriptString",617],[5,"ComponentBuildResult",37]],"b":[[103,"impl-Component%3CR,+HasState,+ST%3E"],[104,"impl-Component%3CR,+FixedNoState,+()%3E"],[123,"impl-Arc%3C%5BMaybeUninit%3CT%3E%5D,+A%3E"],[124,"impl-Arc%3CMaybeUninit%3CT%3E,+A%3E"],[180,"impl-Debug-for-Arc%3CT,+A%3E"],[181,"impl-Pointer-for-Arc%3CT,+A%3E"],[182,"impl-Display-for-Arc%3CT,+A%3E"],[186,"impl-From%3C%5BT;+N%5D%3E-for-Arc%3C%5BT%5D%3E"],[187,"impl-From%3C%26%5BT%5D%3E-for-Arc%3C%5BT%5D%3E"],[188,"impl-From%3CVec%3CT,+A%3E%3E-for-Arc%3C%5BT%5D,+A%3E"],[189,"impl-From%3CArc%3Cstr%3E%3E-for-Arc%3C%5Bu8%5D%3E"],[191,"impl-From%3CCString%3E-for-Arc%3CCStr%3E"],[192,"impl-From%3CString%3E-for-Arc%3Cstr%3E"],[193,"impl-From%3CBox%3CT,+A%3E%3E-for-Arc%3CT,+A%3E"],[194,"impl-From%3C%26CStr%3E-for-Arc%3CCStr%3E"],[195,"impl-From%3C%26Path%3E-for-Arc%3CPath%3E"],[196,"impl-From%3C%26OsStr%3E-for-Arc%3COsStr%3E"],[197,"impl-From%3CCow%3C\'a,+B%3E%3E-for-Arc%3CB%3E"],[198,"impl-From%3C%26str%3E-for-Arc%3Cstr%3E"],[199,"impl-From%3CPathBuf%3E-for-Arc%3CPath%3E"],[200,"impl-From%3CT%3E-for-Arc%3CT%3E"],[201,"impl-From%3COsString%3E-for-Arc%3COsStr%3E"],[358,"impl-Service%3CRequest%3CB%3E%3E-for-MethodRouter%3C(),+E%3E"],[359,"impl-Service%3CIncomingStream%3C\'_%3E%3E-for-MethodRouter"],[360,"impl-Handler%3C(),+S%3E-for-MethodRouter%3CS%3E"],[362,"impl-Service%3CIncomingStream%3C\'_%3E%3E-for-Router"],[363,"impl-Service%3CRequest%3CB%3E%3E-for-Router"],[472,"impl-Service%3CIncomingStream%3C\'_%3E%3E-for-MethodRouter"],[473,"impl-Service%3CRequest%3CB%3E%3E-for-MethodRouter%3C(),+E%3E"],[477,"impl-Service%3CRequest%3CB%3E%3E-for-Router"],[478,"impl-Service%3CIncomingStream%3C\'_%3E%3E-for-Router"]],"c":"OjAAAAAAAAA=","e":"OzAAAAEAAFYBRQAFAAMAGwABAB4ABQAlABoARAADAEwABQBTABYAawABAG8AAQB2AAAAeAAAAHoAAQCAAAYAigAAAIwAAQCPAAIAkwAAAJcAAACaAAAAnQAAAJ8ABAClAAAAqQAAAKsAAQCuAAIAswAFALoAAADLAAEA0QADANsAAQDlAAEA6AACAOwAAgD3AAAA/gAAAAwBAAAOAQcAGQEAAB0BAAAfAQQAJwEKAD0BAgBBAQAAQwEAAEUBAQBZASQAggEAAIcBBgCVAQUArAEAAK4BAgCyAQIAtgEDALsBAwDCAQIA2QEKAPABBQD6ARUAFQIGACICEABLAgkAWAIAAF0CAABfAgoAbgIGAHYCAgB6AgAAfAIBAIECBgA="}]\ +["fishnet",{"t":"IEFNNNQCXNCQXNQNCNCQNNQQQNNNKFFFIFNNNNNNNNNMONNNNNNNNNNNNNNMNNNNNNMNNNNCNNNNOONNNNNNNNNNNNNNNNNNFIEEFKIFKENNNNNNNNNNNNNNNNNNQNNNNNNNNNEXXNEQQNNNNNNNNNNNNNNNNXNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNQNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNCQNNNNNQQNNNQNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNTTTFFFTTTTFFFFTHHNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNHNHNNNNNNNNNNNNNNNNNNNNNNNNNNCHNHNNHNHNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNCNNNNHNHNHNHNNHNHNNNNNNNNNNNNHNHNHNHNNNNNNNNNNNHNHNNNNNNNNNNNNNNNNNNNNNNNNNFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNFHHHHHHHHHHHHHHHHHHHHFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNPPFGNNNNNNNNNNNNNNNNNNHNNNNNNNFFKMNNNNNNNNNNNCNNNNNNNNFFFNNNNNNNHHHHNNNNNNHNNNOHOOOONNNNNNNNN","n":["Markup","Page","Website","add_page","borrow","borrow_mut","c","component","component","compression","css","css","dyn_component","from","html","into","js","new","page","script","serve","serve_dir","state","state_init","style","try_from","try_into","type_id","BuildableComponent","BuiltComponent","Component","ComponentBuildResult","ComponentRunner","ComponentState","add_script","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build","built_component","clone","clone","clone_into","clone_into","deref","endpoint","fmt","fmt","from","from","from","from","from_ref","from_ref","id","id","into","into","into","into","is_dynamic","name","name","name","nest_service","new","prelude","render","render","render_dynamic","route","router","runner","style","to_owned","to_owned","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","with_runner","with_runner","with_state","Arc","BoxFuture","BuildableComponent","ComponentState","Extension","FutureExt","Markup","Mutex","Render","ScriptType","allocator","as_fd","as_ptr","as_raw_fd","as_ref","assume_init","assume_init","blocking_lock","blocking_lock_owned","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","boxed","boxed_local","c","call","catch_unwind","cause","clone","clone","clone_into","clone_into","clone_span","cmp","component","component","component","const_new","css","css","css","current_span","decrement_strong_count","decrement_strong_count_in","default","default","default","deref","deref","deref_mut","description","downcast","downcast_raw","downcast_unchecked","downgrade","drop","drop_span","dyn_component","enabled","enter","eq","event","event_enabled","exit","flatten","flatten_stream","flush","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_iter","from_raw","from_raw_in","from_ref","from_ref","from_request","from_request_parts","fuse","ge","get_mut","get_mut","get_mut_unchecked","gt","hash","html","increment_strong_count","increment_strong_count_in","inspect","into","into","into","into_inner","into_inner","into_make_service","into_make_service_with_connect_info","into_raw","into_response","into_response_parts","into_service","into_stream","is_read_vectored","is_write_vectored","layer","le","left_future","lock","lock_owned","lt","make_mut","map","map_into","max_level_hint","ne","never_error","new","new","new_cyclic","new_in","new_span","new_uninit","new_uninit_in","new_uninit_slice","new_uninit_slice_in","new_zeroed","new_zeroed_in","new_zeroed_slice","new_zeroed_slice_in","now_or_never","partial_cmp","pin","pin_in","poll_unpin","provide","ptr_eq","read","read_buf","read_to_end","read_to_string","read_vectored","record","record_follows_from","register_callsite","remote_handle","render","render_to","render_to","right_future","routing","script","seek","shared","source","spawn_local_obj","spawn_obj","state","state_init","status","status_local","strong_count","style","then","to_owned","to_owned","to_string","try_close","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_lock","try_lock_owned","try_new","try_new_in","try_new_uninit","try_new_uninit_in","try_new_zeroed","try_new_zeroed_in","try_pin","try_pin_in","try_unwrap","type_id","type_id","type_id","unit_error","unwrap","unwrap_or_clone","view","weak_count","write","write_vectored","DELETE","GET","HEAD","IntoMakeService","MethodFilter","MethodRouter","OPTIONS","PATCH","POST","PUT","Route","Router","RouterAsService","RouterIntoService","TRACE","any","any_service","as_service","attach_page","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","call","call","call","call","call","call","call","call","call","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","default","default","delete","delete","delete_service","delete_service","eq","fallback","fallback","fallback_service","fallback_service","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from_ref","from_ref","from_ref","from_ref","from_ref","from_ref","future","get","get","get_service","get_service","handle_error","head","head","head_service","head_service","into","into","into","into","into","into","into","into_make_service","into_make_service","into_make_service","into_make_service","into_make_service","into_make_service","into_make_service","into_make_service","into_make_service","into_make_service_with_connect_info","into_make_service_with_connect_info","into_make_service_with_connect_info","into_make_service_with_connect_info","into_make_service_with_connect_info","into_make_service_with_connect_info","into_make_service_with_connect_info","into_make_service_with_connect_info","into_make_service_with_connect_info","into_service","into_service","layer","layer","make_service","make_service","make_service","merge","merge","method_routing","nest","nest_service","new","new","on","on","on_service","on_service","options","options","options_service","options_service","or","patch","patch","patch_service","patch_service","poll_ready","poll_ready","poll_ready","poll_ready","poll_ready","poll_ready","poll_ready","poll_ready","poll_ready","poll_ready","poll_ready","post","post","post_service","post_service","put","put","put_service","put_service","route","route_layer","route_layer","route_service","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","trace","trace","trace_service","trace_service","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","with_state","with_state","InfallibleRouteFuture","IntoMakeServiceFuture","RouteFuture","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","fmt","from","from","from","into","into","into","into_future","into_future","into_future","poll","poll","poll","try_from","try_from","try_from","try_into","try_into","try_into","try_poll","try_poll","type_id","type_id","type_id","MethodRouter","any","any_service","delete","delete_service","get","get_service","head","head_service","on","on_service","options","options_service","patch","patch_service","post","post_service","put","put_service","trace","trace_service","RenderedStyle","StyleFragment","Stylesheet","add","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","clone","clone_into","fmt","fmt","from","from","from","from_ref","into","into","into","new","new","render","render","to_owned","try_from","try_from","try_from","try_into","try_into","try_into","type_id","type_id","type_id","External","Inline","ScriptString","ScriptType","as_str","borrow","borrow","borrow_mut","borrow_mut","clone","clone_into","consume","eq","fmt","fmt","from","from","from","from_ref","hash","into","into","minify_script","to_owned","try_from","try_from","try_into","try_into","type_id","type_id","BuiltPage","Page","RouterPageExt","attach_page","borrow","borrow","borrow_mut","borrow_mut","from","from","into","into","new","new","render","render_context","try_from","try_from","try_into","try_into","type_id","type_id","with_body","with_head","GlobalStore","GlobalStoreEntry","RenderResult","add","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","enter_page","enter_temporary_render","exit_page","exit_temporary_render","fmt","fmt","from","from","from","get","global_store","into","into","into","new_components","render_component","routers","runners","scripts","style","try_from","try_from","try_from","try_into","try_into","try_into","type_id","type_id","type_id"],"q":[[0,"fishnet"],[28,"fishnet::component"],[96,"fishnet::component::prelude"],[316,"fishnet::component::prelude::routing"],[520,"fishnet::component::prelude::routing::future"],[553,"fishnet::component::prelude::routing::method_routing"],[574,"fishnet::css"],[609,"fishnet::js"],[639,"fishnet::page"],[663,"fishnet::page::render_context"],[702,"core::result"],[703,"core::any"],[704,"core::clone"],[705,"core::marker"],[706,"core::marker"],[707,"alloc::boxed"],[708,"core::pin"],[709,"core::fmt"],[710,"core::fmt"],[711,"http::request"],[712,"core::convert"],[713,"tower_service"],[714,"core::ops::function"],[715,"core::ops::function"],[716,"std::os::fd::owned"],[717,"std::os::fd::owned"],[718,"core::mem::maybe_uninit"],[719,"tokio::sync::mutex"],[720,"tokio::sync::mutex"],[721,"core::error"],[722,"core::option"],[723,"tracing_core::span"],[724,"tracing_core::subscriber"],[725,"core::cmp"],[726,"core::cmp"],[727,"core::any"],[728,"tracing_core::metadata"],[729,"core::cmp"],[730,"futures_util::future::future"],[731,"futures_util::future::future"],[732,"std::io::error"],[733,"core::fmt"],[734,"alloc::borrow"],[735,"alloc::borrow"],[736,"alloc::string"],[737,"std::ffi::os_str"],[738,"alloc::ffi::c_str"],[739,"std::path"],[740,"std::path"],[741,"http::request"],[742,"core::cmp"],[743,"core::hash"],[744,"axum::extract::connect_info"],[745,"http::response"],[746,"axum_core::response::into_response_parts"],[747,"futures_util::future::future"],[748,"futures_util::future::future"],[749,"core::task::poll"],[750,"core::error"],[751,"std::io"],[752,"tracing_core::span"],[753,"futures_util::future::future::remote_handle"],[754,"std::io"],[755,"futures_task::future_obj"],[756,"futures_task::spawn"],[757,"futures_task::spawn"],[758,"std::io"],[759,"axum::serve"],[760,"bytes::bytes"],[761,"http_body"],[762,"tower_layer"],[763,"core::convert"],[764,"axum::routing::method_filter"]],"i":[0,0,0,1,1,1,0,0,0,1,0,0,0,1,0,1,0,1,0,0,1,1,0,0,0,1,1,1,0,0,0,0,0,0,9,155,9,18,19,155,9,18,19,14,155,18,19,18,19,19,19,18,19,155,9,18,19,18,19,14,18,155,9,18,19,18,14,9,18,9,9,0,9,18,9,9,155,155,9,18,19,155,9,18,19,155,9,18,19,155,9,18,19,9,9,9,0,0,0,0,0,0,0,0,0,0,36,36,36,36,36,36,36,45,45,52,36,36,45,52,36,45,48,48,0,52,48,36,52,36,52,36,36,36,0,0,0,45,0,0,0,36,36,36,52,36,45,52,36,52,36,36,36,36,36,36,36,0,36,36,36,36,36,36,48,48,36,52,36,36,36,45,52,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,45,45,45,36,36,36,52,36,52,52,48,36,36,45,36,36,36,0,36,36,48,52,36,45,36,45,52,52,36,52,52,52,48,36,36,52,36,48,45,45,36,36,48,48,36,36,48,36,45,36,36,36,36,36,36,36,36,36,36,36,48,36,36,36,48,36,36,36,36,36,36,36,36,36,36,48,114,114,36,48,0,0,36,48,36,36,36,0,0,36,36,36,0,48,52,36,36,36,52,36,36,45,52,36,45,45,45,36,36,36,36,36,36,36,36,36,52,36,45,48,36,36,36,36,36,36,139,139,139,0,0,0,139,139,139,139,0,0,0,0,139,0,0,131,131,32,137,131,132,138,92,139,32,137,131,132,138,92,139,32,32,32,137,131,131,132,138,92,32,137,131,138,92,139,32,137,131,138,92,139,32,131,0,32,0,32,139,32,131,32,131,32,137,131,132,138,92,139,32,137,131,132,138,92,139,32,137,131,138,92,139,0,0,32,0,32,32,0,32,0,32,32,137,131,132,138,92,139,32,32,32,137,131,131,132,138,92,32,32,32,137,131,131,132,138,92,32,131,32,131,32,131,92,32,131,0,131,131,32,131,0,32,0,32,0,32,0,32,139,0,32,0,32,32,32,32,137,131,131,131,132,138,92,92,0,32,0,32,0,32,0,32,131,32,131,131,32,137,131,138,92,139,0,32,0,32,32,137,131,132,138,92,139,139,32,137,131,132,138,92,139,32,137,131,132,138,92,139,32,131,0,0,0,144,145,146,144,145,146,144,144,145,146,144,145,146,144,145,146,144,145,146,144,145,146,144,145,146,144,145,144,145,146,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,147,33,148,147,33,148,147,148,148,148,147,33,148,147,148,33,148,147,33,147,33,147,148,33,148,147,33,148,147,33,148,147,10,10,0,0,149,10,149,10,149,149,149,149,10,10,149,10,149,149,149,10,10,149,0,149,10,149,10,149,10,149,0,0,0,150,151,3,151,3,151,3,151,3,151,3,151,0,151,3,151,3,151,3,3,3,0,0,0,152,154,153,152,154,153,152,0,0,0,0,153,152,154,153,152,152,0,154,153,152,154,0,154,154,153,153,154,153,152,154,153,152,154,153,152],"f":"```{{bdf}b}{ce{}{}}0```{{bh}b}```{cc{}}`2`{{}b}``{{bj}l}{{bd}b}```{c{{n{e}}}{}{}}0{cA`{}}``````{{{Ab{ceg}}Ad}{{Ab{ceg}}}{}{}{AfAhAj}}88888888{{Ald}{{Bb{{B`{An}}}}}}`{BdBd}{{{Bf{c}}}{{Bf{c}}}{AfAhAjAf}}{{ce}l{}{}}0{{{Bf{c}}}e{AfAhAj}{}}{{{Bf{c}}}d{AfAhAj}}{{BdBh}Bj}{{{Bf{c}}Bh}Bj{AfAhAjBl}}>>>>>>{Ald}{Bdd}{ce{}{}}000{Bdh}3{{{Ab{ceg}}}d{}{}{AfAhAj}}3{{{Ab{ceg}}di}{{Ab{ceg}}}{}{}{AfAhAj}{{Cf{{C`{Bn}}}{{Cb{Cd}}}}AfAh}}{{dd}{{Ab{``l}}}}`{{{Ab{`ce}}g}{{`{Al}}}{AhAj}{AfAhAjAfAhAj}{{Cn{{Bf{e}}}{{Ch{{Cl{Cj}}}}}}AhAj}}{BdCj}1{{{Ab{ceg}}dD`}{{Ab{ceg}}}{}{}{AfAhAj}}``{{{Ab{ceg}}Db}{{Ab{ceg}}}{}{}{AfAhAj}}88{c{{n{e}}}{}{}}0000000{cA`{}}000{{{Ab{c`e}}g}{{Ab{c`e}}}{}{AfAhAj}{{Dd{{Bf{e}}}{{Ch{{Cl{l}}}}}}AhAj}}{{{Ab{c`l}}{Df{l}}}{{Ab{c`l}}}{}}{{{Ab{c`l}}e}{{Ab{``e}}}{}{AfAhAj}}``````````{{{Dh{ce}}}e{}Dj}{{{Dh{c}}}Dl{DnE`}}{{{Dh{ce}}}{}E`Dj}{{{Dh{c}}}EbEd}{{{Dh{ce}}}cE`Dj}{{{Dh{{Ef{c}}e}}}{{Dh{ce}}}{}Dj}{{{Dh{{Eh{{Ef{c}}}}e}}}{{Dh{{Eh{c}}e}}}{}Dj}{{{Ej{c}}}{{El{c}}}E`}{{{Dh{{Ej{c}}}}}{{En{c}}}E`}{ce{}{}}050000{F`{{Bb{{B`{An}}}}}}0`{{c{C`{Bn}}e}{}{}{}}{F`{{Fb{F`}}}}{{{Dh{c}}}{{Ff{Fd}}}{FdE`}}{{{Fh{c}}}{{Fh{c}}}Af}{{{Dh{ce}}}{{Dh{ce}}}E`{DjAf}}{{ce}l{}{}}0{{{Dh{c}}Fj}Fj{FlE`}}{{{Dh{ce}}{Dh{ce}}}Fn{G`E`}Dj}```{c{{Ej{c}}}E`}```{{{Dh{c}}}Gb{FlE`}}{{}l}{clDj}{{}{{Fh{c}}}Gd}{{}{{Dh{c}}}Gd}{{}{{Ej{c}}}Gd}{{{Fh{c}}}{}{}}{{{Dh{ce}}}cE`Dj}1{{{Dh{c}}}d{FdE`}}{{{Dh{Gfc}}}{{n{{Dh{ec}}{Dh{Gfc}}}}}Dj{GfAhAj}}{{{Dh{c}}A`}{{Ff{l}}}{FlE`}}{{{Dh{Gfc}}}{{Dh{ec}}}Dj{GfAhAj}}{{{Dh{ce}}}{{Gh{ce}}}E`{AfDj}}{{{Dh{ce}}}lE`Dj}{{{Dh{c}}Fj}l{FlE`}}`{{{Dh{c}}Gj}h{FlE`}}1{{{Dh{ce}}{Dh{ce}}}h{GlE`}Dj}{{{Dh{c}}Gn}l{FlE`}}{{{Dh{c}}Gn}h{FlE`}}4{F`{{H`{F`}}}}{F`{{Hb{F`}}}}{{{Dh{Hd}}}{{n{lHf}}}}{{{Fh{c}}Bh}{{n{lHh}}}Bl}{{{Dh{ce}}Bh}{{n{lHh}}}{BlE`}Dj}{{{Dh{ce}}Bh}{{n{lHh}}}E`Dj}{{{Dh{ce}}Bh}{{n{lHh}}}{HjE`}Dj}{{{Ej{c}}Bh}{{n{lHh}}}{BlE`}}{cc{}}{{{Hl{c}}}{{Dh{{Eh{c}}}}}{}}{Hn{{Dh{Hn}}}}{{{I`{c}}}{{Dh{c}}}{IbE`}}{d{{Dh{d}}}}{Id{{Dh{Id}}}}{c{{Dh{c}}}{}}{{{B`{ce}}}{{Dh{ce}}}E`Dj}{If{{Dh{d}}}}{Ih{{Dh{Id}}}}{{{Dh{d}}}{{Dh{{Eh{Ij}}}}}}:{Ilc{}}{{{In{ce}}}{{Dh{{Eh{c}}e}}}{}{DjAf}}{{{Eh{c}}}{{Dh{{Eh{c}}}}}Af}{J`{{Dh{Hn}}}}{Jb{{Dh{Jd}}}}{Jd{{Dh{Jd}}}}{cc{}}{c{{Ej{c}}}{}}7{e{{Dh{{Eh{c}}}}}{}{{Jh{}{{Jf{c}}}}}}{{}{{Dh{c}}}E`}{c{{Dh{ec}}}DjE`}44{{{C`{Bn}}c}{{Bb{{B`{An}}}}}{}}{{Jjc}{{Bb{{B`{An}}}}}{AhAj}}{F`{{Jl{F`}}}}{{{Dh{ce}}{Dh{ce}}}h{JnE`}Dj}{{{Dh{ce}}}{{Ff{c}}}E`Dj}{{{Ej{c}}}cE`}{{{Dh{ce}}}cE`Dj}3{{{Dh{ce}}g}l{K`E`}DjKb}`{{}l}{cl{AfDj}}{{F`e}{{Kd{F`e}}}{}{{Dd{c}}}}{ce{}{}}00{{{Dh{ce}}}{{Ff{c}}}{}Dj}7{c{{Kh{{Kf{egl}}}}}{}{}{}}{c{{Kj{{Kf{egl}}i}}}{}{}{}{}}{{{Dh{ce}}}{}E`Dj}{{{Fh{c}}}{{Kl{Bn}}}{AfAhAj}}{{{Fh{c}}Kn}{{n{Kn}}}{AfAhAj}}{c{{Kf{egl}}}{}{}{}}{F`{{L`{F`}}}}{{{Dh{Hd}}}h}0{{{Fh{c}}e}{}{AfAhAj}{}}{{{Dh{ce}}{Dh{ce}}}h{JnE`}Dj}{F`{{Lb{F`e}}}{}{{An{}{{Ch{c}}}}}}{{{Ej{c}}}{{El{c}}}E`}{{{Dh{{Ej{c}}}}}{{En{c}}}E`}3{{{Dh{ce}}}cAf{DjAf}}{{F`g}{{Ld{F`g}}}{}{}{{Dd{c}{{Ch{e}}}}}}{F`{{Lf{F`c}}}{}}{{{Dh{c}}}{{Ff{Lh}}}{FlE`}}{{{Dh{ce}}{Dh{ce}}}h{GlE`}Dj}{F`{{Lj{F`}}}}{c{{Dh{c}}}{}}{c{{Ej{c}}}E`}{e{{Dh{c}}}{}{{Dd{{Gh{c}}}{{Ch{c}}}}}}{{ce}{{Dh{ce}}}{}Dj}{{{Dh{c}}Ll}Fj{FlE`}}{{}{{Dh{{Ef{c}}}}}{}}{c{{Dh{{Ef{e}}c}}}Dj{}}{Ln{{Dh{{Eh{{Ef{c}}}}}}}{}}{{Lnc}{{Dh{{Eh{{Ef{e}}}}c}}}Dj{}}3210{F`{{Ff{c}}}{}}{{{Dh{ce}}{Dh{ce}}}{{Ff{Fn}}}{JnE`}Dj}{c{{Bb{{Dh{c}}}}}{}}{{ce}{{Bb{{Dh{ce}}}}}{}Dj}{{F`M`}{{Mb{c}}}{}}{{{Dh{c}}Md}l{FdE`}}{{{Dh{ce}}{Dh{ce}}}hE`Dj}{{{Dh{Hd}}{Eh{Ij}}}{{n{LnHf}}}}{{{Dh{Hd}}Mf}{{n{lHf}}}}{{{Dh{Hd}}{In{Ij}}}{{n{LnHf}}}}{{{Dh{Hd}}If}{{n{LnHf}}}}{{{Dh{Hd}}{Eh{Mh}}}{{n{LnHf}}}}{{{Dh{c}}FjMj}l{FlE`}}{{{Dh{c}}FjFj}l{FlE`}}{{{Dh{c}}Gj}Ml{FlE`}}{F`{{Nb{{Mn{F`}}{N`{c}}}}}{}}{Nd{{Nf{If}}}}{{NdIf}l}{{{Dh{c}}If}l{NdE`}}{F`{{Lb{eF`}}}{}{{An{}{{Ch{c}}}}}}``{{{Dh{Hd}}Nh}{{n{NjHf}}}}{F`{{Nl{F`}}}}{{{Dh{c}}}{{Ff{Fd}}}{FdE`}}{{{Dh{c}}{Nn{l}}}{{n{lO`}}}{ObE`}}{{{Dh{c}}{Od{l}}}{{n{lO`}}}{OfE`}}``{{{Dh{c}}}{{n{lO`}}}{OfE`}}{{{Dh{c}}}{{n{lO`}}}{ObE`}}{{{Dh{ce}}}LnE`Dj}`{{F`g}{{Oh{F`eg}}}{}An{{Dd{c}{{Ch{e}}}}}}{ce{}{}}0{cIf{}}{{{Dh{c}}Fj}h{FlE`}}{c{{n{e}}}{}{}}0{{{Dh{{Eh{c}}e}}}{{n{{Dh{{Hl{c}}e}}}}}{}Dj}1111{{{Ej{c}}}{{n{{El{c}}Oj}}}E`}{{{Dh{{Ej{c}}}}}{{n{{En{c}}Oj}}}E`}{c{{n{{Dh{c}}Ol}}}{}}{{ce}{{n{{Dh{ce}}Ol}}}{}Dj}{{}{{n{{Dh{{Ef{c}}}}Ol}}}{}}{c{{n{{Dh{{Ef{e}}c}}Ol}}}Dj{}}10{c{{n{{Bb{{Dh{c}}}}Ol}}}{}}{{ce}{{n{{Bb{{Dh{ce}}}}Ol}}}{}Dj}{{{Dh{ce}}}{{n{c{Dh{ce}}}}}{}Dj}{cA`{}}00{F`{{On{F`}}}}{{{Dh{{A@`{c}}}}}{{n{cl}}}Ah}{{{Dh{ce}}}cAf{DjAf}}{{{Dh{{A@`{c}}}}g}{{n{el}}}Ah{}{{Dd{c}{{Ch{e}}}}}}{{{Dh{ce}}}LnE`Dj}{{{Dh{Hd}}{Eh{Ij}}}{{n{LnHf}}}}{{{Dh{Hd}}{Eh{A@b}}}{{n{LnHf}}}}```````````````{g{{D`{e}}}{}{AfAhAj}{{A@d{ce}}}}{c{{D`{e}}}{{Cf{{C`{Bn}}}}AfAh}Af}{{{A@f{c}}}{{A@h{ec}}}{AfAhAj}{}}{{A@fdf}{{Bb{{B`{An}}}}}}{ce{}{}}0000000000000{{{D`{c}}{C`{Bn}}c}{}Af}{{D`A@j}}{{{D`{lc}}{C`{e}}}{}{}{{AA`{}{{A@l{A@n}}}}Ah}}{{{AAb{c}}{C`{e}}}{}{}{{AA`{}{{A@l{A@n}}}}Ah}}{{A@fA@j}}{{A@f{C`{c}}}{}{{AA`{}{{A@l{A@n}}}}Ah}}{{{A@h{c}}{C`{c}}}{}{{AA`{}{{A@l{A@n}}}}Ah}}{{{AAd{c}}{C`{c}}}{}{{AA`{}{{A@l{A@n}}}}Ah}}{{{Kh{c}}e}{}Af{}}{{{D`{ce}}}{{D`{ce}}}{}{}}{{{AAb{c}}}{{AAb{c}}}{}}{{{A@f{c}}}{{A@f{c}}}{}}{{{AAd{ce}}}{{AAd{ce}}}{}{}}{{{Kh{c}}}{{Kh{c}}}Af}{AAfAAf}{{ce}l{}{}}00000{{}{{D`{ce}}}Af{}}{{}{{A@f{c}}}{AfAhAj}}{g{{D`{e}}}{}{AfAhAj}{{A@d{ce}}}}{{{D`{c}}g}{{D`{c}}}{AhAjAf}{}{{A@d{ec}}}}{c{{D`{e}}}{{Cf{{C`{Bn}}}}AfAh}Af}{{{D`{ce}}g}{{D`{ce}}}Af{}{{Cf{{C`{Bn}}}{{Cb{e}}}}AfAh}}{{AAfAAf}h}3{{{A@f{c}}g}{{A@f{c}}}{AfAhAj}{}{{A@d{ec}}}}2{{{A@f{c}}e}{{A@f{c}}}{AfAhAj}{{Cf{{C`{Bn}}}{{Cb{Cd}}}}AfAh}}{{{D`{ce}}Bh}{{n{lHh}}}{}{}}{{{AAb{c}}Bh}{{n{lHh}}}{}}{{{A@f{c}}Bh}{{n{lHh}}}{}}{{{A@h{ce}}Bh}{{n{lHh}}}{}Bl}{{{AAd{ce}}Bh}{{n{lHh}}}{}Bl}{{{Kh{c}}Bh}{{n{lHh}}}Bl}{{AAfBh}{{n{lHh}}}}{cc{}}000000000000`>=<;{{{D`{ce}}g}{{D`{c}}}Af{}{AfAhAj}}?>=<{ce{}{}}000000{D`{{Kh{D`}}}}{c{{Kh{e}}}{}{}}{c{{Kh{{Kf{egl}}}}}{}{}{}}11{A@f{{Kh{A@f}}}}222{c{{Kj{eg}}}{}{}{}}{c{{Kj{{Kf{egl}}i}}}{}{}{}{}}{D`{{Kj{D`c}}}{}}22{A@f{{Kj{A@fc}}}{}}333{c{{Kf{egl}}}{}{}{}}{{{A@f{c}}}{{AAd{ec}}}{AfAhAj}{}}{{{D`{ce}}g}{{D`{ci}}}Af{}{{AAh{{AAb{e}}}}AfAh}{}}{{{A@f{c}}e}{{A@f{c}}}{AfAhAj}{{AAh{AAb}}AfAh}}{{ce}{}{}{}}00{{{D`{ce}}{D`{ce}}}{{D`{ce}}}Af{}}{{{A@f{c}}e}{{A@f{c}}}{AfAhAj}{{AAj{{A@f{c}}}}}}`{{{A@f{c}}d{A@f{c}}}{{A@f{c}}}{AfAhAj}}{{{A@f{c}}de}{{A@f{c}}}{AfAhAj}{{Cf{{C`{Bn}}}{{Cb{Cd}}}}AfAh}}{{}{{D`{ce}}}Af{}}{{}{{A@f{c}}}{AfAhAj}}{{AAfg}{{D`{e}}}{}{AfAhAj}{{A@d{ce}}}}{{{D`{c}}AAfg}{{D`{c}}}{AhAjAf}{}{{A@d{ec}}}}{{AAfc}{{D`{e}}}{{Cf{{C`{Bn}}}}AfAh}Af}{{{D`{ce}}AAfg}{{D`{ce}}}Af{}{{Cf{{C`{Bn}}}{{Cb{e}}}}AfAh}}{g{{D`{e}}}{}{AfAhAj}{{A@d{ce}}}}{{{D`{c}}g}{{D`{c}}}{AhAjAf}{}{{A@d{ec}}}}{c{{D`{e}}}{{Cf{{C`{Bn}}}}AfAh}Af}{{{D`{ce}}g}{{D`{ce}}}Af{}{{Cf{{C`{Bn}}}{{Cb{e}}}}AfAh}}{{AAfAAf}AAf}4321{{cM`}{{Mb{{n{l}}}}}{}}{{{D`{lc}}M`}{{Mb{{n{l}}}}}{}}{{D`M`}{{Mb{{n{l}}}}}}{{{AAb{c}}M`}{{Mb{{n{l}}}}}{}}{{A@fM`}{{Mb{{n{l}}}}}}40{{{A@h{c}}M`}{{Mb{{n{l}}}}}{{AA`{}{{A@l{A@n}}}}Ah}}{{{AAd{c}}M`}{{Mb{{n{l}}}}}{{AA`{}{{A@l{A@n}}}}Ah}}6{{{Kh{c}}M`}{{Mb{{n{l}}}}}Af}<;:9<;:9{{{A@f{c}}d{D`{c}}}{{A@f{c}}}{AfAhAj}}{{{D`{ce}}g}{{D`{ce}}}Af{}{{AAh{{AAb{e}}}}AfAh}}{{{A@f{c}}e}{{A@f{c}}}{AfAhAj}{{AAh{AAb}}AfAh}}{{{A@f{c}}de}{{A@f{c}}}{AfAhAj}{{Cf{{C`{Bn}}}{{Cb{Cd}}}}AfAh}}{ce{}{}}00000{g{{D`{e}}}{}{AfAhAj}{{A@d{ce}}}}{{{D`{c}}g}{{D`{c}}}{AhAjAf}{}{{A@d{ec}}}}{c{{D`{e}}}{{Cf{{C`{Bn}}}}AfAh}Af}{{{D`{ce}}g}{{D`{ce}}}Af{}{{Cf{{C`{Bn}}}{{Cb{e}}}}AfAh}}{c{{n{e}}}{}{}}00000{AAl{{n{AAfAAn}}}}11111111{cA`{}}000000{{{D`{ce}}c}{{D`{ge}}}Af{}{}}{{{A@f{c}}c}{{A@f{e}}}{AfAhAj}{}}```999999{{{AB`{c}}Bh}{{n{lHh}}}{}}{cc{}}00;;;{c{}{}}00{{{Bb{{AB`{c}}}}M`}Mb{}}{{{Bb{{ABb{c}}}}M`}Mb{}}{{{Bb{ABd}}M`}Mb}::::::{{{Bb{c}}M`}Mb{}}0999`?=?=?=?={{AAfg}{{D`{e}}}{}{AfAhAj}{{A@d{ce}}}}{{AAfc}{{D`{e}}}{{Cf{{C`{Bn}}}}AfAh}Af}{g{{D`{e}}}{}{AfAhAj}{{A@d{ce}}}}{c{{D`{e}}}{{Cf{{C`{Bn}}}}AfAh}Af}10101010```{{ABfABh}l}{ce{}{}}00000{ABhABh}{{ce}l{}{}}{{ABhBh}Bj}{{ABfBh}Bj}????444{{d{Eh{{Nb{dd}}}}}Db}{{}ABf}{{Dbd}ABh}{ABfIf}8{c{{n{e}}}{}{}}00000{cA`{}}00````{ABjd};;;;{ABjABj}:{ABjIf}{{AdAd}h}{{AdBh}Bj}{{ABjBh}Bj}{cc{}}0{AdABj}1{{Adc}lKb}{ce{}{}}080;;;;::```{{ABldf}{{Bb{{B`{An}}}}}}11114411{{fd}{{Nb{{Dh{{Ej{ABn}}}}A@f}}}}{df}{{{Fh{{Dh{{Ej{ABn}}}}}}}Cj}`????>>{{fc}f{{Cn{}{{Ch{{Cl{Cj}}}}}}AhAj}}{{fCj}f}```{{AC`dc}l{{Dd{}{{Ch{ACb}}}}}}777777{ABnl}{{}l}{{}ACd}{{}h}{{ACbBh}Bj}{{AC`Bh}Bj}{cc{}}00{{AC`d}{{Ff{{Dh{ACb}}}}}}{{}AC`}{ce{}{}}00`{{de}CjAl{{Dd{}{{Ch{c}}}}}}````{c{{n{e}}}{}{}}00000{cA`{}}00","D":"BIb","p":[[5,"Website",0],[1,"str"],[5,"Page",639],[1,"bool"],[1,"u16"],[1,"unit"],[6,"Result",702],[5,"TypeId",703],[5,"Component",28],[6,"ScriptType",609],[10,"Clone",704],[10,"Send",705],[10,"Sync",705],[10,"BuildableComponent",28],[10,"Future",706],[5,"Box",707],[5,"Pin",708],[5,"BuiltComponent",28],[5,"ComponentState",28],[5,"Formatter",709],[8,"Result",709],[10,"Debug",709],[5,"Body",710],[5,"Request",711],[17,"Error"],[6,"Infallible",712],[10,"Service",713],[17,"Output"],[8,"Markup",0],[8,"BoxFuture",96],[10,"Fn",714],[5,"MethodRouter",316],[5,"StyleFragment",574],[10,"FnOnce",714],[8,"ComponentRunner",28],[5,"Arc",96],[10,"Allocator",715],[5,"BorrowedFd",716],[10,"AsFd",716],[10,"Sized",705],[1,"i32"],[10,"AsRawFd",717],[20,"MaybeUninit",718],[1,"slice"],[5,"Mutex",96],[5,"MutexGuard",719],[5,"OwnedMutexGuard",719],[10,"FutureExt",96],[5,"CatchUnwind",720],[10,"Error",721],[6,"Option",722],[5,"Extension",96],[5,"Id",723],[10,"Subscriber",724],[6,"Ordering",725],[10,"Ord",725],[5,"Current",723],[10,"Default",726],[10,"Any",703],[5,"Weak",727],[5,"Metadata",728],[10,"PartialEq",725],[5,"Event",729],[5,"Flatten",730],[5,"FlattenStream",730],[5,"File",731],[5,"Error",732],[5,"Error",709],[10,"Display",709],[1,"array"],[5,"CStr",733],[6,"Cow",734],[10,"ToOwned",734],[5,"OsStr",735],[5,"String",736],[5,"OsString",735],[1,"u8"],[1,"never"],[5,"Vec",737],[5,"CString",738],[5,"PathBuf",739],[5,"Path",739],[17,"Item"],[10,"IntoIterator",740],[5,"Parts",711],[5,"Fuse",741],[10,"PartialOrd",725],[10,"Hash",742],[10,"Hasher",742],[5,"Inspect",730],[5,"HandlerService",743],[5,"IntoMakeService",316],[5,"IntoMakeServiceWithConnectInfo",744],[5,"Response",745],[5,"ResponseParts",746],[5,"IntoStream",730],[6,"Either",747],[5,"Map",730],[5,"MapInto",730],[5,"LevelFilter",728],[5,"NeverError",730],[5,"Attributes",723],[1,"usize"],[5,"Context",748],[6,"Poll",749],[5,"Request",721],[5,"BorrowedCursor",750],[5,"IoSliceMut",751],[5,"Record",723],[5,"Interest",724],[5,"Remote",752],[5,"RemoteHandle",752],[1,"tuple"],[10,"Render",96],[5,"PreEscaped",753],[6,"SeekFrom",751],[1,"u64"],[5,"Shared",754],[5,"LocalFutureObj",755],[5,"SpawnError",756],[10,"LocalSpawn",756],[5,"FutureObj",755],[10,"Spawn",756],[5,"Then",730],[5,"TryLockError",719],[5,"AllocError",715],[5,"UnitError",730],[5,"RwLock",757],[5,"IoSlice",751],[10,"Handler",758],[5,"Router",316],[5,"RouterAsService",316],[5,"IncomingStream",759],[17,"Data"],[5,"Bytes",760],[10,"Body",761],[5,"Route",316],[5,"RouterIntoService",316],[5,"MethodFilter",316],[10,"Layer",762],[10,"Into",712],[5,"Method",763],[5,"NoMatchingMethodFilter",764],[5,"IntoMakeServiceFuture",520],[5,"RouteFuture",520],[5,"InfallibleRouteFuture",520],[5,"Stylesheet",574],[5,"RenderedStyle",574],[5,"ScriptString",609],[10,"RouterPageExt",639],[5,"BuiltPage",639],[5,"GlobalStore",663],[5,"GlobalStoreEntry",663],[5,"RenderResult",663],[5,"ComponentBuildResult",28]],"b":[[93,"impl-Component%3CR,+HasState,+ST%3E"],[94,"impl-Component%3CR,+FixedNoState,+()%3E"],[111,"impl-Arc%3CMaybeUninit%3CT%3E,+A%3E"],[112,"impl-Arc%3C%5BMaybeUninit%3CT%3E%5D,+A%3E"],[168,"impl-Debug-for-Arc%3CT,+A%3E"],[169,"impl-Pointer-for-Arc%3CT,+A%3E"],[170,"impl-Display-for-Arc%3CT,+A%3E"],[173,"impl-From%3C%5BT;+N%5D%3E-for-Arc%3C%5BT%5D%3E"],[174,"impl-From%3C%26CStr%3E-for-Arc%3CCStr%3E"],[175,"impl-From%3CCow%3C\'a,+B%3E%3E-for-Arc%3CB%3E"],[176,"impl-From%3C%26str%3E-for-Arc%3Cstr%3E"],[177,"impl-From%3C%26OsStr%3E-for-Arc%3COsStr%3E"],[178,"impl-From%3CT%3E-for-Arc%3CT%3E"],[179,"impl-From%3CBox%3CT,+A%3E%3E-for-Arc%3CT,+A%3E"],[180,"impl-From%3CString%3E-for-Arc%3Cstr%3E"],[181,"impl-From%3COsString%3E-for-Arc%3COsStr%3E"],[182,"impl-From%3CArc%3Cstr%3E%3E-for-Arc%3C%5Bu8%5D%3E"],[185,"impl-From%3CVec%3CT,+A%3E%3E-for-Arc%3C%5BT%5D,+A%3E"],[186,"impl-From%3C%26%5BT%5D%3E-for-Arc%3C%5BT%5D%3E"],[187,"impl-From%3CCString%3E-for-Arc%3CCStr%3E"],[188,"impl-From%3CPathBuf%3E-for-Arc%3CPath%3E"],[189,"impl-From%3C%26Path%3E-for-Arc%3CPath%3E"],[349,"impl-Handler%3C(),+S%3E-for-MethodRouter%3CS%3E"],[350,"impl-Service%3CIncomingStream%3C\'_%3E%3E-for-MethodRouter"],[351,"impl-Service%3CRequest%3CB%3E%3E-for-MethodRouter%3C(),+E%3E"],[353,"impl-Service%3CIncomingStream%3C\'_%3E%3E-for-Router"],[354,"impl-Service%3CRequest%3CB%3E%3E-for-Router"],[464,"impl-Service%3CRequest%3CB%3E%3E-for-MethodRouter%3C(),+E%3E"],[465,"impl-Service%3CIncomingStream%3C\'_%3E%3E-for-MethodRouter"],[467,"impl-Service%3CRequest%3CB%3E%3E-for-Router"],[469,"impl-Service%3CIncomingStream%3C\'_%3E%3E-for-Router"]],"c":"OjAAAAAAAAA=","e":"OzAAAAEAAHUBSwACAAAABQABABcAAQAaABsAOgADAEIABQBJABYAYwABAGoAAABsAAAAbgABAHQABgB+AAAAgAABAIMAAgCHAAAAiwAAAI4AAACRAAAAkwAEAJkAAACdAAAAnwABAKIAAgCnAAUAuQAAAMAAAQDFAAMAzwAAANkAAQDcAAIA4AACAOsAAADyAAAAAAEAAAIBBwANAQAAEQEAABMBBgAdAQoAMwECADcBAAA5AQAAOwEBAE8BJQB5AQAAfgEGAIwBBQCkAQMAqQEEAK8BAQCyAQMAuQECANABCgDnAQUA8QEVAAwCBgAZAhAAQgIKAFACAABVAgAAVwIKAGYCBgBuAgIAcwICAHkCBwCEAgMAjAIAAI4CAACQAgUAlwIAAJwCBQCmAgEAsAIAALICDAA="}]\ ]')); if (typeof exports !== 'undefined') exports.searchIndex = searchIndex; else if (window.initSearch) window.initSearch(searchIndex); diff --git a/docs/search.desc/fishnet/fishnet-desc-0-.js b/docs/search.desc/fishnet/fishnet-desc-0-.js index a870132..5f935b8 100644 --- a/docs/search.desc/fishnet/fishnet-desc-0-.js +++ b/docs/search.desc/fishnet/fishnet-desc-0-.js @@ -1 +1 @@ -searchState.loadedDescShard("fishnet", 0, "fishnet is a opinionated, performant web framework for …\nA block of markup is a string that does not need to be …\nA page represents a visitable route on the website.\nA simple website builder. A Website consists of multiple …\nAdd a page to the website.\nadd components to the page.\nreusable components for building web pages (aka the main …\nattribute macro for creating new components\nEnable or disable compression for the website.\ndata structures and functions for dealing with css\nmacro for generating a StyleFragment from css.\nsame as component, but forces the component to be …\nReturns the argument unchanged.\nReturns the argument unchanged.\nmacro for generating Markup from html.\nCalls U::from(self).\nCalls U::from(self).\ndata structures and functions for dealing with js\nCreate a new page.\nCreate a new website.\nadd js to the page from outside a component.\nStart serving the website on the given port.\nServe a directory as static files.\nadd css to the page from outside a component.\nAdd content to the page.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\ncommonly used imports for building components.\nAdd state to the component. Since the state will be passed …\nA thread-safe reference-counting pointer. ‘Arc’ stands …\nAn owned dynamically typed Future for use in cases where …\nExtractor and response for extensions.\nAn extension trait for Futures that provides a variety of …\nA block of markup is a string that does not need to be …\nAn asynchronous Mutex-like type.\nRepresents a type that can be rendered as HTML.\nReturns a reference to the underlying allocator.\nProvides a raw pointer to the data.\nConverts to Arc<[T]>.\nConverts to Arc<T>.\nBlockingly locks this Mutex. When the lock has been …\nBlockingly locks this Mutex. When the lock has been …\nWrap the future in a Box, pinning it.\nWrap the future in a Box, pinning it.\nadd components to the page.\nCatches unwinding panics while polling the future.\nMakes a clone of the Arc pointer.\nComparison for two Arcs.\nattribute macro for creating new components\nattribute macro for creating new components\nCreates a new lock in an unlocked state ready for use.\nmacro for generating a StyleFragment from css.\nmacro for generating a StyleFragment from css.\nDecrements the strong reference count on the Arc<T> …\nDecrements the strong reference count on the Arc<T> …\nCreates a new Arc<T>, with the Default value for T.\nAttempt to downcast the Arc<dyn Any + Send + Sync> to a …\nDowncasts the Arc<dyn Any + Send + Sync> to a concrete …\nCreates a new Weak pointer to this allocation.\nDrops the Arc.\nsame as component, but forces the component to be …\nEquality for two Arcs.\nFlatten the execution of this future when the output of …\nFlatten the execution of this future when the successful …\nReturns the argument unchanged.\nConverts a [T; N] into an Arc<[T]>.\nAllocate a reference-counted slice and fill it by cloning v…\nAllocate a reference-counted slice and move v’s items …\nConverts an atomically reference-counted string slice into …\nReturns the argument unchanged.\nConverts a CString into an Arc<CStr> by moving the CString …\nAllocate a reference-counted str and copy v into it.\nMove a boxed object to a new, reference-counted allocation.\nConverts a &CStr into a Arc<CStr>, by copying the contents …\nConverts a Path into an Arc by copying the Path data into …\nCopies the string into a newly allocated Arc<OsStr>.\nCreate an atomically reference-counted pointer from a …\nAllocate a reference-counted str and copy v into it.\nConverts a PathBuf into an Arc<Path> by moving the PathBuf …\nConverts a T into an Arc<T>\nConverts an OsString into an Arc<OsStr> by moving the …\nReturns the argument unchanged.\nTakes each element in the Iterator and collects it into an …\nConstructs an Arc<T> from a raw pointer.\nConstructs an Arc<T, A> from a raw pointer.\nFuse a future such that poll will never again be called …\n‘Greater than or equal to’ comparison for two Arcs.\nReturns a mutable reference into the given Arc, if there …\nReturns a mutable reference to the underlying data.\nReturns a mutable reference into the given Arc, without …\nGreater-than comparison for two Arcs.\nIncrements the strong reference count on the Arc<T> …\nIncrements the strong reference count on the Arc<T> …\nDo something with the output of a future before passing it …\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nReturns the inner value, if the Arc has exactly one strong …\nConsumes the mutex, returning the underlying data.\nConsumes the Arc, returning the wrapped pointer.\nConvert this future into a single element stream.\n‘Less than or equal to’ comparison for two Arcs.\nWrap this future in an Either future, making it the …\nLocks this mutex, causing the current task to yield until …\nLocks this mutex, causing the current task to yield until …\nLess-than comparison for two Arcs.\nMakes a mutable reference into the given Arc.\nMap this future’s output to a different type, returning …\nMap this future’s output to a different type, returning …\nInequality for two Arcs.\nTurns a Future<Output = T> into a …\nConstructs a new Arc<T>.\nCreates a new lock in an unlocked state ready for use.\nConstructs a new Arc<T> while giving you a Weak<T> to the …\nConstructs a new Arc<T> in the provided allocator.\nConstructs a new Arc with uninitialized contents.\nConstructs a new Arc with uninitialized contents in the …\nConstructs a new atomically reference-counted slice with …\nConstructs a new atomically reference-counted slice with …\nConstructs a new Arc with uninitialized contents, with the …\nConstructs a new Arc with uninitialized contents, with the …\nConstructs a new atomically reference-counted slice with …\nConstructs a new atomically reference-counted slice with …\nEvaluates and consumes the future, returning the resulting …\nPartial comparison for two Arcs.\nConstructs a new Pin<Arc<T>>. If T does not implement Unpin…\nConstructs a new Pin<Arc<T, A>> in the provided allocator. …\nA convenience for calling Future::poll on Unpin future …\nReturns true if the two Arcs point to the same allocation …\nTurn this future into a future that yields () on …\nRenders self as a block of Markup.\nAppends a representation of self to the given buffer.\nWrap this future in an Either future, making it the …\nRouting between Services and handlers.\nadd js to the page from outside a component.\nCreate a cloneable handle to this future where all handles …\nGets the number of strong (Arc) pointers to this …\nadd css to the page from outside a component.\nChain on a computation for when a future finished, passing …\nAttempts to acquire the lock, and returns TryLockError if …\nAttempts to acquire the lock, and returns TryLockError if …\nConstructs a new Arc<T>, returning an error if allocation …\nConstructs a new Arc<T, A> in the provided allocator, …\nConstructs a new Arc with uninitialized contents, …\nConstructs a new Arc with uninitialized contents, in the …\nConstructs a new Arc with uninitialized contents, with the …\nConstructs a new Arc with uninitialized contents, with the …\nConstructs a new Pin<Arc<T>>, return an error if …\nConstructs a new Pin<Arc<T, A>> in the provided allocator, …\nReturns the inner value, if the Arc has exactly one strong …\nTurns a Future<Output = T> into a …\nIf we have the only reference to T then unwrap it. …\nGets the number of Weak pointers to this allocation.\nMatch DELETE requests.\nMatch GET requests.\nMatch HEAD requests.\nA MakeService that produces axum router services.\nA filter that matches one or more HTTP methods.\nA Service that accepts requests based on a MethodFilter and\nMatch OPTIONS requests.\nMatch PATCH requests.\nMatch POST requests.\nMatch PUT requests.\nHow routes are stored inside a Router.\nThe router type for composing handlers and services.\nA Router converted into a borrowed Service with a fixed …\nA Router converted into an owned Service with a fixed body …\nMatch TRACE requests.\nRoute requests with the given handler regardless of the …\nRoute requests to the given service regardless of its …\nConvert the router into a borrowed Service with a fixed …\nRoute DELETE requests to the given handler.\nChain an additional handler that will only accept DELETE …\nRoute DELETE requests to the given service.\nChain an additional service that will only accept DELETE …\nAdd a fallback Handler to the router.\nAdd a fallback Handler to the router.\nAdd a fallback service to the router.\nAdd a fallback Service to the router.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nFuture types.\nRoute GET requests to the given handler.\nChain an additional handler that will only accept GET …\nRoute GET requests to the given service.\nChain an additional service that will only accept GET …\nApply a HandleErrorLayer.\nRoute HEAD requests to the given handler.\nChain an additional handler that will only accept HEAD …\nRoute HEAD requests to the given service.\nChain an additional service that will only accept HEAD …\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nConvert the router into a MakeService.\nConvert this router into a MakeService, that is a Service …\nConvert the router into a MakeService which stores …\nConvert this router into a MakeService, that will store C…\nConvert the router into an owned Service with a fixed …\nApply a tower::Layer to all routes in the router.\nApply a tower::Layer to all routes in the router.\nMerge two routers into one.\nMerge the paths and fallbacks of two routers into a single …\nRoute to services and handlers based on HTTP methods.\nNest a Router at some path.\nLike nest, but accepts an arbitrary Service.\nCreate a default MethodRouter that will respond with …\nCreate a new Router.\nRoute requests with the given method to the handler.\nChain an additional handler that will accept requests …\nRoute requests with the given method to the service.\nChain an additional service that will accept requests …\nRoute OPTIONS requests to the given handler.\nChain an additional handler that will only accept OPTIONS …\nRoute OPTIONS requests to the given service.\nChain an additional service that will only accept OPTIONS …\nPerforms the OR operation between the MethodFilter in self …\nRoute PATCH requests to the given handler.\nChain an additional handler that will only accept PATCH …\nRoute PATCH requests to the given service.\nChain an additional service that will only accept PATCH …\nRoute POST requests to the given handler.\nChain an additional handler that will only accept POST …\nRoute POST requests to the given service.\nChain an additional service that will only accept POST …\nRoute PUT requests to the given handler.\nChain an additional handler that will only accept PUT …\nRoute PUT requests to the given service.\nChain an additional service that will only accept PUT …\nAdd another route to the router.\nApply a tower::Layer to the router that will only run if …\nApply a tower::Layer to the router that will only run if …\nAdd another route to the router that calls a Service.\nRoute TRACE requests to the given handler.\nChain an additional handler that will only accept TRACE …\nRoute TRACE requests to the given service.\nChain an additional service that will only accept TRACE …\nProvide the state for the router.\nProvide the state for the router.\nA RouteFuture that always yields a Response.\nResponse future for IntoMakeService.\nResponse future for Route.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nA Service that accepts requests based on a MethodFilter and\nRoute requests with the given handler regardless of the …\nRoute requests to the given service regardless of its …\nRoute DELETE requests to the given handler.\nRoute DELETE requests to the given service.\nRoute GET requests to the given handler.\nRoute GET requests to the given service.\nRoute HEAD requests to the given handler.\nRoute HEAD requests to the given service.\nRoute requests with the given method to the handler.\nRoute requests with the given method to the service.\nRoute OPTIONS requests to the given handler.\nRoute OPTIONS requests to the given service.\nRoute PATCH requests to the given handler.\nRoute PATCH requests to the given service.\nRoute POST requests to the given handler.\nRoute POST requests to the given service.\nRoute PUT requests to the given handler.\nRoute PUT requests to the given service.\nRoute TRACE requests to the given handler.\nRoute TRACE requests to the given service.\nstring representation of a rendered StyleFragment.\ncss generated using the css! macro.\na full css stylesheet\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nconstruct a new StyleFragment using the given string.\nrender the StyleFragment relative to the passed in …\nan external script file.\nan inline script\nstring representation of a script\nsource of a javascript script\nconsume the ScriptString, returning the inner string.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nminify the given ScriptString. this will also wrap it in …") \ No newline at end of file +searchState.loadedDescShard("fishnet", 0, "fishnet is a opinionated, performant web framework for …\nA block of markup is a string that does not need to be …\nA simple website builder. A Website consists of multiple …\nAdd a page to the website.\nadd components to the page.\nreusable components for building web pages (aka the main …\nattribute macro for creating new components\nEnable or disable compression for the website.\ndata structures and functions for dealing with css\nmacro for generating a StyleFragment from css.\nsame as component, but forces the component to be …\nReturns the argument unchanged.\nmacro for generating Markup from html.\nCalls U::from(self).\ndata structures and functions for dealing with js\nCreate a new website.\nA visitable page on the Website.\nadd js to the page\nStart serving the website on the given port.\nServe a directory as static files.\nadd css to the page\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\ncommonly used imports for building components.\nAdd state to the component. Since the state will be passed …\nA thread-safe reference-counting pointer. ‘Arc’ stands …\nAn owned dynamically typed Future for use in cases where …\nExtractor and response for extensions.\nAn extension trait for Futures that provides a variety of …\nA block of markup is a string that does not need to be …\nAn asynchronous Mutex-like type.\nRepresents a type that can be rendered as HTML.\nReturns a reference to the underlying allocator.\nProvides a raw pointer to the data.\nConverts to Arc<T>.\nConverts to Arc<[T]>.\nBlockingly locks this Mutex. When the lock has been …\nBlockingly locks this Mutex. When the lock has been …\nWrap the future in a Box, pinning it.\nWrap the future in a Box, pinning it.\nadd components to the page.\nCatches unwinding panics while polling the future.\nMakes a clone of the Arc pointer.\nComparison for two Arcs.\nattribute macro for creating new components\nattribute macro for creating new components\nCreates a new lock in an unlocked state ready for use.\nmacro for generating a StyleFragment from css.\nmacro for generating a StyleFragment from css.\nDecrements the strong reference count on the Arc<T> …\nDecrements the strong reference count on the Arc<T> …\nCreates a new Arc<T>, with the Default value for T.\nAttempt to downcast the Arc<dyn Any + Send + Sync> to a …\nDowncasts the Arc<dyn Any + Send + Sync> to a concrete …\nCreates a new Weak pointer to this allocation.\nDrops the Arc.\nsame as component, but forces the component to be …\nEquality for two Arcs.\nFlatten the execution of this future when the output of …\nFlatten the execution of this future when the successful …\nReturns the argument unchanged.\nConverts a [T; N] into an Arc<[T]>.\nConverts a &CStr into a Arc<CStr>, by copying the contents …\nCreate an atomically reference-counted pointer from a …\nAllocate a reference-counted str and copy v into it.\nCopies the string into a newly allocated Arc<OsStr>.\nConverts a T into an Arc<T>\nMove a boxed object to a new, reference-counted allocation.\nAllocate a reference-counted str and copy v into it.\nConverts an OsString into an Arc<OsStr> by moving the …\nConverts an atomically reference-counted string slice into …\nReturns the argument unchanged.\nAllocate a reference-counted slice and move v’s items …\nAllocate a reference-counted slice and fill it by cloning v…\nConverts a CString into an Arc<CStr> by moving the CString …\nConverts a PathBuf into an Arc<Path> by moving the PathBuf …\nConverts a Path into an Arc by copying the Path data into …\nReturns the argument unchanged.\nTakes each element in the Iterator and collects it into an …\nConstructs an Arc<T> from a raw pointer.\nConstructs an Arc<T, A> from a raw pointer.\nFuse a future such that poll will never again be called …\n‘Greater than or equal to’ comparison for two Arcs.\nReturns a mutable reference into the given Arc, if there …\nReturns a mutable reference to the underlying data.\nReturns a mutable reference into the given Arc, without …\nGreater-than comparison for two Arcs.\nmacro for generating Markup from html.\nIncrements the strong reference count on the Arc<T> …\nIncrements the strong reference count on the Arc<T> …\nDo something with the output of a future before passing it …\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nReturns the inner value, if the Arc has exactly one strong …\nConsumes the mutex, returning the underlying data.\nConsumes the Arc, returning the wrapped pointer.\nConvert this future into a single element stream.\n‘Less than or equal to’ comparison for two Arcs.\nWrap this future in an Either future, making it the …\nLocks this mutex, causing the current task to yield until …\nLocks this mutex, causing the current task to yield until …\nLess-than comparison for two Arcs.\nMakes a mutable reference into the given Arc.\nMap this future’s output to a different type, returning …\nMap this future’s output to a different type, returning …\nInequality for two Arcs.\nTurns a Future<Output = T> into a …\nConstructs a new Arc<T>.\nCreates a new lock in an unlocked state ready for use.\nConstructs a new Arc<T> while giving you a Weak<T> to the …\nConstructs a new Arc<T> in the provided allocator.\nConstructs a new Arc with uninitialized contents.\nConstructs a new Arc with uninitialized contents in the …\nConstructs a new atomically reference-counted slice with …\nConstructs a new atomically reference-counted slice with …\nConstructs a new Arc with uninitialized contents, with the …\nConstructs a new Arc with uninitialized contents, with the …\nConstructs a new atomically reference-counted slice with …\nConstructs a new atomically reference-counted slice with …\nEvaluates and consumes the future, returning the resulting …\nPartial comparison for two Arcs.\nConstructs a new Pin<Arc<T>>. If T does not implement Unpin…\nConstructs a new Pin<Arc<T, A>> in the provided allocator. …\nA convenience for calling Future::poll on Unpin future …\nReturns true if the two Arcs point to the same allocation …\nTurn this future into a future that yields () on …\nRenders self as a block of Markup.\nAppends a representation of self to the given buffer.\nWrap this future in an Either future, making it the …\nRouting between Services and handlers.\nadd js to the page\nCreate a cloneable handle to this future where all handles …\nGets the number of strong (Arc) pointers to this …\nadd css to the page\nChain on a computation for when a future finished, passing …\nAttempts to acquire the lock, and returns TryLockError if …\nAttempts to acquire the lock, and returns TryLockError if …\nConstructs a new Arc<T>, returning an error if allocation …\nConstructs a new Arc<T, A> in the provided allocator, …\nConstructs a new Arc with uninitialized contents, …\nConstructs a new Arc with uninitialized contents, in the …\nConstructs a new Arc with uninitialized contents, with the …\nConstructs a new Arc with uninitialized contents, with the …\nConstructs a new Pin<Arc<T>>, return an error if …\nConstructs a new Pin<Arc<T, A>> in the provided allocator, …\nReturns the inner value, if the Arc has exactly one strong …\nTurns a Future<Output = T> into a …\nIf we have the only reference to T then unwrap it. …\nGets the number of Weak pointers to this allocation.\nMatch DELETE requests.\nMatch GET requests.\nMatch HEAD requests.\nA MakeService that produces axum router services.\nA filter that matches one or more HTTP methods.\nA Service that accepts requests based on a MethodFilter and\nMatch OPTIONS requests.\nMatch PATCH requests.\nMatch POST requests.\nMatch PUT requests.\nHow routes are stored inside a Router.\nThe router type for composing handlers and services.\nA Router converted into a borrowed Service with a fixed …\nA Router converted into an owned Service with a fixed body …\nMatch TRACE requests.\nRoute requests with the given handler regardless of the …\nRoute requests to the given service regardless of its …\nConvert the router into a borrowed Service with a fixed …\nRoute DELETE requests to the given handler.\nChain an additional handler that will only accept DELETE …\nRoute DELETE requests to the given service.\nChain an additional service that will only accept DELETE …\nAdd a fallback Handler to the router.\nAdd a fallback Handler to the router.\nAdd a fallback service to the router.\nAdd a fallback Service to the router.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nFuture types.\nRoute GET requests to the given handler.\nChain an additional handler that will only accept GET …\nRoute GET requests to the given service.\nChain an additional service that will only accept GET …\nApply a HandleErrorLayer.\nRoute HEAD requests to the given handler.\nChain an additional handler that will only accept HEAD …\nRoute HEAD requests to the given service.\nChain an additional service that will only accept HEAD …\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nConvert the router into a MakeService.\nConvert this router into a MakeService, that is a Service …\nConvert the router into a MakeService which stores …\nConvert this router into a MakeService, that will store C…\nConvert the router into an owned Service with a fixed …\nApply a tower::Layer to all routes in the router.\nApply a tower::Layer to all routes in the router.\nMerge two routers into one.\nMerge the paths and fallbacks of two routers into a single …\nRoute to services and handlers based on HTTP methods.\nNest a Router at some path.\nLike nest, but accepts an arbitrary Service.\nCreate a default MethodRouter that will respond with …\nCreate a new Router.\nRoute requests with the given method to the handler.\nChain an additional handler that will accept requests …\nRoute requests with the given method to the service.\nChain an additional service that will accept requests …\nRoute OPTIONS requests to the given handler.\nChain an additional handler that will only accept OPTIONS …\nRoute OPTIONS requests to the given service.\nChain an additional service that will only accept OPTIONS …\nPerforms the OR operation between the MethodFilter in self …\nRoute PATCH requests to the given handler.\nChain an additional handler that will only accept PATCH …\nRoute PATCH requests to the given service.\nChain an additional service that will only accept PATCH …\nRoute POST requests to the given handler.\nChain an additional handler that will only accept POST …\nRoute POST requests to the given service.\nChain an additional service that will only accept POST …\nRoute PUT requests to the given handler.\nChain an additional handler that will only accept PUT …\nRoute PUT requests to the given service.\nChain an additional service that will only accept PUT …\nAdd another route to the router.\nApply a tower::Layer to the router that will only run if …\nApply a tower::Layer to the router that will only run if …\nAdd another route to the router that calls a Service.\nRoute TRACE requests to the given handler.\nChain an additional handler that will only accept TRACE …\nRoute TRACE requests to the given service.\nChain an additional service that will only accept TRACE …\nProvide the state for the router.\nProvide the state for the router.\nA RouteFuture that always yields a Response.\nResponse future for IntoMakeService.\nResponse future for Route.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nA Service that accepts requests based on a MethodFilter and\nRoute requests with the given handler regardless of the …\nRoute requests to the given service regardless of its …\nRoute DELETE requests to the given handler.\nRoute DELETE requests to the given service.\nRoute GET requests to the given handler.\nRoute GET requests to the given service.\nRoute HEAD requests to the given handler.\nRoute HEAD requests to the given service.\nRoute requests with the given method to the handler.\nRoute requests with the given method to the service.\nRoute OPTIONS requests to the given handler.\nRoute OPTIONS requests to the given service.\nRoute PATCH requests to the given handler.\nRoute PATCH requests to the given service.\nRoute POST requests to the given handler.\nRoute POST requests to the given service.\nRoute PUT requests to the given handler.\nRoute PUT requests to the given service.\nRoute TRACE requests to the given handler.\nRoute TRACE requests to the given service.\nstring representation of a rendered StyleFragment.\ncss generated using the css! macro.\na full css stylesheet\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nconstruct a new StyleFragment using the given string.\nrender the StyleFragment relative to the passed in …\nan external script file.\nan inline script\nstring representation of a script\nsource of a javascript script\nconsume the ScriptString, returning the inner string.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nminify the given ScriptString. this will also wrap it in …\nA page represents a visitable route on the website.\nAllows attaching a page to a router.\nAttach the given page to the router. This involves …\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCreate a new page.\nmanaging resources during a render\nAdd content to the page.\ncollection of resources that are page independent\na single global (page independent) resource\nThe result of a page render.\nadd a GlobalStoreEntry to the store\nEnter a page render context.\nEnter a temporary render context.\nExit a page render context.\nExit a temporary render context.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nget a GlobalStoreEntry from its id.\nacquire access to the GlobalStore.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nRender a component into the current page render context.") \ No newline at end of file diff --git a/docs/src/fishnet/component.rs.html b/docs/src/fishnet/component.rs.html index 057b5e1..0198323 100644 --- a/docs/src/fishnet/component.rs.html +++ b/docs/src/fishnet/component.rs.html @@ -246,6 +246,7 @@ 246 247 248 +249

    //! reusable components for building web pages (aka the main thing)
     
     pub mod prelude;
    @@ -256,7 +257,8 @@
     mod render;
     use render::ContentRenderer;
     
    -pub mod fake_macros;
    +#[doc(hidden)]
    +pub mod fake_macros;
     
     use crate::css::StyleFragment;
     use crate::js::ScriptType;
    diff --git a/docs/src/fishnet/component/prelude.rs.html b/docs/src/fishnet/component/prelude.rs.html
    index 40e1129..2e1fa1b 100644
    --- a/docs/src/fishnet/component/prelude.rs.html
    +++ b/docs/src/fishnet/component/prelude.rs.html
    @@ -29,15 +29,15 @@
     pub use crate::c;
     
     // components itself
    -pub use super::{BuildableComponent, ComponentState};
    -
    -pub use super::fake_macros::*;
    +pub use super::fake_macros::state;
    +pub use super::fake_macros::state_init;
    +pub use super::{BuildableComponent, ComponentState};
     pub use crate::{component, dyn_component};
     
     // html, js, css
     pub use crate::js::ScriptType;
    -pub use crate::{css, script, style};
    -pub use maud::{html, Markup, Render};
    +pub use crate::{css, html, script, style, Markup};
    +pub use maud::Render;
     
     // boxing runner futures
     pub use futures::future::{BoxFuture, FutureExt};
    diff --git a/docs/src/fishnet/css.rs.html b/docs/src/fishnet/css.rs.html
    index 17d132c..109acdf 100644
    --- a/docs/src/fishnet/css.rs.html
    +++ b/docs/src/fishnet/css.rs.html
    @@ -124,6 +124,7 @@
     124
     125
     126
    +127
     
    //! data structures and functions for dealing with css
     use std::collections::{hash_map::Entry, HashMap};
     use tracing::debug;
    @@ -193,6 +194,7 @@
     ///
     /// a stylesheet is basically just a collection of [`RenderedStyle`]s. however it caches all its
     /// renders, so you can only add to it and never remove things.
    +#[derive(Debug)]
     pub struct Stylesheet {
         style: String,
         rendered_media_queries: String,
    diff --git a/docs/src/fishnet/lib.rs.html b/docs/src/fishnet/lib.rs.html
    index ede897b..b3d6ac1 100644
    --- a/docs/src/fishnet/lib.rs.html
    +++ b/docs/src/fishnet/lib.rs.html
    @@ -363,6 +363,7 @@
     363
     364
     365
    +366
     
    //! fishnet is a opinionated, performant web framework for small projects and personal websites where [htmx](https://htmx.org/) is a first class citizen.
     //!
     //! # overview
    @@ -529,11 +530,14 @@
     //!
     //! #[component]
     //! fn awesome_htmx_btn() {
    +//!
     //!     #[route("/", POST)]
    -//!     async fn click_endpoint(state: Extension<_>) -> Markup {
    +//!     async fn click_endpoint(state: Extension<ComponentState<()>>) -> Markup {
     //!         html! { "hiiii!!" }
     //!     }
     //!
    +//!     // just leave the state empty
    +//!     let state = state!(());
     //!     html! {
     //!         button hx-post=(state.endpoint()) hx-swap="outerHTML" {
     //!             "click me"
    @@ -587,8 +591,8 @@
     //! `> div` is perfectly valid. it selects all the `div`s that are direct children of the
     //! component. this also means that a selector like `*` will only affect the components children.
     //!
    -//! if you want to style a specific child component, its class name will always be derived from the
    -//! type you put into the [`component!`](macro@component) macro (e.g. "SomeChild" becomes
    +//! if you want to style a specific child component, its css class name will always be derived from the
    +//! components function name when using the [`component`](macro@component) macro (e.g. "some_child" becomes
     //! "some-child"). this also means that conflicts can occur if you use the same name multiple
     //! times, choose your names wisely...
     //!
    @@ -606,9 +610,7 @@
     pub mod component;
     mod routes;
     
    -mod page;
    -#[doc(hidden)]
    -pub use page::render_context::{global_store, render_component, GlobalStoreEntry};
    +pub mod page;
     pub use page::Page;
     
     mod website;
    diff --git a/docs/src/fishnet/page.rs.html b/docs/src/fishnet/page.rs.html
    index c1d8745..6db58c7 100644
    --- a/docs/src/fishnet/page.rs.html
    +++ b/docs/src/fishnet/page.rs.html
    @@ -291,10 +291,10 @@
         head: Markup,
         body_renderer: Box<dyn Fn() -> BoxFuture<'static, Markup> + Send + Sync>,
     
    -    pub used_globals: HashSet<String>,
    -    pub components: Arc<Mutex<ComponentStore>>,
    +    used_globals: HashSet<String>,
    +    components: Arc<Mutex<ComponentStore>>,
     
    -    pub api_path: String,
    +    api_path: String,
         api_router: APIRouter,
     
         script_path: String,
    @@ -309,7 +309,7 @@
     
     impl BuiltPage {
         #[instrument(name = "Page::build", skip_all, fields(name = %page.name))]
    -    async fn new(page: Page, path: &str) -> (Arc<Mutex<BuiltPage>>, Router) {
    +    pub async fn new(page: Page, path: &str) -> (Arc<Mutex<BuiltPage>>, Router) {
             let base_path = path.trim_end_matches('/');
             let script_path = format!("{}/script.js", base_path);
             let style_path = format!("{}/style.css", base_path);
    @@ -367,7 +367,7 @@
             )
         }
     
    -    async fn render(page: Extension<Arc<Mutex<Self>>>) -> Markup {
    +    pub async fn render(page: Extension<Arc<Mutex<Self>>>) -> Markup {
             let start = std::time::Instant::now();
     
             let mut page_guard = page.lock().await;
    diff --git a/docs/src/fishnet/page/render_context.rs.html b/docs/src/fishnet/page/render_context.rs.html
    index 8a1129e..8e881c6 100644
    --- a/docs/src/fishnet/page/render_context.rs.html
    +++ b/docs/src/fishnet/page/render_context.rs.html
    @@ -386,7 +386,76 @@
     386
     387
     388
    -
    use axum::routing::Router;
    +389
    +390
    +391
    +392
    +393
    +394
    +395
    +396
    +397
    +398
    +399
    +400
    +401
    +402
    +403
    +404
    +405
    +406
    +407
    +408
    +409
    +410
    +411
    +412
    +413
    +414
    +415
    +416
    +417
    +418
    +419
    +420
    +421
    +422
    +423
    +424
    +425
    +426
    +427
    +428
    +429
    +430
    +431
    +432
    +433
    +434
    +435
    +436
    +437
    +438
    +439
    +440
    +441
    +442
    +
    //! managing resources during a render
    +//!
    +//! the render context is used under the hood whenever you use macros that add things to the
    +//! page (e.g. [`c!`](crate::c!), [`style!`](crate::style!), [`script!`](crate::script!), ...).
    +//!
    +//! before a page renders its contents, it attaches itself to the render context via [`enter_page`]. during the
    +//! render when a resource is about to be added, it is first checked whether it already exists on
    +//! the render context. if yes, it is not added again and just reused. otherwise it is newly
    +//! constructed. after the render is finished, the page can use [`exit_page`] to get a list of all
    +//! the newly constructed things during the render and then process them further (e.g. add routes
    +//! from new components, minify added scripts, ...)
    +//!
    +//! you usually don't need to call anything from in here manually unless you want to have finer
    +//! control over resources (like dynamically adding resources to the page)
    +
    +use axum::routing::Router;
     use futures::future::BoxFuture;
     use maud::{html, Markup};
     use std::collections::{hash_map::Entry, HashMap, HashSet};
    @@ -398,20 +467,22 @@
     use crate::component::{BuildableComponent, BuiltComponent};
     use crate::page::BuiltPage;
     use crate::routes::ComponentRoute;
    +use crate::{css, js};
     
     fn render_context() -> &'static Mutex<Option<RenderContext>> {
         static RENDER_CONTEXT: OnceLock<Mutex<Option<RenderContext>>> = OnceLock::new();
         RENDER_CONTEXT.get_or_init(|| Mutex::new(None))
     }
     
    -#[doc(hidden)]
    +/// acquire access to the [`GlobalStore`].
     pub fn global_store() -> &'static GlobalStore {
         static GLOBAL_STORE: OnceLock<GlobalStore> = OnceLock::new();
         GLOBAL_STORE.get_or_init(|| GlobalStore::new())
     }
     
     #[derive(Debug)]
    -pub(crate) struct ComponentStore(HashMap<String, BuiltComponent>);
    +#[doc(hidden)]
    +pub struct ComponentStore(pub HashMap<String, BuiltComponent>);
     
     impl ComponentStore {
         pub(crate) fn new() -> Self {
    @@ -419,21 +490,29 @@
         }
     }
     
    -#[derive(Debug)]
    -#[doc(hidden)]
    +/// a single global (page independent) resource
    +#[derive(Debug)]
     pub struct GlobalStoreEntry {
    -    pub scripts: Vec<crate::js::ScriptType>,
    -    pub style: Option<crate::css::RenderedStyle>,
    +    pub scripts: Vec<js::ScriptType>,
    +    pub style: Option<css::RenderedStyle>,
     }
     
    -#[derive(Debug)]
    +/// collection of resources that are page independent
    +#[derive(Debug)]
     pub struct GlobalStore(Mutex<HashMap<String, Arc<GlobalStoreEntry>>>);
     impl GlobalStore {
    -    pub fn new() -> Self {
    +    pub(crate) fn new() -> Self {
             Self(Mutex::new(HashMap::new()))
         }
     
    -    pub async fn add<F>(&self, id: &str, globals: F)
    +    /// add a [`GlobalStoreEntry`] to the store
    +    ///
    +    /// does nothing if there already is a entry under the given id.
    +    /// otherwise the `globals` closure is executed to create a new entry
    +    ///
    +    /// this will also notify the currently active render context about the newly added resource
    +    /// (which usually means that it gets added to the rendered page)
    +    pub async fn add<F>(&self, id: &str, globals: F)
         where
             F: FnOnce() -> GlobalStoreEntry,
         {
    @@ -450,12 +529,13 @@
             }
         }
     
    -    pub async fn get<'a>(&'a self, id: &str) -> Option<Arc<GlobalStoreEntry>> {
    +    /// get a [`GlobalStoreEntry`] from its id.
    +    pub async fn get<'a>(&'a self, id: &str) -> Option<Arc<GlobalStoreEntry>> {
             self.0.lock().await.get(id).cloned()
         }
     }
     
    -struct RenderContext {
    +pub(crate) struct RenderContext {
         base_route: String,
     
         components: Arc<Mutex<ComponentStore>>,
    @@ -501,7 +581,7 @@
     /// Contains all the scripts, runners and routers that were collected during the rendering.
     /// * `scripts` - A list of scripts that should be included in the page.
     /// * `runners` - A list of runners that should be executed.
    -/// * `routers` - A list of routers that should be accessible from the page. This is usually achieved using a [APIRouter](`crate::routes::APIRouter`).
    +/// * `routers` - A list of routers that should be accessible from the page at the given routes
     pub struct RenderResult {
         pub runners: Vec<BoxFuture<'static, ()>>,
         pub routers: Vec<(ComponentRoute, Router)>,
    @@ -513,9 +593,7 @@
     /// This should be called before rendering any components.
     /// After the rendering is complete, `exit_page` should be called to acquire the results.
     /// Calling `enter_page` while another page is being rendered results in the loss of the previous page's render results!
    -///
    -/// You usually don't need to call this function yourself.
    -pub(crate) async fn enter_page(page: &mut BuiltPage) {
    +pub async fn enter_page(page: &mut BuiltPage) {
         let mut context = render_context().lock().await;
     
         if context.is_some() {
    @@ -528,10 +606,9 @@
     /// Exit a page render context.
     ///
     /// This should be called after rendering all components. It will return the `RenderResult` containing all the scripts and runners that were collected during the rendering.
    -///
     /// # Panics
     /// Panics if no page is currently being rendered. (i.e. `enter_page` was not called before)
    -pub(crate) async fn exit_page() -> RenderResult {
    +pub async fn exit_page() -> RenderResult {
         let mut context = render_context().lock().await;
     
         context
    @@ -638,10 +715,11 @@
     /// Furthermore, it will be recorded, whether any dynamic components were rendered during the temporary render.
     /// This can be used to "test-render" a static component to see if it contains any dynamic children.
     ///
    -/// Temporary render contexts can be exited using `exit_temporary_render`, and can be nested.
    +/// Temporary render contexts can be exited using [`exit_temporary_render`], and can be multiple
    +/// levels deep. it is up to you to ensure that you always exit every render you enter.
     ///
     /// You usually don't need to call this function yourself.
    -pub(crate) async fn enter_temporary_render() {
    +pub async fn enter_temporary_render() {
         let mut context = render_context().lock().await;
         if let Some(context) = context.as_mut() {
             trace!("entering temporary render");
    @@ -654,11 +732,11 @@
     
     /// Exit a temporary render context.
     ///
    -/// Returns true if the temporary render was static (i.e. no dynamic components were rendered).
    +/// Returns true if the temporary render started via [`enter_temporary_render`] was static (i.e. no dynamic components were rendered).
     /// If not within a (temporary) render context, this function will always return true.
     ///
     /// You usually don't need to call this function yourself.
    -pub(crate) async fn exit_temporary_render() -> bool {
    +pub async fn exit_temporary_render() -> bool {
         let mut context = render_context().lock().await;
         if let Some(context) = context.as_mut() {
             if context.temporary_render_depth == 0 {
    @@ -677,12 +755,32 @@
         }
     }
     
    -/// add [`css`](crate::css!) to the page from outside a component.
    +/// add [`css`](crate::css!) to the page
     ///
    -/// this is helpful for adding styling to functions that just return [`Markup`](crate::Markup).
    -/// you have to call this from within a page render or the css will not be added to the page.
    +/// you have to call this from within a page render or it will not work.
     ///
    -/// ### usage
    +/// there are two ways to use this macro:
    +/// ## from within a component
    +/// ```rust
    +/// use fishnet::component::prelude::*;
    +///
    +/// #[component]
    +/// async fn my_component() {
    +///     style!(css!{
    +///         color: red;
    +///     });
    +///
    +///     html! {
    +///         "hello world!"
    +///     }
    +/// }
    +///```
    +///
    +/// ## from outside a component
    +/// additionally to providing the style, you also have to name the top level class yourself as the
    +/// first argument.
    +///
    +/// this is helpful for adding styling to functions that just return [`Markup`](crate::Markup).
     /// ```rust
     /// use fishnet::{style, html, Markup, css};
     ///
    @@ -697,22 +795,30 @@
     ///         }
     ///     }
     /// }
    +/// ```
     #[macro_export]
     macro_rules! style {
    +    ($css: expr) => {{
    +        compile_error!(
    +            "you have to provide a class name to the style macro or use it from within a component"
    +        );
    +    }};
         ($tl_class: literal, $css:expr) => {{
    -        $crate::global_store()
    -            .add($crate::const_nanoid!(10), || $crate::GlobalStoreEntry {
    -                scripts: Vec::new(),
    -                style: Some($css.render($tl_class)),
    +        $crate::page::render_context::global_store()
    +            .add($crate::const_nanoid!(10), || {
    +                $crate::page::render_context::GlobalStoreEntry {
    +                    scripts: Vec::new(),
    +                    style: Some($css.render($tl_class)),
    +                }
                 })
                 .await;
         }};
     }
     
    -/// add js to the page from outside a component.
    +/// add js to the page
     ///
    -/// this is helpful for adding styling to functions that just return [`Markup`](crate::Markup).
    -/// you have to call this from within a page render or the js will not be added to the page.
    +/// differently to the [`css!`] macro, this will work identically whether you are within a
    +/// component or not. you still have to be within a page render though or it will do nothing.
     ///
     /// ### usage
     /// ```rust
    @@ -731,10 +837,12 @@
     #[macro_export]
     macro_rules! script {
         ($js:literal) => {{
    -        $crate::global_store()
    -            .add($crate::const_nanoid!(10), || $crate::GlobalStoreEntry {
    -                scripts: vec![$crate::js::ScriptType::Inline($js)],
    -                style: None,
    +        $crate::page::render_context::global_store()
    +            .add($crate::const_nanoid!(10), || {
    +                $crate::page::render_context::GlobalStoreEntry {
    +                    scripts: vec![$crate::js::ScriptType::Inline($js)],
    +                    style: None,
    +                }
                 })
                 .await;
         }};
    @@ -771,7 +879,7 @@
         ($component:expr) => {{
             let component = || $component;
     
    -        $crate::render_component($crate::const_nanoid!(10), component).await
    +        $crate::page::render_context::render_component($crate::const_nanoid!(10), component).await
         }};
     }
     
    \ No newline at end of file diff --git a/docs/trait.impl/core/fmt/trait.Debug.js b/docs/trait.impl/core/fmt/trait.Debug.js index daeb656..af23cd7 100644 --- a/docs/trait.impl/core/fmt/trait.Debug.js +++ b/docs/trait.impl/core/fmt/trait.Debug.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"fishnet":[["impl Debug for ScriptType"],["impl Debug for BuiltComponent"],["impl Debug for RenderedStyle"],["impl Debug for ScriptString"],["impl<ST> Debug for ComponentState<ST>
    where\n ST: Clone + Send + Sync + Debug,
    "]] +"fishnet":[["impl Debug for ScriptType"],["impl Debug for BuiltComponent"],["impl Debug for RenderedStyle"],["impl Debug for Stylesheet"],["impl Debug for ScriptString"],["impl Debug for GlobalStore"],["impl Debug for GlobalStoreEntry"],["impl<ST> Debug for ComponentState<ST>
    where\n ST: Clone + Send + Sync + Debug,
    "]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/core/marker/trait.Freeze.js b/docs/trait.impl/core/marker/trait.Freeze.js index f35025a..d92edbb 100644 --- a/docs/trait.impl/core/marker/trait.Freeze.js +++ b/docs/trait.impl/core/marker/trait.Freeze.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"fishnet":[["impl Freeze for ScriptType",1,["fishnet::js::ScriptType"]],["impl Freeze for BuiltComponent",1,["fishnet::component::build::BuiltComponent"]],["impl Freeze for ComponentBuildResult",1,["fishnet::component::build::ComponentBuildResult"]],["impl Freeze for RenderedStyle",1,["fishnet::css::RenderedStyle"]],["impl Freeze for Stylesheet",1,["fishnet::css::Stylesheet"]],["impl Freeze for ScriptString",1,["fishnet::js::ScriptString"]],["impl Freeze for Page",1,["fishnet::page::Page"]],["impl Freeze for Website",1,["fishnet::website::Website"]],["impl<'a> Freeze for StyleFragment<'a>",1,["fishnet::css::StyleFragment"]],["impl<R, S, ST> Freeze for Component<R, S, ST>
    where\n ST: Freeze,
    ",1,["fishnet::component::Component"]],["impl<ST> Freeze for ComponentState<ST>
    where\n ST: Freeze,
    ",1,["fishnet::component::ComponentState"]]] +"fishnet":[["impl !Freeze for GlobalStore",1,["fishnet::page::render_context::GlobalStore"]],["impl Freeze for ScriptType",1,["fishnet::js::ScriptType"]],["impl Freeze for BuiltComponent",1,["fishnet::component::build::BuiltComponent"]],["impl Freeze for ComponentBuildResult",1,["fishnet::component::build::ComponentBuildResult"]],["impl Freeze for RenderedStyle",1,["fishnet::css::RenderedStyle"]],["impl Freeze for Stylesheet",1,["fishnet::css::Stylesheet"]],["impl Freeze for ScriptString",1,["fishnet::js::ScriptString"]],["impl Freeze for GlobalStoreEntry",1,["fishnet::page::render_context::GlobalStoreEntry"]],["impl Freeze for RenderResult",1,["fishnet::page::render_context::RenderResult"]],["impl Freeze for BuiltPage",1,["fishnet::page::BuiltPage"]],["impl Freeze for Page",1,["fishnet::page::Page"]],["impl Freeze for Website",1,["fishnet::website::Website"]],["impl<'a> Freeze for StyleFragment<'a>",1,["fishnet::css::StyleFragment"]],["impl<R, S, ST> Freeze for Component<R, S, ST>
    where\n ST: Freeze,
    ",1,["fishnet::component::Component"]],["impl<ST> Freeze for ComponentState<ST>
    where\n ST: Freeze,
    ",1,["fishnet::component::ComponentState"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/core/marker/trait.Send.js b/docs/trait.impl/core/marker/trait.Send.js index 2b4a394..9d1efb9 100644 --- a/docs/trait.impl/core/marker/trait.Send.js +++ b/docs/trait.impl/core/marker/trait.Send.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"fishnet":[["impl Send for ScriptType",1,["fishnet::js::ScriptType"]],["impl Send for BuiltComponent",1,["fishnet::component::build::BuiltComponent"]],["impl Send for ComponentBuildResult",1,["fishnet::component::build::ComponentBuildResult"]],["impl Send for RenderedStyle",1,["fishnet::css::RenderedStyle"]],["impl Send for Stylesheet",1,["fishnet::css::Stylesheet"]],["impl Send for ScriptString",1,["fishnet::js::ScriptString"]],["impl Send for Page",1,["fishnet::page::Page"]],["impl Send for Website",1,["fishnet::website::Website"]],["impl<'a> Send for StyleFragment<'a>",1,["fishnet::css::StyleFragment"]],["impl<R, S, ST> Send for Component<R, S, ST>
    where\n R: Send,\n S: Send,
    ",1,["fishnet::component::Component"]],["impl<ST> Send for ComponentState<ST>",1,["fishnet::component::ComponentState"]]] +"fishnet":[["impl Send for ScriptType",1,["fishnet::js::ScriptType"]],["impl Send for BuiltComponent",1,["fishnet::component::build::BuiltComponent"]],["impl Send for ComponentBuildResult",1,["fishnet::component::build::ComponentBuildResult"]],["impl Send for RenderedStyle",1,["fishnet::css::RenderedStyle"]],["impl Send for Stylesheet",1,["fishnet::css::Stylesheet"]],["impl Send for ScriptString",1,["fishnet::js::ScriptString"]],["impl Send for GlobalStore",1,["fishnet::page::render_context::GlobalStore"]],["impl Send for GlobalStoreEntry",1,["fishnet::page::render_context::GlobalStoreEntry"]],["impl Send for RenderResult",1,["fishnet::page::render_context::RenderResult"]],["impl Send for BuiltPage",1,["fishnet::page::BuiltPage"]],["impl Send for Page",1,["fishnet::page::Page"]],["impl Send for Website",1,["fishnet::website::Website"]],["impl<'a> Send for StyleFragment<'a>",1,["fishnet::css::StyleFragment"]],["impl<R, S, ST> Send for Component<R, S, ST>
    where\n R: Send,\n S: Send,
    ",1,["fishnet::component::Component"]],["impl<ST> Send for ComponentState<ST>",1,["fishnet::component::ComponentState"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/core/marker/trait.Sync.js b/docs/trait.impl/core/marker/trait.Sync.js index e3681a2..50c84b5 100644 --- a/docs/trait.impl/core/marker/trait.Sync.js +++ b/docs/trait.impl/core/marker/trait.Sync.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"fishnet":[["impl !Sync for ComponentBuildResult",1,["fishnet::component::build::ComponentBuildResult"]],["impl Sync for ScriptType",1,["fishnet::js::ScriptType"]],["impl Sync for BuiltComponent",1,["fishnet::component::build::BuiltComponent"]],["impl Sync for RenderedStyle",1,["fishnet::css::RenderedStyle"]],["impl Sync for Stylesheet",1,["fishnet::css::Stylesheet"]],["impl Sync for ScriptString",1,["fishnet::js::ScriptString"]],["impl Sync for Page",1,["fishnet::page::Page"]],["impl Sync for Website",1,["fishnet::website::Website"]],["impl<'a> Sync for StyleFragment<'a>",1,["fishnet::css::StyleFragment"]],["impl<R, S, ST> Sync for Component<R, S, ST>
    where\n R: Sync,\n S: Sync,
    ",1,["fishnet::component::Component"]],["impl<ST> Sync for ComponentState<ST>",1,["fishnet::component::ComponentState"]]] +"fishnet":[["impl !Sync for ComponentBuildResult",1,["fishnet::component::build::ComponentBuildResult"]],["impl !Sync for RenderResult",1,["fishnet::page::render_context::RenderResult"]],["impl Sync for ScriptType",1,["fishnet::js::ScriptType"]],["impl Sync for BuiltComponent",1,["fishnet::component::build::BuiltComponent"]],["impl Sync for RenderedStyle",1,["fishnet::css::RenderedStyle"]],["impl Sync for Stylesheet",1,["fishnet::css::Stylesheet"]],["impl Sync for ScriptString",1,["fishnet::js::ScriptString"]],["impl Sync for GlobalStore",1,["fishnet::page::render_context::GlobalStore"]],["impl Sync for GlobalStoreEntry",1,["fishnet::page::render_context::GlobalStoreEntry"]],["impl Sync for BuiltPage",1,["fishnet::page::BuiltPage"]],["impl Sync for Page",1,["fishnet::page::Page"]],["impl Sync for Website",1,["fishnet::website::Website"]],["impl<'a> Sync for StyleFragment<'a>",1,["fishnet::css::StyleFragment"]],["impl<R, S, ST> Sync for Component<R, S, ST>
    where\n R: Sync,\n S: Sync,
    ",1,["fishnet::component::Component"]],["impl<ST> Sync for ComponentState<ST>",1,["fishnet::component::ComponentState"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/core/marker/trait.Unpin.js b/docs/trait.impl/core/marker/trait.Unpin.js index 0dfc5d3..fa013c6 100644 --- a/docs/trait.impl/core/marker/trait.Unpin.js +++ b/docs/trait.impl/core/marker/trait.Unpin.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"fishnet":[["impl Unpin for ScriptType",1,["fishnet::js::ScriptType"]],["impl Unpin for BuiltComponent",1,["fishnet::component::build::BuiltComponent"]],["impl Unpin for ComponentBuildResult",1,["fishnet::component::build::ComponentBuildResult"]],["impl Unpin for RenderedStyle",1,["fishnet::css::RenderedStyle"]],["impl Unpin for Stylesheet",1,["fishnet::css::Stylesheet"]],["impl Unpin for ScriptString",1,["fishnet::js::ScriptString"]],["impl Unpin for Page",1,["fishnet::page::Page"]],["impl Unpin for Website",1,["fishnet::website::Website"]],["impl<'a> Unpin for StyleFragment<'a>",1,["fishnet::css::StyleFragment"]],["impl<R, S, ST> Unpin for Component<R, S, ST>
    where\n ST: Unpin,\n R: Unpin,\n S: Unpin,
    ",1,["fishnet::component::Component"]],["impl<ST> Unpin for ComponentState<ST>
    where\n ST: Unpin,
    ",1,["fishnet::component::ComponentState"]]] +"fishnet":[["impl Unpin for ScriptType",1,["fishnet::js::ScriptType"]],["impl Unpin for BuiltComponent",1,["fishnet::component::build::BuiltComponent"]],["impl Unpin for ComponentBuildResult",1,["fishnet::component::build::ComponentBuildResult"]],["impl Unpin for RenderedStyle",1,["fishnet::css::RenderedStyle"]],["impl Unpin for Stylesheet",1,["fishnet::css::Stylesheet"]],["impl Unpin for ScriptString",1,["fishnet::js::ScriptString"]],["impl Unpin for GlobalStore",1,["fishnet::page::render_context::GlobalStore"]],["impl Unpin for GlobalStoreEntry",1,["fishnet::page::render_context::GlobalStoreEntry"]],["impl Unpin for RenderResult",1,["fishnet::page::render_context::RenderResult"]],["impl Unpin for BuiltPage",1,["fishnet::page::BuiltPage"]],["impl Unpin for Page",1,["fishnet::page::Page"]],["impl Unpin for Website",1,["fishnet::website::Website"]],["impl<'a> Unpin for StyleFragment<'a>",1,["fishnet::css::StyleFragment"]],["impl<R, S, ST> Unpin for Component<R, S, ST>
    where\n ST: Unpin,\n R: Unpin,\n S: Unpin,
    ",1,["fishnet::component::Component"]],["impl<ST> Unpin for ComponentState<ST>
    where\n ST: Unpin,
    ",1,["fishnet::component::ComponentState"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js b/docs/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js index 924f51a..4a7ea51 100644 --- a/docs/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js +++ b/docs/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"fishnet":[["impl !RefUnwindSafe for BuiltComponent",1,["fishnet::component::build::BuiltComponent"]],["impl !RefUnwindSafe for ComponentBuildResult",1,["fishnet::component::build::ComponentBuildResult"]],["impl !RefUnwindSafe for Page",1,["fishnet::page::Page"]],["impl !RefUnwindSafe for Website",1,["fishnet::website::Website"]],["impl RefUnwindSafe for ScriptType",1,["fishnet::js::ScriptType"]],["impl RefUnwindSafe for RenderedStyle",1,["fishnet::css::RenderedStyle"]],["impl RefUnwindSafe for Stylesheet",1,["fishnet::css::Stylesheet"]],["impl RefUnwindSafe for ScriptString",1,["fishnet::js::ScriptString"]],["impl<'a> RefUnwindSafe for StyleFragment<'a>",1,["fishnet::css::StyleFragment"]],["impl<R, S, ST> !RefUnwindSafe for Component<R, S, ST>",1,["fishnet::component::Component"]],["impl<ST> RefUnwindSafe for ComponentState<ST>
    where\n ST: RefUnwindSafe,
    ",1,["fishnet::component::ComponentState"]]] +"fishnet":[["impl !RefUnwindSafe for BuiltComponent",1,["fishnet::component::build::BuiltComponent"]],["impl !RefUnwindSafe for ComponentBuildResult",1,["fishnet::component::build::ComponentBuildResult"]],["impl !RefUnwindSafe for GlobalStore",1,["fishnet::page::render_context::GlobalStore"]],["impl !RefUnwindSafe for RenderResult",1,["fishnet::page::render_context::RenderResult"]],["impl !RefUnwindSafe for BuiltPage",1,["fishnet::page::BuiltPage"]],["impl !RefUnwindSafe for Page",1,["fishnet::page::Page"]],["impl !RefUnwindSafe for Website",1,["fishnet::website::Website"]],["impl RefUnwindSafe for ScriptType",1,["fishnet::js::ScriptType"]],["impl RefUnwindSafe for RenderedStyle",1,["fishnet::css::RenderedStyle"]],["impl RefUnwindSafe for Stylesheet",1,["fishnet::css::Stylesheet"]],["impl RefUnwindSafe for ScriptString",1,["fishnet::js::ScriptString"]],["impl RefUnwindSafe for GlobalStoreEntry",1,["fishnet::page::render_context::GlobalStoreEntry"]],["impl<'a> RefUnwindSafe for StyleFragment<'a>",1,["fishnet::css::StyleFragment"]],["impl<R, S, ST> !RefUnwindSafe for Component<R, S, ST>",1,["fishnet::component::Component"]],["impl<ST> RefUnwindSafe for ComponentState<ST>
    where\n ST: RefUnwindSafe,
    ",1,["fishnet::component::ComponentState"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js b/docs/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js index 212ee35..76a8f41 100644 --- a/docs/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js +++ b/docs/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"fishnet":[["impl !UnwindSafe for BuiltComponent",1,["fishnet::component::build::BuiltComponent"]],["impl !UnwindSafe for ComponentBuildResult",1,["fishnet::component::build::ComponentBuildResult"]],["impl !UnwindSafe for Page",1,["fishnet::page::Page"]],["impl !UnwindSafe for Website",1,["fishnet::website::Website"]],["impl UnwindSafe for ScriptType",1,["fishnet::js::ScriptType"]],["impl UnwindSafe for RenderedStyle",1,["fishnet::css::RenderedStyle"]],["impl UnwindSafe for Stylesheet",1,["fishnet::css::Stylesheet"]],["impl UnwindSafe for ScriptString",1,["fishnet::js::ScriptString"]],["impl<'a> UnwindSafe for StyleFragment<'a>",1,["fishnet::css::StyleFragment"]],["impl<R, S, ST> !UnwindSafe for Component<R, S, ST>",1,["fishnet::component::Component"]],["impl<ST> UnwindSafe for ComponentState<ST>
    where\n ST: UnwindSafe,
    ",1,["fishnet::component::ComponentState"]]] +"fishnet":[["impl !UnwindSafe for BuiltComponent",1,["fishnet::component::build::BuiltComponent"]],["impl !UnwindSafe for ComponentBuildResult",1,["fishnet::component::build::ComponentBuildResult"]],["impl !UnwindSafe for GlobalStore",1,["fishnet::page::render_context::GlobalStore"]],["impl !UnwindSafe for RenderResult",1,["fishnet::page::render_context::RenderResult"]],["impl !UnwindSafe for BuiltPage",1,["fishnet::page::BuiltPage"]],["impl !UnwindSafe for Page",1,["fishnet::page::Page"]],["impl !UnwindSafe for Website",1,["fishnet::website::Website"]],["impl UnwindSafe for ScriptType",1,["fishnet::js::ScriptType"]],["impl UnwindSafe for RenderedStyle",1,["fishnet::css::RenderedStyle"]],["impl UnwindSafe for Stylesheet",1,["fishnet::css::Stylesheet"]],["impl UnwindSafe for ScriptString",1,["fishnet::js::ScriptString"]],["impl UnwindSafe for GlobalStoreEntry",1,["fishnet::page::render_context::GlobalStoreEntry"]],["impl<'a> UnwindSafe for StyleFragment<'a>",1,["fishnet::css::StyleFragment"]],["impl<R, S, ST> !UnwindSafe for Component<R, S, ST>",1,["fishnet::component::Component"]],["impl<ST> UnwindSafe for ComponentState<ST>
    where\n ST: UnwindSafe,
    ",1,["fishnet::component::ComponentState"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/fishnet/page/trait.RouterPageExt.js b/docs/trait.impl/fishnet/page/trait.RouterPageExt.js new file mode 100644 index 0000000..6ef4cab --- /dev/null +++ b/docs/trait.impl/fishnet/page/trait.RouterPageExt.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"fishnet":[] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/fishnet-macros/src/lib.rs b/fishnet-macros/src/lib.rs index e318929..75b4c72 100644 --- a/fishnet-macros/src/lib.rs +++ b/fishnet-macros/src/lib.rs @@ -87,8 +87,6 @@ pub fn dyn_component( let component = component::parse_dyn(item); let out = quote!( - extern crate fishnet; - #component ); diff --git a/fishnet/benches/rendering.rs b/fishnet/benches/rendering.rs index a491b0a..c18c436 100644 --- a/fishnet/benches/rendering.rs +++ b/fishnet/benches/rendering.rs @@ -1,79 +1,226 @@ use fishnet::component::prelude::*; +use fishnet::page::render_context; use fishnet::page::{BuiltPage, Page}; -use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion}; macro_rules! make_page { - ($component: expr, $amt: literal) => {{ - let runtime = tokio::runtime::Builder::new_current_thread() - .build() - .unwrap(); - - let page = Page::new("bench").with_body(|| { - async { - for _ in 0..$amt { - let _ = fishnet::render_component(&nanoid::nanoid!(10), || $component); - } + ($runtime: ident, $body: tt) => {{ + let page = Page::new("bench").with_body(move || async move { $body }.boxed()); - html! {} - } - .boxed() - }); + let (built, _) = $runtime.block_on(async { + let built = BuiltPage::new(page, "/").await; - let (built, _) = runtime.block_on(async { BuiltPage::new(page, "/").await }); + built + }); built }}; } +macro_rules! make_page_side_by_side { + ($component: expr, $amt: ident, $runtime: ident) => {{ + make_page!($runtime, { + let mut render = String::new(); + + for _ in 0..$amt { + render.push_str( + &render_context::render_component(&nanoid::nanoid!(10), || $component) + .await + .0, + ); + } + + maud::PreEscaped(render) + }) + }}; +} +macro_rules! make_page_nested { + ($component: expr, $runtime: ident) => {{ + make_page!($runtime, { + let nested = $component(|| { + async move { + c!($component(|| async move { + c!($component(|| { + async move { + c!($component(|| async { + html! { + "Hello world!" + } + } + .boxed())) + } + .boxed() + })) + } + .boxed())) + } + .boxed() + }); + + render_context::render_component(&nanoid::nanoid!(10), || nested).await + }) + }}; +} fn bench_render(cr: &mut Criterion) { #[component] fn basic_component() { + let a = black_box(0); + html! { - "Hello world!" + "Hello world!" (a) } } - let page = make_page!(basic_component(), 1000); + #[component] + fn styled_component() { + style!(css! { + color: red; + }); - cr.bench_with_input( - BenchmarkId::new("render_basic", 1000), - &Extension(page), - |b, page| { - let runtime = tokio::runtime::Builder::new_current_thread() - .build() - .unwrap(); + let a = black_box(0); - b.to_async(runtime) - .iter(|| async { BuiltPage::render(page.clone()).await }) - }, - ); + html! { + "Hello world!" (a) + } + } #[component] - fn styled_component() { + fn stateful_component() { + let state = state!(usize); + + html! { + "Hello world!" (*state) + } + } + + #[dyn_component] + fn dyn_component() { + let a = black_box(0); + + html! { + "Hello world!" (a) + } + } + + let runtime = tokio::runtime::Builder::new_current_thread() + .enable_time() + .build() + .unwrap(); + + let mut group = cr.benchmark_group("render side-by-side"); + + for i in [1, 100, 250] { + let page_basic = make_page_side_by_side!(basic_component(), i, runtime); + group.bench_with_input( + BenchmarkId::new("basic", i), + &Extension(page_basic), + |b, page| { + b.to_async(&runtime) + .iter(|| BuiltPage::render(page.clone())); + }, + ); + + let page_styled = make_page_side_by_side!(styled_component(), i, runtime); + group.bench_with_input( + BenchmarkId::new("styled", i), + &Extension(page_styled), + |b, page| { + b.to_async(&runtime) + .iter(|| BuiltPage::render(page.clone())); + }, + ); + + let page_stateful = make_page_side_by_side!(stateful_component(), i, runtime); + group.bench_with_input( + BenchmarkId::new("stateful", i), + &Extension(page_stateful), + |b, page| { + b.to_async(&runtime) + .iter(|| BuiltPage::render(page.clone())); + }, + ); + + let page_dyn = make_page_side_by_side!(dyn_component(), i, runtime); + group.bench_with_input( + BenchmarkId::new("dynamic", i), + &Extension(page_dyn), + |b, page| { + b.to_async(&runtime) + .iter(|| BuiltPage::render(page.clone())); + }, + ); + } + group.finish(); + + #[component] + fn basic_nested_component( + inner: impl Fn() -> BoxFuture<'static, Markup> + Send + Sync + 'static, + ) { + let inner = state_init!(Arc::new(inner)); + + html! { + (inner().await) + } + } + + #[component] + fn styled_nested_component( + inner: impl Fn() -> BoxFuture<'static, Markup> + Send + Sync + 'static, + ) { + let inner = state_init!(Arc::new(inner)); + style!(css! { color: red; }); html! { - "Hello world!" + (inner().await) + } + } + + #[dyn_component] + fn dyn_nested_component( + inner: impl Fn() -> BoxFuture<'static, Markup> + Send + Sync + 'static, + ) { + let inner = state_init!(Arc::new(inner)); + + html! { + (inner().await) } } + let mut group = cr.benchmark_group("render nested"); - let page = make_page!(basic_component(), 1000); + let page_basic = make_page_nested!(basic_nested_component, runtime); + group.bench_with_input( + BenchmarkId::new("basic", 3), + &Extension(page_basic), + |b, page| { + b.to_async(&runtime) + .iter(|| BuiltPage::render(page.clone())); + }, + ); - cr.bench_with_input( - BenchmarkId::new("render_styled", 1000), - &Extension(page), + let page_styled = make_page_nested!(styled_nested_component, runtime); + group.bench_with_input( + BenchmarkId::new("styled", 3), + &Extension(page_styled), |b, page| { - let runtime = tokio::runtime::Builder::new_current_thread() - .build() - .unwrap(); + b.to_async(&runtime) + .iter(|| BuiltPage::render(page.clone())); + }, + ); - b.to_async(runtime) - .iter(|| async { BuiltPage::render(page.clone()).await }) + let page_dyn = make_page_nested!(dyn_nested_component, runtime); + group.bench_with_input( + BenchmarkId::new("dynamic", 3), + &Extension(page_dyn), + |b, page| { + b.to_async(&runtime) + .iter(|| BuiltPage::render(page.clone())); }, ); + group.finish(); } criterion_group!(benches, bench_render); diff --git a/fishnet/src/component.rs b/fishnet/src/component.rs index b94d5f7..b5094dc 100644 --- a/fishnet/src/component.rs +++ b/fishnet/src/component.rs @@ -8,6 +8,7 @@ pub use build::{BuildableComponent, BuiltComponent, ComponentBuildResult}; mod render; use render::ContentRenderer; +#[doc(hidden)] pub mod fake_macros; use crate::css::StyleFragment; diff --git a/fishnet/src/component/prelude.rs b/fishnet/src/component/prelude.rs index 23bf055..dafe66e 100644 --- a/fishnet/src/component/prelude.rs +++ b/fishnet/src/component/prelude.rs @@ -3,15 +3,15 @@ pub use crate::c; // components itself +pub use super::fake_macros::state; +pub use super::fake_macros::state_init; pub use super::{BuildableComponent, ComponentState}; - -pub use super::fake_macros::*; pub use crate::{component, dyn_component}; // html, js, css pub use crate::js::ScriptType; -pub use crate::{css, script, style}; -pub use maud::{html, Markup, Render}; +pub use crate::{css, html, script, style, Markup}; +pub use maud::Render; // boxing runner futures pub use futures::future::{BoxFuture, FutureExt}; diff --git a/fishnet/src/css.rs b/fishnet/src/css.rs index 744bab3..5ec6c55 100644 --- a/fishnet/src/css.rs +++ b/fishnet/src/css.rs @@ -67,6 +67,7 @@ pub struct RenderedStyle { /// /// a stylesheet is basically just a collection of [`RenderedStyle`]s. however it caches all its /// renders, so you can only add to it and never remove things. +#[derive(Debug)] pub struct Stylesheet { style: String, rendered_media_queries: String, diff --git a/fishnet/src/lib.rs b/fishnet/src/lib.rs index d8a06d4..c1d09d0 100644 --- a/fishnet/src/lib.rs +++ b/fishnet/src/lib.rs @@ -225,8 +225,8 @@ //! `> div` is perfectly valid. it selects all the `div`s that are direct children of the //! component. this also means that a selector like `*` will only affect the components children. //! -//! if you want to style a specific child component, its class name will always be derived from the -//! type you put into the [`component!`](macro@component) macro (e.g. "SomeChild" becomes +//! if you want to style a specific child component, its css class name will always be derived from the +//! components function name when using the [`component`](macro@component) macro (e.g. "some_child" becomes //! "some-child"). this also means that conflicts can occur if you use the same name multiple //! times, choose your names wisely... //! @@ -245,8 +245,6 @@ pub mod component; mod routes; pub mod page; -#[doc(hidden)] -pub use page::render_context::{global_store, render_component, GlobalStoreEntry}; pub use page::Page; mod website; diff --git a/fishnet/src/page/render_context.rs b/fishnet/src/page/render_context.rs index fa0f132..dc3789b 100644 --- a/fishnet/src/page/render_context.rs +++ b/fishnet/src/page/render_context.rs @@ -1,3 +1,18 @@ +//! managing resources during a render +//! +//! the render context is used under the hood whenever you use macros that add things to the +//! page (e.g. [`c!`](crate::c!), [`style!`](crate::style!), [`script!`](crate::script!), ...). +//! +//! before a page renders its contents, it attaches itself to the render context via [`enter_page`]. during the +//! render when a resource is about to be added, it is first checked whether it already exists on +//! the render context. if yes, it is not added again and just reused. otherwise it is newly +//! constructed. after the render is finished, the page can use [`exit_page`] to get a list of all +//! the newly constructed things during the render and then process them further (e.g. add routes +//! from new components, minify added scripts, ...) +//! +//! you usually don't need to call anything from in here manually unless you want to have finer +//! control over resources (like dynamically adding resources to the page) + use axum::routing::Router; use futures::future::BoxFuture; use maud::{html, Markup}; @@ -10,20 +25,22 @@ use tracing::{error, instrument, trace, warn}; use crate::component::{BuildableComponent, BuiltComponent}; use crate::page::BuiltPage; use crate::routes::ComponentRoute; +use crate::{css, js}; fn render_context() -> &'static Mutex> { static RENDER_CONTEXT: OnceLock>> = OnceLock::new(); RENDER_CONTEXT.get_or_init(|| Mutex::new(None)) } -#[doc(hidden)] +/// acquire access to the [`GlobalStore`]. pub fn global_store() -> &'static GlobalStore { static GLOBAL_STORE: OnceLock = OnceLock::new(); GLOBAL_STORE.get_or_init(|| GlobalStore::new()) } #[derive(Debug)] -pub(crate) struct ComponentStore(HashMap); +#[doc(hidden)] +pub struct ComponentStore(pub HashMap); impl ComponentStore { pub(crate) fn new() -> Self { @@ -31,20 +48,28 @@ impl ComponentStore { } } +/// a single global (page independent) resource #[derive(Debug)] -#[doc(hidden)] pub struct GlobalStoreEntry { - pub scripts: Vec, - pub style: Option, + pub scripts: Vec, + pub style: Option, } +/// collection of resources that are page independent #[derive(Debug)] pub struct GlobalStore(Mutex>>); impl GlobalStore { - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self(Mutex::new(HashMap::new())) } + /// add a [`GlobalStoreEntry`] to the store + /// + /// does nothing if there already is a entry under the given id. + /// otherwise the `globals` closure is executed to create a new entry + /// + /// this will also notify the currently active render context about the newly added resource + /// (which usually means that it gets added to the rendered page) pub async fn add(&self, id: &str, globals: F) where F: FnOnce() -> GlobalStoreEntry, @@ -62,12 +87,13 @@ impl GlobalStore { } } + /// get a [`GlobalStoreEntry`] from its id. pub async fn get<'a>(&'a self, id: &str) -> Option> { self.0.lock().await.get(id).cloned() } } -struct RenderContext { +pub(crate) struct RenderContext { base_route: String, components: Arc>, @@ -113,7 +139,7 @@ impl RenderContext { /// Contains all the scripts, runners and routers that were collected during the rendering. /// * `scripts` - A list of scripts that should be included in the page. /// * `runners` - A list of runners that should be executed. -/// * `routers` - A list of routers that should be accessible from the page. This is usually achieved using a [APIRouter](`crate::routes::APIRouter`). +/// * `routers` - A list of routers that should be accessible from the page at the given routes pub struct RenderResult { pub runners: Vec>, pub routers: Vec<(ComponentRoute, Router)>, @@ -125,9 +151,7 @@ pub struct RenderResult { /// This should be called before rendering any components. /// After the rendering is complete, `exit_page` should be called to acquire the results. /// Calling `enter_page` while another page is being rendered results in the loss of the previous page's render results! -/// -/// You usually don't need to call this function yourself. -pub(crate) async fn enter_page(page: &mut BuiltPage) { +pub async fn enter_page(page: &mut BuiltPage) { let mut context = render_context().lock().await; if context.is_some() { @@ -140,10 +164,9 @@ pub(crate) async fn enter_page(page: &mut BuiltPage) { /// Exit a page render context. /// /// This should be called after rendering all components. It will return the `RenderResult` containing all the scripts and runners that were collected during the rendering. -/// /// # Panics /// Panics if no page is currently being rendered. (i.e. `enter_page` was not called before) -pub(crate) async fn exit_page() -> RenderResult { +pub async fn exit_page() -> RenderResult { let mut context = render_context().lock().await; context @@ -250,10 +273,11 @@ where /// Furthermore, it will be recorded, whether any dynamic components were rendered during the temporary render. /// This can be used to "test-render" a static component to see if it contains any dynamic children. /// -/// Temporary render contexts can be exited using `exit_temporary_render`, and can be nested. +/// Temporary render contexts can be exited using [`exit_temporary_render`], and can be multiple +/// levels deep. it is up to you to ensure that you always exit every render you enter. /// /// You usually don't need to call this function yourself. -pub(crate) async fn enter_temporary_render() { +pub async fn enter_temporary_render() { let mut context = render_context().lock().await; if let Some(context) = context.as_mut() { trace!("entering temporary render"); @@ -266,11 +290,11 @@ pub(crate) async fn enter_temporary_render() { /// Exit a temporary render context. /// -/// Returns true if the temporary render was static (i.e. no dynamic components were rendered). +/// Returns true if the temporary render started via [`enter_temporary_render`] was static (i.e. no dynamic components were rendered). /// If not within a (temporary) render context, this function will always return true. /// /// You usually don't need to call this function yourself. -pub(crate) async fn exit_temporary_render() -> bool { +pub async fn exit_temporary_render() -> bool { let mut context = render_context().lock().await; if let Some(context) = context.as_mut() { if context.temporary_render_depth == 0 { @@ -289,12 +313,32 @@ pub(crate) async fn exit_temporary_render() -> bool { } } -/// add [`css`](crate::css!) to the page from outside a component. +/// add [`css`](crate::css!) to the page /// -/// this is helpful for adding styling to functions that just return [`Markup`](crate::Markup). -/// you have to call this from within a page render or the css will not be added to the page. +/// you have to call this from within a page render or it will not work. /// -/// ### usage +/// there are two ways to use this macro: +/// ## from within a component +/// ```rust +/// use fishnet::component::prelude::*; +/// +/// #[component] +/// async fn my_component() { +/// style!(css!{ +/// color: red; +/// }); +/// +/// html! { +/// "hello world!" +/// } +/// } +///``` +/// +/// ## from outside a component +/// additionally to providing the style, you also have to name the top level class yourself as the +/// first argument. +/// +/// this is helpful for adding styling to functions that just return [`Markup`](crate::Markup). /// ```rust /// use fishnet::{style, html, Markup, css}; /// @@ -309,22 +353,30 @@ pub(crate) async fn exit_temporary_render() -> bool { /// } /// } /// } +/// ``` #[macro_export] macro_rules! style { + ($css: expr) => {{ + compile_error!( + "you have to provide a class name to the style macro or use it from within a component" + ); + }}; ($tl_class: literal, $css:expr) => {{ - $crate::global_store() - .add($crate::const_nanoid!(10), || $crate::GlobalStoreEntry { - scripts: Vec::new(), - style: Some($css.render($tl_class)), + $crate::page::render_context::global_store() + .add($crate::const_nanoid!(10), || { + $crate::page::render_context::GlobalStoreEntry { + scripts: Vec::new(), + style: Some($css.render($tl_class)), + } }) .await; }}; } -/// add js to the page from outside a component. +/// add js to the page /// -/// this is helpful for adding styling to functions that just return [`Markup`](crate::Markup). -/// you have to call this from within a page render or the js will not be added to the page. +/// differently to the [`css!`] macro, this will work identically whether you are within a +/// component or not. you still have to be within a page render though or it will do nothing. /// /// ### usage /// ```rust @@ -343,10 +395,12 @@ macro_rules! style { #[macro_export] macro_rules! script { ($js:literal) => {{ - $crate::global_store() - .add($crate::const_nanoid!(10), || $crate::GlobalStoreEntry { - scripts: vec![$crate::js::ScriptType::Inline($js)], - style: None, + $crate::page::render_context::global_store() + .add($crate::const_nanoid!(10), || { + $crate::page::render_context::GlobalStoreEntry { + scripts: vec![$crate::js::ScriptType::Inline($js)], + style: None, + } }) .await; }}; @@ -383,6 +437,6 @@ macro_rules! c { ($component:expr) => {{ let component = || $component; - $crate::render_component($crate::const_nanoid!(10), component).await + $crate::page::render_context::render_component($crate::const_nanoid!(10), component).await }}; } diff --git a/fishnet/tests/test_component.rs b/fishnet/tests/test_component.rs index 44783ee..16559a8 100644 --- a/fishnet/tests/test_component.rs +++ b/fishnet/tests/test_component.rs @@ -1,6 +1,6 @@ extern crate fishnet_macros; use fishnet::component::prelude::*; -use fishnet::global_store; +use fishnet::page::render_context::global_store; use fishnet_macros::{component, css}; use std::sync::Arc;