50 lines
1.5 KiB
JavaScript
50 lines
1.5 KiB
JavaScript
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
import { dirname, resolve } from "node:path";
|
|
|
|
const manifestPath = resolve("dist/client/.vite/manifest.json");
|
|
const outputPath = resolve("dist/client/index.html");
|
|
|
|
const themeBootstrapScript = `
|
|
(() => {
|
|
try {
|
|
const storageKey = "theme";
|
|
const stored = localStorage.getItem(storageKey);
|
|
const theme = stored === "light" || stored === "dark"
|
|
? stored
|
|
: (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light");
|
|
|
|
document.documentElement.setAttribute("data-theme", theme);
|
|
} catch {
|
|
document.documentElement.setAttribute("data-theme", "light");
|
|
}
|
|
})();
|
|
`.trim();
|
|
|
|
const manifest = JSON.parse(await readFile(manifestPath, "utf8"));
|
|
const entry = manifest["src/entry-client.tsx"];
|
|
|
|
if (!entry?.file) {
|
|
throw new Error("Could not find src/entry-client.tsx in the client manifest.");
|
|
}
|
|
|
|
const cssLinks = Array.isArray(entry.css) ? entry.css.map((href) => ` <link rel="stylesheet" href="/${href}">`).join("\n") : "";
|
|
|
|
const html = `<!doctype html>
|
|
<html lang="en" data-theme="light">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<link rel="icon" href="/favicon.ico">
|
|
<script>${themeBootstrapScript}</script>
|
|
${cssLinks}
|
|
</head>
|
|
<body>
|
|
<div id="app"></div>
|
|
<script type="module" src="/${entry.file}"></script>
|
|
</body>
|
|
</html>
|
|
`;
|
|
|
|
await mkdir(dirname(outputPath), { recursive: true });
|
|
await writeFile(outputPath, html, "utf8");
|