@quillmark/wasm 0.97.0 → 0.99.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.
@@ -1,33 +1,38 @@
1
- // @quillmark/wasm/runtime canonical consumer API.
1
+ // @quillmark/wasm/runtime: canonical consumer API.
2
2
  //
3
3
  // `Quill`/`Document` are re-exported verbatim from the core build (their full
4
4
  // surface, no drift). Render-side types (`RenderResult`, `RenderOptions`,
5
5
  // `Artifact`, `OutputFormat`, `PageSize`, `PaintOptions`, `PaintResult`) are
6
- // defined HERE as the canonical, backend-neutral render contract NOT sourced
6
+ // defined HERE as the canonical, backend-neutral render contract: NOT sourced
7
7
  // from any one private backend build. A type-level drift guard
8
8
  // (`runtime.types.test-d.ts`, via `npm run typecheck`) asserts they stay
9
9
  // mutually assignable with the Typst backend's generated declarations. `Engine`
10
10
  // is the render dispatcher that hides the cross-WASM-memory seam.
11
11
 
12
12
  // CANONICAL INVARIANT: the root re-exports the core build's `Quill`/`Document`
13
- // verbatim they are the SAME classes, never wrappers. There is exactly one
13
+ // verbatim; they are the SAME classes, never wrappers. There is exactly one
14
14
  // public entry point, so this is a structural fact. Replacing the re-export
15
15
  // with a wrapper is a breaking design change, not a refactor. See runtime.js.
16
+ //
17
+ // ONE COPY PER PROCESS: two copies of this package are two WASM linear memories
18
+ // and two `Quill`/`Document` classes. Every method taking a handle refuses one
19
+ // belonging to another copy, with a `QuillmarkError` naming `npm ls
20
+ // @quillmark/wasm`. Errors are the exception: `isQuillmarkError` is structural.
16
21
  export { Quill, Document, init } from '../core/wasm.js';
17
22
  // The document-free content codec, re-exported from the core build.
18
23
  export { importMarkdown, exportMarkdown, rebase, mapPos } from '../core/wasm.js';
19
- // The document-model path parser/serializer route on `Diagnostic.path`
24
+ // The document-model path parser/serializer: route on `Diagnostic.path`
20
25
  // segments instead of regexing the string.
21
26
  export { parseDocPath, formatDocPath } from '../core/wasm.js';
22
27
 
23
28
  import type { CardAddr } from '../core/wasm.js';
24
29
 
25
30
  /**
26
- * The main card's address the default target of the card-scoped verbs
31
+ * The main card's address: the default target of the card-scoped verbs
27
32
  * (`storeFields` / `storeExt` / `commitFields` / …). A named, {@link CardAddr}-typed
28
33
  * alias for the empty address `{}`, so a main-card write names its target:
29
34
  * `doc.storeFields(MAIN_CARD_ADDR, fields)`. It IS `{}` (frozen at runtime), a
30
- * pure alias `{}` and `undefined` stay equally valid. A card selector only,
35
+ * pure alias: `{}` and `undefined` stay equally valid. A card selector only,
31
36
  * never a field address.
32
37
  */
33
38
  export declare const MAIN_CARD_ADDR: CardAddr;
@@ -49,17 +54,24 @@ export type {
49
54
  QuillMetadata
50
55
  } from '../core/wasm.js';
51
56
 
52
- // Content edit vocabulary the op-grained content model `Document`'s methods
57
+ // Content edit vocabulary: the op-grained content model `Document`'s methods
53
58
  // speak (`applyChange(addr, bundle)`, `install(addr, rt)`, `revise(…) => Delta`).
54
59
  // Declared in the core build; re-exported here so the single public entry point
55
- // names every type its own re-exported surface already references `Card.body`
60
+ // names every type its own re-exported surface already references: `Card.body`
56
61
  // is a `Content`, `PayloadItem.nestedFills` a `PathStep[][]`, `CardInput.body` a
57
- // `Content | string` rather than forcing consumers to derive them structurally
62
+ // `Content | string`: rather than forcing consumers to derive them structurally
58
63
  // off the `Document` handle. The content write path (a ProseMirror↔content codec)
59
64
  // must name all of them; they are its correctness core, not edge types.
65
+ // `ContentLineKind` is the shared half of `ContentLine` and `setKind`, so lifting
66
+ // a line's kind whole (destructure off `containers`/`continues`, spread the rest
67
+ // into the op) is the version-proof spelling of building a `setKind`. Naming it
68
+ // is what makes that spelling type-check without a cast. The alternative, an
69
+ // arm-by-arm switch, means guessing at the open arm's shape and re-editing on
70
+ // every arm added.
60
71
  export type {
61
72
  Content,
62
73
  ContentLine,
74
+ ContentLineKind,
63
75
  ContentContainer,
64
76
  ContentMark,
65
77
  ContentIsland,
@@ -78,7 +90,7 @@ export type {
78
90
  DocPathSeg
79
91
  } from '../core/wasm.js';
80
92
 
81
- // The resolved-value view the return shape of `quill.resolve(doc)`. Value
93
+ // The resolved-value view: the return shape of `quill.resolve(doc)`. Value
82
94
  // + source rung per declared field (the body is a `body` sibling on its card,
83
95
  // never a row in `fields`); diagnostics stay `quill.validate`, guidance stays
84
96
  // `quill.schema`.
@@ -96,14 +108,14 @@ export type {
96
108
  // ── Error contract ──────────────────────────────────────────────────────────
97
109
 
98
110
  /**
99
- * The error every fallible method in this package throws parse
111
+ * The error every fallible method in this package throws: parse
100
112
  * (`Document.fromMarkdown`), document mutation, validation
101
113
  * (`Quill.fromTree`, `quill.validate`), and rendering (`engine.render`,
102
114
  * `engine.open`, `session.render`).
103
115
  *
104
116
  * This is a STRUCTURAL interface, not a class: the WASM layer throws a real
105
117
  * `Error` and attaches `diagnostics` to it, so there is no constructor to
106
- * `instanceof` against narrow with {@link isQuillmarkError}. `diagnostics`
118
+ * `instanceof` against, narrow with {@link isQuillmarkError}. `diagnostics`
107
119
  * is always non-empty; `message` is the first diagnostic's message (or an
108
120
  * `"N error(s): …"` aggregate for multi-diagnostic failures), so iterate
109
121
  * `diagnostics` for per-error detail. The shape is identical to
@@ -115,22 +127,33 @@ export interface QuillmarkError extends Error {
115
127
 
116
128
  /**
117
129
  * Narrow an unknown caught value to {@link QuillmarkError}. Structural
118
- * (`Error` carrying a `diagnostics` array), so it works on errors from any
119
- * build or WASM instance in the page consistent with the package's
120
- * duck-typed handling of handles.
130
+ * (`Error` carrying a `diagnostics` array), so it narrows errors from any build
131
+ * or WASM instance in the page. Handles are the opposite: a `Quill` or
132
+ * `Document` from a second copy of this package is rejected wherever it is
133
+ * passed, since two copies are two linear memories. An error is data, not a
134
+ * handle, so nothing is gained by refusing one that crossed.
121
135
  */
122
136
  export declare function isQuillmarkError(e: unknown): e is QuillmarkError;
123
137
 
124
138
  // ── Open-set discriminant guards ────────────────────────────────────────────
125
- // `ContentIsland.type` / `ContentMark.type` are open sets — each union has a
126
- // residual `{ type: string; }` arm, so a bare discriminant check never narrows
127
- // the payload (TS keeps the residual arm live, since a `string` can equal the
128
- // literal). These guards are the checked narrowing path for the pinned arms; an
129
- // unrecognized `type` fails every guard and keeps its opaque payload. Only the
130
- // payload-carrying arms get a guard the bare marks
131
- // (`strong`/`emph`/`underline`/`strike`/`code`) narrow to nothing.
132
-
133
- import type { ContentIsland, TableProps, ImageProps, ContentMark } from '../core/wasm.js';
139
+ // `ContentIsland.type`, `ContentMark.type`, `ContentLine.kind`, and
140
+ // `ContentContainer.container` are open sets: each union has a residual
141
+ // `{ …: string; }` arm, so a bare discriminant check never narrows the payload
142
+ // (TS keeps the residual arm live, since a `string` can equal the literal).
143
+ // These guards are the checked narrowing path for the pinned arms; an
144
+ // unrecognized discriminant fails every guard and keeps its opaque payload. Only
145
+ // the payload-carrying arms get a guard: the bare marks
146
+ // (`strong`/`emph`/`underline`/`strike`/`code`), the payload-free lines
147
+ // (`para`/`island`/`rule`), and `quote` narrow to nothing.
148
+
149
+ import type {
150
+ ContentIsland,
151
+ TableProps,
152
+ ImageProps,
153
+ ContentMark,
154
+ ContentLine,
155
+ ContentContainer
156
+ } from '../core/wasm.js';
134
157
 
135
158
  /** Narrow a {@link ContentIsland} to the pinned `table` arm (`props: TableProps`). */
136
159
  export declare function isTableIsland(
@@ -152,6 +175,59 @@ export declare function isAnchorMark(
152
175
  mark: ContentMark
153
176
  ): mark is ContentMark & { type: 'anchor'; id: string };
154
177
 
178
+ /** Narrow a {@link ContentLine} to the `heading` arm (carries `level`). */
179
+ export declare function isHeadingLine(
180
+ line: ContentLine
181
+ ): line is ContentLine & { kind: 'heading'; level: number };
182
+
183
+ /** Narrow a {@link ContentLine} to the `code` arm (carries `lang`). */
184
+ export declare function isCodeLine(
185
+ line: ContentLine
186
+ ): line is ContentLine & { kind: 'code'; lang?: string };
187
+
188
+ /** Narrow a {@link ContentContainer} to the `list_item` arm (carries its shape). */
189
+ export declare function isListItemContainer(
190
+ container: ContentContainer
191
+ ): container is ContentContainer & {
192
+ container: 'list_item';
193
+ ordered: boolean;
194
+ start: number;
195
+ ordinal: number;
196
+ };
197
+
198
+ // ── Open-set membership guards ──────────────────────────────────────────────
199
+ // The guards above answer "is this arm X", one pinned arm at a time. These four
200
+ // answer "is this a value this build knows?": the question a read-modify-write
201
+ // consumer must ask, since lowering an edit restates every line's kind and
202
+ // containers, and a construct the consumer cannot hold is gone on write-back
203
+ // unless it is carried inertly. Without a predicate a consumer enumerates the
204
+ // built-in names itself and re-couples to a closed set, going wrong at the first
205
+ // release that adds one.
206
+ //
207
+ // They classify unknown TAGS, not unknown payloads on known tags: a future
208
+ // `kind: "footnote"` carrying a sibling `ref` loses `ref` at any consumer that
209
+ // predates it, with or without these.
210
+
211
+ /** True when this build does not know `line.kind`: the open arm, carrying opaque `attrs`. */
212
+ export declare function isUnknownLine(
213
+ line: ContentLine
214
+ ): line is ContentLine & { kind: string; attrs: unknown };
215
+
216
+ /** True when this build does not know `container.container`. See {@link isUnknownLine}. */
217
+ export declare function isUnknownContainer(
218
+ container: ContentContainer
219
+ ): container is ContentContainer & { container: string; attrs: unknown };
220
+
221
+ /** True when this build does not know `mark.type`. See {@link isUnknownLine}. */
222
+ export declare function isUnknownMark(
223
+ mark: ContentMark
224
+ ): mark is ContentMark & { type: string; attrs: unknown };
225
+
226
+ /** True when this build does not know `island.type` (its payload rides `props`, not `attrs`). */
227
+ export declare function isUnknownIsland(
228
+ island: ContentIsland
229
+ ): island is ContentIsland & { type: string; props: unknown };
230
+
155
231
  // ── Canonical render-side types ─────────────────────────────────────────────
156
232
  // These are the BACKEND-NEUTRAL render contract of the plural-backend API. They
157
233
  // are defined HERE (not re-exported from one private backend) because no single
@@ -180,21 +256,21 @@ export interface RenderOptions {
180
256
  /**
181
257
  * Populate {@link RenderResult.regions} with the schema-field geometry
182
258
  * sidecar (the same entries {@link LiveSession.regions} serves), for
183
- * consumers without a live session e.g. overlays over a one-shot SVG
259
+ * consumers without a live session; e.g. overlays over a one-shot SVG
184
260
  * export. Defaults to `false`: exports pay no introspection cost.
185
261
  */
186
262
  regions?: boolean;
187
263
  }
188
264
 
189
265
  /**
190
- * How precisely a {@link ContentHit.pos} resolved the marker a caret UI reads
266
+ * How precisely a {@link ContentHit.pos} resolved: the marker a caret UI reads
191
267
  * to decide whether to trust the offset. Never sub-cluster: `'cluster'` is the
192
268
  * finest, `'segment'` the floor it degrades to on origin-less ink.
193
269
  *
194
- * - `'cluster'` `pos` is the first content char of the cluster under the point
270
+ * - `'cluster'`: `pos` is the first content char of the cluster under the point
195
271
  * (an escaped/CJK/shaping cluster floors to its first char). Place the caret
196
272
  * at `pos` directly.
197
- * - `'segment'` the point hit origin-less ink (list markers, numbering, a
273
+ * - `'segment'`: the point hit origin-less ink (list markers, numbering, a
198
274
  * multi-line code fence's interior), so `pos` degraded to the containing
199
275
  * segment's start. Treat `pos` as the selected segment, not a caret.
200
276
  */
@@ -203,7 +279,7 @@ export type HitGranularity = 'cluster' | 'segment';
203
279
  /** A click resolved to a field and USV offset into its Content. */
204
280
  export interface ContentHit {
205
281
  /**
206
- * The field's canonical `DocPath` address (`parseDocPath`-routable) the same
282
+ * The field's canonical `DocPath` address (`parseDocPath`-routable): the same
207
283
  * address {@link LiveSession.fieldAt} returns for that point.
208
284
  */
209
285
  field: string;
@@ -218,28 +294,28 @@ export interface ContentHit {
218
294
  /**
219
295
  * A rendered field region: the canonical `DocPath` field address (`field`) plus
220
296
  * its geometry (`rect`) on the page. Emitted by backends that place schema fields
221
- * (`pdfform` AcroForm widgets; Typst form-fields and span-tracked content
297
+ * (`pdfform` AcroForm widgets; Typst form-fields and span-tracked content:
222
298
  * richtext bodies, `richtext[]` elements, card content fields, direct scalar
223
- * references). Only fields with a schema address produce a region a
299
+ * references). Only fields with a schema address produce a region: a
224
300
  * backend-only widget produces none, and the backend widget name never
225
301
  * appears.
226
302
  *
227
303
  * Use it to scroll to / highlight the focused field's rect; for the click
228
304
  * direction use {@link LiveSession.fieldAt}, which resolves a point on *any*
229
- * placement, not just the first one surfaced here. Geometry only
305
+ * placement, not just the first one surfaced here. Geometry only:
230
306
  * `LiveSession.paint` already bakes every value into the raster (see
231
307
  * {@link LiveSession}), so a region is never a compositing input.
232
308
  *
233
309
  * COORDINATE TRANSFORM. `rect` is in PDF points with a **bottom-left** origin.
234
310
  *
235
311
  * For an **HTML/CSS overlay** on a `width:100%` canvas, position hotspots as
236
- * percentages of the page they track the displayed size across DPI and pane
312
+ * percentages of the page; they track the displayed size across DPI and pane
237
313
  * resize for free, and only the Y axis flips:
238
314
  *
239
315
  * ```js
240
316
  * const [x0, y0, x1, y1] = region.rect; // PDF pt, bottom-left origin
241
317
  * const left = (x0 / pageWidthPt) * 100; // % of page (from PageSize.widthPt)
242
- * const top = (1 - y1 / pageHeightPt) * 100; // % flip Y (from PageSize.heightPt)
318
+ * const top = (1 - y1 / pageHeightPt) * 100; // %: flip Y (from PageSize.heightPt)
243
319
  * const width = ((x1 - x0) / pageWidthPt) * 100;
244
320
  * const height = ((y1 - y0) / pageHeightPt) * 100;
245
321
  * ```
@@ -265,7 +341,7 @@ export interface FieldRegion {
265
341
  /** `[x0, y0, x1, y1]` in PDF points (1/72″), bottom-left origin. */
266
342
  rect: [number, number, number, number];
267
343
  /**
268
- * The content slice this box covers USV `[start, end)` into the field's
344
+ * The content slice this box covers: USV `[start, end)` into the field's
269
345
  * `Content` for content ink (one segment), absent for a scalar reference
270
346
  * site or widget. Consumers key segment highlights on it;
271
347
  * {@link LiveSession.fieldBoxes} unions same-page segments for the
@@ -281,7 +357,7 @@ export interface RenderResult {
281
357
  outputFormat: OutputFormat;
282
358
  renderTimeMs: number;
283
359
  /**
284
- * Schema-field geometry sidecar populated only when
360
+ * Schema-field geometry sidecar: populated only when
285
361
  * {@link RenderOptions.regions} requested it; empty otherwise. The same
286
362
  * entries {@link LiveSession.regions} serves, for consumers without a live
287
363
  * session. Page indices are document-space even under a `pages` subset
@@ -291,7 +367,7 @@ export interface RenderResult {
291
367
  }
292
368
 
293
369
  /** Canonical contract every backend build must satisfy. The emittable formats. */
294
- export type OutputFormat = 'pdf' | 'svg' | 'txt' | 'png';
370
+ export type OutputFormat = 'pdf' | 'svg' | 'png';
295
371
 
296
372
  /**
297
373
  * Canonical contract every backend build must satisfy. Page geometry in pt.
@@ -325,7 +401,7 @@ export interface PaintResult {
325
401
  */
326
402
  clamped: boolean;
327
403
  /**
328
- * The `densityScale` actually applied equal to the requested value unless
404
+ * The `densityScale` actually applied: equal to the requested value unless
329
405
  * `clamped`, then reduced proportionally. `layoutScale × effectiveDensityScale`
330
406
  * is the scale the backing store was rasterized at.
331
407
  */
@@ -348,7 +424,7 @@ export interface ChangeSet {
348
424
  * imported backend build module; `formats`/`canvas` are the REQUIRED static
349
425
  * capability manifest. That manifest is what makes
350
426
  * `Engine.supportedFormats`/`Engine.supportsCanvas` always FREE: they answer
351
- * from it directly no backend binary is loaded and no quill is cloned into
427
+ * from it directly, no backend binary is loaded and no quill is cloned into
352
428
  * backend memory. A malformed descriptor throws at `new Engine(...)`.
353
429
  */
354
430
  export interface BackendDescriptor {
@@ -361,7 +437,7 @@ export interface EngineOptions {
361
437
  /**
362
438
  * Extra or overriding backend descriptors, merged over the built-ins. Keys are
363
439
  * backend ids (as declared by `Quill.yaml`'s `backend:` and reported by
364
- * `Quill.backendId`). Each value is a `BackendDescriptor` `formats`/`canvas`
440
+ * `Quill.backendId`). Each value is a `BackendDescriptor`: `formats`/`canvas`
365
441
  * are required, so capability probes are ALWAYS free (no binary load, no quill
366
442
  * clone). Malformed entries throw at construction. The default registry maps
367
443
  * `"typst"` to the bundled Typst build.
@@ -401,12 +477,12 @@ export declare class Engine {
401
477
  supportedFormats(quill: Quill): Promise<OutputFormat[]>;
402
478
 
403
479
  /**
404
- * Whether `quill`'s BACKEND can paint sessions to a canvas a pre-session
480
+ * Whether `quill`'s BACKEND can paint sessions to a canvas: a pre-session
405
481
  * ESTIMATE, not a fact about any particular compile. Same always-free probe
406
482
  * as `supportedFormats`: answered from the descriptor's required `canvas`
407
483
  * manifest, no binary load and no quill clone. Both the Typst and pdfform
408
484
  * backends report `true` here unconditionally; each paints a complete page
409
- * raster (see {@link LiveSession.paint}) but a specific compile can still
485
+ * raster (see {@link LiveSession.paint}), but a specific compile can still
410
486
  * refuse to paint (e.g. a 0-page document), so this can answer `true` while
411
487
  * the resulting {@link LiveSession.supportsCanvas} answers `false`. Gate
412
488
  * mounting a canvas UI on this; gate the actual `paint` call on the session's
@@ -419,7 +495,7 @@ export declare class Engine {
419
495
  * Iterative render session over a compiled snapshot. `free()` when done.
420
496
  *
421
497
  * CANVAS PAINT IS COMPLETE. {@link LiveSession.paint} writes a complete page
422
- * raster every piece of page content is already visible in the painted
498
+ * raster: every piece of page content is already visible in the painted
423
499
  * pixels, with NO compositing required by the caller. Both backends that
424
500
  * support canvas satisfy this: Typst rasterizes its laid-out page natively;
425
501
  * pdfform pre-flattens bound field values into the page content and rasterizes
@@ -433,7 +509,7 @@ export declare class LiveSession {
433
509
  readonly pageCount: number;
434
510
  readonly backendId: string;
435
511
  /**
436
- * `true` iff `paint`/`pageSize` will succeed for THIS compile the
512
+ * `true` iff `paint`/`pageSize` will succeed for THIS compile: the
437
513
  * authoritative answer, derived from the session's canvas seam, so it can
438
514
  * never disagree with what `paint` actually does. This can be `false` even
439
515
  * when {@link Engine.supportsCanvas} answered `true` for the same `quill`
@@ -444,7 +520,7 @@ export declare class LiveSession {
444
520
  readonly supportsCanvas: boolean;
445
521
  readonly warnings: Diagnostic[];
446
522
  /**
447
- * Recompile the session against `doc` the edit verb of a live preview.
523
+ * Recompile the session against `doc`: the edit verb of a live preview.
448
524
  * Transactional: on throw every read (`render`, `paint`, `pageSize`,
449
525
  * `regions`) keeps serving the last-good compile, and the session recovers
450
526
  * on the next successful `apply`. On success reads serve the new compile;
@@ -464,30 +540,30 @@ export declare class LiveSession {
464
540
  * (so a highlight covers continuation pages); a scalar referenced at
465
541
  * several plate sites surfaces each site; tracked content plus a
466
542
  * `field:`-bound widget yields both, widget ordered first. Group by
467
- * `field` every entry routes to that field. Later placements of one
543
+ * `field`: every entry routes to that field. Later placements of one
468
544
  * content value are not enumerated; {@link fieldAt} still resolves
469
545
  * clicks on them.
470
546
  */
471
547
  regions(): FieldRegion[];
472
548
  /**
473
549
  * The whole-field highlight boxes for `field` (a canonical `DocPath` address,
474
- * as {@link regions} keys) one union rect per page, over the field's
550
+ * as {@link regions} keys): one union rect per page, over the field's
475
551
  * `span`-bearing content segments (the "highlight the focused field"
476
552
  * quantity). Owns the union {@link regions} leaves derived
477
553
  * (span-filter + per-page union), keeping `regions()` the low-level disjoint
478
- * truth, so a consumer stops reimplementing it. **Content only** a field
554
+ * truth, so a consumer stops reimplementing it. **Content only**: a field
479
555
  * placed solely as a scalar reference or a bound widget carries no `span`
480
556
  * and returns `[]`; its box is a single {@link regions} rect. Reflects the
481
557
  * current compile, like `regions()`.
482
558
  */
483
559
  fieldBoxes(field: string): FieldRegion[];
484
560
  /**
485
- * The schema field whose content is under a point on `page` the forward
561
+ * The schema field whose content is under a point on `page`, the forward
486
562
  * (click → field) direction: hit-test a click against the compiled
487
563
  * document and get back the canonical `DocPath` field address
488
564
  * (`parseDocPath`-routable) to focus in the editor, or `undefined` off any
489
565
  * field's ink. `x`/`y` are PDF points with a **bottom-left** origin, the
490
- * same space as {@link FieldRegion.rect} from a canvas click, invert the
566
+ * same space as {@link FieldRegion.rect}, from a canvas click, invert the
491
567
  * overlay transform documented there:
492
568
  * `x = clickPx.x / renderScale`,
493
569
  * `y = pageHeightPt - clickPx.y / renderScale`. Unlike {@link regions},
@@ -500,7 +576,7 @@ export declare class LiveSession {
500
576
  */
501
577
  positionAt(page: number, x: number, y: number): ContentHit | undefined;
502
578
  /**
503
- * Content position → caret rect reverse of {@link positionAt}. `field` is a
579
+ * Content position → caret rect: reverse of {@link positionAt}. `field` is a
504
580
  * canonical `DocPath` address (`parseDocPath`-routable), as {@link regions} keys.
505
581
  */
506
582
  locate(field: string, pos: number): FieldRegion | undefined;
@@ -509,18 +585,18 @@ export declare class LiveSession {
509
585
  /**
510
586
  * Paint `page` into a 2D canvas context, sizing the backing store itself
511
587
  * (it owns `canvas.width`/`height`; the caller owns `canvas.style.*`). The
512
- * painted raster is COMPLETE all page content visible, no caller-side
588
+ * painted raster is COMPLETE: all page content visible, no caller-side
513
589
  * compositing (Typst rasterizes natively; pdfform rasterizes its
514
590
  * pre-flattened page). Effective rasterization scale is
515
591
  * `layoutScale × densityScale`, clamped so neither backing dimension exceeds
516
- * 16384 px {@link PaintResult.clamped} reports the clamp and
592
+ * 16384 px: {@link PaintResult.clamped} reports the clamp and
517
593
  * {@link PaintResult.effectiveDensityScale} the density actually applied.
518
594
  *
519
595
  * The write is a whole-backing-store `putImageData`, which bypasses the 2D
520
596
  * context transform, `globalAlpha`, and clip: the painter owns the entire
521
597
  * canvas, so give each visible page its own `` element. You cannot
522
598
  * paint two pages into one canvas, paint into a sub-rect, or apply a context
523
- * transform through this call the raster is complete precisely so you never
599
+ * transform through this call: the raster is complete precisely so you never
524
600
  * need to. Keep the per-page canvases alive while their pages stay near the
525
601
  * viewport: each `paint` re-rasterizes from scratch, so reusing (pooling) a
526
602
  * canvas across pages on scroll re-runs a full render, whereas an idle canvas
@@ -534,7 +610,7 @@ export declare class LiveSession {
534
610
  free(): void;
535
611
  }
536
612
 
537
- // ── Typed writer the schema-bound front door ───────────────────────────────
613
+ // ── Typed writer: the schema-bound front door ───────────────────────────────
538
614
 
539
615
  // `quill.writer(doc)` is patched onto the re-exported `Quill` prototype (the
540
616
  // class is re-exported verbatim, so the method is declared by merging into the
@@ -542,20 +618,20 @@ export declare class LiveSession {
542
618
  declare module '../core/wasm.js' {
543
619
  interface Quill {
544
620
  /**
545
- * Bind this quill's schema to `doc` for typed writes the documented
621
+ * Bind this quill's schema to `doc` for typed writes: the documented
546
622
  * front door, mirroring core's `quill.writer(&mut doc)`. The schema grants
547
623
  * the typing, so the quill is the factory. The returned writer holds both
548
624
  * handles by reference and owns neither (nothing to `free()`); it is
549
- * ephemeral by convention bind, write, discard.
625
+ * ephemeral by convention: bind, write, discard.
550
626
  */
551
627
  writer(doc: Document): DocumentWriter;
552
628
  /**
553
- * Bind this quill's schema to `doc` for interpreted reads the read twin of
629
+ * Bind this quill's schema to `doc` for interpreted reads: the read twin of
554
630
  * {@link Quill.writer}, mirroring core's `quill.reader(&doc)`. Each field is
555
631
  * read by its declared type (a richtext field to markdown, every other type
556
632
  * verbatim) with schema authority, so a name the schema does not declare
557
633
  * throws rather than reading back `undefined`. Holds both handles by
558
- * reference and owns neither (nothing to `free()`); ephemeral by convention
634
+ * reference and owns neither (nothing to `free()`); ephemeral by convention:
559
635
  * bind, read, discard.
560
636
  */
561
637
  reader(doc: Document): DocumentReader;
@@ -563,22 +639,22 @@ declare module '../core/wasm.js' {
563
639
  }
564
640
 
565
641
  /**
566
- * A `Document` bound to its `Quill` for typed writes the schema-bound writer,
642
+ * A `Document` bound to its `Quill` for typed writes: the schema-bound writer,
567
643
  * constructed via {@link Quill.writer}. Speaks names, values, and markdown. Bare
568
644
  * `set` / `setAll` / `setBody` / `reviseField` / `addCard` / `card(i).set`
569
645
  * instead of threading the `quill` handle through the underscored ABI. Holds both
570
- * handles by reference and owns neither nothing to `free()`.
646
+ * handles by reference and owns neither: nothing to `free()`.
571
647
  *
572
648
  * Typed commit is the default whenever a quill is in hand: it resolves each
573
649
  * field's schema type and strict-commits it, throwing `UnknownField` for a name
574
- * the schema does not declare on the typed path an undeclared name is a typo,
650
+ * the schema does not declare, on the typed path an undeclared name is a typo,
575
651
  * not a fallback. The raw `Document.storeField` / `storeFields` verbs remain the
576
652
  * deliberate quill-free primitive (standalone data, storage/migration infra, or
577
653
  * holding not-yet-conforming in-progress input).
578
654
  */
579
655
  export declare class DocumentWriter {
580
656
  constructor(quill: Quill, doc: Document);
581
- /** The bound document the instance passed in, mutated in place. */
657
+ /** The bound document: the instance passed in, mutated in place. */
582
658
  readonly document: Document;
583
659
  /**
584
660
  * Typed-commit one main-card field (strict coerce, mismatch throws now).
@@ -586,19 +662,19 @@ export declare class DocumentWriter {
586
662
  */
587
663
  set(name: string, value: unknown): void;
588
664
  /**
589
- * Typed-commit several main-card fields atomically nothing is applied on
665
+ * Typed-commit several main-card fields atomically: nothing is applied on
590
666
  * error (throws a {@link QuillmarkError} carrying one diagnostic per
591
667
  * offending field, including an `UnknownField` for each undeclared name).
592
668
  */
593
669
  setAll(fields: Record<string, unknown>): void;
594
670
  /**
595
671
  * Set the main body from markdown (edit semantics: anchors rebase), discarding
596
- * the delta the receipt-free body write. Use `doc.revise({}, md)` for the
672
+ * the delta, the receipt-free body write. Use `doc.revise({}, md)` for the
597
673
  * `Delta` receipt.
598
674
  */
599
675
  setBody(markdown: string): void;
600
676
  /**
601
- * Revise the richtext main-card field `name` from markdown typed *and*
677
+ * Revise the richtext main-card field `name` from markdown: typed *and*
602
678
  * anchor-preserving. Surviving anchors rebase, then the diffed result is
603
679
  * schema-conformed (`richtext(inline)` rejects a multi-block result). Throws
604
680
  * `UnknownField` for a name the schema does not declare. Returns the `Delta`.
@@ -606,7 +682,7 @@ export declare class DocumentWriter {
606
682
  reviseField(name: string, markdown: string): Delta;
607
683
  /**
608
684
  * Build a composable card of `kind`, typed-commit `fields` onto it, set its
609
- * body from optional markdown, and place it the fused `makeCard` + typed
685
+ * body from optional markdown, and place it: the fused `makeCard` + typed
610
686
  * commit + insertion. `at` picks the position: omitted appends, a number
611
687
  * inserts at that index, so a positioned typed insert is one atomic call
612
688
  * rather than `addCard` + `moveCard`. Transactional: a rejected field (throws
@@ -618,9 +694,10 @@ export declare class DocumentWriter {
618
694
  removeCard(index: number): Card | undefined;
619
695
  /**
620
696
  * A {@link CardWriter} for the composable card at `index`. Index validity is
621
- * checked lazily at commit time, so this never throws. The cursor is
622
- * ephemeral a `removeCard`/`addCard` between binding and writing silently
623
- * retargets it; for durable addressing stamp `$id` and re-resolve at write.
697
+ * checked lazily at commit time, so an out-of-range index does not throw here.
698
+ * The cursor is ephemeral: a `removeCard`/`addCard` between binding and writing
699
+ * silently retargets it; for durable addressing stamp `$id` and re-resolve at
700
+ * write.
624
701
  */
625
702
  card(index: number): CardWriter;
626
703
  }
@@ -637,7 +714,7 @@ export declare class CardWriter {
637
714
  readonly index: number;
638
715
  /**
639
716
  * The bound card's `$kind` (empty string when it carries none), read through
640
- * the document mirrors core `CardWriter::kind()`. Throws `IndexOutOfRange`
717
+ * the document: mirrors core `CardWriter::kind()`. Throws `IndexOutOfRange`
641
718
  * if the bound index is out of range.
642
719
  */
643
720
  readonly kind: string;
@@ -646,7 +723,7 @@ export declare class CardWriter {
646
723
  /** Set this card's body from markdown (edit semantics), discarding the delta. */
647
724
  setBody(markdown: string): void;
648
725
  /**
649
- * Revise the richtext field `name` on this card from markdown typed *and*
726
+ * Revise the richtext field `name` on this card from markdown: typed *and*
650
727
  * anchor-preserving; the card twin of {@link DocumentWriter.reviseField}.
651
728
  * Throws `UnknownField` for an undeclared name and `IndexOutOfRange` if the
652
729
  * bound index is out of range. Returns the `Delta`.
@@ -655,12 +732,12 @@ export declare class CardWriter {
655
732
  }
656
733
 
657
734
  /**
658
- * A `Document` bound to its `Quill` for interpreted reads the schema-plane read
735
+ * A `Document` bound to its `Quill` for interpreted reads: the schema-plane read
659
736
  * surface, constructed via {@link Quill.reader} and the read twin of
660
737
  * {@link DocumentWriter}. One `get` reads each field by its declared type: a
661
738
  * richtext field to its markdown projection, a plaintext field to its literal
662
739
  * text, every other type its canonical value verbatim. Holds both handles by
663
- * reference and owns neither nothing to `free()`.
740
+ * reference and owns neither: nothing to `free()`.
664
741
  *
665
742
  * The schema authority is the point: unlike the quill-free transport `Document.getStored`,
666
743
  * a name the schema does not declare throws `UnknownField` (a typo) rather than
@@ -671,7 +748,7 @@ export declare class CardWriter {
671
748
  */
672
749
  export declare class DocumentReader {
673
750
  constructor(quill: Quill, doc: Document);
674
- /** The bound document the instance passed in. */
751
+ /** The bound document: the instance passed in. */
675
752
  readonly document: Document;
676
753
  /**
677
754
  * Read the value at `addr`, interpreted by its declared type: a richtext field
@@ -682,12 +759,13 @@ export declare class DocumentReader {
682
759
  * `IndexOutOfRange` for a bad `addr.card`.
683
760
  */
684
761
  get(addr: Addr | string): unknown;
685
- /** The main body's markdown the quill-free body read. Equals `get({})`. */
762
+ /** The main body's markdown: the quill-free body read. Equals `get({})`. */
686
763
  getBody(): string;
687
764
  /**
688
765
  * A {@link CardReader} for the composable card at `index`. Index validity is
689
- * checked lazily at read time, so this never throws. The cursor is ephemeral —
690
- * a `removeCard`/`addCard` between binding and reading silently retargets it.
766
+ * checked lazily at read time, so an out-of-range index does not throw here.
767
+ * The cursor is ephemeral: a `removeCard`/`addCard` between binding and reading
768
+ * silently retargets it.
691
769
  */
692
770
  card(index: number): CardReader;
693
771
  }
@@ -713,6 +791,6 @@ export declare class CardReader {
713
791
  * `IndexOutOfRange` for a bad index.
714
792
  */
715
793
  get(name: string): unknown;
716
- /** This card's body markdown the card twin of {@link DocumentReader.getBody}. */
794
+ /** This card's body markdown: the card twin of {@link DocumentReader.getBody}. */
717
795
  getBody(): string;
718
796
  }