#!/usr/bin/env node /** * Single-source POSIX dashboard from posix-compliance-matrix.json. * Run from pretest; commit docs/reference/posix-dashboard.md when the matrix changes. */ import fs from 'node:fs' import path from 'node:path' import process from 'node:process' import { fileURLToPath } from 'node:url' const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..') const matrixPath = path.join(root, 'docs/reference/posix-compliance-matrix.json') const outPath = path.join(root, 'docs/reference/posix-dashboard.md') function escCell(s) { return String(s).replace(/\|/g, '\\|').replace(/\n/g, ' ') } function main() { const matrix = JSON.parse(fs.readFileSync(matrixPath, 'utf8')) const rows = [] const push = (area, key, value) => { rows.push(`| ${escCell(area)} | ${escCell(key)} | ${escCell(value)} |`) } push('Profile', 'profileId', matrix.profileId || '') push('Profile', 'schema', String(matrix.schema ?? '')) if (matrix.note) push('Profile', 'note', matrix.note) if (matrix.utilities && typeof matrix.utilities === 'object') { for (const [k, v] of Object.entries(matrix.utilities)) { push('Utilities', k, typeof v === 'string' ? v : JSON.stringify(v)) } } if (matrix.shell && typeof matrix.shell === 'object') { for (const [k, v] of Object.entries(matrix.shell)) { push('Shell', k, typeof v === 'string' ? v : JSON.stringify(v)) } } if (matrix.vfs && typeof matrix.vfs === 'object') { for (const [k, v] of Object.entries(matrix.vfs)) { push('VFS', k, typeof v === 'string' ? v : JSON.stringify(v)) } } if (matrix.synthetic_proc && typeof matrix.synthetic_proc === 'object') { for (const [k, v] of Object.entries(matrix.synthetic_proc)) { if (k === 'paths' && Array.isArray(v)) { push('synthetic /proc', k, v.join(', ')) } else { push( 'synthetic /proc', k, typeof v === 'string' ? v : JSON.stringify(v) ) } } } if (Array.isArray(matrix.commandIndex)) { for (const row of matrix.commandIndex) { if (!row || typeof row !== 'object') continue const name = String(row.name || '').trim() if (!name) continue const tier = String(row.tier || '').trim() || 'unspecified' push('Coreutils commandIndex', name, tier) } } const body = `# POSIX compliance dashboard (generated) **Do not edit by hand.** Regenerated by \`scripts/gen-posix-dashboard.mjs\` (via \`npm run pretest\`). Source: [\`docs/reference/posix-compliance-matrix.json\`](posix-compliance-matrix.json). Normative narrative: [\`docs/architecture/POSIX_DECLARED_PROFILE.md\`](../architecture/POSIX_DECLARED_PROFILE.md), handbook ch.9, [\`docs/reference/environment-and-posix-appendix.md\`](environment-and-posix-appendix.md). | Area | Key | Value | | --- | --- | --- | ${rows.join('\n')} ` fs.mkdirSync(path.dirname(outPath), { recursive: true }) fs.writeFileSync(outPath, body, 'utf8') process.stdout.write(`gen-posix-dashboard: wrote ${outPath}\n`) } main()