@quillmark/wasm 0.112.0 → 0.114.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.
@@ -17,7 +17,7 @@ export type PayloadItem =
17
17
  /**
18
18
  * Paths to `!must_fill` markers nested *inside* `value` (the `value`
19
19
  * projection itself is fill-free). Absent when the field has no nested
20
- * placeholders. Preserved across `insertCard` / `makeCard`.
20
+ * placeholders. Preserved across `insertCard`.
21
21
  */
22
22
  nestedFills?: PathStep[][];
23
23
  }
@@ -72,11 +72,10 @@ export interface Content {
72
72
  islands: ContentIsland[];
73
73
  }
74
74
 
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
- * Every role spells its payload in `attrs`, known or not, so promoting one moves
78
- * no bytes. The open arm blocks discriminant narrowing, so read
79
- * `attrs.level`/`attrs.lang` behind a check of the arm you want. */
75
+ /** One `\n`-separated segment of `Content.text`, in order. `kind` is a closed
76
+ * set: a role outside it is refused wherever content is decoded. Every role
77
+ * spells its payload in `attrs`, so `kind === "heading"` narrows `attrs` to
78
+ * `{ level: number }` with no guard. */
80
79
  export type ContentLine = {
81
80
  containers: ContentContainer[];
82
81
  /** A within-block hard line break rather than a new block. Omitted (false) in the common case. */
@@ -89,57 +88,50 @@ export type ContentLineKind =
89
88
  | { kind: "heading"; attrs: { level: number } }
90
89
  | { kind: "code"; attrs?: { lang?: string } }
91
90
  | { kind: "island" }
92
- | { kind: "rule" }
93
- | { kind: string; attrs?: unknown };
91
+ | { kind: "rule" };
94
92
 
95
- /** An ancestor block a line nests inside, outermost first. Open like
96
- * `ContentLine.kind`: an unrecognized container round-trips with opaque `attrs`
97
- * and renders transparently (its lines sit at the enclosing level).
93
+ /** An ancestor block a line nests inside, outermost first. Closed like
94
+ * `ContentLine.kind`.
98
95
  *
99
96
  * Two adjacent lines sit in the same container iff their whole path matches, so
100
97
  * `instance` is what tells one container from an adjacent sibling of identical
101
98
  * shape — two consecutive quotes, two consecutive lists — which contiguity
102
99
  * alone reads as one.
103
100
  *
104
- * **A writer owes a distinct value per adjacent sibling run**, not merely a
105
- * value. Runs of one shape sharing one arrive as one: a second list's items come
106
- * back as continuation paragraphs of the first, markers gone. The field is
107
- * required, so a checker reports the omission; it cannot report a `0` stamped on
108
- * both, which is the same write. A codec flattening a tree takes them from
109
- * `assignInstances` in `@quillmark/wasm/runtime` rather than by hand. Any
110
- * distinct pair works; a write is canonicalized to `0`/`1`.
101
+ * **A writer owes a distinct value per adjacent sibling run.** Runs of one shape
102
+ * sharing one arrive as one: a second list's items come back as continuation
103
+ * paragraphs of the first, markers gone. Nothing reports that — an omitted field
104
+ * and a `0` stamped on both are the same write so a codec flattening a tree
105
+ * takes them from `assignInstances` in `@quillmark/wasm` rather than by hand.
106
+ * Any distinct pair works; a write is canonicalized to `0`/`1`.
111
107
  *
112
- * Reading is not the mirror of writing. Every read spells the field, the `0` on
113
- * a container with nothing to be told apart from included. A read also carries a
114
- * discriminator on pairs no writer had to spell: `1.` beside a list starting at
115
- * `3` differs by `start`, so those runs arrive apart with nothing written, and
116
- * the canonical form spends one anyway because Markdown reads only a list's
117
- * first number.
118
- *
119
- * Content parsed from a stored document is the one shape that arrives without
120
- * it — storage omits a zero — and needs a cast. */
108
+ * Absent is `0`, and a read omits it there, so a container with nothing adjacent
109
+ * to be told apart from carries no key. A read does spell one on pairs no writer
110
+ * had to: `1.` beside a list starting at `3` differs by `start`, so those runs
111
+ * arrive apart with nothing written, and the canonical form spends a
112
+ * discriminator anyway because Markdown reads only a list's first number. */
121
113
  export type ContentContainer =
122
114
  | {
123
115
  container: "list_item";
124
116
  attrs: { ordered: boolean; start: number; ordinal: number };
125
- instance: number;
117
+ instance?: number;
126
118
  }
127
- | { container: "quote"; instance: number }
128
- | { container: string; attrs?: unknown; instance: number };
119
+ | { container: "quote"; instance?: number };
129
120
 
130
- /** A mark over char range `[start, end)` into `Content.text`. The open `type`
131
- * arm blocks discriminant narrowing, so read a payload-carrying arm behind its
132
- * guard: `isLinkMark` (`attrs.url`) / `isAnchorMark` (`attrs.id`), from
133
- * `@quillmark/wasm/runtime`. An `anchor`'s `id` is a caller-supplied opaque
121
+ /** A mark over char range `[start, end)` into `Content.text`. `type` is a
122
+ * closed set, so `type === "link"` narrows `attrs` to `{ url: string }` with no
123
+ * guard. An `anchor`'s `id` is a caller-supplied opaque
134
124
  * handle, unique per `Content` and invariant while the mark lives (positions
135
125
  * rebase, the id never does); it has no markdown projection and survives only
136
126
  * through the edit lane. */
137
- export type ContentMark = { start: number; end: number } & (
127
+ export type ContentMark = { start: number; end: number } & ContentMarkKind;
128
+
129
+ /** A mark's type with its payload, shared by `ContentMark` and a `MarkOp`'s
130
+ * `add` / `remove`. */
131
+ export type ContentMarkKind =
138
132
  | { type: "strong" | "emph" | "underline" | "strike" | "code" }
139
133
  | { type: "link"; attrs: { url: string } }
140
- | { type: "anchor"; attrs: { id: string } }
141
- | { type: string; attrs?: unknown }
142
- );
134
+ | { type: "anchor"; attrs: { id: string } };
143
135
 
144
136
  /** A cell in a `TableProps`. `marks` rides the prose `ContentMark` shape, but
145
137
  * each mark's `start`/`end` are USV offsets into this cell's `text`, not into
@@ -158,28 +150,25 @@ export interface TableProps {
158
150
  aligns: ("none" | "left" | "center" | "right")[];
159
151
  }
160
152
 
161
- /** `props` of a `type: "image"` island. */
153
+ /** `props` of a `type: "image"` island. Stores and round-trips; no backend
154
+ * typesets one, and a render that holds one warns `backend::declined_construct`,
155
+ * because what `url` names is undecided. */
162
156
  export interface ImageProps {
163
157
  url: string;
164
158
  alt: string;
165
159
  }
166
160
 
167
- /** How faithfully the markdown projection can carry an island. Open: an unknown
168
- * class round-trips verbatim and reads as `unrepresentable`. */
169
- export type ContentLossClass = "lossless" | "degraded" | "unrepresentable" | (string & {});
161
+ /** How faithfully the markdown projection can carry an island. */
162
+ export type ContentLossClass = "lossless" | "degraded" | "unrepresentable";
170
163
 
171
- /** A structured object occupying one island slot in `Content.text`. `type` is an
172
- * open set: `props` is `TableProps` for `table` and `ImageProps` for `image`,
173
- * and any other type round-trips with opaque `props`. The open arm blocks
174
- * narrowing, so read `props` behind the `isTableIsland` / `isImageIsland`
175
- * guards (from `@quillmark/wasm/runtime`). */
164
+ /** A structured object occupying one island slot in `Content.text`. `type` is a
165
+ * closed set, so `type === "table"` narrows `props` to `TableProps`. */
176
166
  export type ContentIsland = {
177
167
  id: string;
178
168
  loss: ContentLossClass;
179
169
  } & (
180
170
  | { type: "table"; props: TableProps }
181
171
  | { type: "image"; props: ImageProps }
182
- | { type: string; props: unknown }
183
172
  );
184
173
 
185
174
  /**
@@ -219,6 +208,10 @@ export interface CardAddr {
219
208
  * A text-splice change set over the USV content (CodeMirror `ChangeSet`
220
209
  * semantics), returned by `revise` and by the `rebase` codec. Map a stored
221
210
  * position through it with `mapPos`.
211
+ *
212
+ * Applying one admits an `insert` string rather than storing it verbatim: `\r`
213
+ * and the Unicode bidi controls drop, and a line separator — VT, FF, NEL,
214
+ * U+2028, U+2029 — becomes a space. Nothing reports the substitution.
222
215
  */
223
216
  export interface Delta {
224
217
  ops: ({ retain: number } | { insert: string } | { delete: number })[];
@@ -229,24 +222,25 @@ export type Assoc = "before" | "after";
229
222
 
230
223
  /**
231
224
  * A mark edit in final-text coordinates (post-delta, post-line-op). `add` /
232
- * `remove` carry the `ContentMark` vocabulary; `removeAnchor` drops one identity
233
- * anchor by id. An `add` of an `anchor` requires a non-empty `id` not already
234
- * live in the field; a collision or the empty id throws.
225
+ * `remove` are a `ContentMark` under an op, so a held mark spreads in whole;
226
+ * `removeAnchor` drops one identity anchor by id. An `add` of an `anchor`
227
+ * requires a non-empty `id` not already live in the field; a collision or the
228
+ * empty id throws.
235
229
  */
236
230
  export type MarkOp =
237
- | ({ op: "add" | "remove"; start: number; end: number } & (
238
- | { type: "strong" | "emph" | "underline" | "strike" | "code" }
239
- | { type: "link"; url: string }
240
- | { type: "anchor"; id: string }
241
- | { type: string; attrs: unknown }
242
- ))
231
+ | ({ op: "add" | "remove" } & ContentMark)
243
232
  | { op: "removeAnchor"; id: string };
244
233
 
245
234
  /**
246
235
  * A line/block edit. `split`/`join` splice `\n` in post-`delta`,
247
236
  * post-`islandOps` coordinates; `setKind`/`setContainers`/`setContinues` touch
248
237
  * metadata. `setContinues` sets or clears a line's within-block hard-break flag
249
- * (`ContentLine.continues`); `continues: true` on line 0 is rejected.
238
+ * (`ContentLine.continues`); `continues: true` lands as `false` on line 0, which
239
+ * nothing precedes, on a line whose containers differ from the line above, and
240
+ * on one following a heading, island or rule, each a block of one line.
241
+ * `setKind` lands a kind the line's text contradicts — `island` or `rule` over
242
+ * prose, `code` over a slot — as `para`, which is what re-importing the line's
243
+ * own markdown yields. Read the content back to see where an op settled.
250
244
  */
251
245
  export type LineOp =
252
246
  | { op: "split"; at: number }
@@ -277,11 +271,19 @@ export type LineOp =
277
271
  * A `set` stores the `loss` it is given; nothing re-derives the class from the
278
272
  * new `props`.
279
273
  *
280
- * An island is *inline* (a slot inside a paragraph) unless its line says
281
- * otherwise. A **block** island is one bundle of all three channels, in the
282
- * order they apply: `delta` inserts the `\n` that opens the line, `islandOps`
283
- * inserts the slot, `lineOps` tags the line `{ op: "setKind", kind: "island" }`.
284
- * `{ op: "split" }` cannot open that line, since line ops run after island ops.
274
+ * An island is *inline* (a slot inside a paragraph) or a **block** (that slot
275
+ * alone on a line under `kind: "island"`), and for a slot alone on a line the
276
+ * type settles which: markdown writes a `table` as a block and an image inline,
277
+ * so the line's `kind` is read off the type and a `setKind` spelling it
278
+ * otherwise does not survive. Landing a block island is one bundle of all three
279
+ * channels, in the order they apply: `delta` inserts the `\n` that opens the
280
+ * line, `islandOps` inserts the slot, `lineOps` tags the line
281
+ * `{ op: "setKind", kind: "island" }`. `{ op: "split" }` cannot open that line,
282
+ * since line ops run after island ops.
283
+ *
284
+ * A `table` has no inline placement: markdown writes it as a block, so an
285
+ * `insert` whose `at` is not an empty line throws, as does a `set` retyping an
286
+ * inline island into one.
285
287
  */
286
288
  export type IslandOp =
287
289
  | ({ op: "set" } & ContentIsland)
@@ -450,6 +452,11 @@ export interface QuillFieldUi {
450
452
  /** Label for an `enum`'s blank option. Absent, the consumer supplies a
451
453
  * conventional label of its own. */
452
454
  blank_title?: string;
455
+ /** The control the field asks for, where the shape admits more than one.
456
+ * A request, not a contract: a consumer that cannot draw it falls back to
457
+ * its own choice for the type. `"table"` is valid only on an `array`
458
+ * whose `items` is an `object`. */
459
+ layout?: "table";
453
460
  }
454
461
 
455
462
  /** One entry in a card's `ui.groups` registry: a display-label override for the
@@ -501,7 +508,7 @@ export interface QuillCardBody {
501
508
  * gates render: an absent field blank-fills.
502
509
  */
503
510
  export interface QuillFieldSchema {
504
- type: "string" | "number" | "integer" | "boolean" | "array" | "object" | "date" | "datetime" | "richtext" | "plaintext" | "enum";
511
+ type: "string" | "number" | "integer" | "boolean" | "array" | "object" | "date" | "datetime" | "richtext" | "plaintext" | "enum" | "matrix";
505
512
  description?: string;
506
513
  default?: unknown;
507
514
  example?: unknown;
@@ -513,14 +520,30 @@ export interface QuillFieldSchema {
513
520
  * member. Declaring it makes the field rest as a container,
514
521
  * `{value: <member>, …that member's fields}`, rather than a bare string. */
515
522
  variants?: Record<string, Record<string, QuillFieldSchema>>;
523
+ /** The roster of a `type: "matrix"` field, required there and valid
524
+ * nowhere else: the closed vocabulary a document ticks, in display order.
525
+ * Each member is an object of `held` plus the field's `properties`
526
+ * (the columns), addressed as `<field>.<member id>.held`. */
527
+ members?: QuillMatrixGroup[];
516
528
  ui?: QuillFieldUi;
517
529
  properties?: Record<string, QuillFieldSchema>;
518
530
  items?: QuillFieldSchema;
531
+ /** The element count past which an `array` overflows the page it is laid
532
+ * out on. Valid only on an `array`. Never gates render: a document over
533
+ * the cap warns `validation::cardinality` and renders. */
534
+ max?: number;
519
535
  /** `true` on a `richtext` or `plaintext` field declared `inline`: the
520
536
  * single-paragraph, container-free, island-free constraint. */
521
537
  inline?: boolean;
522
538
  }
523
539
 
540
+ /** One block of a `type: "matrix"` roster: an optional display heading and the
541
+ * members under it, member id to display title. Key order is display order. */
542
+ export interface QuillMatrixGroup {
543
+ group?: string;
544
+ values: Record<string, string>;
545
+ }
546
+
524
547
  /** Schema entry for the main card or a named card kind. */
525
548
  export interface QuillCardSchema {
526
549
  description?: string;
@@ -575,15 +598,9 @@ export interface ContentHit {
575
598
  }
576
599
 
577
600
  /**
578
- * A schema field address plus its geometry on the page, for scrolling to or
579
- * highlighting a field; use `LiveSession.fieldAt` for the click direction.
580
- *
581
- * `field` is **not** unique: content fields surface one region per segment
582
- * (paragraph, heading, whole code fence) and per page each touches, a scalar
583
- * referenced at several plate sites surfaces each site, and tracked content
584
- * plus a `field:`-bound widget yields both. Group by `field`. The whole-field
585
- * highlight is the union of a page's `span`-bearing rects, so inter-paragraph
586
- * whitespace stays uncovered; `LiveSession.fieldBoxes(field)` owns that union.
601
+ * A schema field address plus its geometry on the page. `field` is **not**
602
+ * unique, and the whole-field highlight is a union `LiveSession.fieldBoxes`
603
+ * owns: the consumer's copy of this contract is `runtime/runtime.d.ts`.
587
604
  */
588
605
  export interface FieldRegion {
589
606
  /**
@@ -608,8 +625,36 @@ export interface FieldRegion {
608
625
  }
609
626
 
610
627
  /**
611
- * Diagnostic message (error or warning)
628
+ * How precisely a `ContentHit.pos` resolved. Never sub-cluster: `cluster` is
629
+ * the finest this API offers, `segment` the floor it degrades to.
630
+ */
631
+ export type HitGranularity = "cluster" | "segment";
632
+
633
+ /**
634
+ * Output formats supported by backends. Gated behind the engine surface so
635
+ * tsify omits it from the core bundle, which has no rendering surface.
636
+ */
637
+ export type OutputFormat = "pdf" | "svg" | "png";
638
+
639
+ /**
640
+ * What a committed `LiveSession.update` changed. `dirtyPages` lists pages whose
641
+ * content differs from the previous compile, including pages the edit added;
642
+ * removed pages are implied by `pageCount`.
612
643
  */
644
+ export interface ChangeSet {
645
+ pageCount: number;
646
+ dirtyPages: number[];
647
+ }
648
+
649
+ export interface Artifact {
650
+ format: OutputFormat;
651
+ /**
652
+ * `serde_bytes` so the boundary emits a real `Uint8Array`, not `number[]`.
653
+ */
654
+ bytes: Uint8Array;
655
+ mimeType: string;
656
+ }
657
+
613
658
  export interface Diagnostic {
614
659
  severity: Severity;
615
660
  code?: string;
@@ -629,18 +674,14 @@ export interface Diagnostic {
629
674
  * `skip_serializing_if`, so an omitted field would be declared required.
630
675
  */
631
676
  args?: Record<string, unknown>;
632
- sourceChain?: string[];
633
677
  }
634
678
 
635
- /**
636
- * How precisely a `ContentHit.pos` resolved. Never sub-cluster: `cluster` is
637
- * the finest this API offers, `segment` the floor it degrades to.
638
- */
639
- export type HitGranularity = "cluster" | "segment";
679
+ export interface Location {
680
+ file: string;
681
+ line: number;
682
+ column: number;
683
+ }
640
684
 
641
- /**
642
- * Options for rendering.
643
- */
644
685
  export interface RenderOptions {
645
686
  format?: OutputFormat;
646
687
  /**
@@ -649,14 +690,10 @@ export interface RenderOptions {
649
690
  ppi?: number;
650
691
  /**
651
692
  * 0-based page indices to render; `undefined` renders all pages. An index
652
- * `>= pageCount` throws `typst::page_index_out_of_bounds`. Not supported
653
- * for PDF output: throws `typst::pdf_page_selection_not_supported`.
693
+ * `>= pageCount` throws `backend::page_index_out_of_bounds`. Not supported
694
+ * for PDF output: throws `backend::page_selection_not_supported`.
654
695
  */
655
696
  pages?: number[];
656
- /**
657
- * PDF `/Info` `/Producer` override; defaults to `Quillmark <version>`.
658
- */
659
- producer?: string;
660
697
  /**
661
698
  * Populate `RenderResult.regions` with schema-field geometry, for consumers
662
699
  * without a live session. Defaults to `false`. Page indices are
@@ -665,32 +702,10 @@ export interface RenderOptions {
665
702
  regions?: boolean;
666
703
  }
667
704
 
668
- /**
669
- * Output formats supported by backends. Gated behind the engine surface so
670
- * tsify omits it from the core bundle, which has no rendering surface.
671
- */
672
- export type OutputFormat = "pdf" | "svg" | "png";
673
-
674
- /**
675
- * Rendered artifact (PDF, SVG, etc.).
676
- */
677
- export interface Artifact {
678
- format: OutputFormat;
679
- /**
680
- * `serde_bytes` so the boundary emits a real `Uint8Array`, not `number[]`.
681
- */
682
- bytes: Uint8Array;
683
- mimeType: string;
684
- }
685
-
686
- /**
687
- * Result of a render operation.
688
- */
689
705
  export interface RenderResult {
690
706
  artifacts: Artifact[];
691
707
  warnings: Diagnostic[];
692
708
  outputFormat: OutputFormat;
693
- renderTimeMs: number;
694
709
  /**
695
710
  * Schema-field geometry, populated only when `RenderOptions.regions` asked
696
711
  * for it. Page indices are document-space even under a `pages` subset.
@@ -698,31 +713,9 @@ export interface RenderResult {
698
713
  regions: FieldRegion[];
699
714
  }
700
715
 
701
- /**
702
- * Source location for errors and warnings
703
- */
704
- export interface Location {
705
- file: string;
706
- line: number;
707
- column: number;
708
- }
709
-
710
- /**
711
- * What a committed `LiveSession.update` changed. `dirtyPages` lists pages whose
712
- * content differs from the previous compile, including pages the edit added;
713
- * removed pages are implied by `pageCount`.
714
- */
715
- export interface ChangeSet {
716
- pageCount: number;
717
- dirtyPages: number[];
718
- }
719
-
720
716
  export type Severity = "error" | "warning";
721
717
 
722
718
 
723
- /**
724
- * Typed in-memory Quillmark document.
725
- */
726
719
  export class Document {
727
720
  free(): void;
728
721
  [Symbol.dispose](): void;
@@ -744,8 +737,8 @@ export class Document {
744
737
  */
745
738
  applyChange(addr: Addr | string, bundle: ChangeBundle): void;
746
739
  /**
747
- * Authoring-ergonomics header introducing a blueprint to an LLM/MCP consumer
748
- * for the given `quillName`, re-exposed from core.
740
+ * A blueprint's fill obligation for the given `quillName`, re-exposed from
741
+ * core. Carries no tool name: pair it with your own next-step directive.
749
742
  */
750
743
  static blueprintInstruction(quill_name: string): string;
751
744
  /**
@@ -758,12 +751,6 @@ export class Document {
758
751
  * which interprets by declared type. An out-of-range `addr.card` throws.
759
752
  */
760
753
  bodyMarkdown(addr?: CardAddr): string;
761
- /**
762
- * A single composable card by index, so reading one need not materialize
763
- * every card via [`cards`](Self::cards). An out-of-range `index` throws
764
- * `edit::index_out_of_range`.
765
- */
766
- card(index: number): Card;
767
754
  /**
768
755
  * The composable card's own path, `cards.<kind>[index]`: the root
769
756
  * [`pathFor`](Self::path_for) extends, for anchoring the card rather than
@@ -771,9 +758,15 @@ export class Document {
771
758
  * `cards[index]`.
772
759
  */
773
760
  cardPath(index: number): string;
761
+ /**
762
+ * A single composable card by index, so reading one need not materialize
763
+ * every card via [`cards`](Self::cards). An out-of-range `index` throws
764
+ * `edit::index_out_of_range`.
765
+ */
766
+ card(index: number): Card;
774
767
  clone(): Document;
775
768
  /**
776
- * Storage version this build writes via [`toJson`](Document::to_json). The
769
+ * Storage version this build writes via [`toStored`](Document::to_stored). The
777
770
  * tag advances only when the wire format changes, not on every release.
778
771
  */
779
772
  static currentStorageVersion(): string;
@@ -781,27 +774,22 @@ export class Document {
781
774
  * Structural equality, excluding parse-time `warnings`.
782
775
  */
783
776
  equals(other: Document): boolean;
784
- /**
785
- * Render a Diagnostic as the canonical pretty-printed text, so it looks
786
- * identical whichever consumer surfaces it.
787
- */
788
- static formatDiagnostic(diag: Diagnostic): string;
789
777
  /**
790
778
  * Authoring-format rules for the card-yaml markdown surface, re-exposed from
791
779
  * core. Constant across calls; read once and cache.
792
780
  */
793
781
  static formatRules(): string;
782
+ /**
783
+ * Parse markdown into a typed Document. Throws on parse errors.
784
+ */
785
+ static fromMarkdown(markdown: string): Document;
794
786
  /**
795
787
  * Reconstruct a `Document` from a versioned storage DTO string produced by
796
- * [`toJson`](Document::to_json). The result carries no parse-time warnings.
788
+ * [`toStored`](Document::to_stored). The result carries no parse-time warnings.
797
789
  * Throws if `json` is not a valid storage DTO (malformed JSON, unknown
798
790
  * `schema`, missing fields, or unparseable quill reference).
799
791
  */
800
- static fromJson(json: string): Document;
801
- /**
802
- * Parse markdown into a typed Document. Throws on parse errors.
803
- */
804
- static fromMarkdown(markdown: string): Document;
792
+ static fromStored(json: string): Document;
805
793
  /**
806
794
  * The whole `$ext` map at `addr` (a card address, absent `card` = main), or
807
795
  * `undefined` when the card carries none: the `$ext` read that avoids
@@ -809,12 +797,6 @@ export class Document {
809
797
  * out-of-range card.
810
798
  */
811
799
  getExt(addr?: CardAddr): Record<string, unknown> | undefined;
812
- /**
813
- * The value stored under `$ext[ns]` at `addr` (a card address, absent `card`
814
- * = main), or `undefined`. Throws on a present `field` or an out-of-range
815
- * card.
816
- */
817
- getExtNamespace(addr: CardAddr, ns: string): unknown;
818
800
  /**
819
801
  * Read the **verbatim stored value** at `addr`: a field's raw payload value,
820
802
  * or the body content when `addr.field` is absent. A bare string is `Addr`
@@ -831,9 +813,8 @@ export class Document {
831
813
  * conformed, and this read reports what is there. For the `Content` either
832
814
  * way use `reader.getContent`.
833
815
  *
834
- * The body arm is typed `Content` and answers in the seam form, spelling
835
- * every `ContentContainer.instance`. A field arm echoes the stored bytes,
836
- * which omit a zero: verbatim is the contract, and is why it is `unknown`.
816
+ * The body arm is typed `Content`; a field arm echoes the stored bytes
817
+ * unread, which is the contract and why it is `unknown`.
837
818
  */
838
819
  getStored(addr: Addr | string): unknown;
839
820
  /**
@@ -851,26 +832,12 @@ export class Document {
851
832
  isFill(addr: Addr | string): boolean;
852
833
  /**
853
834
  * Replace this document's contents **in place** from a versioned storage DTO
854
- * string: the mutating twin of [`fromJson`](Document::from_json). Parse-time
855
- * `warnings` are cleared. Throws on an invalid DTO, leaving the document
856
- * unchanged.
857
- *
858
- * The cross-WASM-memory `Document` bridge: mutate a document on a
859
- * backend-memory clone, then write the state back into the caller's
860
- * canonical document, without the caller re-binding its variable.
861
- */
862
- loadJson(json: string): void;
863
- /**
864
- * Build a fresh `Card` from a kind and a flat field map: the ergonomic
865
- * constructor for `insertCard`, which also takes any `Card` object
866
- * directly. Each `fields` entry becomes a card field in insertion order;
867
- * `body` defaults to `""`.
868
- *
869
- * Checks only what a detached card can decide alone: field-name grammar and
870
- * value depth. Kind validity is positional, so `insertCard` is its gate and
871
- * any kind string is accepted here.
835
+ * string: the mutating twin of [`fromStored`](Document::from_stored).
836
+ * Parse-time `warnings` are cleared. Throws on an invalid DTO, leaving the
837
+ * document unchanged. A caller holding the document need not re-bind its
838
+ * variable.
872
839
  */
873
- static makeCard(kind: string, fields?: Record<string, unknown>, body?: string): Card;
840
+ loadStored(json: string): void;
874
841
  /**
875
842
  * Move the card at `from` to position `to`. `from == to` is a no-op.
876
843
  */
@@ -919,17 +886,10 @@ export class Document {
919
886
  removeCard(index: number): Card | undefined;
920
887
  /**
921
888
  * Remove the `$ext` map on the card `addr` targets entirely, returning the
922
- * previous map or `undefined`. Discards every namespace at once; prefer
923
- * `removeExtNamespace`. Throws on a present `field` or an out-of-range card.
889
+ * previous map or `undefined`. Discards every namespace at once. Throws on
890
+ * a present `field` or an out-of-range card.
924
891
  */
925
892
  removeExt(addr?: CardAddr): Record<string, unknown> | undefined;
926
- /**
927
- * Remove `$ext[ns]` on the card `addr` targets, returning its value or
928
- * `undefined`; drops `$ext` once empty. `addr` is a card address (absent =
929
- * main). Preserves sibling namespaces. Throws on a present `field` or an
930
- * out-of-range card.
931
- */
932
- removeExtNamespace(addr: CardAddr, ns: string): any;
933
893
  /**
934
894
  * Remove a field at `addr`, returning the removed value or `undefined`. A
935
895
  * bare string is `Addr` shorthand for `{ field }`. A body address throws, as
@@ -959,12 +919,6 @@ export class Document {
959
919
  * and keeps `seedCard` pure: the quill never reads the document.
960
920
  */
961
921
  seedOverlay(kind: string): Record<string, unknown> | undefined;
962
- /**
963
- * Replace the kind of the card at `index`. Payload and body are untouched;
964
- * schema-aware migration is the caller's responsibility.
965
- * Throws if `index` is out of range or `newKind` is invalid.
966
- */
967
- setCardKind(index: number, new_kind: string): void;
968
922
  /**
969
923
  * Replace the QUILL reference string. Throws if `ref_str` is invalid.
970
924
  */
@@ -972,7 +926,7 @@ export class Document {
972
926
  /**
973
927
  * Read the storage version tag from a raw storage DTO string without a full
974
928
  * parse, or `undefined`. Unknown future versions come back as-is, which
975
- * distinguishes "build too old" from "payload corrupt" when `fromJson`
929
+ * distinguishes "build too old" from "payload corrupt" when `fromStored`
976
930
  * throws. This is the storage version, not a field schema, though the JSON
977
931
  * key is spelled `"schema"`: that is the DTO's serde tag.
978
932
  */
@@ -980,16 +934,12 @@ export class Document {
980
934
  /**
981
935
  * Replace the opaque `$ext` map on the card `addr` targets (absent `card` =
982
936
  * main). `value` must be a plain object. `$ext` carries out-of-band consumer
983
- * state and never reaches the rendered output. Throws on a present `field`
984
- * or an out-of-range card.
937
+ * state and never reaches the rendered output. The whole map is the write,
938
+ * so a consumer holding one namespace merges the rest:
939
+ * `{...doc.getExt(addr), [ns]: v}`. Throws on a present `field` or an
940
+ * out-of-range card.
985
941
  */
986
942
  storeExt(addr: CardAddr, value: any): void;
987
- /**
988
- * Merge `value` into `$ext[ns]` on the card `addr` targets, preserving
989
- * sibling namespaces: the recommended `$ext` write. Throws on a present
990
- * `field` or an out-of-range card.
991
- */
992
- storeExtNamespace(addr: CardAddr, ns: string, value: any): void;
993
943
  /**
994
944
  * Store a field verbatim at `addr`, deferring coercion to render; the typed
995
945
  * write is [`commitField`](Document::commit_field). A bare string is `Addr`
@@ -1019,24 +969,18 @@ export class Document {
1019
969
  * with. Throws if `overlay` cannot be serialized or nests too deep.
1020
970
  */
1021
971
  storeSeedOverlay(card_kind: string, overlay: any): void;
1022
- /**
1023
- * Serialize this document to a versioned storage DTO string. Prefer it over
1024
- * `toMarkdown` for persistence: the wire format is frozen per `schema`
1025
- * version and the output is byte-deterministic within one, so equal
1026
- * documents hash equal. Parse-time `warnings` are excluded.
1027
- */
1028
- toJson(): string;
1029
972
  /**
1030
973
  * Emit canonical Quillmark Markdown. Round-trip safe: re-parsing the
1031
974
  * result produces a `Document` equal to `self` by value and by type.
1032
975
  */
1033
976
  toMarkdown(): string;
1034
977
  /**
1035
- * Like [`fromJson`](Document::from_json) but returns `undefined` instead of
1036
- * throwing when `json` is not a valid storage DTO, to discriminate format
1037
- * without exceptions as control flow.
978
+ * Serialize this document to a versioned storage DTO string. Prefer it over
979
+ * `toMarkdown` for persistence: the wire format is frozen per `schema`
980
+ * version and the output is byte-deterministic within one, so equal
981
+ * documents hash equal. Parse-time `warnings` are excluded.
1038
982
  */
1039
- static tryFromJson(json: string): Document | undefined;
983
+ toStored(): string;
1040
984
  /**
1041
985
  * Number of composable cards, excluding the main card.
1042
986
  */
@@ -1051,20 +995,20 @@ export class Document {
1051
995
  * The non-fatal diagnostics of the load that produced this document: parse
1052
996
  * warnings, plus `conform::*` warnings when it came through `quill.parse`.
1053
997
  * Session state, not document value: `equals` and the storage DTO exclude
1054
- * it, and `fromJson` / `loadJson` clear it.
998
+ * it, and `fromStored` / `loadStored` clear it.
1055
999
  */
1056
1000
  readonly warnings: Diagnostic[];
1057
1001
  }
1058
1002
 
1059
1003
  /**
1060
- * Live render session: every read serves the current compile. `apply(doc)`
1004
+ * Live render session: every read serves the current compile. `update(doc)`
1061
1005
  * recompiles a whole document in place, transactionally — on throw the reads
1062
1006
  * keep serving the last-good compile. Geometry is per-compile, so re-read it
1063
- * after each committed `apply`.
1007
+ * after each committed `update`.
1064
1008
  *
1065
1009
  * A zero-page document yields a valid session (`pageCount === 0`) whose
1066
- * `paint(ctx, 0)` and `pageSize(0)` throw; branch on `pageCount === 0` rather
1067
- * than catching.
1010
+ * `paint(ctx, 0)` and `pageSize(0)` throw as any out-of-range page does; branch
1011
+ * on `pageCount === 0` rather than catching.
1068
1012
  */
1069
1013
  export class LiveSession {
1070
1014
  private constructor();
@@ -1101,8 +1045,8 @@ export class LiveSession {
1101
1045
  */
1102
1046
  locate(field: string, pos: number): FieldRegion | undefined;
1103
1047
  /**
1104
- * Page dimensions in points (1 pt = 1/72 inch).
1105
- * Throws if the backend has no canvas painter or `page` is out of range.
1048
+ * Page dimensions in points (1 pt = 1/72 inch). Throws if `page` is out of
1049
+ * range, which a zero-page compile makes true of every index.
1106
1050
  */
1107
1051
  pageSize(page: number): PageSize;
1108
1052
  /**
@@ -1117,8 +1061,9 @@ export class LiveSession {
1117
1061
  * its own `<canvas>`: no compositing, sub-rect, or transform reaches through
1118
1062
  * this call.
1119
1063
  *
1120
- * Throws if the backend has no canvas painter, `page` is out of range, `ctx`
1121
- * is the wrong type, or either scale is non-finite or `<= 0`.
1064
+ * Throws if `page` is out of range, `ctx` is the wrong type, either scale is
1065
+ * non-finite or `<= 0`, or the page cannot be rasterized at the resulting
1066
+ * scale (`backend::invalid_raster_scale`).
1122
1067
  */
1123
1068
  paint(ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, page: number, opts: PaintOptions | undefined): PaintResult;
1124
1069
  /**
@@ -1159,13 +1104,9 @@ export class LiveSession {
1159
1104
  */
1160
1105
  readonly backendId: string;
1161
1106
  readonly pageCount: number;
1162
- /**
1163
- * `true` iff `paint` and `pageSize` will succeed for this session.
1164
- */
1165
- readonly supportsCanvas: boolean;
1166
1107
  /**
1167
1108
  * Non-fatal diagnostics of the session's **current compile**, refreshed by
1168
- * each committed `apply`; a failed apply keeps the last-good compile's.
1109
+ * each committed `update`; a failed `update` keeps the last-good compile's.
1169
1110
  * Also appended to `RenderResult.warnings` on each `render()`.
1170
1111
  */
1171
1112
  readonly warnings: Diagnostic[];
@@ -1179,7 +1120,7 @@ export class Quill {
1179
1120
  * Land `doc`'s declared content fields at their canonical rest **in
1180
1121
  * place**, returning the `conform::*` diagnostics for values that would not
1181
1122
  * commit. The read-repair verb for a document that arrived through the
1182
- * transport door (`fromMarkdown`, `fromJson`, a stored row).
1123
+ * transport door (`fromMarkdown`, `fromStored`, a stored row).
1183
1124
  *
1184
1125
  * Idempotent: an equal value is not rewritten, so YAML comments and stored
1185
1126
  * bytes survive. A `!must_fill` marker anywhere in a field's value skips
@@ -1207,14 +1148,6 @@ export class Quill {
1207
1148
  * is stale, use `Document.fromMarkdown`, `setQuillRef`, then `quill.conform`.
1208
1149
  */
1209
1150
  parse(markdown: string): Document;
1210
- /**
1211
- * The resolved-value view of `doc`: for every declared field, the value the
1212
- * render projection would use and the `FieldSource` rung it came from
1213
- * (`"authored" | "default" | "blank"`). The card body is a `body` sibling on
1214
- * its card, never a row in `fields`, and `null` when the kind enables no
1215
- * body. Value and provenance only; completeness stays `validate`'s.
1216
- */
1217
- resolve(doc: Document): Resolved;
1218
1151
  /**
1219
1152
  * Seed a starter composable `Card` of the given kind (carries `$kind`),
1220
1153
  * layering an optional per-kind seed `overlay` over the schema-example base
@@ -1244,8 +1177,8 @@ export class Quill {
1244
1177
  *
1245
1178
  * This is how a quill crosses a WASM linear-memory boundary as data: a
1246
1179
  * `Quill` built in one build cannot be passed to an engine in another, so
1247
- * `@quillmark/wasm/runtime` re-feeds this tree to the backend build's
1248
- * `Quill.fromTree` on demand.
1180
+ * the `@quillmark/wasm` runtime layer re-feeds this tree to the backend
1181
+ * build's `Quill.fromTree` on demand.
1249
1182
  */
1250
1183
  toTree(): Map<string, Uint8Array>;
1251
1184
  /**
@@ -1262,9 +1195,9 @@ export class Quill {
1262
1195
  readonly backendId: string;
1263
1196
  readonly blueprint: string;
1264
1197
  /**
1265
- * Identity snapshot of the `quill:` section of `Quill.yaml` plus any extra
1266
- * `quill:` keys. Pure config: output formats are a resolved-backend
1267
- * capability read from `Quillmark.supportedFormats`, not part of this.
1198
+ * Identity snapshot of the `quill:` section of `Quill.yaml`. Pure config:
1199
+ * output formats are a resolved-backend capability read from
1200
+ * `Quillmark.supportedFormats`, not part of this.
1268
1201
  */
1269
1202
  readonly metadata: QuillMetadata;
1270
1203
  /**
@@ -1273,6 +1206,12 @@ export class Quill {
1273
1206
  * ordering contract.
1274
1207
  */
1275
1208
  readonly schema: QuillSchema;
1209
+ /**
1210
+ * The advisory diagnostics of the load that produced this quill: what is
1211
+ * wrong with it short of refusing it. A quill that loads clean answers
1212
+ * `[]`.
1213
+ */
1214
+ readonly warnings: Diagnostic[];
1276
1215
  }
1277
1216
 
1278
1217
  /**
@@ -1299,12 +1238,6 @@ export class Quillmark {
1299
1238
  * backend matches the quill's declared one.
1300
1239
  */
1301
1240
  supportedFormats(quill: Quill): OutputFormat[];
1302
- /**
1303
- * Whether `quill`'s backend can paint sessions to a canvas; `false` when the
1304
- * backend is unsupported. A cheap probe before mounting a preview UI. The
1305
- * authoritative answer is the session's `supportsCanvas` getter.
1306
- */
1307
- supportsCanvas(quill: Quill): boolean;
1308
1241
  }
1309
1242
 
1310
1243
  /**
@@ -1313,6 +1246,19 @@ export class Quillmark {
1313
1246
  */
1314
1247
  export function exportMarkdown(rt: Content): string;
1315
1248
 
1249
+ /**
1250
+ * Render a diagnostic as the CLI and Python's `str(diagnostic)` render it:
1251
+ * the severity tag and the message, the code parenthesised after them, then
1252
+ * location, path and hint each on an indented line of its own. The engine
1253
+ * owns the one printer, so a consumer surfacing diagnostics reads it here
1254
+ * rather than keeping a copy of the layout that drifts from the CLI's.
1255
+ *
1256
+ * Takes the `Diagnostic` shape every read hands back. Throws on a value that
1257
+ * is not one — a missing `severity` or `message`, or a `severity` outside the
1258
+ * two-value ladder.
1259
+ */
1260
+ export function formatDiagnostic(diagnostic: Diagnostic): string;
1261
+
1316
1262
  /**
1317
1263
  * Serialize structured [`DocPathSeg`] segments back to the canonical path
1318
1264
  * string: the inverse of `parseDocPath`. Throws on a segment array the
@@ -1403,18 +1349,15 @@ export interface InitOutput {
1403
1349
  readonly document_clone: (a: number) => number;
1404
1350
  readonly document_currentStorageVersion: (a: number) => void;
1405
1351
  readonly document_equals: (a: number, b: number) => number;
1406
- readonly document_formatDiagnostic: (a: number, b: number) => void;
1407
1352
  readonly document_formatRules: (a: number) => void;
1408
- readonly document_fromJson: (a: number, b: number, c: number) => void;
1409
1353
  readonly document_fromMarkdown: (a: number, b: number, c: number) => void;
1354
+ readonly document_fromStored: (a: number, b: number, c: number) => void;
1410
1355
  readonly document_getExt: (a: number, b: number, c: number) => void;
1411
- readonly document_getExtNamespace: (a: number, b: number, c: number, d: number, e: number) => void;
1412
1356
  readonly document_getStored: (a: number, b: number, c: number) => void;
1413
1357
  readonly document_insertCard: (a: number, b: number, c: number, d: number) => void;
1414
1358
  readonly document_isFill: (a: number, b: number, c: number) => void;
1415
- readonly document_loadJson: (a: number, b: number, c: number, d: number) => void;
1359
+ readonly document_loadStored: (a: number, b: number, c: number, d: number) => void;
1416
1360
  readonly document_main: (a: number, b: number) => void;
1417
- readonly document_makeCard: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
1418
1361
  readonly document_moveCard: (a: number, b: number, c: number, d: number) => void;
1419
1362
  readonly document_new: (a: number, b: number, c: number) => void;
1420
1363
  readonly document_overwrite: (a: number, b: number, c: number, d: number) => void;
@@ -1423,61 +1366,57 @@ export interface InitOutput {
1423
1366
  readonly document_quillRefHint: (a: number) => void;
1424
1367
  readonly document_removeCard: (a: number, b: number, c: number) => void;
1425
1368
  readonly document_removeExt: (a: number, b: number, c: number) => void;
1426
- readonly document_removeExtNamespace: (a: number, b: number, c: number, d: number, e: number) => void;
1427
1369
  readonly document_removeField: (a: number, b: number, c: number) => void;
1428
1370
  readonly document_removeSeedOverlay: (a: number, b: number, c: number, d: number) => void;
1429
1371
  readonly document_revise: (a: number, b: number, c: number, d: number, e: number) => void;
1430
1372
  readonly document_seedOverlay: (a: number, b: number, c: number, d: number) => void;
1431
- readonly document_setCardKind: (a: number, b: number, c: number, d: number, e: number) => void;
1432
1373
  readonly document_setQuillRef: (a: number, b: number, c: number, d: number) => void;
1433
1374
  readonly document_storageVersionOf: (a: number, b: number, c: number) => void;
1434
1375
  readonly document_storeExt: (a: number, b: number, c: number, d: number) => void;
1435
- readonly document_storeExtNamespace: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
1436
1376
  readonly document_storeField: (a: number, b: number, c: number, d: number) => void;
1437
1377
  readonly document_storeFields: (a: number, b: number, c: number, d: number) => void;
1438
1378
  readonly document_storeFill: (a: number, b: number, c: number, d: number) => void;
1439
1379
  readonly document_storeSeedOverlay: (a: number, b: number, c: number, d: number, e: number) => void;
1440
- readonly document_toJson: (a: number, b: number) => void;
1441
1380
  readonly document_toMarkdown: (a: number, b: number) => void;
1442
- readonly document_tryFromJson: (a: number, b: number) => number;
1381
+ readonly document_toStored: (a: number, b: number) => void;
1443
1382
  readonly document_warnings: (a: number, b: number) => void;
1444
1383
  readonly exportMarkdown: (a: number, b: number) => void;
1384
+ readonly formatDiagnostic: (a: number, b: number) => void;
1445
1385
  readonly formatDocPath: (a: number, b: number) => void;
1446
1386
  readonly importMarkdown: (a: number, b: number, c: number) => void;
1447
1387
  readonly livesession_backendId: (a: number, b: number) => void;
1448
1388
  readonly livesession_fieldAt: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
1449
1389
  readonly livesession_fieldBoxes: (a: number, b: number, c: number, d: number) => void;
1450
- readonly livesession_locate: (a: number, b: number, c: number, d: number) => number;
1390
+ readonly livesession_locate: (a: number, b: number, c: number, d: number, e: number) => void;
1451
1391
  readonly livesession_pageCount: (a: number) => number;
1452
1392
  readonly livesession_pageSize: (a: number, b: number, c: number) => void;
1453
1393
  readonly livesession_paint: (a: number, b: number, c: number, d: number, e: number) => void;
1454
- readonly livesession_positionAt: (a: number, b: number, c: number, d: number, e: number) => number;
1394
+ readonly livesession_positionAt: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
1455
1395
  readonly livesession_regions: (a: number, b: number) => void;
1456
1396
  readonly livesession_render: (a: number, b: number, c: number) => void;
1457
- readonly livesession_supportsCanvas: (a: number) => number;
1458
1397
  readonly livesession_update: (a: number, b: number, c: number) => void;
1459
1398
  readonly livesession_warnings: (a: number, b: number) => void;
1460
1399
  readonly mapMarks: (a: number, b: number, c: number) => void;
1461
1400
  readonly mapPos: (a: number, b: number, c: number, d: number) => void;
1462
1401
  readonly parseDocPath: (a: number, b: number, c: number) => void;
1402
+ readonly quill__resolve: (a: number, b: number, c: number) => void;
1463
1403
  readonly quill_backendId: (a: number, b: number) => void;
1464
1404
  readonly quill_blueprint: (a: number, b: number) => void;
1465
1405
  readonly quill_conform: (a: number, b: number, c: number) => void;
1466
1406
  readonly quill_fromTree: (a: number, b: number) => void;
1467
1407
  readonly quill_metadata: (a: number, b: number) => void;
1468
1408
  readonly quill_parse: (a: number, b: number, c: number, d: number) => void;
1469
- readonly quill_resolve: (a: number, b: number, c: number) => void;
1470
1409
  readonly quill_schema: (a: number, b: number) => void;
1471
1410
  readonly quill_seedCard: (a: number, b: number, c: number, d: number, e: number) => void;
1472
1411
  readonly quill_seedDocument: (a: number) => number;
1473
1412
  readonly quill_seedMain: (a: number, b: number) => void;
1474
1413
  readonly quill_toTree: (a: number) => number;
1475
1414
  readonly quill_validate: (a: number, b: number, c: number) => void;
1415
+ readonly quill_warnings: (a: number, b: number) => void;
1476
1416
  readonly quillmark_new: () => number;
1477
1417
  readonly quillmark_open: (a: number, b: number, c: number, d: number) => void;
1478
1418
  readonly quillmark_render: (a: number, b: number, c: number, d: number, e: number) => void;
1479
1419
  readonly quillmark_supportedFormats: (a: number, b: number, c: number) => void;
1480
- readonly quillmark_supportsCanvas: (a: number, b: number) => number;
1481
1420
  readonly rebase: (a: number, b: number, c: number, d: number) => void;
1482
1421
  readonly start: () => void;
1483
1422
  readonly __wbindgen_export: (a: number, b: number) => number;