diff --git a/src/lib/slugify.ts b/src/lib/slugify.ts new file mode 100644 index 0000000..c9fc59f --- /dev/null +++ b/src/lib/slugify.ts @@ -0,0 +1,8 @@ +export function slugify(input?: string): string { + if (!input) return "" + let slug = input.toLowerCase().trim() + slug = slug.normalize("NFD").replace(/[\u0300-\u036f]/g, "") + slug = slug.replace(/[^a-z0-9\s-]/g, " ").trim() + slug = slug.replace(/[\s-]+/g, "-") + return slug +} diff --git a/tests/int/slugify.int.spec.ts b/tests/int/slugify.int.spec.ts new file mode 100644 index 0000000..ca400b0 --- /dev/null +++ b/tests/int/slugify.int.spec.ts @@ -0,0 +1,20 @@ +import { describe, expect, it } from 'vitest' +import { slugify } from '@/lib/slugify' + +describe('slugify', () => { + it('lowercases and replaces spaces with hyphens', () => { + expect(slugify('Hello World')).toBe('hello-world') + }) + it('strips accents', () => { + expect(slugify('Café Résumé')).toBe('cafe-resume') + }) + it('collapses multiple separators', () => { + expect(slugify('a b---c')).toBe('a-b-c') + }) + it('drops disallowed characters', () => { + expect(slugify("It's awesome!")).toBe('it-s-awesome') + }) + it('returns empty string for undefined input', () => { + expect(slugify(undefined)).toBe('') + }) +})