All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 44s
96 lines
2.7 KiB
TypeScript
96 lines
2.7 KiB
TypeScript
import { defineConfig, type Plugin } from "vite";
|
|
import react from "@vitejs/plugin-react-swc";
|
|
import { lingui } from "@lingui/vite-plugin";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
|
|
const SITE_NAME = process.env.GERBEUR_SITE_NAME || "gerbeur";
|
|
|
|
function manifestPlugin(): Plugin {
|
|
const cssPath = path.resolve("src/index.css");
|
|
const outPath = path.resolve("public/manifest.webmanifest");
|
|
|
|
function cssVar(rootBlock: string, name: string): string | undefined {
|
|
return rootBlock.match(
|
|
new RegExp(`${name.replace("-", "\\-")}:\\s*(#[0-9a-fA-F]{3,8})`),
|
|
)?.[1];
|
|
}
|
|
|
|
function generate() {
|
|
const css = fs.readFileSync(cssPath, "utf-8");
|
|
// Only read the first :root block — dark-mode defaults, before any @media overrides
|
|
const rootBlock = css.match(/:root\s*\{([^}]+)\}/)?.[1] ?? "";
|
|
const bgColor = cssVar(rootBlock, "--color-bg") ?? "#111827";
|
|
|
|
const manifest = {
|
|
name: SITE_NAME,
|
|
short_name: SITE_NAME,
|
|
start_url: "/",
|
|
display: "standalone",
|
|
background_color: bgColor,
|
|
theme_color: bgColor,
|
|
icons: [{ src: "/favicon.svg", type: "image/svg+xml", sizes: "any" }],
|
|
share_target: {
|
|
action: "/",
|
|
method: "GET",
|
|
params: { url: "share_url", title: "share_title", text: "share_text" },
|
|
},
|
|
};
|
|
|
|
fs.writeFileSync(outPath, JSON.stringify(manifest, null, 2) + "\n");
|
|
}
|
|
|
|
return {
|
|
name: "generate-manifest",
|
|
buildStart: generate,
|
|
configureServer(server) {
|
|
generate();
|
|
server.watcher.on("change", (file) => {
|
|
if (path.resolve(file) === cssPath) generate();
|
|
});
|
|
},
|
|
};
|
|
}
|
|
|
|
export default defineConfig({
|
|
server: {
|
|
port: 3000,
|
|
watch: {
|
|
ignored: ["**/api/**"],
|
|
},
|
|
},
|
|
build: {
|
|
rollupOptions: {
|
|
output: {
|
|
manualChunks(id) {
|
|
if (id.includes("react-markdown") || id.includes("remark-gfm") || id.includes("remark-parse") || id.includes("mdast") || id.includes("micromark") || id.includes("unist")) {
|
|
return "vendor-markdown";
|
|
}
|
|
if (id.includes("node_modules")) {
|
|
return "vendor";
|
|
}
|
|
},
|
|
},
|
|
},
|
|
},
|
|
plugins: [
|
|
manifestPlugin(),
|
|
{
|
|
// In dev the API server isn't serving index.html, so replace the placeholder here.
|
|
// In production the Oak server does the replacement at runtime (see api/lib/static.ts).
|
|
name: "inject-site-name",
|
|
transformIndexHtml: {
|
|
order: "pre",
|
|
handler: (html, ctx) =>
|
|
ctx.server
|
|
? html.replaceAll("__SITE_NAME__", SITE_NAME)
|
|
: html,
|
|
},
|
|
},
|
|
lingui(),
|
|
react({
|
|
plugins: [["@lingui/swc-plugin", {}]],
|
|
}),
|
|
],
|
|
});
|