@quillmark/wasm 0.88.0 → 0.90.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/core/wasm.d.ts ADDED
@@ -0,0 +1,439 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /** A field or comment entry in a `Card.payloadItems` list. */
5
+ export type PayloadItem =
6
+ | { type: "field"; key: string; value: unknown; fill?: boolean }
7
+ | { type: "comment"; text: string; inline?: boolean };
8
+
9
+ /**
10
+ * A single card block. The one shape exchanged in both directions: returned by
11
+ * `Document.main` / `Document.cards` / `Document.removeCard` / `Quill.seedCard`,
12
+ * and accepted by `Document.pushCard` / `Document.insertCard`. Build a fresh
13
+ * one with `Document.makeCard`.
14
+ *
15
+ * `$` system entries are hoisted to named fields: `kind` (the `$kind`, empty
16
+ * string when none), optional `quill` (the `$quill` `name@version`, main card
17
+ * only), optional `id` (`$id`), and optional `ext` (`$ext`). `payloadItems`
18
+ * carries user fields and comments in order.
19
+ */
20
+ export interface Card {
21
+ kind: string;
22
+ quill?: string;
23
+ id?: string;
24
+ ext?: Record<string, unknown>;
25
+ payloadItems: PayloadItem[];
26
+ body: string;
27
+ }
28
+
29
+
30
+
31
+ /** UI layout hints for a single field. */
32
+ export interface QuillFieldUi {
33
+ group?: string;
34
+ order?: number;
35
+ compact?: boolean;
36
+ multiline?: boolean;
37
+ }
38
+
39
+ /** UI layout hints for a card (main or named card kind). */
40
+ export interface QuillCardUi {
41
+ title?: string;
42
+ }
43
+
44
+ /** Body namespace for a card (main or named card kind). */
45
+ export interface QuillCardBody {
46
+ /** When false, consumers must not accept or store body content for this card kind. Defaults to true. */
47
+ enabled?: boolean;
48
+ /** Example body content embedded verbatim in the blueprint body region. Fallback is "Write <card> body here." */
49
+ example?: string;
50
+ }
51
+
52
+ /** Schema entry for a single field declared in a quill's `Quill.yaml`.
53
+ *
54
+ * A field's *cell* is determined by `default`: a field with a `default`
55
+ * is **Endorsed** (the rendered value is shippable as-is), while a field
56
+ * without a `default` is **Unendorsed** (the blueprint carries a
57
+ * `<must-fill>` sentinel and validation reports
58
+ * `validation::field_absent` if the field is absent at validate
59
+ * time — a non-fatal signal, since the render path zero-fills an absent
60
+ * field). There is no separate `required` axis.
61
+ */
62
+ export interface QuillFieldSchema {
63
+ type: "string" | "number" | "integer" | "boolean" | "array" | "object" | "datetime" | "markdown";
64
+ description?: string;
65
+ default?: unknown;
66
+ example?: unknown;
67
+ enum?: string[];
68
+ ui?: QuillFieldUi;
69
+ properties?: Record<string, QuillFieldSchema>;
70
+ items?: QuillFieldSchema;
71
+ }
72
+
73
+ /** Schema entry for the main card or a named card kind. */
74
+ export interface QuillCardSchema {
75
+ description?: string;
76
+ fields: Record<string, QuillFieldSchema>;
77
+ ui?: QuillCardUi;
78
+ body?: QuillCardBody;
79
+ }
80
+
81
+ /**
82
+ * Document schema returned by `Quill.schema`. Includes optional `ui` keys.
83
+ *
84
+ * Describes only the user-fillable fields. The quill reference
85
+ * (constructed as `${metadata.name}@${metadata.version}`) and card-kind
86
+ * discriminators are document-level metadata, not schema fields.
87
+ */
88
+ export interface QuillSchema {
89
+ main: QuillCardSchema;
90
+ /** Present only when the quill declares at least one named card kind. */
91
+ card_kinds?: Record<string, QuillCardSchema>;
92
+ }
93
+
94
+ /**
95
+ * Identity snapshot mirroring the `quill:` section of `Quill.yaml`.
96
+ * The schema lives on `Quill.schema`; the backend's output formats are a
97
+ * resolved-backend capability read from the engine (`Quillmark.supportedFormats`),
98
+ * not part of this pure-config snapshot.
99
+ */
100
+ export interface QuillMetadata {
101
+ name: string;
102
+ version: string;
103
+ backend: string;
104
+ author: string;
105
+ description: string;
106
+ }
107
+
108
+
109
+ export interface Diagnostic {
110
+ severity: Severity;
111
+ code?: string;
112
+ message: string;
113
+ location?: Location;
114
+ path?: string;
115
+ hint?: string;
116
+ sourceChain?: string[];
117
+ }
118
+
119
+ export interface Location {
120
+ file: string;
121
+ line: number;
122
+ column: number;
123
+ }
124
+
125
+ export type Severity = "error" | "warning" | "note";
126
+
127
+
128
+ /**
129
+ * Typed in-memory Quillmark document.
130
+ */
131
+ export class Document {
132
+ private constructor();
133
+ free(): void;
134
+ [Symbol.dispose](): void;
135
+ /**
136
+ * Authoring-ergonomics header introducing a blueprint to an LLM/MCP
137
+ * consumer for the given `quillName`. Surfaced verbatim by every binding
138
+ * so the wording stays uniform across CLI / Python / MCP.
139
+ */
140
+ static blueprintInstruction(quill_name: string): string;
141
+ clone(): Document;
142
+ /**
143
+ * Schema version this build writes via [`toJson`](Document::to_json).
144
+ * Tracks the `Document` model version (not the running crate version):
145
+ * the tag advances only when the wire format changes, not on every release.
146
+ */
147
+ static currentSchemaVersion(): string;
148
+ /**
149
+ * Structural equality (parse-time `warnings` excluded). Use to debounce
150
+ * upstream prop updates instead of re-parsing on every keystroke.
151
+ */
152
+ equals(other: Document): boolean;
153
+ /**
154
+ * Render a Diagnostic as the canonical pretty-printed text every binding
155
+ * shows (CLI, Python, MCP). Single source of truth so a Diagnostic looks
156
+ * identical no matter which consumer surfaces it.
157
+ */
158
+ static formatDiagnostic(diag: Diagnostic): string;
159
+ /**
160
+ * Authoring-format rules for the card-yaml markdown surface — the same
161
+ * text every binding (CLI, Python, MCP) shows so callers reading errors
162
+ * from one binding can use the rules from any other. Read once at
163
+ * startup and cache; the value never changes between calls.
164
+ */
165
+ static formatRules(): string;
166
+ /**
167
+ * Reconstruct a `Document` from a versioned storage DTO string produced
168
+ * by [`toJson`](Document::to_json). Unknown `schema` tags are rejected.
169
+ * The result carries no parse-time warnings (`.warnings` is always empty).
170
+ *
171
+ * Throws if `json` is not a valid storage DTO (malformed JSON, unknown
172
+ * `schema`, missing fields, or unparseable quill reference).
173
+ */
174
+ static fromJson(json: string): Document;
175
+ /**
176
+ * Parse markdown into a typed Document. Throws on parse errors.
177
+ */
178
+ static fromMarkdown(markdown: string): Document;
179
+ /**
180
+ * Insert a card at `index` (must be in `0..=cards.length`). Accepts a
181
+ * `Card` (see [`pushCard`](Self::push_card)).
182
+ */
183
+ insertCard(index: number, card: Card): void;
184
+ /**
185
+ * Build a fresh `Card` from a kind and a flat field map — the ergonomic
186
+ * constructor for `pushCard` / `insertCard`. `fields` is an optional
187
+ * `Record<string, unknown>` (each entry becomes a card field, in
188
+ * insertion order); `body` defaults to `""`. Kind validity is checked by
189
+ * `pushCard` / `insertCard`, not here.
190
+ */
191
+ static makeCard(kind: string, fields?: Record<string, unknown>, body?: string): Card;
192
+ /**
193
+ * Move the card at `from` to position `to`. `from == to` is a no-op.
194
+ */
195
+ moveCard(from: number, to: number): void;
196
+ /**
197
+ * Append a card to the end of the card list. Accepts a `Card` (the shape
198
+ * returned by `cards` / `removeCard` / `quill.seedCard`); build a fresh
199
+ * one with [`Document.makeCard`](Document::make_card). Throws if
200
+ * `card.kind` is not a valid kind name.
201
+ */
202
+ pushCard(card: Card): void;
203
+ /**
204
+ * The canonical `$quill` reference grammar as author-facing text. Single
205
+ * source of truth (CLI, Python, MCP): drive schema `describe` and
206
+ * validation messages from this instead of re-stating the rule — it
207
+ * matches the `hint` on `parse::invalid_quill_reference`. Cache it; the
208
+ * value never changes.
209
+ */
210
+ static quillRefHint(): string;
211
+ removeCard(index: number): Card | undefined;
212
+ /**
213
+ * Remove the `$ext` map from the composable card at `index` *entirely*,
214
+ * returning the previous map or `undefined`. Throws if out of range.
215
+ * Prefer `removeCardExtNamespace` to clear only one consumer's slot.
216
+ */
217
+ removeCardExt(index: number): Record<string, unknown> | undefined;
218
+ /**
219
+ * Remove `namespace` from the composable card's `$ext` map, returning the
220
+ * value stored there or `undefined`; clears `$ext` entirely once empty.
221
+ * The card-indexed twin of `removeExtNamespace`. Throws if out of range.
222
+ */
223
+ removeCardExtNamespace(index: number, namespace: string): any;
224
+ /**
225
+ * Remove a field on the card at `index`. Returns the removed value or
226
+ * `undefined`. Throws if `index` is out of range or `name` is invalid.
227
+ */
228
+ removeCardField(index: number, name: string): any;
229
+ /**
230
+ * Remove the `$ext` map from the main card *entirely*, returning the
231
+ * previous map or `undefined`. This is a blunt escape hatch that discards
232
+ * every namespace at once — prefer `removeExtNamespace` to clear only your
233
+ * own slot while leaving sibling consumers' state intact.
234
+ */
235
+ removeExt(): Record<string, unknown> | undefined;
236
+ /**
237
+ * Remove `namespace` from the main card's `$ext` map, returning the value
238
+ * stored there or `undefined`. This is the recommended way to clear `$ext`
239
+ * state: sibling namespaces survive, and when the last namespace is removed
240
+ * the `$ext` entry is dropped entirely (not left as `$ext: {}`).
241
+ */
242
+ removeExtNamespace(namespace: string): any;
243
+ /**
244
+ * Remove a payload field on the main card, returning the removed value or
245
+ * `undefined`. Throws if `name` does not match `[a-z_][a-z0-9_]*`.
246
+ */
247
+ removeField(name: string): any;
248
+ replaceBody(body: string): void;
249
+ /**
250
+ * Read the `schema` version tag from a raw storage DTO string without a
251
+ * full parse, or `undefined`. Returns unknown future versions as-is —
252
+ * useful to distinguish "build too old" from "payload corrupt" when
253
+ * `fromJson` throws.
254
+ */
255
+ static schemaVersionOf(json: string): string | undefined;
256
+ /**
257
+ * Replace the `$ext` map on the composable card at `index`. Throws if out
258
+ * of range or `value` is not a plain object. Named to mirror `setExt` on
259
+ * the main card; `setCardExtNamespace` is the sibling-safe alternative.
260
+ */
261
+ setCardExt(index: number, value: any): void;
262
+ /**
263
+ * Merge `value` into the composable card's `$ext` map under `namespace`,
264
+ * preserving sibling namespaces. The card-indexed twin of `setExtNamespace`.
265
+ * Throws if out of range or `value` cannot be serialized.
266
+ */
267
+ setCardExtNamespace(index: number, namespace: string, value: any): void;
268
+ /**
269
+ * Replace the kind of the card at `index`. Payload and body are untouched;
270
+ * schema-aware migration is the caller's responsibility.
271
+ * Throws if `index` is out of range or `newKind` is invalid.
272
+ */
273
+ setCardKind(index: number, new_kind: string): void;
274
+ /**
275
+ * Replace the opaque `$ext` map on the main card. `value` must be a plain
276
+ * object; throws otherwise. `$ext` carries out-of-band consumer state and
277
+ * never reaches the rendered output. Pass `{}` to record an explicit
278
+ * empty `$ext`.
279
+ */
280
+ setExt(value: any): void;
281
+ /**
282
+ * Merge `value` into the main card's `$ext` map under `namespace`, creating
283
+ * the map when absent and replacing any existing value at that key. Sibling
284
+ * namespaces are preserved, so independent consumers (`$ext.presentation`,
285
+ * `$ext.agent`, …) don't clobber each other.
286
+ */
287
+ setExtNamespace(namespace: string, value: any): void;
288
+ /**
289
+ * Update a payload field on the main card. Clears any existing `!fill` marker.
290
+ *
291
+ * Throws if `name` does not match `[a-z_][a-z0-9_]*`.
292
+ */
293
+ setField(name: string, value: any): void;
294
+ /**
295
+ * Update a payload field on the main card and mark it as `!fill`.
296
+ * Throws on invalid name (see [`setField`](Document::set_field)).
297
+ */
298
+ setFill(name: string, value: any): void;
299
+ /**
300
+ * Replace the QUILL reference string. Throws if `ref_str` is invalid.
301
+ */
302
+ setQuillRef(ref_str: string): void;
303
+ /**
304
+ * Serialize this document to a versioned storage DTO string.
305
+ *
306
+ * Prefer this over `toMarkdown` for persistence across restarts or crate
307
+ * upgrades — the wire format is frozen per `schema` version. Parse-time
308
+ * `warnings` are excluded from the DTO.
309
+ *
310
+ * Output is **byte-deterministic** within a `schema` version: equal
311
+ * documents produce byte-equal output, safe for content-hash use cases.
312
+ */
313
+ toJson(): string;
314
+ /**
315
+ * Emit canonical Quillmark Markdown. Round-trip safe: re-parsing the
316
+ * result produces a `Document` equal to `self` by value and by type.
317
+ */
318
+ toMarkdown(): string;
319
+ /**
320
+ * Like [`fromJson`](Document::from_json) but returns `undefined` instead
321
+ * of throwing when `json` is not a valid storage DTO — use to
322
+ * discriminate format without exceptions as control flow.
323
+ * `undefined` means "not a storage DTO"; `fromMarkdown` still throws on
324
+ * genuinely malformed markdown.
325
+ */
326
+ static tryFromJson(json: string): Document | undefined;
327
+ /**
328
+ * Replace the body of the card at `index`. Throws if out of range.
329
+ */
330
+ updateCardBody(index: number, body: string): void;
331
+ /**
332
+ * Update a field on the card at `index`.
333
+ * Throws if `index` is out of range, `name` is reserved or invalid.
334
+ */
335
+ updateCardField(index: number, name: string, value: any): void;
336
+ /**
337
+ * Number of composable cards (excludes the main card). O(1).
338
+ */
339
+ readonly cardCount: number;
340
+ readonly cards: Card[];
341
+ /**
342
+ * The document's main (entry) card. Allocates and serializes on each
343
+ * call — cache locally if read in a hot loop.
344
+ */
345
+ readonly main: Card;
346
+ readonly quillRef: string;
347
+ readonly warnings: Diagnostic[];
348
+ }
349
+
350
+ export class Quill {
351
+ private constructor();
352
+ free(): void;
353
+ [Symbol.dispose](): void;
354
+ /**
355
+ * Build a quill from a file tree. Pure — no backend, no engine; the
356
+ * declared backend is resolved later, at render time.
357
+ *
358
+ * Accepts either a `Map<string, Uint8Array>` or a plain object
359
+ * (`Record<string, Uint8Array>`). Plain objects are walked via
360
+ * `Object.entries` at the boundary; the Rust side sees a single
361
+ * canonical shape.
362
+ */
363
+ static fromTree(tree: Map<string, Uint8Array>): Quill;
364
+ /**
365
+ * Seed a starter composable `Card` of the given kind (carries `$kind`),
366
+ * committing its fields' `example:` values and leaving every other field
367
+ * absent. Returns `undefined` if `cardKind` is not declared in this
368
+ * quill's schema, else a `Card` that feeds straight into
369
+ * `Document.pushCard` / `insertCard`.
370
+ */
371
+ seedCard(card_kind: string): Card | undefined;
372
+ /**
373
+ * Seed a starter `Document` from the schema — the main card plus one
374
+ * instance of each composable card kind, each committing its fields'
375
+ * `example:` values and leaving every other field absent (interpolated at
376
+ * render: `default:`, else type-empty zero). Illustration-first: a field
377
+ * with both an `example` and a `default` renders its example. See
378
+ * `prose/canon/SCHEMAS.md` § "Document seeding".
379
+ */
380
+ seedDocument(): Document;
381
+ /**
382
+ * Seed a starter main `Card` (carries `$quill`) from the schema — the
383
+ * `$kind: main` card of [`seedDocument`](Self::seed_document) in
384
+ * isolation, committing each field's `example:` value. Returns the same
385
+ * `Card` shape as the `Document.main` getter.
386
+ */
387
+ seedMain(): Card;
388
+ /**
389
+ * Flatten this quill back into its canonical file tree — the inverse of
390
+ * [`fromTree`](Self::from_tree). Round-trips: `Quill.fromTree(q.toTree())`
391
+ * reproduces an equivalent quill.
392
+ *
393
+ * This is how a quill crosses a WASM linear-memory boundary as data: a
394
+ * `Quill` built in one build (e.g. the Typst-less `@quillmark/wasm/core`)
395
+ * cannot be passed to an engine in another (separate linear memories), so
396
+ * `@quillmark/wasm/runtime` re-feeds this tree to the backend build's
397
+ * `Quill.fromTree` on demand. Keys are `"/"`-joined relative paths,
398
+ * matching what `fromTree` accepts.
399
+ */
400
+ toTree(): Map<string, Uint8Array>;
401
+ /**
402
+ * Validate `doc` against this quill's schema, returning every diagnostic
403
+ * (an empty array when the document is valid).
404
+ *
405
+ * Forwards the canonical `validation::*` diagnostics — same `code`,
406
+ * `path`, and `hint` the engine emits — including the non-fatal
407
+ * `validation::field_absent` completeness signal that `render` demotes.
408
+ * Field values, defaults, and order are not part of this surface: read
409
+ * them from the `Document` payload and `Quill.schema` (fields carry
410
+ * `ui.order`).
411
+ */
412
+ validate(doc: Document): Diagnostic[];
413
+ /**
414
+ * The *declared* backend identifier (`config.backend`, e.g. `"typst"`).
415
+ * Intent, not a resolved capability — capability (`supportedFormats` /
416
+ * `supportsCanvas`) is read from the engine.
417
+ */
418
+ readonly backendId: string;
419
+ readonly blueprint: string;
420
+ /**
421
+ * Identity snapshot of the `quill:` section of `Quill.yaml` plus any extra
422
+ * `quill:` keys. Pure config — the backend's output formats are a
423
+ * resolved-backend capability read from the engine
424
+ * (`Quillmark.supportedFormats`), not part of this snapshot.
425
+ */
426
+ readonly metadata: QuillMetadata;
427
+ /**
428
+ * Document schema for the quill: the user-fillable fields plus their
429
+ * `ui` hints (group / order / showWhen). The single field-metadata
430
+ * surface — drives form editors and LLM/MCP consumers alike. Returns the
431
+ * `QuillSchema` shape.
432
+ */
433
+ readonly schema: QuillSchema;
434
+ }
435
+
436
+ /**
437
+ * Initialize the WASM module with panic hooks for better error messages
438
+ */
439
+ export function init(): void;
package/core/wasm.js ADDED
@@ -0,0 +1,9 @@
1
+ /* @ts-self-types="./wasm.d.ts" */
2
+ import * as wasm from "./wasm_bg.wasm";
3
+ import { __wbg_set_wasm } from "./wasm_bg.js";
4
+
5
+ __wbg_set_wasm(wasm);
6
+ wasm.__wbindgen_start();
7
+ export {
8
+ Document, Quill, init
9
+ } from "./wasm_bg.js";