@quillmark/wasm 0.92.1 → 0.95.1

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.
@@ -0,0 +1,1066 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /**
5
+ * A path to a value nested inside a field `value`: `string` keys and
6
+ * `number` array indices, e.g. `["addr", "street"]` or `["recipients", 0, "name"]`.
7
+ */
8
+ export type PathStep = string | number;
9
+
10
+ /** A field or comment entry in a `Card.payloadItems` list. */
11
+ export type PayloadItem =
12
+ | {
13
+ type: "field";
14
+ key: string;
15
+ value: unknown;
16
+ fill?: boolean;
17
+ /**
18
+ * Paths to `!must_fill` markers nested *inside* `value` (the `value`
19
+ * projection itself is fill-free). Absent when the field has no nested
20
+ * placeholders. Preserved across `insertCard` / `makeCard`.
21
+ */
22
+ nestedFills?: PathStep[][];
23
+ }
24
+ | { type: "comment"; text: string; inline?: boolean };
25
+
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.
32
+ *
33
+ * `$` 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 `id` (`$id`), 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.
38
+ */
39
+ export interface Card {
40
+ kind: string;
41
+ quill?: string;
42
+ id?: string;
43
+ ext?: Record<string, unknown>;
44
+ seed?: Record<string, unknown>;
45
+ payloadItems: PayloadItem[];
46
+ /**
47
+ * The card body as canonical `Content` — the source-of-truth content model.
48
+ * Always this content shape on read, never a markdown string. For the markdown
49
+ * projection call the codec `exportMarkdown(card.body)`. Write a body back
50
+ * with `doc.install(addr, rt)` / `doc.revise(addr, md)`, or via `CardInput.body`.
51
+ */
52
+ body: Content;
53
+ }
54
+
55
+ /**
56
+ * A card written *into* a document — the input twin of `Card`, accepted by
57
+ * `Document.insertCard`. Like `Card` but `body` also
58
+ * takes a markdown `string` (imported to the content, so a markdown / LLM writer
59
+ * needn't build the `Content` shape), and every field but `kind` is optional —
60
+ * an absent field defaults (no payload items, an empty body). Write one inline
61
+ * (`{ kind, body }`) or build it with `Document.makeCard`.
62
+ */
63
+ export interface CardInput {
64
+ kind: string;
65
+ quill?: string;
66
+ id?: string;
67
+ ext?: Record<string, unknown>;
68
+ seed?: Record<string, unknown>;
69
+ payloadItems?: PayloadItem[];
70
+ body?: Content | string;
71
+ }
72
+
73
+ /**
74
+ * Canonical richtext content — the content model for a card body (and richtext
75
+ * fields). One text sequence over a single coordinate space (Unicode scalar
76
+ * values): `text` plus line attributes, anchored `marks`, and embedded
77
+ * `islands`. Every edit is a splice; markdown is a projection, not the model.
78
+ * Mirrors `quillmark_content::serial`'s canonical JSON encoding.
79
+ */
80
+ export interface Content {
81
+ text: string;
82
+ lines: ContentLine[];
83
+ marks: ContentMark[];
84
+ islands: ContentIsland[];
85
+ }
86
+
87
+ /** One `\n`-separated segment of `Content.text`, in order. */
88
+ export type ContentLine = {
89
+ containers: ContentContainer[];
90
+ /** A within-block hard line break rather than a new block. Omitted (false) in the common case. */
91
+ continues?: boolean;
92
+ } & (
93
+ | { kind: "para" }
94
+ | { kind: "heading"; level: number }
95
+ | { kind: "code"; lang?: string }
96
+ | { kind: "island" }
97
+ | { kind: "rule" }
98
+ );
99
+
100
+ /** An ancestor block a line nests inside, outermost first. */
101
+ export type ContentContainer =
102
+ | { container: "list_item"; ordered: boolean; start: number; ordinal: number }
103
+ | { container: "quote" };
104
+
105
+ /** A mark over char range `[start, end)` into `Content.text`. */
106
+ export type ContentMark = { start: number; end: number } & (
107
+ | { type: "strong" | "emph" | "underline" | "strike" | "code" }
108
+ | { type: "link"; url: string }
109
+ | { type: "anchor"; id: string }
110
+ | { type: string; attrs: unknown }
111
+ );
112
+
113
+ /** A structured object (table, figure, …) occupying one island slot in `Content.text`. */
114
+ export interface ContentIsland {
115
+ id: string;
116
+ type: string;
117
+ props: unknown;
118
+ /** How faithfully the markdown projection can carry this island. */
119
+ loss: "lossless" | "degraded" | "unrepresentable";
120
+ }
121
+
122
+ /**
123
+ * A write address — one navigation concept for the whole `Document` surface. An
124
+ * absent `field` targets the card body; an absent `card` targets the main card.
125
+ * `{}` is the main-card body; `{ card: 2 }` the body of the composable card at
126
+ * index 2; `{ field: "intro" }` the main card's `intro` field; `{ card: 2,
127
+ * field: "intro" }` a card field.
128
+ *
129
+ * On the `Addr`-taking verbs a **bare string** is shorthand for `{ field: name }`
130
+ * — `doc.storeField("qty", 3)`, `doc.revise("intro", md)` — the one coercion
131
+ * rule. A bare number is *not* an addr (`{ card: 2 }` is the self-documenting
132
+ * spelling), so no third navigation idiom re-fragments the surface.
133
+ */
134
+ export interface Addr {
135
+ card?: number;
136
+ field?: string;
137
+ }
138
+
139
+ /**
140
+ * A card-only address — the axis the card-scoped verbs (`storeFields`,
141
+ * `storeExt`, `getExt`, `commitFields`, …) take. An absent `card` targets the
142
+ * main card. A present `field` throws: a card address takes only `card`, and a
143
+ * would-be nested write is a bug the error names rather than silently ignores.
144
+ */
145
+ export interface CardAddr {
146
+ card?: number;
147
+ }
148
+
149
+ /**
150
+ * A text-splice change set over the USV content (CodeMirror `ChangeSet`
151
+ * semantics) — plain, structured-clone-able data. Returned by `revise` and by
152
+ * the `rebase` codec; map a stored position through it with `mapPos`.
153
+ */
154
+ export interface Delta {
155
+ ops: ({ retain: number } | { insert: string } | { delete: number })[];
156
+ }
157
+
158
+ /** Which side of a same-position insertion `mapPos` lands a point on. */
159
+ export type Assoc = "before" | "after";
160
+
161
+ /**
162
+ * A mark edit in final-text coordinates (post-delta, post-line-op). `add` /
163
+ * `remove` carry the `ContentMark` vocabulary (`{ type, … }`); `removeAnchor`
164
+ * drops one identity anchor by id.
165
+ */
166
+ export type MarkOp =
167
+ | ({ op: "add" | "remove"; start: number; end: number } & (
168
+ | { type: "strong" | "emph" | "underline" | "strike" | "code" }
169
+ | { type: "link"; url: string }
170
+ | { type: "anchor"; id: string }
171
+ | { type: string; attrs: unknown }
172
+ ))
173
+ | { op: "removeAnchor"; id: string };
174
+
175
+ /**
176
+ * A line/block edit. `split`/`join` splice `\n`; `setKind`/`setContainers`/
177
+ * `setContinues` touch metadata. `setContinues` sets/clears a line's within-block
178
+ * hard-break flag (`ContentLine.continues`) — the op-grained way to lower a
179
+ * Shift+Enter hard break or a new code-fence interior line; `continues: true` on
180
+ * line 0 is rejected (nothing precedes it to continue).
181
+ */
182
+ export type LineOp =
183
+ | { op: "split"; at: number }
184
+ | { op: "join"; line: number }
185
+ | ({ op: "setKind"; line: number } & (
186
+ | { kind: "para" | "island" | "rule" }
187
+ | { kind: "heading"; level: number }
188
+ | { kind: "code"; lang?: string }
189
+ ))
190
+ | { op: "setContainers"; line: number; containers: ContentContainer[] }
191
+ | { op: "setContinues"; line: number; continues: boolean };
192
+
193
+ /**
194
+ * A committed content edit bundle for `applyChange`: a text `delta` (default no
195
+ * text change), then `lineOps`, then `markOps` (mark ranges are in post-delta
196
+ * coordinates). Every field is optional.
197
+ */
198
+ export interface ChangeBundle {
199
+ delta?: Delta;
200
+ lineOps?: LineOp[];
201
+ markOps?: MarkOp[];
202
+ }
203
+
204
+
205
+
206
+ /**
207
+ * Page dimensions in points (1 pt = 1/72 inch). Typst measures in Typst
208
+ * points; pdfform measures in PDF points — the same unit.
209
+ *
210
+ * Report-only: the painter sizes the canvas itself based on
211
+ * `PaintOptions`. `pageSize` is exposed for callers that need page
212
+ * geometry up-front (e.g. to lay out a scrollable list of canvases
213
+ * before any pixels are rendered).
214
+ */
215
+ export interface PageSize {
216
+ widthPt: number;
217
+ heightPt: number;
218
+ }
219
+
220
+ /**
221
+ * Inputs to `LiveSession.paint`. Both fields are optional and default
222
+ * to `1`.
223
+ *
224
+ * - `layoutScale` — layout-space pixels per point (Typst point / PDF
225
+ * point — the same 1/72″ unit). For on-screen
226
+ * canvases this is CSS pixels per pt; the page's layout-pixel size is
227
+ * `widthPt * layoutScale × heightPt * layoutScale`. The painter
228
+ * surfaces these dimensions as `layoutWidth` / `layoutHeight` so
229
+ * consumers can drive `canvas.style.*` (or any layout system).
230
+ * - `densityScale` — backing-store density multiplier. Fold
231
+ * `window.devicePixelRatio`, in-app zoom, and `visualViewport.scale`
232
+ * (pinch-zoom) into a single value here. Defaults to `1`, which
233
+ * produces a non-retina backing store — pass `window.devicePixelRatio`
234
+ * for crisp output on high-DPI displays.
235
+ *
236
+ * The effective rasterization scale is `layoutScale * densityScale`.
237
+ * Both must be finite and `> 0`. For `OffscreenCanvasRenderingContext2D`
238
+ * the two collapse to a single scalar; folding everything into
239
+ * `densityScale` is the simplest convention.
240
+ */
241
+ export interface PaintOptions {
242
+ layoutScale?: number;
243
+ densityScale?: number;
244
+ }
245
+
246
+ /**
247
+ * Returned by `LiveSession.paint`.
248
+ *
249
+ * - `layoutWidth` / `layoutHeight` — layout-pixel dimensions of the
250
+ * canvas's display box. For on-screen canvases this is CSS pixels:
251
+ * set `canvas.style.width = layoutWidth + "px"` and
252
+ * `canvas.style.height = layoutHeight + "px"` (or feed these into
253
+ * your layout system). Independent of `densityScale`.
254
+ * - `pixelWidth` / `pixelHeight` — integer backing-store pixel
255
+ * dimensions the painter wrote to `canvas.width` / `canvas.height`.
256
+ * Equal to `round(layoutWidth * densityScale)` ×
257
+ * `round(layoutHeight * densityScale)` *unless* the requested backing
258
+ * exceeded the painter's safe maximum (16384 px per side), in which
259
+ * case `densityScale` was clamped to fit.
260
+ * - `clamped` — `true` when that 16384-px clamp fired, so the page is
261
+ * painted at fewer device pixels than requested and renders soft at the
262
+ * same `canvas.style` size. Reads the clamp off the return value instead
263
+ * of the `pixelWidth < round(layoutWidth * densityScale)` derivation.
264
+ * - `effectiveDensityScale` — the `densityScale` actually applied: the
265
+ * requested value unless `clamped`, then reduced proportionally.
266
+ * `layoutScale * effectiveDensityScale` is the scale the backing store
267
+ * was rasterized at.
268
+ *
269
+ * The painter owns `canvas.width` / `canvas.height`; consumers must not
270
+ * write to them. The painter does **not** touch `canvas.style.*`;
271
+ * consumers own layout. The write is a whole-backing-store `putImageData`,
272
+ * which bypasses the 2D context transform, `globalAlpha`, and clip: give
273
+ * each visible page its own `` — you cannot composite two pages, a
274
+ * sub-rect, or a context transform through `paint`.
275
+ *
276
+ * For `OffscreenCanvasRenderingContext2D` (Worker rasterization, no
277
+ * DOM), `layoutWidth` / `layoutHeight` are informational — there's no
278
+ * CSS layout box to apply them to.
279
+ */
280
+ export interface PaintResult {
281
+ layoutWidth: number;
282
+ layoutHeight: number;
283
+ pixelWidth: number;
284
+ pixelHeight: number;
285
+ clamped: boolean;
286
+ effectiveDensityScale: number;
287
+ }
288
+
289
+
290
+
291
+ /** UI layout hints for a single field. Field display order is not a hint:
292
+ * key order in the schema's `fields`/`properties` objects is declaration
293
+ * order, the ordering contract. */
294
+ export interface QuillFieldUi {
295
+ title?: string;
296
+ group?: string;
297
+ compact?: boolean;
298
+ multiline?: boolean;
299
+ }
300
+
301
+ /** UI layout hints for a card (main or named card kind). */
302
+ export interface QuillCardUi {
303
+ title?: string;
304
+ }
305
+
306
+ /** Body namespace for a card (main or named card kind). */
307
+ export interface QuillCardBody {
308
+ /** When false, consumers must not accept or store body content for this card kind. Defaults to true. */
309
+ enabled?: boolean;
310
+ /** Example body content embedded verbatim in the blueprint body region. Fallback is "Write <card> body here." */
311
+ example?: string;
312
+ }
313
+
314
+ /** Schema entry for a single field declared in a quill's `Quill.yaml`.
315
+ *
316
+ * A field's *cell* is determined by `default`: a field with a `default`
317
+ * is **Endorsed** (the rendered value is shippable as-is), while a field
318
+ * without a `default` is **Unendorsed** (the blueprint carries a
319
+ * `!must_fill` marker; a marker left in the document yields the non-fatal
320
+ * `validation::must_fill` warning from validate, and the render path
321
+ * zero-fills the field). There is no separate `required` axis.
322
+ */
323
+ export interface QuillFieldSchema {
324
+ type: "string" | "number" | "integer" | "boolean" | "array" | "object" | "date" | "datetime" | "richtext" | "plaintext" | "enum";
325
+ description?: string;
326
+ default?: unknown;
327
+ example?: unknown;
328
+ /** Closed value domain. On `type: "enum"` declared as `values`; the
329
+ * deprecated `enum` modifier on `type: "string"` is accepted for one
330
+ * release. Both round-trip through this field. */
331
+ enum?: string[];
332
+ /** Required on `type: "enum"`: the closed set of allowed string values. */
333
+ values?: string[];
334
+ ui?: QuillFieldUi;
335
+ properties?: Record<string, QuillFieldSchema>;
336
+ items?: QuillFieldSchema;
337
+ /** Present (and `true`) on a `richtext` or `plaintext` field declared
338
+ * `inline` — the single-paragraph, container-free, island-free constraint.
339
+ * Core serializes `inline: true` into the schema JSON; absent otherwise. */
340
+ inline?: boolean;
341
+ }
342
+
343
+ /** Schema entry for the main card or a named card kind. */
344
+ export interface QuillCardSchema {
345
+ description?: string;
346
+ fields: Record<string, QuillFieldSchema>;
347
+ ui?: QuillCardUi;
348
+ body?: QuillCardBody;
349
+ }
350
+
351
+ /**
352
+ * Document schema returned by `Quill.schema`. Includes optional `ui` keys.
353
+ *
354
+ * Describes only the user-fillable fields. The quill reference
355
+ * (constructed as `${metadata.name}@${metadata.version}`) and card-kind
356
+ * discriminators are document-level metadata, not schema fields.
357
+ */
358
+ export interface QuillSchema {
359
+ main: QuillCardSchema;
360
+ /** Present only when the quill declares at least one named card kind. */
361
+ card_kinds?: Record<string, QuillCardSchema>;
362
+ }
363
+
364
+ /**
365
+ * Identity snapshot mirroring the `quill:` section of `Quill.yaml`.
366
+ * The schema lives on `Quill.schema`; the backend's output formats are a
367
+ * resolved-backend capability read from the engine (`Quillmark.supportedFormats`),
368
+ * not part of this pure-config snapshot.
369
+ */
370
+ export interface QuillMetadata {
371
+ name: string;
372
+ version: string;
373
+ backend: string;
374
+ author: string;
375
+ description: string;
376
+ }
377
+
378
+
379
+ export interface Artifact {
380
+ format: OutputFormat;
381
+ bytes: Uint8Array;
382
+ mimeType: string;
383
+ }
384
+
385
+ export interface ChangeSet {
386
+ pageCount: number;
387
+ dirtyPages: number[];
388
+ }
389
+
390
+ export interface ContentHit {
391
+ field: string;
392
+ pos: number;
393
+ granularity?: HitGranularity;
394
+ }
395
+
396
+ export interface Diagnostic {
397
+ severity: Severity;
398
+ code?: string;
399
+ message: string;
400
+ location?: Location;
401
+ path?: string;
402
+ hint?: string;
403
+ sourceChain?: string[];
404
+ }
405
+
406
+ export interface FieldRegion {
407
+ field: string;
408
+ page: number;
409
+ rect: [number, number, number, number];
410
+ span?: [number, number];
411
+ }
412
+
413
+ export interface Location {
414
+ file: string;
415
+ line: number;
416
+ column: number;
417
+ }
418
+
419
+ export interface RenderOptions {
420
+ format?: OutputFormat;
421
+ ppi?: number;
422
+ pages?: number[];
423
+ producer?: string;
424
+ regions?: boolean;
425
+ }
426
+
427
+ export interface RenderResult {
428
+ artifacts: Artifact[];
429
+ warnings: Diagnostic[];
430
+ outputFormat: OutputFormat;
431
+ renderTimeMs: number;
432
+ regions: FieldRegion[];
433
+ }
434
+
435
+ export type HitGranularity = "cluster" | "segment";
436
+
437
+ export type OutputFormat = "pdf" | "svg" | "txt" | "png";
438
+
439
+ export type Severity = "error" | "warning";
440
+
441
+
442
+ /**
443
+ * Typed in-memory Quillmark document.
444
+ */
445
+ export class Document {
446
+ free(): void;
447
+ [Symbol.dispose](): void;
448
+ /**
449
+ * **Apply** a committed content edit `bundle` (`{ delta?, lineOps?, markOps? }`)
450
+ * at `addr` — the editor splice: text delta first, then line ops, then mark
451
+ * ops (mark ranges in final-text coordinates), each all-or-nothing. An absent
452
+ * `addr.field` targets the body, an absent `addr.card` the main card.
453
+ *
454
+ * Throws on an out-of-range card, a field that is not richtext, a malformed
455
+ * bundle, or an op that applies out of bounds (the value is unchanged on a
456
+ * failed apply).
457
+ */
458
+ applyChange(addr: Addr | string, bundle: ChangeBundle): void;
459
+ /**
460
+ * Authoring-ergonomics header introducing a blueprint to an LLM/MCP
461
+ * consumer for the given `quillName`. Re-exposes core's canonical text for
462
+ * JS consumers; any surface that draws from the same core source stays
463
+ * uniform.
464
+ */
465
+ static blueprintInstruction(quill_name: string): string;
466
+ /**
467
+ * A single composable card by index — the whole `Card`, the card-indexed
468
+ * twin of the [`main`](Self::main) getter, so reading one card need not
469
+ * materialize every card via [`cards`](Self::cards). An out-of-range
470
+ * `index` throws `[EditError::IndexOutOfRange]`, matching the card write
471
+ * verbs.
472
+ */
473
+ card(index: number): Card;
474
+ /**
475
+ * The index of the first composable card whose `$id` equals `id`, or
476
+ * `undefined` when none carries it. Resolves the canonical durable address
477
+ * without a hand-rolled scan over [`cards`](Self::cards); `$id` is
478
+ * non-unique by design, so the first match wins.
479
+ */
480
+ cardIndexById(id: string): number | undefined;
481
+ clone(): Document;
482
+ /**
483
+ * Schema version this build writes via [`toJson`](Document::to_json).
484
+ * Tracks the `Document` model version (not the running crate version):
485
+ * the tag advances only when the wire format changes, not on every release.
486
+ */
487
+ static currentSchemaVersion(): string;
488
+ /**
489
+ * Structural equality (parse-time `warnings` excluded). Use to debounce
490
+ * upstream prop updates instead of re-parsing on every keystroke.
491
+ */
492
+ equals(other: Document): boolean;
493
+ /**
494
+ * Render a Diagnostic as the canonical pretty-printed text (core's
495
+ * `Diagnostic::fmt_pretty`). Single source of truth so a Diagnostic looks
496
+ * identical no matter which consumer surfaces it.
497
+ */
498
+ static formatDiagnostic(diag: Diagnostic): string;
499
+ /**
500
+ * Authoring-format rules for the card-yaml markdown surface. The canonical
501
+ * text is core's (`quillmark_core::document::FORMAT_RULES`), re-exposed
502
+ * here for JS consumers so it matches any other surface that draws from the
503
+ * same source. Read once at startup and cache; the value never changes
504
+ * between calls.
505
+ */
506
+ static formatRules(): string;
507
+ /**
508
+ * Reconstruct a `Document` from a versioned storage DTO string produced
509
+ * by [`toJson`](Document::to_json). Unknown `schema` tags are rejected.
510
+ * The result carries no parse-time warnings (`.warnings` is always empty).
511
+ *
512
+ * Throws if `json` is not a valid storage DTO (malformed JSON, unknown
513
+ * `schema`, missing fields, or unparseable quill reference).
514
+ */
515
+ static fromJson(json: string): Document;
516
+ /**
517
+ * Parse markdown into a typed Document. Throws on parse errors.
518
+ */
519
+ static fromMarkdown(markdown: string): Document;
520
+ /**
521
+ * Read the value at `addr` — the raw stored payload value of a field (a
522
+ * content object for a richtext field, a scalar/array/object otherwise), or
523
+ * the **body content** when `addr.field` is absent. A bare string is `Addr`
524
+ * shorthand for `{ field }`. Reads are total over the field axis: an absent
525
+ * field is `undefined`; only an out-of-range `addr.card` throws
526
+ * `[EditError::IndexOutOfRange]`. Reads need no schema, so they live on
527
+ * `Document`, not the typed writer; for the markdown projection of a
528
+ * richtext value use [`getMarkdown`](Self::get_markdown).
529
+ */
530
+ get(addr: Addr | string): unknown;
531
+ /**
532
+ * The whole `$ext` map at `addr` (a card address, absent `card` = main), or
533
+ * `undefined` when the card carries none. The fine-grained `$ext` read —
534
+ * your own state without serializing the whole card. Throws on a present
535
+ * `field` (a card address takes only `card`) or an out-of-range card.
536
+ */
537
+ getExt(addr?: CardAddr): Record<string, unknown> | undefined;
538
+ /**
539
+ * The value stored under `$ext[ns]` at `addr` (a card address, absent `card`
540
+ * = main), or `undefined`. The namespace-scoped `$ext` read — your own slot
541
+ * without a whole-card serialize, and non-destructive (unlike
542
+ * `removeExtNamespace`). Throws on a present `field` or an out-of-range card.
543
+ */
544
+ getExtNamespace(addr: CardAddr, ns: string): unknown;
545
+ /**
546
+ * The **body** markdown projection — the main body, or a composable card's
547
+ * body (`{ card }`) — the on-demand, lossy export (content-only marks do not
548
+ * survive markdown). A body's type is a format fact, not a schema fact, so
549
+ * this read stays quill-free; a body is never absent.
550
+ *
551
+ * `addr` is an optional **card address** (`{ card }`, absent = main). A
552
+ * present `field` throws — a field's markdown is read through the
553
+ * schema-plane `quill.view(doc).get(field)`, which interprets by declared
554
+ * type (#978). An out-of-range `addr.card` throws.
555
+ */
556
+ getMarkdown(addr?: CardAddr): string;
557
+ /**
558
+ * Insert a card — the single insertion verb: `at` absent appends, a number
559
+ * inserts at that index (must be in `0..=cards.length`). Accepts a
560
+ * `CardInput` — a card read back (`cards` / `removeCard` / `quill.seedCard`),
561
+ * a [`makeCard`](Document::make_card) result, or a bare `{ kind, body }`
562
+ * (every returned `Card` is a valid `CardInput`). Throws if `card.kind` is
563
+ * not a valid kind name, or if `at` is out of range.
564
+ */
565
+ insertCard(card: CardInput, at?: number): void;
566
+ /**
567
+ * **Install** a richtext value at `addr` — **value semantics**, content only.
568
+ * Stores exactly `rt` (a canonical `Content` content object); the identity
569
+ * anchors of any previous value are gone. An absent `addr.field` targets the
570
+ * body, an absent `addr.card` the main card. For "here's new markdown," use
571
+ * [`revise`](Document::revise); the cold-import path is spelled at the call
572
+ * site as `install(addr, importMarkdown(md))`, so anchor loss is visible in
573
+ * source.
574
+ *
575
+ * Throws on an out-of-range card, a malformed field name, or an `rt` that is
576
+ * not a canonical content object.
577
+ */
578
+ install(addr: Addr | string, rt: Content): void;
579
+ /**
580
+ * Whether the field at `addr` is marked `!must_fill`. A bare string is `Addr`
581
+ * shorthand for `{ field }`. `false` for an absent field (truthful — it isn't
582
+ * marked) and for a body address (a body is never a fill). Only an
583
+ * out-of-range `addr.card` throws.
584
+ */
585
+ isFill(addr: Addr | string): boolean;
586
+ /**
587
+ * Replace this document's contents **in place** from a versioned storage
588
+ * DTO string — the mutating twin of the static
589
+ * [`fromJson`](Document::from_json) constructor. Parse-time `warnings` are
590
+ * cleared. Throws (leaving the document unchanged) on an invalid DTO.
591
+ *
592
+ * The cross-WASM-memory `Document` bridge: mutate a document on a
593
+ * backend-memory clone, then write the mutated state back into the caller's
594
+ * canonical document with this — the one way to update a live handle across
595
+ * the linear-memory seam without the caller re-binding its variable.
596
+ */
597
+ loadJson(json: string): void;
598
+ /**
599
+ * Build a fresh `Card` from a kind and a flat field map — the ergonomic
600
+ * constructor for `insertCard`. `fields` is an optional
601
+ * `Record<string, unknown>` (each entry becomes a card field, in
602
+ * insertion order); `body` defaults to `""`. Kind validity is checked by
603
+ * `insertCard`, not here.
604
+ */
605
+ static makeCard(kind: string, fields?: Record<string, unknown>, body?: string): Card;
606
+ /**
607
+ * Move the card at `from` to position `to`. `from == to` is a no-op.
608
+ */
609
+ moveCard(from: number, to: number): void;
610
+ /**
611
+ * `new Document(quillRef)` — a blank document: a main card carrying only
612
+ * `$quill`, an empty body, and no composable cards. The programmatic
613
+ * blank canvas: absent fields resolve at render time (`default`, else
614
+ * type-empty zero), so nothing the caller did not set reaches the
615
+ * output. For an example-filled starter use `Quill.seedDocument()`.
616
+ * Throws on an invalid quill reference. Mirrors Python `Document(quill_ref)`.
617
+ */
618
+ constructor(quill_ref: string);
619
+ /**
620
+ * The canonical `$quill` reference grammar as author-facing text. Core is
621
+ * the single source of truth: drive schema `describe` and validation
622
+ * messages from this instead of re-stating the rule — it matches the
623
+ * `hint` on `parse::invalid_quill_reference`. Cache it; the value never
624
+ * changes.
625
+ */
626
+ static quillRefHint(): string;
627
+ removeCard(index: number): Card | undefined;
628
+ /**
629
+ * Remove the `$ext` map on the card `addr` targets *entirely*, returning the
630
+ * previous map or `undefined` — a blunt escape hatch that discards every
631
+ * namespace at once (prefer `removeExtNamespace`). `addr` is a card address
632
+ * (absent = main). Throws on a present `field` or an out-of-range card.
633
+ */
634
+ removeExt(addr?: CardAddr): Record<string, unknown> | undefined;
635
+ /**
636
+ * Remove `$ext[ns]` on the card `addr` targets, returning its value or
637
+ * `undefined`; drops `$ext` once empty. `addr` is a card address (absent =
638
+ * main). Preserves sibling namespaces. Throws on a present `field` or an
639
+ * out-of-range card.
640
+ */
641
+ removeExtNamespace(addr: CardAddr, ns: string): any;
642
+ /**
643
+ * Remove a field at `addr`, returning the removed value or `undefined`. A
644
+ * bare string is `Addr` shorthand for `{ field }`. One `remove` verb serves
645
+ * every write lane. A body address throws; throws on an out-of-range card or
646
+ * a malformed name.
647
+ */
648
+ removeField(addr: Addr | string): any;
649
+ /**
650
+ * Remove `cardKind` from the main card's `$seed` map, returning its
651
+ * overlay or `undefined`; drops `$seed` entirely once empty. Sibling kinds
652
+ * survive. `$seed` is main-only, so this takes no address.
653
+ */
654
+ removeSeedNamespace(card_kind: string): any;
655
+ /**
656
+ * **Revise** the richtext value at `addr` from a markdown string — **edit
657
+ * semantics**, the default write path, returning the text [`Delta`]. Imports
658
+ * the markdown, diffs it against the current value, rebases surviving
659
+ * identity anchors, and returns the change an editor bridge maps its own
660
+ * positions through (`mapPos`). An absent `addr.field` targets the body, an
661
+ * absent `addr.card` the main card; an absent field cold-imports from empty.
662
+ *
663
+ * Throws on an out-of-range card, a malformed field name, a present
664
+ * non-content field value, or an over-nested markdown input.
665
+ */
666
+ revise(addr: Addr | string, markdown: string): Delta;
667
+ /**
668
+ * Read the `schema` version tag from a raw storage DTO string without a
669
+ * full parse, or `undefined`. Returns unknown future versions as-is —
670
+ * useful to distinguish "build too old" from "payload corrupt" when
671
+ * `fromJson` throws.
672
+ */
673
+ static schemaVersionOf(json: string): string | undefined;
674
+ /**
675
+ * The main card's `$seed` overlay object for `kind` (the `$seed[kind]`
676
+ * entry), or `undefined` when absent. The cheap read that feeds
677
+ * `quill.seedCard(kind, overlay)` without serializing the whole main card
678
+ * via [`main`](Self::main) to fish out one key — and it keeps `seedCard`
679
+ * pure: the quill still never reads the document.
680
+ */
681
+ seedOverlay(kind: string): Record<string, unknown> | undefined;
682
+ /**
683
+ * Replace the kind of the card at `index`. Payload and body are untouched;
684
+ * schema-aware migration is the caller's responsibility.
685
+ * Throws if `index` is out of range or `newKind` is invalid.
686
+ */
687
+ setCardKind(index: number, new_kind: string): void;
688
+ /**
689
+ * Replace the QUILL reference string. Throws if `ref_str` is invalid.
690
+ */
691
+ setQuillRef(ref_str: string): void;
692
+ /**
693
+ * Replace the opaque `$ext` map on the card `addr` targets (a card address,
694
+ * absent `card` = main). `value` must be a plain object. `$ext` carries
695
+ * out-of-band consumer state and never reaches the rendered output; pass
696
+ * `{}` for an explicit empty `$ext`. Quill-free and verbatim — an opaque
697
+ * `store` verb. Throws on a present `field` or an out-of-range card.
698
+ */
699
+ storeExt(addr: CardAddr, value: any): void;
700
+ /**
701
+ * Merge `value` into `$ext[ns]` on the card `addr` targets, preserving
702
+ * sibling namespaces — the recommended `$ext` write. `addr` is a card
703
+ * address (absent = main). Quill-free and verbatim — an opaque `store` verb.
704
+ * Throws on a present `field` or an out-of-range card.
705
+ */
706
+ storeExtNamespace(addr: CardAddr, ns: string, value: any): void;
707
+ /**
708
+ * Store a field verbatim at `addr` — the opaque store (**store** = verbatim,
709
+ * coercion deferred to render; the typed write is
710
+ * [`commitField`](Document::commit_field)). A bare string is `Addr`
711
+ * shorthand for `{ field }`, so `doc.storeField("qty", 3)` reads as written;
712
+ * `{ card: 2, field: "qty" }` targets a composable card. Clears any
713
+ * `!must_fill` marker. A body address (no `field`) throws — a body is never
714
+ * opaque; write it with `revise` / `install` / `writer.setBody`. Throws on
715
+ * an out-of-range card or a malformed name.
716
+ */
717
+ storeField(addr: Addr | string, value: any): void;
718
+ /**
719
+ * Store several fields verbatim and atomically on the card `addr` targets —
720
+ * the opaque store's batch. `addr` is a **card address** (`{ card }`, absent
721
+ * = main); a present `field` throws. The batch verb takes the address first
722
+ * and is never shape-overloaded, because `card` is a legal field name:
723
+ * `storeFields({}, fields)` is the main card, `storeFields({ card: 2 },
724
+ * fields)` a composable one — never ambiguous with "set field `card`".
725
+ * Nothing is applied on error; the thrown error's `diagnostics` carry one
726
+ * entry per offending field. Throws on an out-of-range card.
727
+ */
728
+ storeFields(addr: CardAddr, fields: Record<string, unknown>): void;
729
+ /**
730
+ * Store a field verbatim at `addr` and mark it `!must_fill` — the opaque
731
+ * store's fill variant, card-capable (a bare string or `{ field }` for main,
732
+ * `{ card, field }` for a composable card). A body address throws. Same
733
+ * validation as [`storeField`](Document::store_field).
734
+ */
735
+ storeFill(addr: Addr | string, value: any): void;
736
+ /**
737
+ * Merge a card-kind's seed `overlay` into the **main** card's `$seed` map
738
+ * under `cardKind`, preserving sibling kinds — `$seed` lives on the main
739
+ * card by model, so this takes no address. Sets the starting values new
740
+ * cards of that kind spawn with. Quill-free and verbatim — an opaque `store`
741
+ * verb. Throws if `overlay` cannot be serialized or nests too deep.
742
+ */
743
+ storeSeedNamespace(card_kind: string, overlay: any): void;
744
+ /**
745
+ * Serialize this document to a versioned storage DTO string.
746
+ *
747
+ * Prefer this over `toMarkdown` for persistence across restarts or crate
748
+ * upgrades — the wire format is frozen per `schema` version. Parse-time
749
+ * `warnings` are excluded from the DTO.
750
+ *
751
+ * Output is **byte-deterministic** within a `schema` version: equal
752
+ * documents produce byte-equal output, safe for content-hash use cases.
753
+ */
754
+ toJson(): string;
755
+ /**
756
+ * Emit canonical Quillmark Markdown. Round-trip safe: re-parsing the
757
+ * result produces a `Document` equal to `self` by value and by type.
758
+ */
759
+ toMarkdown(): string;
760
+ /**
761
+ * Like [`fromJson`](Document::from_json) but returns `undefined` instead
762
+ * of throwing when `json` is not a valid storage DTO — use to
763
+ * discriminate format without exceptions as control flow.
764
+ * `undefined` means "not a storage DTO"; `fromMarkdown` still throws on
765
+ * genuinely malformed markdown.
766
+ */
767
+ static tryFromJson(json: string): Document | undefined;
768
+ /**
769
+ * Number of composable cards (excludes the main card). O(1).
770
+ */
771
+ readonly cardCount: number;
772
+ readonly cards: Card[];
773
+ /**
774
+ * The document's main (entry) card. Allocates and serializes on each
775
+ * call — cache locally if read in a hot loop.
776
+ */
777
+ readonly main: Card;
778
+ readonly quillRef: string;
779
+ readonly warnings: Diagnostic[];
780
+ }
781
+
782
+ /**
783
+ * Live render session: reads (`render`, `paint`, `pageSize`, `regions`,
784
+ * `fieldAt`, `positionAt`, `locate`) serve the current compile. `apply(doc)`
785
+ * recompiles a whole document in place, transactionally (on throw every read
786
+ * keeps serving the last-good compile). Geometry reads reflect the current
787
+ * compile; anchoring a caret across edits is the editor's job — re-read
788
+ * geometry after each committed `apply`.
789
+ *
790
+ * **Empty documents.** A zero-page document yields a valid session
791
+ * (`pageCount === 0`); `paint(ctx, 0)` or `pageSize(0)` throws with
792
+ * `"page index 0 out of range (pageCount=0)"`. Branch on `pageCount === 0`
793
+ * rather than catching the error.
794
+ */
795
+ export class LiveSession {
796
+ private constructor();
797
+ free(): void;
798
+ [Symbol.dispose](): void;
799
+ /**
800
+ * Recompile the session against `doc` — the edit verb of a live preview.
801
+ * The document is compiled through the same schema pipeline as `open`
802
+ * (same quill), then applied transactionally: on throw every read
803
+ * (`render`, `paint`, `pageSize`, `regions`, `fieldAt`) keeps serving the last-good
804
+ * compile, and the session recovers on the next successful `apply`. On
805
+ * success reads serve the new compile; repaint `dirtyPages ∩ visible`.
806
+ */
807
+ apply(doc: Document): ChangeSet;
808
+ /**
809
+ * The schema field whose content is under a point on `page` — the
810
+ * forward (click → field) direction: hit-test a click against the
811
+ * compiled document and get back the field address to focus in the
812
+ * editor, or `undefined` off any field's ink. `x`/`y` are PDF points
813
+ * with a **bottom-left** origin, the same space as `FieldRegion.rect` —
814
+ * from a canvas click, invert the overlay transform documented on
815
+ * `FieldRegion`: `x = clickPx.x / renderScale`,
816
+ * `y = pageHeightPt - clickPx.y / renderScale`. Unlike `regions()`,
817
+ * *every* placement answers, not just the first.
818
+ */
819
+ fieldAt(page: number, x: number, y: number): string | undefined;
820
+ /**
821
+ * The whole-field highlight boxes for `field` — one union rect per page,
822
+ * over the field's `span`-bearing content segments. The convenience that
823
+ * owns the union `regions()` leaves derived: it keeps `regions()` the
824
+ * low-level disjoint truth (#829) and folds the span-filter + per-page
825
+ * union here, so a "highlight the focused field" consumer stops
826
+ * reimplementing it. **Content only** — a field placed solely as a scalar
827
+ * reference or a bound widget carries no `span` and returns `[]`; its box
828
+ * is a single `regions()` rect. Reflects the current compile, like
829
+ * `regions()`.
830
+ */
831
+ fieldBoxes(field: string): FieldRegion[];
832
+ /**
833
+ * A content position → **caret rect** — the reverse of `positionAt`: given
834
+ * a field and a USV offset into its `Content`, return the box (in the
835
+ * same bottom-left PDF-point space as `FieldRegion.rect`) to draw a caret
836
+ * at, its `span` collapsed to `[pos, pos]`; `undefined` when the field
837
+ * places no tracked content or the offset maps to no drawn glyph.
838
+ */
839
+ locate(field: string, pos: number): FieldRegion | undefined;
840
+ /**
841
+ * Page dimensions in points (1 pt = 1/72 inch).
842
+ * Throws if the backend has no canvas painter or `page` is out of range.
843
+ */
844
+ pageSize(page: number): PageSize;
845
+ /**
846
+ * Paint `page` into a `CanvasRenderingContext2D` or
847
+ * `OffscreenCanvasRenderingContext2D`. The painter owns
848
+ * `canvas.width`/`height` (no `clearRect` needed); consumers own
849
+ * `canvas.style.*`. If `layoutScale * densityScale` exceeds 16384 px
850
+ * per side, `densityScale` is clamped — `PaintResult.clamped` reports it and
851
+ * `PaintResult.effectiveDensityScale` carries the density actually applied.
852
+ *
853
+ * `put_image_data` writes the whole backing store, bypassing the 2D
854
+ * context's transform, `globalAlpha`, and clip: the painter owns the entire
855
+ * canvas, so each visible page needs its own `` — you cannot composite
856
+ * two pages, a sub-rect, or a context transform through this call.
857
+ *
858
+ * Throws if the backend has no canvas painter, `page` is out of range,
859
+ * `ctx` is the wrong type, or either scale is non-finite or `<= 0`.
860
+ */
861
+ paint(ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, page: number, opts: PaintOptions | undefined): PaintResult;
862
+ /**
863
+ * A point → **content position** — the fine-grained click direction:
864
+ * hit-test a point and get back the field *and* a USV offset into its
865
+ * `Content` (for placing a caret or mapping a selection into the content
866
+ * model), or `undefined` off all content ink. `x`/`y` are PDF points,
867
+ * bottom-left origin — the same space as `fieldAt`. The offset is
868
+ * cluster-exact and degrades to the containing segment's start on
869
+ * origin-less ink (list markers, a code fence's interior). See
870
+ * `ContentHit`.
871
+ */
872
+ positionAt(page: number, x: number, y: number): ContentHit | undefined;
873
+ /**
874
+ * Schema-field geometry for this compiled session — each content field's
875
+ * **first placement** (one region per page it touches) plus widget and
876
+ * scalar-reference-site regions, keyed on the quill schema field path; a
877
+ * field may still appear more than once (group by `field`, see
878
+ * `FieldRegion`). A session-level query: no render, no byte artifact. An
879
+ * interactive preview reads it to scroll to / highlight the focused
880
+ * field over a `paint`-ed canvas; the click direction is `fieldAt`.
881
+ * Empty for backends that place no schema fields.
882
+ */
883
+ regions(): FieldRegion[];
884
+ render(opts?: RenderOptions | null): RenderResult;
885
+ /**
886
+ * The backend that produced this session (e.g. `"typst"`).
887
+ */
888
+ readonly backendId: string;
889
+ readonly pageCount: number;
890
+ /**
891
+ * `true` iff `paint` and `pageSize` will succeed for this session. Derived
892
+ * from the session's canvas seam, so it reflects exactly what `paint` will
893
+ * do — no separately captured flag.
894
+ */
895
+ readonly supportsCanvas: boolean;
896
+ /**
897
+ * Non-fatal diagnostics of the session's **current compile** (e.g. Typst
898
+ * font fallback) — set at open and refreshed by each committed `apply`;
899
+ * a failed apply keeps the last-good compile's warnings. Also appended
900
+ * to `RenderResult.warnings` on each `render()` call.
901
+ */
902
+ readonly warnings: Diagnostic[];
903
+ }
904
+
905
+ export class Quill {
906
+ private constructor();
907
+ free(): void;
908
+ [Symbol.dispose](): void;
909
+ /**
910
+ * Build a quill from a file tree. Pure — no backend, no engine; the
911
+ * declared backend is resolved later, at render time.
912
+ *
913
+ * Accepts either a `Map<string, Uint8Array>` or a plain object
914
+ * (`Record<string, Uint8Array>`). Plain objects are walked via
915
+ * `Object.entries` at the boundary; the Rust side sees a single
916
+ * canonical shape.
917
+ */
918
+ static fromTree(tree: Map<string, Uint8Array>): Quill;
919
+ /**
920
+ * Seed a starter composable `Card` of the given kind (carries `$kind`),
921
+ * layering an optional per-kind seed `overlay` over the schema-example
922
+ * base (`overlay › example › absent`). Returns `undefined` if `cardKind`
923
+ * is not declared in this quill's schema, else a `Card` that feeds
924
+ * straight into `Document.insertCard`.
925
+ *
926
+ * Pass `document.seedOverlay(cardKind)` as `overlay` so a card added to a
927
+ * template-derived document inherits its curated starting values; omit it
928
+ * (or pass `undefined` / `null`) for the bare schema seed. `overlay` is a
929
+ * plain object — this reads the document, it does not mutate it.
930
+ */
931
+ seedCard(card_kind: string, overlay: Record<string, unknown> | undefined): Card | undefined;
932
+ /**
933
+ * Seed a starter `Document` from the schema — the main card plus one
934
+ * instance of each composable card kind, each committing its fields'
935
+ * `example:` values and leaving every other field absent (interpolated at
936
+ * render: `default:`, else type-empty zero). Illustration-first: a field
937
+ * with both an `example` and a `default` renders its example. See
938
+ * `prose/canon/SCHEMAS.md` § "Document seeding".
939
+ */
940
+ seedDocument(): Document;
941
+ /**
942
+ * Seed a starter main `Card` (carries `$quill`) from the schema — the
943
+ * `$kind: main` card of [`seedDocument`](Self::seed_document) in
944
+ * isolation, committing each field's `example:` value. Returns the same
945
+ * `Card` shape as the `Document.main` getter.
946
+ */
947
+ seedMain(): Card;
948
+ /**
949
+ * Flatten this quill back into its canonical file tree — the inverse of
950
+ * [`fromTree`](Self::from_tree). Round-trips: `Quill.fromTree(q.toTree())`
951
+ * reproduces an equivalent quill.
952
+ *
953
+ * This is how a quill crosses a WASM linear-memory boundary as data: a
954
+ * `Quill` built in one build (e.g. the Typst-less `@quillmark/wasm/core`)
955
+ * cannot be passed to an engine in another (separate linear memories), so
956
+ * `@quillmark/wasm/runtime` re-feeds this tree to the backend build's
957
+ * `Quill.fromTree` on demand. Keys are `"/"`-joined relative paths,
958
+ * matching what `fromTree` accepts.
959
+ */
960
+ toTree(): Map<string, Uint8Array>;
961
+ /**
962
+ * Validate `doc` against this quill's schema, returning every diagnostic
963
+ * (an empty array when the document is valid).
964
+ *
965
+ * Forwards the canonical `validation::*` diagnostics — same `code`,
966
+ * `path`, and `hint` the engine emits — including the non-fatal
967
+ * `validation::must_fill` warning for each `!must_fill` marker left in
968
+ * the document. Field values, defaults, and order are not part of this
969
+ * surface: read them from the `Document` payload and `Quill.schema`
970
+ * (schema key order is display order).
971
+ */
972
+ validate(doc: Document): Diagnostic[];
973
+ /**
974
+ * The *declared* backend identifier (`config.backend`, e.g. `"typst"`).
975
+ * Intent, not a resolved capability — capability (`supportedFormats` /
976
+ * `supportsCanvas`) is read from the engine.
977
+ */
978
+ readonly backendId: string;
979
+ readonly blueprint: string;
980
+ /**
981
+ * Identity snapshot of the `quill:` section of `Quill.yaml` plus any extra
982
+ * `quill:` keys. Pure config — the backend's output formats are a
983
+ * resolved-backend capability read from the engine
984
+ * (`Quillmark.supportedFormats`), not part of this snapshot.
985
+ */
986
+ readonly metadata: QuillMetadata;
987
+ /**
988
+ * Document schema for the quill: the user-fillable fields plus their
989
+ * `ui` hints (title / group / compact / multiline). The single
990
+ * field-metadata surface — drives form editors and LLM/MCP consumers
991
+ * alike. Key order in `fields`/`properties` is declaration order — the
992
+ * ordering contract. Returns the `QuillSchema` shape.
993
+ */
994
+ readonly schema: QuillSchema;
995
+ }
996
+
997
+ /**
998
+ * Render engine: a backend registry and render dispatcher. Render build only —
999
+ * the core build constructs and validates quills without it.
1000
+ */
1001
+ export class Quillmark {
1002
+ free(): void;
1003
+ [Symbol.dispose](): void;
1004
+ constructor();
1005
+ /**
1006
+ * Open a live render session for `doc` against `quill`'s backend.
1007
+ */
1008
+ open(quill: Quill, doc: Document): LiveSession;
1009
+ /**
1010
+ * Render `doc` against `quill` in one shot. Convenience over `open` +
1011
+ * `LiveSession.render`: an unset `output_format` falls back to the
1012
+ * backend's first supported format.
1013
+ */
1014
+ render(quill: Quill, doc: Document, opts?: RenderOptions | null): RenderResult;
1015
+ /**
1016
+ * The output formats `quill`'s backend can emit. Static capability —
1017
+ * resolves the backend but compiles nothing. Throws `engine::backend_not_found`
1018
+ * if no registered backend matches the quill's declared backend.
1019
+ */
1020
+ supportedFormats(quill: Quill): OutputFormat[];
1021
+ /**
1022
+ * Pre-session hint: `true` iff `quill`'s backend can paint sessions to a
1023
+ * canvas, derived from the backend's output formats; `false` when the
1024
+ * backend is unsupported. Use as a cheap precondition probe before mounting
1025
+ * a canvas-based preview UI; the authoritative answer is the session's
1026
+ * `supportsCanvas` getter once `open()` has been called.
1027
+ */
1028
+ supportsCanvas(quill: Quill): boolean;
1029
+ }
1030
+
1031
+ /**
1032
+ * Export a canonical `Content` content to its markdown projection — the pure
1033
+ * on-demand codec behind `exportMarkdown(card.body)`. Throws if `rt` is not a
1034
+ * canonical content.
1035
+ */
1036
+ export function exportMarkdown(rt: Content): string;
1037
+
1038
+ /**
1039
+ * Import a markdown string to a canonical `Content` content — the pure,
1040
+ * document-free codec. Pair with `install(addr, importMarkdown(md))` to spell
1041
+ * the cold (anchor-losing) write at the call site; prefer `revise` for edit
1042
+ * semantics. Throws on an over-nested input.
1043
+ */
1044
+ export function importMarkdown(markdown: string): Content;
1045
+
1046
+ /**
1047
+ * Initialize the WASM module with panic hooks for better error messages
1048
+ */
1049
+ export function init(): void;
1050
+
1051
+ /**
1052
+ * Map a base content position through a `delta` to its new position — the pure
1053
+ * position-mapping codec an editor bridge composes to hold a caret stable
1054
+ * across a `revise`. `assoc` decides the side of a same-position insertion
1055
+ * (`"after"` moves past it). Throws on a malformed `delta`.
1056
+ */
1057
+ export function mapPos(delta: Delta, pos: number, assoc: Assoc): number;
1058
+
1059
+ /**
1060
+ * Rebase `markdown` onto a `base` content — the pure, document-free twin of
1061
+ * `revise`: cold-import + `diff_import`, returning the new `content` and the
1062
+ * text `delta` (surviving anchors rebased). Use it to compute a revise without
1063
+ * a document in hand; `revise(addr, md)` fuses this with the store for
1064
+ * atomicity. Throws on an over-nested markdown input or a non-content `base`.
1065
+ */
1066
+ export function rebase(base: Content, markdown: string): { content: Content; delta: Delta };