@quillmark/wasm 0.114.0 → 0.116.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/CHANGELOG.md +377 -0
- package/README.md +50 -49
- package/core/wasm.d.ts +93 -118
- package/core/wasm.js +114 -102
- package/core/wasm_bg.wasm +0 -0
- package/core/wasm_bg.wasm.d.ts +5 -5
- package/package.json +1 -1
- package/render/wasm.d.ts +119 -185
- package/render/wasm.js +138 -144
- package/render/wasm_bg.wasm +0 -0
- package/render/wasm_bg.wasm.d.ts +7 -7
- package/runtime/runtime.d.ts +52 -66
- package/runtime/runtime.js +25 -13
package/runtime/runtime.d.ts
CHANGED
|
@@ -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,12 +107,12 @@ export type {
|
|
|
103
107
|
Severity,
|
|
104
108
|
QuillSchema,
|
|
105
109
|
QuillFieldSchema,
|
|
110
|
+
QuillFieldType,
|
|
106
111
|
QuillCardSchema,
|
|
107
112
|
QuillCardBody,
|
|
108
113
|
QuillFieldUi,
|
|
109
114
|
QuillCardUi,
|
|
110
115
|
QuillGroupUi,
|
|
111
|
-
QuillMatrixGroup,
|
|
112
116
|
QuillMetadata
|
|
113
117
|
} from '../core/wasm.js';
|
|
114
118
|
|
|
@@ -182,9 +186,9 @@ export declare function isQuillmarkError(e: unknown): e is QuillmarkError;
|
|
|
182
186
|
|
|
183
187
|
import type { ContentContainer } from '../core/wasm.js';
|
|
184
188
|
|
|
185
|
-
// `ContentIsland.type`, `ContentMark.type`, `ContentLine.kind
|
|
186
|
-
// `ContentContainer.container`
|
|
187
|
-
//
|
|
189
|
+
// `ContentIsland.type`, `ContentMark.type`, `ContentLine.kind` and
|
|
190
|
+
// `ContentContainer.container` are closed sets, so a bare discriminant check
|
|
191
|
+
// narrows the payload on its own:
|
|
188
192
|
// `line.kind === 'heading'` reaches `line.attrs.level`, with no guard to call.
|
|
189
193
|
|
|
190
194
|
/**
|
|
@@ -293,8 +297,9 @@ export interface ContentHit {
|
|
|
293
297
|
*
|
|
294
298
|
* ```js
|
|
295
299
|
* const [x0, y0, x1, y1] = region.rect;
|
|
296
|
-
* // Into a raster
|
|
297
|
-
* const
|
|
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;
|
|
298
303
|
* // Or, for an HTML overlay on a width:100% canvas, as % of the page, which
|
|
299
304
|
* // tracks the displayed size across DPI and pane resize with no scale to thread:
|
|
300
305
|
* const leftPct = (x0 / pageWidthPt) * 100, topPct = (1 - y1 / pageHeightPt) * 100;
|
|
@@ -304,9 +309,9 @@ export interface FieldRegion {
|
|
|
304
309
|
/**
|
|
305
310
|
* The field's canonical `DocPath` address (`parseDocPath`-routable), not a
|
|
306
311
|
* backend widget name: `main.signature_block`,
|
|
307
|
-
* `cards.<kind>[<i>].signature_block
|
|
308
|
-
*
|
|
309
|
-
*
|
|
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.
|
|
310
315
|
*/
|
|
311
316
|
field: string;
|
|
312
317
|
/** 0-based page index. */
|
|
@@ -344,36 +349,6 @@ export interface PageSize {
|
|
|
344
349
|
heightPt: number;
|
|
345
350
|
}
|
|
346
351
|
|
|
347
|
-
/** Inputs to `paint`. */
|
|
348
|
-
export interface PaintOptions {
|
|
349
|
-
/** How big the page is on screen, in CSS px per point. Default 1. */
|
|
350
|
-
layoutScale?: number;
|
|
351
|
-
/**
|
|
352
|
-
* How sharp it is: `window.devicePixelRatio`, in-app zoom and
|
|
353
|
-
* `visualViewport.scale` folded into one number. Default 1, because the
|
|
354
|
-
* painter cannot see any of them (SSR, tests, off-screen).
|
|
355
|
-
*/
|
|
356
|
-
densityScale?: number;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
/** Output of `paint`. */
|
|
360
|
-
export interface PaintResult {
|
|
361
|
-
layoutWidth: number; // canvas.style.width target; independent of densityScale
|
|
362
|
-
layoutHeight: number;
|
|
363
|
-
pixelWidth: number; // canvas.width the painter wrote (clamped at 16384)
|
|
364
|
-
pixelHeight: number;
|
|
365
|
-
/**
|
|
366
|
-
* True when the backing-store clamp forced `densityScale` down: the page
|
|
367
|
-
* renders soft at the same `canvas.style` size.
|
|
368
|
-
*/
|
|
369
|
-
clamped: boolean;
|
|
370
|
-
/**
|
|
371
|
-
* The `densityScale` actually applied, reduced proportionally when
|
|
372
|
-
* `clamped`. `layoutScale × effectiveDensityScale` is the rasterized scale.
|
|
373
|
-
*/
|
|
374
|
-
effectiveDensityScale: number;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
352
|
/**
|
|
378
353
|
* Output of {@link LiveSession.update}: `dirtyPages` lists the pages whose
|
|
379
354
|
* content differs from the previous compile, including added pages; removed
|
|
@@ -426,21 +401,27 @@ export declare class Engine {
|
|
|
426
401
|
* synchronously before the first await, so the caller may `free()` them as
|
|
427
402
|
* soon as this call returns.
|
|
428
403
|
*
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
*
|
|
432
|
-
*
|
|
433
|
-
*
|
|
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}.
|
|
434
411
|
*/
|
|
435
|
-
render(quill: Quill, doc: Document, options?: RenderOptions): Promise<RenderResult>;
|
|
412
|
+
render(quill: Quill, doc: Document, options?: RenderOptions, today?: string): Promise<RenderResult>;
|
|
436
413
|
|
|
437
414
|
/**
|
|
438
415
|
* Open a live render session (canvas preview / per-page paint / `update`).
|
|
439
416
|
* The `quill` and `doc` handles are read synchronously before the first
|
|
440
417
|
* await, so the caller may `free()` them as soon as this call returns; the
|
|
441
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`.
|
|
442
423
|
*/
|
|
443
|
-
open(quill: Quill, doc: Document): Promise<LiveSession>;
|
|
424
|
+
open(quill: Quill, doc: Document, today?: string): Promise<LiveSession>;
|
|
444
425
|
|
|
445
426
|
/**
|
|
446
427
|
* Output formats `quill`'s backend can emit. An always-free pre-render probe:
|
|
@@ -505,15 +486,17 @@ export declare class LiveSession {
|
|
|
505
486
|
* The schema field whose content is under a point on `page`: the canonical
|
|
506
487
|
* `DocPath` address to focus in the editor, or `undefined` off any field's
|
|
507
488
|
* ink. `x`/`y` are PDF points with a **bottom-left** origin, the same space as
|
|
508
|
-
* {@link FieldRegion.rect}
|
|
509
|
-
*
|
|
510
|
-
* `
|
|
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},
|
|
511
494
|
* *every* placement answers, not just the first.
|
|
512
495
|
*
|
|
513
496
|
* `tolPt` is how far off the ink a click still counts, in the same points,
|
|
514
497
|
* and defaults to `0` — exact. It is pointer slack, so derive it from the
|
|
515
|
-
*
|
|
516
|
-
*
|
|
498
|
+
* same `k` (`slackPx / k`) rather than fixing a value in points, which
|
|
499
|
+
* shrinks under the cursor as the page zooms out. The
|
|
517
500
|
* nearest placement answers and containment is distance zero, so raising
|
|
518
501
|
* `tolPt` only ever fills a miss.
|
|
519
502
|
*/
|
|
@@ -532,14 +515,16 @@ export declare class LiveSession {
|
|
|
532
515
|
* canonical `DocPath` address (`parseDocPath`-routable), as {@link regions} keys.
|
|
533
516
|
*/
|
|
534
517
|
locate(field: string, pos: number): FieldRegion | undefined;
|
|
535
|
-
/** Page geometry in points (1/72″).
|
|
518
|
+
/** Page geometry in points (1/72″). */
|
|
536
519
|
pageSize(page: number): PageSize;
|
|
537
520
|
/**
|
|
538
|
-
* Paint `page` into a 2D canvas context
|
|
539
|
-
*
|
|
540
|
-
*
|
|
541
|
-
*
|
|
542
|
-
*
|
|
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.
|
|
543
528
|
*
|
|
544
529
|
* The write is a whole-backing-store `putImageData`, which bypasses the 2D
|
|
545
530
|
* context transform, `globalAlpha`, and clip, so give each visible page its
|
|
@@ -552,8 +537,8 @@ export declare class LiveSession {
|
|
|
552
537
|
paint(
|
|
553
538
|
ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
|
|
554
539
|
page: number,
|
|
555
|
-
|
|
556
|
-
):
|
|
540
|
+
scale: number
|
|
541
|
+
): void;
|
|
557
542
|
free(): void;
|
|
558
543
|
}
|
|
559
544
|
|
|
@@ -657,8 +642,8 @@ export declare class CardWriter {
|
|
|
657
642
|
/** The bound card index. */
|
|
658
643
|
readonly index: number;
|
|
659
644
|
/**
|
|
660
|
-
* The bound card's `$kind
|
|
661
|
-
*
|
|
645
|
+
* The bound card's `$kind`. Throws `IndexOutOfRange` for a bad bound
|
|
646
|
+
* index.
|
|
662
647
|
*/
|
|
663
648
|
readonly kind: string;
|
|
664
649
|
set(name: string, value: unknown): void;
|
|
@@ -739,10 +724,11 @@ export declare class DocumentReader {
|
|
|
739
724
|
* The resolved-value view: for every declared field, the value the render
|
|
740
725
|
* projection would use and the rung it came from (`authored` / `default` /
|
|
741
726
|
* `blank`). The one read that blank-fills and coerces; {@link get} reports
|
|
742
|
-
* what the document carries. Value and provenance only;
|
|
743
|
-
* `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.
|
|
744
730
|
*/
|
|
745
|
-
resolve(): Resolved;
|
|
731
|
+
resolve(today?: string): Resolved;
|
|
746
732
|
/**
|
|
747
733
|
* A {@link CardReader} for the composable card at `index`. Index validity is
|
|
748
734
|
* checked lazily at read time, so an out-of-range index does not throw here.
|
|
@@ -763,8 +749,8 @@ export declare class CardReader {
|
|
|
763
749
|
/** The bound card index. */
|
|
764
750
|
readonly index: number;
|
|
765
751
|
/**
|
|
766
|
-
* The bound card's `$kind
|
|
767
|
-
*
|
|
752
|
+
* The bound card's `$kind`. Throws `IndexOutOfRange` if the bound index is
|
|
753
|
+
* out of range.
|
|
768
754
|
*/
|
|
769
755
|
readonly kind: string;
|
|
770
756
|
/**
|
package/runtime/runtime.js
CHANGED
|
@@ -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
|
|
@@ -174,7 +177,7 @@ const HANDLE_KINDS = {
|
|
|
174
177
|
},
|
|
175
178
|
Document: {
|
|
176
179
|
code: 'runtime::not_a_document',
|
|
177
|
-
hint: 'Pass a Document built by Document.fromMarkdown / fromStored or quill.seedDocument. A Document from another copy of @quillmark/wasm is refused too — each copy is its own WASM linear memory and its own class — so run `npm ls @quillmark/wasm` and dedupe to one.'
|
|
180
|
+
hint: 'Pass a Document built by Document.fromMarkdown / fromStored or quill.seedDocument / emptyDocument. A Document from another copy of @quillmark/wasm is refused too — each copy is its own WASM linear memory and its own class — so run `npm ls @quillmark/wasm` and dedupe to one.'
|
|
178
181
|
}
|
|
179
182
|
};
|
|
180
183
|
|
|
@@ -219,9 +222,15 @@ function requireLocalQuill(quill, method) {
|
|
|
219
222
|
// WELD_KEYS is the rule `Container::same_weld` owns upstream: which `attrs`
|
|
220
223
|
// entries two adjacent runs must share for the markdown projection to read them
|
|
221
224
|
// as one. `start` is not among them, since CommonMark reads only a list's first
|
|
222
|
-
// number — a subset, which is why every container needs its own entry.
|
|
223
|
-
//
|
|
224
|
-
//
|
|
225
|
+
// number — a subset, which is why every container needs its own entry.
|
|
226
|
+
//
|
|
227
|
+
// Re-spelled here rather than called, because `assignInstances` answers before
|
|
228
|
+
// wasm initializes (`prose/canon/BINDINGS.md` § "WebAssembly"). What holds the
|
|
229
|
+
// two spellings equal is running the rule, not comparing their sources:
|
|
230
|
+
// `runtime.test.js` § "container run boundaries" stamps a pair and re-imports
|
|
231
|
+
// it, where `Content::normalize` re-mints against the Rust predicate. A tag the
|
|
232
|
+
// table omits welds with nothing, so `tests/known_names_drift.rs` pins that
|
|
233
|
+
// every container has an entry.
|
|
225
234
|
|
|
226
235
|
const WELD_KEYS = { list_item: ['ordered'], quote: [] };
|
|
227
236
|
|
|
@@ -513,15 +522,16 @@ export class Engine {
|
|
|
513
522
|
* @param {Quill} quill
|
|
514
523
|
* @param {Document} doc
|
|
515
524
|
* @param {object} [options] render options (`{ format, ppi, pages, regions }`)
|
|
525
|
+
* @param {string} [today] the render date, `YYYY-MM-DD`
|
|
516
526
|
* @returns {Promise<import('./runtime.js').RenderResult>}
|
|
517
527
|
*/
|
|
518
|
-
async render(quill, doc, options) {
|
|
528
|
+
async render(quill, doc, options, today) {
|
|
519
529
|
return this.#withClones(
|
|
520
530
|
'engine.render(quill, doc)',
|
|
521
531
|
quill,
|
|
522
532
|
doc,
|
|
523
533
|
({ engine, quill: q, doc: d, docWarnings }) => {
|
|
524
|
-
const result = engine.render(q, d, options ?? undefined);
|
|
534
|
+
const result = engine.render(q, d, options ?? undefined, today);
|
|
525
535
|
result.warnings = docWarnings.concat(result.warnings);
|
|
526
536
|
return result;
|
|
527
537
|
}
|
|
@@ -531,14 +541,15 @@ export class Engine {
|
|
|
531
541
|
/**
|
|
532
542
|
* @param {Quill} quill
|
|
533
543
|
* @param {Document} doc
|
|
544
|
+
* @param {string} [today] the render date, `YYYY-MM-DD`
|
|
534
545
|
* @returns {Promise<LiveSession>}
|
|
535
546
|
*/
|
|
536
|
-
async open(quill, doc) {
|
|
547
|
+
async open(quill, doc, today) {
|
|
537
548
|
return this.#withClones(
|
|
538
549
|
'engine.open(quill, doc)',
|
|
539
550
|
quill,
|
|
540
551
|
doc,
|
|
541
|
-
({ 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)
|
|
542
553
|
);
|
|
543
554
|
}
|
|
544
555
|
|
|
@@ -654,10 +665,10 @@ export class LiveSession {
|
|
|
654
665
|
/**
|
|
655
666
|
* @param {CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D} ctx
|
|
656
667
|
* @param {number} page
|
|
657
|
-
* @param {
|
|
668
|
+
* @param {number} scale
|
|
658
669
|
*/
|
|
659
|
-
paint(ctx, page,
|
|
660
|
-
|
|
670
|
+
paint(ctx, page, scale) {
|
|
671
|
+
this.#inner.paint(ctx, page, scale);
|
|
661
672
|
}
|
|
662
673
|
|
|
663
674
|
free() {
|
|
@@ -860,10 +871,11 @@ export class DocumentReader {
|
|
|
860
871
|
return this.#doc._readerGet(this.#quill, {});
|
|
861
872
|
}
|
|
862
873
|
/**
|
|
874
|
+
* @param {string} [today] the render date, `YYYY-MM-DD`
|
|
863
875
|
* @returns {Resolved}
|
|
864
876
|
*/
|
|
865
|
-
resolve() {
|
|
866
|
-
return this.#quill._resolve(this.#doc);
|
|
877
|
+
resolve(today) {
|
|
878
|
+
return this.#quill._resolve(this.#doc, today);
|
|
867
879
|
}
|
|
868
880
|
/**
|
|
869
881
|
* @param {number} index
|