simple-fs-server/islands/ContentRenderer.tsx

75 lines
2.1 KiB
TypeScript
Raw Permalink Normal View History

2023-01-05 18:18:07 +09:00
import { extname } from "path/posix.ts";
2023-01-06 22:17:45 +09:00
import MarkdownRenderer from "../components/MarkdownRenderer.tsx";
2023-01-05 18:18:07 +09:00
import { useEffect, useState } from "preact/hooks";
const TypeToExt = {
2023-01-06 18:24:27 +09:00
"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"]),
};
2023-01-05 18:18:07 +09:00
function extToType(ext: string) {
2023-01-06 18:24:27 +09:00
for (const [type, exts] of Object.entries(TypeToExt)) {
if (exts.has(ext)) {
return type;
2023-01-05 18:18:07 +09:00
}
2023-01-06 18:24:27 +09:00
}
return "unknown";
2023-01-05 18:18:07 +09:00
}
2023-01-06 18:24:27 +09:00
function FetchAndRender(props: { src: string; type: string }) {
const src = props.src;
const ext = extname(src);
const [content, setContent] = useState("");
useEffect(() => {
2023-01-06 22:17:45 +09:00
(async () => {
const res = await fetch(src);
const content = await res.text();
setContent(content);
})();
2023-01-06 18:24:27 +09:00
}, [src]);
2023-01-06 22:17:45 +09:00
2023-01-06 18:24:27 +09:00
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:
2023-01-06 22:17:45 +09:00
return <p>error: invalid type: {props.type} content: {content}</p>;
2023-01-06 18:24:27 +09:00
}
2023-01-05 18:18:07 +09:00
}
2023-01-14 03:03:58 +09:00
export function RenderView(props: { src: string; mdbase?: string }) {
2023-01-06 18:24:27 +09:00
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:
2023-01-06 22:17:45 +09:00
return <p>error: invalid type: {type} src: {src}</p>;
2023-01-06 18:24:27 +09:00
}
2023-01-05 18:18:07 +09:00
}
export default RenderView;