| 14 | 20 | | // `Vary: Accept` is required so HTML caches don't poison Markdown responses. |
| 15 | 21 | | // Browsers don't list `text/markdown` in their Accept header, so they never |
| 16 | 22 | | // hit this branch and continue to receive HTML. |
| 23 | + | // |
| 24 | + | // Strategy: read the pre-rendered `.md` sibling of the requested URL and |
| 25 | + | // return its body. This works on every runtime because every adapter ships |
| 26 | + | // `<path>.md` as a static asset — using a static-asset read (rather than |
| 27 | + | // rewriting to the dynamic `/md/[...slug]` route) avoids the route's |
| 28 | + | // `readFile` path, which is unavailable in workerd / Cloudflare Workers. |
| 29 | + | // On Cloudflare we read via the `ASSETS` binding directly; on Node-based |
| 30 | + | // adapters we sub-fetch the same origin so the in-process static handler |
| 31 | + | // answers. |
| 17 | 32 | | // --------------------------------------------------------------------------- |
| 18 | 33 | | |
| 19 | | - | export default function ContentNegotiation() { |
| 20 | | - | const { pathname } = useUrl(); |
| 34 | + | export default async function ContentNegotiation() { |
| 35 | + | const url = useUrl(); |
| 36 | + | const { pathname } = url; |
| 37 | + | |
| 38 | + | // Already inside the dynamic markdown handler — leave it alone. |
| 39 | + | if (pathname.startsWith("/md/")) { |
| 40 | + | return; |
| 41 | + | } |
| 21 | 42 | | |
| 22 | | - | // Skip URLs that already target the markdown route or have a `.md` suffix — |
| 23 | | - | // those go through the existing /md/ handler. |
| 24 | | - | if (pathname.startsWith("/md/") || pathname.endsWith(".md")) { |
| 43 | + | // Explicit `.md` URLs route through the dynamic `/md/[...slug]` handler. |
| 44 | + | // Build-time pre-rendering relies on this rewrite to capture each page's |
| 45 | + | // markdown into a static asset; without it the export step writes empty |
| 46 | + | // files. At runtime the rewritten path only fires when no static `.md` |
| 47 | + | // sibling matched (e.g. dev server, or a brand-new page) — Cloudflare |
| 48 | + | // Assets / the in-process static handler still serve the pre-rendered |
| 49 | + | // file directly. |
| 50 | + | if (pathname.endsWith(".md")) { |
| 51 | + | const mdPath = pathname.replace(/\.md$/, ""); |
| 52 | + | rewrite(`/md${mdPath}`); |
| 25 | 53 | | return; |
| 26 | 54 | | } |
| 27 | 55 | | |