html_types/
text.rs

1use derive_more::Into;
2/// The HTML text node. This is used inside tags eg <p>Text</p>
3#[derive(Into, Clone, PartialEq, Eq, Debug)]
4pub struct Text(String);
5
6impl Text {
7    /// Creates a text node. Note: will escape html markup eg <,>,&
8    pub fn create<S>(text: S) -> Text
9    where
10        S: Into<String>,
11    {
12        // I suspect there might be a more complete ruleset here
13        let text = text.into();
14        let gt = ">";
15        let lt = "<";
16        let amp = "&";
17        let gt_escaped = "&gt;";
18        let lt_escaped = "&lt;";
19        let amp_escaped = "&amp;";
20        let text = text
21            .replace(amp, amp_escaped)
22            .replace(gt, gt_escaped)
23            .replace(lt, lt_escaped);
24        Text(text)
25    }
26}
27
28#[cfg(test)]
29mod tests {
30    use super::*;
31    #[test]
32    fn unescaped() {
33        let input = Text::create("Hello");
34        let expected = Text("Hello".to_string());
35        assert_eq!(input, expected);
36    }
37
38    #[test]
39    fn escaped_greater_than() {
40        let input = Text::create(">attempt");
41        let expected = Text("&gt;attempt".to_string());
42        assert_eq!(input, expected);
43    }
44
45    #[test]
46    fn escaped_less_than() {
47        let input = Text::create("<attempt");
48        let expected = Text("&lt;attempt".to_string());
49        assert_eq!(input, expected);
50    }
51
52    #[test]
53    fn escaped_ampersand() {
54        let input = Text::create("&attempt");
55        let expected = Text("&amp;attempt".to_string());
56        assert_eq!(input, expected);
57    }
58}