flowink 0.1.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/LICENSE +21 -0
- package/NOTICE.md +17 -0
- package/README.md +301 -0
- package/dist/errors.d.ts +13 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +3560 -0
- package/dist/index.js.map +7 -0
- package/dist/layout.d.ts +13 -0
- package/dist/parse.d.ts +3 -0
- package/dist/parser/generated.d.ts +3 -0
- package/dist/parser/preprocess.d.ts +11 -0
- package/dist/parser/semantic.d.ts +76 -0
- package/dist/place-labels.d.ts +15 -0
- package/dist/rasterize.d.ts +47 -0
- package/dist/text.d.ts +36 -0
- package/dist/types.d.ts +88 -0
- package/examples/basic.mmd +4 -0
- package/examples/chinese.mmd +2 -0
- package/examples/cycle.mmd +2 -0
- package/examples/decision.mmd +4 -0
- package/examples/hero.mmd +2 -0
- package/examples/subgraph.mmd +5 -0
- package/package.json +71 -0
- package/vendor/mermaid/LICENSE +21 -0
- package/vendor/mermaid/README.md +16 -0
- package/vendor/mermaid/flow.jison +635 -0
- package/vendor/mermaid/flowDb.ts +1336 -0
- package/vendor/mermaid/flowParser.ts +12 -0
- package/vendor/mermaid/provenance.json +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 FlowInk contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/NOTICE.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
FlowInk's own source is licensed under MIT.
|
|
4
|
+
|
|
5
|
+
The flowchart grammar, portions of parsing/semantic processing, and upstream
|
|
6
|
+
compatibility fixtures derive from Mermaid 12.0.0 (MIT), tag `mermaid@12.0.0`,
|
|
7
|
+
commit `98a0945418c76238f15df2afaddbba4272656c3b`.
|
|
8
|
+
Source: https://github.com/mermaid-js/mermaid/tree/mermaid%4012.0.0
|
|
9
|
+
The upstream license and grammar provenance are included in `vendor/mermaid`.
|
|
10
|
+
The parser is generated at build time by Jison (MIT).
|
|
11
|
+
|
|
12
|
+
Runtime dependencies retain their own licenses; they are installed separately
|
|
13
|
+
and not relicensed by FlowInk. In particular, elkjs is distributed under
|
|
14
|
+
`EPL-2.0 OR GPL-3.0-or-later`; its license is included in the installed elkjs
|
|
15
|
+
package. See https://github.com/kieler/elkjs/blob/master/LICENSE.md.
|
|
16
|
+
|
|
17
|
+
Graph::Easy is a visual reference. FlowInk contains no Graph::Easy code.
|
package/README.md
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# FlowInk
|
|
4
|
+
|
|
5
|
+
**Mermaid flowcharts, rendered as text.**
|
|
6
|
+
|
|
7
|
+
ASCII and Unicode diagrams for Node.js and the browser.
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/flowink)
|
|
10
|
+
[](#quick-start)
|
|
11
|
+
[](#compatibility)
|
|
12
|
+
[](#development)
|
|
13
|
+
[](LICENSE)
|
|
14
|
+
|
|
15
|
+
[Quick start](#quick-start) · [Examples](#examples) · [API](#api) · [Compatibility](#compatibility) · [Development](#development)
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<!-- example:hero:start -->
|
|
20
|
+
```text
|
|
21
|
+
+---------+ +------------+
|
|
22
|
+
| Mermaid |->| Plain text |
|
|
23
|
+
+---------+ +------------+
|
|
24
|
+
```
|
|
25
|
+
<!-- example:hero:end -->
|
|
26
|
+
|
|
27
|
+
## Why FlowInk?
|
|
28
|
+
|
|
29
|
+
- **Keep your Mermaid source.** Uses the official flowchart grammar pinned to Mermaid 12.0.0.
|
|
30
|
+
- **Choose your alphabet.** ASCII by default, Unicode when you want box-drawing characters.
|
|
31
|
+
- **Keep the graph intact.** Branches, cycles, parallel edges, self-loops, and nested subgraphs.
|
|
32
|
+
- **Keep the details.** Chinese text, multiline labels, and plain-text Markdown/HTML content; styles and interactions stay in the parsed data.
|
|
33
|
+
- **Use JavaScript.** ESM API, JSDoc-derived TypeScript declarations, and no runtime DOM or external executable requirement.
|
|
34
|
+
|
|
35
|
+
## Quick start
|
|
36
|
+
|
|
37
|
+
Requires **Node.js 22.12+**. Install from npm:
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
npm install flowink
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Create `demo.mjs` in your project:
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
import { parse, render } from 'flowink';
|
|
47
|
+
|
|
48
|
+
const source = `flowchart LR
|
|
49
|
+
A[Mermaid] --> B[Plain text]
|
|
50
|
+
`;
|
|
51
|
+
|
|
52
|
+
console.log(await render(source));
|
|
53
|
+
console.log(await render(source, { charset: 'unicode' }));
|
|
54
|
+
|
|
55
|
+
const graph = parse(source);
|
|
56
|
+
console.log(graph.nodes, graph.edges);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
node demo.mjs
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Browser applications can import `flowink` through their usual bundler.
|
|
64
|
+
|
|
65
|
+
## Examples
|
|
66
|
+
|
|
67
|
+
Each output below is generated by `render()` from the accompanying source. The inputs are also available in [`examples/`](examples).
|
|
68
|
+
|
|
69
|
+
### 1. A decision with two outcomes
|
|
70
|
+
|
|
71
|
+
<!-- example:decision:start -->
|
|
72
|
+
**Mermaid source**
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
flowchart TB
|
|
76
|
+
A[Start] --> B{Ready?}
|
|
77
|
+
B -->|yes| C[Ship]
|
|
78
|
+
B -->|no| D[Wait]
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Unicode output** · `render(source, { charset: 'unicode' })`
|
|
82
|
+
|
|
83
|
+
```text
|
|
84
|
+
┌────────┐
|
|
85
|
+
│ Start │
|
|
86
|
+
└────────┘
|
|
87
|
+
┌─┘
|
|
88
|
+
▼
|
|
89
|
+
╱────────╲
|
|
90
|
+
│ │
|
|
91
|
+
◁ Ready? ▷
|
|
92
|
+
│ │
|
|
93
|
+
╲────────╱
|
|
94
|
+
┌┘ │
|
|
95
|
+
│ └─────┐
|
|
96
|
+
│ no │
|
|
97
|
+
yes │ │
|
|
98
|
+
│ │
|
|
99
|
+
│ │
|
|
100
|
+
▼ ▼
|
|
101
|
+
┌───────┐┌───────┐
|
|
102
|
+
│ Ship ││ Wait │
|
|
103
|
+
└───────┘└───────┘
|
|
104
|
+
```
|
|
105
|
+
<!-- example:decision:end -->
|
|
106
|
+
|
|
107
|
+
### 2. Chinese and multiline labels
|
|
108
|
+
|
|
109
|
+
Drawing characters and label text are independent: ASCII mode also preserves Chinese and other Unicode labels. Use a monospace font with suitable CJK and emoji support.
|
|
110
|
+
|
|
111
|
+
<!-- example:chinese:start -->
|
|
112
|
+
**Mermaid source**
|
|
113
|
+
|
|
114
|
+
```text
|
|
115
|
+
flowchart LR
|
|
116
|
+
A["開始"] -->|確認| B["完成<br/>下一步"]
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Unicode output** · `render(source, { charset: 'unicode' })`
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
確認
|
|
123
|
+
┌──────┐ ┌────────┐
|
|
124
|
+
│ 開始 │────────▶│ 完成 │
|
|
125
|
+
│ │ │ 下一步 │
|
|
126
|
+
└──────┘ └────────┘
|
|
127
|
+
```
|
|
128
|
+
<!-- example:chinese:end -->
|
|
129
|
+
|
|
130
|
+
<details>
|
|
131
|
+
<summary><strong>3. A cycle — follow the return edge</strong></summary>
|
|
132
|
+
|
|
133
|
+
<!-- example:cycle:start -->
|
|
134
|
+
**Mermaid source**
|
|
135
|
+
|
|
136
|
+
```text
|
|
137
|
+
flowchart TB
|
|
138
|
+
A[Plan] --> B[Build] --> C[Review] --> A
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**ASCII output** · `render(source, { charset: 'ascii' })`
|
|
142
|
+
|
|
143
|
+
```text
|
|
144
|
+
+-------+
|
|
145
|
+
| Plan |
|
|
146
|
+
+-------+
|
|
147
|
+
++ ^
|
|
148
|
+
| +----+
|
|
149
|
+
v |
|
|
150
|
+
+-------+ |
|
|
151
|
+
| Build | |
|
|
152
|
+
+-------+ |
|
|
153
|
+
++ |
|
|
154
|
+
| |
|
|
155
|
+
v +----+
|
|
156
|
+
+--------+
|
|
157
|
+
| Review |
|
|
158
|
+
+--------+
|
|
159
|
+
```
|
|
160
|
+
<!-- example:cycle:end -->
|
|
161
|
+
|
|
162
|
+
</details>
|
|
163
|
+
|
|
164
|
+
<details>
|
|
165
|
+
<summary><strong>4. A subgraph with an outgoing connection</strong></summary>
|
|
166
|
+
|
|
167
|
+
<!-- example:subgraph:start -->
|
|
168
|
+
**Mermaid source**
|
|
169
|
+
|
|
170
|
+
```text
|
|
171
|
+
flowchart TB
|
|
172
|
+
subgraph Build
|
|
173
|
+
A[Parse] --> B[Layout]
|
|
174
|
+
end
|
|
175
|
+
B --> C[Text]
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**ASCII output** · `render(source, { charset: 'ascii' })`
|
|
179
|
+
|
|
180
|
+
```text
|
|
181
|
+
+------------+
|
|
182
|
+
| Build |
|
|
183
|
+
| +--------+ |
|
|
184
|
+
| | Parse | |
|
|
185
|
+
| +--------+ |
|
|
186
|
+
| +-+ |
|
|
187
|
+
| v |
|
|
188
|
+
| +--------+ |
|
|
189
|
+
| | Layout | |
|
|
190
|
+
| +--------+ |
|
|
191
|
+
| | |
|
|
192
|
+
+-----|------+
|
|
193
|
+
|
|
|
194
|
+
|
|
|
195
|
+
v
|
|
196
|
+
+------+
|
|
197
|
+
| Text |
|
|
198
|
+
+------+
|
|
199
|
+
```
|
|
200
|
+
<!-- example:subgraph:end -->
|
|
201
|
+
|
|
202
|
+
</details>
|
|
203
|
+
|
|
204
|
+
## API
|
|
205
|
+
|
|
206
|
+
### `render(source, options?) → Promise<string>`
|
|
207
|
+
|
|
208
|
+
```js
|
|
209
|
+
const ascii = await render(source);
|
|
210
|
+
const unicode = await render(source, { charset: 'unicode' });
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
| Option | Values | Default |
|
|
214
|
+
| --- | --- | --- |
|
|
215
|
+
| `charset` | `'ascii'`, `'unicode'` | `'ascii'` |
|
|
216
|
+
|
|
217
|
+
Output has no trailing spaces or trailing newline. There is no fixed total width, and labels are not truncated. Dense diagrams may expand to preserve wire spacing and readable label placement.
|
|
218
|
+
|
|
219
|
+
### `parse(source) → FlowGraph`
|
|
220
|
+
|
|
221
|
+
Returns an independent, serializable graph, retaining the exact original input.
|
|
222
|
+
|
|
223
|
+
| Field | Contents |
|
|
224
|
+
| --- | --- |
|
|
225
|
+
| `source` | Original Mermaid source |
|
|
226
|
+
| `direction` | Normalized flow direction |
|
|
227
|
+
| `nodes` | IDs, labels, label types, shapes, parents, styles, classes, metadata |
|
|
228
|
+
| `edges` | IDs, endpoints, labels, arrows, stroke, length, styles, classes, metadata |
|
|
229
|
+
| `subgraphs` | IDs, titles, membership, hierarchy, local directions, metadata |
|
|
230
|
+
| `classes` | Named style definitions |
|
|
231
|
+
| `metadata` | Frontmatter, directives, accessibility information, and other non-drawing data |
|
|
232
|
+
|
|
233
|
+
### Errors
|
|
234
|
+
|
|
235
|
+
```js
|
|
236
|
+
import { FlowInkError, render } from 'flowink';
|
|
237
|
+
|
|
238
|
+
try {
|
|
239
|
+
console.log(await render(source));
|
|
240
|
+
} catch (error) {
|
|
241
|
+
if (error instanceof FlowInkError) {
|
|
242
|
+
console.error(error.code, error.message);
|
|
243
|
+
if (error.line !== undefined) {
|
|
244
|
+
console.error(`Line ${error.line}, column ${error.column}`);
|
|
245
|
+
}
|
|
246
|
+
} else {
|
|
247
|
+
throw error;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Located syntax errors use one-based lines and columns in the original source. Layout failures are reported explicitly; a successful render must not silently omit an edge.
|
|
253
|
+
|
|
254
|
+
## Compatibility
|
|
255
|
+
|
|
256
|
+
**The baseline is Mermaid 12.0.0**, tag `mermaid@12.0.0`, commit [`98a0945`](https://github.com/mermaid-js/mermaid/tree/98a0945418c76238f15df2afaddbba4272656c3b). The official Jison grammar is vendored unchanged and generated into JavaScript during the build. See [grammar provenance](vendor/mermaid/README.md).
|
|
257
|
+
|
|
258
|
+
```text
|
|
259
|
+
Mermaid source → parser + graph model → ELK layout → character grid → text
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
| Feature | Text representation |
|
|
263
|
+
| --- | --- |
|
|
264
|
+
| Flowchart/graph syntax, chained links, multi-node links, edge IDs | Parsed using the pinned upstream grammar |
|
|
265
|
+
| Branches, cycles, parallel edges, self-loops | Orthogonal routes with separate endpoints and collision checks |
|
|
266
|
+
| Nested subgraphs and cross-boundary edges | Containers with Mermaid's direction inheritance behavior |
|
|
267
|
+
| Common node shapes | Text approximations |
|
|
268
|
+
| Other shapes, images, icons | Shape annotations or text placeholders |
|
|
269
|
+
| HTML and Markdown labels | Plain text, preserving line breaks and entities |
|
|
270
|
+
| Colors, CSS, animation, links, callbacks | Retained as data; callbacks are not executed and images are not fetched |
|
|
271
|
+
| Invisible edges | Influence layout without visible strokes |
|
|
272
|
+
|
|
273
|
+
FlowInk uses its own text layout rather than Mermaid SVG coordinates. Nonjoining crossings use `#` in ASCII and `╳` in Unicode, distinct from corners and junctions. Alignment follows character display widths; fonts and terminals can differ in their Unicode width conventions.
|
|
274
|
+
|
|
275
|
+
Compatibility covers this version's **flowcharts**, not other Mermaid diagram types or future releases. The first version supplies the package API; a CLI and editor UI are outside its current scope.
|
|
276
|
+
|
|
277
|
+
## Development
|
|
278
|
+
|
|
279
|
+
```sh
|
|
280
|
+
git clone https://github.com/william1010121/flowink.git
|
|
281
|
+
cd flowink
|
|
282
|
+
npm ci
|
|
283
|
+
npm run build
|
|
284
|
+
npm test
|
|
285
|
+
npm run test:types
|
|
286
|
+
npm run test:package
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Verification
|
|
290
|
+
|
|
291
|
+
The suite covers **435 upstream fixtures**, including complete static inputs and bounded arrow, length, keyword, and character matrices. It also checks graph geometry, labels, Unicode widths, error locations, and repeated/concurrent calls.
|
|
292
|
+
|
|
293
|
+
- **Parser comparison:** upstream cases use Mermaid's raw parser and FlowDB; preprocessing cases use Mermaid's public API. [Fixture provenance and exclusions](test/fixtures/upstream/README.md).
|
|
294
|
+
- **Package installation:** `test:package` checks archive contents and installs the tarball in a temporary directory outside the project.
|
|
295
|
+
- **Browser execution:** `npm run test:browser:build` generates `.cache/browser-smoke/index.html`. Serve that directory over HTTP and open the page to compare five diagrams in both charsets against Node.js output. Results are available in `window.__flowinkSmoke`.
|
|
296
|
+
|
|
297
|
+
Fixtures are checked in, so tests do not download upstream source on each run. Mermaid itself is a development-only oracle dependency. Rendering is asynchronous but still uses CPU; applications can run large layouts in their own worker.
|
|
298
|
+
|
|
299
|
+
## License
|
|
300
|
+
|
|
301
|
+
FlowInk's own code is [MIT](LICENSE). Mermaid-derived files retain their MIT attribution. Runtime dependencies retain their own licenses, including elkjs's `EPL-2.0 OR GPL-3.0-or-later`. See [third-party notices](NOTICE.md).
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** An input or layout error. Locations refer to the original Mermaid source. */
|
|
2
|
+
export class FlowInkError extends Error {
|
|
3
|
+
/** @param {string} message @param {{code?:string,line?:number,column?:number,cause?:unknown}} [options] */
|
|
4
|
+
constructor(message: string, options?: {
|
|
5
|
+
code?: string;
|
|
6
|
+
line?: number;
|
|
7
|
+
column?: number;
|
|
8
|
+
cause?: unknown;
|
|
9
|
+
});
|
|
10
|
+
code: string;
|
|
11
|
+
line: number;
|
|
12
|
+
column: number;
|
|
13
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** @typedef {import('./types.js').FlowGraph} FlowGraph */
|
|
2
|
+
/** @typedef {import('./types.js').RenderOptions} RenderOptions */
|
|
3
|
+
/**
|
|
4
|
+
* Render a Mermaid 12.0.0 flowchart as a plain text diagram.
|
|
5
|
+
* @param {string} source Mermaid flowchart source.
|
|
6
|
+
* @param {RenderOptions} [options]
|
|
7
|
+
* @returns {Promise<string>}
|
|
8
|
+
*/
|
|
9
|
+
export function render(source: string, options?: RenderOptions): Promise<string>;
|
|
10
|
+
export type FlowGraph = import("./types.js").FlowGraph;
|
|
11
|
+
export type RenderOptions = import("./types.js").RenderOptions;
|
|
12
|
+
import { parse } from './parse.js';
|
|
13
|
+
import { FlowInkError } from './errors.js';
|
|
14
|
+
export { parse, FlowInkError };
|