// c21 — handler: serves the raw markdown source of an editable doc // page from the main domain. Replaces the previous "view source on // git.tdd.md" link so the docs site doesn't depend on the Forgejo // subdomain for "view source". Reuses c32_edit_resolve so the same // allowlist (sama / guides / blog + safe slug regex) protects both // the editor and the raw view from path traversal. import { resolveEdit } from "./b32_edit_resolve.ts"; import { renderNotFound, htmlResponse } from "./b51_render_layout.ts"; // The route literal is `/content/:section/:filename` and the handler // requires the filename to end in `.md`. We don't use `:slug.md` // because Bun's path parser treats that as a single param literally // named "slug.md", which makes the URL un-typeable. export const rawSourceHandler = async ( req: Request & { params: { section: string; filename: string } }, ): Promise => { const fullPath = `/content/${req.params.section}/${req.params.filename}`; const notFound = async (): Promise => { const html = await renderNotFound(fullPath); return htmlResponse(html, 404); }; if (!req.params.filename.endsWith(".md")) return await notFound(); const slug = req.params.filename.slice(0, -3); const resolved = resolveEdit(req.params.section, slug); if (!resolved) return await notFound(); const file = Bun.file(`./${resolved.filePath}`); if (!(await file.exists())) return await notFound(); // text/plain so browsers render the markdown source inline rather // than offering a download. UTF-8 is fixed because the content/ dir // is UTF-8 throughout (verified by sama-verify). return new Response(await file.text(), { headers: { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "public, max-age=60", }, }); };