-
-
Save MLKrisJohnson/2d2df47879ee6afd3be9d6788241fe99 to your computer and use it in GitHub Desktop.
| { | |
| "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 | |
| } |
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
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!
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 (usingdisplay()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...
thanks