66 lines
2.1 KiB
TypeScript
66 lines
2.1 KiB
TypeScript
|
import { extname } from "path/posix.ts";
|
||
|
import MarkdownRenderer from "./MarkdownRenderer.tsx";
|
||
|
import { useEffect, useState } from "preact/hooks";
|
||
|
|
||
|
const TypeToExt = {
|
||
|
"image": new Set([".png", ".jpg", ".jpeg", ".gif", ".svg"]),
|
||
|
"video": new Set([".mp4", ".webm", ".ogg"]),
|
||
|
"audio": new Set([".mp3", ".wav", ".flac"]),
|
||
|
"md": new Set([".md"]),
|
||
|
"text": new Set([".txt"]),
|
||
|
"code": new Set([".json", ".js", ".ts", ".css", ".tsx", ".jsx"]),
|
||
|
}
|
||
|
|
||
|
function extToType(ext: string) {
|
||
|
for (const [type, exts] of Object.entries(TypeToExt)) {
|
||
|
if (exts.has(ext)) {
|
||
|
return type;
|
||
|
}
|
||
|
}
|
||
|
return "unknown";
|
||
|
}
|
||
|
|
||
|
function FetchAndRender(props: {src: string, type: string}){
|
||
|
const src = props.src;
|
||
|
const ext = extname(src);
|
||
|
const [content, setContent] = useState("");
|
||
|
useEffect(() => {
|
||
|
fetch(src).then(res => res.text()).then(setContent);
|
||
|
}, [src]);
|
||
|
switch (props.type) {
|
||
|
case "text":
|
||
|
return <div style={{ whiteSpace: "pre-wrap" }}>{content}</div>;
|
||
|
case "md":
|
||
|
return <MarkdownRenderer text={content} />;
|
||
|
case "code":
|
||
|
return <pre style={{ whiteSpace: "pre-wrap" }}><code lang={ext.slice(1)}>{content}</code></pre>;
|
||
|
//case "csv":
|
||
|
// return <CsvRenderer content={content} />;
|
||
|
default:
|
||
|
return <>error: invalid type: {props.type} content: {content}</>;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export function RenderView(props: {src: string}) {
|
||
|
const src = props.src;
|
||
|
const type = extToType(extname(src));
|
||
|
switch (type) {
|
||
|
case "text":
|
||
|
case "md":
|
||
|
case "code":
|
||
|
return <FetchAndRender src={src} type={type}></FetchAndRender>
|
||
|
//case "csv":
|
||
|
// return <CsvRenderer content={content} />;
|
||
|
case "image":
|
||
|
return <img style={{ width: "100%" }} src={src} />;
|
||
|
case "video":
|
||
|
return <video style={{ width: "100%" }} controls src={src} />;
|
||
|
case "audio":
|
||
|
return <audio style={{ width: "100%" }} controls src={src} />;
|
||
|
default:
|
||
|
return <>error: invalid type: {type} src: {src}</>;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export default RenderView;
|