Files
tolaria/src/utils/notePathIdentity.ts
2026-05-04 04:59:50 +02:00

68 lines
2.5 KiB
TypeScript

export type NotePath = string
export type VaultPath = string
export type VaultRelativePath = string
type PathLike = NotePath | null | undefined
type ItemWithNotePath = { path: NotePath }
function stripWindowsExtendedPathPrefix(path: NotePath): NotePath {
return path
.replace(/^\\\\\?\\UNC\\/iu, '//')
.replace(/^\\\\\?\\/u, '')
}
export function normalizeNotePathSeparators(path: NotePath): NotePath {
return stripWindowsExtendedPathPrefix(path).replaceAll('\\', '/')
}
export function normalizeNotePathForIdentity(path: NotePath): NotePath {
return normalizeNotePathSeparators(path)
.replace(/^\/private\/tmp(?=\/|$)/u, '/tmp')
.replace(/\/+$/u, '')
}
export function normalizeNotePathForCollision(path: NotePath): NotePath {
return normalizeNotePathForIdentity(path).toLocaleLowerCase()
}
export function notePathsMatch(leftPath: PathLike, rightPath: PathLike): boolean {
if (!leftPath || !rightPath) return false
return normalizeNotePathForIdentity(leftPath) === normalizeNotePathForIdentity(rightPath)
}
export function notePathsCollide(leftPath: PathLike, rightPath: PathLike): boolean {
if (!leftPath || !rightPath) return false
return normalizeNotePathForCollision(leftPath) === normalizeNotePathForCollision(rightPath)
}
export function findByNotePath<T extends ItemWithNotePath>(items: T[], path: PathLike): T | undefined {
if (!path) return undefined
return items.find((item) => notePathsMatch(item.path, path))
}
export function findByCollidingNotePath<T extends ItemWithNotePath>(items: T[], path: PathLike): T | undefined {
if (!path) return undefined
return items.find((item) => notePathsCollide(item.path, path))
}
export function notePathFilename(path: NotePath): string {
const normalized = normalizeNotePathSeparators(path).replace(/\/+$/u, '')
return normalized.split('/').filter(Boolean).at(-1) ?? normalized
}
export function normalizeVaultRelativePath(path: VaultRelativePath): VaultRelativePath {
return normalizeNotePathSeparators(path.trim()).replace(/^\/+|\/+$/gu, '')
}
export function vaultRelativePathLabel(path: VaultRelativePath): string {
const normalized = normalizeVaultRelativePath(path)
return normalized.split('/').filter(Boolean).at(-1) ?? normalized
}
export function joinVaultPath(vaultPath: VaultPath, relativePath: VaultRelativePath): NotePath {
const root = vaultPath.replace(/[\\/]+$/u, '') || '/'
const child = normalizeVaultRelativePath(relativePath)
if (!child) return root
return root === '/' ? `/${child}` : `${root}/${child}`
}