Ship file viewer, editor improvements, and private package releases

This commit is contained in:
Clintchiz committed 2026-09-09 11:20:11 +05:30
1 parent 645914955c
commit a4a31032b9
158 files changed
+10523 -137

No files matched your search

+68
View File
@@ -0,0 +1,68 @@
import type { ViewerKind } from "./types.ts";
/** Kind classification only; MIME ownership remains with uploader. */
export const extensions: Record<ViewerKind, readonly string[]> = {
image: ["jpg", "jpeg", "png", "gif", "webp", "bmp", "ico", "avif"],
vector: ["svg"],
pdf: ["pdf"],
code: [
"js",
"jsx",
"ts",
"tsx",
"py",
"java",
"cpp",
"c",
"h",
"cs",
"css",
"json",
"xml",
"sql",
"sh",
"yaml",
"yml",
],
text: ["txt", "md", "log"],
markup: ["html", "htm"],
sheet: ["csv", "tsv", "xls", "xlsx", "ods"],
doc: ["doc", "docx", "dotx", "odt", "rtf", "ppt", "pptx", "ppsx", "potx", "odp"],
audio: ["mp3", "wav", "aac", "flac", "ogg"],
video: ["mp4", "webm", "mov", "avi", "mkv"],
archive: ["zip", "rar", "7z", "tar", "gz", "tgz"],
binary: ["psd", "ai", "tif", "tiff", "exe", "dll"],
};
export function extensionOf(name: string): string {
const base = (name.split(/[?#]/)[0] ?? "").split(/[/\\]/).pop() ?? "";
const dot = base.lastIndexOf(".");
return dot < 0 ? "" : base.slice(dot).toLowerCase();
}
export function kindOfExtension(ext: string): ViewerKind {
return (
(Object.keys(extensions) as ViewerKind[]).find((kind) =>
extensions[kind].includes(ext.replace(/^\./, "").toLowerCase()),
) ?? "binary"
);
}
export function kindOfMime(mime: string): ViewerKind | undefined {
const type = mime.split(";")[0]!.trim().toLowerCase();
if (type === "image/svg+xml") return "vector";
if (type === "text/html" || type === "application/xhtml+xml") return "markup";
if (type === "application/pdf") return "pdf";
if (/^(application|text)\/(json|xml|javascript|x-javascript)$/.test(type) || type === "text/css")
return "code";
if (/^text\/(csv|tab-separated-values)$/.test(type) || /spreadsheet|ms-excel/.test(type))
return "sheet";
if (/opendocument\.spreadsheet/.test(type)) return "sheet";
if (/msword|wordprocessing|presentation|powerpoint|opendocument|rtf/.test(type)) return "doc";
if (/zip|gzip|x-tar|x-7z|rar/.test(type)) return "archive";
if (/^image\/(png|jpeg|gif|webp|bmp|x-icon|vnd.microsoft.icon|avif)$/.test(type)) return "image";
if (type.startsWith("audio/")) return "audio";
if (type.startsWith("video/")) return "video";
if (type.startsWith("text/")) return "text";
return undefined;
}