1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! Type-safe HTML templating support.
//!
//! Enabled via the `html` feature. The core idea: every HTML5 element gets
//! its own proc-macro (`html!`, `body!`, `div!`, ...) that constructs a
//! type implementing both [`IntoHtml`] (for composition) and
//! [`IntoResponse`](crate::service::web::response::IntoResponse) (so the
//! result can be returned directly from a web handler). For runtime tag
//! names — typically [web components] — see the [`custom!`] macro.
//!
//! ```ignore
//! use rama_http::protocols::html::*;
//! use rama_http::service::web::response::IntoResponse;
//!
//! async fn handler() -> impl IntoResponse {
//! html!(
//! head!(title!("Hi")),
//! body!(
//! h1!("Hello, ", "world!"),
//! custom!("my-icon", name = "smile"),
//! ),
//! )
//! }
//! ```
//!
//! `<html>` is always the document root, so [`html!`] automatically
//! prepends `<!DOCTYPE html>` to its output — i.e. `html!(...)` returns
//! a complete page that can be returned from a handler as-is. If you
//! really need a bare `<html>` element without the doctype, use
//! `custom!("html", ...)`.
//!
//! ## What gets escaped, what does not
//!
//! Anything spliced in via an expression (`{name}`, `self.value`, etc.)
//! goes through HTML escaping by virtue of [`IntoHtml`]. The static parts
//! emitted by the macros themselves are wrapped in [`PreEscaped`] and
//! written verbatim. If you have *trusted* HTML you want to splice in
//! raw — e.g. an SVG icon or a pre-rendered fragment — wrap it in
//! `PreEscaped(...)` yourself.
//!
//! ## Custom (user-defined) types
//!
//! Implementing [`IntoHtml`] on your own type lets it participate in
//! templates just like the built-in scalars. For composite types, simply
//! return another [`IntoHtml`] from `into_html`; for "leaf" types, return
//! `self` and override `escape_and_write`.
//!
//! This is the main path for adding type-safe support for custom HTML
//! shapes — e.g. components with strongly-typed required attributes —
//! built on top of the macro layer:
//!
//! ```ignore
//! use rama_http::protocols::html::*;
//!
//! struct UserIcon { user_id: u64, size: IconSize }
//! enum IconSize { Sm, Md, Lg }
//!
//! impl IntoHtml for UserIcon {
//! fn into_html(self) -> impl IntoHtml {
//! let size = match self.size { IconSize::Sm => "sm", IconSize::Md => "md", IconSize::Lg => "lg" };
//! custom!("user-icon", "data-user-id" = self.user_id, size = size)
//! }
//! }
//! ```
//!
//! [web components]: https://developer.mozilla.org/en-US/docs/Web/API/Web_components
//! [`custom!`]: rama_http_macros::custom
pub use ;
pub use join_display;
pub use HtmlBuf;
pub use escape_attr_value_into;
// Re-exported so the proc-macros emitted by `rama-http-macros` can refer
// to them via a single root path (`rama_http::protocols::html::Either{,3..9}`),
// without depending on the user knowing where `rama-core` lives.
//
// In practice the user normally only encounters these via `if`/`else if`
// chains inside element macros — the Either chain is generated for them.
pub use ;
pub use custom;
// One re-exported proc-macro per known HTML5 element.
//
// Kept in alphabetical order to match the canonical list at MDN
// (<https://developer.mozilla.org/en-US/docs/Web/HTML/Element>).
pub use ;