use regex::Regex;
use std::sync::LazyLock;
static HTML_TAG_REGEX: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"<[^>]*>").unwrap());
pub fn strip_html_tags(input: &str) -> String {
HTML_TAG_REGEX.replace_all(input, "").to_string()
}
pub fn escape_html(input: &str) -> String {
input
.replace('&', "&")
.replace('<', "<")
.replace('>', ">")
.replace('"', """)
.replace('\'', "'")
}
pub fn escape_markdown(input: &str) -> String {
input
.replace('_', r"\_")
.replace('*', r"\*")
.replace('[', r"\[")
.replace(']', r"\]")
.replace('(', r"\(")
.replace(')', r"\)")
.replace('~', r"\~")
.replace('`', r"\`")
.replace('>', r"\>")
.replace('#', r"\#")
.replace('+', r"\+")
.replace('-', r"\-")
.replace('=', r"\=")
.replace('|', r"\|")
.replace('{', r"\{")
.replace('}', r"\}")
.replace('.', r"\.")
.replace('!', r"\!")
}
pub fn truncate_string(s: &str, max_len: usize) -> &str {
if s.len() <= max_len {
s
} else {
let mut end = max_len;
while !s.is_char_boundary(end) && end > 0 {
end -= 1;
}
&s[..end]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_strip_html_tags() {
assert_eq!(strip_html_tags("<b>hello</b>"), "hello");
assert_eq!(strip_html_tags("<a href=\"test\">link</a>"), "link");
}
#[test]
fn test_escape_html() {
assert_eq!(escape_html("<script>"), "<script>");
assert_eq!(escape_html("a & b"), "a & b");
}
#[test]
fn test_truncate_string() {
assert_eq!(truncate_string("hello world", 5), "hello");
assert_eq!(truncate_string("hello", 10), "hello");
}
}