Skip to content

Comment on individual Mermaid nodes and edges #1470

Description

@bendrucker

I'm happy to work on this one, but wanted to track the proposal first, especially given the related issue.

A rendered Mermaid diagram is currently an all-or-nothing annotation target. Pinpoint skips it entirely (data-pinpoint-ignore on the grab container, added in #819 so that releasing a pan-drag stopped creating a whole-block annotation), and text selection is excluded along with it. The only way to comment on a diagram today is to toggle Show source and annotate the whole fenced block as one code block, which points the agent at the entire diagram.

Reviewers want to point at a specific node, edge, edge label, or subgraph and say what is wrong with that one thing.

Relation to existing issues

#911 tracks diagram generation and iteration and does not cover annotating a rendered diagram. Its one comment asks for something adjacent: freehand circling on a Mermaid diagram, with the resulting image handed back to a multimodal agent. That is a different mechanism (raster capture through the Image Annotator) reaching for a similar goal, and the two can coexist. Structured targeting gives the agent the source identifier of the thing being discussed. Freehand gives it a picture.

Nothing else in the tracker covers per-element diagram commenting.

Feasibility

I rendered the common diagram types through the pinned Mermaid 11 configuration (securityLevel: 'strict', htmlLabels: true) in a browser and inspected the emitted SVG and its hit behavior.

Mermaid emits source-derived identity for flowchart, class, state, and ER diagrams:

Surface DOM Anchor
Node <g id="flowchart-A-0" class="node"> source key A
Edge <path id="L_A_B_0" class="flowchart-link"> fully semantic
Subgraph <g id="grp" class="cluster"> source id verbatim
Edge label <g class="edgeLabel"> ordinal plus text

Re-rendering identical source reproduces those ids exactly. Inserting a node upstream shifts only the trailing counter (flowchart-A-0 becomes flowchart-A-1) while the source key and every edge id survive unchanged. So the durable anchor is the source key plus a text snapshot, resolved back through g.node[id^="flowchart-A-"] and verified against the snapshot. That is the same fail-closed shape as the existing HtmlElementAnchor.

Sequence, pie, and gantt diagrams carry no source-derived ids. Actors are #root-0, pie slices are anonymous path.pieCircle. Those degrade to class, ordinal, and text.

Hit-testing needs one instrumentation pass. Untouched, clicking an edge misses it: edge paths are 1px fill:none strokes, and foreignObject label boxes sit on top and absorb the hit. Cloning each edge path as a transparent stroke-width:16; pointer-events:stroke sibling, then setting pointer-events:none on foreignObject and auto on the label spans, makes every surface resolve correctly from elementFromPoint plus closest(). I confirmed this in the browser for nodes, edges, edge labels, and the subgraph frame. closest() crosses the foreignObject boundary, so a click on a node's HTML label resolves to its <g>.

Painting is cheaper here than on the HTML surface. A highlight rect derived from getBBox() and inserted inside the annotated <g> lives in the diagram's own coordinate space. It pans and zooms with the diagram for free and clips naturally when panned out of view, so there is no overlay reprojection to maintain.

Proposal

Add a diagram target kind to the existing Pinpoint pipeline.

  • Anchor. A new additive field on Annotation, alongside mathTargets and htmlAnchor: { kind: 'node' | 'edge' | 'edgeLabel' | 'cluster', sourceKey, label }. Resolution matches on the source key and verifies the label snapshot, failing closed when the diagram has changed underneath.
  • Targeting. usePinpoint already branches out of the range path for code blocks. A diagram branch slots in the same way, fed by a resolver over the instrumented SVG.
  • Pointer conflict. Keep pan and zoom. Discriminate a click from a drag by movement threshold on mouseup, which is the failure Fix Mermaid block sizing, zoom retention, and pinpoint drag #819 fixed by excluding the block outright.
  • Export. Match the source key back to its line in the fence body so the exported feedback quotes the real Mermaid source (B -->|no| C[(Database)]) rather than only a rendered label, and derive startOffset from that line so the existing export ordering holds.

Scope

Comparable to the math annotation feature, not to the raw-HTML pinpoint surface. Server-side changes are not required.

  • Flowchart family first, where identity is strong.
  • Ordinal-anchored families (sequence, pie, gantt) as a follow-up, or explicitly out of scope for a first version.

Risks

  • data-pinpoint-ignore must be narrowed rather than removed. Text selection has to stay excluded, or web-highlighter will attempt to mark inside foreignObject.
  • The SVG is re-injected through dangerouslySetInnerHTML on content change, and the expanded view remounts it into a portal. Annotations must be re-resolved on each, under the same contract onCodeHighlightSwap already enforces for code-block marks.
  • Share links will not carry diagram anchors. That is the existing documented contract for htmlAnchor, which restores by text search only. Either extend the share payload or accept the degradation.
  • The text-selection path is not a viable alternative. With htmlLabels: true the labels are real HTML and selectable, but offsets would address the fence source, which has no correspondence to the rendered label.

Open decisions

  • Whether the ordinal-anchored diagram families ship at all, given that their anchors break on any reordering.
  • Whether freehand circling from the Visual plan and diagram workflows #911 comment is the same feature or a separate one.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions