@quillmark/wasm 0.115.0 → 0.117.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.
@@ -21,6 +21,8 @@ import type {
21
21
  rebase,
22
22
  mapPos,
23
23
  mapMarks,
24
+ isInline,
25
+ isPlain,
24
26
  parseDocPath,
25
27
  formatDocPath,
26
28
  formatDiagnostic
@@ -41,6 +43,8 @@ export interface CoreSurface {
41
43
  rebase: typeof rebase;
42
44
  mapPos: typeof mapPos;
43
45
  mapMarks: typeof mapMarks;
46
+ isInline: typeof isInline;
47
+ isPlain: typeof isPlain;
44
48
  parseDocPath: typeof parseDocPath;
45
49
  formatDocPath: typeof formatDocPath;
46
50
  formatDiagnostic: typeof formatDiagnostic;
@@ -103,6 +107,7 @@ export type {
103
107
  Severity,
104
108
  QuillSchema,
105
109
  QuillFieldSchema,
110
+ QuillFieldType,
106
111
  QuillCardSchema,
107
112
  QuillCardBody,
108
113
  QuillFieldUi,
@@ -292,8 +297,9 @@ export interface ContentHit {
292
297
  *
293
298
  * ```js
294
299
  * const [x0, y0, x1, y1] = region.rect;
295
- * // Into a raster painted at renderScale (= layoutScale × densityScale):
296
- * const left = x0 * renderScale, top = (pageHeightPt - y1) * renderScale;
300
+ * // Into a painted raster, at the scale it was painted at:
301
+ * const scale = canvas.width / pageWidthPt;
302
+ * const left = x0 * scale, top = (pageHeightPt - y1) * scale;
297
303
  * // Or, for an HTML overlay on a width:100% canvas, as % of the page, which
298
304
  * // tracks the displayed size across DPI and pane resize with no scale to thread:
299
305
  * const leftPct = (x0 / pageWidthPt) * 100, topPct = (1 - y1 / pageHeightPt) * 100;
@@ -303,9 +309,9 @@ export interface FieldRegion {
303
309
  /**
304
310
  * The field's canonical `DocPath` address (`parseDocPath`-routable), not a
305
311
  * backend widget name: `main.signature_block`,
306
- * `cards.<kind>[<i>].signature_block` (`cards[<i>].…` when the card's kind is
307
- * unknown), an array element bracketed and a key dotted. The same spelling
308
- * `Diagnostic.path` uses, so the two join on string equality.
312
+ * `cards.<kind>[<i>].signature_block`, an array element bracketed and a key
313
+ * dotted. The same spelling `Diagnostic.path` uses, so the two join on
314
+ * string equality.
309
315
  */
310
316
  field: string;
311
317
  /** 0-based page index. */
@@ -343,36 +349,6 @@ export interface PageSize {
343
349
  heightPt: number;
344
350
  }
345
351
 
346
- /** Inputs to `paint`. */
347
- export interface PaintOptions {
348
- /** How big the page is on screen, in CSS px per point. Default 1. */
349
- layoutScale?: number;
350
- /**
351
- * How sharp it is: `window.devicePixelRatio`, in-app zoom and
352
- * `visualViewport.scale` folded into one number. Default 1, because the
353
- * painter cannot see any of them (SSR, tests, off-screen).
354
- */
355
- densityScale?: number;
356
- }
357
-
358
- /** Output of `paint`. */
359
- export interface PaintResult {
360
- layoutWidth: number; // canvas.style.width target; independent of densityScale
361
- layoutHeight: number;
362
- pixelWidth: number; // canvas.width the painter wrote (clamped at 16384)
363
- pixelHeight: number;
364
- /**
365
- * True when the backing-store clamp forced `densityScale` down: the page
366
- * renders soft at the same `canvas.style` size.
367
- */
368
- clamped: boolean;
369
- /**
370
- * The `densityScale` actually applied, reduced proportionally when
371
- * `clamped`. `layoutScale × effectiveDensityScale` is the rasterized scale.
372
- */
373
- effectiveDensityScale: number;
374
- }
375
-
376
352
  /**
377
353
  * Output of {@link LiveSession.update}: `dirtyPages` lists the pages whose
378
354
  * content differs from the previous compile, including added pages; removed
@@ -425,21 +401,27 @@ export declare class Engine {
425
401
  * synchronously before the first await, so the caller may `free()` them as
426
402
  * soon as this call returns.
427
403
  *
428
- * This is the surface that merges the two warning halves:
429
- * {@link RenderResult.warnings} carries `doc.warnings` (parse, `conform::*`,
430
- * `plate::unsupported_construct`) ahead of the compile's own. A
431
- * {@link LiveSession} outlives the document it opened from, so
432
- * {@link LiveSession.render} carries the compile half alone.
404
+ * {@link RenderResult.warnings} carries the whole pipeline's, in order:
405
+ * `doc.warnings` (parse and `conform::*`), every `quill.validate(doc)`
406
+ * warning, then the compile's own. A {@link LiveSession} outlives the
407
+ * document it opened from, so {@link LiveSession.render} carries the
408
+ * compile's alone: read `doc.warnings` and `quill.validate(doc)` beside it.
409
+ *
410
+ * `today` reads as on {@link open}.
433
411
  */
434
- render(quill: Quill, doc: Document, options?: RenderOptions): Promise<RenderResult>;
412
+ render(quill: Quill, doc: Document, options?: RenderOptions, today?: string): Promise<RenderResult>;
435
413
 
436
414
  /**
437
415
  * Open a live render session (canvas preview / per-page paint / `update`).
438
416
  * The `quill` and `doc` handles are read synchronously before the first
439
417
  * await, so the caller may `free()` them as soon as this call returns; the
440
418
  * caller owns the returned session and must `.free()` it.
419
+ *
420
+ * `today` (`YYYY-MM-DD`, default the local date) is the render date: a
421
+ * `today` date field renders as it, and so does a plate's
422
+ * `datetime.today()`. The session keeps it for every `update`.
441
423
  */
442
- open(quill: Quill, doc: Document): Promise<LiveSession>;
424
+ open(quill: Quill, doc: Document, today?: string): Promise<LiveSession>;
443
425
 
444
426
  /**
445
427
  * Output formats `quill`'s backend can emit. An always-free pre-render probe:
@@ -504,15 +486,17 @@ export declare class LiveSession {
504
486
  * The schema field whose content is under a point on `page`: the canonical
505
487
  * `DocPath` address to focus in the editor, or `undefined` off any field's
506
488
  * ink. `x`/`y` are PDF points with a **bottom-left** origin, the same space as
507
- * {@link FieldRegion.rect}, so from a canvas click invert the overlay
508
- * transform documented there: `x = clickPx.x / renderScale`,
509
- * `y = pageHeightPt - clickPx.y / renderScale`. Unlike {@link regions},
489
+ * {@link FieldRegion.rect}. A pointer event reports CSS pixels, so divide by
490
+ * the CSS px per point the page is shown at,
491
+ * `k = canvas.clientWidth / pageWidthPt`, not by {@link paint}'s `scale`,
492
+ * which carries `devicePixelRatio`: `x = e.offsetX / k`,
493
+ * `y = pageHeightPt - e.offsetY / k`. Unlike {@link regions},
510
494
  * *every* placement answers, not just the first.
511
495
  *
512
496
  * `tolPt` is how far off the ink a click still counts, in the same points,
513
497
  * and defaults to `0` — exact. It is pointer slack, so derive it from the
514
- * scale the page was drawn at (`slackPx / renderScale`) rather than fixing a
515
- * value in points, which shrinks under the cursor as the page zooms out. The
498
+ * same `k` (`slackPx / k`) rather than fixing a value in points, which
499
+ * shrinks under the cursor as the page zooms out. The
516
500
  * nearest placement answers and containment is distance zero, so raising
517
501
  * `tolPt` only ever fills a miss.
518
502
  */
@@ -531,14 +515,16 @@ export declare class LiveSession {
531
515
  * canonical `DocPath` address (`parseDocPath`-routable), as {@link regions} keys.
532
516
  */
533
517
  locate(field: string, pos: number): FieldRegion | undefined;
534
- /** Page geometry in points (1/72″). Report-only; the painter sizes the canvas. */
518
+ /** Page geometry in points (1/72″). */
535
519
  pageSize(page: number): PageSize;
536
520
  /**
537
- * Paint `page` into a 2D canvas context, sizing the backing store itself (it
538
- * owns `canvas.width`/`height`; the caller owns `canvas.style.*`). The
539
- * rasterization scale is `layoutScale × densityScale`, clamped so neither
540
- * backing dimension exceeds 16384 px; {@link PaintResult.clamped} reports the
541
- * clamp and {@link PaintResult.effectiveDensityScale} the density applied.
521
+ * Paint `page` into a 2D canvas context at `scale` backing-store pixels per
522
+ * point: `devicePixelRatio` times the CSS px per point the page is shown at.
523
+ * The painter owns `canvas.width`/`height`, reducing `scale` where it must so
524
+ * neither exceeds 16384 px, so `canvas.width / widthPt` is the scale painted
525
+ * at; the caller owns `canvas.style.*`, and a canvas styled `width: 100%`
526
+ * needs nothing back from the paint. Throws `backend::invalid_raster_scale`
527
+ * on a `scale` that is not finite and positive.
542
528
  *
543
529
  * The write is a whole-backing-store `putImageData`, which bypasses the 2D
544
530
  * context transform, `globalAlpha`, and clip, so give each visible page its
@@ -551,8 +537,8 @@ export declare class LiveSession {
551
537
  paint(
552
538
  ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
553
539
  page: number,
554
- options?: PaintOptions
555
- ): PaintResult;
540
+ scale: number
541
+ ): void;
556
542
  free(): void;
557
543
  }
558
544
 
@@ -656,8 +642,8 @@ export declare class CardWriter {
656
642
  /** The bound card index. */
657
643
  readonly index: number;
658
644
  /**
659
- * The bound card's `$kind`, empty string when it carries none. Throws
660
- * `IndexOutOfRange` for a bad bound index.
645
+ * The bound card's `$kind`. Throws `IndexOutOfRange` for a bad bound
646
+ * index.
661
647
  */
662
648
  readonly kind: string;
663
649
  set(name: string, value: unknown): void;
@@ -738,10 +724,11 @@ export declare class DocumentReader {
738
724
  * The resolved-value view: for every declared field, the value the render
739
725
  * projection would use and the rung it came from (`authored` / `default` /
740
726
  * `blank`). The one read that blank-fills and coerces; {@link get} reports
741
- * what the document carries. Value and provenance only; completeness stays
742
- * `quill.validate`'s.
727
+ * what the document carries. Value and provenance only; diagnostics stay
728
+ * `quill.validate`'s. `today` reads as on {@link Engine.open}; an editor
729
+ * pairing it with a session passes the session's opening date.
743
730
  */
744
- resolve(): Resolved;
731
+ resolve(today?: string): Resolved;
745
732
  /**
746
733
  * A {@link CardReader} for the composable card at `index`. Index validity is
747
734
  * checked lazily at read time, so an out-of-range index does not throw here.
@@ -762,8 +749,8 @@ export declare class CardReader {
762
749
  /** The bound card index. */
763
750
  readonly index: number;
764
751
  /**
765
- * The bound card's `$kind` (empty string when it carries none). Throws
766
- * `IndexOutOfRange` if the bound index is out of range.
752
+ * The bound card's `$kind`. Throws `IndexOutOfRange` if the bound index is
753
+ * out of range.
767
754
  */
768
755
  readonly kind: string;
769
756
  /**
@@ -20,6 +20,7 @@ import initCore, { Quill, Document } from '../core/wasm.js';
20
20
  // Resolution-time, so `node:fs` never enters a browser graph.
21
21
  import { toModuleSource } from '#quillmark-env';
22
22
  import { importMarkdown, exportMarkdown, rebase, mapPos, mapMarks } from '../core/wasm.js';
23
+ import { isInline, isPlain } from '../core/wasm.js';
23
24
  import { parseDocPath, formatDocPath, formatDiagnostic } from '../core/wasm.js';
24
25
 
25
26
  // A `--target web` build exports its classes synchronously but carries no wasm
@@ -49,6 +50,8 @@ const CORE_SURFACE = Object.freeze({
49
50
  rebase,
50
51
  mapPos,
51
52
  mapMarks,
53
+ isInline,
54
+ isPlain,
52
55
  parseDocPath,
53
56
  formatDocPath,
54
57
  formatDiagnostic
@@ -519,15 +522,16 @@ export class Engine {
519
522
  * @param {Quill} quill
520
523
  * @param {Document} doc
521
524
  * @param {object} [options] render options (`{ format, ppi, pages, regions }`)
525
+ * @param {string} [today] the render date, `YYYY-MM-DD`
522
526
  * @returns {Promise<import('./runtime.js').RenderResult>}
523
527
  */
524
- async render(quill, doc, options) {
528
+ async render(quill, doc, options, today) {
525
529
  return this.#withClones(
526
530
  'engine.render(quill, doc)',
527
531
  quill,
528
532
  doc,
529
533
  ({ engine, quill: q, doc: d, docWarnings }) => {
530
- const result = engine.render(q, d, options ?? undefined);
534
+ const result = engine.render(q, d, options ?? undefined, today);
531
535
  result.warnings = docWarnings.concat(result.warnings);
532
536
  return result;
533
537
  }
@@ -537,14 +541,15 @@ export class Engine {
537
541
  /**
538
542
  * @param {Quill} quill
539
543
  * @param {Document} doc
544
+ * @param {string} [today] the render date, `YYYY-MM-DD`
540
545
  * @returns {Promise<LiveSession>}
541
546
  */
542
- async open(quill, doc) {
547
+ async open(quill, doc, today) {
543
548
  return this.#withClones(
544
549
  'engine.open(quill, doc)',
545
550
  quill,
546
551
  doc,
547
- ({ mod, engine, quill: q, doc: d }) => new LiveSession(engine.open(q, d), mod)
552
+ ({ mod, engine, quill: q, doc: d }) => new LiveSession(engine.open(q, d, today), mod)
548
553
  );
549
554
  }
550
555
 
@@ -660,10 +665,10 @@ export class LiveSession {
660
665
  /**
661
666
  * @param {CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D} ctx
662
667
  * @param {number} page
663
- * @param {object} [options]
668
+ * @param {number} scale
664
669
  */
665
- paint(ctx, page, options) {
666
- return this.#inner.paint(ctx, page, options);
670
+ paint(ctx, page, scale) {
671
+ this.#inner.paint(ctx, page, scale);
667
672
  }
668
673
 
669
674
  free() {
@@ -866,10 +871,11 @@ export class DocumentReader {
866
871
  return this.#doc._readerGet(this.#quill, {});
867
872
  }
868
873
  /**
874
+ * @param {string} [today] the render date, `YYYY-MM-DD`
869
875
  * @returns {Resolved}
870
876
  */
871
- resolve() {
872
- return this.#quill._resolve(this.#doc);
877
+ resolve(today) {
878
+ return this.#quill._resolve(this.#doc, today);
873
879
  }
874
880
  /**
875
881
  * @param {number} index