53 lines
1.4 KiB
TypeScript
53 lines
1.4 KiB
TypeScript
export function sanitizeFilenameSegment(value: string | null | undefined, fallback = ''): string {
|
|
if (typeof value !== 'string') {
|
|
return fallback;
|
|
}
|
|
|
|
const normalized = value
|
|
.trim()
|
|
.normalize('NFKD')
|
|
.replace(/[\u0300-\u036f]/g, '');
|
|
|
|
const slug = normalized.replace(/[^A-Za-z0-9]+/g, '-').replace(/^-+|-+$/g, '').toLowerCase();
|
|
|
|
return slug.length ? slug : fallback;
|
|
}
|
|
|
|
export function normalizeEventDateSegment(dateValue: string | null | undefined): string | null {
|
|
if (!dateValue) {
|
|
return null;
|
|
}
|
|
|
|
const trimmed = dateValue.trim();
|
|
if (!trimmed) {
|
|
return null;
|
|
}
|
|
|
|
const isoCandidate = trimmed.slice(0, 10);
|
|
if (/^\d{4}-\d{2}-\d{2}$/.test(isoCandidate)) {
|
|
return isoCandidate;
|
|
}
|
|
|
|
const parsed = new Date(trimmed);
|
|
if (Number.isNaN(parsed.getTime())) {
|
|
return null;
|
|
}
|
|
|
|
return parsed.toISOString().slice(0, 10);
|
|
}
|
|
|
|
export function buildDownloadFilename(
|
|
parts: Array<string | null | undefined>,
|
|
extension: string,
|
|
fallback = 'download',
|
|
): string {
|
|
const sanitizedParts = parts
|
|
.map((part) => sanitizeFilenameSegment(part, ''))
|
|
.filter((segment) => segment.length > 0);
|
|
|
|
const base = sanitizedParts.length ? sanitizedParts.join('-') : fallback;
|
|
const cleanExtension = sanitizeFilenameSegment(extension, '').replace(/[^a-z0-9]/gi, '') || 'bin';
|
|
|
|
return `${base}.${cleanExtension.toLowerCase()}`;
|
|
}
|