#![deny(missing_docs)]
#![deny(rustdoc::broken_intra_doc_links)]
mod case;
mod normalize;
mod separator;
pub use case::CaseMode;
#[derive(Debug, Clone, Copy)]
pub struct SlugOpts {
pub separator: char,
pub case: CaseMode,
pub split_camel: bool,
}
impl Default for SlugOpts {
fn default() -> Self {
Self {
separator: '-',
case: CaseMode::Preserve,
split_camel: false,
}
}
}
#[must_use]
pub fn slugify(input: &str, opts: &SlugOpts) -> String {
slugify_with_sentinel(input, opts.separator, opts)
}
#[must_use]
pub fn slugify_with_sentinel(input: &str, sentinel: char, opts: &SlugOpts) -> String {
let normalized = normalize::nfkc(input);
let folded = normalize::fold_to_ascii_keep(&normalized, sentinel);
let with_sentinels = separator::replace_non_alnum(&folded, sentinel);
let collapsed = separator::collapse_runs(&with_sentinels, sentinel);
let cased = case::apply(&collapsed, opts.case);
let trimmed = cased.trim_matches(sentinel).to_string();
if sentinel == opts.separator {
trimmed
} else {
trimmed.replace(sentinel, &opts.separator.to_string())
}
}