hornwitser.no/cli.ts
Hornwitser f708088ef7 Re-organise cli.ts into functions and sub-commands
Add the necessary boilerplate for cli.ts to provide more than one
command, with the resource gathering step split out from the build
step in order for it to be re-usable.
2025-02-01 16:25:45 +01:00

85 lines
2.3 KiB
TypeScript

import * as fs from "node:fs";
import * as posix from "node:path/posix";
import { prettify, htmlDocument } from "antihtml";
import { pages } from "./content/pages.js";
import type { Page } from "./content/types.js";
import { resolveRefs } from "./utils/resolve-refs.js";
function pageToHtml(page: Page) {
if (!page.ref.startsWith("/")) {
throw new Error(`ref "${page.ref}" for "${page.title}" is not absolute.`);
}
return htmlDocument(
prettify(
resolveRefs(
page.content,
posix.dirname(page.ref),
)
)
)
}
function assembleResources() {
const webDir = "public";
const resources = new Map<string, string | Page>();
for (const entry of fs.readdirSync(webDir, { recursive: true, withFileTypes: true })) {
if (!entry.isFile())
continue;
const parentPath = entry.parentPath.replace(/\\/g, "/");
const ref = `${parentPath.slice(webDir.length)}/${entry.name}`;
resources.set(ref, `${parentPath}/${entry.name}`);
}
for (const page of pages) {
if (resources.has(page.ref)) {
const existing = resources.get(page.ref)!;
const other = typeof existing === "string" ? "a static resource" : `"${existing.title}"`;
throw new Error(`ref "${page.ref}" is taken up by both "${page.title}" and ${other}`)
}
resources.set(page.ref, page);
}
return resources;
}
function build() {
const outDir = "build/web";
const dirsCreated = new Set<string>()
for (const [ref, resource] of assembleResources()) {
const refDir = `${outDir}${posix.dirname(ref)}`;
if (!dirsCreated.has(refDir)) {
fs.mkdirSync(refDir, { recursive: true });
}
console.log(`writing ${outDir}${ref}`);
let content;
if (typeof resource === "string") {
content = fs.readFileSync(resource);
} else {
content = pageToHtml(resource);
}
fs.writeFileSync(`${outDir}${ref}`, content);
}
}
function printUsage() {
console.log("Usage: cli.js <cmd>");
console.log(" build - Copy resources and generated pages to build directory.");
}
function main(runtime: string, script: string, args: string[]) {
if (!args.length) {
printUsage();
process.exitCode = 1;
return;
}
const [command, ...commandArgs] = args;
if (command === "build") {
build();
} else {
console.log(`Error: Unkown sub-command ${command}`);
printUsage();
process.exitCode = 1;
}
}
const [runtime, script, ...args] = process.argv;
main(runtime, script, args)