Yog.Render.Mermaid (YogEx v0.98.0)

Copy Markdown View Source

Mermaid.js format export for embedding diagrams in web pages and documents.

This module exports graphs to Mermaid syntax, a JavaScript-based diagramming tool that renders diagrams from text definitions. Mermaid is supported natively in GitHub, GitLab, Notion, and many other platforms.

Quick Start

# Export to Mermaid syntax
mermaid = Yog.Render.Mermaid.to_mermaid(my_graph, Yog.Render.Mermaid.default_options())

# Use in Markdown:
# ```mermaid
# graph TD
#     A[Node 1] --> B[Node 2]
# ```

Supported Diagram Types

This module generates flowchart-style diagrams:

  • Graph TD: Top-down (vertical) layout
  • Graph LR: Left-to-right (horizontal) layout
  • Graph BT: Bottom-to-top layout
  • Graph RL: Right-to-left layout

Customization

Control styling via options/0:

  • Node shapes (rounded, rectangular, circular, rhombus, hexagon, etc.)
  • Labels and edge annotations
  • Highlight specific nodes or edges
  • Per-node and per-edge styling (custom colors, stroke widths, etc.)
  • Subgraphs for visual grouping
  • Direction and orientation
  • CSS-based styling with custom lengths

Per-Element Styling

Provide custom attribute functions for fine-grained control:

options = %{
  Yog.Render.Mermaid.default_options() |
  node_attributes: fn id, data ->
    case id do
      1 -> [{:fill, "#e1f5fe"}, {:stroke, "#0288d1"}]
      _ -> []
    end
  end,
  edge_attributes: fn from, to, weight ->
    if weight > 10 do
      [{:stroke, "#d32f2f"}, {:stroke_width, "3px"}]
    else
      []
    end
  end
}

Subgraphs

Group nodes visually using subgraphs:

options = %{
  Yog.Render.Mermaid.default_options() |
  subgraphs: [
    %{
      name: "Group A",
      label: "Cluster A",
      node_ids: [1, 2, 3]
    }
  ]
}

Embedding Options

PlatformMethod
GitHub/GitLabNative Markdown support
NotionMermaid code block
VS CodeMermaid extension
Static siteMermaid.js library
JupyterMermaid magic commands

Live Editor

Test and refine diagrams at Mermaid Live Editor.

References

Summary

Types

CSS length unit for styling.

Direction for graph layout

Node shape options for Mermaid diagrams.

Options for customizing Mermaid diagram rendering

A subgraph for grouping nodes visually in the diagram.

Functions

Creates Mermaid options that color nodes by community assignment.

Creates Mermaid options that color the source and sink sides of a min-cut.

Creates default Mermaid options with simple labeling.

Creates default Mermaid options with custom label formatters for both nodes and edges.

Creates default Mermaid options with a custom edge formatter.

Creates default Mermaid options with all edge labels hidden.

Creates Mermaid options that highlight matched edges from a matching result.

Creates Mermaid options that highlight an MST result.

Converts a shortest path result to highlighted Mermaid options.

Returns a pre-configured theme as Mermaid options.

Converts a graph to Mermaid diagram syntax.

Types

css_length()

@type css_length() ::
  {:px, integer()}
  | {:em, float()}
  | {:rem, float()}
  | {:percent, float()}
  | {:custom, String.t()}

CSS length unit for styling.

Mermaid supports various CSS length units:

  • :px - Pixels (most common)
  • :em - Ems (relative to font size)
  • :rem - Rems (relative to root font size)
  • :percent - Percentage
  • {:custom, string} - Custom CSS value (for advanced users)

direction()

@type direction() :: :td | :lr | :bt | :rl

Direction for graph layout

node_shape()

@type node_shape() ::
  :rounded_rect
  | :stadium
  | :subroutine
  | :cylinder
  | :circle
  | :asymmetric
  | :rhombus
  | :hexagon
  | :parallelogram
  | :parallelogram_alt
  | :trapezoid
  | :trapezoid_alt

Node shape options for Mermaid diagrams.

Each shape has a specific Mermaid syntax:

  • :rounded_rect - [label] - Rectangle with rounded corners
  • :stadium - ([label]) - Stadium shape (pill)
  • :subroutine - [[label]] - Subroutine shape (rectangle with side lines)
  • :cylinder - [(label)] - Cylindrical shape (database)
  • :circle - ((label)) - Circle
  • :asymmetric - >label] - Asymmetric shape (flag)
  • :rhombus - {label} - Rhombus (decision)
  • :hexagon - {{label}} - Hexagon
  • :parallelogram - [/label/] - Parallelogram
  • :parallelogram_alt - [\label\] - Parallelogram alt
  • :trapezoid - [/label\] - Trapezoid
  • :trapezoid_alt - [\label/] - Trapezoid alt

options()

@type options() :: %{
  node_label: (Yog.node_id(), any() -> String.t()),
  edge_label: (any() -> String.t()),
  highlighted_nodes: [Yog.node_id()] | nil,
  highlighted_edges: [{Yog.node_id(), Yog.node_id()}] | nil,
  node_attributes: (Yog.node_id(), any() -> [{atom(), String.t()}]),
  edge_attributes: (Yog.node_id(), Yog.node_id(), any() ->
                      [{atom(), String.t()}]),
  subgraphs: [subgraph()] | nil,
  direction: direction(),
  node_shape: node_shape() | (Yog.node_id(), any() -> node_shape()),
  default_fill: String.t() | nil,
  default_stroke: String.t() | nil,
  default_stroke_width: css_length() | nil,
  default_font_color: String.t() | nil,
  default_link_stroke: String.t() | nil,
  highlight_fill: String.t(),
  highlight_stroke: String.t(),
  highlight_stroke_width: css_length(),
  link_thickness: css_length(),
  highlight_link_stroke: String.t(),
  highlight_link_stroke_width: css_length()
}

Options for customizing Mermaid diagram rendering

subgraph()

@type subgraph() :: %{
  name: String.t(),
  label: String.t() | nil,
  node_ids: [Yog.node_id()] | nil
}

A subgraph for grouping nodes visually in the diagram.

Functions

community_to_options(map, base_options \\ default_options())

@spec community_to_options(Yog.Community.Result.t(), options()) :: options()

Creates Mermaid options that color nodes by community assignment.

Each community gets a distinct color from a generated palette. The palette cycles through visually distinct hues using inline node styles.

Example

result = Yog.Community.Louvain.detect(graph)
options = Yog.Render.Mermaid.community_to_options(result)
mermaid = Yog.Render.Mermaid.to_mermaid(graph, options)

cut_to_options(map, base_options \\ default_options())

@spec cut_to_options(Yog.Flow.MinCutResult.t(), options()) :: options()

Creates Mermaid options that color the source and sink sides of a min-cut.

Source-side nodes are colored with source_color (default: light blue), sink-side nodes with sink_color (default: light coral).

Requires the MinCutResult to have source_side and sink_side populated (use track_partitions: true or extract_min_cut/1).

Example

result = Yog.Flow.MinCut.global_min_cut(graph, track_partitions: true)
options = Yog.Render.Mermaid.cut_to_options(result)
mermaid = Yog.Render.Mermaid.to_mermaid(graph, options)

default_options()

@spec default_options() :: options()

Creates default Mermaid options with simple labeling.

Uses node ID as label and edge weight as-is. Default configuration:

  • Direction: Top-to-bottom (TD)
  • Node shape: Rounded rectangle
  • Highlight: Yellow fill with orange stroke

Examples

iex> opts = Yog.Render.Mermaid.default_options()
iex> opts.direction
:td
iex> opts.node_shape
:rounded_rect
iex> opts.highlight_fill
"#ffeb3b"

default_options_with(list)

@spec default_options_with(
  node_label: (Yog.node_id(), any() -> String.t()),
  edge_label: (any() -> String.t())
) :: options()

Creates default Mermaid options with custom label formatters for both nodes and edges.

Example

options = Yog.Render.Mermaid.default_options_with(
  node_label: fn id, data -> "#{data} (#{id})" end,
  edge_label: fn weight -> "#{weight} ms" end
)

default_options_with_edge_formatter(edge_formatter)

@spec default_options_with_edge_formatter((any() -> String.t())) :: options()

Creates default Mermaid options with a custom edge formatter.

Use this when your graph has non-String edge data (e.g., Int, Float, custom types).

Example

# For a graph with Int edge weights
options = Yog.Render.Mermaid.default_options_with_edge_formatter(fn weight ->
  Integer.to_string(weight)
end)

default_options_without_labels()

@spec default_options_without_labels() :: options()

Creates default Mermaid options with all edge labels hidden.

Use this when you want a clean diagram without edge annotations.

Example

mermaid = Yog.Render.Mermaid.to_mermaid(graph,
  Yog.Render.Mermaid.default_options_without_labels()
)

matching_to_options(matching, base_options \\ default_options())

@spec matching_to_options(%{required(Yog.node_id()) => Yog.node_id()}, options()) ::
  options()

Creates Mermaid options that highlight matched edges from a matching result.

Works with results from both Yog.Matching.hopcroft_karp/1 and Yog.Matching.hungarian/2 (the matching map component).

Example

matching = Yog.Matching.hopcroft_karp(graph)
options = Yog.Render.Mermaid.matching_to_options(matching)
mermaid = Yog.Render.Mermaid.to_mermaid(graph, options)

mst_to_options(result, base_options \\ default_options())

@spec mst_to_options(Yog.MST.Result.t(), options()) :: options()

Creates Mermaid options that highlight an MST result.

MST edges are highlighted and MST nodes use default styling.

Example

result = Yog.MST.kruskal(graph)
options = Yog.Render.Mermaid.mst_to_options(result)
mermaid = Yog.Render.Mermaid.to_mermaid(graph, options)

path_to_options(path, base_options \\ default_options())

@spec path_to_options(map(), options()) :: options()

Converts a shortest path result to highlighted Mermaid options.

Creates a copy of the base options with the path's nodes and edges set to be highlighted.

Example

case Yog.Pathfinding.Dijkstra.shortest_path(...) do
  {:ok, path} ->
    options = Yog.Render.Mermaid.path_to_options(path, Yog.Render.Mermaid.default_options())
    mermaid = Yog.Render.Mermaid.to_mermaid(graph, options)
  :error ->
    ""
end

theme(atom)

@spec theme(atom()) :: options()

Returns a pre-configured theme as Mermaid options.

Available themes:

  • :default — Yellow highlight, orange stroke (same as default_options/0)
  • :dark — Dark-friendly colors with neon accent colors
  • :minimal — Clean wireframe look with no fills and thin lines
  • :presentation — Large strokes and bold colors for slides and demos

Examples

iex> opts = Yog.Render.Mermaid.theme(:dark)
iex> opts.highlight_fill
"#16213e"
iex> opts.highlight_stroke
"#e94560"

iex> opts = Yog.Render.Mermaid.theme(:minimal)
iex> opts.link_thickness
{:px, 1}

iex> opts = Yog.Render.Mermaid.theme(:presentation)
iex> opts.highlight_stroke_width
{:px, 4}

to_mermaid(graph, options \\ default_options())

@spec to_mermaid(Yog.graph(), options()) :: String.t()

Converts a graph to Mermaid diagram syntax.

The graph's node data and edge data must be convertible to strings. Use the options to customize labels, styling, and to define subgraphs.

Time Complexity: O(V + E + S) where S is the total number of nodes across all subgraphs.

Example

graph =
  Yog.directed()
  |> Yog.add_node(1, "Start")
  |> Yog.add_node(2, "Process")
  |> Yog.add_node(3, "End")
  |> Yog.add_edge_ensure(from: 1, to: 2, with: "5")
  |> Yog.add_edge_ensure(from: 2, to: 3, with: "3")

# Basic rendering
diagram = Yog.Render.Mermaid.to_mermaid(graph, default_options())

# Highlight a path
options = %{
  default_options() |
  highlighted_nodes: [1, 2, 3],
  highlighted_edges: [{1, 2}, {2, 3}]
}
highlighted = Yog.Render.Mermaid.to_mermaid(graph, options)

The output can be embedded in markdown:

```mermaid
graph TD
  1["Start"]
  2["Process"]
  3["End"]
  1 -->|5| 2
  2 -->|3| 3
```