Mermaid text, on a canvas you can actually edit
Mermaid renders text to a picture. Grafloria reads that same text into a live diagram you can drag, connect, restyle and delete from — and writes it back out as a body any Mermaid renderer accepts. The text stays the document; the canvas stops being read-only.
This is the real engine parsing real Mermaid in your browser — not a screenshot, not a
pre-baked SVG. Try changing a shape to {Decision?}, adding
-->|label|, or breaking the syntax on purpose.
Four diagram types, read and written
Mermaid has grown past 29 diagram types. Grafloria speaks four of them — the graph-family ones people actually paste into an editor — and every one is a matched parser + model + generator, because a type that parses but cannot re-emit itself loses everything on first save. The rest fail safe (below), which we consider far better than a plausible-looking wrong diagram.
flowchart / graph
The full base grammar plus Mermaid-native styling: all node shapes, glued and spaced
edges, edge labels, subgraph → real groups, style,
classDef, :::, click and direction.
erDiagram
Entities with typed attribute blocks, PK/FK/UK badges, all sixteen cardinality pairs mapped to crow's-foot markers, identifying vs non-identifying, labelled relationships — landing as interactive table cards, not boxes.
classDiagram
Classes, members in both spellings, visibility and classifiers, generics, annotations, multiplicity, notes — and all 72 legal relationship operators, derived from the grammar rather than a hand-written table.
stateDiagram / -v2
States, transitions, scoped [*] and [H] pseudo-states,
composite states as nested groups, concurrent -- regions, fork / join /
choice, and direction scoped to the composite that declares it.
sequenceDiagram, gantt, pie, …
Every other type — journey, gitGraph, mindmap, timeline, C4, sankey, xychart and the
rest — returns an explicit unsupported signal naming the type. Never a blank
canvas, never a garbage graph. sequenceDiagram is the most-requested next.
It round-trips, and the round trip is the hard part
Reading Mermaid is the easy direction. The interesting one is what happens after somebody moves a node: positions are not expressible in Mermaid's grammar, so a naive exporter throws them away, and every save quietly re-scrambles the diagram.
The visible body always stays valid Mermaid
Grafloria writes a body GitHub, GitLab and mermaid.live all render — and parks everything
the grammar cannot say in a %% comment those renderers ignore. So the same
text is both a lossless Grafloria document and an ordinary Mermaid snippet. That
rule is not a convention we try to remember; it is the constraint the three tiers below
exist to enforce.
Mermaid's own extension points
Anything with a native analog uses it: fill and stroke become style /
classDef, containers become subgraph, navigation becomes
click. Visible, portable, renders everywhere.
%%grafloria: directives
Grafloria-only semantics with no Mermaid analog — edge animation, node status, routing hints — ride in comments, one line per entity. Mermaid skips them; the body still renders.
The document sidecar
A single %%grafloria:document line carries the exact model for a
byte-lossless machine round trip, with a body hash so a hand-edit to the visible text
wins over the stale sidecar.
// npm i @grafloria/engine import { importDiagramText, exportDiagramText } from '@grafloria/engine'; // Mermaid in → a real DiagramModel you can render and edit. const r = importDiagramText(`flowchart TD Start([Start]) --> Check{Valid?} Check -->|yes| Save[[Persist]]`); if (r.unsupported) console.warn(`no parser for ${r.unsupported} yet`); else render({ nodes: r.diagram.getNodes(), edges: r.diagram.getLinks() }, host); // …and back out. lossless:false gives the plain body for a README; // the default adds the sidecar so positions survive the trip. const text = exportDiagramText(diagram, { lossless: false });
Verified against real Mermaid, in CI
A compatibility claim is worth exactly as much as the thing that checks it. Ours is an oracle gate: 28 cases driven through real mermaid v11 in both directions — every input we say we read, and every body we emit, parsed by Mermaid itself on each run. It has already caught an export bug no unit test would have (ER relationship labels colliding with cardinality keywords). Any new type or syntax has to arrive with oracle cases.
The demos are gates too: the Mermaid viewer and the lossless text form both run in CI with real pointer events and pixel-diffed goldens, so the pages on this site cannot rot without failing the build.
What it does not do yet
The gaps below are all lossy, never wrong — the diagram you get is the diagram you wrote, minus something named here. That property matters more to us than the length of the list, so here is the list.
erDiagram three known losses
ENTITY["display alias"]parses, but Mermaid 11 has no syntax to write it back — the alias rides the sidecar instead of the visible body.- ER
style/classDef/:::directives are ignored, not applied to the entity cards. - Relationships are table-level. Mermaid's ER grammar cannot say which column a relationship uses, so the kit's column-pinned edges have nothing to import from. That one is Mermaid's limit, not ours.
classDiagram grouping and two glyphs
namespace Foo { … }— the classes survive, the grouping does not. The largest remaining class gap.- Both-ends operators (
<|--|>,*--o, …) keep their structure and re-export exactly, but draw with one marker: the notation table has no both-ends kind yet. - Lollipop
()--parses and round-trips as a realization, but renders as the dashed triangle rather than the interface ball.
stateDiagram layout, not structure
- Concurrent regions are modelled and re-exported correctly, but layout does not band them — no dashed divider yet. The structure is right; the picture is not.
[H]/[H*]round-trip, but draw as a plain circle instead of the H-in-circle glyph.- State
classDef/classstyling is not applied, and an inline:::hookis captured by name but not re-emitted.
all types layout and the directive channel
- Imported layout is a naive grid for ER / class / state — no type-aware placement (ER by FK dependency, class by inheritance depth) yet.
- The Tier-2
%%grafloria:per-entity channel is wired for flowchart only; the other three fall back to the Tier-3 sidecar, which is lossless but opaque.
Mermaid and Mermaid Chart are trademarks of their respective owners; Grafloria is an independent MIT project and implements the Mermaid syntax with its own parser — it does not bundle, fork, or depend on the Mermaid runtime. Coverage described here is current as of July 2026 and is tracked in the engine's gap analysis; corrections and requests are welcome via GitHub issues.