yrby 0.6.1 → 0.7.1
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 +4 -4
- data/CHANGELOG.md +75 -28
- data/Cargo.lock +29 -29
- data/README.md +297 -98
- data/ext/yrby/Cargo.toml +3 -3
- data/ext/yrby/crates/html-core/Cargo.toml +5 -4
- data/ext/yrby/crates/html-core/src/lib.rs +3 -7
- data/ext/yrby/crates/lexical-html/Cargo.toml +5 -4
- data/ext/yrby/crates/lexical-html/src/lib.rs +6 -10
- data/ext/yrby/crates/prosemirror-html/Cargo.toml +5 -4
- data/ext/yrby/crates/prosemirror-html/src/lib.rs +114 -72
- data/ext/yrby/src/lib.rs +10 -10
- data/ext/yrby/src/protocol.rs +63 -0
- data/lib/generators/yrby/install/templates/document_channel.rb +1 -1
- data/lib/generators/yrby/tables/tables_generator.rb +3 -3
- data/lib/y/decoder.rb +64 -0
- data/lib/y/version.rb +1 -1
- data/lib/y.rb +2 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 80931cbbabc08011f5f8ac78dfcf92e648feaf39ef8338ba7abb77bd575bb231
|
|
4
|
+
data.tar.gz: 340e157cea8aeee6ab5013ca43571e74a8f01f514ee8172aad81e14c10cf55b6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fe5ba9524856f360def8b53a942bc8142017cb87254344aaeab9b90d4006471d3f480db5c527e4563f031ebc25d9c504c3070d306308676e10f11127ac6695c7
|
|
7
|
+
data.tar.gz: ef2cf7df98eced8c39ad5059ff12d3dfbdd8fc6dbd22c949163cc074d1710add09b9c4adb9d4c4ca24fa957f1b5983578c9f38623a80b0a4172027da4505a3a9
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,53 @@ All notable changes to this project are documented here. The format is based on
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project aims
|
|
5
5
|
to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.7.1] - 2026-08-19
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- `Y::ProseMirror` and `Y::Tiptap` keep marks shared by adjacent text
|
|
12
|
+
runs open across them, the way ProseMirror's own serializer does:
|
|
13
|
+
bold then bold-italic renders as `<strong>a<em>b</em></strong>`, not
|
|
14
|
+
as two sibling `<strong>` wraps. A mark whose attributes differ
|
|
15
|
+
between runs never merges. Found by the new cross-renderer
|
|
16
|
+
verification, which checks the renderers against a live Tiptap
|
|
17
|
+
editor, `@tiptap/html`'s static `generateHTML`, `tiptap-php`,
|
|
18
|
+
Lexical's `$generateHtmlFromNodes`, and Payload CMS's
|
|
19
|
+
`convertLexicalToHTML` on a shared corpus.
|
|
20
|
+
|
|
21
|
+
## [0.7.0] - 2026-08-11
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- `Y::Decoder` ships in the core gem and loads with `require "y"`. It was
|
|
26
|
+
scaffolded as a separate `yrby-decoder` gem, but it is 66 lines of pure
|
|
27
|
+
Ruby over `Doc#read_text` / `read_xml`, requires the native core either
|
|
28
|
+
way, and the separate gem was never published, so the split left the
|
|
29
|
+
module in no gem at all. The `yrby-decoder` name is retired unused.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- `Doc#handle_sync_message` answers a SyncStep1 with the doc's full state,
|
|
34
|
+
pending included, matching Y.js's `encodeStateAsUpdate`. It previously
|
|
35
|
+
served integrated-only state. A peer parks a served pending struct the
|
|
36
|
+
same way the doc did and heals it when the missing dependency arrives
|
|
37
|
+
from its sender's ack-driven retransmit. `compacted_state_update` still
|
|
38
|
+
excludes pending, so compaction cannot freeze a gap into a snapshot.
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- **`Doc#update_advances?` no longer misreads a gappy merged update carrying
|
|
43
|
+
novel content as a no-op.** A crafted frame can hide an internal gap behind
|
|
44
|
+
a Skip block while its post-gap blocks still integrate (yrs plants a Skip
|
|
45
|
+
hole in the store). That moves neither the doc's public state vector nor
|
|
46
|
+
pending, so the probe comparison reported genuinely novel content as
|
|
47
|
+
"doesn't advance"; `update_ready?` accepted the frame and the doc applied
|
|
48
|
+
it, but it was never recorded to the durable log or broadcast. Any
|
|
49
|
+
insertion past the update's own (Skip-capped) `state_vector()` now
|
|
50
|
+
conservatively reports as advancing. Not reachable through standard Yjs
|
|
51
|
+
providers (a client's own updates and diffs are gap-free), so this closes
|
|
52
|
+
a hostile-input hole, not a real-world regression.
|
|
53
|
+
|
|
7
54
|
## [0.6.1] - 2026-08-04
|
|
8
55
|
|
|
9
56
|
### Fixed
|
|
@@ -21,16 +68,16 @@ to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
21
68
|
### Added
|
|
22
69
|
|
|
23
70
|
- **Custom render rules for `Y::Lexical` and `Y::ProseMirror`.** Both
|
|
24
|
-
renderers now take a block registering rules per node type
|
|
71
|
+
renderers now take a block registering rules per node type:
|
|
25
72
|
`rules.node "callout", tag: "aside"` for markup-as-data, a Ruby block for
|
|
26
|
-
logic
|
|
73
|
+
logic, plus `nodes:`/`marks:` keywords as the equivalent data form, to
|
|
27
74
|
render node types the pinned schemas don't know or to override how a
|
|
28
75
|
built-in renders.
|
|
29
76
|
Declarative rules (`tag`/`attrs`/`text`/`contains`, with templates mixing
|
|
30
77
|
literals and attribute references) render natively at full speed. Callback
|
|
31
78
|
rules run a Ruby block per node, receiving its type, attributes,
|
|
32
79
|
already-rendered children, and `child_types` (its element/block children by
|
|
33
|
-
type
|
|
80
|
+
type, the structural facts behind gallery counts and nested-list classes).
|
|
34
81
|
The block runs after the document read has finished, never while the doc is
|
|
35
82
|
locked, so it can safely read or write the same doc. Blocks are proven
|
|
36
83
|
sufficient for whole schemas: the gem's own editor schemas (`Y::Lexxy`,
|
|
@@ -38,13 +85,13 @@ to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
38
85
|
output byte-identical to a live editor's. With no callback rules the
|
|
39
86
|
render path is unchanged, byte for byte. See "Custom nodes and marks" in
|
|
40
87
|
the README.
|
|
41
|
-
- **`Y::Lexical#node_types` / `Y::ProseMirror#node_types
|
|
88
|
+
- **`Y::Lexical#node_types` / `Y::ProseMirror#node_types`: schema
|
|
42
89
|
discovery.** Ask a real document which node types it holds and what they
|
|
43
90
|
look like: counts, attribute names as stored, child types, whether text
|
|
44
91
|
runs appear, and whether a builtin or one of your rules already handles
|
|
45
92
|
each ("handled" nil marks what still needs a rule). Editors store names
|
|
46
93
|
you'd never guess; this is how you find them.
|
|
47
|
-
- `Y::RenderRules.escape_text` / `escape_attr
|
|
94
|
+
- `Y::RenderRules.escape_text` / `escape_attr`: the exact escaping the
|
|
48
95
|
native renderers use, for blocks that build markup from stored values
|
|
49
96
|
(ERB's `html_escape` also rewrites apostrophes, which breaks byte parity
|
|
50
97
|
with editor output).
|
|
@@ -54,15 +101,15 @@ to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
54
101
|
- **Lexical rendering is now two classes: `Y::Lexical` (core Lexical) and
|
|
55
102
|
`Y::Lexxy` (core plus the Lexxy schema as render rules).** Stock Lexical
|
|
56
103
|
has no canonical serializer, so the editor-specific class carries the
|
|
57
|
-
editor's name
|
|
104
|
+
editor's name; `Y::Lexxy.new(doc).to_html` is the byte-parity call for
|
|
58
105
|
Lexxy/Rails apps, and `Y::Lexical` is the base any other Lexical editor
|
|
59
106
|
extends with its own rules. The
|
|
60
|
-
native side renders core structure
|
|
107
|
+
native side renders core structure (paragraphs, headings, quotes, code,
|
|
61
108
|
lists, tables, links, the full text-format model. Lexxy's own node types
|
|
62
109
|
(attachments, galleries, `early_escape_code`, `horizontal_divider`) and its
|
|
63
110
|
decorations of core nodes (the table figure wrapper, header-cell styling,
|
|
64
111
|
the nested-list-item class) are rules applied beneath the app's, on the
|
|
65
|
-
same extension API
|
|
112
|
+
same extension API; the gem's Lexxy support is the API's first consumer.
|
|
66
113
|
Output is unchanged: the fixture tests still hold `to_html` byte-identical
|
|
67
114
|
to a live editor's serialized value, now through the extension path. An
|
|
68
115
|
unknown Lexical container also degrades better: its block children render
|
|
@@ -71,8 +118,8 @@ to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
71
118
|
ProseMirror) and `Y::Tiptap` (core plus Tiptap's extension nodes as render
|
|
72
119
|
rules).** `Y::Tiptap.new(doc).to_html` is the byte-parity call for Tiptap
|
|
73
120
|
apps. The native side renders prosemirror-schema-basic plus the
|
|
74
|
-
prosemirror-tables family; Tiptap's extension nodes
|
|
75
|
-
the details family
|
|
121
|
+
prosemirror-tables family; Tiptap's extension nodes (task lists, mentions,
|
|
122
|
+
the details family) are `Y::Tiptap::NODES` rules. Marks stay native in the
|
|
76
123
|
base class: mark rendering (nesting order, `textStyle` CSS, `code`
|
|
77
124
|
exclusivity) runs through text-run machinery node rules don't reach, so
|
|
78
125
|
`Y::ProseMirror` still renders Tiptap's full mark set and `rules.mark`
|
|
@@ -83,7 +130,7 @@ to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
83
130
|
|
|
84
131
|
### Added
|
|
85
132
|
|
|
86
|
-
- **`Y::Lexical
|
|
133
|
+
- **`Y::Lexical`: render Lexical/Lexxy documents to HTML.**
|
|
87
134
|
`Y::Lexical.new(doc).to_html` turns a Lexxy document into HTML on the server,
|
|
88
135
|
with no Node process or headless editor. The output is identical to the HTML
|
|
89
136
|
a `lexxy-editor` submits to Rails; the tests check it byte-for-byte against a
|
|
@@ -101,12 +148,12 @@ to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
101
148
|
|
|
102
149
|
### Added
|
|
103
150
|
|
|
104
|
-
- **`Y::ProseMirror
|
|
151
|
+
- **`Y::ProseMirror`: render ProseMirror/Tiptap documents to HTML.**
|
|
105
152
|
`Y::ProseMirror.new(doc).to_html` turns a Tiptap document into HTML on the
|
|
106
153
|
server, with no Node process or headless editor. The output matches Tiptap's
|
|
107
154
|
own `getHTML()`; the tests check it byte-for-byte against a document captured
|
|
108
155
|
from a real editor. It follows `ueberdosis/tiptap-php` and reads both name
|
|
109
|
-
styles editors use
|
|
156
|
+
styles editors use: Tiptap's `bulletList`/`bold` and prosemirror-schema-basic's
|
|
110
157
|
`bullet_list`/`strong`. Covers paragraphs, headings, blockquotes,
|
|
111
158
|
bullet/ordered/task lists, code blocks, links, images, mentions, details,
|
|
112
159
|
hard breaks, horizontal rules, tables, text styles (color, font family), and
|
|
@@ -122,8 +169,8 @@ Fixes from a full source review.
|
|
|
122
169
|
|
|
123
170
|
- **`Doc#update_ready?` is now exact.** It previously checked only the
|
|
124
171
|
per-client clock lower bound, but yrs's real integration gate also requires
|
|
125
|
-
every block referenced by an item's origin / right-origin / parent
|
|
126
|
-
routinely belong to *other* clients
|
|
172
|
+
every block referenced by an item's origin / right-origin / parent (which
|
|
173
|
+
routinely belong to *other* clients) and post-Skip blocks in a merged update
|
|
127
174
|
sit above the lower bound. An update could pass the clock check yet park as
|
|
128
175
|
pending; downstream, `update_advances?` then misread the parked update as an
|
|
129
176
|
already-applied retry (pending doesn't move a state vector) and the sync
|
|
@@ -147,7 +194,7 @@ Fixes from a full source review.
|
|
|
147
194
|
### Changed
|
|
148
195
|
|
|
149
196
|
- `update_advances?` skips its full-document probe when the update carries
|
|
150
|
-
blocks beyond the doc's state vector (a novel update trivially advances)
|
|
197
|
+
blocks beyond the doc's state vector (a novel update trivially advances);
|
|
151
198
|
the common case no longer pays O(doc) per frame.
|
|
152
199
|
- The gem no longer packages the `yrby-decoder` gem's files (they ship in that
|
|
153
200
|
gem; the duplicate copy could shadow a newer standalone release), and now
|
|
@@ -158,7 +205,7 @@ Fixes from a full source review.
|
|
|
158
205
|
### Fixed
|
|
159
206
|
|
|
160
207
|
- **Sync no longer serves un-integrable pending structs.** When a doc holds a
|
|
161
|
-
*pending* struct (a gappy update whose causally-prior update is missing
|
|
208
|
+
*pending* struct (a gappy update whose causally-prior update is missing, e.g.
|
|
162
209
|
legacy data recorded before the `update_ready?` gate existed), its integrated
|
|
163
210
|
state vector is empty but `encode_state_as_update` merges the pending bytes back
|
|
164
211
|
in. Answering a peer's `SyncStep1` with that state handed the peer content it
|
|
@@ -166,18 +213,18 @@ Fixes from a full source review.
|
|
|
166
213
|
non-empty-content mismatch drove endless resync traffic (observed as a browser
|
|
167
214
|
re-sending frames several times a second). `handle_sync_message` now answers
|
|
168
215
|
`SyncStep1` with **integrated-only** state, so a server never serves a struct it
|
|
169
|
-
can't integrate itself. Neutralizes existing poisoned server state on deploy
|
|
216
|
+
can't integrate itself. Neutralizes existing poisoned server state on deploy;
|
|
170
217
|
no migration needed. The server's own pending is untouched and still heals if
|
|
171
218
|
the missing dependency later arrives (only then does the content become
|
|
172
219
|
visible in sync). Live delta relay (`Update` frames) is unchanged.
|
|
173
220
|
|
|
174
221
|
### Added
|
|
175
222
|
|
|
176
|
-
- `Doc#pending
|
|
223
|
+
- `Doc#pending?`: true if the doc holds un-integrable pending structs or a
|
|
177
224
|
pending delete set (content waiting on a missing causally-prior update).
|
|
178
|
-
- `Doc#compacted_state_update
|
|
225
|
+
- `Doc#compacted_state_update`: like `encode_state_as_update` (full state) but
|
|
179
226
|
**gap-free**: excludes pending structs/delete set. Use it when persisting or
|
|
180
|
-
serving state other peers will apply. Non-destructive
|
|
227
|
+
serving state other peers will apply. Non-destructive; the doc keeps its
|
|
181
228
|
pending (so it can still heal), and `encode_state_as_update` stays lossless for
|
|
182
229
|
raw-update recovery.
|
|
183
230
|
|
|
@@ -195,13 +242,13 @@ Fixes from a full source review.
|
|
|
195
242
|
before vs. after a trial apply on an isolated probe: a genuinely new deletion
|
|
196
243
|
changes it (`true`); an already-applied retry re-encodes identically (`false`).
|
|
197
244
|
Insert/format-only updates keep the cheaper state-vector path, so only
|
|
198
|
-
delete-bearing frames
|
|
245
|
+
delete-bearing frames (a minority) pay for the exact comparison. The exactly-
|
|
199
246
|
once guarantee is unchanged in the safe direction: a real deletion is never
|
|
200
247
|
dropped.
|
|
201
248
|
|
|
202
249
|
This lets `yrby-actioncable` (and any caller gating `on_change` on
|
|
203
|
-
`update_advances?`) settle a duplicate pure-delete frame as `:applied`
|
|
204
|
-
but not stored or relayed
|
|
250
|
+
`update_advances?`) settle a duplicate pure-delete frame as `:applied` (acked,
|
|
251
|
+
but not stored or relayed), so apps no longer need an app-level
|
|
205
252
|
encode-and-compare guard around their durable writes.
|
|
206
253
|
|
|
207
254
|
## [0.2.2] - 2026-06-30
|
|
@@ -212,7 +259,7 @@ Fixes from a full source review.
|
|
|
212
259
|
embeds child blocks (list items, table cells, nested lists) as `Y.XmlText`
|
|
213
260
|
embeds that `get_string` silently drops, so lists and tables previously came
|
|
214
261
|
back empty. `read_xml` now walks the embeds: text runs build a line, inline
|
|
215
|
-
children (links) join it, and nested block children flush and recurse
|
|
262
|
+
children (links) join it, and nested block children flush and recurse, so a
|
|
216
263
|
document with headings, formatted text, links, bullet/numbered/check/nested
|
|
217
264
|
lists, blockquotes, code blocks and tables extracts every piece of text.
|
|
218
265
|
Lexical decorator elements (horizontal rule, image) are skipped instead of
|
|
@@ -223,17 +270,17 @@ Fixes from a full source review.
|
|
|
223
270
|
|
|
224
271
|
### Changed
|
|
225
272
|
- **Internal:** renamed the native extension crate `y_ruby` → `yrby` (now loads
|
|
226
|
-
from `lib/y/yrby.bundle`). No public API change
|
|
273
|
+
from `lib/y/yrby.bundle`). No public API change: `require "y"` and `Y::Doc`
|
|
227
274
|
are unchanged.
|
|
228
275
|
|
|
229
276
|
## [0.2.0] - 2026-06-28
|
|
230
277
|
|
|
231
278
|
First release. The public Ruby interface is the top-level module **`Y`**
|
|
232
|
-
(`Y::Doc`, `Y::Error`, `Y::VERSION`), loaded with `require "y"
|
|
279
|
+
(`Y::Doc`, `Y::Error`, `Y::VERSION`), loaded with `require "y"`, mirroring the
|
|
233
280
|
`y-rb` gem's `Y::Doc` interface.
|
|
234
281
|
|
|
235
282
|
### Added
|
|
236
|
-
- Native `Doc#read_text` and `Doc#read_map` readers
|
|
283
|
+
- Native `Doc#read_text` and `Doc#read_map` readers: reconstruct plain text and
|
|
237
284
|
a JSON map from the stored CRDT state in-process, server-side, with no Node or
|
|
238
285
|
subprocess.
|
|
239
286
|
|
data/Cargo.lock
CHANGED
|
@@ -227,6 +227,15 @@ version = "1.3.0"
|
|
|
227
227
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
228
228
|
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|
229
229
|
|
|
230
|
+
[[package]]
|
|
231
|
+
name = "lexical-yjs-html"
|
|
232
|
+
version = "0.1.1"
|
|
233
|
+
dependencies = [
|
|
234
|
+
"serde_json",
|
|
235
|
+
"yjs-html-core",
|
|
236
|
+
"yrs",
|
|
237
|
+
]
|
|
238
|
+
|
|
230
239
|
[[package]]
|
|
231
240
|
name = "libc"
|
|
232
241
|
version = "0.2.180"
|
|
@@ -337,6 +346,15 @@ dependencies = [
|
|
|
337
346
|
"unicode-ident",
|
|
338
347
|
]
|
|
339
348
|
|
|
349
|
+
[[package]]
|
|
350
|
+
name = "prosemirror-yjs-html"
|
|
351
|
+
version = "0.1.2"
|
|
352
|
+
dependencies = [
|
|
353
|
+
"serde_json",
|
|
354
|
+
"yjs-html-core",
|
|
355
|
+
"yrs",
|
|
356
|
+
]
|
|
357
|
+
|
|
340
358
|
[[package]]
|
|
341
359
|
name = "quote"
|
|
342
360
|
version = "1.0.43"
|
|
@@ -608,18 +626,26 @@ version = "0.2.1"
|
|
|
608
626
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
609
627
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
|
610
628
|
|
|
629
|
+
[[package]]
|
|
630
|
+
name = "yjs-html-core"
|
|
631
|
+
version = "0.1.1"
|
|
632
|
+
dependencies = [
|
|
633
|
+
"serde_json",
|
|
634
|
+
"yrs",
|
|
635
|
+
]
|
|
636
|
+
|
|
611
637
|
[[package]]
|
|
612
638
|
name = "yrby"
|
|
613
639
|
version = "0.1.0"
|
|
614
640
|
dependencies = [
|
|
641
|
+
"lexical-yjs-html",
|
|
615
642
|
"magnus",
|
|
643
|
+
"prosemirror-yjs-html",
|
|
616
644
|
"rb-sys",
|
|
617
645
|
"rb-sys-env 0.1.2",
|
|
618
646
|
"serde_json",
|
|
647
|
+
"yjs-html-core",
|
|
619
648
|
"yrs",
|
|
620
|
-
"yrs-html-core",
|
|
621
|
-
"yrs-lexical-html",
|
|
622
|
-
"yrs-prosemirror-html",
|
|
623
649
|
]
|
|
624
650
|
|
|
625
651
|
[[package]]
|
|
@@ -640,32 +666,6 @@ dependencies = [
|
|
|
640
666
|
"thiserror",
|
|
641
667
|
]
|
|
642
668
|
|
|
643
|
-
[[package]]
|
|
644
|
-
name = "yrs-html-core"
|
|
645
|
-
version = "0.1.0"
|
|
646
|
-
dependencies = [
|
|
647
|
-
"serde_json",
|
|
648
|
-
"yrs",
|
|
649
|
-
]
|
|
650
|
-
|
|
651
|
-
[[package]]
|
|
652
|
-
name = "yrs-lexical-html"
|
|
653
|
-
version = "0.1.0"
|
|
654
|
-
dependencies = [
|
|
655
|
-
"serde_json",
|
|
656
|
-
"yrs",
|
|
657
|
-
"yrs-html-core",
|
|
658
|
-
]
|
|
659
|
-
|
|
660
|
-
[[package]]
|
|
661
|
-
name = "yrs-prosemirror-html"
|
|
662
|
-
version = "0.1.0"
|
|
663
|
-
dependencies = [
|
|
664
|
-
"serde_json",
|
|
665
|
-
"yrs",
|
|
666
|
-
"yrs-html-core",
|
|
667
|
-
]
|
|
668
|
-
|
|
669
669
|
[[package]]
|
|
670
670
|
name = "zmij"
|
|
671
671
|
version = "1.0.14"
|