mirror of
https://github.com/anomalyco/opencode.git
synced 2026-04-24 23:04:55 +00:00
120 lines
2.4 KiB
TypeScript
120 lines
2.4 KiB
TypeScript
export const ACCEPTED_IMAGE_TYPES = ["image/png", "image/jpeg", "image/gif", "image/webp"]
|
|
|
|
const IMAGE_MIMES = new Set(ACCEPTED_IMAGE_TYPES)
|
|
const IMAGE_EXTS = new Map([
|
|
["gif", "image/gif"],
|
|
["jpeg", "image/jpeg"],
|
|
["jpg", "image/jpeg"],
|
|
["png", "image/png"],
|
|
["webp", "image/webp"],
|
|
])
|
|
const TEXT_MIMES = new Set([
|
|
"application/json",
|
|
"application/ld+json",
|
|
"application/toml",
|
|
"application/x-toml",
|
|
"application/x-yaml",
|
|
"application/xml",
|
|
"application/yaml",
|
|
])
|
|
|
|
export const ACCEPTED_FILE_TYPES = [
|
|
...ACCEPTED_IMAGE_TYPES,
|
|
"application/pdf",
|
|
"text/*",
|
|
"application/json",
|
|
"application/ld+json",
|
|
"application/toml",
|
|
"application/x-toml",
|
|
"application/x-yaml",
|
|
"application/xml",
|
|
"application/yaml",
|
|
".c",
|
|
".cc",
|
|
".cjs",
|
|
".conf",
|
|
".cpp",
|
|
".css",
|
|
".csv",
|
|
".cts",
|
|
".env",
|
|
".go",
|
|
".gql",
|
|
".graphql",
|
|
".h",
|
|
".hh",
|
|
".hpp",
|
|
".htm",
|
|
".html",
|
|
".ini",
|
|
".java",
|
|
".js",
|
|
".json",
|
|
".jsx",
|
|
".log",
|
|
".md",
|
|
".mdx",
|
|
".mjs",
|
|
".mts",
|
|
".py",
|
|
".rb",
|
|
".rs",
|
|
".sass",
|
|
".scss",
|
|
".sh",
|
|
".sql",
|
|
".toml",
|
|
".ts",
|
|
".tsx",
|
|
".txt",
|
|
".xml",
|
|
".yaml",
|
|
".yml",
|
|
".zsh",
|
|
]
|
|
|
|
const SAMPLE = 4096
|
|
|
|
function kind(type: string) {
|
|
return type.split(";", 1)[0]?.trim().toLowerCase() ?? ""
|
|
}
|
|
|
|
function ext(name: string) {
|
|
const idx = name.lastIndexOf(".")
|
|
if (idx === -1) return ""
|
|
return name.slice(idx + 1).toLowerCase()
|
|
}
|
|
|
|
function textMime(type: string) {
|
|
if (!type) return false
|
|
if (type.startsWith("text/")) return true
|
|
if (TEXT_MIMES.has(type)) return true
|
|
if (type.endsWith("+json")) return true
|
|
return type.endsWith("+xml")
|
|
}
|
|
|
|
function textBytes(bytes: Uint8Array) {
|
|
if (bytes.length === 0) return true
|
|
let count = 0
|
|
for (const byte of bytes) {
|
|
if (byte === 0) return false
|
|
if (byte < 9 || (byte > 13 && byte < 32)) count += 1
|
|
}
|
|
return count / bytes.length <= 0.3
|
|
}
|
|
|
|
export async function attachmentMime(file: File) {
|
|
const type = kind(file.type)
|
|
if (IMAGE_MIMES.has(type)) return type
|
|
if (type === "application/pdf") return type
|
|
|
|
const suffix = ext(file.name)
|
|
const fallback = IMAGE_EXTS.get(suffix) ?? (suffix === "pdf" ? "application/pdf" : undefined)
|
|
if ((!type || type === "application/octet-stream") && fallback) return fallback
|
|
|
|
if (textMime(type)) return "text/plain"
|
|
const bytes = new Uint8Array(await file.slice(0, SAMPLE).arrayBuffer())
|
|
if (!textBytes(bytes)) return
|
|
return "text/plain"
|
|
}
|