Repository navigation
Spell out ø, æ, ß and ł in new signup links and refs - #671
Conversation
toKebab stripped accents with NFKD, but ø, æ, œ, ß, ł, đ, þ and ð don't decompose, so they were dropped or split the word: "Smørrebrød" became sm-rrebr-d and "Æblekage" blekage. They are now spelled out (o, ae, oe, ss, l, d, th, d) after the accents come off, so a letter that carries both, like ǿ, is caught too. Only new signup slugs, workspace slugs and field and slot refs use this, so existing links don't change. Fixes #641. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014qBeQRGx7pCq7m7Xv8ZCpD
Tophat: passedRan e2f0948 locally with
For the owner (UX): new signup links and the refs of new fields and slots now spell out ø, æ, œ, ß, ł, đ, þ and ð instead of dropping them or splitting the word. A Danish organizer's "Smørrebrød lunch" now gets Screenshots are in https://claude.ai/code/session_01JgD5nWkvxExYEd7feWgCLE. Generated by Claude Code |
richshaw
left a comment
There was a problem hiding this comment.
Review: passed (round 1)
This PR adds a SPELLED map to src/lib/kebab.ts (ø→o, æ→ae, œ→oe, ß/ẞ→ss, ł→l, đ→d, þ→th, ð→d, upper and lower case) and applies it in toKebab after the accents are stripped and before lowercasing. The regex is built from the map's keys. The PR runs the mapping after NFKD, where the issue's outline said before, and that order is the right one: ǿ decomposes to ø plus a combining acute, so mapping first would miss it, and a test covers this. Uppercase letters map to uppercase spellings and are lowercased afterwards, so ẞ doesn't depend on how toLowerCase treats it. The file still has no Node imports, so the builder can keep using it. I checked the description's claim that existing values don't change: every caller (toSlug in pickAvailableSlug, the slot ref in services/slots.ts, the workspace slug in auth/adapter.ts, and toFieldRef in the builder's add-field) only makes new values. Nothing re-derives a stored slug or ref, or compares against one. The opt-out route's slug check still holds, since output is still [a-z0-9-]. Both "Done when" items are done: there's a test for each mapped letter in both cases, and å, ä and ö come out as before.
Blocking (0): none
Optional (0): none
Earlier threads: none. Copilot couldn't review (quota used up).
Checks: CI is green on e2f0948 (lint-type-test, e2e, CodeQL). The tophat passed on this same SHA at 1280 and 390, so runtime code hasn't changed since. It saw the new slugs and refs, a slug made on main still opened, and Cyrillic still fell back to signup. The branch is behind main but merges cleanly. I went through the diff against the repo checklist. It's a pure helper, with no services, schema, public-route, legal, help or budget impact, and the CHANGELOG has an entry under Fixed. I ran nothing locally, since there were no findings to prove.
Why the owner: UX. A new signup's web address, and the refs of new fields and slots (which show up in the CSV export and to an AI assistant), now spell out these letters. "Smørrebrød lunch" gets /s/smorrebrod-lunch-… instead of /s/sm-rrebr-d-lunch-…. Links already shared don't change. See the tophat's 671-after-desktop-public, 671-after-phone-share and 671-after-phone-old-slug.
https://claude.ai/code/session_01PNvKfYWgbETo6DkRk5LsRm
Generated by Claude Code
|
Approved by the owner at https://claude.ai/code/session_01VpmvHcvGXzLtAcbiLtSQ12 Generated by Claude Code |
Through the server, telemetry and screen branches. No conflicts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
Fixes #641.
The problem
toKebab(src/lib/kebab.ts) makes the kebab-case behind new signup slugs, workspace slugs and field and slot refs. It strips accents with NFKD, but ø, æ, œ, ß, ł, đ, þ and ð don't decompose. So they were dropped or split the word: "Smørrebrød" becamesm-rrebr-d, "Æblekage"blekage, "Straße"stra-eand "Łódź"odz.The fix
toKebabnow spells those letters out, upper and lower case: ø→o, æ→ae, œ→oe, ß→ss (and capital ẞ), ł→l, đ→d, þ→th, ð→d. The regex is built from the map's keys, so the two lists can't drift apart.signup,fieldorslot, as the issue asks. The doc comment now says so.toSlugandtoFieldRefare only called to make new values:pickAvailableSlug, the slot ref inservices/slots.ts, the workspace slug inauth/adapter.tsand the builder's new-field ref. Nothing re-derives a stored one.kebab.tsstill has no Node imports, so the builder can keep using it.Tests
New:
src/lib/kebab.test.ts:Before the fix, 18 of its 20 tests failed. The existing
slug.test.tsandslot-fields.test.tsoutputs are unchanged.Passed on
e2f0948:pnpm lint && pnpm typecheck && pnpm knip && pnpm test(1793). No services, DB, MCP or client bundle changes beyond this pure helper, so nopnpm test:dbwas needed.Generated by Claude Code