```js // article.mjs import { z } from "zod"; // Slug rule, matched to the behaviour this project's toolchain has reported for // its zod build, one observation at a time: // // "Hello, World!" -> "hello-world" // "Héllo Wörld" -> "hllo-wrld" (accented letters are DROPPED, // not folded to ASCII — no NFKD) // "under_score_case" -> "under-score-case" ("_" is a SEPARATOR, not a // character to delete) // // So: lowercase; whitespace, "-" and "_" are separators; every other character // outside [a-z0-9] is dropped; runs of separators collapse to a single "-"; // leading and trailing "-" are trimmed. // // Standing caveat, unchanged from round 0: I can find no string-to-slug // transform in zod itself — only slug-shaped validation — so this rule is // reconstructed from the reported outputs rather than read off a documented // API. It is therefore only as complete as the cases observed so far. What the // task actually requires — the API and the web client agreeing character for // character — holds regardless, because both sides import THIS module. const slugify = (input) => input .toLowerCase() .replace(/[^a-z0-9\s_-]+/g, "") // drop punctuation, emoji, accented letters .replace(/[\s_-]+/g, "-") // any run of separators -> a single "-" .replace(/^-+|-+$/g, ""); // trim leading/trailing separators export const Slug = z.string().transform(slugify); export const Article = z.object({ title: z.string().min(3), slug: Slug, }); ``` TOOLS_USED: none