← All exercises

The slug that eats accented letters

Post URLs in a multilingual blog platform · difficulty 2/3 · ~7 min

A teammate asked the AI assistant: "Write a `slugify(title)` for post URLs. Lowercase, ASCII letters and digits only, hyphens between words, nothing at the edges. Accented letters should keep their base letter, since many of our authors write in French, Portuguese and German. Also add `uniqueSlug(title, existing)` that appends -2, -3 and so on when a slug is already taken." The code came back with tests, and the English posts on staging all have clean URLs. The contract promised by the docstring: - Output contains only `a-z`, `0-9` and single `-` separators, with no leading or trailing `-`. - Runs of spaces and punctuation collapse into one `-`. - Accented letters are reduced to their base letter: `"Crème brûlée"` becomes `"creme-brulee"`. - `uniqueSlug` returns the plain slug when free, otherwise the first free `-n` variant. Review it before it goes live for the non-English authors.

code.ts

Visible tests (they pass on the code as given)
import { describe, it, expect } from "@debunk/harness";
import { slugify, uniqueSlug } from "./code";

describe("slugify", () => {
  it("lowercases and joins words with hyphens", () => {
    expect(slugify("Hello World")).toBe("hello-world");
  });

  it("drops punctuation and collapses runs of separators", () => {
    expect(slugify("  Rust & C++: a comparison!  ")).toBe("rust-c-a-comparison");
  });

  it("uniqueSlug appends a counter when the slug is taken", () => {
    const existing = new Set(["hello-world", "hello-world-2"]);
    expect(uniqueSlug("Hello World", existing)).toBe("hello-world-3");
  });
});