// Bundles the repository docs/ tree into a generated TS module so the docs // browser renders instantly and offline. The GitHub sync layer refreshes it // at runtime when network is available. import { readdirSync, readFileSync, statSync, writeFileSync, mkdirSync } from 'node:fs'; import { join, relative } from 'node:path'; import { fileURLToPath } from 'node:url'; const root = join(fileURLToPath(new URL('.', import.meta.url)), '..', '..', '..'); const docsDir = join(root, 'docs'); const outFile = join(root, 'app/frontend/src/generated/docs-snapshot.ts'); // Directories that are internal working notes rather than user documentation. const SKIP_DIRS = new Set(['archive', 'design', 'superpowers']); function walk(dir) { const entries = []; for (const name of readdirSync(dir)) { const full = join(dir, name); const stat = statSync(full); if (stat.isDirectory()) { if (!SKIP_DIRS.has(name)) entries.push(...walk(full)); } else if (name.toLowerCase().endsWith('.md')) { entries.push(full); } } return entries; } function titleOf(markdown, fallback) { const match = markdown.match(/^#\s+(.+)$/m); if (match) return match[1].replace(/[#*`]/g, '').trim(); return fallback .replace(/\.md$/i, '') .replace(/[-_]+/g, ' ') .replace(/\b\w/g, (c) => c.toUpperCase()); } const files = walk(docsDir).sort(); const docs = files.map((full) => { const rel = relative(docsDir, full).replace(/\\/g, '/'); const markdown = readFileSync(full, 'utf8'); const section = rel.includes('/') ? rel.split('/')[0] : 'docs'; return { path: rel, section, title: titleOf(markdown, rel.split('/').pop() ?? rel), markdown, }; }); const banner = `/**\n * Auto-generated by scripts/generate-docs-snapshot.mjs.\n * Bundled copy of the repository docs tree — the offline fallback for the\n * docs browser. Regenerate with \`npm run generate:docs\`.\n */\n\nexport type BundledDoc = {\n path: string;\n section: string;\n title: string;\n markdown: string;\n};\n\n`; mkdirSync(join(outFile, '..'), { recursive: true }); writeFileSync(outFile, `${banner}export const bundledDocs: BundledDoc[] = ${JSON.stringify(docs, null, 2)};\n`); console.log(`docs snapshot: ${docs.length} files → ${relative(root, outFile)}`);