@quillmark/wasm 0.130.0 → 0.131.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/CHANGELOG.md CHANGED
@@ -1,5 +1,109 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.131.0 - 2026-10-26
4
+
5
+ Upgrade path: [0.130 → 0.131](docs/migrations/0.130-to-0.131.md). A row
6
+ holding a font mark, an element named `table`, a merged cell or a table `head`
7
+ 0.130 cannot draw saves under `quillmark/document@0.131.0`, which a 0.130
8
+ build refuses, so deploy every reader before a writer saves one.
9
+
10
+ ### Storage
11
+
12
+ - fix(core): **a row holding an element named `table`, a table cell spanning
13
+ more than one column or row, or a table `head` a 0.130 build cannot draw
14
+ saves under `quillmark/document@0.131.0`**, as a row holding a `font_family`
15
+ mark does: a 0.130 build refused the element as corrupt and drew the rest
16
+ wrong under `@0.129.0`. The check reads each body and each field and `$seed`
17
+ value that decodes as content, and no longer reads `$ext`, so host data
18
+ shaped like a font mark keeps `@0.129.0`.
19
+
20
+ ### Content
21
+
22
+ - feat(content)!: **a table writes as a GFM pipe table when pipes hold all of
23
+ it, and as an HTML table when it holds column widths, a placement, a cell's
24
+ alignment, a merged cell or other than one header row**, whichever spelling
25
+ the markdown used. An HTML block opening `<table>` imports as a table: the
26
+ subset is `table`, `thead`, `tbody`, `tfoot`, `tr`, `th` and `td`, with
27
+ `widths`, `aligns` and `align` on `<table>` and `colspan`, `rowspan`, `align`
28
+ and `valign` on a cell, whose content is inline markdown. A span stores as a
29
+ cell's `colspan` and `rowspan`, each cell it covers an empty placeholder, and
30
+ the header rows as the table's `head`, a count `headless: true` normalizes
31
+ to `head: 0`. What an HTML table cannot hold warns
32
+ `parse::dropped_construct` as `table`, `table:row`, `table:text` or
33
+ `<tag>[<attr>]`. Markdown after a `</table>` in its HTML block reads as
34
+ markdown of its own. An HTML table is as wide as its widest row, a `<th>`
35
+ row opening its `tbody` is a header row, and `border`, `class`, `scope` and
36
+ `style` drop silently. The Typst backend draws a span through
37
+ `table.cell(colspan:, rowspan:)` and every header row in `table.header`.
38
+ - feat(content)!: **`qm-table` and `qm-cell` no longer spell a table's
39
+ layout**: `qm-table` is an ordinary element name, and a `qm-cell` pair in a
40
+ cell drops, warning `qm-cell`, so markdown written with either loses its
41
+ table layout; rewrite such a table as HTML.
42
+ - fix(content): **a table's `head: 0` keeps `headless: true` beside it**, so a
43
+ 0.130 reader draws no header row on a table 0.131 saved, and a richtext
44
+ field holding a 0.130 `headless: true` table reads as content, exporting as
45
+ a table where it wrote its YAML tree. A cell a span covers keeps its `align`
46
+ and `valign`, drawn again once the span shrinks, and a cell holding a mark,
47
+ a comment anchor included, is no placeholder a span covers. A 0.130 row
48
+ holding `headless: true` or a cell span rewrites once when saved, under the
49
+ same tag unless a span still covers more than one slot, which saves under
50
+ `@0.131.0`.
51
+ - fix(content)!: **a body formatting mark spanning a line break loads as one
52
+ mark per line**, cut at each `\n`, the form markdown export writes, so a
53
+ mark over a hard break round-trips through markdown and a `MarkOp::Add`
54
+ across lines reads back split. A stored row holding such a
55
+ mark saves to new bytes on its first load. A table cell's or footnote's
56
+ marks still span its `<br>`.
57
+ - fix(content)!: **`link` is keyed like `font_family`**: overlapping links
58
+ settle to one url per character, the later-starting one winning, and a
59
+ `MarkOp::Add` of a link over a link replaces its url there, so
60
+ `MarkKind::is_keyed` holds for `Link`. Keyed marks settle before the cut at
61
+ line breaks, so a later-starting family keeps its whole range across one.
62
+ - fix(content)!: **a table's grid is capped at `MAX_TABLE_CELLS` (100 000)
63
+ slots, and a markdown import's tables share the cap**: import drops the rows
64
+ past it, warning `table:size`, and the stored lanes refuse such a table as
65
+ `Invariant::TableTooLarge` before padding it, where a few bytes could
66
+ allocate millions of cells.
67
+ - fix(content): **a code span in an HTML table's cell never reaches past a
68
+ subset tag**, so a stray backtick is the cell's text rather than merging
69
+ cells, rows or the prose after the table, and a code mark over a subset tag
70
+ exports the tag as escaped text.
71
+
72
+ ### Fonts
73
+
74
+ - feat!: **a run of richtext sets a font family, spelled in markdown as an
75
+ inline `<qm-span family="…">` pair** and stored as a `font_family` mark, one
76
+ family per character, so export writes nested pairs back side by side. A
77
+ row holding a `font_family` mark saves as `quillmark/document@0.131.0`,
78
+ which a 0.130 build refuses; `currentStorageVersion()` /
79
+ `current_storage_version()` return that tag. `MarkKind` gains
80
+ `FontFamily { name }`, `StoredDocument` gains `V0_131_0`, and the WASM
81
+ `ContentMark` gains `font_family`. A `qm-span` tag line, which 0.130 read as
82
+ an element named `span`, drops and warns `qm-span`.
83
+ - feat!: **an engine takes a host font library**: `Engine::with_fonts`, the
84
+ `fonts` option of `new Engine(..)`, `Engine(fonts=..)` and `--font` on
85
+ `quillmark render` and `quillmark workspace`. A file other than `.ttf`,
86
+ `.otf`, `.ttc` or `.otc` fails as `engine::font_unsupported`, one holding no
87
+ face Typst reads as `engine::font_unreadable`. A library face sets only text
88
+ a font mark sets, and a family the library lacks keeps the surrounding font
89
+ and warns `typst::unknown_font_family`. `TypstBackend` is a struct holding
90
+ the library, built with `TypstBackend::default()` or
91
+ `TypstBackend::new(Arc<FontLibrary>)`, `quillmark_typst::workspace::workspace`
92
+ takes a `&FontLibrary` third, and `Engine::font_faces`,
93
+ `engine.fontFaces(quill)` and `Engine.font_faces(quill)` list the faces,
94
+ sharing the library's bytes rather than copying them. The WASM engine copies
95
+ its `fonts` when built and parses them once, so a refused font rejects every
96
+ verb that loads the render build with the same error. A plate naming a
97
+ library family never reaches its face.
98
+
99
+ ### Fixes
100
+
101
+ - fix(acroform): a `richtext` array element holding no text binds as an empty
102
+ line, so a blank line between groups reaches the widget.
103
+ - fix(core): a list item with nothing after its marker ends at the blank line
104
+ below it, so a card fence inside a code block below such an item stays
105
+ code.
106
+
3
107
  ## v0.130.0 - 2026-10-22
4
108
 
5
109
  Upgrade path: [0.129 → 0.130](docs/migrations/0.129-to-0.130.md). A stored row
package/README.md CHANGED
@@ -182,10 +182,11 @@ const doc = Document.storageVersionOf(content)
182
182
  : Document.fromMarkdown(content);
183
183
  ```
184
184
 
185
- The `schema` value (`quillmark/document@0.129.0`) is the **model version**,
186
- not the running crate version. It is a hand-set constant, bumped only when
187
- the `Document` model itself changes, so every `0.129.x` patch release reads
188
- and writes that same value.
185
+ The `schema` value (`quillmark/document@0.131.0` for a document holding a font
186
+ mark, `@0.129.0` for any other) is the **model version**, not the running crate
187
+ version. It is a hand-set constant, bumped only when the `Document` model
188
+ itself changes, so every `0.131.x` patch release reads and writes those same
189
+ values.
189
190
 
190
191
  - **Upgrading is safe.** A newer build reads documents an older build's
191
192
  *writer* produced. Each schema version's wire format is frozen and never
@@ -206,19 +207,26 @@ and writes that same value.
206
207
  read, newer than the build or retired, rather than guessing at its format.
207
208
  Don't feed documents written by a newer build back into an older one.
208
209
 
209
- To detect a version mismatch before parsing, use the static accessors:
210
+ `Document.currentStorageVersion()` is the newest tag this build writes. A
211
+ save writes the oldest tag that holds the row, so a fresh row can carry an
212
+ older tag still read: a row holding no font mark, `table` element, merged
213
+ table cell or table `head` 0.130 cannot draw saves as
214
+ `quillmark/document@0.129.0`. A tag other than `currentStorageVersion()` is
215
+ therefore not a mismatch. Use `storageVersionOf` after `fromStored` throws,
216
+ to tell "a version this build does not read" from "corrupt":
210
217
 
211
218
  ```ts
212
- const v = Document.storageVersionOf(blob); // undefined | string
213
- if (v && v !== Document.currentStorageVersion()) {
214
- // payload is from a build with a different model version
219
+ try {
220
+ return Document.fromStored(blob);
221
+ } catch (err) {
222
+ const v = Document.storageVersionOf(blob); // undefined | string
223
+ // v: a tag this build does not read; undefined: not a stored document
215
224
  }
216
225
  ```
217
226
 
218
227
  `storageVersionOf` does not validate the payload: it only reads the
219
228
  `schema` field, returning `undefined` for non-JSON, non-objects, or
220
- payloads that don't carry one. Use it to distinguish "wrong version" from
221
- "corrupt" when `fromStored` throws.
229
+ payloads that don't carry one.
222
230
 
223
231
  In short: persist the `toStored` string, resave rows under a retired tag
224
232
  before upgrading past it, never downgrade. The full design (including how
@@ -2153,14 +2153,14 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH RE
2153
2153
 
2154
2154
  ## Apache License 2.0
2155
2155
 
2156
- - quillmark-acroform 0.130.0 (https://github.com/borb-sh/quillmark)
2157
- - quillmark-typst 0.130.0 (https://github.com/borb-sh/quillmark)
2158
- - quillmark-cli 0.130.0 (https://github.com/borb-sh/quillmark)
2159
- - quillmark-python 0.130.0
2160
- - quillmark-content 0.130.0 (https://github.com/borb-sh/quillmark)
2161
- - quillmark-core 0.130.0 (https://github.com/borb-sh/quillmark)
2162
- - quillmark 0.130.0 (https://github.com/borb-sh/quillmark)
2163
- - quillmark-pdf 0.130.0 (https://github.com/borb-sh/quillmark)
2156
+ - quillmark-acroform 0.131.0 (https://github.com/borb-sh/quillmark)
2157
+ - quillmark-typst 0.131.0 (https://github.com/borb-sh/quillmark)
2158
+ - quillmark-cli 0.131.0 (https://github.com/borb-sh/quillmark)
2159
+ - quillmark-python 0.131.0
2160
+ - quillmark-content 0.131.0 (https://github.com/borb-sh/quillmark)
2161
+ - quillmark-core 0.131.0 (https://github.com/borb-sh/quillmark)
2162
+ - quillmark 0.131.0 (https://github.com/borb-sh/quillmark)
2163
+ - quillmark-pdf 0.131.0 (https://github.com/borb-sh/quillmark)
2164
2164
  - ciborium-io 0.2.2 (https://github.com/enarx/ciborium)
2165
2165
  - ciborium-ll 0.2.2 (https://github.com/enarx/ciborium)
2166
2166
  - ciborium 0.2.2 (https://github.com/enarx/ciborium)
@@ -2377,6 +2377,11 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH RE
2377
2377
  - clap 4.6.7 (https://github.com/clap-rs/clap)
2378
2378
  - clap_builder 4.6.7 (https://github.com/clap-rs/clap)
2379
2379
  - clap_derive 4.6.7 (https://github.com/clap-rs/clap)
2380
+ - serde_spanned 1.1.2 (https://github.com/toml-rs/toml)
2381
+ - toml 1.1.8+spec-1.1.0 (https://github.com/toml-rs/toml)
2382
+ - toml_datetime 1.1.2+spec-1.1.0 (https://github.com/toml-rs/toml)
2383
+ - toml_parser 1.1.5+spec-1.1.0 (https://github.com/toml-rs/toml)
2384
+ - toml_writer 1.1.3+spec-1.1.0 (https://github.com/toml-rs/toml)
2380
2385
 
2381
2386
  ~~~~text
2382
2387
  Apache License
@@ -2600,15 +2605,10 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH RE
2600
2605
  - once_cell_polyfill 1.70.2 (https://github.com/polyfill-rs/once_cell_polyfill)
2601
2606
  - quick-error 2.0.1 (http://github.com/tailhook/quick-error)
2602
2607
  - serde_spanned 0.6.9 (https://github.com/toml-rs/toml)
2603
- - serde_spanned 1.1.1 (https://github.com/toml-rs/toml)
2604
2608
  - toml 0.8.23 (https://github.com/toml-rs/toml)
2605
- - toml 1.1.6+spec-1.1.0 (https://github.com/toml-rs/toml)
2606
2609
  - toml_datetime 0.6.11 (https://github.com/toml-rs/toml)
2607
- - toml_datetime 1.1.1+spec-1.1.0 (https://github.com/toml-rs/toml)
2608
2610
  - toml_edit 0.22.27 (https://github.com/toml-rs/toml)
2609
- - toml_parser 1.1.3+spec-1.1.0 (https://github.com/toml-rs/toml)
2610
2611
  - toml_write 0.1.2 (https://github.com/toml-rs/toml)
2611
- - toml_writer 1.1.2+spec-1.1.0 (https://github.com/toml-rs/toml)
2612
2612
 
2613
2613
  ~~~~text
2614
2614
  Apache License
@@ -4555,7 +4555,7 @@ limitations under the License.
4555
4555
  - unic-langid-macros-impl 0.9.6 (https://github.com/zbraniecki/unic-locale)
4556
4556
  - unic-langid-macros 0.9.6 (https://github.com/zbraniecki/unic-locale)
4557
4557
  - unic-langid 0.9.6 (https://github.com/zbraniecki/unic-locale)
4558
- - unicase 2.9.0 (https://github.com/seanmonstar/unicase)
4558
+ - unicase 2.10.0 (https://github.com/seanmonstar/unicase)
4559
4559
  - unicode-bidi-mirroring 0.4.0 (https://github.com/RazrFalcon/unicode-bidi-mirroring)
4560
4560
  - unicode-bidi 0.3.18 (https://github.com/servo/unicode-bidi)
4561
4561
  - unicode-ccc 0.4.0 (https://github.com/RazrFalcon/unicode-ccc)
@@ -5395,6 +5395,7 @@ APPENDIX: How to apply the Apache License to your work.
5395
5395
 
5396
5396
  ## Apache License 2.0
5397
5397
 
5398
+ - getrandom 0.4.3 (https://github.com/rust-random/getrandom)
5398
5399
  - rand_chacha 0.3.1 (https://github.com/rust-random/rand)
5399
5400
 
5400
5401
  ~~~~text
@@ -6247,8 +6248,8 @@ limitations under the License.
6247
6248
 
6248
6249
  ## Apache License 2.0
6249
6250
 
6250
- - quillmark-wasm 0.130.0 (https://github.com/borb-sh/quillmark)
6251
- - quillmark-fixtures 0.130.0
6251
+ - quillmark-wasm 0.131.0 (https://github.com/borb-sh/quillmark)
6252
+ - quillmark-fixtures 0.131.0
6252
6253
  - arraydeque 0.5.1 (https://github.com/andylokandy/arraydeque)
6253
6254
  - codex 0.3.0 (https://github.com/typst/codex)
6254
6255
  - color 0.3.3 (https://github.com/linebender/color)
@@ -6311,7 +6312,7 @@ limitations under the License.
6311
6312
  - serde_core 1.0.229 (https://github.com/serde-rs/serde)
6312
6313
  - serde_derive 1.0.229 (https://github.com/serde-rs/serde)
6313
6314
  - serde_derive_internals 0.29.1 (https://github.com/serde-rs/serde)
6314
- - serde_json 1.0.151 (https://github.com/serde-rs/json)
6315
+ - serde_json 1.0.154 (https://github.com/serde-rs/json)
6315
6316
  - serde_path_to_error 0.1.20 (https://github.com/dtolnay/path-to-error)
6316
6317
  - serde_yaml 0.9.34+deprecated (https://github.com/dtolnay/serde-yaml)
6317
6318
  - siphasher 1.0.2 (https://github.com/jedisct1/rust-siphash)
package/core/wasm.d.ts CHANGED
@@ -132,7 +132,8 @@ export type ContentMark = { start: number; end: number } & ContentMarkKind;
132
132
  export type ContentMarkKind =
133
133
  | { type: "strong" | "emph" | "underline" | "strike" | "code" }
134
134
  | { type: "link"; attrs: { url: string } }
135
- | { type: "anchor"; attrs: { id: string } };
135
+ | { type: "anchor"; attrs: { id: string } }
136
+ | { type: "font_family"; attrs: { name: string } };
136
137
 
137
138
  /** A cell in a `TableProps`. `marks` rides the prose `ContentMark` shape, but
138
139
  * each mark's `start`/`end` are USV offsets into this cell's `text`, not into
@@ -144,12 +145,17 @@ export interface TableCell {
144
145
  align?: "left" | "center" | "right";
145
146
  /** The cell's vertical alignment; absent is the quill's. */
146
147
  valign?: "top" | "middle" | "bottom";
148
+ /** The columns the cell spans, from 2; absent is one. Each cell it covers
149
+ * holds its slot as an empty placeholder. */
150
+ colspan?: number;
151
+ /** The rows the cell spans, from 2; absent is one. */
152
+ rowspan?: number;
147
153
  }
148
154
 
149
- /** `props` of a `type: "table"` island: a pipe table normalized to one column
150
- * count that `header`, every row of `rows`, `aligns` and `widths` all share.
151
- * A layout key at its default is absent; one holding a value outside its type
152
- * stays as written and reads as absent. */
155
+ /** `props` of a `type: "table"` island: a rectangular grid normalized to one
156
+ * column count that `header`, every row of `rows`, `aligns` and `widths` all
157
+ * share. A layout key at its default is absent; one holding a value outside
158
+ * its type stays as written and reads as absent. */
153
159
  export interface TableProps {
154
160
  header: TableCell[];
155
161
  rows: TableCell[][];
@@ -161,8 +167,9 @@ export interface TableProps {
161
167
  widths?: (number | null)[];
162
168
  /** The table's placement; absent is the quill's. */
163
169
  align?: "left" | "center" | "right";
164
- /** `true` draws `header` as the first body row; absent is a header row. */
165
- headless?: true;
170
+ /** How many rows from the top of `header` then `rows` are header rows;
171
+ * `0` draws `header` as the first body row, and absent is one. */
172
+ head?: number;
166
173
  }
167
174
 
168
175
  /** `props` of a `type: "image"` island. Stores and round-trips; no backend
@@ -300,7 +307,9 @@ export type Assoc = "before" | "after";
300
307
  /**
301
308
  * A mark edit in final-text coordinates (post-delta, post-line-op). `add` /
302
309
  * `remove` are a `ContentMark` under an op, so a held mark spreads in whole;
303
- * `removeAnchor` drops one identity anchor by id. An `add` of an `anchor`
310
+ * `removeAnchor` drops one identity anchor by id. An `add` of a `link` or a
311
+ * `font_family` replaces the one under its range, and a mark added across a
312
+ * line break reads back as one mark per line. An `add` of an `anchor`
304
313
  * requires a non-empty `id` not already live in the field; a collision or the
305
314
  * empty id throws.
306
315
  */
@@ -675,8 +684,11 @@ export class Document {
675
684
  card(index: number): Card;
676
685
  clone(): Document;
677
686
  /**
678
- * Storage version this build writes via [`toStored`](Document::to_stored). The
679
- * tag advances only when the wire format changes, not on every release.
687
+ * The newest storage version this build writes via
688
+ * [`toStored`](Document::to_stored): a document spelling a font mark, a
689
+ * `table` element, a merged table cell or a table head 0.130 cannot draw
690
+ * carries it, every other the tag before it, which a 0.130 build reads. The tag advances only when the wire format changes, not on
691
+ * every release.
680
692
  */
681
693
  static currentStorageVersion(): string;
682
694
  /**
package/core/wasm.js CHANGED
@@ -441,8 +441,11 @@ export class Document {
441
441
  return Document.__wrap(ret);
442
442
  }
443
443
  /**
444
- * Storage version this build writes via [`toStored`](Document::to_stored). The
445
- * tag advances only when the wire format changes, not on every release.
444
+ * The newest storage version this build writes via
445
+ * [`toStored`](Document::to_stored): a document spelling a font mark, a
446
+ * `table` element, a merged table cell or a table head 0.130 cannot draw
447
+ * carries it, every other the tag before it, which a 0.130 build reads. The tag advances only when the wire format changes, not on
448
+ * every release.
446
449
  * @returns {string}
447
450
  */
448
451
  static currentStorageVersion() {
package/core/wasm_bg.wasm CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quillmark/wasm",
3
- "version": "0.130.0",
3
+ "version": "0.131.0",
4
4
  "description": "WebAssembly bindings for Quillmark, a schema-driven document framework",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
package/render/wasm.d.ts CHANGED
@@ -132,7 +132,8 @@ export type ContentMark = { start: number; end: number } & ContentMarkKind;
132
132
  export type ContentMarkKind =
133
133
  | { type: "strong" | "emph" | "underline" | "strike" | "code" }
134
134
  | { type: "link"; attrs: { url: string } }
135
- | { type: "anchor"; attrs: { id: string } };
135
+ | { type: "anchor"; attrs: { id: string } }
136
+ | { type: "font_family"; attrs: { name: string } };
136
137
 
137
138
  /** A cell in a `TableProps`. `marks` rides the prose `ContentMark` shape, but
138
139
  * each mark's `start`/`end` are USV offsets into this cell's `text`, not into
@@ -144,12 +145,17 @@ export interface TableCell {
144
145
  align?: "left" | "center" | "right";
145
146
  /** The cell's vertical alignment; absent is the quill's. */
146
147
  valign?: "top" | "middle" | "bottom";
148
+ /** The columns the cell spans, from 2; absent is one. Each cell it covers
149
+ * holds its slot as an empty placeholder. */
150
+ colspan?: number;
151
+ /** The rows the cell spans, from 2; absent is one. */
152
+ rowspan?: number;
147
153
  }
148
154
 
149
- /** `props` of a `type: "table"` island: a pipe table normalized to one column
150
- * count that `header`, every row of `rows`, `aligns` and `widths` all share.
151
- * A layout key at its default is absent; one holding a value outside its type
152
- * stays as written and reads as absent. */
155
+ /** `props` of a `type: "table"` island: a rectangular grid normalized to one
156
+ * column count that `header`, every row of `rows`, `aligns` and `widths` all
157
+ * share. A layout key at its default is absent; one holding a value outside
158
+ * its type stays as written and reads as absent. */
153
159
  export interface TableProps {
154
160
  header: TableCell[];
155
161
  rows: TableCell[][];
@@ -161,8 +167,9 @@ export interface TableProps {
161
167
  widths?: (number | null)[];
162
168
  /** The table's placement; absent is the quill's. */
163
169
  align?: "left" | "center" | "right";
164
- /** `true` draws `header` as the first body row; absent is a header row. */
165
- headless?: true;
170
+ /** How many rows from the top of `header` then `rows` are header rows;
171
+ * `0` draws `header` as the first body row, and absent is one. */
172
+ head?: number;
166
173
  }
167
174
 
168
175
  /** `props` of a `type: "image"` island. Stores and round-trips; no backend
@@ -300,7 +307,9 @@ export type Assoc = "before" | "after";
300
307
  /**
301
308
  * A mark edit in final-text coordinates (post-delta, post-line-op). `add` /
302
309
  * `remove` are a `ContentMark` under an op, so a held mark spreads in whole;
303
- * `removeAnchor` drops one identity anchor by id. An `add` of an `anchor`
310
+ * `removeAnchor` drops one identity anchor by id. An `add` of a `link` or a
311
+ * `font_family` replaces the one under its range, and a mark added across a
312
+ * line break reads back as one mark per line. An `add` of an `anchor`
304
313
  * requires a non-empty `id` not already live in the field; a collision or the
305
314
  * empty id throws.
306
315
  */
@@ -471,6 +480,19 @@ export interface Resolved {
471
480
 
472
481
 
473
482
 
483
+ /** One face a session sets text in, with what an editor needs for an
484
+ * `@font-face` rule: the family, the CSS weight and style, and the font file.
485
+ * `index` is the face's place in `data` where the file is a collection. */
486
+ export interface FontFace {
487
+ family: string;
488
+ weight: number;
489
+ style: "normal" | "italic" | "oblique";
490
+ index: number;
491
+ data: Uint8Array;
492
+ }
493
+
494
+
495
+
474
496
  /** UI layout hints for a single field. Display order is not a hint: key order
475
497
  * in the schema's `fields`/`properties` objects is the ordering contract. */
476
498
  export interface QuillFieldUi {
@@ -813,8 +835,11 @@ export class Document {
813
835
  card(index: number): Card;
814
836
  clone(): Document;
815
837
  /**
816
- * Storage version this build writes via [`toStored`](Document::to_stored). The
817
- * tag advances only when the wire format changes, not on every release.
838
+ * The newest storage version this build writes via
839
+ * [`toStored`](Document::to_stored): a document spelling a font mark, a
840
+ * `table` element, a merged table cell or a table head 0.130 cannot draw
841
+ * carries it, every other the tag before it, which a 0.130 build reads. The tag advances only when the wire format changes, not on
842
+ * every release.
818
843
  */
819
844
  static currentStorageVersion(): string;
820
845
  /**
@@ -1056,7 +1081,18 @@ export class Document {
1056
1081
  export class Engine {
1057
1082
  free(): void;
1058
1083
  [Symbol.dispose](): void;
1059
- constructor();
1084
+ /**
1085
+ * The text faces a `font_family` mark may set in a session of `quill`:
1086
+ * the host library's, in library order.
1087
+ */
1088
+ fontFaces(quill: Quill): FontFace[];
1089
+ /**
1090
+ * An engine whose sessions also set text in `fonts`, the host's font
1091
+ * library: each a `.ttf`, `.otf`, `.ttc` or `.otc` file, parsed once
1092
+ * here. A file in another format throws `engine::font_unsupported`, and
1093
+ * one holding no readable face `engine::font_unreadable`.
1094
+ */
1095
+ constructor(fonts: Uint8Array[] | undefined);
1060
1096
  /**
1061
1097
  * Open a live render session for `doc` against `quill`'s backend, on the
1062
1098
  * render date `today` (`YYYY-MM-DD`, default the local date).
@@ -1475,7 +1511,8 @@ export interface InitOutput {
1475
1511
  readonly document_toMarkdown: (a: number, b: number) => void;
1476
1512
  readonly document_toStored: (a: number, b: number) => void;
1477
1513
  readonly document_warnings: (a: number, b: number) => void;
1478
- readonly engine_new: () => number;
1514
+ readonly engine_fontFaces: (a: number, b: number, c: number) => void;
1515
+ readonly engine_new: (a: number, b: number) => void;
1479
1516
  readonly engine_open: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
1480
1517
  readonly engine_render: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
1481
1518
  readonly engine_supportedFormats: (a: number, b: number, c: number) => void;
package/render/wasm.js CHANGED
@@ -441,8 +441,11 @@ export class Document {
441
441
  return Document.__wrap(ret);
442
442
  }
443
443
  /**
444
- * Storage version this build writes via [`toStored`](Document::to_stored). The
445
- * tag advances only when the wire format changes, not on every release.
444
+ * The newest storage version this build writes via
445
+ * [`toStored`](Document::to_stored): a document spelling a font mark, a
446
+ * `table` element, a merged table cell or a table head 0.130 cannot draw
447
+ * carries it, every other the tag before it, which a 0.130 build reads. The tag advances only when the wire format changes, not on
448
+ * every release.
446
449
  * @returns {string}
447
450
  */
448
451
  static currentStorageVersion() {
@@ -1203,11 +1206,51 @@ export class Engine {
1203
1206
  const ptr = this.__destroy_into_raw();
1204
1207
  wasm.__wbg_engine_free(ptr, 0);
1205
1208
  }
1206
- constructor() {
1207
- const ret = wasm.engine_new();
1208
- this.__wbg_ptr = ret;
1209
- EngineFinalization.register(this, this.__wbg_ptr, this);
1210
- return this;
1209
+ /**
1210
+ * The text faces a `font_family` mark may set in a session of `quill`:
1211
+ * the host library's, in library order.
1212
+ * @param {Quill} quill
1213
+ * @returns {FontFace[]}
1214
+ */
1215
+ fontFaces(quill) {
1216
+ try {
1217
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
1218
+ _assertClass(quill, Quill);
1219
+ wasm.engine_fontFaces(retptr, this.__wbg_ptr, quill.__wbg_ptr);
1220
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
1221
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
1222
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
1223
+ if (r2) {
1224
+ throw takeObject(r1);
1225
+ }
1226
+ return takeObject(r0);
1227
+ } finally {
1228
+ wasm.__wbindgen_add_to_stack_pointer(16);
1229
+ }
1230
+ }
1231
+ /**
1232
+ * An engine whose sessions also set text in `fonts`, the host's font
1233
+ * library: each a `.ttf`, `.otf`, `.ttc` or `.otc` file, parsed once
1234
+ * here. A file in another format throws `engine::font_unsupported`, and
1235
+ * one holding no readable face `engine::font_unreadable`.
1236
+ * @param {Uint8Array[] | undefined} fonts
1237
+ */
1238
+ constructor(fonts) {
1239
+ try {
1240
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
1241
+ wasm.engine_new(retptr, addHeapObject(fonts));
1242
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
1243
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
1244
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
1245
+ if (r2) {
1246
+ throw takeObject(r1);
1247
+ }
1248
+ this.__wbg_ptr = r0;
1249
+ EngineFinalization.register(this, this.__wbg_ptr, this);
1250
+ return this;
1251
+ } finally {
1252
+ wasm.__wbindgen_add_to_stack_pointer(16);
1253
+ }
1211
1254
  }
1212
1255
  /**
1213
1256
  * Open a live render session for `doc` against `quill`'s backend, on the
@@ -2452,6 +2495,9 @@ function __wbg_get_imports() {
2452
2495
  const ret = Reflect.getPrototypeOf(getObject(arg0));
2453
2496
  return addHeapObject(ret);
2454
2497
  }, arguments); },
2498
+ __wbg_getRandomValues_436a51d0629d84e1: function() { return handleError(function (arg0, arg1) {
2499
+ globalThis.crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1));
2500
+ }, arguments); },
2455
2501
  __wbg_get_658f6698067d9515: function() { return handleError(function (arg0, arg1) {
2456
2502
  const ret = Reflect.get(getObject(arg0), getObject(arg1));
2457
2503
  return addHeapObject(ret);
@@ -2603,6 +2649,10 @@ function __wbg_get_imports() {
2603
2649
  __wbg_prototypesetcall_bc27214492979395: function(arg0, arg1, arg2) {
2604
2650
  Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), getObject(arg2));
2605
2651
  },
2652
+ __wbg_push_2baf45db356cf468: function(arg0, arg1) {
2653
+ const ret = getObject(arg0).push(getObject(arg1));
2654
+ return ret;
2655
+ },
2606
2656
  __wbg_putImageData_11570c06086c9e05: function() { return handleError(function (arg0, arg1, arg2, arg3) {
2607
2657
  getObject(arg0).putImageData(getObject(arg1), arg2, arg3);
2608
2658
  }, arguments); },
Binary file
@@ -52,7 +52,8 @@ export const document_toAnnotatedMarkdown: (a: number, b: number) => void;
52
52
  export const document_toMarkdown: (a: number, b: number) => void;
53
53
  export const document_toStored: (a: number, b: number) => void;
54
54
  export const document_warnings: (a: number, b: number) => void;
55
- export const engine_new: () => number;
55
+ export const engine_fontFaces: (a: number, b: number, c: number) => void;
56
+ export const engine_new: (a: number, b: number) => void;
56
57
  export const engine_open: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
57
58
  export const engine_render: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
58
59
  export const engine_supportedFormats: (a: number, b: number, c: number) => void;
@@ -415,6 +415,31 @@ export interface EngineOptions {
415
415
  * `"typst"` and `"acroform"` to the bundled render build.
416
416
  */
417
417
  backends?: Record<string, BackendDescriptor>;
418
+
419
+ /**
420
+ * The host's font library: each a `.ttf`, `.otf`, `.ttc` or `.otc` file,
421
+ * whose faces set only text a `font_family` mark sets. The bytes are
422
+ * copied at construction, cross into the render build once, when it loads,
423
+ * and are parsed there once. A file it refuses rejects every verb that
424
+ * needs that build, the first and each later one, with the same error:
425
+ * `engine::font_unsupported` for another format, `engine::font_unreadable`
426
+ * for a file holding no readable face. A value that is not an array of
427
+ * `Uint8Array` throws at construction.
428
+ */
429
+ fonts?: Uint8Array[];
430
+ }
431
+
432
+ /**
433
+ * One face a session sets text in, with what an editor needs for an
434
+ * `@font-face` rule: the family, the CSS weight and style, and the font file.
435
+ * `index` is the face's place in `data` where the file is a collection.
436
+ */
437
+ export interface FontFace {
438
+ family: string;
439
+ weight: number;
440
+ style: 'normal' | 'italic' | 'oblique';
441
+ index: number;
442
+ data: Uint8Array;
418
443
  }
419
444
 
420
445
  /**
@@ -485,6 +510,15 @@ export declare class Engine {
485
510
  * backend binary or cloning the quill. Async for API stability.
486
511
  */
487
512
  supportedFormats(quill: Quill): Promise<OutputFormat[]>;
513
+
514
+ /**
515
+ * The text faces a `font_family` mark may set in a session of `quill`: the
516
+ * host library's, in the order of `fonts`. A quill's own fonts and the
517
+ * embedded fallback set its plate, never a mark. Loads the backend and
518
+ * clones the quill as `open` does; a backend that reads no fonts answers
519
+ * `[]`.
520
+ */
521
+ fontFaces(quill: Quill): Promise<FontFace[]>;
488
522
  }
489
523
 
490
524
  /**