mdbook_core/utils/
html.rs

1//! Utilities for dealing with HTML.
2
3use std::borrow::Cow;
4
5/// Escape characters to make it safe for an HTML string.
6pub fn escape_html_attribute(text: &str) -> Cow<'_, str> {
7    let needs_escape: &[char] = &['<', '>', '\'', '"', '\\', '&'];
8    let mut s = text;
9    let mut output = String::new();
10    while let Some(next) = s.find(needs_escape) {
11        output.push_str(&s[..next]);
12        match s.as_bytes()[next] {
13            b'<' => output.push_str("&lt;"),
14            b'>' => output.push_str("&gt;"),
15            b'\'' => output.push_str("&#39;"),
16            b'"' => output.push_str("&quot;"),
17            b'\\' => output.push_str("&#92;"),
18            b'&' => output.push_str("&amp;"),
19            _ => unreachable!(),
20        }
21        s = &s[next + 1..];
22    }
23    if output.is_empty() {
24        Cow::Borrowed(text)
25    } else {
26        output.push_str(s);
27        Cow::Owned(output)
28    }
29}
30
31/// Escape `<`, `>`, and '&' for HTML.
32pub fn escape_html(text: &str) -> Cow<'_, str> {
33    let needs_escape: &[char] = &['<', '>', '&'];
34    let mut s = text;
35    let mut output = String::new();
36    while let Some(next) = s.find(needs_escape) {
37        output.push_str(&s[..next]);
38        match s.as_bytes()[next] {
39            b'<' => output.push_str("&lt;"),
40            b'>' => output.push_str("&gt;"),
41            b'&' => output.push_str("&amp;"),
42            _ => unreachable!(),
43        }
44        s = &s[next + 1..];
45    }
46    if output.is_empty() {
47        Cow::Borrowed(text)
48    } else {
49        output.push_str(s);
50        Cow::Owned(output)
51    }
52}
53
54#[test]
55fn attributes_are_escaped() {
56    assert_eq!(escape_html_attribute(""), "");
57    assert_eq!(escape_html_attribute("<"), "&lt;");
58    assert_eq!(escape_html_attribute(">"), "&gt;");
59    assert_eq!(escape_html_attribute("<>"), "&lt;&gt;");
60    assert_eq!(escape_html_attribute("<test>"), "&lt;test&gt;");
61    assert_eq!(escape_html_attribute("a<test>b"), "a&lt;test&gt;b");
62    assert_eq!(escape_html_attribute("'"), "&#39;");
63    assert_eq!(escape_html_attribute("\\"), "&#92;");
64    assert_eq!(escape_html_attribute("&"), "&amp;");
65}
66
67#[test]
68fn html_is_escaped() {
69    assert_eq!(escape_html(""), "");
70    assert_eq!(escape_html("<"), "&lt;");
71    assert_eq!(escape_html(">"), "&gt;");
72    assert_eq!(escape_html("&"), "&amp;");
73    assert_eq!(escape_html("<>"), "&lt;&gt;");
74    assert_eq!(escape_html("<test>"), "&lt;test&gt;");
75    assert_eq!(escape_html("a<test>b"), "a&lt;test&gt;b");
76    assert_eq!(escape_html("'"), "'");
77    assert_eq!(escape_html("\\"), "\\");
78}