#!/usr/bin/env node // Site build for the delivery-arc page (CSP-clean: script-src 'self', no inline JS). // Reads pilot/arc.tpl.html, splits the app "); if (i < 0 || j < i) throw new Error("app script block not found"); let app = tpl.slice(i + 8, j) .replace("__MAN_GITOPS__", man("gitops")) .replace("__MAN_SUPPLY__", man("supply")) .replace("__MAN_HELM__", man("helm")); let body = tpl.slice(0, i) + tpl.slice(j + 9); const heroes = { __HERO_GITOPS__: "course-VI-gitops.webp", __HERO_SUPPLY__: "course-VII-supply-chain.webp", __HERO_HELM__: "course-VIII-helm-press.webp", __HERO_APPENDIX__: "appendix-dependency-ledger.webp", }; for (const [ph, file] of Object.entries(heroes)) body = body.replace(ph, "/assets/" + file); if (body.includes("__HERO_") || app.includes("__MAN_")) throw new Error("unfilled placeholder"); const favicon = "data:image/svg+xml," + encodeURIComponent( ``); const html = ` The Exploded Cluster ${body} `; mkdirSync(join(DIST, "assets"), { recursive: true }); writeFileSync(join(DIST, "index.html"), html); writeFileSync(join(DIST, "arc.js"), app); copyFileSync(join(ROOT, "gsap.min.js"), join(DIST, "gsap.min.js")); copyFileSync(join(ROOT, "st.min.js"), join(DIST, "st.min.js")); for (const f of Object.values(heroes)) copyFileSync(join(ROOT, "assets/dist", f), join(DIST, "assets", f)); // CSP gate: no inline