@quillmark/wasm 0.81.0 → 0.83.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bundler/wasm.d.ts CHANGED
@@ -4,10 +4,10 @@
4
4
  /**
5
5
  * Input shape for `Document.pushCard` and `Document.insertCard`.
6
6
  *
7
- * Only `tag` is required. `fields` defaults to `{}`, `body` to `""`.
7
+ * Only `kind` is required. `fields` defaults to `{}`, `body` to `""`.
8
8
  */
9
9
  export interface CardInput {
10
- tag: string;
10
+ kind: string;
11
11
  fields?: Record<string, unknown>;
12
12
  body?: string;
13
13
  }
@@ -130,8 +130,9 @@ export interface QuillCardSchema {
130
130
  /**
131
131
  * Document schema returned by `Quill.schema`. Includes optional `ui` keys.
132
132
  *
133
- * `main.fields.QUILL` and `card_kinds[name].fields.CARD` are required
134
- * sentinels with `const` values telling consumers what to write.
133
+ * Describes only the user-fillable fields. The quill reference
134
+ * (constructed as `${metadata.name}@${metadata.version}`) and card-kind
135
+ * discriminators are document-level metadata, not schema fields.
135
136
  */
136
137
  export interface QuillSchema {
137
138
  main: QuillCardSchema;
@@ -183,8 +184,8 @@ export interface FormCard {
183
184
  * Schema-aware form view of a document, returned by `Quill.form`.
184
185
  *
185
186
  * - `main` — the main card viewed through the quill's main schema.
186
- * - `cards` — composable card blocks, in document order (unknown tags excluded).
187
- * - `diagnostics` — diagnostics from unknown card tags and validation.
187
+ * - `cards` — composable card blocks, in document order (unknown kinds excluded).
188
+ * - `diagnostics` — diagnostics from unknown card kinds and validation.
188
189
  */
189
190
  export interface Form {
190
191
  main: FormCard;
@@ -200,10 +201,9 @@ export interface Artifact {
200
201
  }
201
202
 
202
203
  export interface Card {
203
- sentinel: string;
204
- tag: string;
205
- frontmatter: Record<string, unknown>;
206
- frontmatterItems: FrontmatterItem[];
204
+ kind: string;
205
+ payloadItems: PayloadItem[];
206
+ ext?: Record<string, unknown> | undefined;
207
207
  body: string;
208
208
  }
209
209
 
@@ -236,394 +236,174 @@ export interface RenderResult {
236
236
  renderTimeMs: number;
237
237
  }
238
238
 
239
- export type FrontmatterItem = { kind: "field"; key: string; value: unknown; fill?: boolean } | { kind: "comment"; text: string; inline?: boolean };
240
-
241
239
  export type OutputFormat = "pdf" | "svg" | "txt" | "png";
242
240
 
241
+ export type PayloadItem = { type: "field"; key: string; value: unknown; fill?: boolean } | { type: "comment"; text: string; inline?: boolean };
242
+
243
243
  export type Severity = "error" | "warning" | "note";
244
244
 
245
245
 
246
246
  /**
247
247
  * Typed in-memory Quillmark document.
248
- *
249
- * Created via `Document.fromMarkdown(markdown)`. Exposes:
250
- * - `quillRef` (string)
251
- * - `frontmatter` (JS object/Record)
252
- * - `body` (string)
253
- * - `cards` (array of Card objects)
254
- * - `warnings` (array of Diagnostic objects)
255
- *
256
- * `toMarkdown()` emits canonical Quillmark Markdown that round-trips back to
257
- * an equal `Document` by value and by type.
258
248
  */
259
249
  export class Document {
260
250
  private constructor();
261
251
  free(): void;
262
252
  [Symbol.dispose](): void;
263
- /**
264
- * Return a fresh `Document` handle with the same parse state.
265
- *
266
- * Mutations on the returned handle do not affect the original and
267
- * vice versa. Parse-time warnings are snapshotted alongside the
268
- * document — they describe the original parse, not the edit
269
- * history of either handle.
270
- */
271
253
  clone(): Document;
272
254
  /**
273
255
  * Schema version this build writes via [`toJson`](Document::to_json).
274
- *
275
- * Compare a payload's [`schemaVersionOf`](Document::schema_version_of)
276
- * against this to detect mismatches before calling
277
- * [`fromJson`](Document::from_json).
278
- *
279
- * The tag tracks the **`Document` model version** — the crate version
280
- * at which the wire format was last changed — not the running crate
281
- * version. Every patch and minor release within the same model
282
- * generation returns the same string; the tag advances only when a
283
- * new schema variant ships.
256
+ * Tracks the `Document` model version (not the running crate version):
257
+ * the tag advances only when the wire format changes, not on every release.
284
258
  */
285
259
  static currentSchemaVersion(): string;
286
260
  /**
287
- * Structural equality against another `Document`.
288
- *
289
- * Compares `main` and `cards` by value (matching core's [`PartialEq`]).
290
- * Parse-time `warnings` are intentionally excluded — they describe the
291
- * source text, not the document's content.
292
- *
293
- * Use this to debounce upstream prop updates: keep the last parsed
294
- * `Document` and compare instead of re-parsing on every keystroke.
261
+ * Structural equality (parse-time `warnings` excluded). Use to debounce
262
+ * upstream prop updates instead of re-parsing on every keystroke.
295
263
  */
296
264
  equals(other: Document): boolean;
297
265
  /**
298
- * Reconstruct a `Document` from its versioned storage DTO string.
266
+ * Reconstruct a `Document` from a versioned storage DTO string produced
267
+ * by [`toJson`](Document::to_json). Unknown `schema` tags are rejected.
268
+ * The result carries no parse-time warnings (`.warnings` is always empty).
299
269
  *
300
- * `json` must be a string produced by [`toJson`](Document::to_json)
301
- * the versioned storage DTO. Parsing and schema dispatch happen inside
302
- * the module via `serde_json`; the JS `JSON` global is not involved.
303
- * Unknown `schema` tags are rejected.
304
- *
305
- * The reconstructed document carries no parse-time warnings — the DTO
306
- * describes content, not source text — so `.warnings` is always empty.
307
- *
308
- * Throws a JS `Error` if `json` is not a valid storage DTO (malformed
309
- * JSON, unknown `schema`, missing fields, or an unparseable quill
310
- * reference).
270
+ * Throws if `json` is not a valid storage DTO (malformed JSON, unknown
271
+ * `schema`, missing fields, or unparseable quill reference).
311
272
  */
312
273
  static fromJson(json: string): Document;
313
274
  /**
314
- * Parse markdown into a typed Document.
315
- *
316
- * Returns the document with any parse-time warnings accessible via `.warnings`.
317
- * Throws on parse errors.
275
+ * Parse markdown into a typed Document. Throws on parse errors.
318
276
  */
319
277
  static fromMarkdown(markdown: string): Document;
320
278
  /**
321
- * Insert a card at the given index.
322
- *
323
- * `index` must be in `0..=cards.length`. Out-of-range throws an `Error`.
324
- *
325
- * Mutators never modify `warnings`.
279
+ * Insert a card at `index` (must be in `0..=cards.length`).
326
280
  */
327
281
  insertCard(index: number, card: CardInput): void;
328
282
  /**
329
- * Move the card at `from` to position `to`.
330
- *
331
- * `from == to` is a no-op. Both indices must be in `0..cards.length`.
332
- * Out-of-range throws an `Error`.
333
- *
334
- * Mutators never modify `warnings`.
283
+ * Move the card at `from` to position `to`. `from == to` is a no-op.
335
284
  */
336
285
  moveCard(from: number, to: number): void;
337
286
  /**
338
287
  * Append a card to the end of the card list.
339
- *
340
- * `card` must be a JS object with a `tag` string field and optional
341
- * `fields` (object) and `body` (string).
342
- *
343
- * Throws an `Error` if `card.tag` is not a valid tag name.
344
- *
345
- * Mutators never modify `warnings`.
288
+ * Throws if `card.kind` is not a valid kind name.
346
289
  */
347
290
  pushCard(card: CardInput): void;
348
- /**
349
- * Remove the card at `index` and return it, or `undefined` if out of range.
350
- *
351
- * Mutators never modify `warnings`.
352
- */
353
291
  removeCard(index: number): Card | undefined;
354
292
  /**
355
- * Remove a frontmatter field on the card at `index`, returning the
356
- * removed value or `undefined` if the field was absent.
357
- *
358
- * Throws if `index` is out of range, `name` is reserved, or `name` does
359
- * not match `[a-z_][a-z0-9_]*`.
360
- *
361
- * Mutators never modify `warnings`.
293
+ * Remove a field on the card at `index`. Returns the removed value or
294
+ * `undefined`. Throws if `index` is out of range or `name` is invalid.
362
295
  */
363
296
  removeCardField(index: number, name: string): any;
364
297
  /**
365
- * Remove a frontmatter field on the main card, returning the removed value or `undefined`.
366
- *
367
- * Throws an `Error` whose message includes the `EditError` variant name
368
- * and details if `name` is reserved (`BODY`, `CARDS`, `QUILL`, `CARD`)
369
- * or does not match `[a-z_][a-z0-9_]*`. Absence of an otherwise-valid
370
- * name returns `undefined`.
371
- *
372
- * Mutators never modify `warnings`.
298
+ * Remove a payload field on the main card, returning the removed value or
299
+ * `undefined`. Throws if `name` does not match `[a-z_][a-z0-9_]*`.
373
300
  */
374
301
  removeField(name: string): any;
375
- /**
376
- * Replace the main card's body (the global Markdown body).
377
- *
378
- * Mutators never modify `warnings`.
379
- */
380
302
  replaceBody(body: string): void;
381
303
  /**
382
- * Read the schema version from a raw storage DTO string without
383
- * performing a full parse, or `undefined`.
384
- *
385
- * Returns the `schema` field as-is — including unknown future versions
386
- * that `fromJson` would reject. Use this to distinguish "this build is
387
- * too old for the payload" from "the payload is corrupt" when
388
- * [`fromJson`](Document::from_json) throws:
389
- *
390
- * ```js
391
- * const v = Document.schemaVersionOf(blob);
392
- * if (v === undefined) {
393
- * // not a stored DTO at all — try fromMarkdown
394
- * } else if (v !== Document.currentSchemaVersion()) {
395
- * // newer (or older unmigrated) schema — prompt the user to upgrade
396
- * } else {
397
- * doc = Document.fromJson(blob);
398
- * }
399
- * ```
304
+ * Read the `schema` version tag from a raw storage DTO string without a
305
+ * full parse, or `undefined`. Returns unknown future versions as-is —
306
+ * useful to distinguish "build too old" from "payload corrupt" when
307
+ * `fromJson` throws.
400
308
  */
401
309
  static schemaVersionOf(json: string): string | undefined;
402
310
  /**
403
- * Replace the tag of the composable card at `index`.
404
- *
405
- * Mutates only the sentinel the card's frontmatter and body are
406
- * untouched. Schema-aware migration (clearing orphan fields, applying
407
- * new defaults) is the caller's responsibility; `setCardTag` is a
408
- * structural primitive.
409
- *
410
- * Throws if `index` is out of range or if `newTag` does not match
411
- * `[a-z_][a-z0-9_]*`.
412
- *
413
- * Mutators never modify `warnings`.
311
+ * Replace the kind of the card at `index`. Payload and body are untouched;
312
+ * schema-aware migration is the caller's responsibility.
313
+ * Throws if `index` is out of range or `newKind` is invalid.
414
314
  */
415
- setCardTag(index: number, new_tag: string): void;
315
+ setCardKind(index: number, new_kind: string): void;
416
316
  /**
417
- * Update a frontmatter field on the main card.
418
- *
419
- * Convenience method: equivalent to `doc.mainMut().setField(name, value)`.
420
- * Clears any existing `!fill` marker on the field.
317
+ * Update a payload field on the main card. Clears any existing `!fill` marker.
421
318
  *
422
- * Throws an `Error` whose message includes the `EditError` variant name and
423
- * details if `name` is reserved (`BODY`, `CARDS`, `QUILL`, `CARD`) or does
424
- * not match `[a-z_][a-z0-9_]*`.
425
- *
426
- * Mutators never modify `warnings`.
319
+ * Throws if `name` does not match `[a-z_][a-z0-9_]*`.
427
320
  */
428
321
  setField(name: string, value: any): void;
429
322
  /**
430
- * Update a frontmatter field on the main card AND mark it as `!fill`.
431
- *
432
- * Convenience method: equivalent to `doc.mainMut().setFill(name, value)`.
433
- *
323
+ * Update a payload field on the main card and mark it as `!fill`.
434
324
  * Throws on invalid name (see [`setField`](Document::set_field)).
435
- *
436
- * Mutators never modify `warnings`.
437
325
  */
438
326
  setFill(name: string, value: any): void;
439
327
  /**
440
- * Replace the QUILL reference string.
441
- *
442
- * Throws if `ref_str` is not a valid `QuillReference`.
443
- *
444
- * Mutators never modify `warnings`.
328
+ * Replace the QUILL reference string. Throws if `ref_str` is invalid.
445
329
  */
446
330
  setQuillRef(ref_str: string): void;
447
331
  /**
448
332
  * Serialize this document to a versioned storage DTO string.
449
333
  *
450
- * Returns the document as a JSON string carrying a `schema` version
451
- * field. The string is produced inside the module via `serde_json` and
452
- * round-trips losslessly back to an equal `Document` via
453
- * [`fromJson`](Document::from_json) — the JS `JSON` global is not
454
- * involved in either direction.
455
- *
456
- * Use this — not [`toMarkdown`](Document::to_markdown) — to persist a
457
- * document across a process restart or crate upgrade; the wire format
458
- * is frozen per `schema` version, whereas Markdown syntax evolves.
459
- * Parse-time `warnings` are not part of the DTO.
460
- *
461
- * The result is standard JSON text, so callers that want to inspect it
462
- * may `JSON.parse` it — but treating it as an opaque blob is the
463
- * intended use.
464
- *
465
- * ## Byte-stability
466
- *
467
- * The output is a **byte-deterministic** function of the document's
468
- * value within a given `schema` version: two documents that compare
469
- * equal under [`equals`](Document::equals) serialize to byte-equal
470
- * strings, and the same document re-serialized in a later patch or
471
- * minor release of this crate (same `schema`) produces the same bytes.
472
- * Content-hash use cases (template-divergence detection, cache keys)
473
- * can rely on this without re-canonicalizing.
334
+ * Prefer this over `toMarkdown` for persistence across restarts or crate
335
+ * upgrades the wire format is frozen per `schema` version. Parse-time
336
+ * `warnings` are excluded from the DTO.
474
337
  *
475
- * Specifics: object fields are emitted in struct-declaration order;
476
- * frontmatter field values preserve their YAML insertion order (no
477
- * key sorting); whitespace is `serde_json`'s compact form (no spaces
478
- * between tokens, no trailing newline); strings use `serde_json`'s
479
- * standard escape set. A schema-version bump may change any of these.
338
+ * Output is **byte-deterministic** within a `schema` version: equal
339
+ * documents produce byte-equal output, safe for content-hash use cases.
480
340
  */
481
341
  toJson(): string;
482
342
  /**
483
- * Emit canonical Quillmark Markdown.
484
- *
485
- * Returns the document serialised as a Quillmark Markdown string.
486
- * The output is type-fidelity round-trip safe: re-parsing the result
487
- * produces a `Document` equal to `self` by value and by type.
343
+ * Emit canonical Quillmark Markdown. Round-trip safe: re-parsing the
344
+ * result produces a `Document` equal to `self` by value and by type.
488
345
  */
489
346
  toMarkdown(): string;
490
347
  /**
491
- * Reconstruct a `Document` from a storage DTO string, or `undefined`.
492
- *
493
- * Like [`fromJson`](Document::from_json), but returns `undefined`
494
- * instead of throwing when `json` is not a valid storage DTO. Use this
495
- * to detect format and fall back without exceptions as control flow:
496
- *
497
- * ```js
498
- * const doc = Document.tryFromJson(content) ?? Document.fromMarkdown(content);
499
- * ```
500
- *
501
- * `undefined` only ever means "not a storage DTO" — `fromMarkdown`
502
- * still throws on genuinely malformed markdown.
348
+ * Like [`fromJson`](Document::from_json) but returns `undefined` instead
349
+ * of throwing when `json` is not a valid storage DTO — use to
350
+ * discriminate format without exceptions as control flow.
351
+ * `undefined` means "not a storage DTO"; `fromMarkdown` still throws on
352
+ * genuinely malformed markdown.
503
353
  */
504
354
  static tryFromJson(json: string): Document | undefined;
505
355
  /**
506
- * Replace the body of the card at `index`.
507
- *
508
- * Throws if `index` is out of range.
509
- *
510
- * Mutators never modify `warnings`.
356
+ * Replace the body of the card at `index`. Throws if out of range.
511
357
  */
512
358
  updateCardBody(index: number, body: string): void;
513
359
  /**
514
360
  * Update a field on the card at `index`.
515
- *
516
- * Convenience method: equivalent to `doc.card_mut(index)?.set_field(name, value)`.
517
- *
518
- * Throws if `index` is out of range, `name` is reserved or invalid, or
519
- * `value` cannot be serialized.
520
- *
521
- * Mutators never modify `warnings`.
361
+ * Throws if `index` is out of range, `name` is reserved or invalid.
522
362
  */
523
363
  updateCardField(index: number, name: string, value: any): void;
524
364
  /**
525
- * Number of composable cards (excludes the main card).
526
- *
527
- * O(1). Use this to validate indices before calling card mutators
528
- * instead of allocating the full `cards` array.
365
+ * Number of composable cards (excludes the main card). O(1).
529
366
  */
530
367
  readonly cardCount: number;
531
- /**
532
- * Ordered list of composable card blocks as typed `Card` objects.
533
- */
534
368
  readonly cards: Card[];
535
369
  /**
536
- * The document's main (entry) card.
537
- *
538
- * Carries the QUILL sentinel, the document-level frontmatter, and the
539
- * global body. Frontmatter/body reads and mutations go through this
540
- * handle — there are no document-level shortcuts after the rework.
541
- *
542
- * Allocates and serializes on each call — cache locally if read in a hot loop.
370
+ * The document's main (entry) card. Allocates and serializes on each
371
+ * call — cache locally if read in a hot loop.
543
372
  */
544
373
  readonly main: Card;
545
- /**
546
- * The QUILL reference string (e.g. `"usaf_memo@0.1"`).
547
- */
548
374
  readonly quillRef: string;
549
- /**
550
- * Non-fatal parse-time warnings as an array of typed `Diagnostic` objects.
551
- */
552
375
  readonly warnings: Diagnostic[];
553
376
  }
554
377
 
555
- /**
556
- * Opaque, shareable Quill handle.
557
- */
558
378
  export class Quill {
559
379
  private constructor();
560
380
  free(): void;
561
381
  [Symbol.dispose](): void;
562
382
  /**
563
- * A blank form for a card of the given kind no document values supplied.
564
- *
565
- * Returns `null` if `cardKind` is not declared in this quill's schema.
566
- * Otherwise returns a plain JS object shaped like a single entry in
567
- * [`Form::cards`].
568
- *
569
- * [`Form::cards`]: quillmark::form::Form::cards
383
+ * Blank `FormCard` for the given card kind. Returns `null` if `cardKind`
384
+ * is not declared in this quill's schema.
570
385
  */
571
386
  blankCard(card_kind: string): FormCard | null;
572
387
  /**
573
- * A blank form for the main card no document values supplied.
574
- *
575
- * Returns a plain JS object with the same shape as one entry in
576
- * [`Form::main`]. Every declared field's `source` is `"default"` (when
577
- * the schema declares a default) or `"missing"`.
578
- *
579
- * [`Form::main`]: quillmark::form::Form::main
388
+ * Blank `FormCard` for the main card with no document values.
389
+ * Every field's `source` is `"default"` or `"missing"`.
580
390
  */
581
391
  blankMain(): FormCard;
582
392
  /**
583
- * The schema-aware form view of `doc`.
584
- *
585
- * Returns a plain JS object (not a class) that is immediately
586
- * `JSON.stringify`-able. The shape mirrors [`Form`]:
587
- *
588
- * ```json
589
- * {
590
- * "main": { "schema": {...}, "values": { "field": {...} } },
591
- * "cards": [ ... ],
592
- * "diagnostics": [ ... ]
593
- * }
594
- * ```
595
- *
596
- * **Snapshot semantics.** This is a read-only snapshot of the document
597
- * at call time. Subsequent edits to `doc` require calling `form` again.
598
- *
599
- * [`Form`]: quillmark::form::Form
393
+ * The schema-aware form view of `doc`. Read-only snapshot at call time;
394
+ * subsequent edits to `doc` require calling `form` again.
600
395
  */
601
396
  form(doc: Document): Form;
602
- /**
603
- * Open an iterative render session for page-selective rendering.
604
- */
605
397
  open(doc: Document): RenderSession;
606
- /**
607
- * Render a document to final artifacts.
608
- */
609
398
  render(doc: Document, opts?: RenderOptions | null): RenderResult;
610
399
  /**
611
400
  * The resolved backend identifier (e.g. `"typst"`).
612
401
  */
613
402
  readonly backendId: string;
614
- /**
615
- * Auto-generated annotated Markdown blueprint for LLM consumers.
616
- */
617
403
  readonly blueprint: string;
618
404
  /**
619
405
  * Identity snapshot of the `quill:` section of `Quill.yaml`, plus
620
- * `supportedFormats` and any custom `quill:` keys.
621
- *
622
- * Consumers that need validation run their own validator against
623
- * `metadata.schema`.
624
- *
625
- * Equivalent by value for the lifetime of the handle; the quill is
626
- * immutable once constructed.
406
+ * `supportedFormats` and any extra `quill:` keys.
627
407
  */
628
408
  readonly metadata: QuillMetadata;
629
409
  /**
@@ -631,25 +411,16 @@ export class Quill {
631
411
  */
632
412
  readonly schema: QuillSchema;
633
413
  /**
634
- * Whether this quill's backend supports canvas preview.
635
- *
636
414
  * `true` iff `RenderSession.paint` and `RenderSession.pageSize` will
637
- * succeed for sessions opened by this quill. Use this as a precondition
638
- * probe before mounting a canvas-based preview UI; the throw on `paint`
639
- * remains the enforcement contract.
415
+ * succeed for sessions opened by this quill. Use as a precondition
416
+ * probe before mounting a canvas-based preview UI.
640
417
  */
641
418
  readonly supportsCanvas: boolean;
642
419
  }
643
420
 
644
- /**
645
- * Quillmark WASM Engine
646
- */
647
421
  export class Quillmark {
648
422
  free(): void;
649
423
  [Symbol.dispose](): void;
650
- /**
651
- * JavaScript constructor: `new Quillmark()`
652
- */
653
424
  constructor();
654
425
  /**
655
426
  * Load a quill from a file tree and attach the appropriate backend.
@@ -663,19 +434,12 @@ export class Quillmark {
663
434
  }
664
435
 
665
436
  /**
666
- * An iterative render handle backed by an immutable compiled snapshot.
667
- *
668
- * Created via [`Quill::open`]. Holds the compiled output so that
669
- * [`RenderSession::render`], [`RenderSession::paint`], and
670
- * [`RenderSession::page_size`] can be called repeatedly without
671
- * recompiling.
437
+ * Iterative render handle backed by an immutable compiled snapshot.
672
438
  *
673
- * **Empty documents.** A document that compiles to zero pages still
674
- * produces a valid session (`pageCount === 0`). Iterating
675
- * `0..pageCount` is then a no-op; calling `paint(ctx, 0)` or
676
- * `pageSize(0)` throws `"... page index 0 out of range
677
- * (pageCount=0)"`. Hosts that surface "no pages to preview" UI should
678
- * branch on `pageCount === 0` rather than on a thrown error.
439
+ * **Empty documents.** A zero-page document yields a valid session
440
+ * (`pageCount === 0`); `paint(ctx, 0)` or `pageSize(0)` throws with
441
+ * `"page index 0 out of range (pageCount=0)"`. Branch on `pageCount === 0`
442
+ * rather than catching the error.
679
443
  */
680
444
  export class RenderSession {
681
445
  private constructor();
@@ -683,94 +447,33 @@ export class RenderSession {
683
447
  [Symbol.dispose](): void;
684
448
  /**
685
449
  * Page dimensions in Typst points (1 pt = 1/72 inch).
686
- *
687
- * Report-only: the painter sizes the canvas itself based on
688
- * `PaintOptions`. Exposed for consumers that need page geometry
689
- * up-front (e.g. to lay out a scrollable list of canvases before
690
- * any pixels are rendered).
691
- *
692
- * Stable for a given `page` across the session's lifetime — the
693
- * compiled document is an immutable snapshot, so callers can cache
694
- * results.
695
- *
696
- * Throws if the underlying backend has no canvas painter (i.e. is not
697
- * the Typst backend) or if `page` is out of range.
450
+ * Throws if the backend has no canvas painter or `page` is out of range.
698
451
  */
699
452
  pageSize(page: number): PageSize;
700
453
  /**
701
- * Paint `page` into a 2D canvas context.
454
+ * Paint `page` into a `CanvasRenderingContext2D` or
455
+ * `OffscreenCanvasRenderingContext2D`. The painter owns
456
+ * `canvas.width`/`height` (no `clearRect` needed); consumers own
457
+ * `canvas.style.*`. If `layoutScale * densityScale` exceeds 16384 px
458
+ * per side, `densityScale` is clamped — detect via `PaintResult.pixelWidth`.
702
459
  *
703
- * Accepts either a `CanvasRenderingContext2D` (main thread) or an
704
- * `OffscreenCanvasRenderingContext2D` (Worker / off-DOM rasterization).
705
- * Both dispatch to the same Rust rasterizer; the dispatch happens at
706
- * the JS boundary so neither context type is privileged.
707
- *
708
- * The painter owns `canvas.width` / `canvas.height` and writes them
709
- * itself; consumers must not. The painter does not touch
710
- * `canvas.style.*` — that's layout, owned by the consumer (see
711
- * `PaintResult.layoutWidth` / `layoutHeight`).
712
- *
713
- * `opts.layoutScale` (default 1.0) is layout-space pixels per Typst
714
- * point and determines the canvas's display-box size. `opts.densityScale`
715
- * (default 1.0) is the rasterization density multiplier the consumer
716
- * folds `window.devicePixelRatio`, in-app zoom, and
717
- * `visualViewport.scale` (pinch-zoom) into. The effective
718
- * rasterization scale is `layoutScale * densityScale`.
719
- *
720
- * If `layoutScale * densityScale` would exceed the safe backing-store
721
- * maximum (16384 px per side), `densityScale` is clamped
722
- * proportionally so the largest dimension fits. The actual
723
- * backing-store dimensions are reported in the returned
724
- * `PaintResult` — compare against
725
- * `round(layoutWidth * densityScale)` to detect clamping.
726
- *
727
- * Each call resets the backing store (`paint` is always a full
728
- * repaint). Consumers do not need to call `clearRect`.
729
- *
730
- * Throws when:
731
- * - the backend does not support canvas preview (message includes the
732
- * resolved `backendId`),
733
- * - `page` is out of range,
734
- * - `ctx` is neither `CanvasRenderingContext2D` nor
735
- * `OffscreenCanvasRenderingContext2D`,
736
- * - `opts.layoutScale` or `opts.densityScale` is non-finite or `<= 0`.
460
+ * Throws if the backend has no canvas painter, `page` is out of range,
461
+ * `ctx` is the wrong type, or either scale is non-finite or `<= 0`.
737
462
  */
738
463
  paint(ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, page: number, opts: PaintOptions | undefined): PaintResult;
739
- /**
740
- * Render all or selected pages from this session.
741
- */
742
464
  render(opts?: RenderOptions | null): RenderResult;
743
465
  /**
744
466
  * The backend that produced this session (e.g. `"typst"`).
745
- *
746
- * Equal to the `backendId` of the [`Quill`] that opened this session
747
- * (sessions inherit their quill's backend), so checking either is fine.
748
467
  */
749
468
  readonly backendId: string;
750
- /**
751
- * Number of pages in this render session.
752
- *
753
- * Stable for the lifetime of the session — the underlying compiled
754
- * document is an immutable snapshot.
755
- */
756
469
  readonly pageCount: number;
757
470
  /**
758
- * Whether this session's backend supports canvas preview.
759
- *
760
- * `true` iff [`paint`](Self::paint) and [`page_size`](Self::page_size)
761
- * will succeed. Equal to `Quill.supportsCanvas` for the quill that
762
- * opened this session.
471
+ * `true` iff `paint` and `pageSize` will succeed for this session.
763
472
  */
764
473
  readonly supportsCanvas: boolean;
765
474
  /**
766
- * Session-level warnings attached at `quill.open(...)` time.
767
- *
768
- * Snapshot of any non-fatal diagnostics emitted while opening the
769
- * session (e.g. version compatibility shims). Stable across the
770
- * session's lifetime. These are also appended to
771
- * [`RenderResult.warnings`] on every `render()` call; the accessor
772
- * surfaces them to canvas-preview consumers that don't go through
773
- * `render()`.
475
+ * Non-fatal diagnostics emitted when opening the session. Also appended
476
+ * to `RenderResult.warnings` on each `render()` call.
774
477
  */
775
478
  readonly warnings: Diagnostic[];
776
479
  }