Initial Paprika Next.js implementation
This commit is contained in:
101
scripts/extract-legacy-pages.mjs
Normal file
101
scripts/extract-legacy-pages.mjs
Normal file
@@ -0,0 +1,101 @@
|
||||
import fs from "node:fs";
|
||||
import vm from "node:vm";
|
||||
|
||||
const sourcePath = "doc/index.html";
|
||||
const html = fs.readFileSync(sourcePath, "utf8");
|
||||
|
||||
const styleMatch = html.match(/<style>([\s\S]*?)<\/style>/);
|
||||
const scriptMatch = html.match(/<script>([\s\S]*?)<\/script>/);
|
||||
|
||||
if (!styleMatch || !scriptMatch) {
|
||||
throw new Error("Could not find inline style or script in doc/index.html");
|
||||
}
|
||||
|
||||
const css = styleMatch[1]
|
||||
.replaceAll("href=\"?page=", "href=\"/")
|
||||
.replace(/href="\/home"/g, "href=\"/\"");
|
||||
|
||||
const legacyScript = scriptMatch[1];
|
||||
const renderScript = legacyScript.replace(
|
||||
/const params = new URLSearchParams\(window\.location\.search\);[\s\S]*$/,
|
||||
"globalThis.__pageData = pageData;"
|
||||
);
|
||||
|
||||
const sandbox = {
|
||||
console,
|
||||
URLSearchParams,
|
||||
window: { location: { search: "" } },
|
||||
document: {
|
||||
title: "",
|
||||
getElementById() {
|
||||
return { innerHTML: "" };
|
||||
},
|
||||
querySelectorAll() {
|
||||
return [];
|
||||
},
|
||||
querySelector() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
vm.createContext(sandbox);
|
||||
vm.runInContext(renderScript, sandbox, { filename: sourcePath });
|
||||
|
||||
const pageData = sandbox.__pageData;
|
||||
const routeMap = {
|
||||
home: "/",
|
||||
press: "/press",
|
||||
judging: "/judging",
|
||||
scholarly: "/scholarly",
|
||||
services: "/services",
|
||||
why: "/why",
|
||||
resources: "/resources",
|
||||
faq: "/faq",
|
||||
thanks: "/thanks",
|
||||
terms: "/terms",
|
||||
privacy: "/privacy",
|
||||
disclaimer: "/disclaimer"
|
||||
};
|
||||
|
||||
const pages = Object.fromEntries(
|
||||
Object.entries(routeMap).map(([key, path]) => {
|
||||
const page = pageData[key];
|
||||
if (!page?.body) {
|
||||
throw new Error(`Missing page body for ${key}`);
|
||||
}
|
||||
return [
|
||||
key,
|
||||
{
|
||||
key,
|
||||
path,
|
||||
title: key === "home" ? "Paprika" : `Paprika - ${key}`,
|
||||
html: normalizeLinks(page.body)
|
||||
}
|
||||
];
|
||||
})
|
||||
);
|
||||
|
||||
function normalizeLinks(value) {
|
||||
return value
|
||||
.replaceAll("href=\"?page=home\"", "href=\"/\"")
|
||||
.replace(/href="\?page=([a-z-]+)"/g, (_match, page) => {
|
||||
if (page === "home") return "href=\"/\"";
|
||||
return `href="/${page}"`;
|
||||
});
|
||||
}
|
||||
|
||||
fs.mkdirSync("app", { recursive: true });
|
||||
fs.mkdirSync("lib", { recursive: true });
|
||||
|
||||
fs.writeFileSync(
|
||||
"app/globals.css",
|
||||
`${css}\n\n.form-error { color: var(--deep-red); font-size: 14px; font-weight: 750; line-height: 1.4; }\n.form-success { color: var(--green); font-size: 14px; font-weight: 750; line-height: 1.4; }\n.field-control { width: 100%; border: 0; outline: 0; background: transparent; color: var(--ink); font: inherit; font-weight: 650; }\n.field-control::placeholder { color: var(--muted); opacity: .78; }\ntextarea.field-control { min-height: 126px; resize: vertical; line-height: 1.45; }\n.checkbox-field { align-items: flex-start; gap: 12px; text-align: left; color: var(--text); font-size: 14px; line-height: 1.45; }\n.checkbox-field input { margin-top: 3px; accent-color: var(--red); }\n.button[disabled] { cursor: not-allowed; opacity: .62; }\n`
|
||||
);
|
||||
|
||||
fs.writeFileSync(
|
||||
"lib/legacy-pages.ts",
|
||||
`export type LegacyPageKey = ${Object.keys(pages).map((key) => JSON.stringify(key)).join(" | ")};\n\nexport type LegacyPage = {\n key: LegacyPageKey;\n path: string;\n title: string;\n html: string;\n};\n\nexport const legacyPages = ${JSON.stringify(pages, null, 2)} as const satisfies Record<LegacyPageKey, LegacyPage>;\n`
|
||||
);
|
||||
|
||||
console.log(`Generated ${Object.keys(pages).length} pages from ${sourcePath}`);
|
||||
Reference in New Issue
Block a user