@docx-editor.dev/core 2.29.0 → 2.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/automation.cjs +1 -1
- package/dist/automation.d.ts +22 -26
- package/dist/automation.js +1 -1
- package/dist/binding.cjs +1 -1
- package/dist/binding.d.ts +47 -40
- package/dist/binding.js +1 -1
- package/dist/bookmark-names-DDuAra_V.d.ts +37 -0
- package/dist/{chrome-print-CAs51cpq.d.ts → chrome-print-BWvaVEhD.d.ts} +577 -243
- package/dist/chunk-243W4WW2.cjs +2 -0
- package/dist/{chunk-G4HOFIKJ.js → chunk-2E2RPEKX.js} +1 -1
- package/dist/chunk-4S24UOPG.js +30 -0
- package/dist/chunk-5JPIEN54.cjs +3 -0
- package/dist/{chunk-7WQ7AAHW.cjs → chunk-5SO5QDMV.cjs} +1 -1
- package/dist/{chunk-UHHYFIDT.cjs → chunk-6IDOVU6L.cjs} +1 -1
- package/dist/chunk-DBOOTED4.cjs +30 -0
- package/dist/chunk-EOTAXOJY.cjs +5 -0
- package/dist/chunk-FDAKJ2SJ.cjs +30 -0
- package/dist/chunk-FNNOJNGY.js +3 -0
- package/dist/chunk-FT33HRZP.js +5 -0
- package/dist/{chunk-W35WTWAO.cjs → chunk-HC6YNKUI.cjs} +1 -1
- package/dist/chunk-HZ66UCIS.js +2 -0
- package/dist/{chunk-MM5QBMTE.cjs → chunk-IBRBNT37.cjs} +1 -1
- package/dist/chunk-IVIN7X43.js +30 -0
- package/dist/chunk-LZY6B6IV.js +4 -0
- package/dist/chunk-MOYYRVFV.cjs +2 -0
- package/dist/{chunk-OMCG63ZF.js → chunk-N6B3BXCL.js} +1 -1
- package/dist/chunk-Q5K2GGNG.js +2 -0
- package/dist/chunk-R2XINWVE.js +7 -0
- package/dist/chunk-SUEXVBPR.js +1 -0
- package/dist/chunk-T2QQHG5C.js +18 -0
- package/dist/{chunk-LSZ6KPKK.js → chunk-VWIJKH4A.js} +1 -1
- package/dist/chunk-WO4V6PNS.cjs +18 -0
- package/dist/chunk-XMJKFURD.cjs +4 -0
- package/dist/{chunk-BY2ACZZ6.cjs → chunk-XSTGE3NI.cjs} +1 -1
- package/dist/chunk-YQWMI6J5.cjs +7 -0
- package/dist/{chunk-RCLZXP3B.js → chunk-ZCJS7D7S.js} +1 -1
- package/dist/collaboration/replication.cjs +1 -1
- package/dist/collaboration/replication.d.ts +4 -5
- package/dist/collaboration/replication.js +1 -1
- package/dist/collaboration.d.ts +3 -4
- package/dist/contracts/document.d.ts +3 -3
- package/dist/contracts/editor.d.ts +8 -9
- package/dist/contracts/interaction.d.ts +2 -2
- package/dist/contracts/modules.d.ts +12 -13
- package/dist/contracts/types.d.ts +2 -2
- package/dist/{custom-node-writes-Bn6uciLb.d.ts → custom-node-writes-TeUvMP13.d.ts} +2 -2
- package/dist/{diagnostic-context-B8M79cfK.d.ts → diagnostic-context-DJ0P1uZE.d.ts} +3 -2
- package/dist/{diagnostic-hints-BeVjfNOv.d.ts → diagnostic-hints-C9JlLz1L.d.ts} +12 -5
- package/dist/{document-protection-CUb55pl_.d.ts → document-protection-C8x3P2J6.d.ts} +1 -1
- package/dist/{editor-CZQZmTIU.d.ts → editor-B2ShlO23.d.ts} +368 -52
- package/dist/{editor-scope-7o9xweiJ.d.ts → editor-scope-C7ke1KJG.d.ts} +57 -4
- package/dist/editor.cjs +1 -1
- package/dist/editor.css +5 -3
- package/dist/editor.d.ts +606 -34
- package/dist/editor.js +1 -1
- package/dist/export.cjs +2 -2
- package/dist/export.d.ts +17 -15
- package/dist/export.js +2 -2
- package/dist/{font-resolver-lSBLirLR.d.ts → font-resolver-CWh40DYp.d.ts} +1 -1
- package/dist/font-shaping-policy-BvpkrfxM.d.ts +7 -0
- package/dist/{headless-document-view-pp3q7wIh.d.ts → headless-document-view-qOpaCF82.d.ts} +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +24 -24
- package/dist/index.js +1 -1
- package/dist/{layout-shaping-BD-dF_rn.d.ts → layout-shaping-CWS3j0Xr.d.ts} +3 -2
- package/dist/layout.cjs +1 -1
- package/dist/layout.d.ts +112 -44
- package/dist/layout.js +1 -1
- package/dist/{note-properties-qQUjO1GQ.d.ts → note-properties-QsKh24sM.d.ts} +1 -1
- package/dist/{omml-equation-BUbU0utM.d.ts → omml-equation-BsLAa2lX.d.ts} +38 -8
- package/dist/output.cjs +1 -1
- package/dist/output.d.ts +20 -10
- package/dist/output.js +1 -1
- package/dist/{protocol-DYzzz2ej.d.ts → protocol-COZJUKUY.d.ts} +94 -2
- package/dist/{review-paragraph-order-CN_0l2Cb.d.ts → review-paragraph-order-C_QbCKcH.d.ts} +1 -1
- package/dist/{semantic-cell-selection-eYag3P47.d.ts → semantic-cell-selection-Cub9FDa8.d.ts} +2 -2
- package/dist/{semantic-interaction-kR_QB845.d.ts → semantic-interaction-dApRIYpt.d.ts} +1 -1
- package/dist/{semantic-paint-ZayFF3tD.d.ts → semantic-paint-DLzA8sjP.d.ts} +3 -3
- package/dist/{semantic-record-queries-Bsgth6lv.d.ts → semantic-record-queries-3yp9o11g.d.ts} +1 -1
- package/dist/{semantic-records-DQmumPgL.d.ts → semantic-records-B-akgRch.d.ts} +207 -139
- package/dist/store.cjs +1 -1
- package/dist/store.d.ts +49 -136
- package/dist/store.js +1 -1
- package/dist/{tree-package-store-CovjNARF.d.ts → tree-package-store-B8l8DX3Z.d.ts} +612 -428
- package/dist/{tree-session-contract-CZVAGl51.d.ts → tree-session-contract-DeLRqohz.d.ts} +28 -13
- package/dist/{types-barrel-DuC5QBNC.d.ts → types-barrel-CkF2JbU4.d.ts} +1146 -745
- package/package.json +2 -2
- package/dist/chunk-236O4YQW.js +0 -2
- package/dist/chunk-6JPL6ZAS.cjs +0 -5
- package/dist/chunk-6ZQP4HQ7.js +0 -3
- package/dist/chunk-BCXH4BXB.js +0 -5
- package/dist/chunk-CAJEXXVG.cjs +0 -4
- package/dist/chunk-CPWLFPWC.js +0 -30
- package/dist/chunk-D7ZMDMPX.cjs +0 -3
- package/dist/chunk-DOHF6FA7.cjs +0 -30
- package/dist/chunk-DVX32P2P.js +0 -27
- package/dist/chunk-E4LOMDNL.js +0 -1
- package/dist/chunk-EKLM7NWB.cjs +0 -7
- package/dist/chunk-G3K63G7P.cjs +0 -27
- package/dist/chunk-JLVBDYVQ.cjs +0 -2
- package/dist/chunk-LQX36Z5P.js +0 -7
- package/dist/chunk-OSFOJTHU.cjs +0 -18
- package/dist/chunk-T6K2QYNZ.cjs +0 -2
- package/dist/chunk-TRGAVV2Y.js +0 -4
- package/dist/chunk-U4JZVSOE.js +0 -2
- package/dist/chunk-YQ5G6LC7.js +0 -18
- package/dist/image-resources-tXLQShoC.d.ts +0 -211
|
@@ -1,16 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Q as OoxmlPackage, ax as RevisionAttributionInput, ay as DrawingTreeDocOp, O as OoxmlPart, N as OoxmlNode, ak as OoxmlElement, az as OoxmlParagraphNode, aA as OoxmlNoteNode, aB as OoxmlContinuationSeparatorNode, aC as OoxmlEndnotesNode, aD as OoxmlFootnotesNode, aE as OoxmlNoteRefNode, aF as OoxmlNoteReferenceNode, aG as OoxmlSeparatorNode, aH as ImpactClass, ag as TreeDocOp, av as TreeOpRejection } from './types-barrel-DuC5QBNC.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* How saved field results are addressed.
|
|
6
|
-
*
|
|
7
|
-
* - `atomic`: every closed field is one offset unit.
|
|
8
|
-
* - `editable`: the results of CREATEDATE, DATE, FILENAME, FILLIN, HYPERLINK, MERGEFIELD,
|
|
9
|
-
* PRINTDATE, QUOTE, SAVEDATE, SEQ, and TIME fields are text when their results are unnested.
|
|
10
|
-
* Simple fields inside complex field results are not supported in this mode. Other nested
|
|
11
|
-
* results, other field types, and legacy FORMTEXT inputs keep their existing addressing.
|
|
12
|
-
*/
|
|
13
|
-
type FieldResultsMode = 'atomic' | 'editable';
|
|
1
|
+
import { Q as OoxmlPackage, af as SupportedImageMime, O as OoxmlPart, N as OoxmlNode, ap as OoxmlElement, aH as PackageWatermarkWrite, aI as OoxmlInvariantIssue, aE as ImageDecodePort, aG as RevisionAttributionInput, aJ as DrawingTreeDocOp, aK as ImpactClass, ao as TreeDocOp, aC as TreeOpRejection, aL as OoxmlParagraphNode, aM as OoxmlNoteNode, aN as OoxmlContinuationSeparatorNode, aO as OoxmlEndnotesNode, aP as OoxmlFootnotesNode, aQ as OoxmlNoteRefNode, aR as OoxmlNoteReferenceNode, aS as OoxmlSeparatorNode } from './types-barrel-CkF2JbU4.js';
|
|
14
2
|
|
|
15
3
|
/** A freshly allocated drawing property id, or the reason one could not be minted. */
|
|
16
4
|
type DrawingPropertyIdResult = {
|
|
@@ -74,52 +62,6 @@ interface ExternalImageFetchPort {
|
|
|
74
62
|
}>>;
|
|
75
63
|
}
|
|
76
64
|
|
|
77
|
-
interface InsertImageInput {
|
|
78
|
-
readonly paragraphId: string;
|
|
79
|
-
readonly offset: number;
|
|
80
|
-
readonly bytes: Uint8Array;
|
|
81
|
-
readonly mime: SupportedImageMime;
|
|
82
|
-
readonly widthPoints: number;
|
|
83
|
-
readonly heightPoints: number;
|
|
84
|
-
readonly decodePort: ImageDecodePort;
|
|
85
|
-
readonly expectedPackageRevision: number;
|
|
86
|
-
readonly commitGuard?: () => boolean;
|
|
87
|
-
readonly title?: string;
|
|
88
|
-
readonly description?: string;
|
|
89
|
-
readonly hyperlink?: string;
|
|
90
|
-
/** Present in suggesting mode: the inserted drawing's run goes into a `w:ins`. */
|
|
91
|
-
readonly revision?: RevisionAttributionInput;
|
|
92
|
-
/**
|
|
93
|
-
* Collaboration actor for the ids this insert mints — `wp:docPr/@id`, the image
|
|
94
|
-
* relationship, and a hyperlink relationship when one is asked for.
|
|
95
|
-
*
|
|
96
|
-
* EXPLICIT, and not the ambient `runWithTransactionActor` binding, because this entry is
|
|
97
|
-
* async: the mint runs after `await validateEmbeddedImageForCommit` and the ambient actor
|
|
98
|
-
* is synchronous-only. A wrap around the call would compile, read as correct, and be gone
|
|
99
|
-
* by the time the id is taken. Omitted (solo) keeps Word's dense `highest + 1` sequence.
|
|
100
|
-
*/
|
|
101
|
-
readonly actorId?: string;
|
|
102
|
-
}
|
|
103
|
-
interface ReplaceImageOptions {
|
|
104
|
-
readonly expectedPackageRevision: number;
|
|
105
|
-
readonly commitGuard?: () => boolean;
|
|
106
|
-
/** Collaboration actor for the replacement's minted ids. See {@link InsertImageInput.actorId}. */
|
|
107
|
-
readonly actorId?: string;
|
|
108
|
-
}
|
|
109
|
-
type ImageIntentResult = (Extract<PackageTransactResult, {
|
|
110
|
-
ok: true;
|
|
111
|
-
}> & {
|
|
112
|
-
readonly drawingNodeId?: string;
|
|
113
|
-
readonly mediaPartName?: string;
|
|
114
|
-
}) | Extract<PackageTransactResult, {
|
|
115
|
-
ok: false;
|
|
116
|
-
}>;
|
|
117
|
-
interface ApplyImagePropertiesInput {
|
|
118
|
-
readonly drawingNodeId: string;
|
|
119
|
-
readonly ops: readonly DrawingTreeDocOp[];
|
|
120
|
-
readonly hyperlink: string | null;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
65
|
/** `w:headerReference w:type` vocabulary (ECMA-376 §17.10.5): default, first page, even pages. */
|
|
124
66
|
type HeaderFooterVariant = 'default' | 'first' | 'even';
|
|
125
67
|
/** Header vs footer region kind for chrome and lifecycle ops. */
|
|
@@ -233,6 +175,13 @@ type HeaderFooterLifecycleOp = {
|
|
|
233
175
|
*/
|
|
234
176
|
readonly op: 'setDocumentProtection';
|
|
235
177
|
readonly enforce: boolean;
|
|
178
|
+
} | {
|
|
179
|
+
/**
|
|
180
|
+
* Replace the document watermark in every header a section shows; null removes it.
|
|
181
|
+
* It may create a section's default header, so it rides this lane's package undo unit.
|
|
182
|
+
*/
|
|
183
|
+
readonly op: 'setWatermark';
|
|
184
|
+
readonly watermark: PackageWatermarkWrite | null;
|
|
236
185
|
};
|
|
237
186
|
/** Why a header/footer lifecycle op was refused. */
|
|
238
187
|
type HeaderFooterLifecycleRejection = 'invalidArgs' | 'tree-invariant';
|
|
@@ -258,338 +207,198 @@ declare function isHeaderFooterLifecycleOp(op: {
|
|
|
258
207
|
*/
|
|
259
208
|
declare function applyHeaderFooterLifecycleOp(pkg: OoxmlPackage, op: HeaderFooterLifecycleOp): HeaderFooterLifecycleResult;
|
|
260
209
|
|
|
261
|
-
/** UTF-16 placeholder for one atomic note unit in `paragraphTextOf` / segments. */
|
|
262
|
-
declare const NOTE_ATOM_CHAR = "\uFFFC";
|
|
263
|
-
/** Signed 32-bit Word-compatible note id range (positive allocation only). */
|
|
264
|
-
declare const NOTE_ID_MIN = 1;
|
|
265
|
-
/** Largest note id Word accepts — signed 32-bit. */
|
|
266
|
-
declare const NOTE_ID_MAX = 2147483647;
|
|
267
|
-
/** Reserved separator / continuation ids — never allocated for normal notes. */
|
|
268
|
-
declare const NOTE_SEPARATOR_ID = -1;
|
|
269
|
-
/** Reserved id of the continuation-separator entry. Never allocated to a real note. */
|
|
270
|
-
declare const NOTE_CONTINUATION_SEPARATOR_ID = 0;
|
|
271
|
-
/** Which notes part a note lives in. Decides both placement and numbering rules. */
|
|
272
|
-
type NoteKind = 'footnote' | 'endnote';
|
|
273
|
-
/** Authored `ST_FtnEdn` including explicit `normal`. Absent means Word default (normal). */
|
|
274
210
|
/**
|
|
275
|
-
*
|
|
211
|
+
* How saved field results are addressed.
|
|
276
212
|
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
213
|
+
* - `atomic`: every closed field is one offset unit.
|
|
214
|
+
* - `editable`: the results of CREATEDATE, DATE, FILENAME, FILLIN, HYPERLINK, MERGEFIELD,
|
|
215
|
+
* PRINTDATE, QUOTE, SAVEDATE, SEQ, and TIME fields are text when their results are unnested.
|
|
216
|
+
* Simple fields inside complex field results are not supported in this mode. Other nested
|
|
217
|
+
* results, other field types, and legacy FORMTEXT inputs keep their existing addressing.
|
|
279
218
|
*/
|
|
280
|
-
type
|
|
281
|
-
|
|
282
|
-
|
|
219
|
+
type FieldResultsMode = 'atomic' | 'editable';
|
|
220
|
+
|
|
221
|
+
/** An edited part, or the invariant violations that rejected the edit. */
|
|
222
|
+
type OoxmlEditResult = {
|
|
223
|
+
readonly ok: true;
|
|
224
|
+
readonly part: OoxmlPart;
|
|
225
|
+
} | {
|
|
226
|
+
readonly ok: false;
|
|
227
|
+
readonly issues: readonly OoxmlInvariantIssue[];
|
|
228
|
+
};
|
|
283
229
|
/**
|
|
284
|
-
*
|
|
230
|
+
* An opt-in relaxation of `ST_Lock` for hosts that protect WHAT a control says, not how it looks.
|
|
285
231
|
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
*
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
} | null;
|
|
297
|
-
/** Whether a node is a `w:footnotes` part root. */
|
|
298
|
-
declare function isFootnotesNode(node: OoxmlNode): node is OoxmlFootnotesNode;
|
|
299
|
-
/** Whether a node is a `w:endnotes` part root. */
|
|
300
|
-
declare function isEndnotesNode(node: OoxmlNode): node is OoxmlEndnotesNode;
|
|
301
|
-
/** Whether a node is a `w:footnote` or `w:endnote` body. */
|
|
302
|
-
declare function isNoteNode(node: OoxmlNode): node is OoxmlNoteNode;
|
|
303
|
-
/** Whether a node is a body-side `w:footnoteReference` / `w:endnoteReference`. */
|
|
304
|
-
declare function isNoteReferenceNode(node: OoxmlNode): node is OoxmlNoteReferenceNode;
|
|
305
|
-
/** Whether a node is the `w:footnoteRef` / `w:endnoteRef` mark inside a note's own body. */
|
|
306
|
-
declare function isNoteRefNode(node: OoxmlNode): node is OoxmlNoteRefNode;
|
|
307
|
-
/** Whether a node is the `w:separator` rule drawn above the note area. */
|
|
308
|
-
declare function isSeparatorNode(node: OoxmlNode): node is OoxmlSeparatorNode;
|
|
309
|
-
/** Whether a node is the `w:continuationSeparator` rule used on continuation pages. */
|
|
310
|
-
declare function isContinuationSeparatorNode(node: OoxmlNode): node is OoxmlContinuationSeparatorNode;
|
|
311
|
-
/** Typed or generic `w:footnote` / `w:endnote`. */
|
|
312
|
-
declare function noteKindOf(node: OoxmlNode): NoteKind | null;
|
|
313
|
-
/** Authored `@w:id` on a note or noteReference when parseable. */
|
|
314
|
-
declare function noteIdOf(node: OoxmlNode): number | null;
|
|
315
|
-
/** Authored `@w:type` (`ST_FtnEdn`) when present and schema-legal; else `undefined`. */
|
|
316
|
-
declare function noteTypeOf(node: OoxmlNode): NoteType | undefined;
|
|
317
|
-
/** Whether a note is a normal (body) note — absent type and explicit `normal` both count. */
|
|
318
|
-
declare function isNormalNote(node: OoxmlNode): boolean;
|
|
319
|
-
/** Typed or generic footnote/endnote reference kind. */
|
|
320
|
-
declare function noteReferenceKindOf(node: OoxmlNode): NoteKind | null;
|
|
321
|
-
/** Typed or generic `w:footnoteRef` / `w:endnoteRef`. */
|
|
322
|
-
declare function noteRefKindOf(node: OoxmlNode): NoteKind | null;
|
|
323
|
-
/**
|
|
324
|
-
* Read `@w:customMarkFollows` on a note reference.
|
|
325
|
-
* Returns `undefined` when absent; otherwise the OOXML on/off interpretation.
|
|
326
|
-
*/
|
|
327
|
-
declare function customMarkFollows(node: OoxmlNode): boolean | undefined;
|
|
328
|
-
/** Model text contributed by one atomic note unit. */
|
|
329
|
-
declare function noteAtomText(): typeof NOTE_ATOM_CHAR;
|
|
330
|
-
/**
|
|
331
|
-
* True when a run-inner node is a typed note atom that contributes one UTF-16 unit.
|
|
332
|
-
* Demoted/malformed known locals stay generic and contribute nothing.
|
|
232
|
+
* ECMA-376 `contentLocked` forbids editing the control's contents and Word reads formatting as
|
|
233
|
+
* part of that, which is the default here. A host that puts protected text in a control (a
|
|
234
|
+
* template placeholder the user must not retype) but lets authors style it sets
|
|
235
|
+
* `allowFormattingInLockedContent`: a run-property write (bold, colour, font, size, highlight …),
|
|
236
|
+
* on runs or on a paragraph mark, then passes the CONTENT half of the lock. The exception never
|
|
237
|
+
* admits a property that hides text (`w:vanish`, `w:specVanish`, `w:webHidden`), which the
|
|
238
|
+
* run-property vocabulary refuses today anyway. Text edits, deletion of the content, paragraph properties,
|
|
239
|
+
* removal of a `sdtLocked` wrapper and `w:dataBinding` refusals are unchanged.
|
|
240
|
+
*
|
|
241
|
+
* @public
|
|
333
242
|
*/
|
|
334
|
-
|
|
243
|
+
interface ContentLockPolicy {
|
|
244
|
+
/** Let run formatting pass a content lock; text and removal stay refused. Default `false`. */
|
|
245
|
+
readonly allowFormattingInLockedContent?: boolean;
|
|
246
|
+
}
|
|
335
247
|
/**
|
|
336
|
-
*
|
|
248
|
+
* How an edit primitive validates its result.
|
|
337
249
|
*
|
|
338
|
-
*
|
|
250
|
+
* By default every primitive runs the full-part invariant validation before handing its
|
|
251
|
+
* result back — the safe reading for an isolated call. A TRANSACTION applying many ops pays
|
|
252
|
+
* that full-tree walk once per primitive, which is what made a hundred-paragraph paste
|
|
253
|
+
* quadratic; it defers instead, and runs the same validation ONCE on the final tree before
|
|
254
|
+
* anything is published. Deferring is only sound for a caller that owns a commit boundary:
|
|
255
|
+
* nothing may escape between the unvalidated intermediate and the validated result.
|
|
339
256
|
*/
|
|
340
|
-
interface
|
|
341
|
-
readonly
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
257
|
+
interface EditOptions {
|
|
258
|
+
readonly deferValidation?: boolean;
|
|
259
|
+
/**
|
|
260
|
+
* How a content control's `w:lock` is read for ops that only restyle text. Absent means
|
|
261
|
+
* the default: `contentLocked` / `sdtContentLocked` refuse every write, formatting included.
|
|
262
|
+
*/
|
|
263
|
+
readonly contentLockPolicy?: ContentLockPolicy;
|
|
264
|
+
/**
|
|
265
|
+
* A shared minter for `@w:id` on a NEW revision, for the ops of one transaction.
|
|
266
|
+
*
|
|
267
|
+
* `nextRevisionId` walks the whole part to find the highest id in use, and a formatting
|
|
268
|
+
* write emits one op per run — so a Select All + Bold in suggesting mode paid a
|
|
269
|
+
* document-wide walk thousands of times over. The transaction hands its ops one minter
|
|
270
|
+
* instead, and it is DROPPED the moment an op that can import foreign revision ids runs
|
|
271
|
+
* (a paste carries its own), because a stale minter would hand out an id the document had
|
|
272
|
+
* just started using — and two revisions sharing an address are one card in the pane.
|
|
273
|
+
*
|
|
274
|
+
* Absent means "mint your own": every applier falls back to its own walk, which is what a
|
|
275
|
+
* caller outside a transaction gets.
|
|
276
|
+
*/
|
|
277
|
+
readonly revisionIds?: () => string;
|
|
278
|
+
/**
|
|
279
|
+
* The transaction's revision-id bookkeeping for the tracked TEXT ops, where `revisionIds`
|
|
280
|
+
* above hands the property ops one shared id for their whole group.
|
|
281
|
+
*
|
|
282
|
+
* Absent means "mint your own and remember nothing", which is what a caller outside a
|
|
283
|
+
* transaction gets: every applier falls back to its own walk of the part.
|
|
284
|
+
*/
|
|
285
|
+
readonly trackedRevisionIds?: TransactionRevisionIds;
|
|
286
|
+
/**
|
|
287
|
+
* How the op addresses saved field results (`field-result-mode.ts`). Absent keeps the mode
|
|
288
|
+
* of the enclosing store call, which is `atomic` outside any editable transaction.
|
|
289
|
+
*/
|
|
290
|
+
readonly fieldResults?: FieldResultsMode;
|
|
345
291
|
}
|
|
346
292
|
/**
|
|
347
|
-
*
|
|
293
|
+
* What one transaction knows about the revision ids its tracked text ops write.
|
|
348
294
|
*
|
|
349
|
-
*
|
|
350
|
-
*
|
|
351
|
-
*
|
|
295
|
+
* TWO questions, and they are the same bookkeeping. `nextRevisionId` walks the whole part, so
|
|
296
|
+
* a replacement — a `deleteText` and an `insertText` in one transaction — walked it twice, and
|
|
297
|
+
* on a five-hundred-page document that doubled the cost of every one. And an insertion aimed
|
|
298
|
+
* at the front edge of a deletion relocates past it only when that deletion is THIS
|
|
299
|
+
* transaction's own: typing over a selection. Backspace, then a keystroke, is two
|
|
300
|
+
* transactions, and there the typed text belongs in FRONT of the struck character, as Word
|
|
301
|
+
* writes it. Adjacency alone cannot tell the two apart; the ids can.
|
|
352
302
|
*/
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
|
|
303
|
+
interface TransactionRevisionIds {
|
|
304
|
+
/** A fresh `@w:id`, from this transaction's one walk of the part. */
|
|
305
|
+
mint(): string;
|
|
306
|
+
/**
|
|
307
|
+
* Record a wrapper this transaction wrote, by its FULL `CT_TrackChange` identity — id,
|
|
308
|
+
* author and date, as `revisionKey` spells it. Not by the id alone: that number comes out
|
|
309
|
+
* of the file, nothing makes it unique, and a strike joining `w:id="3"` in one paragraph
|
|
310
|
+
* would otherwise claim an unrelated `w:id="3"` elsewhere as this edit's own.
|
|
311
|
+
*/
|
|
312
|
+
wrote(key: string): void;
|
|
313
|
+
/** Whether this transaction wrote a wrapper with that identity. */
|
|
314
|
+
wroteUnder(key: string): boolean;
|
|
315
|
+
}
|
|
316
|
+
/** Every node id currently present in the part. */
|
|
317
|
+
declare function collectNodeIds(part: OoxmlPart): Set<string>;
|
|
356
318
|
/**
|
|
357
|
-
*
|
|
319
|
+
* Mint ids for nodes an edit introduces.
|
|
358
320
|
*
|
|
359
|
-
*
|
|
360
|
-
*
|
|
321
|
+
* Deterministic and collision-checked against the whole part: a structural-path id from the
|
|
322
|
+
* original parse (`/word/document.xml#0.1.2`) and a minted one (`/word/document.xml#new:3`)
|
|
323
|
+
* can never coincide, and the counter skips anything already taken so repeated edits in one
|
|
324
|
+
* session stay unique.
|
|
361
325
|
*
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
* footnote from one snapshot otherwise both mint `w:id="1"`: the merge keeps both bodies
|
|
365
|
-
* under one id, both `w:footnoteReference` marks resolve to the first, and one author's note
|
|
366
|
-
* becomes unreachable.
|
|
326
|
+
* Allocators share reservations across edited roots and restored roots. Preview edits,
|
|
327
|
+
* detached nodes, and undo branches must not reuse an identity that collaboration retains.
|
|
367
328
|
*
|
|
368
|
-
*
|
|
369
|
-
*
|
|
370
|
-
* only ever climbs from a non-negative residue, so `-1` (separator) is unreachable.
|
|
371
|
-
*/
|
|
372
|
-
declare function allocateNoteId(notesRoot: OoxmlNode, actorId?: string): number | null;
|
|
373
|
-
/** Collect note bodies from a footnotes/endnotes root, bounded. */
|
|
374
|
-
declare function notesOf(root: OoxmlNode): readonly OoxmlNoteNode[];
|
|
375
|
-
/** Find a typed note by id inside a notes-part root. */
|
|
376
|
-
declare function findNoteById(root: OoxmlNode, noteId: number): OoxmlNoteNode | undefined;
|
|
377
|
-
|
|
378
|
-
/** Cap on nodes visited while scanning for note references across stories. */
|
|
379
|
-
declare const MAX_NOTE_REFERENCE_SCAN = 20000;
|
|
380
|
-
/**
|
|
381
|
-
* Cap on XML parts walked in one package-wide note-reference scan (N/N+1 gate).
|
|
382
|
-
* Soft targets are not allowed: exceeding this marks the shared budget truncated.
|
|
329
|
+
* Checks the part's node index directly rather than copying every id into a fresh set: the
|
|
330
|
+
* copy was O(document) per op, and an allocator is created for every op.
|
|
383
331
|
*/
|
|
384
|
-
declare
|
|
332
|
+
declare function createNodeIdAllocator(part: OoxmlPart, family?: 'new' | 'paste'): () => string;
|
|
333
|
+
/** Whether a node id exists in the part. */
|
|
334
|
+
declare function hasNode(part: OoxmlPart, nodeId: string): boolean;
|
|
335
|
+
/** Read a node back out of a part by id. */
|
|
336
|
+
declare function findNode(part: OoxmlPart, nodeId: string): OoxmlNode | null;
|
|
337
|
+
/** The element that holds a node, or null for the root and for unknown ids. */
|
|
338
|
+
declare function parentNodeOf(part: OoxmlPart, nodeId: string): OoxmlElement | null;
|
|
339
|
+
/** Replace one node's children wholesale. */
|
|
340
|
+
declare function replaceChildren(part: OoxmlPart, nodeId: string, children: readonly OoxmlNode[], options?: EditOptions): OoxmlEditResult;
|
|
341
|
+
/** Insert children into a node at `index` (clamped to the child list). */
|
|
342
|
+
declare function insertChildren(part: OoxmlPart, nodeId: string, index: number, children: readonly OoxmlNode[], options?: EditOptions): OoxmlEditResult;
|
|
343
|
+
/** Replace one node with another, keeping its position among its siblings. */
|
|
344
|
+
declare function replaceNode(part: OoxmlPart, nodeId: string, replacement: OoxmlNode, options?: EditOptions): OoxmlEditResult;
|
|
345
|
+
/** Remove a node and its subtree. */
|
|
346
|
+
declare function removeNode(part: OoxmlPart, nodeId: string, options?: EditOptions): OoxmlEditResult;
|
|
385
347
|
/**
|
|
386
|
-
*
|
|
348
|
+
* Apply several primitives as ONE atomic step.
|
|
387
349
|
*
|
|
388
|
-
*
|
|
389
|
-
*
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
/**
|
|
393
|
-
* Load-time note diagnostics. Array API preserved; truncation is signaled as a typed
|
|
394
|
-
* entry rather than by throwing or rejecting the package.
|
|
350
|
+
* Each edit runs against the result of the previous one, and the whole sequence is
|
|
351
|
+
* validated once at the end. If any step fails, the ORIGINAL part is what the caller keeps
|
|
352
|
+
* — there is no partially-edited intermediate to publish. This is the shape a multi-`DocOp`
|
|
353
|
+
* store transaction needs.
|
|
395
354
|
*/
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
readonly noteId: number;
|
|
400
|
-
/** Paragraph / container node id when known. */
|
|
401
|
-
readonly sourceNodeId?: string;
|
|
402
|
-
} | {
|
|
403
|
-
/** Hard visited/part budget or soft hit cap stopped the scan before full coverage. */
|
|
404
|
-
readonly code: 'note-reference-scan-truncated';
|
|
405
|
-
};
|
|
406
|
-
/** One note reference found in a story, with where it sits. */
|
|
407
|
-
interface NoteReferenceHit {
|
|
408
|
-
readonly noteKind: NoteKind;
|
|
409
|
-
readonly noteId: number;
|
|
410
|
-
readonly nodeId: string;
|
|
355
|
+
declare function applyEdits(part: OoxmlPart, edits: readonly ((current: OoxmlPart) => OoxmlEditResult)[], options?: EditOptions): OoxmlEditResult;
|
|
356
|
+
|
|
357
|
+
interface InsertImageInput {
|
|
411
358
|
readonly paragraphId: string;
|
|
412
|
-
|
|
413
|
-
readonly
|
|
414
|
-
readonly
|
|
415
|
-
|
|
416
|
-
readonly
|
|
359
|
+
readonly offset: number;
|
|
360
|
+
readonly bytes: Uint8Array;
|
|
361
|
+
readonly mime: SupportedImageMime;
|
|
362
|
+
readonly widthPoints: number;
|
|
363
|
+
readonly heightPoints: number;
|
|
364
|
+
readonly decodePort: ImageDecodePort;
|
|
365
|
+
readonly expectedPackageRevision: number;
|
|
366
|
+
readonly commitGuard?: () => boolean;
|
|
367
|
+
readonly title?: string;
|
|
368
|
+
readonly description?: string;
|
|
369
|
+
readonly hyperlink?: string;
|
|
370
|
+
/** Present in suggesting mode: the inserted drawing's run goes into a `w:ins`. */
|
|
371
|
+
readonly revision?: RevisionAttributionInput;
|
|
372
|
+
/**
|
|
373
|
+
* Collaboration actor for the ids this insert mints — `wp:docPr/@id`, the image
|
|
374
|
+
* relationship, and a hyperlink relationship when one is asked for.
|
|
375
|
+
*
|
|
376
|
+
* EXPLICIT, and not the ambient `runWithTransactionActor` binding, because this entry is
|
|
377
|
+
* async: the mint runs after `await validateEmbeddedImageForCommit` and the ambient actor
|
|
378
|
+
* is synchronous-only. A wrap around the call would compile, read as correct, and be gone
|
|
379
|
+
* by the time the id is taken. Omitted (solo) keeps Word's dense `highest + 1` sequence.
|
|
380
|
+
*/
|
|
381
|
+
readonly actorId?: string;
|
|
417
382
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
readonly maxParts: number;
|
|
424
|
-
/** Set when a walk stops before finishing because a cap was hit. */
|
|
425
|
-
truncated: boolean;
|
|
426
|
-
}
|
|
427
|
-
/** A bounded budget for scanning note references, so a crafted document cannot stall a load. */
|
|
428
|
-
declare function createNoteReferenceScanBudget(maxVisited?: number, maxParts?: number): NoteReferenceScanBudget;
|
|
429
|
-
/**
|
|
430
|
-
* Resolve the footnotes or endnotes part via safe Internal document relationships.
|
|
431
|
-
*
|
|
432
|
-
* Unusable matching relationships (External, unsafe target, missing part, wrong root)
|
|
433
|
-
* are skipped — never fetched, never accepted — so a decoy first match cannot hide a
|
|
434
|
-
* later usable Internal notes part (same continue-past-bad pattern as settingsPartOf).
|
|
435
|
-
*/
|
|
436
|
-
declare function resolveNotesPart(pkg: OoxmlPackage, noteKind: NoteKind): OoxmlPart | null;
|
|
437
|
-
/** Walk a part without applying a layout projection. */
|
|
438
|
-
declare function collectNoteReferences(part: OoxmlPart, options?: {
|
|
439
|
-
readonly maxHits?: number;
|
|
440
|
-
readonly budget?: NoteReferenceScanBudget;
|
|
441
|
-
}): readonly NoteReferenceHit[];
|
|
442
|
-
/** Collect references across every XML part under one shared part + visited-node budget. */
|
|
443
|
-
declare function collectPackageNoteReferences(pkg: OoxmlPackage, options?: {
|
|
444
|
-
readonly budget?: NoteReferenceScanBudget;
|
|
445
|
-
/** Soft hit cap for diagnostics. Omit / Infinity for mutation scans. */
|
|
446
|
-
readonly maxHits?: number;
|
|
447
|
-
}): readonly NoteReferenceHit[];
|
|
448
|
-
/**
|
|
449
|
-
* Load diagnostics for dangling note references. Fail-open: never throws or mutates;
|
|
450
|
-
* returns diagnostics for callers to surface. Does not invent missing note bodies.
|
|
451
|
-
*
|
|
452
|
-
* When the hard visited/part budget truncates or the soft hit cap binds, appends a single
|
|
453
|
-
* `note-reference-scan-truncated` entry so incomplete coverage is visible without breaking
|
|
454
|
-
* consumers that filter on `dangling-note-reference`.
|
|
455
|
-
*/
|
|
456
|
-
declare function diagnoseNoteReferences(pkg: OoxmlPackage): readonly NoteDiagnostic[];
|
|
457
|
-
/** Whether a notes-part root contains a note with the given id (any type). */
|
|
458
|
-
declare function notesPartHasId(part: OoxmlPart, noteId: number): boolean;
|
|
459
|
-
/** List normal (body) note ids in document order, bounded. */
|
|
460
|
-
declare function normalNoteIds(part: OoxmlPart): readonly number[];
|
|
461
|
-
|
|
462
|
-
/** How far a note lifecycle op reaches — which parts a caller must expect to have changed. */
|
|
463
|
-
type NoteLifecycleImpact = 'flow-structural' | 'global';
|
|
464
|
-
/**
|
|
465
|
-
* A note lifecycle mutation: insert, delete, convert, or set properties.
|
|
466
|
-
*
|
|
467
|
-
* Package-level rather than story-level, because every one of these touches the main document,
|
|
468
|
-
* the notes part, the document relationships AND `[Content_Types].xml` together.
|
|
469
|
-
*/
|
|
470
|
-
type NoteLifecycleOp = {
|
|
471
|
-
readonly op: 'insertNote';
|
|
472
|
-
readonly noteKind: NoteKind;
|
|
473
|
-
readonly paragraphId: string;
|
|
474
|
-
readonly offset: number;
|
|
475
|
-
/**
|
|
476
|
-
* Write the citing reference as a TRACKED insertion: the reference run goes inside a
|
|
477
|
-
* `w:ins` carrying this attribution. The note body stays plain — rejecting the
|
|
478
|
-
* reference removes it, and the orphaned body is swept by the same cascade an
|
|
479
|
-
* untracked reference deletion triggers.
|
|
480
|
-
*/
|
|
481
|
-
readonly revision?: RevisionAttributionInput;
|
|
482
|
-
} | {
|
|
483
|
-
readonly op: 'deleteNote';
|
|
484
|
-
readonly noteKind: NoteKind;
|
|
485
|
-
readonly noteId: number;
|
|
486
|
-
} | {
|
|
487
|
-
readonly op: 'convertNote';
|
|
488
|
-
readonly fromKind: NoteKind;
|
|
489
|
-
readonly noteId: number;
|
|
490
|
-
} | {
|
|
491
|
-
/**
|
|
492
|
-
* Convert every normal note of `fromKind` in document order. One atomic package
|
|
493
|
-
* transaction / undo unit with the same validation as repeated `convertNote`.
|
|
494
|
-
*/
|
|
495
|
-
readonly op: 'convertAllNotes';
|
|
496
|
-
readonly fromKind: NoteKind;
|
|
497
|
-
} | {
|
|
498
|
-
readonly op: 'setNoteProperties';
|
|
499
|
-
readonly scope: 'document' | 'section';
|
|
500
|
-
readonly sectionIndex?: number;
|
|
501
|
-
readonly footnote?: {
|
|
502
|
-
readonly numFmt?: string;
|
|
503
|
-
readonly numRestart?: string;
|
|
504
|
-
readonly position?: string;
|
|
505
|
-
readonly numStart?: number;
|
|
506
|
-
};
|
|
507
|
-
readonly endnote?: {
|
|
508
|
-
readonly numFmt?: string;
|
|
509
|
-
readonly numRestart?: string;
|
|
510
|
-
readonly position?: string;
|
|
511
|
-
readonly numStart?: number;
|
|
512
|
-
};
|
|
513
|
-
};
|
|
514
|
-
/** Why a note lifecycle op was refused. */
|
|
515
|
-
type NoteLifecycleRejection = 'invalidArgs' | 'invalid-property-value' | 'tree-invariant';
|
|
516
|
-
/**
|
|
517
|
-
* A new package, or a typed rejection.
|
|
518
|
-
*
|
|
519
|
-
* Application is PURE and all-or-nothing: there are no partial writes, so a refused op leaves the
|
|
520
|
-
* caller's package untouched rather than half-migrated across four parts.
|
|
521
|
-
*/
|
|
522
|
-
type NoteLifecycleResult = {
|
|
523
|
-
readonly ok: true;
|
|
524
|
-
readonly package: OoxmlPackage;
|
|
525
|
-
readonly impact: NoteLifecycleImpact;
|
|
526
|
-
readonly noteId?: number;
|
|
527
|
-
readonly noteKind?: NoteKind;
|
|
528
|
-
readonly createdPartName?: string;
|
|
529
|
-
} | {
|
|
530
|
-
readonly ok: false;
|
|
531
|
-
readonly reason: NoteLifecycleRejection;
|
|
532
|
-
readonly detail?: string;
|
|
533
|
-
};
|
|
534
|
-
/** Whether an op is a note lifecycle op rather than a story-level one. */
|
|
535
|
-
declare function isNoteLifecycleOp(op: {
|
|
536
|
-
readonly op: string;
|
|
537
|
-
}): op is NoteLifecycleOp;
|
|
538
|
-
/** Attribution and limits applied to one note lifecycle op. */
|
|
539
|
-
interface NoteLifecycleOptions {
|
|
540
|
-
/**
|
|
541
|
-
* Shared part + visited-node budget for reference scans. When omitted a fresh default
|
|
542
|
-
* budget is used. Truncation rejects the op with the original package unchanged.
|
|
543
|
-
*/
|
|
544
|
-
readonly scanBudget?: NoteReferenceScanBudget;
|
|
383
|
+
interface ReplaceImageOptions {
|
|
384
|
+
readonly expectedPackageRevision: number;
|
|
385
|
+
readonly commitGuard?: () => boolean;
|
|
386
|
+
/** Collaboration actor for the replacement's minted ids. See {@link InsertImageInput.actorId}. */
|
|
387
|
+
readonly actorId?: string;
|
|
545
388
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
* Independent full budgets per snapshot. When omitted each snapshot gets its own
|
|
559
|
-
* default budget — never share one counter across before/after walks.
|
|
560
|
-
*/
|
|
561
|
-
readonly beforeBudget?: NoteReferenceScanBudget;
|
|
562
|
-
readonly afterBudget?: NoteReferenceScanBudget;
|
|
389
|
+
type ImageIntentResult = (Extract<PackageTransactResult, {
|
|
390
|
+
ok: true;
|
|
391
|
+
}> & {
|
|
392
|
+
readonly drawingNodeId?: string;
|
|
393
|
+
readonly mediaPartName?: string;
|
|
394
|
+
}) | Extract<PackageTransactResult, {
|
|
395
|
+
ok: false;
|
|
396
|
+
}>;
|
|
397
|
+
interface ApplyImagePropertiesInput {
|
|
398
|
+
readonly drawingNodeId: string;
|
|
399
|
+
readonly ops: readonly DrawingTreeDocOp[];
|
|
400
|
+
readonly hyperlink: string | null;
|
|
563
401
|
}
|
|
564
|
-
/**
|
|
565
|
-
* Remove note bodies for references that disappeared between two package snapshots.
|
|
566
|
-
* Used when `deleteText` or `deleteBlock` removes a `noteReference` atom so body+ref stay
|
|
567
|
-
* one undo unit.
|
|
568
|
-
*
|
|
569
|
-
* Each snapshot gets an independent full visited/part budget. If either scan truncates
|
|
570
|
-
* the cascade fails closed so a hostile package cannot skip body deletion silently —
|
|
571
|
-
* without accidentally halving capacity by charging both walks to one counter.
|
|
572
|
-
*/
|
|
573
|
-
declare function cascadeDeletedNoteReferences(before: OoxmlPackage, after: OoxmlPackage, options?: CascadeDeletedNoteReferencesOptions): OoxmlPackage | null;
|
|
574
|
-
|
|
575
|
-
/**
|
|
576
|
-
* The identity of one continuous user gesture, for history grouping.
|
|
577
|
-
*
|
|
578
|
-
* A live color picker, a font-size stepper or a spacing slider applies every intermediate
|
|
579
|
-
* value so the document updates under the pointer, and each of those writes is a
|
|
580
|
-
* transaction in its own right — it must render, and a collaborator must receive it. What
|
|
581
|
-
* they are NOT is separate undo steps. The caller mints one token when the gesture starts
|
|
582
|
-
* (`Symbol('color-drag')`) and passes it with every write until the gesture ends.
|
|
583
|
-
*
|
|
584
|
-
* A symbol rather than a string, so two unrelated callers cannot collide by naming their
|
|
585
|
-
* gesture the same way, and so a token cannot outlive its gesture by accident through
|
|
586
|
-
* serialization.
|
|
587
|
-
*/
|
|
588
|
-
type HistoryGroup = symbol;
|
|
589
|
-
type HistoryCaptureKind = 'started' | 'extended' | 'split';
|
|
590
|
-
type HistoryCaptureReason = 'package-unit' | 'composition';
|
|
591
|
-
declare function observeHistoryGroup<T>(group: HistoryGroup, report: (kind: HistoryCaptureKind, reason?: HistoryCaptureReason) => void, run: () => T): T;
|
|
592
|
-
declare function reportHistoryGroup(group: HistoryGroup | undefined, kind: HistoryCaptureKind, reason?: HistoryCaptureReason): void;
|
|
593
402
|
|
|
594
403
|
/** How one transaction behaves: its story scope, its attribution, and its selection marks. */
|
|
595
404
|
interface TransactOptions {
|
|
@@ -646,6 +455,11 @@ interface TreeDocumentStoreOptions {
|
|
|
646
455
|
* document can gain or lose protection while its stories stay open.
|
|
647
456
|
*/
|
|
648
457
|
readonly settingsPart?: () => OoxmlPart | null | undefined;
|
|
458
|
+
/**
|
|
459
|
+
* Opt-in relaxation of `w:lock` for run-property writes. See {@link ContentLockPolicy};
|
|
460
|
+
* absent, `contentLocked` and `sdtContentLocked` refuse formatting like any other write.
|
|
461
|
+
*/
|
|
462
|
+
readonly contentLockPolicy?: ContentLockPolicy;
|
|
649
463
|
}
|
|
650
464
|
|
|
651
465
|
/** A selection the caller wants restored when an entry is undone or redone. */
|
|
@@ -746,6 +560,10 @@ interface TransactionContext {
|
|
|
746
560
|
* The edit is a pure function of the working package, so a rejected transaction discards it
|
|
747
561
|
* with everything else. Returning the SAME package is a no-op, not a failure — a primitive
|
|
748
562
|
* that finds nothing to do says so that way.
|
|
563
|
+
*
|
|
564
|
+
* Engine package edits refuse by throwing the internal `PackageEditRefusal`
|
|
565
|
+
* (`package-edit-refusal.ts`): the transaction is refused with its reason, `package-changed`
|
|
566
|
+
* by default, and nothing is applied. Any other throw escapes `transact` as a crash.
|
|
749
567
|
*/
|
|
750
568
|
applyPackage(edit: (pkg: OoxmlPackage) => OoxmlPackage): boolean;
|
|
751
569
|
/** The selection to restore when this entry is undone. */
|
|
@@ -809,10 +627,13 @@ declare class TreeDocumentStore {
|
|
|
809
627
|
private commitCounter;
|
|
810
628
|
private readonly undoStack;
|
|
811
629
|
private readonly redoStack;
|
|
630
|
+
private pushCount;
|
|
812
631
|
private readonly subscribers;
|
|
813
632
|
private readonly historyLimit;
|
|
814
633
|
/** See {@link TreeDocumentStoreOptions.settingsPart}. */
|
|
815
634
|
private readonly settingsPartOverride;
|
|
635
|
+
/** See {@link TreeDocumentStoreOptions.contentLockPolicy}. */
|
|
636
|
+
private readonly contentLockPolicy;
|
|
816
637
|
/** Package-aware story tag applied to publishes (including undo/redo). */
|
|
817
638
|
private storyRef;
|
|
818
639
|
/** Open composition, if any. While set, transactions extend one entry (task 5.5). */
|
|
@@ -838,6 +659,12 @@ declare class TreeDocumentStore {
|
|
|
838
659
|
get canRedo(): boolean;
|
|
839
660
|
/** Retained entries — the unit `undo()` reverses, so tests can assert grouping. */
|
|
840
661
|
get historyDepth(): number;
|
|
662
|
+
/**
|
|
663
|
+
* How many entries this store has ever pushed. Monotonic, unlike `historyDepth`, which
|
|
664
|
+
* stands still at the history limit because the oldest entry is shifted out.
|
|
665
|
+
* @internal
|
|
666
|
+
*/
|
|
667
|
+
get historyPushCount(): number;
|
|
841
668
|
get compositionActive(): boolean;
|
|
842
669
|
/**
|
|
843
670
|
* Replace the package OUTSIDE the transaction and history lanes.
|
|
@@ -909,73 +736,412 @@ declare class TreeDocumentStore {
|
|
|
909
736
|
selectionForUndo(): SelectionMark | null;
|
|
910
737
|
/** The selection to restore for the entry `redo()` would reapply next. */
|
|
911
738
|
selectionForRedo(): SelectionMark | null;
|
|
912
|
-
private pushUndo;
|
|
913
|
-
private publish;
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
/** Decoded fragment payloads above this cap are refused before any package work. */
|
|
917
|
-
declare const MAX_FRAGMENT_DECODED_BYTES: number;
|
|
918
|
-
interface FragmentPasteInput {
|
|
919
|
-
readonly paragraphId: string;
|
|
920
|
-
readonly offset: number;
|
|
921
|
-
/** The fragment package zip (from the clipboard codec or the HTML projection). */
|
|
922
|
-
readonly fragmentBytes: Uint8Array;
|
|
923
|
-
readonly lastMarkCovered: boolean;
|
|
924
|
-
/** Ops that clear the current selection first (the surface's deleteSelectionPlan). */
|
|
925
|
-
readonly priorOps?: readonly TreeDocOp[];
|
|
926
739
|
/**
|
|
927
|
-
*
|
|
928
|
-
*
|
|
929
|
-
*
|
|
930
|
-
* `wp:docPr/@id` — and the merge reads the actor off the open transaction. Without one, two
|
|
931
|
-
* replicas pasting the same fragment from one snapshot mint the same numbers, and only the
|
|
932
|
-
* merged document shows it. Omitted (solo) keeps Word's dense sequences.
|
|
740
|
+
* Remove the newest undo entry and answer its selections, for the package coordinator
|
|
741
|
+
* when a package history group absorbs the story pointer that entry belonged to.
|
|
742
|
+
* @internal
|
|
933
743
|
*/
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
ok: true;
|
|
938
|
-
}> & {
|
|
939
|
-
readonly blockCount: number;
|
|
940
|
-
}) | Extract<PackageTransactResult, {
|
|
941
|
-
ok: false;
|
|
942
|
-
}>;
|
|
943
|
-
/**
|
|
944
|
-
* Read the fragment through the bounded file-open trust boundary, merge its resources,
|
|
945
|
-
* and land its blocks — all inside one transaction. Any refusal leaves the document
|
|
946
|
-
* exactly as it was; the caller (the paste router) degrades to the next flavour.
|
|
947
|
-
*/
|
|
948
|
-
declare function applyFragmentPaste(store: TreePackageStore, scope: StoryScope, input: FragmentPasteInput): FragmentPasteResult;
|
|
949
|
-
|
|
950
|
-
/** Attribution stamped on one remote canonical publication. */
|
|
951
|
-
interface RemotePackageAttribution {
|
|
952
|
-
readonly origin: string;
|
|
953
|
-
readonly actorId?: string;
|
|
954
|
-
readonly operationId?: string;
|
|
744
|
+
discardNewestUndoEntry(): Pick<HistoryEntry, 'selectionBefore' | 'selectionAfter'> | null;
|
|
745
|
+
private pushUndo;
|
|
746
|
+
private publish;
|
|
955
747
|
}
|
|
956
748
|
|
|
957
|
-
type NoteCascadeFn = (before: OoxmlPackage, after: OoxmlPackage) => OoxmlPackage | null;
|
|
958
749
|
/**
|
|
959
|
-
*
|
|
750
|
+
* The identity of one continuous user gesture, for history grouping.
|
|
960
751
|
*
|
|
961
|
-
*
|
|
962
|
-
*
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
} | {
|
|
967
|
-
readonly kind: 'headerFooter';
|
|
968
|
-
readonly rId: string;
|
|
969
|
-
} | {
|
|
970
|
-
readonly kind: 'notesPart';
|
|
971
|
-
readonly noteKind: NoteKind;
|
|
972
|
-
};
|
|
973
|
-
/**
|
|
974
|
-
* Why a story scope could not be resolved to a part.
|
|
752
|
+
* A live color picker, a font-size stepper or a spacing slider applies every intermediate
|
|
753
|
+
* value so the document updates under the pointer, and each of those writes is a
|
|
754
|
+
* transaction in its own right — it must render, and a collaborator must receive it. What
|
|
755
|
+
* they are NOT is separate undo steps. The caller mints one token when the gesture starts
|
|
756
|
+
* (`Symbol('color-drag')`) and passes it with every write until the gesture ends.
|
|
975
757
|
*
|
|
976
|
-
*
|
|
977
|
-
*
|
|
978
|
-
*
|
|
758
|
+
* A symbol rather than a string, so two unrelated callers cannot collide by naming their
|
|
759
|
+
* gesture the same way, and so a token cannot outlive its gesture by accident through
|
|
760
|
+
* serialization.
|
|
761
|
+
*/
|
|
762
|
+
type HistoryGroup = symbol;
|
|
763
|
+
type HistoryCaptureKind = 'started' | 'extended' | 'split';
|
|
764
|
+
type HistoryCaptureReason = 'package-unit' | 'composition';
|
|
765
|
+
declare function observeHistoryGroup<T>(group: HistoryGroup, report: (kind: HistoryCaptureKind, reason?: HistoryCaptureReason) => void, run: () => T): T;
|
|
766
|
+
declare function reportHistoryGroup(group: HistoryGroup | undefined, kind: HistoryCaptureKind, reason?: HistoryCaptureReason): void;
|
|
767
|
+
|
|
768
|
+
/** UTF-16 placeholder for one atomic note unit in `paragraphTextOf` / segments. */
|
|
769
|
+
declare const NOTE_ATOM_CHAR = "\uFFFC";
|
|
770
|
+
/** Signed 32-bit Word-compatible note id range (positive allocation only). */
|
|
771
|
+
declare const NOTE_ID_MIN = 1;
|
|
772
|
+
/** Largest note id Word accepts — signed 32-bit. */
|
|
773
|
+
declare const NOTE_ID_MAX = 2147483647;
|
|
774
|
+
/** Reserved separator / continuation ids — never allocated for normal notes. */
|
|
775
|
+
declare const NOTE_SEPARATOR_ID = -1;
|
|
776
|
+
/** Reserved id of the continuation-separator entry. Never allocated to a real note. */
|
|
777
|
+
declare const NOTE_CONTINUATION_SEPARATOR_ID = 0;
|
|
778
|
+
/** Which notes part a note lives in. Decides both placement and numbering rules. */
|
|
779
|
+
type NoteKind = 'footnote' | 'endnote';
|
|
780
|
+
/** Authored `ST_FtnEdn` including explicit `normal`. Absent means Word default (normal). */
|
|
781
|
+
/**
|
|
782
|
+
* What a note entry IS.
|
|
783
|
+
*
|
|
784
|
+
* Only `normal` is a note a reader sees. The others are the furniture Word stores in the same
|
|
785
|
+
* part — the rules and notices drawn around the note area — reached by reserved ids.
|
|
786
|
+
*/
|
|
787
|
+
type NoteType = 'normal' | 'separator' | 'continuationSeparator' | 'continuationNotice';
|
|
788
|
+
/** Parse a signed decimal note id; reject non-integers and out-of-int32 values. */
|
|
789
|
+
declare function parseNoteId(raw: string | undefined): number | null;
|
|
790
|
+
/**
|
|
791
|
+
* Canonical `EditorScope { kind: 'note'; id }` encoding.
|
|
792
|
+
*
|
|
793
|
+
* Footnote id `1` and endnote id `1` coexist, so the kind is part of the string:
|
|
794
|
+
* `footnote:2` / `endnote:-1`. Do not invent a parallel scope union arm.
|
|
795
|
+
*/
|
|
796
|
+
declare function formatNoteScopeId(noteKind: NoteKind, noteId: number): string;
|
|
797
|
+
/**
|
|
798
|
+
* Parse {@link formatNoteScopeId}. Returns `null` for malformed / out-of-range ids.
|
|
799
|
+
*/
|
|
800
|
+
declare function parseNoteScopeId(id: string): {
|
|
801
|
+
readonly noteKind: NoteKind;
|
|
802
|
+
readonly noteId: number;
|
|
803
|
+
} | null;
|
|
804
|
+
/** Whether a node is a `w:footnotes` part root. */
|
|
805
|
+
declare function isFootnotesNode(node: OoxmlNode): node is OoxmlFootnotesNode;
|
|
806
|
+
/** Whether a node is a `w:endnotes` part root. */
|
|
807
|
+
declare function isEndnotesNode(node: OoxmlNode): node is OoxmlEndnotesNode;
|
|
808
|
+
/** Whether a node is a `w:footnote` or `w:endnote` body. */
|
|
809
|
+
declare function isNoteNode(node: OoxmlNode): node is OoxmlNoteNode;
|
|
810
|
+
/** Whether a node is a body-side `w:footnoteReference` / `w:endnoteReference`. */
|
|
811
|
+
declare function isNoteReferenceNode(node: OoxmlNode): node is OoxmlNoteReferenceNode;
|
|
812
|
+
/** Whether a node is the `w:footnoteRef` / `w:endnoteRef` mark inside a note's own body. */
|
|
813
|
+
declare function isNoteRefNode(node: OoxmlNode): node is OoxmlNoteRefNode;
|
|
814
|
+
/** Whether a node is the `w:separator` rule drawn above the note area. */
|
|
815
|
+
declare function isSeparatorNode(node: OoxmlNode): node is OoxmlSeparatorNode;
|
|
816
|
+
/** Whether a node is the `w:continuationSeparator` rule used on continuation pages. */
|
|
817
|
+
declare function isContinuationSeparatorNode(node: OoxmlNode): node is OoxmlContinuationSeparatorNode;
|
|
818
|
+
/** Typed or generic `w:footnote` / `w:endnote`. */
|
|
819
|
+
declare function noteKindOf(node: OoxmlNode): NoteKind | null;
|
|
820
|
+
/** Authored `@w:id` on a note or noteReference when parseable. */
|
|
821
|
+
declare function noteIdOf(node: OoxmlNode): number | null;
|
|
822
|
+
/** Authored `@w:type` (`ST_FtnEdn`) when present and schema-legal; else `undefined`. */
|
|
823
|
+
declare function noteTypeOf(node: OoxmlNode): NoteType | undefined;
|
|
824
|
+
/** Whether a note is a normal (body) note — absent type and explicit `normal` both count. */
|
|
825
|
+
declare function isNormalNote(node: OoxmlNode): boolean;
|
|
826
|
+
/** Typed or generic footnote/endnote reference kind. */
|
|
827
|
+
declare function noteReferenceKindOf(node: OoxmlNode): NoteKind | null;
|
|
828
|
+
/** Typed or generic `w:footnoteRef` / `w:endnoteRef`. */
|
|
829
|
+
declare function noteRefKindOf(node: OoxmlNode): NoteKind | null;
|
|
830
|
+
/**
|
|
831
|
+
* Read `@w:customMarkFollows` on a note reference.
|
|
832
|
+
* Returns `undefined` when absent; otherwise the OOXML on/off interpretation.
|
|
833
|
+
*/
|
|
834
|
+
declare function customMarkFollows(node: OoxmlNode): boolean | undefined;
|
|
835
|
+
/** Model text contributed by one atomic note unit. */
|
|
836
|
+
declare function noteAtomText(): typeof NOTE_ATOM_CHAR;
|
|
837
|
+
/**
|
|
838
|
+
* True when a run-inner node is a typed note atom that contributes one UTF-16 unit.
|
|
839
|
+
* Demoted/malformed known locals stay generic and contribute nothing.
|
|
840
|
+
*/
|
|
841
|
+
declare function isNoteAtomNode(node: OoxmlNode): boolean;
|
|
842
|
+
/**
|
|
843
|
+
* One atomic note span inside a paragraph for caret / delete / selection.
|
|
844
|
+
*
|
|
845
|
+
* Each typed note atom is a single-node span (`removeNodeIds` = that node).
|
|
846
|
+
*/
|
|
847
|
+
interface AtomicNoteSpan {
|
|
848
|
+
readonly kind: 'noteReference' | 'noteRef' | 'separator' | 'continuationSeparator';
|
|
849
|
+
readonly node: OoxmlNode;
|
|
850
|
+
readonly runId: string;
|
|
851
|
+
readonly removeNodeIds: readonly string[];
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Collect typed note atoms in document order (one segment each).
|
|
855
|
+
*
|
|
856
|
+
* Walks the same paragraph-inline surface as `segmentsOf` / `walkParagraphInline`:
|
|
857
|
+
* hyperlinks and content controls flatten; only direct run children contribute atoms.
|
|
858
|
+
* A demoted run-inner SDT husk stays opaque — no phantom addressable hit.
|
|
859
|
+
*/
|
|
860
|
+
declare function atomicNoteSpansOf(paragraph: OoxmlParagraphNode): readonly AtomicNoteSpan[];
|
|
861
|
+
/** Cap on notes scanned when allocating / indexing a notes part. */
|
|
862
|
+
declare const MAX_NOTES_PER_PART = 10000;
|
|
863
|
+
/**
|
|
864
|
+
* Allocate the next positive signed 32-bit note id for a notes-part root.
|
|
865
|
+
*
|
|
866
|
+
* Solo: `max(existing)+1`, the dense sequence Word writes. `null` on exhaustion, so the
|
|
867
|
+
* caller refuses rather than wrapping onto an id a note already holds.
|
|
868
|
+
*
|
|
869
|
+
* With a collaboration actor bound — explicit argument, or the open store transaction — the
|
|
870
|
+
* id is the next unused value in that actor's stripe. Two peers each adding their first
|
|
871
|
+
* footnote from one snapshot otherwise both mint `w:id="1"`: the merge keeps both bodies
|
|
872
|
+
* under one id, both `w:footnoteReference` marks resolve to the first, and one author's note
|
|
873
|
+
* becomes unreachable.
|
|
874
|
+
*
|
|
875
|
+
* The reserved ids stay reserved either way. `0` (continuation separator) is seeded as used,
|
|
876
|
+
* so a residue of 0 advances one class instead of taking Word's furniture, and a stripe walk
|
|
877
|
+
* only ever climbs from a non-negative residue, so `-1` (separator) is unreachable.
|
|
878
|
+
*/
|
|
879
|
+
declare function allocateNoteId(notesRoot: OoxmlNode, actorId?: string): number | null;
|
|
880
|
+
/** Collect note bodies from a footnotes/endnotes root, bounded. */
|
|
881
|
+
declare function notesOf(root: OoxmlNode): readonly OoxmlNoteNode[];
|
|
882
|
+
/** Find a typed note by id inside a notes-part root. */
|
|
883
|
+
declare function findNoteById(root: OoxmlNode, noteId: number): OoxmlNoteNode | undefined;
|
|
884
|
+
|
|
885
|
+
/** Cap on nodes visited while scanning for note references across stories. */
|
|
886
|
+
declare const MAX_NOTE_REFERENCE_SCAN = 20000;
|
|
887
|
+
/**
|
|
888
|
+
* Cap on XML parts walked in one package-wide note-reference scan (N/N+1 gate).
|
|
889
|
+
* Soft targets are not allowed: exceeding this marks the shared budget truncated.
|
|
890
|
+
*/
|
|
891
|
+
declare const MAX_NOTE_REFERENCE_PARTS = 256;
|
|
892
|
+
/**
|
|
893
|
+
* A load-time note problem worth reporting.
|
|
894
|
+
*
|
|
895
|
+
* `dangling-note-reference` is a citation pointing at no note; `note-reference-scan-truncated`
|
|
896
|
+
* says the scan hit its budget, so absence of further diagnostics is not proof of correctness.
|
|
897
|
+
*/
|
|
898
|
+
type NoteDiagnosticCode = 'dangling-note-reference' | 'note-reference-scan-truncated';
|
|
899
|
+
/**
|
|
900
|
+
* Load-time note diagnostics. Array API preserved; truncation is signaled as a typed
|
|
901
|
+
* entry rather than by throwing or rejecting the package.
|
|
902
|
+
*/
|
|
903
|
+
type NoteDiagnostic = {
|
|
904
|
+
readonly code: 'dangling-note-reference';
|
|
905
|
+
readonly noteKind: NoteKind;
|
|
906
|
+
readonly noteId: number;
|
|
907
|
+
/** Paragraph / container node id when known. */
|
|
908
|
+
readonly sourceNodeId?: string;
|
|
909
|
+
} | {
|
|
910
|
+
/** Hard visited/part budget or soft hit cap stopped the scan before full coverage. */
|
|
911
|
+
readonly code: 'note-reference-scan-truncated';
|
|
912
|
+
};
|
|
913
|
+
/** One note reference found in a story, with where it sits. */
|
|
914
|
+
interface NoteReferenceHit {
|
|
915
|
+
readonly noteKind: NoteKind;
|
|
916
|
+
readonly noteId: number;
|
|
917
|
+
readonly nodeId: string;
|
|
918
|
+
readonly paragraphId: string;
|
|
919
|
+
/** Canonical UTF-16 atom offset within {@link paragraphId} (U+FFFC model). */
|
|
920
|
+
readonly atomOffset: number;
|
|
921
|
+
readonly customMarkFollows: boolean;
|
|
922
|
+
/** Canonical part name that owns this reference. */
|
|
923
|
+
readonly partName: string;
|
|
924
|
+
}
|
|
925
|
+
/** Mutable visited-node + part budget shared across parts / package snapshots. */
|
|
926
|
+
interface NoteReferenceScanBudget {
|
|
927
|
+
visited: number;
|
|
928
|
+
readonly maxVisited: number;
|
|
929
|
+
parts: number;
|
|
930
|
+
readonly maxParts: number;
|
|
931
|
+
/** Set when a walk stops before finishing because a cap was hit. */
|
|
932
|
+
truncated: boolean;
|
|
933
|
+
}
|
|
934
|
+
/** A bounded budget for scanning note references, so a crafted document cannot stall a load. */
|
|
935
|
+
declare function createNoteReferenceScanBudget(maxVisited?: number, maxParts?: number): NoteReferenceScanBudget;
|
|
936
|
+
/**
|
|
937
|
+
* Resolve the footnotes or endnotes part via safe Internal document relationships.
|
|
938
|
+
*
|
|
939
|
+
* Unusable matching relationships (External, unsafe target, missing part, wrong root)
|
|
940
|
+
* are skipped — never fetched, never accepted — so a decoy first match cannot hide a
|
|
941
|
+
* later usable Internal notes part (same continue-past-bad pattern as settingsPartOf).
|
|
942
|
+
*/
|
|
943
|
+
declare function resolveNotesPart(pkg: OoxmlPackage, noteKind: NoteKind): OoxmlPart | null;
|
|
944
|
+
/** Walk a part without applying a layout projection. */
|
|
945
|
+
declare function collectNoteReferences(part: OoxmlPart, options?: {
|
|
946
|
+
readonly maxHits?: number;
|
|
947
|
+
readonly budget?: NoteReferenceScanBudget;
|
|
948
|
+
}): readonly NoteReferenceHit[];
|
|
949
|
+
/** Collect references across every XML part under one shared part + visited-node budget. */
|
|
950
|
+
declare function collectPackageNoteReferences(pkg: OoxmlPackage, options?: {
|
|
951
|
+
readonly budget?: NoteReferenceScanBudget;
|
|
952
|
+
/** Soft hit cap for diagnostics. Omit / Infinity for mutation scans. */
|
|
953
|
+
readonly maxHits?: number;
|
|
954
|
+
}): readonly NoteReferenceHit[];
|
|
955
|
+
/**
|
|
956
|
+
* Load diagnostics for dangling note references. Fail-open: never throws or mutates;
|
|
957
|
+
* returns diagnostics for callers to surface. Does not invent missing note bodies.
|
|
958
|
+
*
|
|
959
|
+
* When the hard visited/part budget truncates or the soft hit cap binds, appends a single
|
|
960
|
+
* `note-reference-scan-truncated` entry so incomplete coverage is visible without breaking
|
|
961
|
+
* consumers that filter on `dangling-note-reference`.
|
|
962
|
+
*/
|
|
963
|
+
declare function diagnoseNoteReferences(pkg: OoxmlPackage): readonly NoteDiagnostic[];
|
|
964
|
+
/** Whether a notes-part root contains a note with the given id (any type). */
|
|
965
|
+
declare function notesPartHasId(part: OoxmlPart, noteId: number): boolean;
|
|
966
|
+
/** List normal (body) note ids in document order, bounded. */
|
|
967
|
+
declare function normalNoteIds(part: OoxmlPart): readonly number[];
|
|
968
|
+
|
|
969
|
+
/** How far a note lifecycle op reaches — which parts a caller must expect to have changed. */
|
|
970
|
+
type NoteLifecycleImpact = 'flow-structural' | 'global';
|
|
971
|
+
/**
|
|
972
|
+
* A note lifecycle mutation: insert, delete, convert, or set properties.
|
|
973
|
+
*
|
|
974
|
+
* Package-level rather than story-level, because every one of these touches the main document,
|
|
975
|
+
* the notes part, the document relationships AND `[Content_Types].xml` together.
|
|
976
|
+
*/
|
|
977
|
+
type NoteLifecycleOp = {
|
|
978
|
+
readonly op: 'insertNote';
|
|
979
|
+
readonly noteKind: NoteKind;
|
|
980
|
+
readonly paragraphId: string;
|
|
981
|
+
readonly offset: number;
|
|
982
|
+
/**
|
|
983
|
+
* Write the citing reference as a TRACKED insertion: the reference run goes inside a
|
|
984
|
+
* `w:ins` carrying this attribution. The note body stays plain — rejecting the
|
|
985
|
+
* reference removes it, and the orphaned body is swept by the same cascade an
|
|
986
|
+
* untracked reference deletion triggers.
|
|
987
|
+
*/
|
|
988
|
+
readonly revision?: RevisionAttributionInput;
|
|
989
|
+
} | {
|
|
990
|
+
readonly op: 'deleteNote';
|
|
991
|
+
readonly noteKind: NoteKind;
|
|
992
|
+
readonly noteId: number;
|
|
993
|
+
} | {
|
|
994
|
+
readonly op: 'convertNote';
|
|
995
|
+
readonly fromKind: NoteKind;
|
|
996
|
+
readonly noteId: number;
|
|
997
|
+
} | {
|
|
998
|
+
/**
|
|
999
|
+
* Convert every normal note of `fromKind` in document order. One atomic package
|
|
1000
|
+
* transaction / undo unit with the same validation as repeated `convertNote`.
|
|
1001
|
+
*/
|
|
1002
|
+
readonly op: 'convertAllNotes';
|
|
1003
|
+
readonly fromKind: NoteKind;
|
|
1004
|
+
} | {
|
|
1005
|
+
readonly op: 'setNoteProperties';
|
|
1006
|
+
readonly scope: 'document' | 'section';
|
|
1007
|
+
readonly sectionIndex?: number;
|
|
1008
|
+
readonly footnote?: {
|
|
1009
|
+
readonly numFmt?: string;
|
|
1010
|
+
readonly numRestart?: string;
|
|
1011
|
+
readonly position?: string;
|
|
1012
|
+
readonly numStart?: number;
|
|
1013
|
+
};
|
|
1014
|
+
readonly endnote?: {
|
|
1015
|
+
readonly numFmt?: string;
|
|
1016
|
+
readonly numRestart?: string;
|
|
1017
|
+
readonly position?: string;
|
|
1018
|
+
readonly numStart?: number;
|
|
1019
|
+
};
|
|
1020
|
+
};
|
|
1021
|
+
/** Why a note lifecycle op was refused. */
|
|
1022
|
+
type NoteLifecycleRejection = 'invalidArgs' | 'invalid-property-value' | 'tree-invariant';
|
|
1023
|
+
/**
|
|
1024
|
+
* A new package, or a typed rejection.
|
|
1025
|
+
*
|
|
1026
|
+
* Application is PURE and all-or-nothing: there are no partial writes, so a refused op leaves the
|
|
1027
|
+
* caller's package untouched rather than half-migrated across four parts.
|
|
1028
|
+
*/
|
|
1029
|
+
type NoteLifecycleResult = {
|
|
1030
|
+
readonly ok: true;
|
|
1031
|
+
readonly package: OoxmlPackage;
|
|
1032
|
+
readonly impact: NoteLifecycleImpact;
|
|
1033
|
+
readonly noteId?: number;
|
|
1034
|
+
readonly noteKind?: NoteKind;
|
|
1035
|
+
readonly createdPartName?: string;
|
|
1036
|
+
} | {
|
|
1037
|
+
readonly ok: false;
|
|
1038
|
+
readonly reason: NoteLifecycleRejection;
|
|
1039
|
+
readonly detail?: string;
|
|
1040
|
+
};
|
|
1041
|
+
/** Whether an op is a note lifecycle op rather than a story-level one. */
|
|
1042
|
+
declare function isNoteLifecycleOp(op: {
|
|
1043
|
+
readonly op: string;
|
|
1044
|
+
}): op is NoteLifecycleOp;
|
|
1045
|
+
/** Attribution and limits applied to one note lifecycle op. */
|
|
1046
|
+
interface NoteLifecycleOptions {
|
|
1047
|
+
/**
|
|
1048
|
+
* Shared part + visited-node budget for reference scans. When omitted a fresh default
|
|
1049
|
+
* budget is used. Truncation rejects the op with the original package unchanged.
|
|
1050
|
+
*/
|
|
1051
|
+
readonly scanBudget?: NoteReferenceScanBudget;
|
|
1052
|
+
}
|
|
1053
|
+
/**
|
|
1054
|
+
* Apply one note lifecycle op atomically. Rejected ops leave the input package untouched.
|
|
1055
|
+
*/
|
|
1056
|
+
declare function applyNoteLifecycleOp(pkg: OoxmlPackage, op: NoteLifecycleOp, options?: NoteLifecycleOptions): NoteLifecycleResult;
|
|
1057
|
+
/**
|
|
1058
|
+
* How deleting text cascades into the notes it referenced.
|
|
1059
|
+
*
|
|
1060
|
+
* A note's body and the citation reaching it are one thing to a reader, so removing the reference
|
|
1061
|
+
* must remove the body too or the notes part keeps an entry nothing points at.
|
|
1062
|
+
*/
|
|
1063
|
+
interface CascadeDeletedNoteReferencesOptions {
|
|
1064
|
+
/**
|
|
1065
|
+
* Independent full budgets per snapshot. When omitted each snapshot gets its own
|
|
1066
|
+
* default budget — never share one counter across before/after walks.
|
|
1067
|
+
*/
|
|
1068
|
+
readonly beforeBudget?: NoteReferenceScanBudget;
|
|
1069
|
+
readonly afterBudget?: NoteReferenceScanBudget;
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Remove note bodies for references that disappeared between two package snapshots.
|
|
1073
|
+
* Used when `deleteText` or `deleteBlock` removes a `noteReference` atom so body+ref stay
|
|
1074
|
+
* one undo unit.
|
|
1075
|
+
*
|
|
1076
|
+
* Each snapshot gets an independent full visited/part budget. If either scan truncates
|
|
1077
|
+
* the cascade fails closed so a hostile package cannot skip body deletion silently —
|
|
1078
|
+
* without accidentally halving capacity by charging both walks to one counter.
|
|
1079
|
+
*/
|
|
1080
|
+
declare function cascadeDeletedNoteReferences(before: OoxmlPackage, after: OoxmlPackage, options?: CascadeDeletedNoteReferencesOptions): OoxmlPackage | null;
|
|
1081
|
+
|
|
1082
|
+
/** Decoded fragment payloads above this cap are refused before any package work. */
|
|
1083
|
+
declare const MAX_FRAGMENT_DECODED_BYTES: number;
|
|
1084
|
+
interface FragmentPasteInput {
|
|
1085
|
+
readonly paragraphId: string;
|
|
1086
|
+
readonly offset: number;
|
|
1087
|
+
/** The fragment package zip (from the clipboard codec or the HTML projection). */
|
|
1088
|
+
readonly fragmentBytes: Uint8Array;
|
|
1089
|
+
readonly lastMarkCovered: boolean;
|
|
1090
|
+
/** Ops that clear the current selection first (the surface's deleteSelectionPlan). */
|
|
1091
|
+
readonly priorOps?: readonly TreeDocOp[];
|
|
1092
|
+
/**
|
|
1093
|
+
* Collaboration actor for the ids this paste mints.
|
|
1094
|
+
*
|
|
1095
|
+
* A paste freshens three package-wide namespaces — bookmark `@w:id`, revision `@w:id` and
|
|
1096
|
+
* `wp:docPr/@id` — and the merge reads the actor off the open transaction. Without one, two
|
|
1097
|
+
* replicas pasting the same fragment from one snapshot mint the same numbers, and only the
|
|
1098
|
+
* merged document shows it. Omitted (solo) keeps Word's dense sequences.
|
|
1099
|
+
*/
|
|
1100
|
+
readonly actorId?: string;
|
|
1101
|
+
}
|
|
1102
|
+
type FragmentPasteResult = (Extract<PackageTransactResult, {
|
|
1103
|
+
ok: true;
|
|
1104
|
+
}> & {
|
|
1105
|
+
readonly blockCount: number;
|
|
1106
|
+
}) | Extract<PackageTransactResult, {
|
|
1107
|
+
ok: false;
|
|
1108
|
+
}>;
|
|
1109
|
+
/**
|
|
1110
|
+
* Read the fragment through the bounded file-open trust boundary, merge its resources,
|
|
1111
|
+
* and land its blocks — all inside one transaction. Any refusal leaves the document
|
|
1112
|
+
* exactly as it was; the caller (the paste router) degrades to the next flavour.
|
|
1113
|
+
*/
|
|
1114
|
+
declare function applyFragmentPaste(store: TreePackageStore, scope: StoryScope, input: FragmentPasteInput): FragmentPasteResult;
|
|
1115
|
+
|
|
1116
|
+
/** Attribution stamped on one remote canonical publication. */
|
|
1117
|
+
interface RemotePackageAttribution {
|
|
1118
|
+
readonly origin: string;
|
|
1119
|
+
readonly actorId?: string;
|
|
1120
|
+
readonly operationId?: string;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
type NoteCascadeFn = (before: OoxmlPackage, after: OoxmlPackage) => OoxmlPackage | null;
|
|
1124
|
+
/**
|
|
1125
|
+
* Editable story target.
|
|
1126
|
+
*
|
|
1127
|
+
* Body and headerFooter mirror `EditorScope`. Notes use one lazy store per notes part
|
|
1128
|
+
* (`notesPart`) — not one store per note — resolved through safe document relationships.
|
|
1129
|
+
*/
|
|
1130
|
+
type StoryScope = {
|
|
1131
|
+
readonly kind: 'body';
|
|
1132
|
+
} | {
|
|
1133
|
+
readonly kind: 'headerFooter';
|
|
1134
|
+
readonly rId: string;
|
|
1135
|
+
} | {
|
|
1136
|
+
readonly kind: 'notesPart';
|
|
1137
|
+
readonly noteKind: NoteKind;
|
|
1138
|
+
};
|
|
1139
|
+
/**
|
|
1140
|
+
* Why a story scope could not be resolved to a part.
|
|
1141
|
+
*
|
|
1142
|
+
* Several of these are FILE-hostile shapes rather than caller mistakes:
|
|
1143
|
+
* `external-relationship` and `bad-relationship-target` are how a crafted document tries to
|
|
1144
|
+
* point a story at something outside the package, and both are refused rather than followed.
|
|
979
1145
|
*/
|
|
980
1146
|
type StoryTargetRejection = 'unknown-scope' | 'dangling-relationship' | 'wrong-relationship-type' | 'external-relationship' | 'bad-relationship-target' | 'missing-part' | 'not-a-story-part' | 'too-many-story-stores';
|
|
981
1147
|
/** A story scope resolved to a part, or the typed reason it could not be. */
|
|
@@ -1002,6 +1168,8 @@ declare const DEFAULT_MAX_EDITABLE_STORY_PARTS = 64;
|
|
|
1002
1168
|
/** How a package store is constructed: limits, history depth, and review contributions. */
|
|
1003
1169
|
interface TreePackageStoreOptions {
|
|
1004
1170
|
readonly historyLimit?: number;
|
|
1171
|
+
/** Opt-in relaxation of `w:lock` for run-property writes, for the body and every story store. */
|
|
1172
|
+
readonly contentLockPolicy?: ContentLockPolicy;
|
|
1005
1173
|
/** Bound on opened story stores; defaults to {@link DEFAULT_MAX_EDITABLE_STORY_PARTS}. */
|
|
1006
1174
|
readonly maxEditableStoryParts?: number;
|
|
1007
1175
|
/**
|
|
@@ -1025,8 +1193,10 @@ declare class TreePackageStore {
|
|
|
1025
1193
|
private readonly rIdToPartName;
|
|
1026
1194
|
private readonly undoOrder;
|
|
1027
1195
|
private readonly redoOrder;
|
|
1196
|
+
private readonly historyGroups;
|
|
1028
1197
|
private readonly subscribers;
|
|
1029
1198
|
private readonly historyLimit;
|
|
1199
|
+
private readonly contentLockPolicy;
|
|
1030
1200
|
private readonly maxEditableStoryParts;
|
|
1031
1201
|
private readonly cascadeNoteReferences;
|
|
1032
1202
|
private lastChange;
|
|
@@ -1051,6 +1221,14 @@ declare class TreePackageStore {
|
|
|
1051
1221
|
* a matching tuple proves the snapshot cannot differ; nothing invalidates explicitly.
|
|
1052
1222
|
*/
|
|
1053
1223
|
private currentPackageMemo;
|
|
1224
|
+
/**
|
|
1225
|
+
* What the body and every story store open with. `settingsPart` is the SAME live getter for
|
|
1226
|
+
* all of them: a story store is built from a PART, whose synthetic package holds no
|
|
1227
|
+
* `settings.xml`, and a store keeps its own working copy, so a replaced `settings.xml` left one
|
|
1228
|
+
* story reading stale protection. Protection that holds in a header but not the body is worse
|
|
1229
|
+
* than none: it looks enforced. The lock policy reaches every story for the same reason.
|
|
1230
|
+
*/
|
|
1231
|
+
private storyStoreOptions;
|
|
1054
1232
|
constructor(pkg: OoxmlPackage, main: OoxmlPart, options?: TreePackageStoreOptions);
|
|
1055
1233
|
get packageRevision(): number;
|
|
1056
1234
|
get canUndo(): boolean;
|
|
@@ -1100,6 +1278,8 @@ declare class TreePackageStore {
|
|
|
1100
1278
|
*/
|
|
1101
1279
|
applyLifecycleOp(op: HeaderFooterLifecycleOp | NoteLifecycleOp | TreeDocOp, options?: {
|
|
1102
1280
|
readonly actorId?: string;
|
|
1281
|
+
/** @internal */
|
|
1282
|
+
readonly historyGroup?: HistoryGroup;
|
|
1103
1283
|
}): PackageTransactResult;
|
|
1104
1284
|
private commitLifecycleOp;
|
|
1105
1285
|
undo(): TreeModelChange | null;
|
|
@@ -1170,6 +1350,8 @@ declare class TreePackageStore {
|
|
|
1170
1350
|
* started from to this instead, the same promotion the note cascade does.
|
|
1171
1351
|
*/
|
|
1172
1352
|
adoptPackageUnit(before: OoxmlPackage): void;
|
|
1353
|
+
/** {@link adoptPackageUnit} as a frame of a history group. @internal */
|
|
1354
|
+
adoptGroupedPackageUnit(before: OoxmlPackage, historyGroup: HistoryGroup | undefined): void;
|
|
1173
1355
|
/** Install a full package snapshot (public seam for post-fetch cleanup). */
|
|
1174
1356
|
installPackageSnapshot(snapshot: OoxmlPackage): void;
|
|
1175
1357
|
/**
|
|
@@ -1190,6 +1372,8 @@ declare class TreePackageStore {
|
|
|
1190
1372
|
private openHeaderFooterStore;
|
|
1191
1373
|
private storyRefForPart;
|
|
1192
1374
|
private syncPackageFromStore;
|
|
1375
|
+
/** Close every open history group: the story stores' and the coordinator's. */
|
|
1376
|
+
private closeHistoryGroups;
|
|
1193
1377
|
private pushUndoPointer;
|
|
1194
1378
|
/** Keep history-reachable stories and prune unreachable shell hyperlink owners. */
|
|
1195
1379
|
private evictUnreachableStories;
|
|
@@ -1197,5 +1381,5 @@ declare class TreePackageStore {
|
|
|
1197
1381
|
private publishSynthetic;
|
|
1198
1382
|
}
|
|
1199
1383
|
|
|
1200
|
-
export {
|
|
1201
|
-
export type {
|
|
1384
|
+
export { NOTE_CONTINUATION_SEPARATOR_ID as B, DEFAULT_MAX_EDITABLE_STORY_PARTS as D, NOTE_ID_MAX as G, NOTE_ID_MIN as J, NOTE_SEPARATOR_ID as K, MAX_FRAGMENT_DECODED_BYTES as M, TreePackageStore as T, allocateDrawingPropertyId as a8, allocateNoteId as a9, isNoteNode as aA, isNoteRefNode as aB, isNoteReferenceNode as aC, isSeparatorNode as aD, normalNoteIds as aE, noteAtomText as aF, noteIdOf as aG, noteKindOf as aH, noteRefKindOf as aI, noteReferenceKindOf as aJ, noteTypeOf as aK, notesOf as aL, notesPartHasId as aM, observeHistoryGroup as aN, parentNodeOf as aO, parseNoteId as aP, parseNoteScopeId as aQ, removeNode as aR, replaceChildren as aS, replaceNode as aT, resolveHeaderFooterParts as aU, resolveHeaderFooterPartsBySection as aV, resolveHeaderFooterResolutionBySection as aW, resolveNotesPart as aX, withBinaryPart as aY, withEmbeddedImage as aZ, withoutUnreferencedImagePart as a_, applyEdits as aa, applyFragmentPaste as ab, applyHeaderFooterLifecycleOp as ac, applyNoteLifecycleOp as ad, atomicNoteSpansOf as ae, cascadeDeletedNoteReferences as af, collectNodeIds as ag, collectNoteReferences as ah, collectPackageNoteReferences as ai, collectSectionPropertyNodes as aj, createNodeIdAllocator as ak, createNoteReferenceScanBudget as al, customMarkFollows as am, diagnoseNoteReferences as an, findNode as ao, findNoteById as ap, formatNoteScopeId as aq, hasNode as ar, insertChildren as as, isContinuationSeparatorNode as at, isEndnotesNode as au, isFootnotesNode as av, isHeaderFooterLifecycleOp as aw, isNormalNote as ax, isNoteAtomNode as ay, isNoteLifecycleOp as az, TreeDocumentStore as f, reportHistoryGroup as r, MAX_NOTES_PER_PART as w, MAX_NOTE_REFERENCE_PARTS as x, MAX_NOTE_REFERENCE_SCAN as y, NOTE_ATOM_CHAR as z };
|
|
1385
|
+
export type { PackageTransactResult as $, ApplyImagePropertiesInput as A, ContentLockPolicy as C, EditOptions as E, FieldResultsMode as F, HeaderFooterParts as H, InsertImageInput as I, NoteDiagnostic as L, NoteKind as N, NoteDiagnosticCode as O, NoteLifecycleImpact as P, NoteLifecycleOp as Q, ReplaceImageOptions as R, StoryScope as S, NoteLifecycleOptions as U, NoteLifecycleRejection as V, NoteLifecycleResult as W, NoteReferenceHit as X, NoteReferenceScanBudget as Y, NoteType as Z, OoxmlEditResult as _, HeaderFooterSectionResolution as a, RemotePackageAttribution as a0, StoryResolveResult as a1, TransactionRevisionIds as a2, TreeDocumentStoreOptions as a3, TreePackageStoreOptions as a4, TreeStoryRef as a5, TransactResult as a6, TransactionContext as a7, StoryTargetRejection as b, HeaderFooterVariant as c, HistoryGroup as d, TreeModelChange as e, SelectionMark as g, TransactOptions as h, ImageIntentResult as i, FragmentPasteInput as j, FragmentPasteResult as k, AtomicNoteSpan as l, CascadeDeletedNoteReferencesOptions as m, DrawingPropertyIdResult as n, HeaderFooterKind as o, HeaderFooterLifecycleImpact as p, HeaderFooterLifecycleOp as q, HeaderFooterLifecycleRejection as s, HeaderFooterLifecycleResult as t, HeaderFooterSlotMeta as u, HistoryCaptureKind as v };
|