#![deny(missing_docs, rust_2018_idioms, elided_lifetimes_in_paths)]
#![crate_name = "el_slugify"]
use deunicode::deunicode_char;
pub fn slugify(value: &str) -> String {
slugify_with_replacement(value, '-')
}
pub fn slugify_with_replacement(value: &str, replacement: char) -> String {
trim_trailing_space(sanitize(value, replacement).to_lowercase().as_str(), replacement)
}
fn sanitize(value: &str, replacement: char) -> String {
let mut out = String::new();
for elem in value.chars() {
if is_contained_in_limited_set(elem) {
out.push(elem)
} else if elem.is_alphabetic() {
let decoded_elem = deunicode_char(elem).map(|d| sanitize(d, replacement));
if let Some(decoded) = decoded_elem {
out.push_str(&decoded);
}
} else if !out.ends_with(replacement) {
out.push(replacement)
}
}
out.to_string()
}
fn is_contained_in_limited_set(value: char) -> bool {
matches!(value, '0'..='9' | 'a'..='z' | 'A'..='Z')
}
fn trim_trailing_space(value: &str, replacement: char) -> String {
let mut check_value = value.to_string();
if check_value.starts_with(replacement) {
check_value.remove(0);
}
if check_value.ends_with(replacement) {
check_value.pop();
}
check_value.to_string()
}
#[cfg(test)]
mod tests {
use std::time::Instant;
use slugify::slugify;
use crate::{slugify as el_slugify};
#[test]
fn slugify_long_special_chars_wor2() {
let binding = std::iter::repeat("#% MaČKA mački grize rep! (RIB-a) ~*")
.take(10000).collect::<String>();
let start = Instant::now();
let _ = el_slugify(binding.as_str());
let elapsed = start.elapsed();
println!(">> El slugify took: {:?}", elapsed);
let start = Instant::now();
let _ = slugify!(binding.as_str());
let elapsed = start.elapsed();
println!(">> Slugify took: {:?}", elapsed);
}
#[test]
fn test_slugify() {
assert_eq!(el_slugify("Wait! Listen \n\t!!!Runagalðr$ ~"), "wait-listen-runagaldr");
assert_eq!(el_slugify("影 _ 師 嗎"), "ying-shi-ma");
assert_eq!(el_slugify("影師嗎"), "ying-shi-ma");
assert_eq!(el_slugify("di su ćevapi?"), "di-su-cevapi");
assert_eq!(el_slugify("!-.#"), "");
assert_eq!(el_slugify("! kako a je"), "kako-a-je");
assert_eq!(el_slugify("iako ** .+a na"), "iako-a-na");
assert_eq!(el_slugify(" -!abc"), "abc");
assert_eq!(el_slugify("iako *."), "iako");
assert_eq!(el_slugify("dakako"), "dakako"); assert_eq!(el_slugify(" -!kako tako _:+"), "kako-tako");
assert_eq!(el_slugify(""), "");
assert_eq!(el_slugify("!-.#"), "");
}
}