@canvist/headless 0.0.0 → 0.2.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.
Files changed (51) hide show
  1. package/dist/calls.d.ts +15 -0
  2. package/dist/calls.js +20 -0
  3. package/dist/create.d.ts +17 -0
  4. package/dist/create.js +29 -0
  5. package/dist/engine.d.ts +125 -0
  6. package/dist/engine.js +176 -0
  7. package/dist/errors.d.ts +13 -0
  8. package/dist/errors.js +5 -0
  9. package/dist/extensions.generated.d.ts +1022 -0
  10. package/dist/extensions.generated.js +744 -0
  11. package/dist/extras.generated.d.ts +5803 -0
  12. package/dist/extras.generated.js +2600 -0
  13. package/dist/full.d.ts +21 -0
  14. package/dist/full.js +63 -0
  15. package/dist/gemoji.generated.d.ts +29 -0
  16. package/dist/gemoji.generated.js +30 -0
  17. package/dist/load.d.ts +21 -0
  18. package/dist/load.js +41 -0
  19. package/dist/mod.d.ts +25 -0
  20. package/dist/mod.js +24 -0
  21. package/dist/native.d.ts +115 -0
  22. package/dist/native.js +235 -0
  23. package/dist/scene-types.d.ts +223 -0
  24. package/dist/scene-types.js +1 -0
  25. package/dist/scene.d.ts +105 -0
  26. package/dist/scene.js +153 -0
  27. package/dist/ssr.d.ts +66 -0
  28. package/dist/ssr.js +98 -0
  29. package/dist/types.d.ts +232 -0
  30. package/dist/types.js +1 -0
  31. package/package.json +90 -1
  32. package/readme.md +96 -0
  33. package/wasm/canvist_headless_wasm.d.ts +216 -0
  34. package/wasm/canvist_headless_wasm.js +910 -0
  35. package/wasm/canvist_headless_wasm_bg.wasm +0 -0
  36. package/wasm/canvist_headless_wasm_bg.wasm.d.ts +44 -0
  37. package/wasm-full/canvist_headless_full.d.ts +223 -0
  38. package/wasm-full/canvist_headless_full.js +923 -0
  39. package/wasm-full/canvist_headless_full_bg.wasm +0 -0
  40. package/wasm-full/canvist_headless_full_bg.wasm.d.ts +45 -0
  41. package/wasm-scene/canvist_headless_scene.d.ts +332 -0
  42. package/wasm-scene/canvist_headless_scene.js +1231 -0
  43. package/wasm-scene/canvist_headless_scene_bg.wasm +0 -0
  44. package/wasm-scene/canvist_headless_scene_bg.wasm.d.ts +66 -0
  45. package/wasm-ssr/canvist_headless_ssr.d.ts +250 -0
  46. package/wasm-ssr/canvist_headless_ssr.js +1025 -0
  47. package/wasm-ssr/canvist_headless_ssr_bg.wasm +0 -0
  48. package/wasm-ssr/canvist_headless_ssr_bg.wasm.d.ts +50 -0
  49. package/CHANGELOG.md +0 -3
  50. package/LICENSE +0 -24
  51. package/README.md +0 -3
package/readme.md ADDED
@@ -0,0 +1,96 @@
1
+ <p align="center">
2
+ <a href="https://github.com/canvist/canvist">
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/canvist/canvist/main/assets/brand/vector/lockup-dark.svg">
5
+ <img width="220" src="https://raw.githubusercontent.com/canvist/canvist/main/assets/brand/vector/lockup.svg" alt="canvist" />
6
+ </picture>
7
+ </a>
8
+ </p>
9
+
10
+ <p align="center">
11
+ <a href="https://github.com/canvist/canvist/blob/main/docs/src/quick-start/server-typescript.md"><strong>Quick start</strong></a> ·
12
+ <a href="https://github.com/canvist/canvist/blob/main/docs/src/readme.md"><strong>Docs</strong></a> ·
13
+ <a href="https://github.com/canvist/canvist/blob/main/docs/src/reference/contributing.md"><strong>Contributing</strong></a> ·
14
+ <a href="https://github.com/canvist/canvist"><strong>canvist</strong></a>
15
+ </p>
16
+
17
+ <p align="center">
18
+ <a href="https://www.npmjs.com/package/@canvist/headless"><img src="https://img.shields.io/npm/v/%40canvist%2Fheadless?color=3B2CF5" alt="npm version" /></a>
19
+ <a href="https://github.com/canvist/canvist/actions/workflows/headless-js.yml"><img src="https://github.com/canvist/canvist/actions/workflows/headless-js.yml/badge.svg?branch=main" alt="headless-js status" /></a>
20
+ <a href="https://unlicense.org"><img src="https://img.shields.io/badge/license-Unlicense-3B2CF5" alt="Unlicense" /></a>
21
+ </p>
22
+
23
+ # @canvist/headless
24
+
25
+ canvist's document model and editing engine for JavaScript with no DOM: Node, Deno, Bun, and Workers. Convert between ProseMirror/TipTap JSON, HTML, Markdown, and text, run typed editing commands, and serve Yjs collaboration from the same Rust core the editor uses, compiled to WebAssembly.
26
+
27
+ ```sh
28
+ npm install @canvist/headless
29
+ ```
30
+
31
+ ```ts
32
+ import { createEngine } from "@canvist/headless";
33
+
34
+ const engine = await createEngine(); // TipTap's StarterKit
35
+ const doc = engine.parse("markdown", "Hello world");
36
+
37
+ doc.select({ path: [0], offset: 6 }, { path: [0], offset: 11 });
38
+ doc.commands.toggleBold();
39
+ doc.export("html"); // "<p>Hello <strong>world</strong></p>"
40
+ ```
41
+
42
+ ## Types follow your extensions
43
+
44
+ A document only offers the commands, queries, blocks, and marks of the extensions you registered:
45
+
46
+ ```ts
47
+ import { bold, createEngine, heading } from "@canvist/headless";
48
+
49
+ const engine = await createEngine([bold, heading]);
50
+ const doc = engine.create();
51
+
52
+ doc.commands.setHeading({ level: 2 }); // levels are 1 | 2 | 3 | 4 | 5 | 6
53
+ doc.commands.toggleItalic(); // type error: italic is not registered
54
+ doc.commands.setHeading({ level: 7 }); // type error
55
+ ```
56
+
57
+ ## Every other extension
58
+
59
+ `@canvist/headless` compiles in TipTap's StarterKit. Every other extension canvist ships, from highlights and text styles to mentions, emoji, and media, is in `@canvist/headless/full`: a larger WebAssembly module with the same API.
60
+
61
+ ```ts
62
+ import { createEngine, highlight, starterKit } from "@canvist/headless/full";
63
+
64
+ const engine = await createEngine([...starterKit, highlight]);
65
+ const doc = engine.parse("markdown", "Hello world");
66
+ doc.selectAll();
67
+ doc.commands.toggleHighlight();
68
+ doc.export("html"); // "<p><mark>Hello world</mark></p>"
69
+ ```
70
+
71
+ ## What else it does
72
+
73
+ - **Positions:** `{ path, offset }`, where `path` walks the block tree and `offset` counts UTF-16 code units, like JavaScript strings. Errors are `CanvistError`s with the same stable `code`s as the Rust and Dart packages.
74
+ - **Collaboration:** a document can be a Yjs peer and a y-websocket-compatible server endpoint (`share`, `syncStart`, `receiveSync`). [`examples/server`](./examples/server) serves `POST /convert` and a `/sync/:room` WebSocket in a few lines.
75
+ - **Server-side rendering:** `@canvist/headless/ssr` renders a document as HTML and CSS laid out exactly as `@canvist/web` paints it, so the live editor hydrates from it without moving a pixel, and as SVG for previews. It's a separate WebAssembly module too. See [Server-side rendering](../../docs/src/quick-start/ssr.md).
76
+ - **Canvas scenes:** `@canvist/headless/scene` loads canvist canvas scenes and exports SVG and PNG, for thumbnails, social cards, and designs an agent writes. It's a separate WebAssembly module, so the document entry point stays small.
77
+ - **Workers:** runtimes without a file system pass the module they imported: `createEngine(undefined, { wasm })`.
78
+
79
+ A typed command costs about 0.7 µs in Node and a collaborator's keystroke about 4.6 µs, at 10,000 paragraphs. `node bench/overhead.ts` reproduces the numbers.
80
+
81
+ <details>
82
+ <summary><strong>Development</strong></summary>
83
+
84
+ ```sh
85
+ npm ci
86
+ npm run build:wasm # the StarterKit module into wasm/, the full one into wasm-full/, the scene module into wasm-scene/, and the rendering module into wasm-ssr/
87
+ npm test # conformance and API tests in Node
88
+ deno task test # the same, plus the server example, in Deno
89
+ npm run check:types # tsc --noEmit, including the type-level tests
90
+ npm run generate # regenerate the extension descriptors
91
+ npm run build # JavaScript and declarations for npm, into dist/
92
+ ```
93
+
94
+ The tests run the shared fixtures in [`conformance/`](../../conformance), which the Rust and Dart packages run too.
95
+
96
+ </details>
@@ -0,0 +1,216 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /**
5
+ * One document and its editor.
6
+ */
7
+ export class WasmDoc {
8
+ private constructor();
9
+ free(): void;
10
+ [Symbol.dispose](): void;
11
+ /**
12
+ * Apply a v1 Yjs update; returns whether the document changed.
13
+ */
14
+ applyUpdate(update: Uint8Array): boolean;
15
+ /**
16
+ * Whether the named command would apply.
17
+ */
18
+ can(name: string, args: string): boolean;
19
+ /**
20
+ * Delete the selection.
21
+ */
22
+ deleteSelection(): boolean;
23
+ /**
24
+ * What a peer at `state_vector` is missing, as one v1 update.
25
+ */
26
+ encodeDiff(state_vector: Uint8Array): Uint8Array;
27
+ /**
28
+ * The whole shared state as one v1 update.
29
+ */
30
+ encodeState(): Uint8Array;
31
+ /**
32
+ * The document as `format`.
33
+ */
34
+ export(format_name: string): string;
35
+ /**
36
+ * This peer's changes since the last call, as y-sync update messages.
37
+ */
38
+ flushSync(): Uint8Array[];
39
+ /**
40
+ * Replace the selection with `text`, without input rules.
41
+ */
42
+ insertText(text: string): boolean;
43
+ /**
44
+ * Paste `content` read as `format` over the selection.
45
+ */
46
+ paste(format_name: string, content: string): boolean;
47
+ /**
48
+ * Press a key binding such as `Enter` or `Mod-b`.
49
+ */
50
+ press(key: string): boolean;
51
+ /**
52
+ * Answer the named query, as JSON.
53
+ */
54
+ query(name: string, args: string): string;
55
+ /**
56
+ * Handle a y-sync message: returns `[reply, broadcast, changed]`, the
57
+ * messages for the sender, the messages for everyone else, and whether
58
+ * the document changed.
59
+ */
60
+ receiveSync(message: Uint8Array): [Uint8Array[], Uint8Array[], boolean];
61
+ /**
62
+ * Redo the last undone call.
63
+ */
64
+ redo(): boolean;
65
+ /**
66
+ * Run the named command with JSON arguments.
67
+ */
68
+ run(name: string, args: string): boolean;
69
+ /**
70
+ * Select the whole document.
71
+ */
72
+ selectAll(): void;
73
+ /**
74
+ * Select from the anchor to the head; offsets count UTF-16 code units.
75
+ */
76
+ select(anchor_path: Uint32Array, anchor_offset: number, head_path: Uint32Array, head_offset: number): void;
77
+ /**
78
+ * The anchor and head as JSON positions, or `null` for a block
79
+ * selection.
80
+ */
81
+ selection(): string;
82
+ /**
83
+ * Start sharing the document as yrs client `client_id`.
84
+ */
85
+ share(client_id: number): void;
86
+ /**
87
+ * The content and selection as snapshot JSON.
88
+ */
89
+ snapshot(): string;
90
+ /**
91
+ * The v1 state vector.
92
+ */
93
+ stateVector(): Uint8Array;
94
+ /**
95
+ * The y-sync message to greet a connecting client with.
96
+ */
97
+ syncStart(): Uint8Array;
98
+ /**
99
+ * Drain this peer's own v1 updates.
100
+ */
101
+ takeUpdates(): Uint8Array[];
102
+ /**
103
+ * Type `text` one character at a time, running input rules.
104
+ */
105
+ typeText(text: string): boolean;
106
+ /**
107
+ * Undo the last call that changed the document.
108
+ */
109
+ undo(): boolean;
110
+ /**
111
+ * `{ rejectedBlocks, waiting }` as JSON.
112
+ */
113
+ validate(): string;
114
+ }
115
+
116
+ /**
117
+ * A configured set of extensions that creates documents.
118
+ */
119
+ export class WasmEngine {
120
+ free(): void;
121
+ [Symbol.dispose](): void;
122
+ /**
123
+ * A document with one empty paragraph.
124
+ */
125
+ create(): WasmDoc;
126
+ /**
127
+ * Join a shared document from v1 Yjs state as yrs client `client_id`.
128
+ */
129
+ fromYjs(state: Uint8Array, client_id: number): WasmDoc;
130
+ /**
131
+ * The registered extensions' metadata as JSON.
132
+ */
133
+ metadata(): string;
134
+ /**
135
+ * An engine with the named extensions, allocating block ids as
136
+ * `client`.
137
+ */
138
+ constructor(extensions: string[], client: number);
139
+ /**
140
+ * Read `input` as `format` (`json`, `html`, `markdown`, or `text`).
141
+ */
142
+ parse(format_name: string, input: string): WasmDoc;
143
+ /**
144
+ * Recreate a document from a snapshot's JSON text.
145
+ */
146
+ restore(snapshot: string): WasmDoc;
147
+ }
148
+
149
+ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
150
+
151
+ export interface InitOutput {
152
+ readonly memory: WebAssembly.Memory;
153
+ readonly __wbg_wasmdoc_free: (a: number, b: number) => void;
154
+ readonly __wbg_wasmengine_free: (a: number, b: number) => void;
155
+ readonly wasmdoc_applyUpdate: (a: number, b: number, c: number) => [number, number, number];
156
+ readonly wasmdoc_can: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
157
+ readonly wasmdoc_deleteSelection: (a: number) => [number, number, number];
158
+ readonly wasmdoc_encodeDiff: (a: number, b: number, c: number) => [number, number, number, number];
159
+ readonly wasmdoc_encodeState: (a: number) => [number, number, number, number];
160
+ readonly wasmdoc_export: (a: number, b: number, c: number) => [number, number, number, number];
161
+ readonly wasmdoc_flushSync: (a: number) => [number, number, number];
162
+ readonly wasmdoc_insertText: (a: number, b: number, c: number) => [number, number, number];
163
+ readonly wasmdoc_paste: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
164
+ readonly wasmdoc_press: (a: number, b: number, c: number) => [number, number, number];
165
+ readonly wasmdoc_query: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number];
166
+ readonly wasmdoc_receiveSync: (a: number, b: number, c: number) => [number, number, number];
167
+ readonly wasmdoc_redo: (a: number) => [number, number, number];
168
+ readonly wasmdoc_run: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
169
+ readonly wasmdoc_select: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number];
170
+ readonly wasmdoc_selectAll: (a: number) => [number, number];
171
+ readonly wasmdoc_selection: (a: number) => [number, number];
172
+ readonly wasmdoc_share: (a: number, b: number) => [number, number];
173
+ readonly wasmdoc_snapshot: (a: number) => [number, number];
174
+ readonly wasmdoc_stateVector: (a: number) => [number, number, number, number];
175
+ readonly wasmdoc_syncStart: (a: number) => [number, number, number, number];
176
+ readonly wasmdoc_takeUpdates: (a: number) => [number, number, number];
177
+ readonly wasmdoc_typeText: (a: number, b: number, c: number) => [number, number, number];
178
+ readonly wasmdoc_undo: (a: number) => [number, number, number];
179
+ readonly wasmdoc_validate: (a: number) => [number, number, number, number];
180
+ readonly wasmengine_create: (a: number) => [number, number, number];
181
+ readonly wasmengine_fromYjs: (a: number, b: number, c: number, d: number) => [number, number, number];
182
+ readonly wasmengine_metadata: (a: number) => [number, number];
183
+ readonly wasmengine_new: (a: number, b: number, c: number) => [number, number, number];
184
+ readonly wasmengine_parse: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
185
+ readonly wasmengine_restore: (a: number, b: number, c: number) => [number, number, number];
186
+ readonly __wbindgen_malloc: (a: number, b: number) => number;
187
+ readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
188
+ readonly __wbindgen_exn_store: (a: number) => void;
189
+ readonly __externref_table_alloc: () => number;
190
+ readonly __wbindgen_externrefs: WebAssembly.Table;
191
+ readonly __externref_table_dealloc: (a: number) => void;
192
+ readonly __wbindgen_free: (a: number, b: number, c: number) => void;
193
+ readonly __wbindgen_start: () => void;
194
+ }
195
+
196
+ export type SyncInitInput = BufferSource | WebAssembly.Module;
197
+
198
+ /**
199
+ * Instantiates the given `module`, which can either be bytes or
200
+ * a precompiled `WebAssembly.Module`.
201
+ *
202
+ * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
203
+ *
204
+ * @returns {InitOutput}
205
+ */
206
+ export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
207
+
208
+ /**
209
+ * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
210
+ * for everything else, calls `WebAssembly.instantiate` directly.
211
+ *
212
+ * @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
213
+ *
214
+ * @returns {Promise<InitOutput>}
215
+ */
216
+ export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;