103 lines
2.7 KiB
Python
103 lines
2.7 KiB
Python
from __future__ import annotations
|
|
|
|
import mimetypes
|
|
from pathlib import PurePosixPath
|
|
|
|
_MARKDOWN_EXTENSIONS = frozenset({".md", ".markdown", ".mdx"})
|
|
_PDF_EXTENSIONS = frozenset({".pdf"})
|
|
_TEXT_EXTENSIONS = frozenset(
|
|
{
|
|
".txt",
|
|
".text",
|
|
".log",
|
|
".json",
|
|
".jsonl",
|
|
".yaml",
|
|
".yml",
|
|
".toml",
|
|
".ini",
|
|
".cfg",
|
|
".conf",
|
|
".csv",
|
|
".tsv",
|
|
".py",
|
|
".js",
|
|
".ts",
|
|
".jsx",
|
|
".tsx",
|
|
".vue",
|
|
".html",
|
|
".htm",
|
|
".css",
|
|
".less",
|
|
".scss",
|
|
".xml",
|
|
".sql",
|
|
".sh",
|
|
".bash",
|
|
".zsh",
|
|
".fish",
|
|
".env",
|
|
".dockerfile",
|
|
".gitignore",
|
|
".weather",
|
|
}
|
|
)
|
|
_IMAGE_EXTENSIONS = frozenset({".png", ".jpg", ".jpeg", ".gif", ".bmp", ".webp", ".svg"})
|
|
_BINARY_SIGNATURES = (
|
|
b"\x7fELF",
|
|
b"MZ",
|
|
b"%PDF-",
|
|
b"PK\x03\x04",
|
|
b"PK\x05\x06",
|
|
b"PK\x07\x08",
|
|
b"\x89PNG\r\n\x1a\n",
|
|
b"\xff\xd8\xff",
|
|
b"GIF87a",
|
|
b"GIF89a",
|
|
b"RIFF",
|
|
)
|
|
|
|
|
|
def detect_preview_type(path: str, raw_content: bytes) -> tuple[str, bool, str | None]:
|
|
suffix = PurePosixPath(path).suffix.lower()
|
|
mime_type, _encoding = mimetypes.guess_type(path)
|
|
head = raw_content[:1024]
|
|
|
|
if suffix in _IMAGE_EXTENSIONS or (mime_type and mime_type.startswith("image/")):
|
|
return "image", True, None
|
|
|
|
if suffix in _PDF_EXTENSIONS or mime_type == "application/pdf" or head.startswith(b"%PDF-"):
|
|
return "pdf", True, None
|
|
|
|
if suffix in _MARKDOWN_EXTENSIONS:
|
|
return "markdown", True, None
|
|
|
|
if suffix in _TEXT_EXTENSIONS:
|
|
return "text", True, None
|
|
|
|
if b"\x00" in head:
|
|
return "unsupported", False, "当前文件是二进制文件,暂不支持预览"
|
|
|
|
if any(head.startswith(signature) for signature in _BINARY_SIGNATURES):
|
|
if head.startswith(b"RIFF") and b"WEBP" in head[:16]:
|
|
return "image", True, None
|
|
return "unsupported", False, "当前文件格式暂不支持预览"
|
|
|
|
if mime_type:
|
|
if mime_type.startswith("text/"):
|
|
return "text", True, None
|
|
if mime_type in {"application/json", "application/xml", "application/javascript"}:
|
|
return "text", True, None
|
|
if mime_type.startswith("application/"):
|
|
return "unsupported", False, "当前文件格式暂不支持预览"
|
|
|
|
if not raw_content:
|
|
return "text", True, None
|
|
|
|
try:
|
|
raw_content.decode("utf-8")
|
|
return "text", True, None
|
|
except UnicodeDecodeError:
|
|
return "unsupported", False, "当前文件不是可读文本,暂不支持预览"
|