pub fn truncate(value: &str, max_len: Option<usize>) -> String {
let Some(max_len) = max_len else {
return value.to_string();
};
if max_len == 0 {
return String::new();
}
let char_count = value.chars().count();
if char_count <= max_len {
return value.to_string();
}
if max_len <= 3 {
return value.chars().take(max_len).collect();
}
let truncated: String = value.chars().take(max_len - 3).collect();
format!("{}...", truncated)
}
pub fn is_uuid(value: &str) -> bool {
value.len() == 36 && value.matches("-").count() == 4
}
pub fn strip_markdown(input: &str) -> String {
use std::sync::OnceLock;
use regex::Regex;
static PATTERNS: OnceLock<Vec<(Regex, &str)>> = OnceLock::new();
let patterns = PATTERNS.get_or_init(|| {
vec![
(Regex::new(r"!\[([^\]]*)\]\([^)]+\)").unwrap(), "$1"),
(Regex::new(r"\[([^\]]+)\]\([^)]+\)").unwrap(), "$1"),
(Regex::new(r"\*{3}([^*]+)\*{3}").unwrap(), "$1"),
(Regex::new(r"_{3}([^_]+)_{3}").unwrap(), "$1"),
(Regex::new(r"\*{2}([^*]+)\*{2}").unwrap(), "$1"),
(Regex::new(r"_{2}([^_]+)_{2}").unwrap(), "$1"),
(Regex::new(r"\*([^*]+)\*").unwrap(), "$1"),
(Regex::new(r"(?:^|[\s(])_([^_]+)_(?:[\s).,;:!?]|$)").unwrap(), "$1"),
(Regex::new(r"~~([^~]+)~~").unwrap(), "$1"),
(Regex::new(r"`([^`]+)`").unwrap(), "$1"),
(Regex::new(r"(?m)^#{1,6}\s+").unwrap(), ""),
(Regex::new(r"(?m)^[-*_]{3,}\s*$").unwrap(), ""),
(Regex::new(r"(?m)^>\s?").unwrap(), ""),
(Regex::new(r"(?m)^[\s]*[-*+]\s").unwrap(), " "),
(Regex::new(r"(?m)^[\s]*\d+\.\s").unwrap(), " "),
]
});
let mut result = input.to_string();
static CODE_FENCE: OnceLock<Regex> = OnceLock::new();
let code_fence = CODE_FENCE.get_or_init(|| Regex::new(r"(?m)^```\w*\s*$").unwrap());
result = code_fence.replace_all(&result, "").to_string();
for (pattern, replacement) in patterns {
result = pattern.replace_all(&result, *replacement).to_string();
}
static MULTI_BLANK: OnceLock<Regex> = OnceLock::new();
let multi_blank = MULTI_BLANK.get_or_init(|| Regex::new(r"\n{3,}").unwrap());
result = multi_blank.replace_all(&result, "\n\n").to_string();
result.trim().to_string()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_truncate_none() {
assert_eq!(truncate("hello world", None), "hello world");
}
#[test]
fn test_truncate_zero() {
assert_eq!(truncate("hello", Some(0)), "");
}
#[test]
fn test_truncate_short_string() {
assert_eq!(truncate("hi", Some(10)), "hi");
}
#[test]
fn test_truncate_exact_length() {
assert_eq!(truncate("hello", Some(5)), "hello");
}
#[test]
fn test_truncate_with_ellipsis() {
assert_eq!(truncate("hello world", Some(8)), "hello...");
}
#[test]
fn test_truncate_unicode() {
assert_eq!(truncate("こんにちは世界", Some(5)), "こん...");
assert_eq!(truncate("hello世界", Some(8)), "hello世界");
assert_eq!(truncate("hello世界", Some(6)), "hel...");
}
#[test]
fn test_is_uuid_valid() {
assert!(is_uuid("550e8400-e29b-41d4-a716-446655440000"));
assert!(is_uuid("00000000-0000-0000-0000-000000000000"));
}
#[test]
fn test_is_uuid_invalid() {
assert!(!is_uuid("not-a-uuid"));
assert!(!is_uuid("550e8400e29b41d4a716446655440000")); assert!(!is_uuid("550e8400-e29b-41d4-a716")); assert!(!is_uuid("")); }
#[test]
fn test_strip_markdown_headers() {
assert_eq!(strip_markdown("# Title"), "Title");
assert_eq!(strip_markdown("## Subtitle"), "Subtitle");
assert_eq!(strip_markdown("### Deep"), "Deep");
}
#[test]
fn test_strip_markdown_bold_italic() {
assert_eq!(strip_markdown("**bold**"), "bold");
assert_eq!(strip_markdown("__bold__"), "bold");
assert_eq!(strip_markdown("*italic*"), "italic");
assert_eq!(strip_markdown("***both***"), "both");
}
#[test]
fn test_strip_markdown_links() {
assert_eq!(strip_markdown("[click here](https://example.com)"), "click here");
assert_eq!(strip_markdown(""), "alt text");
}
#[test]
fn test_strip_markdown_code() {
assert_eq!(strip_markdown("`inline code`"), "inline code");
assert_eq!(strip_markdown("```rust\nlet x = 1;\n```"), "let x = 1;");
}
#[test]
fn test_strip_markdown_strikethrough() {
assert_eq!(strip_markdown("~~deleted~~"), "deleted");
}
#[test]
fn test_strip_markdown_blockquote() {
assert_eq!(strip_markdown("> quoted text"), "quoted text");
}
#[test]
fn test_strip_markdown_lists() {
assert_eq!(strip_markdown("- item one"), "item one");
assert_eq!(strip_markdown("* item two"), "item two");
assert_eq!(strip_markdown("1. numbered"), "numbered");
assert_eq!(strip_markdown("text\n- item"), "text\n item");
}
#[test]
fn test_strip_markdown_horizontal_rule() {
assert_eq!(strip_markdown("above\n---\nbelow"), "above\n\nbelow");
}
#[test]
fn test_strip_markdown_plain_text() {
assert_eq!(strip_markdown("just plain text"), "just plain text");
}
#[test]
fn test_strip_markdown_collapses_blank_lines() {
assert_eq!(strip_markdown("a\n\n\n\nb"), "a\n\nb");
}
}