diff --git a/apps/server/src/services/utils.spec.ts b/apps/server/src/services/utils.spec.ts index 6e027b7bd..b7e57b441 100644 --- a/apps/server/src/services/utils.spec.ts +++ b/apps/server/src/services/utils.spec.ts @@ -681,3 +681,33 @@ describe("#normalizeCustomHandlerPattern", () => { }); }); }); + +describe("#slugify", () => { + it("should return a slugified string", () => { + const testString = "This is a Test String! With unicode & Special #Chars."; + const expectedSlug = "this-is-a-test-string-with-unicode-special-chars"; + const result = utils.slugify(testString); + expect(result).toBe(expectedSlug); + }); + + it("supports CJK characters without alteration", () => { + const testString = "测试中文字符"; + const expectedSlug = "测试中文字符"; + const result = utils.slugify(testString); + expect(result).toBe(expectedSlug); + }); + + it("supports Cyrillic characters without alteration", () => { + const testString = "Тестирование кириллических символов"; + const expectedSlug = "тестирование-кириллических-символов"; + const result = utils.slugify(testString); + expect(result).toBe(expectedSlug); + }); + + it("removes diacritic marks from characters", () => { + const testString = "Café naïve façade jalapeño"; + const expectedSlug = "cafe-naive-facade-jalapeno"; + const result = utils.slugify(testString); + expect(result).toBe(expectedSlug); + }); +}); diff --git a/apps/server/src/services/utils.ts b/apps/server/src/services/utils.ts index 8a4d7c7aa..cdaa9d719 100644 --- a/apps/server/src/services/utils.ts +++ b/apps/server/src/services/utils.ts @@ -499,7 +499,8 @@ export function formatSize(size: number | null | undefined) { function slugify(text: string) { return text - .normalize("NFKD") // handles accents like é → e + .normalize("NFKD") // decompose accents + .replace(/\p{Mark}/gu, "") // remove diacritics cleanly .toLowerCase() .replace(/[^\p{Letter}\p{Number}]+/gu, "-") // keep Unicode letters/numbers .replace(/(^-|-$)+/g, ""); // trim leading/trailing dashes