39 lines
1.2 KiB
TypeScript
39 lines
1.2 KiB
TypeScript
/**
|
|
* Builds the URL slugs of dumps and playlists from their titles. The dump and
|
|
* playlist services store the slug when the record is created or retitled.
|
|
*
|
|
* @module
|
|
*/
|
|
|
|
/**
|
|
* Matches a UUID. A dump or playlist route takes either an id or a slug, and
|
|
* the services test the parameter with this to know which column to look up.
|
|
*/
|
|
export const UUID_RE =
|
|
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
|
|
/**
|
|
* Turns `title` into lowercase ASCII words joined by dashes, at most 60
|
|
* characters long. Accents are dropped, and a title with no ASCII letter or
|
|
* digit gives `untitled`.
|
|
*/
|
|
export function slugify(title: string): string {
|
|
const slug = title
|
|
.toLowerCase()
|
|
.normalize("NFD")
|
|
// NFD splits an accented letter into the letter and a combining mark.
|
|
.replace(/[\u0300-\u036f]/g, "")
|
|
.replace(/[^a-z0-9]+/g, "-")
|
|
.replace(/^-+|-+$/g, "")
|
|
.substring(0, 60);
|
|
return slug || "untitled";
|
|
}
|
|
|
|
/**
|
|
* Returns a record's slug, its title's {@link slugify} followed by the first 8
|
|
* characters of `id`. The suffix keeps two records with the same title apart.
|
|
*/
|
|
export function makeSlug(title: string, id: string): string {
|
|
return `${slugify(title)}-${id.substring(0, 8)}`;
|
|
}
|