Saltar al contenido principal

stringToSlug

Paquete: @tiendana/utils

Convierte un string a formato URL-friendly (slug), removiendo acentos, caracteres especiales y espacios, reemplazándolos por guiones.

Características​

✅ Convierte a minúsculas
✅ Remueve acentos y diacríticos
✅ Elimina caracteres especiales
✅ Reemplaza espacios por guiones
✅ Normaliza guiones múltiples
✅ Maneja ñ, ç y caracteres latinos

Firma​

function stringToSlug(str: string): string

Parámetros​

ParámetroTipoDescripciónRequerido
strstringString a convertir en slug✅

Retorno​

Tipo: string

String en formato slug: minúsculas, sin acentos, sin caracteres especiales, con guiones en lugar de espacios.

Ejemplos de Uso​

Conversión Básica​

import { stringToSlug } from '@tiendana/utils';

stringToSlug('Hola Mundo');
// 'hola-mundo'

stringToSlug('¡Título con Acentos!');
// 'titulo-con-acentos'

stringToSlug('España & Portugal');
// 'espana-portugal'

URLs de Blog​

interface BlogPost {
title: string;
content: string;
}

function createBlogUrl(post: BlogPost): string {
const slug = stringToSlug(post.title);
return `/blog/${slug}`;
}

createBlogUrl({ title: 'Las Mejores Prácticas de TypeScript', content: '...' });
// '/blog/las-mejores-practicas-de-typescript'

URLs de Productos​

interface Product {
id: number;
name: string;
}

function getProductUrl(product: Product): string {
const slug = stringToSlug(product.name);
return `/productos/${product.id}/${slug}`;
}

getProductUrl({ id: 123, name: 'Computadora Portátil HP 15"' });
// '/productos/123/computadora-portatil-hp-15'

Categorías​

const categories = [
'Tecnología & Innovación',
'Salud y Bienestar',
'Deportes/Recreación'
];

const categoryUrls = categories.map(cat => ({
name: cat,
slug: stringToSlug(cat),
url: `/categorias/${stringToSlug(cat)}`
}));

// [
// { name: 'Tecnología & Innovación', slug: 'tecnologia-innovacion', url: '/categorias/tecnologia-innovacion' },
// { name: 'Salud y Bienestar', slug: 'salud-y-bienestar', url: '/categorias/salud-y-bienestar' },
// { name: 'Deportes/Recreación', slug: 'deportes-recreacion', url: '/categorias/deportes-recreacion' }
// ]

Nombres de Archivo​

function generateFileName(userTitle: string, extension: string): string {
const slug = stringToSlug(userTitle);
const timestamp = Date.now();
return `${slug}-${timestamp}.${extension}`;
}

generateFileName('Mi Reporte Anual 2024', 'pdf');
// 'mi-reporte-anual-2024-1701234567890.pdf'

Tags/Etiquetas​

interface Tag {
name: string;
slug: string;
}

function createTag(name: string): Tag {
return {
name,
slug: stringToSlug(name)
};
}

const tags = [
'JavaScript',
'Diseño UI/UX',
'Marketing Digital'
].map(createTag);

// [
// { name: 'JavaScript', slug: 'javascript' },
// { name: 'Diseño UI/UX', slug: 'diseno-ui-ux' },
// { name: 'Marketing Digital', slug: 'marketing-digital' }
// ]

SEO Friendly URLs​

interface Article {
id: string;
title: string;
category: string;
publishDate: Date;
}

function generateSeoUrl(article: Article): string {
const titleSlug = stringToSlug(article.title);
const categorySlug = stringToSlug(article.category);
const year = article.publishDate.getFullYear();
const month = String(article.publishDate.getMonth() + 1).padStart(2, '0');

return `/${categorySlug}/${year}/${month}/${titleSlug}`;
}

generateSeoUrl({
id: '123',
title: 'Guía Completa de React Hooks',
category: 'Programación Web',
publishDate: new Date('2024-03-15')
});
// '/programacion-web/2024/03/guia-completa-de-react-hooks'

Rutas de API​

function generateApiEndpoint(resourceType: string, action: string): string {
const typeSlug = stringToSlug(resourceType);
const actionSlug = stringToSlug(action);

return `/api/v1/${typeSlug}/${actionSlug}`;
}

generateApiEndpoint('User Profiles', 'Get All Active');
// '/api/v1/user-profiles/get-all-active'

Directorios​

function createProjectDirectory(projectName: string): string {
const slug = stringToSlug(projectName);
return `./projects/${slug}`;
}

createProjectDirectory('Mi Nuevo Proyecto 2024');
// './projects/mi-nuevo-proyecto-2024'

Casos de Uso Comunes​

  • URLs de contenido: Blog posts, artículos, páginas
  • URLs de productos: E-commerce, catálogos
  • SEO: URLs amigables para buscadores
  • Nombres de archivo: Archivos generados dinámicamente
  • Rutas de API: Endpoints descriptivos
  • Tags y categorías: Navegación por etiquetas
  • Directorios: Nombres de carpetas sin espacios ni caracteres especiales

Transformaciones​

La función aplica las siguientes transformaciones en orden:

  1. Trim: Elimina espacios al inicio y final
  2. Lowercase: Convierte todo a minúsculas
  3. Normalize: Normaliza caracteres Unicode (NFD)
  4. Replace accents: Reemplaza acentos por caracteres base
    • àáäâ → a
    • èéëê → e
    • ñ → n
    • ç → c
    • · / _ , : ; → -
  5. Remove invalid chars: Elimina caracteres no alfanuméricos (excepto espacios y guiones)
  6. Remove combining marks: Elimina marcas diacríticas combinadas
  7. Collapse whitespace: Reemplaza espacios por guiones
  8. Collapse dashes: Normaliza guiones múltiples a uno solo

Notas Técnicas​

  • Normalización Unicode: Usa normalize('NFD') para descomponer caracteres
  • Regex performance: Usa múltiples regex para transformaciones específicas
  • Lowercase primero: Convierte a minúsculas antes de normalizar
  • Guiones finales: No elimina guiones al inicio/final (considera agregar .trim() al resultado)
  • Inmutabilidad: No modifica el string original

Limitaciones​

Guiones al inicio/final

La función no elimina guiones al inicio o final del resultado:

stringToSlug('  - Título - ');
// '-titulo-'

Para eliminarlos:

function cleanSlug(str: string): string {
return stringToSlug(str).replace(/^-+|-+$/g, '');
}

Implementación​

export function stringToSlug(str: string): string {
str = str.replace(/^\s+|\s+$/g, ''); // trim
str = str.toLowerCase().trim().normalize('NFD');

// remove accents, swap ñ for n, etc
const from = 'àáäâèéëêìíïîòóöôùúüûñç·/_,:;';
const to = 'aaaaeeeeiiiioooouuuunc------';
for (let i = 0, l = from.length; i < l; i++) {
str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
}

str = str.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
.replace(/[\u0300-\u036f]/g, '') // remove combining marks
.replace(/\s+/g, '-') // collapse whitespace and replace by -
.replace(/-+/g, '-'); // collapse dashes

return str;
}

Ver También​