Skip to main content

workflow_html/
escape.rs

1use lazy_static::lazy_static;
2use regex::Regex;
3use std::borrow::Cow;
4
5/// Escapes characters unsafe within an HTML attribute value (`<`, `>`, `&`, `"`),
6/// returning the input unchanged (borrowed) when no escaping is needed.
7pub fn escape_attr<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
8    lazy_static! {
9        static ref REGEX: Regex = Regex::new("[<>&\"]").unwrap();
10    }
11    let input = input.into();
12    let first = REGEX.find(&input);
13    if let Some(m) = first {
14        let first = m.start();
15        let len = input.len();
16        let mut output: Vec<u8> = Vec::with_capacity(len + len / 2);
17        output.extend_from_slice(input[0..first].as_bytes());
18        let rest = input[first..].bytes();
19        for c in rest {
20            match c {
21                b'<' => output.extend_from_slice(b"&lt;"),
22                b'>' => output.extend_from_slice(b"&gt;"),
23                b'&' => output.extend_from_slice(b"&amp;"),
24                b'"' => output.extend_from_slice(b"&quot;"),
25                _ => output.push(c),
26            }
27        }
28        Cow::Owned(unsafe { String::from_utf8_unchecked(output) })
29    } else {
30        input
31    }
32}
33/// Escapes characters unsafe within HTML text content (`<`, `>`, `&`),
34/// returning the input unchanged (borrowed) when no escaping is needed.
35pub fn escape_html<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
36    lazy_static! {
37        static ref REGEX: Regex = Regex::new("[<>&]").unwrap();
38    }
39    let input = input.into();
40    let first = REGEX.find(&input);
41    if let Some(m) = first {
42        let first = m.start();
43        let len = input.len();
44        let mut output: Vec<u8> = Vec::with_capacity(len + len / 2);
45        output.extend_from_slice(input[0..first].as_bytes());
46        let rest = input[first..].bytes();
47        for c in rest {
48            match c {
49                b'<' => output.extend_from_slice(b"&lt;"),
50                b'>' => output.extend_from_slice(b"&gt;"),
51                b'&' => output.extend_from_slice(b"&amp;"),
52                _ => output.push(c),
53            }
54        }
55        Cow::Owned(unsafe { String::from_utf8_unchecked(output) })
56    } else {
57        input
58    }
59}