Expand description
§slugrs
Fast, flexible, locale-aware slugify library for Rust. Mirrors the behavior of Node.js’s slugify package.
§Installation
On crates.io:
[dependencies]
slugrs = "0.3.4"Local path (during development):
[dependencies]
slugrs = { path = "../slugrs" }§Quick Start
Recommended: Fluent Slugifier
use slugrs::{Slugifier, Locale};
let slug = Slugifier::new()
.separator("_")
.locale(Some(Locale::Tr))
.max_length(Some(24))
.slugify("İstanbul'a hoş geldiniz!");
assert_eq!(slug, "istanbula_hos_geldiniz");Alternatives:
use slugrs::slugify;
// Defaults: separator "-", lowercase, trim, apostrophe removal, emoji removal
assert_eq!(slugify("Hello, World!"), "hello-world");use slugrs::{slugify_with_options, Options, Locale};
// Simple customization (Options builder)
let slug = slugify_with_options(
"Füße lösen Ärger",
&Options::default().separator("_").locale(Some(Locale::De))
);
assert_eq!(slug, "fuesse_loesen_aerger");
let tr = Options::default().locale(Some(Locale::Tr));
assert_eq!(slugify_with_options("İstanbul'a hoş geldiniz!", &tr), "istanbula-hos-geldiniz");§Batch processing
use slugrs::{slugify_many, slugify_many_auto, Slugifier, Options, Locale};
// Sequential batch
let out = slugify_many(["Hello World", "Crème Brûlée"].as_slice(), &Options::default());
assert_eq!(out, vec!["hello-world", "creme-brulee"]);
// Auto batch (uses a heuristic: total bytes and count)
let auto = slugify_many_auto(&["Hello World", "Crème Brûlée"], &Options::default());
assert_eq!(auto, vec!["hello-world", "creme-brulee"]);
// Fluent
let s = Slugifier::new().locale(Some(Locale::Tr));
let v2 = s.slugify_many_auto(&["İstanbul'un Müzesi", "Çağdaş Heykelciliğimizin Temsilcisi"]);
assert_eq!(v2, vec!["istanbulun-muzesi", "cagdas-heykelciligimizin-temsilcisi"]);§Parallel (optional feature)
Enable the dependency feature in your Cargo.toml:
[dependencies]
slugrs = { version = "0.3.4", features = ["parallel"] }Then you can call the parallel helpers:
use slugrs::{par_slugify_many, Slugifier, Options};
let out = par_slugify_many(["Hello World", "Crème Brûlée"].as_slice(), &Options::default());
let s = Slugifier::new();
let v2 = s.par_slugify_many(["Hello", "World"].as_slice());Heuristic (auto) rules:
- Chooses parallel when total_bytes ≥ 100_000 × logical_cores, or input_count ≥ 1000.
- Otherwise runs sequentially to avoid parallel overhead on small workloads.
§API
slugify(input: &str) -> String: Slugify with default options.slugify_with_options(input: &str, options: &Options) -> String: Full control.slugify_many<'a, I: IntoIterator<Item=&'a str>>(inputs, options) -> Vec<String>slugify_many_auto(inputs: &[&str], options) -> Vec<String>par_slugify_many<'a, I: IntoParallelIterator<Item=&'a str>>(inputs, options) -> Vec<String>(feature:parallel)Slugifier: Helper type for repeated calls with the same options (includes batch and parallel methods).Locale: Language-specific conversions (De,Tr,Ar).
§Options
| Field | Type | Default | Description |
|---|---|---|---|
separator | String | "-" | Word separator. Consecutive separators are collapsed. |
locale | Option<Locale> | None | Language-specific mappings like TR/DE/AR. |
remove | Option<Regex> | None | Custom removal regex applied before processing. |
lowercase | bool | true | Convert output to lowercase. |
trim | bool | true | Trim leading/trailing separators. |
max_length | Option<usize> | None | Max length; trims trailing separator after truncation. |
drop_emoji | bool | true | Drop emoji and most symbol characters pre-processing. |
drop_apostrophes | bool | true | Drop apostrophes to avoid inserting separators. |
Notes:
- Emoji and similar symbols are removed by default.
- Non-ASCII characters are transliterated via
deunicode. - Apostrophes (“’”,
’) are removed by default to avoid extra separators.
§Locale Support
Locale::Tr:İ/ı -> I/i,ğ -> g,ş -> s,ç -> c,ö -> o,ü -> u, etc.Locale::De:ä -> ae,ö -> oe,ü -> ue,ß -> ss, etc.Locale::Ar: basic Arabic to Latin mappings (hamza/diacritics dropped) to produce readable slugs. Example:- “الحرب على غزة مباشر إسرائيل” →
alharb-ealaa-ghazat-mubashir-iisrayiyl
- “الحرب على غزة مباشر إسرائيل” →
Locale transforms are applied before transliteration; remaining characters are then converted to ASCII.
§Examples
use regex::Regex;
use slugrs::{Slugifier, slugify, slugify_with_options, Options, Locale};
assert_eq!(slugify("Crème brûlée"), "creme-brulee");
assert_eq!(slugify("🔥 Rust & Friends"), "rust-friends");
let opts = Options::default().separator("_").remove(Some(Regex::new("[0-9]").unwrap()));
assert_eq!(slugify_with_options("A1 B2 C3", &opts), "a_b_c");
let s = Slugifier::new().separator("--").trim(true);
assert_eq!(s.slugify(" A--B__C "), "a--b--c");
let limited = Options::default().max_length(Some(10));
assert_eq!(slugify_with_options("this is a very long title", &limited), "this-is-a");
let ar = Options::default().locale(Some(Locale::Ar));
assert_eq!(slugify_with_options("الحرب على غزة مباشر إسرائيل", &ar), "alharb-ealaa-ghazat-mubashir-iisrayiyl");§Performance
- Single pass build after one-shot transliteration, minimized allocations.
- Optional parallel batch processing for large workloads.
§Tests
cargo test§License
MIT
Structs§
- Options
- Configurable options for slugification.
- Slugifier
- Slugifier processes strings into URL-friendly slugs.
Enums§
- Locale
- Supported locales for special-case transliterations.
Functions§
- par_
slugify_ many - Parallel slugify (requires
parallelfeature). - slugify
- Slugify with default options.
- slugify_
many - Slugify many inputs with the same options. Allocates one
Stringper input. - slugify_
many_ auto - Auto batch over a slice using a heuristic; uses parallel when beneficial.
- slugify_
with_ options