Horrorshow is a macro-based HTML templating library. For those of you who saw the last post, horrorshow has become quite a bit more useful.

Links

Project: GitHub, crates.io

Docs: https://stebalien.github.io/horrorshow-rs/horrorshow/

Features

Works on stable.

Built-in html escaping (that should be audited by someone who knows what they are doing…).

Can render into existing strings and io writers.

fast (compiles to assembly).

Composable.

Non features:

Really unhelpful errors. Unfortunately, there’s no way to tell rust: “don’t look in this ugly macro code for type errors, assume I meant every word of this macro code and the error is elsewhere.”

To be able to return a template, it needs to be boxed. This is because templates are actually closures. However, this is only true of returned templates; you don’t need to allocate when rendering locally.

Example

#[macro_use] extern crate horrorshow; use horrorshow::{RenderBox, Template}; fn render_post(post: Post) -> Box<RenderBox> { let Post { title, body, tags } = post; box_html! { article { header(class="post-header") { h1 : title; ul { |t| tags.iter().fold(t, |t, tag| t << html! { li : tag }); /* // You should be able to write the following but rust doesn't // re-borrow when using binary operators (gh#25753). |t| for tag in tags { t << html! { li : tag }; } */ } } section(class="post-body") : body; } } } fn render<I: Iterator<Item=Post>>(title: &str, posts: I) -> String { (html! { : raw!("<!DOCTYPE html>"); html { head { title : title } body { main { header { h1 : title } section(id="posts") { |t| posts.fold(t, |t, post| t << render_post(post)); } } } } }).into_string() } struct Post { title: String, tags: Vec<String>, body: String, } fn main() { let posts = vec![ Post { title: String::from("First Post"), tags: vec![String::from("first post")], body: String::from("My Test Post"), }, Post { title: String::from("Second Post"), tags: vec![], body: String::from("My Second Test Post"), }, ]; println!("{}", render("my blog", posts.into_iter())); }

Output:

<!DOCTYPE html> <html> <head> <title>my blog</title> </head> <body> <main> <header> <h1>my blog</h1> </header> <section id="posts"> <article> <header class="post-header"> <h1>First Post</h1> <ul> <li>first post</li> </ul> </header> <section class="post-body">My Test Post</section> </article> <article> <header class="post-header"> <h1>Second Post</h1> <ul></ul> </header> <section class="post-body">My Second Test Post</section> </article> </section> </main> </body> </html>

If you have any comments on the current error handling design, please post them here: Error Handling Design in Horrorshow