// Foundry page generator. Each typeface is a boxed content card with a
// specimen (inlined SVG for bitmap/vector faces, @font-face for the rest),
// license, and platform usage. Specimens are contextual (AC piece names,
// the kidlisp logotype, paper titles). Run: node build.mjs
// (regenerate the bitmap/vector SVGs first: node gen-specimens.mjs)
import fs from "node:fs";
import { fileURLToPath } from "node:url";
import { dirname, join } from "node:path";
const HERE = dirname(fileURLToPath(import.meta.url));
const svg = (n) => { try { return fs.readFileSync(join(HERE, "specimens", n), "utf8"); } catch { return ""; } };
const rows = (...names) => names.map(svg).filter(Boolean).map((s) => `
${s}
`).join("");
const web = (stack, sample, cls = "") => `${sample}
`;
// the kidlisp.com logotype — Comic Relief, per-letter baby colors
const KIDLISP = (() => {
const word = [["K","#FF6B6B"],["i","#4ECDC4"],["d","#FFE66D"],["L","#95E1D3"],["i","#F38181"],["s","#AA96DA"],["p","#70D6FF"]];
const com = [["c","#FF6B6B"],["o","#9370DB"],["m","#90EE90"]];
const sp = ([c, col]) => `${c}`;
return `${word.map(sp).join("")}.${com.map(sp).join("")}
`;
})();
const GROUPS = [
{ title: "AC Native — cut in-house", color: "pink", faces: [
{ name: "font_1", tag: "bitmap · vector strokes · 6×10", spec: rows("font_1-1.svg","font_1-2.svg","font_1-3.svg"),
lic: ["native","AC original","OFL candidate — release with a reserved font name."], used: ["chat","melody","tracker","speaker","default text"] },
{ name: "microtype", tag: "bitmap · 3×5 · legacy", lic: ["native","AC original","superseded by MatrixChunky8"], used: ["legacy QR labels"] },
]},
{ title: "Bitmap — bundled", color: "cyan", faces: [
{ name: "MatrixChunky8", tag: "BDF · proportional · 8px", spec: rows("mc8-1.svg","mc8-2.svg","mc8-3.svg"),
lic: ["cc","CC-BY — Trip5 / Conventional Chaos","third-party, attribution required","https://github.com/trip5/Matrix-Fonts"], used: ["HUD","tooltips","gamepad","tapes","autocomplete","typecheck","offline"] },
{ name: "unifont", tag: "BDF · 16×8 · full Unicode", spec: rows("unifont-latin.svg","unifont-multi.svg"),
lic: ["gpl","GNU GPL v2+ — GNU Unifont","multilingual fallback; copyleft","https://unifoundry.com/unifont/"], used: ["CJK / emoji / accented fallback"] },
]},
{ title: "Papers — LaTeX / arXiv", color: "purple", faces: [
{ name: "Latin Modern Roman", tag: "serif · OTF", spec: web("'Latin Modern Roman',serif", `Pieces Not Programs
`),
lic: ["gust","GUST Font License (free, OFL-like)","the TeX default; ships with TeX Live"], used: ["all /papers arXiv PDFs (body)"] },
{ name: "Latin Modern Sans", tag: "sans · OTF", spec: web("'Latin Modern Sans',sans-serif", `Repository Archaeology
`),
lic: ["gust","GUST Font License (free, OFL-like)"], used: ["paper headings & figures"] },
{ name: "Latin Modern Mono", tag: "monospace · OTF", spec: web("'Latin Modern Mono',monospace", `(wipe "blue")
`),
lic: ["gust","GUST Font License (free, OFL-like)"], used: ["paper code listings"] },
]},
{ title: "Licensed", color: "gold", faces: [
{ name: "Berkeley Mono", tag: "monospace · variable", spec: web("'Berkeley Mono Variable',monospace", `prompt chat kidlisp
`),
lic: ["commercial","Commercial — Berkeley Graphics, from $75","⚠ not open-source-compatible; commercial use 'UI only', IDE/terminal needs sign-off","https://usgraphics.com/products/berkeley-mono"], used: ["code & UI","papers","kidlisp.com","checkout"] },
{ name: "YWFT Processing", tag: "display · headings", spec: web("'YWFT Processing',sans-serif", `aesthetic.computer
`),
lic: ["proprietary","Proprietary — YouWorkForThem (pageview-licensed)","drawn 2001 for Casey Reas (Processing); no license file in repo — verify","https://www.youworkforthem.com/font-license"], used: ["titles & branding","decks","vscode-extension"] },
]},
{ title: "Open & bundled — OFL / CC / public domain", color: "green", faces: [
{ name: "Comic Relief", tag: "display · TTF · the kidlisp.com logotype", spec: web("'Comic Relief',cursive", KIDLISP),
lic: ["ofl","SIL OFL"], used: ["kidlisp.com logo","kidlisp paper","oven","sosoft"] },
{ name: "Monaspace Argon", tag: "monospace · OTF", spec: web("'Monaspace Argon',monospace", `freehand line box
`),
lic: ["ofl","SIL OFL — GitHub"], used: ["slab/seed"] },
{ name: "Poppins", tag: "geometric · TTF", spec: web("'Poppins',sans-serif", `melody stample tape
`),
lic: ["ofl","SIL OFL"], used: ["reports"] },
{ name: "Proggy Clean", tag: "bitmap mono · TTF", spec: web("'ProggyClean',monospace", `spray smear 1v1
`),
lic: ["pd","Public domain"], used: ["apple HTML fallback"] },
{ name: "Bravura", tag: "music notation · SMuFL", spec: web("'Bravura',serif", `𝄞 ♩ ♪ ♫ ♬ ♭ ♮ ♯
`, "tall"),
lic: ["ofl","SIL OFL — Steinberg"], used: ["slab/menuband"] },
]},
{ title: "Candidates — FOSS, bundleable (not yet adopted)", color: "green", faces: [
{ name: "Departure Mono", tag: "pixel mono", spec: web("'Departure Mono',monospace", `freehand tape
`),
lic: ["mit","MIT — Helena Zhang","lo-fi pixel mono","https://departuremono.com"], role: "candidate · bundleable now" },
{ name: "Space Mono", tag: "display mono", spec: web("'Space Mono',monospace", `prompt notepat
`),
lic: ["ofl","SIL OFL — Colophon"], role: "candidate · bundleable now" },
{ name: "Space Grotesk", tag: "geometric display", spec: web("'Space Grotesk',sans-serif", `aesthetic computer
`),
lic: ["ofl","SIL OFL — Florian Karsten"], role: "candidate · bundleable now" },
{ name: "Inter", tag: "UI sans", spec: web("'Inter',sans-serif", `painting melody
`),
lic: ["ofl","SIL OFL — Rasmus Andersson"], role: "candidate · bundleable now" },
{ name: "Silkscreen", tag: "pixel · bitmap", spec: web("'Silkscreen',sans-serif", `kidlisp chat
`),
lic: ["ofl","SIL OFL — Jason Kottke"], role: "candidate · bundleable now" },
{ name: "Press Start 2P", tag: "arcade pixel", spec: web("'Press Start 2P',monospace", `balls
`),
lic: ["ofl","SIL OFL — CodeMan38"], role: "candidate · bundleable now" },
{ name: "Handjet", tag: "variable pixel / element", spec: web("'Handjet',monospace", `wand bleep
`),
lic: ["ofl","SIL OFL — Rosetta"], role: "candidate · bundleable now" },
]},
];
const KIND = { native:["AC NATIVE","cyan"], cc:["CC-BY","green"], gpl:["GPL","purple"], gust:["GUST","green"], mit:["MIT","green"], commercial:["COMMERCIAL","pink"], proprietary:["PROPRIETARY","gold"], ofl:["OFL","green"], pd:["PD","green"] };
function licBlock(lic){
const [kind, label, ...rest] = lic;
const [klabel, kcolor] = KIND[kind];
const url = rest.find((n)=>/^https?:/.test(n));
const notes = rest.filter((n)=>!/^https?:/.test(n));
return `${klabel} ${label}`
+ notes.map((t)=>`
${t}`).join("")
+ (url?`
↗`:"") + `
`;
}
const card = (f) => `${f.name}${f.tag}
`
+ (f.spec?`
${f.spec}
`:"")
+ licBlock(f.lic)
+ `
${f.role || ("used: " + f.used.join(", "))}
`;
const SECTIONS = GROUPS.map((g)=>`${g.title}
${g.faces.map(card).join("")}
`).join("");
const HTML = `
type foundry · Aesthetic Computer
Type Foundry.
AC NATIVE our cut
CC / OFL / PD / GUST free to bundle
GPL copyleft
COMMERCIAL paid
PROPRIETARY terms vary
${SECTIONS}
`;
fs.writeFileSync(join(HERE, "index.html"), HTML);
console.log("wrote index.html (" + HTML.length + " bytes), " + GROUPS.reduce((n,g)=>n+g.faces.length,0) + " faces");