@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.
- package/dist/calls.d.ts +15 -0
- package/dist/calls.js +20 -0
- package/dist/create.d.ts +17 -0
- package/dist/create.js +29 -0
- package/dist/engine.d.ts +125 -0
- package/dist/engine.js +176 -0
- package/dist/errors.d.ts +13 -0
- package/dist/errors.js +5 -0
- package/dist/extensions.generated.d.ts +1022 -0
- package/dist/extensions.generated.js +744 -0
- package/dist/extras.generated.d.ts +5803 -0
- package/dist/extras.generated.js +2600 -0
- package/dist/full.d.ts +21 -0
- package/dist/full.js +63 -0
- package/dist/gemoji.generated.d.ts +29 -0
- package/dist/gemoji.generated.js +30 -0
- package/dist/load.d.ts +21 -0
- package/dist/load.js +41 -0
- package/dist/mod.d.ts +25 -0
- package/dist/mod.js +24 -0
- package/dist/native.d.ts +115 -0
- package/dist/native.js +235 -0
- package/dist/scene-types.d.ts +223 -0
- package/dist/scene-types.js +1 -0
- package/dist/scene.d.ts +105 -0
- package/dist/scene.js +153 -0
- package/dist/ssr.d.ts +66 -0
- package/dist/ssr.js +98 -0
- package/dist/types.d.ts +232 -0
- package/dist/types.js +1 -0
- package/package.json +90 -1
- package/readme.md +96 -0
- package/wasm/canvist_headless_wasm.d.ts +216 -0
- package/wasm/canvist_headless_wasm.js +910 -0
- package/wasm/canvist_headless_wasm_bg.wasm +0 -0
- package/wasm/canvist_headless_wasm_bg.wasm.d.ts +44 -0
- package/wasm-full/canvist_headless_full.d.ts +223 -0
- package/wasm-full/canvist_headless_full.js +923 -0
- package/wasm-full/canvist_headless_full_bg.wasm +0 -0
- package/wasm-full/canvist_headless_full_bg.wasm.d.ts +45 -0
- package/wasm-scene/canvist_headless_scene.d.ts +332 -0
- package/wasm-scene/canvist_headless_scene.js +1231 -0
- package/wasm-scene/canvist_headless_scene_bg.wasm +0 -0
- package/wasm-scene/canvist_headless_scene_bg.wasm.d.ts +66 -0
- package/wasm-ssr/canvist_headless_ssr.d.ts +250 -0
- package/wasm-ssr/canvist_headless_ssr.js +1025 -0
- package/wasm-ssr/canvist_headless_ssr_bg.wasm +0 -0
- package/wasm-ssr/canvist_headless_ssr_bg.wasm.d.ts +50 -0
- package/CHANGELOG.md +0 -3
- package/LICENSE +0 -24
- 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>;
|