Skip to content

Instantly share code, notes, and snippets.

@MLKrisJohnson
Last active November 21, 2025 10:13
Show Gist options
  • Select an option

  • Save MLKrisJohnson/2d2df47879ee6afd3be9d6788241fe99 to your computer and use it in GitHub Desktop.

Select an option

Save MLKrisJohnson/2d2df47879ee6afd3be9d6788241fe99 to your computer and use it in GitHub Desktop.
Displaying Mermaid Diagrams in a Jupyter Notebook Using Python
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Displaying Mermaid Diagrams in a Jupyter Notebook Using Python\n",
"\n",
"This code is based upon code at <https://mermaid.js.org/config/Tutorials.html#jupyter-integration-with-mermaid-js>."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<img src=\"https://mermaid.ink/img/CmdyYXBoIExSOwogICAgQS0tPiBCICYgQyAmIEQ7CiAgICBCLS0+IEEgJiBFOwogICAgQy0tPiBBICYgRTsKICAgIEQtLT4gQSAmIEU7CiAgICBFLS0+IEIgJiBDICYgRDsK\"/>"
],
"text/plain": [
"<IPython.core.display.Image object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import base64\n",
"from IPython.display import Image, display\n",
"\n",
"def mm_ink(graphbytes):\n",
" \"\"\"Given a bytes object holding a Mermaid-format graph, return a URL that will generate the image.\"\"\"\n",
" base64_bytes = base64.b64encode(graphbytes)\n",
" base64_string = base64_bytes.decode(\"ascii\")\n",
" return \"https://mermaid.ink/img/\" + base64_string\n",
"\n",
"def mm_display(graphbytes):\n",
" \"\"\"Given a bytes object holding a Mermaid-format graph, display it.\"\"\"\n",
" display(Image(url=mm_ink(graphbytes)))\n",
"\n",
"def mm(graph):\n",
" \"\"\"Given a string containing a Mermaid-format graph, display it.\"\"\"\n",
" graphbytes = graph.encode(\"ascii\")\n",
" mm_display(graphbytes)\n",
"\n",
"def mm_link(graph):\n",
" \"\"\"Given a string containing a Mermaid-format graph, return URL for display.\"\"\"\n",
" graphbytes = graph.encode(\"ascii\")\n",
" return mm_ink(graphbytes)\n",
" \n",
"def mm_path(path):\n",
" \"\"\"Given a path to a file containing a Mermaid-format graph, display it\"\"\"\n",
" with open(path, 'rb') as f:\n",
" graphbytes = f.read()\n",
" mm_display(graphbytes)\n",
"\n",
"mm(\"\"\"\n",
"graph LR;\n",
" A--> B & C & D;\n",
" B--> A & E;\n",
" C--> A & E;\n",
" D--> A & E;\n",
" E--> B & C & D;\n",
"\"\"\")"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<img src=\"https://mermaid.ink/img/Z3JhcGggTFI7CiAgICBBLS0+IEIgJiBDICYgRDsKICAgIEItLT4gQSAmIEU7CiAgICBDLS0+IEEgJiBFOwogICAgRC0tPiBBICYgRTsKICAgIEUtLT4gQiAmIEMgJiBEOwo=\"/>"
],
"text/plain": [
"<IPython.core.display.Image object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"mm_path('test.mmd')"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'https://mermaid.ink/img/CmdyYXBoIExSOwogICAgQS0tPiBCICYgQyAmIEQ7CiAgICBCLS0+IEEgJiBFOwogICAgQy0tPiBBICYgRTsKICAgIEQtLT4gQSAmIEU7CiAgICBFLS0+IEIgJiBDICYgRDsK'"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mm_link(\"\"\"\n",
"graph LR;\n",
" A--> B & C & D;\n",
" B--> A & E;\n",
" C--> A & E;\n",
" D--> A & E;\n",
" E--> B & C & D;\n",
"\"\"\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "ai",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.7"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@JeevansSP
Copy link

thanks

@diraneyya
Copy link

diraneyya commented Mar 20, 2025

To do it in SVG instead which gives more visually-pleasing results:

import base64
from IPython.display import display_svg
from urllib.request import Request, urlopen

def mm(graph):
    graphbytes = graph.encode("ascii")
    base64_bytes = base64.b64encode(graphbytes)
    base64_string = base64_bytes.decode("ascii")
    url="https://mermaid.ink/svg/" + base64_string
    req=Request(url, headers={'User-Agent': 'IPython/Notebook'})
    display_svg(urlopen(req).read().decode(), raw=True)

More information can be found at https://gist.github.com/diraneyya/1177344d2ead2185c0316f8b5f6ef67b

@diraneyya
Copy link

I have to say that this is the first time I learn that .mmd is rendered as a Mermaid diagram in GitHub. I know that .md files do not support Mermaid in Gists which is why this is actually very useful. I am also pleased to see that there are two files in this Gist, which illustrates that Gists are actually just git repositories. Thank you!

@cben
Copy link

cben commented Jun 22, 2025

Does display_svg(..., raw=True) work well for you?
In Jupyter sure, but most ways I tried of embedding SVG into notebook don't render well on NBViewer/GitHub/GitLab/both. Images linking to src="https://mermaid.ink/..." is fine, it's the actually embedding the image into .ipynb that's giving me trouble. [old man yelling at cloud]

  • Disabling %%{init: { "htmlLabels": false, "flowchart": { "htmlLabels": false } } }%%, when possible, generally makes SVG more compatible. Not enough β€” before / after β€” but hopefully more future-proof.
  • NBViewer issue, looks like GitHub uses β‰ˆsame code? GitLab OTOH renders SVG practically fine πŸ‘
  • With current JupyterLab (4.4.3), I don't even need external conversion services! Turns out that emitting "text/vnd.mermaid" MIME type not only renders locally, but adds back the SVG representation to the cell, and saves that to .ipynb ✨
    Combined with GitLab hosting, is closest I found to the holy grail of locally authorable & locally viewable & easy to share notebooks.
    https://gitlab.com/cben/sandbox/blob/6bdb770ff0a64e5187eed927b71ef866c056e70d/jupyter_notebook/mermaid_mime_type.ipynb (using display() for side-effect output), https://gitlab.com/cben/ipywm-notes/-/blob/8bc4e93498af3371ee04e8c899b2ae23e8296d5c/HANDOFF.ipynb (a Mermaid class with rich repr + magic).
  • ```mermaid fenced blocks render fine in markdown files on GitHub/GitLab β€” but not yet in markdown notebook cells.
    For now, splitting diagrams to separate code cells is best solution I found :-/ Unfortunately, "Collapse code" to hide the diagram source in Jupyter is NOT honored by GitLab rendering.
  • GitLab renders SVGs with pretty low height; scrollable but it doesn't know the "true" size of the diagram, cause it sticks it in an iframe πŸ™ˆ.
    Ooof, those mermaid.ink external images are maybe not so bad? 😜
    πŸ€” personally, I'll take the imperfect-yet-working GitLab as good enough; people who want better view can clone & open notebook locally...

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