Skip to main content

forma_server/
raw.rs

1//! The named raw HTML boundary. A RawHtml is reviewed application markup,
2//! not sanitized data. Each constructor belongs on the application's SR8
3//! allowlist with an owner. PageConfig::body_prefix accepts this type directly.
4use std::{fmt, ops::Deref};
5
6/// Markup explicitly vouched for by the application. The private field and sole
7/// named constructor keep raw entry points searchable; strings cannot become a
8/// RawHtml through From, Into, Default or deserialization.
9///
10/// ```
11/// use forma_server::RawHtml;
12/// let logo = RawHtml::trusted("<nav>Example</nav>");
13/// assert_eq!(logo.as_str(), "<nav>Example</nav>");
14/// ```
15///
16/// Verified by: crates/forma-server/tests/internal_renderer/raw_html.rs > "a_search_finds_one_raw_constructor"
17pub struct RawHtml {
18    html: Box<str>,
19}
20
21impl RawHtml {
22    /// Vouch for `html`: forma-server writes it into the page as it is.
23    ///
24    /// Whatever reaches the markup is trusted. Escape any value from a
25    /// request, a database or a tenant before it goes in, or render it
26    /// through a component instead, where the walker escapes it for you.
27    /// Each call belongs on the application's raw-entry allowlist
28    /// (`forma-raw-lint`) with an owner.
29    pub fn trusted(html: impl Into<String>) -> RawHtml {
30        let html = html.into().into_boxed_str();
31        RawHtml { html }
32    }
33
34    /// The markup.
35    pub fn as_str(&self) -> &str {
36        &self.html
37    }
38}
39
40impl Deref for RawHtml {
41    type Target = str;
42
43    fn deref(&self) -> &str {
44        &self.html
45    }
46}
47
48impl Clone for RawHtml {
49    fn clone(&self) -> Self {
50        RawHtml::trusted(&*self.html)
51    }
52}
53
54impl PartialEq for RawHtml {
55    fn eq(&self, other: &Self) -> bool {
56        self.html == other.html
57    }
58}
59
60impl Eq for RawHtml {}
61
62impl fmt::Debug for RawHtml {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        f.debug_tuple("RawHtml").field(&&*self.html).finish()
65    }
66}