AirShelf/core/frontend/scripts/generate-exact-html.mjs

95 lines
3.3 KiB
JavaScript

import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { basename, dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
const root = dirname(fileURLToPath(import.meta.url));
const frontendRoot = join(root, "..");
const exactRoot = join(frontendRoot, "public", "exact");
const outFile = join(frontendRoot, "src", "routes", "exact-html.ts");
const componentRoot = join(frontendRoot, "src", "routes", "exact-pages");
const pages = [
["account", "account.html"],
["assetFactory", "asset-factory.html"],
["dashboard", "index.html"],
["imageOptimize", "image-optimize.html"],
["library", "library.html"],
["login", "login.html"],
["messages", "messages.html"],
["modelPhoto", "model-photo.html"],
["modelPhotoDemoA", "model-photo-demo-a.html"],
["modelPhotoDemoB", "model-photo-demo-b.html"],
["pipeline", "pipeline.html"],
["platformCover", "platform-cover.html"],
["productCreate", "product-create.html"],
["productCreateUpload", "product-create-upload.html"],
["productDetail", "product-detail.html"],
["products", "products.html"],
["projectWizard", "projects-new.html"],
["projects", "projects.html"],
["register", "register.html"],
["settings", "settings.html"],
["team", "team.html"]
];
function normalizeDocument(html, fileName) {
const withMeta = html.replace(
/<head>/i,
`<head>\n<meta name="x-airshelf-exact-source" content="${basename(fileName)}">`
);
return withMeta
.replace(/(src|href)="assets\//g, '$1="/exact/assets/')
.replace(/url\((['"]?)assets\//g, "url($1/exact/assets/")
.replace(
"history.replaceState(null, '', '#' + id);",
"try { window.location.hash = id; } catch (e) {}"
);
}
mkdirSync(dirname(outFile), { recursive: true });
mkdirSync(componentRoot, { recursive: true });
const entries = pages
.map(([key, fileName]) => {
const html = normalizeDocument(readFileSync(join(exactRoot, fileName), "utf8"), fileName);
return ` ${JSON.stringify(key)}: ${JSON.stringify(html)}`;
})
.join(",\n");
const keys = pages.map(([key]) => JSON.stringify(key)).join(" | ");
writeFileSync(
outFile,
`/* This file is generated by scripts/generate-exact-html.mjs. Do not edit by hand. */\n` +
`export type ExactHtmlKey = ${keys};\n\n` +
`export const exactHtmlDocuments: Record<ExactHtmlKey, string> = {\n${entries}\n};\n`,
"utf8"
);
function toPascalCase(value) {
return value
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
.split(/[-_]/)
.filter(Boolean)
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
.join("");
}
for (const [key] of pages) {
const componentName = `Exact${toPascalCase(key)}Page`;
const fileName = `${key.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase()}.tsx`;
writeFileSync(
join(componentRoot, fileName),
`/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */\n` +
`import { ExactDocumentPage } from "../exact-document";\n` +
`import type { ExactDocumentPageProps } from "../exact-document";\n\n` +
`export function ${componentName}(props: Omit<ExactDocumentPageProps, "pageKey">) {\n` +
` return <ExactDocumentPage {...props} pageKey=${JSON.stringify(key)} />;\n` +
`}\n\n` +
`export default ${componentName};\n`,
"utf8"
);
}
console.log(`generated ${pages.length} exact documents -> ${outFile}`);