Control accents, separators and length

v0.0.1

The defaults of MishkaSlug.slugify/2 match WordPress, so a migrated slug stays the same. This guide changes them one at a time: Latin accents, the characters kept inside a word, digits, the Persian half-space, words that mix scripts and the length of the slug.

Before you begin

Mishka Slug installed. See Get Started. Every option is optional, and an unknown option or a value outside the accepted ones raises ArgumentError.

Keep or remove accents

By default (latin: :ascii) Latin letters lose their accents. latin: :keep leaves them as typed. Only Latin changes: Greek, Cyrillic, Arabic and every other script keep their letters and marks.

elixir
MishkaSlug.slugify("Café Crème")
#=> {:ok, "cafe-creme"}

MishkaSlug.slugify("Café Crème", latin: :keep)
#=> {:ok, "café-crème"}

MishkaSlug.slugify("Straße")
#=> {:ok, "strase"}

MishkaSlug.slugify("Straße", language: "de")
#=> {:ok, "strasse"}

Keep underscores, dots and tildes

The keep: option lists the characters kept inside a word. Only ".", "_" and "~" are accepted, and the list replaces the default ["_"].

elixir
MishkaSlug.slugify("snake_case_name")
#=> {:ok, "snake_case_name"}

MishkaSlug.slugify("snake_case_name", keep: [])
#=> {:ok, "snake-case-name"}

MishkaSlug.slugify("a_b.c")
#=> {:ok, "a_b-c"}

MishkaSlug.slugify("a_b.c", keep: [".", "_"])
#=> {:ok, "a_b.c"}

MishkaSlug.slugify("Release v1.2", keep: ["."])
#=> {:ok, "release-v1.2"}

By default a kept character at the start or end of a word stays, as WordPress leaves it. Set trim_kept: true to remove it.

elixir
MishkaSlug.slugify("__init__ my_post_")
#=> {:ok, "__init__-my_post_"}

MishkaSlug.slugify("__init__ my_post_", trim_kept: true)
#=> {:ok, "init-my_post"}

Other characters always separate words. & is dropped, an apostrophe inside a word is removed, and a comma is a separator.

elixir
MishkaSlug.slugify("Q&A")
#=> {:ok, "q-a"}

MishkaSlug.slugify("don't")
#=> {:ok, "dont"}

MishkaSlug.slugify("1,000")
#=> {:ok, "1-000"}

Write digits as 0-9

digits: :keep leaves digits as typed. digits: :ascii writes every decimal digit as 0-9.

elixir
MishkaSlug.slugify("سنة ٢٠٢٥ كتاب", digits: :ascii)
#=> {:ok, "سنة-2025-كتاب"}

Glue or split the Persian half-space

The half-space (U+200C) joins the parts of a Persian word. zwnj: :remove, the default, glues them. zwnj: :separator turns it into a word break.

elixir
MishkaSlug.slugify("قیمت‌گذاری نرم‌افزار")
#=> {:ok, "قیمتگذاری-نرمافزار"}

MishkaSlug.slugify("قیمت‌گذاری نرم‌افزار", zwnj: :separator)
#=> {:ok, "قیمت-گذاری-نرم-افزار"}

Refuse words that mix scripts

A word never mixes scripts in a slug. By default (mixed_scripts: :split) the word is cut where the script changes. Set mixed_scripts: :reject to refuse the title instead. The a in these examples is the Cyrillic letter U+0430, a look-alike of the Latin a.

elixir
MishkaSlug.slugify("pаypal")
#=> {:ok, "p-а-ypal"}

MishkaSlug.slugify("pаypal", mixed_scripts: :reject)
#=> {:error, :mixed_scripts}

Limit the length

max_length: is the longest slug, counted in code points. Whole words are kept while they fit. A first word that is too long is cut between two graphemes.

elixir
MishkaSlug.slugify("hello world foo", max_length: 13)
#=> {:ok, "hello-world"}

MishkaSlug.slugify("supercalifragilistic", max_length: 5)
#=> {:ok, "super"}

Next steps