@quillmark/wasm 0.103.0 → 0.105.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 +199 -26
- package/README.md +76 -210
- package/backends/pdfform/wasm.d.ts +484 -683
- package/backends/pdfform/wasm.js +415 -469
- package/backends/pdfform/wasm_bg.wasm +0 -0
- package/backends/pdfform/wasm_bg.wasm.d.ts +3 -0
- package/backends/typst/wasm.d.ts +484 -683
- package/backends/typst/wasm.js +415 -469
- package/backends/typst/wasm_bg.wasm +0 -0
- package/backends/typst/wasm_bg.wasm.d.ts +3 -0
- package/core/wasm.d.ts +356 -462
- package/core/wasm.js +360 -389
- package/core/wasm_bg.wasm +0 -0
- package/core/wasm_bg.wasm.d.ts +3 -0
- package/package.json +2 -2
- package/runtime/runtime.d.ts +181 -252
- package/runtime/runtime.js +191 -347
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,9 +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
|
-
*
|
|
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.
|
|
402
364
|
*/
|
|
403
365
|
field: string;
|
|
404
366
|
/** 0-based page index. */
|
|
@@ -415,67 +377,54 @@ export interface FieldRegion {
|
|
|
415
377
|
span?: [number, number];
|
|
416
378
|
}
|
|
417
379
|
|
|
418
|
-
/**
|
|
380
|
+
/** Result of one render. */
|
|
419
381
|
export interface RenderResult {
|
|
420
382
|
artifacts: Artifact[];
|
|
421
383
|
warnings: Diagnostic[];
|
|
422
384
|
outputFormat: OutputFormat;
|
|
423
385
|
renderTimeMs: number;
|
|
424
386
|
/**
|
|
425
|
-
* Schema-field geometry
|
|
426
|
-
*
|
|
427
|
-
* entries {@link LiveSession.regions} serves, for consumers without a live
|
|
428
|
-
* session. Page indices are document-space even under a `pages` subset
|
|
429
|
-
* 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.
|
|
430
389
|
*/
|
|
431
390
|
regions: FieldRegion[];
|
|
432
391
|
}
|
|
433
392
|
|
|
434
|
-
/**
|
|
393
|
+
/** The emittable formats. */
|
|
435
394
|
export type OutputFormat = 'pdf' | 'svg' | 'png';
|
|
436
395
|
|
|
437
|
-
/**
|
|
438
|
-
* Canonical contract every backend build must satisfy. Page geometry in pt.
|
|
439
|
-
*/
|
|
396
|
+
/** Page geometry, in points. */
|
|
440
397
|
export interface PageSize {
|
|
441
398
|
widthPt: number;
|
|
442
399
|
heightPt: number;
|
|
443
400
|
}
|
|
444
401
|
|
|
445
|
-
/**
|
|
446
|
-
* Canonical contract every backend build must satisfy. Inputs to `paint`.
|
|
447
|
-
*/
|
|
402
|
+
/** Inputs to `paint`. */
|
|
448
403
|
export interface PaintOptions {
|
|
449
404
|
layoutScale?: number;
|
|
450
405
|
densityScale?: number;
|
|
451
406
|
}
|
|
452
407
|
|
|
453
|
-
/**
|
|
454
|
-
* Canonical contract every backend build must satisfy. Output of `paint`.
|
|
455
|
-
*/
|
|
408
|
+
/** Output of `paint`. */
|
|
456
409
|
export interface PaintResult {
|
|
457
410
|
layoutWidth: number; // canvas.style.width target; independent of densityScale
|
|
458
411
|
layoutHeight: number;
|
|
459
412
|
pixelWidth: number; // canvas.width the painter wrote (clamped at 16384)
|
|
460
413
|
pixelHeight: number;
|
|
461
414
|
/**
|
|
462
|
-
* True when
|
|
463
|
-
*
|
|
464
|
-
* `canvas.style` size. Reads the clamp off the return value instead of the
|
|
465
|
-
* `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.
|
|
466
417
|
*/
|
|
467
418
|
clamped: boolean;
|
|
468
419
|
/**
|
|
469
|
-
* The `densityScale` actually applied
|
|
470
|
-
* `clamped
|
|
471
|
-
* 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.
|
|
472
422
|
*/
|
|
473
423
|
effectiveDensityScale: number;
|
|
474
424
|
}
|
|
475
425
|
|
|
476
426
|
/**
|
|
477
|
-
*
|
|
478
|
-
* {@link LiveSession.update}: `dirtyPages` lists the pages whose rendered
|
|
427
|
+
* Output of {@link LiveSession.update}: `dirtyPages` lists the pages whose
|
|
479
428
|
* content differs from the previous compile, including added pages; removed
|
|
480
429
|
* pages are implied by `pageCount`. Repaint `dirty ∩ visible`.
|
|
481
430
|
*/
|
|
@@ -485,12 +434,11 @@ export interface ChangeSet {
|
|
|
485
434
|
}
|
|
486
435
|
|
|
487
436
|
/**
|
|
488
|
-
* A backend registry entry. `load` is the lazy thunk returning the
|
|
489
|
-
* imported backend build module; `formats`/`canvas` are the
|
|
490
|
-
* capability manifest
|
|
491
|
-
* `Engine.
|
|
492
|
-
*
|
|
493
|
-
* 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(...)`.
|
|
494
442
|
*/
|
|
495
443
|
export interface BackendDescriptor {
|
|
496
444
|
load: () => Promise<unknown>;
|
|
@@ -535,23 +483,20 @@ export declare class Engine {
|
|
|
535
483
|
open(quill: Quill, doc: Document): Promise<LiveSession>;
|
|
536
484
|
|
|
537
485
|
/**
|
|
538
|
-
* Output formats `quill`'s backend can emit. An
|
|
539
|
-
* it answers from the descriptor's
|
|
540
|
-
*
|
|
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.
|
|
541
489
|
*/
|
|
542
490
|
supportedFormats(quill: Quill): Promise<OutputFormat[]>;
|
|
543
491
|
|
|
544
492
|
/**
|
|
545
|
-
* Whether `quill`'s
|
|
546
|
-
*
|
|
547
|
-
*
|
|
548
|
-
*
|
|
549
|
-
*
|
|
550
|
-
*
|
|
551
|
-
*
|
|
552
|
-
* the resulting {@link LiveSession.supportsCanvas} answers `false`. Gate
|
|
553
|
-
* mounting a canvas UI on this; gate the actual `paint` call on the session's
|
|
554
|
-
* 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.
|
|
555
500
|
*/
|
|
556
501
|
supportsCanvas(quill: Quill): Promise<boolean>;
|
|
557
502
|
}
|
|
@@ -559,14 +504,11 @@ export declare class Engine {
|
|
|
559
504
|
/**
|
|
560
505
|
* Iterative render session over a compiled snapshot. `free()` when done.
|
|
561
506
|
*
|
|
562
|
-
* CANVAS PAINT IS COMPLETE
|
|
563
|
-
* raster
|
|
564
|
-
*
|
|
565
|
-
*
|
|
566
|
-
*
|
|
567
|
-
* that, so field values appear in the raster on their own.
|
|
568
|
-
* {@link LiveSession.regions} carries schema-field geometry for interactive
|
|
569
|
-
* 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
|
|
570
512
|
* complete the picture.
|
|
571
513
|
*/
|
|
572
514
|
export declare class LiveSession {
|
|
@@ -575,21 +517,18 @@ export declare class LiveSession {
|
|
|
575
517
|
readonly backendId: string;
|
|
576
518
|
/**
|
|
577
519
|
* `true` iff `paint`/`pageSize` will succeed for THIS compile: the
|
|
578
|
-
* authoritative answer,
|
|
579
|
-
*
|
|
580
|
-
*
|
|
581
|
-
* (
|
|
582
|
-
* backend compiled to a 0-page document has nothing to paint). Re-check
|
|
583
|
-
* 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.
|
|
584
524
|
*/
|
|
585
525
|
readonly supportsCanvas: boolean;
|
|
586
526
|
readonly warnings: Diagnostic[];
|
|
587
527
|
/**
|
|
588
528
|
* Recompile the session against `doc`: the edit verb of a live preview.
|
|
589
|
-
* Transactional
|
|
590
|
-
*
|
|
591
|
-
*
|
|
592
|
-
* 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`.
|
|
593
532
|
*/
|
|
594
533
|
update(doc: Document): ChangeSet;
|
|
595
534
|
render(options?: RenderOptions): RenderResult;
|
|
@@ -600,37 +539,29 @@ export declare class LiveSession {
|
|
|
600
539
|
* field over a `paint`-ed canvas; the click direction is {@link fieldAt}.
|
|
601
540
|
* Empty for backends that place no schema fields.
|
|
602
541
|
*
|
|
603
|
-
* `field` is **not** unique: a content field surfaces its **first
|
|
604
|
-
*
|
|
605
|
-
*
|
|
606
|
-
*
|
|
607
|
-
*
|
|
608
|
-
*
|
|
609
|
-
* content value are not enumerated; {@link fieldAt} still resolves
|
|
610
|
-
* 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.
|
|
611
548
|
*/
|
|
612
549
|
regions(): FieldRegion[];
|
|
613
550
|
/**
|
|
614
551
|
* The whole-field highlight boxes for `field` (a canonical `DocPath` address,
|
|
615
|
-
* as {@link regions} keys): one union rect per page
|
|
616
|
-
* `span`-bearing content segments
|
|
617
|
-
*
|
|
618
|
-
*
|
|
619
|
-
*
|
|
620
|
-
* placed solely as a scalar reference or a bound widget carries no `span`
|
|
621
|
-
* and returns `[]`; its box is a single {@link regions} rect. Reflects the
|
|
622
|
-
* 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.
|
|
623
557
|
*/
|
|
624
558
|
fieldBoxes(field: string): FieldRegion[];
|
|
625
559
|
/**
|
|
626
|
-
* The schema field whose content is under a point on `page
|
|
627
|
-
*
|
|
628
|
-
*
|
|
629
|
-
*
|
|
630
|
-
*
|
|
631
|
-
* same space as {@link FieldRegion.rect}, from a canvas click, invert the
|
|
632
|
-
* overlay transform documented there:
|
|
633
|
-
* `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`,
|
|
634
565
|
* `y = pageHeightPt - clickPx.y / renderScale`. Unlike {@link regions},
|
|
635
566
|
* *every* placement answers, not just the first.
|
|
636
567
|
*/
|
|
@@ -648,24 +579,19 @@ export declare class LiveSession {
|
|
|
648
579
|
/** Page geometry in points (1/72″). Report-only; the painter sizes the canvas. */
|
|
649
580
|
pageSize(page: number): PageSize;
|
|
650
581
|
/**
|
|
651
|
-
* Paint `page` into a 2D canvas context, sizing the backing store itself
|
|
652
|
-
*
|
|
653
|
-
*
|
|
654
|
-
*
|
|
655
|
-
*
|
|
656
|
-
* `layoutScale × densityScale`, clamped so neither backing dimension exceeds
|
|
657
|
-
* 16384 px: {@link PaintResult.clamped} reports the clamp and
|
|
658
|
-
* {@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.
|
|
659
587
|
*
|
|
660
588
|
* The write is a whole-backing-store `putImageData`, which bypasses the 2D
|
|
661
|
-
* context transform, `globalAlpha`, and clip
|
|
662
|
-
* canvas
|
|
663
|
-
*
|
|
664
|
-
*
|
|
665
|
-
*
|
|
666
|
-
*
|
|
667
|
-
* canvas across pages on scroll re-runs a full render, whereas an idle canvas
|
|
668
|
-
* 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.
|
|
669
595
|
*/
|
|
670
596
|
paint(
|
|
671
597
|
ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
|
|
@@ -683,11 +609,9 @@ export declare class LiveSession {
|
|
|
683
609
|
declare module '../core/wasm.js' {
|
|
684
610
|
interface Quill {
|
|
685
611
|
/**
|
|
686
|
-
* Bind this quill's schema to `doc` for typed writes
|
|
687
|
-
*
|
|
688
|
-
*
|
|
689
|
-
* handles by reference and owns neither (nothing to `free()`); it is
|
|
690
|
-
* 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.
|
|
691
615
|
*/
|
|
692
616
|
writer(doc: Document): DocumentWriter;
|
|
693
617
|
/**
|
|
@@ -704,18 +628,16 @@ declare module '../core/wasm.js' {
|
|
|
704
628
|
}
|
|
705
629
|
|
|
706
630
|
/**
|
|
707
|
-
* A `Document` bound to its `Quill` for typed writes
|
|
708
|
-
*
|
|
709
|
-
* `
|
|
710
|
-
*
|
|
711
|
-
* 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.
|
|
712
635
|
*
|
|
713
636
|
* Typed commit is the default whenever a quill is in hand: it resolves each
|
|
714
|
-
* field's schema type and strict-commits it, throwing `UnknownField` for
|
|
715
|
-
*
|
|
716
|
-
*
|
|
717
|
-
*
|
|
718
|
-
* 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).
|
|
719
641
|
*/
|
|
720
642
|
export declare class DocumentWriter {
|
|
721
643
|
constructor(quill: Quill, doc: Document);
|
|
@@ -733,10 +655,9 @@ export declare class DocumentWriter {
|
|
|
733
655
|
*/
|
|
734
656
|
setAll(fields: Record<string, unknown>): void;
|
|
735
657
|
/**
|
|
736
|
-
* Revise the main body from markdown
|
|
737
|
-
*
|
|
738
|
-
*
|
|
739
|
-
* 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.
|
|
740
661
|
*/
|
|
741
662
|
reviseBody(markdown: string): Delta;
|
|
742
663
|
/**
|
|
@@ -752,12 +673,10 @@ export declare class DocumentWriter {
|
|
|
752
673
|
reviseField(name: string, text: string): Delta;
|
|
753
674
|
/**
|
|
754
675
|
* Build a composable card of `kind`, typed-commit `fields` onto it, set its
|
|
755
|
-
* body from optional markdown, and place it
|
|
756
|
-
*
|
|
757
|
-
*
|
|
758
|
-
*
|
|
759
|
-
* a per-field diagnostic bundle) or an invalid kind/body/position leaves the
|
|
760
|
-
* 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.
|
|
761
680
|
*/
|
|
762
681
|
addCard(kind: string, fields?: Record<string, unknown>, body?: string, at?: number): void;
|
|
763
682
|
/** Remove the composable card at `index`, returning it (or `undefined`). */
|
|
@@ -783,9 +702,8 @@ export declare class CardWriter {
|
|
|
783
702
|
/** The bound card index. */
|
|
784
703
|
readonly index: number;
|
|
785
704
|
/**
|
|
786
|
-
* The bound card's `$kind
|
|
787
|
-
*
|
|
788
|
-
* 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.
|
|
789
707
|
*/
|
|
790
708
|
readonly kind: string;
|
|
791
709
|
set(name: string, value: unknown): void;
|
|
@@ -793,34 +711,29 @@ export declare class CardWriter {
|
|
|
793
711
|
/** Revise this card's body from markdown (edit semantics), returning the text `Delta`. */
|
|
794
712
|
reviseBody(markdown: string): Delta;
|
|
795
713
|
/**
|
|
796
|
-
*
|
|
797
|
-
*
|
|
798
|
-
* codec included. Throws `UnknownField` for an undeclared name and
|
|
799
|
-
* `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.
|
|
800
716
|
*/
|
|
801
717
|
reviseField(name: string, text: string): Delta;
|
|
802
718
|
}
|
|
803
719
|
|
|
804
720
|
/**
|
|
805
|
-
* A `Document` bound to its `Quill` for interpreted reads
|
|
806
|
-
*
|
|
807
|
-
*
|
|
808
|
-
*
|
|
809
|
-
* text, every other type its canonical value verbatim. Holds both handles by
|
|
810
|
-
* 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.
|
|
811
725
|
*
|
|
812
|
-
* The schema authority is the point: unlike the quill-free
|
|
813
|
-
*
|
|
814
|
-
*
|
|
815
|
-
*
|
|
816
|
-
*
|
|
817
|
-
* 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.
|
|
818
731
|
*
|
|
819
732
|
* `getContent` is the same read at the other end of the codec, returning the
|
|
820
733
|
* `Content` rather than the projection. It binds the quill for the same reason
|
|
821
|
-
* `get` does:
|
|
822
|
-
*
|
|
823
|
-
*
|
|
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.
|
|
824
737
|
*/
|
|
825
738
|
export declare class DocumentReader {
|
|
826
739
|
constructor(quill: Quill, doc: Document);
|
|
@@ -836,16 +749,31 @@ export declare class DocumentReader {
|
|
|
836
749
|
*/
|
|
837
750
|
get(addr: Addr | string): unknown;
|
|
838
751
|
/**
|
|
839
|
-
* Read the content field at `addr` as
|
|
840
|
-
*
|
|
841
|
-
*
|
|
842
|
-
*
|
|
843
|
-
*
|
|
844
|
-
*
|
|
845
|
-
* `
|
|
846
|
-
* 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`.
|
|
847
759
|
*/
|
|
848
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;
|
|
849
777
|
/** The main body's markdown: the quill-free body read. Equals `get({})`. */
|
|
850
778
|
bodyMarkdown(): string;
|
|
851
779
|
/**
|
|
@@ -879,10 +807,11 @@ export declare class CardReader {
|
|
|
879
807
|
*/
|
|
880
808
|
get(name: string): unknown;
|
|
881
809
|
/**
|
|
882
|
-
*
|
|
883
|
-
* `Content`: the card twin of {@link DocumentReader.getContent}.
|
|
810
|
+
* The card twin of {@link DocumentReader.getContent}.
|
|
884
811
|
*/
|
|
885
812
|
getContent(name: string): Content | undefined;
|
|
813
|
+
/** The card twin of {@link DocumentReader.getContentAt}. */
|
|
814
|
+
getContentAt(name: string, path: PathStep[]): Content | undefined;
|
|
886
815
|
/** This card's body markdown: the card twin of {@link DocumentReader.bodyMarkdown}. */
|
|
887
816
|
bodyMarkdown(): string;
|
|
888
817
|
}
|