@quillmark/wasm 0.92.1 → 0.94.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 +536 -0
- package/README.md +147 -62
- package/backends/pdfform/wasm.d.ts +1099 -0
- package/backends/pdfform/wasm.js +9 -0
- package/backends/pdfform/wasm_bg.js +2670 -0
- package/backends/pdfform/wasm_bg.wasm +0 -0
- package/backends/pdfform/wasm_bg.wasm.d.ts +101 -0
- package/backends/typst/wasm.d.ts +544 -94
- package/backends/typst/wasm.js +1 -1
- package/backends/typst/wasm_bg.js +893 -227
- package/backends/typst/wasm_bg.wasm +0 -0
- package/backends/typst/wasm_bg.wasm.d.ts +34 -11
- package/core/wasm.d.ts +372 -37
- package/core/wasm.js +1 -1
- package/core/wasm_bg.js +562 -59
- package/core/wasm_bg.wasm +0 -0
- package/core/wasm_bg.wasm.d.ts +20 -3
- package/package.json +4 -3
- package/runtime/runtime.d.ts +327 -21
- package/runtime/runtime.js +355 -30
package/core/wasm_bg.wasm
CHANGED
|
Binary file
|
package/core/wasm_bg.wasm.d.ts
CHANGED
|
@@ -3,20 +3,31 @@
|
|
|
3
3
|
export const memory: WebAssembly.Memory;
|
|
4
4
|
export const __wbg_document_free: (a: number, b: number) => void;
|
|
5
5
|
export const __wbg_quill_free: (a: number, b: number) => void;
|
|
6
|
+
export const document_addCard: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void;
|
|
7
|
+
export const document_applyChange: (a: number, b: number, c: number, d: number) => void;
|
|
6
8
|
export const document_blueprintInstruction: (a: number, b: number, c: number) => void;
|
|
7
9
|
export const document_cardCount: (a: number) => number;
|
|
8
10
|
export const document_cards: (a: number, b: number) => void;
|
|
9
11
|
export const document_clone: (a: number) => number;
|
|
12
|
+
export const document_commitCardField: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
13
|
+
export const document_commitCardFields: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
14
|
+
export const document_commitField: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
15
|
+
export const document_commitFields: (a: number, b: number, c: number, d: number) => void;
|
|
10
16
|
export const document_currentSchemaVersion: (a: number) => void;
|
|
11
17
|
export const document_equals: (a: number, b: number) => number;
|
|
12
18
|
export const document_formatDiagnostic: (a: number, b: number) => void;
|
|
13
19
|
export const document_formatRules: (a: number) => void;
|
|
14
20
|
export const document_fromJson: (a: number, b: number, c: number) => void;
|
|
15
21
|
export const document_fromMarkdown: (a: number, b: number, c: number) => void;
|
|
22
|
+
export const document_get: (a: number, b: number, c: number, d: number) => void;
|
|
23
|
+
export const document_getMarkdown: (a: number, b: number, c: number, d: number) => void;
|
|
16
24
|
export const document_insertCard: (a: number, b: number, c: number, d: number) => void;
|
|
25
|
+
export const document_install: (a: number, b: number, c: number, d: number) => void;
|
|
26
|
+
export const document_loadJson: (a: number, b: number, c: number, d: number) => void;
|
|
17
27
|
export const document_main: (a: number, b: number) => void;
|
|
18
28
|
export const document_makeCard: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
19
29
|
export const document_moveCard: (a: number, b: number, c: number, d: number) => void;
|
|
30
|
+
export const document_new: (a: number, b: number, c: number) => void;
|
|
20
31
|
export const document_pushCard: (a: number, b: number, c: number) => void;
|
|
21
32
|
export const document_quillRef: (a: number, b: number) => void;
|
|
22
33
|
export const document_quillRefHint: (a: number) => void;
|
|
@@ -28,24 +39,29 @@ export const document_removeExt: (a: number, b: number) => void;
|
|
|
28
39
|
export const document_removeExtNamespace: (a: number, b: number, c: number, d: number) => void;
|
|
29
40
|
export const document_removeField: (a: number, b: number, c: number, d: number) => void;
|
|
30
41
|
export const document_removeSeedNamespace: (a: number, b: number, c: number, d: number) => void;
|
|
31
|
-
export const document_replaceBody: (a: number, b: number, c: number) => void;
|
|
42
|
+
export const document_replaceBody: (a: number, b: number, c: number, d: number) => void;
|
|
43
|
+
export const document_revise: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
32
44
|
export const document_schemaVersionOf: (a: number, b: number, c: number) => void;
|
|
33
45
|
export const document_setCardExt: (a: number, b: number, c: number, d: number) => void;
|
|
34
46
|
export const document_setCardExtNamespace: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
47
|
+
export const document_setCardField: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
48
|
+
export const document_setCardFields: (a: number, b: number, c: number, d: number) => void;
|
|
35
49
|
export const document_setCardKind: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
36
50
|
export const document_setExt: (a: number, b: number, c: number) => void;
|
|
37
51
|
export const document_setExtNamespace: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
38
52
|
export const document_setField: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
53
|
+
export const document_setFields: (a: number, b: number, c: number) => void;
|
|
39
54
|
export const document_setFill: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
40
55
|
export const document_setQuillRef: (a: number, b: number, c: number, d: number) => void;
|
|
41
56
|
export const document_setSeedNamespace: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
42
57
|
export const document_toJson: (a: number, b: number) => void;
|
|
43
58
|
export const document_toMarkdown: (a: number, b: number) => void;
|
|
44
59
|
export const document_tryFromJson: (a: number, b: number) => number;
|
|
45
|
-
export const document_updateCardBody: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
46
|
-
export const document_updateCardField: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
47
60
|
export const document_warnings: (a: number, b: number) => void;
|
|
61
|
+
export const exportMarkdown: (a: number, b: number) => void;
|
|
62
|
+
export const importMarkdown: (a: number, b: number, c: number) => void;
|
|
48
63
|
export const init: () => void;
|
|
64
|
+
export const mapPos: (a: number, b: number, c: number, d: number) => void;
|
|
49
65
|
export const quill_backendId: (a: number, b: number) => void;
|
|
50
66
|
export const quill_blueprint: (a: number, b: number) => void;
|
|
51
67
|
export const quill_fromTree: (a: number, b: number) => void;
|
|
@@ -56,6 +72,7 @@ export const quill_seedDocument: (a: number) => number;
|
|
|
56
72
|
export const quill_seedMain: (a: number, b: number) => void;
|
|
57
73
|
export const quill_toTree: (a: number) => number;
|
|
58
74
|
export const quill_validate: (a: number, b: number, c: number) => void;
|
|
75
|
+
export const rebase: (a: number, b: number, c: number, d: number) => void;
|
|
59
76
|
export const __wbindgen_export: (a: number, b: number) => number;
|
|
60
77
|
export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
|
|
61
78
|
export const __wbindgen_export3: (a: number) => void;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quillmark/wasm",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "WebAssembly bindings for
|
|
3
|
+
"version": "0.94.0",
|
|
4
|
+
"description": "WebAssembly bindings for Quillmark, a schema-driven document engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT OR Apache-2.0",
|
|
7
7
|
"engines": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
12
|
-
"url": "git+https://github.com/
|
|
12
|
+
"url": "git+https://github.com/borb-sh/quillmark.git"
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
15
15
|
"core",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"sideEffects": [
|
|
31
31
|
"./core/wasm.js",
|
|
32
32
|
"./backends/typst/wasm.js",
|
|
33
|
+
"./backends/pdfform/wasm.js",
|
|
33
34
|
"./runtime/runtime.js"
|
|
34
35
|
]
|
|
35
36
|
}
|
package/runtime/runtime.d.ts
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
// public entry point, so this is a structural fact. Replacing the re-export
|
|
15
15
|
// with a wrapper is a breaking design change, not a refactor. See runtime.js.
|
|
16
16
|
export { Quill, Document, init } from '../core/wasm.js';
|
|
17
|
+
// The document-free corpus codec, re-exported from the core build.
|
|
18
|
+
export { importMarkdown, exportMarkdown, rebase, mapPos } from '../core/wasm.js';
|
|
17
19
|
|
|
18
20
|
// Core-build types consumers read off `Quill`/`Document`.
|
|
19
21
|
export type {
|
|
@@ -68,7 +70,7 @@ export declare function isQuillmarkError(e: unknown): e is QuillmarkError;
|
|
|
68
70
|
// (run via `npm run typecheck`), so these and the generated
|
|
69
71
|
// `pkg/backends/typst/wasm.d.ts` cannot silently diverge.
|
|
70
72
|
|
|
71
|
-
import type { Quill, Document } from '../core/wasm.js';
|
|
73
|
+
import type { Quill, Document, Card } from '../core/wasm.js';
|
|
72
74
|
import type { Diagnostic } from '../core/wasm.js';
|
|
73
75
|
|
|
74
76
|
/** Canonical contract every backend build must satisfy. One emitted output. */
|
|
@@ -84,6 +86,92 @@ export interface RenderOptions {
|
|
|
84
86
|
ppi?: number;
|
|
85
87
|
pages?: number[];
|
|
86
88
|
producer?: string;
|
|
89
|
+
/**
|
|
90
|
+
* Populate {@link RenderResult.regions} with the schema-field geometry
|
|
91
|
+
* sidecar (the same entries {@link LiveSession.regions} serves), for
|
|
92
|
+
* consumers without a live session — e.g. overlays over a one-shot SVG
|
|
93
|
+
* export. Defaults to `false`: exports pay no introspection cost.
|
|
94
|
+
*/
|
|
95
|
+
regions?: boolean;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* How precisely a {@link CorpusHit.pos} resolved — the marker a caret UI reads
|
|
100
|
+
* to decide whether to trust the offset. Never sub-cluster: `'cluster'` is the
|
|
101
|
+
* finest, `'segment'` the floor it degrades to on origin-less ink.
|
|
102
|
+
*
|
|
103
|
+
* - `'cluster'` — `pos` is the first corpus char of the cluster under the point
|
|
104
|
+
* (an escaped/CJK/shaping cluster floors to its first char). Place the caret
|
|
105
|
+
* at `pos` directly.
|
|
106
|
+
* - `'segment'` — the point hit origin-less ink (list markers, numbering, a
|
|
107
|
+
* multi-line code fence's interior), so `pos` degraded to the containing
|
|
108
|
+
* segment's start. Treat `pos` as the selected segment, not a caret.
|
|
109
|
+
*/
|
|
110
|
+
export type HitGranularity = 'cluster' | 'segment';
|
|
111
|
+
|
|
112
|
+
/** A click resolved to a field and USV offset into its RichText. */
|
|
113
|
+
export interface CorpusHit {
|
|
114
|
+
field: string;
|
|
115
|
+
pos: number;
|
|
116
|
+
/**
|
|
117
|
+
* Whether {@link pos} is cluster-exact or floored to the segment start
|
|
118
|
+
* ({@link HitGranularity}). Absent when the backend does not report it.
|
|
119
|
+
*/
|
|
120
|
+
granularity?: HitGranularity;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* A rendered field region: the quill schema field address (`field`) plus its
|
|
125
|
+
* geometry (`rect`) on the page. Emitted by backends that place schema fields
|
|
126
|
+
* (`pdfform` AcroForm widgets; Typst form-fields and span-tracked content —
|
|
127
|
+
* richtext bodies, `richtext[]` elements, card content fields, direct scalar
|
|
128
|
+
* references). Only fields with a schema address produce a region — a
|
|
129
|
+
* backend-only widget produces none, and the backend widget name never
|
|
130
|
+
* appears.
|
|
131
|
+
*
|
|
132
|
+
* Use it to scroll to / highlight the focused field's rect; for the click
|
|
133
|
+
* direction use {@link LiveSession.fieldAt}, which resolves a point on *any*
|
|
134
|
+
* placement, not just the first one surfaced here. Geometry only —
|
|
135
|
+
* `LiveSession.paint` already bakes every value into the raster (see
|
|
136
|
+
* {@link LiveSession}), so a region is never a compositing input.
|
|
137
|
+
*
|
|
138
|
+
* COORDINATE TRANSFORM. `rect` is in PDF points with a **bottom-left** origin.
|
|
139
|
+
*
|
|
140
|
+
* For an **HTML/CSS overlay** on a `width:100%` canvas, position hotspots as
|
|
141
|
+
* percentages of the page — they track the displayed size across DPI and pane
|
|
142
|
+
* resize for free, and only the Y axis flips:
|
|
143
|
+
*
|
|
144
|
+
* ```js
|
|
145
|
+
* const [x0, y0, x1, y1] = region.rect; // PDF pt, bottom-left origin
|
|
146
|
+
* const left = (x0 / pageWidthPt) * 100; // % of page (from PageSize.widthPt)
|
|
147
|
+
* const top = (1 - y1 / pageHeightPt) * 100; // % — flip Y (from PageSize.heightPt)
|
|
148
|
+
* const width = ((x1 - x0) / pageWidthPt) * 100;
|
|
149
|
+
* const height = ((y1 - y0) / pageHeightPt) * 100;
|
|
150
|
+
* ```
|
|
151
|
+
*
|
|
152
|
+
* For painting **into a raster** at `renderScale` (= `layoutScale × densityScale`),
|
|
153
|
+
* use the device-pixel form instead:
|
|
154
|
+
*
|
|
155
|
+
* ```js
|
|
156
|
+
* const left = x0 * renderScale;
|
|
157
|
+
* const top = (pageHeightPt - y1) * renderScale; // flip Y
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
export interface FieldRegion {
|
|
161
|
+
/** Quill schema field path (e.g. `"signature_block"`), not a backend widget name. */
|
|
162
|
+
field: string;
|
|
163
|
+
/** 0-based page index. */
|
|
164
|
+
page: number;
|
|
165
|
+
/** `[x0, y0, x1, y1]` in PDF points (1/72″), bottom-left origin. */
|
|
166
|
+
rect: [number, number, number, number];
|
|
167
|
+
/**
|
|
168
|
+
* The corpus slice this box covers — USV `[start, end)` into the field's
|
|
169
|
+
* `RichText` for content ink (one segment), absent for a scalar reference
|
|
170
|
+
* site or widget. Consumers key segment highlights on it;
|
|
171
|
+
* {@link LiveSession.fieldBoxes} unions same-page segments for the
|
|
172
|
+
* whole-field box.
|
|
173
|
+
*/
|
|
174
|
+
span?: [number, number];
|
|
87
175
|
}
|
|
88
176
|
|
|
89
177
|
/** Canonical contract every backend build must satisfy. Result of one render. */
|
|
@@ -92,6 +180,14 @@ export interface RenderResult {
|
|
|
92
180
|
warnings: Diagnostic[];
|
|
93
181
|
outputFormat: OutputFormat;
|
|
94
182
|
renderTimeMs: number;
|
|
183
|
+
/**
|
|
184
|
+
* Schema-field geometry sidecar — populated only when
|
|
185
|
+
* {@link RenderOptions.regions} requested it; empty otherwise. The same
|
|
186
|
+
* entries {@link LiveSession.regions} serves, for consumers without a live
|
|
187
|
+
* session. Page indices are document-space even under a `pages` subset
|
|
188
|
+
* render.
|
|
189
|
+
*/
|
|
190
|
+
regions: FieldRegion[];
|
|
95
191
|
}
|
|
96
192
|
|
|
97
193
|
/** Canonical contract every backend build must satisfy. The emittable formats. */
|
|
@@ -99,7 +195,6 @@ export type OutputFormat = 'pdf' | 'svg' | 'txt' | 'png';
|
|
|
99
195
|
|
|
100
196
|
/**
|
|
101
197
|
* Canonical contract every backend build must satisfy. Page geometry in pt.
|
|
102
|
-
* @experimental Part of the iterative-session/canvas surface — see {@link RenderSession}.
|
|
103
198
|
*/
|
|
104
199
|
export interface PageSize {
|
|
105
200
|
widthPt: number;
|
|
@@ -108,7 +203,6 @@ export interface PageSize {
|
|
|
108
203
|
|
|
109
204
|
/**
|
|
110
205
|
* Canonical contract every backend build must satisfy. Inputs to `paint`.
|
|
111
|
-
* @experimental Part of the iterative-session/canvas surface — see {@link RenderSession}.
|
|
112
206
|
*/
|
|
113
207
|
export interface PaintOptions {
|
|
114
208
|
layoutScale?: number;
|
|
@@ -117,13 +211,36 @@ export interface PaintOptions {
|
|
|
117
211
|
|
|
118
212
|
/**
|
|
119
213
|
* Canonical contract every backend build must satisfy. Output of `paint`.
|
|
120
|
-
* @experimental Part of the iterative-session/canvas surface — see {@link RenderSession}.
|
|
121
214
|
*/
|
|
122
215
|
export interface PaintResult {
|
|
123
|
-
layoutWidth: number;
|
|
216
|
+
layoutWidth: number; // canvas.style.width target; independent of densityScale
|
|
124
217
|
layoutHeight: number;
|
|
125
|
-
pixelWidth: number;
|
|
218
|
+
pixelWidth: number; // canvas.width the painter wrote (clamped at 16384)
|
|
126
219
|
pixelHeight: number;
|
|
220
|
+
/**
|
|
221
|
+
* True when `MAX_BACKING_DIMENSION` forced `densityScale` down: the page is
|
|
222
|
+
* painted at fewer device pixels than requested and renders soft at the same
|
|
223
|
+
* `canvas.style` size. Reads the clamp off the return value instead of the
|
|
224
|
+
* `pixelWidth < round(layoutWidth × densityScale)` derivation.
|
|
225
|
+
*/
|
|
226
|
+
clamped: boolean;
|
|
227
|
+
/**
|
|
228
|
+
* The `densityScale` actually applied — equal to the requested value unless
|
|
229
|
+
* `clamped`, then reduced proportionally. `layoutScale × effectiveDensityScale`
|
|
230
|
+
* is the scale the backing store was rasterized at.
|
|
231
|
+
*/
|
|
232
|
+
effectiveDensityScale: number;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Canonical contract every backend build must satisfy. Output of
|
|
237
|
+
* {@link LiveSession.apply}: `dirtyPages` lists the pages whose rendered
|
|
238
|
+
* content differs from the previous compile, including added pages; removed
|
|
239
|
+
* pages are implied by `pageCount`. Repaint `dirty ∩ visible`.
|
|
240
|
+
*/
|
|
241
|
+
export interface ChangeSet {
|
|
242
|
+
pageCount: number;
|
|
243
|
+
dirtyPages: number[];
|
|
127
244
|
}
|
|
128
245
|
|
|
129
246
|
/**
|
|
@@ -161,16 +278,20 @@ export interface EngineOptions {
|
|
|
161
278
|
export declare class Engine {
|
|
162
279
|
constructor(options?: EngineOptions);
|
|
163
280
|
|
|
164
|
-
/**
|
|
281
|
+
/**
|
|
282
|
+
* Render `doc` against `quill` in one shot. Both handles are read
|
|
283
|
+
* synchronously before the first await, so the caller may `free()` them as
|
|
284
|
+
* soon as this call returns.
|
|
285
|
+
*/
|
|
165
286
|
render(quill: Quill, doc: Document, options?: RenderOptions): Promise<RenderResult>;
|
|
166
287
|
|
|
167
288
|
/**
|
|
168
|
-
* Open
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
289
|
+
* Open a live render session (canvas preview / per-page paint / `apply`).
|
|
290
|
+
* The `quill` and `doc` handles are read synchronously before the first
|
|
291
|
+
* await, so the caller may `free()` them as soon as this call returns; the
|
|
292
|
+
* caller owns the returned session and must `.free()` it.
|
|
172
293
|
*/
|
|
173
|
-
open(quill: Quill, doc: Document): Promise<
|
|
294
|
+
open(quill: Quill, doc: Document): Promise<LiveSession>;
|
|
174
295
|
|
|
175
296
|
/**
|
|
176
297
|
* Output formats `quill`'s backend can emit. An ALWAYS-free pre-render probe:
|
|
@@ -180,29 +301,126 @@ export declare class Engine {
|
|
|
180
301
|
supportedFormats(quill: Quill): Promise<OutputFormat[]>;
|
|
181
302
|
|
|
182
303
|
/**
|
|
183
|
-
* Whether `quill`'s
|
|
184
|
-
*
|
|
185
|
-
* `
|
|
186
|
-
*
|
|
304
|
+
* Whether `quill`'s BACKEND can paint sessions to a canvas — a pre-session
|
|
305
|
+
* ESTIMATE, not a fact about any particular compile. Same always-free probe
|
|
306
|
+
* as `supportedFormats`: answered from the descriptor's required `canvas`
|
|
307
|
+
* manifest, no binary load and no quill clone. Both the Typst and pdfform
|
|
308
|
+
* backends report `true` here unconditionally; each paints a complete page
|
|
309
|
+
* raster (see {@link LiveSession.paint}) — but a specific compile can still
|
|
310
|
+
* refuse to paint (e.g. a 0-page document), so this can answer `true` while
|
|
311
|
+
* the resulting {@link LiveSession.supportsCanvas} answers `false`. Gate
|
|
312
|
+
* mounting a canvas UI on this; gate the actual `paint` call on the session's
|
|
313
|
+
* getter once `open()` has run.
|
|
187
314
|
*/
|
|
188
315
|
supportsCanvas(quill: Quill): Promise<boolean>;
|
|
189
316
|
}
|
|
190
317
|
|
|
191
318
|
/**
|
|
192
319
|
* Iterative render session over a compiled snapshot. `free()` when done.
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
320
|
+
*
|
|
321
|
+
* CANVAS PAINT IS COMPLETE. {@link LiveSession.paint} writes a complete page
|
|
322
|
+
* raster — every piece of page content is already visible in the painted
|
|
323
|
+
* pixels, with NO compositing required by the caller. Both backends that
|
|
324
|
+
* support canvas satisfy this: Typst rasterizes its laid-out page natively;
|
|
325
|
+
* pdfform pre-flattens bound field values into the page content and rasterizes
|
|
326
|
+
* that, so field values appear in the raster on their own.
|
|
327
|
+
* {@link LiveSession.regions} carries schema-field geometry for interactive
|
|
328
|
+
* overlays / cross-navigation drawn on top of the raster; it is never needed to
|
|
329
|
+
* complete the picture.
|
|
197
330
|
*/
|
|
198
|
-
export declare class
|
|
331
|
+
export declare class LiveSession {
|
|
199
332
|
private constructor();
|
|
200
333
|
readonly pageCount: number;
|
|
201
334
|
readonly backendId: string;
|
|
335
|
+
/**
|
|
336
|
+
* `true` iff `paint`/`pageSize` will succeed for THIS compile — the
|
|
337
|
+
* authoritative answer, derived from the session's canvas seam, so it can
|
|
338
|
+
* never disagree with what `paint` actually does. This can be `false` even
|
|
339
|
+
* when {@link Engine.supportsCanvas} answered `true` for the same `quill`
|
|
340
|
+
* (that probe is a pre-session backend estimate; e.g. a canvas-capable
|
|
341
|
+
* backend compiled to a 0-page document has nothing to paint). Re-check
|
|
342
|
+
* this getter after `open()` rather than relying on the engine hint alone.
|
|
343
|
+
*/
|
|
202
344
|
readonly supportsCanvas: boolean;
|
|
203
345
|
readonly warnings: Diagnostic[];
|
|
346
|
+
/**
|
|
347
|
+
* Recompile the session against `doc` — the edit verb of a live preview.
|
|
348
|
+
* Transactional: on throw every read (`render`, `paint`, `pageSize`,
|
|
349
|
+
* `regions`) keeps serving the last-good compile, and the session recovers
|
|
350
|
+
* on the next successful `apply`. On success reads serve the new compile;
|
|
351
|
+
* repaint `dirtyPages ∩ visible`.
|
|
352
|
+
*/
|
|
353
|
+
apply(doc: Document): ChangeSet;
|
|
204
354
|
render(options?: RenderOptions): RenderResult;
|
|
355
|
+
/**
|
|
356
|
+
* Schema-field geometry for this compiled session, keyed on quill schema
|
|
357
|
+
* field path. A session-level query: no render, no byte artifact. Read it
|
|
358
|
+
* to scroll to / highlight the focused field over a `paint`-ed canvas;
|
|
359
|
+
* the click direction is {@link fieldAt}. Empty for backends that place
|
|
360
|
+
* no schema fields.
|
|
361
|
+
*
|
|
362
|
+
* `field` is **not** unique: a content field surfaces its **first
|
|
363
|
+
* placement** as one {@link FieldRegion} per page that placement touches
|
|
364
|
+
* (so a highlight covers continuation pages); a scalar referenced at
|
|
365
|
+
* several plate sites surfaces each site; tracked content plus a
|
|
366
|
+
* `field:`-bound widget yields both, widget ordered first. Group by
|
|
367
|
+
* `field` — every entry routes to that field. Later placements of one
|
|
368
|
+
* content value are not enumerated; {@link fieldAt} still resolves
|
|
369
|
+
* clicks on them.
|
|
370
|
+
*/
|
|
371
|
+
regions(): FieldRegion[];
|
|
372
|
+
/**
|
|
373
|
+
* The whole-field highlight boxes for `field` — one union rect per page,
|
|
374
|
+
* over the field's `span`-bearing content segments (the "highlight the
|
|
375
|
+
* focused field" quantity). Owns the union {@link regions} leaves derived
|
|
376
|
+
* (span-filter + per-page union), keeping `regions()` the low-level disjoint
|
|
377
|
+
* truth, so a consumer stops reimplementing it. **Content only** — a field
|
|
378
|
+
* placed solely as a scalar reference or a bound widget carries no `span`
|
|
379
|
+
* and returns `[]`; its box is a single {@link regions} rect. Reflects the
|
|
380
|
+
* current compile, like `regions()`.
|
|
381
|
+
*/
|
|
382
|
+
fieldBoxes(field: string): FieldRegion[];
|
|
383
|
+
/**
|
|
384
|
+
* The schema field whose content is under a point on `page` — the forward
|
|
385
|
+
* (click → field) direction: hit-test a click against the compiled
|
|
386
|
+
* document and get back the field address to focus in the editor, or
|
|
387
|
+
* `undefined` off any field's ink. `x`/`y` are PDF points with a
|
|
388
|
+
* **bottom-left** origin, the same space as {@link FieldRegion.rect} —
|
|
389
|
+
* from a canvas click, invert the overlay transform documented there:
|
|
390
|
+
* `x = clickPx.x / renderScale`,
|
|
391
|
+
* `y = pageHeightPt - clickPx.y / renderScale`. Unlike {@link regions},
|
|
392
|
+
* *every* placement answers, not just the first.
|
|
393
|
+
*/
|
|
394
|
+
fieldAt(page: number, x: number, y: number): string | undefined;
|
|
395
|
+
/**
|
|
396
|
+
* Fine-grained click → corpus position (caret placement). Same PDF-point
|
|
397
|
+
* space as {@link fieldAt}; `undefined` off all content ink.
|
|
398
|
+
*/
|
|
399
|
+
positionAt(page: number, x: number, y: number): CorpusHit | undefined;
|
|
400
|
+
/** Corpus position → caret rect — reverse of {@link positionAt}. */
|
|
401
|
+
locate(field: string, pos: number): FieldRegion | undefined;
|
|
402
|
+
/** Page geometry in points (1/72″). Report-only; the painter sizes the canvas. */
|
|
205
403
|
pageSize(page: number): PageSize;
|
|
404
|
+
/**
|
|
405
|
+
* Paint `page` into a 2D canvas context, sizing the backing store itself
|
|
406
|
+
* (it owns `canvas.width`/`height`; the caller owns `canvas.style.*`). The
|
|
407
|
+
* painted raster is COMPLETE — all page content visible, no caller-side
|
|
408
|
+
* compositing (Typst rasterizes natively; pdfform rasterizes its
|
|
409
|
+
* pre-flattened page). Effective rasterization scale is
|
|
410
|
+
* `layoutScale × densityScale`, clamped so neither backing dimension exceeds
|
|
411
|
+
* 16384 px — {@link PaintResult.clamped} reports the clamp and
|
|
412
|
+
* {@link PaintResult.effectiveDensityScale} the density actually applied.
|
|
413
|
+
*
|
|
414
|
+
* The write is a whole-backing-store `putImageData`, which bypasses the 2D
|
|
415
|
+
* context transform, `globalAlpha`, and clip: the painter owns the entire
|
|
416
|
+
* canvas, so give each visible page its own `` element. You cannot
|
|
417
|
+
* paint two pages into one canvas, paint into a sub-rect, or apply a context
|
|
418
|
+
* transform through this call — the raster is complete precisely so you never
|
|
419
|
+
* need to. Keep the per-page canvases alive while their pages stay near the
|
|
420
|
+
* viewport: each `paint` re-rasterizes from scratch, so reusing (pooling) a
|
|
421
|
+
* canvas across pages on scroll re-runs a full render, whereas an idle canvas
|
|
422
|
+
* retains its pixels for free.
|
|
423
|
+
*/
|
|
206
424
|
paint(
|
|
207
425
|
ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
|
|
208
426
|
page: number,
|
|
@@ -210,3 +428,91 @@ export declare class RenderSession {
|
|
|
210
428
|
): PaintResult;
|
|
211
429
|
free(): void;
|
|
212
430
|
}
|
|
431
|
+
|
|
432
|
+
// ── Typed writer — the tier-1 front door ────────────────────────────────────
|
|
433
|
+
|
|
434
|
+
// `quill.writer(doc)` is patched onto the re-exported `Quill` prototype (the
|
|
435
|
+
// class is re-exported verbatim, so the method is declared by merging into the
|
|
436
|
+
// core module's `Quill` rather than redeclaring the class).
|
|
437
|
+
declare module '../core/wasm.js' {
|
|
438
|
+
interface Quill {
|
|
439
|
+
/**
|
|
440
|
+
* Bind this quill's schema to `doc` for typed writes — the documented
|
|
441
|
+
* front door, mirroring core's `quill.writer(&mut doc)`. The schema grants
|
|
442
|
+
* the typing, so the quill is the factory. The returned writer holds both
|
|
443
|
+
* handles by reference and owns neither (nothing to `free()`); it is
|
|
444
|
+
* ephemeral by convention — bind, write, discard.
|
|
445
|
+
*/
|
|
446
|
+
writer(doc: Document): DocumentWriter;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* A `Document` bound to its `Quill` for typed writes — the tier-1 default,
|
|
452
|
+
* constructed via {@link Quill.writer}. Speaks names, values, and markdown; a
|
|
453
|
+
* consumer here never meets an `Addr`, a corpus object, or a `Delta`. Bare
|
|
454
|
+
* `set` / `setAll` / `setBody` / `addCard` / `card(i).set` instead of threading
|
|
455
|
+
* the `quill` handle through every `commit*` call. Holds both handles by
|
|
456
|
+
* reference and owns neither — nothing to `free()`.
|
|
457
|
+
*
|
|
458
|
+
* Typed commit is the default whenever a quill is in hand: it resolves each
|
|
459
|
+
* field's schema type and strict-commits it, throwing `UnknownField` for a name
|
|
460
|
+
* the schema does not declare — on the typed path an undeclared name is a typo,
|
|
461
|
+
* not a fallback. The raw `Document.setField` / `setFields` verbs remain the
|
|
462
|
+
* deliberate quill-free primitive (standalone data, storage/migration infra, or
|
|
463
|
+
* holding not-yet-conforming in-progress input).
|
|
464
|
+
*/
|
|
465
|
+
export declare class DocumentWriter {
|
|
466
|
+
constructor(quill: Quill, doc: Document);
|
|
467
|
+
/** The bound document — the instance passed in, mutated in place. */
|
|
468
|
+
readonly document: Document;
|
|
469
|
+
/**
|
|
470
|
+
* Typed-commit one main-card field (strict coerce, mismatch throws now).
|
|
471
|
+
* Throws `UnknownField` for a name the schema does not declare.
|
|
472
|
+
*/
|
|
473
|
+
set(name: string, value: unknown): void;
|
|
474
|
+
/**
|
|
475
|
+
* Typed-commit several main-card fields atomically — nothing is applied on
|
|
476
|
+
* error (throws a {@link QuillmarkError} carrying one diagnostic per
|
|
477
|
+
* offending field, including an `UnknownField` for each undeclared name).
|
|
478
|
+
*/
|
|
479
|
+
setAll(fields: Record<string, unknown>): void;
|
|
480
|
+
/**
|
|
481
|
+
* Set the main body from markdown (edit semantics: anchors rebase), discarding
|
|
482
|
+
* the delta — the receipt-free body write. Use `doc.revise({}, md)` for the
|
|
483
|
+
* `Delta` receipt.
|
|
484
|
+
*/
|
|
485
|
+
setBody(markdown: string): void;
|
|
486
|
+
/**
|
|
487
|
+
* Build a composable card of `kind`, typed-commit `fields` onto it, set its
|
|
488
|
+
* body from optional markdown, and append it — the fused `makeCard` + typed
|
|
489
|
+
* commit + `pushCard`. Transactional: a rejected field (throws a per-field
|
|
490
|
+
* diagnostic bundle) or an invalid kind/body leaves the document untouched.
|
|
491
|
+
*/
|
|
492
|
+
addCard(kind: string, fields?: Record<string, unknown>, body?: string): void;
|
|
493
|
+
/** Remove the composable card at `index`, returning it (or `undefined`). */
|
|
494
|
+
removeCard(index: number): Card | undefined;
|
|
495
|
+
/**
|
|
496
|
+
* A {@link CardWriter} for the composable card at `index`. Index validity is
|
|
497
|
+
* checked lazily at commit time, so this never throws. The cursor is
|
|
498
|
+
* ephemeral — a `removeCard`/`addCard` between binding and writing silently
|
|
499
|
+
* retargets it; for durable addressing stamp `$id` and re-resolve at write.
|
|
500
|
+
*/
|
|
501
|
+
card(index: number): CardWriter;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* A composable card bound to its `Quill` for typed writes, from
|
|
506
|
+
* {@link DocumentWriter.card}. Same verbs as {@link DocumentWriter}, targeting
|
|
507
|
+
* the card at its bound index; each write throws `IndexOutOfRange` if that index
|
|
508
|
+
* is out of range.
|
|
509
|
+
*/
|
|
510
|
+
export declare class CardWriter {
|
|
511
|
+
constructor(quill: Quill, doc: Document, index: number);
|
|
512
|
+
/** The bound card index. */
|
|
513
|
+
readonly index: number;
|
|
514
|
+
set(name: string, value: unknown): void;
|
|
515
|
+
setAll(fields: Record<string, unknown>): void;
|
|
516
|
+
/** Set this card's body from markdown (edit semantics), discarding the delta. */
|
|
517
|
+
setBody(markdown: string): void;
|
|
518
|
+
}
|