import React, { Fragment } from "react"; import { File, FileArchive, FileAudio, FileCode, FileImage, FileSpreadsheet, FileText, FileVideo, } from "lucide-react"; import { filePathLabel, parseFilePaths } from "@/src/core"; function fileIcon(label: string) { const extension = label.split(".").at(-1)?.toLowerCase(); if (/^(png|jpe?g|gif|webp|svg|bmp|tiff?|avif|heic)$/.test(extension ?? "")) return FileImage; if (/^(mp3|wav|ogg|flac|m4a|aac)$/.test(extension ?? "")) return FileAudio; if (/^(mp4|mov|webm|mkv|avi)$/.test(extension ?? "")) return FileVideo; if (/^(zip|gz|tar|bz2|xz|7z|rar)$/.test(extension ?? "")) return FileArchive; if (/^(csv|tsv|xlsx?|ods)$/.test(extension ?? "")) return FileSpreadsheet; if (/^(js|jsx|ts|tsx|py|rb|rs|go|c|cpp|h|java|json|html|css|sh|yaml|yml)$/.test(extension ?? "")) return FileCode; if (/^(pdf|txt|md|mdx|rtf|docx?|odt|tex|epub)$/.test(extension ?? "")) return FileText; return File; } export interface FilePathChipProps { path: string; /** Editors can make the chip atomic; transcript renderers can omit this. */ contentEditable?: false; className?: string; } /** Pure presentation: no links, open actions, HTML injection or path probing. */ export function FilePathChip({ path, contentEditable, className }: FilePathChipProps) { const label = filePathLabel(path); const Icon = fileIcon(label); return ( ); } /** Ordinary learner text stays ordinary text; only quoted paths become chips. */ export function PathText({ text }: { text: string }) { return ( <> {parseFilePaths(text).map((part) => ( {part.kind === "path" ? : part.text} ))} ); }