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 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.
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dewasm
4
+ module Pozeiden
5
+ VERSION = "0.1.0"
6
+
7
+ # The pozeiden revision this gem's WebAssembly module was built from.
8
+ POZEIDEN_VERSION = "0.4.1 (071fbbb85fb73a06994c163c6093123bd3ac11f6)"
9
+ end
10
+ end