@forevka/wordcanvas 0.7.1 → 0.7.2
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-lib/assets/{worker-D8rUOKfg.js → worker-4HYrkNrG.js} +10873 -10730
- package/dist-lib/assets/worker-CJpwUzKh.js +2403 -0
- package/dist-lib/blockFactory-B_CLnkUh.js +106 -0
- package/dist-lib/browser-p_rkUcqE.js +1339 -0
- package/dist-lib/builder.js +14 -13
- package/dist-lib/editorApp-mTD0YNv-.js +9863 -0
- package/dist-lib/export.js +4507 -4456
- package/dist-lib/generate-toc.js +5 -5
- package/dist-lib/import.js +2 -2
- package/dist-lib/measure.js +2 -2
- package/dist-lib/{measureHost-CMiJKdlk.js → measureHost-B2aKX7lF.js} +1 -1
- package/dist-lib/metrics-BUMIC9Mv.js +164 -0
- package/dist-lib/pipeline-DD0nxAYM.js +1850 -0
- package/dist-lib/recalc-docx.js +2 -2
- package/dist-lib/recalcToc-CFCGCgij.js +3985 -0
- package/dist-lib/styleProps-DhqDEfvc.js +149 -0
- package/dist-lib/stylesheet-B6oczA-L.js +141 -0
- package/dist-lib/{toc-B6VpkJge.js → toc-Dj57zdz-.js} +5 -5
- package/dist-lib/{webmcp-6WxRNKCc.js → webmcp-CXghUon_.js} +2 -2
- package/dist-lib/{wordcanvas-CFqpDK0k.js → wordcanvas-D5DI9ZR1.js} +49 -23
- package/dist-lib/wordcanvas.js +1 -1
- package/dist-node/{chunk-22JHAERT.js → chunk-57L5XMCL.js} +235 -39
- package/dist-node/chunk-57L5XMCL.js.map +7 -0
- package/dist-node/{chunk-4PDVRJF6.js → chunk-EMY2P524.js} +32 -2
- package/dist-node/chunk-EMY2P524.js.map +7 -0
- package/dist-node/{chunk-6AJJMHKY.js → chunk-KJV7GJ3H.js} +1 -1
- package/dist-node/chunk-KJV7GJ3H.js.map +7 -0
- package/dist-node/{chunk-CDN6WU2P.js → chunk-PIMVQULL.js} +7 -1
- package/dist-node/chunk-PIMVQULL.js.map +7 -0
- package/dist-node/{chunk-BRAPV465.js → chunk-SA26UVIJ.js} +2 -2
- package/dist-node/{chunk-RNB336F3.js → chunk-T3253N22.js} +92 -14
- package/dist-node/{chunk-RNB336F3.js.map → chunk-T3253N22.js.map} +2 -2
- package/dist-node/{chunk-4ICCHZX4.js → chunk-U27EBKBG.js} +37 -1
- package/dist-node/chunk-U27EBKBG.js.map +7 -0
- package/dist-node/{engine-5FGDJD2H.js → engine-5F7DUU4W.js} +4 -4
- package/dist-node/export.js +89 -24
- package/dist-node/export.js.map +2 -2
- package/dist-node/generate-toc.js +6 -6
- package/dist-node/import.js +3 -3
- package/dist-node/measure.js +2 -2
- package/dist-node/recalc-docx.js +4 -4
- package/package.json +1 -1
- package/types/model.d.ts +46 -0
- package/types/wordcanvas.d.ts +212 -157
- package/dist-lib/assets/worker-wXuuyshQ.js +0 -2258
- package/dist-lib/blockFactory-CUI4Rqiq.js +0 -186
- package/dist-lib/browser-DkKxreJM.js +0 -1305
- package/dist-lib/editorApp-DLXMmtu5.js +0 -8023
- package/dist-lib/metrics-CkAo4zh8.js +0 -143
- package/dist-lib/pipeline-CbxmCE84.js +0 -1705
- package/dist-lib/recalcToc-g1hFKSNs.js +0 -3935
- package/dist-lib/styleProps-Db5pEkG8.js +0 -127
- package/dist-node/chunk-22JHAERT.js.map +0 -7
- package/dist-node/chunk-4ICCHZX4.js.map +0 -7
- package/dist-node/chunk-4PDVRJF6.js.map +0 -7
- package/dist-node/chunk-6AJJMHKY.js.map +0 -7
- package/dist-node/chunk-CDN6WU2P.js.map +0 -7
- /package/dist-node/{chunk-BRAPV465.js.map → chunk-SA26UVIJ.js.map} +0 -0
- /package/dist-node/{engine-5FGDJD2H.js.map → engine-5F7DUU4W.js.map} +0 -0
|
@@ -6,17 +6,17 @@ const __filename = __fileURLToPath(import.meta.url);
|
|
|
6
6
|
const __dirname = __pathDirname(__filename);
|
|
7
7
|
import {
|
|
8
8
|
runImport
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-57L5XMCL.js";
|
|
10
10
|
import {
|
|
11
11
|
el,
|
|
12
12
|
escapeText,
|
|
13
13
|
paraCoreXml,
|
|
14
14
|
runPropsXml,
|
|
15
15
|
textEl
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-EMY2P524.js";
|
|
17
17
|
import {
|
|
18
18
|
findMainDocumentPart
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-KJV7GJ3H.js";
|
|
20
20
|
import {
|
|
21
21
|
pageOfBlockMap
|
|
22
22
|
} from "./chunk-EGSAVPCC.js";
|
|
@@ -28,15 +28,15 @@ import {
|
|
|
28
28
|
} from "./chunk-5PUCGN47.js";
|
|
29
29
|
import {
|
|
30
30
|
createLayoutEngine
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-T3253N22.js";
|
|
32
32
|
import {
|
|
33
33
|
detectTocHeadings,
|
|
34
34
|
inRange,
|
|
35
35
|
parseTocInstruction,
|
|
36
36
|
textOfRuns,
|
|
37
37
|
tocEntryStyle
|
|
38
|
-
} from "./chunk-
|
|
39
|
-
import "./chunk-
|
|
38
|
+
} from "./chunk-PIMVQULL.js";
|
|
39
|
+
import "./chunk-U27EBKBG.js";
|
|
40
40
|
import "./chunk-XSRSBST2.js";
|
|
41
41
|
|
|
42
42
|
// src/recalc/generateTocDocx.ts
|
package/dist-node/import.js
CHANGED
|
@@ -6,10 +6,10 @@ const __filename = __fileURLToPath(import.meta.url);
|
|
|
6
6
|
const __dirname = __pathDirname(__filename);
|
|
7
7
|
import {
|
|
8
8
|
runImport
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-57L5XMCL.js";
|
|
10
|
+
import "./chunk-KJV7GJ3H.js";
|
|
11
11
|
import "./chunk-5PUCGN47.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-PIMVQULL.js";
|
|
13
13
|
import "./chunk-XSRSBST2.js";
|
|
14
14
|
export {
|
|
15
15
|
runImport
|
package/dist-node/measure.js
CHANGED
|
@@ -6,8 +6,8 @@ const __filename = __fileURLToPath(import.meta.url);
|
|
|
6
6
|
const __dirname = __pathDirname(__filename);
|
|
7
7
|
import {
|
|
8
8
|
installMeasureHost
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-SA26UVIJ.js";
|
|
10
|
+
import "./chunk-U27EBKBG.js";
|
|
11
11
|
import "./chunk-XSRSBST2.js";
|
|
12
12
|
export {
|
|
13
13
|
installMeasureHost
|
package/dist-node/recalc-docx.js
CHANGED
|
@@ -6,7 +6,7 @@ const __filename = __fileURLToPath(import.meta.url);
|
|
|
6
6
|
const __dirname = __pathDirname(__filename);
|
|
7
7
|
import {
|
|
8
8
|
findMainDocumentPart
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-KJV7GJ3H.js";
|
|
10
10
|
import {
|
|
11
11
|
pageOfBlockMap
|
|
12
12
|
} from "./chunk-EGSAVPCC.js";
|
|
@@ -18,9 +18,9 @@ import {
|
|
|
18
18
|
} from "./chunk-5PUCGN47.js";
|
|
19
19
|
import {
|
|
20
20
|
createLayoutEngine
|
|
21
|
-
} from "./chunk-
|
|
22
|
-
import "./chunk-
|
|
23
|
-
import "./chunk-
|
|
21
|
+
} from "./chunk-T3253N22.js";
|
|
22
|
+
import "./chunk-PIMVQULL.js";
|
|
23
|
+
import "./chunk-U27EBKBG.js";
|
|
24
24
|
import "./chunk-XSRSBST2.js";
|
|
25
25
|
|
|
26
26
|
// src/recalc/patchTocDocx.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forevka/wordcanvas",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Open-source embeddable Word-style document editor: canvas-rendered, with live collaboration, track changes & comments, and DOCX/PDF import & export. A lightweight alternative to Syncfusion, OnlyOffice, and DevExpress document editors. Self-contained, zero runtime dependencies.",
|
|
6
6
|
"license": "MIT",
|
package/types/model.d.ts
CHANGED
|
@@ -25,6 +25,9 @@ export interface CharStyle {
|
|
|
25
25
|
footnoteRef?: string | undefined;
|
|
26
26
|
/** Content-control membership (properties live in Document.sdts). */
|
|
27
27
|
sdtId?: string | undefined;
|
|
28
|
+
/** Character-style reference (w:rStyle → a type==="character" NamedStyle).
|
|
29
|
+
* Reference only — concrete formatting stays baked on the run. */
|
|
30
|
+
charStyleId?: string | undefined;
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
export interface TabStop {
|
|
@@ -120,6 +123,15 @@ export interface TableRow {
|
|
|
120
123
|
cells: TableCell[];
|
|
121
124
|
}
|
|
122
125
|
|
|
126
|
+
export interface TableCondOverrides {
|
|
127
|
+
firstRow?: boolean;
|
|
128
|
+
lastRow?: boolean;
|
|
129
|
+
firstCol?: boolean;
|
|
130
|
+
lastCol?: boolean;
|
|
131
|
+
bandRows?: boolean;
|
|
132
|
+
bandCols?: boolean;
|
|
133
|
+
}
|
|
134
|
+
|
|
123
135
|
export interface TableBlock {
|
|
124
136
|
kind: "table";
|
|
125
137
|
id: string;
|
|
@@ -127,10 +139,38 @@ export interface TableBlock {
|
|
|
127
139
|
rows: TableRow[];
|
|
128
140
|
/** Column widths as fractions of content width (sum = 1). Absent = equal. */
|
|
129
141
|
colFractions?: number[];
|
|
142
|
+
/** Table-style reference (→ Document.tableStyles); effective cell formatting is baked. */
|
|
143
|
+
styleId?: string | undefined;
|
|
144
|
+
/** Which conditional bands of the referenced style are active (w:tblLook). */
|
|
145
|
+
condOverrides?: TableCondOverrides;
|
|
130
146
|
}
|
|
131
147
|
|
|
132
148
|
export type Block = Paragraph | ImageBlock | TableBlock;
|
|
133
149
|
|
|
150
|
+
/** Conditional-format slots of a table style (OOXML w:tblStylePr types). */
|
|
151
|
+
export type TableCond =
|
|
152
|
+
| "wholeTable"
|
|
153
|
+
| "firstRow" | "lastRow" | "firstCol" | "lastCol"
|
|
154
|
+
| "band1Horz" | "band2Horz" | "band1Vert" | "band2Vert"
|
|
155
|
+
| "nwCell" | "neCell" | "swCell" | "seCell";
|
|
156
|
+
|
|
157
|
+
export interface TableCondProps {
|
|
158
|
+
char?: Partial<CharStyle>;
|
|
159
|
+
para?: Partial<ParaStyle>;
|
|
160
|
+
shading?: string;
|
|
161
|
+
borders?: CellBorders;
|
|
162
|
+
margin?: CellMargin;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export interface TableStyle {
|
|
166
|
+
id: string;
|
|
167
|
+
name: string;
|
|
168
|
+
basedOn?: string;
|
|
169
|
+
conds: Partial<Record<TableCond, TableCondProps>>;
|
|
170
|
+
rowBandSize?: number;
|
|
171
|
+
colBandSize?: number;
|
|
172
|
+
}
|
|
173
|
+
|
|
134
174
|
export type BandContainer = "header" | "footer" | "headerFirst" | "headerEven" | "footerFirst" | "footerEven";
|
|
135
175
|
|
|
136
176
|
export interface SectionProps {
|
|
@@ -152,11 +192,15 @@ export interface SectionProps {
|
|
|
152
192
|
footerEven?: Block[];
|
|
153
193
|
}
|
|
154
194
|
|
|
195
|
+
export type NamedStyleType = "paragraph" | "character";
|
|
196
|
+
|
|
155
197
|
export interface NamedStyle {
|
|
156
198
|
/** Shares the docx styleId space ("Normal", "Heading1", …). */
|
|
157
199
|
id: string;
|
|
158
200
|
/** Display name. */
|
|
159
201
|
name: string;
|
|
202
|
+
/** Paragraph vs character style. Optional; untyped styles read as "paragraph". */
|
|
203
|
+
type?: NamedStyleType;
|
|
160
204
|
basedOn?: string;
|
|
161
205
|
char: Partial<CharStyle>;
|
|
162
206
|
para: Partial<ParaStyle>;
|
|
@@ -216,6 +260,8 @@ export interface Document {
|
|
|
216
260
|
stylesheet?: Stylesheet;
|
|
217
261
|
/** List definitions keyed by id. */
|
|
218
262
|
lists?: Record<string, ListDefinition>;
|
|
263
|
+
/** Table styles keyed by id (docx styleId space). */
|
|
264
|
+
tableStyles?: Record<string, TableStyle>;
|
|
219
265
|
/** Footnote bodies keyed by ref id. */
|
|
220
266
|
footnotes?: Record<string, Paragraph[]>;
|
|
221
267
|
/** Content-control properties keyed by sdtId. */
|
package/types/wordcanvas.d.ts
CHANGED
|
@@ -1,157 +1,212 @@
|
|
|
1
|
-
// Public type surface for the @forevka/wordcanvas (WordCanvas) package.
|
|
2
|
-
// Hand-written so the published types stay small, self-contained, and stable
|
|
3
|
-
// regardless of internal refactors — no dependency on internal workspace types.
|
|
4
|
-
|
|
5
|
-
import type { Document } from "./model";
|
|
6
|
-
|
|
7
|
-
export type { Document } from "./model";
|
|
8
|
-
|
|
9
|
-
/** Caller-supplied identity, used for change attribution and presence. */
|
|
10
|
-
export interface UserInfo {
|
|
11
|
-
id: string;
|
|
12
|
-
firstName: string;
|
|
13
|
-
lastName: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/** One other collaborator currently in the document (online mode). */
|
|
17
|
-
export interface Participant {
|
|
18
|
-
siteId: string;
|
|
19
|
-
user?: UserInfo;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface WordCanvasOptions {
|
|
23
|
-
/** Element to mount the editor into. */
|
|
24
|
-
container: HTMLElement;
|
|
25
|
-
/** Backend base URL (e.g. "https://api.example.com"). Online iff provided;
|
|
26
|
-
* omit for a fully offline editor (no sync, publish, or share). */
|
|
27
|
-
backendUrl?: string;
|
|
28
|
-
/** Open this document on load (online only) — e.g. the id returned by an
|
|
29
|
-
* upload. Canonical name; `collabId` is the deprecated alias. */
|
|
30
|
-
docId?: string;
|
|
31
|
-
/** @deprecated Use `docId`. Join an existing collaboration session on load. */
|
|
32
|
-
collabId?: string;
|
|
33
|
-
/** Caller-supplied identity (attribution + presence). The embedder owns auth. */
|
|
34
|
-
user?: UserInfo;
|
|
35
|
-
/** Override how a share link is surfaced (default: a built-in dialog). */
|
|
36
|
-
onShareLink?: (url: string, docId: string) => void;
|
|
37
|
-
/** Resolve a custom (developer-defined) field's content from your backend. When
|
|
38
|
-
* set, right-clicking a custom field offers "Update Field (<name>)"; the
|
|
39
|
-
* callback receives the field's name + verbatim instruction and returns the new
|
|
40
|
-
* result to splice in (see FieldResult). */
|
|
41
|
-
resolveField?: FieldResolver;
|
|
42
|
-
/** Expose this editor to AI agents over WebMCP (https://webmcp.dev), the standard
|
|
43
|
-
* `navigator.modelContext` API. `true` registers the full tool set — read &
|
|
44
|
-
* inspect (including a layout-geometry dump for debugging rendering / text-
|
|
45
|
-
* placement issues), plus suggestions, comments, and direct edits. Pass an
|
|
46
|
-
* object to restrict capabilities or namespace the tool names. The WebMCP
|
|
47
|
-
* polyfill is lazy-loaded only when this is set, so it adds nothing for
|
|
48
|
-
* embedders that don't opt in. Connect an agent via the WebMCP browser
|
|
49
|
-
* extension / Chrome DevTools MCP. */
|
|
50
|
-
agentTools?: boolean | AgentToolsOptions;
|
|
51
|
-
/** Track first-load progress so you can show a loader while the big chunks
|
|
52
|
-
* stream. Fires for the editor JS chunk download (`phase: "bundle"`,
|
|
53
|
-
* indeterminate) and the bundled font fetch (`phase: "fonts"`, the dominant
|
|
54
|
-
* ~9 MB cost — a smooth, size-weighted bar), then once at `phase: "ready"`
|
|
55
|
-
* with `percent: 1`. Read `percent` (0..1, monotonic) to drive a progress bar. */
|
|
56
|
-
onLoadProgress?: (progress: LoadProgress) => void;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/** First-load progress (see WordCanvasOptions.onLoadProgress). */
|
|
60
|
-
export interface LoadProgress {
|
|
61
|
-
/** Coarse stage: "bundle" = downloading the editor JS chunk (indeterminate —
|
|
62
|
-
* a dynamic import can't be byte-measured); "fonts" = fetching the bundled
|
|
63
|
-
* fonts (measurable); "ready" = mount complete. */
|
|
64
|
-
phase: "bundle" | "fonts" | "ready";
|
|
65
|
-
/** Overall startup progress, 0..1, monotonic. Drive a progress bar with this. */
|
|
66
|
-
percent: number;
|
|
67
|
-
/** Bytes fetched / total for the current measurable phase (fonts). Both 0 when
|
|
68
|
-
* the phase is indeterminate (bundle). Informational. */
|
|
69
|
-
loaded: number;
|
|
70
|
-
total: number;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/** Opt-in WebMCP agent tooling (see WordCanvasOptions.agentTools). */
|
|
74
|
-
export interface AgentToolsOptions {
|
|
75
|
-
/** Which tool buckets to register. Default: all three.
|
|
76
|
-
* - `read` — read & inspect (get_document, get_selection, search_document,
|
|
77
|
-
* inspect_layout, get_document_stats);
|
|
78
|
-
* - `suggest` — set_mode, comments, tracked-change suggestions, accept/reject;
|
|
79
|
-
* - `edit` — replace_text, insert_text, format_text, set_alignment,
|
|
80
|
-
* select_range, undo/redo, set_document. */
|
|
81
|
-
capabilities?: ("read" | "suggest" | "edit")[];
|
|
82
|
-
/** Optional prefix so several editors on one page don't collide
|
|
83
|
-
* (e.g. "doc1" → "doc1_get_document"). */
|
|
84
|
-
name?: string;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/** Request passed to a custom-field resolver (see WordCanvasOptions.resolveField). */
|
|
88
|
-
export interface FieldResolveRequest {
|
|
89
|
-
/** The field's id within the document. */
|
|
90
|
-
fieldId: string;
|
|
91
|
-
/** Field keyword, uppercased (e.g. "MYCHART"). */
|
|
92
|
-
name: string;
|
|
93
|
-
/** The verbatim field instruction (e.g. ` MYCHART "sales-2026" `). */
|
|
94
|
-
instruction: string;
|
|
95
|
-
/** The collaboration doc id, when the session has one. */
|
|
96
|
-
docId?: string;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/** What a field resolver returns:
|
|
100
|
-
* - a full **.docx** (ArrayBuffer / Uint8Array / Blob) — RECOMMENDED: imported
|
|
101
|
-
* through the same pipeline as opening a document, so images, tables, lists and
|
|
102
|
-
* styles come through (media survives export);
|
|
103
|
-
* - or an **OOXML fragment string** (w:p / w:tbl, or a w:document) for simple,
|
|
104
|
-
* text-only results (no embedded media). */
|
|
105
|
-
export type FieldResult = string | ArrayBuffer | Uint8Array | Blob;
|
|
106
|
-
|
|
107
|
-
/** Host hook producing a field's result for a resolve request. */
|
|
108
|
-
export type FieldResolver = (req: FieldResolveRequest) => Promise<FieldResult>;
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
export
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
export interface
|
|
121
|
-
/**
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
1
|
+
// Public type surface for the @forevka/wordcanvas (WordCanvas) package.
|
|
2
|
+
// Hand-written so the published types stay small, self-contained, and stable
|
|
3
|
+
// regardless of internal refactors — no dependency on internal workspace types.
|
|
4
|
+
|
|
5
|
+
import type { Block, Document, ParaStyle, Run } from "./model";
|
|
6
|
+
|
|
7
|
+
export type { Document } from "./model";
|
|
8
|
+
|
|
9
|
+
/** Caller-supplied identity, used for change attribution and presence. */
|
|
10
|
+
export interface UserInfo {
|
|
11
|
+
id: string;
|
|
12
|
+
firstName: string;
|
|
13
|
+
lastName: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** One other collaborator currently in the document (online mode). */
|
|
17
|
+
export interface Participant {
|
|
18
|
+
siteId: string;
|
|
19
|
+
user?: UserInfo;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface WordCanvasOptions {
|
|
23
|
+
/** Element to mount the editor into. */
|
|
24
|
+
container: HTMLElement;
|
|
25
|
+
/** Backend base URL (e.g. "https://api.example.com"). Online iff provided;
|
|
26
|
+
* omit for a fully offline editor (no sync, publish, or share). */
|
|
27
|
+
backendUrl?: string;
|
|
28
|
+
/** Open this document on load (online only) — e.g. the id returned by an
|
|
29
|
+
* upload. Canonical name; `collabId` is the deprecated alias. */
|
|
30
|
+
docId?: string;
|
|
31
|
+
/** @deprecated Use `docId`. Join an existing collaboration session on load. */
|
|
32
|
+
collabId?: string;
|
|
33
|
+
/** Caller-supplied identity (attribution + presence). The embedder owns auth. */
|
|
34
|
+
user?: UserInfo;
|
|
35
|
+
/** Override how a share link is surfaced (default: a built-in dialog). */
|
|
36
|
+
onShareLink?: (url: string, docId: string) => void;
|
|
37
|
+
/** Resolve a custom (developer-defined) field's content from your backend. When
|
|
38
|
+
* set, right-clicking a custom field offers "Update Field (<name>)"; the
|
|
39
|
+
* callback receives the field's name + verbatim instruction and returns the new
|
|
40
|
+
* result to splice in (see FieldResult). */
|
|
41
|
+
resolveField?: FieldResolver;
|
|
42
|
+
/** Expose this editor to AI agents over WebMCP (https://webmcp.dev), the standard
|
|
43
|
+
* `navigator.modelContext` API. `true` registers the full tool set — read &
|
|
44
|
+
* inspect (including a layout-geometry dump for debugging rendering / text-
|
|
45
|
+
* placement issues), plus suggestions, comments, and direct edits. Pass an
|
|
46
|
+
* object to restrict capabilities or namespace the tool names. The WebMCP
|
|
47
|
+
* polyfill is lazy-loaded only when this is set, so it adds nothing for
|
|
48
|
+
* embedders that don't opt in. Connect an agent via the WebMCP browser
|
|
49
|
+
* extension / Chrome DevTools MCP. */
|
|
50
|
+
agentTools?: boolean | AgentToolsOptions;
|
|
51
|
+
/** Track first-load progress so you can show a loader while the big chunks
|
|
52
|
+
* stream. Fires for the editor JS chunk download (`phase: "bundle"`,
|
|
53
|
+
* indeterminate) and the bundled font fetch (`phase: "fonts"`, the dominant
|
|
54
|
+
* ~9 MB cost — a smooth, size-weighted bar), then once at `phase: "ready"`
|
|
55
|
+
* with `percent: 1`. Read `percent` (0..1, monotonic) to drive a progress bar. */
|
|
56
|
+
onLoadProgress?: (progress: LoadProgress) => void;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** First-load progress (see WordCanvasOptions.onLoadProgress). */
|
|
60
|
+
export interface LoadProgress {
|
|
61
|
+
/** Coarse stage: "bundle" = downloading the editor JS chunk (indeterminate —
|
|
62
|
+
* a dynamic import can't be byte-measured); "fonts" = fetching the bundled
|
|
63
|
+
* fonts (measurable); "ready" = mount complete. */
|
|
64
|
+
phase: "bundle" | "fonts" | "ready";
|
|
65
|
+
/** Overall startup progress, 0..1, monotonic. Drive a progress bar with this. */
|
|
66
|
+
percent: number;
|
|
67
|
+
/** Bytes fetched / total for the current measurable phase (fonts). Both 0 when
|
|
68
|
+
* the phase is indeterminate (bundle). Informational. */
|
|
69
|
+
loaded: number;
|
|
70
|
+
total: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Opt-in WebMCP agent tooling (see WordCanvasOptions.agentTools). */
|
|
74
|
+
export interface AgentToolsOptions {
|
|
75
|
+
/** Which tool buckets to register. Default: all three.
|
|
76
|
+
* - `read` — read & inspect (get_document, get_selection, search_document,
|
|
77
|
+
* inspect_layout, get_document_stats);
|
|
78
|
+
* - `suggest` — set_mode, comments, tracked-change suggestions, accept/reject;
|
|
79
|
+
* - `edit` — replace_text, insert_text, format_text, set_alignment,
|
|
80
|
+
* select_range, undo/redo, set_document. */
|
|
81
|
+
capabilities?: ("read" | "suggest" | "edit")[];
|
|
82
|
+
/** Optional prefix so several editors on one page don't collide
|
|
83
|
+
* (e.g. "doc1" → "doc1_get_document"). */
|
|
84
|
+
name?: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Request passed to a custom-field resolver (see WordCanvasOptions.resolveField). */
|
|
88
|
+
export interface FieldResolveRequest {
|
|
89
|
+
/** The field's id within the document. */
|
|
90
|
+
fieldId: string;
|
|
91
|
+
/** Field keyword, uppercased (e.g. "MYCHART"). */
|
|
92
|
+
name: string;
|
|
93
|
+
/** The verbatim field instruction (e.g. ` MYCHART "sales-2026" `). */
|
|
94
|
+
instruction: string;
|
|
95
|
+
/** The collaboration doc id, when the session has one. */
|
|
96
|
+
docId?: string;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** What a field resolver returns:
|
|
100
|
+
* - a full **.docx** (ArrayBuffer / Uint8Array / Blob) — RECOMMENDED: imported
|
|
101
|
+
* through the same pipeline as opening a document, so images, tables, lists and
|
|
102
|
+
* styles come through (media survives export);
|
|
103
|
+
* - or an **OOXML fragment string** (w:p / w:tbl, or a w:document) for simple,
|
|
104
|
+
* text-only results (no embedded media). */
|
|
105
|
+
export type FieldResult = string | ArrayBuffer | Uint8Array | Blob;
|
|
106
|
+
|
|
107
|
+
/** Host hook producing a field's result for a resolve request. */
|
|
108
|
+
export type FieldResolver = (req: FieldResolveRequest) => Promise<FieldResult>;
|
|
109
|
+
|
|
110
|
+
/** What to render into a child-document surface (see WordCanvas.createChild). */
|
|
111
|
+
export type ChildContent =
|
|
112
|
+
| { kind: "blocks"; blocks: Block[] }
|
|
113
|
+
| { kind: "fragment"; fragment: { blocks: { runs: Run[]; style: ParaStyle }[]; inline?: boolean } }
|
|
114
|
+
| { kind: "runs"; runs: Run[]; paraStyle?: ParaStyle }
|
|
115
|
+
/** Body OOXML (w:p / w:tbl, or a w:document). Media-free (no images by r:id). */
|
|
116
|
+
| { kind: "ooxml"; ooxml: string }
|
|
117
|
+
/** A real sample of a named style ("AaBbCc" in the style's resolved formatting). */
|
|
118
|
+
| { kind: "styleSample"; styleId: string; sampleText?: string };
|
|
119
|
+
|
|
120
|
+
export interface ChildRenderOptions {
|
|
121
|
+
/** Layout/wrap width in CSS px. Default: target.clientWidth. */
|
|
122
|
+
widthPx?: number;
|
|
123
|
+
/** Child section margins (all sides), CSS px. Default 0. */
|
|
124
|
+
padding?: number;
|
|
125
|
+
/** Cap the displayed height; content beyond it is clipped. */
|
|
126
|
+
maxHeightPx?: number;
|
|
127
|
+
/** Fixed presentational scale (1 = 100%). Ignored when `fit` is set. */
|
|
128
|
+
zoom?: number;
|
|
129
|
+
/** Auto-scale the content to fit `widthPx` × `maxHeightPx` (compact swatches). */
|
|
130
|
+
fit?: boolean;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** A live interactive editor over a child slice (canvas-native editing). */
|
|
134
|
+
export interface ChildEditorHandle {
|
|
135
|
+
/** The edited content as model blocks (hand back to splice into the parent). */
|
|
136
|
+
getBlocks(): Block[];
|
|
137
|
+
getDocument(): Document;
|
|
138
|
+
/** Insert an image at the caret. The bytes are registered in the parent
|
|
139
|
+
* document's shared media store (content-addressed), so the image renders here,
|
|
140
|
+
* survives serialize/export, and resolves after commit-back. Dimensions default
|
|
141
|
+
* to the image's natural size. */
|
|
142
|
+
insertImage(bytes: Uint8Array, mime: string, opts?: { widthPx?: number; heightPx?: number }): Promise<void>;
|
|
143
|
+
destroy(): void;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** A lightweight sibling document that shares the parent editor's live styles,
|
|
147
|
+
* fonts and theme and renders/edits a content slice on canvas. */
|
|
148
|
+
export interface ChildDocument {
|
|
149
|
+
/** Paint a static preview of `content` into `target`. Safe to call repeatedly. */
|
|
150
|
+
render(target: HTMLElement, content: ChildContent, opts?: ChildRenderOptions): void;
|
|
151
|
+
/** Mount an interactive editor over `content` inside `target`. */
|
|
152
|
+
mountEditor(target: HTMLElement, content: ChildContent, opts?: ChildRenderOptions): ChildEditorHandle;
|
|
153
|
+
/** Tear down every surface/editor this child created. */
|
|
154
|
+
destroy(): void;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Event name → payload, for `on(...)`/`off(...)`. */
|
|
158
|
+
export interface WordCanvasEventMap {
|
|
159
|
+
ready: Record<string, never>;
|
|
160
|
+
shared: { docId: string; url: string };
|
|
161
|
+
userEntered: { siteId: string; user?: UserInfo };
|
|
162
|
+
userLeave: { siteId: string; user?: UserInfo };
|
|
163
|
+
presence: { participants: Participant[] };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Handle resolved once the editor is mounted (via `whenReady()`). */
|
|
167
|
+
export interface EditorHandle {
|
|
168
|
+
/** Snapshot of the current document (plain data). */
|
|
169
|
+
getDocument(): Document;
|
|
170
|
+
/** Create a child document sharing this editor's live styles/fonts/theme. */
|
|
171
|
+
createChild(): ChildDocument;
|
|
172
|
+
/** Replace the open document with a programmatically-built one (e.g. a
|
|
173
|
+
* DocumentBuilder result). Cloned; drops undo history and any live collab
|
|
174
|
+
* session; preserves zoom + scroll. */
|
|
175
|
+
setDocument(doc: Document): void;
|
|
176
|
+
/** Open a .docx (auto-publishes when online); resolves when loaded. */
|
|
177
|
+
openDocx(file: File | ArrayBuffer): Promise<void>;
|
|
178
|
+
/** Publish the current document and resolve its shareable link (online only). */
|
|
179
|
+
share(): Promise<string>;
|
|
180
|
+
getDocId(): string | null;
|
|
181
|
+
getShareLink(): string | null;
|
|
182
|
+
destroy(): void;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export declare class WordCanvas {
|
|
186
|
+
constructor(opts: WordCanvasOptions);
|
|
187
|
+
/** Subscribe to a collaboration event. Returns an unsubscribe function. */
|
|
188
|
+
on<E extends keyof WordCanvasEventMap>(event: E, handler: (data: WordCanvasEventMap[E]) => void): () => void;
|
|
189
|
+
/** Unsubscribe a handler previously passed to `on()`. */
|
|
190
|
+
off<E extends keyof WordCanvasEventMap>(event: E, handler: (data: WordCanvasEventMap[E]) => void): void;
|
|
191
|
+
/** Resolves once the editor is mounted and ready. */
|
|
192
|
+
whenReady(): Promise<EditorHandle>;
|
|
193
|
+
/** Create a child document that shares this editor's live styles, fonts and
|
|
194
|
+
* theme — render a real, document-styled preview of a content slice onto a
|
|
195
|
+
* canvas (instead of an HTML approximation), or mount a canvas-native editor
|
|
196
|
+
* over a slice. Returned synchronously; render() before ready is buffered.
|
|
197
|
+
* (mountEditor() requires the editor to be ready — await whenReady() first.) */
|
|
198
|
+
createChild(): ChildDocument;
|
|
199
|
+
/** Open a .docx. When online, auto-publishes it and surfaces a share link. */
|
|
200
|
+
openDocx(file: File | ArrayBuffer): Promise<void>;
|
|
201
|
+
/** Replace the open document with a programmatically-built one (e.g. a
|
|
202
|
+
* DocumentBuilder result). The input is cloned. Like openDocx, this starts a
|
|
203
|
+
* NEW document: undo history and any live collab session are dropped (the
|
|
204
|
+
* next share() forks). Zoom and scroll are preserved, so calling this on
|
|
205
|
+
* every data change gives a stable live preview. */
|
|
206
|
+
setDocument(doc: Document): Promise<void>;
|
|
207
|
+
/** Publish the current document and resolve its shareable link (online only). */
|
|
208
|
+
share(): Promise<string>;
|
|
209
|
+
getDocId(): string | null;
|
|
210
|
+
getShareLink(): string | null;
|
|
211
|
+
destroy(): void;
|
|
212
|
+
}
|