Render technical diagrams with mermaid

This commit is contained in:
Ruslan Bakiev
2026-05-01 14:41:02 +07:00
parent fc6117c8f5
commit 3a3bd09a8c
20 changed files with 1191 additions and 391 deletions

View File

@@ -0,0 +1,94 @@
<script setup lang="ts">
import mermaid from 'mermaid';
import { computed, onMounted, ref, watch } from 'vue';
const props = defineProps<{
chart: string;
}>();
const svg = ref('');
const error = ref('');
let initialized = false;
let diagramId = 0;
function initMermaid() {
if (initialized) {
return;
}
mermaid.initialize({
startOnLoad: false,
theme: 'neutral',
securityLevel: 'strict',
fontFamily: 'Inter, Arial, sans-serif',
flowchart: {
useMaxWidth: true,
htmlLabels: true,
},
});
initialized = true;
}
const source = computed(() => props.chart.trim());
async function renderDiagram() {
if (!import.meta.client) {
return;
}
try {
initMermaid();
error.value = '';
diagramId += 1;
const { svg: result } = await mermaid.render(`mermaid-diagram-${diagramId}`, source.value);
svg.value = result;
} catch (cause) {
svg.value = '';
error.value = cause instanceof Error ? cause.message : 'Failed to render Mermaid diagram.';
}
}
onMounted(() => {
void renderDiagram();
});
watch(source, () => {
void renderDiagram();
});
</script>
<template>
<div class="mermaid-diagram">
<div v-if="error" class="mermaid-diagram__error">{{ error }}</div>
<div v-else class="mermaid-diagram__canvas" v-html="svg" />
</div>
</template>
<style scoped>
.mermaid-diagram {
margin: 1.25rem 0 1.75rem;
border: 1px solid #d9dee7;
border-radius: 20px;
background: #fff;
overflow: hidden;
}
.mermaid-diagram__canvas {
padding: 1rem;
}
.mermaid-diagram__canvas :deep(svg) {
display: block;
width: 100%;
height: auto;
}
.mermaid-diagram__error {
padding: 1rem 1.25rem;
color: #b42318;
background: #fef3f2;
font-size: 0.95rem;
}
</style>