/* * Turns the SPA build into real static files. * * Without this, GitHub Pages has no file at /install and answers a direct * link with its 404 page. Writing one HTML file per route means every URL * returns 200 with its own title, description, and fully rendered body; the * client then hydrates it into the same interactive app. * * Run after both `vite build` and `vite build --ssr`. */ import { mkdir, readFile, writeFile } from 'node:fs/promises' import { dirname, join } from 'node:path' import { NOT_FOUND_META, ROUTES, type RouteMeta } from '../src/lib/routes.ts' /* * Held in a variable so TypeScript does not try to resolve it: the module is * a build artefact, and `bun run typecheck` runs before `vite build --ssr` * has produced it. The cast is the contract with src/entry-server.tsx. */ const SSR_ENTRY = '../dist-ssr/entry-server.js' const { render } = (await import(SSR_ENTRY)) as { render: (location: string) => string } const DIST = join(import.meta.dirname, '..', 'dist') const SITE_URL = 'https://re-invention.nl/soulseek-rs/' const escapeAttr = (value: string): string => value.replace(/&/g, '&').replace(/"/g, '"').replace(/` matched by attribute and value. */ const setMeta = (html: string, attr: string, name: string, value: string): string => html.replace( new RegExp(`( { const canonical = meta.path === '/' ? SITE_URL : `${SITE_URL}${meta.path.slice(1)}/` let out = html.replace( /