@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.
package/core/wasm_bg.js CHANGED
@@ -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}
@@ -1371,6 +1371,34 @@ export class Quill {
1371
1371
  wasm.__wbindgen_add_to_stack_pointer(16);
1372
1372
  }
1373
1373
  }
1374
+ /**
1375
+ * The resolved-value view of `doc` against this quill's schema — for every
1376
+ * declared field the value the render projection would use and the
1377
+ * `FieldSource` rung it came from (`"authored" | "default" | "zero"`), in
1378
+ * one call. The card body rides the `fields` map under the `$body` key.
1379
+ *
1380
+ * Value and provenance only: completeness and errors stay `validate`'s
1381
+ * (a consumer merges it with its own diagnostic producers regardless), and
1382
+ * schema guidance reads from `Quill.schema`.
1383
+ * @param {Document} doc
1384
+ * @returns {Resolved}
1385
+ */
1386
+ resolve(doc) {
1387
+ try {
1388
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
1389
+ _assertClass(doc, Document);
1390
+ wasm.quill_resolve(retptr, this.__wbg_ptr, doc.__wbg_ptr);
1391
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
1392
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
1393
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
1394
+ if (r2) {
1395
+ throw takeObject(r1);
1396
+ }
1397
+ return takeObject(r0);
1398
+ } finally {
1399
+ wasm.__wbindgen_add_to_stack_pointer(16);
1400
+ }
1401
+ }
1374
1402
  /**
1375
1403
  * Document schema for the quill: the user-fillable fields plus their
1376
1404
  * `ui` hints (title / group / compact / multiline). The single
@@ -1542,6 +1570,40 @@ export function exportMarkdown(rt) {
1542
1570
  }
1543
1571
  }
1544
1572
 
1573
+ /**
1574
+ * Serialize structured [`DocPathSeg`] segments back to the canonical path
1575
+ * string — the inverse of `parseDocPath`, for a consumer that builds a path
1576
+ * rather than reads one. Throws on a segment array the deserializer rejects,
1577
+ * and on an empty segment array (symmetric with `parseDocPath("")`, which
1578
+ * throws "empty path").
1579
+ * @param {DocPathSeg[]} segs
1580
+ * @returns {string}
1581
+ */
1582
+ export function formatDocPath(segs) {
1583
+ let deferred2_0;
1584
+ let deferred2_1;
1585
+ try {
1586
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
1587
+ wasm.formatDocPath(retptr, addHeapObject(segs));
1588
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
1589
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
1590
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
1591
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
1592
+ var ptr1 = r0;
1593
+ var len1 = r1;
1594
+ if (r3) {
1595
+ ptr1 = 0; len1 = 0;
1596
+ throw takeObject(r2);
1597
+ }
1598
+ deferred2_0 = ptr1;
1599
+ deferred2_1 = len1;
1600
+ return getStringFromWasm0(ptr1, len1);
1601
+ } finally {
1602
+ wasm.__wbindgen_add_to_stack_pointer(16);
1603
+ wasm.__wbindgen_export4(deferred2_0, deferred2_1, 1);
1604
+ }
1605
+ }
1606
+
1545
1607
  /**
1546
1608
  * Import a markdown string to a canonical `Content` content — the pure,
1547
1609
  * document-free codec. Pair with `install(addr, importMarkdown(md))` to spell
@@ -1601,6 +1663,33 @@ export function mapPos(delta, pos, assoc) {
1601
1663
  }
1602
1664
  }
1603
1665
 
1666
+ /**
1667
+ * Parse a canonical document-model `Diagnostic.path`
1668
+ * (`cards.<kind>[<i>].<field>`, `main.body`, `recipients[0].name`) into its
1669
+ * structured [`DocPathSeg`] segments — the exported inverse of the engine's
1670
+ * one path serializer, so a consumer routes on segments instead of regexing
1671
+ * the string. Throws on a malformed path.
1672
+ * @param {string} path
1673
+ * @returns {DocPathSeg[]}
1674
+ */
1675
+ export function parseDocPath(path) {
1676
+ try {
1677
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
1678
+ const ptr0 = passStringToWasm0(path, wasm.__wbindgen_export, wasm.__wbindgen_export2);
1679
+ const len0 = WASM_VECTOR_LEN;
1680
+ wasm.parseDocPath(retptr, ptr0, len0);
1681
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
1682
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
1683
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
1684
+ if (r2) {
1685
+ throw takeObject(r1);
1686
+ }
1687
+ return takeObject(r0);
1688
+ } finally {
1689
+ wasm.__wbindgen_add_to_stack_pointer(16);
1690
+ }
1691
+ }
1692
+
1604
1693
  /**
1605
1694
  * Rebase `markdown` onto a `base` content — the pure, document-free twin of
1606
1695
  * `revise`: cold-import + `diff_import`, returning the new `content` and the
package/core/wasm_bg.wasm CHANGED
Binary file
@@ -6,8 +6,8 @@ export const __wbg_quill_free: (a: number, b: number) => void;
6
6
  export const document__addCard: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void;
7
7
  export const document__commitField: (a: number, b: number, c: number, d: number, e: number) => void;
8
8
  export const document__commitFields: (a: number, b: number, c: number, d: number, e: number) => void;
9
+ export const document__readerGet: (a: number, b: number, c: number, d: number) => void;
9
10
  export const document__reviseField: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
10
- export const document__viewGet: (a: number, b: number, c: number, d: number) => void;
11
11
  export const document_applyChange: (a: number, b: number, c: number, d: number) => void;
12
12
  export const document_blueprintInstruction: (a: number, b: number, c: number) => void;
13
13
  export const document_card: (a: number, b: number, c: number) => void;
@@ -56,13 +56,16 @@ export const document_toMarkdown: (a: number, b: number) => void;
56
56
  export const document_tryFromJson: (a: number, b: number) => number;
57
57
  export const document_warnings: (a: number, b: number) => void;
58
58
  export const exportMarkdown: (a: number, b: number) => void;
59
+ export const formatDocPath: (a: number, b: number) => void;
59
60
  export const importMarkdown: (a: number, b: number, c: number) => void;
60
61
  export const init: () => void;
61
62
  export const mapPos: (a: number, b: number, c: number, d: number) => void;
63
+ export const parseDocPath: (a: number, b: number, c: number) => void;
62
64
  export const quill_backendId: (a: number, b: number) => void;
63
65
  export const quill_blueprint: (a: number, b: number) => void;
64
66
  export const quill_fromTree: (a: number, b: number) => void;
65
67
  export const quill_metadata: (a: number, b: number) => void;
68
+ export const quill_resolve: (a: number, b: number, c: number) => void;
66
69
  export const quill_schema: (a: number, b: number) => void;
67
70
  export const quill_seedCard: (a: number, b: number, c: number, d: number, e: number) => void;
68
71
  export const quill_seedDocument: (a: number) => number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quillmark/wasm",
3
- "version": "0.95.1",
3
+ "version": "0.96.0",
4
4
  "description": "WebAssembly bindings for Quillmark, a schema-driven document engine",
5
5
  "type": "module",
6
6
  "license": "MIT OR Apache-2.0",
@@ -16,6 +16,9 @@
16
16
  export { Quill, Document, init } from '../core/wasm.js';
17
17
  // The document-free content codec, re-exported from the core build.
18
18
  export { importMarkdown, exportMarkdown, rebase, mapPos } from '../core/wasm.js';
19
+ // The document-model path parser/serializer — route on `Diagnostic.path`
20
+ // segments instead of regexing the string.
21
+ export { parseDocPath, formatDocPath } from '../core/wasm.js';
19
22
 
20
23
  import type { CardAddr } from '../core/wasm.js';
21
24
 
@@ -42,6 +45,7 @@ export type {
42
45
  QuillCardBody,
43
46
  QuillFieldUi,
44
47
  QuillCardUi,
48
+ QuillGroupUi,
45
49
  QuillMetadata
46
50
  } from '../core/wasm.js';
47
51
 
@@ -59,6 +63,9 @@ export type {
59
63
  ContentContainer,
60
64
  ContentMark,
61
65
  ContentIsland,
66
+ TableProps,
67
+ ImageProps,
68
+ TableCell,
62
69
  CardInput,
63
70
  PathStep,
64
71
  Addr,
@@ -67,7 +74,22 @@ export type {
67
74
  Assoc,
68
75
  LineOp,
69
76
  MarkOp,
70
- ChangeBundle
77
+ ChangeBundle,
78
+ DocPathSeg
79
+ } from '../core/wasm.js';
80
+
81
+ // The resolved-value view — the return shape of `quill.resolve(doc)`. Value
82
+ // + source rung per declared field (the body rides the fields map under
83
+ // `$body`); diagnostics stay `quill.validate`, guidance stays `quill.schema`.
84
+ // Declared in the core build's generated `.d.ts` via a
85
+ // `typescript_custom_section`; re-exported here so the single public entry
86
+ // point names them.
87
+ export type {
88
+ FieldSource,
89
+ ResolvedField,
90
+ ResolvedMain,
91
+ ResolvedCard,
92
+ Resolved
71
93
  } from '../core/wasm.js';
72
94
 
73
95
  // ── Error contract ──────────────────────────────────────────────────────────
@@ -148,6 +170,10 @@ export type HitGranularity = 'cluster' | 'segment';
148
170
 
149
171
  /** A click resolved to a field and USV offset into its Content. */
150
172
  export interface ContentHit {
173
+ /**
174
+ * The field's canonical `DocPath` address (`parseDocPath`-routable) — the same
175
+ * address {@link LiveSession.fieldAt} returns for that point.
176
+ */
151
177
  field: string;
152
178
  pos: number;
153
179
  /**
@@ -158,8 +184,8 @@ export interface ContentHit {
158
184
  }
159
185
 
160
186
  /**
161
- * A rendered field region: the quill schema field address (`field`) plus its
162
- * geometry (`rect`) on the page. Emitted by backends that place schema fields
187
+ * A rendered field region: the canonical `DocPath` field address (`field`) plus
188
+ * its geometry (`rect`) on the page. Emitted by backends that place schema fields
163
189
  * (`pdfform` AcroForm widgets; Typst form-fields and span-tracked content —
164
190
  * richtext bodies, `richtext[]` elements, card content fields, direct scalar
165
191
  * references). Only fields with a schema address produce a region — a
@@ -195,7 +221,12 @@ export interface ContentHit {
195
221
  * ```
196
222
  */
197
223
  export interface FieldRegion {
198
- /** Quill schema field path (e.g. `"signature_block"`), not a backend widget name. */
224
+ /**
225
+ * The field's canonical `DocPath` address (`parseDocPath`-routable), not a
226
+ * backend widget name: `main.signature_block` for a main field,
227
+ * `cards.<kind>[<i>].signature_block` for a card field (`cards[<i>].…` when the
228
+ * card's kind is unknown).
229
+ */
199
230
  field: string;
200
231
  /** 0-based page index. */
201
232
  page: number;
@@ -390,11 +421,11 @@ export declare class LiveSession {
390
421
  apply(doc: Document): ChangeSet;
391
422
  render(options?: RenderOptions): RenderResult;
392
423
  /**
393
- * Schema-field geometry for this compiled session, keyed on quill schema
394
- * field path. A session-level query: no render, no byte artifact. Read it
395
- * to scroll to / highlight the focused field over a `paint`-ed canvas;
396
- * the click direction is {@link fieldAt}. Empty for backends that place
397
- * no schema fields.
424
+ * Schema-field geometry for this compiled session, keyed on the canonical
425
+ * `DocPath` address (`parseDocPath`-routable). A session-level query: no
426
+ * render, no byte artifact. Read it to scroll to / highlight the focused
427
+ * field over a `paint`-ed canvas; the click direction is {@link fieldAt}.
428
+ * Empty for backends that place no schema fields.
398
429
  *
399
430
  * `field` is **not** unique: a content field surfaces its **first
400
431
  * placement** as one {@link FieldRegion} per page that placement touches
@@ -407,9 +438,10 @@ export declare class LiveSession {
407
438
  */
408
439
  regions(): FieldRegion[];
409
440
  /**
410
- * The whole-field highlight boxes for `field` one union rect per page,
411
- * over the field's `span`-bearing content segments (the "highlight the
412
- * focused field" quantity). Owns the union {@link regions} leaves derived
441
+ * The whole-field highlight boxes for `field` (a canonical `DocPath` address,
442
+ * as {@link regions} keys) one union rect per page, over the field's
443
+ * `span`-bearing content segments (the "highlight the focused field"
444
+ * quantity). Owns the union {@link regions} leaves derived
413
445
  * (span-filter + per-page union), keeping `regions()` the low-level disjoint
414
446
  * truth, so a consumer stops reimplementing it. **Content only** — a field
415
447
  * placed solely as a scalar reference or a bound widget carries no `span`
@@ -420,10 +452,11 @@ export declare class LiveSession {
420
452
  /**
421
453
  * The schema field whose content is under a point on `page` — the forward
422
454
  * (click → field) direction: hit-test a click against the compiled
423
- * document and get back the field address to focus in the editor, or
424
- * `undefined` off any field's ink. `x`/`y` are PDF points with a
425
- * **bottom-left** origin, the same space as {@link FieldRegion.rect} —
426
- * from a canvas click, invert the overlay transform documented there:
455
+ * document and get back the canonical `DocPath` field address
456
+ * (`parseDocPath`-routable) to focus in the editor, or `undefined` off any
457
+ * field's ink. `x`/`y` are PDF points with a **bottom-left** origin, the
458
+ * same space as {@link FieldRegion.rect} — from a canvas click, invert the
459
+ * overlay transform documented there:
427
460
  * `x = clickPx.x / renderScale`,
428
461
  * `y = pageHeightPt - clickPx.y / renderScale`. Unlike {@link regions},
429
462
  * *every* placement answers, not just the first.
@@ -434,7 +467,10 @@ export declare class LiveSession {
434
467
  * space as {@link fieldAt}; `undefined` off all content ink.
435
468
  */
436
469
  positionAt(page: number, x: number, y: number): ContentHit | undefined;
437
- /** Content position → caret rect — reverse of {@link positionAt}. */
470
+ /**
471
+ * Content position → caret rect — reverse of {@link positionAt}. `field` is a
472
+ * canonical `DocPath` address (`parseDocPath`-routable), as {@link regions} keys.
473
+ */
438
474
  locate(field: string, pos: number): FieldRegion | undefined;
439
475
  /** Page geometry in points (1/72″). Report-only; the painter sizes the canvas. */
440
476
  pageSize(page: number): PageSize;
@@ -483,14 +519,14 @@ declare module '../core/wasm.js' {
483
519
  writer(doc: Document): DocumentWriter;
484
520
  /**
485
521
  * Bind this quill's schema to `doc` for interpreted reads — the read twin of
486
- * {@link Quill.writer}, mirroring core's `quill.view(&doc)`. Each field is
522
+ * {@link Quill.writer}, mirroring core's `quill.reader(&doc)`. Each field is
487
523
  * read by its declared type (a richtext field to markdown, every other type
488
524
  * verbatim) with schema authority, so a name the schema does not declare
489
525
  * throws rather than reading back `undefined`. Holds both handles by
490
526
  * reference and owns neither (nothing to `free()`); ephemeral by convention —
491
527
  * bind, read, discard.
492
528
  */
493
- view(doc: Document): DocumentView;
529
+ reader(doc: Document): DocumentReader;
494
530
  }
495
531
  }
496
532
 
@@ -588,7 +624,7 @@ export declare class CardWriter {
588
624
 
589
625
  /**
590
626
  * A `Document` bound to its `Quill` for interpreted reads — the schema-plane read
591
- * view, constructed via {@link Quill.view} and the read twin of
627
+ * surface, constructed via {@link Quill.reader} and the read twin of
592
628
  * {@link DocumentWriter}. One `get` reads each field by its declared type: a
593
629
  * richtext field to its markdown projection, a plaintext field to its literal
594
630
  * text, every other type its canonical value verbatim. Holds both handles by
@@ -601,7 +637,7 @@ export declare class CardWriter {
601
637
  * body-only `Document.getMarkdown`. The body read stays quill-free (a body's type
602
638
  * is a format fact) and never throws.
603
639
  */
604
- export declare class DocumentView {
640
+ export declare class DocumentReader {
605
641
  constructor(quill: Quill, doc: Document);
606
642
  /** The bound document — the instance passed in. */
607
643
  readonly document: Document;
@@ -617,20 +653,20 @@ export declare class DocumentView {
617
653
  /** The main body's markdown — the quill-free body read. Equals `get({})`. */
618
654
  getBody(): string;
619
655
  /**
620
- * A {@link CardView} for the composable card at `index`. Index validity is
656
+ * A {@link CardReader} for the composable card at `index`. Index validity is
621
657
  * checked lazily at read time, so this never throws. The cursor is ephemeral —
622
658
  * a `removeCard`/`addCard` between binding and reading silently retargets it.
623
659
  */
624
- card(index: number): CardView;
660
+ card(index: number): CardReader;
625
661
  }
626
662
 
627
663
  /**
628
664
  * A composable card bound to its `Quill` for interpreted reads, from
629
- * {@link DocumentView.card}. Same verbs as {@link DocumentView}, reading the card
665
+ * {@link DocumentReader.card}. Same verbs as {@link DocumentReader}, reading the card
630
666
  * at its bound index; each read throws `IndexOutOfRange` if that index is out of
631
667
  * range.
632
668
  */
633
- export declare class CardView {
669
+ export declare class CardReader {
634
670
  constructor(quill: Quill, doc: Document, index: number);
635
671
  /** The bound card index. */
636
672
  readonly index: number;
@@ -645,6 +681,6 @@ export declare class CardView {
645
681
  * `IndexOutOfRange` for a bad index.
646
682
  */
647
683
  get(name: string): unknown;
648
- /** This card's body markdown — the card twin of {@link DocumentView.getBody}. */
684
+ /** This card's body markdown — the card twin of {@link DocumentReader.getBody}. */
649
685
  getBody(): string;
650
686
  }
@@ -63,6 +63,10 @@ export { Quill, Document, init };
63
63
  // projection), `importMarkdown`, and the position-mapping pair (`rebase`,
64
64
  // `mapPos`).
65
65
  export { importMarkdown, exportMarkdown, rebase, mapPos } from '../core/wasm.js';
66
+ // The document-model path parser/serializer: `parseDocPath(str) => DocPathSeg[]`
67
+ // and its inverse `formatDocPath`, so a consumer routes on `Diagnostic.path`
68
+ // segments instead of reverse-engineering the grammar.
69
+ export { parseDocPath, formatDocPath } from '../core/wasm.js';
66
70
 
67
71
  // ── The main-card address ───────────────────────────────────────────────────
68
72
  /**
@@ -749,11 +753,11 @@ Quill.prototype.writer = function writer(doc) {
749
753
  return new DocumentWriter(this, doc);
750
754
  };
751
755
 
752
- // ── Typed-reader sugar: the schema-plane read view ──────────────────────────
756
+ // ── Typed-reader sugar: the schema-plane read surface ──────────────────────────
753
757
  // The read twin of the writer above. The transport `Document.get` is schema-free
754
758
  // — a `Document` cannot say which fields are richtext, so an unknown field name
755
759
  // reads back `undefined` rather than as the typo it is. Binding the quill's
756
- // schema (`_viewGet` takes the handle, like the `commit*` verbs) lets one `get`
760
+ // schema (`_readerGet` takes the handle, like the `commit*` verbs) lets one `get`
757
761
  // interpret by declared type: a richtext field to markdown, a plaintext field to
758
762
  // its literal text, every other type verbatim, and an unknown name throws
759
763
  // `UnknownField`. A field's markdown lives here, not on the body-only
@@ -762,11 +766,11 @@ Quill.prototype.writer = function writer(doc) {
762
766
 
763
767
  /**
764
768
  * A {@link Document} bound to its {@link Quill} for typed reads — the JS twin of
765
- * Rust's `quill.view(&doc)` and the read counterpart of {@link DocumentWriter}.
769
+ * Rust's `quill.reader(&doc)` and the read counterpart of {@link DocumentWriter}.
766
770
  * Reads target the main card; use {@link card} for a composable card. Holds both
767
771
  * handles by reference and owns neither, so there is nothing to `free()`.
768
772
  */
769
- export class DocumentView {
773
+ export class DocumentReader {
770
774
  #quill;
771
775
  #doc;
772
776
  /**
@@ -792,7 +796,7 @@ export class DocumentView {
792
796
  * @returns {unknown}
793
797
  */
794
798
  get(addr) {
795
- return this.#doc._viewGet(this.#quill, addr);
799
+ return this.#doc._readerGet(this.#quill, addr);
796
800
  }
797
801
  /**
798
802
  * The main body's markdown — the quill-free body read (a body's type is a
@@ -800,28 +804,28 @@ export class DocumentView {
800
804
  * @returns {string}
801
805
  */
802
806
  getBody() {
803
- return this.#doc._viewGet(this.#quill, {});
807
+ return this.#doc._readerGet(this.#quill, {});
804
808
  }
805
809
  /**
806
- * A {@link CardView} bound to the composable card at `index`. Index validity
810
+ * A {@link CardReader} bound to the composable card at `index`. Index validity
807
811
  * is checked lazily by the underlying read (it throws `IndexOutOfRange` at read
808
812
  * time), so constructing one never throws. Ephemeral like the writer cursor —
809
813
  * it holds `index`, not the card, so a `removeCard`/`addCard` between binding
810
814
  * and reading silently retargets it.
811
815
  * @param {number} index
812
- * @returns {CardView}
816
+ * @returns {CardReader}
813
817
  */
814
818
  card(index) {
815
- return new CardView(this.#quill, this.#doc, index);
819
+ return new CardReader(this.#quill, this.#doc, index);
816
820
  }
817
821
  }
818
822
 
819
823
  /**
820
824
  * A single composable card bound to its {@link Quill} for typed reads, from
821
- * {@link DocumentView.card}. Same `get` / `getBody` verbs as
822
- * {@link DocumentView}, reading the card at its bound index.
825
+ * {@link DocumentReader.card}. Same `get` / `getBody` verbs as
826
+ * {@link DocumentReader}, reading the card at its bound index.
823
827
  */
824
- export class CardView {
828
+ export class CardReader {
825
829
  #quill;
826
830
  #doc;
827
831
  #index;
@@ -855,30 +859,30 @@ export class CardView {
855
859
  * @returns {unknown}
856
860
  */
857
861
  get(name) {
858
- return this.#doc._viewGet(this.#quill, { card: this.#index, field: name });
862
+ return this.#doc._readerGet(this.#quill, { card: this.#index, field: name });
859
863
  }
860
864
  /**
861
- * This card's body markdown — the card twin of {@link DocumentView.getBody}.
865
+ * This card's body markdown — the card twin of {@link DocumentReader.getBody}.
862
866
  * @returns {string}
863
867
  */
864
868
  getBody() {
865
- return this.#doc._viewGet(this.#quill, { card: this.#index });
869
+ return this.#doc._readerGet(this.#quill, { card: this.#index });
866
870
  }
867
871
  }
868
872
 
869
- // ── `quill.view(doc)` — the schema-plane read front door ─────────────────────
873
+ // ── `quill.reader(doc)` — the schema-plane read front door ─────────────────────
870
874
  // The read twin of `quill.writer(doc)`, patched onto the same re-exported `Quill`
871
875
  // prototype (the `Quill === CoreQuill` identity invariant holds — this only adds
872
- // a method constructing the pure-JS view, which owns no WASM handle).
876
+ // a method constructing the pure-JS reader, which owns no WASM handle).
873
877
  /**
874
- * A {@link DocumentView} binding this quill's schema to `doc` for interpreted
875
- * reads — the read front door, mirroring core's `quill.view(&doc)`. The returned
876
- * view holds both handles by reference and owns neither, so there is nothing to
878
+ * A {@link DocumentReader} binding this quill's schema to `doc` for interpreted
879
+ * reads — the read front door, mirroring core's `quill.reader(&doc)`. The returned
880
+ * reader holds both handles by reference and owns neither, so there is nothing to
877
881
  * `free()`. Ephemeral by convention: bind, read, discard.
878
882
  * @this {Quill}
879
883
  * @param {Document} doc the document to read, held by reference (not owned)
880
- * @returns {DocumentView}
884
+ * @returns {DocumentReader}
881
885
  */
882
- Quill.prototype.view = function view(doc) {
883
- return new DocumentView(this, doc);
886
+ Quill.prototype.reader = function reader(doc) {
887
+ return new DocumentReader(this, doc);
884
888
  };