fix: derive a topic slug that survives a Korean name
Creating a topic failed intermittently — "a topic with that slug already exists" — and worked when the author retried with a different name. The rule was never intermittent, only invisible: the slug kept `[a-z0-9]` and dropped everything else, so a Korean name contributed nothing. Whatever Latin word or number happened to be in it became the entire slug. Two ways that goes wrong, and the author hit both. `인증` reduced to an empty string, which the form refused before a request was ever sent. `Redis 캐시` and `Redis 클러스터` both reduced to `redis`, so the second one collided with the first — a real conflict, reported honestly, about a slug the author never chose and could not see. Hangul is now romanized rather than discarded. Syllables decompose arithmetically into initial, medial and final jamo, so this needs no table and is deterministic: `백엔드 아키텍처` becomes `baekendeu-akitekcheo`. Only the jamo mapping from Revised Romanization is applied — the sound-change rules are deliberately left out, because a slug is read, not pronounced, and those rules would make one name produce different slugs in different contexts. The output keeps the shape document slugs already use (`^[a-z0-9]+(?:-[a-z0-9]+)*$`), so the repository has one slug rule rather than two, and the tests assert exactly that.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useCallback, useEffect, useState, type FormEvent } from "react";
|
||||
|
||||
import type { ProjectIndexItem, TopicEdit } from "../../../contracts/management/contract.ts";
|
||||
import { slugFromName } from "./slug-from-name.ts";
|
||||
import { useStudio } from "../use-studio.ts";
|
||||
|
||||
/**
|
||||
@@ -51,15 +52,11 @@ export function TaxonomyManager() {
|
||||
}, [managementGateway, generation]);
|
||||
|
||||
/**
|
||||
* slug 를 비워 두면 이름에서 만든다. 한글 이름이 흔한데 slug 는 ASCII 만 받으므로, 비운 채로
|
||||
* 저장하면 서버가 422 로 거절한다 — 사용자가 규칙을 몰라도 되도록 여기서 채운다.
|
||||
* slug 를 비워 두면 이름에서 만든다. 한글 이름이 흔한데 이전 규칙은 한글을 전부 버려서, 이름에
|
||||
* 섞인 영문·숫자만 남았다 — `인증` 은 빈 slug 가 되고 `Redis 캐시` 와 `Redis 클러스터` 는 둘 다
|
||||
* `redis` 가 됐다. 지금은 로마자로 옮긴다 ({@link slugFromName}).
|
||||
*/
|
||||
const slugify = (value: string) =>
|
||||
value
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/gu, "-")
|
||||
.replace(/^-+|-+$/gu, "");
|
||||
const slugify = slugFromName;
|
||||
|
||||
const submitTopic = async (event: FormEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
Reference in New Issue
Block a user