Files
mes-budgets-participatifs/src/lib/utils.ts

106 lines
3.0 KiB
TypeScript

import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
/**
* Traite le message du footer en remplaçant [LINK] par le lien vers le repository
*/
export function processFooterMessage(message: string, repositoryUrl: string): string {
return message.replace(/\[LINK\]/g, repositoryUrl);
}
/**
* Traite le message du footer et retourne le texte avec les liens Markdown remplacés
*/
export function parseFooterMessage(message: string, repositoryUrl: string): { text: string; links: Array<{ text: string; url: string; start: number; end: number }> } {
const links: Array<{ text: string; url: string; start: number; end: number }> = [];
let processedText = message;
// Remplacer [texte](GITURL) par le texte du lien
const linkRegex = /\[([^\]]+)\]\(GITURL\)/g;
let match;
let offset = 0;
while ((match = linkRegex.exec(message)) !== null) {
const linkText = match[1]; // Le texte entre crochets
const fullMatch = match[0]; // Le match complet [texte](GITURL)
const start = match.index + offset;
const end = start + linkText.length;
links.push({
text: linkText,
url: repositoryUrl,
start,
end
});
processedText = processedText.replace(fullMatch, linkText);
offset += linkText.length - fullMatch.length;
}
return { text: processedText, links };
}
/**
* Génère un slug à partir d'un titre
*/
export function generateSlug(title: string): string {
return title
.toLowerCase()
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '') // Supprime les accents
.replace(/[^a-z0-9\s-]/g, '') // Garde seulement lettres, chiffres, espaces et tirets
.replace(/\s+/g, '-') // Remplace les espaces par des tirets
.replace(/-+/g, '-') // Remplace les tirets multiples par un seul
.trim();
}
/**
* Génère un ID court aléatoire
*/
export function generateShortId(): string {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
let result = '';
for (let i = 0; i < 8; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
/**
* Formate un montant en euros
*/
export function formatCurrency(amount: number): string {
return new Intl.NumberFormat('fr-FR', {
style: 'currency',
currency: 'EUR',
}).format(amount);
}
/**
* Formate une date
*/
export function formatDate(date: Date | string): string {
const dateObj = typeof date === 'string' ? new Date(date) : date;
return dateObj.toLocaleDateString('fr-FR');
}
/**
* Valide une adresse email
*/
export function validateEmail(email: string): boolean {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
/**
* Nettoie le HTML pour éviter les attaques XSS
*/
export function sanitizeHtml(html: string): string {
// Supprime les balises dangereuses
return html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
}