Reorganise source files into src and web
Use a more traditional source code layout with the code located in the src/ dir and static web content in the web/ dir, while the other places are for data not related to code or content.
This commit is contained in:
parent
82323c9158
commit
c8527f17f7
20 changed files with 35 additions and 36 deletions
106
src/cli.ts
Normal file
106
src/cli.ts
Normal file
|
@ -0,0 +1,106 @@
|
|||
import * as fs from "node:fs";
|
||||
import * as posix from "node:path/posix";
|
||||
import { prettify, htmlDocument } from "antihtml";
|
||||
import { pages } from "./pages.js";
|
||||
import type { Page } from "./types.js";
|
||||
import { resolveRefs } from "./utils/resolve-refs.js";
|
||||
import { createServer } from "./utils/http-server.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 = "web";
|
||||
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 serve() {
|
||||
const resources = assembleResources();
|
||||
const server = createServer(
|
||||
(ref) => {
|
||||
const resource = resources.get(ref);
|
||||
if (resource === undefined)
|
||||
return undefined;
|
||||
if (typeof resource === "string")
|
||||
return fs.readFileSync(resource);
|
||||
return Buffer.from(pageToHtml(resource));
|
||||
}
|
||||
);
|
||||
|
||||
server.listen(8080);
|
||||
console.log("Listening on http://localhost:8080");
|
||||
}
|
||||
|
||||
function printUsage() {
|
||||
console.log("Usage: cli.js <cmd>");
|
||||
console.log(" build - Copy resources and generated pages to build directory.");
|
||||
console.log(" serve - Host website on localhost:8080 for development purposes.");
|
||||
}
|
||||
|
||||
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 if (command === "serve") {
|
||||
serve();
|
||||
} else {
|
||||
console.log(`Error: Unkown sub-command ${command}`);
|
||||
printUsage();
|
||||
process.exitCode = 1;
|
||||
}
|
||||
}
|
||||
|
||||
const [runtime, script, ...args] = process.argv;
|
||||
main(runtime, script, args)
|
Loading…
Add table
Add a link
Reference in a new issue