@quillmark/wasm 0.104.0 → 0.106.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.d.ts CHANGED
@@ -24,17 +24,13 @@ export type PayloadItem =
24
24
  | { type: "comment"; text: string; inline?: boolean };
25
25
 
26
26
  /**
27
- * A single card block, as read back from a document: returned by
28
- * `Document.main` / `Document.cards` / `Document.removeCard` / `Quill.seedCard`
29
- * / `Document.makeCard`. To feed a card *into* a document use `CardInput`
30
- * (which `insertCard` accepts); every `Card` is a valid `CardInput`,
31
- * so a card read from one document pushes straight into another.
27
+ * A single card block, as read back from a document. Every `Card` is a valid
28
+ * `CardInput`, so a card read from one document pushes straight into another.
32
29
  *
33
30
  * `$` system entries are hoisted to named fields: `kind` (the `$kind`, empty
34
- * string when none), optional `quill` (the `$quill` `name@version`, main card
35
- * only), optional `ext` (`$ext`), and optional `seed`
36
- * (the `$seed` per-kind overlay map, main card only). `payloadItems` carries
37
- * user fields and comments in order.
31
+ * string when none), `quill` (`$quill` `name@version`, main card only), `ext`
32
+ * (`$ext`), and `seed` (the `$seed` per-kind overlay map, main card only).
33
+ * `payloadItems` carries user fields and comments in order.
38
34
  */
39
35
  export interface Card {
40
36
  kind: string;
@@ -43,21 +39,16 @@ export interface Card {
43
39
  seed?: Record<string, unknown>;
44
40
  payloadItems: PayloadItem[];
45
41
  /**
46
- * The card body as canonical `Content`: the source-of-truth content model.
47
- * Always this content shape on read, never a markdown string. For the markdown
48
- * projection call the codec `exportMarkdown(card.body)`. Write a body back
49
- * with `doc.overwrite(addr, rt)` / `doc.revise(addr, md)`, or via `CardInput.body`.
42
+ * The card body as canonical `Content`, never a markdown string. For the
43
+ * markdown projection call `exportMarkdown(card.body)`.
50
44
  */
51
45
  body: Content;
52
46
  }
53
47
 
54
48
  /**
55
- * A card written *into* a document: the input twin of `Card`, accepted by
56
- * `Document.insertCard`. Like `Card` but `body` also
57
- * takes a markdown `string` (imported to the content, so a markdown / LLM writer
58
- * needn't build the `Content` shape), and every field but `kind` is optional:
59
- * an absent field defaults (no payload items, an empty body). Write one inline
60
- * (`{ kind, body }`) or build it with `Document.makeCard`.
49
+ * A card written *into* a document, accepted by `Document.insertCard`. Like
50
+ * `Card`, but `body` also takes a markdown `string`, and every field but `kind`
51
+ * is optional (defaulting to no payload items and an empty body).
61
52
  */
62
53
  export interface CardInput {
63
54
  kind: string;
@@ -69,11 +60,10 @@ export interface CardInput {
69
60
  }
70
61
 
71
62
  /**
72
- * Canonical richtext content: the content model for a card body (and richtext
73
- * fields). One text sequence over a single coordinate space (Unicode scalar
74
- * values): `text` plus line attributes, anchored `marks`, and embedded
75
- * `islands`. Every edit is a splice; markdown is a projection, not the model.
76
- * Mirrors `quillmark_content::serial`'s canonical JSON encoding.
63
+ * Canonical richtext content: the model behind a card body and richtext fields.
64
+ * One text sequence over a single coordinate space (Unicode scalar values):
65
+ * `text` plus line attributes, anchored `marks`, and embedded `islands`. Every
66
+ * edit is a splice; markdown is a projection, not the model.
77
67
  */
78
68
  export interface Content {
79
69
  text: string;
@@ -82,19 +72,17 @@ export interface Content {
82
72
  islands: ContentIsland[];
83
73
  }
84
74
 
85
- /** One `\n`-separated segment of `Content.text`, in order. `kind` is an open set
86
- * (as on `ContentIsland` and `ContentMark`): a role this build does not know
87
- * round-trips with opaque `attrs` and renders as a paragraph, so a document
88
- * carrying a future block construct still opens. The open arm blocks discriminant
89
- * narrowing, so read `level`/`lang` behind a check of the arm you want. */
75
+ /** One `\n`-separated segment of `Content.text`, in order. `kind` is an open set:
76
+ * an unknown role round-trips with opaque `attrs` and renders as a paragraph.
77
+ * The open arm blocks discriminant narrowing, so read `level`/`lang` behind a
78
+ * check of the arm you want. */
90
79
  export type ContentLine = {
91
80
  containers: ContentContainer[];
92
81
  /** A within-block hard line break rather than a new block. Omitted (false) in the common case. */
93
82
  continues?: boolean;
94
83
  } & ContentLineKind;
95
84
 
96
- /** A line's block role, declared once for `ContentLine` and the `setKind` op:
97
- * a new role is one edit here, as for `ContentContainer`. */
85
+ /** A line's block role, shared by `ContentLine` and the `setKind` op. */
98
86
  export type ContentLineKind =
99
87
  | { kind: "para" }
100
88
  | { kind: "heading"; level: number }
@@ -112,13 +100,12 @@ export type ContentContainer =
112
100
  | { container: string; attrs: unknown };
113
101
 
114
102
  /** A mark over char range `[start, end)` into `Content.text`. The open `type`
115
- * arm blocks discriminant narrowing (as on `ContentIsland`), so read a
116
- * payload-carrying arm behind its guard: `isLinkMark` (`url`) / `isAnchorMark`
117
- * (`id`), from `@quillmark/wasm/runtime`; the bare arms carry no payload. An
118
- * `anchor`'s `id` is a caller-supplied, opaque handle, unique per `Content` and
119
- * invariant while the mark lives (positions rebase, the id never does); it has no
120
- * markdown projection and survives only through the edit lane. See DOCUMENT_STORAGE
121
- * § Anchor-id identity. */
103
+ * arm blocks discriminant narrowing, so read a payload-carrying arm behind its
104
+ * guard: `isLinkMark` (`url`) / `isAnchorMark` (`id`), from
105
+ * `@quillmark/wasm/runtime`. An `anchor`'s `id` is a caller-supplied opaque
106
+ * handle, unique per `Content` and invariant while the mark lives (positions
107
+ * rebase, the id never does); it has no markdown projection and survives only
108
+ * through the edit lane. */
122
109
  export type ContentMark = { start: number; end: number } & (
123
110
  | { type: "strong" | "emph" | "underline" | "strike" | "code" }
124
111
  | { type: "link"; url: string }
@@ -126,9 +113,8 @@ export type ContentMark = { start: number; end: number } & (
126
113
  | { type: string; attrs: unknown }
127
114
  );
128
115
 
129
- /** A cell in a `TableProps`: its plain `text` plus the `marks` over it. `marks`
130
- * rides the same wire shape as prose `ContentMark`, but each mark's `start`/`end`
131
- * are USV offsets into this cell's `text` (`0..text.length`), not into
116
+ /** A cell in a `TableProps`. `marks` rides the prose `ContentMark` shape, but
117
+ * each mark's `start`/`end` are USV offsets into this cell's `text`, not into
132
118
  * `Content.text`. */
133
119
  export interface TableCell {
134
120
  text: string;
@@ -150,17 +136,15 @@ export interface ImageProps {
150
136
  alt: string;
151
137
  }
152
138
 
153
- /** A structured object occupying one island slot in `Content.text`. `type` is an
154
- * open set: the engine pins `props` as `TableProps` for `table` and `ImageProps`
155
- * for `image`; an island of any other type round-trips with opaque `props`. Like
156
- * `ContentMark`, the open `type` arm means a discriminant check does not itself
157
- * narrow `props`: read `props` as the matching shape behind the `isTableIsland` /
158
- * `isImageIsland` guards (from `@quillmark/wasm/runtime`), which narrow it. */
159
- /** How faithfully the markdown projection can carry an island. Open like an
160
- * island `type`: a class this build does not know round-trips verbatim, and
161
- * reads as `unrepresentable`. */
139
+ /** How faithfully the markdown projection can carry an island. Open: an unknown
140
+ * class round-trips verbatim and reads as `unrepresentable`. */
162
141
  export type ContentLossClass = "lossless" | "degraded" | "unrepresentable" | (string & {});
163
142
 
143
+ /** A structured object occupying one island slot in `Content.text`. `type` is an
144
+ * open set: `props` is `TableProps` for `table` and `ImageProps` for `image`,
145
+ * and any other type round-trips with opaque `props`. The open arm blocks
146
+ * narrowing, so read `props` behind the `isTableIsland` / `isImageIsland`
147
+ * guards (from `@quillmark/wasm/runtime`). */
164
148
  export type ContentIsland = {
165
149
  id: string;
166
150
  loss: ContentLossClass;
@@ -178,14 +162,16 @@ export type ContentIsland = {
178
162
  * field: "intro" }` a card field.
179
163
  *
180
164
  * On the `Addr`-taking verbs a **bare string** is shorthand for `{ field: name }`
181
- * (`doc.storeField("qty", 3)`, `doc.revise("intro", md)`) the one coercion
182
- * rule. A bare number is *not* an addr (`{ card: 2 }` is the self-documenting
183
- * spelling), so no third navigation idiom re-fragments the surface.
165
+ * (`doc.storeField("qty", 3)`); a bare number is *not* an addr.
184
166
  *
185
167
  * `doc.pathFor(addr)` mints the address as its canonical `DocPath` string, the
186
168
  * anchor `Diagnostic.path` carries and `session.locate` / `session.fieldBoxes`
187
- * take: a card path is kind-qualified, so building one by hand needs the card's
169
+ * take. A card path is kind-qualified, so a hand-built one needs the card's
188
170
  * `$kind`, and a wrong-kind path matches nothing silently.
171
+ *
172
+ * An `Addr` names a field, never a value inside one: every verb that takes one
173
+ * would then carry an element axis it cannot answer. The one read that reaches
174
+ * inside takes the path as its own argument, `reader.getContentAt(addr, path)`.
189
175
  */
190
176
  export interface Addr {
191
177
  card?: number;
@@ -193,10 +179,9 @@ export interface Addr {
193
179
  }
194
180
 
195
181
  /**
196
- * A card-only address: the axis the card-scoped verbs (`storeFields`,
197
- * `storeExt`, `getExt`, `commitFields`, …) take. An absent `card` targets the
198
- * main card. A present `field` throws: a card address takes only `card`, and a
199
- * would-be nested write is a bug the error names rather than silently ignores.
182
+ * A card-only address, taken by the card-scoped verbs (`storeFields`,
183
+ * `storeExt`, `getExt`, `commitFields`, …). An absent `card` targets the main
184
+ * card; a present `field` throws.
200
185
  */
201
186
  export interface CardAddr {
202
187
  card?: number;
@@ -204,8 +189,8 @@ export interface CardAddr {
204
189
 
205
190
  /**
206
191
  * A text-splice change set over the USV content (CodeMirror `ChangeSet`
207
- * semantics): plain, structured-clone-able data. Returned by `revise` and by
208
- * the `rebase` codec; map a stored position through it with `mapPos`.
192
+ * semantics), returned by `revise` and by the `rebase` codec. Map a stored
193
+ * position through it with `mapPos`.
209
194
  */
210
195
  export interface Delta {
211
196
  ops: ({ retain: number } | { insert: string } | { delete: number })[];
@@ -216,11 +201,9 @@ export type Assoc = "before" | "after";
216
201
 
217
202
  /**
218
203
  * A mark edit in final-text coordinates (post-delta, post-line-op). `add` /
219
- * `remove` carry the `ContentMark` vocabulary (`{ type, }`); `removeAnchor`
220
- * drops one identity anchor by id. An `add` of an `anchor` requires a non-empty
221
- * `id` not already live in the field: a collision or the empty id throws
222
- * (ids are caller-supplied and unique per `Content`; DOCUMENT_STORAGE
223
- * § Anchor-id identity).
204
+ * `remove` carry the `ContentMark` vocabulary; `removeAnchor` drops one identity
205
+ * anchor by id. An `add` of an `anchor` requires a non-empty `id` not already
206
+ * live in the field; a collision or the empty id throws.
224
207
  */
225
208
  export type MarkOp =
226
209
  | ({ op: "add" | "remove"; start: number; end: number } & (
@@ -232,12 +215,10 @@ export type MarkOp =
232
215
  | { op: "removeAnchor"; id: string };
233
216
 
234
217
  /**
235
- * A line/block edit. `split`/`join` splice `\n` in post-`delta`, post-`islandOps`
236
- * coordinates; `setKind`/`setContainers`/`setContinues` touch metadata.
237
- * `setContinues` sets/clears a line's within-block hard-break flag
238
- * (`ContentLine.continues`): the op-grained way to lower a Shift+Enter hard
239
- * break or a new code-fence interior line; `continues: true` on line 0 is
240
- * rejected (nothing precedes it to continue).
218
+ * A line/block edit. `split`/`join` splice `\n` in post-`delta`,
219
+ * post-`islandOps` coordinates; `setKind`/`setContainers`/`setContinues` touch
220
+ * metadata. `setContinues` sets or clears a line's within-block hard-break flag
221
+ * (`ContentLine.continues`); `continues: true` on line 0 is rejected.
241
222
  */
242
223
  export type LineOp =
243
224
  | { op: "split"; at: number }
@@ -248,34 +229,25 @@ export type LineOp =
248
229
 
249
230
  /**
250
231
  * An island edit: the only channel that reaches an island's payload, a table's
251
- * cells or an image's url.
252
- *
253
- * Both ops move one island entry and leave the field's text and marks alone, so
254
- * an island edit keeps every identity anchor in the field. That is why a table
255
- * edit lowers to `applyChange` rather than `overwrite`, which drops them all.
232
+ * cells or an image's url. Both ops leave the field's text and marks alone, so
233
+ * an island edit keeps every identity anchor in the field.
256
234
  *
257
- * `set` addresses an existing island by `id`; an `id` no island carries throws
258
- * rather than passing silently. `insert` places a new island's slot at `at`
259
- * together with its entry, so a slot never exists without an island behind it;
260
- * its `id` must be non-empty and unused. `at` is a position in the text the
261
- * `delta` and this bundle's earlier island ops left: each insert splices its
262
- * slot before the next op reads the text, so slots after `a` and `b` of `abc`
263
- * go in at 1 and 3. A stale frame misplaces slots and never throws.
235
+ * `set` addresses an existing island by `id`; an unknown `id` throws. `insert`
236
+ * places a new island's slot at `at` together with its entry, so a slot never
237
+ * exists without an island behind it; its `id` must be non-empty and unused.
238
+ * `at` is a position in the text the `delta` and this bundle's earlier island
239
+ * ops left, so slots after `a` and `b` of `abc` go in at 1 and 3. A stale frame
240
+ * misplaces slots and never throws. A `delta` insert string may not carry a
241
+ * slot, which would orphan: split such a splice into the slot-free `delta` plus
242
+ * one `insert` per slot.
264
243
  *
265
- * A `delta` insert string may not carry a slot, which would orphan. A producer
266
- * that computes one splice over the whole field text carries slots in it on any
267
- * paste of an island or undo of a deletion; that splice splits into the
268
- * slot-free `delta` plus one `insert` per slot.
244
+ * Deleting an island needs no op: a `delta` that removes its slot drops the
245
+ * island whole, and a block island's line demotes to `para`. Re-landing it is an
246
+ * `insert` of the full island under its original id; a pasted copy of a live
247
+ * island mints a fresh one.
269
248
  *
270
- * Deleting an island needs no op, and the drop is whole: a `delta` that removes
271
- * its slot drops the island from the store. Re-landing it is an `insert` of the
272
- * full island under its original id, and only the producer that deleted it
273
- * still holds that value. A pasted copy of a live island is new and mints fresh
274
- * (DOCUMENT_STORAGE § Island-id determinism). A block island's line demotes to
275
- * `para` when its slot goes, so re-landing one re-tags the line too.
276
- *
277
- * A `set` stores the `loss` it is given: nothing re-derives the class from the
278
- * new `props`, so a write that changes what markdown can carry must say so.
249
+ * A `set` stores the `loss` it is given; nothing re-derives the class from the
250
+ * new `props`.
279
251
  *
280
252
  * An island is *inline* (a slot inside a paragraph) unless its line says
281
253
  * otherwise. A **block** island is one bundle of all three channels, in the
@@ -288,13 +260,12 @@ export type IslandOp =
288
260
  | ({ op: "insert"; at: number } & ContentIsland);
289
261
 
290
262
  /**
291
- * A committed content edit bundle for `applyChange`: a text `delta` (default no
292
- * text change), then `islandOps`, then `lineOps`, then `markOps` (mark ranges
293
- * are in final-text coordinates: every earlier channel applied). Every field is
294
- * optional.
263
+ * A committed content edit bundle for `applyChange`, applied in order: a text
264
+ * `delta`, then `islandOps`, then `lineOps`, then `markOps` (mark ranges are in
265
+ * final-text coordinates). Every field is optional.
295
266
  *
296
- * Within each channel ops apply in sequence, each against the state the earlier
297
- * ones left: an island `insert`'s `at` counts earlier ops' slots, and `lineOps`
267
+ * Within each channel ops apply in sequence against the state the earlier ones
268
+ * left: an island `insert`'s `at` counts earlier ops' slots, and `lineOps`
298
269
  * positions and indices renumber through earlier `split`/`join`.
299
270
  */
300
271
  export interface ChangeBundle {
@@ -322,14 +293,12 @@ export type DocPathSeg =
322
293
 
323
294
 
324
295
  /** The commitment-ladder rung that produced a `ResolvedField.value`. */
325
- export type FieldSource = "authored" | "default" | "zero";
296
+ export type FieldSource = "authored" | "default" | "blank";
326
297
 
327
298
  /**
328
299
  * One resolved row: its `name`, the value the render projection would use, and
329
- * the `FieldSource` rung it came from. Rows are an ordered array: declaration
330
- * order is structural, not object-key order. The card body is a `body` sibling
331
- * on its card, never a row in `fields`. Diagnostics stay `Quill.validate`'s;
332
- * schema guidance (`example:`, labels) reads from `Quill.schema`.
300
+ * the `FieldSource` rung it came from. Rows are an ordered array, so declaration
301
+ * order is structural rather than object-key order.
333
302
  */
334
303
  export interface ResolvedField {
335
304
  name: string;
@@ -359,9 +328,8 @@ export interface ResolvedCard {
359
328
  }
360
329
 
361
330
  /**
362
- * The resolved-value view (`Quill.resolve`): the main card and every
363
- * composable card. Value and provenance only: completeness and errors stay
364
- * `Quill.validate`.
331
+ * The resolved-value view (`Quill.resolve`): the main card and every composable
332
+ * card. Value and provenance only; completeness stays `Quill.validate`'s.
365
333
  */
366
334
  export interface Resolved {
367
335
  main: ResolvedMain;
@@ -370,20 +338,21 @@ export interface Resolved {
370
338
 
371
339
 
372
340
 
373
- /** UI layout hints for a single field. Field display order is not a hint:
374
- * key order in the schema's `fields`/`properties` objects is declaration
375
- * order, the ordering contract. */
341
+ /** UI layout hints for a single field. Display order is not a hint: key order
342
+ * in the schema's `fields`/`properties` objects is the ordering contract. */
376
343
  export interface QuillFieldUi {
377
344
  title?: string;
378
345
  group?: string;
379
346
  compact?: boolean;
380
347
  multiline?: boolean;
348
+ /** Label for an `enum`'s blank option. Absent, the consumer supplies a
349
+ * conventional label of its own. */
350
+ blank_title?: string;
381
351
  }
382
352
 
383
353
  /** One entry in a card's `ui.groups` registry: a display-label override for the
384
- * group id (the map key). An empty object carries no override: the consumer
385
- * derives the label from the id (`memo_for` → "Memo For"), as it does a field
386
- * label from its key. */
354
+ * group id (the map key). An empty object carries no override, and the consumer
355
+ * derives the label from the id (`memo_for` → "Memo For"). */
387
356
  export interface QuillGroupUi {
388
357
  title?: string;
389
358
  }
@@ -391,16 +360,14 @@ export interface QuillGroupUi {
391
360
  /** UI layout hints for a card (main or named card kind). */
392
361
  export interface QuillCardUi {
393
362
  title?: string;
394
- /** The card's group registry: the ordered table of contents naming every
395
- * group a field's `ui.group` may reference. The map key is the group id, and
396
- * key order is declaration order: the display-order contract, the same one
397
- * `fields` key order carries. Absent when the card declares no groups (or
398
- * uses the deprecated implicit-group form). */
363
+ /** The groups a field's `ui.group` may reference, keyed by group id. Key
364
+ * order is the display-order contract, as with `fields`. Absent when the
365
+ * card declares no groups. */
399
366
  groups?: Record<string, QuillGroupUi>;
400
367
  }
401
368
 
402
- /** A block construct a body can hold. `paragraph` is absent on purpose: it is
403
- * the floor and cannot be declined. */
369
+ /** A block construct a body can hold. `paragraph` is the floor and cannot be
370
+ * declined, so it is absent. */
404
371
  export type QuillBlockConstruct =
405
372
  | "heading"
406
373
  | "rule"
@@ -416,40 +383,43 @@ export interface QuillCardBody {
416
383
  enabled?: boolean;
417
384
  /** Example body content embedded verbatim in the blueprint body region. Fallback is "Write <card> body here." */
418
385
  example?: string;
419
- /** Block constructs this quill's plate does not typeset in this body.
420
- *
421
- * Absent or empty means it declines nothing, which is the default. An
422
- * editor reads this to decline a gesture before the author makes it; a body
423
- * that holds one anyway draws a non-fatal `plate::unsupported_construct`
424
- * warning carrying the construct and a count. It is the quill's claim about
425
- * its own plate, and nothing verifies it: a construct absent from this list
426
- * is not a promise that the plate typesets it. */
386
+ /** Block constructs this quill's plate does not typeset in this body;
387
+ * absent or empty declines nothing. A body that holds one anyway draws a
388
+ * non-fatal `plate::unsupported_construct` warning. Nothing verifies the
389
+ * claim: absence from this list is not a promise the plate typesets it. */
427
390
  unsupported?: QuillBlockConstruct[];
428
391
  }
429
392
 
430
393
  /** Schema entry for a single field declared in a quill's `Quill.yaml`.
431
394
  *
432
- * A field's *cell* is determined by `default`: a field with a `default`
433
- * is **Endorsed** (the rendered value is shippable as-is), while a field
434
- * without a `default` is **Unendorsed** (the blueprint carries a
435
- * `!must_fill` marker; a marker left in the document yields the non-fatal
436
- * `validation::must_fill` warning from validate, and the render path
437
- * zero-fills the field). There is no separate `required` axis.
395
+ * Two independent axes, and no separate `required` one. `default` and
396
+ * `example` say what the cell holds; `must_fill` says whether a human must
397
+ * author it, deriving from `default`'s absence when left unset. An obliged
398
+ * field carries a `!must_fill` marker in the blueprint and warns
399
+ * `validation::must_fill` while the document leaves it unauthored. Neither
400
+ * axis gates render: an absent field blank-fills.
438
401
  */
439
402
  export interface QuillFieldSchema {
440
403
  type: "string" | "number" | "integer" | "boolean" | "array" | "object" | "date" | "datetime" | "richtext" | "plaintext" | "enum";
441
404
  description?: string;
442
405
  default?: unknown;
443
406
  example?: unknown;
444
- /** Required on `type: "enum"`, and valid nowhere else: the closed set of
445
- * allowed string values. */
407
+ /** The closed set of allowed values. Required on `type: "enum"`, and valid
408
+ * nowhere else. */
446
409
  values?: string[];
410
+ /** Per-member field sets on a card-level `type: "enum"` field, keyed by
411
+ * member: the fields that exist only where the discriminant holds that
412
+ * member. Declaring it makes the field rest as a container,
413
+ * `{value: <member>, …that member's fields}`, rather than a bare string. */
414
+ variants?: Record<string, Record<string, QuillFieldSchema>>;
415
+ /** Whether a human must author the field. Absent, it derives from
416
+ * `default`: a defaulted field is unobliged, a defaultless one obliged. */
417
+ must_fill?: boolean;
447
418
  ui?: QuillFieldUi;
448
419
  properties?: Record<string, QuillFieldSchema>;
449
420
  items?: QuillFieldSchema;
450
- /** Present (and `true`) on a `richtext` or `plaintext` field declared
451
- * `inline`: the single-paragraph, container-free, island-free constraint.
452
- * Core serializes `inline: true` into the schema JSON; absent otherwise. */
421
+ /** `true` on a `richtext` or `plaintext` field declared `inline`: the
422
+ * single-paragraph, container-free, island-free constraint. */
453
423
  inline?: boolean;
454
424
  }
455
425
 
@@ -462,10 +432,8 @@ export interface QuillCardSchema {
462
432
  }
463
433
 
464
434
  /**
465
- * Document schema returned by `Quill.schema`. Includes optional `ui` keys.
466
- *
467
- * Describes only the user-fillable fields. The quill reference
468
- * (constructed as `${metadata.name}@${metadata.version}`) and card-kind
435
+ * Document schema returned by `Quill.schema`: the user-fillable fields only.
436
+ * The quill reference (`${metadata.name}@${metadata.version}`) and card-kind
469
437
  * discriminators are document-level metadata, not schema fields.
470
438
  */
471
439
  export interface QuillSchema {
@@ -475,10 +443,9 @@ export interface QuillSchema {
475
443
  }
476
444
 
477
445
  /**
478
- * Identity snapshot mirroring the `quill:` section of `Quill.yaml`.
479
- * The schema lives on `Quill.schema`; the backend's output formats are a
480
- * resolved-backend capability read from the engine (`Quillmark.supportedFormats`),
481
- * not part of this pure-config snapshot.
446
+ * Identity snapshot mirroring the `quill:` section of `Quill.yaml`. The schema
447
+ * lives on `Quill.schema`; output formats are a resolved-backend capability read
448
+ * from `Quillmark.supportedFormats`, not part of this config snapshot.
482
449
  */
483
450
  export interface QuillMetadata {
484
451
  name: string;
@@ -498,31 +465,22 @@ export interface Diagnostic {
498
465
  message: string;
499
466
  location?: Location;
500
467
  /**
501
- * Document-model path anchor (e.g. `\"cards.indorsement[0].signature_block\"`).
502
- *
503
- * Set on schema validation diagnostics; `undefined` otherwise. See the
504
- * Rust `quillmark_core::error` module docs for the path grammar.
468
+ * Document-model path anchor (e.g. `\"cards.indorsement[0].signature_block\"`),
469
+ * set on schema validation diagnostics and `undefined` otherwise.
505
470
  */
506
471
  path?: string;
507
472
  hint?: string;
508
473
  /**
509
- * The facts `message` interpolates, keyed by name. With `code`, the
510
- * substitution unit needed to word this diagnostic in another language;
511
- * `prose/canon/ERROR.md` § \"Diagnostic args\" tabulates the keys per code.
474
+ * The facts `message` interpolates, keyed by name. With `code`, enough to
475
+ * word this diagnostic in another language.
512
476
  *
513
- * Declared optional explicitly because `tsify` does not read
514
- * `skip_serializing_if`: without this, a field the runtime omits is
515
- * declared required. `sourceChain` carries that mismatch.
477
+ * Declared optional explicitly: `tsify` does not read
478
+ * `skip_serializing_if`, so an omitted field would be declared required.
516
479
  */
517
480
  args?: Record<string, unknown>;
518
481
  sourceChain?: string[];
519
482
  }
520
483
 
521
- /**
522
- * Severity levels for diagnostics
523
- */
524
- export type Severity = "error" | "warning";
525
-
526
484
  /**
527
485
  * Source location for errors and warnings
528
486
  */
@@ -532,6 +490,8 @@ export interface Location {
532
490
  column: number;
533
491
  }
534
492
 
493
+ export type Severity = "error" | "warning";
494
+
535
495
 
536
496
  /**
537
497
  * Typed in-memory Quillmark document.
@@ -540,86 +500,69 @@ export class Document {
540
500
  free(): void;
541
501
  [Symbol.dispose](): void;
542
502
  /**
543
- * **Apply** a committed content edit `bundle`
544
- * (`{ delta?, islandOps?, lineOps?, markOps? }`) at `addr`, the editor
545
- * splice: text delta first, then island ops, then line ops, then mark ops
546
- * (mark ranges in final-text coordinates), each all-or-nothing. An absent
547
- * `addr.field` targets the body, an absent `addr.card` the main card.
548
- *
549
- * The island channel keeps a table or image edit on the op path: it moves
550
- * the island alone, so the anchors elsewhere in the field survive an edit
503
+ * **Apply** a committed content edit `bundle` at `addr`, the editor splice:
504
+ * text delta first, then island ops, then line ops, then mark ops (mark
505
+ * ranges in final-text coordinates), all-or-nothing. An absent `addr.field`
506
+ * targets the body, an absent `addr.card` the main card. The island channel
507
+ * moves an island alone, so anchors elsewhere in the field survive an edit
551
508
  * `overwrite` would clear.
552
509
  *
553
510
  * Throws on an out-of-range card, a field that is not richtext, a malformed
554
- * bundle, or an op that applies out of bounds (the value is unchanged on a
555
- * failed apply).
511
+ * bundle, or an op that applies out of bounds; the value is unchanged on a
512
+ * failed apply.
556
513
  */
557
514
  applyChange(addr: Addr | string, bundle: ChangeBundle): void;
558
515
  /**
559
- * Authoring-ergonomics header introducing a blueprint to an LLM/MCP
560
- * consumer for the given `quillName`. Re-exposes core's canonical text for
561
- * JS consumers; any surface that draws from the same core source stays
562
- * uniform.
516
+ * Authoring-ergonomics header introducing a blueprint to an LLM/MCP consumer
517
+ * for the given `quillName`, re-exposed from core.
563
518
  */
564
519
  static blueprintInstruction(quill_name: string): string;
565
520
  /**
566
- * The **body** markdown projection (the main body, or a composable card's
567
- * body (`{ card }`)) the on-demand, lossy export (content-only marks do not
568
- * survive markdown). A body's type is a format fact, not a schema fact, so
569
- * this read stays quill-free; a body is never absent.
521
+ * The **body** markdown projection: an on-demand, lossy export (content-only
522
+ * marks do not survive markdown). A body's type is a format fact, not a
523
+ * schema fact, so this read stays quill-free, and a body is never absent.
570
524
  *
571
- * `addr` is an optional **card address** (`{ card }`, absent = main). A
572
- * present `field` throws: a field's markdown is read through the
573
- * schema-plane `quill.reader(doc).get(field)`, which interprets by declared
574
- * type. An out-of-range `addr.card` throws.
525
+ * `addr` is an optional card address (absent = main). A present `field`
526
+ * throws: read a field's markdown through `quill.reader(doc).get(field)`,
527
+ * which interprets by declared type. An out-of-range `addr.card` throws.
575
528
  */
576
529
  bodyMarkdown(addr?: CardAddr): string;
577
530
  /**
578
- * A single composable card by index: the whole `Card`, the card-indexed
579
- * twin of the [`main`](Self::main) getter, so reading one card need not
580
- * materialize every card via [`cards`](Self::cards). An out-of-range
581
- * `index` throws `edit::index_out_of_range`, matching the card write
582
- * verbs.
531
+ * A single composable card by index, so reading one need not materialize
532
+ * every card via [`cards`](Self::cards). An out-of-range `index` throws
533
+ * `edit::index_out_of_range`.
583
534
  */
584
535
  card(index: number): Card;
585
536
  /**
586
- * The composable card's own path, `cards.<kind>[index]`: the whole-card
587
- * root [`pathFor`](Self::path_for) extends, for a consumer anchoring the
588
- * card rather than one of its fields. Total on the index axis for the same
589
- * reason, out of range renders `cards[index]`.
537
+ * The composable card's own path, `cards.<kind>[index]`: the root
538
+ * [`pathFor`](Self::path_for) extends, for anchoring the card rather than
539
+ * one of its fields. Total on the index axis; out of range renders
540
+ * `cards[index]`.
590
541
  */
591
542
  cardPath(index: number): string;
592
543
  clone(): Document;
593
544
  /**
594
- * Storage version this build writes via [`toJson`](Document::to_json).
595
- * Tracks the `Document` model version (not the running crate version):
596
- * the tag advances only when the wire format changes, not on every release.
545
+ * Storage version this build writes via [`toJson`](Document::to_json). The
546
+ * tag advances only when the wire format changes, not on every release.
597
547
  */
598
548
  static currentStorageVersion(): string;
599
549
  /**
600
- * Structural equality (parse-time `warnings` excluded). Use to debounce
601
- * upstream prop updates instead of re-parsing on every keystroke.
550
+ * Structural equality, excluding parse-time `warnings`.
602
551
  */
603
552
  equals(other: Document): boolean;
604
553
  /**
605
- * Render a Diagnostic as the canonical pretty-printed text (core's
606
- * `Diagnostic::fmt_pretty`). Single source of truth so a Diagnostic looks
607
- * identical no matter which consumer surfaces it.
554
+ * Render a Diagnostic as the canonical pretty-printed text, so it looks
555
+ * identical whichever consumer surfaces it.
608
556
  */
609
557
  static formatDiagnostic(diag: Diagnostic): string;
610
558
  /**
611
- * Authoring-format rules for the card-yaml markdown surface. The canonical
612
- * text is core's (`quillmark_core::document::FORMAT_RULES`), re-exposed
613
- * here for JS consumers so it matches any other surface that draws from the
614
- * same source. Read once at startup and cache; the value never changes
615
- * between calls.
559
+ * Authoring-format rules for the card-yaml markdown surface, re-exposed from
560
+ * core. Constant across calls; read once and cache.
616
561
  */
617
562
  static formatRules(): string;
618
563
  /**
619
- * Reconstruct a `Document` from a versioned storage DTO string produced
620
- * by [`toJson`](Document::to_json). Unknown `schema` tags are rejected.
621
- * The result carries no parse-time warnings (`.warnings` is always empty).
622
- *
564
+ * Reconstruct a `Document` from a versioned storage DTO string produced by
565
+ * [`toJson`](Document::to_json). The result carries no parse-time warnings.
623
566
  * Throws if `json` is not a valid storage DTO (malformed JSON, unknown
624
567
  * `schema`, missing fields, or unparseable quill reference).
625
568
  */
@@ -630,81 +573,66 @@ export class Document {
630
573
  static fromMarkdown(markdown: string): Document;
631
574
  /**
632
575
  * The whole `$ext` map at `addr` (a card address, absent `card` = main), or
633
- * `undefined` when the card carries none. The fine-grained `$ext` read:
634
- * your own state without serializing the whole card. Throws on a present
635
- * `field` (a card address takes only `card`) or an out-of-range card.
576
+ * `undefined` when the card carries none: the `$ext` read that avoids
577
+ * serializing the whole card. Throws on a present `field` or an
578
+ * out-of-range card.
636
579
  */
637
580
  getExt(addr?: CardAddr): Record<string, unknown> | undefined;
638
581
  /**
639
582
  * The value stored under `$ext[ns]` at `addr` (a card address, absent `card`
640
- * = main), or `undefined`. The namespace-scoped `$ext` read: your own slot
641
- * without a whole-card serialize, and non-destructive (unlike
642
- * `removeExtNamespace`). Throws on a present `field` or an out-of-range card.
583
+ * = main), or `undefined`. Throws on a present `field` or an out-of-range
584
+ * card.
643
585
  */
644
586
  getExtNamespace(addr: CardAddr, ns: string): unknown;
645
587
  /**
646
- * Read the **verbatim stored value** at `addr`: the raw payload value of a
647
- * field, or the **body content** when `addr.field` is absent. A bare
648
- * string is `Addr` shorthand for `{ field }`. Reads are total over the field
649
- * axis: an absent field is `undefined`; only an out-of-range `addr.card`
650
- * throws `edit::index_out_of_range`. Needs no schema, so it lives on
651
- * `Document`: the read echo of the verbatim `store*` write, distinct from
652
- * the interpreted schema-plane [`reader.get`](Self::reader_get). For the
653
- * markdown projection use [`bodyMarkdown`](Self::get_markdown) (body) or
654
- * `reader.get` (a field's declared type).
588
+ * Read the **verbatim stored value** at `addr`: a field's raw payload value,
589
+ * or the body content when `addr.field` is absent. A bare string is `Addr`
590
+ * shorthand for `{ field }`. Needs no schema: the read echo of the verbatim
591
+ * `store*` write, distinct from the interpreted
592
+ * [`reader.get`](Self::reader_get). Reads are total over the field axis — an
593
+ * absent field is `undefined` and only an out-of-range `addr.card` throws
594
+ * `edit::index_out_of_range`.
655
595
  *
656
- * **A content field at rest has one stored form per codec**: a `richtext`
657
- * field holds the canonical content object, a `plaintext` field its literal
658
- * string. A document that came through the bound door (`quill.parse` /
659
- * `quill.conform`) is at rest, so this read no longer depends on which lane
660
- * built it. A document that came through the transport door
661
- * (`Document.fromMarkdown`, a legacy stored row) may rest as authored until
662
- * it is conformed, and this read reports what is there. For the `Content`
663
- * either way, use the schema-plane `reader.getContent`, which decodes
664
- * through the codec the field's declared type names.
596
+ * A content field at rest has one stored form per codec: a `richtext` field
597
+ * holds the canonical content object, a `plaintext` field its literal
598
+ * string. A document from the bound door (`quill.parse` / `quill.conform`)
599
+ * is at rest; one from the transport door may rest as authored until it is
600
+ * conformed, and this read reports what is there. For the `Content` either
601
+ * way use `reader.getContent`.
665
602
  */
666
603
  getStored(addr: Addr | string): unknown;
667
604
  /**
668
- * Insert a card, the single insertion verb: `at` absent appends, a number
669
- * inserts at that index (must be in `0..=cards.length`). Accepts a
670
- * `CardInput`: a card read back (`cards` / `removeCard` / `quill.seedCard`),
671
- * a [`makeCard`](Document::make_card) result, or a bare `{ kind, body }`
672
- * (every returned `Card` is a valid `CardInput`). Throws if `card.kind` is
673
- * not a valid kind name, or if `at` is out of range.
605
+ * Insert a card: `at` absent appends, a number inserts at that index (in
606
+ * `0..=cards.length`). Accepts any `CardInput`, including a card read back
607
+ * out of a document. Throws if `card.kind` is not a valid kind name, or if
608
+ * `at` is out of range.
674
609
  */
675
610
  insertCard(card: CardInput, at?: number): void;
676
611
  /**
677
612
  * Whether the field at `addr` is marked `!must_fill`. A bare string is `Addr`
678
- * shorthand for `{ field }`. `false` for an absent field (truthful: it isn't
679
- * marked) and for a body address (a body is never a fill). Only an
680
- * out-of-range `addr.card` throws.
613
+ * shorthand for `{ field }`. `false` for an absent field and for a body
614
+ * address; only an out-of-range `addr.card` throws.
681
615
  */
682
616
  isFill(addr: Addr | string): boolean;
683
617
  /**
684
- * Replace this document's contents **in place** from a versioned storage
685
- * DTO string: the mutating twin of the static
686
- * [`fromJson`](Document::from_json) constructor. Parse-time `warnings` are
687
- * cleared. Throws (leaving the document unchanged) on an invalid DTO.
618
+ * Replace this document's contents **in place** from a versioned storage DTO
619
+ * string: the mutating twin of [`fromJson`](Document::from_json). Parse-time
620
+ * `warnings` are cleared. Throws on an invalid DTO, leaving the document
621
+ * unchanged.
688
622
  *
689
623
  * The cross-WASM-memory `Document` bridge: mutate a document on a
690
- * backend-memory clone, then write the mutated state back into the caller's
691
- * canonical document with this, the one way to update a live handle across
692
- * the linear-memory seam without the caller re-binding its variable.
624
+ * backend-memory clone, then write the state back into the caller's
625
+ * canonical document, without the caller re-binding its variable.
693
626
  */
694
627
  loadJson(json: string): void;
695
628
  /**
696
629
  * Build a fresh `Card` from a kind and a flat field map: the ergonomic
697
- * constructor for `insertCard`. `fields` is an optional
698
- * `Record<string, unknown>` (each entry becomes a card field, in
699
- * insertion order); `body` defaults to `""`.
630
+ * constructor for `insertCard`, which also takes any `Card` object
631
+ * directly. Each `fields` entry becomes a card field in insertion order;
632
+ * `body` defaults to `""`.
700
633
  *
701
- * Sugar, not a required step: `insertCard` takes any `Card` object, and
702
- * `removeCard` returns one, so a card round-trips without passing through
703
- * here.
704
- *
705
- * Checks only what a detached card can decide alone: field-name grammar
706
- * and value depth. Kind validity is positional (`main` is right for the
707
- * root, reserved for a composable card) so `insertCard` is its gate, and
634
+ * Checks only what a detached card can decide alone: field-name grammar and
635
+ * value depth. Kind validity is positional, so `insertCard` is its gate and
708
636
  * any kind string is accepted here.
709
637
  */
710
638
  static makeCard(kind: string, fields?: Record<string, unknown>, body?: string): Card;
@@ -713,66 +641,51 @@ export class Document {
713
641
  */
714
642
  moveCard(from: number, to: number): void;
715
643
  /**
716
- * `new Document(quillRef)`, a blank document: a main card carrying only
717
- * `$quill`, an empty body, and no composable cards. The programmatic
718
- * blank canvas: absent fields resolve at render time (`default`, else
719
- * type-empty zero), so nothing the caller did not set reaches the
720
- * output. For an example-filled starter use `Quill.seedDocument()`.
721
- * Throws on an invalid quill reference. Mirrors Python `Document(quill_ref)`.
644
+ * A blank document: a main card carrying only `$quill`, an empty body, and
645
+ * no composable cards. Absent fields resolve at render time (`default`, else
646
+ * the field's blank), so nothing the caller did not set reaches the output.
647
+ * For an example-filled starter use `Quill.seedDocument()`. Throws on an
648
+ * invalid quill reference.
722
649
  */
723
650
  constructor(quill_ref: string);
724
651
  /**
725
- * **Overwrite** the content value at `addr`: **value semantics**, content
726
- * only. Stores exactly `rt` (a canonical `Content` content object); the
727
- * identity anchors of any previous value are gone. The bottom rung of the
728
- * content lane's ladder by anchor fate: `overwrite` destroys,
729
- * [`revise`](Document::revise) rebases,
730
- * [`applyChange`](Document::apply_change) preserves. An absent `addr.field`
731
- * targets the body, an absent `addr.card` the main card. Cold-importing
732
- * markdown is spelled `overwrite(addr, importMarkdown(md))` at the call
733
- * site, where the anchor loss is visible.
652
+ * **Overwrite** the content value at `addr` with exactly `rt`: value
653
+ * semantics, so the identity anchors of any previous value are gone. By
654
+ * anchor fate `overwrite` destroys, [`revise`](Document::revise) rebases,
655
+ * and [`applyChange`](Document::apply_change) preserves. An absent
656
+ * `addr.field` targets the body, an absent `addr.card` the main card.
734
657
  *
735
658
  * Throws on an out-of-range card, a malformed field name, or an `rt` that is
736
659
  * not a canonical content object.
737
660
  */
738
661
  overwrite(addr: Addr | string, rt: Content): void;
739
662
  /**
740
- * `addr`'s canonical `DocPath` string, the anchor `Diagnostic.path`
741
- * carries: `pathFor()` is `main.body`, `pathFor("intro")` `main.intro`,
742
- * `pathFor({card: 2})` `cards.<kind>[2].body`. A consumer holding an
743
- * `Addr` mints one without restating the kind lookup, the `Addr` defaults
744
- * or the range guard.
663
+ * `addr`'s canonical `DocPath` string, the anchor `Diagnostic.path` carries:
664
+ * `pathFor()` is `main.body`, `pathFor("intro")` `main.intro`,
665
+ * `pathFor({card: 2})` `cards.<kind>[2].body`.
745
666
  *
746
- * The kind is the card's stored `$kind` verbatim, the quill-free rule the
747
- * addressed mutators anchor with and the geometry translation uses, not
748
- * `validate`'s declared-kind filter: a `Document` holds a `$quill`
749
- * reference and no schema. That is the one edge where this path and a
750
- * `validate` diagnostic path differ for the same card.
667
+ * The kind is the card's stored `$kind` verbatim, not `validate`'s
668
+ * declared-kind filter, since a `Document` holds a `$quill` reference and no
669
+ * schema. That is the one edge where this path and a `validate` diagnostic
670
+ * path differ for the same card.
751
671
  *
752
- * **Total on the index axis**, unlike the `Addr` reads (`getStored`,
753
- * `isFill`, `bodyMarkdown`), which throw there: a path is an anchor, not
754
- * a read. An out-of-range `{card: 7, field: "from"}` extends the
755
- * unknown-kind root `edit::index_out_of_range` anchors at, rendering
756
- * `cards[7].from`, which parses back and resolves to nothing rather than
757
- * mis-targeting. So a per-keystroke call needs no `try`; a caller wanting
758
- * a drop-it guard has [`cardCount`](Self::card_count). Only a malformed
759
- * address throws.
672
+ * **Total on the index axis**, unlike the `Addr` reads, which throw there:
673
+ * an out-of-range `{card: 7, field: "from"}` renders `cards[7].from`, which
674
+ * parses back and resolves to nothing rather than mis-targeting. Only a
675
+ * malformed address throws.
760
676
  */
761
677
  pathFor(addr: Addr | string): string;
762
678
  /**
763
- * The canonical `$quill` reference grammar as author-facing text. Core is
764
- * the single source of truth: drive schema `describe` and validation
765
- * messages from this instead of re-stating the rule; it matches the
766
- * `hint` on `parse::invalid_quill_reference`. Cache it; the value never
767
- * changes.
679
+ * The canonical `$quill` reference grammar as author-facing text: the same
680
+ * text the `parse::invalid_quill_reference` hint carries. Drive validation
681
+ * messages from this instead of re-stating the rule.
768
682
  */
769
683
  static quillRefHint(): string;
770
684
  removeCard(index: number): Card | undefined;
771
685
  /**
772
- * Remove the `$ext` map on the card `addr` targets *entirely*, returning the
773
- * previous map or `undefined`: a blunt escape hatch that discards every
774
- * namespace at once (prefer `removeExtNamespace`). `addr` is a card address
775
- * (absent = main). Throws on a present `field` or an out-of-range card.
686
+ * Remove the `$ext` map on the card `addr` targets entirely, returning the
687
+ * previous map or `undefined`. Discards every namespace at once; prefer
688
+ * `removeExtNamespace`. Throws on a present `field` or an out-of-range card.
776
689
  */
777
690
  removeExt(addr?: CardAddr): Record<string, unknown> | undefined;
778
691
  /**
@@ -784,35 +697,31 @@ export class Document {
784
697
  removeExtNamespace(addr: CardAddr, ns: string): any;
785
698
  /**
786
699
  * Remove a field at `addr`, returning the removed value or `undefined`. A
787
- * bare string is `Addr` shorthand for `{ field }`. One `remove` verb serves
788
- * every write lane. A body address throws; throws on an out-of-range card or
789
- * a malformed name.
700
+ * bare string is `Addr` shorthand for `{ field }`. A body address throws, as
701
+ * does an out-of-range card or a malformed name.
790
702
  */
791
703
  removeField(addr: Addr | string): any;
792
704
  /**
793
- * Remove `cardKind` from the main card's `$seed` map, returning its
794
- * overlay or `undefined`; drops `$seed` entirely once empty. Sibling kinds
795
- * survive. `$seed` is main-only, so this takes no address.
705
+ * Remove `cardKind` from the main card's `$seed` map, returning its overlay
706
+ * or `undefined`; drops `$seed` entirely once empty. Sibling kinds survive.
796
707
  */
797
708
  removeSeedOverlay(card_kind: string): any;
798
709
  /**
799
- * **Revise** the richtext value at `addr` from a markdown string: **edit
800
- * semantics**, the default write path, returning the text `Delta`. Imports
801
- * the markdown, diffs it against the current value, rebases surviving
802
- * identity anchors, and returns the change an editor bridge maps its own
803
- * positions through (`mapPos`). An absent `addr.field` targets the body, an
804
- * absent `addr.card` the main card; an absent field cold-imports from empty.
710
+ * **Revise** the richtext value at `addr` from a markdown string: the
711
+ * default write path. Imports the markdown, diffs it against the current
712
+ * value, rebases surviving identity anchors, and returns the text `Delta` an
713
+ * editor bridge maps its own positions through (`mapPos`). An absent
714
+ * `addr.field` targets the body, an absent `addr.card` the main card; an
715
+ * absent field cold-imports from empty.
805
716
  *
806
717
  * Throws on an out-of-range card, a malformed field name, a present
807
718
  * non-content field value, or an over-nested markdown input.
808
719
  */
809
720
  revise(addr: Addr | string, markdown: string): Delta;
810
721
  /**
811
- * The main card's `$seed` overlay object for `kind` (the `$seed[kind]`
812
- * entry), or `undefined` when absent. The cheap read that feeds
813
- * `quill.seedCard(kind, overlay)` without serializing the whole main card
814
- * via [`main`](Self::main) to fish out one key, and it keeps `seedCard`
815
- * pure: the quill still never reads the document.
722
+ * The main card's `$seed[kind]` overlay object, or `undefined`. Feeds
723
+ * `quill.seedCard(kind, overlay)` without serializing the whole main card,
724
+ * and keeps `seedCard` pure: the quill never reads the document.
816
725
  */
817
726
  seedOverlay(kind: string): Record<string, unknown> | undefined;
818
727
  /**
@@ -826,78 +735,60 @@ export class Document {
826
735
  */
827
736
  setQuillRef(ref_str: string): void;
828
737
  /**
829
- * Read the storage version tag from a raw storage DTO string without a
830
- * full parse, or `undefined`. Returns unknown future versions as-is:
831
- * useful to distinguish "build too old" from "payload corrupt" when
832
- * `fromJson` throws.
833
- *
834
- * The storage version, not a field schema ([`schema`](Quill::schema) is the
835
- * quill's field declarations). The JSON key is spelled `"schema"`: it is
836
- * the DTO's serde tag, and retagging it would break the version dispatch
837
- * it drives.
738
+ * Read the storage version tag from a raw storage DTO string without a full
739
+ * parse, or `undefined`. Unknown future versions come back as-is, which
740
+ * distinguishes "build too old" from "payload corrupt" when `fromJson`
741
+ * throws. This is the storage version, not a field schema, though the JSON
742
+ * key is spelled `"schema"`: that is the DTO's serde tag.
838
743
  */
839
744
  static storageVersionOf(json: string): string | undefined;
840
745
  /**
841
- * Replace the opaque `$ext` map on the card `addr` targets (a card address,
842
- * absent `card` = main). `value` must be a plain object. `$ext` carries
843
- * out-of-band consumer state and never reaches the rendered output; pass
844
- * `{}` for an explicit empty `$ext`. Quill-free and verbatim: an opaque
845
- * `store` verb. Throws on a present `field` or an out-of-range card.
746
+ * Replace the opaque `$ext` map on the card `addr` targets (absent `card` =
747
+ * main). `value` must be a plain object. `$ext` carries out-of-band consumer
748
+ * state and never reaches the rendered output. Throws on a present `field`
749
+ * or an out-of-range card.
846
750
  */
847
751
  storeExt(addr: CardAddr, value: any): void;
848
752
  /**
849
753
  * Merge `value` into `$ext[ns]` on the card `addr` targets, preserving
850
- * sibling namespaces: the recommended `$ext` write. `addr` is a card
851
- * address (absent = main). Quill-free and verbatim: an opaque `store` verb.
852
- * Throws on a present `field` or an out-of-range card.
754
+ * sibling namespaces: the recommended `$ext` write. Throws on a present
755
+ * `field` or an out-of-range card.
853
756
  */
854
757
  storeExtNamespace(addr: CardAddr, ns: string, value: any): void;
855
758
  /**
856
- * Store a field verbatim at `addr`: the opaque store (**store** = verbatim,
857
- * coercion deferred to render; the typed write is
858
- * [`commitField`](Document::commit_field)). A bare string is `Addr`
859
- * shorthand for `{ field }`, so `doc.storeField("qty", 3)` reads as written;
860
- * `{ card: 2, field: "qty" }` targets a composable card. Clears any
861
- * `!must_fill` marker. A body address (no `field`) throws: a body is never
862
- * opaque; write it with `revise` / `overwrite` / `writer.reviseBody`. Throws on
863
- * an out-of-range card or a malformed name.
759
+ * Store a field verbatim at `addr`, deferring coercion to render; the typed
760
+ * write is [`commitField`](Document::commit_field). A bare string is `Addr`
761
+ * shorthand for `{ field }`; `{ card: 2, field: "qty" }` targets a
762
+ * composable card. Clears any `!must_fill` marker. A body address throws:
763
+ * write a body with `revise` / `overwrite`. Throws on an out-of-range card
764
+ * or a malformed name.
864
765
  */
865
766
  storeField(addr: Addr | string, value: any): void;
866
767
  /**
867
- * Store several fields verbatim and atomically on the card `addr` targets:
868
- * the opaque store's batch. `addr` is a **card address** (`{ card }`, absent
869
- * = main); a present `field` throws. The batch verb takes the address first
870
- * and is never shape-overloaded, because `card` is a legal field name:
871
- * `storeFields({}, fields)` is the main card, `storeFields({ card: 2 },
872
- * fields)` a composable one, never ambiguous with "set field `card`".
873
- * Nothing is applied on error; the thrown error's `diagnostics` carry one
874
- * entry per offending field. Throws on an out-of-range card.
768
+ * Store several fields verbatim and atomically on the card `addr` targets.
769
+ * `addr` is a **card address** (`{ card }`, absent = main) and comes first
770
+ * because `card` is itself a legal field name; a present `field` throws.
771
+ * Nothing is applied on error, and the thrown error's `diagnostics` carry
772
+ * one entry per offending field. Throws on an out-of-range card.
875
773
  */
876
774
  storeFields(addr: CardAddr, fields: Record<string, unknown>): void;
877
775
  /**
878
- * Store a field verbatim at `addr` and mark it `!must_fill`: the opaque
879
- * store's fill variant, card-capable (a bare string or `{ field }` for main,
880
- * `{ card, field }` for a composable card). A body address throws. Same
881
- * validation as [`storeField`](Document::store_field).
776
+ * Store a field verbatim at `addr` and mark it `!must_fill`. A body address
777
+ * throws; same validation as [`storeField`](Document::store_field).
882
778
  */
883
779
  storeFill(addr: Addr | string, value: any): void;
884
780
  /**
885
781
  * Merge a card-kind's seed `overlay` into the **main** card's `$seed` map
886
- * under `cardKind`, preserving sibling kinds: `$seed` lives on the main
887
- * card by model, so this takes no address. Sets the starting values new
888
- * cards of that kind spawn with. Quill-free and verbatim: an opaque `store`
889
- * verb. Throws if `overlay` cannot be serialized or nests too deep.
782
+ * under `cardKind`, preserving sibling kinds; `$seed` is main-only, so this
783
+ * takes no address. Sets the starting values new cards of that kind spawn
784
+ * with. Throws if `overlay` cannot be serialized or nests too deep.
890
785
  */
891
786
  storeSeedOverlay(card_kind: string, overlay: any): void;
892
787
  /**
893
- * Serialize this document to a versioned storage DTO string.
894
- *
895
- * Prefer this over `toMarkdown` for persistence across restarts or crate
896
- * upgrades: the wire format is frozen per `schema` version. Parse-time
897
- * `warnings` are excluded from the DTO.
898
- *
899
- * Output is **byte-deterministic** within a `schema` version: equal
900
- * documents produce byte-equal output, safe for content-hash use cases.
788
+ * Serialize this document to a versioned storage DTO string. Prefer it over
789
+ * `toMarkdown` for persistence: the wire format is frozen per `schema`
790
+ * version and the output is byte-deterministic within one, so equal
791
+ * documents hash equal. Parse-time `warnings` are excluded.
901
792
  */
902
793
  toJson(): string;
903
794
  /**
@@ -906,29 +797,26 @@ export class Document {
906
797
  */
907
798
  toMarkdown(): string;
908
799
  /**
909
- * Like [`fromJson`](Document::from_json) but returns `undefined` instead
910
- * of throwing when `json` is not a valid storage DTO: use to
911
- * discriminate format without exceptions as control flow.
912
- * `undefined` means "not a storage DTO"; `fromMarkdown` still throws on
913
- * genuinely malformed markdown.
800
+ * Like [`fromJson`](Document::from_json) but returns `undefined` instead of
801
+ * throwing when `json` is not a valid storage DTO, to discriminate format
802
+ * without exceptions as control flow.
914
803
  */
915
804
  static tryFromJson(json: string): Document | undefined;
916
805
  /**
917
- * Number of composable cards (excludes the main card). O(1).
806
+ * Number of composable cards, excluding the main card.
918
807
  */
919
808
  readonly cardCount: number;
920
809
  readonly cards: Card[];
921
810
  /**
922
- * The document's main (entry) card. Allocates and serializes on each
923
- * call: cache locally if read in a hot loop.
811
+ * The document's main (entry) card. Allocates and serializes on each call.
924
812
  */
925
813
  readonly main: Card;
926
814
  readonly quillRef: string;
927
815
  /**
928
816
  * The non-fatal diagnostics of the load that produced this document: parse
929
- * warnings, plus the `conform::*` warnings when it came through
930
- * `quill.parse`. Session state, not document value: `equals` and the
931
- * storage DTO exclude it, and `fromJson` / `loadJson` clear it.
817
+ * warnings, plus `conform::*` warnings when it came through `quill.parse`.
818
+ * Session state, not document value: `equals` and the storage DTO exclude
819
+ * it, and `fromJson` / `loadJson` clear it.
932
820
  */
933
821
  readonly warnings: Diagnostic[];
934
822
  }
@@ -939,196 +827,152 @@ export class Quill {
939
827
  [Symbol.dispose](): void;
940
828
  /**
941
829
  * Land `doc`'s declared content fields at their canonical rest **in
942
- * place**, returning the `conform::*` diagnostics for the values that would
943
- * not commit (an empty array when everything rested).
830
+ * place**, returning the `conform::*` diagnostics for values that would not
831
+ * commit. The read-repair verb for a document that arrived through the
832
+ * transport door (`fromMarkdown`, `fromJson`, a stored row).
944
833
  *
945
- * The read-repair verb: a document that arrived through the transport door
946
- * (`fromMarkdown`, `fromJson`, a stored row) converges here, and is then
947
- * eligible for rewrite under its current schema tag. Idempotent, and a
948
- * no-op on an already-canonical document: an equal value is not rewritten,
949
- * so YAML comments and stored bytes survive.
950
- *
951
- * A `!must_fill` marker anywhere in a field's value skips that field (the
952
- * marker is the state), and a value the strict write refuses stays as
953
- * authored with a diagnostic. Throws when `doc` declares a different
954
- * `$quill`, before any mutation.
834
+ * Idempotent: an equal value is not rewritten, so YAML comments and stored
835
+ * bytes survive. A `!must_fill` marker anywhere in a field's value skips
836
+ * that field, and a value the strict write refuses stays as authored with a
837
+ * diagnostic. Throws when `doc` declares a different `$quill`, before any
838
+ * mutation.
955
839
  */
956
840
  conform(doc: Document): Diagnostic[];
957
841
  /**
958
- * Build a quill from a file tree. Pure: no backend, no engine; the
959
- * declared backend is resolved later, at render time.
960
- *
961
- * Accepts either a `Map<string, Uint8Array>` or a plain object
962
- * (`Record<string, Uint8Array>`). Plain objects are walked via
963
- * `Object.entries` at the boundary; the Rust side sees a single
964
- * canonical shape.
842
+ * Build a quill from a file tree. Pure: the declared backend is resolved
843
+ * later, at render time. Accepts a `Map<string, Uint8Array>` or a plain
844
+ * object.
965
845
  */
966
846
  static fromTree(tree: Map<string, Uint8Array>): Quill;
967
847
  /**
968
- * Parse `markdown` and conform it against this quill: the **primary
969
- * ingestion path**, and the bound twin of the schema-free
970
- * `Document.fromMarkdown`. The returned document rests at its canonical
971
- * form (a `richtext` field as a content object, a `plaintext` field as its
972
- * literal string), so `getStored` answers "content object or string?" by the
973
- * field's declared codec rather than by how the document was built.
848
+ * Parse `markdown` and conform it against this quill: the primary ingestion
849
+ * path, and the bound twin of the schema-free `Document.fromMarkdown`. The
850
+ * returned document rests at its canonical form (a `richtext` field as a
851
+ * content object, a `plaintext` field as its literal string), so `getStored`
852
+ * answers by the field's declared codec, not by how the document was built.
974
853
  *
975
854
  * Parse warnings and the `conform::*` diagnostics both land on
976
855
  * `doc.warnings`. Throws on a parse failure, or when `markdown` declares a
977
- * `$quill` this quill does not answer to: nothing conforms under the wrong
978
- * schema. To open a document whose `$quill` is stale, use the transport
979
- * door (`Document.fromMarkdown`, `setQuillRef`, then `quill.conform`).
856
+ * `$quill` this quill does not answer to. To open a document whose `$quill`
857
+ * is stale, use `Document.fromMarkdown`, `setQuillRef`, then `quill.conform`.
980
858
  */
981
859
  parse(markdown: string): Document;
982
860
  /**
983
- * The resolved-value view of `doc` against this quill's schema: for every
984
- * declared field the value the render projection would use and the
985
- * `FieldSource` rung it came from (`"authored" | "default" | "zero"`), in
986
- * one call. The card body is a `body` sibling on its card (row `name`
987
- * `"body"`), never a row in `fields`: `null` when the kind enables no body.
988
- *
989
- * Value and provenance only: completeness and errors stay `validate`'s
990
- * (a consumer merges it with its own diagnostic producers regardless), and
991
- * schema guidance reads from `Quill.schema`.
861
+ * The resolved-value view of `doc`: for every declared field, the value the
862
+ * render projection would use and the `FieldSource` rung it came from
863
+ * (`"authored" | "default" | "blank"`). The card body is a `body` sibling on
864
+ * its card, never a row in `fields`, and `null` when the kind enables no
865
+ * body. Value and provenance only; completeness stays `validate`'s.
992
866
  */
993
867
  resolve(doc: Document): Resolved;
994
868
  /**
995
869
  * Seed a starter composable `Card` of the given kind (carries `$kind`),
996
- * layering an optional per-kind seed `overlay` over the schema-example
997
- * base (`overlay › example › absent`). Returns `undefined` if `cardKind`
998
- * is not declared in this quill's schema, else a `Card` that feeds
999
- * straight into `Document.insertCard`.
870
+ * layering an optional per-kind seed `overlay` over the schema-example base
871
+ * (`overlay › example › absent`). `undefined` when `cardKind` is not
872
+ * declared in this quill's schema.
1000
873
  *
1001
874
  * Pass `document.seedOverlay(cardKind)` as `overlay` so a card added to a
1002
875
  * template-derived document inherits its curated starting values; omit it
1003
- * (or pass `undefined` / `null`) for the bare schema seed. `overlay` is a
1004
- * plain object: this reads the document, it does not mutate it.
876
+ * for the bare schema seed.
1005
877
  */
1006
878
  seedCard(card_kind: string, overlay: Record<string, unknown> | undefined): Card | undefined;
1007
879
  /**
1008
- * Seed a starter `Document` from the schema, the main card plus one
1009
- * instance of each composable card kind, each committing its fields'
1010
- * `example:` values and leaving every other field absent (interpolated at
1011
- * render: `default:`, else type-empty zero). Illustration-first: a field
1012
- * with both an `example` and a `default` renders its example. See
1013
- * `prose/canon/SCHEMAS.md` § "Document seeding".
880
+ * Seed a starter `Document` from the schema: the main card plus one instance
881
+ * of each composable card kind, each committing its fields' `example:`
882
+ * values and leaving every other field absent (interpolated at render as
883
+ * `default:`, else the field's blank). A field with both renders its example.
1014
884
  */
1015
885
  seedDocument(): Document;
1016
886
  /**
1017
887
  * Seed a starter main `Card` (carries `$quill`) from the schema: the
1018
- * `$kind: main` card of [`seedDocument`](Self::seed_document) in
1019
- * isolation, committing each field's `example:` value. Returns the same
1020
- * `Card` shape as the `Document.main` getter.
888
+ * `$kind: main` card of [`seedDocument`](Self::seed_document) alone.
1021
889
  */
1022
890
  seedMain(): Card;
1023
891
  /**
1024
- * Flatten this quill back into its canonical file tree: the inverse of
1025
- * [`fromTree`](Self::from_tree). Round-trips: `Quill.fromTree(q.toTree())`
1026
- * reproduces an equivalent quill.
892
+ * Flatten this quill back into its canonical file tree, the inverse of
893
+ * [`fromTree`](Self::from_tree). Keys are `"/"`-joined relative paths.
1027
894
  *
1028
895
  * This is how a quill crosses a WASM linear-memory boundary as data: a
1029
- * `Quill` built in one build (e.g. the Typst-less `@quillmark/wasm/core`)
1030
- * cannot be passed to an engine in another (separate linear memories), so
896
+ * `Quill` built in one build cannot be passed to an engine in another, so
1031
897
  * `@quillmark/wasm/runtime` re-feeds this tree to the backend build's
1032
- * `Quill.fromTree` on demand. Keys are `"/"`-joined relative paths,
1033
- * matching what `fromTree` accepts.
898
+ * `Quill.fromTree` on demand.
1034
899
  */
1035
900
  toTree(): Map<string, Uint8Array>;
1036
901
  /**
1037
902
  * Validate `doc` against this quill's schema, returning every diagnostic
1038
- * (an empty array when the document is valid).
1039
- *
1040
- * Forwards the canonical `validation::*` diagnostics (same `code`,
1041
- * `path`, and `hint` the engine emits) including the non-fatal
1042
- * `validation::must_fill` warning for each `!must_fill` marker left in
1043
- * the document. Field values, defaults, and order are not part of this
1044
- * surface: read them from the `Document` payload and `Quill.schema`
1045
- * (schema key order is display order).
903
+ * (empty when the document is valid). Forwards the canonical
904
+ * `validation::*` diagnostics the engine emits, including the non-fatal
905
+ * `validation::must_fill` warning per `!must_fill` marker left behind.
1046
906
  */
1047
907
  validate(doc: Document): Diagnostic[];
1048
908
  /**
1049
- * The *declared* backend identifier (`config.backend`, e.g. `"typst"`).
1050
- * Intent, not a resolved capability: capability (`supportedFormats` /
1051
- * `supportsCanvas`) is read from the engine.
909
+ * The *declared* backend identifier (e.g. `"typst"`): intent, not a
910
+ * resolved capability. Capability is read from the engine.
1052
911
  */
1053
912
  readonly backendId: string;
1054
913
  readonly blueprint: string;
1055
914
  /**
1056
915
  * Identity snapshot of the `quill:` section of `Quill.yaml` plus any extra
1057
- * `quill:` keys. Pure config: the backend's output formats are a
1058
- * resolved-backend capability read from the engine
1059
- * (`Quillmark.supportedFormats`), not part of this snapshot.
916
+ * `quill:` keys. Pure config: output formats are a resolved-backend
917
+ * capability read from `Quillmark.supportedFormats`, not part of this.
1060
918
  */
1061
919
  readonly metadata: QuillMetadata;
1062
920
  /**
1063
- * Document schema for the quill: the user-fillable fields plus their
1064
- * `ui` hints (title / group / compact / multiline). The single
1065
- * field-metadata surface: drives form editors and LLM/MCP consumers
1066
- * alike. Key order in `fields`/`properties` is declaration order: the
1067
- * ordering contract. Returns the `QuillSchema` shape.
921
+ * Document schema for the quill: the user-fillable fields plus their `ui`
922
+ * hints. Key order in `fields`/`properties` is declaration order, the
923
+ * ordering contract.
1068
924
  */
1069
925
  readonly schema: QuillSchema;
1070
926
  }
1071
927
 
1072
928
  /**
1073
- * Export a canonical `Content` content to its markdown projection: the pure
1074
- * on-demand codec behind `exportMarkdown(card.body)`. Throws if `rt` is not a
929
+ * Export canonical `Content` to its markdown projection. Throws if `rt` is not
1075
930
  * canonical content.
1076
931
  */
1077
932
  export function exportMarkdown(rt: Content): string;
1078
933
 
1079
934
  /**
1080
935
  * Serialize structured [`DocPathSeg`] segments back to the canonical path
1081
- * string: the inverse of `parseDocPath`, for a consumer that builds a path
1082
- * rather than reads one. Throws on a segment array the deserializer rejects,
1083
- * and on an empty segment array (symmetric with `parseDocPath("")`, which
1084
- * throws "empty path").
936
+ * string: the inverse of `parseDocPath`. Throws on a segment array the
937
+ * deserializer rejects, and on an empty one.
1085
938
  */
1086
939
  export function formatDocPath(segs: DocPathSeg[]): string;
1087
940
 
1088
941
  /**
1089
- * Import a markdown string to a canonical `Content` content: the pure,
1090
- * document-free codec. Pair with `overwrite(addr, importMarkdown(md))` to spell
1091
- * the cold (anchor-losing) write at the call site; prefer `revise` for edit
1092
- * semantics. Throws on an over-nested input.
942
+ * Import a markdown string to canonical `Content`: the pure, document-free
943
+ * codec. `overwrite(addr, importMarkdown(md))` spells the cold, anchor-losing
944
+ * write; prefer `revise` for edit semantics. Throws on an over-nested input.
1093
945
  */
1094
946
  export function importMarkdown(markdown: string): Content;
1095
947
 
1096
948
  /**
1097
949
  * Map a base content position (a USV index into `Content.text`, not a UTF-16
1098
- * offset) through a `delta` to its new USV position: the pure position-mapping
1099
- * codec an editor bridge composes to hold a caret stable across a `revise`.
1100
- * `assoc` decides the side of a same-position insertion (`"after"` moves past
1101
- * it). Throws on a malformed `delta`.
950
+ * offset) through a `delta` to its new position, holding a caret stable across
951
+ * a `revise`. `assoc` decides the side of a same-position insertion (`"after"`
952
+ * moves past it). Throws on a malformed `delta`.
1102
953
  */
1103
954
  export function mapPos(delta: Delta, pos: number, assoc: Assoc): number;
1104
955
 
1105
956
  /**
1106
- * Parse a canonical document-model `Diagnostic.path`
1107
- * (`cards.<kind>[<i>].<field>`, `main.body`, `recipients[0].name`) into its
1108
- * structured [`DocPathSeg`] segments: the exported inverse of the engine's
1109
- * one path serializer, so a consumer routes on segments instead of regexing
1110
- * the string. Throws on a malformed path.
957
+ * Parse a canonical document-model `Diagnostic.path` (`cards.<kind>[<i>].<field>`,
958
+ * `main.body`, `recipients[0].name`) into structured [`DocPathSeg`] segments, so
959
+ * a consumer routes on segments instead of regexing the string. Throws on a
960
+ * malformed path.
1111
961
  */
1112
962
  export function parseDocPath(path: string): DocPathSeg[];
1113
963
 
1114
964
  /**
1115
- * Rebase `markdown` onto a `base` content, the pure, document-free twin of
1116
- * `revise`: cold-import + `diff_import`, returning the new `content` and the
1117
- * text `delta` (its offsets USV indices into `Content.text`, surviving anchors
1118
- * rebased). Use it to compute a revise without a document in hand; `revise(addr,
1119
- * md)` fuses this with the store for atomicity. Throws on an over-nested
1120
- * markdown input or a non-content `base`.
965
+ * Rebase `markdown` onto a `base` content: the document-free twin of `revise`,
966
+ * returning the new `content` and the text `delta` (offsets are USV indices into
967
+ * `Content.text`, surviving anchors rebased). Throws on an over-nested markdown
968
+ * input or a non-content `base`.
1121
969
  */
1122
970
  export function rebase(base: Content, markdown: string): { content: Content; delta: Delta };
1123
971
 
1124
972
  /**
1125
- * Runs at instantiation (the wasm-bindgen start section): installs the panic
1126
- * hook, so a Rust panic reaches the console as a stack trace rather than
1127
- * `unreachable`.
1128
- *
1129
- * Not the package's `init`. That name belongs to the hand-written runtime,
1130
- * which owns instantiation itself (`runtime/runtime.js`); this runs as part of
1131
- * the instantiation it awaits.
973
+ * Runs at instantiation, so a Rust panic reaches the console as a stack trace
974
+ * rather than `unreachable`. Not the package's `init` that name belongs to
975
+ * the hand-written runtime, which owns instantiation itself.
1132
976
  */
1133
977
  export function start(): void;
1134
978
 
@@ -1143,6 +987,7 @@ export interface InitOutput {
1143
987
  readonly document__commitFields: (a: number, b: number, c: number, d: number, e: number) => void;
1144
988
  readonly document__readerGet: (a: number, b: number, c: number, d: number) => void;
1145
989
  readonly document__readerGetContent: (a: number, b: number, c: number, d: number) => void;
990
+ readonly document__readerGetContentAt: (a: number, b: number, c: number, d: number, e: number) => void;
1146
991
  readonly document__reviseField: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
1147
992
  readonly document_applyChange: (a: number, b: number, c: number, d: number) => void;
1148
993
  readonly document_blueprintInstruction: (a: number, b: number, c: number) => void;