// Stage the marimo notebook exports produced by deploy/export-notebooks.py // into public/, where Astro will pick them up as static files. // // The raw marimo HTML lands at public/nb/.html (served /nb/.html) // and is what the notebook pages iframe. It deliberately does NOT live under // /notebooks/ — those URLs belong to the Astro pages that wrap it in the // garden chrome, and with build.format:'file' the two would collide on a // trailing slash. // // No exports (export script never ran, or nothing is marked) is a normal // state, not an error: the notebooks section simply doesn't render. import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const REPO = path.join(path.dirname(fileURLToPath(import.meta.url)), '..'); const SRC_DIR = path.join(REPO, 'notebooks-export'); const OUT_DIR = path.join(REPO, 'public', 'nb'); fs.rmSync(OUT_DIR, { recursive: true, force: true }); let index = []; try { index = JSON.parse(fs.readFileSync(path.join(SRC_DIR, 'index.json'), 'utf8')); } catch { console.log('copy-notebooks: no notebooks-export/index.json — nothing to stage'); process.exit(0); } fs.mkdirSync(OUT_DIR, { recursive: true }); let copied = 0; for (const nb of index) { const src = path.join(SRC_DIR, `${nb.slug}.html`); if (!fs.existsSync(src)) { // export-notebooks.py only indexes notebooks it exported, so this means // the two got out of sync — warn rather than ship a link to a 404 console.warn(`copy-notebooks: MISSING export for indexed notebook ${nb.slug}`); continue; } fs.copyFileSync(src, path.join(OUT_DIR, `${nb.slug}.html`)); copied++; } console.log(`copy-notebooks: ${copied}/${index.length} staged -> ${OUT_DIR}`);