Text.Slug (Text v0.5.0)

Copy Markdown View Source

URL-safe slug generation with locale-aware Unicode folding.

Produces a lowercase, separator-joined ASCII string suitable for URLs, filenames, and other identifiers from any UTF-8 input. Unlike a naive ASCII filter, this module handles:

  • Latin diacritics"café résumé""cafe-resume".

  • Locale-specific folding rules baked into CLDR — German "ß" folds to "ss", Turkish "İ" to "i", Vietnamese "Đ" to "D", etc. (via the unicode_transform package's Latin-ASCII transform).

  • Cross-script transliteration"Привет мир""privet-mir", "北京""beijing", "こんにちは""konnichiha" — for inputs in any script unicode_transform has a <Script>-Latin transform for. Disable with transliterate: false to drop non-Latin characters instead.

Algorithm

  1. (Optional) per-script transliteration via unicode_transform, leaving Latin runs untouched.

  2. ASCII folding via Latin-ASCII (handles diacritics and the locale-specific cases above).

  3. Lowercase.

  4. Replace each maximal run of non-[a-z0-9] characters with the separator.

  5. Trim leading and trailing separators.

Summary

Functions

Returns a URL-safe slug for the given string.

Functions

slugify(text, options \\ [])

@spec slugify(
  String.t(),
  keyword()
) :: String.t()

Returns a URL-safe slug for the given string.

Arguments

  • text is a UTF-8 string.

Options

  • :separator — the joining string used between word runs and inserted in place of non-alphanumeric characters. Defaults to "-". Any non-empty string is allowed; "_" is the common alternative.

  • :transliterate — when true (default), characters in non-Latin scripts are first transliterated to Latin via unicode_transform's <Script>-Latin transforms (for those scripts that have one). When false, non-Latin characters are dropped during the ASCII folding step.

Returns

  • A non-empty lowercase ASCII string. Returns "" if the input has no characters that survive the pipeline (e.g. all-emoji input with transliterate: false).

Examples

iex> Text.Slug.slugify("Hello World")
"hello-world"

iex> Text.Slug.slugify("café résumé")
"cafe-resume"

iex> Text.Slug.slugify("Straße München")
"strasse-munchen"

iex> Text.Slug.slugify("İstanbul Çanakkale")
"istanbul-canakkale"

iex> Text.Slug.slugify("Đà Nẵng")
"da-nang"

iex> Text.Slug.slugify("Hello World", separator: "_")
"hello_world"

iex> Text.Slug.slugify("  multiple   spaces  ")
"multiple-spaces"

iex> Text.Slug.slugify("a/b\\c")
"a-b-c"