@quillmark/wasm 0.95.1 → 0.96.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.
@@ -29,7 +29,7 @@ export class Document {
29
29
  * the document, so a rejected field (or an invalid kind, body, or
30
30
  * out-of-range `at`) leaves the document untouched. Field errors throw the
31
31
  * same per-field diagnostic bundle as [`commitFields`](Self::commit_fields),
32
- * including an `[EditError::UnknownField]` per undeclared name; an invalid
32
+ * including an `edit::unknown_field` per undeclared name; an invalid
33
33
  * kind or body, or an out-of-range position, throws a single-entry bundle
34
34
  * keyed `$kind` / `$body`.
35
35
  * @param {Quill} quill
@@ -72,12 +72,12 @@ export class Document {
72
72
  * address throws — a body has no field schema; write it with `writer.setBody`
73
73
  * / `revise`. A field declared in the schema is strict-committed (a mismatch
74
74
  * throws now, not at render); a name the schema does not declare throws
75
- * `[EditError::UnknownField]` rather than falling to the opaque store — on
75
+ * `edit::unknown_field` rather than falling to the opaque store — on
76
76
  * the typed path it is a typo. Use [`storeField`](Document::store_field) for
77
- * opaque storage. Also throws `[EditError::FieldConform]` /
78
- * `[EditError::FieldRichtextDecode]` / `[EditError::FieldRichtextNotInline]`
79
- * on a typed mismatch, `[EditError::InvalidFieldName]` on a malformed name,
80
- * and `[EditError::IndexOutOfRange]` on an out-of-range card.
77
+ * opaque storage. Also throws `edit::field_conform` /
78
+ * `edit::field_richtext_decode` / `edit::field_richtext_not_inline`
79
+ * on a typed mismatch, `edit::invalid_field_name` on a malformed name,
80
+ * and `edit::index_out_of_range` on an out-of-range card.
81
81
  *
82
82
  * The `quill` handle is passed per call because a `Document` carries only a
83
83
  * `$quill` reference, not the resolved schema.
@@ -107,7 +107,7 @@ export class Document {
107
107
  * the same per-field-diagnostic error contract as
108
108
  * [`storeFields`](Document::store_fields) — nothing is applied on error and
109
109
  * the thrown error's `diagnostics` carry one entry per offending field,
110
- * including an `[EditError::UnknownField]` for any name the schema does not
110
+ * including an `edit::unknown_field` for any name the schema does not
111
111
  * declare, so a whole-form submit sees every typo in one pass. Throws on an
112
112
  * out-of-range card.
113
113
  * @param {Quill} quill
@@ -129,32 +129,34 @@ export class Document {
129
129
  }
130
130
  }
131
131
  /**
132
- * Revise the richtext field at `addr` from markdown, typed *and*
133
- * anchor-preserving — the ABI under `writer.reviseField`. Resolves the
134
- * field's schema from `quill` (main card, or the addressed card's `$kind`)
135
- * and defers to [`TypedWriter::revise_field`](quillmark_core::TypedWriter::revise_field):
136
- * surviving anchors rebase (as [`revise`](Self::revise)), then the diffed
137
- * result is schema-conformed, so a `richtext(inline)` field rejects a
138
- * multi-block result with `[EditError::FieldRichtextNotInline]`. Returns the
139
- * text [`Delta`].
132
+ * Interpreted read at `addr`, resolving the field's declared `type` from
133
+ * `quill` — the stable ABI under the runtime `reader.get` / `reader.card(i).get`.
134
+ * The schema-plane twin of the quill-free [`get`](Self::get): a `richtext`
135
+ * field returns its markdown projection, every other declared type its
136
+ * canonical value verbatim, so a consumer holding the quill reads by field
137
+ * meaning rather than by wire shape.
140
138
  *
141
- * `addr` must name a field (a bare string is `{ field }`); a body address
142
- * throws (a body carries no field schema use [`revise`](Self::revise)). A
143
- * name the schema does not declare throws `[EditError::UnknownField]`. Throws
144
- * on an out-of-range card. Hidden from the `.d.ts`; the visible verb is
145
- * `writer.reviseField` in the runtime layer.
139
+ * A bare string is `Addr` shorthand for `{ field }`; `{ card, field }`
140
+ * targets a composable card (its `$kind` resolves the schema). Returns
141
+ * `undefined` for an **absent** field. An absent `addr.field` reads the body
142
+ * markdown quill-free, mirroring [`getMarkdown`](Self::get_markdown), since
143
+ * a body's type is a format fact, not a schema fact. A name the schema does
144
+ * not declare throws `edit::unknown_field` (the authority `getMarkdown`
145
+ * lacks — there an unknown name reads back `undefined`); a `richtext` field
146
+ * holding a value that does not decode throws `edit::field_richtext_decode`;
147
+ * an out-of-range `addr.card` throws.
148
+ *
149
+ * The `quill` handle is passed per call because a `Document` carries only a
150
+ * `$quill` reference, not the resolved schema.
146
151
  * @param {Quill} quill
147
152
  * @param {Addr | string} addr
148
- * @param {string} markdown
149
- * @returns {Delta}
153
+ * @returns {unknown}
150
154
  */
151
- _reviseField(quill, addr, markdown) {
155
+ _readerGet(quill, addr) {
152
156
  try {
153
157
  const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
154
158
  _assertClass(quill, Quill);
155
- const ptr0 = passStringToWasm0(markdown, wasm.__wbindgen_export, wasm.__wbindgen_export2);
156
- const len0 = WASM_VECTOR_LEN;
157
- wasm.document__reviseField(retptr, this.__wbg_ptr, quill.__wbg_ptr, addHeapObject(addr), ptr0, len0);
159
+ wasm.document__readerGet(retptr, this.__wbg_ptr, quill.__wbg_ptr, addHeapObject(addr));
158
160
  var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
159
161
  var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
160
162
  var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
@@ -167,34 +169,32 @@ export class Document {
167
169
  }
168
170
  }
169
171
  /**
170
- * Interpreted read at `addr`, resolving the field's declared `type` from
171
- * `quill` — the stable ABI under the runtime `view.get` / `view.card(i).get`.
172
- * The schema-plane twin of the quill-free [`get`](Self::get): a `richtext`
173
- * field returns its markdown projection, every other declared type its
174
- * canonical value verbatim, so a consumer holding the quill reads by field
175
- * meaning rather than by wire shape.
176
- *
177
- * A bare string is `Addr` shorthand for `{ field }`; `{ card, field }`
178
- * targets a composable card (its `$kind` resolves the schema). Returns
179
- * `undefined` for an **absent** field. An absent `addr.field` reads the body
180
- * markdown — quill-free, mirroring [`getMarkdown`](Self::get_markdown), since
181
- * a body's type is a format fact, not a schema fact. A name the schema does
182
- * not declare throws `[EditError::UnknownField]` (the authority `getMarkdown`
183
- * lacks — there an unknown name reads back `undefined`); a `richtext` field
184
- * holding a value that does not decode throws `[EditError::FieldRichtextDecode]`;
185
- * an out-of-range `addr.card` throws.
172
+ * Revise the richtext field at `addr` from markdown, typed *and*
173
+ * anchor-preserving — the ABI under `writer.reviseField`. Resolves the
174
+ * field's schema from `quill` (main card, or the addressed card's `$kind`)
175
+ * and defers to [`TypedWriter::revise_field`](quillmark_core::TypedWriter::revise_field):
176
+ * surviving anchors rebase (as [`revise`](Self::revise)), then the diffed
177
+ * result is schema-conformed, so a `richtext(inline)` field rejects a
178
+ * multi-block result with `edit::field_richtext_not_inline`. Returns the
179
+ * text [`Delta`].
186
180
  *
187
- * The `quill` handle is passed per call because a `Document` carries only a
188
- * `$quill` reference, not the resolved schema.
181
+ * `addr` must name a field (a bare string is `{ field }`); a body address
182
+ * throws (a body carries no field schema — use [`revise`](Self::revise)). A
183
+ * name the schema does not declare throws `edit::unknown_field`. Throws
184
+ * on an out-of-range card. Hidden from the `.d.ts`; the visible verb is
185
+ * `writer.reviseField` in the runtime layer.
189
186
  * @param {Quill} quill
190
187
  * @param {Addr | string} addr
191
- * @returns {unknown}
188
+ * @param {string} markdown
189
+ * @returns {Delta}
192
190
  */
193
- _viewGet(quill, addr) {
191
+ _reviseField(quill, addr, markdown) {
194
192
  try {
195
193
  const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
196
194
  _assertClass(quill, Quill);
197
- wasm.document__viewGet(retptr, this.__wbg_ptr, quill.__wbg_ptr, addHeapObject(addr));
195
+ const ptr0 = passStringToWasm0(markdown, wasm.__wbindgen_export, wasm.__wbindgen_export2);
196
+ const len0 = WASM_VECTOR_LEN;
197
+ wasm.document__reviseField(retptr, this.__wbg_ptr, quill.__wbg_ptr, addHeapObject(addr), ptr0, len0);
198
198
  var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
199
199
  var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
200
200
  var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
@@ -261,7 +261,7 @@ export class Document {
261
261
  * A single composable card by index — the whole `Card`, the card-indexed
262
262
  * twin of the [`main`](Self::main) getter, so reading one card need not
263
263
  * materialize every card via [`cards`](Self::cards). An out-of-range
264
- * `index` throws `[EditError::IndexOutOfRange]`, matching the card write
264
+ * `index` throws `edit::index_out_of_range`, matching the card write
265
265
  * verbs.
266
266
  * @param {number} index
267
267
  * @returns {Card}
@@ -463,7 +463,7 @@ export class Document {
463
463
  * the **body content** when `addr.field` is absent. A bare string is `Addr`
464
464
  * shorthand for `{ field }`. Reads are total over the field axis: an absent
465
465
  * field is `undefined`; only an out-of-range `addr.card` throws
466
- * `[EditError::IndexOutOfRange]`. Reads need no schema, so they live on
466
+ * `edit::index_out_of_range`. Reads need no schema, so they live on
467
467
  * `Document`, not the typed writer; for the markdown projection of a
468
468
  * richtext value use [`getMarkdown`](Self::get_markdown).
469
469
  * @param {Addr | string} addr
@@ -541,7 +541,7 @@ export class Document {
541
541
  *
542
542
  * `addr` is an optional **card address** (`{ card }`, absent = main). A
543
543
  * present `field` throws — a field's markdown is read through the
544
- * schema-plane `quill.view(doc).get(field)`, which interprets by declared
544
+ * schema-plane `quill.reader(doc).get(field)`, which interprets by declared
545
545
  * type (#978). An out-of-range `addr.card` throws.
546
546
  * @param {CardAddr} [addr]
547
547
  * @returns {string}
@@ -1344,8 +1344,8 @@ export class LiveSession {
1344
1344
  /**
1345
1345
  * The schema field whose content is under a point on `page` — the
1346
1346
  * forward (click → field) direction: hit-test a click against the
1347
- * compiled document and get back the field address to focus in the
1348
- * editor, or `undefined` off any field's ink. `x`/`y` are PDF points
1347
+ * compiled document and get back the `DocPath` field address to focus in
1348
+ * the editor, or `undefined` off any field's ink. `x`/`y` are PDF points
1349
1349
  * with a **bottom-left** origin, the same space as `FieldRegion.rect` —
1350
1350
  * from a canvas click, invert the overlay transform documented on
1351
1351
  * `FieldRegion`: `x = clickPx.x / renderScale`,
@@ -1502,11 +1502,12 @@ export class LiveSession {
1502
1502
  /**
1503
1503
  * Schema-field geometry for this compiled session — each content field's
1504
1504
  * **first placement** (one region per page it touches) plus widget and
1505
- * scalar-reference-site regions, keyed on the quill schema field path; a
1506
- * field may still appear more than once (group by `field`, see
1507
- * `FieldRegion`). A session-level query: no render, no byte artifact. An
1508
- * interactive preview reads it to scroll to / highlight the focused
1509
- * field over a `paint`-ed canvas; the click direction is `fieldAt`.
1505
+ * scalar-reference-site regions, keyed on the canonical `DocPath` address
1506
+ * (`parseDocPath`-routable; the session resolves the backend's plate-space
1507
+ * per-kind ordinal to it); a field may still appear more than once (group
1508
+ * by `field`, see `FieldRegion`). A session-level query: no render, no byte
1509
+ * artifact. An interactive preview reads it to scroll to / highlight the
1510
+ * focused field over a `paint`-ed canvas; the click direction is `fieldAt`.
1510
1511
  * Empty for backends that place no schema fields.
1511
1512
  * @returns {FieldRegion[]}
1512
1513
  */
@@ -1686,6 +1687,34 @@ export class Quill {
1686
1687
  wasm.__wbindgen_add_to_stack_pointer(16);
1687
1688
  }
1688
1689
  }
1690
+ /**
1691
+ * The resolved-value view of `doc` against this quill's schema — for every
1692
+ * declared field the value the render projection would use and the
1693
+ * `FieldSource` rung it came from (`"authored" | "default" | "zero"`), in
1694
+ * one call. The card body rides the `fields` map under the `$body` key.
1695
+ *
1696
+ * Value and provenance only: completeness and errors stay `validate`'s
1697
+ * (a consumer merges it with its own diagnostic producers regardless), and
1698
+ * schema guidance reads from `Quill.schema`.
1699
+ * @param {Document} doc
1700
+ * @returns {Resolved}
1701
+ */
1702
+ resolve(doc) {
1703
+ try {
1704
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
1705
+ _assertClass(doc, Document);
1706
+ wasm.quill_resolve(retptr, this.__wbg_ptr, doc.__wbg_ptr);
1707
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
1708
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
1709
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
1710
+ if (r2) {
1711
+ throw takeObject(r1);
1712
+ }
1713
+ return takeObject(r0);
1714
+ } finally {
1715
+ wasm.__wbindgen_add_to_stack_pointer(16);
1716
+ }
1717
+ }
1689
1718
  /**
1690
1719
  * Document schema for the quill: the user-fillable fields plus their
1691
1720
  * `ui` hints (title / group / compact / multiline). The single
@@ -1967,6 +1996,40 @@ export function exportMarkdown(rt) {
1967
1996
  }
1968
1997
  }
1969
1998
 
1999
+ /**
2000
+ * Serialize structured [`DocPathSeg`] segments back to the canonical path
2001
+ * string — the inverse of `parseDocPath`, for a consumer that builds a path
2002
+ * rather than reads one. Throws on a segment array the deserializer rejects,
2003
+ * and on an empty segment array (symmetric with `parseDocPath("")`, which
2004
+ * throws "empty path").
2005
+ * @param {DocPathSeg[]} segs
2006
+ * @returns {string}
2007
+ */
2008
+ export function formatDocPath(segs) {
2009
+ let deferred2_0;
2010
+ let deferred2_1;
2011
+ try {
2012
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
2013
+ wasm.formatDocPath(retptr, addHeapObject(segs));
2014
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
2015
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
2016
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
2017
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
2018
+ var ptr1 = r0;
2019
+ var len1 = r1;
2020
+ if (r3) {
2021
+ ptr1 = 0; len1 = 0;
2022
+ throw takeObject(r2);
2023
+ }
2024
+ deferred2_0 = ptr1;
2025
+ deferred2_1 = len1;
2026
+ return getStringFromWasm0(ptr1, len1);
2027
+ } finally {
2028
+ wasm.__wbindgen_add_to_stack_pointer(16);
2029
+ wasm.__wbindgen_export4(deferred2_0, deferred2_1, 1);
2030
+ }
2031
+ }
2032
+
1970
2033
  /**
1971
2034
  * Import a markdown string to a canonical `Content` content — the pure,
1972
2035
  * document-free codec. Pair with `install(addr, importMarkdown(md))` to spell
@@ -2026,6 +2089,33 @@ export function mapPos(delta, pos, assoc) {
2026
2089
  }
2027
2090
  }
2028
2091
 
2092
+ /**
2093
+ * Parse a canonical document-model `Diagnostic.path`
2094
+ * (`cards.<kind>[<i>].<field>`, `main.body`, `recipients[0].name`) into its
2095
+ * structured [`DocPathSeg`] segments — the exported inverse of the engine's
2096
+ * one path serializer, so a consumer routes on segments instead of regexing
2097
+ * the string. Throws on a malformed path.
2098
+ * @param {string} path
2099
+ * @returns {DocPathSeg[]}
2100
+ */
2101
+ export function parseDocPath(path) {
2102
+ try {
2103
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
2104
+ const ptr0 = passStringToWasm0(path, wasm.__wbindgen_export, wasm.__wbindgen_export2);
2105
+ const len0 = WASM_VECTOR_LEN;
2106
+ wasm.parseDocPath(retptr, ptr0, len0);
2107
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
2108
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
2109
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
2110
+ if (r2) {
2111
+ throw takeObject(r1);
2112
+ }
2113
+ return takeObject(r0);
2114
+ } finally {
2115
+ wasm.__wbindgen_add_to_stack_pointer(16);
2116
+ }
2117
+ }
2118
+
2029
2119
  /**
2030
2120
  * Rebase `markdown` onto a `base` content — the pure, document-free twin of
2031
2121
  * `revise`: cold-import + `diff_import`, returning the new `content` and the
Binary file
@@ -8,8 +8,8 @@ export const __wbg_quillmark_free: (a: number, b: number) => void;
8
8
  export const document__addCard: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void;
9
9
  export const document__commitField: (a: number, b: number, c: number, d: number, e: number) => void;
10
10
  export const document__commitFields: (a: number, b: number, c: number, d: number, e: number) => void;
11
+ export const document__readerGet: (a: number, b: number, c: number, d: number) => void;
11
12
  export const document__reviseField: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
12
- export const document__viewGet: (a: number, b: number, c: number, d: number) => void;
13
13
  export const document_applyChange: (a: number, b: number, c: number, d: number) => void;
14
14
  export const document_blueprintInstruction: (a: number, b: number, c: number) => void;
15
15
  export const document_card: (a: number, b: number, c: number) => void;
@@ -58,6 +58,7 @@ export const document_toMarkdown: (a: number, b: number) => void;
58
58
  export const document_tryFromJson: (a: number, b: number) => number;
59
59
  export const document_warnings: (a: number, b: number) => void;
60
60
  export const exportMarkdown: (a: number, b: number) => void;
61
+ export const formatDocPath: (a: number, b: number) => void;
61
62
  export const importMarkdown: (a: number, b: number, c: number) => void;
62
63
  export const init: () => void;
63
64
  export const livesession_apply: (a: number, b: number, c: number) => void;
@@ -74,10 +75,12 @@ export const livesession_render: (a: number, b: number, c: number) => void;
74
75
  export const livesession_supportsCanvas: (a: number) => number;
75
76
  export const livesession_warnings: (a: number, b: number) => void;
76
77
  export const mapPos: (a: number, b: number, c: number, d: number) => void;
78
+ export const parseDocPath: (a: number, b: number, c: number) => void;
77
79
  export const quill_backendId: (a: number, b: number) => void;
78
80
  export const quill_blueprint: (a: number, b: number) => void;
79
81
  export const quill_fromTree: (a: number, b: number) => void;
80
82
  export const quill_metadata: (a: number, b: number) => void;
83
+ export const quill_resolve: (a: number, b: number, c: number) => void;
81
84
  export const quill_schema: (a: number, b: number) => void;
82
85
  export const quill_seedCard: (a: number, b: number, c: number, d: number, e: number) => void;
83
86
  export const quill_seedDocument: (a: number) => number;
@@ -110,14 +110,44 @@ export type ContentMark = { start: number; end: number } & (
110
110
  | { type: string; attrs: unknown }
111
111
  );
112
112
 
113
- /** A structured object (table, figure, …) occupying one island slot in `Content.text`. */
114
- export interface ContentIsland {
113
+ /** A cell in a `TableProps` its plain `text` plus the `marks` over it. `marks`
114
+ * rides the same wire shape as prose `ContentMark`, but each mark's `start`/`end`
115
+ * are USV offsets into this cell's `text` (`0..text.length`), not into
116
+ * `Content.text`. */
117
+ export interface TableCell {
118
+ text: string;
119
+ marks: ContentMark[];
120
+ }
121
+
122
+ /** `props` of a `type: "table"` island: a pipe table normalized to one column
123
+ * count that `header`, every row of `rows`, and `aligns` all share. */
124
+ export interface TableProps {
125
+ header: TableCell[];
126
+ rows: TableCell[][];
127
+ /** Per-column alignment, one entry per column. */
128
+ aligns: ("none" | "left" | "center" | "right")[];
129
+ }
130
+
131
+ /** `props` of a `type: "image"` island. */
132
+ export interface ImageProps {
133
+ url: string;
134
+ alt: string;
135
+ }
136
+
137
+ /** A structured object occupying one island slot in `Content.text`. `type` is an
138
+ * open set: the engine pins `props` as `TableProps` for `table` and `ImageProps`
139
+ * for `image`; an island of any other type round-trips with opaque `props`. Like
140
+ * `ContentMark`, the open `type` arm means a discriminant check does not itself
141
+ * narrow `props` — key off `type` and read `props` as the matching shape. */
142
+ export type ContentIsland = {
115
143
  id: string;
116
- type: string;
117
- props: unknown;
118
144
  /** How faithfully the markdown projection can carry this island. */
119
145
  loss: "lossless" | "degraded" | "unrepresentable";
120
- }
146
+ } & (
147
+ | { type: "table"; props: TableProps }
148
+ | { type: "image"; props: ImageProps }
149
+ | { type: string; props: unknown }
150
+ );
121
151
 
122
152
  /**
123
153
  * A write address — one navigation concept for the whole `Document` surface. An
@@ -203,6 +233,21 @@ export interface ChangeBundle {
203
233
 
204
234
 
205
235
 
236
+ /**
237
+ * One segment of a parsed `Diagnostic.path` (see `parseDocPath`). The head
238
+ * carries the document-model root — `main` (only before `body`), a `card`
239
+ * (`kind: null` is the unknown-kind `cards[i]` form), or a `field`; the tail is
240
+ * `field` / `index` / a terminal `body`.
241
+ */
242
+ export type DocPathSeg =
243
+ | { seg: "main" }
244
+ | { seg: "card"; kind: string | null; index: number }
245
+ | { seg: "field"; name: string }
246
+ | { seg: "index"; index: number }
247
+ | { seg: "body" };
248
+
249
+
250
+
206
251
  /**
207
252
  * Page dimensions in points (1 pt = 1/72 inch). Typst measures in Typst
208
253
  * points; pdfform measures in PDF points — the same unit.
@@ -288,6 +333,55 @@ export interface PaintResult {
288
333
 
289
334
 
290
335
 
336
+ /** The commitment-ladder rung that produced a `ResolvedField.value`. */
337
+ export type FieldSource = "authored" | "default" | "zero";
338
+
339
+ /**
340
+ * One resolved row: its `name`, the value the render projection would use, and
341
+ * the `FieldSource` rung it came from. Rows are an ordered array — declaration
342
+ * order is structural, not object-key order. The card body is a `body` sibling
343
+ * on its card, never a row in `fields`. Diagnostics stay `Quill.validate`'s;
344
+ * schema guidance (`example:`, labels) reads from `Quill.schema`.
345
+ */
346
+ export interface ResolvedField {
347
+ name: string;
348
+ value: unknown;
349
+ source: FieldSource;
350
+ }
351
+
352
+ /**
353
+ * The main card's resolved rows in declaration order, plus its body row —
354
+ * `null` when the main enables no body.
355
+ */
356
+ export interface ResolvedMain {
357
+ fields: ResolvedField[];
358
+ body: ResolvedField | null;
359
+ }
360
+
361
+ /**
362
+ * One composable card's resolved rows in declaration order, with its authored
363
+ * `kind` (`null` for an unknown-kind card), its document-array `index`, and its
364
+ * body row — `null` when the kind enables no body.
365
+ */
366
+ export interface ResolvedCard {
367
+ kind: string | null;
368
+ index: number;
369
+ fields: ResolvedField[];
370
+ body: ResolvedField | null;
371
+ }
372
+
373
+ /**
374
+ * The resolved-value view (`Quill.resolve`): the main card and every
375
+ * composable card. Value and provenance only — completeness and errors stay
376
+ * `Quill.validate`.
377
+ */
378
+ export interface Resolved {
379
+ main: ResolvedMain;
380
+ cards: ResolvedCard[];
381
+ }
382
+
383
+
384
+
291
385
  /** UI layout hints for a single field. Field display order is not a hint:
292
386
  * key order in the schema's `fields`/`properties` objects is declaration
293
387
  * order, the ordering contract. */
@@ -298,9 +392,23 @@ export interface QuillFieldUi {
298
392
  multiline?: boolean;
299
393
  }
300
394
 
395
+ /** One entry in a card's `ui.groups` registry: a display-label override for the
396
+ * group id (the map key). An empty object carries no override — the consumer
397
+ * derives the label from the id (`memo_for` → "Memo For"), as it does a field
398
+ * label from its key. */
399
+ export interface QuillGroupUi {
400
+ title?: string;
401
+ }
402
+
301
403
  /** UI layout hints for a card (main or named card kind). */
302
404
  export interface QuillCardUi {
303
405
  title?: string;
406
+ /** The card's group registry: the ordered table of contents naming every
407
+ * group a field's `ui.group` may reference. The map key is the group id, and
408
+ * key order is declaration order — the display-order contract, the same one
409
+ * `fields` key order carries. Absent when the card declares no groups (or
410
+ * uses the deprecated implicit-group form). */
411
+ groups?: Record<string, QuillGroupUi>;
304
412
  }
305
413
 
306
414
  /** Body namespace for a card (main or named card kind). */
@@ -467,7 +575,7 @@ export class Document {
467
575
  * A single composable card by index — the whole `Card`, the card-indexed
468
576
  * twin of the [`main`](Self::main) getter, so reading one card need not
469
577
  * materialize every card via [`cards`](Self::cards). An out-of-range
470
- * `index` throws `[EditError::IndexOutOfRange]`, matching the card write
578
+ * `index` throws `edit::index_out_of_range`, matching the card write
471
579
  * verbs.
472
580
  */
473
581
  card(index: number): Card;
@@ -523,7 +631,7 @@ export class Document {
523
631
  * the **body content** when `addr.field` is absent. A bare string is `Addr`
524
632
  * shorthand for `{ field }`. Reads are total over the field axis: an absent
525
633
  * field is `undefined`; only an out-of-range `addr.card` throws
526
- * `[EditError::IndexOutOfRange]`. Reads need no schema, so they live on
634
+ * `edit::index_out_of_range`. Reads need no schema, so they live on
527
635
  * `Document`, not the typed writer; for the markdown projection of a
528
636
  * richtext value use [`getMarkdown`](Self::get_markdown).
529
637
  */
@@ -550,7 +658,7 @@ export class Document {
550
658
  *
551
659
  * `addr` is an optional **card address** (`{ card }`, absent = main). A
552
660
  * present `field` throws — a field's markdown is read through the
553
- * schema-plane `quill.view(doc).get(field)`, which interprets by declared
661
+ * schema-plane `quill.reader(doc).get(field)`, which interprets by declared
554
662
  * type (#978). An out-of-range `addr.card` throws.
555
663
  */
556
664
  getMarkdown(addr?: CardAddr): string;
@@ -808,8 +916,8 @@ export class LiveSession {
808
916
  /**
809
917
  * The schema field whose content is under a point on `page` — the
810
918
  * forward (click → field) direction: hit-test a click against the
811
- * compiled document and get back the field address to focus in the
812
- * editor, or `undefined` off any field's ink. `x`/`y` are PDF points
919
+ * compiled document and get back the `DocPath` field address to focus in
920
+ * the editor, or `undefined` off any field's ink. `x`/`y` are PDF points
813
921
  * with a **bottom-left** origin, the same space as `FieldRegion.rect` —
814
922
  * from a canvas click, invert the overlay transform documented on
815
923
  * `FieldRegion`: `x = clickPx.x / renderScale`,
@@ -873,11 +981,12 @@ export class LiveSession {
873
981
  /**
874
982
  * Schema-field geometry for this compiled session — each content field's
875
983
  * **first placement** (one region per page it touches) plus widget and
876
- * scalar-reference-site regions, keyed on the quill schema field path; a
877
- * field may still appear more than once (group by `field`, see
878
- * `FieldRegion`). A session-level query: no render, no byte artifact. An
879
- * interactive preview reads it to scroll to / highlight the focused
880
- * field over a `paint`-ed canvas; the click direction is `fieldAt`.
984
+ * scalar-reference-site regions, keyed on the canonical `DocPath` address
985
+ * (`parseDocPath`-routable; the session resolves the backend's plate-space
986
+ * per-kind ordinal to it); a field may still appear more than once (group
987
+ * by `field`, see `FieldRegion`). A session-level query: no render, no byte
988
+ * artifact. An interactive preview reads it to scroll to / highlight the
989
+ * focused field over a `paint`-ed canvas; the click direction is `fieldAt`.
881
990
  * Empty for backends that place no schema fields.
882
991
  */
883
992
  regions(): FieldRegion[];
@@ -916,6 +1025,17 @@ export class Quill {
916
1025
  * canonical shape.
917
1026
  */
918
1027
  static fromTree(tree: Map<string, Uint8Array>): Quill;
1028
+ /**
1029
+ * The resolved-value view of `doc` against this quill's schema — for every
1030
+ * declared field the value the render projection would use and the
1031
+ * `FieldSource` rung it came from (`"authored" | "default" | "zero"`), in
1032
+ * one call. The card body rides the `fields` map under the `$body` key.
1033
+ *
1034
+ * Value and provenance only: completeness and errors stay `validate`'s
1035
+ * (a consumer merges it with its own diagnostic producers regardless), and
1036
+ * schema guidance reads from `Quill.schema`.
1037
+ */
1038
+ resolve(doc: Document): Resolved;
919
1039
  /**
920
1040
  * Seed a starter composable `Card` of the given kind (carries `$kind`),
921
1041
  * layering an optional per-kind seed `overlay` over the schema-example
@@ -1035,6 +1155,15 @@ export class Quillmark {
1035
1155
  */
1036
1156
  export function exportMarkdown(rt: Content): string;
1037
1157
 
1158
+ /**
1159
+ * Serialize structured [`DocPathSeg`] segments back to the canonical path
1160
+ * string — the inverse of `parseDocPath`, for a consumer that builds a path
1161
+ * rather than reads one. Throws on a segment array the deserializer rejects,
1162
+ * and on an empty segment array (symmetric with `parseDocPath("")`, which
1163
+ * throws "empty path").
1164
+ */
1165
+ export function formatDocPath(segs: DocPathSeg[]): string;
1166
+
1038
1167
  /**
1039
1168
  * Import a markdown string to a canonical `Content` content — the pure,
1040
1169
  * document-free codec. Pair with `install(addr, importMarkdown(md))` to spell
@@ -1056,6 +1185,15 @@ export function init(): void;
1056
1185
  */
1057
1186
  export function mapPos(delta: Delta, pos: number, assoc: Assoc): number;
1058
1187
 
1188
+ /**
1189
+ * Parse a canonical document-model `Diagnostic.path`
1190
+ * (`cards.<kind>[<i>].<field>`, `main.body`, `recipients[0].name`) into its
1191
+ * structured [`DocPathSeg`] segments — the exported inverse of the engine's
1192
+ * one path serializer, so a consumer routes on segments instead of regexing
1193
+ * the string. Throws on a malformed path.
1194
+ */
1195
+ export function parseDocPath(path: string): DocPathSeg[];
1196
+
1059
1197
  /**
1060
1198
  * Rebase `markdown` onto a `base` content — the pure, document-free twin of
1061
1199
  * `revise`: cold-import + `diff_import`, returning the new `content` and the
@@ -5,5 +5,5 @@ import { __wbg_set_wasm } from "./wasm_bg.js";
5
5
  __wbg_set_wasm(wasm);
6
6
  wasm.__wbindgen_start();
7
7
  export {
8
- Document, LiveSession, Quill, Quillmark, exportMarkdown, importMarkdown, init, mapPos, rebase
8
+ Document, LiveSession, Quill, Quillmark, exportMarkdown, formatDocPath, importMarkdown, init, mapPos, parseDocPath, rebase
9
9
  } from "./wasm_bg.js";