1 unstable release
0.1.0 | Jan 16, 2024 |
---|
#22 in #err
34KB
199 lines
Leptos Macabre
Scary simple server-side rendering. Powered by Leptos.
use leptos_macabre::*;
let result: Result<_, &str> = Ok("Done!");
let style = "color: green;";
section! {
h1!{ "Uploads" },
match result {
Ok(msg) => div! {
@htmx-get="/uploads";
@style;
p!{ "Status: ", msg },
},
Err(err) => strong! {
@class="error";
"Uh Oh: " err
},
}
};
Syntax
- Attributes starts with
@
and end with;
. - Attributes Values are expressions returning
impl leptos::IntoAttribute
. - Attributes Values can be shorthanded when the name equals a variable in scope.
Raw identifiers (i.e.
r#type
) are not supported. - Children are expressions returning
impl leptos::IntoView
. - Children can be delimited with an optional comma (helps rustfmt and auto-indenting, sometimes).
Details & Conveniences
Compile Time & Lsp
Due to everything being a minimally recursive macro_rules!
, auto-complete and suggestions
are incredibly snappy.
Auto .into_view()
Every macro in this crate returns a View
, this intentionally diverts from
leptos to not require .into_view()
on each arm (an understandable requirement).
use leptos_macabre::*;
let result = Some(true);
let href = "#section";
match result {
Some(true) => a!(@href; "Go here!"),
Some(false) => p!(@class="bad"; "Uh-oh!"),
None => div!(),
};
Every Element a Macro.
Each element is a separate macro. This saves many keystrokes. It is different from most Rust HTML macros.
use leptos::*;
use leptos_macabre::*;
view! { <button>"27 keystrokes"</button> }
button! { "10 keystrokes" }
Re-Export
This crate exports the leptos_dom
items needed to work. If you just want
to make HTML on the server, you can skip adding leptos
as its own dependency.
Drawbacks
No reactivity that can't be implemented with a script!
or normal html event
handlers. No signals. Performance will probably be worse when compared directly
to leptos::view!
.
leptos
components with props are minimally supported. The generated Prop*
struct would need to be provided as an argument, meaning you skip
many of the conveniences of using #[component]
in the first place (optional
props etc).
use leptos_macabre::*;
use leptos::component;
#[component]
fn MyButton() -> impl leptos::IntoView {}
#[component]
fn MyA(href: &'static str) -> impl leptos::IntoView {}
p!{ MyButton };
p!{ MyButton() };
p!{ MyA(MyAProps { href: "#red" }) };
Since children are just expressions returning impl IntoView
, you can swap out
components with boring old functions.
use leptos_macabre::*;
fn my_button() -> impl leptos::IntoView { }
fn my_a(href: &'static str) -> impl leptos::IntoView {}
fn my_b(inner: Option<bool>) -> impl leptos::IntoView {}
div! {
my_button,
my_button(),
my_a("#red"),
my_b(Some(true)) ,
};
Name
I always thought the horrorshow
crate was neat, and leptos
is close to the
disease leptospirosis. It is all just a little grim. Secondly, this crate is
created with nested macro_rules!
, something truly horrendous.
Dependencies
~14–27MB
~413K SLoC