Skip to the code
cf.

Slugify

Write slugify(text). It turns a title into a slug, the readable part of a URL like /recipes/creme-brulee-in-10-minutes. A slug contains only the lowercase letters a to z, the digits 0 to 9, and hyphens.

Lowercase every letter and remove its accents: É becomes e, ñ becomes n, and ř becomes r. An accent may be stored in the letter itself or as a separate mark right after it (e followed by U+0301, the combining acute accent); remove it either way.

Drop apostrophes, both ' and ’, so Don't becomes dont. Every other run of characters that aren't a to z or 0 to 9 becomes a single hyphen: spaces, punctuation, symbols, emoji, and letters from other alphabets.

The slug never starts or ends with a hyphen. If nothing is left, return "".

slugify("Crème Brûlée in 10 Minutes!"); // "creme-brulee-in-10-minutes"
slugify("  Don't   stop -- me now ");    // "dont-stop-me-now"
slugify("São Paulo & Tōkyō");            // "sao-paulo-tokyo"
slugify("東京");                          // ""

What the tests check

  1. lowercases and joins words with hyphens
    expect(slugify("Hello World")).toBe("hello-world");
    expect(slugify("JavaScript Problems")).toBe("javascript-problems");
    
  2. removes accents from letters
    expect(slugify("Crème Brûlée")).toBe("creme-brulee");
    expect(slugify("Dvořák")).toBe("dvorak");
    expect(slugify("ÉCOLE Ñandú")).toBe("ecole-nandu");
    expect(slugify("Zoë Ångström")).toBe("zoe-angstrom");
    expect(slugify("Việt Nam")).toBe("viet-nam");
    
  3. removes accents stored as separate marks
    expect(slugify("Pe\u0301rez")).toBe("perez");
    expect(slugify("Cafe\u0301 Mu\u0308ller")).toBe("cafe-muller");
    
  4. turns each run of other characters into one hyphen
    expect(slugify("rock & roll")).toBe("rock-roll");
    expect(slugify("one -- two__three...four")).toBe("one-two-three-four");
    expect(slugify("I ❤️ JS")).toBe("i-js");
    expect(slugify("I❤️JS")).toBe("i-js");
    expect(slugify("Tokyo東京Tower")).toBe("tokyo-tower");
    expect(slugify("C++/C# tips")).toBe("c-c-tips");
    expect(slugify("Ελληνικά and English")).toBe("and-english");
    
  5. drops apostrophes instead of splitting the word
    expect(slugify("Don't stop")).toBe("dont-stop");
    expect(slugify("It’s Ada’s book")).toBe("its-adas-book");
    expect(slugify("rock 'n' roll")).toBe("rock-n-roll");
    
  6. keeps digits
    expect(slugify("Top 10 tips for 2024")).toBe("top-10-tips-for-2024");
    expect(slugify("HTML5 vs. CSS3")).toBe("html5-vs-css3");
    
  7. never starts or ends with a hyphen
    expect(slugify("  --Hello, world!--  ")).toBe("hello-world");
    expect(slugify("¿Qué pasa?")).toBe("que-pasa");
    expect(slugify("...dots")).toBe("dots");
    
  8. returns "" when nothing is left
    expect(slugify("")).toBe("");
    expect(slugify("!!! ???")).toBe("");
    expect(slugify("東京")).toBe("");
    

Learn more

solution.jsSaved in this browser

Run tests runs every test on your code, here in your browser. The problem is solved when they all pass.

Ctrl + Enter runs the tests (⌘ + Enter on a Mac).