Files
portfolio/lib/slug.ts
2026-01-12 14:36:10 +00:00

31 lines
887 B
TypeScript

export function slugify(input: string): string {
return input
.trim()
.toLowerCase()
.replace(/['"]/g, "")
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-+|-+$/g, "");
}
export async function generateUniqueSlug(opts: {
base: string;
isTaken: (slug: string) => Promise<boolean>;
maxAttempts?: number;
}): Promise<string> {
const maxAttempts = opts.maxAttempts ?? 50;
const normalizedBase = slugify(opts.base) || "item";
let candidate = normalizedBase;
for (let i = 0; i < maxAttempts; i++) {
// First try the base, then base-2, base-3, ...
candidate = i === 0 ? normalizedBase : `${normalizedBase}-${i + 1}`;
// eslint-disable-next-line no-await-in-loop
const taken = await opts.isTaken(candidate);
if (!taken) return candidate;
}
// Last resort: append timestamp to avoid collisions
return `${normalizedBase}-${Date.now()}`;
}