Public
Edited
Feb 22, 2024
Importers
1 star
McNulty's Inputs
GraphViz -> forceDirected format
Insert cell
Insert cell
Insert cell
parseGraphViz(`
electron [type=framework, platform=desktop] -> node.js [communication=IPC];
react-flow [type=library, usage=UI] -> electron, next.js [communication=API];
next.js [type=framework, platform=web] -> node.js [communication=HTTP];
electron -> main.js, preload.js, package.json [relationship=includes];
electron -> electron-builder [tool=build system];
electron-builder -> build [command=build, platform=all];
react-flow -> src/components, .babelrc, webpack.config.js [relationship=includes];
react-flow -> npm [tool=package manager];
npm -> start, build [command=run dev, build];
next.js -> pages, next.config.js, package.json [relationship=includes];
next.js -> next build, next start [command=build, start];
node.js -> server.js, package.json [relationship=includes];
node.js [type=runtime, platform=server] -> npm, nodemon [tool=package manager, development tool];
npm -> install, start [command=install dependencies, run server];
nodemon -> npm start [command=restart server on change];
`)
Insert cell
function parseGraphViz(graphVizStr) {
function parseSrcSide(str) {
const [objectsStr, annotationsStr] = str
.split("[")
.map((x, i) => (i > 0 ? x.slice(0, -1) : x)); // remove "]" from second slice
const annotations = annotationsStr
? annotationsStr.split(",").reduce((memo, el) => {
const [key, val] = el.split("=");
memo[key] = val;
return memo;
}, {})
: undefined;
return objectsStr.split(",").map(id => ({ id, annotations }));
}


const statements = graphVizStr
.replace(/\s/g, "")
.split(";")
.filter((x) => x);
let id = 0;
return statements.map((s) => {
const [srcString, targetString] = s.split("->");
console.log(srcString);
return {
sources: parseSrcSide(srcString),
targets: targetString ? parseSrcSide(targetString) : []
}
})
.map(({sources, targets}) => {
const edges = sources.flatMap((s,i) => targets.map((t,j) => ({
source: s.id,
target: t.id,
id: id++,
annotations: t.annotations
})));
return {
nodes: [...targets.map(t => ({id: t.id })), ...sources], // targets don't carry over metadata
edges
};
}).reduce((memo, el) => {
return {
nodes: _.uniqBy([...memo.nodes, ...el.nodes], d=>d.id),
edges: _.uniqBy([...memo.edges, ...el.edges], d=>d.id),
}
}, {nodes:[], edges:[]});
}
Insert cell
d3 = require("d3@5")
Insert cell
_ = require("lodash")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more