import catppuccinIcons from "@iconify-json/catppuccin/icons.json"; import { EXT_TO_LANGUAGE_ID } from "./constants"; import * as fileIconsMod from "./fileIcons"; import * as folderIconsMod from "./folderIcons"; const catFileNames = fileIconsMod.fileNames as Record; const catFileExtensions = fileIconsMod.fileExtensions as Record; const catLanguageIds = fileIconsMod.languageIds as Record; const catFolderNames = folderIconsMod.folderNames as Record; type IconifySet = { icons: Record; aliases?: Record; width?: number; height?: number; }; const cat = catppuccinIcons as unknown as IconifySet; const CAT_W = cat.width ?? 16; const CAT_H = cat.height ?? 16; const DEFAULT_FILE = "file"; const DEFAULT_FOLDER = "folder"; const DEFAULT_FOLDER_OPEN = "folder-open"; const dataUrlCache = new Map(); // Catppuccin's manifest emits names like `folder_src`/`typescript-react`, but // the iconify export normalizes everything to hyphenated slugs. function toIconifySlug(name: string): string { return name.replace(/_/g, "-"); } function catBody(iconName: string): string | null { const slug = toIconifySlug(iconName); const direct = cat.icons[slug]; if (direct) return direct.body; const alias = cat.aliases?.[slug]; if (alias) { const parent = cat.icons[alias.parent]; if (parent) return parent.body; } return null; } function buildDataUrl(iconName: string): string | null { const cached = dataUrlCache.get(iconName); if (cached !== undefined) return cached || null; const body = catBody(iconName); if (!body) { dataUrlCache.set(iconName, ""); return null; } const svg = `${body}`; const url = `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`; dataUrlCache.set(iconName, url); return url; } function extOf(name: string): string { const lower = name.toLowerCase(); const dot = lower.indexOf("."); if (dot === -1 || dot === lower.length - 1) return ""; return lower.slice(dot + 1); } export function fileIconUrl(name: string): string { const lower = name.toLowerCase(); const byName = catFileNames[lower]; if (byName) { const url = buildDataUrl(byName); if (url) return url; } let ext = extOf(lower); while (ext) { const iconName = catFileExtensions[ext]; if (iconName) { const url = buildDataUrl(iconName); if (url) return url; } const langId = EXT_TO_LANGUAGE_ID[ext]; if (langId) { const iconByLang = catLanguageIds[langId]; if (iconByLang) { const url = buildDataUrl(iconByLang); if (url) return url; } } const nextDot = ext.indexOf("."); if (nextDot === -1) break; ext = ext.slice(nextDot + 1); } return buildDataUrl(DEFAULT_FILE) ?? ""; } export function folderIconUrl(name: string, expanded: boolean): string { const lower = name.toLowerCase(); const mapped = catFolderNames[lower]; if (mapped) { const slug = toIconifySlug(mapped); const target = expanded ? `${slug}-open` : slug; const url = buildDataUrl(target); if (url) return url; } return buildDataUrl(expanded ? DEFAULT_FOLDER_OPEN : DEFAULT_FOLDER) ?? ""; }