From Add Mermaid pane · Issue #2733 · holoviz/panel · GitHub
import param
import panel as pn
from panel.custom import JSComponent
pn.extension()
class MermaidDiagram(JSComponent):
value = param.String(default="graph TD; A-->B; A-->C; B-->D; C-->D;")
_esm = """
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: false });
export async function render({ model, el }) {
const { svg } = await mermaid.render('graphDiv', model.value);
el.innerHTML = svg; // Set the rendered SVG in the container
}
"""
_importmap = {
"imports": {
"mermaid": "https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs"
}
}
diagram = MermaidDiagram(
value=(
"""
graph LR
A --- B
B-->C[fa:fa-ban forbidden]
B-->D(fa:fa-spinner);
"""
)
)
diagram.show()
2 Likes
Marc
2
I played a bit around with it. Adding the ability to update the diagram and the config.
Try on PY.CAFE
import panel as pn
import param
from panel.custom import JSComponent
from panel.widgets import WidgetBase
pn.extension()
class MermaidConfiguration(pn.viewable.Viewer, WidgetBase):
value = param.Dict(constant=True)
look = param.Selector(default="classic", objects=["classic", "handDrawn"])
theme = param.Selector(
default="default", objects=["default", "forest", "dark", "neutral"]
)
@param.depends("look", "theme", watch=True, on_init=True)
def _update_value(self):
with param.edit_constant(self):
self.value = {"look": self.look, "theme": self.theme}
def __panel__(self):
return pn.Column("### Mermaid Configuration", self.param.look, self.param.theme)
class MermaidDiagram(JSComponent):
"""A MermaidDiagram Pane
Example:
diagram = MermaidDiagram(
object=(
'''
graph LR
A --- B
B-->C[fa:fa-ban forbidden]
B-->D(fa:fa-spinner);
'''
)
)
"""
object = param.String(default="")
configuration = param.Dict({}, allow_refs=True)
_esm = """
import mermaid from 'mermaid';
async function getSVG(object) {
if (object) {
const { svg } = await mermaid.render('graphDiv', object);
return svg;
} else {
return null;
}
}
export async function render({ model, el }) {
function update_configuration(){
const config = {...model.configuration, startOnLoad: false};
mermaid.initialize(config);
}
update_configuration();
async function update_object() {
el.innerHTML = await getSVG(model.object);
}
await update_object();
model.on('object', update_object);
model.on('configuration', ()=>{update_configuration();update_object()});
}
"""
_importmap = {
"imports": {
"mermaid": "https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs"
}
}
examples = {
"Default": """
graph LR
A --- B
B-->C[fa:fa-ban forbidden]
B-->D(fa:fa-spinner);
""",
"Architecture": """
architecture-beta
group api(cloud)[API]
service db(database)[Database] in api
service disk1(disk)[Storage] in api
service disk2(disk)[Storage] in api
service server(server)[Server] in api
db:L -- R:server
disk1:T -- B:server
disk2:T -- B:db
""",
}
config = MermaidConfiguration()
diagram = MermaidDiagram(
configuration=config, styles={"border": "1px solid black"}, width=500
)
example = pn.widgets.Select(options=examples, name="Example")
@param.depends(example, watch=True)
def update(object):
diagram.object = object
update(example.value)
pn.Column(config, example, diagram).servable()
1 Like
We should make a pane out of this
1 Like
Marc
4
I’ve released awesome-panel/panel-mermaid.
pip install panel-mermaid
1 Like