Skip to content

Three small improvements for embedding dlin diagrams in docs and PRs #166

Description

@adam-stone-zocdoc

Context

I use dlin to generate dbt lineage diagrams for design docs and pull request descriptions. The DOT output piped through Graphviz gets very close to being directly embeddable, and three small changes would get it the rest of the way. Let me know what you think and I can open PRs for these!


1. Optional suppression of redundant edge labels

DOT and Mermaid output label every edge with its dependency type (label="ref"). When every edge in a graph is the same type, the labels are pure noise and they measurably inflate the rendered image.

On a 31-node graph, dropping them took the PNG from 3576x1450 to 3439x966 — a 33% height reduction, purely from removing repeated text.

Today I do this post-process:

dlin graph <model> --no-transitive -o dot | sed -E 's/ *\[label="ref"\]//'

Proposal: a --no-edge-labels flag, or omit the label automatically when all edges in the output share one type.

2. Wrap long node labels

Some teams' dbt naming conventions produce long model names, often with a __ separator between domain and entity. Rendered as single-line labels these create very wide nodes, and the resulting image is far wider than it is tall — awkward to embed in a document or a PR, where it renders as a thin unreadable strip.

Wrapping labels at the __ boundary on the same 31-node graph:

Dimensions Aspect ratio
Single-line labels 3439x966 3.56:1
Wrapped at __ 2300x1028 2.24:1

A 33% width reduction, and the result is comfortably embeddable.

Proposal: a --wrap-labels[=<SEPARATOR>] flag, defaulting to __, or a generic max-width character wrap. Applies to DOT and Mermaid (both support multi-line labels — \n and <br/> respectively).

3. Draggable nodes in -o html

The HTML output is genuinely useful — self-contained, no external requests, with pan, zoom, search and a detail panel. The one thing people reach for and don't find is dragging a node to untangle a dense area.

The emitted markup already has everything needed:

  • edges carry data-source / data-target
  • nodes are <g data-id="..." class="node">
  • the canvas pan handler already has if (e.target.closest('.node')) return;, so mousedown on a node currently falls through unused
  • the full adjacency map is already serialized client-side as const data

So this looks like it could be JS-only inside the existing IIFE — recompute the incident edge paths on drag — with no changes to the layout engine, no new dependencies, and no change to -o svg.

Three things worth flagging for whoever implements it:

  • pan/zoom is a CSS transform with a scale variable; mouse deltas need dividing by scale or drags desync when zoomed
  • a source/target pair isn't unique (multi-edges), so edge lookup needs querySelectorAll
  • the self-loop bezier formula degenerates and needs a NaN guard

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