Streamlit 中使用 Mermaid 流程图

First Post:

Last Update:

St.markdown does not render mermaid graphs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def mermaid(code: str) -> None:
components.html(
f"""
<pre class="mermaid">
{code}
</pre>

<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({{ startOnLoad: true }});
</script>
"""
)

mermaid("""
graph LR
A --> B --> C
""")

带动态高度调整的完整版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
from time import sleep
import streamlit as st
from streamlit.components.v1 import html
from streamlit_js_eval import streamlit_js_eval

if "svg_height" not in st.session_state:
st.session_state["svg_height"] = 200

if "previous_mermaid" not in st.session_state:
st.session_state["previous_mermaid"] = ""

def mermaid(code: str) -> None:
html(
f"""
<pre class="mermaid">
{code}
</pre>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({{ startOnLoad: true }});
</script>
""",
height=st.session_state["svg_height"] + 50,
)

selection = st.selectbox("Choose example", ["Simple", "Class Diagram", "Flowchart"])

if selection == "Simple":
code = """
graph LR
A --> B --> C
"""
elif selection == "Class Diagram":
code = """
classDiagram
Animal <|-- Duck
Animal <|-- Fish
Animal <|-- Zebra
Animal : +int age
class Duck{ +String beakColor +swim() +quack() }
class Fish{ -int sizeInFeet -canEat() }
class Zebra{ +bool is_wild +run() }
"""
else:
code = """
graph TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
"""

mermaid(code)

if code != st.session_state["previous_mermaid"]:
st.session_state["previous_mermaid"] = code
sleep(1)
streamlit_js_eval(
js_expressions='parent.document.getElementsByTagName("iframe")[0].contentDocument.getElementsByClassName("mermaid")[0].getElementsByTagName("svg")[0].getBBox().height',
key="svg_height",
)