Skip to main content

html_escape/
lib.rs

1use std::cmp::max;
2
3pub fn escape(src: &str) -> String {
4    let mut ret_val = String::with_capacity(max(4, src.len()));
5    for c in src.chars() {
6        let replacement = match c {
7            // this character, when confronted, will start a tag
8            '<' => "&lt;",
9            // in an unquoted attribute, will end the attribute value
10            '>' => "&gt;",
11            // in an attribute surrounded by double quotes, this character will end the attribute value
12            '\"' => "&quot;",
13            // in an attribute surrounded by single quotes, this character will end the attribute value
14            '\'' => "&apos;",
15            // in HTML5, returns a bogus parse error in an unquoted attribute, while in SGML/HTML, it will end an attribute value surrounded by backquotes
16            '`' => "&grave;",
17            // in an unquoted attribute, this character will end the attribute
18            '/' => "&#47;",
19            // starts an entity reference
20            '&' => "&amp;",
21            // if at the beginning of an unquoted attribute, will get ignored
22            '=' => "&#61;",
23            // will end an unquoted attribute
24            ' ' => "&#32;",
25            '\t' => "&#9;",
26            '\n' => "&#10;",
27            '\x0c' => "&#12;",
28            '\r' => "&#13;",
29            // a spec-compliant browser will perform this replacement anyway, but the middleware might not
30            '\0' => "&#65533;",
31            // ALL OTHER CHARACTERS ARE PASSED THROUGH VERBATIM
32            _ => {
33                ret_val.push(c);
34                continue;
35            }
36        };
37        ret_val.push_str(replacement);
38    }
39    ret_val
40}