programming_framework / generator /mermaid-from-json.js
garywelz's picture
Sync programming_framework from local progframe
06e4298
#!/usr/bin/env node
/**
* Mermaid Subgraph Generator
* Input: discourse JSON + optional filter (propMax for Euclid, or --full)
* Output: Mermaid graph TD string
*
* Usage:
* node mermaid-from-json.js data/euclid-elements-book-i.json [propMax]
* node mermaid-from-json.js data/euclid-elements-book-i.json --full
*/
const fs = require('fs');
const path = require('path');
const jsonPath = process.argv[2];
const filterArg = process.argv[3];
if (!jsonPath) {
console.error("Usage: node mermaid-from-json.js <discourse.json> [propMax|--full]");
process.exit(1);
}
const discourse = JSON.parse(fs.readFileSync(jsonPath, "utf8"));
function closure(propMax) {
const needed = new Set();
for (let i = 1; i <= propMax; i++) needed.add(`Prop${i}`);
let changed = true;
while (changed) {
changed = false;
for (const e of discourse.edges) {
if (needed.has(e.to) && !needed.has(e.from)) { needed.add(e.from); changed = true; }
}
}
return n => n.type !== "proposition" || needed.has(n.id);
}
const filter = filterArg === "--full" || !filterArg
? () => true
: closure(parseInt(filterArg, 10));
const nodes = discourse.nodes.filter(filter);
const nodeIds = new Set(nodes.map(n => n.id));
const edges = discourse.edges.filter(e => nodeIds.has(e.from) && nodeIds.has(e.to));
const lines = ["graph TD"];
for (const n of nodes) {
const desc = n.short || (n.label && n.label.length > 35 ? n.label.slice(0, 32) + "..." : n.label || n.id);
const lbl = (n.shortLabel || n.id) + "\\n" + (desc || "");
lines.push(` ${n.id}["${String(lbl).replace(/"/g, '\\"')}"]`);
}
for (const e of edges) {
lines.push(` ${e.from} --> ${e.to}`);
}
const colorScheme = discourse.colorScheme || {};
const types = [...new Set(nodes.map(n => n.colorClass || n.type))];
for (const t of types) {
const c = colorScheme[t] || { fill: "#1abc9c", stroke: "#16a085" };
lines.push(` classDef ${t} fill:${c.fill},color:#fff,stroke:${c.stroke}`);
}
for (const t of types) {
const ids = nodes.filter(n => (n.colorClass || n.type) === t).map(n => n.id).join(",");
if (ids) lines.push(` class ${ids} ${t}`);
}
console.log(lines.join("\n"));