@docx-editor.dev/editor-api 0.0.1-placeholder → 2.0.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/LICENSE.md +121 -0
- package/README.md +150 -2
- package/THIRD_PARTY_NOTICES.md +22 -0
- package/dist/browser.d.mts +86 -0
- package/dist/browser.d.ts +86 -0
- package/dist/browser.js +1 -0
- package/dist/browser.mjs +1 -0
- package/dist/index.d.mts +157 -0
- package/dist/index.d.ts +157 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/dist/server-C96AzKaT.d.mts +1965 -0
- package/dist/server-C96AzKaT.d.ts +1965 -0
- package/package.json +67 -4
|
@@ -0,0 +1,1965 @@
|
|
|
1
|
+
import { AutomationOperation, AutomationValue, AutomationHandle, AutomationHost, AutomationCapabilities, AutomationSpan } from '@docx-editor.dev/core/automation';
|
|
2
|
+
|
|
3
|
+
/** Whether an action reads or writes. Drives the conditional-revision rule in `sync()`. */
|
|
4
|
+
type ActionSort = 'read' | 'write';
|
|
5
|
+
interface QueuedAction {
|
|
6
|
+
readonly sort: ActionSort;
|
|
7
|
+
/** The consumer-facing name of what this action is for, for errors. Never a handle. */
|
|
8
|
+
readonly label: string;
|
|
9
|
+
/**
|
|
10
|
+
* The host operation for this action.
|
|
11
|
+
*
|
|
12
|
+
* Called once, at dispatch. May throw `InvalidObjectPath` if the object it addresses stopped
|
|
13
|
+
* being addressable between the call that queued it and the sync — which refuses the batch
|
|
14
|
+
* before anything is sent.
|
|
15
|
+
*/
|
|
16
|
+
plan(): AutomationOperation;
|
|
17
|
+
/** The host's answer for this action, in batch order. */
|
|
18
|
+
settle(value: AutomationValue): void;
|
|
19
|
+
}
|
|
20
|
+
declare class ActionQueue {
|
|
21
|
+
#private;
|
|
22
|
+
get size(): number;
|
|
23
|
+
/** What is queued right now, for tests and for the empty-batch shortcut. */
|
|
24
|
+
get pending(): readonly QueuedAction[];
|
|
25
|
+
push(action: QueuedAction): void;
|
|
26
|
+
/** Hand over everything queued and forget it. Never replayed — see the file header. */
|
|
27
|
+
take(): readonly QueuedAction[];
|
|
28
|
+
/** Drop everything queued: what a finished run does with actions nobody synced. */
|
|
29
|
+
clear(): void;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** What a promised member is told once the read that looked for it has answered. */
|
|
33
|
+
interface PromisedItem {
|
|
34
|
+
/** @internal The member was there, at this address. */
|
|
35
|
+
hydrateAddress(address: ObjectAddress): void;
|
|
36
|
+
/** @internal There was no such member. */
|
|
37
|
+
hydrateNull(): void;
|
|
38
|
+
}
|
|
39
|
+
declare abstract class ItemCollection<T extends ClientObject> extends ClientObject {
|
|
40
|
+
#private;
|
|
41
|
+
protected constructor(context: RequestContext, path: ObjectPath);
|
|
42
|
+
/**
|
|
43
|
+
* The read that lists this collection's members, or `null` when a write already answered them.
|
|
44
|
+
*
|
|
45
|
+
* `Paragraph#split` is the case that needs the second shape: the operation that breaks the
|
|
46
|
+
* paragraph is the same operation that says what the pieces are, so the collection it answers is
|
|
47
|
+
* filled by that command's own result. Listing it again afterwards would describe a DIFFERENT
|
|
48
|
+
* document — the one the split produced — and quietly turn one atomic call into two.
|
|
49
|
+
*/
|
|
50
|
+
protected abstract listing(): AutomationOperation | null;
|
|
51
|
+
/** How many members an answer holds, without building any of them. */
|
|
52
|
+
protected abstract size(value: AutomationValue, label: string): number;
|
|
53
|
+
/** Where the member at `index` is, or `undefined` if the answer has no such member. */
|
|
54
|
+
protected abstract addressAt(value: AutomationValue, label: string, index: number): ObjectAddress | undefined;
|
|
55
|
+
/** A member of this collection, already addressed. */
|
|
56
|
+
protected abstract itemAt(label: string, address: ObjectAddress): T;
|
|
57
|
+
/** A member with no verdict yet — what both item accessors answer with. */
|
|
58
|
+
protected abstract promised(label: string, nullable: boolean): T & PromisedItem;
|
|
59
|
+
/**
|
|
60
|
+
* The members this collection was loaded with.
|
|
61
|
+
*
|
|
62
|
+
* `PropertyNotLoaded` until a `load(...)` has been synced: a collection that answered `[]`
|
|
63
|
+
* before it had been read would be indistinguishable from an empty document.
|
|
64
|
+
*/
|
|
65
|
+
get items(): readonly T[];
|
|
66
|
+
/** @internal Take the members straight from the command that produced them. */
|
|
67
|
+
fill(value: AutomationValue, label: string): void;
|
|
68
|
+
/** @internal Plan the read this object's `load(...)` asked for. */
|
|
69
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
70
|
+
/** One member, by which end of the collection it is at. */
|
|
71
|
+
protected edge(edge: 'first' | 'last', accessor: string, nullable: boolean): T;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The shape almost every collection here has: a listing that answers HANDLES.
|
|
75
|
+
*
|
|
76
|
+
* Only the paragraph and range collections need anything else — ranges are spans, and a split
|
|
77
|
+
* answers its own members — so the size-and-address half is written once rather than in each of the
|
|
78
|
+
* seven collections that would otherwise copy it and be able to copy it wrongly.
|
|
79
|
+
*/
|
|
80
|
+
declare abstract class HandleCollection<T extends ClientObject & PromisedItem> extends ItemCollection<T> {
|
|
81
|
+
/** @internal How many members the listing's answer describes. */
|
|
82
|
+
protected size(value: AutomationValue, label: string): number;
|
|
83
|
+
/** @internal The address of one member of the listing's answer. */
|
|
84
|
+
protected addressAt(value: AutomationValue, label: string, index: number): ObjectAddress | undefined;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
declare abstract class ModelObject extends ClientObject {
|
|
88
|
+
/** Queue a read whose text answer becomes the loaded property `name`. */
|
|
89
|
+
protected loadTextInto(name: string, plan: () => AutomationOperation): void;
|
|
90
|
+
/** Queue a command with nothing to answer. Nothing is written until `sync()`. */
|
|
91
|
+
protected command(name: string, plan: () => AutomationOperation): void;
|
|
92
|
+
/**
|
|
93
|
+
* Queue a command whose answer this call has no use for.
|
|
94
|
+
*
|
|
95
|
+
* `clear()` is the case: the operation behind it is a replacement, and a replacement answers the
|
|
96
|
+
* range it wrote — a range over no text, here. The answer is dropped rather than checked for a
|
|
97
|
+
* shape the method does not return, so that the operation stays the same one an insertion uses.
|
|
98
|
+
*/
|
|
99
|
+
protected commandDiscarding(name: string, plan: () => AutomationOperation): void;
|
|
100
|
+
/** Queue a command whose answer names something the caller keeps. */
|
|
101
|
+
protected commandAnswering(label: string, plan: () => AutomationOperation, settle: (value: AutomationValue) => void): void;
|
|
102
|
+
/** Queue a read whose answer is hydrated by the caller. */
|
|
103
|
+
protected read(label: string, plan: () => AutomationOperation, settle: (value: AutomationValue) => void): void;
|
|
104
|
+
/** The properties a load asked for, refusing any name this object does not have. */
|
|
105
|
+
protected selection(request: ResolvedLoadOptions, available: readonly string[]): readonly string[];
|
|
106
|
+
/** @internal Plan the read this object's `load(...)` asked for. */
|
|
107
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* A list: the set of paragraphs sharing one numbering id.
|
|
112
|
+
*
|
|
113
|
+
* A list is not an ELEMENT. OOXML has no list — it has paragraphs that each name a `w:numId`, and
|
|
114
|
+
* a list is the set that name the same one. So {@link List.id} is that number,
|
|
115
|
+
* {@link List.paragraphs} is the set, and a list exists exactly as long as some paragraph is
|
|
116
|
+
* still in it.
|
|
117
|
+
*
|
|
118
|
+
* @public
|
|
119
|
+
*/
|
|
120
|
+
declare class List extends ModelObject implements PromisedItem {
|
|
121
|
+
#private;
|
|
122
|
+
/** @internal A list a read has already named. */
|
|
123
|
+
static at(context: RequestContext, label: string, address: ObjectAddress): List;
|
|
124
|
+
/** @internal A list a queued read will name, or report as nothing. */
|
|
125
|
+
static promised(context: RequestContext, label: string, nullable: boolean): List;
|
|
126
|
+
private constructor();
|
|
127
|
+
/** @internal Bind this object to the address the owning read answered. */
|
|
128
|
+
hydrateAddress(address: ObjectAddress): void;
|
|
129
|
+
/** @internal Settle as the null object: the read found nothing to name. */
|
|
130
|
+
hydrateNull(): void;
|
|
131
|
+
/** The `w:numId` the list's paragraphs share — the document's own identity for the list. */
|
|
132
|
+
get id(): number;
|
|
133
|
+
/** Every paragraph in the list, in reading order. */
|
|
134
|
+
get paragraphs(): ParagraphCollection;
|
|
135
|
+
/** The list's paragraphs at one level, in reading order. */
|
|
136
|
+
getLevelParagraphs(level: number): ParagraphCollection;
|
|
137
|
+
/**
|
|
138
|
+
* Add a numbered paragraph to the list, at its start or its end.
|
|
139
|
+
*
|
|
140
|
+
* All four of Word's locations are accepted and `Before`/`After` land INSIDE the list, at the
|
|
141
|
+
* first and last position — the same places `Start` and `End` name. A list is a set of paragraphs
|
|
142
|
+
* rather than a region, so "before the list" is a position in the story rather than in the list,
|
|
143
|
+
* and `Paragraph#insertParagraph` is what addresses that. The divergence is recorded in
|
|
144
|
+
* `compat/manifest.json`.
|
|
145
|
+
*/
|
|
146
|
+
insertParagraph(paragraphText: string, insertLocation: 'Start' | 'End' | 'Before' | 'After'): Paragraph;
|
|
147
|
+
/** @internal Plan the read this object's `load(...)` asked for. */
|
|
148
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* The lists in a story, as of the batch that loaded them.
|
|
152
|
+
*
|
|
153
|
+
* @public
|
|
154
|
+
*/
|
|
155
|
+
declare class ListCollection extends HandleCollection<List> {
|
|
156
|
+
#private;
|
|
157
|
+
/** @internal The lists of one story, in the order their numbers first appear. */
|
|
158
|
+
static of(context: RequestContext, label: string, owner: ObjectPath, body: AutomationHandle): ListCollection;
|
|
159
|
+
private constructor();
|
|
160
|
+
/** The first list. `ItemNotFound` at the sync if the story has none. */
|
|
161
|
+
getFirst(): List;
|
|
162
|
+
/**
|
|
163
|
+
* The list with one `w:numId`, or `ItemNotFound` where the story has none.
|
|
164
|
+
*
|
|
165
|
+
* ONE read, answered by the host: a `w:numId` is a document value, and matching it against a
|
|
166
|
+
* listing on this side would mean asking every list for its id and choosing locally — a batch
|
|
167
|
+
* whose size depends on the document, to answer a question the host can answer directly. A number
|
|
168
|
+
* no paragraph uses names a numbering definition rather than a list, and is refused.
|
|
169
|
+
*/
|
|
170
|
+
getById(id: number): List;
|
|
171
|
+
/** @internal The read that answers this collection's members. */
|
|
172
|
+
protected listing(): AutomationOperation;
|
|
173
|
+
/** @internal Build one member from an address the listing answered. */
|
|
174
|
+
protected itemAt(label: string, address: ObjectAddress): List;
|
|
175
|
+
/** @internal A member an edge accessor named before the sync that finds it. */
|
|
176
|
+
protected promised(label: string, nullable: boolean): List & PromisedItem;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* A paragraph's membership of a list: which list, and at what level.
|
|
180
|
+
*
|
|
181
|
+
* `listString` (the "3." or "iv)" a reader sees) and `siblingIndex` are absent because they are
|
|
182
|
+
* PAINTED, not authored — computed during layout by a counter that walks the story applying
|
|
183
|
+
* `numbering.xml`, its abstract-numbering indirection, restarts and overrides. Answering them
|
|
184
|
+
* here would mean a second counter that disagrees with the one on screen the first time a
|
|
185
|
+
* document overrides a level.
|
|
186
|
+
*
|
|
187
|
+
* @public
|
|
188
|
+
*/
|
|
189
|
+
declare class ListItem extends ModelObject {
|
|
190
|
+
#private;
|
|
191
|
+
/** @internal The list membership of the paragraph `owner` addresses. */
|
|
192
|
+
static of(context: RequestContext, label: string, owner: ObjectPath): ListItem;
|
|
193
|
+
private constructor();
|
|
194
|
+
/**
|
|
195
|
+
* How deeply the item is nested: zero for a top-level item, up to eight.
|
|
196
|
+
*
|
|
197
|
+
* Writing it is Word's Increase/Decrease Indent on a list item — the paragraph keeps its list and
|
|
198
|
+
* changes its level, which is why this is one property rather than a pair of verbs.
|
|
199
|
+
*/
|
|
200
|
+
get level(): number;
|
|
201
|
+
set level(value: number);
|
|
202
|
+
/** @internal Plan the read this object's `load(...)` asked for. */
|
|
203
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** What the object is, which is what decides how its characters are named. */
|
|
207
|
+
type SpanOwner = 'body' | 'paragraph' | 'span';
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* The character formatting of whatever it belongs to: a story, a stretch of one, or a paragraph.
|
|
211
|
+
*
|
|
212
|
+
* A font has no identity of its own — it is a view onto its owner's characters and shares its
|
|
213
|
+
* owner's path, so a font reached from a deleted paragraph's range refuses at the same moment the
|
|
214
|
+
* range does rather than holding a stale address.
|
|
215
|
+
*
|
|
216
|
+
* Reading is AGREEMENT, and `null` means "no agreed value": every run the owner covers says bold,
|
|
217
|
+
* or the answer is null. Null is also the answer when nothing in range authors the property at
|
|
218
|
+
* all. Both are one answer on purpose, because this API reads what the document AUTHORS rather
|
|
219
|
+
* than what the style cascade computes — a heading whose bold comes from `styles.xml` reads null.
|
|
220
|
+
* Answering the cascade would let a caller read an inherited value, write it straight back, and
|
|
221
|
+
* silently freeze it into the paragraph as if the author had chosen it.
|
|
222
|
+
*
|
|
223
|
+
* Assignments within one `sync()` are ONE write: `font.bold = true; font.size = 12` accumulates
|
|
224
|
+
* into a single run-property operation. That is required, not an optimisation — a run-property
|
|
225
|
+
* write carries the run's whole property bag, so a second write planned from the same pre-batch
|
|
226
|
+
* tree would carry a bag the first had already superseded, which the host refuses with
|
|
227
|
+
* `ConflictingChanges`.
|
|
228
|
+
*
|
|
229
|
+
* @public
|
|
230
|
+
*/
|
|
231
|
+
declare class Font extends ModelObject {
|
|
232
|
+
#private;
|
|
233
|
+
/** @internal The font of the object `owner` addresses. */
|
|
234
|
+
static of(context: RequestContext, label: string, owner: ObjectPath, kind: SpanOwner): Font;
|
|
235
|
+
private constructor();
|
|
236
|
+
/** Whether every character agrees it is bold, or `null` where they do not. */
|
|
237
|
+
get bold(): boolean;
|
|
238
|
+
set bold(value: boolean);
|
|
239
|
+
/** Whether every run in range is italic. `null` where they disagree or none says. */
|
|
240
|
+
get italic(): boolean;
|
|
241
|
+
set italic(value: boolean);
|
|
242
|
+
/** `#RRGGBB`. `null` where the characters disagree, or where the colour is `auto`. */
|
|
243
|
+
get color(): string;
|
|
244
|
+
set color(value: string);
|
|
245
|
+
/** The typeface name the characters state, or `null` where they do not agree on one. */
|
|
246
|
+
get name(): string;
|
|
247
|
+
set name(value: string);
|
|
248
|
+
/** Points. */
|
|
249
|
+
get size(): number;
|
|
250
|
+
set size(value: number);
|
|
251
|
+
/**
|
|
252
|
+
* One read for every property asked for.
|
|
253
|
+
*
|
|
254
|
+
* They all come out of the same runs, so asking for them one at a time would send several
|
|
255
|
+
* operations about the same characters and make a caller's cost depend on how many fields they
|
|
256
|
+
* happened to name.
|
|
257
|
+
*/
|
|
258
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** Every place this API can insert at. Individual members accept a subset. */
|
|
262
|
+
type InsertLocation = 'Replace' | 'Start' | 'End' | 'Before' | 'After';
|
|
263
|
+
/** Where a story accepts text: over all of it, or at either edge. */
|
|
264
|
+
type BodyInsertTextLocation = Extract<InsertLocation, 'Replace' | 'Start' | 'End'>;
|
|
265
|
+
/** Where a story accepts a paragraph. `Start`/`End` mean "before the first"/"after the last". */
|
|
266
|
+
type BodyInsertParagraphLocation = Extract<InsertLocation, 'Start' | 'End'>;
|
|
267
|
+
/** Where a paragraph accepts text: over all of it, or at either edge of it. */
|
|
268
|
+
type ParagraphInsertTextLocation = Extract<InsertLocation, 'Replace' | 'Start' | 'End'>;
|
|
269
|
+
/** Which side of a paragraph or a range a new paragraph goes on. */
|
|
270
|
+
type BesideLocation = Extract<InsertLocation, 'Before' | 'After'>;
|
|
271
|
+
/** Where a range accepts text. See `Range#insertText` for what `Before`/`Start` mean here. */
|
|
272
|
+
type RangeInsertTextLocation = InsertLocation;
|
|
273
|
+
/** Where a selection lands: over the range, or collapsed to one of its edges. */
|
|
274
|
+
type SelectionMode = 'Select' | 'Start' | 'End';
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* A name a document gives to a stretch of itself.
|
|
278
|
+
*
|
|
279
|
+
* A bookmark IS its name. OOXML writes it as a pair of markers around the text, and the name is
|
|
280
|
+
* the only thing identifying it — so this object is a name plus the range those markers currently
|
|
281
|
+
* enclose. A bookmark whose markers left with the text they surrounded refuses rather than
|
|
282
|
+
* answering where they used to be.
|
|
283
|
+
*
|
|
284
|
+
* `start`, `end` and `delete` are absent by design: the first two are document-wide character
|
|
285
|
+
* offsets, the coordinate space this API does not maintain, and `delete` would have to remove a
|
|
286
|
+
* marker pair, which the canonical write path does not offer.
|
|
287
|
+
*
|
|
288
|
+
* @public
|
|
289
|
+
*/
|
|
290
|
+
declare class Bookmark extends ModelObject implements PromisedItem {
|
|
291
|
+
#private;
|
|
292
|
+
/** @internal A bookmark a read has already named. */
|
|
293
|
+
static at(context: RequestContext, label: string, address: ObjectAddress): Bookmark;
|
|
294
|
+
/** @internal A bookmark a queued read will name, or report as nothing. */
|
|
295
|
+
static promised(context: RequestContext, label: string, nullable: boolean): Bookmark;
|
|
296
|
+
private constructor();
|
|
297
|
+
/** @internal Bind this object to the address the owning read answered. */
|
|
298
|
+
hydrateAddress(address: ObjectAddress): void;
|
|
299
|
+
/** @internal Settle as the null object: the read found nothing to name. */
|
|
300
|
+
hydrateNull(): void;
|
|
301
|
+
/** The name the document declares this bookmark with. */
|
|
302
|
+
get name(): string;
|
|
303
|
+
/**
|
|
304
|
+
* The text the bookmark's markers enclose.
|
|
305
|
+
*
|
|
306
|
+
* Read when it is asked for rather than carried by the bookmark, because the markers move with the
|
|
307
|
+
* text: the range a caller gets is where the bookmark is now, not where it was when the collection
|
|
308
|
+
* was loaded.
|
|
309
|
+
*/
|
|
310
|
+
get range(): Range;
|
|
311
|
+
/** Put the reader's selection on the bookmark. `NotSupported` where there is no reader. */
|
|
312
|
+
select(selectionMode_?: SelectionMode): void;
|
|
313
|
+
/** @internal Plan the read this object's `load(...)` asked for. */
|
|
314
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* The bookmarks of a story or a range, as of the batch that loaded them.
|
|
318
|
+
*
|
|
319
|
+
* Like every collection here, `items` is the LOADED answer rather than a live view: bookmarks
|
|
320
|
+
* added after the load are not in it, and reaching them means loading again.
|
|
321
|
+
*
|
|
322
|
+
* @public
|
|
323
|
+
*/
|
|
324
|
+
declare class BookmarkCollection extends HandleCollection<Bookmark> {
|
|
325
|
+
#private;
|
|
326
|
+
/** @internal The bookmarks a scope holds: a whole story's, or the ones a range overlaps. */
|
|
327
|
+
static of(context: RequestContext, label: string, owner: ObjectPath, plan: () => AutomationOperation): BookmarkCollection;
|
|
328
|
+
private constructor();
|
|
329
|
+
/** @internal The read that answers this collection's members. */
|
|
330
|
+
protected listing(): AutomationOperation;
|
|
331
|
+
/** @internal Build one member from an address the listing answered. */
|
|
332
|
+
protected itemAt(label: string, address: ObjectAddress): Bookmark;
|
|
333
|
+
/** @internal A member an edge accessor named before the sync that finds it. */
|
|
334
|
+
protected promised(label: string, nullable: boolean): Bookmark & PromisedItem;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* How a search is narrowed.
|
|
339
|
+
*
|
|
340
|
+
* Every flag is honoured or REFUSED — never quietly ignored. A search that accepted
|
|
341
|
+
* `matchWildcards` and then ran a plain-text scan would answer the wrong offsets to a caller who
|
|
342
|
+
* edits at them, so the unimplemented options reach the host and come back as `NotSupported`.
|
|
343
|
+
*
|
|
344
|
+
* They are declared here rather than left off the type because omitting them would make
|
|
345
|
+
* `{ matchWildcards: true }` a compile error in code that is otherwise source-compatible with
|
|
346
|
+
* Word. The honest answer to that code is a runtime refusal naming the option, not a type error
|
|
347
|
+
* naming the interface.
|
|
348
|
+
*
|
|
349
|
+
* @public
|
|
350
|
+
*/
|
|
351
|
+
interface SearchOptions {
|
|
352
|
+
/** Match the query's case. Off by default, like Word's Find. */
|
|
353
|
+
readonly matchCase?: boolean;
|
|
354
|
+
/** Only match where the query stands alone as a word. */
|
|
355
|
+
readonly matchWholeWord?: boolean;
|
|
356
|
+
/** Not implemented; `true` is refused with `NotSupported`. */
|
|
357
|
+
readonly ignorePunct?: boolean;
|
|
358
|
+
/** Not implemented; `true` is refused with `NotSupported`. */
|
|
359
|
+
readonly ignoreSpace?: boolean;
|
|
360
|
+
/** Not implemented; `true` is refused with `NotSupported`. */
|
|
361
|
+
readonly matchWildcards?: boolean;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* A stretch of a story: two endpoints, each a paragraph and a UTF-16 offset.
|
|
366
|
+
*
|
|
367
|
+
* A range is a SNAPSHOT, not a tracked region. Its endpoints name the paragraphs they were found
|
|
368
|
+
* in and the offsets they were found at, so it stays meaningful across edits ELSEWHERE in the
|
|
369
|
+
* document and becomes an explicit `InvalidObjectPath` refusal once one of its paragraphs is
|
|
370
|
+
* gone. What it deliberately does not do is follow edits INSIDE itself: a range over `"alpha"`
|
|
371
|
+
* whose paragraph then gains a word at offset 0 still names offsets 0..5. Word's own ranges do
|
|
372
|
+
* move, by keeping a live region in the document; this API has none, and pretending otherwise
|
|
373
|
+
* would answer text from a place the caller was not looking at.
|
|
374
|
+
*
|
|
375
|
+
* That is also why `start` and `end` are absent rather than unimplemented — they are
|
|
376
|
+
* document-wide character positions, a different addressing scheme from this API's paragraph
|
|
377
|
+
* identity plus UTF-16 offset. Ask a range for its {@link Range.paragraphs} instead.
|
|
378
|
+
*
|
|
379
|
+
* @public
|
|
380
|
+
*/
|
|
381
|
+
declare class Range extends ModelObject implements PromisedItem {
|
|
382
|
+
#private;
|
|
383
|
+
/** @internal A range a read already found. */
|
|
384
|
+
static at(context: RequestContext, label: string, address: ObjectAddress): Range;
|
|
385
|
+
/** @internal A range a queued operation will name, or report as nothing. */
|
|
386
|
+
static promised(context: RequestContext, label: string, nullable: boolean): Range;
|
|
387
|
+
private constructor();
|
|
388
|
+
/** @internal Bind this object to the address the owning read answered. */
|
|
389
|
+
hydrateAddress(address: ObjectAddress): void;
|
|
390
|
+
/** @internal Settle as the null object: the read found nothing to name. */
|
|
391
|
+
hydrateNull(): void;
|
|
392
|
+
/**
|
|
393
|
+
* The text between this range's endpoints.
|
|
394
|
+
*
|
|
395
|
+
* A range that crosses paragraph marks reads a carriage return at each one, so counting
|
|
396
|
+
* characters in this string counts the same positions the engine writes at.
|
|
397
|
+
*/
|
|
398
|
+
get text(): string;
|
|
399
|
+
/** The character formatting of the characters this range covers. */
|
|
400
|
+
get font(): Font;
|
|
401
|
+
/** The paragraphs this range covers, in reading order. */
|
|
402
|
+
get paragraphs(): ParagraphCollection;
|
|
403
|
+
/**
|
|
404
|
+
* The paragraph style, by the name a reader sees in the styles gallery.
|
|
405
|
+
*
|
|
406
|
+
* Reading answers the name every paragraph this range covers agrees on, and `null` where they do not or
|
|
407
|
+
* where the document names no style. Writing applies it to all of them, and a name the document
|
|
408
|
+
* does not already define is refused rather than created — a minted style would report itself
|
|
409
|
+
* applied while the text stayed exactly as it looked.
|
|
410
|
+
*/
|
|
411
|
+
get style(): string;
|
|
412
|
+
set style(value: string);
|
|
413
|
+
/**
|
|
414
|
+
* The hyperlink over these characters: an absolute URL, or `#anchor` for a place in the document.
|
|
415
|
+
*
|
|
416
|
+
* `''` where the range is not in a link, and where it straddles two — a stretch covering parts of
|
|
417
|
+
* two different links has no one target, and answering either would be a guess.
|
|
418
|
+
*
|
|
419
|
+
* WRITING IT AUTHORS A LINK over exactly these characters, and `''` removes one. A URL whose
|
|
420
|
+
* scheme this engine would refuse to OPEN is refused here too, by the same allowlist: a document
|
|
421
|
+
* this API writes must not be one it would then decline to follow.
|
|
422
|
+
*/
|
|
423
|
+
get hyperlink(): string;
|
|
424
|
+
set hyperlink(value: string);
|
|
425
|
+
/** The bookmarks whose text this range overlaps, in document order. */
|
|
426
|
+
get bookmarks(): BookmarkCollection;
|
|
427
|
+
/** Every occurrence of `searchText` inside this range, as ranges. */
|
|
428
|
+
search(searchText: string, options?: SearchOptions): RangeCollection;
|
|
429
|
+
/**
|
|
430
|
+
* Write text at or over this range. Answers the range the written text occupies.
|
|
431
|
+
*
|
|
432
|
+
* `Before`/`Start` and `After`/`End` land at the SAME position here, and the difference Word
|
|
433
|
+
* draws between them — whether the new text becomes part of this range — has no meaning for a
|
|
434
|
+
* snapshot. Both pairs are accepted because source-compatible code uses all four; what a caller
|
|
435
|
+
* gets back is a range naming the text that was written, in every case.
|
|
436
|
+
*/
|
|
437
|
+
insertText(text: string, insertLocation: 'Replace' | 'Start' | 'End' | 'Before' | 'After'): Range;
|
|
438
|
+
/** Add a paragraph before or after the one this range starts or ends in. */
|
|
439
|
+
insertParagraph(paragraphText: string, insertLocation: 'Before' | 'After'): Paragraph;
|
|
440
|
+
/**
|
|
441
|
+
* Put the reader's selection on this range.
|
|
442
|
+
*
|
|
443
|
+
* Refused with `NotSupported` where there is no reader — a document opened from bytes on a
|
|
444
|
+
* server has no caret, and moving one would be a claim about a screen nobody is looking at. The
|
|
445
|
+
* check is at the CALL rather than at the sync, so the mistake is reported where it was made.
|
|
446
|
+
*/
|
|
447
|
+
select(selectionMode_?: SelectionMode): void;
|
|
448
|
+
/** @internal Plan the read this object's `load(...)` asked for. */
|
|
449
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/** Paragraph alignment values readable and writable through this object model. */
|
|
453
|
+
type ParagraphAlignment = 'Mixed' | 'Unknown' | 'Left' | 'Centered' | 'Right' | 'Justified';
|
|
454
|
+
/**
|
|
455
|
+
* One paragraph: what it says, what it is, and the ways it can be changed.
|
|
456
|
+
*
|
|
457
|
+
* Identity is the document's own. {@link Paragraph.uniqueLocalId} is the `w14:paraId` the file
|
|
458
|
+
* carries — the value Word writes, and the one `commentsExtended.xml` and coauthoring merges
|
|
459
|
+
* already anchor to — never a position in a collection. Deleting the paragraph above this one
|
|
460
|
+
* does not change it, which is the point: an agent that read a document, thought about it, and
|
|
461
|
+
* now wants to write to "the paragraph I was looking at" cannot express that with an index. A
|
|
462
|
+
* paragraph the file gave no id gets one deterministically at open, so the same bytes always
|
|
463
|
+
* answer the same identities and saving writes them back.
|
|
464
|
+
*
|
|
465
|
+
* A structural edit owns its paragraph for the batch: `delete()`, `split()` and
|
|
466
|
+
* `insertParagraph()` change what offsets mean, so a second call in the same `sync()` that also
|
|
467
|
+
* touches this paragraph is refused with `ConflictingChanges` rather than planned against
|
|
468
|
+
* coordinates that have stopped describing it. Two syncs get both edits, each exactly as asked.
|
|
469
|
+
*
|
|
470
|
+
* @public
|
|
471
|
+
*/
|
|
472
|
+
declare class Paragraph extends ModelObject implements PromisedItem {
|
|
473
|
+
#private;
|
|
474
|
+
/** @internal A paragraph a read has already named. */
|
|
475
|
+
static at(context: RequestContext, label: string, address: ObjectAddress): Paragraph;
|
|
476
|
+
/** @internal A paragraph a queued operation will name, or report as nothing. */
|
|
477
|
+
static promised(context: RequestContext, label: string, nullable: boolean): Paragraph;
|
|
478
|
+
private constructor();
|
|
479
|
+
/** @internal Bind this object to the address the owning read answered. */
|
|
480
|
+
hydrateAddress(address: ObjectAddress): void;
|
|
481
|
+
/** @internal Settle as the null object: the read found nothing to name. */
|
|
482
|
+
hydrateNull(): void;
|
|
483
|
+
/** This paragraph's text. Readable after `load('text')` and a `sync()`. */
|
|
484
|
+
get text(): string;
|
|
485
|
+
/**
|
|
486
|
+
* The document's own identity for this paragraph.
|
|
487
|
+
*
|
|
488
|
+
* Stable across edits elsewhere in the document and across a save and reopen, because it is
|
|
489
|
+
* written into the file rather than worked out from where the paragraph sits.
|
|
490
|
+
*/
|
|
491
|
+
get uniqueLocalId(): string;
|
|
492
|
+
/**
|
|
493
|
+
* The paragraph style, by the name a reader sees in the styles gallery.
|
|
494
|
+
*
|
|
495
|
+
* `null` where the document names none. A name it does not already define is refused rather than
|
|
496
|
+
* created, and the write rides the same `w:pPr` rewrite the alignment and indent members do — so
|
|
497
|
+
* applying a style and adjusting a spacing in one sync is one write rather than a refusal.
|
|
498
|
+
*/
|
|
499
|
+
get style(): string;
|
|
500
|
+
set style(value: string);
|
|
501
|
+
/** The character formatting of this paragraph's characters, and of its paragraph mark. */
|
|
502
|
+
get font(): Font;
|
|
503
|
+
/**
|
|
504
|
+
* How the paragraph's lines are aligned, or `Unknown` where it authors no alignment.
|
|
505
|
+
*
|
|
506
|
+
* `Unknown` rather than `Left`: a paragraph that states nothing may still be centred by its
|
|
507
|
+
* style, and naming a side would be a claim about the cascade this lane does not resolve.
|
|
508
|
+
*/
|
|
509
|
+
get alignment(): ParagraphAlignment;
|
|
510
|
+
set alignment(value: ParagraphAlignment);
|
|
511
|
+
/** Points. Negative for a hanging indent — the first line starting left of the rest. */
|
|
512
|
+
get firstLineIndent(): number;
|
|
513
|
+
set firstLineIndent(value: number);
|
|
514
|
+
/** Points. */
|
|
515
|
+
get leftIndent(): number;
|
|
516
|
+
set leftIndent(value: number);
|
|
517
|
+
/** Points. */
|
|
518
|
+
get rightIndent(): number;
|
|
519
|
+
set rightIndent(value: number);
|
|
520
|
+
/** Points between the paragraph's lines. */
|
|
521
|
+
get lineSpacing(): number;
|
|
522
|
+
set lineSpacing(value: number);
|
|
523
|
+
/** Points above the paragraph. */
|
|
524
|
+
get spaceBefore(): number;
|
|
525
|
+
set spaceBefore(value: number);
|
|
526
|
+
/** Points below the paragraph. */
|
|
527
|
+
get spaceAfter(): number;
|
|
528
|
+
set spaceAfter(value: number);
|
|
529
|
+
/**
|
|
530
|
+
* The list this paragraph is in.
|
|
531
|
+
*
|
|
532
|
+
* A paragraph in NO list refuses the batch (`InvalidArgument`), the way upstream's own accessor
|
|
533
|
+
* throws: a list a paragraph is not in has no members to answer, and a null object here would
|
|
534
|
+
* make "not numbered" indistinguishable from "numbered by a list this document has lost".
|
|
535
|
+
*/
|
|
536
|
+
get list(): List;
|
|
537
|
+
/** Where this paragraph sits in its list. Reading `level` on a paragraph in none refuses. */
|
|
538
|
+
get listItem(): ListItem;
|
|
539
|
+
/** Empty this paragraph's text, leaving the paragraph itself where it is. */
|
|
540
|
+
clear(): void;
|
|
541
|
+
/** Remove this paragraph and everything in it. */
|
|
542
|
+
delete(): void;
|
|
543
|
+
/** Write text over this paragraph or at either edge of it. Answers the written text's range. */
|
|
544
|
+
insertText(text: string, insertLocation: 'Replace' | 'Start' | 'End'): Range;
|
|
545
|
+
/** Add a paragraph beside this one. Answers the new paragraph. */
|
|
546
|
+
insertParagraph(paragraphText: string, insertLocation: 'Before' | 'After'): Paragraph;
|
|
547
|
+
/**
|
|
548
|
+
* Break this paragraph at every occurrence of any delimiter.
|
|
549
|
+
*
|
|
550
|
+
* Answers one range per resulting paragraph, in reading order, INCLUDING the piece that keeps
|
|
551
|
+
* this paragraph's identity — so a caller can read back what each piece became without having to
|
|
552
|
+
* work out which of them is the original. The collection is filled by the split itself: there is
|
|
553
|
+
* no second read, because a second read would describe the document the split had already made.
|
|
554
|
+
*/
|
|
555
|
+
split(delimiters: string[], trimDelimiters?: boolean, trimSpacing?: boolean): RangeCollection;
|
|
556
|
+
/** @internal Plan the read this object's `load(...)` asked for. */
|
|
557
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* The paragraphs of a story, a range, or a list, as of the batch that loaded them.
|
|
562
|
+
*
|
|
563
|
+
* Contains paragraphs at every depth — inside table cells, nested tables, and block-level content
|
|
564
|
+
* controls — matching Word's own collection rather than only the owner's direct children.
|
|
565
|
+
*
|
|
566
|
+
* One of the two collections whose members are not plain handles: the pieces a
|
|
567
|
+
* {@link Paragraph.split} answers are filled in by the split's own command rather than by a
|
|
568
|
+
* separate listing read.
|
|
569
|
+
*
|
|
570
|
+
* @public
|
|
571
|
+
*/
|
|
572
|
+
declare class ParagraphCollection extends ItemCollection<Paragraph> {
|
|
573
|
+
#private;
|
|
574
|
+
/** @internal A story's paragraphs, or a range's, depending on the path it derives from. */
|
|
575
|
+
static of(context: RequestContext, label: string, owner: ObjectPath): ParagraphCollection;
|
|
576
|
+
/**
|
|
577
|
+
* @internal Paragraphs a named read answers: a list's items, or one level of them.
|
|
578
|
+
*
|
|
579
|
+
* The owner's own address does not say which paragraphs are wanted — a list is not a place in the
|
|
580
|
+
* story, it is a set of them — so the operation is supplied instead of derived.
|
|
581
|
+
*/
|
|
582
|
+
static overListing(context: RequestContext, label: string, owner: ObjectPath, plan: () => AutomationOperation): ParagraphCollection;
|
|
583
|
+
private constructor();
|
|
584
|
+
/** The first paragraph. `ItemNotFound` at the sync if the collection holds none. */
|
|
585
|
+
getFirst(): Paragraph;
|
|
586
|
+
/** The last paragraph. `ItemNotFound` at the sync if the collection holds none. */
|
|
587
|
+
getLast(): Paragraph;
|
|
588
|
+
/** The first paragraph, or an object that will report `isNullObject`. */
|
|
589
|
+
getFirstOrNullObject(): Paragraph;
|
|
590
|
+
/** The last paragraph, or an object that will report `isNullObject`. */
|
|
591
|
+
getLastOrNullObject(): Paragraph;
|
|
592
|
+
/** @internal The read that answers this collection's members. */
|
|
593
|
+
protected listing(): AutomationOperation;
|
|
594
|
+
/** @internal How many members the listing's answer describes. */
|
|
595
|
+
protected size(value: AutomationValue, label: string): number;
|
|
596
|
+
/** @internal The address of one member of the listing's answer. */
|
|
597
|
+
protected addressAt(value: AutomationValue, label: string, index: number): ObjectAddress | undefined;
|
|
598
|
+
/** @internal Build one member from an address the listing answered. */
|
|
599
|
+
protected itemAt(label: string, address: ObjectAddress): Paragraph;
|
|
600
|
+
/** @internal A member an edge accessor named before the sync that finds it. */
|
|
601
|
+
protected promised(label: string, nullable: boolean): Paragraph & PromisedItem;
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Ranges a read produced — the hits of a search, or the pieces a split answered.
|
|
605
|
+
*
|
|
606
|
+
* Its members are SPANS rather than handles, which is what separates it from the handle-backed
|
|
607
|
+
* collections: each item carries its own paragraph-plus-offset endpoints instead of an opaque
|
|
608
|
+
* host-minted id.
|
|
609
|
+
*
|
|
610
|
+
* @public
|
|
611
|
+
*/
|
|
612
|
+
declare class RangeCollection extends ItemCollection<Range> {
|
|
613
|
+
#private;
|
|
614
|
+
/** @internal Ranges a read answers: where some text occurs. */
|
|
615
|
+
static of(context: RequestContext, label: string, owner: ObjectPath, plan: () => AutomationOperation): RangeCollection;
|
|
616
|
+
/** @internal Ranges a command answers: the pieces a split produced. Filled by that command. */
|
|
617
|
+
static answered(context: RequestContext, label: string, owner: ObjectPath): RangeCollection;
|
|
618
|
+
private constructor();
|
|
619
|
+
/** The first range. `ItemNotFound` at the sync if nothing matched. */
|
|
620
|
+
getFirst(): Range;
|
|
621
|
+
/**
|
|
622
|
+
* The last range. `ItemNotFound` at the sync if nothing matched.
|
|
623
|
+
*
|
|
624
|
+
* A DocxEditor member rather than a compatibility one: the reference's range collection publishes
|
|
625
|
+
* only its first, and the pieces of a split are the case that makes the other end worth having —
|
|
626
|
+
* "the paragraph this one ended up as" is the last piece, and counting `items` to find it means
|
|
627
|
+
* loading them all. Recorded as an omission in `compat/manifest.json` for that reason.
|
|
628
|
+
*/
|
|
629
|
+
getLast(): Range;
|
|
630
|
+
/** The first range, or an object that will report `isNullObject`. */
|
|
631
|
+
getFirstOrNullObject(): Range;
|
|
632
|
+
/** @internal The read that answers this collection's members. */
|
|
633
|
+
protected listing(): AutomationOperation | null;
|
|
634
|
+
/** @internal How many members the listing's answer describes. */
|
|
635
|
+
protected size(value: AutomationValue, label: string): number;
|
|
636
|
+
/** @internal The address of one member of the listing's answer. */
|
|
637
|
+
protected addressAt(value: AutomationValue, label: string, index: number): ObjectAddress | undefined;
|
|
638
|
+
/** @internal Build one member from an address the listing answered. */
|
|
639
|
+
protected itemAt(label: string, address: ObjectAddress): Range;
|
|
640
|
+
/** @internal A member an edge accessor named before the sync that finds it. */
|
|
641
|
+
protected promised(label: string, nullable: boolean): Range & PromisedItem;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* What a control's own type accepts as a value.
|
|
646
|
+
*
|
|
647
|
+
* A discriminated union rather than `unknown`: a dropdown and a checkbox do not take the same
|
|
648
|
+
* kind of thing, and a single `setValue(value: string)` would have to guess what `'true'` means
|
|
649
|
+
* to a date picker.
|
|
650
|
+
*/
|
|
651
|
+
type ContentControlValue = {
|
|
652
|
+
readonly kind: 'text';
|
|
653
|
+
readonly text: string;
|
|
654
|
+
} | {
|
|
655
|
+
readonly kind: 'listItem';
|
|
656
|
+
readonly value: string;
|
|
657
|
+
} | {
|
|
658
|
+
readonly kind: 'checkbox';
|
|
659
|
+
readonly checked: boolean;
|
|
660
|
+
}
|
|
661
|
+
/** `YYYY-MM-DD`, or a full ISO-8601 instant. */
|
|
662
|
+
| {
|
|
663
|
+
readonly kind: 'date';
|
|
664
|
+
readonly iso: string;
|
|
665
|
+
};
|
|
666
|
+
/** The lock a control carries. `ST_Lock`, spelled as the schema spells it. */
|
|
667
|
+
type ContentControlLockState = 'unlocked' | 'sdtLocked' | 'contentLocked' | 'sdtContentLocked';
|
|
668
|
+
/** The control types this API can create. Picture and repeating section are deferred. */
|
|
669
|
+
type ContentControlSubtype = 'richText' | 'plainText' | 'dropDownList' | 'comboBox' | 'date';
|
|
670
|
+
/**
|
|
671
|
+
* A part of a document a template marked as a field.
|
|
672
|
+
*
|
|
673
|
+
* A control is NOT its `w:id`. The attribute is optional in OOXML and unique nowhere, so a
|
|
674
|
+
* document may hold one control with no id and two with the same one. This object is addressed by
|
|
675
|
+
* an opaque host-minted handle instead, and {@link ContentControl.id} is answered as METADATA — a
|
|
676
|
+
* label the file wrote, empty where it wrote none. `getById` still exists, because a template
|
|
677
|
+
* author knows their own numbering, and it answers the first match in document order rather than
|
|
678
|
+
* refusing.
|
|
679
|
+
*
|
|
680
|
+
* A control's contents are not its value. `text` reads the characters; `setValue` writes in the
|
|
681
|
+
* vocabulary the control's own type accepts — a declared item for a dropdown, an ISO date for a
|
|
682
|
+
* date picker, a state for a checkbox — because writing `"true"` into a checkbox's runs would
|
|
683
|
+
* produce a document whose glyph and whose `w14:checked` disagree.
|
|
684
|
+
*
|
|
685
|
+
* @public
|
|
686
|
+
*/
|
|
687
|
+
declare class ContentControl extends ModelObject implements PromisedItem {
|
|
688
|
+
#private;
|
|
689
|
+
/** @internal A control a read has already named. */
|
|
690
|
+
static at(context: RequestContext, label: string, address: ObjectAddress): ContentControl;
|
|
691
|
+
/** @internal A control a queued read will name, or report as nothing. */
|
|
692
|
+
static promised(context: RequestContext, label: string, nullable: boolean): ContentControl;
|
|
693
|
+
private constructor();
|
|
694
|
+
/** @internal Bind this object to the address the owning read answered. */
|
|
695
|
+
hydrateAddress(address: ObjectAddress): void;
|
|
696
|
+
/** @internal Settle as the null object: the read found nothing to name. */
|
|
697
|
+
hydrateNull(): void;
|
|
698
|
+
/**
|
|
699
|
+
* The `w:id` the file wrote, as a string, and `''` where it wrote none.
|
|
700
|
+
*
|
|
701
|
+
* A STRING and not a number, deliberately. The identity of this object is its handle; a numeric
|
|
702
|
+
* `id` invites a caller to key a map on a value the schema lets a document repeat.
|
|
703
|
+
*/
|
|
704
|
+
get id(): string;
|
|
705
|
+
/** `w:tag` — the machine-readable label a template puts on a field. `''` where absent. */
|
|
706
|
+
get tag(): string;
|
|
707
|
+
set tag(value: string);
|
|
708
|
+
/** `w:alias` — what Word's UI calls the control's title. `''` where absent. */
|
|
709
|
+
get title(): string;
|
|
710
|
+
set title(value: string);
|
|
711
|
+
/** What kind of control it is: `plainText`, `dropDownList`, `checkbox`, `date`, … */
|
|
712
|
+
get subtype(): string;
|
|
713
|
+
/**
|
|
714
|
+
* Whether the control refuses to be deleted.
|
|
715
|
+
*
|
|
716
|
+
* Reads the lock IN FORCE, so a control an enclosing one protects reports true even when its
|
|
717
|
+
* own `w:lock` says otherwise — that is what the document does, and reporting the control's own
|
|
718
|
+
* half would tell a caller an edit will work when the store is about to refuse it.
|
|
719
|
+
*/
|
|
720
|
+
get cannotDelete(): boolean;
|
|
721
|
+
set cannotDelete(value: boolean);
|
|
722
|
+
/** Whether the control's contents refuse to be edited. Resolved like `cannotDelete`. */
|
|
723
|
+
get cannotEdit(): boolean;
|
|
724
|
+
set cannotEdit(value: boolean);
|
|
725
|
+
/**
|
|
726
|
+
* Whether the control is showing its prompt rather than a value (`w:showingPlcHdr`).
|
|
727
|
+
*
|
|
728
|
+
* STATE, not text. A control showing its placeholder holds the prompt in its runs, and the
|
|
729
|
+
* first thing written into it replaces the whole prompt — so a caller that treats `text` as a
|
|
730
|
+
* value must ask this before believing it.
|
|
731
|
+
*/
|
|
732
|
+
get placeholderShown(): boolean;
|
|
733
|
+
/** Whether the control removes its own wrapper on the first content edit (`w:temporary`). */
|
|
734
|
+
get temporary(): boolean;
|
|
735
|
+
/** The characters the control encloses, as the document reads them. */
|
|
736
|
+
get text(): string;
|
|
737
|
+
/** The paragraphs the control holds. Empty for an inline control, which holds none. */
|
|
738
|
+
get paragraphs(): ParagraphCollection;
|
|
739
|
+
/** The controls INSIDE this one, in document order. */
|
|
740
|
+
get contentControls(): ContentControlCollection;
|
|
741
|
+
/**
|
|
742
|
+
* The stretch of the story the control's content covers.
|
|
743
|
+
*
|
|
744
|
+
* Read when it is asked for rather than carried by the control, because the content moves as
|
|
745
|
+
* the document is edited: the range a caller gets is where the control is now.
|
|
746
|
+
*/
|
|
747
|
+
getRange(rangeLocation?: 'Whole' | 'Start' | 'End' | 'Before' | 'After' | 'Content'): Range;
|
|
748
|
+
/**
|
|
749
|
+
* Write the control's value.
|
|
750
|
+
*
|
|
751
|
+
* The refusals belong to the document, not to this method: a locked control, a control the file
|
|
752
|
+
* bound to custom XML, and a value the control's type does not accept are all refused by the
|
|
753
|
+
* engine's single write path, which is the same path a keystroke takes.
|
|
754
|
+
*/
|
|
755
|
+
setValue(value: ContentControlValue): void;
|
|
756
|
+
/**
|
|
757
|
+
* Put text into the control: over what it holds, or at one end of it.
|
|
758
|
+
*
|
|
759
|
+
* `Replace` goes through the control's own value path, so the prompt it was showing and a
|
|
760
|
+
* `w:temporary` wrapper are dealt with there rather than a second time here. The range comes
|
|
761
|
+
* back from the WRITE and not from a read beside it: reads answer the document as it is when
|
|
762
|
+
* the batch is planned, so a read here would name the text the write was about to replace.
|
|
763
|
+
*/
|
|
764
|
+
insertText(text: string, insertLocation: 'Replace' | 'Start' | 'End'): Range;
|
|
765
|
+
/**
|
|
766
|
+
* Remove the control.
|
|
767
|
+
*
|
|
768
|
+
* `keepContent` true is Word's own "Remove content control": the wrapper goes and the text it
|
|
769
|
+
* held stays exactly where it was. False takes the content with it.
|
|
770
|
+
*/
|
|
771
|
+
delete(keepContent: boolean): void;
|
|
772
|
+
/** @internal Plan the read this object's `load(...)` asked for. */
|
|
773
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
774
|
+
}
|
|
775
|
+
/** Where a collection of controls looks: a story, or inside one control. */
|
|
776
|
+
type ContentControlScope = {
|
|
777
|
+
readonly body: AutomationHandle;
|
|
778
|
+
} | {
|
|
779
|
+
readonly contentControl: AutomationHandle;
|
|
780
|
+
};
|
|
781
|
+
/**
|
|
782
|
+
* The content controls of a document, story or range, as of the batch that loaded them.
|
|
783
|
+
*
|
|
784
|
+
* `getById` answers the first match in document order, because `w:id` is optional in OOXML and
|
|
785
|
+
* unique nowhere — see {@link ContentControl} for why choosing predictably beats refusing.
|
|
786
|
+
*
|
|
787
|
+
* @public
|
|
788
|
+
*/
|
|
789
|
+
declare class ContentControlCollection extends HandleCollection<ContentControl> {
|
|
790
|
+
#private;
|
|
791
|
+
/** @internal The controls of a scope, in document order. */
|
|
792
|
+
static of(context: RequestContext, label: string, owner: ObjectPath, scope: ContentControlScope): ContentControlCollection;
|
|
793
|
+
private constructor();
|
|
794
|
+
/** The first control. `ItemNotFound` at the sync if the scope holds none. */
|
|
795
|
+
getFirst(): ContentControl;
|
|
796
|
+
/** The first control, or an object that says `isNullObject` where there is none. */
|
|
797
|
+
getFirstOrNullObject(): ContentControl;
|
|
798
|
+
/**
|
|
799
|
+
* The first control carrying one `w:id`, or `ItemNotFound` where the scope holds none.
|
|
800
|
+
*
|
|
801
|
+
* FIRST in document order, because `w:id` is not unique. The lookup is one read answered by the
|
|
802
|
+
* host: matching it here would mean asking every control for its id and choosing locally, which
|
|
803
|
+
* is a batch whose size depends on how many controls the document has.
|
|
804
|
+
*/
|
|
805
|
+
getById(id: number): ContentControl;
|
|
806
|
+
/** Every control in the scope carrying one tag, in document order. */
|
|
807
|
+
getByTag(tag: string): ContentControlCollection;
|
|
808
|
+
/** Every control in the scope carrying one title, in document order. */
|
|
809
|
+
getByTitle(title: string): ContentControlCollection;
|
|
810
|
+
/** @internal The read that answers this collection's members. */
|
|
811
|
+
protected listing(): AutomationOperation;
|
|
812
|
+
/** @internal Build one member from an address the listing answered. */
|
|
813
|
+
protected itemAt(label: string, address: ObjectAddress): ContentControl;
|
|
814
|
+
/** @internal A member an edge accessor named before the sync that finds it. */
|
|
815
|
+
protected promised(label: string, nullable: boolean): ContentControl & PromisedItem;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/** Which kind of note: Word's own two. */
|
|
819
|
+
type NoteItemType = 'Footnote' | 'Endnote';
|
|
820
|
+
/**
|
|
821
|
+
* One footnote or endnote: text that belongs to the document but not to its flow.
|
|
822
|
+
*
|
|
823
|
+
* A note IS a story. Its {@link NoteItem.body} is an ordinary {@link Body} — paragraphs,
|
|
824
|
+
* formatting, styles, the same operations — laid out at the foot of a page or the end of the
|
|
825
|
+
* document rather than in the column, so everything the object model can do to the main story it
|
|
826
|
+
* can do to a note without a second vocabulary.
|
|
827
|
+
*
|
|
828
|
+
* `delete()` removes the reference too. A note's body and the citation that reached it are one
|
|
829
|
+
* thing to a reader, and deleting the body alone would leave a mark pointing at nothing. The
|
|
830
|
+
* engine spells that as a package-level transaction, which is why it travels alone in its batch.
|
|
831
|
+
*
|
|
832
|
+
* @public
|
|
833
|
+
*/
|
|
834
|
+
declare class NoteItem extends ModelObject implements PromisedItem {
|
|
835
|
+
#private;
|
|
836
|
+
/** @internal A note a read has already named. */
|
|
837
|
+
static at(context: RequestContext, label: string, address: ObjectAddress): NoteItem;
|
|
838
|
+
/** @internal A note a queued read will name, or report as nothing. */
|
|
839
|
+
static promised(context: RequestContext, label: string, nullable: boolean): NoteItem;
|
|
840
|
+
private constructor();
|
|
841
|
+
/** @internal Bind this object to the address the owning read answered. */
|
|
842
|
+
hydrateAddress(address: ObjectAddress): void;
|
|
843
|
+
/** @internal Settle as the null object: the read found nothing to name. */
|
|
844
|
+
hydrateNull(): void;
|
|
845
|
+
/** Whether this is a footnote or an endnote. */
|
|
846
|
+
get type(): NoteItemType;
|
|
847
|
+
/** The note's own story. */
|
|
848
|
+
get body(): Body;
|
|
849
|
+
/**
|
|
850
|
+
* Remove the note and every reference to it.
|
|
851
|
+
*
|
|
852
|
+
* A package transaction, so it is the ONLY operation its `sync()` may carry — the host refuses it
|
|
853
|
+
* any company rather than committing half a batch. Two syncs get a delete and anything else.
|
|
854
|
+
*/
|
|
855
|
+
delete(): void;
|
|
856
|
+
/** The next note of the same kind. `ItemNotFound` at the sync when this is the last one. */
|
|
857
|
+
getNext(): NoteItem;
|
|
858
|
+
/** @internal Plan the read this object's `load(...)` asked for. */
|
|
859
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* The notes of one kind, in the order the notes part writes them.
|
|
863
|
+
*
|
|
864
|
+
* DocxEditor's own collection type: the pinned reference fixture does not carry
|
|
865
|
+
* `Word.NoteItemCollection`, so it is not measured for conformance — recorded as an omission in
|
|
866
|
+
* `compat/manifest.json` — while `NoteItem` itself is. Without it a note would be unreachable, which
|
|
867
|
+
* is the one thing worse than an unmeasured collection.
|
|
868
|
+
*/
|
|
869
|
+
declare class NoteItemCollection extends HandleCollection<NoteItem> {
|
|
870
|
+
#private;
|
|
871
|
+
/** @internal A collection a named read will answer. */
|
|
872
|
+
static of(context: RequestContext, label: string, owner: ObjectPath, plan: () => AutomationOperation): NoteItemCollection;
|
|
873
|
+
private constructor();
|
|
874
|
+
/** The first note. `ItemNotFound` at the sync if the document has none of this kind. */
|
|
875
|
+
getFirst(): NoteItem;
|
|
876
|
+
/** @internal The read that answers this collection's members. */
|
|
877
|
+
protected listing(): AutomationOperation;
|
|
878
|
+
/** @internal Build one member from an address the listing answered. */
|
|
879
|
+
protected itemAt(label: string, address: ObjectAddress): NoteItem;
|
|
880
|
+
/** @internal A member an edge accessor named before the sync that finds it. */
|
|
881
|
+
protected promised(label: string, nullable: boolean): NoteItem & PromisedItem;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* Word's own names for a kind of change.
|
|
886
|
+
*
|
|
887
|
+
* The WHOLE upstream vocabulary, because a declaration says what a caller may be handed and a caller
|
|
888
|
+
* switching on it should not have to be told which subset this engine happens to produce. Seven of
|
|
889
|
+
* these actually occur — insert, delete, replace, the two property kinds and the two move halves —
|
|
890
|
+
* because a change to a row, a cell or a section is structural, and this engine reports only the
|
|
891
|
+
* changes it can also accept or reject. See `compat/manifest.json`.
|
|
892
|
+
*/
|
|
893
|
+
type RevisionType = 'None' | 'Insert' | 'Delete' | 'Property' | 'ParagraphNumber' | 'DisplayField' | 'Reconcile' | 'Conflict' | 'Style' | 'Replace' | 'ParagraphProperty' | 'TableProperty' | 'SectionProperty' | 'StyleDefinition' | 'MovedFrom' | 'MovedTo' | 'CellInsertion' | 'CellDeletion' | 'CellMerge' | 'CellSplit' | 'ConflictInsert' | 'ConflictDelete';
|
|
894
|
+
/** What a comment and a reply both are: an author, a date, an id and a body. */
|
|
895
|
+
declare abstract class CommentBase extends ModelObject implements PromisedItem {
|
|
896
|
+
/** @internal Bind this object to the address the owning read answered. */
|
|
897
|
+
hydrateAddress(address: ObjectAddress): void;
|
|
898
|
+
/** @internal Settle as the null object: the read found nothing to name. */
|
|
899
|
+
hydrateNull(): void;
|
|
900
|
+
/** Who wrote it. Always present: `CT_TrackChange` makes the author mandatory. */
|
|
901
|
+
get authorName(): string;
|
|
902
|
+
/** When it was written, or `null` where the file recorded no date. */
|
|
903
|
+
get creationDate(): Date;
|
|
904
|
+
/** The document's own id for it (`w:id` in the comments part). */
|
|
905
|
+
get id(): string;
|
|
906
|
+
/**
|
|
907
|
+
* What it says, as plain text.
|
|
908
|
+
*
|
|
909
|
+
* DocxEditor's own member rather than upstream's `content`: upstream declares that one writable,
|
|
910
|
+
* and rewriting a comment body is not an operation this engine offers, so publishing a read-only
|
|
911
|
+
* `content` under the same name would be a quieter divergence than a differently named read.
|
|
912
|
+
*/
|
|
913
|
+
get text(): string;
|
|
914
|
+
protected loadCommentFields(request: ResolvedLoadOptions, extra: readonly string[]): void;
|
|
915
|
+
protected commentHandle(): AutomationHandle;
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* One answer in a comment thread.
|
|
919
|
+
*
|
|
920
|
+
* Authored over the parent comment's own range, because that is where the conversation is
|
|
921
|
+
* anchored and OOXML gives a reply no other place to be. Resolving is a property of the whole
|
|
922
|
+
* thread rather than of any one reply — see {@link Comment.resolved}.
|
|
923
|
+
*
|
|
924
|
+
* @public
|
|
925
|
+
*/
|
|
926
|
+
declare class CommentReply extends CommentBase {
|
|
927
|
+
/** @internal A reply a read has already named. */
|
|
928
|
+
static at(context: RequestContext, label: string, address: ObjectAddress): CommentReply;
|
|
929
|
+
/** @internal A reply a queued operation will name, or report as nothing. */
|
|
930
|
+
static promised(context: RequestContext, label: string, nullable: boolean): CommentReply;
|
|
931
|
+
private constructor();
|
|
932
|
+
/** @internal Plan the read this object's `load(...)` asked for. */
|
|
933
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* The replies to one comment, in thread order, as of the batch that loaded them.
|
|
937
|
+
*
|
|
938
|
+
* @public
|
|
939
|
+
*/
|
|
940
|
+
declare class CommentReplyCollection extends HandleCollection<CommentReply> {
|
|
941
|
+
#private;
|
|
942
|
+
/** @internal The replies to one comment, in document order. */
|
|
943
|
+
static of(context: RequestContext, label: string, owner: ObjectPath, plan: () => AutomationOperation): CommentReplyCollection;
|
|
944
|
+
private constructor();
|
|
945
|
+
/** The first reply. `ItemNotFound` at the sync if nobody answered. */
|
|
946
|
+
getFirst(): CommentReply;
|
|
947
|
+
/** @internal The read that answers this collection's members. */
|
|
948
|
+
protected listing(): AutomationOperation;
|
|
949
|
+
/** @internal Build one member from an address the listing answered. */
|
|
950
|
+
protected itemAt(label: string, address: ObjectAddress): CommentReply;
|
|
951
|
+
/** @internal A member an edge accessor named before the sync that finds it. */
|
|
952
|
+
protected promised(label: string, nullable: boolean): CommentReply & PromisedItem;
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* A comment: a conversation about a stretch of the document, not a single remark.
|
|
956
|
+
*
|
|
957
|
+
* {@link Comment.replies} holds the answers, and resolving is a property of the whole thread —
|
|
958
|
+
* assigning `resolved` marks this comment and everything answering it, which is what Word's own
|
|
959
|
+
* pane does.
|
|
960
|
+
*
|
|
961
|
+
* `authorEmail`, a writable `content`, and `delete` are absent: `CT_Comment` records only an
|
|
962
|
+
* author and initials (Word's addresses live in `people.xml`, which this API does not read), and
|
|
963
|
+
* neither a body rewrite nor a marker-pair removal is an operation the canonical write path
|
|
964
|
+
* offers. The comment's text is published as `text`.
|
|
965
|
+
*
|
|
966
|
+
* @public
|
|
967
|
+
*/
|
|
968
|
+
declare class Comment extends CommentBase {
|
|
969
|
+
#private;
|
|
970
|
+
/** @internal A comment a read has already named. */
|
|
971
|
+
static at(context: RequestContext, label: string, address: ObjectAddress): Comment;
|
|
972
|
+
/** @internal A comment a queued operation will name, or report as nothing. */
|
|
973
|
+
static promised(context: RequestContext, label: string, nullable: boolean): Comment;
|
|
974
|
+
private constructor();
|
|
975
|
+
/**
|
|
976
|
+
* Whether the thread is resolved.
|
|
977
|
+
*
|
|
978
|
+
* Assigning it resolves or reopens the WHOLE thread — this comment and its replies — because that
|
|
979
|
+
* is what resolving a conversation means, and marking the parent alone would leave a reply reading
|
|
980
|
+
* as open under a closed remark.
|
|
981
|
+
*/
|
|
982
|
+
get resolved(): boolean;
|
|
983
|
+
set resolved(value: boolean);
|
|
984
|
+
/** The answers to this comment, in document order. */
|
|
985
|
+
get replies(): CommentReplyCollection;
|
|
986
|
+
/** The words the comment is about. */
|
|
987
|
+
getRange(): Range;
|
|
988
|
+
/**
|
|
989
|
+
* Answer the comment, over the same words it is anchored to.
|
|
990
|
+
*
|
|
991
|
+
* The author is the one the request context was opened with: a reply records who wrote it, and
|
|
992
|
+
* `CT_TrackChange` makes that mandatory, so a context with no author refuses here rather than
|
|
993
|
+
* writing an anonymous remark the file cannot represent.
|
|
994
|
+
*/
|
|
995
|
+
reply(replyText: string): CommentReply;
|
|
996
|
+
/** @internal Plan the read this object's `load(...)` asked for. */
|
|
997
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
998
|
+
}
|
|
999
|
+
/**
|
|
1000
|
+
* The comments on a document, story or range, as of the batch that loaded them.
|
|
1001
|
+
*
|
|
1002
|
+
* @public
|
|
1003
|
+
*/
|
|
1004
|
+
declare class CommentCollection extends HandleCollection<Comment> {
|
|
1005
|
+
#private;
|
|
1006
|
+
/** @internal The comments of a scope: a whole story's, or the ones a range overlaps. */
|
|
1007
|
+
static of(context: RequestContext, label: string, owner: ObjectPath, plan: () => AutomationOperation): CommentCollection;
|
|
1008
|
+
private constructor();
|
|
1009
|
+
/** The first comment. `ItemNotFound` at the sync if there are none. */
|
|
1010
|
+
getFirst(): Comment;
|
|
1011
|
+
/** @internal The read that answers this collection's members. */
|
|
1012
|
+
protected listing(): AutomationOperation;
|
|
1013
|
+
/** @internal Build one member from an address the listing answered. */
|
|
1014
|
+
protected itemAt(label: string, address: ObjectAddress): Comment;
|
|
1015
|
+
/** @internal A member an edge accessor named before the sync that finds it. */
|
|
1016
|
+
protected promised(label: string, nullable: boolean): Comment & PromisedItem;
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* One tracked change, and a decision the engine can act on.
|
|
1020
|
+
*
|
|
1021
|
+
* Only revisions the engine can actually resolve are answered as objects. Structural ones — a
|
|
1022
|
+
* row, a cell, a section, the table grid — are omitted from the collection entirely rather than
|
|
1023
|
+
* shipped as objects whose `accept` and `reject` both refuse: code walking the collection would
|
|
1024
|
+
* stall on such an item with nothing to read that explains why.
|
|
1025
|
+
*
|
|
1026
|
+
* @public
|
|
1027
|
+
*/
|
|
1028
|
+
declare class Revision extends ModelObject implements PromisedItem {
|
|
1029
|
+
#private;
|
|
1030
|
+
/** @internal A change a read has already named. */
|
|
1031
|
+
static at(context: RequestContext, label: string, address: ObjectAddress): Revision;
|
|
1032
|
+
/** @internal A change a queued read will name, or report as nothing. */
|
|
1033
|
+
static promised(context: RequestContext, label: string, nullable: boolean): Revision;
|
|
1034
|
+
private constructor();
|
|
1035
|
+
/** @internal Bind this object to the address the owning read answered. */
|
|
1036
|
+
hydrateAddress(address: ObjectAddress): void;
|
|
1037
|
+
/** @internal Settle as the null object: the read found nothing to name. */
|
|
1038
|
+
hydrateNull(): void;
|
|
1039
|
+
/** Who proposed the change. */
|
|
1040
|
+
get author(): string;
|
|
1041
|
+
/** When they proposed it, or `null` where the file recorded no date. */
|
|
1042
|
+
get date(): Date;
|
|
1043
|
+
/** What kind of change it is, by Word's own name for it. */
|
|
1044
|
+
get type(): RevisionType;
|
|
1045
|
+
/** The words the change covers. */
|
|
1046
|
+
get range(): Range;
|
|
1047
|
+
/** Keep the change, resolving every site that carries its identity in one transaction. */
|
|
1048
|
+
accept(): void;
|
|
1049
|
+
/** Undo the change, likewise in one transaction. */
|
|
1050
|
+
reject(): void;
|
|
1051
|
+
/** @internal Plan the read this object's `load(...)` asked for. */
|
|
1052
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
1053
|
+
}
|
|
1054
|
+
/**
|
|
1055
|
+
* The tracked changes on a document, story or range, as of the batch that loaded them.
|
|
1056
|
+
*
|
|
1057
|
+
* Carries only the revisions the engine can resolve; see {@link Revision} for what is left out
|
|
1058
|
+
* and why.
|
|
1059
|
+
*
|
|
1060
|
+
* @public
|
|
1061
|
+
*/
|
|
1062
|
+
declare class RevisionCollection extends HandleCollection<Revision> {
|
|
1063
|
+
#private;
|
|
1064
|
+
/** @internal The pending decisions of one story. */
|
|
1065
|
+
static of(context: RequestContext, label: string, owner: ObjectPath, body: AutomationHandle, document: AutomationHandle): RevisionCollection;
|
|
1066
|
+
private constructor();
|
|
1067
|
+
/**
|
|
1068
|
+
* Keep every change, as ONE decision and one undo unit.
|
|
1069
|
+
*
|
|
1070
|
+
* The engine's own whole-document operation rather than a loop over `accept`: a reviewer who
|
|
1071
|
+
* accepted a document's changes made one decision, and one undo should take all of them back. It
|
|
1072
|
+
* refuses outright where the document holds a change the engine cannot resolve, which is the
|
|
1073
|
+
* honest answer — accepting the rest would report a document as reviewed while it still carries
|
|
1074
|
+
* pending changes.
|
|
1075
|
+
*/
|
|
1076
|
+
acceptAll(): void;
|
|
1077
|
+
/** Undo every change, likewise as one decision. */
|
|
1078
|
+
rejectAll(): void;
|
|
1079
|
+
/** @internal The read that answers this collection's members. */
|
|
1080
|
+
protected listing(): AutomationOperation;
|
|
1081
|
+
/** @internal Build one member from an address the listing answered. */
|
|
1082
|
+
protected itemAt(label: string, address: ObjectAddress): Revision;
|
|
1083
|
+
/** @internal A member an edge accessor named before the sync that finds it. */
|
|
1084
|
+
protected promised(label: string, nullable: boolean): Revision & PromisedItem;
|
|
1085
|
+
/** A collection is a `ClientObject` rather than a `ModelObject`, so it queues its own writes. */
|
|
1086
|
+
private commandOn;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
/**
|
|
1090
|
+
* Which way round a page is, in Word's own spelling.
|
|
1091
|
+
*
|
|
1092
|
+
* Capitalised here and lower-case in the engine on purpose: the engine speaks OOXML's vocabulary,
|
|
1093
|
+
* and this is the public API's. The mapping lives in this file and nowhere else.
|
|
1094
|
+
*/
|
|
1095
|
+
type PageOrientation = 'Portrait' | 'Landscape';
|
|
1096
|
+
/** Which header or footer of a section: Word's own three variants. */
|
|
1097
|
+
type HeaderFooterType = 'Primary' | 'FirstPage' | 'EvenPages';
|
|
1098
|
+
/**
|
|
1099
|
+
* The page a section is laid out on: paper size, margins, and orientation.
|
|
1100
|
+
*
|
|
1101
|
+
* This is `w:sectPr` — everything a caller usually wants from a section lives here rather than on
|
|
1102
|
+
* {@link Section} itself, which is mostly navigation.
|
|
1103
|
+
*
|
|
1104
|
+
* @public
|
|
1105
|
+
*/
|
|
1106
|
+
declare class PageSetup extends ModelObject {
|
|
1107
|
+
#private;
|
|
1108
|
+
/** @internal The page geometry of the section `owner` addresses. */
|
|
1109
|
+
static of(context: RequestContext, label: string, owner: ObjectPath): PageSetup;
|
|
1110
|
+
private constructor();
|
|
1111
|
+
/** Points. */
|
|
1112
|
+
get pageWidth(): number;
|
|
1113
|
+
set pageWidth(value: number);
|
|
1114
|
+
/** Points. */
|
|
1115
|
+
get pageHeight(): number;
|
|
1116
|
+
set pageHeight(value: number);
|
|
1117
|
+
/**
|
|
1118
|
+
* Which way round the page is.
|
|
1119
|
+
*
|
|
1120
|
+
* Writing it alone SWAPS this section's own dimensions rather than assuming a paper size, so a
|
|
1121
|
+
* document of mixed sizes survives a flip with its sizes intact.
|
|
1122
|
+
*/
|
|
1123
|
+
get orientation(): PageOrientation;
|
|
1124
|
+
set orientation(value: PageOrientation);
|
|
1125
|
+
/** Points. */
|
|
1126
|
+
get topMargin(): number;
|
|
1127
|
+
set topMargin(value: number);
|
|
1128
|
+
/** Points. */
|
|
1129
|
+
get bottomMargin(): number;
|
|
1130
|
+
set bottomMargin(value: number);
|
|
1131
|
+
/** Points. */
|
|
1132
|
+
get leftMargin(): number;
|
|
1133
|
+
set leftMargin(value: number);
|
|
1134
|
+
/** Points. */
|
|
1135
|
+
get rightMargin(): number;
|
|
1136
|
+
set rightMargin(value: number);
|
|
1137
|
+
/** @internal Plan the read this object's `load(...)` asked for. */
|
|
1138
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
1139
|
+
}
|
|
1140
|
+
/**
|
|
1141
|
+
* One section: the document's layout, not its content.
|
|
1142
|
+
*
|
|
1143
|
+
* Everything a caller usually wants — paper size, margins, orientation — is on
|
|
1144
|
+
* {@link Section.pageSetup}. The section itself is mostly navigation: the story it governs, the
|
|
1145
|
+
* header and footer stories it declares, and the section after it.
|
|
1146
|
+
*
|
|
1147
|
+
* `getHeader` and `getFooter` answer a body that may not exist yet, and say so. A section with no
|
|
1148
|
+
* first-page header inherits the previous section's; one at the start of a document with none at
|
|
1149
|
+
* all is refused with `ItemNotFound` rather than minting the part. Word creates the header when a
|
|
1150
|
+
* script asks for it — doing that here would make a READ write to the document, and a header that
|
|
1151
|
+
* exists only because it was asked about is a header the author never added.
|
|
1152
|
+
*
|
|
1153
|
+
* @public
|
|
1154
|
+
*/
|
|
1155
|
+
declare class Section extends ModelObject implements PromisedItem {
|
|
1156
|
+
#private;
|
|
1157
|
+
/** @internal A section a read has already named. */
|
|
1158
|
+
static at(context: RequestContext, label: string, address: ObjectAddress): Section;
|
|
1159
|
+
/** @internal A section a queued read will name, or report as nothing. */
|
|
1160
|
+
static promised(context: RequestContext, label: string, nullable: boolean): Section;
|
|
1161
|
+
private constructor();
|
|
1162
|
+
/** @internal Bind this object to the address the owning read answered. */
|
|
1163
|
+
hydrateAddress(address: ObjectAddress): void;
|
|
1164
|
+
/** @internal Settle as the null object: the read found nothing to name. */
|
|
1165
|
+
hydrateNull(): void;
|
|
1166
|
+
/**
|
|
1167
|
+
* The story this section governs.
|
|
1168
|
+
*
|
|
1169
|
+
* The MAIN story, which every section of a document shares: sections divide a body's layout, not
|
|
1170
|
+
* its text, so this is the same story `document.body` names rather than a slice of it.
|
|
1171
|
+
*/
|
|
1172
|
+
get body(): Body;
|
|
1173
|
+
/** The page this section is laid out on. */
|
|
1174
|
+
get pageSetup(): PageSetup;
|
|
1175
|
+
/** The header story of one variant, as a body. `ItemNotFound` where the document has none. */
|
|
1176
|
+
getHeader(type: HeaderFooterType): Body;
|
|
1177
|
+
/** The footer story of one variant, as a body. `ItemNotFound` where the document has none. */
|
|
1178
|
+
getFooter(type: HeaderFooterType): Body;
|
|
1179
|
+
/** The next section. `ItemNotFound` at the sync when this is the last one. */
|
|
1180
|
+
getNext(): Section;
|
|
1181
|
+
/** @internal Plan the read this object's `load(...)` asked for. */
|
|
1182
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
1183
|
+
}
|
|
1184
|
+
/**
|
|
1185
|
+
* The sections of a document, in document order, as of the batch that loaded them.
|
|
1186
|
+
*
|
|
1187
|
+
* @public
|
|
1188
|
+
*/
|
|
1189
|
+
declare class SectionCollection extends HandleCollection<Section> {
|
|
1190
|
+
#private;
|
|
1191
|
+
/** @internal The document's sections, in document order. */
|
|
1192
|
+
static of(context: RequestContext, label: string, owner: ObjectPath, plan: () => AutomationOperation): SectionCollection;
|
|
1193
|
+
private constructor();
|
|
1194
|
+
/** The first section. `ItemNotFound` at the sync if the document has none. */
|
|
1195
|
+
getFirst(): Section;
|
|
1196
|
+
/** @internal The read that answers this collection's members. */
|
|
1197
|
+
protected listing(): AutomationOperation;
|
|
1198
|
+
/** @internal Build one member from an address the listing answered. */
|
|
1199
|
+
protected itemAt(label: string, address: ObjectAddress): Section;
|
|
1200
|
+
/** @internal A member an edge accessor named before the sync that finds it. */
|
|
1201
|
+
protected promised(label: string, nullable: boolean): Section & PromisedItem;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
/**
|
|
1205
|
+
* The document: the root every other object is reached from.
|
|
1206
|
+
*
|
|
1207
|
+
* Deliberately thin. A document here is not a bag of content — it is the thing that HAS stories.
|
|
1208
|
+
* It publishes the main story as {@link Document.body}, plus that story's paragraphs directly as
|
|
1209
|
+
* `document.paragraphs`, because that is how source-compatible code walks a document.
|
|
1210
|
+
*
|
|
1211
|
+
* Reached once per {@link RequestContext} and memoized: `context.document` is the same object
|
|
1212
|
+
* every time, so a property loaded through one reference reads back through any other.
|
|
1213
|
+
*
|
|
1214
|
+
* @example
|
|
1215
|
+
* ```ts
|
|
1216
|
+
* await runtime.run(async (context) => {
|
|
1217
|
+
* const paragraphs = context.document.paragraphs;
|
|
1218
|
+
* paragraphs.load('text');
|
|
1219
|
+
* await context.sync();
|
|
1220
|
+
* for (const paragraph of paragraphs.items) console.log(paragraph.text);
|
|
1221
|
+
* });
|
|
1222
|
+
* ```
|
|
1223
|
+
*
|
|
1224
|
+
* @public
|
|
1225
|
+
*/
|
|
1226
|
+
declare class Document extends ModelObject {
|
|
1227
|
+
#private;
|
|
1228
|
+
/** @internal One per request context; the context memoizes it. */
|
|
1229
|
+
static open(context: RequestContext): Document;
|
|
1230
|
+
private constructor();
|
|
1231
|
+
/**
|
|
1232
|
+
* The main story.
|
|
1233
|
+
*
|
|
1234
|
+
* The same proxy every time, like every navigation property in this API: a consumer who loads
|
|
1235
|
+
* `document.body` and then reads `document.body.text` is talking about one object, and handing
|
|
1236
|
+
* back a fresh proxy per access would put the load on one and the read on another.
|
|
1237
|
+
*/
|
|
1238
|
+
get body(): Body;
|
|
1239
|
+
/** The main story's paragraphs, in reading order. */
|
|
1240
|
+
get paragraphs(): ParagraphCollection;
|
|
1241
|
+
/** The document's sections, in document order. */
|
|
1242
|
+
get sections(): SectionCollection;
|
|
1243
|
+
/** The content controls of the main story, in document order — the outermost ones. */
|
|
1244
|
+
get contentControls(): ContentControlCollection;
|
|
1245
|
+
/** The comments anchored in the main story, in document order. */
|
|
1246
|
+
get comments(): CommentCollection;
|
|
1247
|
+
/**
|
|
1248
|
+
* The tracked changes of the main story that the engine can resolve.
|
|
1249
|
+
*
|
|
1250
|
+
* Structural changes — a row, a cell, a section, the table grid — are not in it: they are ones the
|
|
1251
|
+
* engine refuses to accept or reject, and an item whose two verbs both refuse would stall code
|
|
1252
|
+
* walking the collection. `acceptAll`/`rejectAll` refuse outright where the document holds one,
|
|
1253
|
+
* rather than reporting a document as reviewed while pending changes remain.
|
|
1254
|
+
*/
|
|
1255
|
+
get revisions(): RevisionCollection;
|
|
1256
|
+
/**
|
|
1257
|
+
* The document's footnotes, in the order its notes part writes them.
|
|
1258
|
+
*
|
|
1259
|
+
* DocxEditor's own accessor: upstream reaches notes through `Body#footnotes`, whose collection type
|
|
1260
|
+
* the pinned reference fixture does not carry — see `compat/manifest.json`. Without an accessor a
|
|
1261
|
+
* note would be unreachable, so it is published here and recorded as unmeasured.
|
|
1262
|
+
*/
|
|
1263
|
+
get footnotes(): NoteItemCollection;
|
|
1264
|
+
/** The document's endnotes, in the order its notes part writes them. */
|
|
1265
|
+
get endnotes(): NoteItemCollection;
|
|
1266
|
+
/** @internal Plan the read this object's `load(...)` asked for. */
|
|
1267
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
/** What a `run` callback is given, and what it may answer with. */
|
|
1271
|
+
type RunCallback<T> = (context: RequestContext) => Promise<T>;
|
|
1272
|
+
/** Capabilities exposed by a DocxEditor runtime, frozen for its lifetime. */
|
|
1273
|
+
interface DocumentCapabilities {
|
|
1274
|
+
/** There is a document to address at all. False for a browser host between mounts. */
|
|
1275
|
+
readonly document: boolean;
|
|
1276
|
+
/** `save()` is offered — true for a server runtime, false for one borrowing an editor. */
|
|
1277
|
+
readonly save: boolean;
|
|
1278
|
+
/** The host raises document events. */
|
|
1279
|
+
readonly events: boolean;
|
|
1280
|
+
/** The host has a user selection to read or move. */
|
|
1281
|
+
readonly selection: boolean;
|
|
1282
|
+
/** The host can be scrolled to a position. */
|
|
1283
|
+
readonly scrolling: boolean;
|
|
1284
|
+
/** The host lays the document out, so paginated positions are meaningful. */
|
|
1285
|
+
readonly layout: boolean;
|
|
1286
|
+
}
|
|
1287
|
+
/**
|
|
1288
|
+
* A runtime: one document host, many runs.
|
|
1289
|
+
*
|
|
1290
|
+
* Runs are ISOLATED, not serialized. Every {@link DocxEditorRuntime.run} gets its own context and
|
|
1291
|
+
* its own queue, so two runs cannot interleave into one batch, and a run started inside another
|
|
1292
|
+
* run works instead of waiting for a lock its own caller holds. Batches are still ordered — each
|
|
1293
|
+
* `sync()` sends one atomic batch, in the order the `sync()` calls happen.
|
|
1294
|
+
*
|
|
1295
|
+
* Disposal is final: {@link DocxEditorRuntime.dispose} releases the host once and is safe to call
|
|
1296
|
+
* again, and every later `run` fails with `RuntimeDisposed`.
|
|
1297
|
+
*
|
|
1298
|
+
* @public
|
|
1299
|
+
*/
|
|
1300
|
+
interface DocxEditorRuntime {
|
|
1301
|
+
/** What the document host behind this runtime can do. Frozen at construction. */
|
|
1302
|
+
readonly capabilities: DocumentCapabilities;
|
|
1303
|
+
/** Run one batch of work against the document. Answers with the callback's value. */
|
|
1304
|
+
run<T>(callback: RunCallback<T>): Promise<T>;
|
|
1305
|
+
/** Run one batch of work, adopting objects a previous run tracked. */
|
|
1306
|
+
run<T>(object: ClientObject | readonly ClientObject[], callback: RunCallback<T>): Promise<T>;
|
|
1307
|
+
/** Release the host. Idempotent. */
|
|
1308
|
+
dispose(): void;
|
|
1309
|
+
}
|
|
1310
|
+
/**
|
|
1311
|
+
* A runtime over DOCX bytes rather than a live editor — what `DocxEditor.createServer` answers.
|
|
1312
|
+
*
|
|
1313
|
+
* Adds {@link DocxEditorServerRuntime.save} to the shared contract, because a server runtime owns
|
|
1314
|
+
* its document and can serialize it; a browser runtime borrows the editor's and cannot.
|
|
1315
|
+
*
|
|
1316
|
+
* @public
|
|
1317
|
+
*/
|
|
1318
|
+
interface DocxEditorServerRuntime extends DocxEditorRuntime {
|
|
1319
|
+
/** The current document as DOCX bytes. */
|
|
1320
|
+
save(): Promise<Uint8Array>;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
/**
|
|
1324
|
+
* The objects a context keeps addressable beyond the run that created them.
|
|
1325
|
+
*
|
|
1326
|
+
* An ordinary proxy stops being usable when its run ends. Tracking one keeps its address alive so
|
|
1327
|
+
* a later `run(object, callback)` can adopt it, and untracking releases it — which matters for
|
|
1328
|
+
* long-lived callers, since a tracked object is a document reference that will not be collected
|
|
1329
|
+
* on its own.
|
|
1330
|
+
*
|
|
1331
|
+
* @public
|
|
1332
|
+
*/
|
|
1333
|
+
declare class TrackedObjects {
|
|
1334
|
+
#private;
|
|
1335
|
+
/** @internal Built by the static factories above, never directly. */
|
|
1336
|
+
constructor(internals: ContextInternals, owns: (object: ClientObject) => boolean);
|
|
1337
|
+
/** Keep these objects usable after this run ends. */
|
|
1338
|
+
add(object: ClientObject | readonly ClientObject[]): void;
|
|
1339
|
+
/** Stop keeping them: they are released when this run ends, like any other object. */
|
|
1340
|
+
remove(object: ClientObject | readonly ClientObject[]): void;
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
/** What a context needs from the runtime that made it. */
|
|
1344
|
+
interface RuntimeSession {
|
|
1345
|
+
readonly host: AutomationHost;
|
|
1346
|
+
readonly capabilities: AutomationCapabilities;
|
|
1347
|
+
/** Who a comment this runtime writes is recorded as, or absent when it may not write one. */
|
|
1348
|
+
readonly author?: string;
|
|
1349
|
+
/** Identity for adoption checks. The session object itself. */
|
|
1350
|
+
readonly id: object;
|
|
1351
|
+
roots(): RootHandles;
|
|
1352
|
+
/** Refuse if the runtime has been disposed. */
|
|
1353
|
+
assertLive(target?: string): void;
|
|
1354
|
+
/**
|
|
1355
|
+
* Build the document proxy for a context.
|
|
1356
|
+
*
|
|
1357
|
+
* Injected rather than imported, so this module does not depend on the object model that
|
|
1358
|
+
* depends on it. The runtime composes the two; the context only knows it can ask for one.
|
|
1359
|
+
*/
|
|
1360
|
+
openDocument(context: RequestContext): Document;
|
|
1361
|
+
}
|
|
1362
|
+
/**
|
|
1363
|
+
* What a `run` hands its callback: one queue, one document, one sync at a time.
|
|
1364
|
+
*
|
|
1365
|
+
* `sync()` is the only thing in this runtime that talks to the document, and it does so exactly
|
|
1366
|
+
* once per call — plan the queued actions in order, send ONE batch, hydrate the answers. That is
|
|
1367
|
+
* where atomicity comes from: the host commits a batch as one transaction, and the runtime never
|
|
1368
|
+
* splits a consumer's `sync()` into several batches behind their back.
|
|
1369
|
+
*
|
|
1370
|
+
* Conditional writes come from the same place. A context that has READ from the document
|
|
1371
|
+
* remembers the revision it read at, and a later batch that writes goes out conditional on it,
|
|
1372
|
+
* failing `StaleDocument` if the document moved. That is what stops a decision made from a cached
|
|
1373
|
+
* read being applied to a document that has since changed — the hazard the read-decide-write
|
|
1374
|
+
* shape of any batching API invites. A context that has read nothing has nothing to be stale
|
|
1375
|
+
* about, so its writes go out unconditionally.
|
|
1376
|
+
*
|
|
1377
|
+
* @public
|
|
1378
|
+
*/
|
|
1379
|
+
declare class RequestContext {
|
|
1380
|
+
#private;
|
|
1381
|
+
private constructor();
|
|
1382
|
+
/**
|
|
1383
|
+
* The document this run is against.
|
|
1384
|
+
*
|
|
1385
|
+
* The SAME object for the life of the context, like every navigation property in this API: a
|
|
1386
|
+
* consumer who loads `context.document.body` and then reads its text is talking about one
|
|
1387
|
+
* object, and a fresh proxy per access would put the load on one and the read on another.
|
|
1388
|
+
*/
|
|
1389
|
+
get document(): Document;
|
|
1390
|
+
/** What the document host behind this context can do. */
|
|
1391
|
+
get capabilities(): DocumentCapabilities;
|
|
1392
|
+
/** Objects kept addressable past the run that created them. See {@link TrackedObjects}. */
|
|
1393
|
+
get trackedObjects(): TrackedObjects;
|
|
1394
|
+
/**
|
|
1395
|
+
* Send everything queued as one batch and hydrate the answers.
|
|
1396
|
+
*
|
|
1397
|
+
* An empty queue is not a round trip. Office-shaped code syncs defensively at the end of a
|
|
1398
|
+
* batch, and turning "nothing to say" into a host call would make a no-op sync advance a
|
|
1399
|
+
* revision and fire a change event for nobody.
|
|
1400
|
+
*/
|
|
1401
|
+
sync(): Promise<void>;
|
|
1402
|
+
/** @internal The seam proxies reach the context through. */
|
|
1403
|
+
get [INTERNALS](): ContextInternals;
|
|
1404
|
+
/** @internal Only `run` may build one, and only `run` may end one. */
|
|
1405
|
+
static begin(session: RuntimeSession): {
|
|
1406
|
+
context: RequestContext;
|
|
1407
|
+
adopt: (objects: readonly ClientObject[]) => void;
|
|
1408
|
+
finish: () => void;
|
|
1409
|
+
};
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
declare const INTERNALS: unique symbol;
|
|
1413
|
+
declare const RELEASE: unique symbol;
|
|
1414
|
+
declare const REBIND: unique symbol;
|
|
1415
|
+
/** The handles every object model starts from. Resolved once per runtime. */
|
|
1416
|
+
interface RootHandles {
|
|
1417
|
+
readonly document: AutomationHandle;
|
|
1418
|
+
readonly body: AutomationHandle;
|
|
1419
|
+
}
|
|
1420
|
+
/** What a proxy may ask of the context it belongs to. */
|
|
1421
|
+
interface ContextInternals {
|
|
1422
|
+
readonly host: AutomationHost;
|
|
1423
|
+
readonly capabilities: AutomationCapabilities;
|
|
1424
|
+
/**
|
|
1425
|
+
* Who a comment written through this context is recorded as, or absent when none was given.
|
|
1426
|
+
*
|
|
1427
|
+
* `CT_TrackChange` makes `@w:author` mandatory, and this API has no signed-in user, so a comment
|
|
1428
|
+
* write refuses (`NotSupported`) rather than putting a made-up name in the file.
|
|
1429
|
+
*/
|
|
1430
|
+
readonly author?: string;
|
|
1431
|
+
readonly queue: ActionQueue;
|
|
1432
|
+
/**
|
|
1433
|
+
* Identity of the runtime session behind this context.
|
|
1434
|
+
*
|
|
1435
|
+
* Compared, never called: it is how `run(object, ...)` refuses to adopt an object minted by a
|
|
1436
|
+
* different runtime, whose handles name a document this host never opened.
|
|
1437
|
+
*/
|
|
1438
|
+
readonly session: object;
|
|
1439
|
+
roots(): RootHandles;
|
|
1440
|
+
/**
|
|
1441
|
+
* Refuse if this context can no longer be used — its run finished, or the runtime was
|
|
1442
|
+
* disposed. `target` names the object or property the caller was reaching for.
|
|
1443
|
+
*/
|
|
1444
|
+
assertUsable(target?: string): void;
|
|
1445
|
+
/**
|
|
1446
|
+
* Whether this context's run has ended.
|
|
1447
|
+
*
|
|
1448
|
+
* Narrower than `assertUsable`, and asked by adoption for a reason: a LIVE context's objects are
|
|
1449
|
+
* still its own, and taking one would interleave that run's next call into another run's batch.
|
|
1450
|
+
*/
|
|
1451
|
+
isFinished(): boolean;
|
|
1452
|
+
/** The revision this context last read at, or `null` if it has never read. */
|
|
1453
|
+
readRevision(): number | null;
|
|
1454
|
+
register(object: RuntimeManagedObject): void;
|
|
1455
|
+
track(object: RuntimeManagedObject): void;
|
|
1456
|
+
untrack(object: RuntimeManagedObject): void;
|
|
1457
|
+
isTracked(object: RuntimeManagedObject): boolean;
|
|
1458
|
+
/**
|
|
1459
|
+
* Give up every claim on an object: it belongs to another context now.
|
|
1460
|
+
*
|
|
1461
|
+
* The other half of a rebind. Without it the object would still be in this context's registries
|
|
1462
|
+
* — two owners for one lifetime, one of which could release it out from under the other.
|
|
1463
|
+
*/
|
|
1464
|
+
disown(object: RuntimeManagedObject): void;
|
|
1465
|
+
}
|
|
1466
|
+
/** What a context may do to a proxy it owns. */
|
|
1467
|
+
interface RuntimeManagedObject {
|
|
1468
|
+
/** @internal Drop this object's document reference; the run that owned it has ended. */
|
|
1469
|
+
[RELEASE](): void;
|
|
1470
|
+
/** Adoption: this object now belongs to another run's context on the same runtime. */
|
|
1471
|
+
[REBIND](context: RequestContext): void;
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
/**
|
|
1475
|
+
* The object form of `load(...)`: which properties, and how much of a collection.
|
|
1476
|
+
*
|
|
1477
|
+
* An unknown key, a non-integer `top`, a property name that is not an identifier, or a value of
|
|
1478
|
+
* the wrong type is refused as `InvalidArgument` here, naming the option — a misspelled key is
|
|
1479
|
+
* the difference between "load selected properties" and "load nothing", which would otherwise
|
|
1480
|
+
* surface as a `PropertyNotLoaded` much later at a call that looks correct.
|
|
1481
|
+
*
|
|
1482
|
+
* @public
|
|
1483
|
+
*/
|
|
1484
|
+
interface LoadQueryOptions {
|
|
1485
|
+
/** Which properties to load. */
|
|
1486
|
+
readonly select?: string | readonly string[];
|
|
1487
|
+
/** Which navigation properties to load along with them. */
|
|
1488
|
+
readonly expand?: string | readonly string[];
|
|
1489
|
+
/** For a collection: at most this many items. */
|
|
1490
|
+
readonly top?: number;
|
|
1491
|
+
/** For a collection: skip this many items first. */
|
|
1492
|
+
readonly skip?: number;
|
|
1493
|
+
}
|
|
1494
|
+
/**
|
|
1495
|
+
* Everything `load(...)` accepts: one property name, several, or a
|
|
1496
|
+
* {@link LoadQueryOptions} object.
|
|
1497
|
+
*
|
|
1498
|
+
* @example
|
|
1499
|
+
* ```ts
|
|
1500
|
+
* paragraph.load('text');
|
|
1501
|
+
* paragraph.load(['text', 'style']);
|
|
1502
|
+
* paragraphs.load({ select: ['text'], top: 5 });
|
|
1503
|
+
* ```
|
|
1504
|
+
*
|
|
1505
|
+
* @public
|
|
1506
|
+
*/
|
|
1507
|
+
type LoadOption = string | readonly string[] | LoadQueryOptions;
|
|
1508
|
+
interface ResolvedLoadOptions {
|
|
1509
|
+
/** Selected property names. Empty means "this object's default set". */
|
|
1510
|
+
readonly select: readonly string[];
|
|
1511
|
+
readonly expand: readonly string[];
|
|
1512
|
+
readonly top?: number;
|
|
1513
|
+
readonly skip?: number;
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
/**
|
|
1517
|
+
* What the host is told to look at.
|
|
1518
|
+
*
|
|
1519
|
+
* Two shapes, because the protocol names two kinds of thing. Most objects ARE something the host
|
|
1520
|
+
* minted a handle for. A stretch of a story is not: it is two endpoints, each a paragraph handle
|
|
1521
|
+
* and a UTF-16 offset, and there is no third object behind it to hand out a handle for. Giving a
|
|
1522
|
+
* range a handle of its own would mean the host tracking a region across every edit, which is a
|
|
1523
|
+
* promise it cannot keep — so the address is the endpoints, and a deleted paragraph makes the
|
|
1524
|
+
* whole address refuse rather than silently name a different place.
|
|
1525
|
+
*/
|
|
1526
|
+
type ObjectAddress = {
|
|
1527
|
+
readonly kind: 'handle';
|
|
1528
|
+
readonly handle: AutomationHandle;
|
|
1529
|
+
} | {
|
|
1530
|
+
readonly kind: 'span';
|
|
1531
|
+
readonly span: AutomationSpan;
|
|
1532
|
+
};
|
|
1533
|
+
type ObjectPathState =
|
|
1534
|
+
/** Promised: created by a queued read that has not answered yet. */
|
|
1535
|
+
{
|
|
1536
|
+
readonly status: 'pending';
|
|
1537
|
+
}
|
|
1538
|
+
/** Addressable: the host has named this object, or the span it stands for is known. */
|
|
1539
|
+
| {
|
|
1540
|
+
readonly status: 'resolved';
|
|
1541
|
+
readonly address: ObjectAddress;
|
|
1542
|
+
}
|
|
1543
|
+
/** A `get…OrNullObject` that found nothing. Not an error, and never addressable. */
|
|
1544
|
+
| {
|
|
1545
|
+
readonly status: 'null';
|
|
1546
|
+
}
|
|
1547
|
+
/** Its run ended without tracking it. Terminal. */
|
|
1548
|
+
| {
|
|
1549
|
+
readonly status: 'released';
|
|
1550
|
+
};
|
|
1551
|
+
declare class ObjectPath {
|
|
1552
|
+
#private;
|
|
1553
|
+
readonly label: string;
|
|
1554
|
+
private constructor();
|
|
1555
|
+
/** A path that is addressable from the moment it exists — a root, or an item just hydrated. */
|
|
1556
|
+
static of(label: string, handle: AutomationHandle): ObjectPath;
|
|
1557
|
+
/** The same, for an object that IS a stretch of a story. */
|
|
1558
|
+
static ofSpan(label: string, span: AutomationSpan): ObjectPath;
|
|
1559
|
+
/** A path a queued read will fill in — or mark null. */
|
|
1560
|
+
static pending(label: string): ObjectPath;
|
|
1561
|
+
/** A path that is whatever its owner's path is, under its own name. */
|
|
1562
|
+
static derived(label: string, parent: ObjectPath): ObjectPath;
|
|
1563
|
+
get state(): ObjectPathState;
|
|
1564
|
+
get isAddressable(): boolean;
|
|
1565
|
+
get isPending(): boolean;
|
|
1566
|
+
get isNull(): boolean;
|
|
1567
|
+
get isReleased(): boolean;
|
|
1568
|
+
/**
|
|
1569
|
+
* What to put in a batch, or a refusal.
|
|
1570
|
+
*
|
|
1571
|
+
* Both refusals are `InvalidObjectPath` on purpose: from a consumer's side "this object was
|
|
1572
|
+
* released" and "this object is still a promise" are the same mistake — using an object the
|
|
1573
|
+
* runtime cannot address yet or any more — and the `target` says which object it was.
|
|
1574
|
+
*/
|
|
1575
|
+
address(): ObjectAddress;
|
|
1576
|
+
/** The handle to address this object with. Refused for anything that is not handle-shaped. */
|
|
1577
|
+
handle(): AutomationHandle;
|
|
1578
|
+
/** The span this object stands for. Refused for anything that is not span-shaped. */
|
|
1579
|
+
span(): AutomationSpan;
|
|
1580
|
+
/**
|
|
1581
|
+
* Hydration: the read answered, and this is the object it named.
|
|
1582
|
+
*
|
|
1583
|
+
* A released path stays released. Hydration arriving for one is not an error — a batch can be
|
|
1584
|
+
* in flight when a run ends — but resurrecting the object would hand back a proxy whose
|
|
1585
|
+
* lifetime rules had already been applied.
|
|
1586
|
+
*/
|
|
1587
|
+
resolveTo(handle: AutomationHandle): void;
|
|
1588
|
+
/** The same, for an object that came back as a stretch of a story. */
|
|
1589
|
+
resolveToSpan(span: AutomationSpan): void;
|
|
1590
|
+
/** Hydration: the read answered, and there was nothing there. */
|
|
1591
|
+
resolveNull(): void;
|
|
1592
|
+
/**
|
|
1593
|
+
* The run ended and nothing kept this object alive. Terminal.
|
|
1594
|
+
*
|
|
1595
|
+
* A derived path does not release: its owner's release is what governs it, and releasing here
|
|
1596
|
+
* would let a collection's lifetime end its parent's.
|
|
1597
|
+
*/
|
|
1598
|
+
release(): void;
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
/**
|
|
1602
|
+
* The base every document proxy extends.
|
|
1603
|
+
*
|
|
1604
|
+
* A proxy is three things and no more: the context it belongs to, the path that says whether it
|
|
1605
|
+
* can be addressed, and the properties a completed `load` filled in.
|
|
1606
|
+
*
|
|
1607
|
+
* A RELEASED proxy still answers what it already knew. Reading a property loaded before the run
|
|
1608
|
+
* ended is served from memory, because that value is a copy the consumer already holds — it is
|
|
1609
|
+
* not a reach into a document. Anything that would talk to the document (`load`, a write, a
|
|
1610
|
+
* method) refuses with `InvalidObjectPath`. The line is "does this need the document", not "does
|
|
1611
|
+
* this look like a read".
|
|
1612
|
+
*
|
|
1613
|
+
* @public
|
|
1614
|
+
*/
|
|
1615
|
+
declare abstract class ClientObject implements RuntimeManagedObject {
|
|
1616
|
+
#private;
|
|
1617
|
+
protected constructor(context: RequestContext, path: ObjectPath, options?: {
|
|
1618
|
+
readonly nullable?: boolean;
|
|
1619
|
+
});
|
|
1620
|
+
/** The context this object currently belongs to. */
|
|
1621
|
+
get context(): RequestContext;
|
|
1622
|
+
/**
|
|
1623
|
+
* Whether this object turned out not to exist.
|
|
1624
|
+
*
|
|
1625
|
+
* Only ever an answer, never a guess: an object that came from a `getItemOrNullObject` has no
|
|
1626
|
+
* verdict until the sync that looked for it, and reading one before then is
|
|
1627
|
+
* `PropertyNotLoaded` rather than a plausible `false`. Objects that are not "or null" are
|
|
1628
|
+
* never null, so they answer immediately.
|
|
1629
|
+
*/
|
|
1630
|
+
get isNullObject(): boolean;
|
|
1631
|
+
/**
|
|
1632
|
+
* Queue the reads that fill in the selected properties.
|
|
1633
|
+
*
|
|
1634
|
+
* Returns `this` so a load can be chained, and queues rather than fetches: the values are
|
|
1635
|
+
* readable after the next `sync()`, and reading before then is `PropertyNotLoaded`.
|
|
1636
|
+
*/
|
|
1637
|
+
load(option?: LoadOption): this;
|
|
1638
|
+
/** What this kind of object does with a resolved load request. */
|
|
1639
|
+
protected abstract onLoad(request: ResolvedLoadOptions): void;
|
|
1640
|
+
/** @internal This object's address, or the placeholder standing in until a sync resolves it. */
|
|
1641
|
+
protected get path(): ObjectPath;
|
|
1642
|
+
/** @internal The owning context's internal surface. */
|
|
1643
|
+
protected get internals(): ContextInternals;
|
|
1644
|
+
/** The handle to address this object with, or `InvalidObjectPath`. */
|
|
1645
|
+
protected handle(): AutomationHandle;
|
|
1646
|
+
/**
|
|
1647
|
+
* The check every call that talks to the document makes first.
|
|
1648
|
+
*
|
|
1649
|
+
* At the CALL, not at the sync: a consumer who writes to an object whose run has ended has
|
|
1650
|
+
* made the mistake already, and reporting it three lines later at `sync()` describes it as a
|
|
1651
|
+
* batch failure instead of as the bad call it was.
|
|
1652
|
+
*
|
|
1653
|
+
* THE OBJECT IS ASKED ABOUT BEFORE ITS CONTEXT, and the order is the answer to a real
|
|
1654
|
+
* question: an untracked object outside its run is BOTH released and holding a finished
|
|
1655
|
+
* context. `InvalidObjectPath` is the useful half — the object itself is gone, and no amount
|
|
1656
|
+
* of starting another run brings it back — whereas a tracked object in the same position is
|
|
1657
|
+
* perfectly good and only needs adopting, which is what `InvalidRequestContext` says.
|
|
1658
|
+
*/
|
|
1659
|
+
protected requireAddressable(): void;
|
|
1660
|
+
/** @internal Add one action to the context's queue, to be planned at the next sync. */
|
|
1661
|
+
protected enqueue(action: QueuedAction): void;
|
|
1662
|
+
/** @internal Read a property a completed `load` filled in; refuses if none did. */
|
|
1663
|
+
protected loadedProperty<T>(name: string): T;
|
|
1664
|
+
/** @internal Whether a completed `load` filled this property in. */
|
|
1665
|
+
protected hasLoadedProperty(name: string): boolean;
|
|
1666
|
+
/** @internal Record a value a completed load produced. */
|
|
1667
|
+
protected setLoadedProperty(name: string, value: unknown): void;
|
|
1668
|
+
/** @internal Drop this object's document reference; the run that owned it has ended. */
|
|
1669
|
+
[RELEASE](): void;
|
|
1670
|
+
/** @internal Adopt this object into another run's context. */
|
|
1671
|
+
[REBIND](context: RequestContext): void;
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
/**
|
|
1675
|
+
* A value a queued method promised to produce, readable after the next `sync()`.
|
|
1676
|
+
*
|
|
1677
|
+
* Deliberately not a `Promise`. A method call inside a batch has not been sent yet, so there is
|
|
1678
|
+
* no pending work to await and nothing that could resolve on its own — awaiting one would
|
|
1679
|
+
* deadlock a consumer who then never calls `sync()`. A result is a box that stays EMPTY until the
|
|
1680
|
+
* sync fills it, and reading it early is `ValueNotLoaded` rather than `undefined` flowing onwards
|
|
1681
|
+
* into something that misinterprets it.
|
|
1682
|
+
*
|
|
1683
|
+
* @example
|
|
1684
|
+
* ```ts
|
|
1685
|
+
* const count = body.getParagraphCount();
|
|
1686
|
+
* await context.sync();
|
|
1687
|
+
* console.log(count.value);
|
|
1688
|
+
* ```
|
|
1689
|
+
*
|
|
1690
|
+
* @public
|
|
1691
|
+
*/
|
|
1692
|
+
declare class ClientResult<T> {
|
|
1693
|
+
#private;
|
|
1694
|
+
/** @internal Use `clientResult()`; only the creator gets the filling half. */
|
|
1695
|
+
private constructor();
|
|
1696
|
+
/**
|
|
1697
|
+
* The value, once a `sync()` has filled it in.
|
|
1698
|
+
*
|
|
1699
|
+
* Reading before then is `ValueNotLoaded` rather than `undefined`, so a mistake surfaces at the
|
|
1700
|
+
* read instead of flowing onwards into something that misinterprets it.
|
|
1701
|
+
*/
|
|
1702
|
+
get value(): T;
|
|
1703
|
+
/** Whether the sync that fills this has happened. */
|
|
1704
|
+
get isLoaded(): boolean;
|
|
1705
|
+
/** @internal The box and the way to fill it, so only the creator can settle it. */
|
|
1706
|
+
static create<T>(target: string): {
|
|
1707
|
+
result: ClientResult<T>;
|
|
1708
|
+
fill: (value: T) => void;
|
|
1709
|
+
};
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
/** What went wrong, as a value a consumer may branch on. */
|
|
1713
|
+
type DocxEditorErrorCode =
|
|
1714
|
+
/** A property was read before a `load(...)` for it completed in a `sync()`. */
|
|
1715
|
+
'PropertyNotLoaded'
|
|
1716
|
+
/** A `ClientResult` value was read before the sync that fills it. */
|
|
1717
|
+
| 'ValueNotLoaded'
|
|
1718
|
+
/** The object is no longer addressable: its run ended and it was not tracked. */
|
|
1719
|
+
| 'InvalidObjectPath'
|
|
1720
|
+
/** The object still belongs to a run that has not finished, so it cannot be handed over. */
|
|
1721
|
+
| 'ObjectInUse'
|
|
1722
|
+
/** An argument or load option this API does not accept. */
|
|
1723
|
+
| 'InvalidArgument'
|
|
1724
|
+
/** The collection has no such item — `getFirst()` on an empty one. */
|
|
1725
|
+
| 'ItemNotFound'
|
|
1726
|
+
/** The host cannot do this at all — a capability it reports false. */
|
|
1727
|
+
| 'NotSupported'
|
|
1728
|
+
/**
|
|
1729
|
+
* The member exists in this API's shape but this version does not implement it.
|
|
1730
|
+
*
|
|
1731
|
+
* Distinct from `NotSupported`, which is about the HOST: a headless document really has no
|
|
1732
|
+
* caret, and no version of this library will give it one. This code means the library, not the
|
|
1733
|
+
* document, is the limit — so a consumer knows to check the release notes rather than the host.
|
|
1734
|
+
*/
|
|
1735
|
+
| 'NotImplemented'
|
|
1736
|
+
/**
|
|
1737
|
+
* Two calls in one batch make claims on the same paragraph that cannot both hold.
|
|
1738
|
+
*
|
|
1739
|
+
* A batch is one transaction planned against the state at its start, which stops being
|
|
1740
|
+
* unambiguous once two calls restructure the same paragraph. Split them across two `sync()`
|
|
1741
|
+
* calls and each gets exactly what it asked for.
|
|
1742
|
+
*/
|
|
1743
|
+
| 'ConflictingChanges'
|
|
1744
|
+
/** The request context's `run` has finished, so it can no longer be used. */
|
|
1745
|
+
| 'InvalidRequestContext'
|
|
1746
|
+
/** The runtime was disposed. Every later operation fails this way. */
|
|
1747
|
+
| 'RuntimeDisposed'
|
|
1748
|
+
/** The document moved under a context that had already read from it; nothing was applied. */
|
|
1749
|
+
| 'StaleDocument'
|
|
1750
|
+
/** The host is live but holds no document right now — an editor between mounts. */
|
|
1751
|
+
| 'DocumentUnavailable'
|
|
1752
|
+
/** The document refused the change, or answered something this runtime cannot use. */
|
|
1753
|
+
| 'GeneralException';
|
|
1754
|
+
/**
|
|
1755
|
+
* The fields a {@link DocxEditorError} is constructed from.
|
|
1756
|
+
*
|
|
1757
|
+
* @public
|
|
1758
|
+
*/
|
|
1759
|
+
interface DocxEditorErrorInit {
|
|
1760
|
+
/** Which refusal this is. The stable thing to branch on. */
|
|
1761
|
+
readonly code: DocxEditorErrorCode;
|
|
1762
|
+
/**
|
|
1763
|
+
* The consumer-facing path of the object or property involved — `document.body.text`, not a
|
|
1764
|
+
* handle. Omitted when there is nothing to name.
|
|
1765
|
+
*/
|
|
1766
|
+
readonly target?: string;
|
|
1767
|
+
/** The revision the context had read at, for `StaleDocument`. */
|
|
1768
|
+
readonly expectedRevision?: number;
|
|
1769
|
+
/** The revision the document was actually at, for `StaleDocument`. */
|
|
1770
|
+
readonly actualRevision?: number;
|
|
1771
|
+
}
|
|
1772
|
+
/**
|
|
1773
|
+
* Every refusal this runtime throws.
|
|
1774
|
+
*
|
|
1775
|
+
* Branch on {@link DocxEditorError.code}, never on the message. Codes are stable public API —
|
|
1776
|
+
* added rather than repurposed — so a consumer that handles `PropertyNotLoaded` by loading and
|
|
1777
|
+
* syncing again keeps working across versions.
|
|
1778
|
+
*
|
|
1779
|
+
* Nothing from the engine appears in the message. Host rejection reasons, opaque handle refs and
|
|
1780
|
+
* offset ranges are all withheld: a ref in a message is a name a consumer can start depending on,
|
|
1781
|
+
* and a store's rejection reason would become a documented one the moment somebody matched on it.
|
|
1782
|
+
* What a consumer gets instead is a stable code, a fixed sentence, and `target` — the
|
|
1783
|
+
* consumer-facing path they wrote themselves.
|
|
1784
|
+
*
|
|
1785
|
+
* @example
|
|
1786
|
+
* ```ts
|
|
1787
|
+
* try {
|
|
1788
|
+
* await context.sync();
|
|
1789
|
+
* } catch (error) {
|
|
1790
|
+
* if (error instanceof DocxEditorError && error.code === 'StaleDocument') {
|
|
1791
|
+
* // Re-read and retry: someone else changed the document first.
|
|
1792
|
+
* }
|
|
1793
|
+
* }
|
|
1794
|
+
* ```
|
|
1795
|
+
*
|
|
1796
|
+
* @public
|
|
1797
|
+
*/
|
|
1798
|
+
declare class DocxEditorError extends Error {
|
|
1799
|
+
/** Which refusal this is. Stable across versions; the thing to branch on. */
|
|
1800
|
+
readonly code: DocxEditorErrorCode;
|
|
1801
|
+
/** Consumer-facing path of the object or property involved, when there is one to name. */
|
|
1802
|
+
readonly target?: string;
|
|
1803
|
+
/** For `StaleDocument`: the revision the context had read at. */
|
|
1804
|
+
readonly expectedRevision?: number;
|
|
1805
|
+
/** For `StaleDocument`: the revision the document was actually at. */
|
|
1806
|
+
readonly actualRevision?: number;
|
|
1807
|
+
constructor(init: DocxEditorErrorInit);
|
|
1808
|
+
}
|
|
1809
|
+
/**
|
|
1810
|
+
* Whether a caught value is one of ours.
|
|
1811
|
+
*
|
|
1812
|
+
* By `name` as well as by `instanceof`: a consumer can end up with two copies of this module
|
|
1813
|
+
* (a bundle plus a dependency's), and an `instanceof` that fails across them would send a
|
|
1814
|
+
* perfectly ordinary `PropertyNotLoaded` down a consumer's unexpected-error path.
|
|
1815
|
+
*/
|
|
1816
|
+
declare function isDocxEditorError(value: unknown): value is DocxEditorError;
|
|
1817
|
+
|
|
1818
|
+
/**
|
|
1819
|
+
* A story: the main body of a document, a header or footer variant, or a note's body — and
|
|
1820
|
+
* everything in it in reading order.
|
|
1821
|
+
*
|
|
1822
|
+
* Its paragraphs are the DOCUMENT'S, not just the top level's. A paragraph inside a table cell,
|
|
1823
|
+
* or inside a table inside a cell, or inside a block-level content control, is an ordinary
|
|
1824
|
+
* editable paragraph and appears here, exactly as it does in Word's own paragraph collection. A
|
|
1825
|
+
* collection listing only direct children would describe a smaller document than the one on
|
|
1826
|
+
* screen.
|
|
1827
|
+
*
|
|
1828
|
+
* {@link Body.clear} leaves one empty paragraph, matching what Word produces when a reader
|
|
1829
|
+
* selects everything and deletes. A body that already holds no paragraph reports
|
|
1830
|
+
* `InvalidArgument` rather than inventing a block.
|
|
1831
|
+
*
|
|
1832
|
+
* @public
|
|
1833
|
+
*/
|
|
1834
|
+
declare class Body extends ModelObject {
|
|
1835
|
+
#private;
|
|
1836
|
+
/** @internal The main story of the document this context is running against. */
|
|
1837
|
+
static main(context: RequestContext, label: string): Body;
|
|
1838
|
+
/**
|
|
1839
|
+
* @internal A story a read will name: a header or footer variant, or a note's body.
|
|
1840
|
+
*
|
|
1841
|
+
* The OWNER queues that read — a section, a note — because a pending object cannot address the
|
|
1842
|
+
* document yet, and it is the owner that can. Like every object a batch produces in this runtime,
|
|
1843
|
+
* the story is addressable from the next batch on.
|
|
1844
|
+
*/
|
|
1845
|
+
static promisedStory(context: RequestContext, label: string): Body;
|
|
1846
|
+
/** @internal Bind this story to the handle the owner's read answered. */
|
|
1847
|
+
hydrateAddress(address: ObjectAddress): void;
|
|
1848
|
+
private constructor();
|
|
1849
|
+
/**
|
|
1850
|
+
* The whole story's text.
|
|
1851
|
+
*
|
|
1852
|
+
* Its paragraphs joined by a carriage return — one paragraph mark each — which is the separator
|
|
1853
|
+
* Word's own text property uses, so a caller counting characters counts what Word counts.
|
|
1854
|
+
*/
|
|
1855
|
+
get text(): string;
|
|
1856
|
+
/** Every paragraph in this story in reading order, at every depth. */
|
|
1857
|
+
get paragraphs(): ParagraphCollection;
|
|
1858
|
+
/** The character formatting of the whole story: what all of it agrees on, and what a write sets. */
|
|
1859
|
+
get font(): Font;
|
|
1860
|
+
/**
|
|
1861
|
+
* @internal A collection over this story under another name.
|
|
1862
|
+
*
|
|
1863
|
+
* `document.paragraphs` is the main story's paragraphs, and it is its OWN object: loading it must
|
|
1864
|
+
* not quietly load `document.body.paragraphs` too, and an error about it should say which of the
|
|
1865
|
+
* two the consumer wrote.
|
|
1866
|
+
*/
|
|
1867
|
+
paragraphsUnder(label: string): ParagraphCollection;
|
|
1868
|
+
/**
|
|
1869
|
+
* The paragraph style, by the name a reader sees in the styles gallery.
|
|
1870
|
+
*
|
|
1871
|
+
* Reading answers the name every paragraph in the story agrees on, and `null` where they do not or
|
|
1872
|
+
* where the document names no style. Writing applies it to all of them, and a name the document
|
|
1873
|
+
* does not already define is refused rather than created — a minted style would report itself
|
|
1874
|
+
* applied while the text stayed exactly as it looked.
|
|
1875
|
+
*/
|
|
1876
|
+
get style(): string;
|
|
1877
|
+
set style(value: string);
|
|
1878
|
+
/** Every list this story holds, in the order their numbers first appear. */
|
|
1879
|
+
get lists(): ListCollection;
|
|
1880
|
+
/**
|
|
1881
|
+
* The content controls this story holds, in document order — the OUTERMOST ones.
|
|
1882
|
+
*
|
|
1883
|
+
* A control inside another is reached through the control that holds it, because a flat list of
|
|
1884
|
+
* a story's controls makes a field and the group wrapping it look like siblings.
|
|
1885
|
+
*/
|
|
1886
|
+
get contentControls(): ContentControlCollection;
|
|
1887
|
+
/** The comments anchored in this story, in document order. Replies hang off the comment. */
|
|
1888
|
+
getComments(): CommentCollection;
|
|
1889
|
+
/**
|
|
1890
|
+
* The tracked changes in this story that the engine can resolve, in document order.
|
|
1891
|
+
*
|
|
1892
|
+
* DocxEditor's own accessor: upstream reaches revisions from the document, and this story-scoped
|
|
1893
|
+
* one is what makes a header's or a note's changes reachable at all. Recorded in
|
|
1894
|
+
* `compat/manifest.json`.
|
|
1895
|
+
*/
|
|
1896
|
+
get revisions(): RevisionCollection;
|
|
1897
|
+
/** Every occurrence of `searchText` in this story, as ranges, in reading order. */
|
|
1898
|
+
search(searchText: string, options?: SearchOptions): RangeCollection;
|
|
1899
|
+
/** Empty the story, leaving one empty paragraph behind. */
|
|
1900
|
+
clear(): void;
|
|
1901
|
+
/** Write text over the whole story, or at either edge of it. Answers the text's own range. */
|
|
1902
|
+
insertText(text: string, insertLocation: 'Replace' | 'Start' | 'End'): Range;
|
|
1903
|
+
/** Add a paragraph at the start or the end of the story. Answers the new paragraph. */
|
|
1904
|
+
insertParagraph(paragraphText: string, insertLocation: 'Start' | 'End'): Paragraph;
|
|
1905
|
+
/** @internal Plan the read this object's `load(...)` asked for. */
|
|
1906
|
+
protected onLoad(request: ResolvedLoadOptions): void;
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
/** Resource limits for the DOCX archive. */
|
|
1910
|
+
interface DocumentZipLimits {
|
|
1911
|
+
/** Most entries the archive may contain. */
|
|
1912
|
+
readonly maxEntries: number;
|
|
1913
|
+
/** Most bytes the archive may decompress to in total. */
|
|
1914
|
+
readonly maxTotalBytes: number;
|
|
1915
|
+
/** Highest tolerated decompression ratio — the zip-bomb guard. */
|
|
1916
|
+
readonly maxRatio?: number;
|
|
1917
|
+
}
|
|
1918
|
+
/** Resource limits for each parsed XML part. */
|
|
1919
|
+
interface DocumentXmlLimits {
|
|
1920
|
+
/** Most bytes any one XML part may be. */
|
|
1921
|
+
readonly maxBytes: number;
|
|
1922
|
+
/** Most elements any one XML part may contain. */
|
|
1923
|
+
readonly maxElements?: number;
|
|
1924
|
+
}
|
|
1925
|
+
/** Optional tighter limits applied while opening untrusted DOCX bytes. */
|
|
1926
|
+
interface DocumentLimits {
|
|
1927
|
+
/** Archive-level caps. */
|
|
1928
|
+
readonly zip?: DocumentZipLimits;
|
|
1929
|
+
/** Per-part XML caps. */
|
|
1930
|
+
readonly xml?: DocumentXmlLimits;
|
|
1931
|
+
/** Most XML parts the package may hold. */
|
|
1932
|
+
readonly maxXmlParts?: number;
|
|
1933
|
+
/** Most relationships the package may declare. */
|
|
1934
|
+
readonly maxRelationships?: number;
|
|
1935
|
+
}
|
|
1936
|
+
/**
|
|
1937
|
+
* How `DocxEditor.createServer` opens a document.
|
|
1938
|
+
*
|
|
1939
|
+
* Opening DOCX bytes is a bounded parse: decompression-ratio and size caps, part and relationship
|
|
1940
|
+
* path validation, DTD- and entity-free XML. A refusal comes back as `InvalidArgument` rather
|
|
1941
|
+
* than as a throw from inside a zip decoder, and says nothing about WHY — a caller opening files
|
|
1942
|
+
* they did not author gets "not a document this API can open", so a probe cannot use the error to
|
|
1943
|
+
* learn the reader's limits.
|
|
1944
|
+
*
|
|
1945
|
+
* @public
|
|
1946
|
+
*/
|
|
1947
|
+
interface CreateServerOptions {
|
|
1948
|
+
/**
|
|
1949
|
+
* Tighter budgets for the bounded reader — zip ratio, part count, XML depth.
|
|
1950
|
+
*
|
|
1951
|
+
* Exposed because a server opening documents it did not author is exactly where a caller may
|
|
1952
|
+
* want smaller limits than the defaults. Omitted means the engine's own defaults.
|
|
1953
|
+
*/
|
|
1954
|
+
readonly limits?: DocumentLimits;
|
|
1955
|
+
/**
|
|
1956
|
+
* Who comments this runtime writes are recorded as.
|
|
1957
|
+
*
|
|
1958
|
+
* Required to write one at all: `CT_TrackChange` makes `@w:author` mandatory and a server has no
|
|
1959
|
+
* signed-in user, so a runtime opened without this refuses comment writes rather than putting a
|
|
1960
|
+
* placeholder name into someone's document.
|
|
1961
|
+
*/
|
|
1962
|
+
readonly author?: string;
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
export { type SearchOptions as $, ListItem as A, type BesideLocation as B, type CreateServerOptions as C, type DocxEditorServerRuntime as D, type LoadOption as E, Font as F, type LoadQueryOptions as G, type HeaderFooterType as H, type InsertLocation as I, NoteItemCollection as J, type NoteItemType as K, List as L, PageSetup as M, NoteItem as N, Paragraph as O, type PageOrientation as P, type ParagraphAlignment as Q, ParagraphCollection as R, type ParagraphInsertTextLocation as S, Range as T, RangeCollection as U, type RangeInsertTextLocation as V, RequestContext as W, Revision as X, RevisionCollection as Y, type RevisionType as Z, type RunCallback as _, Body as a, Section as a0, SectionCollection as a1, type SelectionMode as a2, TrackedObjects as a3, isDocxEditorError as a4, type BodyInsertParagraphLocation as b, type BodyInsertTextLocation as c, Bookmark as d, BookmarkCollection as e, ClientObject as f, ClientResult as g, Comment as h, CommentCollection as i, CommentReply as j, CommentReplyCollection as k, ContentControl as l, ContentControlCollection as m, type ContentControlLockState as n, type ContentControlSubtype as o, type ContentControlValue as p, Document as q, type DocumentCapabilities as r, type DocumentLimits as s, type DocumentXmlLimits as t, type DocumentZipLimits as u, DocxEditorError as v, type DocxEditorErrorCode as w, type DocxEditorErrorInit as x, type DocxEditorRuntime as y, ListCollection as z };
|