What I ran into
Reading graph.html for a 721-node TypeScript project, I could not tell the call graph apart from the file structure. Every edge is drawn the same, so the only way to learn an edge's type is to hover it.
The breakdown for that graph:
| relation |
edges |
| calls |
910 |
| imports + imports_from |
926 |
| contains |
603 |
| references |
38 |
| other |
36 |
contains and imports are ~62% of what is drawn and carry no behavioural information, so they crowd out the edges I was actually looking for. The data is already there — each edge carries its relation as label and it shows in the tooltip — but _html_script blanks the label and gives every edge one colour, so nothing surfaces it at a glance.
What would help
A colour per relation plus a way to hide relations, in the shape of the community legend that already exists. Unticking everything except calls leaves the call graph on its own, which was exactly what I needed.
Would you take a PR?
I have this working locally and would rather ask before opening it, since the README asks for worked examples and extraction bug reports rather than features, and every changelog entry I can see is an issue-linked fix.
What I have, if it is useful:
- A "Connection Types" panel next to the community legend: colour, count and checkbox per relation.
- Off by default. The graph opens with edge colours untouched and nothing repainted at load, so it costs nothing to anyone who ignores it. A checkbox turns it on and the state persists in
localStorage, so it is the reader's choice rather than something baked into the file by whoever generated it. to_html(edge_types=...) and GRAPHIFY_EDGE_TYPES=1 set the initial state, mirroring node_limit / GRAPHIFY_VIZ_NODE_LIMIT.
- Relation strings go through
sanitize_label on the way out and esc() on the way into the DOM, and the lookup maps are null-prototype (a relation named constructor or __proto__ would otherwise corrupt the legend).
- Colouring preserves each edge's own opacity, so the EXTRACTED/inferred distinction is not flattened.
- A click updates only that relation's edges, not the whole array, to avoid a physics rebuild on large graphs.
- Unknown relations get a stable hashed hue, so new extractor relation kinds stay distinguishable with no change needed there.
- Skipped for the aggregated (>node-limit) view, whose meta-edges carry
"<n> cross-community edges" as their relation; a legend row per distinct weight would be noise.
- Tests drive the generated panel's own JavaScript through a small DOM/vis stub (skipped when node is unavailable), so they fail if the behaviour breaks rather than only if a string disappears.
One thing worth fixing regardless
While testing I hit a separate bug in the existing viewer. toggleAllCommunities queries .legend-item and .legend-cb unscoped:
document.querySelectorAll('.legend-item').forEach(...)
document.querySelectorAll('.legend-cb').forEach(cb => { cb.checked = !hide; })
Today nothing else in the page uses those classes, so it is latent, but any second panel reusing the legend styles gets its checkboxes rewritten without its change handlers firing, leaving the sidebar showing a state the graph is not in. Scoping both to #legend fixes it. Happy to send that as a standalone one-line PR whatever you decide about the feature.
Environment: graphify 0.9.22, Python 3.12, Linux.
What I ran into
Reading
graph.htmlfor a 721-node TypeScript project, I could not tell the call graph apart from the file structure. Every edge is drawn the same, so the only way to learn an edge's type is to hover it.The breakdown for that graph:
containsandimportsare ~62% of what is drawn and carry no behavioural information, so they crowd out the edges I was actually looking for. The data is already there — each edge carries its relation aslabeland it shows in the tooltip — but_html_scriptblanks the label and gives every edge one colour, so nothing surfaces it at a glance.What would help
A colour per relation plus a way to hide relations, in the shape of the community legend that already exists. Unticking everything except
callsleaves the call graph on its own, which was exactly what I needed.Would you take a PR?
I have this working locally and would rather ask before opening it, since the README asks for worked examples and extraction bug reports rather than features, and every changelog entry I can see is an issue-linked fix.
What I have, if it is useful:
localStorage, so it is the reader's choice rather than something baked into the file by whoever generated it.to_html(edge_types=...)andGRAPHIFY_EDGE_TYPES=1set the initial state, mirroringnode_limit/GRAPHIFY_VIZ_NODE_LIMIT.sanitize_labelon the way out andesc()on the way into the DOM, and the lookup maps are null-prototype (a relation namedconstructoror__proto__would otherwise corrupt the legend)."<n> cross-community edges"as their relation; a legend row per distinct weight would be noise.One thing worth fixing regardless
While testing I hit a separate bug in the existing viewer.
toggleAllCommunitiesqueries.legend-itemand.legend-cbunscoped:Today nothing else in the page uses those classes, so it is latent, but any second panel reusing the legend styles gets its checkboxes rewritten without its change handlers firing, leaving the sidebar showing a state the graph is not in. Scoping both to
#legendfixes it. Happy to send that as a standalone one-line PR whatever you decide about the feature.Environment: graphify 0.9.22, Python 3.12, Linux.