pub mod parsing;
pub use parsing::*;
pub fn slugify(input: &str, separator: char) -> String {
let mut out = String::with_capacity(input.len());
let mut prev_sep = false;
for c in input.chars() {
if c.is_ascii_alphanumeric() {
out.push(c.to_ascii_lowercase());
prev_sep = false;
} else if !prev_sep {
out.push(separator);
prev_sep = true;
}
}
let trimmed = out.trim_matches(separator);
if trimmed.len() == out.len() {
out
} else {
trimmed.to_string()
}
}
#[cfg(test)]
mod slug_tests {
use super::slugify;
#[test]
fn slugify_lowercases_and_replaces() {
assert_eq!(slugify("Weather Agent", '_'), "weather_agent");
assert_eq!(slugify("billing-v2", '-'), "billing-v2");
assert_eq!(slugify(" Spaces ", '-'), "spaces");
}
#[test]
fn slugify_collapses_separator_runs() {
assert_eq!(slugify("Weather Agent", '-'), "weather-agent");
assert_eq!(slugify("a // b __ c", '-'), "a-b-c");
}
#[test]
fn slugify_is_idempotent_on_canonical_slug() {
let once = slugify("Weather Agent", '-');
assert_eq!(slugify(&once, '-'), once);
}
#[test]
fn slugify_empty_when_no_alphanumerics() {
assert_eq!(slugify("!!!", '-'), "");
assert_eq!(slugify("---", '-'), "");
}
}