1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//! `markup(h)` — the one conversion a rich call site's handler goes through.
//!
//! The macro emits `markup(h)` whatever `h` is, and that expansion is fixed:
//! the core takes anything that already implements [`MarkupHandler`], and
//! the Leptos layer adds the view closure. Which forms the expansion accepts
//! is the Leptos mode's business, not the macro's.
//!
//! | Mode | `markup` takes |
//! |---|---|
//! | none | [`Handler(h)`](Handler) over a [`MarkupHandler`] the caller wrote, or an `Arc<dyn MarkupHandler>` already built |
//! | `ssr`, `hydrate`, `csr` | those, and a **nesting** closure `Fn(AnyView) -> impl IntoAny` or a `Flat` closure `Fn(&MarkupPart) -> impl IntoAny` (`mf2::leptos`) |
//!
//! The Leptos forms erase to one of two concrete handler types, so that the
//! renderer downcasts to a type it knows rather than to the call site's
//! closure. That erasure is why a rich call site costs a thunk rather than a
//! monomorphised renderer.
use Arc;
use crateMarkupHandler;
/// `markup(h)` — the one signature, in every build. What `h` may be is what
/// [`IntoMarkupHandler`] is implemented for, and *that* is the mode's
/// business.
/// `markup_view(h)` — what the macro emits when the handler is written as a
/// closure. In a Leptos mode its bound is the nesting closure's own
/// signature, so `|c| view! { <kbd>{c}</kbd> }` needs no `c: AnyView`: a
/// closure passed where a trait other than `Fn` is expected is never given
/// its argument's type. Elsewhere it is [`markup`].
/// `markup_view(h)` without a Leptos mode: [`markup`].
/// What [`markup`] accepts.
///
/// | Form | Available | What it is |
/// |---|---|---|
/// | [`Handler(h)`](Handler) | always | a [`MarkupHandler`] the caller wrote |
/// | `Arc<dyn MarkupHandler>` | always | one already erased — `markup(markup(h))` is the identity |
/// | `\|children\| view! { … }` | a Leptos mode | a **nesting** handler, called once per `{#name}…{/name}` pair |
/// | `Flat(f)` over `&MarkupPart` | a Leptos mode | a **flat** handler, called once per markup part with no pairing |
///
/// The impls do not overlap, so a rich call site writes the closure and
/// nothing else. A caller's own handler type goes through `Handler` in
/// **every** build rather than bare in some: the same source has to compile
/// whether or not something else in the workspace turned a Leptos mode on.
/// A [`MarkupHandler`] the caller wrote, on its way through [`markup`].
;
/// `Handler(..)`: the handler is the caller's own type, with nothing to
/// show.
/// A handler already erased — `markup(markup(h))` is the identity, which is
/// what lets a call site pass one it built itself.