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};