dewasm-pozeiden 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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/LICENSE-POZEIDEN +75 -0
- data/README.md +231 -0
- data/lib/dewasm/pozeiden/version.rb +10 -0
- data/lib/dewasm/pozeiden/wasm_module.rb +82434 -0
- data/lib/dewasm/pozeiden.rb +155 -0
- metadata +50 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 840e85a24319fdbcc2c333a875f547f80a90370f3f9ce8ee1f6b79f6095be983
|
|
4
|
+
data.tar.gz: 44f58f21c7df3ac443bd14033cdd9c8484ed75061cd3f5fb27d02fc87c5a02e0
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 81a693085219f6198a4b7a0189ff0eef7a235494408614025662e8238a2c02823c2ca534af77c75b1f2cf8a2c287e23d8e4da88b6d9974c30b2e71a766978f21
|
|
7
|
+
data.tar.gz: e8c5324e3437768a57c2ad18fe12c57d385b30243b0d9d84055f380a2774e035c9222d0b4a1236f610205c512c7136d1a8337a4d417ff9bba7a6b73316e8ada1
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hiroya Fujinami
|
|
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.
|
data/LICENSE-POZEIDEN
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# PolyForm Noncommercial License 1.0.0
|
|
2
|
+
|
|
3
|
+
<https://polyformproject.org/licenses/noncommercial/1.0.0>
|
|
4
|
+
|
|
5
|
+
Required Notice: Copyright © 2025 Star City Security Consulting, LLC (SC2) (https://sc2.in)
|
|
6
|
+
|
|
7
|
+
## Acceptance
|
|
8
|
+
|
|
9
|
+
In order to get any license under these terms, you must agree to them as both strict obligations and conditions to all your licenses.
|
|
10
|
+
|
|
11
|
+
## Copyright License
|
|
12
|
+
|
|
13
|
+
The licensor grants you a copyright license for the software to do everything you might do with the software that would otherwise infringe the licensor's copyright in it for any permitted purpose. However, you may only distribute the software according to [Distribution License](#distribution-license) and make changes or new works based on the software according to [Changes and New Works License](#changes-and-new-works-license).
|
|
14
|
+
|
|
15
|
+
## Distribution License
|
|
16
|
+
|
|
17
|
+
The licensor grants you an additional copyright license to distribute copies of the software. Your license to distribute covers distributing the software with changes and new works permitted by [Changes and New Works License](#changes-and-new-works-license).
|
|
18
|
+
|
|
19
|
+
## Notices
|
|
20
|
+
|
|
21
|
+
You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms or the URL for them above, as well as copies of any plain-text lines beginning with `Required Notice:` that the licensor provided with the software. For example:
|
|
22
|
+
|
|
23
|
+
> Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
|
|
24
|
+
|
|
25
|
+
## Changes and New Works License
|
|
26
|
+
|
|
27
|
+
The licensor grants you an additional copyright license to make changes and new works based on the software for any permitted purpose.
|
|
28
|
+
|
|
29
|
+
## Patent License
|
|
30
|
+
|
|
31
|
+
The licensor grants you a patent license for the software that covers patent claims the licensor can license, or becomes able to license, that you would infringe by using the software.
|
|
32
|
+
|
|
33
|
+
## Noncommercial Purposes
|
|
34
|
+
|
|
35
|
+
Any noncommercial purpose is a permitted purpose.
|
|
36
|
+
|
|
37
|
+
## Personal Uses
|
|
38
|
+
|
|
39
|
+
Personal use for research, experiment, and testing for the benefit of public knowledge, personal study, private entertainment, hobby projects, amateur pursuits, or religious observance, without any anticipated commercial application, is use for a permitted purpose.
|
|
40
|
+
|
|
41
|
+
## Noncommercial Organizations
|
|
42
|
+
|
|
43
|
+
Use by any charitable organization, educational institution, public research organization, public safety or health organization, environmental protection organization, or government institution is use for a permitted purpose regardless of the source of funding or obligations resulting from the funding.
|
|
44
|
+
|
|
45
|
+
## Fair Use
|
|
46
|
+
|
|
47
|
+
You may have "fair use" rights for the software under the law. These terms do not limit them.
|
|
48
|
+
|
|
49
|
+
## No Other Rights
|
|
50
|
+
|
|
51
|
+
These terms do not allow you to sublicense or transfer any of your licenses to anyone else, or prevent the licensor from granting licenses to anyone else. These terms do not imply any other licenses.
|
|
52
|
+
|
|
53
|
+
## Patent Defense
|
|
54
|
+
|
|
55
|
+
If you make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
|
|
56
|
+
|
|
57
|
+
## Violations
|
|
58
|
+
|
|
59
|
+
The first time you are notified in writing that you have violated any of these terms, or done anything with the software not covered by your licenses, your licenses can nonetheless continue if you come into full compliance with these terms, and take practical steps to correct past violations, within 32 days of receiving notice. Otherwise, all your licenses end immediately.
|
|
60
|
+
|
|
61
|
+
## No Liability
|
|
62
|
+
|
|
63
|
+
***As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.***
|
|
64
|
+
|
|
65
|
+
## Definitions
|
|
66
|
+
|
|
67
|
+
The **licensor** is the individual or entity offering these terms, and the **software** is the software the licensor makes available under these terms.
|
|
68
|
+
|
|
69
|
+
**You** refers to the individual or entity agreeing to these terms.
|
|
70
|
+
|
|
71
|
+
**Your company** is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. **Control** means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
|
|
72
|
+
|
|
73
|
+
**Your licenses** are all the licenses granted to you for the software under these terms.
|
|
74
|
+
|
|
75
|
+
**Use** means anything you do with the software requiring one of your licenses.
|
data/README.md
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# dewasm-pozeiden
|
|
2
|
+
|
|
3
|
+
**Mermaid** diagram rendering in **pure Ruby**.
|
|
4
|
+
|
|
5
|
+
[pozeiden](https://github.com/sc2in/pozeiden) is a mermaid renderer written in Zig.
|
|
6
|
+
This gem compiles it to `wasm32-wasi` and converts that WebAssembly module to Ruby source with [dewasm](https://github.com/dewasm/dewasm), so rendering runs on plain Ruby.
|
|
7
|
+
There is *no browser*, *no native extension*, and *no wasm runtime* involved: the gem is Ruby code that a stock `ruby` executes.
|
|
8
|
+
|
|
9
|
+
The gem is built from pozeiden 0.4.1 at commit `071fbbb85fb73a06994c163c6093123bd3ac11f6`, pinned in `wasm/build.zig.zon` and surfaced as `Dewasm::Pozeiden::POZEIDEN_VERSION`.
|
|
10
|
+
|
|
11
|
+
Seventeen diagram types are supported, the ones pozeiden implements: pie, flowchart, sequence, gitgraph, class, state, er, gantt, timeline, xychart, quadrant, mindmap, sankey, c4, block, requirement, and kanban.
|
|
12
|
+
|
|
13
|
+
> [!NOTE]
|
|
14
|
+
> This gem **cannot be used commercially**: the rendering core derives from pozeiden, which is licensed under the [PolyForm Noncommercial License 1.0.0](LICENSE-POZEIDEN).
|
|
15
|
+
>
|
|
16
|
+
> [dewasm-merman](https://github.com/dewasm/ruby-merman) is licensed under MIT and covers more diagram types, but is much larger.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```console
|
|
21
|
+
$ gem install dewasm-pozeiden
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Or in `Gemfile`:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
gem "dewasm-pozeiden"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Ruby 3.4 or newer is required, because the converted module stores WebAssembly linear memory in an `IO::Buffer`.
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
Render a diagram to an SVG string:
|
|
35
|
+
|
|
36
|
+
```ruby
|
|
37
|
+
require "dewasm/pozeiden"
|
|
38
|
+
|
|
39
|
+
svg = Dewasm::Pozeiden.render(<<~MERMAID)
|
|
40
|
+
flowchart LR
|
|
41
|
+
A[Start] --> B{Choice}
|
|
42
|
+
B --> C[End]
|
|
43
|
+
MERMAID
|
|
44
|
+
|
|
45
|
+
File.write("flowchart.svg", svg)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Unrecognised input renders pozeiden's fallback SVG and counts as success.
|
|
49
|
+
Pass `strict: true` to get an error instead:
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
Dewasm::Pozeiden.render("this is not a diagram at all")
|
|
53
|
+
# => "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"400\" height=\"120\"> ..."
|
|
54
|
+
|
|
55
|
+
Dewasm::Pozeiden.render("this is not a diagram at all", strict: true)
|
|
56
|
+
# raises Dewasm::Pozeiden::Error: pozeiden returned error.UnknownDiagramType
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`render_with_metadata` also returns the detected diagram type and the accessibility metadata declared in the source:
|
|
60
|
+
|
|
61
|
+
```ruby
|
|
62
|
+
result = Dewasm::Pozeiden.render_with_metadata(<<~MERMAID)
|
|
63
|
+
flowchart LR
|
|
64
|
+
accTitle: Build pipeline
|
|
65
|
+
accDescr: How a build flows
|
|
66
|
+
A --> B
|
|
67
|
+
MERMAID
|
|
68
|
+
|
|
69
|
+
result.diagram_type # => :flowchart
|
|
70
|
+
result.title # => "Build pipeline"
|
|
71
|
+
result.descr # => "How a build flows"
|
|
72
|
+
result.svg # => "<svg ...>"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`detect_diagram_type` classifies the source without rendering it:
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
Dewasm::Pozeiden.detect_diagram_type("pie title Pets\n") # => :pie
|
|
79
|
+
Dewasm::Pozeiden.detect_diagram_type("nothing here\n") # => :unknown
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Rendering options are keyword arguments of `render` and `render_with_metadata`:
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
Dewasm::Pozeiden.render(source, max_width: 800, theme_override: { node_fill: "#ffe4b5" })
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
| Keyword | Meaning |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| `strict:` | Raise on unrecognised input instead of rendering the fallback SVG. Default `false`. |
|
|
91
|
+
| `max_width:` | Scale the SVG so its width does not exceed this many user units. `0` disables. |
|
|
92
|
+
| `max_height:` | Scale the SVG so its height does not exceed this many user units. `0` disables. |
|
|
93
|
+
| `scale:` | Uniform scale factor for the SVG `viewBox`, ignored when `max_width` or `max_height` is set. |
|
|
94
|
+
| `theme_override:` | Theme values to override for this call. |
|
|
95
|
+
| `random:` | Source of random bytes for the module's `random_get` import, anything responding to `bytes(count)`. Default `Random`. |
|
|
96
|
+
|
|
97
|
+
The accepted `theme_override` keys are pozeiden's `ThemeOverride` fields: `background`, `text_color`, `node_fill`, `node_stroke`, `edge_color`, `font_size`, `font_size_small`, and `font_family`.
|
|
98
|
+
The first five and the last take a string, the two font sizes take an integer.
|
|
99
|
+
Any other key raises `Dewasm::Pozeiden::Error` with `zig_error` `:UnknownField`; unknown keys are never ignored.
|
|
100
|
+
|
|
101
|
+
Errors that pozeiden itself reports carry its Zig error name:
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
begin
|
|
105
|
+
Dewasm::Pozeiden.render(source, strict: true)
|
|
106
|
+
rescue Dewasm::Pozeiden::Error => e
|
|
107
|
+
e.zig_error # => :UnknownDiagramType
|
|
108
|
+
end
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Input larger than 4 MiB raises `Dewasm::Pozeiden::Error` before the WebAssembly module is called.
|
|
112
|
+
That is the size of the module's input buffer, chosen to match pozeiden's own `max_input_bytes` default.
|
|
113
|
+
|
|
114
|
+
## API
|
|
115
|
+
|
|
116
|
+
Every call instantiates the converted module, runs, and drops it.
|
|
117
|
+
WebAssembly linear memory is not retained between calls, so no state carries over from one render to the next.
|
|
118
|
+
|
|
119
|
+
| Ruby | pozeiden |
|
|
120
|
+
| --- | --- |
|
|
121
|
+
| `Dewasm::Pozeiden.render(text, **options)` | `renderWithOptions(allocator, text, RenderOptions)` |
|
|
122
|
+
| `Dewasm::Pozeiden.render_with_metadata(text, **options)` | `renderWithMetadata(allocator, text, RenderOptions)` |
|
|
123
|
+
| `Dewasm::Pozeiden.detect_diagram_type(text)` | `detectDiagramType(text)` |
|
|
124
|
+
| `Dewasm::Pozeiden::RenderResult` | `RenderResult` |
|
|
125
|
+
| `Dewasm::Pozeiden::Error#zig_error` | the `@errorName` of the returned error |
|
|
126
|
+
| `Dewasm::Pozeiden::POZEIDEN_VERSION` | the pinned upstream revision |
|
|
127
|
+
|
|
128
|
+
`Dewasm::Pozeiden.render` maps to `renderWithOptions` rather than to the two-argument `render`, because the options are always sent; the defaults are pozeiden's own, so `Dewasm::Pozeiden.render(text)` renders what `render(allocator, text)` renders.
|
|
129
|
+
|
|
130
|
+
## How it is built
|
|
131
|
+
|
|
132
|
+
`wasm/` is a self-contained Zig project: it depends on pozeiden pinned by commit in `wasm/build.zig.zon`, fetched by the Zig package manager into the gitignored `wasm/zig-pkg/`, and `wasm/src/shim.zig` is this project's own WebAssembly interface over pozeiden's public API, not upstream's playground shim.
|
|
133
|
+
The module is built for `wasm32-wasi` in `ReleaseSmall`, single threaded, with the entry point disabled and `rdynamic` set, post-processed with `wasm-opt -Oz --enable-bulk-memory --enable-sign-ext --enable-nontrapping-float-to-int`, and converted to Ruby by dewasm at the revision recorded in `DEWASM_REVISION`.
|
|
134
|
+
|
|
135
|
+
Neither build product is committed: `wasm/pozeiden.wasm` and `lib/dewasm/pozeiden/wasm_module.rb` are produced by the build, and the generated Ruby is shipped in the gem.
|
|
136
|
+
|
|
137
|
+
## Size, memory, and speed
|
|
138
|
+
|
|
139
|
+
<!-- measurements:begin -->
|
|
140
|
+
Measured on macOS 26.5.2, Apple M1 Pro, Ruby 4.0.4.
|
|
141
|
+
|
|
142
|
+
| Quantity | Value |
|
|
143
|
+
| --- | --- |
|
|
144
|
+
| `wasm/pozeiden.wasm` after `wasm-opt -Oz` | 479 KB |
|
|
145
|
+
| Generated `wasm_module.rb` | 2.6 MB |
|
|
146
|
+
| Packaged `.gem` | 366 KB |
|
|
147
|
+
| `require "dewasm/pozeiden"` | 322 ms |
|
|
148
|
+
| Resident memory after `require` | 126.9 MB |
|
|
149
|
+
| `render`, flowchart | 3.6 ms |
|
|
150
|
+
| `render`, pie chart | 38 ms |
|
|
151
|
+
| `render_with_metadata`, flowchart | 3.1 ms |
|
|
152
|
+
| `detect_diagram_type` | 0.3 ms |
|
|
153
|
+
<!-- measurements:end -->
|
|
154
|
+
|
|
155
|
+
The rows fall into three groups.
|
|
156
|
+
The first ones are what ships: the WebAssembly module, the Ruby source dewasm generates from it, and the packaged gem.
|
|
157
|
+
The next two are the one-time cost of loading that source, in time and in resident memory.
|
|
158
|
+
The rest are per-call costs, one call of each function on a small diagram.
|
|
159
|
+
|
|
160
|
+
Three facts hold whatever the magnitudes are.
|
|
161
|
+
Resident memory after `require` is dominated by the instruction sequences of the loaded code, not by rendering, so it is paid once and does not grow with the number of calls.
|
|
162
|
+
Each call allocates the module's linear memory, which holds the 4 MiB input buffer, the 8 MiB scratch arena, and the 4 MiB output buffer, and drops it when the call returns.
|
|
163
|
+
Rendering is deterministic: two renders of the same source produce byte-identical SVGs, both with the default random source and with a fixed one.
|
|
164
|
+
|
|
165
|
+
The numbers move with the pinned pozeiden commit and with the dewasm revision used to generate the module, so rerun `rake measure` after changing either.
|
|
166
|
+
|
|
167
|
+
## Tasks
|
|
168
|
+
|
|
169
|
+
The Rakefile drives everything.
|
|
170
|
+
`rake generate` does not build the WebAssembly module itself, so a clean checkout runs `rake wasm:build` first; from there `rake test` runs what it needs.
|
|
171
|
+
|
|
172
|
+
### `rake wasm:build`
|
|
173
|
+
|
|
174
|
+
```console
|
|
175
|
+
$ rake wasm:build
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Builds `wasm/` with `zig build` and post-processes it into `wasm/pozeiden.wasm` with `wasm-opt -Oz`.
|
|
179
|
+
It needs Zig 0.16 and `wasm-opt` from Binaryen.
|
|
180
|
+
|
|
181
|
+
### `rake generate`
|
|
182
|
+
|
|
183
|
+
```console
|
|
184
|
+
$ rake generate
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Converts that module into the Ruby the gem ships.
|
|
188
|
+
It needs `wasm/pozeiden.wasm`, and a dewasm binary, its path in `DEWASM_BIN`.
|
|
189
|
+
|
|
190
|
+
### `rake test`
|
|
191
|
+
|
|
192
|
+
```console
|
|
193
|
+
$ rake test
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Runs `test/` against the generated module.
|
|
197
|
+
It needs `rake generate`.
|
|
198
|
+
|
|
199
|
+
### `rake measure`
|
|
200
|
+
|
|
201
|
+
```console
|
|
202
|
+
$ rake measure
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Refreshes the measurements table in `README.md` with numbers from this machine.
|
|
206
|
+
It needs `rake generate`, and a built gem in the checkout for the `.gem` row.
|
|
207
|
+
|
|
208
|
+
### `rake build`
|
|
209
|
+
|
|
210
|
+
```console
|
|
211
|
+
$ rake build
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Packages the gem.
|
|
215
|
+
It needs `rake generate`.
|
|
216
|
+
|
|
217
|
+
### `rake clean`
|
|
218
|
+
|
|
219
|
+
```console
|
|
220
|
+
$ rake clean
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Removes the build products, `wasm/zig-out`, and `wasm/.zig-cache`.
|
|
224
|
+
It needs nothing.
|
|
225
|
+
|
|
226
|
+
## License
|
|
227
|
+
|
|
228
|
+
The code in this repository (the shim, the wrapper, the tools, and the tests) is Copyright (c) 2026 Hiroya Fujinami, under the [MIT License](LICENSE).
|
|
229
|
+
|
|
230
|
+
The generated `wasm_module.rb` derives from pozeiden and stays under the [PolyForm Noncommercial License 1.0.0](LICENSE-POZEIDEN), whose required notice is preserved there: Copyright © 2025 Star City Security Consulting, LLC (SC2).
|
|
231
|
+
Every render runs that module, so use of the gem as a whole is bound by the noncommercial restriction.
|