deckhearth/lib/slug-utils.js

66 lines
1.6 KiB
JavaScript
Raw Permalink Normal View History

/**
* Generate a URL-friendly slug from a collection name
*/
export function generateSlug(name) {
return name
.toLowerCase()
.trim()
// Replace spaces and special characters with hyphens
.replace(/[^a-z0-9]+/g, '-')
// Remove leading/trailing hyphens
.replace(/^-+|-+$/g, '')
// Limit length to 50 characters
.substring(0, 50)
// Remove trailing hyphen if truncation created one
.replace(/-+$/, '');
}
/**
* Generate a unique slug by checking against existing slugs
*/
export async function generateUniqueSlug(name, existingSlugs = []) {
const baseSlug = generateSlug(name);
// If base slug is unique, use it
if (!existingSlugs.includes(baseSlug)) {
return baseSlug;
}
// Find the next available number suffix
let counter = 2;
let uniqueSlug = `${baseSlug}-${counter}`;
while (existingSlugs.includes(uniqueSlug)) {
counter++;
uniqueSlug = `${baseSlug}-${counter}`;
}
return uniqueSlug;
}
/**
* Validate a slug format
*/
export function isValidSlug(slug) {
if (!slug || typeof slug !== 'string') {
return false;
}
// Must be 1-50 characters, lowercase letters, numbers, and hyphens only
// Cannot start or end with hyphen
const slugRegex = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
return slugRegex.test(slug) && slug.length <= 50;
}
/**
* Convert existing collection names to suggested slugs for migration
*/
export function suggestSlugForCollection(collection) {
const baseSlug = generateSlug(collection.name);
return {
id: collection.id,
name: collection.name,
currentSlug: collection.slug || null,
suggestedSlug: baseSlug
};
}