mirror of
https://github.com/KivotosRailway/website.git
synced 2026-11-03 11:06:32 +09:00
优化页面数据加载并完善多语言 SEO、新闻回退、主题首屏及自动化回归测试
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import { readFile, readdir, writeFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { isLocale, localeLanguageTags } from "../src/lib/i18n";
|
||||
|
||||
const output = path.resolve("out");
|
||||
const bootstrap = (await readFile("public/init-theme.js", "utf8")).trim();
|
||||
|
||||
async function finalize(directory: string): Promise<number> {
|
||||
let count = 0;
|
||||
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
||||
const file = path.join(directory, entry.name);
|
||||
if (entry.isDirectory()) { count += await finalize(file); continue; }
|
||||
if (!entry.name.endsWith(".html")) continue;
|
||||
const routeLocale = path.relative(output, file).split(path.sep)[0];
|
||||
const language = isLocale(routeLocale) ? localeLanguageTags[routeLocale] : "zh-Hans";
|
||||
const html = await readFile(file, "utf8");
|
||||
if (!html.includes("</head>") || !/<html\b[^>]*\blang="[^"]*"/.test(html)) {
|
||||
throw new Error(`Unexpected exported HTML: ${file}`);
|
||||
}
|
||||
// Static-host boundary: no scripts in React layouts and no extra root layouts
|
||||
// (which would turn language switching into document navigation).
|
||||
const finalized = html
|
||||
.replace(/(<html\b[^>]*\blang=")[^"]*"/, `$1${language}"`)
|
||||
.replace(/<script id="kr-theme-init">[\s\S]*?<\/script>/g, "")
|
||||
.replace("</head>", `<script id="kr-theme-init">${bootstrap}</script></head>`);
|
||||
await writeFile(file, finalized);
|
||||
count += 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
console.log(`[finalize-export] Set document languages and pre-paint themes in ${await finalize(output)} HTML files.`);
|
||||
@@ -0,0 +1,28 @@
|
||||
// Local-only static host for regression tests. Unknown URLs keep a real 404 status.
|
||||
import { createServer } from "node:http";
|
||||
import { readFile, stat } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
const root = path.resolve("out");
|
||||
const types = { ".html": "text/html; charset=utf-8", ".js": "application/javascript", ".css": "text/css", ".json": "application/json", ".txt": "text/plain; charset=utf-8", ".xml": "application/xml", ".svg": "image/svg+xml", ".webp": "image/webp", ".png": "image/png", ".jpg": "image/jpeg", ".woff2": "font/woff2" };
|
||||
createServer(async (request, response) => {
|
||||
try {
|
||||
const url = new URL(request.url, "http://127.0.0.1");
|
||||
let file = path.resolve(root, `.${decodeURIComponent(url.pathname)}`);
|
||||
if (file !== root && !file.startsWith(root + path.sep)) {
|
||||
response.writeHead(403).end(); return;
|
||||
}
|
||||
if ((await stat(file)).isDirectory()) {
|
||||
if (!url.pathname.endsWith("/")) {
|
||||
response.writeHead(308, { Location: `${url.pathname}/${url.search}` }).end(); return;
|
||||
}
|
||||
file = path.join(file, "index.html");
|
||||
}
|
||||
const body = await readFile(file);
|
||||
response.writeHead(200, { "Content-Type": types[path.extname(file)] || "application/octet-stream", "Cache-Control": "no-store" });
|
||||
response.end(body);
|
||||
} catch {
|
||||
response.writeHead(404, { "Content-Type": "text/html; charset=utf-8" });
|
||||
response.end(await readFile(path.join(root, "404.html")));
|
||||
}
|
||||
}).listen(4173, "127.0.0.1", () => console.log("Static export: http://127.0.0.1:4173"));
|
||||
Reference in New Issue
Block a user