Skip to content

Commit

Permalink
Remove htmlescape dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
lukaslueg committed Jul 12, 2024
1 parent 50597bc commit c9253b9
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 2 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ edition = "2021"
visual-debug = []

[dependencies]
htmlescape = "0.3"
unicode-width = "0.1"

[dev-dependencies]
Expand Down
60 changes: 59 additions & 1 deletion src/notactuallysvg.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::{
borrow::Cow,
collections::HashMap,
fmt::{self, Write},
};
Expand Down Expand Up @@ -233,7 +234,7 @@ impl Element {
/// The text is automatically HTML-escaped. It is written before any children.
#[must_use]
pub fn text(mut self, text: &str) -> Self {
self.text = Some(htmlescape::encode_minimal(text));
self.text = Some(encode_minimal(text).into_owned());
self
}

Expand Down Expand Up @@ -343,3 +344,60 @@ impl ::std::fmt::Display for Element {
Ok(())
}
}

/// Entity-encode the bare minimum of the given string (`"`, `&`, `<`, `>`, `'`) to allow
/// safely using that string as pure text in an SVG.
pub fn encode_minimal(inp: &str) -> Cow<str> {
let mut buf = String::new();
let mut last_idx = 0;
for (idx, c) in inp.char_indices() {
if let Some(entity) = match c {
'"' => Some("&quot;"),
'&' => Some("&amp;"),
'<' => Some("&lt;"),
'>' => Some("&gt;"),
'\'' => Some("&#x27;"),
_ => None,
} {
buf.push_str(&inp[last_idx..idx]);
buf.push_str(entity);
last_idx = idx + 1;
}
}
if !buf.is_empty() {
buf.push_str(&inp[last_idx..]);
Cow::Owned(buf)
} else {
Cow::Borrowed(inp)
}
}

#[cfg(test)]
mod tests {
use std::borrow::Cow;

#[test]
fn encode_minimal() {
for (inp, expected) in [
("'a", Some("&#x27;a")),
("", None),
("'", Some("&#x27;")),
("a'", Some("a&#x27;")),
("hello world!", None),
("&", Some("&amp;")),
("<br>", Some("&lt;br&gt;")),
(
"\"a\" is not \"b\"",
Some("&quot;a&quot; is not &quot;b&quot;"),
),
] {
eprintln!("now hear this: {}", inp);
let result = super::encode_minimal(inp);
assert_eq!(result, expected.unwrap_or(inp));
assert!(matches!(
(expected, result),
(None, Cow::Borrowed(_)) | (Some(_), Cow::Owned(_))
));
}
}
}
4 changes: 4 additions & 0 deletions tests/test_lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#[test]
fn test_encode_minimal() {
assert_eq!(railroad::svg::encode_minimal("foo<bar>"), "foo&lt;bar&gt;");
}

0 comments on commit c9253b9

Please sign in to comment.