initial commit
This commit is contained in:
45
lib/files.ts
Normal file
45
lib/files.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { readFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { PUBLIC_DIR, REPO_DIR, safeJoin } from "./paths";
|
||||
|
||||
/* Read-only file serving from the portfolio checkout, so the preview iframe
|
||||
* can load the site's real stylesheets and the post's images. */
|
||||
|
||||
const TYPES: Record<string, string> = {
|
||||
".css": "text/css; charset=utf-8",
|
||||
".png": "image/png",
|
||||
".jpg": "image/jpeg",
|
||||
".jpeg": "image/jpeg",
|
||||
".gif": "image/gif",
|
||||
".webp": "image/webp",
|
||||
".svg": "image/svg+xml",
|
||||
".ico": "image/x-icon",
|
||||
".mp4": "video/mp4",
|
||||
};
|
||||
|
||||
/** Stylesheets the preview may load, keyed by their /site/... path. */
|
||||
const SITE_CSS = new Set(["app/globals.css", "styles/markdown-container.css", "styles/blog.css"]);
|
||||
|
||||
async function send(file: string): Promise<Response> {
|
||||
const type = TYPES[path.extname(file).toLowerCase()];
|
||||
if (!type) return new Response("not found", { status: 404 });
|
||||
try {
|
||||
const body = await readFile(file);
|
||||
return new Response(new Uint8Array(body), {
|
||||
headers: { "content-type": type, "cache-control": "no-cache" },
|
||||
});
|
||||
} catch {
|
||||
return new Response("not found", { status: 404 });
|
||||
}
|
||||
}
|
||||
|
||||
/** /site/<css allowlist> -> repo file; /site/<anything else> -> repo public/. */
|
||||
export function serveSitePath(segments: string[]): Promise<Response> {
|
||||
const rel = segments.join("/");
|
||||
if (SITE_CSS.has(rel)) return send(path.join(REPO_DIR, rel));
|
||||
return send(safeJoin(PUBLIC_DIR, ...segments));
|
||||
}
|
||||
|
||||
export function servePublic(segments: string[]): Promise<Response> {
|
||||
return send(safeJoin(PUBLIC_DIR, ...segments));
|
||||
}
|
||||
Reference in New Issue
Block a user