use std::borrow::Cow;
pub fn escape_html_attribute(text: &str) -> Cow<'_, str> {
let needs_escape: &[char] = &['<', '>', '\'', '"', '\\', '&'];
let mut s = text;
let mut output = String::new();
while let Some(next) = s.find(needs_escape) {
output.push_str(&s[..next]);
match s.as_bytes()[next] {
b'<' => output.push_str("<"),
b'>' => output.push_str(">"),
b'\'' => output.push_str("'"),
b'"' => output.push_str("""),
b'\\' => output.push_str("\"),
b'&' => output.push_str("&"),
_ => unreachable!(),
}
s = &s[next + 1..];
}
if output.is_empty() {
Cow::Borrowed(text)
} else {
output.push_str(s);
Cow::Owned(output)
}
}
pub fn escape_html(text: &str) -> Cow<'_, str> {
let needs_escape: &[char] = &['<', '>', '&'];
let mut s = text;
let mut output = String::new();
while let Some(next) = s.find(needs_escape) {
output.push_str(&s[..next]);
match s.as_bytes()[next] {
b'<' => output.push_str("<"),
b'>' => output.push_str(">"),
b'&' => output.push_str("&"),
_ => unreachable!(),
}
s = &s[next + 1..];
}
if output.is_empty() {
Cow::Borrowed(text)
} else {
output.push_str(s);
Cow::Owned(output)
}
}
#[test]
fn attributes_are_escaped() {
assert_eq!(escape_html_attribute(""), "");
assert_eq!(escape_html_attribute("<"), "<");
assert_eq!(escape_html_attribute(">"), ">");
assert_eq!(escape_html_attribute("<>"), "<>");
assert_eq!(escape_html_attribute("<test>"), "<test>");
assert_eq!(escape_html_attribute("a<test>b"), "a<test>b");
assert_eq!(escape_html_attribute("'"), "'");
assert_eq!(escape_html_attribute("\\"), "\");
assert_eq!(escape_html_attribute("&"), "&");
}
#[test]
fn html_is_escaped() {
assert_eq!(escape_html(""), "");
assert_eq!(escape_html("<"), "<");
assert_eq!(escape_html(">"), ">");
assert_eq!(escape_html("&"), "&");
assert_eq!(escape_html("<>"), "<>");
assert_eq!(escape_html("<test>"), "<test>");
assert_eq!(escape_html("a<test>b"), "a<test>b");
assert_eq!(escape_html("'"), "'");
assert_eq!(escape_html("\\"), "\\");
}