@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/backends/typst/wasm.d.ts
CHANGED
|
@@ -24,10 +24,11 @@ export type PayloadItem =
|
|
|
24
24
|
| { type: "comment"; text: string; inline?: boolean };
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
* A single card block
|
|
28
|
-
* `Document.main` / `Document.cards` / `Document.removeCard` / `Quill.seedCard
|
|
29
|
-
*
|
|
30
|
-
*
|
|
27
|
+
* A single card block, as read back from a document: returned by
|
|
28
|
+
* `Document.main` / `Document.cards` / `Document.removeCard` / `Quill.seedCard`
|
|
29
|
+
* / `Document.makeCard`. To feed a card *into* a document use `CardInput`
|
|
30
|
+
* (which `pushCard` / `insertCard` accept); every `Card` is a valid `CardInput`,
|
|
31
|
+
* so a card read from one document pushes straight into another.
|
|
31
32
|
*
|
|
32
33
|
* `$` system entries are hoisted to named fields: `kind` (the `$kind`, empty
|
|
33
34
|
* string when none), optional `quill` (the `$quill` `name@version`, main card
|
|
@@ -42,13 +43,146 @@ export interface Card {
|
|
|
42
43
|
ext?: Record<string, unknown>;
|
|
43
44
|
seed?: Record<string, unknown>;
|
|
44
45
|
payloadItems: PayloadItem[];
|
|
45
|
-
|
|
46
|
+
/**
|
|
47
|
+
* The card body as canonical `RichText` — the source-of-truth content model.
|
|
48
|
+
* Always this corpus shape on read, never a markdown string. For the markdown
|
|
49
|
+
* projection call the codec `exportMarkdown(card.body)`. Write a body back
|
|
50
|
+
* with `doc.install(addr, rt)` / `doc.revise(addr, md)`, or via `CardInput.body`.
|
|
51
|
+
*/
|
|
52
|
+
body: RichText;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* A card written *into* a document — the input twin of `Card`, accepted by
|
|
57
|
+
* `Document.pushCard` / `Document.insertCard`. Like `Card` but `body` also
|
|
58
|
+
* takes a markdown `string` (imported to the corpus, so a markdown / LLM writer
|
|
59
|
+
* needn't build the `RichText` shape), and every field but `kind` is optional —
|
|
60
|
+
* an absent field defaults (no payload items, an empty body). Write one inline
|
|
61
|
+
* (`{ kind, body }`) or build it with `Document.makeCard`.
|
|
62
|
+
*/
|
|
63
|
+
export interface CardInput {
|
|
64
|
+
kind: string;
|
|
65
|
+
quill?: string;
|
|
66
|
+
id?: string;
|
|
67
|
+
ext?: Record<string, unknown>;
|
|
68
|
+
seed?: Record<string, unknown>;
|
|
69
|
+
payloadItems?: PayloadItem[];
|
|
70
|
+
body?: RichText | string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Canonical richtext corpus — the content model for a card body (and richtext
|
|
75
|
+
* fields). One text sequence over a single coordinate space (Unicode scalar
|
|
76
|
+
* values): `text` plus line attributes, anchored `marks`, and embedded
|
|
77
|
+
* `islands`. Every edit is a splice; markdown is a projection, not the model.
|
|
78
|
+
* Mirrors `quillmark_richtext::serial`'s canonical JSON encoding.
|
|
79
|
+
*/
|
|
80
|
+
export interface RichText {
|
|
81
|
+
text: string;
|
|
82
|
+
lines: RichTextLine[];
|
|
83
|
+
marks: RichTextMark[];
|
|
84
|
+
islands: RichTextIsland[];
|
|
46
85
|
}
|
|
47
86
|
|
|
87
|
+
/** One `\n`-separated segment of `RichText.text`, in order. */
|
|
88
|
+
export type RichTextLine = {
|
|
89
|
+
containers: RichTextContainer[];
|
|
90
|
+
/** A within-block hard line break rather than a new block. Omitted (false) in the common case. */
|
|
91
|
+
continues?: boolean;
|
|
92
|
+
} & (
|
|
93
|
+
| { kind: "para" }
|
|
94
|
+
| { kind: "heading"; level: number }
|
|
95
|
+
| { kind: "code"; lang?: string }
|
|
96
|
+
| { kind: "island" }
|
|
97
|
+
| { kind: "rule" }
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
/** An ancestor block a line nests inside, outermost first. */
|
|
101
|
+
export type RichTextContainer =
|
|
102
|
+
| { container: "list_item"; ordered: boolean; start: number; ordinal: number }
|
|
103
|
+
| { container: "quote" };
|
|
104
|
+
|
|
105
|
+
/** A mark over char range `[start, end)` into `RichText.text`. */
|
|
106
|
+
export type RichTextMark = { start: number; end: number } & (
|
|
107
|
+
| { type: "strong" | "emph" | "underline" | "strike" | "code" }
|
|
108
|
+
| { type: "link"; url: string }
|
|
109
|
+
| { type: "anchor"; id: string }
|
|
110
|
+
| { type: string; attrs: unknown }
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
/** A structured object (table, figure, …) occupying one island slot in `RichText.text`. */
|
|
114
|
+
export interface RichTextIsland {
|
|
115
|
+
id: string;
|
|
116
|
+
type: string;
|
|
117
|
+
props: unknown;
|
|
118
|
+
/** How faithfully the markdown projection can carry this island. */
|
|
119
|
+
loss: "lossless" | "degraded" | "unrepresentable";
|
|
120
|
+
}
|
|
48
121
|
|
|
122
|
+
/**
|
|
123
|
+
* A richtext write address. An absent `field` targets the card body; an absent
|
|
124
|
+
* `card` targets the main card. `{}` is the main-card body; `{ card: 2 }` the
|
|
125
|
+
* body of the composable card at index 2; `{ field: "intro" }` the main card's
|
|
126
|
+
* `intro` richtext field; `{ card: 2, field: "intro" }` a card field.
|
|
127
|
+
*/
|
|
128
|
+
export interface Addr {
|
|
129
|
+
card?: number;
|
|
130
|
+
field?: string;
|
|
131
|
+
}
|
|
49
132
|
|
|
50
133
|
/**
|
|
51
|
-
*
|
|
134
|
+
* A text-splice change set over the USV corpus (CodeMirror `ChangeSet`
|
|
135
|
+
* semantics) — plain, structured-clone-able data. Returned by `revise` and by
|
|
136
|
+
* the `rebase` codec; map a stored position through it with `mapPos`.
|
|
137
|
+
*/
|
|
138
|
+
export interface Delta {
|
|
139
|
+
ops: ({ retain: number } | { insert: string } | { delete: number })[];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Which side of a same-position insertion `mapPos` lands a point on. */
|
|
143
|
+
export type Assoc = "before" | "after";
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* A mark edit in post-text-delta coordinates. `add` / `remove` carry the
|
|
147
|
+
* `RichTextMark` vocabulary (`{ type, … }`); `removeAnchor` drops one identity
|
|
148
|
+
* anchor by id.
|
|
149
|
+
*/
|
|
150
|
+
export type MarkOp =
|
|
151
|
+
| ({ op: "add" | "remove"; start: number; end: number } & (
|
|
152
|
+
| { type: "strong" | "emph" | "underline" | "strike" | "code" }
|
|
153
|
+
| { type: "link"; url: string }
|
|
154
|
+
| { type: "anchor"; id: string }
|
|
155
|
+
| { type: string; attrs: unknown }
|
|
156
|
+
))
|
|
157
|
+
| { op: "removeAnchor"; id: string };
|
|
158
|
+
|
|
159
|
+
/** A line/block edit. `split`/`join` splice `\n`; `setKind`/`setContainers` touch metadata. */
|
|
160
|
+
export type LineOp =
|
|
161
|
+
| { op: "split"; at: number }
|
|
162
|
+
| { op: "join"; line: number }
|
|
163
|
+
| ({ op: "setKind"; line: number } & (
|
|
164
|
+
| { kind: "para" | "island" | "rule" }
|
|
165
|
+
| { kind: "heading"; level: number }
|
|
166
|
+
| { kind: "code"; lang?: string }
|
|
167
|
+
))
|
|
168
|
+
| { op: "setContainers"; line: number; containers: RichTextContainer[] };
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* A committed corpus edit bundle for `applyChange`: a text `delta` (default no
|
|
172
|
+
* text change), then `lineOps`, then `markOps` (mark ranges are in post-delta
|
|
173
|
+
* coordinates). Every field is optional.
|
|
174
|
+
*/
|
|
175
|
+
export interface ChangeBundle {
|
|
176
|
+
delta?: Delta;
|
|
177
|
+
lineOps?: LineOp[];
|
|
178
|
+
markOps?: MarkOp[];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Page dimensions in points (1 pt = 1/72 inch). Typst measures in Typst
|
|
185
|
+
* points; pdfform measures in PDF points — the same unit.
|
|
52
186
|
*
|
|
53
187
|
* Report-only: the painter sizes the canvas itself based on
|
|
54
188
|
* `PaintOptions`. `pageSize` is exposed for callers that need page
|
|
@@ -61,10 +195,11 @@ export interface PageSize {
|
|
|
61
195
|
}
|
|
62
196
|
|
|
63
197
|
/**
|
|
64
|
-
* Inputs to `
|
|
198
|
+
* Inputs to `LiveSession.paint`. Both fields are optional and default
|
|
65
199
|
* to `1`.
|
|
66
200
|
*
|
|
67
|
-
* - `layoutScale` — layout-space pixels per Typst point
|
|
201
|
+
* - `layoutScale` — layout-space pixels per point (Typst point / PDF
|
|
202
|
+
* point — the same 1/72″ unit). For on-screen
|
|
68
203
|
* canvases this is CSS pixels per pt; the page's layout-pixel size is
|
|
69
204
|
* `widthPt * layoutScale × heightPt * layoutScale`. The painter
|
|
70
205
|
* surfaces these dimensions as `layoutWidth` / `layoutHeight` so
|
|
@@ -86,7 +221,7 @@ export interface PaintOptions {
|
|
|
86
221
|
}
|
|
87
222
|
|
|
88
223
|
/**
|
|
89
|
-
* Returned by `
|
|
224
|
+
* Returned by `LiveSession.paint`.
|
|
90
225
|
*
|
|
91
226
|
* - `layoutWidth` / `layoutHeight` — layout-pixel dimensions of the
|
|
92
227
|
* canvas's display box. For on-screen canvases this is CSS pixels:
|
|
@@ -98,12 +233,22 @@ export interface PaintOptions {
|
|
|
98
233
|
* Equal to `round(layoutWidth * densityScale)` ×
|
|
99
234
|
* `round(layoutHeight * densityScale)` *unless* the requested backing
|
|
100
235
|
* exceeded the painter's safe maximum (16384 px per side), in which
|
|
101
|
-
* case `densityScale` was clamped to fit.
|
|
102
|
-
*
|
|
236
|
+
* case `densityScale` was clamped to fit.
|
|
237
|
+
* - `clamped` — `true` when that 16384-px clamp fired, so the page is
|
|
238
|
+
* painted at fewer device pixels than requested and renders soft at the
|
|
239
|
+
* same `canvas.style` size. Reads the clamp off the return value instead
|
|
240
|
+
* of the `pixelWidth < round(layoutWidth * densityScale)` derivation.
|
|
241
|
+
* - `effectiveDensityScale` — the `densityScale` actually applied: the
|
|
242
|
+
* requested value unless `clamped`, then reduced proportionally.
|
|
243
|
+
* `layoutScale * effectiveDensityScale` is the scale the backing store
|
|
244
|
+
* was rasterized at.
|
|
103
245
|
*
|
|
104
246
|
* The painter owns `canvas.width` / `canvas.height`; consumers must not
|
|
105
247
|
* write to them. The painter does **not** touch `canvas.style.*`;
|
|
106
|
-
* consumers own layout.
|
|
248
|
+
* consumers own layout. The write is a whole-backing-store `putImageData`,
|
|
249
|
+
* which bypasses the 2D context transform, `globalAlpha`, and clip: give
|
|
250
|
+
* each visible page its own `` — you cannot composite two pages, a
|
|
251
|
+
* sub-rect, or a context transform through `paint`.
|
|
107
252
|
*
|
|
108
253
|
* For `OffscreenCanvasRenderingContext2D` (Worker rasterization, no
|
|
109
254
|
* DOM), `layoutWidth` / `layoutHeight` are informational — there's no
|
|
@@ -114,14 +259,18 @@ export interface PaintResult {
|
|
|
114
259
|
layoutHeight: number;
|
|
115
260
|
pixelWidth: number;
|
|
116
261
|
pixelHeight: number;
|
|
262
|
+
clamped: boolean;
|
|
263
|
+
effectiveDensityScale: number;
|
|
117
264
|
}
|
|
118
265
|
|
|
119
266
|
|
|
120
267
|
|
|
121
|
-
/** UI layout hints for a single field.
|
|
268
|
+
/** UI layout hints for a single field. Field display order is not a hint:
|
|
269
|
+
* key order in the schema's `fields`/`properties` objects is declaration
|
|
270
|
+
* order, the ordering contract. */
|
|
122
271
|
export interface QuillFieldUi {
|
|
272
|
+
title?: string;
|
|
123
273
|
group?: string;
|
|
124
|
-
order?: number;
|
|
125
274
|
compact?: boolean;
|
|
126
275
|
multiline?: boolean;
|
|
127
276
|
}
|
|
@@ -144,20 +293,28 @@ export interface QuillCardBody {
|
|
|
144
293
|
* A field's *cell* is determined by `default`: a field with a `default`
|
|
145
294
|
* is **Endorsed** (the rendered value is shippable as-is), while a field
|
|
146
295
|
* without a `default` is **Unendorsed** (the blueprint carries a
|
|
147
|
-
*
|
|
148
|
-
* `validation::
|
|
149
|
-
*
|
|
150
|
-
* field). There is no separate `required` axis.
|
|
296
|
+
* `!must_fill` marker; a marker left in the document yields the non-fatal
|
|
297
|
+
* `validation::must_fill` warning from validate, and the render path
|
|
298
|
+
* zero-fills the field). There is no separate `required` axis.
|
|
151
299
|
*/
|
|
152
300
|
export interface QuillFieldSchema {
|
|
153
|
-
type: "string" | "number" | "integer" | "boolean" | "array" | "object" | "datetime" | "
|
|
301
|
+
type: "string" | "number" | "integer" | "boolean" | "array" | "object" | "datetime" | "richtext" | "plaintext" | "enum";
|
|
154
302
|
description?: string;
|
|
155
303
|
default?: unknown;
|
|
156
304
|
example?: unknown;
|
|
305
|
+
/** Closed value domain. On `type: "enum"` declared as `values`; the
|
|
306
|
+
* deprecated `enum` modifier on `type: "string"` is accepted for one
|
|
307
|
+
* release. Both round-trip through this field. */
|
|
157
308
|
enum?: string[];
|
|
309
|
+
/** Required on `type: "enum"`: the closed set of allowed string values. */
|
|
310
|
+
values?: string[];
|
|
158
311
|
ui?: QuillFieldUi;
|
|
159
312
|
properties?: Record<string, QuillFieldSchema>;
|
|
160
313
|
items?: QuillFieldSchema;
|
|
314
|
+
/** Present (and `true`) on a `richtext` or `plaintext` field declared
|
|
315
|
+
* `inline` — the single-paragraph, container-free, island-free constraint.
|
|
316
|
+
* Core serializes `inline: true` into the schema JSON; absent otherwise. */
|
|
317
|
+
inline?: boolean;
|
|
161
318
|
}
|
|
162
319
|
|
|
163
320
|
/** Schema entry for the main card or a named card kind. */
|
|
@@ -202,6 +359,17 @@ export interface Artifact {
|
|
|
202
359
|
mimeType: string;
|
|
203
360
|
}
|
|
204
361
|
|
|
362
|
+
export interface ChangeSet {
|
|
363
|
+
pageCount: number;
|
|
364
|
+
dirtyPages: number[];
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
export interface CorpusHit {
|
|
368
|
+
field: string;
|
|
369
|
+
pos: number;
|
|
370
|
+
granularity?: HitGranularity;
|
|
371
|
+
}
|
|
372
|
+
|
|
205
373
|
export interface Diagnostic {
|
|
206
374
|
severity: Severity;
|
|
207
375
|
code?: string;
|
|
@@ -212,6 +380,13 @@ export interface Diagnostic {
|
|
|
212
380
|
sourceChain?: string[];
|
|
213
381
|
}
|
|
214
382
|
|
|
383
|
+
export interface FieldRegion {
|
|
384
|
+
field: string;
|
|
385
|
+
page: number;
|
|
386
|
+
rect: [number, number, number, number];
|
|
387
|
+
span?: [number, number];
|
|
388
|
+
}
|
|
389
|
+
|
|
215
390
|
export interface Location {
|
|
216
391
|
file: string;
|
|
217
392
|
line: number;
|
|
@@ -223,6 +398,7 @@ export interface RenderOptions {
|
|
|
223
398
|
ppi?: number;
|
|
224
399
|
pages?: number[];
|
|
225
400
|
producer?: string;
|
|
401
|
+
regions?: boolean;
|
|
226
402
|
}
|
|
227
403
|
|
|
228
404
|
export interface RenderResult {
|
|
@@ -230,20 +406,45 @@ export interface RenderResult {
|
|
|
230
406
|
warnings: Diagnostic[];
|
|
231
407
|
outputFormat: OutputFormat;
|
|
232
408
|
renderTimeMs: number;
|
|
409
|
+
regions: FieldRegion[];
|
|
233
410
|
}
|
|
234
411
|
|
|
412
|
+
export type HitGranularity = "cluster" | "segment";
|
|
413
|
+
|
|
235
414
|
export type OutputFormat = "pdf" | "svg" | "txt" | "png";
|
|
236
415
|
|
|
237
|
-
export type Severity = "error" | "warning"
|
|
416
|
+
export type Severity = "error" | "warning";
|
|
238
417
|
|
|
239
418
|
|
|
240
419
|
/**
|
|
241
420
|
* Typed in-memory Quillmark document.
|
|
242
421
|
*/
|
|
243
422
|
export class Document {
|
|
244
|
-
private constructor();
|
|
245
423
|
free(): void;
|
|
246
424
|
[Symbol.dispose](): void;
|
|
425
|
+
/**
|
|
426
|
+
* Build a composable card of `kind`, typed-commit `fields` onto it, set its
|
|
427
|
+
* body from optional markdown, and append it — the ABI under
|
|
428
|
+
* `writer.addCard`. Fuses `makeCard` + typed commit + `pushCard`
|
|
429
|
+
* transactionally: the card is committed in full before it joins the
|
|
430
|
+
* document, so a rejected field (or an invalid kind or body) leaves the
|
|
431
|
+
* document untouched. Field errors throw the same per-field diagnostic
|
|
432
|
+
* bundle as [`commitFields`](Self::commit_fields), including an
|
|
433
|
+
* `[EditError::UnknownField]` per undeclared name; an invalid kind or body
|
|
434
|
+
* throws a single-entry bundle keyed `$kind` / `$body`.
|
|
435
|
+
*/
|
|
436
|
+
addCard(quill: Quill, kind: string, fields?: Record<string, unknown>, body?: string): void;
|
|
437
|
+
/**
|
|
438
|
+
* **Apply** a committed corpus edit `bundle` (`{ delta?, lineOps?, markOps? }`)
|
|
439
|
+
* at `addr` — the editor splice: text delta first, then line ops, then mark
|
|
440
|
+
* ops (mark ranges in post-delta coordinates), each all-or-nothing. An absent
|
|
441
|
+
* `addr.field` targets the body, an absent `addr.card` the main card.
|
|
442
|
+
*
|
|
443
|
+
* Throws on an out-of-range card, a field that is not richtext, a malformed
|
|
444
|
+
* bundle, or an op that applies out of bounds (the value is unchanged on a
|
|
445
|
+
* failed apply).
|
|
446
|
+
*/
|
|
447
|
+
applyChange(addr: Addr, bundle: ChangeBundle): void;
|
|
247
448
|
/**
|
|
248
449
|
* Authoring-ergonomics header introducing a blueprint to an LLM/MCP
|
|
249
450
|
* consumer for the given `quillName`. Re-exposes core's canonical text for
|
|
@@ -252,6 +453,60 @@ export class Document {
|
|
|
252
453
|
*/
|
|
253
454
|
static blueprintInstruction(quill_name: string): string;
|
|
254
455
|
clone(): Document;
|
|
456
|
+
/**
|
|
457
|
+
* Typed field write on the composable card at `index` — the card-indexed
|
|
458
|
+
* twin of [`commitField`](Document::commit_field). Resolves the field's
|
|
459
|
+
* type from the card's `$kind` schema in `quill` and strict-commits it.
|
|
460
|
+
*
|
|
461
|
+
* Throws `[EditError::IndexOutOfRange]` when `index` is out of range, and
|
|
462
|
+
* the same typed-mismatch / name errors as `commitField` — including
|
|
463
|
+
* `[EditError::UnknownField]` for a field the card-kind schema does not
|
|
464
|
+
* declare (an unknown `$kind` has no schema, so every field is undeclared).
|
|
465
|
+
*/
|
|
466
|
+
commitCardField(quill: Quill, index: number, name: string, value: any): void;
|
|
467
|
+
/**
|
|
468
|
+
* Batched twin of [`commitCardField`](Document::commit_card_field):
|
|
469
|
+
* typed-commit several fields on the card at `index` atomically, resolving
|
|
470
|
+
* each field's type from the card's `$kind` schema in `quill`. All-or-nothing
|
|
471
|
+
* with the same per-field-diagnostic contract as
|
|
472
|
+
* [`commitFields`](Document::commit_fields), including an
|
|
473
|
+
* `[EditError::UnknownField]` diagnostic per undeclared name. Throws
|
|
474
|
+
* `[EditError::IndexOutOfRange]` when `index` is out of range.
|
|
475
|
+
*/
|
|
476
|
+
commitCardFields(quill: Quill, index: number, fields: Record<string, unknown>): void;
|
|
477
|
+
/**
|
|
478
|
+
* Typed field write on the main card, resolving the field's schema `type`
|
|
479
|
+
* from `quill` — the one write verb for **every** field type (richtext,
|
|
480
|
+
* scalar, array, object). The schema carries the `inline` constraint, so no
|
|
481
|
+
* type token or flag is passed. A richtext-typed field stores the canonical
|
|
482
|
+
* corpus, so identity marks (anchors, island ids) and corpus-only marks
|
|
483
|
+
* (e.g. `underline`) live on it and survive compiles and the storage DTO.
|
|
484
|
+
* Values use the encoding the seam already speaks: a corpus object
|
|
485
|
+
* or markdown string for richtext, a scalar/array/object otherwise.
|
|
486
|
+
*
|
|
487
|
+
* A field declared in the schema is strict-committed — a mismatch throws
|
|
488
|
+
* now, not at render. A name the schema does not declare throws
|
|
489
|
+
* `[EditError::UnknownField]` rather than falling to the opaque store: on
|
|
490
|
+
* the typed path it is a typo. Use [`setField`](Document::set_field) when
|
|
491
|
+
* opaque storage is the intent. Also throws `[EditError::FieldConform]` /
|
|
492
|
+
* `[EditError::FieldRichtextDecode]` / `[EditError::FieldRichtextNotInline]`
|
|
493
|
+
* on a typed mismatch and `[EditError::InvalidFieldName]` on a malformed
|
|
494
|
+
* name.
|
|
495
|
+
*
|
|
496
|
+
* The `quill` handle is passed per call because a `Document` carries only a
|
|
497
|
+
* `$quill` reference, not the resolved schema.
|
|
498
|
+
*/
|
|
499
|
+
commitField(quill: Quill, name: string, value: any): void;
|
|
500
|
+
/**
|
|
501
|
+
* Batched twin of [`commitField`](Document::commit_field): typed-commit
|
|
502
|
+
* several main-card fields atomically, resolving each field's schema `type`
|
|
503
|
+
* from `quill`. All-or-nothing with the same per-field-diagnostic error
|
|
504
|
+
* contract as [`setFields`](Document::set_fields) — nothing is applied on
|
|
505
|
+
* error and the thrown error's `diagnostics` carry one entry per offending
|
|
506
|
+
* field, including an `[EditError::UnknownField]` for any name the schema
|
|
507
|
+
* does not declare, so a whole-form submit sees every typo in one pass.
|
|
508
|
+
*/
|
|
509
|
+
commitFields(quill: Quill, fields: Record<string, unknown>): void;
|
|
255
510
|
/**
|
|
256
511
|
* Schema version this build writes via [`toJson`](Document::to_json).
|
|
257
512
|
* Tracks the `Document` model version (not the running crate version):
|
|
@@ -290,11 +545,53 @@ export class Document {
|
|
|
290
545
|
* Parse markdown into a typed Document. Throws on parse errors.
|
|
291
546
|
*/
|
|
292
547
|
static fromMarkdown(markdown: string): Document;
|
|
548
|
+
/**
|
|
549
|
+
* Read a main-card field's stored value — the raw payload value (a corpus
|
|
550
|
+
* object for a richtext field, a scalar/array/object otherwise), or
|
|
551
|
+
* `undefined` when the field is absent. The quill-free read: reads need no
|
|
552
|
+
* schema, so they live on `Document`, not the typed writer. For the markdown
|
|
553
|
+
* projection of a richtext value use [`getMarkdown`](Self::get_markdown).
|
|
554
|
+
*/
|
|
555
|
+
get(name: string): any;
|
|
556
|
+
/**
|
|
557
|
+
* The markdown projection of a main-card field (`name` given) or the main
|
|
558
|
+
* body (`name` omitted) — the on-demand, lossy export (corpus-only marks do
|
|
559
|
+
* not survive markdown), returning `""` for an absent field. Re-coins,
|
|
560
|
+
* lazily and by name, the projection the eager `fieldMarkdown` /
|
|
561
|
+
* `bodyMarkdown` getters dropped in #925; call it only when markdown is what
|
|
562
|
+
* you need out.
|
|
563
|
+
*/
|
|
564
|
+
getMarkdown(name?: string): string;
|
|
293
565
|
/**
|
|
294
566
|
* Insert a card at `index` (must be in `0..=cards.length`). Accepts a
|
|
295
|
-
* `
|
|
567
|
+
* `CardInput` (see [`pushCard`](Self::push_card)).
|
|
568
|
+
*/
|
|
569
|
+
insertCard(index: number, card: CardInput): void;
|
|
570
|
+
/**
|
|
571
|
+
* **Install** a richtext value at `addr` — **value semantics**, corpus only.
|
|
572
|
+
* Stores exactly `rt` (a canonical `RichText` corpus object); the identity
|
|
573
|
+
* anchors of any previous value are gone. An absent `addr.field` targets the
|
|
574
|
+
* body, an absent `addr.card` the main card. For "here's new markdown," use
|
|
575
|
+
* [`revise`](Document::revise); the cold-import path is spelled at the call
|
|
576
|
+
* site as `install(addr, importMarkdown(md))`, so anchor loss is visible in
|
|
577
|
+
* source.
|
|
578
|
+
*
|
|
579
|
+
* Throws on an out-of-range card, a malformed field name, or an `rt` that is
|
|
580
|
+
* not a canonical corpus object.
|
|
296
581
|
*/
|
|
297
|
-
|
|
582
|
+
install(addr: Addr, rt: RichText): void;
|
|
583
|
+
/**
|
|
584
|
+
* Replace this document's contents **in place** from a versioned storage
|
|
585
|
+
* DTO string — the mutating twin of the static
|
|
586
|
+
* [`fromJson`](Document::from_json) constructor. Parse-time `warnings` are
|
|
587
|
+
* cleared. Throws (leaving the document unchanged) on an invalid DTO.
|
|
588
|
+
*
|
|
589
|
+
* The cross-WASM-memory `Document` bridge: mutate a document on a
|
|
590
|
+
* backend-memory clone, then write the mutated state back into the caller's
|
|
591
|
+
* canonical document with this — the one way to update a live handle across
|
|
592
|
+
* the linear-memory seam without the caller re-binding its variable.
|
|
593
|
+
*/
|
|
594
|
+
loadJson(json: string): void;
|
|
298
595
|
/**
|
|
299
596
|
* Build a fresh `Card` from a kind and a flat field map — the ergonomic
|
|
300
597
|
* constructor for `pushCard` / `insertCard`. `fields` is an optional
|
|
@@ -308,12 +605,22 @@ export class Document {
|
|
|
308
605
|
*/
|
|
309
606
|
moveCard(from: number, to: number): void;
|
|
310
607
|
/**
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
*
|
|
314
|
-
*
|
|
608
|
+
* `new Document(quillRef)` — a blank document: a main card carrying only
|
|
609
|
+
* `$quill`, an empty body, and no composable cards. The programmatic
|
|
610
|
+
* blank canvas: absent fields resolve at render time (`default`, else
|
|
611
|
+
* type-empty zero), so nothing the caller did not set reaches the
|
|
612
|
+
* output. For an example-filled starter use `Quill.seedDocument()`.
|
|
613
|
+
* Throws on an invalid quill reference. Mirrors Python `Document(quill_ref)`.
|
|
614
|
+
*/
|
|
615
|
+
constructor(quill_ref: string);
|
|
616
|
+
/**
|
|
617
|
+
* Append a card to the end of the card list. Accepts a `CardInput` — a card
|
|
618
|
+
* read back (`cards` / `removeCard` / `quill.seedCard`), a
|
|
619
|
+
* [`makeCard`](Document::make_card) result, or a bare `{ kind, body }`
|
|
620
|
+
* (every returned `Card` is a valid `CardInput`). Throws if `card.kind` is
|
|
621
|
+
* not a valid kind name.
|
|
315
622
|
*/
|
|
316
|
-
pushCard(card:
|
|
623
|
+
pushCard(card: CardInput): void;
|
|
317
624
|
/**
|
|
318
625
|
* The canonical `$quill` reference grammar as author-facing text. Core is
|
|
319
626
|
* the single source of truth: drive schema `describe` and validation
|
|
@@ -365,7 +672,25 @@ export class Document {
|
|
|
365
672
|
* kinds survive.
|
|
366
673
|
*/
|
|
367
674
|
removeSeedNamespace(card_kind: string): any;
|
|
675
|
+
/**
|
|
676
|
+
* **Deprecated** — alias for `revise({}, markdown)`, kept one release cycle.
|
|
677
|
+
* Revise the main card's body from a markdown string (edit semantics: a
|
|
678
|
+
* `diff_import` that rebases surviving anchors). Discards the text delta;
|
|
679
|
+
* call [`revise`](Document::revise) to receive it.
|
|
680
|
+
*/
|
|
368
681
|
replaceBody(body: string): void;
|
|
682
|
+
/**
|
|
683
|
+
* **Revise** the richtext value at `addr` from a markdown string — **edit
|
|
684
|
+
* semantics**, the default write path, returning the text [`Delta`]. Imports
|
|
685
|
+
* the markdown, diffs it against the current value, rebases surviving
|
|
686
|
+
* identity anchors, and returns the change an editor bridge maps its own
|
|
687
|
+
* positions through (`mapPos`). An absent `addr.field` targets the body, an
|
|
688
|
+
* absent `addr.card` the main card; an absent field cold-imports from empty.
|
|
689
|
+
*
|
|
690
|
+
* Throws on an out-of-range card, a malformed field name, a present
|
|
691
|
+
* non-corpus field value, or an over-nested markdown input.
|
|
692
|
+
*/
|
|
693
|
+
revise(addr: Addr, markdown: string): Delta;
|
|
369
694
|
/**
|
|
370
695
|
* Read the `schema` version tag from a raw storage DTO string without a
|
|
371
696
|
* full parse, or `undefined`. Returns unknown future versions as-is —
|
|
@@ -385,6 +710,19 @@ export class Document {
|
|
|
385
710
|
* Throws if out of range or `value` cannot be serialized.
|
|
386
711
|
*/
|
|
387
712
|
setCardExtNamespace(index: number, namespace: string, value: any): void;
|
|
713
|
+
/**
|
|
714
|
+
* Set a field on the card at `index` — the card-indexed twin of
|
|
715
|
+
* [`setField`](Document::set_field). Stores the value opaquely.
|
|
716
|
+
* Throws if `index` is out of range, `name` is reserved or invalid.
|
|
717
|
+
*/
|
|
718
|
+
setCardField(index: number, name: string, value: any): void;
|
|
719
|
+
/**
|
|
720
|
+
* Batched twin of [`setCardField`](Document::set_card_field): set
|
|
721
|
+
* several fields on the card at `index` atomically. Same all-or-nothing,
|
|
722
|
+
* one-diagnostic-per-field contract as [`setFields`](Document::set_fields).
|
|
723
|
+
* Throws if `index` is out of range.
|
|
724
|
+
*/
|
|
725
|
+
setCardFields(index: number, fields: Record<string, unknown>): void;
|
|
388
726
|
/**
|
|
389
727
|
* Replace the kind of the card at `index`. Payload and body are untouched;
|
|
390
728
|
* schema-aware migration is the caller's responsibility.
|
|
@@ -411,6 +749,15 @@ export class Document {
|
|
|
411
749
|
* Throws if `name` does not match `[A-Za-z_][A-Za-z0-9_]*`.
|
|
412
750
|
*/
|
|
413
751
|
setField(name: string, value: any): void;
|
|
752
|
+
/**
|
|
753
|
+
* Set several main-card payload fields atomically from a plain object,
|
|
754
|
+
* clearing any `!must_fill` marker on each key. Nothing is applied on
|
|
755
|
+
* error; the thrown error's `diagnostics` array carries one entry per
|
|
756
|
+
* offending field (`path` = field name), so externally-sourced names
|
|
757
|
+
* (database columns, form keys) surface every violation in one pass.
|
|
758
|
+
* Mirrors Python `set_fields`.
|
|
759
|
+
*/
|
|
760
|
+
setFields(fields: Record<string, unknown>): void;
|
|
414
761
|
/**
|
|
415
762
|
* Update a payload field on the main card and mark it as `!must_fill`.
|
|
416
763
|
* Throws on invalid name (see [`setField`](Document::set_field)).
|
|
@@ -451,15 +798,6 @@ export class Document {
|
|
|
451
798
|
* genuinely malformed markdown.
|
|
452
799
|
*/
|
|
453
800
|
static tryFromJson(json: string): Document | undefined;
|
|
454
|
-
/**
|
|
455
|
-
* Replace the body of the card at `index`. Throws if out of range.
|
|
456
|
-
*/
|
|
457
|
-
updateCardBody(index: number, body: string): void;
|
|
458
|
-
/**
|
|
459
|
-
* Update a field on the card at `index`.
|
|
460
|
-
* Throws if `index` is out of range, `name` is reserved or invalid.
|
|
461
|
-
*/
|
|
462
|
-
updateCardField(index: number, name: string, value: any): void;
|
|
463
801
|
/**
|
|
464
802
|
* Number of composable cards (excludes the main card). O(1).
|
|
465
803
|
*/
|
|
@@ -474,6 +812,129 @@ export class Document {
|
|
|
474
812
|
readonly warnings: Diagnostic[];
|
|
475
813
|
}
|
|
476
814
|
|
|
815
|
+
/**
|
|
816
|
+
* Live render session: reads (`render`, `paint`, `pageSize`, `regions`,
|
|
817
|
+
* `fieldAt`, `positionAt`, `locate`) serve the current compile. `apply(doc)`
|
|
818
|
+
* recompiles a whole document in place, transactionally (on throw every read
|
|
819
|
+
* keeps serving the last-good compile). Geometry reads reflect the current
|
|
820
|
+
* compile; anchoring a caret across edits is the editor's job — re-read
|
|
821
|
+
* geometry after each committed `apply`.
|
|
822
|
+
*
|
|
823
|
+
* **Empty documents.** A zero-page document yields a valid session
|
|
824
|
+
* (`pageCount === 0`); `paint(ctx, 0)` or `pageSize(0)` throws with
|
|
825
|
+
* `"page index 0 out of range (pageCount=0)"`. Branch on `pageCount === 0`
|
|
826
|
+
* rather than catching the error.
|
|
827
|
+
*/
|
|
828
|
+
export class LiveSession {
|
|
829
|
+
private constructor();
|
|
830
|
+
free(): void;
|
|
831
|
+
[Symbol.dispose](): void;
|
|
832
|
+
/**
|
|
833
|
+
* Recompile the session against `doc` — the edit verb of a live preview.
|
|
834
|
+
* The document is compiled through the same schema pipeline as `open`
|
|
835
|
+
* (same quill), then applied transactionally: on throw every read
|
|
836
|
+
* (`render`, `paint`, `pageSize`, `regions`, `fieldAt`) keeps serving the last-good
|
|
837
|
+
* compile, and the session recovers on the next successful `apply`. On
|
|
838
|
+
* success reads serve the new compile; repaint `dirtyPages ∩ visible`.
|
|
839
|
+
*/
|
|
840
|
+
apply(doc: Document): ChangeSet;
|
|
841
|
+
/**
|
|
842
|
+
* The schema field whose content is under a point on `page` — the
|
|
843
|
+
* forward (click → field) direction: hit-test a click against the
|
|
844
|
+
* compiled document and get back the field address to focus in the
|
|
845
|
+
* editor, or `undefined` off any field's ink. `x`/`y` are PDF points
|
|
846
|
+
* with a **bottom-left** origin, the same space as `FieldRegion.rect` —
|
|
847
|
+
* from a canvas click, invert the overlay transform documented on
|
|
848
|
+
* `FieldRegion`: `x = clickPx.x / renderScale`,
|
|
849
|
+
* `y = pageHeightPt - clickPx.y / renderScale`. Unlike `regions()`,
|
|
850
|
+
* *every* placement answers, not just the first.
|
|
851
|
+
*/
|
|
852
|
+
fieldAt(page: number, x: number, y: number): string | undefined;
|
|
853
|
+
/**
|
|
854
|
+
* The whole-field highlight boxes for `field` — one union rect per page,
|
|
855
|
+
* over the field's `span`-bearing content segments. The convenience that
|
|
856
|
+
* owns the union `regions()` leaves derived: it keeps `regions()` the
|
|
857
|
+
* low-level disjoint truth (#829) and folds the span-filter + per-page
|
|
858
|
+
* union here, so a "highlight the focused field" consumer stops
|
|
859
|
+
* reimplementing it. **Content only** — a field placed solely as a scalar
|
|
860
|
+
* reference or a bound widget carries no `span` and returns `[]`; its box
|
|
861
|
+
* is a single `regions()` rect. Reflects the current compile, like
|
|
862
|
+
* `regions()`.
|
|
863
|
+
*/
|
|
864
|
+
fieldBoxes(field: string): FieldRegion[];
|
|
865
|
+
/**
|
|
866
|
+
* A corpus position → **caret rect** — the reverse of `positionAt`: given
|
|
867
|
+
* a field and a USV offset into its `RichText`, return the box (in the
|
|
868
|
+
* same bottom-left PDF-point space as `FieldRegion.rect`) to draw a caret
|
|
869
|
+
* at, its `span` collapsed to `[pos, pos]`; `undefined` when the field
|
|
870
|
+
* places no tracked content or the offset maps to no drawn glyph.
|
|
871
|
+
*/
|
|
872
|
+
locate(field: string, pos: number): FieldRegion | undefined;
|
|
873
|
+
/**
|
|
874
|
+
* Page dimensions in points (1 pt = 1/72 inch).
|
|
875
|
+
* Throws if the backend has no canvas painter or `page` is out of range.
|
|
876
|
+
*/
|
|
877
|
+
pageSize(page: number): PageSize;
|
|
878
|
+
/**
|
|
879
|
+
* Paint `page` into a `CanvasRenderingContext2D` or
|
|
880
|
+
* `OffscreenCanvasRenderingContext2D`. The painter owns
|
|
881
|
+
* `canvas.width`/`height` (no `clearRect` needed); consumers own
|
|
882
|
+
* `canvas.style.*`. If `layoutScale * densityScale` exceeds 16384 px
|
|
883
|
+
* per side, `densityScale` is clamped — `PaintResult.clamped` reports it and
|
|
884
|
+
* `PaintResult.effectiveDensityScale` carries the density actually applied.
|
|
885
|
+
*
|
|
886
|
+
* `put_image_data` writes the whole backing store, bypassing the 2D
|
|
887
|
+
* context's transform, `globalAlpha`, and clip: the painter owns the entire
|
|
888
|
+
* canvas, so each visible page needs its own `` — you cannot composite
|
|
889
|
+
* two pages, a sub-rect, or a context transform through this call.
|
|
890
|
+
*
|
|
891
|
+
* Throws if the backend has no canvas painter, `page` is out of range,
|
|
892
|
+
* `ctx` is the wrong type, or either scale is non-finite or `<= 0`.
|
|
893
|
+
*/
|
|
894
|
+
paint(ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, page: number, opts: PaintOptions | undefined): PaintResult;
|
|
895
|
+
/**
|
|
896
|
+
* A point → **corpus position** — the fine-grained click direction:
|
|
897
|
+
* hit-test a point and get back the field *and* a USV offset into its
|
|
898
|
+
* `RichText` (for placing a caret or mapping a selection into the content
|
|
899
|
+
* model), or `undefined` off all content ink. `x`/`y` are PDF points,
|
|
900
|
+
* bottom-left origin — the same space as `fieldAt`. The offset is
|
|
901
|
+
* cluster-exact and degrades to the containing segment's start on
|
|
902
|
+
* origin-less ink (list markers, a code fence's interior). See
|
|
903
|
+
* `CorpusHit`.
|
|
904
|
+
*/
|
|
905
|
+
positionAt(page: number, x: number, y: number): CorpusHit | undefined;
|
|
906
|
+
/**
|
|
907
|
+
* Schema-field geometry for this compiled session — each content field's
|
|
908
|
+
* **first placement** (one region per page it touches) plus widget and
|
|
909
|
+
* scalar-reference-site regions, keyed on the quill schema field path; a
|
|
910
|
+
* field may still appear more than once (group by `field`, see
|
|
911
|
+
* `FieldRegion`). A session-level query: no render, no byte artifact. An
|
|
912
|
+
* interactive preview reads it to scroll to / highlight the focused
|
|
913
|
+
* field over a `paint`-ed canvas; the click direction is `fieldAt`.
|
|
914
|
+
* Empty for backends that place no schema fields.
|
|
915
|
+
*/
|
|
916
|
+
regions(): FieldRegion[];
|
|
917
|
+
render(opts?: RenderOptions | null): RenderResult;
|
|
918
|
+
/**
|
|
919
|
+
* The backend that produced this session (e.g. `"typst"`).
|
|
920
|
+
*/
|
|
921
|
+
readonly backendId: string;
|
|
922
|
+
readonly pageCount: number;
|
|
923
|
+
/**
|
|
924
|
+
* `true` iff `paint` and `pageSize` will succeed for this session. Derived
|
|
925
|
+
* from the session's canvas seam, so it reflects exactly what `paint` will
|
|
926
|
+
* do — no separately captured flag.
|
|
927
|
+
*/
|
|
928
|
+
readonly supportsCanvas: boolean;
|
|
929
|
+
/**
|
|
930
|
+
* Non-fatal diagnostics of the session's **current compile** (e.g. Typst
|
|
931
|
+
* font fallback) — set at open and refreshed by each committed `apply`;
|
|
932
|
+
* a failed apply keeps the last-good compile's warnings. Also appended
|
|
933
|
+
* to `RenderResult.warnings` on each `render()` call.
|
|
934
|
+
*/
|
|
935
|
+
readonly warnings: Diagnostic[];
|
|
936
|
+
}
|
|
937
|
+
|
|
477
938
|
export class Quill {
|
|
478
939
|
private constructor();
|
|
479
940
|
free(): void;
|
|
@@ -536,10 +997,10 @@ export class Quill {
|
|
|
536
997
|
*
|
|
537
998
|
* Forwards the canonical `validation::*` diagnostics — same `code`,
|
|
538
999
|
* `path`, and `hint` the engine emits — including the non-fatal
|
|
539
|
-
* `validation::
|
|
540
|
-
* Field values, defaults, and order are not part of this
|
|
541
|
-
* them from the `Document` payload and `Quill.schema`
|
|
542
|
-
*
|
|
1000
|
+
* `validation::must_fill` warning for each `!must_fill` marker left in
|
|
1001
|
+
* the document. Field values, defaults, and order are not part of this
|
|
1002
|
+
* surface: read them from the `Document` payload and `Quill.schema`
|
|
1003
|
+
* (schema key order is display order).
|
|
543
1004
|
*/
|
|
544
1005
|
validate(doc: Document): Diagnostic[];
|
|
545
1006
|
/**
|
|
@@ -558,9 +1019,10 @@ export class Quill {
|
|
|
558
1019
|
readonly metadata: QuillMetadata;
|
|
559
1020
|
/**
|
|
560
1021
|
* Document schema for the quill: the user-fillable fields plus their
|
|
561
|
-
* `ui` hints (group /
|
|
562
|
-
* surface — drives form editors and LLM/MCP consumers
|
|
563
|
-
* `
|
|
1022
|
+
* `ui` hints (title / group / compact / multiline). The single
|
|
1023
|
+
* field-metadata surface — drives form editors and LLM/MCP consumers
|
|
1024
|
+
* alike. Key order in `fields`/`properties` is declaration order — the
|
|
1025
|
+
* ordering contract. Returns the `QuillSchema` shape.
|
|
564
1026
|
*/
|
|
565
1027
|
readonly schema: QuillSchema;
|
|
566
1028
|
}
|
|
@@ -574,76 +1036,64 @@ export class Quillmark {
|
|
|
574
1036
|
[Symbol.dispose](): void;
|
|
575
1037
|
constructor();
|
|
576
1038
|
/**
|
|
577
|
-
* Open
|
|
1039
|
+
* Open a live render session for `doc` against `quill`'s backend.
|
|
578
1040
|
*/
|
|
579
|
-
open(quill: Quill, doc: Document):
|
|
1041
|
+
open(quill: Quill, doc: Document): LiveSession;
|
|
580
1042
|
/**
|
|
581
1043
|
* Render `doc` against `quill` in one shot. Convenience over `open` +
|
|
582
|
-
* `
|
|
1044
|
+
* `LiveSession.render`: an unset `output_format` falls back to the
|
|
583
1045
|
* backend's first supported format.
|
|
584
1046
|
*/
|
|
585
1047
|
render(quill: Quill, doc: Document, opts?: RenderOptions | null): RenderResult;
|
|
586
1048
|
/**
|
|
587
1049
|
* The output formats `quill`'s backend can emit. Static capability —
|
|
588
|
-
* resolves the backend but compiles nothing. Throws `
|
|
1050
|
+
* resolves the backend but compiles nothing. Throws `engine::backend_not_found`
|
|
589
1051
|
* if no registered backend matches the quill's declared backend.
|
|
590
1052
|
*/
|
|
591
1053
|
supportedFormats(quill: Quill): OutputFormat[];
|
|
592
1054
|
/**
|
|
593
|
-
* `true` iff `quill`'s backend can paint sessions to a
|
|
594
|
-
* the
|
|
595
|
-
* Use as a precondition probe before mounting
|
|
1055
|
+
* Pre-session hint: `true` iff `quill`'s backend can paint sessions to a
|
|
1056
|
+
* canvas, derived from the backend's output formats; `false` when the
|
|
1057
|
+
* backend is unsupported. Use as a cheap precondition probe before mounting
|
|
1058
|
+
* a canvas-based preview UI; the authoritative answer is the session's
|
|
1059
|
+
* `supportsCanvas` getter once `open()` has been called.
|
|
596
1060
|
*/
|
|
597
1061
|
supportsCanvas(quill: Quill): boolean;
|
|
598
1062
|
}
|
|
599
1063
|
|
|
600
1064
|
/**
|
|
601
|
-
*
|
|
602
|
-
*
|
|
603
|
-
*
|
|
604
|
-
* (`pageCount === 0`); `paint(ctx, 0)` or `pageSize(0)` throws with
|
|
605
|
-
* `"page index 0 out of range (pageCount=0)"`. Branch on `pageCount === 0`
|
|
606
|
-
* rather than catching the error.
|
|
1065
|
+
* Export a canonical `RichText` corpus to its markdown projection — the pure
|
|
1066
|
+
* codec that replaces the eager `bodyMarkdown` / `fieldMarkdown` precomputes
|
|
1067
|
+
* (`exportMarkdown(card.body)`). Throws if `rt` is not a canonical corpus.
|
|
607
1068
|
*/
|
|
608
|
-
export
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
/**
|
|
618
|
-
* Paint `page` into a `CanvasRenderingContext2D` or
|
|
619
|
-
* `OffscreenCanvasRenderingContext2D`. The painter owns
|
|
620
|
-
* `canvas.width`/`height` (no `clearRect` needed); consumers own
|
|
621
|
-
* `canvas.style.*`. If `layoutScale * densityScale` exceeds 16384 px
|
|
622
|
-
* per side, `densityScale` is clamped — detect via `PaintResult.pixelWidth`.
|
|
623
|
-
*
|
|
624
|
-
* Throws if the backend has no canvas painter, `page` is out of range,
|
|
625
|
-
* `ctx` is the wrong type, or either scale is non-finite or `<= 0`.
|
|
626
|
-
*/
|
|
627
|
-
paint(ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, page: number, opts: PaintOptions | undefined): PaintResult;
|
|
628
|
-
render(opts?: RenderOptions | null): RenderResult;
|
|
629
|
-
/**
|
|
630
|
-
* The backend that produced this session (e.g. `"typst"`).
|
|
631
|
-
*/
|
|
632
|
-
readonly backendId: string;
|
|
633
|
-
readonly pageCount: number;
|
|
634
|
-
/**
|
|
635
|
-
* `true` iff `paint` and `pageSize` will succeed for this session. The
|
|
636
|
-
* backend's canvas capability, captured at open time.
|
|
637
|
-
*/
|
|
638
|
-
readonly supportsCanvas: boolean;
|
|
639
|
-
/**
|
|
640
|
-
* Non-fatal diagnostics emitted when opening the session. Also appended
|
|
641
|
-
* to `RenderResult.warnings` on each `render()` call.
|
|
642
|
-
*/
|
|
643
|
-
readonly warnings: Diagnostic[];
|
|
644
|
-
}
|
|
1069
|
+
export function exportMarkdown(rt: RichText): string;
|
|
1070
|
+
|
|
1071
|
+
/**
|
|
1072
|
+
* Import a markdown string to a canonical `RichText` corpus — the pure,
|
|
1073
|
+
* document-free codec. Pair with `install(addr, importMarkdown(md))` to spell
|
|
1074
|
+
* the cold (anchor-losing) write at the call site; prefer `revise` for edit
|
|
1075
|
+
* semantics. Throws on an over-nested input.
|
|
1076
|
+
*/
|
|
1077
|
+
export function importMarkdown(markdown: string): RichText;
|
|
645
1078
|
|
|
646
1079
|
/**
|
|
647
1080
|
* Initialize the WASM module with panic hooks for better error messages
|
|
648
1081
|
*/
|
|
649
1082
|
export function init(): void;
|
|
1083
|
+
|
|
1084
|
+
/**
|
|
1085
|
+
* Map a base corpus position through a `delta` to its new position — the pure
|
|
1086
|
+
* position-mapping codec an editor bridge composes to hold a caret stable
|
|
1087
|
+
* across a `revise`. `assoc` decides the side of a same-position insertion
|
|
1088
|
+
* (`"after"` moves past it). Throws on a malformed `delta`.
|
|
1089
|
+
*/
|
|
1090
|
+
export function mapPos(delta: Delta, pos: number, assoc: Assoc): number;
|
|
1091
|
+
|
|
1092
|
+
/**
|
|
1093
|
+
* Rebase `markdown` onto a `base` corpus — the pure, document-free twin of
|
|
1094
|
+
* `revise`: cold-import + `diff_import`, returning the new `corpus` and the
|
|
1095
|
+
* text `delta` (surviving anchors rebased). Use it to compute a revise without
|
|
1096
|
+
* a document in hand; `revise(addr, md)` fuses this with the store for
|
|
1097
|
+
* atomicity. Throws on an over-nested markdown input or a non-corpus `base`.
|
|
1098
|
+
*/
|
|
1099
|
+
export function rebase(base: RichText, markdown: string): { corpus: RichText; delta: Delta };
|