Files
tolaria/src/utils/viewFilename.ts
2026-04-28 05:39:41 +02:00

60 lines
1.3 KiB
TypeScript

const VIEW_FILENAME_EXTENSION = '.yml'
const FALLBACK_VIEW_FILENAME_STEM = 'view'
const WINDOWS_RESERVED_DEVICE_NAMES = new Set([
'CON',
'PRN',
'AUX',
'NUL',
'COM1',
'COM2',
'COM3',
'COM4',
'COM5',
'COM6',
'COM7',
'COM8',
'COM9',
'LPT1',
'LPT2',
'LPT3',
'LPT4',
'LPT5',
'LPT6',
'LPT7',
'LPT8',
'LPT9',
])
export function slugifyViewFilenameStem(name: string): string {
const stem = name
.normalize('NFKC')
.toLocaleLowerCase()
.trim()
.replace(/[^\p{Letter}\p{Number}]+/gu, '-')
.replace(/(^-+|-+$)/g, '')
return avoidReservedDeviceName(stem || FALLBACK_VIEW_FILENAME_STEM)
}
export function createViewFilename(name: string, existingFilenames: string[] = []): string {
const baseStem = slugifyViewFilenameStem(name)
const usedFilenames = new Set(existingFilenames.map((filename) => filename.toLocaleLowerCase()))
let candidateStem = baseStem
let suffix = 2
while (usedFilenames.has(filenameFromStem(candidateStem).toLocaleLowerCase())) {
candidateStem = `${baseStem}-${suffix}`
suffix += 1
}
return filenameFromStem(candidateStem)
}
function filenameFromStem(stem: string): string {
return `${stem}${VIEW_FILENAME_EXTENSION}`
}
function avoidReservedDeviceName(stem: string): string {
return WINDOWS_RESERVED_DEVICE_NAMES.has(stem.toLocaleUpperCase()) ? `${stem}-view` : stem
}