Skip to main content

resuma_macros/
lib.rs

1//! Resuma procedural macros.
2//!
3//! Re-exported by the [`resuma`](https://docs.rs/resuma) crate. Typical surface:
4//!
5//! | Macro | Role |
6//! |-------|------|
7//! | [`view!`] | JSX-like templates → [`View`](https://docs.rs/resuma/latest/resuma/enum.View.html) |
8//! | [`#[component]`](component) | Resumable component + props builder (lazy handler boundary) |
9//! | [`#[server]`](server) | Async RPC at `POST /_resuma/action/:name` |
10//! | [`computed!`](computed) | Client-replayable derived signal (rs2js) |
11//! | [`effect!`](effect) | Client-replayable side effect (rs2js) |
12//! | [`debounce!`](debounce) | Debounced client reaction |
13//! | [`#[island]`](island) | Optional heavy lazy boundary (`load = "visible"`) |
14//! | [`js!`](js) | Raw JavaScript handler escape hatch |
15
16mod component_macro;
17mod computed_macro;
18mod debounce_macro;
19mod effect_macro;
20mod island_macro;
21mod js_macro;
22mod layout_macro;
23mod load_macro;
24mod middleware_macro;
25mod rs2js;
26mod server_macro;
27mod submit_macro;
28mod view_macro;
29
30use proc_macro::TokenStream;
31
32/// `view!` — JSX-like template macro.
33#[proc_macro]
34pub fn view(input: TokenStream) -> TokenStream {
35    view_macro::expand(input.into()).into()
36}
37
38/// `#[component]` — resumable component with generated props builder.
39///
40/// Wraps output in a lazy handler boundary; event handlers register under
41/// `/_resuma/handler/{ComponentName}.js`. For heavy optional lazy bundles, see [`island`].
42#[proc_macro_attribute]
43pub fn component(args: TokenStream, input: TokenStream) -> TokenStream {
44    component_macro::expand(args.into(), input.into()).into()
45}
46
47/// `#[server]` — exposes an async fn as a server action.
48#[proc_macro_attribute]
49pub fn server(args: TokenStream, input: TokenStream) -> TokenStream {
50    server_macro::expand(args.into(), input.into()).into()
51}
52
53/// `#[island]` — optional interactive boundary for heavy or visibility-gated JS.
54///
55/// Most UI only needs [`component`]. Use islands for large client bundles,
56/// `#[island(load = "visible")]`, or dev HMR refresh via `GET /_resuma/island/:instance`.
57#[proc_macro_attribute]
58pub fn island(args: TokenStream, input: TokenStream) -> TokenStream {
59    island_macro::expand(args.into(), input.into()).into()
60}
61
62/// `#[load]` — Resuma Flow server data loader.
63#[proc_macro_attribute]
64pub fn load(args: TokenStream, input: TokenStream) -> TokenStream {
65    load_macro::expand(args.into(), input.into()).into()
66}
67
68/// `#[submit]` — Resuma Flow form submission handler.
69#[proc_macro_attribute]
70pub fn submit(args: TokenStream, input: TokenStream) -> TokenStream {
71    submit_macro::expand(args.into(), input.into()).into()
72}
73
74/// `#[layout]` — Resuma Flow layout wrapper.
75#[proc_macro_attribute]
76pub fn layout(args: TokenStream, input: TokenStream) -> TokenStream {
77    layout_macro::expand(args.into(), input.into()).into()
78}
79
80/// `#[middleware]` — Resuma Flow request middleware.
81#[proc_macro_attribute]
82pub fn middleware(args: TokenStream, input: TokenStream) -> TokenStream {
83    middleware_macro::expand(args.into(), input.into()).into()
84}
85
86/// `js!` — raw JavaScript escape hatch for event handlers.
87#[proc_macro]
88pub fn js(input: TokenStream) -> TokenStream {
89    js_macro::expand(input.into()).into()
90}
91
92/// `computed!([deps…], move || …)` — derived signal with client replay (rs2js-translated).
93///
94/// Runs during SSR and replays in the browser when dependencies change.
95/// For SSR-only derived state, use [`use_computed`](https://docs.rs/resuma/latest/resuma/fn.use_computed.html) instead.
96#[proc_macro]
97pub fn computed(input: TokenStream) -> TokenStream {
98    computed_macro::expand(input.into()).into()
99}
100
101/// `effect!([signals…], move || { … })` — client-replayable side effect (rs2js).
102#[proc_macro]
103pub fn effect(input: TokenStream) -> TokenStream {
104    effect_macro::expand(input.into()).into()
105}
106
107/// `debounce!([deps…], ms, move || …)` — debounced client reaction (rs2js-translated).
108///
109/// ```ignore
110/// debounce!([search], 300, move || { /* runs after search settles */ });
111/// ```
112#[proc_macro]
113pub fn debounce(input: TokenStream) -> TokenStream {
114    debounce_macro::expand(input.into()).into()
115}