Add human-readable event URL slugs with legacy redirect support.
Store unique slugs on events, backfill existing records, redirect old UUID and alias URLs to canonical slug pages, and expose slug editing plus alias management in the admin event modal. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Convert a title into a URL-safe slug.
|
||||
* Lowercases, strips accents, replaces non-alphanumerics with hyphens,
|
||||
* collapses repeated hyphens, and trims leading/trailing hyphens.
|
||||
*/
|
||||
export function slugify(title: string): string {
|
||||
return title
|
||||
.toLowerCase()
|
||||
.normalize('NFKD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
.replace(/[^a-z0-9]+/g, '-')
|
||||
.replace(/-+/g, '-')
|
||||
.replace(/^-|-$/g, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a slug from a title that does not collide with any of the
|
||||
* provided existing slugs. Appends -2, -3, ... when needed.
|
||||
*/
|
||||
export function uniqueSlug(title: string, existingSlugs: string[]): string {
|
||||
const base = slugify(title) || 'event';
|
||||
const taken = new Set(existingSlugs);
|
||||
if (!taken.has(base)) return base;
|
||||
let n = 2;
|
||||
while (taken.has(`${base}-${n}`)) n++;
|
||||
return `${base}-${n}`;
|
||||
}
|
||||
Reference in New Issue
Block a user