@bernierllc/slug-generator
v1.0.1
Published
SEO-friendly URL slug generation with Unicode support and collision handling
Downloads
115
Readme
@bernierllc/slug-generator
SEO-friendly URL slug generation with Unicode support and collision handling.
Installation
npm install @bernierllc/slug-generatorFeatures
- 🌍 Unicode Support - Handles international characters (German ß, Spanish ñ, French é, etc.)
- 🔄 Collision Detection - Generates unique slugs with numeric, random, or timestamp suffixes
- ⚙️ Customizable - Configure separator, max length, case handling, and character replacements
- 🎯 SEO-Optimized - Removes special characters, normalizes whitespace, truncates intelligently
- 📦 Zero Dependencies - Pure TypeScript implementation
- 🌐 Universal - Works in Node.js and browser environments
Usage
Basic Usage
import { generateSlug } from '@bernierllc/slug-generator';
const slug = generateSlug('Hello World!');
// Output: "hello-world"
const blogPost = generateSlug('How to Build a React App in 2025');
// Output: "how-to-build-a-react-app-in-2025"Advanced Usage with Options
import { SlugGenerator } from '@bernierllc/slug-generator';
const generator = new SlugGenerator({
separator: '_',
maxLength: 50,
lowercase: true,
removeDiacritics: true,
strict: true,
replacements: {
'&': 'and',
'@': 'at',
'%': 'percent'
}
});
const result = generator.generate('A & B @ 50% Off!');
// Output: { slug: "a_and_b_at_50_percent_off", modified: true, changes: [...], truncated: false }Unicode and International Characters
import { generateSlug } from '@bernierllc/slug-generator';
// German
generateSlug('Größe und Qualität');
// Output: "grosse-und-qualitat"
// Spanish
generateSlug('Niño en España');
// Output: "nino-en-espana"
// French
generateSlug('Crème brûlée au café');
// Output: "creme-brulee-au-cafe"
// Mixed
generateSlug('Café København Łódź');
// Output: "cafe-kobenhavn-lodz"Collision Handling
import { generateUniqueSlug } from '@bernierllc/slug-generator';
const existing = ['hello-world', 'hello-world-1'];
// Numeric suffix (default)
const slug1 = generateUniqueSlug('Hello World', existing);
// Output: "hello-world-2"
// Random suffix
const generator = new SlugGenerator();
const result = generator.generateUnique('Hello World', {
existing: ['hello-world'],
suffixFormat: 'random'
});
// Output: { slug: "hello-world-a3f9k", ... }
// Timestamp suffix
const result2 = generator.generateUnique('Hello World', {
existing: ['hello-world'],
suffixFormat: 'timestamp'
});
// Output: { slug: "hello-world-l5m2n8p", ... }Validation
import { isValidSlug } from '@bernierllc/slug-generator';
isValidSlug('hello-world'); // true
isValidSlug('hello world'); // false (contains space)
isValidSlug('hello-world!'); // false (contains special char)
isValidSlug(''); // false (empty)API Reference
generateSlug(text: string, options?: SlugOptions): string
Generate a slug from text using default or custom options.
Parameters:
text- Input text to convertoptions- Optional configuration (seeSlugOptions)
Returns: Generated slug string
generateUniqueSlug(text: string, existing: string[], options?: SlugOptions): string
Generate a unique slug by adding suffixes to avoid collisions.
Parameters:
text- Input text to convertexisting- Array of existing slugs to check againstoptions- Optional configuration (seeSlugOptions)
Returns: Unique slug string
isValidSlug(slug: string, options?: SlugOptions): boolean
Validate if a string is a valid slug.
Parameters:
slug- String to validateoptions- Optional configuration (seeSlugOptions)
Returns: true if valid, false otherwise
SlugGenerator
Main class for slug generation with instance-level configuration.
Constructor:
new SlugGenerator(options?: SlugOptions)Methods:
generate(text: string): SlugResult- Generate slug with detailed resultgenerateUnique(text: string, options: CollisionOptions): SlugResult- Generate unique slugisValidSlug(slug: string): boolean- Validate slug format
SlugOptions
Configuration options for slug generation:
interface SlugOptions {
separator?: string; // Default: '-'
lowercase?: boolean; // Default: true
maxLength?: number; // Default: 100
removeDiacritics?: boolean; // Default: true
strict?: boolean; // Default: true (remove all non-alphanumeric)
replacements?: Record<string, string>; // Custom character replacements
}SlugResult
Detailed result from slug generation:
interface SlugResult {
slug: string; // Generated slug
modified: boolean; // Whether original text was changed
changes: string[]; // List of transformations applied
truncated: boolean; // Whether slug was truncated
}CollisionOptions
Options for handling slug collisions:
interface CollisionOptions {
existing: string[]; // Existing slugs to check
suffixFormat?: 'numeric' | 'random' | 'timestamp'; // Default: 'numeric'
maxAttempts?: number; // Default: 100
}Configuration
Environment Variables
This package has no environment variables (pure utility - all configuration via options).
Runtime Configuration
All configuration is passed via constructor or function parameters:
// Instance configuration
const generator = new SlugGenerator({
separator: '_',
maxLength: 80,
replacements: { '&': 'and' }
});
// Per-call configuration
const slug = generateSlug('Hello World', { separator: '_' });Examples
Blog Post Slugs
import { generateSlug } from '@bernierllc/slug-generator';
const posts = [
'How to Build a React App in 2025',
'Top 10 JavaScript Tips & Tricks',
'Understanding TypeScript Generics'
];
const slugs = posts.map(title => generateSlug(title));
// [
// "how-to-build-a-react-app-in-2025",
// "top-10-javascript-tips-tricks",
// "understanding-typescript-generics"
// ]Product URLs
import { SlugGenerator } from '@bernierllc/slug-generator';
const generator = new SlugGenerator({
maxLength: 60,
replacements: {
'&': 'and',
'%': 'percent',
'$': 'dollar'
}
});
const product = 'Nike Air Max 90 - Men\'s Running Shoes - $120';
const result = generator.generate(product);
// { slug: "nike-air-max-90-mens-running-shoes-dollar120", ... }Content Management System
import { SlugGenerator } from '@bernierllc/slug-generator';
class ContentService {
private generator = new SlugGenerator();
async createPost(title: string) {
// Get existing slugs from database
const existingSlugs = await this.getExistingSlugs();
// Generate unique slug
const result = this.generator.generateUnique(title, {
existing: existingSlugs,
suffixFormat: 'numeric'
});
return {
title,
slug: result.slug,
url: `/blog/${result.slug}`
};
}
private async getExistingSlugs(): Promise<string[]> {
// Database query
return ['existing-post', 'another-post'];
}
}E-commerce Categories
import { generateSlug } from '@bernierllc/slug-generator';
const categories = {
'Men\'s Clothing & Accessories': generateSlug('Men\'s Clothing & Accessories'),
'Women\'s Shoes & Boots': generateSlug('Women\'s Shoes & Boots'),
'Electronics & Gadgets': generateSlug('Electronics & Gadgets')
};
// {
// "Men's Clothing & Accessories": "mens-clothing-accessories",
// "Women's Shoes & Boots": "womens-shoes-boots",
// "Electronics & Gadgets": "electronics-gadgets"
// }Integration Status
Logger Integration
Status: Not applicable
Justification: This is a pure utility package with no runtime state, side effects, or error conditions that require logging. The SlugGenerator class is stateless and deterministic - it simply converts strings to URL-friendly slugs. All errors are thrown as exceptions that calling code can handle, and there are no background operations, network calls, or state changes that would benefit from structured logging.
Pattern: Pure functional utility - no logger integration needed.
NeverHub Integration
Status: Not applicable
Justification: This is a core utility package that provides slug generation functionality. It does not participate in service discovery, event publishing, or service mesh operations. It's a stateless utility that can be used by any service or application without requiring service registration or discovery.
Pattern: Core utility - no service mesh integration needed.
Docs-Suite Integration
Status: Ready
Format: TypeDoc-compatible JSDoc comments are included throughout the source code. All public APIs are documented with examples and type information.
Performance
- Typical title (50 chars): <1ms
- Long title (200 chars): <2ms
- Unicode heavy (100 chars): <3ms
- Collision detection (100 existing): <5ms
Browser Support
Works in all modern browsers and Node.js environments:
- Node.js 16+
- Chrome, Firefox, Safari, Edge (latest 2 versions)
License
Copyright (c) 2025 Bernier LLC. All rights reserved.
This file is licensed to the client under a limited-use license. The client may use and modify this code only within the scope of the project it was delivered for. Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
Related Packages
Used By
@bernierllc/content-editor-service- Generates slugs for new content@bernierllc/content-workflow-service- Slug validation and uniqueness@bernierllc/social-publisher- URL generation for published content
Part Of
- Content Management Suite - Blog content workflow and URL generation
Support
For issues, questions, or feature requests, please contact Bernier LLC.
