@quillmark/wasm 0.101.0 → 0.103.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_bg.wasm CHANGED
Binary file
@@ -11,11 +11,12 @@ export const document__readerGetContent: (a: number, b: number, c: number, d: nu
11
11
  export const document__reviseField: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
12
12
  export const document_applyChange: (a: number, b: number, c: number, d: number) => void;
13
13
  export const document_blueprintInstruction: (a: number, b: number, c: number) => void;
14
+ export const document_bodyMarkdown: (a: number, b: number, c: number) => void;
14
15
  export const document_card: (a: number, b: number, c: number) => void;
15
16
  export const document_cardCount: (a: number) => number;
16
17
  export const document_cards: (a: number, b: number) => void;
17
18
  export const document_clone: (a: number) => number;
18
- export const document_currentSchemaVersion: (a: number) => void;
19
+ export const document_currentStorageVersion: (a: number) => void;
19
20
  export const document_equals: (a: number, b: number) => number;
20
21
  export const document_formatDiagnostic: (a: number, b: number) => void;
21
22
  export const document_formatRules: (a: number) => void;
@@ -23,34 +24,33 @@ export const document_fromJson: (a: number, b: number, c: number) => void;
23
24
  export const document_fromMarkdown: (a: number, b: number, c: number) => void;
24
25
  export const document_getExt: (a: number, b: number, c: number) => void;
25
26
  export const document_getExtNamespace: (a: number, b: number, c: number, d: number, e: number) => void;
26
- export const document_getMarkdown: (a: number, b: number, c: number) => void;
27
27
  export const document_getStored: (a: number, b: number, c: number) => void;
28
28
  export const document_insertCard: (a: number, b: number, c: number, d: number) => void;
29
- export const document_install: (a: number, b: number, c: number, d: number) => void;
30
29
  export const document_isFill: (a: number, b: number, c: number) => void;
31
30
  export const document_loadJson: (a: number, b: number, c: number, d: number) => void;
32
31
  export const document_main: (a: number, b: number) => void;
33
32
  export const document_makeCard: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
34
33
  export const document_moveCard: (a: number, b: number, c: number, d: number) => void;
35
34
  export const document_new: (a: number, b: number, c: number) => void;
35
+ export const document_overwrite: (a: number, b: number, c: number, d: number) => void;
36
36
  export const document_quillRef: (a: number, b: number) => void;
37
37
  export const document_quillRefHint: (a: number) => void;
38
38
  export const document_removeCard: (a: number, b: number, c: number) => void;
39
39
  export const document_removeExt: (a: number, b: number, c: number) => void;
40
40
  export const document_removeExtNamespace: (a: number, b: number, c: number, d: number, e: number) => void;
41
41
  export const document_removeField: (a: number, b: number, c: number) => void;
42
- export const document_removeSeedNamespace: (a: number, b: number, c: number, d: number) => void;
42
+ export const document_removeSeedOverlay: (a: number, b: number, c: number, d: number) => void;
43
43
  export const document_revise: (a: number, b: number, c: number, d: number, e: number) => void;
44
- export const document_schemaVersionOf: (a: number, b: number, c: number) => void;
45
44
  export const document_seedOverlay: (a: number, b: number, c: number, d: number) => void;
46
45
  export const document_setCardKind: (a: number, b: number, c: number, d: number, e: number) => void;
47
46
  export const document_setQuillRef: (a: number, b: number, c: number, d: number) => void;
47
+ export const document_storageVersionOf: (a: number, b: number, c: number) => void;
48
48
  export const document_storeExt: (a: number, b: number, c: number, d: number) => void;
49
49
  export const document_storeExtNamespace: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
50
50
  export const document_storeField: (a: number, b: number, c: number, d: number) => void;
51
51
  export const document_storeFields: (a: number, b: number, c: number, d: number) => void;
52
52
  export const document_storeFill: (a: number, b: number, c: number, d: number) => void;
53
- export const document_storeSeedNamespace: (a: number, b: number, c: number, d: number, e: number) => void;
53
+ export const document_storeSeedOverlay: (a: number, b: number, c: number, d: number, e: number) => void;
54
54
  export const document_toJson: (a: number, b: number) => void;
55
55
  export const document_toMarkdown: (a: number, b: number) => void;
56
56
  export const document_tryFromJson: (a: number, b: number) => number;
@@ -58,7 +58,6 @@ export const document_warnings: (a: number, b: number) => void;
58
58
  export const exportMarkdown: (a: number, b: number) => void;
59
59
  export const formatDocPath: (a: number, b: number) => void;
60
60
  export const importMarkdown: (a: number, b: number, c: number) => void;
61
- export const init: () => void;
62
61
  export const mapPos: (a: number, b: number, c: number, d: number) => void;
63
62
  export const parseDocPath: (a: number, b: number, c: number) => void;
64
63
  export const quill_backendId: (a: number, b: number) => void;
@@ -75,6 +74,7 @@ export const quill_seedMain: (a: number, b: number) => void;
75
74
  export const quill_toTree: (a: number) => number;
76
75
  export const quill_validate: (a: number, b: number, c: number) => void;
77
76
  export const rebase: (a: number, b: number, c: number, d: number) => void;
77
+ export const start: () => void;
78
78
  export const __wbindgen_export: (a: number, b: number) => number;
79
79
  export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
80
80
  export const __wbindgen_export3: (a: number) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quillmark/wasm",
3
- "version": "0.101.0",
3
+ "version": "0.103.0",
4
4
  "description": "WebAssembly bindings for Quillmark, a schema-driven document engine",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -27,10 +27,13 @@
27
27
  "default": "./runtime/runtime.js"
28
28
  }
29
29
  },
30
+ "imports": {
31
+ "#quillmark-env": {
32
+ "node": "./runtime/env-node.js",
33
+ "default": "./runtime/env-web.js"
34
+ }
35
+ },
30
36
  "sideEffects": [
31
- "./core/wasm.js",
32
- "./backends/typst/wasm.js",
33
- "./backends/pdfform/wasm.js",
34
37
  "./runtime/runtime.js"
35
38
  ]
36
39
  }
@@ -0,0 +1,20 @@
1
+ // The Node half of the `#quillmark-env` seam (package.json `imports`). See
2
+ // env-web.js for why the seam is resolution-time rather than a runtime branch.
3
+ //
4
+ // Node's `fetch` rejects `file:` URLs, so the default source (a `file:` URL
5
+ // pointing at the binary beside this package) is read off disk into bytes.
6
+ // Everything else (caller-supplied bytes, a `Response`, a `WebAssembly.Module`,
7
+ // an `http:` URL) passes through to the generated glue untouched.
8
+
9
+ import { readFile } from 'node:fs/promises';
10
+ import { fileURLToPath } from 'node:url';
11
+
12
+ /**
13
+ * @param {unknown} source
14
+ * @returns {Promise<unknown> | unknown} bytes for a `file:` URL, else `source`
15
+ */
16
+ export function toModuleSource(source) {
17
+ return source instanceof URL && source.protocol === 'file:'
18
+ ? readFile(fileURLToPath(source))
19
+ : source;
20
+ }
@@ -0,0 +1,19 @@
1
+ // The browser half of the `#quillmark-env` seam (package.json `imports`): the
2
+ // wasm byte source, resolved per environment at module resolution rather than
3
+ // by sniffing globals at runtime.
4
+ //
5
+ // A pass-through here. wasm-bindgen's `--target web` glue accepts a URL and
6
+ // fetches it itself (`WebAssembly.instantiateStreaming`), the streaming path.
7
+ //
8
+ // The seam exists for the Node half, which cannot, and `node:fs` must never
9
+ // reach a browser graph. Static resolution keeps it out: no `typeof process`
10
+ // branch for a bundler to trip over, no dynamic `import('node:fs')` to warn
11
+ // about.
12
+
13
+ /**
14
+ * @param {unknown} source
15
+ * @returns {unknown} `source` unchanged
16
+ */
17
+ export function toModuleSource(source) {
18
+ return source;
19
+ }
@@ -1,29 +1,93 @@
1
1
  // @quillmark/wasm/runtime: canonical consumer API.
2
2
  //
3
- // `Quill`/`Document` are re-exported verbatim from the core build (their full
4
- // surface, no drift). Render-side types (`RenderResult`, `RenderOptions`,
5
- // `Artifact`, `OutputFormat`, `PageSize`, `PaintOptions`, `PaintResult`) are
6
- // defined HERE as the canonical, backend-neutral render contract: NOT sourced
7
- // from any one private backend build. A type-level drift guard
8
- // (`runtime.types.test-d.ts`, via `npm run typecheck`) asserts they stay
9
- // mutually assignable with the Typst backend's generated declarations. `Engine`
10
- // is the render dispatcher that hides the cross-WASM-memory seam.
11
-
12
- // CANONICAL INVARIANT: the root re-exports the core build's `Quill`/`Document`
13
- // verbatim; they are the SAME classes, never wrappers. There is exactly one
14
- // public entry point, so this is a structural fact. Replacing the re-export
15
- // with a wrapper is a breaking design change, not a refactor. See runtime.js.
3
+ // Render-side types (`RenderResult`, `RenderOptions`, `Artifact`,
4
+ // `OutputFormat`, `PageSize`, `PaintOptions`, `PaintResult`) are defined HERE as
5
+ // the canonical, backend-neutral render contract: NOT sourced from any one
6
+ // private backend build. A type-level drift guard (`runtime.types.test-d.ts`,
7
+ // via `npm run typecheck`) asserts they stay mutually assignable with the Typst
8
+ // backend's generated declarations. `Engine` is the render dispatcher that hides
9
+ // the cross-WASM-memory seam.
10
+
11
+ // CANONICAL INVARIANT: the `Quill`/`Document` `init` resolves to ARE the core
12
+ // build's classes, their full surface, never wrappers. There is exactly one
13
+ // public entry point, so this is a structural fact. Handing out a wrapper is a
14
+ // breaking design change, not a refactor. See runtime.js.
16
15
  //
17
16
  // ONE COPY PER PROCESS: two copies of this package are two WASM linear memories
18
17
  // and two `Quill`/`Document` classes. Every method taking a handle refuses one
19
18
  // belonging to another copy, with a `QuillmarkError` naming `npm ls
20
19
  // @quillmark/wasm`. Errors are the exception: `isQuillmarkError` is structural.
21
- export { Quill, Document, init } from '../core/wasm.js';
22
- // The document-free content codec, re-exported from the core build.
23
- export { importMarkdown, exportMarkdown, rebase, mapPos } from '../core/wasm.js';
24
- // The document-model path parser/serializer: route on `Diagnostic.path`
25
- // segments instead of regexing the string.
26
- export { parseDocPath, formatDocPath } from '../core/wasm.js';
20
+
21
+ // The instance types, so an annotation (`let q: Quill`) needs no await. Their
22
+ // values are `CoreSurface`'s.
23
+ export type { Quill, Document } from '../core/wasm.js';
24
+
25
+ import type {
26
+ InitInput,
27
+ Quill as CoreQuill,
28
+ Document as CoreDocument,
29
+ importMarkdown,
30
+ exportMarkdown,
31
+ rebase,
32
+ mapPos,
33
+ parseDocPath,
34
+ formatDocPath
35
+ } from '../core/wasm.js';
36
+
37
+ /**
38
+ * The core build's surface: what its WASM instance stands behind, and therefore
39
+ * what `init` resolves to. Exported nowhere statically, so awaiting is the only
40
+ * way to hold one.
41
+ *
42
+ * `Quill` and `Document` here are the classes, statics included
43
+ * (`Quill.fromTree`, `Document.fromMarkdown`), not the instance types above.
44
+ * Each member carries the core build's own declaration, docs and all.
45
+ */
46
+ export interface CoreSurface {
47
+ Quill: typeof CoreQuill;
48
+ Document: typeof CoreDocument;
49
+ importMarkdown: typeof importMarkdown;
50
+ exportMarkdown: typeof exportMarkdown;
51
+ rebase: typeof rebase;
52
+ mapPos: typeof mapPos;
53
+ parseDocPath: typeof parseDocPath;
54
+ formatDocPath: typeof formatDocPath;
55
+ }
56
+
57
+ /**
58
+ * Instantiate the core WASM build and resolve to its surface.
59
+ *
60
+ * ```ts
61
+ * import { init } from '@quillmark/wasm';
62
+ * const { Quill, Document } = await init();
63
+ * ```
64
+ *
65
+ * The builds are `--target web`: classes export synchronously, the instance
66
+ * behind them arrives here. Identical in every environment: the binary is
67
+ * fetched and streamed in a browser, read off disk under Node, and the call
68
+ * site is the same line.
69
+ *
70
+ * THE ONLY DOOR to `Quill`, `Document` and the free functions, so the pre-init
71
+ * mistake is not expressible. Destructure at each entry point (route loader,
72
+ * hydration path, worker) rather than threading one result around: the gate is
73
+ * memoized and concurrency-safe, so every await after the first is free. A
74
+ * failed init clears the memo, so a retry is possible. Per realm: a Worker
75
+ * loads and initializes its own copy.
76
+ *
77
+ * Both failure codes REJECT, so one `catch` covers the gate. Delivery follows
78
+ * the function kind across this surface: a sync verb throws, a
79
+ * promise-returning verb rejects, and nothing does both.
80
+ *
81
+ * Backends are NOT initialized here. `Engine` instantiates a backend inside its
82
+ * lazy load, on first render against it.
83
+ *
84
+ * @param source override the binary's source (bytes, a `Response`, a
85
+ * `WebAssembly.Module`, a URL) for hosts that route assets themselves or
86
+ * embed the binary. Pass it on the FIRST call; a later call passing a
87
+ * different source rejects with `runtime::init_conflict` rather than silently
88
+ * ignoring it. Passing the same value again is fine.
89
+ */
90
+ export declare function init(source?: InitInput): Promise<CoreSurface>;
27
91
 
28
92
  import type { CardAddr } from '../core/wasm.js';
29
93
 
@@ -55,7 +119,7 @@ export type {
55
119
  } from '../core/wasm.js';
56
120
 
57
121
  // Content edit vocabulary: the op-grained content model `Document`'s methods
58
- // speak (`applyChange(addr, bundle)`, `install(addr, rt)`, `revise(…) => Delta`).
122
+ // speak (`applyChange(addr, bundle)`, `overwrite(addr, rt)`, `revise(…) => Delta`).
59
123
  // Declared in the core build; re-exported here so the single public entry point
60
124
  // names every type its own re-exported surface already references: `Card.body`
61
125
  // is a `Content`, `PayloadItem.nestedFills` a `PathStep[][]`, `CardInput.body` a
@@ -411,7 +475,7 @@ export interface PaintResult {
411
475
 
412
476
  /**
413
477
  * Canonical contract every backend build must satisfy. Output of
414
- * {@link LiveSession.apply}: `dirtyPages` lists the pages whose rendered
478
+ * {@link LiveSession.update}: `dirtyPages` lists the pages whose rendered
415
479
  * content differs from the previous compile, including added pages; removed
416
480
  * pages are implied by `pageCount`. Repaint `dirty ∩ visible`.
417
481
  */
@@ -463,7 +527,7 @@ export declare class Engine {
463
527
  render(quill: Quill, doc: Document, options?: RenderOptions): Promise<RenderResult>;
464
528
 
465
529
  /**
466
- * Open a live render session (canvas preview / per-page paint / `apply`).
530
+ * Open a live render session (canvas preview / per-page paint / `update`).
467
531
  * The `quill` and `doc` handles are read synchronously before the first
468
532
  * await, so the caller may `free()` them as soon as this call returns; the
469
533
  * caller owns the returned session and must `.free()` it.
@@ -524,10 +588,10 @@ export declare class LiveSession {
524
588
  * Recompile the session against `doc`: the edit verb of a live preview.
525
589
  * Transactional: on throw every read (`render`, `paint`, `pageSize`,
526
590
  * `regions`) keeps serving the last-good compile, and the session recovers
527
- * on the next successful `apply`. On success reads serve the new compile;
591
+ * on the next successful `update`. On success reads serve the new compile;
528
592
  * repaint `dirtyPages ∩ visible`.
529
593
  */
530
- apply(doc: Document): ChangeSet;
594
+ update(doc: Document): ChangeSet;
531
595
  render(options?: RenderOptions): RenderResult;
532
596
  /**
533
597
  * Schema-field geometry for this compiled session, keyed on the canonical
@@ -642,7 +706,7 @@ declare module '../core/wasm.js' {
642
706
  /**
643
707
  * A `Document` bound to its `Quill` for typed writes: the schema-bound writer,
644
708
  * constructed via {@link Quill.writer}. Speaks names, values, and markdown. Bare
645
- * `set` / `setAll` / `setBody` / `reviseField` / `addCard` / `card(i).set`
709
+ * `set` / `setAll` / `reviseBody` / `reviseField` / `addCard` / `card(i).set`
646
710
  * instead of threading the `quill` handle through the underscored ABI. Holds both
647
711
  * handles by reference and owns neither: nothing to `free()`.
648
712
  *
@@ -669,11 +733,12 @@ export declare class DocumentWriter {
669
733
  */
670
734
  setAll(fields: Record<string, unknown>): void;
671
735
  /**
672
- * Set the main body from markdown (edit semantics: anchors rebase), discarding
673
- * the delta, the receipt-free body write. Use `doc.revise({}, md)` for the
674
- * `Delta` receipt.
736
+ * Revise the main body from markdown (edit semantics: anchors rebase),
737
+ * returning the text `Delta`. The content lane's `revise` reached through the
738
+ * writer: a body carries no field schema to type against, so the receipt is
739
+ * the content lane's.
675
740
  */
676
- setBody(markdown: string): void;
741
+ reviseBody(markdown: string): Delta;
677
742
  /**
678
743
  * Revise the content main-card field `name` from authored text: typed *and*
679
744
  * anchor-preserving. Surviving anchors rebase, then the diffed result is
@@ -725,8 +790,8 @@ export declare class CardWriter {
725
790
  readonly kind: string;
726
791
  set(name: string, value: unknown): void;
727
792
  setAll(fields: Record<string, unknown>): void;
728
- /** Set this card's body from markdown (edit semantics), discarding the delta. */
729
- setBody(markdown: string): void;
793
+ /** Revise this card's body from markdown (edit semantics), returning the text `Delta`. */
794
+ reviseBody(markdown: string): Delta;
730
795
  /**
731
796
  * Revise the content field `name` on this card from authored text: typed *and*
732
797
  * anchor-preserving; the card twin of {@link DocumentWriter.reviseField},
@@ -747,12 +812,12 @@ export declare class CardWriter {
747
812
  * The schema authority is the point: unlike the quill-free transport `Document.getStored`,
748
813
  * a name the schema does not declare throws `UnknownField` (a typo) rather than
749
814
  * reading back `undefined`, and a content field holding a value that does not
750
- * decode throws `FieldRichtextDecode`. A field's markdown lives here, not on the
751
- * body-only `Document.getMarkdown`. The body read stays quill-free (a body's type
815
+ * decode throws `FieldDecode`. A field's markdown lives here, not on the
816
+ * body-only `Document.bodyMarkdown`. The body read stays quill-free (a body's type
752
817
  * is a format fact) and never throws.
753
818
  *
754
819
  * `getContent` is the same read at the other end of the codec, returning the
755
- * corpus rather than the projection. It binds the quill for the same reason
820
+ * `Content` rather than the projection. It binds the quill for the same reason
756
821
  * `get` does: a `richtext` string is markdown and a `plaintext` string is
757
822
  * literal text, so the same stored bytes decode two ways and only the declared
758
823
  * type says which.
@@ -766,23 +831,23 @@ export declare class DocumentReader {
766
831
  * to markdown, every other type verbatim. A bare string is `Addr` shorthand for
767
832
  * `{ field }`; an absent `addr.field` reads the body markdown. `undefined` for
768
833
  * an absent field; throws `UnknownField` for a name the schema does not declare,
769
- * `FieldRichtextDecode` for a richtext field holding an undecodable value, and
834
+ * `FieldDecode` for a richtext field holding an undecodable value, and
770
835
  * `IndexOutOfRange` for a bad `addr.card`.
771
836
  */
772
837
  get(addr: Addr | string): unknown;
773
838
  /**
774
- * Read the content field at `addr` as its canonical `Content` corpus: the
775
- * corpus twin of {@link get}, which projects. Decodes through the codec the
839
+ * Read the content field at `addr` as its canonical `Content`: the
840
+ * `Content` twin of {@link get}, which projects. Decodes through the codec the
776
841
  * declared type names (`richtext` as markdown, `plaintext` as literal text),
777
- * so a committed field and a parsed one read back the same corpus and the
842
+ * so a committed field and a parsed one read back the same `Content` and the
778
843
  * storage form stops being the caller's business. An absent `addr.field`
779
- * reads the body corpus. `undefined` for an absent field; throws
844
+ * reads the body `Content`. `undefined` for an absent field; throws
780
845
  * `UnknownField`, `FieldNotContent` for a declared type that is not a content
781
- * leaf, `FieldRichtextDecode` for an undecodable value, and `IndexOutOfRange`.
846
+ * leaf, `FieldDecode` for an undecodable value, and `IndexOutOfRange`.
782
847
  */
783
848
  getContent(addr: Addr | string): Content | undefined;
784
849
  /** The main body's markdown: the quill-free body read. Equals `get({})`. */
785
- getBody(): string;
850
+ bodyMarkdown(): string;
786
851
  /**
787
852
  * A {@link CardReader} for the composable card at `index`. Index validity is
788
853
  * checked lazily at read time, so an out-of-range index does not throw here.
@@ -815,9 +880,9 @@ export declare class CardReader {
815
880
  get(name: string): unknown;
816
881
  /**
817
882
  * Read the content field `name` on this card as its canonical `Content`
818
- * corpus: the card twin of {@link DocumentReader.getContent}.
883
+ * `Content`: the card twin of {@link DocumentReader.getContent}.
819
884
  */
820
885
  getContent(name: string): Content | undefined;
821
- /** This card's body markdown: the card twin of {@link DocumentReader.getBody}. */
822
- getBody(): string;
886
+ /** This card's body markdown: the card twin of {@link DocumentReader.bodyMarkdown}. */
887
+ bodyMarkdown(): string;
823
888
  }