// Generates the "diagnostic pipeline" hero banner as one SVG per language. // Layout is identical across languages; only the node text changes. // Run: node scripts/gen-banner.mjs → writes assets/banner-.svg import { writeFileSync } from "node:fs"; import { fileURLToPath } from "node:url"; import { dirname, join } from "node:path"; const ROOT = join(dirname(fileURLToPath(import.meta.url)), ".."); // Mirrored to both dirs, matching the repo's logo.svg / demo.gif convention: // assets/ for the READMEs, docs/ for the GitHub Pages site. const OUT_DIRS = ["assets", "docs"].map((d) => join(ROOT, d)); // Four-stage pipeline: input → sources → risks → output. // Each node carries an accent dot color drawn from the logo palette. const ACCENTS = ["#3b82f6", "#6366f1", "#b07d2b", "#22c55e"]; // main = short headline, sub = supporting detail. Kept short so centered // text never overflows the fixed node width across scripts (CJK + Latin). const LANGS = { "en": [ { main: "Your code", sub: "PR or whole repo" }, { main: "12 classics", sub: "Brooks · Fowler · Martin" }, { main: "12 decay risks", sub: "R1–R6 · T1–T6" }, { main: "Cited findings", sub: "Symptom → Remedy" }, ], "zh-CN": [ { main: "你的代码", sub: "PR 或整个仓库" }, { main: "十二本经典", sub: "布鲁克斯 · 福勒 · 马丁" }, { main: "十二类衰退风险", sub: "R1–R6 · T1–T6" }, { main: "带出处的结论", sub: "症状 → 对策" }, ], "zh-TW": [ { main: "你的程式碼", sub: "PR 或整個儲存庫" }, { main: "十二本經典", sub: "布魯克斯 · 福勒 · 馬丁" }, { main: "十二類衰退風險", sub: "R1–R6 · T1–T6" }, { main: "帶出處的結論", sub: "症狀 → 對策" }, ], "ja": [ { main: "あなたのコード", sub: "PR / リポジトリ全体" }, { main: "古典12冊", sub: "Brooks · Fowler · Martin" }, { main: "12の劣化リスク", sub: "R1–R6 · T1–T6" }, { main: "出典付きの指摘", sub: "症状 → 対策" }, ], "ko": [ { main: "당신의 코드", sub: "PR / 전체 저장소" }, { main: "고전 12권", sub: "Brooks · Fowler · Martin" }, { main: "12가지 리스크", sub: "R1–R6 · T1–T6" }, { main: "출처 있는 진단", sub: "증상 → 처방" }, ], "es": [ { main: "Tu código", sub: "PR o repo completo" }, { main: "12 clásicos", sub: "Brooks · Fowler · Martin" }, { main: "12 riesgos", sub: "de deterioro · R1–T6" }, { main: "Hallazgos", sub: "Síntoma → Remedio" }, ], }; const W = 1040, H = 200; const NODE_W = 210, NODE_H = 128, NODE_Y = 36; const GAP = (W - 40 - NODE_W * 4) / 3; // even gaps, 20px outer margin const FONT = `-apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans", "Microsoft YaHei", "Malgun Gothic", sans-serif`; const esc = (s) => s.replace(/&/g, "&").replace(//g, ">"); const nodeX = (i) => Math.round(20 + i * (NODE_W + GAP)); function node(i, { main, sub }) { const x = nodeX(i), cx = x + NODE_W / 2; return ` ${esc(main)} ${esc(sub)} `; } function arrow(i) { const start = nodeX(i) + NODE_W, end = nodeX(i + 1); const y = NODE_Y + NODE_H / 2; const mid = (start + end) / 2; return ` `; } function svg(nodes) { const body = nodes.map((n, i) => node(i, n)).join("") + [0, 1, 2].map(arrow).join(""); return `${body} `; } for (const [lang, nodes] of Object.entries(LANGS)) { const content = svg(nodes); for (const dir of OUT_DIRS) { const file = join(dir, `banner-${lang}.svg`); writeFileSync(file, content); console.log(`wrote ${file}`); } }