feat(flowchart): collapsible subgraphs via @{ view: collapsed }#7785
feat(flowchart): collapsible subgraphs via @{ view: collapsed }#7785knsv-bot wants to merge 3 commits into
Conversation
A subgraph annotated with `@{ view: collapsed }` now renders as a single
compact node. Its internal nodes are hidden and edges crossing the subgraph
boundary are redirected to the collapsed node; nested collapses resolve to
the outermost collapsed ancestor.
Subgraph metadata is routed through the existing `id@{ ... }` statement
syntax in addVertex, so no grammar change is required. A new `collapsedGroup`
shape renders the compact node with a title and an ellipsis indicator.
Resolves #7784
🦋 Changeset detectedLatest commit: 5f7d987 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
✅ Deploy Preview for mermaid-js ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
@mermaid-js/examples
mermaid
@mermaid-js/layout-elk
@mermaid-js/layout-tidy-tree
@mermaid-js/mermaid-zenuml
@mermaid-js/parser
@mermaid-js/tiny
commit: |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #7785 +/- ##
==========================================
- Coverage 3.25% 3.24% -0.01%
==========================================
Files 600 601 +1
Lines 60960 61143 +183
Branches 917 918 +1
==========================================
Hits 1986 1986
- Misses 58974 59157 +183
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
The latest updates on your projects. Learn more about Argos notifications ↗︎
|
Covers an edge that targets the deepest node (two levels in) while the outermost subgraph is collapsed — the edge should redirect to the outermost collapsed node.
ashishjain0512
left a comment
There was a problem hiding this comment.
[sisyphus-bot]
Thanks for this — collapsible subgraphs is a frequently requested feature (#7784) and this is a really clean take on it. I read the full diff, ran an XSS/injection pass over the new shape and the metadata-routing changes, and verified the collapse/redirect logic against the unit and parser tests. Summary below; one important gap (docs) and a few small polish items, nothing blocking.
What's working well
- 🎉 Reusing
id@{ ... }instead of a grammar change. Routing subgraph metadata through the existingaddVertexpath (flowDb.ts:154 area) is exactly the right call — it avoids touching the JISON grammar, keeps the syntax consistent with node metadata, and means zero parser-regression risk. Nicely reasoned in the commit message too. - 🎉 Excellent test coverage for the scope. Unit tests in
flowDb.spec.tscover the normal-group baseline, collapse-to-single-node, boundary-edge redirect, internal-edge drop (self-loop avoidance), and nested outermost-ancestor resolution. The parser test and five e2e snapshots (including a handDrawn case and a deeply-nested redirect) round it out. This is the kind of coverage that makes a shared-rendering change safe to merge. - 🎉 Hand-drawn mode implemented from the start in
collapsedGroup.tsvia the rough.js path — not deferred, which is great. - 🎉 The edge-redirect logic is genuinely correct. I traced the
outermostCollapsedcontainment walk (with theseencycle guard) and the self-loop-vs-internal-edge distinction — thestart === end && (map.has(start) || map.has(end))guard correctly drops internal edges while preserving real self-loops on uncollapsed nodes. The nested case resolving to the outermost ancestor is handled well.
Security
XSS/injection review: clean. The @{ view: ... } value is parsed via yaml.load, only ever compared === 'collapsed' to select a literal shape string, and never reaches a DOM sink. The subgraph title flows through the same shared labelHelper (which sanitizes) as the existing expanded rect branch, and the new shape emits only plain rect/line/circle nodes that pass through the normal DOMPurify boundary. No new tags/attributes, no foreignObject/<use>/event handlers. No widening of the attack surface.
Things to address
- 🟡 [important] Missing user-facing documentation for the new syntax. This PR introduces a brand-new public syntax (
subgraphId@{ view: collapsed }) but adds no docs inpackages/mermaid/src/docs/syntax/flowchart.md(the only doc changes are the auto-generated interface line-number shifts). The subgraphs section is around flowchart.md:894 — it'd be great to add a short subsection there with an example, so the feature is discoverable. Remember to use theMERMAID_RELEASE_VERSIONplaceholder for the version.
Nits & suggestions
- 🟢 [nit] Import ordering in
shapes.ts:6—collapsedGroupis inserted betweenbowTieRectandcard, but alphabetically it sorts aftercard(ca<co). Minor, just for consistency with the rest of the block. - 🟢 [nit]
collapsedGroup.ts:585—const labelEl = shapeSvg.select('.label'); if (labelEl)is always truthy (d3selectreturns a non-null selection even when empty). If the intent is to guard against a missing label, useif (!labelEl.empty()). Harmless as-is since.attr()on an empty selection is a no-op. - 💡 [suggestion] When several edges from the same external node target different internal members of one collapsed subgraph (e.g.
X-->AandX-->BwithA,Bcollapsed), they redirect to two parallelX-->collapsededges with distinct counter-based ids. Functionally fine, but it renders as duplicate arrows. Deduplicating redirected edges on(start, end, label)could tidy that up — worth considering, not required for this PR. - 💡 [suggestion] The early
returnin the new subgraph-metadata branch ofaddVertexmeans anysubgraphId@{ ... }now routes all keys tosubGraph.metadata(onlyviewis consumed) and skips vertex creation. That's the right behavior forview, but worth a one-line comment noting other metadata keys on a subgraph id are intentionally ignored, so a future reader doesn't expect e.g.shapeto apply there.
Really solid work overall — once the docs are in, this is good to go. Let me know if you'd like a hand with the docs example. 🚀
🤖 Automated review. Severity: 0 blocking / 1 important / 2 nit / 2 suggestion / 4 praise.
Summary
Resolves #7784
Adds opt-in collapsible subgraphs to the flowchart. A subgraph annotated with
@{ view: collapsed }is rendered as a single compact node instead of an expanded container:flowchart TD Start --> one subgraph one [My Group] A --> B B --> C end one --> End one@{ view: collapsed }How it works
id@{ ... }statement syntax —addVertexdetects when the id refers to a declared subgraph and routes the metadata onto it. No grammar change is required.flowDb.getData().collapsedGroupshape renders the compact node (title + dashed separator + ellipsis indicator), reusing the cluster theme variables.Classification
rendering-util(new shape)view: collapsedsyntax; existing diagrams produce identical output. The new shape is purely additive.rendering-util/rendering-elements/shapes/collapsedGroup.ts+ one registration entry inshapes.ts(additive only; follows the existing pattern forkanbanItem/classBox/erBox).Verification
vitest run packages/mermaid/src/diagrams/flowchart/)cypress/integration/rendering/flowchart/flowchart-v2.spec.js(collapsed, side-by-side, hand-drawn, nested)--no-sandbox; suite is heavy) — covered by the new snapshot tests in CIminor)