@forevka/wordcanvas 0.1.0 → 0.3.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/README.md +7 -4
- package/dist-lib/assets/{engine-DZ0JqUhP.js → engine-BVd9_fny.js} +1126 -1125
- package/dist-lib/assets/{worker-DL4Rxrg-.js → worker-C35TK5Ee.js} +1 -1
- package/dist-lib/builder.js +2347 -0
- package/dist-lib/{editorApp-Bl8rfr3S.js → editorApp-DYckquXo.js} +5052 -5577
- package/dist-lib/types-5-egHV_r.js +972 -0
- package/dist-lib/wordcanvas.js +65 -2
- package/package.json +6 -1
- package/types/builder.d.ts +231 -0
- package/types/model.d.ts +225 -0
- package/types/wordcanvas.d.ts +16 -0
- package/dist-lib/wordcanvas-DPJsuqnm.js +0 -365
package/dist-lib/wordcanvas.js
CHANGED
|
@@ -1,4 +1,67 @@
|
|
|
1
|
-
|
|
1
|
+
class s {
|
|
2
|
+
handle = null;
|
|
3
|
+
ready;
|
|
4
|
+
handlers = /* @__PURE__ */ new Map();
|
|
5
|
+
constructor(e) {
|
|
6
|
+
this.ready = new Promise((t) => {
|
|
7
|
+
const a = {
|
|
8
|
+
container: e.container,
|
|
9
|
+
backendUrl: e.backendUrl,
|
|
10
|
+
// `docId` is the canonical name; fall back to the deprecated `collabId`.
|
|
11
|
+
collabId: e.docId ?? e.collabId,
|
|
12
|
+
user: e.user,
|
|
13
|
+
onShareLink: e.onShareLink,
|
|
14
|
+
onReady: (n) => {
|
|
15
|
+
this.handle = n, t(n);
|
|
16
|
+
},
|
|
17
|
+
onEvent: (n) => this.emit(n)
|
|
18
|
+
};
|
|
19
|
+
import("./editorApp-DYckquXo.js").then((n) => n.mountEditorApp(a));
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/** Subscribe to a collaboration event. Returns an unsubscribe function. */
|
|
23
|
+
on(e, t) {
|
|
24
|
+
let a = this.handlers.get(e);
|
|
25
|
+
return a || this.handlers.set(e, a = /* @__PURE__ */ new Set()), a.add(t), () => this.off(e, t);
|
|
26
|
+
}
|
|
27
|
+
/** Unsubscribe a handler previously passed to on(). */
|
|
28
|
+
off(e, t) {
|
|
29
|
+
this.handlers.get(e)?.delete(t);
|
|
30
|
+
}
|
|
31
|
+
emit(e) {
|
|
32
|
+
const { type: t, ...a } = e;
|
|
33
|
+
for (const n of this.handlers.get(t) ?? []) n(a);
|
|
34
|
+
}
|
|
35
|
+
/** Resolves once the editor is mounted and ready. */
|
|
36
|
+
whenReady() {
|
|
37
|
+
return this.ready;
|
|
38
|
+
}
|
|
39
|
+
/** Open a .docx. When online, auto-publishes it and surfaces a share link. */
|
|
40
|
+
async openDocx(e) {
|
|
41
|
+
return (await this.ready).openDocx(e);
|
|
42
|
+
}
|
|
43
|
+
/** Replace the open document with a programmatically-built one (e.g. a
|
|
44
|
+
* DocumentBuilder result). The input is cloned. Like openDocx, this starts
|
|
45
|
+
* a NEW document: undo history and any live collab session are dropped
|
|
46
|
+
* (the next share() forks). Zoom and scroll position are preserved, so
|
|
47
|
+
* calling this on every data change gives a stable live preview. */
|
|
48
|
+
async setDocument(e) {
|
|
49
|
+
(await this.ready).setDocument(e);
|
|
50
|
+
}
|
|
51
|
+
/** Publish the current document and resolve its shareable link (online only). */
|
|
52
|
+
async share() {
|
|
53
|
+
return (await this.ready).share();
|
|
54
|
+
}
|
|
55
|
+
getDocId() {
|
|
56
|
+
return this.handle?.getDocId() ?? null;
|
|
57
|
+
}
|
|
58
|
+
getShareLink() {
|
|
59
|
+
return this.handle?.getShareLink() ?? null;
|
|
60
|
+
}
|
|
61
|
+
destroy() {
|
|
62
|
+
this.handle?.destroy(), this.handle = null, this.handlers.clear();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
2
65
|
export {
|
|
3
|
-
|
|
66
|
+
s as WordCanvas
|
|
4
67
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forevka/wordcanvas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Embeddable canvas-rendered, Word-compatible document editor with live collaboration and DOCX/PDF import & export. Self-contained, zero runtime dependencies.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"types": "./types/wordcanvas.d.ts",
|
|
33
33
|
"import": "./dist-lib/wordcanvas.js"
|
|
34
34
|
},
|
|
35
|
+
"./builder": "./src/builder/index.ts",
|
|
35
36
|
"./import": "./src/import/docx/pipeline.ts",
|
|
36
37
|
"./export": "./src/export/pipeline.ts",
|
|
37
38
|
"./export/measure": "./src/export/shared/measureHost.ts"
|
|
@@ -42,6 +43,10 @@
|
|
|
42
43
|
".": {
|
|
43
44
|
"types": "./types/wordcanvas.d.ts",
|
|
44
45
|
"import": "./dist-lib/wordcanvas.js"
|
|
46
|
+
},
|
|
47
|
+
"./builder": {
|
|
48
|
+
"types": "./types/builder.d.ts",
|
|
49
|
+
"import": "./dist-lib/builder.js"
|
|
45
50
|
}
|
|
46
51
|
}
|
|
47
52
|
},
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
// Public type surface for @forevka/wordcanvas/builder — the fluent
|
|
2
|
+
// programmatic document composer. Hand-written, self-contained (model types
|
|
3
|
+
// come from ./model, shared with wordcanvas.d.ts).
|
|
4
|
+
//
|
|
5
|
+
// import { DocumentBuilder } from "@forevka/wordcanvas/builder";
|
|
6
|
+
// const b = await DocumentBuilder.fromTemplate(templateBytes);
|
|
7
|
+
// const doc = b.paragraph(data.title).withStyle("Heading1").build();
|
|
8
|
+
//
|
|
9
|
+
// Works in the browser (live preview via WordCanvas.setDocument) and in Node
|
|
10
|
+
// (server-side DOCX/PDF generation via the export subpath).
|
|
11
|
+
|
|
12
|
+
import type { CellBorders, CellMargin, CharStyle, Document, NamedStyle, ParaStyle, Stylesheet } from "./model";
|
|
13
|
+
|
|
14
|
+
export type { Block, CharStyle, Document, NamedStyle, ParaStyle, Stylesheet } from "./model";
|
|
15
|
+
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Units
|
|
18
|
+
|
|
19
|
+
/** Inches → px @96dpi. */
|
|
20
|
+
export declare function inches(n: number): number;
|
|
21
|
+
/** Centimeters → px @96dpi. */
|
|
22
|
+
export declare function cm(n: number): number;
|
|
23
|
+
/** Points (1/72in) → px @96dpi. */
|
|
24
|
+
export declare function pt(n: number): number;
|
|
25
|
+
/** Twips (1/20pt) → px @96dpi. */
|
|
26
|
+
export declare function twips(n: number): number;
|
|
27
|
+
|
|
28
|
+
export interface PageSize {
|
|
29
|
+
pageWidthPx: number;
|
|
30
|
+
pageHeightPx: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Common page sizes in px @96dpi. */
|
|
34
|
+
export declare const PAGE_SIZES: Record<"Letter" | "Legal" | "A4" | "A3" | "Tabloid", PageSize>;
|
|
35
|
+
export type PageSizeName = keyof typeof PAGE_SIZES;
|
|
36
|
+
|
|
37
|
+
/** Base64-encode image bytes as a portable data: URL. */
|
|
38
|
+
export declare function bytesToDataUrl(bytes: Uint8Array | ArrayBuffer, mime: string): string;
|
|
39
|
+
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Options
|
|
42
|
+
|
|
43
|
+
export interface BuilderWarning {
|
|
44
|
+
code: string;
|
|
45
|
+
message: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface CreateOptions {
|
|
49
|
+
pageSize?: PageSizeName | PageSize;
|
|
50
|
+
margins?: Partial<{ top: number; right: number; bottom: number; left: number }>;
|
|
51
|
+
/** Start from a custom stylesheet (default: the editor's default gallery). */
|
|
52
|
+
stylesheet?: Stylesheet;
|
|
53
|
+
/** Deterministic id namespace (tests); default is a random per-builder seed. */
|
|
54
|
+
idSeed?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface TemplateOptions {
|
|
58
|
+
/** Keep the template's body content and append after it (default: discard —
|
|
59
|
+
* the template contributes styles, lists, page setup, and bands). */
|
|
60
|
+
keepBody?: boolean;
|
|
61
|
+
idSeed?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface PageSetup {
|
|
65
|
+
pageSize?: PageSizeName | PageSize;
|
|
66
|
+
orientation?: "portrait" | "landscape";
|
|
67
|
+
margins?: Partial<{ top: number; right: number; bottom: number; left: number }>;
|
|
68
|
+
columns?: { count: number; gapPx?: number };
|
|
69
|
+
headerDistancePx?: number;
|
|
70
|
+
footerDistancePx?: number;
|
|
71
|
+
pageNumberStart?: number;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface BandOptions {
|
|
75
|
+
/** Which page band variant: default (all pages), first page, or even pages. */
|
|
76
|
+
variant?: "default" | "first" | "even";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface ImageOptions {
|
|
80
|
+
/** Required — the builder runs in Node too, where images can't be measured. */
|
|
81
|
+
widthPx: number;
|
|
82
|
+
heightPx: number;
|
|
83
|
+
align?: "left" | "center" | "right";
|
|
84
|
+
wrap?: "block" | "square";
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface ListItem {
|
|
88
|
+
text: string;
|
|
89
|
+
/** Nesting level 0..8 (default 0, or ListOptions.level). */
|
|
90
|
+
level?: number;
|
|
91
|
+
style?: Partial<CharStyle>;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface ListOptions {
|
|
95
|
+
kind?: "bullet" | "number";
|
|
96
|
+
/** Reference an existing list definition (e.g. one carried by the template). */
|
|
97
|
+
listId?: string;
|
|
98
|
+
level?: number;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface CellSpec {
|
|
102
|
+
text?: string;
|
|
103
|
+
colSpan?: number;
|
|
104
|
+
rowSpan?: number;
|
|
105
|
+
/** Background fill (CSS color). */
|
|
106
|
+
shading?: string;
|
|
107
|
+
borders?: CellBorders;
|
|
108
|
+
margin?: CellMargin;
|
|
109
|
+
/** Char formatting for the cell's text. */
|
|
110
|
+
style?: Partial<CharStyle>;
|
|
111
|
+
align?: ParaStyle["align"];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export type CellContent = string | CellSpec;
|
|
115
|
+
export type CellOptions = Omit<CellSpec, "text">;
|
|
116
|
+
|
|
117
|
+
export interface TableOptions {
|
|
118
|
+
/** Column widths as fractions of the content width (normalized to sum 1). */
|
|
119
|
+
colFractions?: number[];
|
|
120
|
+
/** Bold every run in the first row. */
|
|
121
|
+
headerRow?: boolean;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface SpacingOptions {
|
|
125
|
+
before?: number;
|
|
126
|
+
after?: number;
|
|
127
|
+
lineHeight?: number;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export interface IndentOptions {
|
|
131
|
+
left?: number;
|
|
132
|
+
right?: number;
|
|
133
|
+
firstLine?: number;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
// Scopes
|
|
138
|
+
|
|
139
|
+
/** Block-scope surface shared by the document body, header/footer bands, and
|
|
140
|
+
* table cells. Methods append eagerly and return the scope (or a paragraph
|
|
141
|
+
* scope that delegates back), so chains never need a seal step. */
|
|
142
|
+
export declare class StoryBuilder {
|
|
143
|
+
paragraph(text?: string, style?: Partial<CharStyle>): ParagraphBuilder<this>;
|
|
144
|
+
table(rows: CellContent[][], opts?: TableOptions): this;
|
|
145
|
+
table(build: (t: TableBuilder) => void, opts?: TableOptions): this;
|
|
146
|
+
image(src: string | { data: Uint8Array | ArrayBuffer; mime: string }, opts: ImageOptions): this;
|
|
147
|
+
list(items: (string | ListItem)[], opts?: ListOptions): this;
|
|
148
|
+
bulletList(items: (string | ListItem)[]): this;
|
|
149
|
+
numberedList(items: (string | ListItem)[]): this;
|
|
150
|
+
/** The NEXT block starts a new page. */
|
|
151
|
+
pageBreak(): this;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Paragraph scope. Char formatting (bold/color/font/…) patches every run
|
|
155
|
+
* already in the paragraph and becomes the default for later text() runs;
|
|
156
|
+
* mixed formatting uses text(t, { …patch }). Any block-starting call pops
|
|
157
|
+
* back to the parent scope. */
|
|
158
|
+
export declare class ParagraphBuilder<P extends StoryBuilder> {
|
|
159
|
+
/** Apply a named style: sets the reference and patches exactly the fields
|
|
160
|
+
* the style defines. Direct formatting applied AFTER this call wins. */
|
|
161
|
+
withStyle(id: string): this;
|
|
162
|
+
/** Append a run. Inherits the scope's accrued formatting; `style` wins. */
|
|
163
|
+
text(text: string, style?: Partial<CharStyle>): this;
|
|
164
|
+
bold(on?: boolean): this;
|
|
165
|
+
italic(on?: boolean): this;
|
|
166
|
+
underline(on?: boolean): this;
|
|
167
|
+
strikethrough(on?: boolean): this;
|
|
168
|
+
color(cssColor: string): this;
|
|
169
|
+
highlight(cssColor: string): this;
|
|
170
|
+
fontSize(px: number): this;
|
|
171
|
+
font(family: string): this;
|
|
172
|
+
link(url: string): this;
|
|
173
|
+
align(align: ParaStyle["align"]): this;
|
|
174
|
+
spacing(opts: SpacingOptions): this;
|
|
175
|
+
indent(opts: IndentOptions): this;
|
|
176
|
+
keepWithNext(on?: boolean): this;
|
|
177
|
+
/** Escape the paragraph scope explicitly (block-starting calls do it implicitly). */
|
|
178
|
+
end(): P;
|
|
179
|
+
|
|
180
|
+
// Delegated block-starting surface (pops this scope):
|
|
181
|
+
paragraph(text?: string, style?: Partial<CharStyle>): ParagraphBuilder<P>;
|
|
182
|
+
table(rows: CellContent[][], opts?: TableOptions): P;
|
|
183
|
+
table(build: (t: TableBuilder) => void, opts?: TableOptions): P;
|
|
184
|
+
image(src: string | { data: Uint8Array | ArrayBuffer; mime: string }, opts: ImageOptions): P;
|
|
185
|
+
list(items: (string | ListItem)[], opts?: ListOptions): P;
|
|
186
|
+
bulletList(items: (string | ListItem)[]): P;
|
|
187
|
+
numberedList(items: (string | ListItem)[]): P;
|
|
188
|
+
pageBreak(): P;
|
|
189
|
+
|
|
190
|
+
// Document-level delegators (only when the parent is the root builder):
|
|
191
|
+
header(this: ParagraphBuilder<DocumentBuilder>, build: (s: StoryBuilder) => void, opts?: BandOptions): DocumentBuilder;
|
|
192
|
+
footer(this: ParagraphBuilder<DocumentBuilder>, build: (s: StoryBuilder) => void, opts?: BandOptions): DocumentBuilder;
|
|
193
|
+
pageSetup(this: ParagraphBuilder<DocumentBuilder>, setup: PageSetup): DocumentBuilder;
|
|
194
|
+
style(this: ParagraphBuilder<DocumentBuilder>, def: NamedStyle): DocumentBuilder;
|
|
195
|
+
build(this: ParagraphBuilder<DocumentBuilder>): Document;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export declare class TableBuilder {
|
|
199
|
+
row(cells: CellContent[]): this;
|
|
200
|
+
row(build: (r: RowBuilder) => void): this;
|
|
201
|
+
rows(data: CellContent[][]): this;
|
|
202
|
+
colFractions(fractions: number[]): this;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export declare class RowBuilder {
|
|
206
|
+
cell(content: CellContent, opts?: CellOptions): this;
|
|
207
|
+
cell(build: (s: StoryBuilder) => void, opts?: CellOptions): this;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** Root of the fluent builder. Produces the same plain-data Document the
|
|
211
|
+
* editor renders (WordCanvas.setDocument) and the exporters write. build()
|
|
212
|
+
* returns a deep clone; the builder stays usable afterwards. */
|
|
213
|
+
export declare class DocumentBuilder extends StoryBuilder {
|
|
214
|
+
/** Start from a blank document (default stylesheet, US Letter, 1in margins). */
|
|
215
|
+
static create(opts?: CreateOptions): DocumentBuilder;
|
|
216
|
+
/** Start from a .docx template: its stylesheet, list definitions, page setup,
|
|
217
|
+
* and header/footer bands carry over (body discarded unless keepBody). */
|
|
218
|
+
static fromTemplate(docx: ArrayBuffer | Uint8Array, opts?: TemplateOptions): Promise<DocumentBuilder>;
|
|
219
|
+
|
|
220
|
+
/** Lossy decisions (unknown style ids, template import warnings, …). */
|
|
221
|
+
readonly warnings: readonly BuilderWarning[];
|
|
222
|
+
/** Compose a header band (replaces the variant's existing story). */
|
|
223
|
+
header(build: (s: StoryBuilder) => void, opts?: BandOptions): this;
|
|
224
|
+
footer(build: (s: StoryBuilder) => void, opts?: BandOptions): this;
|
|
225
|
+
/** Merge page geometry onto the section (template values are the base). */
|
|
226
|
+
pageSetup(setup: PageSetup): this;
|
|
227
|
+
/** Register (or override) a named style — BEFORE applying it via withStyle(). */
|
|
228
|
+
style(def: NamedStyle): this;
|
|
229
|
+
/** Snapshot the document: deep clone, guaranteed at least one paragraph. */
|
|
230
|
+
build(): Document;
|
|
231
|
+
}
|
package/types/model.d.ts
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
// Public document-model types for @forevka/wordcanvas. Hand-written (like
|
|
2
|
+
// wordcanvas.d.ts) so the published surface stays self-contained and stable;
|
|
3
|
+
// mirrors shared/src/model — the editor, builder, and exporters all consume
|
|
4
|
+
// this same plain-data shape.
|
|
5
|
+
|
|
6
|
+
export interface CharStyle {
|
|
7
|
+
fontFamily: string;
|
|
8
|
+
fontSizePx: number;
|
|
9
|
+
bold: boolean;
|
|
10
|
+
italic: boolean;
|
|
11
|
+
underline: boolean;
|
|
12
|
+
strikethrough: boolean;
|
|
13
|
+
/** CSS color, e.g. "#202124". */
|
|
14
|
+
color: string;
|
|
15
|
+
/** Hidden text (OOXML w:vanish) — preserved but never laid out or painted. */
|
|
16
|
+
hidden?: boolean;
|
|
17
|
+
letterSpacingPx?: number;
|
|
18
|
+
/** Background highlight (Word's text highlight). */
|
|
19
|
+
highlightColor?: string | undefined;
|
|
20
|
+
/** Sub/superscript. */
|
|
21
|
+
verticalAlign?: "sub" | "super" | undefined;
|
|
22
|
+
/** Hyperlink target; linked runs paint blue+underlined. */
|
|
23
|
+
link?: string | undefined;
|
|
24
|
+
/** Footnote reference id — this run is the marker. */
|
|
25
|
+
footnoteRef?: string | undefined;
|
|
26
|
+
/** Content-control membership (properties live in Document.sdts). */
|
|
27
|
+
sdtId?: string | undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface TabStop {
|
|
31
|
+
/** Position from the left content edge, px. */
|
|
32
|
+
posPx: number;
|
|
33
|
+
align?: "left" | "center" | "right" | "decimal";
|
|
34
|
+
leader?: "none" | "dot" | "dash" | "underscore";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface ParaStyle {
|
|
38
|
+
align: "left" | "center" | "right" | "justify";
|
|
39
|
+
/** Line height multiplier. */
|
|
40
|
+
lineHeight: number;
|
|
41
|
+
spaceBeforePx: number;
|
|
42
|
+
spaceAfterPx: number;
|
|
43
|
+
indentFirstLinePx: number;
|
|
44
|
+
indentLeftPx: number;
|
|
45
|
+
indentRightPx?: number;
|
|
46
|
+
keepWithNext?: boolean;
|
|
47
|
+
keepLinesTogether?: boolean;
|
|
48
|
+
/** This paragraph starts a new page. */
|
|
49
|
+
pageBreakBefore?: boolean;
|
|
50
|
+
/** List membership: definition id + level 0..8. */
|
|
51
|
+
list?: { listId: string; level: number } | undefined;
|
|
52
|
+
/** Named style reference into Document.stylesheet (e.g. "Heading1"). */
|
|
53
|
+
namedStyle?: string;
|
|
54
|
+
columnBreakBefore?: boolean;
|
|
55
|
+
tabStops?: TabStop[];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Style-homogeneous span of text. */
|
|
59
|
+
export interface Run {
|
|
60
|
+
text: string;
|
|
61
|
+
style: CharStyle;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface Paragraph {
|
|
65
|
+
kind: "paragraph";
|
|
66
|
+
/** Stable unique id. */
|
|
67
|
+
id: string;
|
|
68
|
+
revision: number;
|
|
69
|
+
runs: Run[];
|
|
70
|
+
style: ParaStyle;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface ImageBlock {
|
|
74
|
+
kind: "image";
|
|
75
|
+
id: string;
|
|
76
|
+
revision: number;
|
|
77
|
+
/** Image URL — use data: URLs for portable documents. */
|
|
78
|
+
src: string;
|
|
79
|
+
/** Content address of the bytes (sha256 hex), when registered. */
|
|
80
|
+
mediaId?: string;
|
|
81
|
+
widthPx: number;
|
|
82
|
+
heightPx: number;
|
|
83
|
+
align: "left" | "center" | "right";
|
|
84
|
+
/** 'block' (default): own line. 'square': floats per align, text wraps. */
|
|
85
|
+
wrap?: "block" | "square";
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface CellBorder {
|
|
89
|
+
color: string;
|
|
90
|
+
widthPx: number;
|
|
91
|
+
style?: "single" | "double" | "dashed" | "dotted";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface CellBorders {
|
|
95
|
+
top?: CellBorder;
|
|
96
|
+
right?: CellBorder;
|
|
97
|
+
bottom?: CellBorder;
|
|
98
|
+
left?: CellBorder;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface CellMargin {
|
|
102
|
+
top: number;
|
|
103
|
+
right: number;
|
|
104
|
+
bottom: number;
|
|
105
|
+
left: number;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface TableCell {
|
|
109
|
+
id: string;
|
|
110
|
+
blocks: Block[];
|
|
111
|
+
colSpan?: number;
|
|
112
|
+
rowSpan?: number;
|
|
113
|
+
/** Background fill (CSS color). */
|
|
114
|
+
shading?: string;
|
|
115
|
+
borders?: CellBorders;
|
|
116
|
+
margin?: CellMargin;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface TableRow {
|
|
120
|
+
cells: TableCell[];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface TableBlock {
|
|
124
|
+
kind: "table";
|
|
125
|
+
id: string;
|
|
126
|
+
revision: number;
|
|
127
|
+
rows: TableRow[];
|
|
128
|
+
/** Column widths as fractions of content width (sum = 1). Absent = equal. */
|
|
129
|
+
colFractions?: number[];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export type Block = Paragraph | ImageBlock | TableBlock;
|
|
133
|
+
|
|
134
|
+
export type BandContainer = "header" | "footer" | "headerFirst" | "headerEven" | "footerFirst" | "footerEven";
|
|
135
|
+
|
|
136
|
+
export interface SectionProps {
|
|
137
|
+
pageWidthPx: number;
|
|
138
|
+
pageHeightPx: number;
|
|
139
|
+
marginPx: { top: number; right: number; bottom: number; left: number };
|
|
140
|
+
/** Newspaper columns. Absent = single column. */
|
|
141
|
+
columns?: { count: number; gapPx: number };
|
|
142
|
+
pageNumberStart?: number;
|
|
143
|
+
headerDistancePx?: number;
|
|
144
|
+
footerDistancePx?: number;
|
|
145
|
+
/** Header/footer block stories. {page}/{pages} tokens in run text are
|
|
146
|
+
* substituted per page at layout time. */
|
|
147
|
+
header?: Block[];
|
|
148
|
+
footer?: Block[];
|
|
149
|
+
headerFirst?: Block[];
|
|
150
|
+
headerEven?: Block[];
|
|
151
|
+
footerFirst?: Block[];
|
|
152
|
+
footerEven?: Block[];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export interface NamedStyle {
|
|
156
|
+
/** Shares the docx styleId space ("Normal", "Heading1", …). */
|
|
157
|
+
id: string;
|
|
158
|
+
/** Display name. */
|
|
159
|
+
name: string;
|
|
160
|
+
basedOn?: string;
|
|
161
|
+
char: Partial<CharStyle>;
|
|
162
|
+
para: Partial<ParaStyle>;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export interface Stylesheet {
|
|
166
|
+
styles: NamedStyle[];
|
|
167
|
+
defaultStyleId: string;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export type ListNumberFormat = "bullet" | "decimal" | "lowerLetter" | "upperLetter" | "lowerRoman" | "upperRoman";
|
|
171
|
+
|
|
172
|
+
export interface ListLevel {
|
|
173
|
+
format: ListNumberFormat;
|
|
174
|
+
/** Marker pattern; %N is level N-1's counter (e.g. "%1."). Ignored for bullets. */
|
|
175
|
+
text: string;
|
|
176
|
+
bulletChar?: string;
|
|
177
|
+
indentLeftPx: number;
|
|
178
|
+
hangingPx: number;
|
|
179
|
+
start: number;
|
|
180
|
+
markerStyle?: Partial<CharStyle>;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export interface ListDefinition {
|
|
184
|
+
id: string;
|
|
185
|
+
/** Up to 9 levels (0..8). */
|
|
186
|
+
levels: ListLevel[];
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export interface DocPosition {
|
|
190
|
+
blockId: string;
|
|
191
|
+
offset: number;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export interface BookmarkRange {
|
|
195
|
+
start: DocPosition;
|
|
196
|
+
end: DocPosition;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export type SdtType = "richText" | "plainText" | "checkbox" | "dropDown" | "comboBox" | "date";
|
|
200
|
+
|
|
201
|
+
export interface SdtProps {
|
|
202
|
+
type: SdtType;
|
|
203
|
+
alias?: string;
|
|
204
|
+
tag?: string;
|
|
205
|
+
placeholder?: boolean;
|
|
206
|
+
listItems?: { display: string; value: string }[];
|
|
207
|
+
dateFormat?: string;
|
|
208
|
+
checked?: boolean;
|
|
209
|
+
lockContent?: boolean;
|
|
210
|
+
lockControl?: boolean;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export interface Document {
|
|
214
|
+
section: SectionProps;
|
|
215
|
+
blocks: Block[];
|
|
216
|
+
stylesheet?: Stylesheet;
|
|
217
|
+
/** List definitions keyed by id. */
|
|
218
|
+
lists?: Record<string, ListDefinition>;
|
|
219
|
+
/** Footnote bodies keyed by ref id. */
|
|
220
|
+
footnotes?: Record<string, Paragraph[]>;
|
|
221
|
+
/** Content-control properties keyed by sdtId. */
|
|
222
|
+
sdts?: Record<string, SdtProps>;
|
|
223
|
+
/** Bookmark name → character range. */
|
|
224
|
+
bookmarks?: Record<string, BookmarkRange>;
|
|
225
|
+
}
|
package/types/wordcanvas.d.ts
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
// Hand-written so the published types stay small, self-contained, and stable
|
|
3
3
|
// regardless of internal refactors — no dependency on internal workspace types.
|
|
4
4
|
|
|
5
|
+
import type { Document } from "./model";
|
|
6
|
+
|
|
7
|
+
export type { Document } from "./model";
|
|
8
|
+
|
|
5
9
|
/** Caller-supplied identity, used for change attribution and presence. */
|
|
6
10
|
export interface UserInfo {
|
|
7
11
|
id: string;
|
|
@@ -43,6 +47,12 @@ export interface WordCanvasEventMap {
|
|
|
43
47
|
|
|
44
48
|
/** Handle resolved once the editor is mounted (via `whenReady()`). */
|
|
45
49
|
export interface EditorHandle {
|
|
50
|
+
/** Snapshot of the current document (plain data). */
|
|
51
|
+
getDocument(): Document;
|
|
52
|
+
/** Replace the open document with a programmatically-built one (e.g. a
|
|
53
|
+
* DocumentBuilder result). Cloned; drops undo history and any live collab
|
|
54
|
+
* session; preserves zoom + scroll. */
|
|
55
|
+
setDocument(doc: Document): void;
|
|
46
56
|
/** Open a .docx (auto-publishes when online); resolves when loaded. */
|
|
47
57
|
openDocx(file: File | ArrayBuffer): Promise<void>;
|
|
48
58
|
/** Publish the current document and resolve its shareable link (online only). */
|
|
@@ -62,6 +72,12 @@ export declare class WordCanvas {
|
|
|
62
72
|
whenReady(): Promise<EditorHandle>;
|
|
63
73
|
/** Open a .docx. When online, auto-publishes it and surfaces a share link. */
|
|
64
74
|
openDocx(file: File | ArrayBuffer): Promise<void>;
|
|
75
|
+
/** Replace the open document with a programmatically-built one (e.g. a
|
|
76
|
+
* DocumentBuilder result). The input is cloned. Like openDocx, this starts a
|
|
77
|
+
* NEW document: undo history and any live collab session are dropped (the
|
|
78
|
+
* next share() forks). Zoom and scroll are preserved, so calling this on
|
|
79
|
+
* every data change gives a stable live preview. */
|
|
80
|
+
setDocument(doc: Document): Promise<void>;
|
|
65
81
|
/** Publish the current document and resolve its shareable link (online only). */
|
|
66
82
|
share(): Promise<string>;
|
|
67
83
|
getDocId(): string | null;
|