#[must_use]
pub fn escape_text(input: &str) -> String {
let mut out = String::with_capacity(input.len());
for c in input.chars() {
match c {
'<' => out.push_str("<"),
'>' => out.push_str(">"),
'&' => out.push_str("&"),
_ => out.push(c),
}
}
out
}
#[must_use]
pub fn escape_attribute(input: &str) -> String {
let mut out = String::with_capacity(input.len());
for c in input.chars() {
match c {
'<' => out.push_str("<"),
'>' => out.push_str(">"),
'&' => out.push_str("&"),
'"' => out.push_str("""),
'\n' => out.push_str(" "),
'\r' => out.push_str(" "),
'\t' => out.push_str("	"),
_ => out.push(c),
}
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn escapes_markup_in_text() {
assert_eq!(escape_text("<a>&"), "<a>&");
}
#[test]
fn escapes_quotes_in_attributes() {
assert_eq!(escape_attribute(r#"a"b"#), "a"b");
}
#[test]
fn escapes_newlines_in_attributes() {
assert_eq!(escape_attribute("a\nb"), "a b");
}
#[test]
fn leaves_ordinary_text_alone() {
assert_eq!(escape_text("plain text"), "plain text");
}
}