/** * Convert repo developer-guide/*.md into man(7) page objects (same pipeline as handbook). */ import { readFile, readdir } from 'fs/promises' import { join } from 'path' import { handbookMdToDescription } from './ingest-handbook-for-man.mjs' const SECTION = 7 function firstHeadingTitle(md) { const m = md.match(/^#\s+(.+)$/m) if (!m) return 'Bare OS developer guide' let t = m[1] t = t.replace(/\*\*([^*]+)\*\*/g, '$1') t = t.replace(/`([^`]+)`/g, '$1') return t.trim() } /** * @param {string} repoRoot * @returns {Promise} */ export async function buildDeveloperGuideManPages(repoRoot) { const dir = join(repoRoot, 'developer-guide') let names try { names = (await readdir(dir)).filter((f) => f.endsWith('.md')) } catch { return [] } names.sort((a, b) => { if (a === 'README.md') return -1 if (b === 'README.md') return 1 return a.localeCompare(b) }) /** @type {{ file: string, name: string, title: string, aliases?: string[] }[]} */ const meta = [] for (const file of names) { if (file === 'README.md') { meta.push({ file, name: 'bare-os-developer-guide', title: 'Bare OS developer guide — index and reading order', aliases: ['developer-guide', 'devguide'] }) } else { const base = file.replace(/\.md$/i, '') meta.push({ file, name: 'devguide-' + base, title: '', aliases: [] }) } } const pages = [] for (let j = 0; j < meta.length; j++) { const m = meta[j] const filePath = join(dir, m.file) const md = await readFile(filePath, 'utf8') const title = m.title || firstHeadingTitle(md) const description = handbookMdToDescription(md, 'developer-guide/' + m.file) const next = meta[j + 1] const prev = meta[j - 1] /** @type {{ name: string, section: number }[]} */ const seeAlso = [] if (next) seeAlso.push({ name: next.name, section: SECTION }) if (prev) seeAlso.push({ name: prev.name, section: SECTION }) seeAlso.push({ name: 'man', section: 1 }) seeAlso.push({ name: 'bare-os-handbook', section: SECTION }) const kw = new Set([ 'developer', 'devguide', 'develop', 'script', 'asyncfunction', 'ctx', 'bare-os', 'guide' ]) for (const t of m.name.split(/[^a-z0-9]+/i)) { if (t.length > 1) kw.add(t.toLowerCase()) } for (const t of title.toLowerCase().split(/[^a-z0-9]+/)) { if (t.length > 2) kw.add(t) } const page = { name: m.name, section: SECTION, title, synopsis: [ 'man 7 ' + m.name, 'Developer guide chapter (developer-guide/' + m.file + ')' ], description, descriptionMode: 'preserve', options: [], keywords: Array.from(kw), seeAlso, bareOsNotes: 'Generated at build time from developer-guide/' + m.file + '. Mermaid diagrams omitted in terminal; see repo Markdown for figures.' } if (m.aliases && m.aliases.length) page.aliases = m.aliases pages.push(page) } return pages }