diff options
Diffstat (limited to '')
-rw-r--r-- | Cargo.lock | 7 | ||||
-rw-r--r-- | askama/Cargo.toml | 1 | ||||
-rw-r--r-- | askama/src/filters.rs | 50 |
3 files changed, 47 insertions, 11 deletions
@@ -10,7 +10,6 @@ dependencies = [ name = "askama" version = "0.1.0" dependencies = [ - "htmlescape 0.3.1 (git+https://github.com/veddan/rust-htmlescape)", "nom 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -24,11 +23,6 @@ dependencies = [ ] [[package]] -name = "htmlescape" -version = "0.3.1" -source = "git+https://github.com/veddan/rust-htmlescape#1699b539179798e705ad8464128492a0a0092876" - -[[package]] name = "nom" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -53,7 +47,6 @@ version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum htmlescape 0.3.1 (git+https://github.com/veddan/rust-htmlescape)" = "<none>" "checksum nom 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d4598834859fedb9a0a69d5b862a970e77982a92f544d547257a4d49469067" "checksum quote 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b44fd83db28b83c1c58187159934906e5e955c812e211df413b76b03c909a5" "checksum syn 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f94368aae82bb29656c98443a7026ca931a659e8d19dcdc41d6e273054e820" diff --git a/askama/Cargo.toml b/askama/Cargo.toml index 55c6059..2f28018 100644 --- a/askama/Cargo.toml +++ b/askama/Cargo.toml @@ -8,6 +8,5 @@ license = "MIT/Apache-2.0" workspace = ".." [dependencies] -htmlescape = { git = "https://github.com/veddan/rust-htmlescape" } nom = "2.1" syn = "0.11" diff --git a/askama/src/filters.rs b/askama/src/filters.rs index 08feed3..fd8222c 100644 --- a/askama/src/filters.rs +++ b/askama/src/filters.rs @@ -1,8 +1,52 @@ -extern crate htmlescape; - use std::fmt; +fn escapable(b: &u8) -> bool { + *b == b'<' || *b == b'>' || *b == b'&' +} + pub fn e(s: &fmt::Display) -> String { let s = format!("{}", s); - htmlescape::encode_minimal(&s) + let mut found = Vec::new(); + for (i, b) in s.as_bytes().iter().enumerate() { + if escapable(b) { + found.push(i); + } + } + if found.is_empty() { + return s; + } + + let bytes = s.as_bytes(); + let max_len = bytes.len() + found.len() * 3; + let mut res = Vec::<u8>::with_capacity(max_len); + let mut start = 0; + for idx in &found { + if start < *idx { + res.extend(&bytes[start..*idx]); + } + start = *idx + 1; + match bytes[*idx] { + b'<' => { res.extend(b"<"); }, + b'>' => { res.extend(b">"); }, + b'&' => { res.extend(b"&"); }, + _ => panic!("incorrect indexing"), + } + } + if start < bytes.len() - 1 { + res.extend(&bytes[start..]); + } + + String::from_utf8(res).unwrap() +} + +#[cfg(test)] +mod tests { + use super::e; + #[test] + fn test_escape() { + assert_eq!(e(&""), ""); + assert_eq!(e(&"<&>"), "<&>"); + assert_eq!(e(&"bla&"), "bla&"); + assert_eq!(e(&"<foo"), "<foo"); + } } |