# Leptos Macabre Scary simple server-side rendering. Powered by [Leptos](https://github.com/leptos-rs/leptos). ```rust 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). ```rust 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. ```rust, ignore use leptos::*; use leptos_macabre::*; view! { } 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). ```rust, ignore 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. ```rust, ignore use leptos_macabre::*; fn my_button() -> impl leptos::IntoView { } fn my_a(href: &'static str) -> impl leptos::IntoView {} fn my_b(inner: Option) -> 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.