@docx-editor.dev/core 2.19.1 → 2.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -32
- package/dist/automation.cjs +1 -1
- package/dist/automation.d.ts +11 -9
- package/dist/automation.js +1 -1
- package/dist/binding.cjs +1 -1
- package/dist/binding.d.ts +9 -10
- package/dist/binding.js +1 -1
- package/dist/chunk-44LQJIKH.cjs +20 -0
- package/dist/chunk-4EHMMSFR.cjs +1 -0
- package/dist/chunk-AFG7Q622.cjs +2 -0
- package/dist/chunk-AJCCS53D.js +1 -0
- package/dist/chunk-AYMSP25Q.js +4 -0
- package/dist/{chunk-GWW5FOLJ.cjs → chunk-B4KZSKF7.cjs} +5 -5
- package/dist/chunk-BDAY2ETZ.js +1 -0
- package/dist/chunk-BNZF6DYC.cjs +18 -0
- package/dist/chunk-BQXF2PFF.js +2 -0
- package/dist/chunk-GIHKVXEO.js +2 -0
- package/dist/chunk-ITNK6C5M.cjs +3 -0
- package/dist/chunk-MP3K4LC5.js +1 -0
- package/dist/chunk-MXOO7KRI.cjs +11 -0
- package/dist/chunk-NG6IQ4SI.js +11 -0
- package/dist/{chunk-NIVIC7PA.cjs → chunk-PYXMAUNR.cjs} +1 -1
- package/dist/chunk-Q2B6HX3R.js +1 -0
- package/dist/chunk-Q5JPPUNR.js +5 -0
- package/dist/chunk-S35UK656.cjs +2 -0
- package/dist/chunk-S6J4O5XP.js +1 -0
- package/dist/chunk-TE43S3LX.cjs +1 -0
- package/dist/chunk-TKQH7BNE.cjs +1 -0
- package/dist/chunk-UKVVUHZL.cjs +1 -0
- package/dist/chunk-VH2DLEZK.js +20 -0
- package/dist/{chunk-BUNY5MRX.js → chunk-VUNFWXHF.js} +1 -1
- package/dist/{chunk-JWHXOJEU.cjs → chunk-WQFNWLNY.cjs} +3 -3
- package/dist/chunk-WZX4UGRQ.js +3 -0
- package/dist/{chunk-2QU7QTM7.js → chunk-X5QNSISI.js} +1 -1
- package/dist/chunk-XS4FOHH6.js +18 -0
- package/dist/{chunk-7VO6BLKV.cjs → chunk-XZY4Q6PJ.cjs} +1 -1
- package/dist/{chunk-76F73CY6.cjs → chunk-Z2ETEZRU.cjs} +1 -1
- package/dist/collaboration/replication.cjs +1 -1
- package/dist/collaboration/replication.d.ts +13 -4
- package/dist/collaboration/replication.js +1 -1
- package/dist/collaboration.d.ts +4 -3
- package/dist/contracts/document.d.ts +3 -2
- package/dist/contracts/editor.cjs +1 -1
- package/dist/contracts/editor.d.ts +9 -10
- package/dist/contracts/editor.js +1 -1
- package/dist/contracts/interaction.d.ts +2 -2
- package/dist/contracts/modules.cjs +1 -1
- package/dist/contracts/modules.d.ts +9 -9
- package/dist/contracts/modules.js +1 -1
- package/dist/contracts/types.d.ts +2 -562
- package/dist/{custom-node-writes-BqIv94ei.d.ts → custom-node-writes-05qS32px.d.ts} +2 -2
- package/dist/{document-protection-BL5zp8cU.d.ts → document-protection-Cr59VKLO.d.ts} +1 -1
- package/dist/{editor-WXbTSXx1.d.ts → editor-BsLSz_7y.d.ts} +43 -39
- package/dist/editor-scope-OHPwVQ5l.d.ts +84 -0
- package/dist/editor.cjs +1 -1
- package/dist/editor.css +1 -1
- package/dist/editor.d.ts +130 -29
- package/dist/editor.js +1 -1
- package/dist/export.cjs +2 -2
- package/dist/export.d.ts +13 -14
- package/dist/export.js +1 -1
- package/dist/{font-resolver-BSrKnTeR.d.ts → font-resolver-CzwdBJDE.d.ts} +1 -1
- package/dist/{headless-document-view-C4ttQJ5H.d.ts → headless-document-view-B7nAiR7P.d.ts} +2 -2
- package/dist/image-resources-C4ilLzog.d.ts +210 -0
- package/dist/{index-C3As-Xxp.d.ts → index-zkvqBQ9o.d.ts} +117 -27
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +18 -19
- package/dist/index.js +1 -1
- package/dist/{layout-shaping-Dqu3JW3p.d.ts → layout-shaping-BJKVTI6i.d.ts} +1 -1
- package/dist/layout.cjs +1 -1
- package/dist/layout.d.ts +72 -20
- package/dist/layout.js +1 -1
- package/dist/{note-properties-RjYgbmXe.d.ts → note-properties-MNztEj5s.d.ts} +2 -2
- package/dist/{omml-equation-hcP9AUFX.d.ts → omml-equation-CbnW9yXd.d.ts} +1 -1
- package/dist/output.cjs +1 -1
- package/dist/output.d.ts +8 -7
- package/dist/output.js +1 -1
- package/dist/{protocol-OdRd17KZ.d.ts → protocol-Co_r0SZQ.d.ts} +14 -4
- package/dist/{review-paragraph-order--jLHXIcd.d.ts → review-paragraph-order-EFaU7TqH.d.ts} +2 -3
- package/dist/{revision-projection-BIHO_qvw.d.ts → revision-projection-DEIvpxiq.d.ts} +16 -2
- package/dist/{semantic-cell-selection-lCYAVCCF.d.ts → semantic-cell-selection-DXmfnDCw.d.ts} +9 -4
- package/dist/{semantic-interaction-0vQXcMZk.d.ts → semantic-interaction-BLu3M6Nn.d.ts} +1 -1
- package/dist/{semantic-paint-BSan4pBk.d.ts → semantic-paint-CPsihA6k.d.ts} +18 -2
- package/dist/{semantic-records-ZcYuB4-H.d.ts → semantic-records-CqD0b5Ex.d.ts} +147 -6
- package/dist/store.cjs +1 -1
- package/dist/store.d.ts +462 -428
- package/dist/store.js +1 -1
- package/dist/{tree-package-fragment-1pdDnhZ_.d.ts → tree-package-fragment-CwJDixNs.d.ts} +44 -3
- package/dist/{tree-session-contract-Cgn6fQ-M.d.ts → tree-session-contract-D9RRWE0C.d.ts} +8 -8
- package/dist/{tree-op-types-DbdM7fJV.d.ts → types-barrel-DLB11iSY.d.ts} +1455 -660
- package/package.json +2 -2
- package/dist/chunk-3JKOZBQ3.cjs +0 -1
- package/dist/chunk-3SU7UWCR.js +0 -1
- package/dist/chunk-5BI4SIHO.cjs +0 -1
- package/dist/chunk-6ESSCMXL.js +0 -2
- package/dist/chunk-6W4DIR4X.cjs +0 -2
- package/dist/chunk-AKQRKR2H.js +0 -1
- package/dist/chunk-BJQDNKEX.js +0 -5
- package/dist/chunk-D5EHDHYV.js +0 -1
- package/dist/chunk-FBWBSHC4.cjs +0 -11
- package/dist/chunk-GOEBQ26R.js +0 -1
- package/dist/chunk-IA7WTZHI.js +0 -11
- package/dist/chunk-IXGUCLER.js +0 -20
- package/dist/chunk-NDPLQG4Y.cjs +0 -18
- package/dist/chunk-NLGUL6QL.js +0 -3
- package/dist/chunk-OHJQ7GPZ.cjs +0 -1
- package/dist/chunk-OWUSDS3L.cjs +0 -20
- package/dist/chunk-RDKPMNN6.cjs +0 -2
- package/dist/chunk-TSDGKNV7.js +0 -2
- package/dist/chunk-TUCDPXBD.js +0 -18
- package/dist/chunk-UOE4WKL7.js +0 -1
- package/dist/chunk-VSCPFHTD.cjs +0 -3
- package/dist/chunk-ZKWRCLT2.cjs +0 -1
- package/dist/chunk-ZUGTEKLM.js +0 -4
- package/dist/editor-scope-DZJT4ukT.d.ts +0 -53
- package/dist/review-items-CJz-kAW8.d.ts +0 -370
|
@@ -1,281 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The engine's trust-boundary caps: recursion depth, element counts, and the rest.
|
|
5
|
-
*
|
|
6
|
-
* A caller may LOWER any of these but never raise or disable one — an override of `Infinity`,
|
|
7
|
-
* zero, a negative or `NaN` clamps into `(0, ceiling]` rather than turning the limit off. These
|
|
8
|
-
* are security ceilings, not performance budgets.
|
|
9
|
-
*/
|
|
10
|
-
interface ResourceLimits {
|
|
11
|
-
/** Max nested-structure recursion (tables/shapes/SDT/groups). */
|
|
12
|
-
readonly maxRecursionDepth: number;
|
|
13
|
-
/** Max total parsed element count. */
|
|
14
|
-
readonly maxElementCount: number;
|
|
15
|
-
/** Max package part count. */
|
|
16
|
-
readonly maxPartCount: number;
|
|
17
|
-
/** Max total decompressed bytes (zip-bomb guard). */
|
|
18
|
-
readonly maxDecompressedBytes: number;
|
|
19
|
-
/** Max total compressed input bytes. */
|
|
20
|
-
readonly maxCompressedBytes: number;
|
|
21
|
-
/** Max decompressed:compressed ratio per entry. */
|
|
22
|
-
readonly maxCompressionRatio: number;
|
|
23
|
-
/** In-memory chunk budget for streaming/spooling. */
|
|
24
|
-
readonly maxChunkBytes: number;
|
|
25
|
-
/** Max pagination passes before non-convergence is declared. */
|
|
26
|
-
readonly maxPaginationPasses: number;
|
|
27
|
-
/** Max queued items in any bounded work queue. */
|
|
28
|
-
readonly maxQueueDepth: number;
|
|
29
|
-
}
|
|
30
|
-
/** Non-disableable hard ceilings: no resolved limit may exceed these. */
|
|
31
|
-
declare const HARD_CEILINGS: ResourceLimits;
|
|
32
|
-
/** Finite defaults, all <= their hard ceiling. */
|
|
33
|
-
declare const DEFAULT_LIMITS: ResourceLimits;
|
|
34
|
-
/**
|
|
35
|
-
* Resolve caller overrides into a frozen, always-finite limit set. Each value is
|
|
36
|
-
* `min(override>0 ? override : default, ceiling)`. Infinity/0/negative/NaN can
|
|
37
|
-
* never disable a limit — the hard ceiling always wins.
|
|
38
|
-
*/
|
|
39
|
-
declare function resolveLimits(overrides?: Partial<ResourceLimits>): ResourceLimits;
|
|
40
|
-
/** Bounded image decode limits (typed-drawings-and-images task 4). */
|
|
41
|
-
/** Trust-boundary caps specific to image decoding and embedding. */
|
|
42
|
-
interface ImageResourceLimits {
|
|
43
|
-
readonly maxEncodedBytes: number;
|
|
44
|
-
readonly maxDecodedBytes: number;
|
|
45
|
-
readonly maxPixels: number;
|
|
46
|
-
readonly maxDimension: number;
|
|
47
|
-
readonly maxPolygonPoints: number;
|
|
48
|
-
readonly maxExternalRedirects: number;
|
|
49
|
-
}
|
|
50
|
-
/** Image caps nothing can raise past. A caller's override clamps into these. */
|
|
51
|
-
declare const IMAGE_RESOURCE_HARD_CEILINGS: ImageResourceLimits;
|
|
52
|
-
/** The image caps in force when a host configures none. Conservative and finite. */
|
|
53
|
-
declare const DEFAULT_IMAGE_RESOURCE_LIMITS: ImageResourceLimits;
|
|
54
|
-
/** Resolve caller overrides into frozen image limits; hard ceilings cannot be raised. */
|
|
55
|
-
declare function resolveImageResourceLimits(overrides?: Partial<ImageResourceLimits>): ImageResourceLimits;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Why a part or relationship name was refused.
|
|
59
|
-
*
|
|
60
|
-
* Path traversal is the reason this exists: a name with `..` or a leading `/` is refused rather
|
|
61
|
-
* than normalized, because normalizing is how a crafted package reaches outside itself.
|
|
62
|
-
*/
|
|
63
|
-
type NameRejection = 'empty' | 'control-char' | 'backslash' | 'drive-or-unc' | 'encoded-separator' | 'encoded-dot' | 'bad-encoding' | 'empty-segment' | 'dot-segment' | 'unsafe-key' | 'segment-trailing-dot' | 'traversal-escape' | 'not-absolute-uri' | 'unsafe-scheme';
|
|
64
|
-
/** A validated OPC name, or the typed reason it was refused. */
|
|
65
|
-
type NameResult = {
|
|
66
|
-
readonly ok: true;
|
|
67
|
-
readonly partName: string;
|
|
68
|
-
} | {
|
|
69
|
-
readonly ok: false;
|
|
70
|
-
readonly reason: NameRejection;
|
|
71
|
-
};
|
|
72
|
-
/**
|
|
73
|
-
* Normalize a ZIP entry name or OPC part name into a canonical part name
|
|
74
|
-
* (`/word/document.xml`). Accepts leading-slash and no-leading-slash inputs;
|
|
75
|
-
* rejects traversal, dot segments, and the attack surface. Duplicate detection
|
|
76
|
-
* folds ASCII case (OPC part-name equivalence).
|
|
77
|
-
*/
|
|
78
|
-
declare function normalizePartName(raw: string): NameResult;
|
|
79
|
-
/**
|
|
80
|
-
* ASCII-only lowercase fold. OPC part-name/extension equivalence is US-ASCII
|
|
81
|
-
* case-insensitive; a locale `toLowerCase()` mis-folds e.g. Turkish `I`/`İ` and
|
|
82
|
-
* could let two "equivalent" part names evade duplicate detection.
|
|
83
|
-
*/
|
|
84
|
-
declare function asciiFold(s: string): string;
|
|
85
|
-
/** Case-folded key for OPC part-name equivalence / duplicate detection. */
|
|
86
|
-
declare function partNameKey(partName: string): string;
|
|
87
|
-
/**
|
|
88
|
-
* Detect archive entries that collide after normalization (before inflation).
|
|
89
|
-
* Returns the case-folded keys that more than one raw name maps to.
|
|
90
|
-
*/
|
|
91
|
-
declare function detectDuplicateNames(rawNames: readonly string[]): {
|
|
92
|
-
readonly duplicates: readonly string[];
|
|
93
|
-
readonly rejected: readonly {
|
|
94
|
-
raw: string;
|
|
95
|
-
reason: NameRejection;
|
|
96
|
-
}[];
|
|
97
|
-
};
|
|
98
|
-
/**
|
|
99
|
-
* Resolve an internal relationship target against its owner part, without
|
|
100
|
-
* escaping the package root. `ownerPartName` is a canonical part name; the base
|
|
101
|
-
* is its containing folder. A leading "/" target is package-absolute. `.`/`..`
|
|
102
|
-
* segments resolve on a stack; popping above root is `traversal-escape`.
|
|
103
|
-
*/
|
|
104
|
-
declare function resolveInternalTarget(ownerPartName: string, rawTarget: string): NameResult;
|
|
105
|
-
/**
|
|
106
|
-
* Validate an external-mode relationship target. It MUST be an absolute URI, is
|
|
107
|
-
* retained verbatim by the caller, and is NEVER owner-resolved or fetched here.
|
|
108
|
-
* Unsafe schemes (javascript/vbscript/data/file) are rejected for runtime sinks;
|
|
109
|
-
* the raw lexical form is still preserved separately by the authored record.
|
|
110
|
-
*/
|
|
111
|
-
declare function validateExternalTarget(raw: string): NameResult;
|
|
112
|
-
|
|
113
|
-
/** One `<Default>`: a file extension mapped to a content type. */
|
|
114
|
-
interface DefaultRecord {
|
|
115
|
-
readonly extension: string;
|
|
116
|
-
readonly contentType: string;
|
|
117
|
-
readonly order: number;
|
|
118
|
-
}
|
|
119
|
-
/** One `<Override>`: a specific part name mapped to a content type. Beats any Default. */
|
|
120
|
-
interface OverrideRecord {
|
|
121
|
-
readonly partName: string;
|
|
122
|
-
readonly contentType: string;
|
|
123
|
-
readonly order: number;
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* The authored `[Content_Types].xml` records, in significant order.
|
|
127
|
-
*
|
|
128
|
-
* Retained rather than collapsed into a lookup, because the file's lexical form and ordering are
|
|
129
|
-
* part of what a lossless save re-emits.
|
|
130
|
-
*/
|
|
131
|
-
interface ContentTypeRecords {
|
|
132
|
-
readonly defaults: readonly DefaultRecord[];
|
|
133
|
-
readonly overrides: readonly OverrideRecord[];
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Why content-type records could not be indexed.
|
|
137
|
-
*
|
|
138
|
-
* All fail CLOSED: conflicting Defaults on one extension, duplicate normalized Override names, or
|
|
139
|
-
* invalid MIME syntax are refused rather than resolved by picking one.
|
|
140
|
-
*/
|
|
141
|
-
type ContentTypeError = {
|
|
142
|
-
readonly code: 'invalid-mime';
|
|
143
|
-
readonly value: string;
|
|
144
|
-
} | {
|
|
145
|
-
readonly code: 'conflicting-default';
|
|
146
|
-
readonly extension: string;
|
|
147
|
-
} | {
|
|
148
|
-
readonly code: 'duplicate-override';
|
|
149
|
-
readonly partName: string;
|
|
150
|
-
} | {
|
|
151
|
-
readonly code: 'invalid-override-name';
|
|
152
|
-
readonly partName: string;
|
|
153
|
-
} | {
|
|
154
|
-
readonly code: 'too-many-records';
|
|
155
|
-
readonly limit: number;
|
|
156
|
-
};
|
|
157
|
-
/** Whether a string is syntactically a MIME type. Syntax only — no registry lookup. */
|
|
158
|
-
declare function isValidMime(value: string): boolean;
|
|
159
|
-
/** ASCII-case-insensitive extension key (leading dot removed; ASCII-only fold). */
|
|
160
|
-
declare function extensionKey(extension: string): string;
|
|
161
|
-
/** The resolved lookup: Override by case-folded part name, Default by case-insensitive extension. */
|
|
162
|
-
interface ContentTypeIndex {
|
|
163
|
-
/** ext key -> single MIME (identical duplicates collapsed). */
|
|
164
|
-
readonly defaults: ReadonlyMap<string, string>;
|
|
165
|
-
/** case-folded part name -> MIME. */
|
|
166
|
-
readonly overrides: ReadonlyMap<string, string>;
|
|
167
|
-
}
|
|
168
|
-
/** The built index, or the conflict that made it impossible. */
|
|
169
|
-
type IndexResult = {
|
|
170
|
-
readonly ok: true;
|
|
171
|
-
readonly index: ContentTypeIndex;
|
|
172
|
-
} | {
|
|
173
|
-
readonly ok: false;
|
|
174
|
-
readonly error: ContentTypeError;
|
|
175
|
-
};
|
|
176
|
-
/**
|
|
177
|
-
* Build a resolved content-type index, failing closed on conflict/duplicate/MIME
|
|
178
|
-
* errors. `maxRecords` bounds the combined record count (N/N+1 gate).
|
|
179
|
-
*/
|
|
180
|
-
declare function buildContentTypeIndex(records: ContentTypeRecords, maxRecords?: number): IndexResult;
|
|
181
|
-
/**
|
|
182
|
-
* A part's content type, or why it has none.
|
|
183
|
-
*
|
|
184
|
-
* An orphan record never determines a part's type — a Default with no matching part is preserved
|
|
185
|
-
* inertly rather than applied.
|
|
186
|
-
*/
|
|
187
|
-
type ResolveResult = {
|
|
188
|
-
readonly ok: true;
|
|
189
|
-
readonly contentType: string;
|
|
190
|
-
readonly source: 'override' | 'default';
|
|
191
|
-
} | {
|
|
192
|
-
readonly ok: false;
|
|
193
|
-
readonly reason: 'unknown';
|
|
194
|
-
};
|
|
195
|
-
/** Resolve a part's content type: Override wins over Default; else unknown. */
|
|
196
|
-
declare function resolveContentType(index: ContentTypeIndex, partName: string): ResolveResult;
|
|
197
|
-
|
|
198
|
-
/** OOXML image relationship type for embedded or linked media parts. */
|
|
199
|
-
declare const IMAGE_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
|
|
200
|
-
/**
|
|
201
|
-
* Whether a relationship points inside the package or out of it.
|
|
202
|
-
*
|
|
203
|
-
* The security-relevant distinction: an `External` target is retained VERBATIM and never
|
|
204
|
-
* owner-resolved or fetched, because auto-loading a file-supplied remote target is a zero-click
|
|
205
|
-
* external fetch.
|
|
206
|
-
*/
|
|
207
|
-
type TargetMode = 'Internal' | 'External';
|
|
208
|
-
/**
|
|
209
|
-
* One authored relationship, with nothing materialized away: owner part, id, type, raw target
|
|
210
|
-
* lexical form, mode, and position.
|
|
211
|
-
*/
|
|
212
|
-
interface RelationshipRecord {
|
|
213
|
-
readonly ownerPart: string;
|
|
214
|
-
readonly id: string;
|
|
215
|
-
readonly type: string;
|
|
216
|
-
readonly rawTarget: string;
|
|
217
|
-
readonly targetMode: TargetMode;
|
|
218
|
-
readonly order: number;
|
|
219
|
-
}
|
|
220
|
-
/** Why a relationship set is invalid. Duplicate ids within one owner fail closed. */
|
|
221
|
-
type RelationshipError = {
|
|
222
|
-
readonly code: 'duplicate-id';
|
|
223
|
-
readonly ownerPart: string;
|
|
224
|
-
readonly id: string;
|
|
225
|
-
};
|
|
226
|
-
/** The validated relationship set, or the conflict that rejected it. */
|
|
227
|
-
type RelationshipSetResult = {
|
|
228
|
-
readonly ok: true;
|
|
229
|
-
readonly byOwner: ReadonlyMap<string, readonly RelationshipRecord[]>;
|
|
230
|
-
} | {
|
|
231
|
-
readonly ok: false;
|
|
232
|
-
readonly error: RelationshipError;
|
|
233
|
-
};
|
|
234
|
-
/** Group relationships by owner in authored order; reject duplicate ids per owner. */
|
|
235
|
-
declare function buildRelationshipSet(records: readonly RelationshipRecord[]): RelationshipSetResult;
|
|
236
|
-
/**
|
|
237
|
-
* A relationship resolved to a part, or the reason it could not be.
|
|
238
|
-
*
|
|
239
|
-
* External targets resolve to a refusal by design: they are never followed from a file.
|
|
240
|
-
*/
|
|
241
|
-
type ResolvedRelationship = {
|
|
242
|
-
readonly mode: 'Internal';
|
|
243
|
-
readonly target: NameResult;
|
|
244
|
-
readonly raw: string;
|
|
245
|
-
} | {
|
|
246
|
-
readonly mode: 'External';
|
|
247
|
-
readonly sinkSafe: NameResult;
|
|
248
|
-
readonly raw: string;
|
|
249
|
-
};
|
|
250
|
-
/**
|
|
251
|
-
* Resolve a relationship to a runtime projection while the raw target stays
|
|
252
|
-
* authored. Internal -> owner-relative part name; External -> sink-safe
|
|
253
|
-
* validation only (never owner-resolved, never fetched). `raw` is always the
|
|
254
|
-
* verbatim authored target.
|
|
255
|
-
*/
|
|
256
|
-
declare function resolveRelationship(rec: RelationshipRecord): ResolvedRelationship;
|
|
257
|
-
/**
|
|
258
|
-
* An image relationship resolved to package bytes, or why it was refused.
|
|
259
|
-
*
|
|
260
|
-
* External-mode image rels are refused rather than fetched — the no-zero-click-external-fetch
|
|
261
|
-
* rule applies to images exactly as it does to links.
|
|
262
|
-
*/
|
|
263
|
-
type ImageRelationshipResolution = {
|
|
264
|
-
readonly mode: 'internal';
|
|
265
|
-
readonly partName: string;
|
|
266
|
-
readonly raw: string;
|
|
267
|
-
} | {
|
|
268
|
-
readonly mode: 'external';
|
|
269
|
-
readonly sinkSafe: boolean;
|
|
270
|
-
readonly raw: string;
|
|
271
|
-
} | {
|
|
272
|
-
readonly mode: 'missing';
|
|
273
|
-
};
|
|
274
|
-
/**
|
|
275
|
-
* Resolve an image relationship id from an owner part. Internal targets resolve
|
|
276
|
-
* owner-relative; external targets are never fetched; a missing id is `missing`.
|
|
277
|
-
*/
|
|
278
|
-
declare function resolveImageRelationship(records: readonly RelationshipRecord[] | undefined, ownerPart: string, relationshipId: string): ImageRelationshipResolution;
|
|
1
|
+
import { c as HistoryGroupOutcome } from './editor-scope-OHPwVQ5l.js';
|
|
279
2
|
|
|
280
3
|
/**
|
|
281
4
|
* One parsed XML node, preserving significant order, whitespace and raw lexical values.
|
|
@@ -1148,35 +871,430 @@ type OoxmlInvariantResult = {
|
|
|
1148
871
|
*/
|
|
1149
872
|
declare function readOoxmlPart(xml: string, metadata: OoxmlPartMetadata, limits?: XmlLimits): OoxmlReadResult;
|
|
1150
873
|
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
* `too-large` and `too-many-entries` are the zip-bomb guards; `bad-name` catches path traversal —
|
|
1155
|
-
* an entry with `..` or a leading `/` is rejected rather than normalized.
|
|
1156
|
-
*/
|
|
1157
|
-
type ZipRejection = 'too-many-entries' | 'too-large' | 'bad-name' | 'inflate-error';
|
|
1158
|
-
/** Archive caps: entry count, total decompressed bytes, and the decompression ratio. */
|
|
1159
|
-
interface ZipLimits {
|
|
1160
|
-
readonly maxEntries: number;
|
|
1161
|
-
/** Max total UNCOMPRESSED bytes across the archive. */
|
|
1162
|
-
readonly maxTotalBytes: number;
|
|
1163
|
-
/** Max per-entry uncompressed:compressed ratio (zip-bomb guard). */
|
|
1164
|
-
readonly maxRatio?: number;
|
|
1165
|
-
}
|
|
1166
|
-
/** The archive caps in force when a host configures none. Conservative and finite. */
|
|
1167
|
-
declare const DEFAULT_ZIP_LIMITS: ZipLimits;
|
|
1168
|
-
/** The read entries, or the typed refusal. Never throws — the bytes are untrusted. */
|
|
1169
|
-
type ZipReadResult = {
|
|
1170
|
-
readonly ok: true;
|
|
1171
|
-
readonly entries: ReadonlyMap<string, Uint8Array>;
|
|
874
|
+
type AutomationTableMutation = {
|
|
875
|
+
readonly kind: 'values';
|
|
876
|
+
readonly values: readonly (readonly string[])[];
|
|
1172
877
|
} | {
|
|
1173
|
-
readonly
|
|
1174
|
-
readonly
|
|
1175
|
-
readonly
|
|
1176
|
-
readonly
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
|
|
878
|
+
readonly kind: 'addRows' | 'addColumns';
|
|
879
|
+
readonly location: 'start' | 'end';
|
|
880
|
+
readonly count: number;
|
|
881
|
+
readonly values?: readonly (readonly string[])[];
|
|
882
|
+
} | {
|
|
883
|
+
readonly kind: 'deleteRows' | 'deleteColumns';
|
|
884
|
+
readonly index: number;
|
|
885
|
+
readonly count: number;
|
|
886
|
+
} | {
|
|
887
|
+
readonly kind: 'delete';
|
|
888
|
+
} | {
|
|
889
|
+
readonly kind: 'properties';
|
|
890
|
+
readonly styleId?: string;
|
|
891
|
+
readonly headerRowCount?: number;
|
|
892
|
+
} | {
|
|
893
|
+
readonly kind: 'cell';
|
|
894
|
+
readonly cellId: string;
|
|
895
|
+
readonly value?: string;
|
|
896
|
+
readonly columnWidth?: number;
|
|
897
|
+
readonly shadingColor?: string;
|
|
898
|
+
readonly verticalAlignment?: 'Top' | 'Center' | 'Bottom';
|
|
899
|
+
};
|
|
900
|
+
|
|
901
|
+
/** Select one declared entry of a legacy Word dropdown form field. */
|
|
902
|
+
interface SetLegacyDropdownOp {
|
|
903
|
+
readonly op: 'setLegacyDropdown';
|
|
904
|
+
readonly paragraphId: string;
|
|
905
|
+
readonly fieldNodeId: string;
|
|
906
|
+
readonly selectedIndex: number;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
interface SetFieldCodeOp {
|
|
910
|
+
readonly op: 'setFieldCode';
|
|
911
|
+
readonly paragraphId: string;
|
|
912
|
+
readonly fieldNodeId: string;
|
|
913
|
+
readonly code: string;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
type InsertTextOp = {
|
|
917
|
+
readonly op: 'insertText';
|
|
918
|
+
readonly paragraphId: string;
|
|
919
|
+
/** Legacy text form identity for protected filling; never an inline wrapper owner. */
|
|
920
|
+
readonly textFormFieldId?: string;
|
|
921
|
+
readonly offset: number;
|
|
922
|
+
readonly text: string;
|
|
923
|
+
/**
|
|
924
|
+
* Write this as a TRACKED insertion, attributed here.
|
|
925
|
+
*
|
|
926
|
+
* On the op rather than on the store, so suggesting stays a decision the surface makes
|
|
927
|
+
* per edit and the write vocabulary stays explicit — a global "everything is tracked
|
|
928
|
+
* now" flag is exactly what `DocEdits` refuses, because it makes the meaning of an op
|
|
929
|
+
* depend on state the op does not carry.
|
|
930
|
+
*/
|
|
931
|
+
readonly revision?: RevisionAttributionInput;
|
|
932
|
+
/**
|
|
933
|
+
* When set, the text belongs INSIDE this content control, whatever sits at the offset.
|
|
934
|
+
*
|
|
935
|
+
* A boundary offset is owned by the run that starts there, which at a control's trailing
|
|
936
|
+
* edge is the run after the control — so an offset alone cannot say "append to this field",
|
|
937
|
+
* the way it cannot say which run of a field result to format (see `targetRunIds`). A
|
|
938
|
+
* caller that names the control gets the text in the control; one that does not gets the
|
|
939
|
+
* plain offset rule, which is what a keystroke beside a field means.
|
|
940
|
+
*/
|
|
941
|
+
readonly inside?: string;
|
|
942
|
+
/**
|
|
943
|
+
* Which side of a run BOUNDARY the text joins. Default `'left'` — Word's typing rule:
|
|
944
|
+
* the next character takes the formatting of the character before the caret.
|
|
945
|
+
*
|
|
946
|
+
* `'right'` is for a caller that is not typing but placing text inside the run that
|
|
947
|
+
* STARTS at the offset — the hyperlink editor rewriting a link's display text, where
|
|
948
|
+
* landing left of the boundary would put the new text outside the link. Ignored when
|
|
949
|
+
* the offset falls strictly inside a run, which has no boundary to choose.
|
|
950
|
+
*/
|
|
951
|
+
readonly bias?: 'left' | 'right';
|
|
952
|
+
};
|
|
953
|
+
type DeleteTextOp = {
|
|
954
|
+
readonly op: 'deleteText';
|
|
955
|
+
readonly paragraphId: string;
|
|
956
|
+
/** Legacy text form identity for protected filling; never an inline wrapper owner. */
|
|
957
|
+
readonly textFormFieldId?: string;
|
|
958
|
+
readonly start: number;
|
|
959
|
+
readonly end: number;
|
|
960
|
+
/** Write this as a TRACKED deletion — the characters stay, wrapped in `w:del`. */
|
|
961
|
+
readonly revision?: RevisionAttributionInput;
|
|
962
|
+
};
|
|
963
|
+
|
|
964
|
+
/** Editable legacy text input types. Other authored types remain inert. */
|
|
965
|
+
type TextFormFieldType = 'regular' | 'number' | 'date';
|
|
966
|
+
/** Options stored in the legacy field definition. Zero means unlimited length. */
|
|
967
|
+
interface TextFormFieldOptions {
|
|
968
|
+
readonly type: TextFormFieldType;
|
|
969
|
+
readonly maxLength: number;
|
|
970
|
+
readonly format: string;
|
|
971
|
+
readonly enabled: boolean;
|
|
972
|
+
}
|
|
973
|
+
/** Supported format choices for legacy text input fields. @public */
|
|
974
|
+
declare const TEXT_FORM_FORMATS: {
|
|
975
|
+
readonly regular: readonly ["", "Uppercase", "Lowercase", "First capital", "Title case"];
|
|
976
|
+
readonly number: readonly ["", "0", "0.00", "#,##0", "#,##0.00", "0%", "0.00%"];
|
|
977
|
+
readonly date: readonly ["", "M/d/yyyy", "MM/dd/yyyy", "d/M/yyyy", "dd/MM/yyyy", "yyyy-MM-dd", "d MMMM yyyy", "MMMM d, yyyy"];
|
|
978
|
+
};
|
|
979
|
+
|
|
980
|
+
/** A legacy text input in the shared paragraph offset space. */
|
|
981
|
+
interface TextFormFieldRange {
|
|
982
|
+
readonly fieldNodeId: string;
|
|
983
|
+
readonly start: number;
|
|
984
|
+
readonly end: number;
|
|
985
|
+
readonly enabled: boolean;
|
|
986
|
+
readonly defaultText: string;
|
|
987
|
+
readonly type: string;
|
|
988
|
+
readonly maxLength: number;
|
|
989
|
+
readonly format: string;
|
|
990
|
+
readonly chromeIds: readonly string[];
|
|
991
|
+
}
|
|
992
|
+
/** Uses the field parser and offset index; never introduces another inline walk. */
|
|
993
|
+
declare function textFormFieldsOf(paragraph: OoxmlParagraphNode): readonly TextFormFieldRange[];
|
|
994
|
+
/** Options edit for an existing legacy text form. */
|
|
995
|
+
interface SetTextFormFieldDefaultOp {
|
|
996
|
+
readonly op: 'setTextFormFieldDefault';
|
|
997
|
+
/** Regional conventions for new date input; defaults to en-US. */
|
|
998
|
+
readonly locale?: string;
|
|
999
|
+
readonly paragraphId: string;
|
|
1000
|
+
readonly fieldNodeId: string;
|
|
1001
|
+
readonly text: string;
|
|
1002
|
+
readonly options?: TextFormFieldOptions;
|
|
1003
|
+
}
|
|
1004
|
+
/** Validate and format the existing result when a user finishes filling a field. */
|
|
1005
|
+
interface CommitTextFormFieldOp {
|
|
1006
|
+
readonly op: 'commitTextFormField';
|
|
1007
|
+
/** Regional conventions for new date input; defaults to en-US. */
|
|
1008
|
+
readonly locale?: string;
|
|
1009
|
+
readonly paragraphId: string;
|
|
1010
|
+
readonly fieldNodeId: string;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
/** One FORMCHECKBOX in the shared paragraph offset space. */
|
|
1014
|
+
interface LegacyCheckboxFieldRange {
|
|
1015
|
+
/** The begin `w:fldChar` node: what the op addresses. */
|
|
1016
|
+
readonly fieldNodeId: string;
|
|
1017
|
+
readonly start: number;
|
|
1018
|
+
readonly end: number;
|
|
1019
|
+
readonly checked: boolean;
|
|
1020
|
+
/** `w:enabled` under `w:ffData`; a disabled field renders but refuses the toggle. */
|
|
1021
|
+
readonly enabled: boolean;
|
|
1022
|
+
}
|
|
1023
|
+
/** Flip a FORMCHECKBOX's state; the only write into `w:ffData` a checkbox permits. */
|
|
1024
|
+
interface SetLegacyCheckboxOp {
|
|
1025
|
+
readonly op: 'setLegacyCheckbox';
|
|
1026
|
+
readonly paragraphId: string;
|
|
1027
|
+
readonly fieldNodeId: string;
|
|
1028
|
+
readonly checked: boolean;
|
|
1029
|
+
}
|
|
1030
|
+
/** Every FORMCHECKBOX in a paragraph, in document order; uses the shared field parser. */
|
|
1031
|
+
declare function legacyCheckboxFieldsOf(paragraph: OoxmlParagraphNode): readonly LegacyCheckboxFieldRange[];
|
|
1032
|
+
|
|
1033
|
+
/** Replace a building block gallery control's content with one block's body. */
|
|
1034
|
+
interface InsertBuildingBlockOp {
|
|
1035
|
+
readonly op: 'insertBuildingBlock';
|
|
1036
|
+
readonly controlId: string;
|
|
1037
|
+
/** `w:docPartPr/w:name` of the picked block, for the journal and the host. */
|
|
1038
|
+
readonly name: string;
|
|
1039
|
+
/**
|
|
1040
|
+
* Self-contained `w:docPartBody` children, cloned with fresh ids at apply.
|
|
1041
|
+
* Resource, style, field, bookmark, note and revision references return `unsupported`.
|
|
1042
|
+
*/
|
|
1043
|
+
readonly blocks: readonly OoxmlNode[];
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
/**
|
|
1047
|
+
* Why a part or relationship name was refused.
|
|
1048
|
+
*
|
|
1049
|
+
* Path traversal is the reason this exists: a name with `..` or a leading `/` is refused rather
|
|
1050
|
+
* than normalized, because normalizing is how a crafted package reaches outside itself.
|
|
1051
|
+
*/
|
|
1052
|
+
type NameRejection = 'empty' | 'control-char' | 'backslash' | 'drive-or-unc' | 'encoded-separator' | 'encoded-dot' | 'bad-encoding' | 'empty-segment' | 'dot-segment' | 'unsafe-key' | 'segment-trailing-dot' | 'traversal-escape' | 'not-absolute-uri' | 'unsafe-scheme';
|
|
1053
|
+
/** A validated OPC name, or the typed reason it was refused. */
|
|
1054
|
+
type NameResult = {
|
|
1055
|
+
readonly ok: true;
|
|
1056
|
+
readonly partName: string;
|
|
1057
|
+
} | {
|
|
1058
|
+
readonly ok: false;
|
|
1059
|
+
readonly reason: NameRejection;
|
|
1060
|
+
};
|
|
1061
|
+
/**
|
|
1062
|
+
* Normalize a ZIP entry name or OPC part name into a canonical part name
|
|
1063
|
+
* (`/word/document.xml`). Accepts leading-slash and no-leading-slash inputs;
|
|
1064
|
+
* rejects traversal, dot segments, and the attack surface. Duplicate detection
|
|
1065
|
+
* folds ASCII case (OPC part-name equivalence).
|
|
1066
|
+
*/
|
|
1067
|
+
declare function normalizePartName(raw: string): NameResult;
|
|
1068
|
+
/**
|
|
1069
|
+
* ASCII-only lowercase fold. OPC part-name/extension equivalence is US-ASCII
|
|
1070
|
+
* case-insensitive; a locale `toLowerCase()` mis-folds e.g. Turkish `I`/`İ` and
|
|
1071
|
+
* could let two "equivalent" part names evade duplicate detection.
|
|
1072
|
+
*/
|
|
1073
|
+
declare function asciiFold(s: string): string;
|
|
1074
|
+
/** Case-folded key for OPC part-name equivalence / duplicate detection. */
|
|
1075
|
+
declare function partNameKey(partName: string): string;
|
|
1076
|
+
/**
|
|
1077
|
+
* Detect archive entries that collide after normalization (before inflation).
|
|
1078
|
+
* Returns the case-folded keys that more than one raw name maps to.
|
|
1079
|
+
*/
|
|
1080
|
+
declare function detectDuplicateNames(rawNames: readonly string[]): {
|
|
1081
|
+
readonly duplicates: readonly string[];
|
|
1082
|
+
readonly rejected: readonly {
|
|
1083
|
+
raw: string;
|
|
1084
|
+
reason: NameRejection;
|
|
1085
|
+
}[];
|
|
1086
|
+
};
|
|
1087
|
+
/**
|
|
1088
|
+
* Resolve an internal relationship target against its owner part, without
|
|
1089
|
+
* escaping the package root. `ownerPartName` is a canonical part name; the base
|
|
1090
|
+
* is its containing folder. A leading "/" target is package-absolute. `.`/`..`
|
|
1091
|
+
* segments resolve on a stack; popping above root is `traversal-escape`.
|
|
1092
|
+
*/
|
|
1093
|
+
declare function resolveInternalTarget(ownerPartName: string, rawTarget: string): NameResult;
|
|
1094
|
+
/**
|
|
1095
|
+
* Validate an external-mode relationship target. It MUST be an absolute URI, is
|
|
1096
|
+
* retained verbatim by the caller, and is NEVER owner-resolved or fetched here.
|
|
1097
|
+
* Unsafe schemes (javascript/vbscript/data/file) are rejected for runtime sinks;
|
|
1098
|
+
* the raw lexical form is still preserved separately by the authored record.
|
|
1099
|
+
*/
|
|
1100
|
+
declare function validateExternalTarget(raw: string): NameResult;
|
|
1101
|
+
|
|
1102
|
+
/** One `<Default>`: a file extension mapped to a content type. */
|
|
1103
|
+
interface DefaultRecord {
|
|
1104
|
+
readonly extension: string;
|
|
1105
|
+
readonly contentType: string;
|
|
1106
|
+
readonly order: number;
|
|
1107
|
+
}
|
|
1108
|
+
/** One `<Override>`: a specific part name mapped to a content type. Beats any Default. */
|
|
1109
|
+
interface OverrideRecord {
|
|
1110
|
+
readonly partName: string;
|
|
1111
|
+
readonly contentType: string;
|
|
1112
|
+
readonly order: number;
|
|
1113
|
+
}
|
|
1114
|
+
/**
|
|
1115
|
+
* The authored `[Content_Types].xml` records, in significant order.
|
|
1116
|
+
*
|
|
1117
|
+
* Retained rather than collapsed into a lookup, because the file's lexical form and ordering are
|
|
1118
|
+
* part of what a lossless save re-emits.
|
|
1119
|
+
*/
|
|
1120
|
+
interface ContentTypeRecords {
|
|
1121
|
+
readonly defaults: readonly DefaultRecord[];
|
|
1122
|
+
readonly overrides: readonly OverrideRecord[];
|
|
1123
|
+
}
|
|
1124
|
+
/**
|
|
1125
|
+
* Why content-type records could not be indexed.
|
|
1126
|
+
*
|
|
1127
|
+
* All fail CLOSED: conflicting Defaults on one extension, duplicate normalized Override names, or
|
|
1128
|
+
* invalid MIME syntax are refused rather than resolved by picking one.
|
|
1129
|
+
*/
|
|
1130
|
+
type ContentTypeError = {
|
|
1131
|
+
readonly code: 'invalid-mime';
|
|
1132
|
+
readonly value: string;
|
|
1133
|
+
} | {
|
|
1134
|
+
readonly code: 'conflicting-default';
|
|
1135
|
+
readonly extension: string;
|
|
1136
|
+
} | {
|
|
1137
|
+
readonly code: 'duplicate-override';
|
|
1138
|
+
readonly partName: string;
|
|
1139
|
+
} | {
|
|
1140
|
+
readonly code: 'invalid-override-name';
|
|
1141
|
+
readonly partName: string;
|
|
1142
|
+
} | {
|
|
1143
|
+
readonly code: 'too-many-records';
|
|
1144
|
+
readonly limit: number;
|
|
1145
|
+
};
|
|
1146
|
+
/** Whether a string is syntactically a MIME type. Syntax only — no registry lookup. */
|
|
1147
|
+
declare function isValidMime(value: string): boolean;
|
|
1148
|
+
/** ASCII-case-insensitive extension key (leading dot removed; ASCII-only fold). */
|
|
1149
|
+
declare function extensionKey(extension: string): string;
|
|
1150
|
+
/** The resolved lookup: Override by case-folded part name, Default by case-insensitive extension. */
|
|
1151
|
+
interface ContentTypeIndex {
|
|
1152
|
+
/** ext key -> single MIME (identical duplicates collapsed). */
|
|
1153
|
+
readonly defaults: ReadonlyMap<string, string>;
|
|
1154
|
+
/** case-folded part name -> MIME. */
|
|
1155
|
+
readonly overrides: ReadonlyMap<string, string>;
|
|
1156
|
+
}
|
|
1157
|
+
/** The built index, or the conflict that made it impossible. */
|
|
1158
|
+
type IndexResult = {
|
|
1159
|
+
readonly ok: true;
|
|
1160
|
+
readonly index: ContentTypeIndex;
|
|
1161
|
+
} | {
|
|
1162
|
+
readonly ok: false;
|
|
1163
|
+
readonly error: ContentTypeError;
|
|
1164
|
+
};
|
|
1165
|
+
/**
|
|
1166
|
+
* Build a resolved content-type index, failing closed on conflict/duplicate/MIME
|
|
1167
|
+
* errors. `maxRecords` bounds the combined record count (N/N+1 gate).
|
|
1168
|
+
*/
|
|
1169
|
+
declare function buildContentTypeIndex(records: ContentTypeRecords, maxRecords?: number): IndexResult;
|
|
1170
|
+
/**
|
|
1171
|
+
* A part's content type, or why it has none.
|
|
1172
|
+
*
|
|
1173
|
+
* An orphan record never determines a part's type — a Default with no matching part is preserved
|
|
1174
|
+
* inertly rather than applied.
|
|
1175
|
+
*/
|
|
1176
|
+
type ResolveResult = {
|
|
1177
|
+
readonly ok: true;
|
|
1178
|
+
readonly contentType: string;
|
|
1179
|
+
readonly source: 'override' | 'default';
|
|
1180
|
+
} | {
|
|
1181
|
+
readonly ok: false;
|
|
1182
|
+
readonly reason: 'unknown';
|
|
1183
|
+
};
|
|
1184
|
+
/** Resolve a part's content type: Override wins over Default; else unknown. */
|
|
1185
|
+
declare function resolveContentType(index: ContentTypeIndex, partName: string): ResolveResult;
|
|
1186
|
+
|
|
1187
|
+
/** OOXML image relationship type for embedded or linked media parts. */
|
|
1188
|
+
declare const IMAGE_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
|
|
1189
|
+
/**
|
|
1190
|
+
* Whether a relationship points inside the package or out of it.
|
|
1191
|
+
*
|
|
1192
|
+
* The security-relevant distinction: an `External` target is retained VERBATIM and never
|
|
1193
|
+
* owner-resolved or fetched, because auto-loading a file-supplied remote target is a zero-click
|
|
1194
|
+
* external fetch.
|
|
1195
|
+
*/
|
|
1196
|
+
type TargetMode = 'Internal' | 'External';
|
|
1197
|
+
/**
|
|
1198
|
+
* One authored relationship, with nothing materialized away: owner part, id, type, raw target
|
|
1199
|
+
* lexical form, mode, and position.
|
|
1200
|
+
*/
|
|
1201
|
+
interface RelationshipRecord {
|
|
1202
|
+
readonly ownerPart: string;
|
|
1203
|
+
readonly id: string;
|
|
1204
|
+
readonly type: string;
|
|
1205
|
+
readonly rawTarget: string;
|
|
1206
|
+
readonly targetMode: TargetMode;
|
|
1207
|
+
readonly order: number;
|
|
1208
|
+
}
|
|
1209
|
+
/** Why a relationship set is invalid. Duplicate ids within one owner fail closed. */
|
|
1210
|
+
type RelationshipError = {
|
|
1211
|
+
readonly code: 'duplicate-id';
|
|
1212
|
+
readonly ownerPart: string;
|
|
1213
|
+
readonly id: string;
|
|
1214
|
+
};
|
|
1215
|
+
/** The validated relationship set, or the conflict that rejected it. */
|
|
1216
|
+
type RelationshipSetResult = {
|
|
1217
|
+
readonly ok: true;
|
|
1218
|
+
readonly byOwner: ReadonlyMap<string, readonly RelationshipRecord[]>;
|
|
1219
|
+
} | {
|
|
1220
|
+
readonly ok: false;
|
|
1221
|
+
readonly error: RelationshipError;
|
|
1222
|
+
};
|
|
1223
|
+
/** Group relationships by owner in authored order; reject duplicate ids per owner. */
|
|
1224
|
+
declare function buildRelationshipSet(records: readonly RelationshipRecord[]): RelationshipSetResult;
|
|
1225
|
+
/**
|
|
1226
|
+
* A relationship resolved to a part, or the reason it could not be.
|
|
1227
|
+
*
|
|
1228
|
+
* External targets resolve to a refusal by design: they are never followed from a file.
|
|
1229
|
+
*/
|
|
1230
|
+
type ResolvedRelationship = {
|
|
1231
|
+
readonly mode: 'Internal';
|
|
1232
|
+
readonly target: NameResult;
|
|
1233
|
+
readonly raw: string;
|
|
1234
|
+
} | {
|
|
1235
|
+
readonly mode: 'External';
|
|
1236
|
+
readonly sinkSafe: NameResult;
|
|
1237
|
+
readonly raw: string;
|
|
1238
|
+
};
|
|
1239
|
+
/**
|
|
1240
|
+
* Resolve a relationship to a runtime projection while the raw target stays
|
|
1241
|
+
* authored. Internal -> owner-relative part name; External -> sink-safe
|
|
1242
|
+
* validation only (never owner-resolved, never fetched). `raw` is always the
|
|
1243
|
+
* verbatim authored target.
|
|
1244
|
+
*/
|
|
1245
|
+
declare function resolveRelationship(rec: RelationshipRecord): ResolvedRelationship;
|
|
1246
|
+
/**
|
|
1247
|
+
* An image relationship resolved to package bytes, or why it was refused.
|
|
1248
|
+
*
|
|
1249
|
+
* External-mode image rels are refused rather than fetched — the no-zero-click-external-fetch
|
|
1250
|
+
* rule applies to images exactly as it does to links.
|
|
1251
|
+
*/
|
|
1252
|
+
type ImageRelationshipResolution = {
|
|
1253
|
+
readonly mode: 'internal';
|
|
1254
|
+
readonly partName: string;
|
|
1255
|
+
readonly raw: string;
|
|
1256
|
+
} | {
|
|
1257
|
+
readonly mode: 'external';
|
|
1258
|
+
readonly sinkSafe: boolean;
|
|
1259
|
+
readonly raw: string;
|
|
1260
|
+
} | {
|
|
1261
|
+
readonly mode: 'missing';
|
|
1262
|
+
};
|
|
1263
|
+
/**
|
|
1264
|
+
* Resolve an image relationship id from an owner part. Internal targets resolve
|
|
1265
|
+
* owner-relative; external targets are never fetched; a missing id is `missing`.
|
|
1266
|
+
*/
|
|
1267
|
+
declare function resolveImageRelationship(records: readonly RelationshipRecord[] | undefined, ownerPart: string, relationshipId: string): ImageRelationshipResolution;
|
|
1268
|
+
|
|
1269
|
+
/**
|
|
1270
|
+
* Why a zip was refused at the trust boundary.
|
|
1271
|
+
*
|
|
1272
|
+
* `too-large` and `too-many-entries` are the zip-bomb guards; `bad-name` catches path traversal —
|
|
1273
|
+
* an entry with `..` or a leading `/` is rejected rather than normalized.
|
|
1274
|
+
*/
|
|
1275
|
+
type ZipRejection = 'too-many-entries' | 'too-large' | 'bad-name' | 'inflate-error';
|
|
1276
|
+
/** Archive caps: entry count, total decompressed bytes, and the decompression ratio. */
|
|
1277
|
+
interface ZipLimits {
|
|
1278
|
+
readonly maxEntries: number;
|
|
1279
|
+
/** Max total UNCOMPRESSED bytes across the archive. */
|
|
1280
|
+
readonly maxTotalBytes: number;
|
|
1281
|
+
/** Max per-entry uncompressed:compressed ratio (zip-bomb guard). */
|
|
1282
|
+
readonly maxRatio?: number;
|
|
1283
|
+
}
|
|
1284
|
+
/** The archive caps in force when a host configures none. Conservative and finite. */
|
|
1285
|
+
declare const DEFAULT_ZIP_LIMITS: ZipLimits;
|
|
1286
|
+
/** The read entries, or the typed refusal. Never throws — the bytes are untrusted. */
|
|
1287
|
+
type ZipReadResult = {
|
|
1288
|
+
readonly ok: true;
|
|
1289
|
+
readonly entries: ReadonlyMap<string, Uint8Array>;
|
|
1290
|
+
} | {
|
|
1291
|
+
readonly ok: false;
|
|
1292
|
+
readonly reason: ZipRejection;
|
|
1293
|
+
readonly detail?: string;
|
|
1294
|
+
readonly limit?: 'zip.maxTotalBytes' | 'zip.maxRatio';
|
|
1295
|
+
};
|
|
1296
|
+
/**
|
|
1297
|
+
* Inflate a ZIP archive with bounds + OPC name normalization. Entry name, count,
|
|
1180
1298
|
* compression-ratio, and total-uncompressed-size limits are enforced BEFORE each
|
|
1181
1299
|
* entry is decompressed (via fflate's pre-inflation filter), so a zip bomb or a
|
|
1182
1300
|
* traversal name is rejected without ever being inflated. Keys are canonical part
|
|
@@ -1573,159 +1691,6 @@ declare function projectDrawing(drawing: OoxmlDrawingNode, context: Readonly<{
|
|
|
1573
1691
|
resolveStyleMatrixReference?: ShapeStyleMatrixResolver;
|
|
1574
1692
|
}>): DrawingProjection | null;
|
|
1575
1693
|
|
|
1576
|
-
/** Opaque handle — bytes are reachable only through {@link mintValidatedImageBytes}. */
|
|
1577
|
-
interface ValidatedImageBytesHandle {
|
|
1578
|
-
readonly registryId: number;
|
|
1579
|
-
readonly resourceKey: string;
|
|
1580
|
-
readonly contentId: string;
|
|
1581
|
-
readonly generation: number;
|
|
1582
|
-
}
|
|
1583
|
-
|
|
1584
|
-
/**
|
|
1585
|
-
* Raster media the decode port measures and any authoring path may write.
|
|
1586
|
-
*
|
|
1587
|
-
* BMP and WebP are here for the same reason the other three are: an `<img>` decodes them
|
|
1588
|
-
* natively, so they need a signature and a structural header and nothing else. BMP is what
|
|
1589
|
-
* older documents carry; WebP is what current Word writes.
|
|
1590
|
-
*/
|
|
1591
|
-
type SupportedImageMime = 'image/png' | 'image/jpeg' | 'image/gif' | 'image/bmp' | 'image/webp';
|
|
1592
|
-
/**
|
|
1593
|
-
* Vector media painted straight from validated bytes. An `<img>` renders SVG in the
|
|
1594
|
-
* browser's secure static mode — no script, no external subresource loads — so there is
|
|
1595
|
-
* no decode step and no raster buffer sized by a file-supplied number.
|
|
1596
|
-
*/
|
|
1597
|
-
type VectorImageMime = 'image/svg+xml';
|
|
1598
|
-
/** Every mime the painter can hand to an `<img>`. */
|
|
1599
|
-
type RenderableImageMime = SupportedImageMime | VectorImageMime;
|
|
1600
|
-
/**
|
|
1601
|
-
* Media kept in the package byte-for-byte that the painter cannot hand to an `<img>`.
|
|
1602
|
-
* A decode port may rasterize it; without one it paints as a labelled placeholder.
|
|
1603
|
-
*/
|
|
1604
|
-
type PreservedImageMime = 'image/tiff' | 'image/x-emf' | 'image/x-wmf';
|
|
1605
|
-
/**
|
|
1606
|
-
* What is known about one embedded image: validated, refused, or still decoding.
|
|
1607
|
-
*
|
|
1608
|
-
* Content type is a CLAIM. Signature sniffing, structural header validation and the decode port
|
|
1609
|
-
* are authoritative, and bytes that fail them never enter public state.
|
|
1610
|
-
*/
|
|
1611
|
-
type ImageResourceState = {
|
|
1612
|
-
readonly kind: 'ready';
|
|
1613
|
-
readonly partName: string;
|
|
1614
|
-
readonly contentId: string;
|
|
1615
|
-
readonly resourceKey: string;
|
|
1616
|
-
readonly validatedHandle: ValidatedImageBytesHandle;
|
|
1617
|
-
readonly mime: RenderableImageMime;
|
|
1618
|
-
readonly pixelWidth: number;
|
|
1619
|
-
readonly pixelHeight: number;
|
|
1620
|
-
readonly dpiX: number;
|
|
1621
|
-
readonly dpiY: number;
|
|
1622
|
-
} | {
|
|
1623
|
-
readonly kind: 'unrenderable';
|
|
1624
|
-
readonly partName: string | null;
|
|
1625
|
-
readonly mime: RenderableImageMime | PreservedImageMime | 'unknown';
|
|
1626
|
-
readonly reason: 'unsupported-format' | 'non-picture-graphic' | 'signature-mismatch' | 'decode-failed' | 'resource-limit';
|
|
1627
|
-
} | {
|
|
1628
|
-
readonly kind: 'external';
|
|
1629
|
-
readonly relationshipId: string;
|
|
1630
|
-
readonly sinkSafe: boolean;
|
|
1631
|
-
} | {
|
|
1632
|
-
readonly kind: 'missing';
|
|
1633
|
-
readonly relationshipId: string;
|
|
1634
|
-
} | {
|
|
1635
|
-
readonly kind: 'pending';
|
|
1636
|
-
readonly resourceKey: string;
|
|
1637
|
-
};
|
|
1638
|
-
/**
|
|
1639
|
-
* The injected image decoder.
|
|
1640
|
-
*
|
|
1641
|
-
* A port rather than a direct `Image`/`createImageBitmap` call, so a worker or server runtime
|
|
1642
|
-
* supplies its own and the engine never reaches for a browser global.
|
|
1643
|
-
*/
|
|
1644
|
-
interface ImageDecodePort {
|
|
1645
|
-
decode(bytes: Uint8Array, mime: SupportedImageMime, limits: ImageResourceLimits,
|
|
1646
|
-
/** Aborted when the owning lookup/session is disposed. */
|
|
1647
|
-
signal?: AbortSignal): Promise<Readonly<{
|
|
1648
|
-
pixelWidth: number;
|
|
1649
|
-
pixelHeight: number;
|
|
1650
|
-
dpiX: number;
|
|
1651
|
-
dpiY: number;
|
|
1652
|
-
}>>;
|
|
1653
|
-
/**
|
|
1654
|
-
* Optional conversion of media an `<img>` cannot render (EMF/WMF metafiles, TIFF) into a
|
|
1655
|
-
* renderable raster. The returned bytes are untrusted and re-enter the full raster
|
|
1656
|
-
* validation path (sniff, header, pixel caps, decode) before they can become a ready
|
|
1657
|
-
* resource. A null return declines the format and keeps the labelled placeholder; so does
|
|
1658
|
-
* a throw, as `decode-failed`.
|
|
1659
|
-
*/
|
|
1660
|
-
convertPreserved?(bytes: Uint8Array, mime: PreservedImageMime, limits: ImageResourceLimits,
|
|
1661
|
-
/** Aborted when the owning lookup/session is disposed. */
|
|
1662
|
-
signal?: AbortSignal): Promise<Readonly<{
|
|
1663
|
-
bytes: Uint8Array;
|
|
1664
|
-
mime: SupportedImageMime;
|
|
1665
|
-
}> | null>;
|
|
1666
|
-
}
|
|
1667
|
-
/** Resolves a relationship id to a validated image resource, or reports why it could not. */
|
|
1668
|
-
interface ImageResourceLookup {
|
|
1669
|
-
readonly resolveEmbedded: (ownerPartName: string, relationshipId: string) => Promise<ImageResourceState>;
|
|
1670
|
-
readonly resolveLinked: (ownerPartName: string, relationshipId: string) => ImageResourceState;
|
|
1671
|
-
readonly resolveForProjection: (projection: DrawingProjection) => Promise<ImageResourceState>;
|
|
1672
|
-
readonly liveReferenceCount: (partName: string) => number;
|
|
1673
|
-
readonly dispose: () => void;
|
|
1674
|
-
}
|
|
1675
|
-
/** Maximum prefix inspected for SVG root detection (exported for bounded-scan tests). */
|
|
1676
|
-
declare const MAX_SVG_SNIFF_BYTES = 512;
|
|
1677
|
-
/** A raster header that passed structural validation: its real MIME type and pixel extent. */
|
|
1678
|
-
interface ValidatedRasterHeader {
|
|
1679
|
-
readonly pixelWidth: number;
|
|
1680
|
-
readonly pixelHeight: number;
|
|
1681
|
-
/** Horizontal physical density when bounded header metadata supplies it. */
|
|
1682
|
-
readonly dpiX?: number;
|
|
1683
|
-
/** Vertical physical density when bounded header metadata supplies it. */
|
|
1684
|
-
readonly dpiY?: number;
|
|
1685
|
-
}
|
|
1686
|
-
/** Bounded scan for an `<svg` document root (optional `<?xml` prolog only). */
|
|
1687
|
-
declare function hasBoundedSvgRoot(bytes: Uint8Array): boolean;
|
|
1688
|
-
/** Signature sniffing — authoritative over declared content type. */
|
|
1689
|
-
declare function sniffImageMime(bytes: Uint8Array): RenderableImageMime | PreservedImageMime | 'unknown';
|
|
1690
|
-
/** Structural PNG IHDR validation before decode. */
|
|
1691
|
-
declare function validatePngHeader(bytes: Uint8Array): ValidatedRasterHeader | null;
|
|
1692
|
-
/** Structural GIF logical screen descriptor validation before decode. */
|
|
1693
|
-
declare function validateGifHeader(bytes: Uint8Array): ValidatedRasterHeader | null;
|
|
1694
|
-
/** Bounded JPEG marker scan through the first supported SOF marker. */
|
|
1695
|
-
declare function validateJpegHeader(bytes: Uint8Array): ValidatedRasterHeader | null;
|
|
1696
|
-
/**
|
|
1697
|
-
* Intrinsic size of an SVG, resolved the way a browser sizes one: absolute `width`/`height`
|
|
1698
|
-
* first, then `viewBox` for the missing axis or ratio, then the CSS 300x150 default.
|
|
1699
|
-
*
|
|
1700
|
-
* This is metadata for insert and reset-to-natural-size only. Layout uses the authored
|
|
1701
|
-
* `wp:extent` and the browser rasterizes into that box, so nothing here sizes an allocation
|
|
1702
|
-
* and an out-of-range value is clamped rather than refused.
|
|
1703
|
-
*/
|
|
1704
|
-
declare function resolveSvgIntrinsicSize(bytes: Uint8Array, limits: ImageResourceLimits): ValidatedRasterHeader | null;
|
|
1705
|
-
/**
|
|
1706
|
-
* Validate a raster image's header structurally and report its real MIME type and extent.
|
|
1707
|
-
*
|
|
1708
|
-
* Content type is a CLAIM; this is what makes it a fact. A file declaring `image/png` over JPEG
|
|
1709
|
-
* bytes is caught here rather than at decode.
|
|
1710
|
-
*/
|
|
1711
|
-
declare function validateRasterHeader(bytes: Uint8Array, mime: SupportedImageMime): ValidatedRasterHeader | null;
|
|
1712
|
-
/** Package-wide live drawing references to a media part name. */
|
|
1713
|
-
declare function liveDrawingReferenceCount(pkg: OoxmlPackage, partName: string): number;
|
|
1714
|
-
/** How the image cache decodes, and what it will spend doing so. */
|
|
1715
|
-
interface CreateImageResourceCacheOptions {
|
|
1716
|
-
readonly limits?: Partial<ImageResourceLimits>;
|
|
1717
|
-
readonly decodePort: ImageDecodePort;
|
|
1718
|
-
}
|
|
1719
|
-
/**
|
|
1720
|
-
* Derived cache for one immutable package snapshot. Registry identity is
|
|
1721
|
-
* `(package snapshot, decodePort object, normalized limits)` — the first caller
|
|
1722
|
-
* never imposes its decoder or limits on later callers with different options.
|
|
1723
|
-
*/
|
|
1724
|
-
declare function imageResourceLookupFor(pkg: OoxmlPackage, options: CreateImageResourceCacheOptions): ImageResourceLookup;
|
|
1725
|
-
/** @deprecated Prefer {@link imageResourceLookupFor} — registry binds cache to package identity. */
|
|
1726
|
-
/** Build the per-document image cache. Validated bytes only; refusals are remembered too. */
|
|
1727
|
-
declare function createImageResourceCache(initialPkg: OoxmlPackage, options: CreateImageResourceCacheOptions): ImageResourceLookup;
|
|
1728
|
-
|
|
1729
1694
|
/** Caps applied while loading a package: zip, XML, part count and relationship count. */
|
|
1730
1695
|
interface OoxmlPackageLimits {
|
|
1731
1696
|
readonly zip?: ZipLimits;
|
|
@@ -1774,162 +1739,108 @@ type OoxmlPackageResult = {
|
|
|
1774
1739
|
readonly ok: true;
|
|
1775
1740
|
readonly package: OoxmlPackage;
|
|
1776
1741
|
} | {
|
|
1777
|
-
readonly ok: false;
|
|
1778
|
-
readonly reason: OoxmlPackageRejection;
|
|
1779
|
-
readonly detail?: string;
|
|
1780
|
-
readonly limit?: 'zip.maxTotalBytes' | 'zip.maxRatio';
|
|
1781
|
-
};
|
|
1782
|
-
declare function readOoxmlPackage(bytes: Uint8Array, limits?: OoxmlPackageLimits): OoxmlPackageResult;
|
|
1783
|
-
/**
|
|
1784
|
-
* Serialize a canonical package back to DOCX bytes.
|
|
1785
|
-
*
|
|
1786
|
-
* Starts from the ORIGINAL entry bytes and overwrites only the parts held as trees. A part
|
|
1787
|
-
* the loader did not model — media, fonts, an XML part outside the modeled set — passes
|
|
1788
|
-
* through untouched, so round-tripping a document cannot lose a part the engine never
|
|
1789
|
-
* claimed to understand.
|
|
1790
|
-
*
|
|
1791
|
-
* The modeled parts are re-emitted NORMALIZED from the tree rather than patched as text.
|
|
1792
|
-
* That is the whole point of the canonical tree: correctness is judged by the two D9
|
|
1793
|
-
* oracles (the namespace-aware fingerprint and the save/reopen semantic digest), not by
|
|
1794
|
-
* byte equality, so a different-but-equivalent spelling is not a defect.
|
|
1795
|
-
*
|
|
1796
|
-
* `writeZip` re-validates every part name, so a name that became unsafe between load and
|
|
1797
|
-
* save cannot be smuggled into the archive.
|
|
1798
|
-
*/
|
|
1799
|
-
declare function writeOoxmlPackage(pkg: OoxmlPackage): Uint8Array;
|
|
1800
|
-
/** Replace one part's tree, returning a new package. Pure, like the tree edits themselves. */
|
|
1801
|
-
declare function withPart(pkg: OoxmlPackage, part: OoxmlPart): OoxmlPackage;
|
|
1802
|
-
|
|
1803
|
-
type AutomationTableMutation = {
|
|
1804
|
-
readonly kind: 'values';
|
|
1805
|
-
readonly values: readonly (readonly string[])[];
|
|
1806
|
-
} | {
|
|
1807
|
-
readonly kind: 'addRows' | 'addColumns';
|
|
1808
|
-
readonly location: 'start' | 'end';
|
|
1809
|
-
readonly count: number;
|
|
1810
|
-
readonly values?: readonly (readonly string[])[];
|
|
1811
|
-
} | {
|
|
1812
|
-
readonly kind: 'deleteRows' | 'deleteColumns';
|
|
1813
|
-
readonly index: number;
|
|
1814
|
-
readonly count: number;
|
|
1815
|
-
} | {
|
|
1816
|
-
readonly kind: 'delete';
|
|
1817
|
-
} | {
|
|
1818
|
-
readonly kind: 'properties';
|
|
1819
|
-
readonly styleId?: string;
|
|
1820
|
-
readonly headerRowCount?: number;
|
|
1821
|
-
} | {
|
|
1822
|
-
readonly kind: 'cell';
|
|
1823
|
-
readonly cellId: string;
|
|
1824
|
-
readonly value?: string;
|
|
1825
|
-
readonly columnWidth?: number;
|
|
1826
|
-
readonly shadingColor?: string;
|
|
1827
|
-
readonly verticalAlignment?: 'Top' | 'Center' | 'Bottom';
|
|
1742
|
+
readonly ok: false;
|
|
1743
|
+
readonly reason: OoxmlPackageRejection;
|
|
1744
|
+
readonly detail?: string;
|
|
1745
|
+
readonly limit?: 'zip.maxTotalBytes' | 'zip.maxRatio';
|
|
1828
1746
|
};
|
|
1747
|
+
declare function readOoxmlPackage(bytes: Uint8Array, limits?: OoxmlPackageLimits): OoxmlPackageResult;
|
|
1748
|
+
/**
|
|
1749
|
+
* Serialize a canonical package back to DOCX bytes.
|
|
1750
|
+
*
|
|
1751
|
+
* Starts from the ORIGINAL entry bytes and overwrites only the parts held as trees. A part
|
|
1752
|
+
* the loader did not model — media, fonts, an XML part outside the modeled set — passes
|
|
1753
|
+
* through untouched, so round-tripping a document cannot lose a part the engine never
|
|
1754
|
+
* claimed to understand.
|
|
1755
|
+
*
|
|
1756
|
+
* The modeled parts are re-emitted NORMALIZED from the tree rather than patched as text.
|
|
1757
|
+
* That is the whole point of the canonical tree: correctness is judged by the two D9
|
|
1758
|
+
* oracles (the namespace-aware fingerprint and the save/reopen semantic digest), not by
|
|
1759
|
+
* byte equality, so a different-but-equivalent spelling is not a defect.
|
|
1760
|
+
*
|
|
1761
|
+
* `writeZip` re-validates every part name, so a name that became unsafe between load and
|
|
1762
|
+
* save cannot be smuggled into the archive.
|
|
1763
|
+
*/
|
|
1764
|
+
declare function writeOoxmlPackage(pkg: OoxmlPackage): Uint8Array;
|
|
1765
|
+
/** Replace one part's tree, returning a new package. Pure, like the tree edits themselves. */
|
|
1766
|
+
declare function withPart(pkg: OoxmlPackage, part: OoxmlPart): OoxmlPackage;
|
|
1829
1767
|
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
readonly code: string;
|
|
1835
|
-
}
|
|
1836
|
-
|
|
1837
|
-
type InsertTextOp = {
|
|
1838
|
-
readonly op: 'insertText';
|
|
1768
|
+
/** The `w15` namespace: `commentsExtended.xml` — thread parent and resolved state. */
|
|
1769
|
+
declare const W15_NAMESPACE_URI = "http://schemas.microsoft.com/office/word/2012/wordml";
|
|
1770
|
+
/** A position in one story: a paragraph node id plus a UTF-16 offset inside it. */
|
|
1771
|
+
interface CommentPosition {
|
|
1839
1772
|
readonly paragraphId: string;
|
|
1840
|
-
/** Legacy text form identity for protected filling; never an inline wrapper owner. */
|
|
1841
|
-
readonly textFormFieldId?: string;
|
|
1842
1773
|
readonly offset: number;
|
|
1843
|
-
readonly text: string;
|
|
1844
|
-
/**
|
|
1845
|
-
* Write this as a TRACKED insertion, attributed here.
|
|
1846
|
-
*
|
|
1847
|
-
* On the op rather than on the store, so suggesting stays a decision the surface makes
|
|
1848
|
-
* per edit and the write vocabulary stays explicit — a global "everything is tracked
|
|
1849
|
-
* now" flag is exactly what `DocEdits` refuses, because it makes the meaning of an op
|
|
1850
|
-
* depend on state the op does not carry.
|
|
1851
|
-
*/
|
|
1852
|
-
readonly revision?: RevisionAttributionInput;
|
|
1853
|
-
/**
|
|
1854
|
-
* When set, the text belongs INSIDE this content control, whatever sits at the offset.
|
|
1855
|
-
*
|
|
1856
|
-
* A boundary offset is owned by the run that starts there, which at a control's trailing
|
|
1857
|
-
* edge is the run after the control — so an offset alone cannot say "append to this field",
|
|
1858
|
-
* the way it cannot say which run of a field result to format (see `targetRunIds`). A
|
|
1859
|
-
* caller that names the control gets the text in the control; one that does not gets the
|
|
1860
|
-
* plain offset rule, which is what a keystroke beside a field means.
|
|
1861
|
-
*/
|
|
1862
|
-
readonly inside?: string;
|
|
1863
|
-
/**
|
|
1864
|
-
* Which side of a run BOUNDARY the text joins. Default `'left'` — Word's typing rule:
|
|
1865
|
-
* the next character takes the formatting of the character before the caret.
|
|
1866
|
-
*
|
|
1867
|
-
* `'right'` is for a caller that is not typing but placing text inside the run that
|
|
1868
|
-
* STARTS at the offset — the hyperlink editor rewriting a link's display text, where
|
|
1869
|
-
* landing left of the boundary would put the new text outside the link. Ignored when
|
|
1870
|
-
* the offset falls strictly inside a run, which has no boundary to choose.
|
|
1871
|
-
*/
|
|
1872
|
-
readonly bias?: 'left' | 'right';
|
|
1873
|
-
};
|
|
1874
|
-
type DeleteTextOp = {
|
|
1875
|
-
readonly op: 'deleteText';
|
|
1876
|
-
readonly paragraphId: string;
|
|
1877
|
-
/** Legacy text form identity for protected filling; never an inline wrapper owner. */
|
|
1878
|
-
readonly textFormFieldId?: string;
|
|
1879
|
-
readonly start: number;
|
|
1880
|
-
readonly end: number;
|
|
1881
|
-
/** Write this as a TRACKED deletion — the characters stay, wrapped in `w:del`. */
|
|
1882
|
-
readonly revision?: RevisionAttributionInput;
|
|
1883
|
-
};
|
|
1884
|
-
|
|
1885
|
-
/** Editable legacy text input types. Other authored types remain inert. */
|
|
1886
|
-
type TextFormFieldType = 'regular' | 'number' | 'date';
|
|
1887
|
-
/** Options stored in the legacy field definition. Zero means unlimited length. */
|
|
1888
|
-
interface TextFormFieldOptions {
|
|
1889
|
-
readonly type: TextFormFieldType;
|
|
1890
|
-
readonly maxLength: number;
|
|
1891
|
-
readonly format: string;
|
|
1892
|
-
readonly enabled: boolean;
|
|
1893
1774
|
}
|
|
1894
|
-
/**
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
interface
|
|
1903
|
-
readonly
|
|
1904
|
-
|
|
1905
|
-
readonly
|
|
1906
|
-
readonly
|
|
1907
|
-
readonly
|
|
1908
|
-
readonly
|
|
1909
|
-
readonly maxLength: number;
|
|
1910
|
-
readonly format: string;
|
|
1911
|
-
readonly chromeIds: readonly string[];
|
|
1775
|
+
/**
|
|
1776
|
+
* Where a comment is anchored, as a range.
|
|
1777
|
+
*
|
|
1778
|
+
* `orphaned` records that the file did not give this comment a usable range — a reference with
|
|
1779
|
+
* no range markers, or a start with no end. The comment is still listed, marked orphaned,
|
|
1780
|
+
* rather than dropped: a reviewer's remark disappearing silently is worse than one that says
|
|
1781
|
+
* it lost its text.
|
|
1782
|
+
*/
|
|
1783
|
+
interface CommentAnchor {
|
|
1784
|
+
readonly commentId: string;
|
|
1785
|
+
/** Canonical name of the part the range lives in, so a header comment is attributable. */
|
|
1786
|
+
readonly partName: string;
|
|
1787
|
+
readonly start: CommentPosition;
|
|
1788
|
+
readonly end: CommentPosition;
|
|
1789
|
+
readonly orphaned: boolean;
|
|
1912
1790
|
}
|
|
1913
|
-
/**
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
readonly
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
readonly
|
|
1921
|
-
|
|
1922
|
-
readonly
|
|
1923
|
-
|
|
1791
|
+
/** One comment as authored in `word/comments.xml`. */
|
|
1792
|
+
interface CommentRecord {
|
|
1793
|
+
readonly id: string;
|
|
1794
|
+
readonly author: string;
|
|
1795
|
+
readonly initials?: string;
|
|
1796
|
+
readonly date?: string;
|
|
1797
|
+
/** Body paragraphs, as tree nodes, so the surface renders measured text rather than a string. */
|
|
1798
|
+
readonly blocks: readonly OoxmlElement[];
|
|
1799
|
+
/** `w14:paraId` of the last body paragraph — the key thread state is stored under. */
|
|
1800
|
+
readonly paraId?: string;
|
|
1801
|
+
/** `@w16cid:parentId` — the `w:id` of the comment this replies to, when the file names it. */
|
|
1802
|
+
readonly parentCommentId?: string;
|
|
1924
1803
|
}
|
|
1925
|
-
/**
|
|
1926
|
-
interface
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
readonly
|
|
1930
|
-
readonly paragraphId: string;
|
|
1931
|
-
readonly fieldNodeId: string;
|
|
1804
|
+
/** Thread state for one comment, read from `commentsExtended.xml`. */
|
|
1805
|
+
interface CommentThreadState {
|
|
1806
|
+
/** `@w15:paraIdParent` — the comment this one replies to, absent for a top-level comment. */
|
|
1807
|
+
readonly parentParaId?: string;
|
|
1808
|
+
readonly done: boolean;
|
|
1932
1809
|
}
|
|
1810
|
+
/**
|
|
1811
|
+
* Every comment anchor in one story, in document order.
|
|
1812
|
+
*
|
|
1813
|
+
* Overlapping and nested ranges are supported because each anchor is resolved independently —
|
|
1814
|
+
* Word produces both, and a model that assumed ranges nest cleanly would mis-anchor them.
|
|
1815
|
+
*
|
|
1816
|
+
* A start with no matching end anchors to the end of its own paragraph and is reported orphaned
|
|
1817
|
+
* rather than guessed at: extending it to the next end marker would attach a reviewer's remark
|
|
1818
|
+
* to text they never saw.
|
|
1819
|
+
*/
|
|
1820
|
+
declare function commentAnchorsOfStory(part: OoxmlPart): CommentAnchor[];
|
|
1821
|
+
/**
|
|
1822
|
+
* The comments in `word/comments.xml`, in authored order.
|
|
1823
|
+
*
|
|
1824
|
+
* Every value here comes from a file an attacker fully controls, so nothing is interpreted:
|
|
1825
|
+
* author, initials and date are carried verbatim for a surface that will set them as TEXT.
|
|
1826
|
+
*/
|
|
1827
|
+
declare function commentsOfPart(part: OoxmlPart): CommentRecord[];
|
|
1828
|
+
/**
|
|
1829
|
+
* Thread state by `w14:paraId`, from `commentsExtended.xml`.
|
|
1830
|
+
*
|
|
1831
|
+
* The part being PRESENT is not evidence of threading. `issue-68-large-comments-suggestions.docx`
|
|
1832
|
+
* ships it with 212 entries carrying `@w15:done` and not one `@w15:paraIdParent`, so it records
|
|
1833
|
+
* resolved state for a flat list. Absent parent means top-level, and that is a fact about the
|
|
1834
|
+
* file rather than a default this code chose.
|
|
1835
|
+
*/
|
|
1836
|
+
declare function threadStateOfPart(part: OoxmlPart): Map<string, CommentThreadState>;
|
|
1837
|
+
/**
|
|
1838
|
+
* Whether the package holds any `w:comment` record — the cheap gate before a reap.
|
|
1839
|
+
*
|
|
1840
|
+
* Overflow cannot prove the package is comment-free, so it returns true and the reap still
|
|
1841
|
+
* runs rather than skipping cleanup.
|
|
1842
|
+
*/
|
|
1843
|
+
declare function hasAnyComment(pkg: OoxmlPackage): boolean;
|
|
1933
1844
|
|
|
1934
1845
|
/** How deep controls may nest before a walk stops descending. Shared by every lane. */
|
|
1935
1846
|
declare const MAX_CONTENT_CONTROL_NESTING = 32;
|
|
@@ -2087,73 +1998,363 @@ interface ContentControlEntry {
|
|
|
2087
1998
|
readonly ancestors: readonly OoxmlContentControlNode[];
|
|
2088
1999
|
}
|
|
2089
2000
|
/**
|
|
2090
|
-
* Every control under a node, in document order, bounded in depth and in count.
|
|
2001
|
+
* Every control under a node, in document order, bounded in depth and in count.
|
|
2002
|
+
*
|
|
2003
|
+
* ONE walk, shared. The nesting bound is the same one layout flattens with, so a control
|
|
2004
|
+
* a lane can address is a control every lane can address — and a file that nests past it
|
|
2005
|
+
* keeps its content in the tree (the serializer never stops) while no walk recurses
|
|
2006
|
+
* further.
|
|
2007
|
+
*/
|
|
2008
|
+
declare function contentControlsIn(root: OoxmlNode, options?: {
|
|
2009
|
+
readonly maxDepth?: number;
|
|
2010
|
+
readonly limit?: number;
|
|
2011
|
+
}): readonly ContentControlEntry[];
|
|
2012
|
+
/** Find one control by canonical node id, with the same bounded walk. */
|
|
2013
|
+
declare function findContentControl(root: OoxmlNode, nodeId: string): ContentControlEntry | null;
|
|
2014
|
+
/**
|
|
2015
|
+
* The plain text a control's content holds, in reading order.
|
|
2016
|
+
*
|
|
2017
|
+
* `w:delText` is excluded: struck text is not the control's value, and a dropdown whose
|
|
2018
|
+
* old item is still present as a tracked deletion would otherwise report both.
|
|
2019
|
+
*/
|
|
2020
|
+
declare function contentControlTextOf(control: OoxmlNode): string;
|
|
2021
|
+
/**
|
|
2022
|
+
* Resolve the lock a position inherits from the controls enclosing it.
|
|
2023
|
+
*
|
|
2024
|
+
* CONSERVATIVE, because a template that says a field cannot be edited and sits inside a
|
|
2025
|
+
* section that says it cannot be removed means both. Each half of `ST_Lock` is taken
|
|
2026
|
+
* independently and the strongest wins, so an unlocked control inside a `contentLocked`
|
|
2027
|
+
* one is still content-locked — a nested control cannot grant a permission its parent
|
|
2028
|
+
* withheld, which is the only reading under which a lock is a lock.
|
|
2029
|
+
*/
|
|
2030
|
+
declare function resolveContentControlLock(chain: readonly ContentControlLock[]): ContentControlLock;
|
|
2031
|
+
/** Whether a resolved lock forbids editing the content it covers. */
|
|
2032
|
+
declare function lockForbidsEdit(lock: ContentControlLock): boolean;
|
|
2033
|
+
/** Whether a resolved lock forbids removing the control itself. */
|
|
2034
|
+
declare function lockForbidsRemoval(lock: ContentControlLock): boolean;
|
|
2035
|
+
/**
|
|
2036
|
+
* `CT_SdtPr`'s declared child order (§17.5.2.38), followed by the type choice.
|
|
2037
|
+
*
|
|
2038
|
+
* Serialization re-emits children in tree order, so the ONLY way a write keeps the
|
|
2039
|
+
* sequence valid is to place the child it authors at its schema position — which is what
|
|
2040
|
+
* {@link orderedContentControlProperties} does.
|
|
2041
|
+
*/
|
|
2042
|
+
declare const CONTENT_CONTROL_PROPERTY_ORDER: readonly string[];
|
|
2043
|
+
/**
|
|
2044
|
+
* Rebuild a `w:sdtPr`'s children in schema order.
|
|
2045
|
+
*
|
|
2046
|
+
* Modelled children sort to their declared position and the type element follows them,
|
|
2047
|
+
* as the sequence requires. Everything else — a `w15:repeatingSection`, a vendor
|
|
2048
|
+
* extension, the `w14:checkbox` that is not part of the ECMA-376 choice — keeps the order
|
|
2049
|
+
* it was authored in and follows the modelled block, so a write that touches one property
|
|
2050
|
+
* neither drops nor reorders anything it does not name.
|
|
2051
|
+
*/
|
|
2052
|
+
declare function orderedContentControlProperties(children: readonly OoxmlNode[]): readonly OoxmlNode[];
|
|
2053
|
+
/**
|
|
2054
|
+
* The next `w:id` to write.
|
|
2055
|
+
*
|
|
2056
|
+
* Solo: one past the document's own maximum. Never a clock, a timestamp, a random source
|
|
2057
|
+
* or a hash: those collide with ids already in the file and produce values Word rejects.
|
|
2058
|
+
* Null when the document already reaches the signed 32-bit bound, so the caller refuses
|
|
2059
|
+
* rather than wrapping into a negative id. Hostile or out-of-range existing values are
|
|
2060
|
+
* ignored for seeding rather than counted past.
|
|
2061
|
+
*
|
|
2062
|
+
* When a collaboration actor is bound (explicit argument or the open store transaction),
|
|
2063
|
+
* the next id is the next unused value in that actor's stripe. Two peers inserting a
|
|
2064
|
+
* generic content control — including a custom node authored as `w:sdt` — from the same
|
|
2065
|
+
* snapshot then cannot share a `w:id`.
|
|
2066
|
+
*/
|
|
2067
|
+
declare function allocateContentControlId(root: OoxmlNode, actorId?: string): number | null;
|
|
2068
|
+
|
|
2069
|
+
/** A position in the model offset space of one story. */
|
|
2070
|
+
interface ReviewPosition {
|
|
2071
|
+
readonly paragraphId: string;
|
|
2072
|
+
readonly offset: number;
|
|
2073
|
+
}
|
|
2074
|
+
/** Where an item is anchored: a range in one story. */
|
|
2075
|
+
interface ReviewRange {
|
|
2076
|
+
readonly partName: string;
|
|
2077
|
+
readonly start: ReviewPosition;
|
|
2078
|
+
readonly end: ReviewPosition;
|
|
2079
|
+
}
|
|
2080
|
+
/**
|
|
2081
|
+
* What kind of decision a revision card represents.
|
|
2082
|
+
*
|
|
2083
|
+
* Wider than the four content wrappers, because a reviewer has to be shown every pending
|
|
2084
|
+
* decision, including the ones that decorate no characters. A card the surface cannot show is
|
|
2085
|
+
* a change the reviewer never learns about — and `acceptAllRevisions` refuses if ANY revision
|
|
2086
|
+
* in the document is one the engine cannot resolve, so an invisible one makes Accept All fail
|
|
2087
|
+
* for a reason nothing on screen explains.
|
|
2088
|
+
*/
|
|
2089
|
+
type ReviewRevisionKind = 'insert' | 'delete'
|
|
2090
|
+
/**
|
|
2091
|
+
* A deletion and an insertion that are one edit: text typed over a selection.
|
|
2092
|
+
*
|
|
2093
|
+
* Word shows these as a single `Replaced "x" with "y"` card, and resolving one half
|
|
2094
|
+
* without the other is never what the reviewer meant — accepting the deletion alone
|
|
2095
|
+
* leaves the replacement text unproposed, rejecting it alone leaves both.
|
|
2096
|
+
*/
|
|
2097
|
+
| 'replace' | 'moveFrom' | 'moveTo'
|
|
2098
|
+
/** `w:rPrChange` / `w:pPrChange` — the words are unchanged, their formatting is not. */
|
|
2099
|
+
| 'format'
|
|
2100
|
+
/** `w:pPr/w:rPr/w:ins|w:del` — a paragraph split or merge. */
|
|
2101
|
+
| 'paragraphMark'
|
|
2102
|
+
/** A row, cell, section or grid revision. Supported row revisions are resolvable. */
|
|
2103
|
+
| 'structural';
|
|
2104
|
+
/**
|
|
2105
|
+
* One tracked change as a review card.
|
|
2106
|
+
*
|
|
2107
|
+
* Keyed per DECISION rather than per site: a revision spanning three ranges is one card, because
|
|
2108
|
+
* accepting it accepts all three.
|
|
2109
|
+
*/
|
|
2110
|
+
interface ReviewRevisionItem {
|
|
2111
|
+
readonly kind: 'revision';
|
|
2112
|
+
/** Stable across renders and unique per DECISION, not per site. */
|
|
2113
|
+
readonly id: string;
|
|
2114
|
+
/** The payload `acceptRevision` / `rejectRevision` take. */
|
|
2115
|
+
readonly address: RevisionAddress;
|
|
2116
|
+
/**
|
|
2117
|
+
* EVERY address this decision covers, `address` first.
|
|
2118
|
+
*
|
|
2119
|
+
* More than one only for a replacement, whose halves a foreign editor may have written
|
|
2120
|
+
* as two independent revisions. Accept and reject walk all of them in one transaction:
|
|
2121
|
+
* resolving one half and leaving the other is a state no reviewer asked for.
|
|
2122
|
+
*/
|
|
2123
|
+
readonly addresses: readonly RevisionAddress[];
|
|
2124
|
+
/** The words a replacement removes. Empty for every other kind. */
|
|
2125
|
+
readonly replacedText: string;
|
|
2126
|
+
readonly revisionKind: ReviewRevisionKind;
|
|
2127
|
+
/** OOXML property-change element, used to resolve independently numbered formatting kinds. */
|
|
2128
|
+
readonly formattingKind?: string;
|
|
2129
|
+
/** Changed direct formatting values, ready for localized review summaries. */
|
|
2130
|
+
readonly formattingChanges?: readonly {
|
|
2131
|
+
readonly property: 'bold' | 'italic' | 'underline' | 'strike' | 'fontFamily' | 'fontSize' | 'color' | 'alignment' | 'leftIndent' | 'rightIndent' | 'firstLineIndent' | 'hangingIndent' | 'spaceBefore' | 'spaceAfter';
|
|
2132
|
+
/** New direct value; null means inherit. Sizes and distances are in points. */
|
|
2133
|
+
readonly value: string | null;
|
|
2134
|
+
}[];
|
|
2135
|
+
/** Newly applied proofing language codes in a tracked formatting change. */
|
|
2136
|
+
readonly formattingLanguages?: readonly string[];
|
|
2137
|
+
/**
|
|
2138
|
+
* WHICH decision a `paragraphMark` records, absent for every other kind.
|
|
2139
|
+
*
|
|
2140
|
+
* `EG_ParaRPrTrackChanges` is `ins? del? moveFrom? moveTo?`, and the four say opposite
|
|
2141
|
+
* things about one break. Without this a card called a deleted break an inserted one, which
|
|
2142
|
+
* is the reverse of what Accept on that card does.
|
|
2143
|
+
*/
|
|
2144
|
+
readonly markDirection?: 'insert' | 'delete' | 'moveFrom' | 'moveTo';
|
|
2145
|
+
readonly author: string;
|
|
2146
|
+
readonly date?: string;
|
|
2147
|
+
/** Text the revision covers, for the card summary. Empty for changes with no characters. */
|
|
2148
|
+
readonly text: string;
|
|
2149
|
+
/** Every site this decision touches, in document order. */
|
|
2150
|
+
readonly ranges: readonly ReviewRange[];
|
|
2151
|
+
/**
|
|
2152
|
+
* How deeply this change is NESTED inside other changes, 0 for an unenclosed one.
|
|
2153
|
+
*
|
|
2154
|
+
* `w:ins` wrapping `w:del` is content one reviewer added and another struck. Both stay
|
|
2155
|
+
* pending, so both are cards, over one identical range — and a range then cannot say which
|
|
2156
|
+
* change a caret is in. Word treats the innermost as the operative one, so it wins the caret
|
|
2157
|
+
* and the change enclosing it stays listed and reachable.
|
|
2158
|
+
*/
|
|
2159
|
+
readonly nesting: number;
|
|
2160
|
+
/**
|
|
2161
|
+
* How many leading `ranges` are the STRUCK half of a replacement.
|
|
2162
|
+
*
|
|
2163
|
+
* A replacement's card is one decision but its ranges are two colours — red over what is
|
|
2164
|
+
* going, green over what takes its place. ABSENT when the halves do not split at a single
|
|
2165
|
+
* point, which is what a file recording both under one revision id can produce; a surface
|
|
2166
|
+
* then has no basis for two colours and should paint one neutral band rather than guess.
|
|
2167
|
+
*/
|
|
2168
|
+
readonly replacedRangeCount?: number;
|
|
2169
|
+
/**
|
|
2170
|
+
* True when the engine cannot resolve this kind, so accept and reject must not be offered.
|
|
2171
|
+
*
|
|
2172
|
+
* Derived by the DERIVATION rather than from a caller-supplied predicate: the refusal list
|
|
2173
|
+
* is internal, and a surface asked to compute it would have to guess. A card that offers a
|
|
2174
|
+
* button the engine will refuse is worse than one that explains why it cannot.
|
|
2175
|
+
*/
|
|
2176
|
+
readonly readOnly: boolean;
|
|
2177
|
+
/** The other half of a move, or the other side of a delete/insert replacement. */
|
|
2178
|
+
readonly pairedWith?: string;
|
|
2179
|
+
/**
|
|
2180
|
+
* Comments answering this change, in document order.
|
|
2181
|
+
*
|
|
2182
|
+
* A reply to a tracked change IS a comment: `w:ins` and `w:del` carry no body, so the text
|
|
2183
|
+
* is written as a comment over the revision's own range and the range is what links them.
|
|
2184
|
+
*/
|
|
2185
|
+
readonly replyIds: readonly string[];
|
|
2186
|
+
}
|
|
2187
|
+
/**
|
|
2188
|
+
* One comment as a review card. A reply carries `parentId`; OOXML gives replies no separate
|
|
2189
|
+
* element, so threads are reconstructed from that link.
|
|
2190
|
+
*/
|
|
2191
|
+
interface ReviewCommentItem {
|
|
2192
|
+
readonly kind: 'comment';
|
|
2193
|
+
readonly id: string;
|
|
2194
|
+
readonly comment: CommentRecord;
|
|
2195
|
+
readonly range: ReviewRange | null;
|
|
2196
|
+
readonly resolved: boolean;
|
|
2197
|
+
/** The comment this replies to, absent for a top-level comment. */
|
|
2198
|
+
readonly parentId?: string;
|
|
2199
|
+
/** The REVISION this comment answers, when it covers exactly that change's characters. */
|
|
2200
|
+
readonly parentRevisionId?: string;
|
|
2201
|
+
/** Replies to this comment, in document order. Empty for a reply or a childless comment. */
|
|
2202
|
+
readonly replyIds: readonly string[];
|
|
2203
|
+
/** True when the file gave this comment no usable range. */
|
|
2204
|
+
readonly orphaned: boolean;
|
|
2205
|
+
}
|
|
2206
|
+
/**
|
|
2207
|
+
* A card contributed by a recognized custom node (`defineCustomNode` with a `reviewCard`
|
|
2208
|
+
* hook), anchored at the node's range.
|
|
2209
|
+
*
|
|
2210
|
+
* Informational, never resolvable: there is nothing to accept or reject, so the engine
|
|
2211
|
+
* refuses those verbs on it. `title` and `detail` are HOST-authored (the definition's hook
|
|
2212
|
+
* produced them), but `attrs` and `text` originate in a file an attacker controls — a
|
|
2213
|
+
* surface renders every one of these as text, never markup.
|
|
2214
|
+
*/
|
|
2215
|
+
interface ReviewCustomItem {
|
|
2216
|
+
readonly kind: 'custom';
|
|
2217
|
+
/** The SDT node's stable id in the canonical tree. */
|
|
2218
|
+
readonly id: string;
|
|
2219
|
+
/** The definition's `name`. */
|
|
2220
|
+
readonly name: string;
|
|
2221
|
+
/** The raw `w:tag` the node was recognized from. Untrusted input. */
|
|
2222
|
+
readonly tag: string;
|
|
2223
|
+
/** Attrs decoded from the tag, after the definition's recognition hook. Untrusted input. */
|
|
2224
|
+
readonly attrs: Readonly<Record<string, string>>;
|
|
2225
|
+
/** The SDT's literal content text. Untrusted input. */
|
|
2226
|
+
readonly text: string;
|
|
2227
|
+
/**
|
|
2228
|
+
* The payload the node's control binds to, after the definition validated it.
|
|
2229
|
+
*
|
|
2230
|
+
* Undefined when the node carries none or the payload did not match — see the pro package's
|
|
2231
|
+
* `RecognizedCustomNode.data`, which this is carried from.
|
|
2232
|
+
*/
|
|
2233
|
+
readonly data?: unknown;
|
|
2234
|
+
/**
|
|
2235
|
+
* Whether this node asked for a sidebar card.
|
|
2236
|
+
*
|
|
2237
|
+
* False for a definition with no `reviewCard`: the item exists so the chip's own surfaces can
|
|
2238
|
+
* read `attrs`, `text` and `data` off it, and the rail leaves it out. A surface listing cards
|
|
2239
|
+
* filters on this rather than on an empty `title`.
|
|
2240
|
+
*/
|
|
2241
|
+
readonly carded: boolean;
|
|
2242
|
+
/** Card title, from the definition's `reviewCard` hook. Empty when `carded` is false. */
|
|
2243
|
+
readonly title: string;
|
|
2244
|
+
/** Card body, from the definition's `reviewCard` hook. */
|
|
2245
|
+
readonly detail?: string;
|
|
2246
|
+
/**
|
|
2247
|
+
* Glyph for this node in the collapsed rail, as an SVG path in a `0 -960 960 960` viewBox.
|
|
2248
|
+
*
|
|
2249
|
+
* A PATH rather than a rendered node because this item crosses core, which is DOM-free and
|
|
2250
|
+
* React-free — the same reason `title` and `detail` are strings. A host that wants arbitrary
|
|
2251
|
+
* markup overrides the `Markers` part's `icon` instead, which lives in the adapter where JSX
|
|
2252
|
+
* belongs. Absent falls back to the generic custom-node glyph.
|
|
2253
|
+
*
|
|
2254
|
+
* HOST-AUTHORED, never file data: it is interpolated into an SVG `d` attribute, and a path
|
|
2255
|
+
* taken from a document would be attacker-controlled markup.
|
|
2256
|
+
*/
|
|
2257
|
+
readonly icon?: string;
|
|
2258
|
+
readonly range: ReviewRange | null;
|
|
2259
|
+
}
|
|
2260
|
+
/**
|
|
2261
|
+
* One pending decision in the review queue: a tracked change, a comment thread, or a pro
|
|
2262
|
+
* custom-node card. Discriminate on `kind`.
|
|
2091
2263
|
*
|
|
2092
|
-
*
|
|
2093
|
-
*
|
|
2094
|
-
* keeps its content in the tree (the serializer never stops) while no walk recurses
|
|
2095
|
-
* further.
|
|
2264
|
+
* The store's own derivation (`collectReviewItems`) only ever produces the first two; the
|
|
2265
|
+
* `kind: 'custom'` card is contributed by the pro review module, which recognizes the node.
|
|
2096
2266
|
*/
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2267
|
+
type ReviewItem = ReviewRevisionItem | ReviewCommentItem | ReviewCustomItem;
|
|
2268
|
+
/** What the review queue derivation reads: one story part plus its comment parts. */
|
|
2269
|
+
interface ReviewModelInput {
|
|
2270
|
+
/** The story the ranges live in — the main document, a header, a note. */
|
|
2271
|
+
readonly storyPart: OoxmlPart;
|
|
2272
|
+
/**
|
|
2273
|
+
* Header/footer story parts, in section order. Their revisions and comment anchors join
|
|
2274
|
+
* the queue: a tracked change in a header is a pending decision like any other, and a
|
|
2275
|
+
* queue that only walked the body silently hid it from the rail AND from Accept All.
|
|
2276
|
+
*/
|
|
2277
|
+
readonly furnitureParts?: readonly OoxmlPart[] | undefined;
|
|
2278
|
+
/** `word/comments.xml`, absent when the package has none. */
|
|
2279
|
+
readonly commentsPart?: OoxmlPart | undefined;
|
|
2280
|
+
/** `word/commentsExtended.xml`, absent when the package has none. */
|
|
2281
|
+
readonly commentsExtendedPart?: OoxmlPart | undefined;
|
|
2282
|
+
/**
|
|
2283
|
+
* Custom node definitions from the module registry, forwarded OPAQUELY.
|
|
2284
|
+
*
|
|
2285
|
+
* Core carries them the way the registry does — as unknowns — so the definition shape
|
|
2286
|
+
* stays a capability-package concern. The pro derivation narrows them and contributes
|
|
2287
|
+
* `kind: 'custom'` cards for definitions that opted in.
|
|
2288
|
+
*/
|
|
2289
|
+
readonly customNodes?: readonly unknown[] | undefined;
|
|
2290
|
+
/**
|
|
2291
|
+
* Where a capability package reports a node it could not read. Supplied per editor, so a page
|
|
2292
|
+
* with two of them keeps their diagnostics apart.
|
|
2293
|
+
*/
|
|
2294
|
+
readonly reportCustomNodeDiagnostic?: ((diagnostic: unknown) => void) | undefined;
|
|
2295
|
+
/**
|
|
2296
|
+
* The payload each of the story's controls binds to, keyed by the control's node id.
|
|
2297
|
+
*
|
|
2298
|
+
* Resolved by the ENGINE and handed over, because a payload lives in a customXml data part
|
|
2299
|
+
* and a derivation that only receives story parts has no way to reach one. Untrusted file
|
|
2300
|
+
* input on both members; a capability package validates it against whatever shape it
|
|
2301
|
+
* declared before handing it to a host.
|
|
2302
|
+
*/
|
|
2303
|
+
readonly customNodePayloads?: ReadonlyMap<string, {
|
|
2304
|
+
readonly nodeId: string;
|
|
2305
|
+
readonly label: string;
|
|
2306
|
+
readonly data: string;
|
|
2307
|
+
}> | undefined;
|
|
2308
|
+
}
|
|
2309
|
+
/** The stable key a surface uses for the active item and for a React list. */
|
|
2310
|
+
declare function reviewItemKey(item: ReviewItem): string;
|
|
2311
|
+
/** Every range a decision touches. One card can cover several, in different paragraphs. */
|
|
2312
|
+
declare function reviewItemRanges(item: ReviewItem): readonly ReviewRange[];
|
|
2313
|
+
/** The first range of an item, in authored order, or null when it has none. */
|
|
2314
|
+
declare function firstReviewRange(item: ReviewItem): ReviewRange | null;
|
|
2103
2315
|
/**
|
|
2104
|
-
*
|
|
2316
|
+
* A single comparable number for document order.
|
|
2105
2317
|
*
|
|
2106
|
-
*
|
|
2107
|
-
*
|
|
2318
|
+
* Paragraph index dominates offset, so a revision spanning paragraphs still sorts by where it
|
|
2319
|
+
* STARTS. An item with no resolvable range sorts last rather than to position zero, which is
|
|
2320
|
+
* where an orphan used to land — tearing an orphaned reply out of its own thread.
|
|
2108
2321
|
*/
|
|
2109
|
-
declare function
|
|
2322
|
+
declare function reviewItemPositionRank(item: ReviewItem, order: ReadonlyMap<string, number>): number;
|
|
2110
2323
|
/**
|
|
2111
|
-
*
|
|
2324
|
+
* Every item covering a position, innermost first.
|
|
2112
2325
|
*
|
|
2113
|
-
*
|
|
2114
|
-
*
|
|
2115
|
-
*
|
|
2116
|
-
* one is still content-locked — a nested control cannot grant a permission its parent
|
|
2117
|
-
* withheld, which is the only reading under which a lock is a lock.
|
|
2326
|
+
* Returning the whole stack rather than one winner is what lets a surface offer cycling, a
|
|
2327
|
+
* stacked card, or a "1 of 3" affordance. A comment wrapping a revision used to be unreachable
|
|
2328
|
+
* because only the tightest range was ever returned.
|
|
2118
2329
|
*/
|
|
2119
|
-
declare function
|
|
2120
|
-
/** Whether a resolved lock forbids editing the content it covers. */
|
|
2121
|
-
declare function lockForbidsEdit(lock: ContentControlLock): boolean;
|
|
2122
|
-
/** Whether a resolved lock forbids removing the control itself. */
|
|
2123
|
-
declare function lockForbidsRemoval(lock: ContentControlLock): boolean;
|
|
2330
|
+
declare function reviewItemsAt(items: readonly ReviewItem[], position: ReviewPosition, order: ReadonlyMap<string, number>): ReviewItem[];
|
|
2124
2331
|
/**
|
|
2125
|
-
*
|
|
2332
|
+
* The item the caret is in, or null.
|
|
2126
2333
|
*
|
|
2127
|
-
*
|
|
2128
|
-
*
|
|
2129
|
-
* {@link orderedContentControlProperties} does.
|
|
2130
|
-
*/
|
|
2131
|
-
declare const CONTENT_CONTROL_PROPERTY_ORDER: readonly string[];
|
|
2132
|
-
/**
|
|
2133
|
-
* Rebuild a `w:sdtPr`'s children in schema order.
|
|
2334
|
+
* A resolved comment never activates: a settled thread must not reopen itself as the reviewer
|
|
2335
|
+
* types near it.
|
|
2134
2336
|
*
|
|
2135
|
-
*
|
|
2136
|
-
*
|
|
2137
|
-
*
|
|
2138
|
-
*
|
|
2139
|
-
*
|
|
2337
|
+
* A REPLY resolves to the thread it belongs to. A reply is anchored over its parent's range,
|
|
2338
|
+
* so both cover the caret — and the reply, being newer, wins the innermost test. It is not a
|
|
2339
|
+
* card of its own (it renders inside its parent's), so the thread would have gone active with
|
|
2340
|
+
* nothing on screen showing it: the reply box vanished from a comment the moment somebody
|
|
2341
|
+
* replied to it.
|
|
2140
2342
|
*/
|
|
2141
|
-
declare function
|
|
2343
|
+
declare function activeReviewItem(items: readonly ReviewItem[], position: ReviewPosition, order: ReadonlyMap<string, number>): ReviewItem | null;
|
|
2142
2344
|
/**
|
|
2143
|
-
*
|
|
2345
|
+
* Walk a reply up to the card that heads its thread. Guarded against a cyclic file.
|
|
2144
2346
|
*
|
|
2145
|
-
*
|
|
2146
|
-
*
|
|
2147
|
-
*
|
|
2148
|
-
* rather than wrapping into a negative id. Hostile or out-of-range existing values are
|
|
2149
|
-
* ignored for seeding rather than counted past.
|
|
2347
|
+
* The head is not always a comment. A reply to a tracked change renders inside the REVISION's
|
|
2348
|
+
* card, so resolving it to itself opened an item nothing on screen was drawing — the reply box
|
|
2349
|
+
* vanished the moment somebody answered a change.
|
|
2150
2350
|
*
|
|
2151
|
-
*
|
|
2152
|
-
*
|
|
2153
|
-
*
|
|
2154
|
-
*
|
|
2351
|
+
* EXPORTED because the paginated surface answers "which card is open" itself, against its own
|
|
2352
|
+
* dismissed-key state, rather than through {@link activeReviewItem}. Two copies of the
|
|
2353
|
+
* innermost-wins rule was survivable while a reply could only be a comment — the parent came
|
|
2354
|
+
* first in `comments.xml` order and won the tie by accident. It stopped being survivable the
|
|
2355
|
+
* moment a reply could answer a revision, which outranks it outright.
|
|
2155
2356
|
*/
|
|
2156
|
-
declare function
|
|
2357
|
+
declare function reviewThreadRootOf(items: readonly ReviewItem[], comment: ReviewCommentItem): ReviewItem;
|
|
2157
2358
|
|
|
2158
2359
|
/** The value a control accepts, by what kind of control it is. */
|
|
2159
2360
|
type ContentControlValueInput = {
|
|
@@ -2182,6 +2383,32 @@ declare const INSERTABLE_CONTENT_CONTROL_TYPES: readonly ["richText", "plainText
|
|
|
2182
2383
|
*/
|
|
2183
2384
|
type InsertableContentControlKind = (typeof INSERTABLE_CONTENT_CONTROL_TYPES)[number];
|
|
2184
2385
|
|
|
2386
|
+
/** A canonical review decision. Keys are valid only in the open document. @public */
|
|
2387
|
+
interface RevisionBatchEntry {
|
|
2388
|
+
readonly key: string;
|
|
2389
|
+
readonly author: string;
|
|
2390
|
+
readonly partName: string;
|
|
2391
|
+
readonly revisionKind: ReviewRevisionItem['revisionKind'];
|
|
2392
|
+
}
|
|
2393
|
+
/** Why a requested decision remains pending. @public */
|
|
2394
|
+
type RevisionBatchSkipReason = 'unsupported-revision' | 'incomplete-group' | 'unknown-revision';
|
|
2395
|
+
/** Outcome of one selected-set decision. Counts refer to review decisions, not XML markers. @public */
|
|
2396
|
+
interface RevisionBatchResult {
|
|
2397
|
+
readonly resolved: readonly RevisionBatchEntry[];
|
|
2398
|
+
readonly skipped: readonly {
|
|
2399
|
+
readonly key: string;
|
|
2400
|
+
readonly reason: RevisionBatchSkipReason;
|
|
2401
|
+
readonly revision?: RevisionBatchEntry;
|
|
2402
|
+
}[];
|
|
2403
|
+
/** All pending decisions in the addressed scope, including excluded and unsupported changes. */
|
|
2404
|
+
readonly remaining: number;
|
|
2405
|
+
}
|
|
2406
|
+
/** @internal Pure preflight; callers commit its operations through their normal write guards. */
|
|
2407
|
+
declare function planRevisionBatch(part: OoxmlPart, action: 'accept' | 'reject', keys?: readonly string[], scopeRoot?: OoxmlNode): {
|
|
2408
|
+
ops: readonly TreeDocOp[];
|
|
2409
|
+
result: RevisionBatchResult;
|
|
2410
|
+
};
|
|
2411
|
+
|
|
2185
2412
|
/** Allowlisted OOXML table border line styles — store/layout authority. */
|
|
2186
2413
|
declare const TABLE_BORDER_STYLES: readonly ["single", "dashed", "dotted", "double", "triple", "thick"];
|
|
2187
2414
|
/**
|
|
@@ -2193,6 +2420,570 @@ declare const TABLE_BORDER_STYLES: readonly ["single", "dashed", "dotted", "doub
|
|
|
2193
2420
|
*/
|
|
2194
2421
|
type TableBorderStyle = (typeof TABLE_BORDER_STYLES)[number];
|
|
2195
2422
|
|
|
2423
|
+
/**
|
|
2424
|
+
* Shared types for the `@docx-editor.dev/core` contract. Type-only, zero runtime.
|
|
2425
|
+
*
|
|
2426
|
+
* `@docx-editor.dev/core/contracts/types` re-exports this module verbatim, through
|
|
2427
|
+
* `types-barrel.ts`. There is no `@docx-editor.dev/core/types` subpath.
|
|
2428
|
+
*/
|
|
2429
|
+
/** Which paragraph-level reads the selection disagrees about. @public */
|
|
2430
|
+
interface ParagraphDisagreements {
|
|
2431
|
+
readonly alignment: boolean;
|
|
2432
|
+
readonly spaceBeforePt: boolean;
|
|
2433
|
+
readonly spaceAfterPt: boolean;
|
|
2434
|
+
readonly lineSpacing: boolean;
|
|
2435
|
+
readonly tabStops: boolean;
|
|
2436
|
+
}
|
|
2437
|
+
/**
|
|
2438
|
+
* The five paragraph flags a Paragraph dialog shows as checkboxes.
|
|
2439
|
+
*
|
|
2440
|
+
* `contextualSpacing` is Word's "Don't add space between paragraphs of the same style";
|
|
2441
|
+
* the rest are its Pagination block. `null` means the selection disagrees.
|
|
2442
|
+
*
|
|
2443
|
+
* @public
|
|
2444
|
+
*/
|
|
2445
|
+
interface ParagraphFlags {
|
|
2446
|
+
readonly contextualSpacing: boolean | null;
|
|
2447
|
+
readonly keepNext: boolean | null;
|
|
2448
|
+
readonly keepLines: boolean | null;
|
|
2449
|
+
readonly widowControl: boolean | null;
|
|
2450
|
+
readonly pageBreakBefore: boolean | null;
|
|
2451
|
+
}
|
|
2452
|
+
/**
|
|
2453
|
+
* Every field of the Paragraph dialog, as `setParagraphFormat` takes it.
|
|
2454
|
+
*
|
|
2455
|
+
* An omitted field is left as authored. `null` REMOVES a setting so the style supplies it
|
|
2456
|
+
* again — not the same as a zero, which blocks the cascade.
|
|
2457
|
+
*
|
|
2458
|
+
* @public
|
|
2459
|
+
*/
|
|
2460
|
+
interface ParagraphFormatCommand {
|
|
2461
|
+
alignment?: 'left' | 'center' | 'right' | 'justify';
|
|
2462
|
+
spaceBeforePt?: number | null;
|
|
2463
|
+
spaceAfterPt?: number | null;
|
|
2464
|
+
lineSpacing?: {
|
|
2465
|
+
rule: 'multiple' | 'exact' | 'atLeast';
|
|
2466
|
+
value: number;
|
|
2467
|
+
} | null;
|
|
2468
|
+
indentLeftTwips?: number | null;
|
|
2469
|
+
indentRightTwips?: number | null;
|
|
2470
|
+
/** ONE signed first-line offset: negative is a hanging indent. */
|
|
2471
|
+
indentFirstLineTwips?: number | null;
|
|
2472
|
+
contextualSpacing?: boolean;
|
|
2473
|
+
keepNext?: boolean;
|
|
2474
|
+
keepLines?: boolean;
|
|
2475
|
+
widowControl?: boolean;
|
|
2476
|
+
pageBreakBefore?: boolean;
|
|
2477
|
+
/**
|
|
2478
|
+
* Replace the paragraph's custom tab stops. An empty list CLEARS them, which is what
|
|
2479
|
+
* "Clear All" does; omit the field to leave them as authored.
|
|
2480
|
+
*/
|
|
2481
|
+
tabStops?: readonly ParagraphTabStop[];
|
|
2482
|
+
}
|
|
2483
|
+
/** One custom tab stop, as a command states it. @public */
|
|
2484
|
+
interface ParagraphTabStop {
|
|
2485
|
+
readonly positionTwips: number;
|
|
2486
|
+
readonly alignment: 'left' | 'center' | 'right' | 'decimal' | 'bar';
|
|
2487
|
+
readonly leader?: 'none' | 'dot' | 'hyphen' | 'underscore' | 'heavy' | 'middleDot';
|
|
2488
|
+
}
|
|
2489
|
+
/** Ownership token for one retained selection highlight. @public */
|
|
2490
|
+
type SelectionPin = symbol;
|
|
2491
|
+
/**
|
|
2492
|
+
* The LLM- and JSON-facing address for a piece of a document.
|
|
2493
|
+
*
|
|
2494
|
+
* `paraId` is the 8-hex `w14:paraId`, matched case-insensitively. `search` is a
|
|
2495
|
+
* phrase that must match EXACTLY ONCE inside that paragraph; ambiguous or
|
|
2496
|
+
* missing matches fail with `'ambiguous'` / `'notFound'` rather than falling
|
|
2497
|
+
* back to first-match.
|
|
2498
|
+
*
|
|
2499
|
+
* Offset-based addressing was tried and abandoned: an agent cannot compute a
|
|
2500
|
+
* character offset it has not seen, and offsets do not survive concurrent
|
|
2501
|
+
* edits. Do not reintroduce `{ blockId, offset }`.
|
|
2502
|
+
*/
|
|
2503
|
+
interface DocAnchor {
|
|
2504
|
+
paraId: string;
|
|
2505
|
+
search?: string;
|
|
2506
|
+
/** Opt-in disambiguation. Omit to require uniqueness. */
|
|
2507
|
+
occurrence?: number;
|
|
2508
|
+
}
|
|
2509
|
+
/** Structural addressing for content the paraId map cannot reach. */
|
|
2510
|
+
interface DocLocation {
|
|
2511
|
+
container: ContainerRef;
|
|
2512
|
+
/** Block indices, descending into tables and content controls. */
|
|
2513
|
+
path: number[];
|
|
2514
|
+
offset?: number;
|
|
2515
|
+
}
|
|
2516
|
+
/**
|
|
2517
|
+
* Which STORY a location belongs to.
|
|
2518
|
+
*
|
|
2519
|
+
* The body is one container; every header, footer and note is another. A path alone is
|
|
2520
|
+
* ambiguous without it, because block index 0 exists in every story a document has.
|
|
2521
|
+
*/
|
|
2522
|
+
type ContainerRef = {
|
|
2523
|
+
part: 'body';
|
|
2524
|
+
} | {
|
|
2525
|
+
part: 'header' | 'footer';
|
|
2526
|
+
rId: string;
|
|
2527
|
+
} | {
|
|
2528
|
+
part: 'footnote' | 'endnote';
|
|
2529
|
+
noteId: number;
|
|
2530
|
+
};
|
|
2531
|
+
/**
|
|
2532
|
+
* Anything an operation can be pointed at: a paragraph-relative {@link DocAnchor}, a structural
|
|
2533
|
+
* {@link DocLocation}, or a {@link DocRange} spanning two of them.
|
|
2534
|
+
*/
|
|
2535
|
+
type DocTarget = DocAnchor | DocLocation | DocRange;
|
|
2536
|
+
/** A span between two positions. The endpoints may be addressed either way, independently. */
|
|
2537
|
+
interface DocRange {
|
|
2538
|
+
from: DocAnchor | DocLocation;
|
|
2539
|
+
to: DocAnchor | DocLocation;
|
|
2540
|
+
}
|
|
2541
|
+
/**
|
|
2542
|
+
* Every write returns this rather than `boolean`.
|
|
2543
|
+
*
|
|
2544
|
+
* A bare boolean cannot distinguish "no-op" from "target not found" from
|
|
2545
|
+
* "content control is locked", and the editor layer already throws eight
|
|
2546
|
+
* distinct ContentControl error classes that a boolean would flatten.
|
|
2547
|
+
*/
|
|
2548
|
+
type ExecResult = {
|
|
2549
|
+
ok: true;
|
|
2550
|
+
changed: boolean;
|
|
2551
|
+
revisions?: RevisionBatchResult;
|
|
2552
|
+
history?: HistoryGroupOutcome;
|
|
2553
|
+
} | {
|
|
2554
|
+
ok: false;
|
|
2555
|
+
code: ExecErrorCode;
|
|
2556
|
+
reason: string;
|
|
2557
|
+
target?: DocTarget;
|
|
2558
|
+
revisions?: RevisionBatchResult;
|
|
2559
|
+
};
|
|
2560
|
+
/**
|
|
2561
|
+
* Why a write was refused, as a value to branch on.
|
|
2562
|
+
*
|
|
2563
|
+
* Deliberately finer-grained than a boolean: "no-op", "target not found" and "content control is
|
|
2564
|
+
* locked" are different outcomes, and a caller retrying the first should not retry the third.
|
|
2565
|
+
*/
|
|
2566
|
+
type ExecErrorCode = 'notFound' | 'ambiguous' | 'locked' | 'bound' | 'typeMismatch' | 'kindMismatch' | 'outOfBounds' | 'unsupported' | 'invalidArgs';
|
|
2567
|
+
/**
|
|
2568
|
+
* A parsed .docx.
|
|
2569
|
+
*
|
|
2570
|
+
* NOT JSON-round-trippable: it holds `Map`s and `Date`s, plus an internal
|
|
2571
|
+
* side-table of verbatim XML used for lossless round-tripping. Use `toJSON` /
|
|
2572
|
+
* `fromJSON` before sending it over JSON-RPC or handing it to a model.
|
|
2573
|
+
*/
|
|
2574
|
+
interface DocxDocument {
|
|
2575
|
+
readonly body: DocumentBody;
|
|
2576
|
+
readonly styles: StyleDefinitions;
|
|
2577
|
+
readonly theme?: Theme;
|
|
2578
|
+
readonly comments: readonly DocComment[];
|
|
2579
|
+
readonly revisions: readonly Revision[];
|
|
2580
|
+
}
|
|
2581
|
+
/** The main story: its blocks in reading order, plus the sections derived from them. */
|
|
2582
|
+
interface DocumentBody {
|
|
2583
|
+
readonly content: readonly Block[];
|
|
2584
|
+
/**
|
|
2585
|
+
* Derived, not stored: recomputed on read from section-break markers and
|
|
2586
|
+
* section inheritance. Never treat it as a spreadable field.
|
|
2587
|
+
*/
|
|
2588
|
+
readonly sections: readonly Section[];
|
|
2589
|
+
}
|
|
2590
|
+
/** The JSON-safe projection of a document. */
|
|
2591
|
+
interface DocxDocumentJSON {
|
|
2592
|
+
readonly [key: string]: unknown;
|
|
2593
|
+
}
|
|
2594
|
+
/** One section: the page it lays out on, and the header/footer stories it declares. */
|
|
2595
|
+
interface Section {
|
|
2596
|
+
readonly properties: SectionProperties;
|
|
2597
|
+
readonly headers: HeaderFooterSet;
|
|
2598
|
+
readonly footers: HeaderFooterSet;
|
|
2599
|
+
}
|
|
2600
|
+
/**
|
|
2601
|
+
* A section's three header (or footer) variants, each a relationship id.
|
|
2602
|
+
*
|
|
2603
|
+
* All optional: a variant a section does not declare inherits the previous section's, and one
|
|
2604
|
+
* absent everywhere means the document simply has none.
|
|
2605
|
+
*/
|
|
2606
|
+
interface HeaderFooterSet {
|
|
2607
|
+
readonly default?: string;
|
|
2608
|
+
readonly first?: string;
|
|
2609
|
+
readonly even?: string;
|
|
2610
|
+
}
|
|
2611
|
+
/** Anything that can sit at block level in a story. Discriminate on `kind`. */
|
|
2612
|
+
type Block = Paragraph | Table | ContentControl;
|
|
2613
|
+
/** One paragraph: its runs, the style it names, and its list membership. */
|
|
2614
|
+
interface Paragraph {
|
|
2615
|
+
readonly kind: 'paragraph';
|
|
2616
|
+
/** `w14:paraId`. The stable handle `DocAnchor` addresses. */
|
|
2617
|
+
readonly paraId?: string;
|
|
2618
|
+
readonly runs: readonly Run[];
|
|
2619
|
+
readonly styleId?: string;
|
|
2620
|
+
readonly numbering?: NumberingRef;
|
|
2621
|
+
}
|
|
2622
|
+
/** A stretch of text sharing one set of character properties. */
|
|
2623
|
+
interface Run {
|
|
2624
|
+
readonly text: string;
|
|
2625
|
+
readonly formatting?: RunFormatting;
|
|
2626
|
+
/** Set when the run carries a tracked change. Unique only within its part. */
|
|
2627
|
+
readonly revisionId?: number;
|
|
2628
|
+
}
|
|
2629
|
+
/**
|
|
2630
|
+
* Character formatting, and — at selection level — the paragraph properties a toolbar reads
|
|
2631
|
+
* alongside it.
|
|
2632
|
+
*
|
|
2633
|
+
* One type serves both roles so a toolbar reads alignment, style and script state from the same
|
|
2634
|
+
* object as bold and italic. On a {@link Run} the selection-level fields stay absent: a run has
|
|
2635
|
+
* no alignment or paragraph style of its own.
|
|
2636
|
+
*/
|
|
2637
|
+
interface RunFormatting {
|
|
2638
|
+
readonly bold?: boolean;
|
|
2639
|
+
readonly italic?: boolean;
|
|
2640
|
+
readonly underline?: boolean;
|
|
2641
|
+
readonly strike?: boolean;
|
|
2642
|
+
readonly color?: ColorValue;
|
|
2643
|
+
readonly highlight?: string;
|
|
2644
|
+
readonly fontFamily?: string;
|
|
2645
|
+
readonly fontSizePt?: number;
|
|
2646
|
+
readonly superscript?: boolean;
|
|
2647
|
+
readonly subscript?: boolean;
|
|
2648
|
+
/** Paragraph alignment at the selection. `both` is OOXML's spelling of justify. */
|
|
2649
|
+
readonly alignment?: 'left' | 'center' | 'right' | 'both';
|
|
2650
|
+
/** Paragraph style id (`w:pStyle`) at the selection. */
|
|
2651
|
+
readonly styleId?: string;
|
|
2652
|
+
/**
|
|
2653
|
+
* Line spacing at the selection, in the unit its rule implies — LINES for `multiple`,
|
|
2654
|
+
* points for `exact` and `atLeast`. The same vocabulary `setLineSpacing` takes, so a
|
|
2655
|
+
* control can show what it reads and send back what it shows. Absent when the
|
|
2656
|
+
* selection's paragraphs disagree or state no line spacing.
|
|
2657
|
+
*/
|
|
2658
|
+
readonly lineSpacing?: {
|
|
2659
|
+
readonly rule: 'multiple' | 'exact' | 'atLeast';
|
|
2660
|
+
readonly value: number;
|
|
2661
|
+
};
|
|
2662
|
+
/**
|
|
2663
|
+
* Space above and below the paragraph at the selection, in points.
|
|
2664
|
+
*
|
|
2665
|
+
* The measurement the cascade STATES — `w:docDefaults`, the style chain and direct
|
|
2666
|
+
* formatting resolved together — not the gap the page finally draws. The two differ for a
|
|
2667
|
+
* paragraph carrying `w:beforeAutospacing`, where Word substitutes its own value and
|
|
2668
|
+
* ignores the measurement, and again where two paragraphs collapse their adjacent spacing.
|
|
2669
|
+
* Absent when the selection's paragraphs disagree or no level states it.
|
|
2670
|
+
*/
|
|
2671
|
+
readonly spaceBeforePt?: number;
|
|
2672
|
+
readonly spaceAfterPt?: number;
|
|
2673
|
+
/**
|
|
2674
|
+
* The paragraph flags the Paragraph dialog shows as checkboxes.
|
|
2675
|
+
*
|
|
2676
|
+
* Each is `true`, `false`, or `null` when the selection's paragraphs disagree — a
|
|
2677
|
+
* checkbox needs all three. Read through the cascade, so a flag a STYLE sets reads as on,
|
|
2678
|
+
* which is what the box has to show over a paragraph the page is visibly keeping with the
|
|
2679
|
+
* next. Absent on a `Run`, like every other selection-level field here.
|
|
2680
|
+
*/
|
|
2681
|
+
readonly paragraphFlags?: ParagraphFlags;
|
|
2682
|
+
/**
|
|
2683
|
+
* Which paragraph-level fields above are absent because the selection DISAGREES, as
|
|
2684
|
+
* opposed to because nothing states them.
|
|
2685
|
+
*
|
|
2686
|
+
* A `null`/absent value alone cannot tell those apart, and both readings have shipped as
|
|
2687
|
+
* bugs: a disagreement rendered as a concrete value is uncorrectable, because the value
|
|
2688
|
+
* that would fix it is the one already on screen; an absent value rendered as "mixed"
|
|
2689
|
+
* tells a single paragraph it disagrees with itself.
|
|
2690
|
+
*/
|
|
2691
|
+
readonly disagrees?: ParagraphDisagreements;
|
|
2692
|
+
/**
|
|
2693
|
+
* The paragraph's custom tab stops at the selection, cascade included. Absent when the
|
|
2694
|
+
* selection disagrees or the paragraphs have none.
|
|
2695
|
+
*/
|
|
2696
|
+
readonly tabStops?: readonly ParagraphTabStop[];
|
|
2697
|
+
/**
|
|
2698
|
+
* The EFFECTIVE paragraph indent at the selection — cascade and numbering merge
|
|
2699
|
+
* included, so a numbered item that authors no `w:ind` reports the indent its list
|
|
2700
|
+
* definition gives it. Absent when nothing is loaded, or when the selection is inside a
|
|
2701
|
+
* table (see {@link IndentFormatting}).
|
|
2702
|
+
*/
|
|
2703
|
+
readonly indent?: IndentFormatting;
|
|
2704
|
+
}
|
|
2705
|
+
/**
|
|
2706
|
+
* Indent at the selection, in twips.
|
|
2707
|
+
*
|
|
2708
|
+
* Unlike every other field here, this does NOT go absent when the selection's paragraphs
|
|
2709
|
+
* disagree. A ruler has to draw its handles somewhere, and Word draws them at the FIRST
|
|
2710
|
+
* selected paragraph's values — Select All is the commonest indent gesture, and hiding the
|
|
2711
|
+
* handles for it would be worse than showing one paragraph's truth. The values are
|
|
2712
|
+
* therefore always the first touched paragraph's, and {@link mixed} records per field
|
|
2713
|
+
* whether the rest agree.
|
|
2714
|
+
*
|
|
2715
|
+
* `firstLine` is ONE SIGNED offset: negative is a hanging indent. OOXML spells it as two
|
|
2716
|
+
* mutually exclusive attributes and this collapses them hanging-wins (§17.3.1.12), which
|
|
2717
|
+
* is the model Word itself keeps.
|
|
2718
|
+
*
|
|
2719
|
+
* Absent inside a table. The value would be correct there, but it is measured from the
|
|
2720
|
+
* cell's content edge while a ruler is drawn against the page's margin, and the ruler does
|
|
2721
|
+
* not know the cell.
|
|
2722
|
+
*/
|
|
2723
|
+
interface IndentFormatting {
|
|
2724
|
+
/** Left indent, signed. Negative pulls text into the margin, as Word allows. */
|
|
2725
|
+
readonly left: number;
|
|
2726
|
+
/** Right indent, signed. */
|
|
2727
|
+
readonly right: number;
|
|
2728
|
+
/** First-line offset from {@link left}, signed. Negative is a hanging indent. */
|
|
2729
|
+
readonly firstLine: number;
|
|
2730
|
+
/** Per field, whether the selection's paragraphs disagree about it. */
|
|
2731
|
+
readonly mixed: {
|
|
2732
|
+
readonly left: boolean;
|
|
2733
|
+
readonly right: boolean;
|
|
2734
|
+
readonly firstLine: boolean;
|
|
2735
|
+
};
|
|
2736
|
+
}
|
|
2737
|
+
/** A table: its rows, and the table style they resolve through. */
|
|
2738
|
+
interface Table {
|
|
2739
|
+
readonly kind: 'table';
|
|
2740
|
+
readonly rows: readonly TableRow[];
|
|
2741
|
+
readonly styleId?: string;
|
|
2742
|
+
}
|
|
2743
|
+
/** One table row. Cell count may vary between rows: `colSpan` and vertical merges reshape it. */
|
|
2744
|
+
interface TableRow {
|
|
2745
|
+
readonly cells: readonly TableCell[];
|
|
2746
|
+
}
|
|
2747
|
+
/**
|
|
2748
|
+
* One cell. Its `content` is ordinary blocks, so a cell may hold paragraphs, nested tables and
|
|
2749
|
+
* content controls alike.
|
|
2750
|
+
*/
|
|
2751
|
+
interface TableCell {
|
|
2752
|
+
readonly content: readonly Block[];
|
|
2753
|
+
/** Vertical merge span. Absent means 1. */
|
|
2754
|
+
readonly rowSpan?: number;
|
|
2755
|
+
/** `w:gridSpan`. Absent means 1. */
|
|
2756
|
+
readonly colSpan?: number;
|
|
2757
|
+
}
|
|
2758
|
+
/** Structured document tag (`w:sdt`). */
|
|
2759
|
+
interface ContentControl {
|
|
2760
|
+
readonly kind: 'contentControl';
|
|
2761
|
+
readonly id: string;
|
|
2762
|
+
readonly tag?: string;
|
|
2763
|
+
readonly alias?: string;
|
|
2764
|
+
readonly controlType: ContentControlType;
|
|
2765
|
+
readonly locked?: boolean;
|
|
2766
|
+
readonly content: readonly Block[];
|
|
2767
|
+
}
|
|
2768
|
+
/** Which kind of control a `w:sdt` is, and therefore what a value written into it must be. */
|
|
2769
|
+
type ContentControlType = 'richText' | 'plainText' | 'checkbox' | 'dropdown' | 'comboBox' | 'date' | 'picture' | 'buildingBlockGallery' | 'repeatingSection';
|
|
2770
|
+
/**
|
|
2771
|
+
* The control kinds an insertion can author.
|
|
2772
|
+
*
|
|
2773
|
+
* A NARROWING of {@link ContentControlType}, not a separate vocabulary: a kind read off an
|
|
2774
|
+
* existing control can be handed straight back to `insertContentControl`. Three kinds are
|
|
2775
|
+
* absent because an insertion would have to invent what they carry — a checkbox needs its two
|
|
2776
|
+
* declared glyph states, a picture needs an image part, a building block gallery needs a
|
|
2777
|
+
* glossary to list, and a repeating section is a container whose items have their own verbs. Reading still answers the wider type; a document may hold
|
|
2778
|
+
* kinds this cannot create.
|
|
2779
|
+
*
|
|
2780
|
+
* `dropDownList` is the same kind as `dropdown`, spelt as OOXML spells it. Both are accepted,
|
|
2781
|
+
* so a type read off a control can be handed back without translating it — and the OOXML
|
|
2782
|
+
* spelling is the one the automation protocol takes, so a caller who uses both surfaces can
|
|
2783
|
+
* write that one everywhere.
|
|
2784
|
+
*/
|
|
2785
|
+
type InsertableContentControlType = Extract<ContentControlType, 'richText' | 'plainText' | 'dropdown' | 'comboBox' | 'date'> | 'dropDownList';
|
|
2786
|
+
/**
|
|
2787
|
+
* Narrows a content-control query. Fields combine with AND; an empty filter matches every
|
|
2788
|
+
* control.
|
|
2789
|
+
*/
|
|
2790
|
+
interface ContentControlFilter {
|
|
2791
|
+
readonly tag?: string;
|
|
2792
|
+
readonly alias?: string;
|
|
2793
|
+
readonly controlType?: ContentControlType;
|
|
2794
|
+
}
|
|
2795
|
+
/**
|
|
2796
|
+
* A position in one story: a paragraph and a UTF-16 offset inside it.
|
|
2797
|
+
*
|
|
2798
|
+
* The same offset space the ops and the caret use, so an anchor read here can be handed
|
|
2799
|
+
* straight back to a selection without re-deriving anything.
|
|
2800
|
+
*/
|
|
2801
|
+
interface DocAnchorRange {
|
|
2802
|
+
/** Canonical part name of the story the range lives in, e.g. `/word/document.xml`. */
|
|
2803
|
+
readonly part: string;
|
|
2804
|
+
readonly startParagraphId: string;
|
|
2805
|
+
readonly startOffset: number;
|
|
2806
|
+
/** May sit in a later paragraph: the range markers are independent elements. */
|
|
2807
|
+
readonly endParagraphId: string;
|
|
2808
|
+
readonly endOffset: number;
|
|
2809
|
+
}
|
|
2810
|
+
/**
|
|
2811
|
+
* One comment or reply, as `comments.xml` records it.
|
|
2812
|
+
*
|
|
2813
|
+
* A reply is a comment with a `parentId`; OOXML gives replies no separate element, so the thread
|
|
2814
|
+
* is reconstructed from that link rather than from nesting.
|
|
2815
|
+
*/
|
|
2816
|
+
interface DocComment {
|
|
2817
|
+
readonly id: string;
|
|
2818
|
+
readonly author: string;
|
|
2819
|
+
/**
|
|
2820
|
+
* OPTIONAL, because `CT_Comment` makes `@w:date` optional and files omit it. A comment
|
|
2821
|
+
* with no date is a comment, not a defect, and fabricating one is a content change.
|
|
2822
|
+
*/
|
|
2823
|
+
readonly date?: string;
|
|
2824
|
+
readonly text: string;
|
|
2825
|
+
readonly parentId?: string;
|
|
2826
|
+
readonly resolved?: boolean;
|
|
2827
|
+
/**
|
|
2828
|
+
* Where the comment is anchored, absent when the file gave it no usable range.
|
|
2829
|
+
*
|
|
2830
|
+
* A comment lives in `comments.xml` and is placed by markers in a STORY, so the story is
|
|
2831
|
+
* part of the address: a comment anchored in a header belongs to a part the body never saw.
|
|
2832
|
+
*/
|
|
2833
|
+
readonly anchor?: DocAnchorRange;
|
|
2834
|
+
/**
|
|
2835
|
+
* True when the file gave this comment no usable range — a reference with no markers, or a
|
|
2836
|
+
* start with no end. Reported rather than dropped: a reviewer's remark vanishing silently
|
|
2837
|
+
* is worse than one that says it lost its text.
|
|
2838
|
+
*/
|
|
2839
|
+
readonly orphaned?: boolean;
|
|
2840
|
+
}
|
|
2841
|
+
/**
|
|
2842
|
+
* What kind of decision a revision represents.
|
|
2843
|
+
*
|
|
2844
|
+
* Wider than insert/delete/format, and it has to be. `w:moveFrom`/`w:moveTo` are not a
|
|
2845
|
+
* deletion and an insertion — resolving one half alone duplicates or loses the content;
|
|
2846
|
+
* `w:pPr/w:rPr/w:ins|w:del` decorates no characters at all and merges paragraphs when
|
|
2847
|
+
* resolved; a row or cell revision is structural. A reviewer shown only three kinds is a
|
|
2848
|
+
* reviewer who never learns about the rest.
|
|
2849
|
+
*/
|
|
2850
|
+
type RevisionType = 'insert' | 'delete'
|
|
2851
|
+
/** A deletion and an insertion that are one edit: text typed over a selection. */
|
|
2852
|
+
| 'replace' | 'moveFrom' | 'moveTo'
|
|
2853
|
+
/** `w:rPrChange` / `w:pPrChange` — the words are unchanged, their formatting is not. */
|
|
2854
|
+
| 'format'
|
|
2855
|
+
/** `w:pPr/w:rPr/w:ins|w:del` — a paragraph split or merge. */
|
|
2856
|
+
| 'paragraphMark'
|
|
2857
|
+
/** A row, cell, section or grid revision. */
|
|
2858
|
+
| 'structural';
|
|
2859
|
+
/**
|
|
2860
|
+
* One tracked change.
|
|
2861
|
+
*
|
|
2862
|
+
* Addressing needs BOTH `id` and `part`: `@w:id` is unique only within a part, so an id alone
|
|
2863
|
+
* names two revisions in any package that has a header or a comments part.
|
|
2864
|
+
*/
|
|
2865
|
+
interface Revision {
|
|
2866
|
+
/** Numeric, and unique only WITHIN a part. Pair with `part` to address one. */
|
|
2867
|
+
readonly id: number;
|
|
2868
|
+
readonly type: RevisionType;
|
|
2869
|
+
readonly author: string;
|
|
2870
|
+
/**
|
|
2871
|
+
* OPTIONAL. `CT_TrackChange` requires `@w:id` and `@w:author` and makes `@w:date`
|
|
2872
|
+
* optional, and producers that omit it are ordinary. Requiring it here forced either a
|
|
2873
|
+
* fabricated date — a content change — or dropping the revision from the list.
|
|
2874
|
+
*/
|
|
2875
|
+
readonly date?: string;
|
|
2876
|
+
/**
|
|
2877
|
+
* REQUIRED, and a canonical PART NAME rather than a three-value enum.
|
|
2878
|
+
*
|
|
2879
|
+
* `@w:id` is unique only within a part, so an address without one names two revisions in a
|
|
2880
|
+
* package that has both. The enum could not express the parts revisions actually occur in:
|
|
2881
|
+
* `header3.xml`, `footer1.xml`, `comments.xml`, and `styles.xml`, which carries
|
|
2882
|
+
* `w:pPrChange` inside style definitions with ids that collide with `document.xml`.
|
|
2883
|
+
*/
|
|
2884
|
+
readonly part: string;
|
|
2885
|
+
}
|
|
2886
|
+
/** `w:sectPr`: the page a section lays out on. Twips throughout, as the file stores them. */
|
|
2887
|
+
interface SectionProperties {
|
|
2888
|
+
readonly pageSize: {
|
|
2889
|
+
widthTwips: number;
|
|
2890
|
+
heightTwips: number;
|
|
2891
|
+
};
|
|
2892
|
+
readonly margins: PageMargins;
|
|
2893
|
+
readonly columns?: {
|
|
2894
|
+
count: number;
|
|
2895
|
+
gapTwips: number;
|
|
2896
|
+
};
|
|
2897
|
+
/** `w:titlePg` — whether the section's first page takes the `first` header/footer variant. */
|
|
2898
|
+
readonly titlePage?: boolean;
|
|
2899
|
+
}
|
|
2900
|
+
/** Page margins in twips. */
|
|
2901
|
+
interface PageMargins {
|
|
2902
|
+
readonly topTwips: number;
|
|
2903
|
+
readonly rightTwips: number;
|
|
2904
|
+
readonly bottomTwips: number;
|
|
2905
|
+
readonly leftTwips: number;
|
|
2906
|
+
}
|
|
2907
|
+
/**
|
|
2908
|
+
* `styles.xml`, split by the three style families that address separately.
|
|
2909
|
+
*
|
|
2910
|
+
* Keyed by style ID rather than by the name a reader sees, because the ID is what a paragraph or
|
|
2911
|
+
* run actually references.
|
|
2912
|
+
*/
|
|
2913
|
+
interface StyleDefinitions {
|
|
2914
|
+
readonly paragraph: ReadonlyMap<string, StyleDefinition>;
|
|
2915
|
+
readonly character: ReadonlyMap<string, StyleDefinition>;
|
|
2916
|
+
readonly table: ReadonlyMap<string, StyleDefinition>;
|
|
2917
|
+
}
|
|
2918
|
+
/** One style: the ID content references, the name a reader sees, and its inheritance link. */
|
|
2919
|
+
interface StyleDefinition {
|
|
2920
|
+
readonly id: string;
|
|
2921
|
+
readonly name: string;
|
|
2922
|
+
/** `w:basedOn` — the style this one inherits from. Absent at the root of a chain. */
|
|
2923
|
+
readonly basedOn?: string;
|
|
2924
|
+
}
|
|
2925
|
+
/** A paragraph's list membership: which `numbering.xml` definition, and at which level. */
|
|
2926
|
+
interface NumberingRef {
|
|
2927
|
+
readonly numId: string;
|
|
2928
|
+
/** Zero-based. OOXML numbering has nine levels, 0 through 8. */
|
|
2929
|
+
readonly level: number;
|
|
2930
|
+
}
|
|
2931
|
+
/**
|
|
2932
|
+
* A colour as the FILE expresses it, not as a resolved RGB string.
|
|
2933
|
+
*
|
|
2934
|
+
* A theme colour stays a theme reference — slot plus tint or shade — so that changing the theme
|
|
2935
|
+
* repaints the document the way Word does. Flattening to hex at read time would freeze the
|
|
2936
|
+
* resolved value and break that link. `auto` is Word's "let the renderer decide", usually black
|
|
2937
|
+
* on white.
|
|
2938
|
+
*/
|
|
2939
|
+
type ColorValue = {
|
|
2940
|
+
readonly kind: 'hex';
|
|
2941
|
+
readonly value: string;
|
|
2942
|
+
} | {
|
|
2943
|
+
readonly kind: 'theme';
|
|
2944
|
+
readonly slot: string;
|
|
2945
|
+
readonly tint?: number;
|
|
2946
|
+
readonly shade?: number;
|
|
2947
|
+
} | {
|
|
2948
|
+
readonly kind: 'auto';
|
|
2949
|
+
};
|
|
2950
|
+
/** `theme1.xml` — what a {@link ColorValue} of kind `theme` resolves against. */
|
|
2951
|
+
interface Theme {
|
|
2952
|
+
readonly colorScheme: ThemeColorScheme;
|
|
2953
|
+
readonly fontScheme?: Record<string, string>;
|
|
2954
|
+
}
|
|
2955
|
+
/** Theme colour slots (`accent1`, `dk1`, `lt2`, …) to hex. */
|
|
2956
|
+
type ThemeColorScheme = Readonly<Record<string, string>>;
|
|
2957
|
+
/** A watermark, which OOXML expresses as either text or an image — never both meaningfully. */
|
|
2958
|
+
interface Watermark {
|
|
2959
|
+
readonly text?: string;
|
|
2960
|
+
readonly imageData?: Uint8Array;
|
|
2961
|
+
}
|
|
2962
|
+
/** A size in EMUs, the unit DrawingML stores extents in. 914400 EMU = 1 inch. */
|
|
2963
|
+
interface Extent {
|
|
2964
|
+
readonly widthEmu: number;
|
|
2965
|
+
readonly heightEmu: number;
|
|
2966
|
+
}
|
|
2967
|
+
/** A font the document names, and whether its bytes travel inside the package. */
|
|
2968
|
+
interface FontDefinition {
|
|
2969
|
+
readonly family: string;
|
|
2970
|
+
readonly embedded: boolean;
|
|
2971
|
+
}
|
|
2972
|
+
/** An axis-aligned rectangle in points, the unit layout works in throughout. */
|
|
2973
|
+
interface Rect {
|
|
2974
|
+
readonly x: number;
|
|
2975
|
+
readonly y: number;
|
|
2976
|
+
readonly width: number;
|
|
2977
|
+
readonly height: number;
|
|
2978
|
+
}
|
|
2979
|
+
/** A position in points. */
|
|
2980
|
+
interface Point {
|
|
2981
|
+
readonly x: number;
|
|
2982
|
+
readonly y: number;
|
|
2983
|
+
}
|
|
2984
|
+
/** What every subscription returns. Calling it twice is safe. */
|
|
2985
|
+
type Unsubscribe = () => void;
|
|
2986
|
+
|
|
2196
2987
|
/**
|
|
2197
2988
|
* How a tracked change is addressed: `@w:id`, `@w:author` and `@w:date` together, within a
|
|
2198
2989
|
* part.
|
|
@@ -2373,10 +3164,14 @@ type TreeDocOp = SetFieldCodeOp | {
|
|
|
2373
3164
|
* changes made one decision, and one undo should restore all of them.
|
|
2374
3165
|
*/
|
|
2375
3166
|
readonly op: 'acceptAllRevisions';
|
|
3167
|
+
/** Exact canonical sites selected by bulk preflight. */
|
|
3168
|
+
readonly siteNodeIds?: readonly string[];
|
|
2376
3169
|
/** Internal shared-notes scope. When present, this must be the canonical id of a note root. */
|
|
2377
3170
|
readonly scopeRootId?: string;
|
|
2378
3171
|
} | {
|
|
2379
3172
|
readonly op: 'rejectAllRevisions';
|
|
3173
|
+
/** Exact canonical sites selected by bulk preflight. */
|
|
3174
|
+
readonly siteNodeIds?: readonly string[];
|
|
2380
3175
|
/** Internal shared-notes scope. When present, this must be the canonical id of a note root. */
|
|
2381
3176
|
readonly scopeRootId?: string;
|
|
2382
3177
|
} | {
|
|
@@ -3098,7 +3893,7 @@ type TreeDocOp = SetFieldCodeOp | {
|
|
|
3098
3893
|
readonly paragraphId: string;
|
|
3099
3894
|
readonly pageNumberText: string;
|
|
3100
3895
|
}[];
|
|
3101
|
-
} | SetTextFormFieldDefaultOp | CommitTextFormFieldOp | {
|
|
3896
|
+
} | SetTextFormFieldDefaultOp | CommitTextFormFieldOp | SetLegacyCheckboxOp | SetLegacyDropdownOp | InsertBuildingBlockOp | {
|
|
3102
3897
|
/**
|
|
3103
3898
|
* Rewrite recognized fields' cached RESULT runs in place — between the `separate` and
|
|
3104
3899
|
* `end` fldChars, or a `w:fldSimple`'s content. The instruction is never modified; a
|
|
@@ -3262,4 +4057,4 @@ type TreeOpResult = {
|
|
|
3262
4057
|
readonly detail?: string;
|
|
3263
4058
|
};
|
|
3264
4059
|
|
|
3265
|
-
export { type
|
|
4060
|
+
export { type RevisionBatchSkipReason as $, type IndentFormatting as A, type Block as B, type CommentRecord as C, type DocxDocument as D, type ExecResult as E, type ParagraphFlags as F, type ParagraphTabStop as G, type HeaderFooterSet as H, type InsertableContentControlType as I, type RevisionType as J, type Section as K, type SectionProperties as L, type StyleDefinition as M, type Theme as N, type OoxmlPart as O, type Paragraph as P, type ThemeColorScheme as Q, type ReviewModelInput as R, type StyleDefinitions as S, type Table as T, type OoxmlNodeId as U, type OoxmlGenericElementNode as V, type TreeDocOp as W, type OoxmlPackageLimits as X, type OoxmlPackageRejection as Y, type RevisionBatchEntry as Z, type RevisionBatchResult as _, type ReviewItem as a, type CommentPosition as a$, type OoxmlProperty as a0, type OoxmlElement as a1, type OoxmlContentControlNode as a2, type OoxmlContentControlContentNode as a3, type DrawingProjection as a4, type TreeOpRejection as a5, type AutomationTableMutation as a6, type SourceCrop as a7, type DrawingKind as a8, type ImageWrapTarget as a9, type OoxmlSeparatorNode as aA, type DrawingTreeDocOp as aB, type ImpactClass as aC, type TreeDocColorValue as aD, IMAGE_WRAP_TARGETS as aE, TEXT_FORM_FORMATS as aF, type TableBorderStyle as aG, type DrawingAccessibility as aH, type DrawingImageEffects as aI, type DrawingTransform as aJ, type VectorShapeProjection as aK, type OoxmlDrawingNode as aL, type OoxmlInvariantResult as aM, type OoxmlFldCharNode as aN, type OoxmlFldSimpleNode as aO, type OoxmlInstrTextNode as aP, type OoxmlInvariantIssue as aQ, type TreeOpResult as aR, type RelationshipRecord as aS, type OoxmlHardBreakNode as aT, type OoxmlAttribute as aU, type CommentThreadState as aV, ACCEPTED_PARAGRAPH_PROPERTIES as aW, ACCEPTED_RUN_PROPERTIES as aX, CONTENT_CONTROL_ID_MAX as aY, CONTENT_CONTROL_PROPERTY_ORDER as aZ, type CommentAnchor as a_, type DrawingPositionInput as aa, type DrawingLocks as ab, type ParagraphFormatCommand as ac, type Watermark as ad, type Rect as ae, type SelectionPin as af, type Unsubscribe as ag, type DocxDocumentJSON as ah, type DrawingHorizontalReferenceFrame as ai, type DrawingVerticalReferenceFrame as aj, type FontDefinition as ak, type NumberingRef as al, type PageMargins as am, type ParagraphDisagreements as an, type Point as ao, type Run as ap, type TableCell as aq, type TableRow as ar, type RevisionAttributionInput as as, type OoxmlParagraphNode as at, type OoxmlNoteNode as au, type OoxmlContinuationSeparatorNode as av, type OoxmlEndnotesNode as aw, type OoxmlFootnotesNode as ax, type OoxmlNoteRefNode as ay, type OoxmlNoteReferenceNode as az, type ReviewRevisionItem as b, type OoxmlReadRejection as b$, type CommitTextFormFieldOp as b0, type ContentControlCheckbox as b1, type ContentControlCheckboxState as b2, type ContentControlDataBinding as b3, type ContentControlDateFormat as b4, type ContentControlEntry as b5, type ContentControlKind as b6, type ContentControlLevel as b7, type ContentControlListItem as b8, type ContentControlLock as b9, type OoxmlContentControlCalendarNode as bA, type OoxmlContentControlCheckboxNode as bB, type OoxmlContentControlCheckedNode as bC, type OoxmlContentControlCheckedStateNode as bD, type OoxmlContentControlComboBoxNode as bE, type OoxmlContentControlDataBindingNode as bF, type OoxmlContentControlDateFormatNode as bG, type OoxmlContentControlDateNode as bH, type OoxmlContentControlDropDownListNode as bI, type OoxmlContentControlEndPropertiesNode as bJ, type OoxmlContentControlLidNode as bK, type OoxmlContentControlListItemNode as bL, type OoxmlContentControlPropertiesNode as bM, type OoxmlContentControlStoreMappedDataAsNode as bN, type OoxmlContentControlTextNode as bO, type OoxmlContentControlUncheckedStateNode as bP, type OoxmlDocumentNode as bQ, type OoxmlExternalTarget as bR, type OoxmlGenericExtensionAttribute as bS, type OoxmlHyperlinkNode as bT, type OoxmlInvariantIssueCode as bU, type OoxmlKnownNodeAttribute as bV, type OoxmlNamespaceBinding as bW, type OoxmlNodeIdentityRules as bX, type OoxmlPackageResult as bY, type OoxmlParagraphPropertiesNode as bZ, type OoxmlPartMetadata as b_, type ContentControlProperties as ba, type ContentTypeError as bb, type ContentTypeIndex as bc, type ContentTypeRecords as bd, DEFAULT_OOXML_PACKAGE_LIMITS as be, DEFAULT_ZIP_LIMITS as bf, type DefaultRecord as bg, type DeleteTextOp as bh, HYPERLINK_RELATIONSHIP_TYPE as bi, type HyperlinkKind as bj, type HyperlinkTarget as bk, IMAGE_RELATIONSHIP_TYPE as bl, type ImageRelationshipResolution as bm, type IndexResult as bn, type InsertBuildingBlockOp as bo, type InsertTextOp as bp, type LegacyCheckboxFieldRange as bq, MAX_CONTENT_CONTROLS_PER_PART as br, MAX_CONTENT_CONTROL_NESTING as bs, type NameRejection as bt, type NameResult as bu, OFFICE_RELATIONSHIP_NAMESPACE_URI as bv, OOXML_NODE_IDENTITY_RULES as bw, type OoxmlBodyNode as bx, type OoxmlBookmarkEndNode as by, type OoxmlBookmarkStartNode as bz, type ReviewCommentItem as c, isContentControlWrapper as c$, type OoxmlReadResult as c0, type OoxmlRunNode as c1, type OoxmlRunPropertiesNode as c2, type OoxmlTabNode as c3, type OoxmlTextElementNode as c4, type OoxmlTextNode as c5, type OoxmlWmlValAttribute as c6, type OoxmlXmlSpaceAttribute as c7, type OverrideRecord as c8, type RelationshipError as c9, allocateContentControlId as cA, asciiFold as cB, buildContentTypeIndex as cC, buildRelationshipSet as cD, childElements as cE, commentAnchorsOfStory as cF, commentsOfPart as cG, contentControlContentChildren as cH, contentControlContentNodeOf as cI, contentControlEndPropertiesNodeOf as cJ, contentControlLevelOf as cK, contentControlPropertiesNodeOf as cL, contentControlPropertiesOf as cM, contentControlTextOf as cN, contentControlsIn as cO, detectDuplicateNames as cP, extensionKey as cQ, findContentControl as cR, findElement as cS, firstReviewRange as cT, flattenContentControls as cU, hasAnyComment as cV, hyperlinkAnchorOf as cW, hyperlinkRelationshipIdOf as cX, hyperlinkTargetOf as cY, isContentControlContentNode as cZ, isContentControlNode as c_, type RelationshipSetResult as ca, type RelationshipTargetResolver as cb, type ResolveResult as cc, type ResolvedRelationship as cd, type SetLegacyCheckboxOp as ce, type SetLegacyDropdownOp as cf, type SetTextFormFieldDefaultOp as cg, TABLE_BORDER_STYLES as ch, type TabStopWrite as ci, type TargetMode as cj, type TextFormFieldOptions as ck, type TextFormFieldRange as cl, type TextFormFieldType as cm, type TreeDocOpKind as cn, type TreeOpEffect as co, W15_NAMESPACE_URI as cp, WML_NAMESPACE_URI as cq, XMLNS_NAMESPACE_URI as cr, XML_NAMESPACE_URI as cs, type XmlLimits as ct, type XmlNode as cu, type XmlRejection as cv, type XmlResult as cw, type ZipLimits as cx, type ZipReadResult as cy, type ZipRejection as cz, type ReviewCustomItem as d, isContentRevisionKind as d0, isHyperlinkNode as d1, isRangeMarkerKind as d2, isValidMime as d3, legacyCheckboxFieldsOf as d4, lockForbidsEdit as d5, lockForbidsRemoval as d6, normalizePartName as d7, orderedContentControlProperties as d8, parseContentControlId as d9, reviewItemsAt as dA, reviewThreadRootOf as dB, partNameKey as da, planRevisionBatch as db, projectDrawing as dc, readOnOffChild as dd, readOoxmlPackage as de, readOoxmlPart as df, readXml as dg, readZip as dh, resolveContentControlLock as di, resolveContentType as dj, resolveImageRelationship as dk, resolveInternalTarget as dl, resolveRelationship as dm, reviewItemKey as dn, reviewItemRanges as dp, textContent as dq, textFormFieldsOf as dr, threadStateOfPart as ds, validateExternalTarget as dt, withPart as du, writeOoxmlPackage as dv, writeZip as dw, type VectorShapeComponent as dx, activeReviewItem as dy, reviewItemPositionRank as dz, type ReviewPosition as e, type ReviewRange as f, type ReviewRevisionKind as g, type RevisionAddress as h, type OoxmlNode as i, type OoxmlPackage as j, type ContentControlType as k, type DocTarget as l, type RunFormatting as m, type Extent as n, type ContainerRef as o, type ContentControlFilter as p, type DocRange as q, type Revision as r, type DocComment as s, type ColorValue as t, type ContentControl as u, type DocAnchor as v, type DocAnchorRange as w, type DocLocation as x, type DocumentBody as y, type ExecErrorCode as z };
|