@docx-editor.dev/editor-api 2.17.0 → 2.19.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.
@@ -1,12 +1,178 @@
1
+ import { AutomationHandle, AutomationSpan, AutomationOperation, AutomationValue, AutomationSpanRef, AutomationHost, AutomationCapabilities, AutomationPaginationOptions } from '@docx-editor.dev/core/automation';
1
2
  import { CollaborationModuleContribution } from '@docx-editor.dev/core/collaboration';
2
- import { AutomationOperation, AutomationValue, AutomationHandle, AutomationHost, AutomationCapabilities, AutomationSpan } from '@docx-editor.dev/core/automation';
3
+
4
+ /** Locations used by Office-shaped insertion calls. Each call validates its allowed subset. @public */
5
+ declare enum InsertLocation {
6
+ replace = "Replace",
7
+ start = "Start",
8
+ end = "End",
9
+ before = "Before",
10
+ after = "After"
11
+ }
12
+ /** Paragraph alignment vocabulary. Mixed and unknown are read states, not authoring modes. @public */
13
+ declare enum Alignment {
14
+ mixed = "Mixed",
15
+ unknown = "Unknown",
16
+ left = "Left",
17
+ centered = "Centered",
18
+ right = "Right",
19
+ justified = "Justified"
20
+ }
21
+ /** Physical page orientation. @public */
22
+ declare enum PageOrientation {
23
+ portrait = "Portrait",
24
+ landscape = "Landscape"
25
+ }
26
+ /** Tracking policy vocabulary. Unsupported policies fail explicitly at sync. @public */
27
+ declare enum ChangeTrackingMode {
28
+ off = "Off",
29
+ trackAll = "TrackAll",
30
+ trackMineOnly = "TrackMineOnly"
31
+ }
32
+ /** Vertical placement of content within a table cell. Mixed cannot be authored. @public */
33
+ declare enum VerticalAlignment {
34
+ mixed = "Mixed",
35
+ top = "Top",
36
+ center = "Center",
37
+ bottom = "Bottom"
38
+ }
39
+ /** Office break vocabulary; enum presence does not imply support for every break kind. @public */
40
+ declare enum BreakType {
41
+ line = "Line",
42
+ page = "Page",
43
+ next = "Next",
44
+ sectionNext = "SectionNext",
45
+ sectionContinuous = "SectionContinuous",
46
+ sectionEven = "SectionEven",
47
+ sectionOdd = "SectionOdd"
48
+ }
49
+ /** Content-control kinds, including the read subtypes that insertion does not accept. @public */
50
+ declare enum ContentControlType {
51
+ unknown = "Unknown",
52
+ richText = "RichText",
53
+ plainText = "PlainText",
54
+ picture = "Picture",
55
+ buildingBlockGallery = "BuildingBlockGallery",
56
+ checkBox = "CheckBox",
57
+ comboBox = "ComboBox",
58
+ datePicker = "DatePicker",
59
+ dropDownList = "DropDownList",
60
+ group = "Group",
61
+ repeatingSection = "RepeatingSection",
62
+ plainTextInline = "PlainTextInline",
63
+ plainTextParagraph = "PlainTextParagraph",
64
+ richTextInline = "RichTextInline",
65
+ richTextParagraphs = "RichTextParagraphs",
66
+ richTextTable = "RichTextTable",
67
+ richTextTableCell = "RichTextTableCell",
68
+ richTextTableRow = "RichTextTableRow"
69
+ }
70
+
71
+ /**
72
+ * What the host is told to look at.
73
+ *
74
+ * Two shapes, because the protocol names two kinds of thing. Most objects ARE something the host
75
+ * minted a handle for. A stretch of a story is not: it is two endpoints, each a paragraph handle
76
+ * and a UTF-16 offset, and there is no third object behind it to hand out a handle for. Giving a
77
+ * range a handle of its own would mean the host tracking a region across every edit, which is a
78
+ * promise it cannot keep — so the address is the endpoints, and a deleted paragraph makes the
79
+ * whole address refuse rather than silently name a different place.
80
+ */
81
+ type ObjectAddress = {
82
+ readonly kind: 'handle';
83
+ readonly handle: AutomationHandle;
84
+ } | {
85
+ readonly kind: 'span';
86
+ readonly span: AutomationSpan;
87
+ };
88
+ type ObjectPathState =
89
+ /** Promised: created by a queued read that has not answered yet. */
90
+ {
91
+ readonly status: 'pending';
92
+ }
93
+ /** Addressable: the host has named this object, or the span it stands for is known. */
94
+ | {
95
+ readonly status: 'resolved';
96
+ readonly address: ObjectAddress;
97
+ }
98
+ /** A `get…OrNullObject` that found nothing. Not an error, and never addressable. */
99
+ | {
100
+ readonly status: 'null';
101
+ }
102
+ /** Its run ended without tracking it. Terminal. */
103
+ | {
104
+ readonly status: 'released';
105
+ };
106
+ declare class ObjectPath {
107
+ #private;
108
+ readonly label: string;
109
+ private constructor();
110
+ /** A path that is addressable from the moment it exists — a root, or an item just hydrated. */
111
+ static of(label: string, handle: AutomationHandle): ObjectPath;
112
+ /** The same, for an object that IS a stretch of a story. */
113
+ static ofSpan(label: string, span: AutomationSpan): ObjectPath;
114
+ /** A path a queued read will fill in — or mark null. */
115
+ static pending(label: string): ObjectPath;
116
+ /** A path that is whatever its owner's path is, under its own name. */
117
+ static derived(label: string, parent: ObjectPath): ObjectPath;
118
+ get state(): ObjectPathState;
119
+ get isAddressable(): boolean;
120
+ get isPending(): boolean;
121
+ get isNull(): boolean;
122
+ get isReleased(): boolean;
123
+ /**
124
+ * What to put in a batch, or a refusal.
125
+ *
126
+ * Both refusals are `InvalidObjectPath` on purpose: from a consumer's side "this object was
127
+ * released" and "this object is still a promise" are the same mistake — using an object the
128
+ * runtime cannot address yet or any more — and the `target` says which object it was.
129
+ *
130
+ * THE CODE IS ONE THING AND THE MESSAGE IS ANOTHER. The two states have different fixes — a
131
+ * promise needs a `sync()`, a released object needs to have been tracked — so the sentence in
132
+ * `errors.ts` names both. It described only the released half for a while, which sent a
133
+ * consumer holding a perfectly good promised object off to `trackedObjects.add(...)`.
134
+ */
135
+ address(): ObjectAddress;
136
+ /** The handle to address this object with. Refused for anything that is not handle-shaped. */
137
+ handle(): AutomationHandle;
138
+ /** The span this object stands for. Refused for anything that is not span-shaped. */
139
+ span(): AutomationSpan;
140
+ /**
141
+ * Hydration: the read answered, and this is the object it named.
142
+ *
143
+ * A released path stays released. Hydration arriving for one is not an error — a batch can be
144
+ * in flight when a run ends — but resurrecting the object would hand back a proxy whose
145
+ * lifetime rules had already been applied.
146
+ */
147
+ resolveTo(handle: AutomationHandle): void;
148
+ /** The same, for an object that came back as a stretch of a story. */
149
+ resolveToSpan(span: AutomationSpan): void;
150
+ /** Hydration: the read answered, and there was nothing there. */
151
+ resolveNull(): void;
152
+ /**
153
+ * The run ended and nothing kept this object alive. Terminal.
154
+ *
155
+ * A derived path does not release: its owner's release is what governs it, and releasing here
156
+ * would let a collection's lifetime end its parent's.
157
+ */
158
+ release(): void;
159
+ }
3
160
 
4
161
  /** Whether an action reads or writes. Drives the conditional-revision rule in `sync()`. */
5
162
  type ActionSort = 'read' | 'write';
163
+
6
164
  interface QueuedAction {
7
165
  readonly sort: ActionSort;
166
+ /** Paths that must resolve before this action can be planned. */
167
+ readonly dependencies?: readonly ObjectPath[];
168
+ /** A scalar load on an OrNullObject proxy is skipped if its lookup resolves null. */
169
+ readonly nullableLoad?: ObjectPath;
8
170
  /** The consumer-facing name of what this action is for, for errors. Never a handle. */
9
171
  readonly label: string;
172
+ /** Detach coalesced setters when sync captures this action, before asynchronous reads. */
173
+ capture?(): void;
174
+ /** Release coalesced state when a batch completes or is discarded. */
175
+ dispose?(): void;
10
176
  /**
11
177
  * The host operation for this action.
12
178
  *
@@ -91,7 +257,7 @@ declare abstract class ModelObject extends ClientObject {
91
257
  /** Queue a read whose text answer becomes the loaded property `name`. */
92
258
  protected loadTextInto(name: string, plan: () => AutomationOperation): void;
93
259
  /** Queue a command with nothing to answer. Nothing is written until `sync()`. */
94
- protected command(name: string, plan: () => AutomationOperation): void;
260
+ protected command(name: string, plan: () => AutomationOperation, dispose?: () => void): void;
95
261
  /**
96
262
  * Queue a command whose answer this call has no use for.
97
263
  *
@@ -101,7 +267,7 @@ declare abstract class ModelObject extends ClientObject {
101
267
  */
102
268
  protected commandDiscarding(name: string, plan: () => AutomationOperation): void;
103
269
  /** Queue a command whose answer names something the caller keeps. */
104
- protected commandAnswering(label: string, plan: () => AutomationOperation, settle: (value: AutomationValue) => void): void;
270
+ protected commandAnswering(label: string, plan: () => AutomationOperation, settle: (value: AutomationValue) => void, dispose?: () => void): void;
105
271
  /** Queue a read whose answer is hydrated by the caller. */
106
272
  protected read(label: string, plan: () => AutomationOperation, settle: (value: AutomationValue) => void): void;
107
273
  /** The properties a load asked for, refusing any name this object does not have. */
@@ -110,6 +276,25 @@ declare abstract class ModelObject extends ClientObject {
110
276
  protected onLoad(request: ResolvedLoadOptions): void;
111
277
  }
112
278
 
279
+ /** Supported Word bullet styles. @public */
280
+ declare enum ListBullet {
281
+ custom = "Custom",
282
+ solid = "Solid",
283
+ hollow = "Hollow",
284
+ square = "Square",
285
+ diamonds = "Diamonds",
286
+ arrow = "Arrow",
287
+ checkmark = "Checkmark"
288
+ }
289
+ /** Supported Word numbering styles. @public */
290
+ declare enum ListNumbering {
291
+ none = "None",
292
+ arabic = "Arabic",
293
+ upperRoman = "UpperRoman",
294
+ lowerRoman = "LowerRoman",
295
+ upperLetter = "UpperLetter",
296
+ lowerLetter = "LowerLetter"
297
+ }
113
298
  /**
114
299
  * A list: the set of paragraphs sharing one numbering id.
115
300
  *
@@ -147,6 +332,16 @@ declare class List extends ModelObject implements PromisedItem {
147
332
  * `compat/manifest.json`.
148
333
  */
149
334
  insertParagraph(paragraphText: string, insertLocation: 'Start' | 'End' | 'Before' | 'After'): Paragraph;
335
+ /** Set a level's bullet glyph. Custom bullets require a Unicode character code. */
336
+ setLevelBullet(level: number, listBullet: ListBullet, charCode?: number, fontName?: string): void;
337
+ setLevelBullet(level: number, listBullet: 'Custom' | 'Solid' | 'Hollow' | 'Square' | 'Diamonds' | 'Arrow' | 'Checkmark', charCode?: number, fontName?: string): void;
338
+ /** Set decimal, letter, Roman, or unnumbered markers. Numeric format entries identify zero-based levels. */
339
+ setLevelNumbering(level: number, listNumbering: ListNumbering, formatString?: (string | number)[]): void;
340
+ setLevelNumbering(level: number, listNumbering: 'None' | 'Arabic' | 'UpperRoman' | 'LowerRoman' | 'UpperLetter' | 'LowerLetter', formatString?: (string | number)[]): void;
341
+ /** Set the starting counter for this list instance without changing other lists. */
342
+ setLevelStartingNumber(level: number, startingNumber: number): void;
343
+ /** Set text indent and relative first-line indent in points. Negative relative values create hanging indents. */
344
+ setLevelIndents(level: number, textIndent: number, bulletNumberPictureIndent: number): void;
150
345
  /** @internal Plan the read this object's `load(...)` asked for. */
151
346
  protected onLoad(request: ResolvedLoadOptions): void;
152
347
  }
@@ -209,6 +404,30 @@ declare class ListItem extends ModelObject {
209
404
  /** What the object is, which is what decides how its characters are named. */
210
405
  type SpanOwner = 'body' | 'paragraph' | 'span';
211
406
 
407
+ /** Office.js underline values. Unsupported runtime modes refuse at sync. @public */
408
+ declare enum UnderlineType {
409
+ mixed = "Mixed",
410
+ none = "None",
411
+ hidden = "Hidden",
412
+ dotLine = "DotLine",
413
+ single = "Single",
414
+ word = "Word",
415
+ double = "Double",
416
+ thick = "Thick",
417
+ dotted = "Dotted",
418
+ dottedHeavy = "DottedHeavy",
419
+ dashLine = "DashLine",
420
+ dashLineHeavy = "DashLineHeavy",
421
+ dashLineLong = "DashLineLong",
422
+ dashLineLongHeavy = "DashLineLongHeavy",
423
+ dotDashLine = "DotDashLine",
424
+ dotDashLineHeavy = "DotDashLineHeavy",
425
+ twoDotDashLine = "TwoDotDashLine",
426
+ twoDotDashLineHeavy = "TwoDotDashLineHeavy",
427
+ wave = "Wave",
428
+ waveHeavy = "WaveHeavy",
429
+ waveDouble = "WaveDouble"
430
+ }
212
431
  /**
213
432
  * The character formatting of whatever it belongs to: a story, a stretch of one, or a paragraph.
214
433
  *
@@ -251,6 +470,18 @@ declare class Font extends ModelObject {
251
470
  /** Points. */
252
471
  get size(): number | null;
253
472
  set size(value: number);
473
+ /** Office underline styles. Mixed, Hidden, and DotLine refuse at sync. */
474
+ get underline(): string | null;
475
+ set underline(value: UnderlineType | 'Mixed' | 'None' | 'Hidden' | 'DotLine' | 'Single' | 'Word' | 'Double' | 'Thick' | 'Dotted' | 'DottedHeavy' | 'DashLine' | 'DashLineHeavy' | 'DashLineLong' | 'DashLineLongHeavy' | 'DotDashLine' | 'DotDashLineHeavy' | 'TwoDotDashLine' | 'TwoDotDashLineHeavy' | 'Wave' | 'WaveHeavy' | 'WaveDouble');
476
+ /** Exact Word palette color, returned as #RRGGBB. Null clears highlighting. */
477
+ get highlightColor(): string | null;
478
+ set highlightColor(value: string);
479
+ get strikeThrough(): boolean | null;
480
+ set strikeThrough(value: boolean);
481
+ get subscript(): boolean | null;
482
+ set subscript(value: boolean);
483
+ get superscript(): boolean | null;
484
+ set superscript(value: boolean);
254
485
  /**
255
486
  * One read for every property asked for.
256
487
  *
@@ -261,18 +492,284 @@ declare class Font extends ModelObject {
261
492
  protected onLoad(request: ResolvedLoadOptions): void;
262
493
  }
263
494
 
495
+ /** Office field types. This runtime authors Page, NumPages, and Empty with a supported code. @public */
496
+ declare enum FieldType {
497
+ addin = "Addin",
498
+ addressBlock = "AddressBlock",
499
+ advance = "Advance",
500
+ ask = "Ask",
501
+ author = "Author",
502
+ autoText = "AutoText",
503
+ autoTextList = "AutoTextList",
504
+ barCode = "BarCode",
505
+ bibliography = "Bibliography",
506
+ bidiOutline = "BidiOutline",
507
+ citation = "Citation",
508
+ comments = "Comments",
509
+ compare = "Compare",
510
+ createDate = "CreateDate",
511
+ data = "Data",
512
+ database = "Database",
513
+ date = "Date",
514
+ displayBarcode = "DisplayBarcode",
515
+ docProperty = "DocProperty",
516
+ docVariable = "DocVariable",
517
+ editTime = "EditTime",
518
+ embedded = "Embedded",
519
+ empty = "Empty",
520
+ eq = "EQ",
521
+ expression = "Expression",
522
+ fileName = "FileName",
523
+ fileSize = "FileSize",
524
+ fillIn = "FillIn",
525
+ formCheckbox = "FormCheckbox",
526
+ formDropdown = "FormDropdown",
527
+ formText = "FormText",
528
+ gotoButton = "GotoButton",
529
+ greetingLine = "GreetingLine",
530
+ hyperlink = "Hyperlink",
531
+ if = "If",
532
+ import = "Import",
533
+ include = "Include",
534
+ includePicture = "IncludePicture",
535
+ includeText = "IncludeText",
536
+ index = "Index",
537
+ info = "Info",
538
+ keywords = "Keywords",
539
+ lastSavedBy = "LastSavedBy",
540
+ link = "Link",
541
+ listNum = "ListNum",
542
+ macroButton = "MacroButton",
543
+ mergeBarcode = "MergeBarcode",
544
+ mergeField = "MergeField",
545
+ mergeRec = "MergeRec",
546
+ mergeSeq = "MergeSeq",
547
+ next = "Next",
548
+ nextIf = "NextIf",
549
+ noteRef = "NoteRef",
550
+ numChars = "NumChars",
551
+ numPages = "NumPages",
552
+ numWords = "NumWords",
553
+ ocx = "OCX",
554
+ others = "Others",
555
+ page = "Page",
556
+ pageRef = "PageRef",
557
+ print = "Print",
558
+ printDate = "PrintDate",
559
+ private = "Private",
560
+ quote = "Quote",
561
+ rd = "RD",
562
+ ref = "Ref",
563
+ revNum = "RevNum",
564
+ saveDate = "SaveDate",
565
+ section = "Section",
566
+ sectionPages = "SectionPages",
567
+ seq = "Seq",
568
+ set = "Set",
569
+ shape = "Shape",
570
+ skipIf = "SkipIf",
571
+ styleRef = "StyleRef",
572
+ subject = "Subject",
573
+ subscriber = "Subscriber",
574
+ symbol = "Symbol",
575
+ ta = "TA",
576
+ tc = "TC",
577
+ template = "Template",
578
+ time = "Time",
579
+ title = "Title",
580
+ toa = "TOA",
581
+ toc = "TOC",
582
+ undefined = "Undefined",
583
+ userAddress = "UserAddress",
584
+ userInitials = "UserInitials",
585
+ userName = "UserName",
586
+ xe = "XE"
587
+ }
588
+ /** String forms of Office field types. @public */
589
+ type FieldTypeLiteral = `${FieldType}`;
590
+
591
+ /** An inline PNG or JPEG picture. Measurements use points. @public */
592
+ declare class InlinePicture extends ModelObject implements PromisedItem {
593
+ #private;
594
+ /** @internal */
595
+ static at(context: RequestContext, label: string, address: ObjectAddress): InlinePicture;
596
+ /** @internal */
597
+ static promised(context: RequestContext, label: string, nullable: boolean): InlinePicture;
598
+ private constructor();
599
+ /** @internal */
600
+ hydrateAddress(address: ObjectAddress): void;
601
+ /** @internal */
602
+ hydrateNull(): void;
603
+ get width(): number;
604
+ set width(value: number);
605
+ get height(): number;
606
+ set height(value: number);
607
+ get lockAspectRatio(): boolean;
608
+ set lockAspectRatio(value: boolean);
609
+ get altTextDescription(): string;
610
+ set altTextDescription(value: string);
611
+ /** Delete this picture. Shared media relationships remain preserved. */
612
+ delete(): void;
613
+ protected onLoad(request: ResolvedLoadOptions): void;
614
+ }
615
+ /** Inline pictures within a body or range. Load items before enumeration. @public */
616
+ declare class InlinePictureCollection extends ItemCollection<InlinePicture> {
617
+ #private;
618
+ /** @internal */
619
+ static of(context: RequestContext, label: string, owner: ObjectPath, kind: SpanOwner): InlinePictureCollection;
620
+ private constructor();
621
+ getFirst(): InlinePicture;
622
+ getLast(): InlinePicture;
623
+ getFirstOrNullObject(): InlinePicture;
624
+ getLastOrNullObject(): InlinePicture;
625
+ protected listing(): AutomationOperation;
626
+ protected size(value: AutomationValue, label: string): number;
627
+ protected addressAt(value: AutomationValue, label: string, index: number): ObjectAddress | undefined;
628
+ protected itemAt(label: string, address: ObjectAddress): InlinePicture;
629
+ protected promised(label: string, nullable: boolean): InlinePicture & PromisedItem;
630
+ }
631
+
632
+ /** A canonical rectangular table. Reads require load() and sync(). @public */
633
+ declare class Table extends ModelObject implements PromisedItem {
634
+ #private;
635
+ /** @internal */
636
+ static at(context: RequestContext, label: string, address: ObjectAddress): Table;
637
+ /** @internal */
638
+ static promised(context: RequestContext, label: string, nullable?: boolean): Table;
639
+ private constructor();
640
+ /** @internal */
641
+ hydrateAddress(address: ObjectAddress): void;
642
+ /** @internal */
643
+ hydrateNull(): void;
644
+ /** Cell text by row. A write replaces the whole rectangular matrix; rich cell content refuses. */
645
+ get values(): string[][];
646
+ set values(value: string[][]);
647
+ /** Table style display name. Writes must name an existing table style in the document. */
648
+ get style(): string;
649
+ set style(value: string);
650
+ /** Number of consecutive leading rows repeated as table headers. */
651
+ get headerRowCount(): number;
652
+ set headerRowCount(value: number);
653
+ /** Number of rows. Load this property before reading it. */
654
+ get rowCount(): number;
655
+ /** Number of columns in the rectangular grid. Load before reading. */
656
+ get columnCount(): number;
657
+ /** Stable row collection. Load `items`, then sync before reading its elements. */
658
+ get rows(): TableRowCollection;
659
+ /** Address a cell by zero-based row and column. Read-derived operations may share its next sync. */
660
+ getCell(rowIndex: number, cellIndex: number): TableCell;
661
+ /** Add rows at an edge. Sync before configuring the returned rows; omitted values create empty cells. */
662
+ addRows(insertLocation: InsertLocation.start | InsertLocation.end | 'Start' | 'End', rowCount: number, values?: string[][]): TableRowCollection;
663
+ /** Add columns at an edge. Values are row-major; new columns initially copy the nearest edge width. */
664
+ addColumns(insertLocation: InsertLocation.start | InsertLocation.end | 'Start' | 'End', columnCount: number, values?: string[][]): void;
665
+ /** Delete consecutive rows from a zero-based index. Defaults to one row. */
666
+ deleteRows(rowIndex: number, rowCount?: number): void;
667
+ /** Delete consecutive columns from a zero-based index. Defaults to one column. */
668
+ deleteColumns(columnIndex: number, columnCount?: number): void;
669
+ /** Delete this table and its contents through the canonical document transaction. */
670
+ delete(): void;
671
+ protected onLoad(request: ResolvedLoadOptions): void;
672
+ }
673
+ /** A row with stable identity. Its cells follow document order. @public */
674
+ declare class TableRow extends ModelObject implements PromisedItem {
675
+ #private;
676
+ /** @internal */
677
+ static at(context: RequestContext, label: string, address: ObjectAddress): TableRow;
678
+ /** @internal */
679
+ static promised(context: RequestContext, label: string, nullable?: boolean): TableRow;
680
+ private constructor();
681
+ /** @internal */
682
+ hydrateAddress(address: ObjectAddress): void;
683
+ /** @internal */
684
+ hydrateNull(): void;
685
+ /** Stable cell collection for this row. Load `items` and sync before reading. */
686
+ get cells(): TableCellCollection;
687
+ }
688
+ /** An ordinary table cell. Column width uses points and changes the whole grid column. @public */
689
+ declare class TableCell extends ModelObject implements PromisedItem {
690
+ #private;
691
+ /** @internal */
692
+ static at(context: RequestContext, label: string, address: ObjectAddress): TableCell;
693
+ /** @internal */
694
+ static promised(context: RequestContext, label: string, nullable?: boolean): TableCell;
695
+ private constructor();
696
+ /** @internal */
697
+ hydrateAddress(address: ObjectAddress): void;
698
+ /** @internal */
699
+ hydrateNull(): void;
700
+ /** A body scoped to this cell for text, ranges, formatting, and nested table navigation. */
701
+ get body(): Body;
702
+ /** Plain cell text. Replacing complex content refuses; use the scoped body for targeted edits. */
703
+ get value(): string;
704
+ set value(value: string);
705
+ /** Width in points. A write affects the whole grid column, not only this cell. */
706
+ get columnWidth(): number;
707
+ set columnWidth(value: number);
708
+ /** Cell background as a supported color string. */
709
+ get shadingColor(): string;
710
+ set shadingColor(value: string);
711
+ /** Top, Center, or Bottom. Mixed is a read state and cannot be assigned. */
712
+ get verticalAlignment(): VerticalAlignment | 'Top' | 'Center' | 'Bottom' | 'Mixed';
713
+ set verticalAlignment(value: VerticalAlignment | 'Top' | 'Center' | 'Bottom' | 'Mixed');
714
+ protected onLoad(request: ResolvedLoadOptions): void;
715
+ }
716
+ /** A loaded collection of Table objects. @public */
717
+ declare class TableCollection extends HandleCollection<Table> {
718
+ #private;
719
+ /** @internal */
720
+ static of(context: RequestContext, label: string, owner: ObjectPath, listing: () => AutomationOperation | null): TableCollection;
721
+ /** @internal */
722
+ static over(context: RequestContext, label: string, owner: ObjectPath, scope: () => AutomationSpanRef): TableCollection;
723
+ private constructor();
724
+ /** Return the first item; an empty collection raises ItemNotFound at sync. */
725
+ getFirst(): Table;
726
+ /** Return the first item or a null object. Check isNullObject after sync. */
727
+ getFirstOrNullObject(): Table;
728
+ protected listing(): AutomationOperation | null;
729
+ protected itemAt(label: string, address: ObjectAddress): Table;
730
+ protected promised(label: string, nullable: boolean): Table & PromisedItem;
731
+ }
732
+ /** A loaded collection of TableRow objects. @public */
733
+ declare class TableRowCollection extends HandleCollection<TableRow> {
734
+ #private;
735
+ /** @internal */
736
+ static of(context: RequestContext, label: string, owner: ObjectPath, listing: () => AutomationOperation | null): TableRowCollection;
737
+ private constructor();
738
+ /** Return the first item; an empty collection raises ItemNotFound at sync. */
739
+ getFirst(): TableRow;
740
+ /** Return the first item or a null object. Check isNullObject after sync. */
741
+ getFirstOrNullObject(): TableRow;
742
+ protected listing(): AutomationOperation | null;
743
+ protected itemAt(label: string, address: ObjectAddress): TableRow;
744
+ protected promised(label: string, nullable: boolean): TableRow & PromisedItem;
745
+ }
746
+ /** A loaded collection of TableCell objects. @public */
747
+ declare class TableCellCollection extends HandleCollection<TableCell> {
748
+ #private;
749
+ /** @internal */
750
+ static of(context: RequestContext, label: string, owner: ObjectPath, listing: () => AutomationOperation | null): TableCellCollection;
751
+ private constructor();
752
+ /** Return the first item; an empty collection raises ItemNotFound at sync. */
753
+ getFirst(): TableCell;
754
+ /** Return the first item or a null object. Check isNullObject after sync. */
755
+ getFirstOrNullObject(): TableCell;
756
+ protected listing(): AutomationOperation | null;
757
+ protected itemAt(label: string, address: ObjectAddress): TableCell;
758
+ protected promised(label: string, nullable: boolean): TableCell & PromisedItem;
759
+ }
760
+
264
761
  /** Every place this API can insert at. Individual members accept a subset. */
265
- type InsertLocation = 'Replace' | 'Start' | 'End' | 'Before' | 'After';
762
+
266
763
  /** Where a story accepts text: over all of it, or at either edge. */
267
- type BodyInsertTextLocation = Extract<InsertLocation, 'Replace' | 'Start' | 'End'>;
764
+ type BodyInsertTextLocation = Extract<RangeInsertTextLocation, 'Replace' | 'Start' | 'End'>;
268
765
  /** Where a story accepts a paragraph. `Start`/`End` mean "before the first"/"after the last". */
269
- type BodyInsertParagraphLocation = Extract<InsertLocation, 'Start' | 'End'>;
766
+ type BodyInsertParagraphLocation = Extract<RangeInsertTextLocation, 'Start' | 'End'>;
270
767
  /** Where a paragraph accepts text: over all of it, or at either edge of it. */
271
- type ParagraphInsertTextLocation = Extract<InsertLocation, 'Replace' | 'Start' | 'End'>;
768
+ type ParagraphInsertTextLocation = Extract<RangeInsertTextLocation, 'Replace' | 'Start' | 'End'>;
272
769
  /** Which side of a paragraph or a range a new paragraph goes on. */
273
- type BesideLocation = Extract<InsertLocation, 'Before' | 'After'>;
770
+ type BesideLocation = Extract<RangeInsertTextLocation, 'Before' | 'After'>;
274
771
  /** Where a range accepts text. See `Range#insertText` for what `Before`/`Start` mean here. */
275
- type RangeInsertTextLocation = InsertLocation;
772
+ type RangeInsertTextLocation = 'Replace' | 'Start' | 'End' | 'Before' | 'After';
276
773
  /** Where a selection lands: over the range, or collapsed to one of its edges. */
277
774
  type SelectionMode = 'Select' | 'Start' | 'End';
278
775
 
@@ -338,9 +835,194 @@ declare class BookmarkCollection extends HandleCollection<Bookmark> {
338
835
  /** @internal The read that answers this collection's members. */
339
836
  protected listing(): AutomationOperation;
340
837
  /** @internal Build one member from an address the listing answered. */
341
- protected itemAt(label: string, address: ObjectAddress): Bookmark;
838
+ protected itemAt(label: string, address: ObjectAddress): Bookmark;
839
+ /** @internal A member an edge accessor named before the sync that finds it. */
840
+ protected promised(label: string, nullable: boolean): Bookmark & PromisedItem;
841
+ }
842
+
843
+ /**
844
+ * What a control's own type accepts as a value.
845
+ *
846
+ * A discriminated union rather than `unknown`: a dropdown and a checkbox do not take the same
847
+ * kind of thing, and a single `setValue(value: string)` would have to guess what `'true'` means
848
+ * to a date picker.
849
+ */
850
+ type ContentControlValue = {
851
+ readonly kind: 'text';
852
+ readonly text: string;
853
+ } | {
854
+ readonly kind: 'listItem';
855
+ readonly value: string;
856
+ } | {
857
+ readonly kind: 'checkbox';
858
+ readonly checked: boolean;
859
+ }
860
+ /** `YYYY-MM-DD`, or a full ISO-8601 instant. */
861
+ | {
862
+ readonly kind: 'date';
863
+ readonly iso: string;
864
+ };
865
+ /** The lock a control carries. `ST_Lock`, spelled as the schema spells it. */
866
+ type ContentControlLockState = 'unlocked' | 'sdtLocked' | 'contentLocked' | 'sdtContentLocked';
867
+ /** The control types this API can create. Picture and repeating section are deferred. */
868
+ type ContentControlSubtype = 'richText' | 'plainText' | 'dropDownList' | 'comboBox' | 'date';
869
+ /**
870
+ * A part of a document a template marked as a field.
871
+ *
872
+ * A control is NOT its `w:id`. The attribute is optional in OOXML and unique nowhere, so a
873
+ * document may hold one control with no id and two with the same one. This object is addressed by
874
+ * an opaque host-minted handle instead, and {@link ContentControl.id} is answered as METADATA — a
875
+ * label the file wrote, empty where it wrote none. `getById` still exists, because a template
876
+ * author knows their own numbering, and it answers the first match in document order rather than
877
+ * refusing.
878
+ *
879
+ * A control's contents are not its value. `text` reads the characters; `setValue` writes in the
880
+ * vocabulary the control's own type accepts — a declared item for a dropdown, an ISO date for a
881
+ * date picker, a state for a checkbox — because writing `"true"` into a checkbox's runs would
882
+ * produce a document whose glyph and whose `w14:checked` disagree.
883
+ *
884
+ * @public
885
+ */
886
+ declare class ContentControl extends ModelObject implements PromisedItem {
887
+ #private;
888
+ /** @internal A control a read has already named. */
889
+ static at(context: RequestContext, label: string, address: ObjectAddress): ContentControl;
890
+ /** @internal A control a queued read will name, or report as nothing. */
891
+ static promised(context: RequestContext, label: string, nullable: boolean): ContentControl;
892
+ private constructor();
893
+ /** @internal Bind this object to the address the owning read answered. */
894
+ hydrateAddress(address: ObjectAddress): void;
895
+ /** @internal Settle as the null object: the read found nothing to name. */
896
+ hydrateNull(): void;
897
+ /**
898
+ * The `w:id` the file wrote, as a string, and `''` where it wrote none.
899
+ *
900
+ * A STRING and not a number, deliberately. The identity of this object is its handle; a numeric
901
+ * `id` invites a caller to key a map on a value the schema lets a document repeat.
902
+ */
903
+ get id(): string;
904
+ /** `w:tag` — the machine-readable label a template puts on a field. `''` where absent. */
905
+ get tag(): string;
906
+ set tag(value: string);
907
+ /** `w:alias` — what Word's UI calls the control's title. `''` where absent. */
908
+ get title(): string;
909
+ set title(value: string);
910
+ /** What kind of control it is: `plainText`, `dropDownList`, `checkbox`, `date`, … */
911
+ get subtype(): string;
912
+ /**
913
+ * Whether the control currently declares an OOXML data binding.
914
+ *
915
+ * This is advisory preflight for callers choosing controls to write. A document can change
916
+ * after this property is loaded, so the atomic sync-time refusal remains the final authority.
917
+ * Only binding presence is exposed: XPath, namespace mappings, store ids, and custom XML
918
+ * content remain inside the untrusted-document boundary.
919
+ */
920
+ get isBound(): boolean;
921
+ /**
922
+ * Whether the control refuses to be deleted.
923
+ *
924
+ * Reads the lock IN FORCE, so a control an enclosing one protects reports true even when its
925
+ * own `w:lock` says otherwise — that is what the document does, and reporting the control's own
926
+ * half would tell a caller an edit will work when the store is about to refuse it.
927
+ */
928
+ get cannotDelete(): boolean;
929
+ set cannotDelete(value: boolean);
930
+ /** Whether the control's contents refuse to be edited. Resolved like `cannotDelete`. */
931
+ get cannotEdit(): boolean;
932
+ set cannotEdit(value: boolean);
933
+ /**
934
+ * Whether the control is showing its prompt rather than a value (`w:showingPlcHdr`).
935
+ *
936
+ * STATE, not text. A control showing its placeholder holds the prompt in its runs, and the
937
+ * first thing written into it replaces the whole prompt — so a caller that treats `text` as a
938
+ * value must ask this before believing it.
939
+ */
940
+ get placeholderShown(): boolean;
941
+ /** Whether the control removes its own wrapper on the first content edit (`w:temporary`). */
942
+ get temporary(): boolean;
943
+ /** The characters the control encloses, as the document reads them. */
944
+ get text(): string;
945
+ /** The paragraphs the control holds. Empty for an inline control, which holds none. */
946
+ get paragraphs(): ParagraphCollection;
947
+ /** The controls INSIDE this one, in document order. */
948
+ get contentControls(): ContentControlCollection;
949
+ /**
950
+ * The stretch of the story the control's content covers.
951
+ *
952
+ * Read when it is asked for rather than carried by the control, because the content moves as
953
+ * the document is edited: the range a caller gets is where the control is now.
954
+ */
955
+ getRange(rangeLocation?: 'Whole' | 'Start' | 'End' | 'Before' | 'After' | 'Content'): Range;
956
+ /**
957
+ * Write the control's value.
958
+ *
959
+ * The refusals belong to the document, not to this method: a locked control, a control the file
960
+ * bound to custom XML, and a value the control's type does not accept are all refused by the
961
+ * engine's single write path, which is the same path a keystroke takes. {@link isBound} is an
962
+ * advisory preflight only; this sync-time check remains authoritative if the document changed
963
+ * after the flag was loaded.
964
+ */
965
+ setValue(value: ContentControlValue): void;
966
+ /**
967
+ * Put text into the control: over what it holds, or at one end of it.
968
+ *
969
+ * `Replace` goes through the control's own value path, so the prompt it was showing and a
970
+ * `w:temporary` wrapper are dealt with there rather than a second time here. The range comes
971
+ * back from the WRITE and not from a read beside it: reads answer the document as it is when
972
+ * the batch is planned, so a read here would name the text the write was about to replace.
973
+ */
974
+ insertText(text: string, insertLocation: InsertLocation.replace | InsertLocation.start | InsertLocation.end | 'Replace' | 'Start' | 'End'): Range;
975
+ /**
976
+ * Remove the control.
977
+ *
978
+ * `keepContent` true is Word's own "Remove content control": the wrapper goes and the text it
979
+ * held stays exactly where it was. False takes the content with it.
980
+ */
981
+ delete(keepContent: boolean): void;
982
+ /** @internal Plan the read this object's `load(...)` asked for. */
983
+ protected onLoad(request: ResolvedLoadOptions): void;
984
+ }
985
+ /** Where a collection of controls looks: a story, or inside one control. */
986
+ type ContentControlScope = {
987
+ readonly body: AutomationHandle;
988
+ } | {
989
+ readonly contentControl: AutomationHandle;
990
+ };
991
+ /**
992
+ * The content controls of a document, story or range, as of the batch that loaded them.
993
+ *
994
+ * `getById` answers the first match in document order, because `w:id` is optional in OOXML and
995
+ * unique nowhere — see {@link ContentControl} for why choosing predictably beats refusing.
996
+ *
997
+ * @public
998
+ */
999
+ declare class ContentControlCollection extends HandleCollection<ContentControl> {
1000
+ #private;
1001
+ /** @internal The controls of a scope, in document order. */
1002
+ static of(context: RequestContext, label: string, owner: ObjectPath, scope: ContentControlScope): ContentControlCollection;
1003
+ private constructor();
1004
+ /** The first control. `ItemNotFound` at the sync if the scope holds none. */
1005
+ getFirst(): ContentControl;
1006
+ /** The first control, or an object that says `isNullObject` where there is none. */
1007
+ getFirstOrNullObject(): ContentControl;
1008
+ /**
1009
+ * The first control carrying one `w:id`, or `ItemNotFound` where the scope holds none.
1010
+ *
1011
+ * FIRST in document order, because `w:id` is not unique. The lookup is one read answered by the
1012
+ * host: matching it here would mean asking every control for its id and choosing locally, which
1013
+ * is a batch whose size depends on how many controls the document has.
1014
+ */
1015
+ getById(id: number): ContentControl;
1016
+ /** Every control in the scope carrying one tag, in document order. */
1017
+ getByTag(tag: string): ContentControlCollection;
1018
+ /** Every control in the scope carrying one title, in document order. */
1019
+ getByTitle(title: string): ContentControlCollection;
1020
+ /** @internal The read that answers this collection's members. */
1021
+ protected listing(): AutomationOperation;
1022
+ /** @internal Build one member from an address the listing answered. */
1023
+ protected itemAt(label: string, address: ObjectAddress): ContentControl;
342
1024
  /** @internal A member an edge accessor named before the sync that finds it. */
343
- protected promised(label: string, nullable: boolean): Bookmark & PromisedItem;
1025
+ protected promised(label: string, nullable: boolean): ContentControl & PromisedItem;
344
1026
  }
345
1027
 
346
1028
  /**
@@ -641,6 +1323,8 @@ declare class Range extends ModelObject implements PromisedItem {
641
1323
  * WRITING IT AUTHORS A LINK over exactly these characters, and `''` removes one. A URL whose
642
1324
  * scheme this engine would refuse to OPEN is refused here too, by the same allowlist: a document
643
1325
  * this API writes must not be one it would then decline to follow.
1326
+ * Partial retargeting and unlinking support ordinary text links directly inside a paragraph.
1327
+ * Complex or nested link wrappers and collapsed ranges inside links refuse with `NotSupported`.
644
1328
  */
645
1329
  get hyperlink(): string;
646
1330
  set hyperlink(value: string);
@@ -663,7 +1347,7 @@ declare class Range extends ModelObject implements PromisedItem {
663
1347
  * snapshot. Both pairs are accepted because source-compatible code uses all four; what a caller
664
1348
  * gets back is a range naming the text that was written, in every case.
665
1349
  */
666
- insertText(text: string, insertLocation: 'Replace' | 'Start' | 'End' | 'Before' | 'After'): Range;
1350
+ insertText(text: string, insertLocation: InsertLocation | 'Replace' | 'Start' | 'End' | 'Before' | 'After'): Range;
667
1351
  /** Delete this range's content. TrackMineOnly preserves inline text as a pending deletion. */
668
1352
  delete(): void;
669
1353
  /** Clear this range's content, preserving the surrounding structure. */
@@ -676,8 +1360,27 @@ declare class Range extends ModelObject implements PromisedItem {
676
1360
  * approximately. A collapsed range creates an insertion-point comment.
677
1361
  */
678
1362
  insertComment(commentText: string): Comment;
1363
+ /**
1364
+ * Wrap this single-paragraph range in a rich-text or plain-text content control.
1365
+ * Await sync before configuring the returned control. Other types explicitly refuse.
1366
+ */
1367
+ insertContentControl(contentControlType?: ContentControlType.richText | ContentControlType.plainText | ContentControlType.buildingBlockGallery | ContentControlType.checkBox | ContentControlType.comboBox | ContentControlType.datePicker | ContentControlType.dropDownList | ContentControlType.group | ContentControlType.picture | ContentControlType.repeatingSection | 'RichText' | 'PlainText' | 'BuildingBlockGallery' | 'CheckBox' | 'ComboBox' | 'DatePicker' | 'DropDownList' | 'Group' | 'Picture' | 'RepeatingSection'): ContentControl;
1368
+ /** Tables contained by this range, in document order. */
1369
+ get tables(): TableCollection;
1370
+ /** Fields fully contained within this range. */
1371
+ get fields(): FieldCollection;
1372
+ insertField(insertLocation: InsertLocation | 'Before' | 'After' | 'Start' | 'End' | 'Replace', fieldType?: FieldType, text?: string, removeFormatting?: boolean): Field;
1373
+ insertField(insertLocation: InsertLocation | 'Before' | 'After' | 'Start' | 'End' | 'Replace', fieldType?: FieldTypeLiteral, text?: string, removeFormatting?: boolean): Field;
1374
+ /** Inline pictures fully contained within this snapshot range. */
1375
+ get inlinePictures(): InlinePictureCollection;
1376
+ /** Insert a bounded PNG/JPEG image. Sync before configuring the returned picture. */
1377
+ insertInlinePictureFromBase64(base64EncodedImage: string, insertLocation: InsertLocation | 'Before' | 'After' | 'Start' | 'End' | 'Replace'): InlinePicture;
1378
+ /** Page and next-page section breaks are supported; other break types refuse at sync. */
1379
+ insertBreak(breakType: BreakType | 'Page' | 'SectionNext' | 'Next' | 'Line' | 'SectionContinuous' | 'SectionEven' | 'SectionOdd', insertLocation: InsertLocation.before | InsertLocation.after | 'Before' | 'After'): void;
1380
+ /** Insert a rectangular table before or after this range. */
1381
+ insertTable(rowCount: number, columnCount: number, insertLocation: InsertLocation.before | InsertLocation.after | 'Before' | 'After', values?: string[][]): Table;
679
1382
  /** Add a paragraph before or after the one this range starts or ends in. */
680
- insertParagraph(paragraphText: string, insertLocation: 'Before' | 'After'): Paragraph;
1383
+ insertParagraph(paragraphText: string, insertLocation: InsertLocation.before | InsertLocation.after | 'Before' | 'After'): Paragraph;
681
1384
  /**
682
1385
  * Put the reader's selection on this range and navigate the editor viewport to it.
683
1386
  *
@@ -696,7 +1399,7 @@ declare class Range extends ModelObject implements PromisedItem {
696
1399
  }
697
1400
 
698
1401
  /** Paragraph alignment values readable and writable through this object model. */
699
- type ParagraphAlignment = 'Mixed' | 'Unknown' | 'Left' | 'Centered' | 'Right' | 'Justified';
1402
+ type ParagraphAlignment = Alignment | 'Mixed' | 'Unknown' | 'Left' | 'Centered' | 'Right' | 'Justified';
700
1403
  /**
701
1404
  * One paragraph: what it says, what it is, and the ways it can be changed.
702
1405
  *
@@ -763,313 +1466,136 @@ declare class Paragraph extends ModelObject implements PromisedItem {
763
1466
  /** Points. */
764
1467
  get rightIndent(): number;
765
1468
  set rightIndent(value: number);
766
- /** Points between the paragraph's lines. */
767
- get lineSpacing(): number;
768
- set lineSpacing(value: number);
769
- /** Points above the paragraph. */
770
- get spaceBefore(): number;
771
- set spaceBefore(value: number);
772
- /** Points below the paragraph. */
773
- get spaceAfter(): number;
774
- set spaceAfter(value: number);
775
- /**
776
- * The list this paragraph is in.
777
- *
778
- * A paragraph in NO list refuses the batch (`InvalidArgument`), the way upstream's own accessor
779
- * throws: a list a paragraph is not in has no members to answer, and a null object here would
780
- * make "not numbered" indistinguishable from "numbered by a list this document has lost".
781
- */
782
- get list(): List;
783
- /** Where this paragraph sits in its list. Reading `level` on a paragraph in none refuses. */
784
- get listItem(): ListItem;
785
- /** Empty this paragraph's text, leaving the paragraph itself where it is. */
786
- clear(): void;
787
- /** Remove this paragraph and everything in it. */
788
- delete(): void;
789
- /** Write text over this paragraph or at either edge of it. Answers the written text's range. */
790
- insertText(text: string, insertLocation: 'Replace' | 'Start' | 'End'): Range;
791
- /** Add a paragraph beside this one. Answers the new paragraph. */
792
- insertParagraph(paragraphText: string, insertLocation: 'Before' | 'After'): Paragraph;
793
- /**
794
- * Break this paragraph at every occurrence of any delimiter.
795
- *
796
- * Answers one range per resulting paragraph, in reading order, INCLUDING the piece that keeps
797
- * this paragraph's identity — so a caller can read back what each piece became without having to
798
- * work out which of them is the original. The collection is filled by the split itself: there is
799
- * no second read, because a second read would describe the document the split had already made.
800
- */
801
- split(delimiters: string[], trimDelimiters?: boolean, trimSpacing?: boolean): RangeCollection;
802
- /** @internal Plan the read this object's `load(...)` asked for. */
803
- protected onLoad(request: ResolvedLoadOptions): void;
804
- }
805
-
806
- /**
807
- * The paragraphs of a story, a range, or a list, as of the batch that loaded them.
808
- *
809
- * Contains paragraphs at every depth — inside table cells, nested tables, and block-level content
810
- * controls — matching Word's own collection rather than only the owner's direct children.
811
- *
812
- * One of the two collections whose members are not plain handles: the pieces a
813
- * {@link Paragraph.split} answers are filled in by the split's own command rather than by a
814
- * separate listing read.
815
- *
816
- * @public
817
- */
818
- declare class ParagraphCollection extends ItemCollection<Paragraph> {
819
- #private;
820
- /** @internal A story's paragraphs, or a range's, depending on the path it derives from. */
821
- static of(context: RequestContext, label: string, owner: ObjectPath): ParagraphCollection;
822
- /**
823
- * @internal Paragraphs a named read answers: a list's items, or one level of them.
824
- *
825
- * The owner's own address does not say which paragraphs are wanted — a list is not a place in the
826
- * story, it is a set of them — so the operation is supplied instead of derived.
827
- */
828
- static overListing(context: RequestContext, label: string, owner: ObjectPath, plan: () => AutomationOperation): ParagraphCollection;
829
- private constructor();
830
- /** The first paragraph. `ItemNotFound` at the sync if the collection holds none. */
831
- getFirst(): Paragraph;
832
- /** The last paragraph. `ItemNotFound` at the sync if the collection holds none. */
833
- getLast(): Paragraph;
834
- /** The first paragraph, or an object that will report `isNullObject`. */
835
- getFirstOrNullObject(): Paragraph;
836
- /** The last paragraph, or an object that will report `isNullObject`. */
837
- getLastOrNullObject(): Paragraph;
838
- /** @internal The read that answers this collection's members. */
839
- protected listing(): AutomationOperation;
840
- /** @internal How many members the listing's answer describes. */
841
- protected size(value: AutomationValue, label: string): number;
842
- /** @internal The address of one member of the listing's answer. */
843
- protected addressAt(value: AutomationValue, label: string, index: number): ObjectAddress | undefined;
844
- /** @internal Build one member from an address the listing answered. */
845
- protected itemAt(label: string, address: ObjectAddress): Paragraph;
846
- /** @internal A member an edge accessor named before the sync that finds it. */
847
- protected promised(label: string, nullable: boolean): Paragraph & PromisedItem;
848
- }
849
- /**
850
- * Ranges a read produced — the hits of a search, or the pieces a split answered.
851
- *
852
- * Its members are SPANS rather than handles, which is what separates it from the handle-backed
853
- * collections: each item carries its own paragraph-plus-offset endpoints instead of an opaque
854
- * host-minted id.
855
- *
856
- * @public
857
- */
858
- declare class RangeCollection extends ItemCollection<Range> {
859
- #private;
860
- /** @internal Ranges a read answers: where some text occurs. */
861
- static of(context: RequestContext, label: string, owner: ObjectPath, plan: () => AutomationOperation): RangeCollection;
862
- /** @internal Ranges a command answers: the pieces a split produced. Filled by that command. */
863
- static answered(context: RequestContext, label: string, owner: ObjectPath): RangeCollection;
864
- private constructor();
865
- /** The first range. `ItemNotFound` at the sync if nothing matched. */
866
- getFirst(): Range;
867
- /**
868
- * The last range. `ItemNotFound` at the sync if nothing matched.
869
- *
870
- * A DocxEditor member rather than a compatibility one: the reference's range collection publishes
871
- * only its first, and the pieces of a split are the case that makes the other end worth having —
872
- * "the paragraph this one ended up as" is the last piece, and counting `items` to find it means
873
- * loading them all. Recorded as an omission in `compat/manifest.json` for that reason.
874
- */
875
- getLast(): Range;
876
- /** The first range, or an object that will report `isNullObject`. */
877
- getFirstOrNullObject(): Range;
878
- /** @internal The read that answers this collection's members. */
879
- protected listing(): AutomationOperation | null;
880
- /** @internal How many members the listing's answer describes. */
881
- protected size(value: AutomationValue, label: string): number;
882
- /** @internal The address of one member of the listing's answer. */
883
- protected addressAt(value: AutomationValue, label: string, index: number): ObjectAddress | undefined;
884
- /** @internal Build one member from an address the listing answered. */
885
- protected itemAt(label: string, address: ObjectAddress): Range;
886
- /** @internal A member an edge accessor named before the sync that finds it. */
887
- protected promised(label: string, nullable: boolean): Range & PromisedItem;
888
- }
889
-
890
- /**
891
- * What a control's own type accepts as a value.
892
- *
893
- * A discriminated union rather than `unknown`: a dropdown and a checkbox do not take the same
894
- * kind of thing, and a single `setValue(value: string)` would have to guess what `'true'` means
895
- * to a date picker.
896
- */
897
- type ContentControlValue = {
898
- readonly kind: 'text';
899
- readonly text: string;
900
- } | {
901
- readonly kind: 'listItem';
902
- readonly value: string;
903
- } | {
904
- readonly kind: 'checkbox';
905
- readonly checked: boolean;
906
- }
907
- /** `YYYY-MM-DD`, or a full ISO-8601 instant. */
908
- | {
909
- readonly kind: 'date';
910
- readonly iso: string;
911
- };
912
- /** The lock a control carries. `ST_Lock`, spelled as the schema spells it. */
913
- type ContentControlLockState = 'unlocked' | 'sdtLocked' | 'contentLocked' | 'sdtContentLocked';
914
- /** The control types this API can create. Picture and repeating section are deferred. */
915
- type ContentControlSubtype = 'richText' | 'plainText' | 'dropDownList' | 'comboBox' | 'date';
916
- /**
917
- * A part of a document a template marked as a field.
918
- *
919
- * A control is NOT its `w:id`. The attribute is optional in OOXML and unique nowhere, so a
920
- * document may hold one control with no id and two with the same one. This object is addressed by
921
- * an opaque host-minted handle instead, and {@link ContentControl.id} is answered as METADATA — a
922
- * label the file wrote, empty where it wrote none. `getById` still exists, because a template
923
- * author knows their own numbering, and it answers the first match in document order rather than
924
- * refusing.
925
- *
926
- * A control's contents are not its value. `text` reads the characters; `setValue` writes in the
927
- * vocabulary the control's own type accepts — a declared item for a dropdown, an ISO date for a
928
- * date picker, a state for a checkbox — because writing `"true"` into a checkbox's runs would
929
- * produce a document whose glyph and whose `w14:checked` disagree.
930
- *
931
- * @public
932
- */
933
- declare class ContentControl extends ModelObject implements PromisedItem {
934
- #private;
935
- /** @internal A control a read has already named. */
936
- static at(context: RequestContext, label: string, address: ObjectAddress): ContentControl;
937
- /** @internal A control a queued read will name, or report as nothing. */
938
- static promised(context: RequestContext, label: string, nullable: boolean): ContentControl;
939
- private constructor();
940
- /** @internal Bind this object to the address the owning read answered. */
941
- hydrateAddress(address: ObjectAddress): void;
942
- /** @internal Settle as the null object: the read found nothing to name. */
943
- hydrateNull(): void;
944
- /**
945
- * The `w:id` the file wrote, as a string, and `''` where it wrote none.
946
- *
947
- * A STRING and not a number, deliberately. The identity of this object is its handle; a numeric
948
- * `id` invites a caller to key a map on a value the schema lets a document repeat.
949
- */
950
- get id(): string;
951
- /** `w:tag` — the machine-readable label a template puts on a field. `''` where absent. */
952
- get tag(): string;
953
- set tag(value: string);
954
- /** `w:alias` — what Word's UI calls the control's title. `''` where absent. */
955
- get title(): string;
956
- set title(value: string);
957
- /** What kind of control it is: `plainText`, `dropDownList`, `checkbox`, `date`, … */
958
- get subtype(): string;
959
- /**
960
- * Whether the control currently declares an OOXML data binding.
961
- *
962
- * This is advisory preflight for callers choosing controls to write. A document can change
963
- * after this property is loaded, so the atomic sync-time refusal remains the final authority.
964
- * Only binding presence is exposed: XPath, namespace mappings, store ids, and custom XML
965
- * content remain inside the untrusted-document boundary.
966
- */
967
- get isBound(): boolean;
968
- /**
969
- * Whether the control refuses to be deleted.
970
- *
971
- * Reads the lock IN FORCE, so a control an enclosing one protects reports true even when its
972
- * own `w:lock` says otherwise — that is what the document does, and reporting the control's own
973
- * half would tell a caller an edit will work when the store is about to refuse it.
974
- */
975
- get cannotDelete(): boolean;
976
- set cannotDelete(value: boolean);
977
- /** Whether the control's contents refuse to be edited. Resolved like `cannotDelete`. */
978
- get cannotEdit(): boolean;
979
- set cannotEdit(value: boolean);
980
- /**
981
- * Whether the control is showing its prompt rather than a value (`w:showingPlcHdr`).
982
- *
983
- * STATE, not text. A control showing its placeholder holds the prompt in its runs, and the
984
- * first thing written into it replaces the whole prompt — so a caller that treats `text` as a
985
- * value must ask this before believing it.
986
- */
987
- get placeholderShown(): boolean;
988
- /** Whether the control removes its own wrapper on the first content edit (`w:temporary`). */
989
- get temporary(): boolean;
990
- /** The characters the control encloses, as the document reads them. */
991
- get text(): string;
992
- /** The paragraphs the control holds. Empty for an inline control, which holds none. */
993
- get paragraphs(): ParagraphCollection;
994
- /** The controls INSIDE this one, in document order. */
995
- get contentControls(): ContentControlCollection;
996
- /**
997
- * The stretch of the story the control's content covers.
998
- *
999
- * Read when it is asked for rather than carried by the control, because the content moves as
1000
- * the document is edited: the range a caller gets is where the control is now.
1001
- */
1002
- getRange(rangeLocation?: 'Whole' | 'Start' | 'End' | 'Before' | 'After' | 'Content'): Range;
1469
+ /** Points between the paragraph's lines. */
1470
+ get lineSpacing(): number;
1471
+ set lineSpacing(value: number);
1472
+ /** Points above the paragraph. */
1473
+ get spaceBefore(): number;
1474
+ set spaceBefore(value: number);
1475
+ /** Points below the paragraph. */
1476
+ get spaceAfter(): number;
1477
+ set spaceAfter(value: number);
1003
1478
  /**
1004
- * Write the control's value.
1479
+ * The list this paragraph is in.
1005
1480
  *
1006
- * The refusals belong to the document, not to this method: a locked control, a control the file
1007
- * bound to custom XML, and a value the control's type does not accept are all refused by the
1008
- * engine's single write path, which is the same path a keystroke takes. {@link isBound} is an
1009
- * advisory preflight only; this sync-time check remains authoritative if the document changed
1010
- * after the flag was loaded.
1481
+ * A paragraph in NO list refuses the batch (`InvalidArgument`), the way upstream's own accessor
1482
+ * throws: a list a paragraph is not in has no members to answer, and a null object here would
1483
+ * make "not numbered" indistinguishable from "numbered by a list this document has lost".
1011
1484
  */
1012
- setValue(value: ContentControlValue): void;
1485
+ get list(): List;
1486
+ /** Address this paragraph's content or an endpoint. Sync before using the returned range. */
1487
+ getRange(rangeLocation?: 'Whole' | 'Content' | 'Start' | 'End' | 'Before' | 'After'): Range;
1488
+ /** Start a new independent bullet list with this paragraph. Sync before using the returned list. */
1489
+ startNewList(): List;
1490
+ /** Join an existing list at a zero-based nesting level. */
1491
+ attachToList(listId: number, level: number): List;
1492
+ /** Remove numbering while preserving the paragraph's text and other formatting. */
1493
+ detachFromList(): void;
1494
+ /** Where this paragraph sits in its list. Reading `level` on a paragraph in none refuses. */
1495
+ get listItem(): ListItem;
1496
+ /** Empty this paragraph's text, leaving the paragraph itself where it is. */
1497
+ clear(): void;
1498
+ /** Remove this paragraph and everything in it. */
1499
+ delete(): void;
1500
+ /** Write text over this paragraph or at either edge of it. Answers the written text's range. */
1501
+ insertText(text: string, insertLocation: InsertLocation.replace | InsertLocation.start | InsertLocation.end | 'Replace' | 'Start' | 'End'): Range;
1502
+ /** Add a paragraph beside this one. Answers the new paragraph. */
1503
+ insertParagraph(paragraphText: string, insertLocation: 'Before' | 'After'): Paragraph;
1013
1504
  /**
1014
- * Put text into the control: over what it holds, or at one end of it.
1505
+ * Break this paragraph at every occurrence of any delimiter.
1015
1506
  *
1016
- * `Replace` goes through the control's own value path, so the prompt it was showing and a
1017
- * `w:temporary` wrapper are dealt with there rather than a second time here. The range comes
1018
- * back from the WRITE and not from a read beside it: reads answer the document as it is when
1019
- * the batch is planned, so a read here would name the text the write was about to replace.
1507
+ * Answers one range per resulting paragraph, in reading order, INCLUDING the piece that keeps
1508
+ * this paragraph's identity — so a caller can read back what each piece became without having to
1509
+ * work out which of them is the original. The collection is filled by the split itself: there is
1510
+ * no second read, because a second read would describe the document the split had already made.
1020
1511
  */
1021
- insertText(text: string, insertLocation: 'Replace' | 'Start' | 'End'): Range;
1512
+ split(delimiters: string[], trimDelimiters?: boolean, trimSpacing?: boolean): RangeCollection;
1513
+ /** @internal Plan the read this object's `load(...)` asked for. */
1514
+ protected onLoad(request: ResolvedLoadOptions): void;
1515
+ }
1516
+
1517
+ /**
1518
+ * The paragraphs of a story, a range, or a list, as of the batch that loaded them.
1519
+ *
1520
+ * Contains paragraphs at every depth — inside table cells, nested tables, and block-level content
1521
+ * controls — matching Word's own collection rather than only the owner's direct children.
1522
+ *
1523
+ * One of the two collections whose members are not plain handles: the pieces a
1524
+ * {@link Paragraph.split} answers are filled in by the split's own command rather than by a
1525
+ * separate listing read.
1526
+ *
1527
+ * @public
1528
+ */
1529
+ declare class ParagraphCollection extends ItemCollection<Paragraph> {
1530
+ #private;
1531
+ /** @internal A story's paragraphs, or a range's, depending on the path it derives from. */
1532
+ static of(context: RequestContext, label: string, owner: ObjectPath): ParagraphCollection;
1022
1533
  /**
1023
- * Remove the control.
1534
+ * @internal Paragraphs a named read answers: a list's items, or one level of them.
1024
1535
  *
1025
- * `keepContent` true is Word's own "Remove content control": the wrapper goes and the text it
1026
- * held stays exactly where it was. False takes the content with it.
1536
+ * The owner's own address does not say which paragraphs are wanted — a list is not a place in the
1537
+ * story, it is a set of them — so the operation is supplied instead of derived.
1027
1538
  */
1028
- delete(keepContent: boolean): void;
1029
- /** @internal Plan the read this object's `load(...)` asked for. */
1030
- protected onLoad(request: ResolvedLoadOptions): void;
1539
+ static overListing(context: RequestContext, label: string, owner: ObjectPath, plan: () => AutomationOperation): ParagraphCollection;
1540
+ private constructor();
1541
+ /** The first paragraph. `ItemNotFound` at the sync if the collection holds none. */
1542
+ getFirst(): Paragraph;
1543
+ /** The last paragraph. `ItemNotFound` at the sync if the collection holds none. */
1544
+ getLast(): Paragraph;
1545
+ /** The first paragraph, or an object that will report `isNullObject`. */
1546
+ getFirstOrNullObject(): Paragraph;
1547
+ /** The last paragraph, or an object that will report `isNullObject`. */
1548
+ getLastOrNullObject(): Paragraph;
1549
+ /** @internal The read that answers this collection's members. */
1550
+ protected listing(): AutomationOperation;
1551
+ /** @internal How many members the listing's answer describes. */
1552
+ protected size(value: AutomationValue, label: string): number;
1553
+ /** @internal The address of one member of the listing's answer. */
1554
+ protected addressAt(value: AutomationValue, label: string, index: number): ObjectAddress | undefined;
1555
+ /** @internal Build one member from an address the listing answered. */
1556
+ protected itemAt(label: string, address: ObjectAddress): Paragraph;
1557
+ /** @internal A member an edge accessor named before the sync that finds it. */
1558
+ protected promised(label: string, nullable: boolean): Paragraph & PromisedItem;
1031
1559
  }
1032
- /** Where a collection of controls looks: a story, or inside one control. */
1033
- type ContentControlScope = {
1034
- readonly body: AutomationHandle;
1035
- } | {
1036
- readonly contentControl: AutomationHandle;
1037
- };
1038
1560
  /**
1039
- * The content controls of a document, story or range, as of the batch that loaded them.
1561
+ * Ranges a read produced — the hits of a search, or the pieces a split answered.
1040
1562
  *
1041
- * `getById` answers the first match in document order, because `w:id` is optional in OOXML and
1042
- * unique nowhere — see {@link ContentControl} for why choosing predictably beats refusing.
1563
+ * Its members are SPANS rather than handles, which is what separates it from the handle-backed
1564
+ * collections: each item carries its own paragraph-plus-offset endpoints instead of an opaque
1565
+ * host-minted id.
1043
1566
  *
1044
1567
  * @public
1045
1568
  */
1046
- declare class ContentControlCollection extends HandleCollection<ContentControl> {
1569
+ declare class RangeCollection extends ItemCollection<Range> {
1047
1570
  #private;
1048
- /** @internal The controls of a scope, in document order. */
1049
- static of(context: RequestContext, label: string, owner: ObjectPath, scope: ContentControlScope): ContentControlCollection;
1571
+ /** @internal Ranges a read answers: where some text occurs. */
1572
+ static of(context: RequestContext, label: string, owner: ObjectPath, plan: () => AutomationOperation): RangeCollection;
1573
+ /** @internal Ranges a command answers: the pieces a split produced. Filled by that command. */
1574
+ static answered(context: RequestContext, label: string, owner: ObjectPath): RangeCollection;
1050
1575
  private constructor();
1051
- /** The first control. `ItemNotFound` at the sync if the scope holds none. */
1052
- getFirst(): ContentControl;
1053
- /** The first control, or an object that says `isNullObject` where there is none. */
1054
- getFirstOrNullObject(): ContentControl;
1576
+ /** The first range. `ItemNotFound` at the sync if nothing matched. */
1577
+ getFirst(): Range;
1055
1578
  /**
1056
- * The first control carrying one `w:id`, or `ItemNotFound` where the scope holds none.
1579
+ * The last range. `ItemNotFound` at the sync if nothing matched.
1057
1580
  *
1058
- * FIRST in document order, because `w:id` is not unique. The lookup is one read answered by the
1059
- * host: matching it here would mean asking every control for its id and choosing locally, which
1060
- * is a batch whose size depends on how many controls the document has.
1581
+ * A DocxEditor member rather than a compatibility one: the reference's range collection publishes
1582
+ * only its first, and the pieces of a split are the case that makes the other end worth having —
1583
+ * "the paragraph this one ended up as" is the last piece, and counting `items` to find it means
1584
+ * loading them all. Recorded as an omission in `compat/manifest.json` for that reason.
1061
1585
  */
1062
- getById(id: number): ContentControl;
1063
- /** Every control in the scope carrying one tag, in document order. */
1064
- getByTag(tag: string): ContentControlCollection;
1065
- /** Every control in the scope carrying one title, in document order. */
1066
- getByTitle(title: string): ContentControlCollection;
1586
+ getLast(): Range;
1587
+ /** The first range, or an object that will report `isNullObject`. */
1588
+ getFirstOrNullObject(): Range;
1067
1589
  /** @internal The read that answers this collection's members. */
1068
- protected listing(): AutomationOperation;
1590
+ protected listing(): AutomationOperation | null;
1591
+ /** @internal How many members the listing's answer describes. */
1592
+ protected size(value: AutomationValue, label: string): number;
1593
+ /** @internal The address of one member of the listing's answer. */
1594
+ protected addressAt(value: AutomationValue, label: string, index: number): ObjectAddress | undefined;
1069
1595
  /** @internal Build one member from an address the listing answered. */
1070
- protected itemAt(label: string, address: ObjectAddress): ContentControl;
1596
+ protected itemAt(label: string, address: ObjectAddress): Range;
1071
1597
  /** @internal A member an edge accessor named before the sync that finds it. */
1072
- protected promised(label: string, nullable: boolean): ContentControl & PromisedItem;
1598
+ protected promised(label: string, nullable: boolean): Range & PromisedItem;
1073
1599
  }
1074
1600
 
1075
1601
  /** Which kind of note: Word's own two. */
@@ -1146,13 +1672,6 @@ declare class NoteItemCollection extends HandleCollection<NoteItem> {
1146
1672
  protected promised(label: string, nullable: boolean): NoteItem & PromisedItem;
1147
1673
  }
1148
1674
 
1149
- /**
1150
- * Which way round a page is, in Word's own spelling.
1151
- *
1152
- * Capitalised here and lower-case in the engine on purpose: the engine speaks OOXML's vocabulary,
1153
- * and this is the public API's. The mapping lives in this file and nowhere else.
1154
- */
1155
- type PageOrientation = 'Portrait' | 'Landscape';
1156
1675
  /** Which header or footer of a section: Word's own three variants. */
1157
1676
  type HeaderFooterType = 'Primary' | 'FirstPage' | 'EvenPages';
1158
1677
  /**
@@ -1180,8 +1699,8 @@ declare class PageSetup extends ModelObject {
1180
1699
  * Writing it alone SWAPS this section's own dimensions rather than assuming a paper size, so a
1181
1700
  * document of mixed sizes survives a flip with its sizes intact.
1182
1701
  */
1183
- get orientation(): PageOrientation;
1184
- set orientation(value: PageOrientation);
1702
+ get orientation(): PageOrientation | 'Portrait' | 'Landscape';
1703
+ set orientation(value: PageOrientation | 'Portrait' | 'Landscape');
1185
1704
  /** Points. */
1186
1705
  get topMargin(): number;
1187
1706
  set topMargin(value: number);
@@ -1232,9 +1751,9 @@ declare class Section extends ModelObject implements PromisedItem {
1232
1751
  get body(): Body;
1233
1752
  /** The page this section is laid out on. */
1234
1753
  get pageSetup(): PageSetup;
1235
- /** The header story of one variant, as a body. `ItemNotFound` where the document has none. */
1754
+ /** The header story, or a virtual empty body created by its first content insertion. */
1236
1755
  getHeader(type: HeaderFooterType): Body;
1237
- /** The footer story of one variant, as a body. `ItemNotFound` where the document has none. */
1756
+ /** The footer story, or a virtual empty body created by its first content insertion. */
1238
1757
  getFooter(type: HeaderFooterType): Body;
1239
1758
  /** The next section. `ItemNotFound` at the sync when this is the last one. */
1240
1759
  getNext(): Section;
@@ -1261,8 +1780,6 @@ declare class SectionCollection extends HandleCollection<Section> {
1261
1780
  protected promised(label: string, nullable: boolean): Section & PromisedItem;
1262
1781
  }
1263
1782
 
1264
- /** Office.js tracking mode names. TrackAll is recognized but currently refused. @public */
1265
- type ChangeTrackingMode = 'Off' | 'TrackAll' | 'TrackMineOnly';
1266
1783
  /**
1267
1784
  * The document: the root every other object is reached from.
1268
1785
  *
@@ -1298,14 +1815,15 @@ declare class Document extends ModelObject {
1298
1815
  static open(context: RequestContext): Document;
1299
1816
  private constructor();
1300
1817
  /**
1301
- * Tracking for this server host. Load 'changeTrackingMode' explicitly before reading.
1818
+ * Tracking for this automation runtime. Load 'changeTrackingMode' explicitly before reading.
1302
1819
  * Document.load() keeps an empty default property set across hosts. Assignments take effect at sync.
1303
1820
  * TrackMineOnly tracks this runtime's inline text edits using its configured author.
1304
- * TrackAll and browser-host mode control are not supported. Unsupported tracked mutation
1821
+ * TrackAll is unsupported. Browser tracked writes require the review module; this setting
1822
+ * does not change the editor UI mode. Unsupported tracked mutation
1305
1823
  * kinds refuse; the setting is session-local and is not saved as a document-wide policy.
1306
1824
  */
1307
- get changeTrackingMode(): ChangeTrackingMode;
1308
- set changeTrackingMode(mode: ChangeTrackingMode);
1825
+ get changeTrackingMode(): ChangeTrackingMode | 'Off' | 'TrackAll' | 'TrackMineOnly';
1826
+ set changeTrackingMode(mode: ChangeTrackingMode | 'Off' | 'TrackAll' | 'TrackMineOnly');
1309
1827
  /**
1310
1828
  * The main story.
1311
1829
  *
@@ -1368,7 +1886,7 @@ interface DocumentCapabilities {
1368
1886
  * Runs are ISOLATED, not serialized. Every {@link DocxEditorRuntime.run} gets its own context and
1369
1887
  * its own queue, so two runs cannot interleave into one batch, and a run started inside another
1370
1888
  * run works instead of waiting for a lock its own caller holds. Batches are still ordered — each
1371
- * `sync()` sends one atomic batch, in the order the `sync()` calls happen.
1889
+ * `sync()` commits writes atomically; read dependencies can use additional read-only batches.
1372
1890
  *
1373
1891
  * Disposal is final: {@link DocxEditorRuntime.dispose} releases the host once and is safe to call
1374
1892
  * again, and every later `run` fails with `RuntimeDisposed`.
@@ -1457,10 +1975,10 @@ interface RuntimeSession {
1457
1975
  /**
1458
1976
  * What a `run` hands its callback: one queue, one document, one sync at a time.
1459
1977
  *
1460
- * `sync()` is the only thing in this runtime that talks to the document, and it does so exactly
1461
- * once per call — plan the queued actions in order, send ONE batch, hydrate the answers. That is
1462
- * where atomicity comes from: the host commits a batch as one transaction, and the runtime never
1463
- * splits a consumer's `sync()` into several batches behind their back.
1978
+ * `sync()` commits all queued commands in one atomic transaction. Supported read-derived
1979
+ * proxy dependencies can require additional read-only transport calls before that commit.
1980
+ * These reads and the final write share one revision; a concurrent change refuses the sync.
1981
+ * Write-created proxies require a separate sync before dependent operations.
1464
1982
  *
1465
1983
  * Conditional writes come from the same place. A context that has READ from the document
1466
1984
  * remembers the revision it read at, and a later batch that writes goes out conditional on it,
@@ -1487,7 +2005,7 @@ declare class RequestContext {
1487
2005
  /** Objects kept addressable past the run that created them. See {@link TrackedObjects}. */
1488
2006
  get trackedObjects(): TrackedObjects;
1489
2007
  /**
1490
- * Send everything queued as one batch and hydrate the answers.
2008
+ * Resolve read prerequisites, then commit queued writes atomically and hydrate answers.
1491
2009
  *
1492
2010
  * An empty queue is not a round trip. Office-shaped code syncs defensively at the end of a
1493
2011
  * batch, and turning "nothing to say" into a host call would make a no-op sync advance a
@@ -1615,96 +2133,6 @@ interface ResolvedLoadOptions {
1615
2133
  readonly skip?: number;
1616
2134
  }
1617
2135
 
1618
- /**
1619
- * What the host is told to look at.
1620
- *
1621
- * Two shapes, because the protocol names two kinds of thing. Most objects ARE something the host
1622
- * minted a handle for. A stretch of a story is not: it is two endpoints, each a paragraph handle
1623
- * and a UTF-16 offset, and there is no third object behind it to hand out a handle for. Giving a
1624
- * range a handle of its own would mean the host tracking a region across every edit, which is a
1625
- * promise it cannot keep — so the address is the endpoints, and a deleted paragraph makes the
1626
- * whole address refuse rather than silently name a different place.
1627
- */
1628
- type ObjectAddress = {
1629
- readonly kind: 'handle';
1630
- readonly handle: AutomationHandle;
1631
- } | {
1632
- readonly kind: 'span';
1633
- readonly span: AutomationSpan;
1634
- };
1635
- type ObjectPathState =
1636
- /** Promised: created by a queued read that has not answered yet. */
1637
- {
1638
- readonly status: 'pending';
1639
- }
1640
- /** Addressable: the host has named this object, or the span it stands for is known. */
1641
- | {
1642
- readonly status: 'resolved';
1643
- readonly address: ObjectAddress;
1644
- }
1645
- /** A `get…OrNullObject` that found nothing. Not an error, and never addressable. */
1646
- | {
1647
- readonly status: 'null';
1648
- }
1649
- /** Its run ended without tracking it. Terminal. */
1650
- | {
1651
- readonly status: 'released';
1652
- };
1653
- declare class ObjectPath {
1654
- #private;
1655
- readonly label: string;
1656
- private constructor();
1657
- /** A path that is addressable from the moment it exists — a root, or an item just hydrated. */
1658
- static of(label: string, handle: AutomationHandle): ObjectPath;
1659
- /** The same, for an object that IS a stretch of a story. */
1660
- static ofSpan(label: string, span: AutomationSpan): ObjectPath;
1661
- /** A path a queued read will fill in — or mark null. */
1662
- static pending(label: string): ObjectPath;
1663
- /** A path that is whatever its owner's path is, under its own name. */
1664
- static derived(label: string, parent: ObjectPath): ObjectPath;
1665
- get state(): ObjectPathState;
1666
- get isAddressable(): boolean;
1667
- get isPending(): boolean;
1668
- get isNull(): boolean;
1669
- get isReleased(): boolean;
1670
- /**
1671
- * What to put in a batch, or a refusal.
1672
- *
1673
- * Both refusals are `InvalidObjectPath` on purpose: from a consumer's side "this object was
1674
- * released" and "this object is still a promise" are the same mistake — using an object the
1675
- * runtime cannot address yet or any more — and the `target` says which object it was.
1676
- *
1677
- * THE CODE IS ONE THING AND THE MESSAGE IS ANOTHER. The two states have different fixes — a
1678
- * promise needs a `sync()`, a released object needs to have been tracked — so the sentence in
1679
- * `errors.ts` names both. It described only the released half for a while, which sent a
1680
- * consumer holding a perfectly good promised object off to `trackedObjects.add(...)`.
1681
- */
1682
- address(): ObjectAddress;
1683
- /** The handle to address this object with. Refused for anything that is not handle-shaped. */
1684
- handle(): AutomationHandle;
1685
- /** The span this object stands for. Refused for anything that is not span-shaped. */
1686
- span(): AutomationSpan;
1687
- /**
1688
- * Hydration: the read answered, and this is the object it named.
1689
- *
1690
- * A released path stays released. Hydration arriving for one is not an error — a batch can be
1691
- * in flight when a run ends — but resurrecting the object would hand back a proxy whose
1692
- * lifetime rules had already been applied.
1693
- */
1694
- resolveTo(handle: AutomationHandle): void;
1695
- /** The same, for an object that came back as a stretch of a story. */
1696
- resolveToSpan(span: AutomationSpan): void;
1697
- /** Hydration: the read answered, and there was nothing there. */
1698
- resolveNull(): void;
1699
- /**
1700
- * The run ended and nothing kept this object alive. Terminal.
1701
- *
1702
- * A derived path does not release: its owner's release is what governs it, and releasing here
1703
- * would let a collection's lifetime end its parent's.
1704
- */
1705
- release(): void;
1706
- }
1707
-
1708
2136
  /**
1709
2137
  * The base every document proxy extends.
1710
2138
  *
@@ -1764,6 +2192,8 @@ declare abstract class ClientObject implements RuntimeManagedObject {
1764
2192
  * perfectly good and only needs adopting, which is what `InvalidRequestContext` says.
1765
2193
  */
1766
2194
  protected requireAddressable(): void;
2195
+ /** Permit queued read dependencies and optional scalar loads; refuse released proxies. */
2196
+ protected requireUsablePath(): void;
1767
2197
  /** @internal Add one action to the context's queue, to be planned at the next sync. */
1768
2198
  protected enqueue(action: QueuedAction): void;
1769
2199
  /** @internal Read a property a completed `load` filled in; refuses if none did. */
@@ -1787,12 +2217,8 @@ declare abstract class ClientObject implements RuntimeManagedObject {
1787
2217
  * sync fills it, and reading it early is `ValueNotLoaded` rather than `undefined` flowing onwards
1788
2218
  * into something that misinterprets it.
1789
2219
  *
1790
- * @example
1791
- * ```ts
1792
- * const count = body.getParagraphCount();
1793
- * await context.sync();
1794
- * console.log(count.value);
1795
- * ```
2220
+ * This is a support type. No current public document method produces a ClientResult.
2221
+ * Document collections expose loaded `items`; read their length after `load('items')` and `sync()`.
1796
2222
  *
1797
2223
  * @public
1798
2224
  */
@@ -1935,6 +2361,43 @@ declare class DocxEditorError extends Error {
1935
2361
  */
1936
2362
  declare function isDocxEditorError(value: unknown): value is DocxEditorError;
1937
2363
 
2364
+ /** An inert Word field. Code writes and evaluation support PAGE and NUMPAGES. @public */
2365
+ declare class Field extends ModelObject implements PromisedItem {
2366
+ #private;
2367
+ /** @internal */
2368
+ static at(context: RequestContext, label: string, address: ObjectAddress): Field;
2369
+ /** @internal */
2370
+ static promised(context: RequestContext, label: string, nullable: boolean): Field;
2371
+ private constructor();
2372
+ /** @internal */
2373
+ hydrateAddress(address: ObjectAddress): void;
2374
+ /** @internal */
2375
+ hydrateNull(): void;
2376
+ get code(): string;
2377
+ set code(value: string);
2378
+ /** Remove this field, including its cached result. Other fields remain inert and unchanged. */
2379
+ delete(): void;
2380
+ /** Compute a cached result using actual host pagination. Missing pagination refuses explicitly. */
2381
+ updateResult(): void;
2382
+ protected onLoad(request: ResolvedLoadOptions): void;
2383
+ }
2384
+ /** Fields contained within a body or range. @public */
2385
+ declare class FieldCollection extends ItemCollection<Field> {
2386
+ #private;
2387
+ /** @internal */
2388
+ static of(context: RequestContext, label: string, owner: ObjectPath, kind: SpanOwner): FieldCollection;
2389
+ private constructor();
2390
+ getFirst(): Field;
2391
+ getLast(): Field;
2392
+ getFirstOrNullObject(): Field;
2393
+ getLastOrNullObject(): Field;
2394
+ protected listing(): AutomationOperation;
2395
+ protected size(value: AutomationValue, label: string): number;
2396
+ protected addressAt(value: AutomationValue, label: string, index: number): ObjectAddress | undefined;
2397
+ protected itemAt(label: string, address: ObjectAddress): Field;
2398
+ protected promised(label: string, nullable: boolean): Field & PromisedItem;
2399
+ }
2400
+
1938
2401
  /**
1939
2402
  * A story: the main body of a document, a header or footer variant, or a note's body — and
1940
2403
  * everything in it in reading order.
@@ -2023,16 +2486,28 @@ declare class Body extends ModelObject {
2023
2486
  * resolve every store-resolvable revision in this story.
2024
2487
  */
2025
2488
  get revisions(): RevisionCollection;
2489
+ /** The whole body or one edge. Await sync before addressing the returned range. */
2490
+ getRange(rangeLocation?: 'Whole' | 'Content' | 'Start' | 'End' | 'Before' | 'After'): Range;
2026
2491
  /** Every occurrence of `searchText` in this story, as ranges, in reading order. */
2027
2492
  search(searchText: string, options?: SearchOptions): RangeCollection;
2028
2493
  /** Empty the story, leaving one empty paragraph behind. */
2029
2494
  clear(): void;
2030
2495
  /** Write text over the whole story, or at either edge of it. Answers the text's own range. */
2031
- insertText(text: string, insertLocation: 'Replace' | 'Start' | 'End'): Range;
2496
+ insertText(text: string, insertLocation: InsertLocation.replace | InsertLocation.start | InsertLocation.end | 'Replace' | 'Start' | 'End'): Range;
2032
2497
  /** Add a paragraph at the start or the end of the story. Answers the new paragraph. */
2033
- insertParagraph(paragraphText: string, insertLocation: 'Start' | 'End'): Paragraph;
2498
+ insertParagraph(paragraphText: string, insertLocation: InsertLocation.start | InsertLocation.end | 'Start' | 'End'): Paragraph;
2034
2499
  /** @internal Plan the read this object's `load(...)` asked for. */
2035
2500
  protected onLoad(request: ResolvedLoadOptions): void;
2501
+ /** Fields within this body. */
2502
+ get fields(): FieldCollection;
2503
+ /** Inline pictures within this body. */
2504
+ get inlinePictures(): InlinePictureCollection;
2505
+ /** Top-level tables within this body or table cell. */
2506
+ get tables(): TableCollection;
2507
+ }
2508
+
2509
+ /** Explicit measurement inputs for headless field calculation. @public */
2510
+ interface ServerPaginationOptions extends AutomationPaginationOptions {
2036
2511
  }
2037
2512
 
2038
2513
  /**
@@ -2089,6 +2564,8 @@ interface DocumentLimits {
2089
2564
  * @public
2090
2565
  */
2091
2566
  interface CreateServerOptions {
2567
+ /** Font-aware pagination required to calculate PAGE/NUMPAGES fields headlessly. */
2568
+ readonly pagination?: ServerPaginationOptions;
2092
2569
  /**
2093
2570
  * Capability modules to register. Collaboration attaches only through a
2094
2571
  * collaboration contribution on this list.
@@ -2120,4 +2597,4 @@ interface CreateServerOptions {
2120
2597
  /** Options for {@link createCollaborative}. @public */
2121
2598
  type CreateCollaborativeOptions = CreateServerOptions;
2122
2599
 
2123
- export { RevisionCollection as $, type DocxEditorRuntime as A, type BesideLocation as B, type CreateServerOptions as C, type DocxEditorServerRuntime as D, type EditorModule as E, Font as F, ListCollection as G, type HeaderFooterType as H, type InsertLocation as I, ListItem as J, type LoadOption as K, List as L, type LoadQueryOptions as M, NoteItem as N, NoteItemCollection as O, type NoteItemType as P, type PageOrientation as Q, PageSetup as R, Paragraph as S, type ParagraphAlignment as T, ParagraphCollection as U, type ParagraphInsertTextLocation as V, Range as W, RangeCollection as X, type RangeInsertTextLocation as Y, RequestContext as Z, Revision as _, type CreateCollaborativeOptions as a, type RevisionTextView as a0, type RevisionType as a1, type RunCallback as a2, type SearchOptions as a3, Section as a4, SectionCollection as a5, type SelectionMode as a6, TrackedObjects as a7, isDocxEditorError as a8, Body as b, type BodyInsertParagraphLocation as c, type BodyInsertTextLocation as d, Bookmark as e, BookmarkCollection as f, type ChangeTrackingMode as g, ClientObject as h, ClientResult as i, Comment as j, CommentCollection as k, CommentReply as l, CommentReplyCollection as m, ContentControl as n, ContentControlCollection as o, type ContentControlLockState as p, type ContentControlSubtype as q, type ContentControlValue as r, Document as s, type DocumentCapabilities as t, type DocumentLimits as u, type DocumentXmlLimits as v, type DocumentZipLimits as w, DocxEditorError as x, type DocxEditorErrorCode as y, type DocxEditorErrorInit as z };
2600
+ export { PageOrientation as $, Alignment as A, type BesideLocation as B, type CreateServerOptions as C, type DocxEditorServerRuntime as D, type DocxEditorErrorCode as E, type DocxEditorErrorInit as F, type DocxEditorRuntime as G, type EditorModule as H, Field as I, FieldCollection as J, FieldType as K, type FieldTypeLiteral as L, Font as M, type HeaderFooterType as N, InlinePicture as O, InlinePictureCollection as P, InsertLocation as Q, List as R, ListBullet as S, ListCollection as T, ListItem as U, ListNumbering as V, type LoadOption as W, type LoadQueryOptions as X, NoteItem as Y, NoteItemCollection as Z, type NoteItemType as _, type CreateCollaborativeOptions as a, PageSetup as a0, Paragraph as a1, type ParagraphAlignment as a2, ParagraphCollection as a3, type ParagraphInsertTextLocation as a4, Range as a5, RangeCollection as a6, type RangeInsertTextLocation as a7, RequestContext as a8, Revision as a9, RevisionCollection as aa, type RevisionTextView as ab, type RevisionType as ac, type RunCallback as ad, type SearchOptions as ae, Section as af, SectionCollection as ag, type SelectionMode as ah, type ServerPaginationOptions as ai, Table as aj, TableCell as ak, TableCellCollection as al, TableCollection as am, TableRow as an, TableRowCollection as ao, TrackedObjects as ap, UnderlineType as aq, VerticalAlignment as ar, isDocxEditorError as as, Body as b, type BodyInsertParagraphLocation as c, type BodyInsertTextLocation as d, Bookmark as e, BookmarkCollection as f, BreakType as g, ChangeTrackingMode as h, ClientObject as i, ClientResult as j, Comment as k, CommentCollection as l, CommentReply as m, CommentReplyCollection as n, ContentControl as o, ContentControlCollection as p, type ContentControlLockState as q, type ContentControlSubtype as r, ContentControlType as s, type ContentControlValue as t, Document as u, type DocumentCapabilities as v, type DocumentLimits as w, type DocumentXmlLimits as x, type DocumentZipLimits as y, DocxEditorError as z };