use regex::Regex;
use std::borrow::Cow;
use std::sync::LazyLock;
use crate::emoji_codes::EMOJI;
static EMOJI_RE: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r":(\S*?)(?:(?:\-)(emoji|text))?:").unwrap());
pub fn emoji_replace<'a>(text: &'a str, default_variant: Option<&str>) -> Cow<'a, str> {
let default_variant_code = match default_variant {
Some("text") => "\u{FE0E}",
Some("emoji") => "\u{FE0F}",
_ => "",
};
EMOJI_RE.replace_all(text, |caps: ®ex::Captures| {
let full_match = caps.get(0).unwrap().as_str();
let emoji_name = caps.get(1).unwrap().as_str().to_lowercase();
let variant = caps.get(2).map(|m| m.as_str());
match EMOJI.get(emoji_name.as_str()) {
Some(emoji_char) => {
let variant_code = match variant {
Some("text") => "\u{FE0E}",
Some("emoji") => "\u{FE0F}",
_ => default_variant_code,
};
format!("{}{}", emoji_char, variant_code)
}
None => full_match.to_string(),
}
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_simple_replacement() {
let result = emoji_replace(":heart:", None);
assert_eq!(result, "\u{2764}");
}
#[test]
fn test_unknown_emoji_unchanged() {
let result = emoji_replace(":unknown_xyz:", None);
assert_eq!(result, ":unknown_xyz:");
}
#[test]
fn test_variant_text() {
let result = emoji_replace(":heart-text:", None);
assert_eq!(result, "\u{2764}\u{FE0E}");
}
#[test]
fn test_variant_emoji() {
let result = emoji_replace(":heart-emoji:", None);
assert_eq!(result, "\u{2764}\u{FE0F}");
}
#[test]
fn test_multiple_emojis() {
let result = emoji_replace("Hello :heart: world :thumbs_up:!", None);
assert_eq!(result, "Hello \u{2764} world \u{1F44D}!");
}
#[test]
fn test_no_emojis_passthrough() {
let result = emoji_replace("Hello, world!", None);
assert_eq!(result, "Hello, world!");
}
#[test]
fn test_default_variant_text() {
let result = emoji_replace(":heart:", Some("text"));
assert_eq!(result, "\u{2764}\u{FE0E}");
}
#[test]
fn test_default_variant_emoji() {
let result = emoji_replace(":heart:", Some("emoji"));
assert_eq!(result, "\u{2764}\u{FE0F}");
}
#[test]
fn test_explicit_variant_overrides_default() {
let result = emoji_replace(":heart-text:", Some("emoji"));
assert_eq!(result, "\u{2764}\u{FE0E}");
}
#[test]
fn test_empty_string() {
let result = emoji_replace("", None);
assert_eq!(result, "");
}
#[test]
fn test_case_insensitive_name() {
let result = emoji_replace(":HEART:", None);
assert_eq!(result, "\u{2764}");
}
}