@quillmark/wasm 0.92.1 → 0.95.1
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 +301 -4
- package/README.md +167 -66
- package/backends/pdfform/wasm.d.ts +1066 -0
- package/backends/pdfform/wasm.js +9 -0
- package/backends/pdfform/wasm_bg.js +2654 -0
- package/backends/pdfform/wasm_bg.wasm +0 -0
- package/backends/pdfform/wasm_bg.wasm.d.ts +98 -0
- package/backends/typst/wasm.d.ts +584 -167
- package/backends/typst/wasm.js +1 -1
- package/backends/typst/wasm_bg.js +1047 -397
- package/backends/typst/wasm_bg.wasm +0 -0
- package/backends/typst/wasm_bg.wasm.d.ts +45 -25
- package/core/wasm.d.ts +412 -110
- package/core/wasm.js +1 -1
- package/core/wasm_bg.js +713 -226
- package/core/wasm_bg.wasm +0 -0
- package/core/wasm_bg.wasm.d.ts +31 -17
- package/package.json +4 -3
- package/runtime/runtime.d.ts +459 -21
- package/runtime/runtime.js +536 -30
|
@@ -0,0 +1,1066 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A path to a value nested inside a field `value`: `string` keys and
|
|
6
|
+
* `number` array indices, e.g. `["addr", "street"]` or `["recipients", 0, "name"]`.
|
|
7
|
+
*/
|
|
8
|
+
export type PathStep = string | number;
|
|
9
|
+
|
|
10
|
+
/** A field or comment entry in a `Card.payloadItems` list. */
|
|
11
|
+
export type PayloadItem =
|
|
12
|
+
| {
|
|
13
|
+
type: "field";
|
|
14
|
+
key: string;
|
|
15
|
+
value: unknown;
|
|
16
|
+
fill?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Paths to `!must_fill` markers nested *inside* `value` (the `value`
|
|
19
|
+
* projection itself is fill-free). Absent when the field has no nested
|
|
20
|
+
* placeholders. Preserved across `insertCard` / `makeCard`.
|
|
21
|
+
*/
|
|
22
|
+
nestedFills?: PathStep[][];
|
|
23
|
+
}
|
|
24
|
+
| { type: "comment"; text: string; inline?: boolean };
|
|
25
|
+
|
|
26
|
+
/**
|
|
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 `insertCard` accepts); every `Card` is a valid `CardInput`,
|
|
31
|
+
* so a card read from one document pushes straight into another.
|
|
32
|
+
*
|
|
33
|
+
* `$` system entries are hoisted to named fields: `kind` (the `$kind`, empty
|
|
34
|
+
* string when none), optional `quill` (the `$quill` `name@version`, main card
|
|
35
|
+
* only), optional `id` (`$id`), optional `ext` (`$ext`), and optional `seed`
|
|
36
|
+
* (the `$seed` per-kind overlay map, main card only). `payloadItems` carries
|
|
37
|
+
* user fields and comments in order.
|
|
38
|
+
*/
|
|
39
|
+
export interface Card {
|
|
40
|
+
kind: string;
|
|
41
|
+
quill?: string;
|
|
42
|
+
id?: string;
|
|
43
|
+
ext?: Record<string, unknown>;
|
|
44
|
+
seed?: Record<string, unknown>;
|
|
45
|
+
payloadItems: PayloadItem[];
|
|
46
|
+
/**
|
|
47
|
+
* The card body as canonical `Content` — the source-of-truth content model.
|
|
48
|
+
* Always this content 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: Content;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* A card written *into* a document — the input twin of `Card`, accepted by
|
|
57
|
+
* `Document.insertCard`. Like `Card` but `body` also
|
|
58
|
+
* takes a markdown `string` (imported to the content, so a markdown / LLM writer
|
|
59
|
+
* needn't build the `Content` 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?: Content | string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Canonical richtext content — 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_content::serial`'s canonical JSON encoding.
|
|
79
|
+
*/
|
|
80
|
+
export interface Content {
|
|
81
|
+
text: string;
|
|
82
|
+
lines: ContentLine[];
|
|
83
|
+
marks: ContentMark[];
|
|
84
|
+
islands: ContentIsland[];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** One `\n`-separated segment of `Content.text`, in order. */
|
|
88
|
+
export type ContentLine = {
|
|
89
|
+
containers: ContentContainer[];
|
|
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 ContentContainer =
|
|
102
|
+
| { container: "list_item"; ordered: boolean; start: number; ordinal: number }
|
|
103
|
+
| { container: "quote" };
|
|
104
|
+
|
|
105
|
+
/** A mark over char range `[start, end)` into `Content.text`. */
|
|
106
|
+
export type ContentMark = { 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 `Content.text`. */
|
|
114
|
+
export interface ContentIsland {
|
|
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
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* A write address — one navigation concept for the whole `Document` surface. An
|
|
124
|
+
* absent `field` targets the card body; an absent `card` targets the main card.
|
|
125
|
+
* `{}` is the main-card body; `{ card: 2 }` the body of the composable card at
|
|
126
|
+
* index 2; `{ field: "intro" }` the main card's `intro` field; `{ card: 2,
|
|
127
|
+
* field: "intro" }` a card field.
|
|
128
|
+
*
|
|
129
|
+
* On the `Addr`-taking verbs a **bare string** is shorthand for `{ field: name }`
|
|
130
|
+
* — `doc.storeField("qty", 3)`, `doc.revise("intro", md)` — the one coercion
|
|
131
|
+
* rule. A bare number is *not* an addr (`{ card: 2 }` is the self-documenting
|
|
132
|
+
* spelling), so no third navigation idiom re-fragments the surface.
|
|
133
|
+
*/
|
|
134
|
+
export interface Addr {
|
|
135
|
+
card?: number;
|
|
136
|
+
field?: string;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* A card-only address — the axis the card-scoped verbs (`storeFields`,
|
|
141
|
+
* `storeExt`, `getExt`, `commitFields`, …) take. An absent `card` targets the
|
|
142
|
+
* main card. A present `field` throws: a card address takes only `card`, and a
|
|
143
|
+
* would-be nested write is a bug the error names rather than silently ignores.
|
|
144
|
+
*/
|
|
145
|
+
export interface CardAddr {
|
|
146
|
+
card?: number;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* A text-splice change set over the USV content (CodeMirror `ChangeSet`
|
|
151
|
+
* semantics) — plain, structured-clone-able data. Returned by `revise` and by
|
|
152
|
+
* the `rebase` codec; map a stored position through it with `mapPos`.
|
|
153
|
+
*/
|
|
154
|
+
export interface Delta {
|
|
155
|
+
ops: ({ retain: number } | { insert: string } | { delete: number })[];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Which side of a same-position insertion `mapPos` lands a point on. */
|
|
159
|
+
export type Assoc = "before" | "after";
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* A mark edit in final-text coordinates (post-delta, post-line-op). `add` /
|
|
163
|
+
* `remove` carry the `ContentMark` vocabulary (`{ type, … }`); `removeAnchor`
|
|
164
|
+
* drops one identity anchor by id.
|
|
165
|
+
*/
|
|
166
|
+
export type MarkOp =
|
|
167
|
+
| ({ op: "add" | "remove"; start: number; end: number } & (
|
|
168
|
+
| { type: "strong" | "emph" | "underline" | "strike" | "code" }
|
|
169
|
+
| { type: "link"; url: string }
|
|
170
|
+
| { type: "anchor"; id: string }
|
|
171
|
+
| { type: string; attrs: unknown }
|
|
172
|
+
))
|
|
173
|
+
| { op: "removeAnchor"; id: string };
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* A line/block edit. `split`/`join` splice `\n`; `setKind`/`setContainers`/
|
|
177
|
+
* `setContinues` touch metadata. `setContinues` sets/clears a line's within-block
|
|
178
|
+
* hard-break flag (`ContentLine.continues`) — the op-grained way to lower a
|
|
179
|
+
* Shift+Enter hard break or a new code-fence interior line; `continues: true` on
|
|
180
|
+
* line 0 is rejected (nothing precedes it to continue).
|
|
181
|
+
*/
|
|
182
|
+
export type LineOp =
|
|
183
|
+
| { op: "split"; at: number }
|
|
184
|
+
| { op: "join"; line: number }
|
|
185
|
+
| ({ op: "setKind"; line: number } & (
|
|
186
|
+
| { kind: "para" | "island" | "rule" }
|
|
187
|
+
| { kind: "heading"; level: number }
|
|
188
|
+
| { kind: "code"; lang?: string }
|
|
189
|
+
))
|
|
190
|
+
| { op: "setContainers"; line: number; containers: ContentContainer[] }
|
|
191
|
+
| { op: "setContinues"; line: number; continues: boolean };
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* A committed content edit bundle for `applyChange`: a text `delta` (default no
|
|
195
|
+
* text change), then `lineOps`, then `markOps` (mark ranges are in post-delta
|
|
196
|
+
* coordinates). Every field is optional.
|
|
197
|
+
*/
|
|
198
|
+
export interface ChangeBundle {
|
|
199
|
+
delta?: Delta;
|
|
200
|
+
lineOps?: LineOp[];
|
|
201
|
+
markOps?: MarkOp[];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Page dimensions in points (1 pt = 1/72 inch). Typst measures in Typst
|
|
208
|
+
* points; pdfform measures in PDF points — the same unit.
|
|
209
|
+
*
|
|
210
|
+
* Report-only: the painter sizes the canvas itself based on
|
|
211
|
+
* `PaintOptions`. `pageSize` is exposed for callers that need page
|
|
212
|
+
* geometry up-front (e.g. to lay out a scrollable list of canvases
|
|
213
|
+
* before any pixels are rendered).
|
|
214
|
+
*/
|
|
215
|
+
export interface PageSize {
|
|
216
|
+
widthPt: number;
|
|
217
|
+
heightPt: number;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Inputs to `LiveSession.paint`. Both fields are optional and default
|
|
222
|
+
* to `1`.
|
|
223
|
+
*
|
|
224
|
+
* - `layoutScale` — layout-space pixels per point (Typst point / PDF
|
|
225
|
+
* point — the same 1/72″ unit). For on-screen
|
|
226
|
+
* canvases this is CSS pixels per pt; the page's layout-pixel size is
|
|
227
|
+
* `widthPt * layoutScale × heightPt * layoutScale`. The painter
|
|
228
|
+
* surfaces these dimensions as `layoutWidth` / `layoutHeight` so
|
|
229
|
+
* consumers can drive `canvas.style.*` (or any layout system).
|
|
230
|
+
* - `densityScale` — backing-store density multiplier. Fold
|
|
231
|
+
* `window.devicePixelRatio`, in-app zoom, and `visualViewport.scale`
|
|
232
|
+
* (pinch-zoom) into a single value here. Defaults to `1`, which
|
|
233
|
+
* produces a non-retina backing store — pass `window.devicePixelRatio`
|
|
234
|
+
* for crisp output on high-DPI displays.
|
|
235
|
+
*
|
|
236
|
+
* The effective rasterization scale is `layoutScale * densityScale`.
|
|
237
|
+
* Both must be finite and `> 0`. For `OffscreenCanvasRenderingContext2D`
|
|
238
|
+
* the two collapse to a single scalar; folding everything into
|
|
239
|
+
* `densityScale` is the simplest convention.
|
|
240
|
+
*/
|
|
241
|
+
export interface PaintOptions {
|
|
242
|
+
layoutScale?: number;
|
|
243
|
+
densityScale?: number;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Returned by `LiveSession.paint`.
|
|
248
|
+
*
|
|
249
|
+
* - `layoutWidth` / `layoutHeight` — layout-pixel dimensions of the
|
|
250
|
+
* canvas's display box. For on-screen canvases this is CSS pixels:
|
|
251
|
+
* set `canvas.style.width = layoutWidth + "px"` and
|
|
252
|
+
* `canvas.style.height = layoutHeight + "px"` (or feed these into
|
|
253
|
+
* your layout system). Independent of `densityScale`.
|
|
254
|
+
* - `pixelWidth` / `pixelHeight` — integer backing-store pixel
|
|
255
|
+
* dimensions the painter wrote to `canvas.width` / `canvas.height`.
|
|
256
|
+
* Equal to `round(layoutWidth * densityScale)` ×
|
|
257
|
+
* `round(layoutHeight * densityScale)` *unless* the requested backing
|
|
258
|
+
* exceeded the painter's safe maximum (16384 px per side), in which
|
|
259
|
+
* case `densityScale` was clamped to fit.
|
|
260
|
+
* - `clamped` — `true` when that 16384-px clamp fired, so the page is
|
|
261
|
+
* painted at fewer device pixels than requested and renders soft at the
|
|
262
|
+
* same `canvas.style` size. Reads the clamp off the return value instead
|
|
263
|
+
* of the `pixelWidth < round(layoutWidth * densityScale)` derivation.
|
|
264
|
+
* - `effectiveDensityScale` — the `densityScale` actually applied: the
|
|
265
|
+
* requested value unless `clamped`, then reduced proportionally.
|
|
266
|
+
* `layoutScale * effectiveDensityScale` is the scale the backing store
|
|
267
|
+
* was rasterized at.
|
|
268
|
+
*
|
|
269
|
+
* The painter owns `canvas.width` / `canvas.height`; consumers must not
|
|
270
|
+
* write to them. The painter does **not** touch `canvas.style.*`;
|
|
271
|
+
* consumers own layout. The write is a whole-backing-store `putImageData`,
|
|
272
|
+
* which bypasses the 2D context transform, `globalAlpha`, and clip: give
|
|
273
|
+
* each visible page its own `` — you cannot composite two pages, a
|
|
274
|
+
* sub-rect, or a context transform through `paint`.
|
|
275
|
+
*
|
|
276
|
+
* For `OffscreenCanvasRenderingContext2D` (Worker rasterization, no
|
|
277
|
+
* DOM), `layoutWidth` / `layoutHeight` are informational — there's no
|
|
278
|
+
* CSS layout box to apply them to.
|
|
279
|
+
*/
|
|
280
|
+
export interface PaintResult {
|
|
281
|
+
layoutWidth: number;
|
|
282
|
+
layoutHeight: number;
|
|
283
|
+
pixelWidth: number;
|
|
284
|
+
pixelHeight: number;
|
|
285
|
+
clamped: boolean;
|
|
286
|
+
effectiveDensityScale: number;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
/** UI layout hints for a single field. Field display order is not a hint:
|
|
292
|
+
* key order in the schema's `fields`/`properties` objects is declaration
|
|
293
|
+
* order, the ordering contract. */
|
|
294
|
+
export interface QuillFieldUi {
|
|
295
|
+
title?: string;
|
|
296
|
+
group?: string;
|
|
297
|
+
compact?: boolean;
|
|
298
|
+
multiline?: boolean;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/** UI layout hints for a card (main or named card kind). */
|
|
302
|
+
export interface QuillCardUi {
|
|
303
|
+
title?: string;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/** Body namespace for a card (main or named card kind). */
|
|
307
|
+
export interface QuillCardBody {
|
|
308
|
+
/** When false, consumers must not accept or store body content for this card kind. Defaults to true. */
|
|
309
|
+
enabled?: boolean;
|
|
310
|
+
/** Example body content embedded verbatim in the blueprint body region. Fallback is "Write <card> body here." */
|
|
311
|
+
example?: string;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** Schema entry for a single field declared in a quill's `Quill.yaml`.
|
|
315
|
+
*
|
|
316
|
+
* A field's *cell* is determined by `default`: a field with a `default`
|
|
317
|
+
* is **Endorsed** (the rendered value is shippable as-is), while a field
|
|
318
|
+
* without a `default` is **Unendorsed** (the blueprint carries a
|
|
319
|
+
* `!must_fill` marker; a marker left in the document yields the non-fatal
|
|
320
|
+
* `validation::must_fill` warning from validate, and the render path
|
|
321
|
+
* zero-fills the field). There is no separate `required` axis.
|
|
322
|
+
*/
|
|
323
|
+
export interface QuillFieldSchema {
|
|
324
|
+
type: "string" | "number" | "integer" | "boolean" | "array" | "object" | "date" | "datetime" | "richtext" | "plaintext" | "enum";
|
|
325
|
+
description?: string;
|
|
326
|
+
default?: unknown;
|
|
327
|
+
example?: unknown;
|
|
328
|
+
/** Closed value domain. On `type: "enum"` declared as `values`; the
|
|
329
|
+
* deprecated `enum` modifier on `type: "string"` is accepted for one
|
|
330
|
+
* release. Both round-trip through this field. */
|
|
331
|
+
enum?: string[];
|
|
332
|
+
/** Required on `type: "enum"`: the closed set of allowed string values. */
|
|
333
|
+
values?: string[];
|
|
334
|
+
ui?: QuillFieldUi;
|
|
335
|
+
properties?: Record<string, QuillFieldSchema>;
|
|
336
|
+
items?: QuillFieldSchema;
|
|
337
|
+
/** Present (and `true`) on a `richtext` or `plaintext` field declared
|
|
338
|
+
* `inline` — the single-paragraph, container-free, island-free constraint.
|
|
339
|
+
* Core serializes `inline: true` into the schema JSON; absent otherwise. */
|
|
340
|
+
inline?: boolean;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/** Schema entry for the main card or a named card kind. */
|
|
344
|
+
export interface QuillCardSchema {
|
|
345
|
+
description?: string;
|
|
346
|
+
fields: Record<string, QuillFieldSchema>;
|
|
347
|
+
ui?: QuillCardUi;
|
|
348
|
+
body?: QuillCardBody;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Document schema returned by `Quill.schema`. Includes optional `ui` keys.
|
|
353
|
+
*
|
|
354
|
+
* Describes only the user-fillable fields. The quill reference
|
|
355
|
+
* (constructed as `${metadata.name}@${metadata.version}`) and card-kind
|
|
356
|
+
* discriminators are document-level metadata, not schema fields.
|
|
357
|
+
*/
|
|
358
|
+
export interface QuillSchema {
|
|
359
|
+
main: QuillCardSchema;
|
|
360
|
+
/** Present only when the quill declares at least one named card kind. */
|
|
361
|
+
card_kinds?: Record<string, QuillCardSchema>;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Identity snapshot mirroring the `quill:` section of `Quill.yaml`.
|
|
366
|
+
* The schema lives on `Quill.schema`; the backend's output formats are a
|
|
367
|
+
* resolved-backend capability read from the engine (`Quillmark.supportedFormats`),
|
|
368
|
+
* not part of this pure-config snapshot.
|
|
369
|
+
*/
|
|
370
|
+
export interface QuillMetadata {
|
|
371
|
+
name: string;
|
|
372
|
+
version: string;
|
|
373
|
+
backend: string;
|
|
374
|
+
author: string;
|
|
375
|
+
description: string;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
export interface Artifact {
|
|
380
|
+
format: OutputFormat;
|
|
381
|
+
bytes: Uint8Array;
|
|
382
|
+
mimeType: string;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
export interface ChangeSet {
|
|
386
|
+
pageCount: number;
|
|
387
|
+
dirtyPages: number[];
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
export interface ContentHit {
|
|
391
|
+
field: string;
|
|
392
|
+
pos: number;
|
|
393
|
+
granularity?: HitGranularity;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
export interface Diagnostic {
|
|
397
|
+
severity: Severity;
|
|
398
|
+
code?: string;
|
|
399
|
+
message: string;
|
|
400
|
+
location?: Location;
|
|
401
|
+
path?: string;
|
|
402
|
+
hint?: string;
|
|
403
|
+
sourceChain?: string[];
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
export interface FieldRegion {
|
|
407
|
+
field: string;
|
|
408
|
+
page: number;
|
|
409
|
+
rect: [number, number, number, number];
|
|
410
|
+
span?: [number, number];
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
export interface Location {
|
|
414
|
+
file: string;
|
|
415
|
+
line: number;
|
|
416
|
+
column: number;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
export interface RenderOptions {
|
|
420
|
+
format?: OutputFormat;
|
|
421
|
+
ppi?: number;
|
|
422
|
+
pages?: number[];
|
|
423
|
+
producer?: string;
|
|
424
|
+
regions?: boolean;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
export interface RenderResult {
|
|
428
|
+
artifacts: Artifact[];
|
|
429
|
+
warnings: Diagnostic[];
|
|
430
|
+
outputFormat: OutputFormat;
|
|
431
|
+
renderTimeMs: number;
|
|
432
|
+
regions: FieldRegion[];
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export type HitGranularity = "cluster" | "segment";
|
|
436
|
+
|
|
437
|
+
export type OutputFormat = "pdf" | "svg" | "txt" | "png";
|
|
438
|
+
|
|
439
|
+
export type Severity = "error" | "warning";
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Typed in-memory Quillmark document.
|
|
444
|
+
*/
|
|
445
|
+
export class Document {
|
|
446
|
+
free(): void;
|
|
447
|
+
[Symbol.dispose](): void;
|
|
448
|
+
/**
|
|
449
|
+
* **Apply** a committed content edit `bundle` (`{ delta?, lineOps?, markOps? }`)
|
|
450
|
+
* at `addr` — the editor splice: text delta first, then line ops, then mark
|
|
451
|
+
* ops (mark ranges in final-text coordinates), each all-or-nothing. An absent
|
|
452
|
+
* `addr.field` targets the body, an absent `addr.card` the main card.
|
|
453
|
+
*
|
|
454
|
+
* Throws on an out-of-range card, a field that is not richtext, a malformed
|
|
455
|
+
* bundle, or an op that applies out of bounds (the value is unchanged on a
|
|
456
|
+
* failed apply).
|
|
457
|
+
*/
|
|
458
|
+
applyChange(addr: Addr | string, bundle: ChangeBundle): void;
|
|
459
|
+
/**
|
|
460
|
+
* Authoring-ergonomics header introducing a blueprint to an LLM/MCP
|
|
461
|
+
* consumer for the given `quillName`. Re-exposes core's canonical text for
|
|
462
|
+
* JS consumers; any surface that draws from the same core source stays
|
|
463
|
+
* uniform.
|
|
464
|
+
*/
|
|
465
|
+
static blueprintInstruction(quill_name: string): string;
|
|
466
|
+
/**
|
|
467
|
+
* A single composable card by index — the whole `Card`, the card-indexed
|
|
468
|
+
* twin of the [`main`](Self::main) getter, so reading one card need not
|
|
469
|
+
* materialize every card via [`cards`](Self::cards). An out-of-range
|
|
470
|
+
* `index` throws `[EditError::IndexOutOfRange]`, matching the card write
|
|
471
|
+
* verbs.
|
|
472
|
+
*/
|
|
473
|
+
card(index: number): Card;
|
|
474
|
+
/**
|
|
475
|
+
* The index of the first composable card whose `$id` equals `id`, or
|
|
476
|
+
* `undefined` when none carries it. Resolves the canonical durable address
|
|
477
|
+
* without a hand-rolled scan over [`cards`](Self::cards); `$id` is
|
|
478
|
+
* non-unique by design, so the first match wins.
|
|
479
|
+
*/
|
|
480
|
+
cardIndexById(id: string): number | undefined;
|
|
481
|
+
clone(): Document;
|
|
482
|
+
/**
|
|
483
|
+
* Schema version this build writes via [`toJson`](Document::to_json).
|
|
484
|
+
* Tracks the `Document` model version (not the running crate version):
|
|
485
|
+
* the tag advances only when the wire format changes, not on every release.
|
|
486
|
+
*/
|
|
487
|
+
static currentSchemaVersion(): string;
|
|
488
|
+
/**
|
|
489
|
+
* Structural equality (parse-time `warnings` excluded). Use to debounce
|
|
490
|
+
* upstream prop updates instead of re-parsing on every keystroke.
|
|
491
|
+
*/
|
|
492
|
+
equals(other: Document): boolean;
|
|
493
|
+
/**
|
|
494
|
+
* Render a Diagnostic as the canonical pretty-printed text (core's
|
|
495
|
+
* `Diagnostic::fmt_pretty`). Single source of truth so a Diagnostic looks
|
|
496
|
+
* identical no matter which consumer surfaces it.
|
|
497
|
+
*/
|
|
498
|
+
static formatDiagnostic(diag: Diagnostic): string;
|
|
499
|
+
/**
|
|
500
|
+
* Authoring-format rules for the card-yaml markdown surface. The canonical
|
|
501
|
+
* text is core's (`quillmark_core::document::FORMAT_RULES`), re-exposed
|
|
502
|
+
* here for JS consumers so it matches any other surface that draws from the
|
|
503
|
+
* same source. Read once at startup and cache; the value never changes
|
|
504
|
+
* between calls.
|
|
505
|
+
*/
|
|
506
|
+
static formatRules(): string;
|
|
507
|
+
/**
|
|
508
|
+
* Reconstruct a `Document` from a versioned storage DTO string produced
|
|
509
|
+
* by [`toJson`](Document::to_json). Unknown `schema` tags are rejected.
|
|
510
|
+
* The result carries no parse-time warnings (`.warnings` is always empty).
|
|
511
|
+
*
|
|
512
|
+
* Throws if `json` is not a valid storage DTO (malformed JSON, unknown
|
|
513
|
+
* `schema`, missing fields, or unparseable quill reference).
|
|
514
|
+
*/
|
|
515
|
+
static fromJson(json: string): Document;
|
|
516
|
+
/**
|
|
517
|
+
* Parse markdown into a typed Document. Throws on parse errors.
|
|
518
|
+
*/
|
|
519
|
+
static fromMarkdown(markdown: string): Document;
|
|
520
|
+
/**
|
|
521
|
+
* Read the value at `addr` — the raw stored payload value of a field (a
|
|
522
|
+
* content object for a richtext field, a scalar/array/object otherwise), or
|
|
523
|
+
* the **body content** when `addr.field` is absent. A bare string is `Addr`
|
|
524
|
+
* shorthand for `{ field }`. Reads are total over the field axis: an absent
|
|
525
|
+
* field is `undefined`; only an out-of-range `addr.card` throws
|
|
526
|
+
* `[EditError::IndexOutOfRange]`. Reads need no schema, so they live on
|
|
527
|
+
* `Document`, not the typed writer; for the markdown projection of a
|
|
528
|
+
* richtext value use [`getMarkdown`](Self::get_markdown).
|
|
529
|
+
*/
|
|
530
|
+
get(addr: Addr | string): unknown;
|
|
531
|
+
/**
|
|
532
|
+
* The whole `$ext` map at `addr` (a card address, absent `card` = main), or
|
|
533
|
+
* `undefined` when the card carries none. The fine-grained `$ext` read —
|
|
534
|
+
* your own state without serializing the whole card. Throws on a present
|
|
535
|
+
* `field` (a card address takes only `card`) or an out-of-range card.
|
|
536
|
+
*/
|
|
537
|
+
getExt(addr?: CardAddr): Record<string, unknown> | undefined;
|
|
538
|
+
/**
|
|
539
|
+
* The value stored under `$ext[ns]` at `addr` (a card address, absent `card`
|
|
540
|
+
* = main), or `undefined`. The namespace-scoped `$ext` read — your own slot
|
|
541
|
+
* without a whole-card serialize, and non-destructive (unlike
|
|
542
|
+
* `removeExtNamespace`). Throws on a present `field` or an out-of-range card.
|
|
543
|
+
*/
|
|
544
|
+
getExtNamespace(addr: CardAddr, ns: string): unknown;
|
|
545
|
+
/**
|
|
546
|
+
* The **body** markdown projection — the main body, or a composable card's
|
|
547
|
+
* body (`{ card }`) — the on-demand, lossy export (content-only marks do not
|
|
548
|
+
* survive markdown). A body's type is a format fact, not a schema fact, so
|
|
549
|
+
* this read stays quill-free; a body is never absent.
|
|
550
|
+
*
|
|
551
|
+
* `addr` is an optional **card address** (`{ card }`, absent = main). A
|
|
552
|
+
* present `field` throws — a field's markdown is read through the
|
|
553
|
+
* schema-plane `quill.view(doc).get(field)`, which interprets by declared
|
|
554
|
+
* type (#978). An out-of-range `addr.card` throws.
|
|
555
|
+
*/
|
|
556
|
+
getMarkdown(addr?: CardAddr): string;
|
|
557
|
+
/**
|
|
558
|
+
* Insert a card — the single insertion verb: `at` absent appends, a number
|
|
559
|
+
* inserts at that index (must be in `0..=cards.length`). Accepts a
|
|
560
|
+
* `CardInput` — a card read back (`cards` / `removeCard` / `quill.seedCard`),
|
|
561
|
+
* a [`makeCard`](Document::make_card) result, or a bare `{ kind, body }`
|
|
562
|
+
* (every returned `Card` is a valid `CardInput`). Throws if `card.kind` is
|
|
563
|
+
* not a valid kind name, or if `at` is out of range.
|
|
564
|
+
*/
|
|
565
|
+
insertCard(card: CardInput, at?: number): void;
|
|
566
|
+
/**
|
|
567
|
+
* **Install** a richtext value at `addr` — **value semantics**, content only.
|
|
568
|
+
* Stores exactly `rt` (a canonical `Content` content object); the identity
|
|
569
|
+
* anchors of any previous value are gone. An absent `addr.field` targets the
|
|
570
|
+
* body, an absent `addr.card` the main card. For "here's new markdown," use
|
|
571
|
+
* [`revise`](Document::revise); the cold-import path is spelled at the call
|
|
572
|
+
* site as `install(addr, importMarkdown(md))`, so anchor loss is visible in
|
|
573
|
+
* source.
|
|
574
|
+
*
|
|
575
|
+
* Throws on an out-of-range card, a malformed field name, or an `rt` that is
|
|
576
|
+
* not a canonical content object.
|
|
577
|
+
*/
|
|
578
|
+
install(addr: Addr | string, rt: Content): void;
|
|
579
|
+
/**
|
|
580
|
+
* Whether the field at `addr` is marked `!must_fill`. A bare string is `Addr`
|
|
581
|
+
* shorthand for `{ field }`. `false` for an absent field (truthful — it isn't
|
|
582
|
+
* marked) and for a body address (a body is never a fill). Only an
|
|
583
|
+
* out-of-range `addr.card` throws.
|
|
584
|
+
*/
|
|
585
|
+
isFill(addr: Addr | string): boolean;
|
|
586
|
+
/**
|
|
587
|
+
* Replace this document's contents **in place** from a versioned storage
|
|
588
|
+
* DTO string — the mutating twin of the static
|
|
589
|
+
* [`fromJson`](Document::from_json) constructor. Parse-time `warnings` are
|
|
590
|
+
* cleared. Throws (leaving the document unchanged) on an invalid DTO.
|
|
591
|
+
*
|
|
592
|
+
* The cross-WASM-memory `Document` bridge: mutate a document on a
|
|
593
|
+
* backend-memory clone, then write the mutated state back into the caller's
|
|
594
|
+
* canonical document with this — the one way to update a live handle across
|
|
595
|
+
* the linear-memory seam without the caller re-binding its variable.
|
|
596
|
+
*/
|
|
597
|
+
loadJson(json: string): void;
|
|
598
|
+
/**
|
|
599
|
+
* Build a fresh `Card` from a kind and a flat field map — the ergonomic
|
|
600
|
+
* constructor for `insertCard`. `fields` is an optional
|
|
601
|
+
* `Record<string, unknown>` (each entry becomes a card field, in
|
|
602
|
+
* insertion order); `body` defaults to `""`. Kind validity is checked by
|
|
603
|
+
* `insertCard`, not here.
|
|
604
|
+
*/
|
|
605
|
+
static makeCard(kind: string, fields?: Record<string, unknown>, body?: string): Card;
|
|
606
|
+
/**
|
|
607
|
+
* Move the card at `from` to position `to`. `from == to` is a no-op.
|
|
608
|
+
*/
|
|
609
|
+
moveCard(from: number, to: number): void;
|
|
610
|
+
/**
|
|
611
|
+
* `new Document(quillRef)` — a blank document: a main card carrying only
|
|
612
|
+
* `$quill`, an empty body, and no composable cards. The programmatic
|
|
613
|
+
* blank canvas: absent fields resolve at render time (`default`, else
|
|
614
|
+
* type-empty zero), so nothing the caller did not set reaches the
|
|
615
|
+
* output. For an example-filled starter use `Quill.seedDocument()`.
|
|
616
|
+
* Throws on an invalid quill reference. Mirrors Python `Document(quill_ref)`.
|
|
617
|
+
*/
|
|
618
|
+
constructor(quill_ref: string);
|
|
619
|
+
/**
|
|
620
|
+
* The canonical `$quill` reference grammar as author-facing text. Core is
|
|
621
|
+
* the single source of truth: drive schema `describe` and validation
|
|
622
|
+
* messages from this instead of re-stating the rule — it matches the
|
|
623
|
+
* `hint` on `parse::invalid_quill_reference`. Cache it; the value never
|
|
624
|
+
* changes.
|
|
625
|
+
*/
|
|
626
|
+
static quillRefHint(): string;
|
|
627
|
+
removeCard(index: number): Card | undefined;
|
|
628
|
+
/**
|
|
629
|
+
* Remove the `$ext` map on the card `addr` targets *entirely*, returning the
|
|
630
|
+
* previous map or `undefined` — a blunt escape hatch that discards every
|
|
631
|
+
* namespace at once (prefer `removeExtNamespace`). `addr` is a card address
|
|
632
|
+
* (absent = main). Throws on a present `field` or an out-of-range card.
|
|
633
|
+
*/
|
|
634
|
+
removeExt(addr?: CardAddr): Record<string, unknown> | undefined;
|
|
635
|
+
/**
|
|
636
|
+
* Remove `$ext[ns]` on the card `addr` targets, returning its value or
|
|
637
|
+
* `undefined`; drops `$ext` once empty. `addr` is a card address (absent =
|
|
638
|
+
* main). Preserves sibling namespaces. Throws on a present `field` or an
|
|
639
|
+
* out-of-range card.
|
|
640
|
+
*/
|
|
641
|
+
removeExtNamespace(addr: CardAddr, ns: string): any;
|
|
642
|
+
/**
|
|
643
|
+
* Remove a field at `addr`, returning the removed value or `undefined`. A
|
|
644
|
+
* bare string is `Addr` shorthand for `{ field }`. One `remove` verb serves
|
|
645
|
+
* every write lane. A body address throws; throws on an out-of-range card or
|
|
646
|
+
* a malformed name.
|
|
647
|
+
*/
|
|
648
|
+
removeField(addr: Addr | string): any;
|
|
649
|
+
/**
|
|
650
|
+
* Remove `cardKind` from the main card's `$seed` map, returning its
|
|
651
|
+
* overlay or `undefined`; drops `$seed` entirely once empty. Sibling kinds
|
|
652
|
+
* survive. `$seed` is main-only, so this takes no address.
|
|
653
|
+
*/
|
|
654
|
+
removeSeedNamespace(card_kind: string): any;
|
|
655
|
+
/**
|
|
656
|
+
* **Revise** the richtext value at `addr` from a markdown string — **edit
|
|
657
|
+
* semantics**, the default write path, returning the text [`Delta`]. Imports
|
|
658
|
+
* the markdown, diffs it against the current value, rebases surviving
|
|
659
|
+
* identity anchors, and returns the change an editor bridge maps its own
|
|
660
|
+
* positions through (`mapPos`). An absent `addr.field` targets the body, an
|
|
661
|
+
* absent `addr.card` the main card; an absent field cold-imports from empty.
|
|
662
|
+
*
|
|
663
|
+
* Throws on an out-of-range card, a malformed field name, a present
|
|
664
|
+
* non-content field value, or an over-nested markdown input.
|
|
665
|
+
*/
|
|
666
|
+
revise(addr: Addr | string, markdown: string): Delta;
|
|
667
|
+
/**
|
|
668
|
+
* Read the `schema` version tag from a raw storage DTO string without a
|
|
669
|
+
* full parse, or `undefined`. Returns unknown future versions as-is —
|
|
670
|
+
* useful to distinguish "build too old" from "payload corrupt" when
|
|
671
|
+
* `fromJson` throws.
|
|
672
|
+
*/
|
|
673
|
+
static schemaVersionOf(json: string): string | undefined;
|
|
674
|
+
/**
|
|
675
|
+
* The main card's `$seed` overlay object for `kind` (the `$seed[kind]`
|
|
676
|
+
* entry), or `undefined` when absent. The cheap read that feeds
|
|
677
|
+
* `quill.seedCard(kind, overlay)` without serializing the whole main card
|
|
678
|
+
* via [`main`](Self::main) to fish out one key — and it keeps `seedCard`
|
|
679
|
+
* pure: the quill still never reads the document.
|
|
680
|
+
*/
|
|
681
|
+
seedOverlay(kind: string): Record<string, unknown> | undefined;
|
|
682
|
+
/**
|
|
683
|
+
* Replace the kind of the card at `index`. Payload and body are untouched;
|
|
684
|
+
* schema-aware migration is the caller's responsibility.
|
|
685
|
+
* Throws if `index` is out of range or `newKind` is invalid.
|
|
686
|
+
*/
|
|
687
|
+
setCardKind(index: number, new_kind: string): void;
|
|
688
|
+
/**
|
|
689
|
+
* Replace the QUILL reference string. Throws if `ref_str` is invalid.
|
|
690
|
+
*/
|
|
691
|
+
setQuillRef(ref_str: string): void;
|
|
692
|
+
/**
|
|
693
|
+
* Replace the opaque `$ext` map on the card `addr` targets (a card address,
|
|
694
|
+
* absent `card` = main). `value` must be a plain object. `$ext` carries
|
|
695
|
+
* out-of-band consumer state and never reaches the rendered output; pass
|
|
696
|
+
* `{}` for an explicit empty `$ext`. Quill-free and verbatim — an opaque
|
|
697
|
+
* `store` verb. Throws on a present `field` or an out-of-range card.
|
|
698
|
+
*/
|
|
699
|
+
storeExt(addr: CardAddr, value: any): void;
|
|
700
|
+
/**
|
|
701
|
+
* Merge `value` into `$ext[ns]` on the card `addr` targets, preserving
|
|
702
|
+
* sibling namespaces — the recommended `$ext` write. `addr` is a card
|
|
703
|
+
* address (absent = main). Quill-free and verbatim — an opaque `store` verb.
|
|
704
|
+
* Throws on a present `field` or an out-of-range card.
|
|
705
|
+
*/
|
|
706
|
+
storeExtNamespace(addr: CardAddr, ns: string, value: any): void;
|
|
707
|
+
/**
|
|
708
|
+
* Store a field verbatim at `addr` — the opaque store (**store** = verbatim,
|
|
709
|
+
* coercion deferred to render; the typed write is
|
|
710
|
+
* [`commitField`](Document::commit_field)). A bare string is `Addr`
|
|
711
|
+
* shorthand for `{ field }`, so `doc.storeField("qty", 3)` reads as written;
|
|
712
|
+
* `{ card: 2, field: "qty" }` targets a composable card. Clears any
|
|
713
|
+
* `!must_fill` marker. A body address (no `field`) throws — a body is never
|
|
714
|
+
* opaque; write it with `revise` / `install` / `writer.setBody`. Throws on
|
|
715
|
+
* an out-of-range card or a malformed name.
|
|
716
|
+
*/
|
|
717
|
+
storeField(addr: Addr | string, value: any): void;
|
|
718
|
+
/**
|
|
719
|
+
* Store several fields verbatim and atomically on the card `addr` targets —
|
|
720
|
+
* the opaque store's batch. `addr` is a **card address** (`{ card }`, absent
|
|
721
|
+
* = main); a present `field` throws. The batch verb takes the address first
|
|
722
|
+
* and is never shape-overloaded, because `card` is a legal field name:
|
|
723
|
+
* `storeFields({}, fields)` is the main card, `storeFields({ card: 2 },
|
|
724
|
+
* fields)` a composable one — never ambiguous with "set field `card`".
|
|
725
|
+
* Nothing is applied on error; the thrown error's `diagnostics` carry one
|
|
726
|
+
* entry per offending field. Throws on an out-of-range card.
|
|
727
|
+
*/
|
|
728
|
+
storeFields(addr: CardAddr, fields: Record<string, unknown>): void;
|
|
729
|
+
/**
|
|
730
|
+
* Store a field verbatim at `addr` and mark it `!must_fill` — the opaque
|
|
731
|
+
* store's fill variant, card-capable (a bare string or `{ field }` for main,
|
|
732
|
+
* `{ card, field }` for a composable card). A body address throws. Same
|
|
733
|
+
* validation as [`storeField`](Document::store_field).
|
|
734
|
+
*/
|
|
735
|
+
storeFill(addr: Addr | string, value: any): void;
|
|
736
|
+
/**
|
|
737
|
+
* Merge a card-kind's seed `overlay` into the **main** card's `$seed` map
|
|
738
|
+
* under `cardKind`, preserving sibling kinds — `$seed` lives on the main
|
|
739
|
+
* card by model, so this takes no address. Sets the starting values new
|
|
740
|
+
* cards of that kind spawn with. Quill-free and verbatim — an opaque `store`
|
|
741
|
+
* verb. Throws if `overlay` cannot be serialized or nests too deep.
|
|
742
|
+
*/
|
|
743
|
+
storeSeedNamespace(card_kind: string, overlay: any): void;
|
|
744
|
+
/**
|
|
745
|
+
* Serialize this document to a versioned storage DTO string.
|
|
746
|
+
*
|
|
747
|
+
* Prefer this over `toMarkdown` for persistence across restarts or crate
|
|
748
|
+
* upgrades — the wire format is frozen per `schema` version. Parse-time
|
|
749
|
+
* `warnings` are excluded from the DTO.
|
|
750
|
+
*
|
|
751
|
+
* Output is **byte-deterministic** within a `schema` version: equal
|
|
752
|
+
* documents produce byte-equal output, safe for content-hash use cases.
|
|
753
|
+
*/
|
|
754
|
+
toJson(): string;
|
|
755
|
+
/**
|
|
756
|
+
* Emit canonical Quillmark Markdown. Round-trip safe: re-parsing the
|
|
757
|
+
* result produces a `Document` equal to `self` by value and by type.
|
|
758
|
+
*/
|
|
759
|
+
toMarkdown(): string;
|
|
760
|
+
/**
|
|
761
|
+
* Like [`fromJson`](Document::from_json) but returns `undefined` instead
|
|
762
|
+
* of throwing when `json` is not a valid storage DTO — use to
|
|
763
|
+
* discriminate format without exceptions as control flow.
|
|
764
|
+
* `undefined` means "not a storage DTO"; `fromMarkdown` still throws on
|
|
765
|
+
* genuinely malformed markdown.
|
|
766
|
+
*/
|
|
767
|
+
static tryFromJson(json: string): Document | undefined;
|
|
768
|
+
/**
|
|
769
|
+
* Number of composable cards (excludes the main card). O(1).
|
|
770
|
+
*/
|
|
771
|
+
readonly cardCount: number;
|
|
772
|
+
readonly cards: Card[];
|
|
773
|
+
/**
|
|
774
|
+
* The document's main (entry) card. Allocates and serializes on each
|
|
775
|
+
* call — cache locally if read in a hot loop.
|
|
776
|
+
*/
|
|
777
|
+
readonly main: Card;
|
|
778
|
+
readonly quillRef: string;
|
|
779
|
+
readonly warnings: Diagnostic[];
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/**
|
|
783
|
+
* Live render session: reads (`render`, `paint`, `pageSize`, `regions`,
|
|
784
|
+
* `fieldAt`, `positionAt`, `locate`) serve the current compile. `apply(doc)`
|
|
785
|
+
* recompiles a whole document in place, transactionally (on throw every read
|
|
786
|
+
* keeps serving the last-good compile). Geometry reads reflect the current
|
|
787
|
+
* compile; anchoring a caret across edits is the editor's job — re-read
|
|
788
|
+
* geometry after each committed `apply`.
|
|
789
|
+
*
|
|
790
|
+
* **Empty documents.** A zero-page document yields a valid session
|
|
791
|
+
* (`pageCount === 0`); `paint(ctx, 0)` or `pageSize(0)` throws with
|
|
792
|
+
* `"page index 0 out of range (pageCount=0)"`. Branch on `pageCount === 0`
|
|
793
|
+
* rather than catching the error.
|
|
794
|
+
*/
|
|
795
|
+
export class LiveSession {
|
|
796
|
+
private constructor();
|
|
797
|
+
free(): void;
|
|
798
|
+
[Symbol.dispose](): void;
|
|
799
|
+
/**
|
|
800
|
+
* Recompile the session against `doc` — the edit verb of a live preview.
|
|
801
|
+
* The document is compiled through the same schema pipeline as `open`
|
|
802
|
+
* (same quill), then applied transactionally: on throw every read
|
|
803
|
+
* (`render`, `paint`, `pageSize`, `regions`, `fieldAt`) keeps serving the last-good
|
|
804
|
+
* compile, and the session recovers on the next successful `apply`. On
|
|
805
|
+
* success reads serve the new compile; repaint `dirtyPages ∩ visible`.
|
|
806
|
+
*/
|
|
807
|
+
apply(doc: Document): ChangeSet;
|
|
808
|
+
/**
|
|
809
|
+
* The schema field whose content is under a point on `page` — the
|
|
810
|
+
* forward (click → field) direction: hit-test a click against the
|
|
811
|
+
* compiled document and get back the field address to focus in the
|
|
812
|
+
* editor, or `undefined` off any field's ink. `x`/`y` are PDF points
|
|
813
|
+
* with a **bottom-left** origin, the same space as `FieldRegion.rect` —
|
|
814
|
+
* from a canvas click, invert the overlay transform documented on
|
|
815
|
+
* `FieldRegion`: `x = clickPx.x / renderScale`,
|
|
816
|
+
* `y = pageHeightPt - clickPx.y / renderScale`. Unlike `regions()`,
|
|
817
|
+
* *every* placement answers, not just the first.
|
|
818
|
+
*/
|
|
819
|
+
fieldAt(page: number, x: number, y: number): string | undefined;
|
|
820
|
+
/**
|
|
821
|
+
* The whole-field highlight boxes for `field` — one union rect per page,
|
|
822
|
+
* over the field's `span`-bearing content segments. The convenience that
|
|
823
|
+
* owns the union `regions()` leaves derived: it keeps `regions()` the
|
|
824
|
+
* low-level disjoint truth (#829) and folds the span-filter + per-page
|
|
825
|
+
* union here, so a "highlight the focused field" consumer stops
|
|
826
|
+
* reimplementing it. **Content only** — a field placed solely as a scalar
|
|
827
|
+
* reference or a bound widget carries no `span` and returns `[]`; its box
|
|
828
|
+
* is a single `regions()` rect. Reflects the current compile, like
|
|
829
|
+
* `regions()`.
|
|
830
|
+
*/
|
|
831
|
+
fieldBoxes(field: string): FieldRegion[];
|
|
832
|
+
/**
|
|
833
|
+
* A content position → **caret rect** — the reverse of `positionAt`: given
|
|
834
|
+
* a field and a USV offset into its `Content`, return the box (in the
|
|
835
|
+
* same bottom-left PDF-point space as `FieldRegion.rect`) to draw a caret
|
|
836
|
+
* at, its `span` collapsed to `[pos, pos]`; `undefined` when the field
|
|
837
|
+
* places no tracked content or the offset maps to no drawn glyph.
|
|
838
|
+
*/
|
|
839
|
+
locate(field: string, pos: number): FieldRegion | undefined;
|
|
840
|
+
/**
|
|
841
|
+
* Page dimensions in points (1 pt = 1/72 inch).
|
|
842
|
+
* Throws if the backend has no canvas painter or `page` is out of range.
|
|
843
|
+
*/
|
|
844
|
+
pageSize(page: number): PageSize;
|
|
845
|
+
/**
|
|
846
|
+
* Paint `page` into a `CanvasRenderingContext2D` or
|
|
847
|
+
* `OffscreenCanvasRenderingContext2D`. The painter owns
|
|
848
|
+
* `canvas.width`/`height` (no `clearRect` needed); consumers own
|
|
849
|
+
* `canvas.style.*`. If `layoutScale * densityScale` exceeds 16384 px
|
|
850
|
+
* per side, `densityScale` is clamped — `PaintResult.clamped` reports it and
|
|
851
|
+
* `PaintResult.effectiveDensityScale` carries the density actually applied.
|
|
852
|
+
*
|
|
853
|
+
* `put_image_data` writes the whole backing store, bypassing the 2D
|
|
854
|
+
* context's transform, `globalAlpha`, and clip: the painter owns the entire
|
|
855
|
+
* canvas, so each visible page needs its own `` — you cannot composite
|
|
856
|
+
* two pages, a sub-rect, or a context transform through this call.
|
|
857
|
+
*
|
|
858
|
+
* Throws if the backend has no canvas painter, `page` is out of range,
|
|
859
|
+
* `ctx` is the wrong type, or either scale is non-finite or `<= 0`.
|
|
860
|
+
*/
|
|
861
|
+
paint(ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, page: number, opts: PaintOptions | undefined): PaintResult;
|
|
862
|
+
/**
|
|
863
|
+
* A point → **content position** — the fine-grained click direction:
|
|
864
|
+
* hit-test a point and get back the field *and* a USV offset into its
|
|
865
|
+
* `Content` (for placing a caret or mapping a selection into the content
|
|
866
|
+
* model), or `undefined` off all content ink. `x`/`y` are PDF points,
|
|
867
|
+
* bottom-left origin — the same space as `fieldAt`. The offset is
|
|
868
|
+
* cluster-exact and degrades to the containing segment's start on
|
|
869
|
+
* origin-less ink (list markers, a code fence's interior). See
|
|
870
|
+
* `ContentHit`.
|
|
871
|
+
*/
|
|
872
|
+
positionAt(page: number, x: number, y: number): ContentHit | undefined;
|
|
873
|
+
/**
|
|
874
|
+
* Schema-field geometry for this compiled session — each content field's
|
|
875
|
+
* **first placement** (one region per page it touches) plus widget and
|
|
876
|
+
* scalar-reference-site regions, keyed on the quill schema field path; a
|
|
877
|
+
* field may still appear more than once (group by `field`, see
|
|
878
|
+
* `FieldRegion`). A session-level query: no render, no byte artifact. An
|
|
879
|
+
* interactive preview reads it to scroll to / highlight the focused
|
|
880
|
+
* field over a `paint`-ed canvas; the click direction is `fieldAt`.
|
|
881
|
+
* Empty for backends that place no schema fields.
|
|
882
|
+
*/
|
|
883
|
+
regions(): FieldRegion[];
|
|
884
|
+
render(opts?: RenderOptions | null): RenderResult;
|
|
885
|
+
/**
|
|
886
|
+
* The backend that produced this session (e.g. `"typst"`).
|
|
887
|
+
*/
|
|
888
|
+
readonly backendId: string;
|
|
889
|
+
readonly pageCount: number;
|
|
890
|
+
/**
|
|
891
|
+
* `true` iff `paint` and `pageSize` will succeed for this session. Derived
|
|
892
|
+
* from the session's canvas seam, so it reflects exactly what `paint` will
|
|
893
|
+
* do — no separately captured flag.
|
|
894
|
+
*/
|
|
895
|
+
readonly supportsCanvas: boolean;
|
|
896
|
+
/**
|
|
897
|
+
* Non-fatal diagnostics of the session's **current compile** (e.g. Typst
|
|
898
|
+
* font fallback) — set at open and refreshed by each committed `apply`;
|
|
899
|
+
* a failed apply keeps the last-good compile's warnings. Also appended
|
|
900
|
+
* to `RenderResult.warnings` on each `render()` call.
|
|
901
|
+
*/
|
|
902
|
+
readonly warnings: Diagnostic[];
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
export class Quill {
|
|
906
|
+
private constructor();
|
|
907
|
+
free(): void;
|
|
908
|
+
[Symbol.dispose](): void;
|
|
909
|
+
/**
|
|
910
|
+
* Build a quill from a file tree. Pure — no backend, no engine; the
|
|
911
|
+
* declared backend is resolved later, at render time.
|
|
912
|
+
*
|
|
913
|
+
* Accepts either a `Map<string, Uint8Array>` or a plain object
|
|
914
|
+
* (`Record<string, Uint8Array>`). Plain objects are walked via
|
|
915
|
+
* `Object.entries` at the boundary; the Rust side sees a single
|
|
916
|
+
* canonical shape.
|
|
917
|
+
*/
|
|
918
|
+
static fromTree(tree: Map<string, Uint8Array>): Quill;
|
|
919
|
+
/**
|
|
920
|
+
* Seed a starter composable `Card` of the given kind (carries `$kind`),
|
|
921
|
+
* layering an optional per-kind seed `overlay` over the schema-example
|
|
922
|
+
* base (`overlay › example › absent`). Returns `undefined` if `cardKind`
|
|
923
|
+
* is not declared in this quill's schema, else a `Card` that feeds
|
|
924
|
+
* straight into `Document.insertCard`.
|
|
925
|
+
*
|
|
926
|
+
* Pass `document.seedOverlay(cardKind)` as `overlay` so a card added to a
|
|
927
|
+
* template-derived document inherits its curated starting values; omit it
|
|
928
|
+
* (or pass `undefined` / `null`) for the bare schema seed. `overlay` is a
|
|
929
|
+
* plain object — this reads the document, it does not mutate it.
|
|
930
|
+
*/
|
|
931
|
+
seedCard(card_kind: string, overlay: Record<string, unknown> | undefined): Card | undefined;
|
|
932
|
+
/**
|
|
933
|
+
* Seed a starter `Document` from the schema — the main card plus one
|
|
934
|
+
* instance of each composable card kind, each committing its fields'
|
|
935
|
+
* `example:` values and leaving every other field absent (interpolated at
|
|
936
|
+
* render: `default:`, else type-empty zero). Illustration-first: a field
|
|
937
|
+
* with both an `example` and a `default` renders its example. See
|
|
938
|
+
* `prose/canon/SCHEMAS.md` § "Document seeding".
|
|
939
|
+
*/
|
|
940
|
+
seedDocument(): Document;
|
|
941
|
+
/**
|
|
942
|
+
* Seed a starter main `Card` (carries `$quill`) from the schema — the
|
|
943
|
+
* `$kind: main` card of [`seedDocument`](Self::seed_document) in
|
|
944
|
+
* isolation, committing each field's `example:` value. Returns the same
|
|
945
|
+
* `Card` shape as the `Document.main` getter.
|
|
946
|
+
*/
|
|
947
|
+
seedMain(): Card;
|
|
948
|
+
/**
|
|
949
|
+
* Flatten this quill back into its canonical file tree — the inverse of
|
|
950
|
+
* [`fromTree`](Self::from_tree). Round-trips: `Quill.fromTree(q.toTree())`
|
|
951
|
+
* reproduces an equivalent quill.
|
|
952
|
+
*
|
|
953
|
+
* This is how a quill crosses a WASM linear-memory boundary as data: a
|
|
954
|
+
* `Quill` built in one build (e.g. the Typst-less `@quillmark/wasm/core`)
|
|
955
|
+
* cannot be passed to an engine in another (separate linear memories), so
|
|
956
|
+
* `@quillmark/wasm/runtime` re-feeds this tree to the backend build's
|
|
957
|
+
* `Quill.fromTree` on demand. Keys are `"/"`-joined relative paths,
|
|
958
|
+
* matching what `fromTree` accepts.
|
|
959
|
+
*/
|
|
960
|
+
toTree(): Map<string, Uint8Array>;
|
|
961
|
+
/**
|
|
962
|
+
* Validate `doc` against this quill's schema, returning every diagnostic
|
|
963
|
+
* (an empty array when the document is valid).
|
|
964
|
+
*
|
|
965
|
+
* Forwards the canonical `validation::*` diagnostics — same `code`,
|
|
966
|
+
* `path`, and `hint` the engine emits — including the non-fatal
|
|
967
|
+
* `validation::must_fill` warning for each `!must_fill` marker left in
|
|
968
|
+
* the document. Field values, defaults, and order are not part of this
|
|
969
|
+
* surface: read them from the `Document` payload and `Quill.schema`
|
|
970
|
+
* (schema key order is display order).
|
|
971
|
+
*/
|
|
972
|
+
validate(doc: Document): Diagnostic[];
|
|
973
|
+
/**
|
|
974
|
+
* The *declared* backend identifier (`config.backend`, e.g. `"typst"`).
|
|
975
|
+
* Intent, not a resolved capability — capability (`supportedFormats` /
|
|
976
|
+
* `supportsCanvas`) is read from the engine.
|
|
977
|
+
*/
|
|
978
|
+
readonly backendId: string;
|
|
979
|
+
readonly blueprint: string;
|
|
980
|
+
/**
|
|
981
|
+
* Identity snapshot of the `quill:` section of `Quill.yaml` plus any extra
|
|
982
|
+
* `quill:` keys. Pure config — the backend's output formats are a
|
|
983
|
+
* resolved-backend capability read from the engine
|
|
984
|
+
* (`Quillmark.supportedFormats`), not part of this snapshot.
|
|
985
|
+
*/
|
|
986
|
+
readonly metadata: QuillMetadata;
|
|
987
|
+
/**
|
|
988
|
+
* Document schema for the quill: the user-fillable fields plus their
|
|
989
|
+
* `ui` hints (title / group / compact / multiline). The single
|
|
990
|
+
* field-metadata surface — drives form editors and LLM/MCP consumers
|
|
991
|
+
* alike. Key order in `fields`/`properties` is declaration order — the
|
|
992
|
+
* ordering contract. Returns the `QuillSchema` shape.
|
|
993
|
+
*/
|
|
994
|
+
readonly schema: QuillSchema;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
/**
|
|
998
|
+
* Render engine: a backend registry and render dispatcher. Render build only —
|
|
999
|
+
* the core build constructs and validates quills without it.
|
|
1000
|
+
*/
|
|
1001
|
+
export class Quillmark {
|
|
1002
|
+
free(): void;
|
|
1003
|
+
[Symbol.dispose](): void;
|
|
1004
|
+
constructor();
|
|
1005
|
+
/**
|
|
1006
|
+
* Open a live render session for `doc` against `quill`'s backend.
|
|
1007
|
+
*/
|
|
1008
|
+
open(quill: Quill, doc: Document): LiveSession;
|
|
1009
|
+
/**
|
|
1010
|
+
* Render `doc` against `quill` in one shot. Convenience over `open` +
|
|
1011
|
+
* `LiveSession.render`: an unset `output_format` falls back to the
|
|
1012
|
+
* backend's first supported format.
|
|
1013
|
+
*/
|
|
1014
|
+
render(quill: Quill, doc: Document, opts?: RenderOptions | null): RenderResult;
|
|
1015
|
+
/**
|
|
1016
|
+
* The output formats `quill`'s backend can emit. Static capability —
|
|
1017
|
+
* resolves the backend but compiles nothing. Throws `engine::backend_not_found`
|
|
1018
|
+
* if no registered backend matches the quill's declared backend.
|
|
1019
|
+
*/
|
|
1020
|
+
supportedFormats(quill: Quill): OutputFormat[];
|
|
1021
|
+
/**
|
|
1022
|
+
* Pre-session hint: `true` iff `quill`'s backend can paint sessions to a
|
|
1023
|
+
* canvas, derived from the backend's output formats; `false` when the
|
|
1024
|
+
* backend is unsupported. Use as a cheap precondition probe before mounting
|
|
1025
|
+
* a canvas-based preview UI; the authoritative answer is the session's
|
|
1026
|
+
* `supportsCanvas` getter once `open()` has been called.
|
|
1027
|
+
*/
|
|
1028
|
+
supportsCanvas(quill: Quill): boolean;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
/**
|
|
1032
|
+
* Export a canonical `Content` content to its markdown projection — the pure
|
|
1033
|
+
* on-demand codec behind `exportMarkdown(card.body)`. Throws if `rt` is not a
|
|
1034
|
+
* canonical content.
|
|
1035
|
+
*/
|
|
1036
|
+
export function exportMarkdown(rt: Content): string;
|
|
1037
|
+
|
|
1038
|
+
/**
|
|
1039
|
+
* Import a markdown string to a canonical `Content` content — the pure,
|
|
1040
|
+
* document-free codec. Pair with `install(addr, importMarkdown(md))` to spell
|
|
1041
|
+
* the cold (anchor-losing) write at the call site; prefer `revise` for edit
|
|
1042
|
+
* semantics. Throws on an over-nested input.
|
|
1043
|
+
*/
|
|
1044
|
+
export function importMarkdown(markdown: string): Content;
|
|
1045
|
+
|
|
1046
|
+
/**
|
|
1047
|
+
* Initialize the WASM module with panic hooks for better error messages
|
|
1048
|
+
*/
|
|
1049
|
+
export function init(): void;
|
|
1050
|
+
|
|
1051
|
+
/**
|
|
1052
|
+
* Map a base content position through a `delta` to its new position — the pure
|
|
1053
|
+
* position-mapping codec an editor bridge composes to hold a caret stable
|
|
1054
|
+
* across a `revise`. `assoc` decides the side of a same-position insertion
|
|
1055
|
+
* (`"after"` moves past it). Throws on a malformed `delta`.
|
|
1056
|
+
*/
|
|
1057
|
+
export function mapPos(delta: Delta, pos: number, assoc: Assoc): number;
|
|
1058
|
+
|
|
1059
|
+
/**
|
|
1060
|
+
* Rebase `markdown` onto a `base` content — the pure, document-free twin of
|
|
1061
|
+
* `revise`: cold-import + `diff_import`, returning the new `content` and the
|
|
1062
|
+
* text `delta` (surviving anchors rebased). Use it to compute a revise without
|
|
1063
|
+
* a document in hand; `revise(addr, md)` fuses this with the store for
|
|
1064
|
+
* atomicity. Throws on an over-nested markdown input or a non-content `base`.
|
|
1065
|
+
*/
|
|
1066
|
+
export function rebase(base: Content, markdown: string): { content: Content; delta: Delta };
|