gen_html/
lib.rs

1//! `gen-html` is a templating library for generating HTML from Rust.
2//!
3//! # Features
4//!
5//! - **Fast** — [`html!`] macro generates code that is as fast as writing to a string by hand.
6//! - **Conditional rendering** — you can use `if`, `for` and `match` inside your templates.
7//! - **Automatic escaping**, however you can opt-out using [`Raw<T>`].
8//! - **Type safety** — HTML tags and attributes are checked at compile time.
9//! - Integration with the rust web ecosystem (`axum`, `actix-web`).
10//!
11//! # Example
12//!
13//! ```
14//! use gen_html::html;
15//!
16//! let markup = html! {
17//!     for i in 1..=3 {
18//!         span { (i.to_string()) }
19//!     }
20//! };
21//!
22//! println!("{}", markup);
23//! # assert_eq!(markup.to_string(), "<span>1</span><span>2</span><span>3</span>");
24//! ```
25//!
26//! The [`html!`] macro roughly expands to this code.
27//!
28//! ```
29//! use gen_html::{Render, render_fn};
30//!
31//! let markup = render_fn(|f| {
32//!     for i in 1..=3 {
33//!         f.write_str("<span>")?;
34//!         (&i.to_string()).render_to(f)?;
35//!         f.write_str("</span>")?;
36//!     }
37//!     Ok(())
38//! });
39//!
40//! /* ... */
41//! # assert_eq!(markup.render().0, "<span>1</span><span>2</span><span>3</span>");
42//! ```
43
44mod escape;
45mod render;
46mod web;
47
48/// The `<!DOCTYPE html>` string literal.
49///
50/// # Example
51///
52/// ```
53/// use gen_html::{DOCTYPE, html};
54///
55/// # let markup =
56/// html! {
57///     (DOCTYPE)
58///     h1 { "hello world" }
59/// }
60/// # ;
61/// # assert_eq!(markup.to_string(), "<!DOCTYPE html><h1>hello world</h1>");
62/// ```
63pub const DOCTYPE: Raw<&str> = Raw("<!DOCTYPE html>");
64
65/// Generate HTML with `maud`-like syntax.
66///
67/// # Syntax
68///
69/// Normal HTML elements are written with curly-braces.
70///
71/// ```
72/// # let markup = gen_html::
73/// html! {
74///     p { "Lorem ipsum dolor sit amet." }
75/// }
76/// # ;
77/// # assert_eq!(markup.to_string(), "<p>Lorem ipsum dolor sit amet.</p>");
78/// ```
79///
80/// Self-closing tags require a trailing semicolon.
81///
82/// ```
83/// # let markup = gen_html::
84/// html! {
85///     img src: "logo.svg" ;
86///     // gets automatically changed to `data-cooldown`
87///     button data_cooldown: "5s" onclick: "..." { "Click me" }
88/// }
89/// # ;
90/// # assert_eq!(
91/// #     markup.to_string(),
92/// #     "<img src=\"logo.svg\"><button data-cooldown=\"5s\" onclick=\"...\">Click me</button>"
93/// # );
94/// ```
95///
96/// Using Rust expressions inside templates.
97///
98/// ```
99/// # let name = "Bob";
100/// # _ = gen_html::
101/// html! {
102///     p { (format!("Hello {name}")) }
103///     img src: (format!("assets/{name}/profile-picture.png")) ;
104/// }
105/// # ;
106/// ```
107///
108/// Conditional rendering with `if`.
109///
110/// ```
111/// # let name = Some("Steve");
112/// # _ = gen_html::
113/// html! {
114///     if let Some(name) = name {
115///         (name)
116///     } else {
117///         "stranger"
118///     }
119/// }
120/// # ;
121/// ```
122///
123/// Pattern matching using `match`.
124///
125/// ```
126/// # let age = 23;
127/// # _ = gen_html::
128/// html! {
129///     match age {
130///         ..18 => "You're not old enough",
131///         18.. => p { "Hello world" }
132///     }
133/// }
134/// # ;
135/// ```
136///
137/// Repeating markup with `for`.
138///
139/// ```
140/// # let titles = ["Titanic"];
141/// # use gen_html::html;
142/// # _ =
143/// html! {
144///     h1 { "Available movies" }
145///     ul {
146///         for title in titles {
147///             li { (title) }
148///         }
149///     }
150/// }
151/// # ;
152/// ```
153pub use gen_html_proc::html;
154
155pub use escape::Escaped;
156pub use render::{Raw, Render, RenderFn, render_fn};