Crate slugrs

Crate slugrs 

Source
Expand description

§slugrs

docs.rs

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

FieldTypeDefaultDescription
separatorString"-"Word separator. Consecutive separators are collapsed.
localeOption<Locale>NoneLanguage-specific mappings like TR/DE/AR.
removeOption<Regex>NoneCustom removal regex applied before processing.
lowercasebooltrueConvert output to lowercase.
trimbooltrueTrim leading/trailing separators.
max_lengthOption<usize>NoneMax length; trims trailing separator after truncation.
drop_emojibooltrueDrop emoji and most symbol characters pre-processing.
drop_apostrophesbooltrueDrop 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 parallel feature).
slugify
Slugify with default options.
slugify_many
Slugify many inputs with the same options. Allocates one String per input.
slugify_many_auto
Auto batch over a slice using a heuristic; uses parallel when beneficial.
slugify_with_options