@quillmark/wasm 0.104.0 → 0.106.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 +244 -27
- package/README.md +72 -206
- package/backends/pdfform/wasm.d.ts +465 -713
- package/backends/pdfform/wasm.js +365 -491
- package/backends/pdfform/wasm_bg.wasm +0 -0
- package/backends/pdfform/wasm_bg.wasm.d.ts +1 -0
- package/backends/typst/wasm.d.ts +465 -713
- package/backends/typst/wasm.js +365 -491
- package/backends/typst/wasm_bg.wasm +0 -0
- package/backends/typst/wasm_bg.wasm.d.ts +1 -0
- package/core/wasm.d.ts +337 -492
- package/core/wasm.js +310 -411
- package/core/wasm_bg.wasm +0 -0
- package/core/wasm_bg.wasm.d.ts +1 -0
- package/package.json +1 -1
- package/runtime/runtime.d.ts +181 -255
- package/runtime/runtime.js +190 -353
package/runtime/runtime.d.ts
CHANGED
|
@@ -1,22 +1,16 @@
|
|
|
1
1
|
// @quillmark/wasm/runtime: canonical consumer API.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// via `npm run typecheck`) asserts they stay mutually assignable with the Typst
|
|
8
|
-
// backend's generated declarations. `Engine` is the render dispatcher that hides
|
|
9
|
-
// the cross-WASM-memory seam.
|
|
10
|
-
|
|
11
|
-
// CANONICAL INVARIANT: the `Quill`/`Document` `init` resolves to ARE the core
|
|
12
|
-
// build's classes, their full surface, never wrappers. There is exactly one
|
|
13
|
-
// public entry point, so this is a structural fact. Handing out a wrapper is a
|
|
14
|
-
// breaking design change, not a refactor. See runtime.js.
|
|
3
|
+
// The render-side types are defined HERE as the backend-neutral render contract,
|
|
4
|
+
// not sourced from any one private backend build; `runtime.types.test-d.ts`
|
|
5
|
+
// asserts they stay mutually assignable with the Typst backend's generated
|
|
6
|
+
// declarations.
|
|
15
7
|
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
8
|
+
// The `Quill`/`Document` `init` resolves to ARE the core build's classes, never
|
|
9
|
+
// wrappers. Two copies of this package are two WASM linear memories and two
|
|
10
|
+
// `Quill`/`Document` classes, so every method taking a handle refuses one
|
|
11
|
+
// belonging to another copy, with a `QuillmarkError` naming
|
|
12
|
+
// `npm ls @quillmark/wasm`. Errors are the exception: `isQuillmarkError` is
|
|
13
|
+
// structural.
|
|
20
14
|
|
|
21
15
|
// The instance types, so an annotation (`let q: Quill`) needs no await. Their
|
|
22
16
|
// values are `CoreSurface`'s.
|
|
@@ -35,13 +29,11 @@ import type {
|
|
|
35
29
|
} from '../core/wasm.js';
|
|
36
30
|
|
|
37
31
|
/**
|
|
38
|
-
* The core build's surface
|
|
39
|
-
*
|
|
40
|
-
* way to hold one.
|
|
32
|
+
* The core build's surface, and therefore what `init` resolves to. Exported
|
|
33
|
+
* nowhere statically, so awaiting is the only way to hold one.
|
|
41
34
|
*
|
|
42
|
-
* `Quill` and `Document` here are the classes, statics included
|
|
43
|
-
*
|
|
44
|
-
* Each member carries the core build's own declaration, docs and all.
|
|
35
|
+
* `Quill` and `Document` here are the classes, statics included, not the
|
|
36
|
+
* instance types above.
|
|
45
37
|
*/
|
|
46
38
|
export interface CoreSurface {
|
|
47
39
|
Quill: typeof CoreQuill;
|
|
@@ -62,24 +54,17 @@ export interface CoreSurface {
|
|
|
62
54
|
* const { Quill, Document } = await init();
|
|
63
55
|
* ```
|
|
64
56
|
*
|
|
65
|
-
* The
|
|
66
|
-
*
|
|
67
|
-
* fetched and streamed in a browser, read off disk under Node, and the call
|
|
68
|
-
* site is the same line.
|
|
57
|
+
* The same line works everywhere: the binary streams from a URL in a browser
|
|
58
|
+
* and is read off disk under Node.
|
|
69
59
|
*
|
|
70
|
-
*
|
|
60
|
+
* The only door to `Quill`, `Document` and the free functions, so the pre-init
|
|
71
61
|
* mistake is not expressible. Destructure at each entry point (route loader,
|
|
72
62
|
* hydration path, worker) rather than threading one result around: the gate is
|
|
73
|
-
* memoized and concurrency-safe, so every await after the first is free
|
|
74
|
-
* failed init clears the memo
|
|
75
|
-
* loads and initializes its own copy.
|
|
63
|
+
* memoized and concurrency-safe, so every await after the first is free, and a
|
|
64
|
+
* failed init clears the memo. Each realm initializes its own copy.
|
|
76
65
|
*
|
|
77
|
-
* Both failure codes
|
|
78
|
-
*
|
|
79
|
-
* promise-returning verb rejects, and nothing does both.
|
|
80
|
-
*
|
|
81
|
-
* Backends are NOT initialized here. `Engine` instantiates a backend inside its
|
|
82
|
-
* lazy load, on first render against it.
|
|
66
|
+
* Both failure codes reject, so one `catch` covers the gate. Backends are not
|
|
67
|
+
* initialized here: `Engine` instantiates one on first render against it.
|
|
83
68
|
*
|
|
84
69
|
* @param source override the binary's source (bytes, a `Response`, a
|
|
85
70
|
* `WebAssembly.Module`, a URL) for hosts that route assets themselves or
|
|
@@ -92,11 +77,9 @@ export declare function init(source?: InitInput): Promise<CoreSurface>;
|
|
|
92
77
|
import type { CardAddr } from '../core/wasm.js';
|
|
93
78
|
|
|
94
79
|
/**
|
|
95
|
-
* The main card's address:
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* `doc.storeFields(MAIN_CARD_ADDR, fields)`. It IS `{}` (frozen at runtime), a
|
|
99
|
-
* pure alias: `{}` and `undefined` stay equally valid. A card selector only,
|
|
80
|
+
* The main card's address: a named, {@link CardAddr}-typed alias for the empty
|
|
81
|
+
* address `{}`, so a main-card write names its target. It *is* `{}` (frozen at
|
|
82
|
+
* runtime), so `{}` and `undefined` stay equally valid. A card selector only,
|
|
100
83
|
* never a field address.
|
|
101
84
|
*/
|
|
102
85
|
export declare const MAIN_CARD_ADDR: CardAddr;
|
|
@@ -193,23 +176,17 @@ export interface QuillmarkError extends Error {
|
|
|
193
176
|
/**
|
|
194
177
|
* Narrow an unknown caught value to {@link QuillmarkError}. Structural
|
|
195
178
|
* (`Error` carrying a `diagnostics` array), so it narrows errors from any build
|
|
196
|
-
* or WASM instance in the page
|
|
197
|
-
*
|
|
198
|
-
* passed, since two copies are two linear memories. An error is data, not a
|
|
199
|
-
* handle, so nothing is gained by refusing one that crossed.
|
|
179
|
+
* or WASM instance in the page — unlike a handle, which is refused when it
|
|
180
|
+
* comes from a second copy of this package.
|
|
200
181
|
*/
|
|
201
182
|
export declare function isQuillmarkError(e: unknown): e is QuillmarkError;
|
|
202
183
|
|
|
203
|
-
// ── Open-set discriminant guards ────────────────────────────────────────────
|
|
204
184
|
// `ContentIsland.type`, `ContentMark.type`, `ContentLine.kind`, and
|
|
205
185
|
// `ContentContainer.container` are open sets: each union has a residual
|
|
206
186
|
// `{ …: string; … }` arm, so a bare discriminant check never narrows the payload
|
|
207
187
|
// (TS keeps the residual arm live, since a `string` can equal the literal).
|
|
208
|
-
// These guards are the checked narrowing path for the pinned arms;
|
|
209
|
-
//
|
|
210
|
-
// the payload-carrying arms get a guard: the bare marks
|
|
211
|
-
// (`strong`/`emph`/`underline`/`strike`/`code`), the payload-free lines
|
|
212
|
-
// (`para`/`island`/`rule`), and `quote` narrow to nothing.
|
|
188
|
+
// These guards are the checked narrowing path for the pinned arms; only the
|
|
189
|
+
// payload-carrying arms get one, since the rest narrow to nothing.
|
|
213
190
|
|
|
214
191
|
import type {
|
|
215
192
|
ContentIsland,
|
|
@@ -260,14 +237,11 @@ export declare function isListItemContainer(
|
|
|
260
237
|
ordinal: number;
|
|
261
238
|
};
|
|
262
239
|
|
|
263
|
-
//
|
|
264
|
-
//
|
|
265
|
-
//
|
|
266
|
-
//
|
|
267
|
-
//
|
|
268
|
-
// unless it is carried inertly. Without a predicate a consumer enumerates the
|
|
269
|
-
// built-in names itself and re-couples to a closed set, going wrong at the first
|
|
270
|
-
// release that adds one.
|
|
240
|
+
// The guards above answer "is this arm X". These four answer "is this a value
|
|
241
|
+
// this build knows?", the question a read-modify-write consumer must ask: an
|
|
242
|
+
// edit restates every line's kind and containers, so a construct the consumer
|
|
243
|
+
// cannot hold is gone on write-back unless carried inertly, and enumerating the
|
|
244
|
+
// built-in names by hand re-couples to a closed set.
|
|
271
245
|
//
|
|
272
246
|
// They classify unknown TAGS, not unknown payloads on known tags: a future
|
|
273
247
|
// `kind: "footnote"` carrying a sibling `ref` loses `ref` at any consumer that
|
|
@@ -293,36 +267,30 @@ export declare function isUnknownIsland(
|
|
|
293
267
|
island: ContentIsland
|
|
294
268
|
): island is ContentIsland & { type: string; props: unknown };
|
|
295
269
|
|
|
296
|
-
//
|
|
297
|
-
//
|
|
298
|
-
//
|
|
299
|
-
//
|
|
300
|
-
// these shapes; that they match the Typst backend's generated declarations is
|
|
301
|
-
// enforced by the type-level drift guard `crates/bindings/wasm/runtime.types.test-d.ts`
|
|
302
|
-
// (run via `npm run typecheck`), so these and the generated
|
|
303
|
-
// `pkg/backends/typst/wasm.d.ts` cannot silently diverge.
|
|
270
|
+
// The backend-neutral render contract, defined here rather than re-exported from
|
|
271
|
+
// one private backend because no single backend owns the canonical API's types.
|
|
272
|
+
// Every backend build must satisfy these shapes; `runtime.types.test-d.ts` keeps
|
|
273
|
+
// them from diverging from the generated `pkg/backends/typst/wasm.d.ts`.
|
|
304
274
|
|
|
305
275
|
import type { Quill, Document, Card } from '../core/wasm.js';
|
|
306
276
|
import type { Diagnostic } from '../core/wasm.js';
|
|
307
277
|
|
|
308
|
-
/**
|
|
278
|
+
/** One emitted output. */
|
|
309
279
|
export interface Artifact {
|
|
310
280
|
format: OutputFormat;
|
|
311
281
|
bytes: Uint8Array;
|
|
312
282
|
mimeType: string;
|
|
313
283
|
}
|
|
314
284
|
|
|
315
|
-
/**
|
|
285
|
+
/** Options for one render. */
|
|
316
286
|
export interface RenderOptions {
|
|
317
287
|
format?: OutputFormat;
|
|
318
288
|
ppi?: number;
|
|
319
289
|
pages?: number[];
|
|
320
290
|
producer?: string;
|
|
321
291
|
/**
|
|
322
|
-
* Populate {@link RenderResult.regions} with
|
|
323
|
-
*
|
|
324
|
-
* consumers without a live session; e.g. overlays over a one-shot SVG
|
|
325
|
-
* export. Defaults to `false`: exports pay no introspection cost.
|
|
292
|
+
* Populate {@link RenderResult.regions} with schema-field geometry, for
|
|
293
|
+
* consumers without a live session. Defaults to `false`.
|
|
326
294
|
*/
|
|
327
295
|
regions?: boolean;
|
|
328
296
|
}
|
|
@@ -332,12 +300,10 @@ export interface RenderOptions {
|
|
|
332
300
|
* to decide whether to trust the offset. Never sub-cluster: `'cluster'` is the
|
|
333
301
|
* finest, `'segment'` the floor it degrades to on origin-less ink.
|
|
334
302
|
*
|
|
335
|
-
* - `'cluster'`: `pos` is the first content char of the cluster under the point
|
|
336
|
-
*
|
|
337
|
-
*
|
|
338
|
-
*
|
|
339
|
-
* multi-line code fence's interior), so `pos` degraded to the containing
|
|
340
|
-
* segment's start. Treat `pos` as the selected segment, not a caret.
|
|
303
|
+
* - `'cluster'`: `pos` is the first content char of the cluster under the point.
|
|
304
|
+
* Place the caret there directly.
|
|
305
|
+
* - `'segment'`: the point hit origin-less ink (list markers, numbering, a code
|
|
306
|
+
* fence's interior), so `pos` is the containing segment's start, not a caret.
|
|
341
307
|
*/
|
|
342
308
|
export type HitGranularity = 'cluster' | 'segment';
|
|
343
309
|
|
|
@@ -358,24 +324,19 @@ export interface ContentHit {
|
|
|
358
324
|
|
|
359
325
|
/**
|
|
360
326
|
* A rendered field region: the canonical `DocPath` field address (`field`) plus
|
|
361
|
-
* its geometry (`rect`) on the page.
|
|
362
|
-
*
|
|
363
|
-
* richtext bodies, `richtext[]` elements, card content fields, direct scalar
|
|
364
|
-
* references). Only fields with a schema address produce a region: a
|
|
365
|
-
* backend-only widget produces none, and the backend widget name never
|
|
327
|
+
* its geometry (`rect`) on the page. Only fields with a schema address produce
|
|
328
|
+
* one: a backend-only widget produces none, and the backend widget name never
|
|
366
329
|
* appears.
|
|
367
330
|
*
|
|
368
|
-
* Use it to scroll to
|
|
331
|
+
* Use it to scroll to or highlight the focused field's rect; for the click
|
|
369
332
|
* direction use {@link LiveSession.fieldAt}, which resolves a point on *any*
|
|
370
|
-
* placement, not just the first one surfaced here.
|
|
371
|
-
* `LiveSession.paint` already bakes every value into the raster (see
|
|
372
|
-
* {@link LiveSession}), so a region is never a compositing input.
|
|
333
|
+
* placement, not just the first one surfaced here.
|
|
373
334
|
*
|
|
374
335
|
* COORDINATE TRANSFORM. `rect` is in PDF points with a **bottom-left** origin.
|
|
375
336
|
*
|
|
376
337
|
* For an **HTML/CSS overlay** on a `width:100%` canvas, position hotspots as
|
|
377
|
-
* percentages of the page
|
|
378
|
-
* resize for free
|
|
338
|
+
* percentages of the page, so they track the displayed size across DPI and pane
|
|
339
|
+
* resize for free; only the Y axis flips:
|
|
379
340
|
*
|
|
380
341
|
* ```js
|
|
381
342
|
* const [x0, y0, x1, y1] = region.rect; // PDF pt, bottom-left origin
|
|
@@ -396,12 +357,10 @@ export interface ContentHit {
|
|
|
396
357
|
export interface FieldRegion {
|
|
397
358
|
/**
|
|
398
359
|
* The field's canonical `DocPath` address (`parseDocPath`-routable), not a
|
|
399
|
-
* backend widget name: `main.signature_block
|
|
400
|
-
* `cards.<kind>[<i>].signature_block`
|
|
401
|
-
*
|
|
402
|
-
*
|
|
403
|
-
* `cards.<kind>[<i>].addr.city` — the same spelling `Diagnostic.path` uses,
|
|
404
|
-
* so the two join on string equality.
|
|
360
|
+
* backend widget name: `main.signature_block`,
|
|
361
|
+
* `cards.<kind>[<i>].signature_block` (`cards[<i>].…` when the card's kind is
|
|
362
|
+
* unknown), an array element bracketed and a key dotted. The same spelling
|
|
363
|
+
* `Diagnostic.path` uses, so the two join on string equality.
|
|
405
364
|
*/
|
|
406
365
|
field: string;
|
|
407
366
|
/** 0-based page index. */
|
|
@@ -418,67 +377,54 @@ export interface FieldRegion {
|
|
|
418
377
|
span?: [number, number];
|
|
419
378
|
}
|
|
420
379
|
|
|
421
|
-
/**
|
|
380
|
+
/** Result of one render. */
|
|
422
381
|
export interface RenderResult {
|
|
423
382
|
artifacts: Artifact[];
|
|
424
383
|
warnings: Diagnostic[];
|
|
425
384
|
outputFormat: OutputFormat;
|
|
426
385
|
renderTimeMs: number;
|
|
427
386
|
/**
|
|
428
|
-
* Schema-field geometry
|
|
429
|
-
*
|
|
430
|
-
* entries {@link LiveSession.regions} serves, for consumers without a live
|
|
431
|
-
* session. Page indices are document-space even under a `pages` subset
|
|
432
|
-
* render.
|
|
387
|
+
* Schema-field geometry, populated only when {@link RenderOptions.regions}
|
|
388
|
+
* asked for it. Page indices are document-space even under a `pages` subset.
|
|
433
389
|
*/
|
|
434
390
|
regions: FieldRegion[];
|
|
435
391
|
}
|
|
436
392
|
|
|
437
|
-
/**
|
|
393
|
+
/** The emittable formats. */
|
|
438
394
|
export type OutputFormat = 'pdf' | 'svg' | 'png';
|
|
439
395
|
|
|
440
|
-
/**
|
|
441
|
-
* Canonical contract every backend build must satisfy. Page geometry in pt.
|
|
442
|
-
*/
|
|
396
|
+
/** Page geometry, in points. */
|
|
443
397
|
export interface PageSize {
|
|
444
398
|
widthPt: number;
|
|
445
399
|
heightPt: number;
|
|
446
400
|
}
|
|
447
401
|
|
|
448
|
-
/**
|
|
449
|
-
* Canonical contract every backend build must satisfy. Inputs to `paint`.
|
|
450
|
-
*/
|
|
402
|
+
/** Inputs to `paint`. */
|
|
451
403
|
export interface PaintOptions {
|
|
452
404
|
layoutScale?: number;
|
|
453
405
|
densityScale?: number;
|
|
454
406
|
}
|
|
455
407
|
|
|
456
|
-
/**
|
|
457
|
-
* Canonical contract every backend build must satisfy. Output of `paint`.
|
|
458
|
-
*/
|
|
408
|
+
/** Output of `paint`. */
|
|
459
409
|
export interface PaintResult {
|
|
460
410
|
layoutWidth: number; // canvas.style.width target; independent of densityScale
|
|
461
411
|
layoutHeight: number;
|
|
462
412
|
pixelWidth: number; // canvas.width the painter wrote (clamped at 16384)
|
|
463
413
|
pixelHeight: number;
|
|
464
414
|
/**
|
|
465
|
-
* True when
|
|
466
|
-
*
|
|
467
|
-
* `canvas.style` size. Reads the clamp off the return value instead of the
|
|
468
|
-
* `pixelWidth < round(layoutWidth × densityScale)` derivation.
|
|
415
|
+
* True when the backing-store clamp forced `densityScale` down: the page
|
|
416
|
+
* renders soft at the same `canvas.style` size.
|
|
469
417
|
*/
|
|
470
418
|
clamped: boolean;
|
|
471
419
|
/**
|
|
472
|
-
* The `densityScale` actually applied
|
|
473
|
-
* `clamped
|
|
474
|
-
* is the scale the backing store was rasterized at.
|
|
420
|
+
* The `densityScale` actually applied, reduced proportionally when
|
|
421
|
+
* `clamped`. `layoutScale × effectiveDensityScale` is the rasterized scale.
|
|
475
422
|
*/
|
|
476
423
|
effectiveDensityScale: number;
|
|
477
424
|
}
|
|
478
425
|
|
|
479
426
|
/**
|
|
480
|
-
*
|
|
481
|
-
* {@link LiveSession.update}: `dirtyPages` lists the pages whose rendered
|
|
427
|
+
* Output of {@link LiveSession.update}: `dirtyPages` lists the pages whose
|
|
482
428
|
* content differs from the previous compile, including added pages; removed
|
|
483
429
|
* pages are implied by `pageCount`. Repaint `dirty ∩ visible`.
|
|
484
430
|
*/
|
|
@@ -488,12 +434,11 @@ export interface ChangeSet {
|
|
|
488
434
|
}
|
|
489
435
|
|
|
490
436
|
/**
|
|
491
|
-
* A backend registry entry. `load` is the lazy thunk returning the
|
|
492
|
-
* imported backend build module; `formats`/`canvas` are the
|
|
493
|
-
* capability manifest
|
|
494
|
-
* `Engine.
|
|
495
|
-
*
|
|
496
|
-
* backend memory. A malformed descriptor throws at `new Engine(...)`.
|
|
437
|
+
* A backend registry entry. `load` is the lazy thunk returning the
|
|
438
|
+
* dynamically-imported backend build module; `formats`/`canvas` are the required
|
|
439
|
+
* static capability manifest, which is what makes `Engine.supportedFormats` and
|
|
440
|
+
* `Engine.supportsCanvas` free: they answer from it without loading a backend
|
|
441
|
+
* binary or cloning a quill. A malformed descriptor throws at `new Engine(...)`.
|
|
497
442
|
*/
|
|
498
443
|
export interface BackendDescriptor {
|
|
499
444
|
load: () => Promise<unknown>;
|
|
@@ -538,23 +483,20 @@ export declare class Engine {
|
|
|
538
483
|
open(quill: Quill, doc: Document): Promise<LiveSession>;
|
|
539
484
|
|
|
540
485
|
/**
|
|
541
|
-
* Output formats `quill`'s backend can emit. An
|
|
542
|
-
* it answers from the descriptor's
|
|
543
|
-
*
|
|
486
|
+
* Output formats `quill`'s backend can emit. An always-free pre-render probe:
|
|
487
|
+
* it answers from the descriptor's `formats` manifest without loading the
|
|
488
|
+
* backend binary or cloning the quill. Async for API stability.
|
|
544
489
|
*/
|
|
545
490
|
supportedFormats(quill: Quill): Promise<OutputFormat[]>;
|
|
546
491
|
|
|
547
492
|
/**
|
|
548
|
-
* Whether `quill`'s
|
|
549
|
-
*
|
|
550
|
-
*
|
|
551
|
-
*
|
|
552
|
-
*
|
|
553
|
-
*
|
|
554
|
-
*
|
|
555
|
-
* the resulting {@link LiveSession.supportsCanvas} answers `false`. Gate
|
|
556
|
-
* mounting a canvas UI on this; gate the actual `paint` call on the session's
|
|
557
|
-
* getter once `open()` has run.
|
|
493
|
+
* Whether `quill`'s backend can paint sessions to a canvas: a pre-session
|
|
494
|
+
* estimate, not a fact about any particular compile, answered from the
|
|
495
|
+
* descriptor's `canvas` manifest like `supportedFormats`. A specific compile
|
|
496
|
+
* can still refuse to paint (a 0-page document, say), so this can answer
|
|
497
|
+
* `true` while the resulting {@link LiveSession.supportsCanvas} answers
|
|
498
|
+
* `false`. Gate mounting a canvas UI on this, and the `paint` call itself on
|
|
499
|
+
* the session's getter.
|
|
558
500
|
*/
|
|
559
501
|
supportsCanvas(quill: Quill): Promise<boolean>;
|
|
560
502
|
}
|
|
@@ -562,14 +504,11 @@ export declare class Engine {
|
|
|
562
504
|
/**
|
|
563
505
|
* Iterative render session over a compiled snapshot. `free()` when done.
|
|
564
506
|
*
|
|
565
|
-
* CANVAS PAINT IS COMPLETE
|
|
566
|
-
* raster
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
570
|
-
* that, so field values appear in the raster on their own.
|
|
571
|
-
* {@link LiveSession.regions} carries schema-field geometry for interactive
|
|
572
|
-
* overlays / cross-navigation drawn on top of the raster; it is never needed to
|
|
507
|
+
* CANVAS PAINT IS COMPLETE: {@link LiveSession.paint} writes a whole page
|
|
508
|
+
* raster, every piece of page content already visible in the painted pixels,
|
|
509
|
+
* with no compositing required by the caller — pdfform pre-flattens bound field
|
|
510
|
+
* values into the page content to satisfy this. {@link LiveSession.regions}
|
|
511
|
+
* carries schema-field geometry for overlays drawn on top; it is never needed to
|
|
573
512
|
* complete the picture.
|
|
574
513
|
*/
|
|
575
514
|
export declare class LiveSession {
|
|
@@ -578,21 +517,18 @@ export declare class LiveSession {
|
|
|
578
517
|
readonly backendId: string;
|
|
579
518
|
/**
|
|
580
519
|
* `true` iff `paint`/`pageSize` will succeed for THIS compile: the
|
|
581
|
-
* authoritative answer,
|
|
582
|
-
*
|
|
583
|
-
*
|
|
584
|
-
* (
|
|
585
|
-
* backend compiled to a 0-page document has nothing to paint). Re-check
|
|
586
|
-
* this getter after `open()` rather than relying on the engine hint alone.
|
|
520
|
+
* authoritative answer, which can be `false` even where
|
|
521
|
+
* {@link Engine.supportsCanvas} answered `true` for the same `quill` (a
|
|
522
|
+
* canvas-capable backend compiled to a 0-page document has nothing to paint).
|
|
523
|
+
* Re-check it after `open()` rather than relying on the engine hint.
|
|
587
524
|
*/
|
|
588
525
|
readonly supportsCanvas: boolean;
|
|
589
526
|
readonly warnings: Diagnostic[];
|
|
590
527
|
/**
|
|
591
528
|
* Recompile the session against `doc`: the edit verb of a live preview.
|
|
592
|
-
* Transactional
|
|
593
|
-
*
|
|
594
|
-
*
|
|
595
|
-
* repaint `dirtyPages ∩ visible`.
|
|
529
|
+
* Transactional — on throw every read keeps serving the last-good compile and
|
|
530
|
+
* the session recovers on the next successful `update`. On success, repaint
|
|
531
|
+
* `dirtyPages ∩ visible`.
|
|
596
532
|
*/
|
|
597
533
|
update(doc: Document): ChangeSet;
|
|
598
534
|
render(options?: RenderOptions): RenderResult;
|
|
@@ -603,37 +539,29 @@ export declare class LiveSession {
|
|
|
603
539
|
* field over a `paint`-ed canvas; the click direction is {@link fieldAt}.
|
|
604
540
|
* Empty for backends that place no schema fields.
|
|
605
541
|
*
|
|
606
|
-
* `field` is **not** unique: a content field surfaces its **first
|
|
607
|
-
*
|
|
608
|
-
*
|
|
609
|
-
*
|
|
610
|
-
*
|
|
611
|
-
*
|
|
612
|
-
* content value are not enumerated; {@link fieldAt} still resolves
|
|
613
|
-
* clicks on them.
|
|
542
|
+
* `field` is **not** unique: a content field surfaces its **first placement**
|
|
543
|
+
* as one {@link FieldRegion} per page that placement touches, a scalar
|
|
544
|
+
* referenced at several plate sites surfaces each site, and tracked content
|
|
545
|
+
* plus a `field:`-bound widget yields both, widget first. Group by `field`.
|
|
546
|
+
* Later placements of one content value are not enumerated; {@link fieldAt}
|
|
547
|
+
* still resolves clicks on them.
|
|
614
548
|
*/
|
|
615
549
|
regions(): FieldRegion[];
|
|
616
550
|
/**
|
|
617
551
|
* The whole-field highlight boxes for `field` (a canonical `DocPath` address,
|
|
618
|
-
* as {@link regions} keys): one union rect per page
|
|
619
|
-
* `span`-bearing content segments
|
|
620
|
-
*
|
|
621
|
-
*
|
|
622
|
-
*
|
|
623
|
-
* placed solely as a scalar reference or a bound widget carries no `span`
|
|
624
|
-
* and returns `[]`; its box is a single {@link regions} rect. Reflects the
|
|
625
|
-
* current compile, like `regions()`.
|
|
552
|
+
* as {@link regions} keys): one union rect per page over the field's
|
|
553
|
+
* `span`-bearing content segments, the union {@link regions} leaves derived.
|
|
554
|
+
* **Content only**: a field placed solely as a scalar reference or a bound
|
|
555
|
+
* widget carries no `span` and returns `[]`, its box being a single
|
|
556
|
+
* {@link regions} rect. Reflects the current compile.
|
|
626
557
|
*/
|
|
627
558
|
fieldBoxes(field: string): FieldRegion[];
|
|
628
559
|
/**
|
|
629
|
-
* The schema field whose content is under a point on `page
|
|
630
|
-
*
|
|
631
|
-
*
|
|
632
|
-
*
|
|
633
|
-
*
|
|
634
|
-
* same space as {@link FieldRegion.rect}, from a canvas click, invert the
|
|
635
|
-
* overlay transform documented there:
|
|
636
|
-
* `x = clickPx.x / renderScale`,
|
|
560
|
+
* The schema field whose content is under a point on `page`: the canonical
|
|
561
|
+
* `DocPath` address to focus in the editor, or `undefined` off any field's
|
|
562
|
+
* ink. `x`/`y` are PDF points with a **bottom-left** origin, the same space as
|
|
563
|
+
* {@link FieldRegion.rect}, so from a canvas click invert the overlay
|
|
564
|
+
* transform documented there: `x = clickPx.x / renderScale`,
|
|
637
565
|
* `y = pageHeightPt - clickPx.y / renderScale`. Unlike {@link regions},
|
|
638
566
|
* *every* placement answers, not just the first.
|
|
639
567
|
*/
|
|
@@ -651,24 +579,19 @@ export declare class LiveSession {
|
|
|
651
579
|
/** Page geometry in points (1/72″). Report-only; the painter sizes the canvas. */
|
|
652
580
|
pageSize(page: number): PageSize;
|
|
653
581
|
/**
|
|
654
|
-
* Paint `page` into a 2D canvas context, sizing the backing store itself
|
|
655
|
-
*
|
|
656
|
-
*
|
|
657
|
-
*
|
|
658
|
-
*
|
|
659
|
-
* `layoutScale × densityScale`, clamped so neither backing dimension exceeds
|
|
660
|
-
* 16384 px: {@link PaintResult.clamped} reports the clamp and
|
|
661
|
-
* {@link PaintResult.effectiveDensityScale} the density actually applied.
|
|
582
|
+
* Paint `page` into a 2D canvas context, sizing the backing store itself (it
|
|
583
|
+
* owns `canvas.width`/`height`; the caller owns `canvas.style.*`). The
|
|
584
|
+
* rasterization scale is `layoutScale × densityScale`, clamped so neither
|
|
585
|
+
* backing dimension exceeds 16384 px; {@link PaintResult.clamped} reports the
|
|
586
|
+
* clamp and {@link PaintResult.effectiveDensityScale} the density applied.
|
|
662
587
|
*
|
|
663
588
|
* The write is a whole-backing-store `putImageData`, which bypasses the 2D
|
|
664
|
-
* context transform, `globalAlpha`, and clip
|
|
665
|
-
* canvas
|
|
666
|
-
*
|
|
667
|
-
*
|
|
668
|
-
*
|
|
669
|
-
*
|
|
670
|
-
* canvas across pages on scroll re-runs a full render, whereas an idle canvas
|
|
671
|
-
* retains its pixels for free.
|
|
589
|
+
* context transform, `globalAlpha`, and clip, so give each visible page its
|
|
590
|
+
* own canvas: no compositing, sub-rect, or transform reaches through this
|
|
591
|
+
* call, and the raster is complete precisely so none is needed. Keep the
|
|
592
|
+
* per-page canvases alive while their pages stay near the viewport: each
|
|
593
|
+
* `paint` re-rasterizes from scratch, whereas an idle canvas retains its
|
|
594
|
+
* pixels for free.
|
|
672
595
|
*/
|
|
673
596
|
paint(
|
|
674
597
|
ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
|
|
@@ -686,11 +609,9 @@ export declare class LiveSession {
|
|
|
686
609
|
declare module '../core/wasm.js' {
|
|
687
610
|
interface Quill {
|
|
688
611
|
/**
|
|
689
|
-
* Bind this quill's schema to `doc` for typed writes
|
|
690
|
-
*
|
|
691
|
-
*
|
|
692
|
-
* handles by reference and owns neither (nothing to `free()`); it is
|
|
693
|
-
* ephemeral by convention: bind, write, discard.
|
|
612
|
+
* Bind this quill's schema to `doc` for typed writes. The returned writer
|
|
613
|
+
* holds both handles by reference and owns neither (nothing to `free()`);
|
|
614
|
+
* it is ephemeral by convention: bind, write, discard.
|
|
694
615
|
*/
|
|
695
616
|
writer(doc: Document): DocumentWriter;
|
|
696
617
|
/**
|
|
@@ -707,18 +628,16 @@ declare module '../core/wasm.js' {
|
|
|
707
628
|
}
|
|
708
629
|
|
|
709
630
|
/**
|
|
710
|
-
* A `Document` bound to its `Quill` for typed writes
|
|
711
|
-
*
|
|
712
|
-
* `
|
|
713
|
-
*
|
|
714
|
-
* handles by reference and owns neither: nothing to `free()`.
|
|
631
|
+
* A `Document` bound to its `Quill` for typed writes, from {@link Quill.writer}.
|
|
632
|
+
* Speaks names, values, and markdown, so bare `set` / `setAll` / `reviseBody` /
|
|
633
|
+
* `reviseField` / `addCard` / `card(i).set` replace threading the `quill` handle
|
|
634
|
+
* through the underscored ABI. Holds both handles by reference and owns neither.
|
|
715
635
|
*
|
|
716
636
|
* Typed commit is the default whenever a quill is in hand: it resolves each
|
|
717
|
-
* field's schema type and strict-commits it, throwing `UnknownField` for
|
|
718
|
-
*
|
|
719
|
-
*
|
|
720
|
-
*
|
|
721
|
-
* holding not-yet-conforming in-progress input).
|
|
637
|
+
* field's schema type and strict-commits it, throwing `UnknownField` for an
|
|
638
|
+
* undeclared name rather than falling back. The raw `Document.storeField` /
|
|
639
|
+
* `storeFields` verbs remain the deliberate quill-free primitive (standalone
|
|
640
|
+
* data, storage/migration infra, or not-yet-conforming in-progress input).
|
|
722
641
|
*/
|
|
723
642
|
export declare class DocumentWriter {
|
|
724
643
|
constructor(quill: Quill, doc: Document);
|
|
@@ -736,10 +655,9 @@ export declare class DocumentWriter {
|
|
|
736
655
|
*/
|
|
737
656
|
setAll(fields: Record<string, unknown>): void;
|
|
738
657
|
/**
|
|
739
|
-
* Revise the main body from markdown
|
|
740
|
-
*
|
|
741
|
-
*
|
|
742
|
-
* the content lane's.
|
|
658
|
+
* Revise the main body from markdown; anchors rebase. Returns the text
|
|
659
|
+
* `Delta`: a body carries no field schema to type against, so this is the
|
|
660
|
+
* content lane's `revise` reached through the writer.
|
|
743
661
|
*/
|
|
744
662
|
reviseBody(markdown: string): Delta;
|
|
745
663
|
/**
|
|
@@ -755,12 +673,10 @@ export declare class DocumentWriter {
|
|
|
755
673
|
reviseField(name: string, text: string): Delta;
|
|
756
674
|
/**
|
|
757
675
|
* Build a composable card of `kind`, typed-commit `fields` onto it, set its
|
|
758
|
-
* body from optional markdown, and place it
|
|
759
|
-
*
|
|
760
|
-
*
|
|
761
|
-
*
|
|
762
|
-
* a per-field diagnostic bundle) or an invalid kind/body/position leaves the
|
|
763
|
-
* document untouched.
|
|
676
|
+
* body from optional markdown, and place it. `at` omitted appends, a number
|
|
677
|
+
* inserts at that index. Transactional: a rejected field (throwing a per-field
|
|
678
|
+
* diagnostic bundle) or an invalid kind, body, or position leaves the document
|
|
679
|
+
* untouched.
|
|
764
680
|
*/
|
|
765
681
|
addCard(kind: string, fields?: Record<string, unknown>, body?: string, at?: number): void;
|
|
766
682
|
/** Remove the composable card at `index`, returning it (or `undefined`). */
|
|
@@ -786,9 +702,8 @@ export declare class CardWriter {
|
|
|
786
702
|
/** The bound card index. */
|
|
787
703
|
readonly index: number;
|
|
788
704
|
/**
|
|
789
|
-
* The bound card's `$kind
|
|
790
|
-
*
|
|
791
|
-
* if the bound index is out of range.
|
|
705
|
+
* The bound card's `$kind`, empty string when it carries none. Throws
|
|
706
|
+
* `IndexOutOfRange` for a bad bound index.
|
|
792
707
|
*/
|
|
793
708
|
readonly kind: string;
|
|
794
709
|
set(name: string, value: unknown): void;
|
|
@@ -796,34 +711,29 @@ export declare class CardWriter {
|
|
|
796
711
|
/** Revise this card's body from markdown (edit semantics), returning the text `Delta`. */
|
|
797
712
|
reviseBody(markdown: string): Delta;
|
|
798
713
|
/**
|
|
799
|
-
*
|
|
800
|
-
*
|
|
801
|
-
* codec included. Throws `UnknownField` for an undeclared name and
|
|
802
|
-
* `IndexOutOfRange` if the bound index is out of range. Returns the `Delta`.
|
|
714
|
+
* The card twin of {@link DocumentWriter.reviseField}. Throws `UnknownField`
|
|
715
|
+
* for an undeclared name and `IndexOutOfRange` for a bad bound index.
|
|
803
716
|
*/
|
|
804
717
|
reviseField(name: string, text: string): Delta;
|
|
805
718
|
}
|
|
806
719
|
|
|
807
720
|
/**
|
|
808
|
-
* A `Document` bound to its `Quill` for interpreted reads
|
|
809
|
-
*
|
|
810
|
-
*
|
|
811
|
-
*
|
|
812
|
-
* text, every other type its canonical value verbatim. Holds both handles by
|
|
813
|
-
* reference and owns neither: nothing to `free()`.
|
|
721
|
+
* A `Document` bound to its `Quill` for interpreted reads, from
|
|
722
|
+
* {@link Quill.reader}: the read twin of {@link DocumentWriter}. One `get` reads
|
|
723
|
+
* each field by its declared type — a richtext field to its markdown projection,
|
|
724
|
+
* a plaintext field to its literal text, every other type verbatim.
|
|
814
725
|
*
|
|
815
|
-
* The schema authority is the point: unlike the quill-free
|
|
816
|
-
*
|
|
817
|
-
*
|
|
818
|
-
*
|
|
819
|
-
*
|
|
820
|
-
* is a format fact) and never throws.
|
|
726
|
+
* The schema authority is the point: unlike the quill-free `Document.getStored`,
|
|
727
|
+
* an undeclared name throws `UnknownField` rather than reading back `undefined`,
|
|
728
|
+
* and an undecodable content value throws `FieldDecode`. A field's markdown lives
|
|
729
|
+
* here, not on the body-only `Document.bodyMarkdown`; the body read stays
|
|
730
|
+
* quill-free and never throws.
|
|
821
731
|
*
|
|
822
732
|
* `getContent` is the same read at the other end of the codec, returning the
|
|
823
733
|
* `Content` rather than the projection. It binds the quill for the same reason
|
|
824
|
-
* `get` does:
|
|
825
|
-
*
|
|
826
|
-
*
|
|
734
|
+
* `get` does: the same stored bytes decode two ways, and only the declared type
|
|
735
|
+
* says which. `getContentAt` is that read one axis further in, for a `Content`
|
|
736
|
+
* nested inside a composite field.
|
|
827
737
|
*/
|
|
828
738
|
export declare class DocumentReader {
|
|
829
739
|
constructor(quill: Quill, doc: Document);
|
|
@@ -839,16 +749,31 @@ export declare class DocumentReader {
|
|
|
839
749
|
*/
|
|
840
750
|
get(addr: Addr | string): unknown;
|
|
841
751
|
/**
|
|
842
|
-
* Read the content field at `addr` as
|
|
843
|
-
*
|
|
844
|
-
*
|
|
845
|
-
*
|
|
846
|
-
*
|
|
847
|
-
*
|
|
848
|
-
* `
|
|
849
|
-
* leaf, `FieldDecode` for an undecodable value, and `IndexOutOfRange`.
|
|
752
|
+
* Read the content field at `addr` as canonical `Content`: the twin of
|
|
753
|
+
* {@link get}, which projects. Decodes through the codec the declared type
|
|
754
|
+
* names, so a committed field and a parsed one read back the same `Content`.
|
|
755
|
+
* An absent `addr.field` reads the body `Content`. `undefined` for an absent
|
|
756
|
+
* field; throws `UnknownField`, `FieldNotContent` for a declared type that is
|
|
757
|
+
* not a content leaf, `FieldDecode` for an undecodable value, and
|
|
758
|
+
* `IndexOutOfRange`.
|
|
850
759
|
*/
|
|
851
760
|
getContent(addr: Addr | string): Content | undefined;
|
|
761
|
+
/**
|
|
762
|
+
* Read the `Content` nested inside the composite field at `addr`, at `path`:
|
|
763
|
+
* `[0]` an element of an `array<richtext>`, `["motto"]` an object's content
|
|
764
|
+
* property, `[1, "notes"]` a leaf under both. The codec is the leaf's declared
|
|
765
|
+
* type's, resolved through the field schema's `items` / `properties`, so the
|
|
766
|
+
* element's storage form is not the caller's business. The empty path is
|
|
767
|
+
* {@link getContent}.
|
|
768
|
+
*
|
|
769
|
+
* `undefined` for an absent field and for a path that names nothing in the
|
|
770
|
+
* stored value: a repeater's row index goes stale between derive and read,
|
|
771
|
+
* so absence there is a read, not a fault. Throws `UnknownField` for an
|
|
772
|
+
* undeclared name at any depth, `FieldNotContent` when `path` resolves to no
|
|
773
|
+
* content leaf, `FieldDecode` anchored at the addressed path, and
|
|
774
|
+
* `IndexOutOfRange` for a bad `addr.card`.
|
|
775
|
+
*/
|
|
776
|
+
getContentAt(addr: Addr | string, path: PathStep[]): Content | undefined;
|
|
852
777
|
/** The main body's markdown: the quill-free body read. Equals `get({})`. */
|
|
853
778
|
bodyMarkdown(): string;
|
|
854
779
|
/**
|
|
@@ -882,10 +807,11 @@ export declare class CardReader {
|
|
|
882
807
|
*/
|
|
883
808
|
get(name: string): unknown;
|
|
884
809
|
/**
|
|
885
|
-
*
|
|
886
|
-
* `Content`: the card twin of {@link DocumentReader.getContent}.
|
|
810
|
+
* The card twin of {@link DocumentReader.getContent}.
|
|
887
811
|
*/
|
|
888
812
|
getContent(name: string): Content | undefined;
|
|
813
|
+
/** The card twin of {@link DocumentReader.getContentAt}. */
|
|
814
|
+
getContentAt(name: string, path: PathStep[]): Content | undefined;
|
|
889
815
|
/** This card's body markdown: the card twin of {@link DocumentReader.bodyMarkdown}. */
|
|
890
816
|
bodyMarkdown(): string;
|
|
891
817
|
}
|