@jarenjs/mermaid 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +282 -0
- package/dist/types/ast.d.ts +210 -0
- package/dist/types/component/index.d.ts +81 -0
- package/dist/types/errors.d.ts +27 -0
- package/dist/types/index.d.ts +97 -0
- package/dist/types/interactive.d.ts +36 -0
- package/dist/types/layout/flowchart.d.ts +12 -0
- package/dist/types/layout/sequence.d.ts +12 -0
- package/dist/types/layout/state.d.ts +19 -0
- package/dist/types/parser/class.d.ts +11 -0
- package/dist/types/parser/config.d.ts +61 -0
- package/dist/types/parser/er.d.ts +11 -0
- package/dist/types/parser/flowchart.d.ts +26 -0
- package/dist/types/parser/gantt.d.ts +11 -0
- package/dist/types/parser/index.d.ts +22 -0
- package/dist/types/parser/pie.d.ts +11 -0
- package/dist/types/parser/sequence.d.ts +16 -0
- package/dist/types/parser/state.d.ts +22 -0
- package/dist/types/plugin.d.ts +50 -0
- package/dist/types/render/error.d.ts +23 -0
- package/dist/types/render/flowchart.d.ts +18 -0
- package/dist/types/render/index.d.ts +23 -0
- package/dist/types/render/misc.d.ts +54 -0
- package/dist/types/render/sequence.d.ts +16 -0
- package/dist/types/styles.d.ts +81 -0
- package/dist/types/theme.d.ts +47 -0
- package/dist/types/to-mermaid.d.ts +20 -0
- package/dist/types/utils.d.ts +47 -0
- package/docs/MERMAID-FORMAT.md +242 -0
- package/package.json +84 -0
- package/schemas/jaren-mermaid-ast.schema.json +78 -0
- package/schemas/jaren-workflow.schema.json +28 -0
- package/src/ast.js +252 -0
- package/src/component/index.js +109 -0
- package/src/errors.js +35 -0
- package/src/index.js +155 -0
- package/src/interactive.js +244 -0
- package/src/layout/flowchart.js +352 -0
- package/src/layout/sequence.js +178 -0
- package/src/layout/state.js +65 -0
- package/src/parser/class.js +90 -0
- package/src/parser/config.js +215 -0
- package/src/parser/er.js +86 -0
- package/src/parser/flowchart.js +413 -0
- package/src/parser/gantt.js +49 -0
- package/src/parser/index.js +122 -0
- package/src/parser/pie.js +32 -0
- package/src/parser/sequence.js +156 -0
- package/src/parser/state.js +137 -0
- package/src/plugin.js +76 -0
- package/src/render/error.js +55 -0
- package/src/render/flowchart.js +249 -0
- package/src/render/index.js +93 -0
- package/src/render/misc.js +135 -0
- package/src/render/sequence.js +152 -0
- package/src/styles.js +181 -0
- package/src/theme.js +180 -0
- package/src/to-mermaid.js +317 -0
- package/src/utils.js +64 -0
- package/styles/mermaid.css +115 -0
- package/stylesheets/dag-to-flowchart.jslt.json +62 -0
- package/stylesheets/flowchart-to-dag.jslt.json +29 -0
- package/stylesheets/state-to-workflow.jslt.json +26 -0
- package/stylesheets/workflow-to-state.jslt.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# @jarenjs/mermaid
|
|
2
|
+
|
|
3
|
+
A native, **headless** Mermaid clone: diagrams-as-code parsed to a
|
|
4
|
+
geometry-free JSON AST and rendered as **pure-vnode SVG** through
|
|
5
|
+
[`@jarenjs/view`](../../packages/view) — no `innerHTML`, no browser, no
|
|
6
|
+
runtime dependency on mermaid.js. It is architecturally native to the
|
|
7
|
+
Jaren stack: parse-once/compile-to-closures, structurally shared,
|
|
8
|
+
content-hash-keyed, and **bidirectional** (`parseMermaid` ⇄
|
|
9
|
+
`toMermaid`).
|
|
10
|
+
|
|
11
|
+
Like [`@jarenjs/md`](../md), it ships in **two layers**: a pure engine
|
|
12
|
+
(text ⇄ AST ⇄ vnode) that knows only the vnode shape, and a visual
|
|
13
|
+
component that packages it for an `@jarenjs/app` host.
|
|
14
|
+
|
|
15
|
+
## Format in one glance
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
import { parseMermaid, toMermaid, renderMermaid } from '@jarenjs/mermaid';
|
|
19
|
+
|
|
20
|
+
const doc = parseMermaid(`flowchart TD
|
|
21
|
+
A[Start] --> B{OK?}
|
|
22
|
+
B -->|yes| C((Done))`);
|
|
23
|
+
|
|
24
|
+
doc.diagram; // 'flowchart'
|
|
25
|
+
doc.ast.nodes[1]; // { id: 'B', label: 'OK?', shape: 'diamond' }
|
|
26
|
+
toMermaid(doc); // canonical text — parseMermaid(toMermaid(doc)) deep-equals doc.ast
|
|
27
|
+
renderMermaid(doc); // ['svg', { viewBox, … }, …] — a pure-vnode SVG, error-safe
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The AST is **geometry-free**: layout is a separate pass, so the AST is a
|
|
31
|
+
faithful semantic model — a directed graph, an ordered interaction, a
|
|
32
|
+
finite state machine — that other engines project. This is the two-layer
|
|
33
|
+
pipeline, drawn in Mermaid (and rendered by this engine on the website):
|
|
34
|
+
|
|
35
|
+
```mermaid
|
|
36
|
+
flowchart LR
|
|
37
|
+
S[source text] --> P[parseMermaid]
|
|
38
|
+
P --> D[DiagramDocument<br/>geometry-free AST]
|
|
39
|
+
D --> L[layoutDiagram]
|
|
40
|
+
L --> R[diagramToVnode]
|
|
41
|
+
R --> V[SVG vnode]
|
|
42
|
+
D --> T[toMermaid]
|
|
43
|
+
T --> S
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Usage
|
|
47
|
+
|
|
48
|
+
**Parse / print / compile (pure):**
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
import { parseMermaid, toMermaid, compileMermaid } from '@jarenjs/mermaid';
|
|
52
|
+
|
|
53
|
+
const c = compileMermaid(source); // parse once; cached projections
|
|
54
|
+
c.doc; // the DiagramDocument
|
|
55
|
+
c.toVnode(); // pure-vnode SVG (reference-stable)
|
|
56
|
+
c.toSvgString(); // standalone SVG string — SSR, no browser
|
|
57
|
+
c.toText(); // canonical Mermaid (toMermaid)
|
|
58
|
+
c.toLayout(); // the PositionedDiagram — pure geometry
|
|
59
|
+
// (nodes x/y/w/h, routed edges); null for
|
|
60
|
+
// types without a layout. The rendered
|
|
61
|
+
// SVG also marks every node/edge with
|
|
62
|
+
// data-id / data-edge+data-from+data-to,
|
|
63
|
+
// so editors hit-test without re-layout.
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Render pipeline:**
|
|
67
|
+
|
|
68
|
+
```mermaid
|
|
69
|
+
sequenceDiagram
|
|
70
|
+
participant H as host
|
|
71
|
+
participant E as engine
|
|
72
|
+
participant V as @jarenjs/view
|
|
73
|
+
H->>E: renderMermaid(source)
|
|
74
|
+
E->>E: parse → layout → render
|
|
75
|
+
E-->>H: SVG vnode
|
|
76
|
+
H->>V: patch(vnode)
|
|
77
|
+
note over V: O(change) diff, keyed by content hash
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Component (host):**
|
|
81
|
+
|
|
82
|
+
```js
|
|
83
|
+
import { createMermaidComponent } from '@jarenjs/mermaid/component';
|
|
84
|
+
const mermaid = createMermaidComponent();
|
|
85
|
+
createApp(appDoc, {
|
|
86
|
+
effects: { ...mermaid.effects }, // mermaid-render, mermaid-load
|
|
87
|
+
viewModel: (state) => ({ ...state, diagram: mermaid.view(state.source) }),
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Markdown plugin** — a `mermaid` fence renders inline, SSR-safe:
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
import { parseMarkdown, mdToVnode } from '@jarenjs/md';
|
|
95
|
+
import { mermaidPlugin } from '@jarenjs/mermaid/plugin';
|
|
96
|
+
const plugins = [mermaidPlugin()];
|
|
97
|
+
mdToVnode(parseMarkdown(md, { plugins }), { plugins }); // fence → inline <svg>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## The AST node types
|
|
101
|
+
|
|
102
|
+
```mermaid
|
|
103
|
+
classDiagram
|
|
104
|
+
class DiagramDocument {
|
|
105
|
+
+String $mermaid
|
|
106
|
+
+String diagram
|
|
107
|
+
+Object config
|
|
108
|
+
+Object ast
|
|
109
|
+
+Object meta
|
|
110
|
+
}
|
|
111
|
+
class FlowNode {
|
|
112
|
+
+String id
|
|
113
|
+
+String label
|
|
114
|
+
+String shape
|
|
115
|
+
}
|
|
116
|
+
class FlowEdge {
|
|
117
|
+
+String from
|
|
118
|
+
+String to
|
|
119
|
+
+String stroke
|
|
120
|
+
}
|
|
121
|
+
DiagramDocument <|-- FlowNode
|
|
122
|
+
DiagramDocument <|-- FlowEdge
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Bidirectional semantic model
|
|
126
|
+
|
|
127
|
+
The geometry-free AST doubles as a reusable domain model, projected
|
|
128
|
+
both ways by plain JSLT stylesheets — no code, just documents. The
|
|
129
|
+
flagship: a `stateDiagram-v2` projects via
|
|
130
|
+
`stylesheets/state-to-workflow.jslt.json` into an executable machine
|
|
131
|
+
(the `@jarenjs/flow` jaren-fsm superset shape `{ initial, states,
|
|
132
|
+
transitions }`, validated by `schemas/jaren-workflow.schema.json`),
|
|
133
|
+
with a transition label's UML parts parsed for it: `event [guard] /
|
|
134
|
+
effect` become the machine's event, guard and `{ "run": effect }`
|
|
135
|
+
descriptor. The reverse stylesheet plus `toMermaid` turns a machine
|
|
136
|
+
back into editable diagram text — string guards round-trip exactly,
|
|
137
|
+
structured members print as documented `[…]` placeholders.
|
|
138
|
+
|
|
139
|
+
The same arrow exists for dataflow: `flowchart-to-dag.jslt.json`
|
|
140
|
+
projects a flowchart into a jaren-dag **skeleton** (task stubs named by
|
|
141
|
+
node id, edge labels becoming ports), and `dag-to-flowchart.jslt.json`
|
|
142
|
+
draws a real dag document as a flowchart — one shape per node kind,
|
|
143
|
+
ports and selects on the edge labels. Acyclicity stays `compileDag`'s
|
|
144
|
+
job; the projection just draws.
|
|
145
|
+
|
|
146
|
+
```mermaid
|
|
147
|
+
flowchart LR
|
|
148
|
+
M[Mermaid text] --> A[state AST]
|
|
149
|
+
A -->|state-to-workflow.jslt| W[machine / FSM]
|
|
150
|
+
W -->|workflow-to-state.jslt| A2[state AST]
|
|
151
|
+
A2 -->|toMermaid| M
|
|
152
|
+
F[flowchart AST] -->|flowchart-to-dag.jslt| D[jaren-dag]
|
|
153
|
+
D -->|dag-to-flowchart.jslt| F
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Diagram coverage
|
|
157
|
+
|
|
158
|
+
Fully laid out: **flowchart**, **sequence**, **state** (through the
|
|
159
|
+
flowchart engine via an adapter — states as rounded nodes, `[*]` as a
|
|
160
|
+
filled start dot and an end ring, verbatim transition labels on the
|
|
161
|
+
edges; composite states stay flattened in v1). Structured panels /
|
|
162
|
+
chart: **class**, **ER**, **gantt**, **pie**. Parse-accepted with an
|
|
163
|
+
honest "not yet laid out" placeholder: mindmap, gitGraph, journey,
|
|
164
|
+
timeline, quadrantChart, requirement. The benchmark's coverage scorecard reports this
|
|
165
|
+
without hiding gaps.
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
## Styling, notes and interaction
|
|
169
|
+
|
|
170
|
+
**`classDef` / `class` / `style` now paint.** The parser always recorded them;
|
|
171
|
+
nothing consumed them, so a styled node rendered exactly like an unstyled one.
|
|
172
|
+
They resolve per node in Mermaid's own precedence — classDef in application
|
|
173
|
+
order, then a per-node `style` — and reach the shape as SVG attributes:
|
|
174
|
+
|
|
175
|
+
```mermaid
|
|
176
|
+
flowchart LR
|
|
177
|
+
A["input"] --> B["result"]
|
|
178
|
+
classDef good fill:#dcfce7,stroke:#16a34a
|
|
179
|
+
class B good
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**`note` is a built-in class.** Mermaid has no flowchart note, and a diagram
|
|
183
|
+
that cannot annotate a node loses exactly what an ASCII drawing used to carry
|
|
184
|
+
in a margin comment. Rather than invent syntax, apply the standard `class`
|
|
185
|
+
statement and the node is themed from the same `note*` tokens the sequence
|
|
186
|
+
renderer uses — dashed border, note fill, following light/dark:
|
|
187
|
+
|
|
188
|
+
```mermaid
|
|
189
|
+
flowchart LR
|
|
190
|
+
K["@jarenjs/core"] --> E["engine"]
|
|
191
|
+
N["pure kernel: no I/O, deterministic"]
|
|
192
|
+
K -.- N
|
|
193
|
+
class N note
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
A dotted link to a note-classed node reads as an annotation, and the document
|
|
197
|
+
stays valid Mermaid that any other tool can still parse — no dialect, no
|
|
198
|
+
compatibility cost.
|
|
199
|
+
|
|
200
|
+
**The label stays readable on whatever fill you pick.** A `fill` you name is a
|
|
201
|
+
constant — it does not follow light/dark — so the ink over it must not follow
|
|
202
|
+
the theme either, or a pale box under a dark theme gets pale text and the
|
|
203
|
+
label vanishes into it. The ink is derived from the fill's measured contrast
|
|
204
|
+
instead, and is guaranteed to clear WCAG AA for any colour. Name a `color`
|
|
205
|
+
yourself and that always wins.
|
|
206
|
+
|
|
207
|
+
**Pan, zoom and touch are opt-in.** `mermaidPlugin({ interactive: true })`
|
|
208
|
+
adds a `hydrate` that attaches to the finished SVG; the render is unchanged
|
|
209
|
+
and server output is byte-identical either way, so a page that does not ask
|
|
210
|
+
for it never loads the module.
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
createMdComponent({ plugins: [mermaidPlugin({ theme: 'host', interactive: true })] });
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The interaction rules are chosen so a figure never fights the page it sits in:
|
|
217
|
+
|
|
218
|
+
| gesture | behaviour |
|
|
219
|
+
|---|---|
|
|
220
|
+
| plain wheel | **scrolls the page** — hijacking it is how embedded viewers ruin a document |
|
|
221
|
+
| ctrl/⌘ + wheel | zooms toward the pointer |
|
|
222
|
+
| one-finger drag | pans **only once zoomed in**; at rest the swipe is the page's, and `touch-action` is switched to say so |
|
|
223
|
+
| two fingers | always pinch-zooms |
|
|
224
|
+
| double-click / tap | zooms in, or resets when already zoomed |
|
|
225
|
+
| keyboard | `+` `-` `0` and arrows, on a focusable figure with an aria-label |
|
|
226
|
+
|
|
227
|
+
Everything runs on the SVG's `viewBox` — four numbers changing. Nothing
|
|
228
|
+
re-renders, nothing re-parses, and the view is clamped so it can never be
|
|
229
|
+
panned off its own canvas.
|
|
230
|
+
|
|
231
|
+
Pie rendering delegates to [`@jarenjs/charts`](../charts) (the pie
|
|
232
|
+
engine's single home) — the emitted SVG is unchanged; mermaid passes
|
|
233
|
+
its class names, palette and theme through the render options.
|
|
234
|
+
|
|
235
|
+
## Performance (measured)
|
|
236
|
+
|
|
237
|
+
Node v22.22.2, 2026-07-19, `npm run benchmark:mermaid` (run it
|
|
238
|
+
yourself). Mermaid has **two** parsers, so there are two honest
|
|
239
|
+
head-to-heads:
|
|
240
|
+
|
|
241
|
+
- **`@mermaid-js/parser`** is the standalone **Langium** parser — it
|
|
242
|
+
covers only the grammars migrated off Jison (pie, gitGraph, …) and
|
|
243
|
+
**cannot parse flowchart or sequence**. The overlapping type is
|
|
244
|
+
**pie**, where `@jarenjs/mermaid` is comparable (~0.003–0.006 ms/op
|
|
245
|
+
either way).
|
|
246
|
+
- **Flowchart and sequence** are still parsed by Mermaid's original
|
|
247
|
+
in-tree **Jison** grammars inside the full `mermaid` package (not by
|
|
248
|
+
`@mermaid-js/parser`). Against `mermaid.parse()` (DOM-coupled, run
|
|
249
|
+
under jsdom), `@jarenjs/mermaid` parses the same sources **roughly two
|
|
250
|
+
orders of magnitude faster**:
|
|
251
|
+
|
|
252
|
+
| flowchart/sequence parse (ms/op) | jaren-mermaid | mermaid.parse (Jison) |
|
|
253
|
+
|---|---|---|
|
|
254
|
+
| flowchart ~5 nodes | ~0.04 | ~10 |
|
|
255
|
+
| sequence ~5 nodes | ~0.02 | ~1.4 |
|
|
256
|
+
| flowchart ~25 nodes | ~0.09 | ~7 |
|
|
257
|
+
| sequence ~25 nodes | ~0.05 | ~4 |
|
|
258
|
+
|
|
259
|
+
(`mermaid.parse` is async and runs the whole parse front-end — type
|
|
260
|
+
detection + Jison + validation — so it is heavy and noisy; these are
|
|
261
|
+
representative, not a bare-grammar microbenchmark.)
|
|
262
|
+
|
|
263
|
+
The headless **parse → layout → SVG string** rows are jaren-only
|
|
264
|
+
(<!--bm:mermaid.svgMs-->~0.46 ms for a 25-node flowchart, ~1.4 ms at 100 nodes<!--/bm-->): mermaid.js
|
|
265
|
+
needs a browser DOM (`getBBox`) to render, so there is no fair
|
|
266
|
+
full-render head-to-head — producing a complete standalone SVG in pure
|
|
267
|
+
Node is a capability it lacks.
|
|
268
|
+
|
|
269
|
+
## Design notes
|
|
270
|
+
|
|
271
|
+
- **Two layers, one-way arrow.** The engine imports only `@jarenjs/core`
|
|
272
|
+
and `@jarenjs/view` (shared SVG builders from `@jarenjs/view/helpers`,
|
|
273
|
+
`hashContent` from core); the component adds the app glue. The Markdown
|
|
274
|
+
plugin lives on the md→mermaid arrow with no cycle.
|
|
275
|
+
- **CSP-safe.** No `eval`, no `new Function`, no `innerHTML`. Text and
|
|
276
|
+
attributes are escaped by the view serializer.
|
|
277
|
+
- **Structural sharing.** Same source → reference-equal vnode; a small
|
|
278
|
+
source change re-emits only affected sub-scenes; block vnodes carry
|
|
279
|
+
content-hash keys.
|
|
280
|
+
|
|
281
|
+
See [ARCHITECTURE.md](ARCHITECTURE.md) and
|
|
282
|
+
[docs/MERMAID-FORMAT.md](docs/MERMAID-FORMAT.md).
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The Mermaid AST vocabulary: node constructors and walkers.
|
|
3
|
+
*
|
|
4
|
+
* Every node is a plain JSON object born from a constructor so that all
|
|
5
|
+
* nodes of a type share one hidden class — property access stays
|
|
6
|
+
* monomorphic and the structural hash is deterministic (MERMAID-FORMAT
|
|
7
|
+
* §4). The AST is deliberately **geometry-free**:
|
|
8
|
+
* layout is a separate pass, so the AST is a faithful, lossless
|
|
9
|
+
* semantic model of the diagram's *meaning* — a directed graph
|
|
10
|
+
* (flowchart), an ordered interaction (sequence), a finite state machine
|
|
11
|
+
* (state) — that other engines project via JSLT without ever seeing a
|
|
12
|
+
* coordinate.
|
|
13
|
+
*
|
|
14
|
+
* Member order is fixed per constructor; keep it stable so the FNV-1a
|
|
15
|
+
* hash of `JSON.stringify` is reproducible and the round-trip printer
|
|
16
|
+
* (`to-mermaid.js`) is a fixed point.
|
|
17
|
+
*/
|
|
18
|
+
/** The diagram-document format version this package produces. */
|
|
19
|
+
export declare const MERMAID_VERSION = "0.1";
|
|
20
|
+
export type DiagramDocument = {
|
|
21
|
+
/**
|
|
22
|
+
* format version
|
|
23
|
+
*/
|
|
24
|
+
$mermaid: string;
|
|
25
|
+
/**
|
|
26
|
+
* diagram type (`flowchart`, `sequence`, …)
|
|
27
|
+
*/
|
|
28
|
+
diagram: string;
|
|
29
|
+
/**
|
|
30
|
+
* plain-JSON config (theme, per-type options)
|
|
31
|
+
*/
|
|
32
|
+
config: any;
|
|
33
|
+
/**
|
|
34
|
+
* the type-specific, geometry-free AST
|
|
35
|
+
*/
|
|
36
|
+
ast: any;
|
|
37
|
+
meta: {
|
|
38
|
+
hash: string;
|
|
39
|
+
direction: string | null;
|
|
40
|
+
title: string | null;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* @typedef {object} DiagramDocument
|
|
45
|
+
* @property {string} $mermaid format version
|
|
46
|
+
* @property {string} diagram diagram type (`flowchart`, `sequence`, …)
|
|
47
|
+
* @property {any} config plain-JSON config (theme, per-type options)
|
|
48
|
+
* @property {any} ast the type-specific, geometry-free AST
|
|
49
|
+
* @property {{ hash: string, direction: string|null, title: string|null }} meta
|
|
50
|
+
*/
|
|
51
|
+
/**
|
|
52
|
+
* Assemble the shared DiagramDocument envelope. Fresh per parse,
|
|
53
|
+
* never mutated after return — share-friendly for JSLT/patch.
|
|
54
|
+
* @param {string} diagram
|
|
55
|
+
* @param {any} config
|
|
56
|
+
* @param {any} ast
|
|
57
|
+
* @param {{ hash: string, direction: string|null, title: string|null }} meta
|
|
58
|
+
* @returns {DiagramDocument}
|
|
59
|
+
*/
|
|
60
|
+
export declare function diagramDocument(diagram: string, config: any, ast: any, meta: {
|
|
61
|
+
hash: string;
|
|
62
|
+
direction: string | null;
|
|
63
|
+
title: string | null;
|
|
64
|
+
}): DiagramDocument;
|
|
65
|
+
export type FlowShape = 'rect' | 'round' | 'stadium' | 'subroutine' | 'cylinder' | 'circle' | 'doublecircle' | 'diamond' | 'hexagon' | 'parallelogram' | 'parallelogram_alt' | 'trapezoid' | 'trapezoid_alt' | 'asymmetric';
|
|
66
|
+
/**
|
|
67
|
+
* @typedef {'rect'|'round'|'stadium'|'subroutine'|'cylinder'|'circle'
|
|
68
|
+
* |'doublecircle'|'diamond'|'hexagon'|'parallelogram'|'parallelogram_alt'
|
|
69
|
+
* |'trapezoid'|'trapezoid_alt'|'asymmetric'} FlowShape
|
|
70
|
+
*/
|
|
71
|
+
/**
|
|
72
|
+
* A flowchart vertex.
|
|
73
|
+
* @param {string} id
|
|
74
|
+
* @param {string} label
|
|
75
|
+
* @param {FlowShape} shape
|
|
76
|
+
* @returns {{ id: string, label: string, shape: FlowShape }}
|
|
77
|
+
*/
|
|
78
|
+
export declare function flowNode(id: string, label: string, shape: FlowShape): {
|
|
79
|
+
id: string;
|
|
80
|
+
label: string;
|
|
81
|
+
shape: FlowShape;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* A flowchart edge (link). `stroke` is the line style, `head`/`tail`
|
|
85
|
+
* the endpoint markers, `length` the dash count (preserved so the
|
|
86
|
+
* canonical printer is a fixed point), `label` the optional edge text.
|
|
87
|
+
* @param {string} from
|
|
88
|
+
* @param {string} to
|
|
89
|
+
* @param {'solid'|'thick'|'dotted'} stroke
|
|
90
|
+
* @param {'none'|'arrow'|'circle'|'cross'} head
|
|
91
|
+
* @param {'none'|'arrow'|'circle'|'cross'} tail
|
|
92
|
+
* @param {number} length
|
|
93
|
+
* @param {string|null} label
|
|
94
|
+
* @returns {object}
|
|
95
|
+
*/
|
|
96
|
+
export declare function flowEdge(from: string, to: string, stroke: 'solid' | 'thick' | 'dotted', head: 'none' | 'arrow' | 'circle' | 'cross', tail: 'none' | 'arrow' | 'circle' | 'cross', length: number, label: string | null): object;
|
|
97
|
+
/**
|
|
98
|
+
* A subgraph grouping.
|
|
99
|
+
* @param {string} id
|
|
100
|
+
* @param {string} label
|
|
101
|
+
* @param {string|null} direction
|
|
102
|
+
* @param {string[]} nodes ids of member nodes
|
|
103
|
+
* @returns {object}
|
|
104
|
+
*/
|
|
105
|
+
export declare function flowSubgraph(id: string, label: string, direction: string | null, nodes: string[]): object;
|
|
106
|
+
/**
|
|
107
|
+
* A `classDef` style class.
|
|
108
|
+
* @param {string} name
|
|
109
|
+
* @param {string} styles semicolon-separated CSS declarations
|
|
110
|
+
* @returns {object}
|
|
111
|
+
*/
|
|
112
|
+
export declare function flowClassDef(name: string, styles: string): object;
|
|
113
|
+
/**
|
|
114
|
+
* A `class`/`:::` assignment of a style class to a node.
|
|
115
|
+
* @param {string} node
|
|
116
|
+
* @param {string} name
|
|
117
|
+
* @returns {object}
|
|
118
|
+
*/
|
|
119
|
+
export declare function flowClass(node: string, name: string): object;
|
|
120
|
+
/**
|
|
121
|
+
* A `style` inline-style assignment to a node.
|
|
122
|
+
* @param {string} node
|
|
123
|
+
* @param {string} styles
|
|
124
|
+
* @returns {object}
|
|
125
|
+
*/
|
|
126
|
+
export declare function flowStyle(node: string, styles: string): object;
|
|
127
|
+
/**
|
|
128
|
+
* The flowchart AST root.
|
|
129
|
+
* @param {string} direction
|
|
130
|
+
* @param {object[]} nodes
|
|
131
|
+
* @param {object[]} edges
|
|
132
|
+
* @param {object[]} subgraphs
|
|
133
|
+
* @param {object[]} classDefs
|
|
134
|
+
* @param {object[]} classes
|
|
135
|
+
* @param {object[]} styles
|
|
136
|
+
* @returns {object}
|
|
137
|
+
*/
|
|
138
|
+
export declare function flowchartAst(direction: string, nodes: object[], edges: object[], subgraphs: object[], classDefs: object[], classes: object[], styles: object[]): object;
|
|
139
|
+
/**
|
|
140
|
+
* A declared participant/actor.
|
|
141
|
+
* @param {string} id
|
|
142
|
+
* @param {string} label
|
|
143
|
+
* @param {'participant'|'actor'} kind
|
|
144
|
+
* @returns {object}
|
|
145
|
+
*/
|
|
146
|
+
export declare function seqParticipant(id: string, label: string, kind: 'participant' | 'actor'): object;
|
|
147
|
+
/**
|
|
148
|
+
* A message statement.
|
|
149
|
+
* @param {string} from
|
|
150
|
+
* @param {string} to
|
|
151
|
+
* @param {string} text
|
|
152
|
+
* @param {'solid'|'dotted'} line
|
|
153
|
+
* @param {'arrow'|'open'|'cross'|'point'} head
|
|
154
|
+
* @param {'activate'|'deactivate'|null} activation `+`/`-` shorthand
|
|
155
|
+
* @returns {object}
|
|
156
|
+
*/
|
|
157
|
+
export declare function seqMessage(from: string, to: string, text: string, line: 'solid' | 'dotted', head: 'arrow' | 'open' | 'cross' | 'point', activation: 'activate' | 'deactivate' | null): object;
|
|
158
|
+
/**
|
|
159
|
+
* A note statement.
|
|
160
|
+
* @param {'left of'|'right of'|'over'} placement
|
|
161
|
+
* @param {string[]} actors
|
|
162
|
+
* @param {string} text
|
|
163
|
+
* @returns {object}
|
|
164
|
+
*/
|
|
165
|
+
export declare function seqNote(placement: 'left of' | 'right of' | 'over', actors: string[], text: string): object;
|
|
166
|
+
/**
|
|
167
|
+
* An explicit activate/deactivate statement.
|
|
168
|
+
* @param {'activate'|'deactivate'} kind
|
|
169
|
+
* @param {string} actor
|
|
170
|
+
* @returns {object}
|
|
171
|
+
*/
|
|
172
|
+
export declare function seqActivation(kind: 'activate' | 'deactivate', actor: string): object;
|
|
173
|
+
/**
|
|
174
|
+
* A block statement (loop/opt/alt/par/critical/break). Single-branch
|
|
175
|
+
* blocks (loop/opt/critical/break) carry one branch; alt/par carry one
|
|
176
|
+
* per `else`/`and` section. `branches` is always present so the shape
|
|
177
|
+
* is monomorphic.
|
|
178
|
+
* @param {'loop'|'opt'|'alt'|'par'|'critical'|'break'} blockType
|
|
179
|
+
* @param {{ label: string, statements: object[] }[]} branches
|
|
180
|
+
* @returns {object}
|
|
181
|
+
*/
|
|
182
|
+
export declare function seqBlock(blockType: 'loop' | 'opt' | 'alt' | 'par' | 'critical' | 'break', branches: {
|
|
183
|
+
label: string;
|
|
184
|
+
statements: object[];
|
|
185
|
+
}[]): object;
|
|
186
|
+
/**
|
|
187
|
+
* The sequence AST root.
|
|
188
|
+
* @param {object[]} participants explicitly declared participants
|
|
189
|
+
* @param {object[]} statements ordered interaction statements
|
|
190
|
+
* @param {boolean} autonumber
|
|
191
|
+
* @returns {object}
|
|
192
|
+
*/
|
|
193
|
+
export declare function sequenceAst(participants: object[], statements: object[], autonumber: boolean): object;
|
|
194
|
+
/**
|
|
195
|
+
* A geometry-free "lines" AST for diagram types that parse-accept but
|
|
196
|
+
* are not yet laid out (the secondary types). Preserves the raw body
|
|
197
|
+
* lines so `toMermaid` round-trips and the coverage scorecard can be
|
|
198
|
+
* honest.
|
|
199
|
+
* @param {string} diagram
|
|
200
|
+
* @param {string[]} lines
|
|
201
|
+
* @returns {object}
|
|
202
|
+
*/
|
|
203
|
+
export declare function rawAst(diagram: string, lines: string[]): object;
|
|
204
|
+
/**
|
|
205
|
+
* Walk the ordered statements of a sequence AST (descending into block
|
|
206
|
+
* branches), calling `visitor(stmt)` pre-order.
|
|
207
|
+
* @param {object[]} statements
|
|
208
|
+
* @param {(stmt: any) => void} visitor
|
|
209
|
+
*/
|
|
210
|
+
export declare function walkSequence(statements: object[], visitor: (stmt: any) => void): void;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The Mermaid VISUAL COMPONENT — part two of the package.
|
|
3
|
+
*
|
|
4
|
+
* Everything below this line is presentation glue; the engine
|
|
5
|
+
* (`@jarenjs/mermaid`) neither knows nor needs any of it. Mirrors
|
|
6
|
+
* `@jarenjs/md`'s `createMdComponent` field-for-field:
|
|
7
|
+
*
|
|
8
|
+
* - `createMermaidComponent()` — a memoized `view()` projection for
|
|
9
|
+
* `@jarenjs/app` viewModels (reference-stable, so an unchanged source
|
|
10
|
+
* patches in O(1) — the O(change) contract), `effects` entries for
|
|
11
|
+
* the app effect registry (`mermaid-render`, `mermaid-load`), and a
|
|
12
|
+
* `hydrate()` pass kept for API symmetry (a no-op in v1: the render is
|
|
13
|
+
* already complete);
|
|
14
|
+
* - `styles/mermaid.css` — the component stylesheet.
|
|
15
|
+
*
|
|
16
|
+
* The boundary is one-way: the component imports the engine, never the
|
|
17
|
+
* reverse.
|
|
18
|
+
*/
|
|
19
|
+
export type MermaidComponentOptions = {
|
|
20
|
+
/**
|
|
21
|
+
* theme name or override object
|
|
22
|
+
*/
|
|
23
|
+
theme?: any;
|
|
24
|
+
/**
|
|
25
|
+
* LRU size for the source-string memo (default 32)
|
|
26
|
+
*/
|
|
27
|
+
memoLimit?: number;
|
|
28
|
+
/**
|
|
29
|
+
* base URL for `mermaid-load`
|
|
30
|
+
*/
|
|
31
|
+
base?: string | URL;
|
|
32
|
+
/**
|
|
33
|
+
* fetch implementation for `mermaid-load`
|
|
34
|
+
*/
|
|
35
|
+
fetch?: typeof globalThis.fetch;
|
|
36
|
+
onHydrateError?: (err: any) => void;
|
|
37
|
+
};
|
|
38
|
+
export type MermaidComponent = {
|
|
39
|
+
/**
|
|
40
|
+
* memoized compile
|
|
41
|
+
*/
|
|
42
|
+
compile: (source: string) => any;
|
|
43
|
+
/**
|
|
44
|
+
* memoized vnode projection
|
|
45
|
+
*/
|
|
46
|
+
view: (sourceOrDoc: any) => any;
|
|
47
|
+
effects: Record<string, (props: any, dispatch: any) => any>;
|
|
48
|
+
/**
|
|
49
|
+
* no-op in v1
|
|
50
|
+
*/
|
|
51
|
+
hydrate: (container: any) => void;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* @typedef {object} MermaidComponentOptions
|
|
55
|
+
* @property {any} [theme] theme name or override object
|
|
56
|
+
* @property {number} [memoLimit] LRU size for the source-string memo (default 32)
|
|
57
|
+
* @property {string | URL} [base] base URL for `mermaid-load`
|
|
58
|
+
* @property {typeof globalThis.fetch} [fetch] fetch implementation for `mermaid-load`
|
|
59
|
+
* @property {(err: any) => void} [onHydrateError]
|
|
60
|
+
*/
|
|
61
|
+
/**
|
|
62
|
+
* @typedef {object} MermaidComponent
|
|
63
|
+
* @property {(source: string) => any} compile memoized compile
|
|
64
|
+
* @property {(sourceOrDoc: any) => any} view memoized vnode projection
|
|
65
|
+
* @property {Record<string, (props: any, dispatch: any) => any>} effects
|
|
66
|
+
* @property {(container: any) => void} hydrate no-op in v1
|
|
67
|
+
*/
|
|
68
|
+
/**
|
|
69
|
+
* Create the Mermaid component.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* const mermaid = createMermaidComponent();
|
|
73
|
+
* createApp(appDoc, {
|
|
74
|
+
* effects: { ...mermaid.effects },
|
|
75
|
+
* viewModel: (state) => ({ ...state, diagram: mermaid.view(state.source) }),
|
|
76
|
+
* });
|
|
77
|
+
*
|
|
78
|
+
* @param {MermaidComponentOptions} [options]
|
|
79
|
+
* @returns {MermaidComponent}
|
|
80
|
+
*/
|
|
81
|
+
export declare function createMermaidComponent(options?: MermaidComponentOptions): MermaidComponent;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The engine's one error type. Parsers raise it with a 1-based
|
|
3
|
+
* `line`/`column`; the render path (`diagramToVnode`/`renderMermaid`)
|
|
4
|
+
* catches it and emits a clear error vnode instead of throwing, so
|
|
5
|
+
* rendering is always total.
|
|
6
|
+
*/
|
|
7
|
+
export declare class MermaidParseError extends Error {
|
|
8
|
+
/** @type {number} */
|
|
9
|
+
line: number;
|
|
10
|
+
/** @type {number} */
|
|
11
|
+
column: number;
|
|
12
|
+
/**
|
|
13
|
+
* @param {string} message
|
|
14
|
+
* @param {number} [line] 1-based line number
|
|
15
|
+
* @param {number} [column] 1-based column number
|
|
16
|
+
*/
|
|
17
|
+
constructor(message: string, line?: number, column?: number);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The `fail(message, position)` idiom from `packages/json/src/path.js`,
|
|
21
|
+
* adapted to line/column. Throws; never returns.
|
|
22
|
+
* @param {string} message
|
|
23
|
+
* @param {number} line
|
|
24
|
+
* @param {number} [column]
|
|
25
|
+
* @returns {never}
|
|
26
|
+
*/
|
|
27
|
+
export declare function fail(message: string, line: number, column?: number): never;
|