wordinweb 0.2.5 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/{chunk-ALLQ5KWP.js → chunk-VL6YPZSD.js} +24793 -7473
- package/dist/chunk-VL6YPZSD.js.map +1 -0
- package/dist/collab.d.ts +109 -4
- package/dist/collab.js +572 -160
- package/dist/collab.js.map +1 -1
- package/dist/{index-CGp6gVjn.d.ts → index-C_oyKJu0.d.ts} +2529 -281
- package/dist/index.d.ts +1 -1
- package/dist/index.js +19 -3
- package/package.json +1 -1
- package/dist/chunk-ALLQ5KWP.js.map +0 -1
|
@@ -123,10 +123,21 @@ interface RunProps {
|
|
|
123
123
|
raise?: number;
|
|
124
124
|
/** w:outline — hollow stroked glyphs. */
|
|
125
125
|
outline?: boolean;
|
|
126
|
+
/** w14:textOutline — glyph outline stroke (WordArt gallery styles). */
|
|
127
|
+
textOutline?: {
|
|
128
|
+
color: string;
|
|
129
|
+
width: number;
|
|
130
|
+
};
|
|
131
|
+
/** w:shadow / w14:shadow — offset glyph shadow. */
|
|
132
|
+
textShadow?: boolean;
|
|
126
133
|
/** w:emboss / w:imprint — Word triple-draws offset copies. */
|
|
127
134
|
emboss?: boolean;
|
|
128
135
|
imprint?: boolean;
|
|
129
136
|
vanish?: boolean;
|
|
137
|
+
/** w:rPr w:snapToGrid: whether this run participates in the section's
|
|
138
|
+
* docGrid. A line whose runs ALL declare 0 lays off the grid (see
|
|
139
|
+
* finishLine); ParaProps.snapToGrid covers the whole paragraph. */
|
|
140
|
+
snapToGrid?: boolean;
|
|
130
141
|
/** Character style id (w:rStyle). */
|
|
131
142
|
styleId?: string;
|
|
132
143
|
lang?: string;
|
|
@@ -308,7 +319,7 @@ interface EmbeddedObjectReference {
|
|
|
308
319
|
progId: string;
|
|
309
320
|
}
|
|
310
321
|
/** OMML equation node (subset: runs, scripts, fractions, radicals). */
|
|
311
|
-
type MathNode = {
|
|
322
|
+
type MathNode = ({
|
|
312
323
|
t: "run";
|
|
313
324
|
text: string;
|
|
314
325
|
normal?: boolean;
|
|
@@ -377,6 +388,15 @@ type MathNode = {
|
|
|
377
388
|
pos: "low" | "upp";
|
|
378
389
|
e: MathNode[];
|
|
379
390
|
lim: MathNode[];
|
|
391
|
+
}) & {
|
|
392
|
+
/**
|
|
393
|
+
* The OMML element this node was read from. Only the math EDITOR's reader
|
|
394
|
+
* (edit/math.ts) sets it; the renderer's parser leaves it undefined. Editing
|
|
395
|
+
* re-emits through it, so the properties the linear syntax does not spell
|
|
396
|
+
* out — run fonts, m:ctrlPr, a matrix's column specs, an n-ary's limit
|
|
397
|
+
* placement — survive a text edit instead of being dropped.
|
|
398
|
+
*/
|
|
399
|
+
src?: XmlElement;
|
|
380
400
|
};
|
|
381
401
|
interface MathContent {
|
|
382
402
|
kind: "math";
|
|
@@ -405,6 +425,11 @@ interface FieldContent {
|
|
|
405
425
|
* (in the fldChar begin's w:ffData). Its presence makes the rendered ballot
|
|
406
426
|
* box a click-to-toggle target; the glyph derives from its w:checked child. */
|
|
407
427
|
checkbox?: XmlElement;
|
|
428
|
+
/** The field's own XML: the `w:fldSimple`, or the `w:fldChar` begin of a
|
|
429
|
+
* complex field. The update pass (edit/update-fields.ts) writes a recomputed
|
|
430
|
+
* result back through it — layout resolves fields from this model, so
|
|
431
|
+
* without the link the computed value has nowhere to land in the file. */
|
|
432
|
+
src?: XmlElement;
|
|
408
433
|
}
|
|
409
434
|
/** What an anchored shape's coordinates are measured from. "char" (relH=
|
|
410
435
|
* "character") measures from the anchor run's pen position; "line" (relV=
|
|
@@ -420,8 +445,11 @@ interface ShapeLine {
|
|
|
420
445
|
color: string;
|
|
421
446
|
/** Stroke weight px. */
|
|
422
447
|
weight: number;
|
|
448
|
+
style?: "single" | "dotted" | "dashed";
|
|
423
449
|
hRel: AnchorRel;
|
|
424
450
|
vRel: AnchorRel;
|
|
451
|
+
/** Source VML v:line for selection and save-back editing. */
|
|
452
|
+
src?: XmlElement;
|
|
425
453
|
}
|
|
426
454
|
interface ShapeTextbox {
|
|
427
455
|
type: "textbox";
|
|
@@ -477,12 +505,18 @@ interface ShapeTextbox {
|
|
|
477
505
|
r: number;
|
|
478
506
|
b: number;
|
|
479
507
|
};
|
|
480
|
-
/** Non-rect preset geometry: paint
|
|
481
|
-
* scaled to the shape box) instead of a rectangle.
|
|
508
|
+
/** Non-rect preset geometry: paint these outline paths (in a viewW x viewH
|
|
509
|
+
* space scaled to the shape box) instead of a rectangle. Each path carries
|
|
510
|
+
* its resolved fill colour (undefined = unfilled) and whether the shape's
|
|
511
|
+
* stroke applies to it. */
|
|
482
512
|
geom?: {
|
|
483
|
-
d: string;
|
|
484
513
|
viewW: number;
|
|
485
514
|
viewH: number;
|
|
515
|
+
paths: {
|
|
516
|
+
d: string;
|
|
517
|
+
fill?: string;
|
|
518
|
+
stroke: boolean;
|
|
519
|
+
}[];
|
|
486
520
|
};
|
|
487
521
|
/** bodyPr a:noAutofit: the box does NOT grow with its text — Word hides
|
|
488
522
|
* whole lines that stick out past the shape bottom (phase23 p12 ovals:
|
|
@@ -492,6 +526,13 @@ interface ShapeTextbox {
|
|
|
492
526
|
* plus the top/bottom insets (the stored cy is only Word's last cached
|
|
493
527
|
* value). Width is fixed. */
|
|
494
528
|
autofitHeight?: boolean;
|
|
529
|
+
/** bodyPr a:normAutofit — "shrink text on overflow". The mode is recorded
|
|
530
|
+
* because the fit report names it, NOT because it changes the layout:
|
|
531
|
+
* probe-shapefit measured fourteen normAutofit shapes through desktop Word
|
|
532
|
+
* and every one paints at its authored size and clips at the box bottom,
|
|
533
|
+
* exactly like a:noAutofit. `clipText` is set alongside this and is what the
|
|
534
|
+
* layout reads. */
|
|
535
|
+
shrinkText?: boolean;
|
|
495
536
|
/** Linked text-box chain id (wps:txbx/@id or wps:linkedTxbx/@id): boxes with
|
|
496
537
|
* the same id form one story. The seq-0 box (wps:txbx) holds the content;
|
|
497
538
|
* later boxes (wps:linkedTxbx, chainSeq>0) are empty sinks that continue the
|
|
@@ -507,6 +548,10 @@ interface ShapeTextbox {
|
|
|
507
548
|
textboxStory?: boolean;
|
|
508
549
|
/** DrawingML WordArt, including the identity textNoShape preset. */
|
|
509
550
|
wordArt?: boolean;
|
|
551
|
+
/** WordArt glyph fill from w14:textFill or the fallback run color. */
|
|
552
|
+
wordArtFill?: string;
|
|
553
|
+
/** WordArt glyph alpha, 0..1. */
|
|
554
|
+
wordArtOpacity?: number;
|
|
510
555
|
/** bodyPr a:prstTxWarp preset name (textArchUp, textWave1, textChevron,
|
|
511
556
|
* textCirclePour, …): the shape's text is bent onto the preset's envelope
|
|
512
557
|
* rather than flowed as ordinary lines. "textNoShape" (no warp) is dropped. */
|
|
@@ -564,6 +609,16 @@ interface ShapeArt {
|
|
|
564
609
|
behind?: boolean;
|
|
565
610
|
/** a:xfrm rotation, degrees clockwise. */
|
|
566
611
|
rotation?: number;
|
|
612
|
+
/** wp:wrapSquare/.../wrapTopAndBottom on the anchor. Only FRAME stories
|
|
613
|
+
* (header/footer/cell) act on it - body flow ignores art wrap, as before. */
|
|
614
|
+
wrap?: WrapMode;
|
|
615
|
+
/** wp:anchor dist* in px, used with `wrap`. */
|
|
616
|
+
dist?: {
|
|
617
|
+
t: number;
|
|
618
|
+
b: number;
|
|
619
|
+
l: number;
|
|
620
|
+
r: number;
|
|
621
|
+
};
|
|
567
622
|
lines: DrawingLine[];
|
|
568
623
|
images: DrawingImage[];
|
|
569
624
|
paths: DrawingPath[];
|
|
@@ -697,16 +752,91 @@ interface DrawingContent {
|
|
|
697
752
|
* SmartArt cached-drawing shapes). Painted above lines/paths. */
|
|
698
753
|
texts?: DrawingTextShape[];
|
|
699
754
|
}
|
|
700
|
-
|
|
755
|
+
/** The c:chartSpace plot kinds the renderer paints. Anything else (3-D, radar,
|
|
756
|
+
* surface, stock, bubble) parses with `unsupported` set instead. */
|
|
757
|
+
type ChartType = "column" | "bar" | "line" | "pie" | "doughnut" | "area" | "scatter";
|
|
701
758
|
interface ChartSeries {
|
|
702
759
|
name: string;
|
|
703
760
|
values: number[];
|
|
761
|
+
/** c:xVal of a scatter series. Every other type shares one category axis,
|
|
762
|
+
* so only scatter carries per-series x values. */
|
|
763
|
+
xValues?: number[];
|
|
764
|
+
/** Explicit series fill/line from c:spPr, overriding the palette slot. */
|
|
765
|
+
color?: string;
|
|
766
|
+
/** Explicit c:dPt fills, keyed by point index (pie slices, single bars). */
|
|
767
|
+
pointColors?: Record<number, string>;
|
|
768
|
+
/** c:smooth — draw the line series through a spline instead of segments. */
|
|
769
|
+
smooth?: boolean;
|
|
770
|
+
/** c:spPr/a:ln/@w, in px. A line or scatter series says here how heavy its
|
|
771
|
+
* stroke is; a scatter series, whose stroke is optional, says it has one. */
|
|
772
|
+
lineWidth?: number;
|
|
773
|
+
/** c:marker/c:symbol, an ST_MarkerStyle name. "none" draws no marker, and a
|
|
774
|
+
* name with no shape behind it takes the series' slot in Word's sequence. */
|
|
775
|
+
markerSymbol?: string;
|
|
776
|
+
/** c:marker/c:size, the width across the marker in px. */
|
|
777
|
+
markerSize?: number;
|
|
778
|
+
}
|
|
779
|
+
type ChartTickMark = "none" | "in" | "out" | "cross";
|
|
780
|
+
/** One axis of a 2-D chart (c:catAx/c:valAx/c:dateAx). */
|
|
781
|
+
interface ChartAxis {
|
|
782
|
+
/** c:delete val="1": Word draws no line, ticks or labels for the axis. */
|
|
783
|
+
hidden?: boolean;
|
|
784
|
+
/** A c:majorGridlines child is present. */
|
|
785
|
+
gridlines?: boolean;
|
|
786
|
+
/** c:numFmt formatCode applied to the tick labels, e.g. "0.0%". */
|
|
787
|
+
format?: string;
|
|
788
|
+
title?: string;
|
|
789
|
+
/** c:scaling overrides of the automatic scale. */
|
|
790
|
+
min?: number;
|
|
791
|
+
max?: number;
|
|
792
|
+
majorUnit?: number;
|
|
793
|
+
/** c:scaling/c:orientation val="maxMin". */
|
|
794
|
+
reversed?: boolean;
|
|
795
|
+
/** c:majorTickMark / c:minorTickMark. The schema default is "out" for major
|
|
796
|
+
* and "none" for minor; Word writes both explicitly. */
|
|
797
|
+
majorTick?: ChartTickMark;
|
|
798
|
+
minorTick?: ChartTickMark;
|
|
799
|
+
/** c:tickLblPos val="none" keeps the axis but drops its labels. */
|
|
800
|
+
labels?: boolean;
|
|
801
|
+
/** c:crossBetween on a value axis, which decides where the category axis puts
|
|
802
|
+
* its points: "between" insets them by half a category (Word's choice for
|
|
803
|
+
* bar and column), "midCat" seats the first and last on the plot's edges
|
|
804
|
+
* (Word's choice for line and area). */
|
|
805
|
+
crossBetween?: "between" | "midCat";
|
|
704
806
|
}
|
|
705
807
|
interface ChartData {
|
|
706
808
|
type: ChartType;
|
|
809
|
+
/** Local name of a plot the renderer does not paint (bar3DChart, radarChart,
|
|
810
|
+
* …). When set, `type` is a placeholder and the renderer draws a labeled box
|
|
811
|
+
* rather than pretending the data is a column chart. */
|
|
812
|
+
unsupported?: string;
|
|
707
813
|
title?: string;
|
|
708
814
|
categories: string[];
|
|
709
815
|
series: ChartSeries[];
|
|
816
|
+
/** c:grouping — how bar/column/area series stack. */
|
|
817
|
+
grouping?: "clustered" | "stacked" | "percentStacked";
|
|
818
|
+
/** Legend edge. Absent when the chart has no c:legend. */
|
|
819
|
+
legend?: "l" | "r" | "t" | "b" | "tr";
|
|
820
|
+
/** c:dLbls showVal on the plot or on every series. */
|
|
821
|
+
dataLabels?: boolean;
|
|
822
|
+
/** c:varyColors — give each point of a single series its own palette slot. */
|
|
823
|
+
varyColors?: boolean;
|
|
824
|
+
categoryAxis?: ChartAxis;
|
|
825
|
+
valueAxis?: ChartAxis;
|
|
826
|
+
/** c:holeSize percent of a doughnut (Word's default is 75). */
|
|
827
|
+
holeSize?: number;
|
|
828
|
+
/** c:gapWidth percent between bar/column categories (Word's default is 150). */
|
|
829
|
+
gapWidth?: number;
|
|
830
|
+
/** c:overlap percent between bars of one category (Word: -27 clustered,
|
|
831
|
+
* 100 stacked). */
|
|
832
|
+
overlap?: number;
|
|
833
|
+
/** c:marker val="1" on a line chart: draw a point marker at each value. */
|
|
834
|
+
markers?: boolean;
|
|
835
|
+
/** Font size in px from c:title//a:defRPr@sz. Word's default title is 14pt. */
|
|
836
|
+
titleSize?: number;
|
|
837
|
+
/** Font size in px from c:txPr//a:defRPr@sz, the chart-wide text size. Word's
|
|
838
|
+
* default for axis labels, legend entries and data labels is 9pt. */
|
|
839
|
+
textSize?: number;
|
|
710
840
|
}
|
|
711
841
|
type SmartArtLayout = "process" | "cycle" | "hierarchy" | "list";
|
|
712
842
|
interface SmartArtData {
|
|
@@ -992,7 +1122,10 @@ interface SectionProps {
|
|
|
992
1122
|
right?: Border;
|
|
993
1123
|
offsetFrom: "text" | "page";
|
|
994
1124
|
};
|
|
995
|
-
/** w:lnNumType: margin line numbering. distance px from the text edge.
|
|
1125
|
+
/** w:lnNumType: margin line numbering. distance px from the text edge.
|
|
1126
|
+
* start is the raw w:start OFFSET (0 when the attribute is absent, its
|
|
1127
|
+
* literal value otherwise) added to the running per-line count — see
|
|
1128
|
+
* parse/section.ts for why an absent attribute isn't just "start 1". */
|
|
996
1129
|
lineNumbering?: {
|
|
997
1130
|
countBy: number;
|
|
998
1131
|
start: number;
|
|
@@ -1004,6 +1137,16 @@ interface SectionProps {
|
|
|
1004
1137
|
footnoteNumStart?: number;
|
|
1005
1138
|
endnoteNumFmt?: string;
|
|
1006
1139
|
endnoteNumStart?: number;
|
|
1140
|
+
/** w:numRestart: when the mark counter resets. Absent means "continuous"
|
|
1141
|
+
* (the whole document shares one counter — this engine's only honored
|
|
1142
|
+
* value; eachSect/eachPage are round-trip preserved but not laid out). */
|
|
1143
|
+
footnoteNumRestart?: "continuous" | "eachSect" | "eachPage";
|
|
1144
|
+
endnoteNumRestart?: "continuous" | "eachSect" | "eachPage";
|
|
1145
|
+
/** w:pos: where the note text is placed. Round-trip preserved only — the
|
|
1146
|
+
* layout always places footnotes at the page bottom and endnotes at the
|
|
1147
|
+
* document end, regardless of this value. */
|
|
1148
|
+
footnotePos?: "pageBottom" | "beneathText";
|
|
1149
|
+
endnotePos?: "sectEnd" | "docEnd";
|
|
1007
1150
|
/** w:textDirection tbRl: the whole section flows as East-Asian vertical
|
|
1008
1151
|
* writing — lines run top-to-bottom, progressing right-to-left. */
|
|
1009
1152
|
textDirection?: "tbRl";
|
|
@@ -1025,6 +1168,10 @@ interface DocComment {
|
|
|
1025
1168
|
paraId?: string;
|
|
1026
1169
|
/** Parent comment id when this comment is a reply (commentsExtended). */
|
|
1027
1170
|
parentId?: string;
|
|
1171
|
+
/** Thread resolved (w15:commentEx w15:done="1" — the [MS-DOCX] CT_CommentEx
|
|
1172
|
+
* extension; ECMA-376 itself has no resolved state). Meaningful on the
|
|
1173
|
+
* thread parent; Word grays the whole thread from the parent's flag. */
|
|
1174
|
+
resolved?: boolean;
|
|
1028
1175
|
}
|
|
1029
1176
|
interface HeaderFooter {
|
|
1030
1177
|
blocks: Block[];
|
|
@@ -1146,10 +1293,10 @@ declare class Package {
|
|
|
1146
1293
|
* the table is keyed by element identity and in-place XML mutation preserves
|
|
1147
1294
|
* identity across `refresh()`.
|
|
1148
1295
|
*/
|
|
1149
|
-
type StableId$
|
|
1296
|
+
type StableId$2 = number;
|
|
1150
1297
|
interface EncodedCaret {
|
|
1151
|
-
blockId: StableId$
|
|
1152
|
-
runId: StableId$
|
|
1298
|
+
blockId: StableId$2;
|
|
1299
|
+
runId: StableId$2;
|
|
1153
1300
|
/** Offset in the run's WIRE space: cumulative through the run's inline
|
|
1154
1301
|
* content in document order, where each w:t contributes its text length
|
|
1155
1302
|
* and each inline separator (w:tab / w:br / w:cr) contributes ONE unit.
|
|
@@ -1193,14 +1340,21 @@ declare class StableIds {
|
|
|
1193
1340
|
/** Explicitly assign an id to a newly created node. Local edits allocate
|
|
1194
1341
|
* (`assign(el)`); applying a replicated edit installs the carried value
|
|
1195
1342
|
* (`assign(el, carriedId)`). Carried ids must not collide. */
|
|
1196
|
-
assign(el: XmlElement, id?: StableId$
|
|
1343
|
+
assign(el: XmlElement, id?: StableId$2): StableId$2;
|
|
1197
1344
|
/** Force `el` to carry `id`, replacing any id it already has (e.g. one
|
|
1198
1345
|
* auto-assigned by a refresh() before a carried id could be installed).
|
|
1199
1346
|
* The previous id is retired. Throws if `id` is held by a different element. */
|
|
1200
|
-
reassign(el: XmlElement, id: StableId$
|
|
1347
|
+
reassign(el: XmlElement, id: StableId$2): void;
|
|
1348
|
+
/** Drop an element's mapping entirely; its id retires (never reused —
|
|
1349
|
+
* `next` stays monotonic). Used before carried-id assignment: a refresh
|
|
1350
|
+
* inside a mutation auto-assigns sequential ids to the nodes it created,
|
|
1351
|
+
* and one of those autos can equal a LATER id of the same carried batch,
|
|
1352
|
+
* which would make reassign throw on a perfectly good intent. No-op for an
|
|
1353
|
+
* unmapped element. */
|
|
1354
|
+
unassign(el: XmlElement): void;
|
|
1201
1355
|
private install;
|
|
1202
|
-
idOf(el: XmlElement): StableId$
|
|
1203
|
-
elOf(id: StableId$
|
|
1356
|
+
idOf(el: XmlElement): StableId$2 | undefined;
|
|
1357
|
+
elOf(id: StableId$2): XmlElement | undefined;
|
|
1204
1358
|
/** Drop mappings for elements no longer reachable from the given roots
|
|
1205
1359
|
* (deleted content). Keeps the table from growing across long sessions.
|
|
1206
1360
|
* Ids of dropped elements are retired, never reused. */
|
|
@@ -1210,10 +1364,10 @@ declare class StableIds {
|
|
|
1210
1364
|
* the tree: `pairs` maps originals→clones (as produced by walking original
|
|
1211
1365
|
* and cloned roots in step). Used by the reconciliation snapshot (plan
|
|
1212
1366
|
* doc 03) so a restore re-keys the table to the restored elements. */
|
|
1213
|
-
captureForClone(originalToClone: Map<XmlElement, XmlElement>): Map<StableId$
|
|
1367
|
+
captureForClone(originalToClone: Map<XmlElement, XmlElement>): Map<StableId$2, XmlElement>;
|
|
1214
1368
|
/** Replace the table wholesale from a captured mapping (restore path). */
|
|
1215
|
-
restore(fromCapture: Map<StableId$
|
|
1216
|
-
nextId(): StableId$
|
|
1369
|
+
restore(fromCapture: Map<StableId$2, XmlElement>, nextId: StableId$2): void;
|
|
1370
|
+
nextId(): StableId$2;
|
|
1217
1371
|
/**
|
|
1218
1372
|
* Export the table as `(id, path)` pairs, where a path is the structural
|
|
1219
1373
|
* location of the id'd element within the given roots: `[rootIndex,
|
|
@@ -1224,14 +1378,14 @@ declare class StableIds {
|
|
|
1224
1378
|
* consistently.
|
|
1225
1379
|
*/
|
|
1226
1380
|
exportSidecar(roots: XmlElement[]): {
|
|
1227
|
-
next: StableId$
|
|
1228
|
-
entries: [StableId$
|
|
1381
|
+
next: StableId$2;
|
|
1382
|
+
entries: [StableId$2, number[]][];
|
|
1229
1383
|
};
|
|
1230
1384
|
/** Rebuild the table from a sidecar against freshly parsed roots (the
|
|
1231
1385
|
* snapshot the sidecar was exported from). Replaces any current mappings. */
|
|
1232
1386
|
importSidecar(roots: XmlElement[], sidecar: {
|
|
1233
|
-
next: StableId$
|
|
1234
|
-
entries: [StableId$
|
|
1387
|
+
next: StableId$2;
|
|
1388
|
+
entries: [StableId$2, number[]][];
|
|
1235
1389
|
}): void;
|
|
1236
1390
|
/** Encode a caret as wire-stable addresses. `t` is the w:t (or other text
|
|
1237
1391
|
* holder) the caret sits in; the run is its nearest tracked ancestor run,
|
|
@@ -1259,6 +1413,8 @@ interface Relationship {
|
|
|
1259
1413
|
}
|
|
1260
1414
|
type Relationships = Map<string, Relationship>;
|
|
1261
1415
|
|
|
1416
|
+
/** The two note parts a document can carry — see notePartsHolding. */
|
|
1417
|
+
type NotePart = "footnotes" | "endnotes";
|
|
1262
1418
|
/**
|
|
1263
1419
|
* A fully parsed .docx: sections of blocks, styles, numbering, theme, and
|
|
1264
1420
|
* header/footer parts, with helpers to resolve effective formatting.
|
|
@@ -1279,7 +1435,7 @@ declare class DocxDocument {
|
|
|
1279
1435
|
/** Header/footer parts keyed by relationship id from document.xml.rels. */
|
|
1280
1436
|
readonly headers: Map<string, HeaderFooter>;
|
|
1281
1437
|
readonly footers: Map<string, HeaderFooter>;
|
|
1282
|
-
/** Note content by note id
|
|
1438
|
+
/** Note content by note id. */
|
|
1283
1439
|
readonly footnotes: Map<number, Block[]>;
|
|
1284
1440
|
readonly endnotes: Map<number, Block[]>;
|
|
1285
1441
|
/** The separator paragraph controls the gap between its rule and the first
|
|
@@ -1292,11 +1448,23 @@ declare class DocxDocument {
|
|
|
1292
1448
|
readonly documentRels: Relationships;
|
|
1293
1449
|
/** settings.xml w:evenAndOddHeaders — enables the "even" header/footer variants. */
|
|
1294
1450
|
readonly evenAndOddHeaders: boolean;
|
|
1451
|
+
/** settings.xml w:autoHyphenation (§17.15.1.10). This engine's layout does
|
|
1452
|
+
* not hyphenate automatically — the setting is round-trip state that
|
|
1453
|
+
* governs Word's own rendering of the document. */
|
|
1454
|
+
readonly autoHyphenation: boolean;
|
|
1455
|
+
/** settings.xml w:hyphenationZone/@w:val in twips (§17.15.1.53); null when
|
|
1456
|
+
* the document does not declare one (Word defaults to 360 = 0.25"). */
|
|
1457
|
+
readonly hyphenationZoneTwips: number | null;
|
|
1458
|
+
/** settings.xml w:doNotHyphenateCaps (§17.15.1.41). */
|
|
1459
|
+
readonly doNotHyphenateCaps: boolean;
|
|
1295
1460
|
/** settings.xml w:mirrorMargins — facing-page (book fold) margins: even
|
|
1296
1461
|
* (verso) pages swap the left/right margins and place the gutter on the
|
|
1297
1462
|
* inside (right) edge so the binding margin stays on the inner side of
|
|
1298
1463
|
* each spread. */
|
|
1299
1464
|
readonly mirrorMargins: boolean;
|
|
1465
|
+
/** settings.xml w:compat w:suppressTopSpacing: the first line of a page
|
|
1466
|
+
* takes its character height, not its authored (exact) line spacing. */
|
|
1467
|
+
readonly suppressTopSpacing: boolean;
|
|
1300
1468
|
/** settings.xml w:defaultTabStop in px (Word default 0.5"). */
|
|
1301
1469
|
readonly defaultTabStop: number;
|
|
1302
1470
|
/** settings.xml w:compat compatibilityMode (12=Word2007, 14=Word2010,
|
|
@@ -1305,6 +1473,12 @@ declare class DocxDocument {
|
|
|
1305
1473
|
* it (nccih: a Heading1/2 after a page break sits at margin + its before).
|
|
1306
1474
|
* Absent → treated as current (15). */
|
|
1307
1475
|
readonly compatibilityMode: number;
|
|
1476
|
+
/** The compatibilityMode settings.xml actually declares, or undefined when
|
|
1477
|
+
* the setting (or settings.xml itself) is missing. `compatibilityMode`
|
|
1478
|
+
* defaults an omitted value to 15, but a table's percentage width needs the
|
|
1479
|
+
* distinction: Word fits the horizontal cell margins inside the table box at
|
|
1480
|
+
* an EXPLICIT 15 and adds them around it when the setting is absent. */
|
|
1481
|
+
readonly declaredCompatibilityMode: number | undefined;
|
|
1308
1482
|
/** settings.xml m:mathPr/m:defJc — default justification for display
|
|
1309
1483
|
* equations whose m:oMathParaPr carries no explicit m:jc (Word default:
|
|
1310
1484
|
* centerGroup — the rows of a broken equation left-align to each other and
|
|
@@ -1340,6 +1514,31 @@ declare class DocxDocument {
|
|
|
1340
1514
|
private footnotesRoot;
|
|
1341
1515
|
private footnotesDirty;
|
|
1342
1516
|
private footnotesRels;
|
|
1517
|
+
/** Retained endnotes.xml tree (endnote insertion + save round-trip). */
|
|
1518
|
+
private endnotesPart;
|
|
1519
|
+
private endnotesRoot;
|
|
1520
|
+
private endnotesDirty;
|
|
1521
|
+
private endnotesRels;
|
|
1522
|
+
/** Retained bibliography sources part (the customXml b:Sources data of
|
|
1523
|
+
* ECMA-376 §22.6), when present. Source-management editing mutates this
|
|
1524
|
+
* tree in place; a document with none gets the part on first create. */
|
|
1525
|
+
private sourcesPart;
|
|
1526
|
+
private sourcesRoot;
|
|
1527
|
+
private sourcesDirty;
|
|
1528
|
+
/** Companion parts written when THIS session created the sources part
|
|
1529
|
+
* (itemProps + its .rels); an arriving part keeps its own companions. */
|
|
1530
|
+
private sourcesAux;
|
|
1531
|
+
/** Retained glossary document part (word/glossary/document.xml, ECMA-376
|
|
1532
|
+
* §17.12: glossaryDocument/docParts/docPart — Word's Quick Parts / Building
|
|
1533
|
+
* Blocks store), when present. Building-block editing mutates this tree in
|
|
1534
|
+
* place; a document with none gets the part on first create. Unlike
|
|
1535
|
+
* headers/footers, a docPart's body is never caret-editable — it is only
|
|
1536
|
+
* ever cloned INTO the main document body (insertBuildingBlock) or captured
|
|
1537
|
+
* OUT of a selection (createBuildingBlock) — so this part carries no
|
|
1538
|
+
* editableRoots()/stable-id integration of its own. */
|
|
1539
|
+
private glossaryPart;
|
|
1540
|
+
private glossaryRoot;
|
|
1541
|
+
private glossaryDirty;
|
|
1343
1542
|
/** Serialize retained optional parts only once actually mutated, keeping
|
|
1344
1543
|
* untouched parts byte-identical through save(). */
|
|
1345
1544
|
private stylesDirty;
|
|
@@ -1462,12 +1661,80 @@ declare class DocxDocument {
|
|
|
1462
1661
|
*/
|
|
1463
1662
|
numberingTree(create?: boolean): XmlElement | null;
|
|
1464
1663
|
markNumberingChanged(): void;
|
|
1664
|
+
/** Retained styles.xml tree, or null when the package has no styles part.
|
|
1665
|
+
* Style-definition editing mutates this tree in place. */
|
|
1666
|
+
stylesTree(): XmlElement | null;
|
|
1667
|
+
/**
|
|
1668
|
+
* Re-resolve the style cascade after a definition changed in place.
|
|
1669
|
+
*
|
|
1670
|
+
* A style definition is not addressed by any paragraph's XML, so mutating one
|
|
1671
|
+
* changes how EVERY paragraph resolves without changing a single w:p. Two
|
|
1672
|
+
* things therefore have to be reset by hand: the parsed Styles map every
|
|
1673
|
+
* effective-props call reads, and layoutGlobalSig, which is what makes the
|
|
1674
|
+
* line-break cache treat cached breaks for unchanged paragraph XML as stale.
|
|
1675
|
+
*/
|
|
1676
|
+
markStylesChanged(): void;
|
|
1677
|
+
/**
|
|
1678
|
+
* Retained bibliography sources tree (b:Sources), or null when the package
|
|
1679
|
+
* has no sources part. With create=true, a missing part is created and
|
|
1680
|
+
* registered the way Word lays one out (ECMA-376 §22.6 + Part 2 custom XML
|
|
1681
|
+
* data storage): the data itself as customXml/itemN.xml, a datastore-item
|
|
1682
|
+
* properties part (itemPropsN.xml) declaring the Bibliography schema URI as
|
|
1683
|
+
* its schemaRef, a .rels from the item to its properties, a customXml
|
|
1684
|
+
* relationship from the main document part, and the content-type overrides.
|
|
1685
|
+
*
|
|
1686
|
+
* DETERMINISM. Everything written is a pure function of the package —
|
|
1687
|
+
* the item number is the first free one, and the datastore itemID GUID is a
|
|
1688
|
+
* fixed constant rather than Word's random draw — so two replicas creating
|
|
1689
|
+
* the part through the same sequenced operation write identical bytes.
|
|
1690
|
+
*/
|
|
1691
|
+
sourcesTree(create?: boolean): XmlElement | null;
|
|
1692
|
+
/**
|
|
1693
|
+
* Invalidate what a sources-part edit changes downstream. Like
|
|
1694
|
+
* markStylesChanged, the part is addressed by no paragraph's XML: a
|
|
1695
|
+
* CITATION field's painted text resolves from the part at layout, so the
|
|
1696
|
+
* layout signature has to drop for unchanged paragraph XML to repaint.
|
|
1697
|
+
*/
|
|
1698
|
+
markSourcesChanged(): void;
|
|
1699
|
+
/**
|
|
1700
|
+
* Retained glossary document tree (w:glossaryDocument), or null when the
|
|
1701
|
+
* package has no glossary part. With create=true, a missing part is
|
|
1702
|
+
* created and registered — package part, document relationship,
|
|
1703
|
+
* content-type override — the createNotesPart discipline.
|
|
1704
|
+
*
|
|
1705
|
+
* The glossary part gets none of the sources part's companion machinery
|
|
1706
|
+
* (no datastore item, no random itemID): it is an ordinary WordprocessingML
|
|
1707
|
+
* part named by relationship TYPE, so creation just mints an empty
|
|
1708
|
+
* `<w:glossaryDocument><w:docParts/></w:glossaryDocument>` and wires it up
|
|
1709
|
+
* — closer to createNotesPart than to sourcesTree. A real Word-authored
|
|
1710
|
+
* glossary part additionally carries its own styles.xml / settings.xml /
|
|
1711
|
+
* fontTable.xml; this engine writes none of them, because a docPart's
|
|
1712
|
+
* content is read once — to clone its blocks into the main document, where
|
|
1713
|
+
* they resolve styles against the MAIN document's own styles.xml — and is
|
|
1714
|
+
* never laid out or rendered as its own story the way a header/footer is.
|
|
1715
|
+
*
|
|
1716
|
+
* DETERMINISM: nothing here depends on Word's random draws (no GUID is
|
|
1717
|
+
* written at all — w:docPartPr/w:guid is optional and this engine never
|
|
1718
|
+
* reads it back), so two replicas creating the part through the same
|
|
1719
|
+
* sequenced operation write identical bytes.
|
|
1720
|
+
*/
|
|
1721
|
+
glossaryTree(create?: boolean): XmlElement | null;
|
|
1722
|
+
/** Invalidate what a glossary-part edit changes: nothing downstream, since
|
|
1723
|
+
* createBuildingBlock/deleteBuildingBlock touch only the glossary tree, not
|
|
1724
|
+
* any paragraph the layout reads. Exists for the same "explicit intent to
|
|
1725
|
+
* persist" reason markSourcesChanged does. */
|
|
1726
|
+
markGlossaryChanged(): void;
|
|
1465
1727
|
/**
|
|
1466
1728
|
* Retained footnotes tree. With create=true, a missing footnotes.xml part
|
|
1467
1729
|
* is created and registered (with Word's required separator footnotes) so
|
|
1468
1730
|
* inserted footnotes serialize and round-trip.
|
|
1469
1731
|
*/
|
|
1470
1732
|
footnotesTree(create?: boolean): XmlElement | null;
|
|
1733
|
+
/** Retained endnotes tree; the endnote mirror of footnotesTree. */
|
|
1734
|
+
endnotesTree(create?: boolean): XmlElement | null;
|
|
1735
|
+
/** Register a new notes part in document.xml.rels and [Content_Types].xml,
|
|
1736
|
+
* and return the part path. The tree itself is the caller's. */
|
|
1737
|
+
private createNotesPart;
|
|
1471
1738
|
/**
|
|
1472
1739
|
* Create an empty header/footer part (with a default-type reference in
|
|
1473
1740
|
* every sectPr) when the document has none - Word does this implicitly the
|
|
@@ -1482,7 +1749,29 @@ declare class DocxDocument {
|
|
|
1482
1749
|
* whether an ensureHeaderFooter intent has anything to do). */
|
|
1483
1750
|
hasHfPart(kind: "header" | "footer"): boolean;
|
|
1484
1751
|
ensureHfPart(kind: "header" | "footer"): XmlElement;
|
|
1752
|
+
/** A w:headerReference / w:footerReference element. */
|
|
1753
|
+
private hfReference;
|
|
1754
|
+
/** Materialize the default body-level sectPr when the document declares no
|
|
1755
|
+
* section properties at all (schema: the body's sectPr is its LAST child). */
|
|
1756
|
+
private ensureBodySectPr;
|
|
1757
|
+
/**
|
|
1758
|
+
* Give every section a header and footer reference of the given variant
|
|
1759
|
+
* type, creating one empty part per band the way Word does the first time
|
|
1760
|
+
* "different first page" (type "first") or "different odd & even pages"
|
|
1761
|
+
* (type "even") is enabled. Sections that already carry a reference of the
|
|
1762
|
+
* type keep it — and its part's content. True when anything was added.
|
|
1763
|
+
*/
|
|
1764
|
+
ensureHfVariantParts(type: "first" | "even"): boolean;
|
|
1765
|
+
/** Create and register a new empty header/footer part — package part,
|
|
1766
|
+
* document relationship, content-type override, hfParts entry — with no
|
|
1767
|
+
* section references of its own; the caller decides which sectPrs point at
|
|
1768
|
+
* it and with which w:type. */
|
|
1769
|
+
private createHfPart;
|
|
1485
1770
|
markFootnotesChanged(): void;
|
|
1771
|
+
markEndnotesChanged(): void;
|
|
1772
|
+
/** Re-derive both id -> blocks maps from the retained trees, so layout sees
|
|
1773
|
+
* an inserted or edited note. */
|
|
1774
|
+
private rederiveNotes;
|
|
1486
1775
|
/** Called by comment edit commands after mutating the comments tree. */
|
|
1487
1776
|
markCommentsChanged(): void;
|
|
1488
1777
|
/**
|
|
@@ -1498,23 +1787,78 @@ declare class DocxDocument {
|
|
|
1498
1787
|
* nearest preceding w:t.
|
|
1499
1788
|
*/
|
|
1500
1789
|
commentAnchors(): Map<string, XmlElement[]>;
|
|
1501
|
-
/** Flag
|
|
1502
|
-
* re-serializes footnotes.xml. Called by the editor after a
|
|
1503
|
-
* no-op for body/header/footer targets. */
|
|
1790
|
+
/** Flag a notes part dirty when `t` lives inside it, so save()
|
|
1791
|
+
* re-serializes footnotes.xml / endnotes.xml. Called by the editor after a
|
|
1792
|
+
* text edit; a no-op for body/header/footer targets. */
|
|
1504
1793
|
markDirtyIfFootnote(t: XmlElement): void;
|
|
1794
|
+
/**
|
|
1795
|
+
* Which note parts hold `el` right now. An operation that DETACHES `el` —
|
|
1796
|
+
* accepting or rejecting a revision, for one — has to ask BEFORE it mutates
|
|
1797
|
+
* and mark the answer afterwards: a detached element belongs to no part, so
|
|
1798
|
+
* a containment test run after the fact reports nothing and save() then
|
|
1799
|
+
* leaves the stale footnotes.xml / endnotes.xml in the package.
|
|
1800
|
+
*/
|
|
1801
|
+
notePartsHolding(el: XmlElement): NotePart[];
|
|
1802
|
+
/** Flag the given note parts dirty, so save() re-serializes exactly those. */
|
|
1803
|
+
markNotePartsChanged(parts: readonly NotePart[]): void;
|
|
1505
1804
|
/** The mutable XML roots (document body, related modeled parts, settings).
|
|
1506
1805
|
* settingsRoot is always second and always present so its history snapshot
|
|
1507
1806
|
* index stays stable even when optional related roots are created later. */
|
|
1508
1807
|
editableRoots(): XmlElement[];
|
|
1808
|
+
/** CT_Settings children that precede w:mirrorMargins in the schema sequence
|
|
1809
|
+
* (§17.15.1.78). Insertions go before the first child that is not a
|
|
1810
|
+
* predecessor, so Word never has to repair settings.xml. */
|
|
1811
|
+
private static readonly SETTINGS_BEFORE_MIRROR;
|
|
1812
|
+
/** The schema predecessors of w:evenAndOddHeaders (§17.10.1): everything up
|
|
1813
|
+
* to mirrorMargins, then the sequence through defaultTableStyle. */
|
|
1814
|
+
private static readonly SETTINGS_BEFORE_EVEN_AND_ODD;
|
|
1815
|
+
/** Set or remove one settings.xml element at its schema position. Null
|
|
1816
|
+
* removes; otherwise the element is (re)inserted before the first child
|
|
1817
|
+
* that is not a schema predecessor. */
|
|
1818
|
+
private setSettingsElement;
|
|
1819
|
+
/** Set or remove one on/off settings.xml toggle at its schema position. */
|
|
1820
|
+
private setSettingsToggle;
|
|
1821
|
+
/** The schema predecessors of w:autoHyphenation: everything through
|
|
1822
|
+
* w:defaultTabStop (§17.15.1.78). Its cluster mates append in order. */
|
|
1823
|
+
private static readonly SETTINGS_BEFORE_AUTO_HYPHENATION;
|
|
1824
|
+
/**
|
|
1825
|
+
* Patch the hyphenation settings (w:autoHyphenation §17.15.1.10,
|
|
1826
|
+
* w:hyphenationZone §17.15.1.53, w:doNotHyphenateCaps §17.15.1.41). Each
|
|
1827
|
+
* present key is written; `zoneTwips: null` removes the zone element. True
|
|
1828
|
+
* when anything changed — the honest no-op a replicated document-scoped
|
|
1829
|
+
* operation needs. This engine's layout does not hyphenate automatically;
|
|
1830
|
+
* the settings govern Word's own rendering of the file.
|
|
1831
|
+
*/
|
|
1832
|
+
setHyphenation(patch: {
|
|
1833
|
+
auto?: boolean;
|
|
1834
|
+
zoneTwips?: number | null;
|
|
1835
|
+
noCaps?: boolean;
|
|
1836
|
+
}): boolean;
|
|
1509
1837
|
/** Toggle the document-global facing-page margin mode in settings.xml. */
|
|
1510
1838
|
setMirrorMargins(enabled: boolean): void;
|
|
1839
|
+
/** Toggle w:evenAndOddHeaders (§17.10.1) — the document-global switch that
|
|
1840
|
+
* makes even pages use the "even" header/footer variants. */
|
|
1841
|
+
setEvenAndOddHeaders(enabled: boolean): void;
|
|
1842
|
+
/** Register settings.xml in document.xml.rels and [Content_Types].xml when
|
|
1843
|
+
* the package was born without it (a minimal document). */
|
|
1844
|
+
private registerSettingsPart;
|
|
1511
1845
|
/**
|
|
1512
1846
|
* Find the parent element of `target` in any modeled XML tree (document
|
|
1513
1847
|
* body, headers, footers). Linear scan — documents are small and this only
|
|
1514
1848
|
* runs on structural edits (Enter, paragraph merge).
|
|
1515
1849
|
*/
|
|
1516
|
-
/**
|
|
1850
|
+
/** The header part roots, in package order. A watermark is authored into
|
|
1851
|
+
* every one of them: Word paints it on every page, and a document with a
|
|
1852
|
+
* first-page or even-page header has more than one header part. */
|
|
1853
|
+
headerRoots(): XmlElement[];
|
|
1854
|
+
/** The footer part roots, in package order — headerRoots' counterpart, for
|
|
1855
|
+
* operations that walk both bands (the page-number gallery's removal
|
|
1856
|
+
* sweep). */
|
|
1857
|
+
footerRoots(): XmlElement[];
|
|
1858
|
+
/** XML roots that can carry tracked changes: body, headers/footers, notes. */
|
|
1517
1859
|
revisionRoots(): XmlElement[];
|
|
1860
|
+
/** Body, header/footer and note roots — every tree the caret can reach. */
|
|
1861
|
+
private contentRoots;
|
|
1518
1862
|
/**
|
|
1519
1863
|
* Memoized child→parent links. Nothing invalidates this map — the tree is
|
|
1520
1864
|
* spliced constantly — so every answer is RE-DERIVED before it is returned:
|
|
@@ -1561,6 +1905,27 @@ declare class DocxDocument {
|
|
|
1561
1905
|
saveAsync(): Promise<Uint8Array>;
|
|
1562
1906
|
private buildPackage;
|
|
1563
1907
|
private buildPackageFiles;
|
|
1908
|
+
/**
|
|
1909
|
+
* Leave out the chart parts the document no longer references.
|
|
1910
|
+
*
|
|
1911
|
+
* Deleting a chart splices its w:drawing out of the story, but the chart
|
|
1912
|
+
* part, its rels part, its embedded workbook, the document relationship, and
|
|
1913
|
+
* the two [Content_Types].xml overrides all stay. An agent that inserts a
|
|
1914
|
+
* chart, deletes it, and inserts a replacement therefore saves TWO chart
|
|
1915
|
+
* parts for the one chart the document shows.
|
|
1916
|
+
*
|
|
1917
|
+
* The release happens here, at save time, rather than when the drawing goes,
|
|
1918
|
+
* because undo restores the drawing XML — r:id and all — from a snapshot
|
|
1919
|
+
* that models package parts but no relationship state. Dropping the
|
|
1920
|
+
* relationship early would make undo produce a chart pointing at nothing.
|
|
1921
|
+
* The live tree keeps everything; only the written bytes lose the orphans,
|
|
1922
|
+
* and the saveJournal puts back the two trees this touches.
|
|
1923
|
+
*
|
|
1924
|
+
* Relationship ids are scoped to the part that owns the rels file, so the
|
|
1925
|
+
* document body is the only place that can reference these ids, and reading
|
|
1926
|
+
* it is a complete check. Headers, footers, and notes carry their own rels.
|
|
1927
|
+
*/
|
|
1928
|
+
private dropOrphanChartParts;
|
|
1564
1929
|
/** Fresh unique docPr id for inserted drawings. Seeded once past the
|
|
1565
1930
|
* highest id already present in any editable root (floor 1000, matching
|
|
1566
1931
|
* the historical seed for documents with no drawings) so a document that
|
|
@@ -1580,6 +1945,23 @@ declare class DocxDocument {
|
|
|
1580
1945
|
addHyperlinkRel(url: string): string;
|
|
1581
1946
|
/** Retarget an existing external relationship (hyperlink href edit). */
|
|
1582
1947
|
setRelTarget(relId: string, url: string): boolean;
|
|
1948
|
+
/** The relationships of the part that holds `source`: a header or footer
|
|
1949
|
+
* part when the element is inside one, else the document part. */
|
|
1950
|
+
private imageRelsOwner;
|
|
1951
|
+
/** Add an image relationship pointing at `part`, in the relationships of
|
|
1952
|
+
* whichever part holds `source`. */
|
|
1953
|
+
private addImageRel;
|
|
1954
|
+
/**
|
|
1955
|
+
* Point a SECOND part at an image part this document already has.
|
|
1956
|
+
*
|
|
1957
|
+
* Word's picture watermark is ONE media part that every header part
|
|
1958
|
+
* references. Registering the image again per header would put a full copy
|
|
1959
|
+
* of the bytes in the package for each one — three headers, three copies of
|
|
1960
|
+
* the same logo — and give the media-install path three pending parts to
|
|
1961
|
+
* fill from one upload.
|
|
1962
|
+
*/
|
|
1963
|
+
linkImageResource(part: string, source: XmlElement): string;
|
|
1964
|
+
private addImageResourceAt;
|
|
1583
1965
|
addImageResource(bytes: Uint8Array, ext: string): string;
|
|
1584
1966
|
/** Add a GLB model part and its Office 2019 model3d relationship. */
|
|
1585
1967
|
addModel3DResource(bytes: Uint8Array): {
|
|
@@ -1652,7 +2034,16 @@ declare class DocxDocument {
|
|
|
1652
2034
|
registerPendingImage(sha: string, ext: string, meta?: {
|
|
1653
2035
|
iv?: string;
|
|
1654
2036
|
genesisId?: string;
|
|
1655
|
-
}): string;
|
|
2037
|
+
}, source?: XmlElement): string;
|
|
2038
|
+
/** As registerPendingImage, and also names the part it made — what a second
|
|
2039
|
+
* part needs to reach the same image through linkImageResource. */
|
|
2040
|
+
registerPendingImagePart(sha: string, ext: string, meta?: {
|
|
2041
|
+
iv?: string;
|
|
2042
|
+
genesisId?: string;
|
|
2043
|
+
}, source?: XmlElement): {
|
|
2044
|
+
relId: string;
|
|
2045
|
+
part: string;
|
|
2046
|
+
};
|
|
1656
2047
|
/** Install fetched bytes into a pending part (doc 05). The caller has
|
|
1657
2048
|
* ALREADY verified the sha against the intent's declaration (the
|
|
1658
2049
|
* reservation is the hash commitment — doc 16 §1.1); this installs and
|
|
@@ -1773,6 +2164,11 @@ interface TextItem {
|
|
|
1773
2164
|
href?: string;
|
|
1774
2165
|
/** Present for editable text (absent on numbering labels etc.). */
|
|
1775
2166
|
src?: TextSource;
|
|
2167
|
+
/** This line is one a fixed-size text box hides past its bottom edge (see
|
|
2168
|
+
* LaidOutPage.hiddenText). It mounts unpainted so a caret can bind to it, so
|
|
2169
|
+
* anything that draws from item geometry — selection, comment highlights —
|
|
2170
|
+
* must skip it or it paints a block where there is no text. */
|
|
2171
|
+
hidden?: true;
|
|
1776
2172
|
/** Source drawing when this text belongs to an independently editable
|
|
1777
2173
|
* text-box story. */
|
|
1778
2174
|
textboxStory?: XmlElement;
|
|
@@ -1788,6 +2184,8 @@ interface TextItem {
|
|
|
1788
2184
|
* layers in-front shapes above the text layer). */
|
|
1789
2185
|
front?: boolean;
|
|
1790
2186
|
z?: number;
|
|
2187
|
+
/** Paint-only alpha for decorative text such as DrawingML WordArt. */
|
|
2188
|
+
opacity?: number;
|
|
1791
2189
|
/** Right-to-left run: renderer sets direction:rtl so the browser shapes and
|
|
1792
2190
|
* orders the (Arabic/Hebrew) glyphs within the span box. */
|
|
1793
2191
|
rtl?: boolean;
|
|
@@ -1898,6 +2296,28 @@ interface ChartItem {
|
|
|
1898
2296
|
height: number;
|
|
1899
2297
|
data: ChartData;
|
|
1900
2298
|
}
|
|
2299
|
+
/** bodyPr autofit mode: how a shape reconciles its text with its box.
|
|
2300
|
+
* "resizeShape" is a:spAutoFit (grow the box), "shrinkText" is a:normAutofit
|
|
2301
|
+
* (scale the text down), "none" is a:noAutofit or no bodyPr autofit at all. */
|
|
2302
|
+
type ShapeAutofit = "none" | "resizeShape" | "shrinkText";
|
|
2303
|
+
/** What a text-bearing shape's laid-out text measured, beside the frame that
|
|
2304
|
+
* holds it. The layout already measures the text to place it; recording the
|
|
2305
|
+
* measurement here is what lets an agent see whether the text fits without
|
|
2306
|
+
* re-measuring anything. */
|
|
2307
|
+
interface DrawingTextFit {
|
|
2308
|
+
/** Widest laid line, px (the text extent, not the box). It can exceed the
|
|
2309
|
+
* box's inset width by a trailing space or an unbreakable token. */
|
|
2310
|
+
textW: number;
|
|
2311
|
+
/** Full laid text height, px. */
|
|
2312
|
+
textH: number;
|
|
2313
|
+
/** The text is taller than the box's insets leave room for. Overflow is a
|
|
2314
|
+
* vertical question: the text is wrapped to the box width by construction,
|
|
2315
|
+
* and a token too wide to wrap spends its excess on extra LINES. */
|
|
2316
|
+
overflow: boolean;
|
|
2317
|
+
/** Lines the box hides because they fall past its bottom. */
|
|
2318
|
+
clippedLines: number;
|
|
2319
|
+
autofit: ShapeAutofit;
|
|
2320
|
+
}
|
|
1901
2321
|
/** Interactive resize zone over a table boundary (column or row). */
|
|
1902
2322
|
interface DrawingHitItem {
|
|
1903
2323
|
kind: "drawingHit";
|
|
@@ -1931,6 +2351,9 @@ interface DrawingHitItem {
|
|
|
1931
2351
|
behind?: boolean;
|
|
1932
2352
|
/** The drawing owns an independently editable text-box story. */
|
|
1933
2353
|
textboxStory?: boolean;
|
|
2354
|
+
/** Measured text extent for a text-bearing shape (agent fit inspection).
|
|
2355
|
+
* Absent on drawings that flow no text: pictures, lines, charts, WordArt. */
|
|
2356
|
+
textFit?: DrawingTextFit;
|
|
1934
2357
|
rotate?: {
|
|
1935
2358
|
deg: number;
|
|
1936
2359
|
ox: number;
|
|
@@ -2000,6 +2423,15 @@ interface WarpTextItem {
|
|
|
2000
2423
|
italic?: boolean;
|
|
2001
2424
|
/** CSS text color. */
|
|
2002
2425
|
fill: string;
|
|
2426
|
+
/** WordArt glyph alpha, 0..1. */
|
|
2427
|
+
opacity?: number;
|
|
2428
|
+
/** w14:textOutline glyph stroke. */
|
|
2429
|
+
outline?: {
|
|
2430
|
+
color: string;
|
|
2431
|
+
width: number;
|
|
2432
|
+
};
|
|
2433
|
+
/** w14:shadow / w:shadow offset glyph shadow. */
|
|
2434
|
+
shadow?: boolean;
|
|
2003
2435
|
/** Preset name (textArchUp, textWave1, textChevron, textCirclePour, …). */
|
|
2004
2436
|
warp: string;
|
|
2005
2437
|
rotate?: {
|
|
@@ -2032,6 +2464,24 @@ interface LaidOutPage {
|
|
|
2032
2464
|
colXs: number[];
|
|
2033
2465
|
colWidths: number[];
|
|
2034
2466
|
}>;
|
|
2467
|
+
/** Lines a fixed-size text box (a:noAutofit) hides past its bottom edge.
|
|
2468
|
+
* Held apart from `items` so nothing that paints, measures, or reads the
|
|
2469
|
+
* page picks them up: they exist only so a caret that lands in the hidden
|
|
2470
|
+
* part of a text-box story still has a place to be. */
|
|
2471
|
+
hiddenText?: TextItem[];
|
|
2472
|
+
}
|
|
2473
|
+
/** Internal page-model window used by the DOM virtualizer. */
|
|
2474
|
+
interface LayoutWindow {
|
|
2475
|
+
/** Ensure that each requested page has a complete positioned item model. */
|
|
2476
|
+
materialize(pageIndexes: Iterable<number>): void;
|
|
2477
|
+
/** Release positioned items outside the requested page window. */
|
|
2478
|
+
releaseExcept(pageIndexes: Iterable<number>): void;
|
|
2479
|
+
/** Return the pages whose positioned items are retained. */
|
|
2480
|
+
retainedPages(): Set<number>;
|
|
2481
|
+
}
|
|
2482
|
+
interface LayoutFontSample {
|
|
2483
|
+
font: FontSpec;
|
|
2484
|
+
text: string;
|
|
2035
2485
|
}
|
|
2036
2486
|
interface LayoutResult {
|
|
2037
2487
|
pages: LaidOutPage[];
|
|
@@ -2050,6 +2500,12 @@ interface LayoutResult {
|
|
|
2050
2500
|
/** Opaque page state used to refresh headers/footers without repaginating
|
|
2051
2501
|
* the body when their measured geometry is unchanged. */
|
|
2052
2502
|
_hf?: unknown;
|
|
2503
|
+
/** Internal positioned-model window. */
|
|
2504
|
+
_window?: LayoutWindow;
|
|
2505
|
+
/** Font samples collected before offscreen page items were released. */
|
|
2506
|
+
_fontSamples?: LayoutFontSample[];
|
|
2507
|
+
/** True when any page contains a 3D model item. */
|
|
2508
|
+
_hasModel3D?: boolean;
|
|
2053
2509
|
}
|
|
2054
2510
|
|
|
2055
2511
|
interface FontMetrics {
|
|
@@ -2085,8 +2541,18 @@ interface TextMeasurer {
|
|
|
2085
2541
|
} | undefined;
|
|
2086
2542
|
}
|
|
2087
2543
|
|
|
2544
|
+
/** One mail-merge data record: column name → this record's value. The host
|
|
2545
|
+
* parses the data file and hands over plain strings; the engine never learns a
|
|
2546
|
+
* path, a connection string or a query. */
|
|
2547
|
+
type MergeRecord = Readonly<Record<string, string>>;
|
|
2088
2548
|
interface LayoutOptions {
|
|
2089
2549
|
measurer?: TextMeasurer;
|
|
2550
|
+
/** Retain positioned items only for a viewport-sized page window. */
|
|
2551
|
+
windowModel?: boolean;
|
|
2552
|
+
/** Mail-merge PREVIEW: the active record's column values, substituted into
|
|
2553
|
+
* MERGEFIELD fields as they are painted. Nothing is written to the document —
|
|
2554
|
+
* see FieldContext.mergeField. Absent renders the «Name» placeholders. */
|
|
2555
|
+
mergeRecord?: MergeRecord;
|
|
2090
2556
|
/** Previous layout result (from an earlier layoutDocument call on the same
|
|
2091
2557
|
* document). Enables incremental relayout: pages whose input blocks and
|
|
2092
2558
|
* lead-in state are unchanged are reused instead of re-laid. The engine falls
|
|
@@ -2129,6 +2595,15 @@ interface RenderOptions {
|
|
|
2129
2595
|
/** Called when the user submits a reply from a balloon's reply box. The
|
|
2130
2596
|
* reply box only renders when this is provided. */
|
|
2131
2597
|
onReplyComment?: (id: string, text: string) => void;
|
|
2598
|
+
/** Called when the user resolves (true) or reopens (false) a thread from
|
|
2599
|
+
* its balloon. The button only renders when this is provided. */
|
|
2600
|
+
onResolveComment?: (id: string, resolved: boolean) => void;
|
|
2601
|
+
/** Called when the user commits an in-balloon edit of a comment's text.
|
|
2602
|
+
* Offered only on comments whose author matches `commentAuthor`. */
|
|
2603
|
+
onEditComment?: (id: string, text: string) => void;
|
|
2604
|
+
/** The local user's comment author name — gates the edit affordance to
|
|
2605
|
+
* their own comments (Word's edit-my-comment rule). */
|
|
2606
|
+
commentAuthor?: string;
|
|
2132
2607
|
}
|
|
2133
2608
|
interface TextBinding {
|
|
2134
2609
|
el: HTMLElement;
|
|
@@ -2210,6 +2685,48 @@ declare function renderToDom(doc: DocxDocument, layout: LayoutResult, container:
|
|
|
2210
2685
|
*/
|
|
2211
2686
|
declare function printPages(root: HTMLElement, pageWidthPx: number, pageHeightPx: number): void;
|
|
2212
2687
|
|
|
2688
|
+
/** The legacy named presets, or any DrawingML ST_ShapeType name the preset
|
|
2689
|
+
* geometry table knows (isValidShapePreset). */
|
|
2690
|
+
type ShapePreset = "line" | "verticalLine" | "rectangle" | "roundedRectangle" | "ellipse" | "diamond" | "textBox" | (string & {});
|
|
2691
|
+
type WordArtPreset = "plain" | "archUp" | "archDown" | "wave" | "chevron" | "circle" | "button" | "chevronDown";
|
|
2692
|
+
/** A WordArt gallery style: glyph fill plus optional outline and shadow
|
|
2693
|
+
* (w14:textFill / w14:textOutline / w14:shadow run effects). */
|
|
2694
|
+
interface WordArtStyle {
|
|
2695
|
+
/** 6-hex-digit RGB, with or without "#". */
|
|
2696
|
+
fill: string;
|
|
2697
|
+
outline?: {
|
|
2698
|
+
color: string;
|
|
2699
|
+
widthPt: number;
|
|
2700
|
+
};
|
|
2701
|
+
shadow?: boolean;
|
|
2702
|
+
}
|
|
2703
|
+
type DrawingLineDash = "solid" | "dashed" | "dotted";
|
|
2704
|
+
type DrawingTool = {
|
|
2705
|
+
kind?: "pen";
|
|
2706
|
+
color: string;
|
|
2707
|
+
width: number;
|
|
2708
|
+
} | {
|
|
2709
|
+
kind: "highlighter";
|
|
2710
|
+
color: string;
|
|
2711
|
+
width: number;
|
|
2712
|
+
} | {
|
|
2713
|
+
kind: "eraser";
|
|
2714
|
+
size: number;
|
|
2715
|
+
} | {
|
|
2716
|
+
kind: "lasso";
|
|
2717
|
+
};
|
|
2718
|
+
/** Outline/shadow for an ordinary run — Word's Home-tab "Text Effects and
|
|
2719
|
+
* Typography" gallery, distinct from inserting a WordArt object. */
|
|
2720
|
+
interface RunTextEffectPatch {
|
|
2721
|
+
outline?: {
|
|
2722
|
+
color: string;
|
|
2723
|
+
widthPt: number;
|
|
2724
|
+
} | null;
|
|
2725
|
+
shadow?: boolean;
|
|
2726
|
+
}
|
|
2727
|
+
/** bodyPr's autofit choice: grow the shape, shrink the text, or neither. */
|
|
2728
|
+
type DrawingTextFitMode = "none" | "resizeShape" | "shrinkText";
|
|
2729
|
+
|
|
2213
2730
|
interface RunFormatPatch {
|
|
2214
2731
|
bold?: boolean;
|
|
2215
2732
|
italic?: boolean;
|
|
@@ -2224,6 +2741,24 @@ interface RunFormatPatch {
|
|
|
2224
2741
|
fontFamily?: string;
|
|
2225
2742
|
/** Superscript/subscript; null returns the run to the baseline. */
|
|
2226
2743
|
verticalAlign?: "superscript" | "subscript" | null;
|
|
2744
|
+
/**
|
|
2745
|
+
* Character style (w:rStyle); null removes the reference.
|
|
2746
|
+
*
|
|
2747
|
+
* This rides the run patch rather than taking an operation of its own
|
|
2748
|
+
* because applying a character style to PART of a run splits the run — which
|
|
2749
|
+
* breaks the registry's position-stable precondition, and which formatRange
|
|
2750
|
+
* already handles with its carried before/middle/after piece ids.
|
|
2751
|
+
*/
|
|
2752
|
+
characterStyleId?: string | null;
|
|
2753
|
+
/**
|
|
2754
|
+
* w14 outline/shadow run effects (Word's Home-tab "Text Effects and
|
|
2755
|
+
* Typography" gallery) — the same vocabulary a WordArt object's text
|
|
2756
|
+
* carries, applied directly to ordinary runs. null removes every w14
|
|
2757
|
+
* effect, reverting to plain text. Rides the run patch rather than an
|
|
2758
|
+
* operation of its own for the same reason characterStyleId does: applying
|
|
2759
|
+
* it to PART of a run splits the run, which formatRange already handles.
|
|
2760
|
+
*/
|
|
2761
|
+
textEffect?: RunTextEffectPatch | null;
|
|
2227
2762
|
/** Remove all direct character formatting (and character style). */
|
|
2228
2763
|
clear?: boolean;
|
|
2229
2764
|
}
|
|
@@ -2238,175 +2773,1121 @@ interface SelectionFormat {
|
|
|
2238
2773
|
highlight?: string;
|
|
2239
2774
|
fontFamily?: string;
|
|
2240
2775
|
verticalAlign?: "superscript" | "subscript";
|
|
2776
|
+
/** The character style every selected run carries, if they agree. Null when
|
|
2777
|
+
* they agree on carrying none; undefined when the selection is mixed. */
|
|
2778
|
+
characterStyleId?: string | null;
|
|
2241
2779
|
}
|
|
2242
2780
|
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
}
|
|
2258
|
-
kind: "lasso";
|
|
2259
|
-
};
|
|
2781
|
+
/**
|
|
2782
|
+
* Shortcuts owned by the embedding application rather than the editor — a
|
|
2783
|
+
* desktop app's menu accelerators, say. A menu accelerator is consumed by the
|
|
2784
|
+
* menu before the editor's keydown handler ever sees it, so the editor cannot
|
|
2785
|
+
* discover these; the host injects them (HelpGuide's `hostShortcuts` prop) and
|
|
2786
|
+
* the sheet becomes a reference for the whole keyboard instead of half of it.
|
|
2787
|
+
*/
|
|
2788
|
+
interface HostShortcutSection {
|
|
2789
|
+
title: string;
|
|
2790
|
+
items: {
|
|
2791
|
+
label: string;
|
|
2792
|
+
keys: string;
|
|
2793
|
+
detail?: string;
|
|
2794
|
+
}[];
|
|
2795
|
+
}
|
|
2260
2796
|
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2797
|
+
/**
|
|
2798
|
+
* CITATION resolution: the document's bibliography sources and the simple
|
|
2799
|
+
* parenthetical and bibliography-entry formats Word paints for the built-in
|
|
2800
|
+
* styles.
|
|
2801
|
+
*
|
|
2802
|
+
* WHERE THE SOURCES LIVE. Word stores the bibliography source list as a
|
|
2803
|
+
* Custom XML Data part (customXml/item1.xml in Word's own files), targeted
|
|
2804
|
+
* from the main document part by a customXml relationship. The markup is the
|
|
2805
|
+
* Bibliography namespace of ECMA-376 §22.6: a b:Sources root whose
|
|
2806
|
+
* StyleName attribute names the selected citation style ("APA", "MLA", …)
|
|
2807
|
+
* and whose b:Source children each carry a b:Tag the CITATION instruction
|
|
2808
|
+
* references. The part is retained by DocxDocument (sourcesTree) so the
|
|
2809
|
+
* source-management operations in edit/sources.ts can mutate it; a part
|
|
2810
|
+
* those operations never touch keeps its original bytes through save().
|
|
2811
|
+
*
|
|
2812
|
+
* WHAT IS FORMATTED. The author-date parenthetical of the simple built-in
|
|
2813
|
+
* styles: "(Author, Year)" for the APA-shaped family and "(Author)" /
|
|
2814
|
+
* "(Author page)" for MLA — plus the matching bibliography ENTRY per source
|
|
2815
|
+
* (bibliographyEntryText below). Full style-sheet fidelity (Word ships an
|
|
2816
|
+
* XSL per style) is out of scope; a CITATION whose display this module
|
|
2817
|
+
* cannot build keeps its cached result, which is Word's own rendering.
|
|
2818
|
+
*
|
|
2819
|
+
* It lives here, above both consumers, for the style-ref.ts reason: layout
|
|
2820
|
+
* paints what the reader sees and the update pass writes what the saved file
|
|
2821
|
+
* carries, and the two must not disagree about the same field.
|
|
2822
|
+
*/
|
|
2823
|
+
/** A person author, in b:NameList order. */
|
|
2824
|
+
interface BibliographyPerson {
|
|
2825
|
+
last: string;
|
|
2826
|
+
first?: string;
|
|
2268
2827
|
}
|
|
2828
|
+
interface BibliographySource {
|
|
2829
|
+
tag: string;
|
|
2830
|
+
/** b:SourceType text ("Book", "JournalArticle", "InternetSite", "Report", …). */
|
|
2831
|
+
sourceType?: string;
|
|
2832
|
+
/** Person authors, in b:NameList order. */
|
|
2833
|
+
authors: BibliographyPerson[];
|
|
2834
|
+
/** b:Author/b:Corporate, used when there is no person author. */
|
|
2835
|
+
corporate?: string;
|
|
2836
|
+
title?: string;
|
|
2837
|
+
year?: string;
|
|
2838
|
+
/** b:JournalName (journal articles). */
|
|
2839
|
+
journal?: string;
|
|
2840
|
+
/** b:Publisher (books, reports). */
|
|
2841
|
+
publisher?: string;
|
|
2842
|
+
/** b:URL (internet sites). */
|
|
2843
|
+
url?: string;
|
|
2844
|
+
}
|
|
2845
|
+
/** The citation styles the style selector offers: the two whose parenthetical
|
|
2846
|
+
* and bibliography-entry rules this module models. One list, so the operation
|
|
2847
|
+
* validator, the agent schema, and the toolbar cannot disagree. */
|
|
2848
|
+
declare const CITATION_STYLES: readonly ["APA", "MLA"];
|
|
2849
|
+
type CitationStyle = (typeof CITATION_STYLES)[number];
|
|
2269
2850
|
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2851
|
+
/** An a:srcRect crop as fractions of the source bitmap trimmed off each edge.
|
|
2852
|
+
* The four together must leave a visible strip on both axes. */
|
|
2853
|
+
interface ImageCrop {
|
|
2854
|
+
l: number;
|
|
2855
|
+
t: number;
|
|
2856
|
+
r: number;
|
|
2857
|
+
b: number;
|
|
2858
|
+
}
|
|
2859
|
+
|
|
2860
|
+
/**
|
|
2861
|
+
* Numbering DEFINITION editing: the levels of an abstract numbering
|
|
2862
|
+
* definition, and the per-instance overrides that restart or continue a
|
|
2863
|
+
* sequence. Applying numbering to a paragraph lives in lists.ts.
|
|
2864
|
+
*
|
|
2865
|
+
* Two things are edited here, and the difference matters:
|
|
2866
|
+
*
|
|
2867
|
+
* - A LEVEL of an abstract definition (w:abstractNum/w:lvl). Every list
|
|
2868
|
+
* instance sharing that abstract definition changes with it.
|
|
2869
|
+
* - An OVERRIDE on one instance (w:num/w:lvlOverride). Only the paragraphs
|
|
2870
|
+
* carrying that numId change, which is how one list restarts at 1 while
|
|
2871
|
+
* another sharing the same look keeps counting.
|
|
2872
|
+
*/
|
|
2873
|
+
/** The numbering formats Word offers for a level. */
|
|
2874
|
+
declare const NUMBER_FORMATS: readonly ["decimal", "decimalZero", "upperRoman", "lowerRoman", "upperLetter", "lowerLetter", "ordinal", "bullet", "none"];
|
|
2875
|
+
type NumberFormat = (typeof NUMBER_FORMATS)[number];
|
|
2876
|
+
/** What one level of a multilevel definition can be changed to. Undefined
|
|
2877
|
+
* leaves a property alone. */
|
|
2878
|
+
interface LevelPatch {
|
|
2879
|
+
format?: NumberFormat;
|
|
2880
|
+
/** The label template: "%1." or "%1.%2." for a multilevel definition, or the
|
|
2881
|
+
* bullet glyph when format is "bullet". */
|
|
2882
|
+
text?: string;
|
|
2883
|
+
/** The counter this level starts at. */
|
|
2884
|
+
start?: number;
|
|
2885
|
+
alignment?: "left" | "center" | "right";
|
|
2886
|
+
/** Text indent, in points. */
|
|
2887
|
+
indentLeftPt?: number;
|
|
2888
|
+
/** Hanging indent of the label, in points. */
|
|
2889
|
+
hangingPt?: number;
|
|
2890
|
+
}
|
|
2891
|
+
/**
|
|
2892
|
+
* Word's multilevel-list gallery, expressed as per-level patches over the
|
|
2893
|
+
* deep numbering ops (setNumberingLevel). One entry per preset; index = ilvl.
|
|
2894
|
+
*/
|
|
2895
|
+
declare const NUMBERING_PRESETS: Record<string, {
|
|
2896
|
+
name: string;
|
|
2897
|
+
levels: LevelPatch[];
|
|
2898
|
+
}>;
|
|
2899
|
+
type NumberingPresetId = keyof typeof NUMBERING_PRESETS;
|
|
2900
|
+
|
|
2901
|
+
/**
|
|
2902
|
+
* Table manipulation: add/remove rows and columns relative to the cell
|
|
2903
|
+
* containing the caret. Mutates source XML; callers checkpoint + relayout.
|
|
2904
|
+
*
|
|
2905
|
+
* v1 scope: column operations refuse tables using gridSpan (merged cells)
|
|
2906
|
+
* rather than corrupt them.
|
|
2907
|
+
*
|
|
2908
|
+
* SUGGESTING MODE. Every formatting operation below takes an optional
|
|
2909
|
+
* RevisionMeta. With one, it records the properties it is about to replace as
|
|
2910
|
+
* a tracked change — w:tblPrChange on the table, w:trPrChange on a row,
|
|
2911
|
+
* w:tcPrChange on a cell — before mutating them, so a reviewer can accept or
|
|
2912
|
+
* reject the change (edit/suggest.ts). Without one it mutates outright, which
|
|
2913
|
+
* is what a direct edit does. STRUCTURAL operations (row and column insert and
|
|
2914
|
+
* delete, merge, split) take no meta: they are not tracked, and the surfaces
|
|
2915
|
+
* that enforce suggesting mode refuse them rather than apply them untracked.
|
|
2916
|
+
*/
|
|
2917
|
+
type TableOp = "rowAbove" | "rowBelow" | "deleteRow" | "colLeft" | "colRight" | "deleteCol" | "deleteTable" | "mergeRight" | "mergeDown" | "splitCell" | {
|
|
2918
|
+
kind: "cellShading";
|
|
2919
|
+
fill: string | null;
|
|
2289
2920
|
} | {
|
|
2290
|
-
kind: "
|
|
2291
|
-
|
|
2292
|
-
runId: number;
|
|
2293
|
-
start: number;
|
|
2294
|
-
end: number;
|
|
2921
|
+
kind: "cellVAlign";
|
|
2922
|
+
v: "top" | "center" | "bottom";
|
|
2295
2923
|
} | {
|
|
2296
|
-
kind: "
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2924
|
+
kind: "textWrapping";
|
|
2925
|
+
wrapping: "none" | "around";
|
|
2926
|
+
xPx: number;
|
|
2927
|
+
yPx: number;
|
|
2928
|
+
};
|
|
2929
|
+
/** The w:val values w:tblBorders / w:tcBorders edges accept. "none" writes
|
|
2930
|
+
* w:val="nil", Word's spelling for an explicitly suppressed rule. */
|
|
2931
|
+
type TableBorderStyle = "single" | "thick" | "double" | "dotted" | "dashed" | "dotDash" | "dotDotDash" | "thinThickSmallGap" | "triple" | "wave" | "none";
|
|
2932
|
+
/** One border edge. Table scope carries the four sides plus the two inside
|
|
2933
|
+
* rules; cell scope carries the four sides plus the two diagonals. Neither
|
|
2934
|
+
* carries the other's — the parser reads only these, so writing the rest
|
|
2935
|
+
* would emit XML that renders nothing. */
|
|
2936
|
+
type TableBorderEdge = "top" | "bottom" | "left" | "right" | "insideH" | "insideV" | "tl2br" | "tr2bl";
|
|
2937
|
+
interface TableBorderSpec {
|
|
2938
|
+
style: TableBorderStyle;
|
|
2939
|
+
/** Stroke width in eighths of a point (w:sz). Word's UI offers 2..48. */
|
|
2940
|
+
sz?: number;
|
|
2941
|
+
/** "#RRGGBB", "RRGGBB", or "auto". */
|
|
2942
|
+
color?: string;
|
|
2943
|
+
/** Gap between rule and content, in points (w:space). */
|
|
2944
|
+
space?: number;
|
|
2945
|
+
}
|
|
2946
|
+
/** Word's six "Table Style Options" checkboxes. Banding is expressed
|
|
2947
|
+
* positively here and inverted into w:noHBand / w:noVBand on write — the
|
|
2948
|
+
* negative spelling is a wire detail, and every caller that had to remember
|
|
2949
|
+
* the inversion got it wrong at least once. */
|
|
2950
|
+
interface TableLookToggles {
|
|
2951
|
+
firstRow: boolean;
|
|
2952
|
+
lastRow: boolean;
|
|
2953
|
+
firstColumn: boolean;
|
|
2954
|
+
lastColumn: boolean;
|
|
2955
|
+
bandedRows: boolean;
|
|
2956
|
+
bandedCols: boolean;
|
|
2957
|
+
}
|
|
2958
|
+
/** Cell padding in points. An omitted side is left as it was; pass null to
|
|
2959
|
+
* setTableCellMargins to drop the whole override. */
|
|
2960
|
+
interface CellMarginsPt {
|
|
2961
|
+
top?: number;
|
|
2962
|
+
left?: number;
|
|
2963
|
+
bottom?: number;
|
|
2964
|
+
right?: number;
|
|
2965
|
+
}
|
|
2966
|
+
/**
|
|
2967
|
+
* What a Table Properties dialog needs to show the table around the caret,
|
|
2968
|
+
* in points throughout so no caller handles twips.
|
|
2969
|
+
*
|
|
2970
|
+
* Read-only, and separate from the setters because Word's dialog PREFILLS:
|
|
2971
|
+
* a width box that opens empty asks the user to retype a number the document
|
|
2972
|
+
* already carries, and one that opens on a guess is worse than empty.
|
|
2973
|
+
*/
|
|
2974
|
+
interface TablePropertiesPt {
|
|
2975
|
+
/** Columns in the table's grid. */
|
|
2976
|
+
columnCount: number;
|
|
2977
|
+
/** Grid column the caret sits in, counting gridSpans to its left. */
|
|
2978
|
+
columnIdx: number;
|
|
2979
|
+
/** w:tblW. An absent element IS "auto" — that is what the schema's default
|
|
2980
|
+
* says — so the unit is always answered. */
|
|
2981
|
+
width: {
|
|
2982
|
+
unit: "pt" | "pct" | "auto";
|
|
2983
|
+
value: number;
|
|
2301
2984
|
};
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2985
|
+
/** Each grid column's width. */
|
|
2986
|
+
columnWidthsPt: number[];
|
|
2987
|
+
/** The table's default cell margins (w:tblCellMar). A side the table does
|
|
2988
|
+
* not declare is ABSENT rather than zero, so a caller can tell an inherited
|
|
2989
|
+
* margin from a suppressed one. */
|
|
2990
|
+
cellMargins: CellMarginsPt;
|
|
2991
|
+
/** Rows in the repeating header band (see setTableHeaderRows). */
|
|
2992
|
+
headerRows: number;
|
|
2993
|
+
}
|
|
2994
|
+
|
|
2995
|
+
/**
|
|
2996
|
+
* Style DEFINITION editing: the entries in styles.xml, as opposed to applying
|
|
2997
|
+
* an existing style to content (setParagraphStyle in blocks.ts, w:rStyle via
|
|
2998
|
+
* the run format patch).
|
|
2999
|
+
*
|
|
3000
|
+
* Everything here mutates the retained styles.xml tree and then calls
|
|
3001
|
+
* doc.markStylesChanged(), which re-parses the tree and drops the layout
|
|
3002
|
+
* signature. That is the whole of the cascade re-resolution: a definition is
|
|
3003
|
+
* not addressed by any paragraph's XML, so no w:p changes and the model
|
|
3004
|
+
* re-derives effective props from the new Styles map on the next layout.
|
|
3005
|
+
*/
|
|
3006
|
+
/** The paragraph properties a style definition can carry, in points.
|
|
3007
|
+
* Null clears the property; undefined leaves it alone. */
|
|
3008
|
+
interface StyleParaPatch {
|
|
3009
|
+
alignment?: "left" | "center" | "right" | "both" | null;
|
|
3010
|
+
spacingBeforePt?: number | null;
|
|
3011
|
+
spacingAfterPt?: number | null;
|
|
3012
|
+
/** Line spacing as a multiple of single (1.5 → w:line="360" auto). */
|
|
3013
|
+
lineMultiple?: number | null;
|
|
3014
|
+
indentLeftPt?: number | null;
|
|
3015
|
+
indentFirstLinePt?: number | null;
|
|
3016
|
+
keepNext?: boolean | null;
|
|
3017
|
+
/** w:outlineLvl 0-8 — what makes a paragraph style a TOC heading level. */
|
|
3018
|
+
outlineLevel?: number | null;
|
|
3019
|
+
}
|
|
3020
|
+
/** The run properties a style definition can carry. Same names as direct
|
|
3021
|
+
* character formatting; `clear` has no meaning for a definition. */
|
|
3022
|
+
type StyleRunPatch = Omit<RunFormatPatch, "clear">;
|
|
3023
|
+
/** The four style kinds a w:style can declare. One list, so a validator and
|
|
3024
|
+
* a schema cannot disagree about which types exist. */
|
|
3025
|
+
declare const STYLE_TYPES: readonly ["paragraph", "character", "table", "numbering"];
|
|
3026
|
+
type StyleType = (typeof STYLE_TYPES)[number];
|
|
3027
|
+
interface StyleSpec {
|
|
3028
|
+
styleId: string;
|
|
3029
|
+
type: StyleType;
|
|
3030
|
+
/** The display name (w:name) — what a gallery shows. */
|
|
3031
|
+
name: string;
|
|
3032
|
+
/** Parent in the cascade. Defaults per type to what Word writes: Normal for
|
|
3033
|
+
* a paragraph style, DefaultParagraphFont for a character style,
|
|
3034
|
+
* TableNormal for a table style, and nothing for a numbering style. */
|
|
3035
|
+
basedOn?: string | null;
|
|
3036
|
+
/** Style applied to the NEXT paragraph after this one (paragraph only). */
|
|
3037
|
+
next?: string | null;
|
|
3038
|
+
/** w:qFormat — show the style in the quick-style gallery. */
|
|
3039
|
+
quickStyle?: boolean;
|
|
3040
|
+
/** w:uiPriority — gallery sort order. */
|
|
3041
|
+
uiPriority?: number;
|
|
3042
|
+
paragraph?: StyleParaPatch;
|
|
3043
|
+
run?: StyleRunPatch;
|
|
3044
|
+
/**
|
|
3045
|
+
* PARAGRAPH styles only: also write the linked character companion Word
|
|
3046
|
+
* pairs with one, so the same look can be applied to a span of text as well
|
|
3047
|
+
* as to a whole paragraph. The companion takes the id `<styleId>Char` and
|
|
3048
|
+
* the name `<name> Char`, copies the paragraph style's run properties, and
|
|
3049
|
+
* the two point at each other through w:link.
|
|
3050
|
+
*
|
|
3051
|
+
* Refused when `<styleId>Char` is already taken, rather than picking
|
|
3052
|
+
* another id: the companion's id has to be derivable from the paragraph
|
|
3053
|
+
* style's, or two replicas applying the same operation would disagree
|
|
3054
|
+
* about what to call it.
|
|
3055
|
+
*/
|
|
3056
|
+
linked?: boolean;
|
|
3057
|
+
/** TABLE styles only: the grid the style draws. Conditional formats
|
|
3058
|
+
* (w:tblStylePr — banded rows, header row) are not expressible yet. */
|
|
3059
|
+
table?: {
|
|
3060
|
+
borders?: Partial<Record<TableBorderEdge, TableBorderSpec>>;
|
|
2307
3061
|
};
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
} | {
|
|
2314
|
-
kind: "formatRange";
|
|
2315
|
-
blockId: number;
|
|
2316
|
-
runId: number;
|
|
2317
|
-
start: number;
|
|
2318
|
-
end: number;
|
|
2319
|
-
patch: Record<string, unknown>;
|
|
2320
|
-
beforeId?: number;
|
|
2321
|
-
middleId: number;
|
|
2322
|
-
afterId?: number;
|
|
2323
|
-
} | {
|
|
2324
|
-
kind: "formatParagraph";
|
|
2325
|
-
blockId: number;
|
|
2326
|
-
align?: "left" | "center" | "right" | "justify";
|
|
2327
|
-
styleId?: string | null;
|
|
2328
|
-
} | {
|
|
2329
|
-
kind: "setListType";
|
|
2330
|
-
blockId: number;
|
|
2331
|
-
listKind: "bullet" | "number" | null;
|
|
2332
|
-
} | {
|
|
2333
|
-
kind: "mergeParagraph";
|
|
2334
|
-
blockId: number;
|
|
2335
|
-
} | {
|
|
2336
|
-
kind: "suggestRevision";
|
|
2337
|
-
ranges?: {
|
|
2338
|
-
blockId: number;
|
|
2339
|
-
runId: number;
|
|
2340
|
-
start: number;
|
|
2341
|
-
end: number;
|
|
2342
|
-
}[];
|
|
2343
|
-
marks?: {
|
|
2344
|
-
blockId: number;
|
|
2345
|
-
glyph: "ins" | "del";
|
|
2346
|
-
}[];
|
|
2347
|
-
suggest: {
|
|
2348
|
-
author: string;
|
|
2349
|
-
date: string;
|
|
3062
|
+
/** NUMBERING styles only, and required for them: the w:numId of the
|
|
3063
|
+
* numbering definition the style names. A numbering style is a NAME for a
|
|
3064
|
+
* list definition, so it carries nothing else of its own. */
|
|
3065
|
+
numbering?: {
|
|
3066
|
+
numId: number;
|
|
2350
3067
|
};
|
|
2351
|
-
}
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
3068
|
+
}
|
|
3069
|
+
interface StylePatch {
|
|
3070
|
+
name?: string;
|
|
3071
|
+
basedOn?: string | null;
|
|
3072
|
+
next?: string | null;
|
|
3073
|
+
quickStyle?: boolean;
|
|
3074
|
+
uiPriority?: number;
|
|
3075
|
+
paragraph?: StyleParaPatch;
|
|
3076
|
+
run?: StyleRunPatch;
|
|
3077
|
+
}
|
|
3078
|
+
/** A gallery row: what a style chooser needs to draw one entry. */
|
|
3079
|
+
interface StyleGalleryEntry {
|
|
3080
|
+
id: string;
|
|
3081
|
+
name: string;
|
|
3082
|
+
type: "paragraph" | "character" | "table" | "numbering";
|
|
3083
|
+
basedOn?: string;
|
|
3084
|
+
/** w:qFormat: Word shows these in the ribbon's quick-style gallery. */
|
|
3085
|
+
quickStyle: boolean;
|
|
3086
|
+
uiPriority?: number;
|
|
3087
|
+
/** True for a style this document declares, false for a built-in offered
|
|
3088
|
+
* without a definition (applying one injects the definition). */
|
|
3089
|
+
defined: boolean;
|
|
3090
|
+
/** Number of paragraphs or runs that reference the style. */
|
|
3091
|
+
usageCount: number;
|
|
3092
|
+
/** Effective run props through the style's basedOn chain — enough to paint a
|
|
3093
|
+
* live preview of the entry. */
|
|
3094
|
+
preview: RunProps;
|
|
3095
|
+
}
|
|
3096
|
+
|
|
3097
|
+
interface Model3DRotation {
|
|
3098
|
+
x: number;
|
|
3099
|
+
y: number;
|
|
3100
|
+
z: number;
|
|
3101
|
+
}
|
|
3102
|
+
|
|
3103
|
+
/**
|
|
3104
|
+
* Bibliography SOURCE editing: the b:Source entries of the customXml sources
|
|
3105
|
+
* part (ECMA-376 §22.6), as opposed to citing one (insertCitationField in
|
|
3106
|
+
* fields.ts) or rendering one (src/citations.ts).
|
|
3107
|
+
*
|
|
3108
|
+
* Everything here mutates the retained sources tree and then calls
|
|
3109
|
+
* doc.markSourcesChanged() — the styles.ts discipline. The part is created on
|
|
3110
|
+
* the first source (doc.sourcesTree(true)); only the sources part is written,
|
|
3111
|
+
* so a package whose sources this engine never touches keeps its original
|
|
3112
|
+
* bytes through save().
|
|
3113
|
+
*/
|
|
3114
|
+
/** The source kinds the manager offers, mapped to the b:SourceType values
|
|
3115
|
+
* Word's own Source Manager writes. The four cover the common cases; an
|
|
3116
|
+
* arriving source of any other type still renders and can be cited. */
|
|
3117
|
+
declare const CITATION_SOURCE_TYPES: readonly ["book", "article", "website", "report"];
|
|
3118
|
+
type CitationSourceType = (typeof CITATION_SOURCE_TYPES)[number];
|
|
3119
|
+
interface CitationSourceSpec {
|
|
3120
|
+
/** Word's Source-Manager tag shape (isValidCitationTag): what a CITATION
|
|
3121
|
+
* instruction references. */
|
|
3122
|
+
tag: string;
|
|
3123
|
+
type: CitationSourceType;
|
|
3124
|
+
/** Person authors. Mutually exclusive with `corporate`. */
|
|
3125
|
+
authors?: BibliographyPerson[];
|
|
3126
|
+
/** Corporate author (b:Corporate). */
|
|
3127
|
+
corporate?: string;
|
|
3128
|
+
title?: string;
|
|
3129
|
+
year?: string;
|
|
3130
|
+
/** Books and reports. */
|
|
3131
|
+
publisher?: string;
|
|
3132
|
+
/** Journal articles (b:JournalName). */
|
|
3133
|
+
journal?: string;
|
|
3134
|
+
/** Internet sites. */
|
|
3135
|
+
url?: string;
|
|
3136
|
+
}
|
|
3137
|
+
/** Everything but the tag, each field optional; an empty string clears the
|
|
3138
|
+
* field. `authors`/`corporate` replace the whole author element. */
|
|
3139
|
+
type CitationSourcePatch = Partial<Omit<CitationSourceSpec, "tag">>;
|
|
3140
|
+
|
|
3141
|
+
type ParagraphDividerStyle = "single" | "double" | "dotted" | "dashed" | "thinThickSmallGap";
|
|
3142
|
+
interface ParagraphDivider {
|
|
3143
|
+
style: ParagraphDividerStyle;
|
|
3144
|
+
color: string;
|
|
3145
|
+
widthPt: number;
|
|
3146
|
+
spacePt: number;
|
|
3147
|
+
}
|
|
3148
|
+
declare const PARAGRAPH_BORDER_EDGES: readonly ["top", "left", "bottom", "right", "between", "bar"];
|
|
3149
|
+
type ParagraphBorderEdge = (typeof PARAGRAPH_BORDER_EDGES)[number];
|
|
3150
|
+
interface ParagraphBordersPatch {
|
|
3151
|
+
/** Edges to change: a spec writes the rule, null removes the direct edge.
|
|
3152
|
+
* Absent edges are left alone. The spec vocabulary is the table border
|
|
3153
|
+
* picker's (style / sz in eighths / color / space in points). */
|
|
3154
|
+
borders?: Partial<Record<ParagraphBorderEdge, TableBorderSpec | null>>;
|
|
3155
|
+
/** Paragraph shading fill "RRGGBB"; null removes the direct w:shd.
|
|
3156
|
+
* Undefined leaves shading alone. */
|
|
3157
|
+
shading?: string | null;
|
|
3158
|
+
}
|
|
3159
|
+
declare const TAB_STOP_ALIGNMENTS: readonly ["left", "center", "right", "decimal", "bar"];
|
|
3160
|
+
declare const TAB_STOP_LEADERS: readonly ["none", "dot", "hyphen", "underscore", "middleDot"];
|
|
3161
|
+
interface TabStopSpec {
|
|
3162
|
+
/** Position in points from the left text edge. */
|
|
3163
|
+
posPt: number;
|
|
3164
|
+
align: (typeof TAB_STOP_ALIGNMENTS)[number];
|
|
3165
|
+
leader: (typeof TAB_STOP_LEADERS)[number];
|
|
3166
|
+
}
|
|
3167
|
+
|
|
3168
|
+
/** The cover-page design gallery. "title" is Word's plain centered title
|
|
3169
|
+
* block (this engine's original single form). "banner" shades the title
|
|
3170
|
+
* paragraph into a colored band — Word's "Sideline"/"Facet" family look —
|
|
3171
|
+
* reusing setParagraphBorders' shading rather than inventing a second way to
|
|
3172
|
+
* paint a fill. "sidebar" left-aligns the block lower on the page with a
|
|
3173
|
+
* colored accent rule on the title, the same reuse for the rule itself. */
|
|
3174
|
+
declare const COVER_PAGE_LAYOUTS: readonly ["title", "banner", "sidebar"];
|
|
3175
|
+
type CoverPageLayout = (typeof COVER_PAGE_LAYOUTS)[number];
|
|
3176
|
+
interface CoverPageContent {
|
|
3177
|
+
title: string;
|
|
3178
|
+
subtitle?: string;
|
|
3179
|
+
author?: string;
|
|
3180
|
+
/** Defaults to "title" — the original single layout, unchanged. */
|
|
3181
|
+
layout?: CoverPageLayout;
|
|
3182
|
+
}
|
|
3183
|
+
/** The w:pgNumType number formats the layout engine paints (its PAGE_FMT
|
|
3184
|
+
* table); the editable subset of ST_NumberFormat (ECMA-376 §17.18.59). */
|
|
3185
|
+
declare const PAGE_NUMBER_FORMATS: readonly ["decimal", "lowerRoman", "upperRoman", "lowerLetter", "upperLetter"];
|
|
3186
|
+
type PageNumberFormat = (typeof PAGE_NUMBER_FORMATS)[number];
|
|
3187
|
+
interface PageNumberFormatPatch {
|
|
3188
|
+
/** w:pgNumType@fmt. null removes the attribute (back to decimal). */
|
|
3189
|
+
fmt?: PageNumberFormat | null;
|
|
3190
|
+
/** w:pgNumType@start. null removes it (numbering continues from the
|
|
3191
|
+
* previous section, the OOXML default). */
|
|
3192
|
+
start?: number | null;
|
|
3193
|
+
}
|
|
3194
|
+
/** Note-mark numbering formats the layout engine paints (formatNoteMark's
|
|
3195
|
+
* table): the page-number format subset plus "chicago", Word's symbol style
|
|
3196
|
+
* (*, †, ‡, §) — footnotes' traditional default in some templates. */
|
|
3197
|
+
declare const NOTE_NUMBER_FORMATS: readonly ["decimal", "lowerRoman", "upperRoman", "lowerLetter", "upperLetter", "chicago"];
|
|
3198
|
+
type NoteNumberFormat = (typeof NOTE_NUMBER_FORMATS)[number];
|
|
3199
|
+
/** ST_RestartNumber (ECMA-376 §17.18.81): when the mark counter resets.
|
|
3200
|
+
* Only "eachSect" is honored by layout (assignNoteNumbers); "continuous" is
|
|
3201
|
+
* the OOXML default; "eachPage" round-trips but is not laid out — see
|
|
3202
|
+
* assignNoteNumbers' comment for why. */
|
|
3203
|
+
declare const NOTE_RESTART_VALUES: readonly ["continuous", "eachSect", "eachPage"];
|
|
3204
|
+
type NoteRestart = (typeof NOTE_RESTART_VALUES)[number];
|
|
3205
|
+
interface FootnoteOptionsPatch {
|
|
3206
|
+
/** w:footnotePr/w:numFmt@val. null removes it (back to decimal). */
|
|
3207
|
+
fmt?: NoteNumberFormat | null;
|
|
3208
|
+
/** w:footnotePr/w:numStart@val. null removes it (back to 1). */
|
|
3209
|
+
start?: number | null;
|
|
3210
|
+
/** w:footnotePr/w:numRestart@val. null removes it (back to continuous). */
|
|
3211
|
+
restart?: NoteRestart | null;
|
|
3212
|
+
/** w:footnotePr/w:pos@val (§17.11.21). null removes it (back to pageBottom). */
|
|
3213
|
+
pos?: "pageBottom" | "beneathText" | null;
|
|
3214
|
+
}
|
|
3215
|
+
interface EndnoteOptionsPatch {
|
|
3216
|
+
fmt?: NoteNumberFormat | null;
|
|
3217
|
+
start?: number | null;
|
|
3218
|
+
restart?: NoteRestart | null;
|
|
3219
|
+
/** w:endnotePr/w:pos@val. null removes it (back to docEnd). */
|
|
3220
|
+
pos?: "sectEnd" | "docEnd" | null;
|
|
3221
|
+
}
|
|
3222
|
+
/** Current w:footnotePr settings for the section governing `t`. */
|
|
3223
|
+
declare function footnoteOptionsAt(doc: DocxDocument, t: XmlElement): {
|
|
3224
|
+
fmt: NoteNumberFormat;
|
|
3225
|
+
start: number | null;
|
|
3226
|
+
restart: NoteRestart;
|
|
3227
|
+
pos: "pageBottom" | "beneathText";
|
|
3228
|
+
};
|
|
3229
|
+
/** Current w:endnotePr settings for the section governing `t`. */
|
|
3230
|
+
declare function endnoteOptionsAt(doc: DocxDocument, t: XmlElement): {
|
|
3231
|
+
fmt: NoteNumberFormat;
|
|
3232
|
+
start: number | null;
|
|
3233
|
+
restart: NoteRestart;
|
|
3234
|
+
pos: "sectEnd" | "docEnd";
|
|
3235
|
+
};
|
|
3236
|
+
interface LineNumberingPatch {
|
|
3237
|
+
/** Turn margin line numbering on/off for the target section(s). */
|
|
3238
|
+
enabled: boolean;
|
|
3239
|
+
/** Number every Nth line (1/5/10). Default 1 when first enabled. */
|
|
3240
|
+
countBy?: number;
|
|
3241
|
+
/** When the count resets. Default newPage when first enabled. */
|
|
3242
|
+
restart?: "continuous" | "newPage" | "newSection";
|
|
3243
|
+
/** First line number. Default 1. */
|
|
3244
|
+
start?: number;
|
|
3245
|
+
}
|
|
3246
|
+
|
|
3247
|
+
declare const PAGE_NUMBER_POSITIONS: readonly ["top", "bottom"];
|
|
3248
|
+
type PageNumberGalleryPosition = (typeof PAGE_NUMBER_POSITIONS)[number];
|
|
3249
|
+
declare const PAGE_NUMBER_ALIGNMENTS: readonly ["left", "center", "right"];
|
|
3250
|
+
type PageNumberGalleryAlign = (typeof PAGE_NUMBER_ALIGNMENTS)[number];
|
|
3251
|
+
declare const HEADER_FOOTER_PRESETS: readonly ["blank", "centeredTitle", "titleAndDate", "threeColumn"];
|
|
3252
|
+
type HeaderFooterPreset = (typeof HEADER_FOOTER_PRESETS)[number];
|
|
3253
|
+
|
|
3254
|
+
/**
|
|
3255
|
+
* A native Word table of contents: a TOC field whose cached result is the
|
|
3256
|
+
* entry list.
|
|
3257
|
+
*
|
|
3258
|
+
* WHY A FIELD AND NOT PLAIN PARAGRAPHS. Word recognises a TOC only by its
|
|
3259
|
+
* field structure, and everything a user expects from one — "Update Table",
|
|
3260
|
+
* the grey field shading, Ctrl-click navigation — follows from it. A pile of
|
|
3261
|
+
* paragraphs that merely looks like a TOC is a document Word cannot maintain.
|
|
3262
|
+
*
|
|
3263
|
+
* THE STRUCTURE, as Word writes it (verified against the parity corpus's
|
|
3264
|
+
* Word-authored TOCs, e.g. wild2-med-nccih-protocol.docx):
|
|
3265
|
+
*
|
|
3266
|
+
* <w:p> first entry paragraph, pStyle TOC1
|
|
3267
|
+
* fldChar begin
|
|
3268
|
+
* instrText ` TOC \o "1-3" \h \z \u `
|
|
3269
|
+
* fldChar separate
|
|
3270
|
+
* <w:hyperlink w:anchor="_Toc…" w:history="1"> … </w:hyperlink>
|
|
3271
|
+
* </w:p>
|
|
3272
|
+
* <w:p> … </w:p> one paragraph per further entry
|
|
3273
|
+
* <w:p> fldChar end </w:p> closes the field
|
|
3274
|
+
*
|
|
3275
|
+
* The field's begin/separate live in the FIRST entry paragraph rather than in
|
|
3276
|
+
* a paragraph of their own, and everything between separate and end is the
|
|
3277
|
+
* cached result. Each entry is a hyperlink to the heading's `_Toc` bookmark,
|
|
3278
|
+
* holding the title, a tab to a right-aligned dot-leader stop, and a PAGEREF
|
|
3279
|
+
* field for the page number.
|
|
3280
|
+
*
|
|
3281
|
+
* HOW IT STAYS CURRENT. The entries' PAGEREF fields are ordinary complex
|
|
3282
|
+
* fields, so the update pass (edit/update-fields.ts) repages the whole table
|
|
3283
|
+
* with no TOC-specific code: it harvests each PAGEREF's page from a layout
|
|
3284
|
+
* like any other. Only a change to the HEADING SET needs rebuildToc, which
|
|
3285
|
+
* replaces the entry paragraphs outright.
|
|
3286
|
+
*/
|
|
3287
|
+
/** Levels a `\o` switch includes, e.g. [1, 3] for `\o "1-3"`. */
|
|
3288
|
+
type TocLevels = [number, number];
|
|
3289
|
+
/** The tab leaders a TOC entry can draw. One list, so a validator and a
|
|
3290
|
+
* schema cannot disagree about which exist. */
|
|
3291
|
+
declare const TOC_LEADERS: readonly ["dot", "hyphen", "underscore", "none"];
|
|
3292
|
+
type TocLeader = (typeof TOC_LEADERS)[number];
|
|
3293
|
+
interface TocOptions {
|
|
3294
|
+
/** Outline levels to include. Default [1, 3], Word's own default. */
|
|
3295
|
+
levels?: TocLevels;
|
|
3296
|
+
/** Tab leader between an entry's title and its page number. */
|
|
3297
|
+
leader?: TocLeader;
|
|
3298
|
+
/** Build a TABLE OF FIGURES instead: entries are the caption paragraphs
|
|
3299
|
+
* whose SEQ field carries this label ("Figure", "Table", …), and the field
|
|
3300
|
+
* instruction takes Word's `\c "Label"` switch (§17.16.5.68). */
|
|
3301
|
+
captionLabel?: string;
|
|
3302
|
+
}
|
|
3303
|
+
|
|
3304
|
+
/**
|
|
3305
|
+
* The operation registry: ONE declaration per edit operation, read by every
|
|
3306
|
+
* surface that used to carry its own hand-written copy.
|
|
3307
|
+
*
|
|
3308
|
+
* Adding an operation used to cost four to six coordinated edits — a core
|
|
3309
|
+
* mutation, an editor dispatch, a wire intent variant in TWO packages, a
|
|
3310
|
+
* transform/validate case, an agent capability row, an agent id-budget case.
|
|
3311
|
+
* Each of those is guarded by a compile-time exhaustiveness gate, so nothing
|
|
3312
|
+
* could silently go missing; the cost was the coordination, not the risk. A
|
|
3313
|
+
* registered operation is declared once here, and the gates then consume the
|
|
3314
|
+
* registry instead of a second hand-maintained list. The gates are NOT
|
|
3315
|
+
* relaxed: an operation that is not registered still has to satisfy every one
|
|
3316
|
+
* of them by hand.
|
|
3317
|
+
*
|
|
3318
|
+
* WHAT MAY BE REGISTERED. The declaration shape below is deliberately narrow.
|
|
3319
|
+
* A registered operation must be:
|
|
3320
|
+
*
|
|
3321
|
+
* 1. ADDRESSED BY STABLE ID — a run, a paragraph, or a table cell paragraph.
|
|
3322
|
+
* The address is the whole of its collaborative "honest no-op" predicate:
|
|
3323
|
+
* when the id does not resolve in the room, the operation applies as a
|
|
3324
|
+
* clean rejection everywhere rather than mutating anything locally.
|
|
3325
|
+
* 2. POSITION-STABLE — it moves no run's text, so a concurrent intent's
|
|
3326
|
+
* offsets need no remapping and its transform is identity. The
|
|
3327
|
+
* text-shaped intents (insertText, deleteText, splitParagraph,
|
|
3328
|
+
* formatRange) each carry bespoke transform logic and stay hand-written.
|
|
3329
|
+
* 3. WITHOUT A WIRE INVERSE — collaborative undo skips it, which is the
|
|
3330
|
+
* status quo for every intent except the four in @wordinweb/collab's
|
|
3331
|
+
* invert.ts. The local path still takes a history checkpoint.
|
|
3332
|
+
*
|
|
3333
|
+
* Those three preconditions ARE the operation's undo and transform
|
|
3334
|
+
* classification. They are stated once, here, instead of repeated per
|
|
3335
|
+
* operation, because every operation the registry admits shares them; an
|
|
3336
|
+
* operation that breaks one of them does not belong in the registry yet.
|
|
3337
|
+
*/
|
|
3338
|
+
/** A stable id from the core side table (the wire's addressing unit). */
|
|
3339
|
+
type StableId$1 = number;
|
|
3340
|
+
/**
|
|
3341
|
+
* How a registered operation names its target on the wire.
|
|
3342
|
+
*
|
|
3343
|
+
* "document" scopes an operation to the whole document, which means it has no
|
|
3344
|
+
* stable id and therefore none of the honest-no-op protection an id gives: a
|
|
3345
|
+
* document address ALWAYS resolves. Such an operation has to supply its own
|
|
3346
|
+
* rejection predicate from the payload — see updateFields below, whose result
|
|
3347
|
+
* count must match the document's field count — and it must carry every value
|
|
3348
|
+
* a replica cannot re-derive identically.
|
|
3349
|
+
*
|
|
3350
|
+
* "object" names a DRAWING: the stable id of the run that CARRIES it, plus an
|
|
3351
|
+
* `objectIndex` into that run's content picking out which drawing it is (a run
|
|
3352
|
+
* can hold several). This is the addressing every hand-written drawing intent
|
|
3353
|
+
* already uses — setImageWrap, resizeDrawing — so a migrated one keeps its
|
|
3354
|
+
* wire shape. The index is NOT in the table below: it is a position inside the
|
|
3355
|
+
* run rather than an id of its own, which is also why it stays out of the
|
|
3356
|
+
* agent-facing field list, where a raw index is forbidden. BOTH halves reject:
|
|
3357
|
+
* an id nobody has and an index that no longer names a drawing are each the
|
|
3358
|
+
* same clean no-op, so the honest-no-op predicate is exactly the one every
|
|
3359
|
+
* addressed operation has. The index's WELL-FORMEDNESS is checked centrally
|
|
3360
|
+
* (see validateRegisteredOperation) rather than by each operation, for the
|
|
3361
|
+
* same reason the three preconditions above are stated once.
|
|
3362
|
+
*/
|
|
3363
|
+
type OperationAddress = "run" | "block" | "cell" | "object" | "document";
|
|
3364
|
+
/**
|
|
3365
|
+
* Agent capability category. Mirrors @wordinweb/agent's
|
|
3366
|
+
* AgentEditCapability["category"]; the agent's typed capability map is what
|
|
3367
|
+
* checks the two stay equal.
|
|
3368
|
+
*/
|
|
3369
|
+
type OperationCategory = "text" | "paragraph" | "review" | "table" | "insert" | "drawing" | "math" | "document";
|
|
3370
|
+
/** An agent-facing payload field beyond the address reference. Order is the
|
|
3371
|
+
* order the agent's JSON schema lists them in. */
|
|
3372
|
+
interface OperationField {
|
|
3373
|
+
name: string;
|
|
3374
|
+
/** Absent means required. */
|
|
3375
|
+
optional?: true;
|
|
3376
|
+
}
|
|
3377
|
+
/** What an address resolved to in the document. */
|
|
3378
|
+
interface OperationTarget {
|
|
3379
|
+
/** The addressed element: the w:r, the w:p, or the w:tbl owning the cell. */
|
|
3380
|
+
el: XmlElement;
|
|
3381
|
+
/** The first w:t under a run, or the first text descendant of a paragraph.
|
|
3382
|
+
* Null when the target carries no text (and for cell addressing). */
|
|
3383
|
+
t: XmlElement | null;
|
|
3384
|
+
/** The parsed run for a run address, null for the other two. Needed by
|
|
3385
|
+
* operations whose state is reachable only through the model — the checkbox
|
|
3386
|
+
* marker parsing hangs on a run's content — rather than from the XML. */
|
|
3387
|
+
run: Run | null;
|
|
3388
|
+
/**
|
|
3389
|
+
* For cell addressing: the addressed w:p itself. `el` deliberately widens a
|
|
3390
|
+
* cell address to the owning w:tbl, which is what a table-scoped operation
|
|
3391
|
+
* wants; a CELL-scoped one (per-edge borders, a margin override) needs the
|
|
3392
|
+
* one cell the caret is in, and the paragraph is how it gets there. Null
|
|
3393
|
+
* for run and block addressing, whose addressed element IS `el`.
|
|
3394
|
+
*/
|
|
3395
|
+
cellParagraph: XmlElement | null;
|
|
3396
|
+
/** For object addressing: the w:drawing (or VML shape) the address named.
|
|
3397
|
+
* Null for every other address. */
|
|
3398
|
+
drawing: XmlElement | null;
|
|
3399
|
+
}
|
|
3400
|
+
interface OperationContext<Payload> {
|
|
3401
|
+
doc: DocxDocument;
|
|
3402
|
+
target: OperationTarget;
|
|
3403
|
+
payload: Payload;
|
|
3404
|
+
}
|
|
3405
|
+
/**
|
|
3406
|
+
* The caller-supplied part of a wire payload: everything except the address
|
|
3407
|
+
* field the dispatcher fills in and the carried ids it allocates.
|
|
3408
|
+
*/
|
|
3409
|
+
type OperationArgs<Payload> = Omit<Payload, "runId" | "blockId" | "cellParagraphId" | "nodeIds">;
|
|
3410
|
+
interface OperationDefinition<Kind extends string, Payload> {
|
|
3411
|
+
kind: Kind;
|
|
3412
|
+
address: OperationAddress;
|
|
3413
|
+
/** Agent capability row: how the operation is grouped and described. */
|
|
3414
|
+
category: OperationCategory;
|
|
3415
|
+
description: string;
|
|
3416
|
+
/** Agent-facing fields beyond the address reference, in schema order. */
|
|
3417
|
+
fields: readonly OperationField[];
|
|
3418
|
+
/**
|
|
3419
|
+
* How many fresh stable ids the mutation needs for the id-tracked nodes it
|
|
3420
|
+
* creates. Omit when it creates none. Every producer (the editor, the React
|
|
3421
|
+
* host, the agent compiler) reads this instead of repeating the arithmetic.
|
|
3422
|
+
*/
|
|
3423
|
+
nodeIds?: (args: OperationArgs<Payload>) => number;
|
|
3424
|
+
/** The mutation removes id-tracked nodes, so the caller must retire their
|
|
3425
|
+
* stable ids afterwards. Deletion and pruning are paired everywhere else in
|
|
3426
|
+
* the apply path (mergeParagraph, removeDrawing); declaring it here keeps
|
|
3427
|
+
* the pairing in the operation's single declaration. */
|
|
3428
|
+
prunesIds?: true;
|
|
3429
|
+
/**
|
|
3430
|
+
* Reject a malformed payload before it is sequenced. Runs on both sides of
|
|
3431
|
+
* the wire, so it must be a pure function of the payload.
|
|
3432
|
+
*/
|
|
3433
|
+
validate?: (payload: Payload) => string | null;
|
|
3434
|
+
/**
|
|
3435
|
+
* The XML mutation, headless and from a resolved target. False means a
|
|
3436
|
+
* clean no-op: the operation applied nothing and every replica agrees.
|
|
3437
|
+
*/
|
|
3438
|
+
apply: (ctx: OperationContext<Payload>) => boolean;
|
|
3439
|
+
}
|
|
3440
|
+
/**
|
|
3441
|
+
* The optional suggest payload a TRACKABLE operation carries, and the
|
|
3442
|
+
* validation they share.
|
|
3443
|
+
*
|
|
3444
|
+
* With it the operation records what it replaced — w:pPrChange for a list
|
|
3445
|
+
* marker, w:tblPrChange / w:trPrChange / w:tcPrChange for table formatting —
|
|
3446
|
+
* instead of mutating outright, so a reviewer can accept or reject it. The
|
|
3447
|
+
* author and date travel in the payload so every replica writes byte-identical
|
|
3448
|
+
* XML; the w:id is scan-derived from identical tree state and needs no
|
|
3449
|
+
* carrying. Omitting it is a direct, untracked edit.
|
|
3450
|
+
*/
|
|
3451
|
+
interface SuggestablePayload {
|
|
3452
|
+
suggest?: {
|
|
3453
|
+
author: string;
|
|
3454
|
+
date: string;
|
|
3455
|
+
};
|
|
3456
|
+
}
|
|
3457
|
+
/** A payload with no fields of its own. Not `Record<string, never>`: that
|
|
3458
|
+
* carries an index signature, which would forbid the clientId/clientSeq/base
|
|
3459
|
+
* bookkeeping @wordinweb/collab intersects onto every wire body. */
|
|
3460
|
+
type NoPayload = Record<never, never>;
|
|
3461
|
+
declare const OPERATIONS: readonly [OperationDefinition<"setListType", {
|
|
3462
|
+
blockId: StableId$1;
|
|
3463
|
+
listKind: "bullet" | "number" | null;
|
|
3464
|
+
/** Additional target paragraphs beyond the addressed one, sharing its
|
|
3465
|
+
* minted numbering definition. Absent = the old single-paragraph form. */
|
|
3466
|
+
moreBlockIds?: StableId$1[];
|
|
3467
|
+
} & SuggestablePayload>, OperationDefinition<"insertTable", {
|
|
3468
|
+
runId: StableId$1;
|
|
3469
|
+
rows: number;
|
|
3470
|
+
cols: number;
|
|
3471
|
+
cells?: string[][];
|
|
3472
|
+
headerRow?: boolean;
|
|
3473
|
+
nodeIds: StableId$1[];
|
|
3474
|
+
}>, OperationDefinition<"resizeTableRow", {
|
|
3475
|
+
cellParagraphId: StableId$1;
|
|
3476
|
+
rowIdx: number;
|
|
3477
|
+
heightPx: number;
|
|
3478
|
+
}>, OperationDefinition<"toggleCheckbox", {
|
|
3479
|
+
runId: StableId$1;
|
|
3480
|
+
}>, OperationDefinition<"updateFields", {
|
|
3481
|
+
results: string[];
|
|
3482
|
+
}>, OperationDefinition<"insertToc", {
|
|
3483
|
+
runId: StableId$1;
|
|
3484
|
+
levels?: TocLevels;
|
|
3485
|
+
leader?: TocLeader;
|
|
3486
|
+
/** With a label the field is a TABLE OF FIGURES (`TOC \c "Label"`): the
|
|
3487
|
+
* entries come from the label's caption paragraphs instead of headings. */
|
|
3488
|
+
captionLabel?: string;
|
|
3489
|
+
entryCount: number;
|
|
3490
|
+
nodeIds: StableId$1[];
|
|
3491
|
+
}>, OperationDefinition<"insertCaption", {
|
|
3492
|
+
blockId: StableId$1;
|
|
3493
|
+
label: string;
|
|
3494
|
+
text?: string;
|
|
3495
|
+
position?: "below" | "above";
|
|
3496
|
+
nodeIds: StableId$1[];
|
|
3497
|
+
}>, OperationDefinition<"ensureRefBookmark", {
|
|
3498
|
+
blockId: StableId$1;
|
|
3499
|
+
name: string;
|
|
3500
|
+
}>, OperationDefinition<"insertIndexEntry", {
|
|
3501
|
+
runId: StableId$1;
|
|
3502
|
+
entry: string;
|
|
3503
|
+
nodeIds: StableId$1[];
|
|
3504
|
+
}>, OperationDefinition<"insertIndex", {
|
|
3505
|
+
runId: StableId$1;
|
|
3506
|
+
entryCount: number;
|
|
3507
|
+
nodeIds: StableId$1[];
|
|
3508
|
+
}>, OperationDefinition<"refreshIndex", {
|
|
3509
|
+
entryCount: number;
|
|
3510
|
+
nodeIds: StableId$1[];
|
|
3511
|
+
}>, OperationDefinition<"createStyle", {
|
|
3512
|
+
style: StyleSpec;
|
|
3513
|
+
}>, OperationDefinition<"modifyStyle", {
|
|
3514
|
+
styleId: string;
|
|
3515
|
+
patch: StylePatch;
|
|
3516
|
+
}>, OperationDefinition<"deleteStyle", {
|
|
3517
|
+
styleId: string;
|
|
3518
|
+
}>, OperationDefinition<"setNumberingLevel", {
|
|
3519
|
+
blockId: StableId$1;
|
|
3520
|
+
ilvl: number | null;
|
|
3521
|
+
patch: LevelPatch;
|
|
3522
|
+
}>, OperationDefinition<"setNumberingRestart", {
|
|
3523
|
+
blockId: StableId$1;
|
|
3524
|
+
start: number | null;
|
|
3525
|
+
}>, OperationDefinition<"setParagraphBorders", {
|
|
3526
|
+
blockId: StableId$1;
|
|
3527
|
+
patch: ParagraphBordersPatch;
|
|
3528
|
+
} & SuggestablePayload>, OperationDefinition<"setTabStops", {
|
|
3529
|
+
blockId: StableId$1;
|
|
3530
|
+
stops: TabStopSpec[];
|
|
3531
|
+
} & SuggestablePayload>, OperationDefinition<"setTableBorders", {
|
|
3532
|
+
cellParagraphId: StableId$1;
|
|
3533
|
+
scope: "cell" | "table";
|
|
3534
|
+
edges: TableBorderEdge[];
|
|
3535
|
+
border: TableBorderSpec | null;
|
|
3536
|
+
} & SuggestablePayload>, OperationDefinition<"setTableStyle", {
|
|
3537
|
+
cellParagraphId: StableId$1;
|
|
3538
|
+
styleId: string | null;
|
|
3539
|
+
} & SuggestablePayload>, OperationDefinition<"setTableLook", {
|
|
3540
|
+
cellParagraphId: StableId$1;
|
|
3541
|
+
look: Partial<TableLookToggles>;
|
|
3542
|
+
} & SuggestablePayload>, OperationDefinition<"setTableWidth", {
|
|
3543
|
+
cellParagraphId: StableId$1;
|
|
3544
|
+
unit: "pt" | "pct" | "auto";
|
|
3545
|
+
value?: number;
|
|
3546
|
+
} & SuggestablePayload>, OperationDefinition<"setTableColumnWidth", {
|
|
3547
|
+
cellParagraphId: StableId$1;
|
|
3548
|
+
colIdx: number;
|
|
3549
|
+
widthPt: number;
|
|
3550
|
+
} & SuggestablePayload>, OperationDefinition<"setTableLayout", {
|
|
3551
|
+
cellParagraphId: StableId$1;
|
|
3552
|
+
layout: "fixed" | "autofit";
|
|
3553
|
+
renderedWidths?: number[];
|
|
3554
|
+
} & SuggestablePayload>, OperationDefinition<"setTableCellMargins", {
|
|
3555
|
+
cellParagraphId: StableId$1;
|
|
3556
|
+
scope: "cell" | "table";
|
|
3557
|
+
margins: CellMarginsPt | null;
|
|
3558
|
+
} & SuggestablePayload>, OperationDefinition<"setTableHeaderRows", {
|
|
3559
|
+
cellParagraphId: StableId$1;
|
|
3560
|
+
count: number;
|
|
3561
|
+
} & SuggestablePayload>, OperationDefinition<"insertTableFormula", {
|
|
3562
|
+
cellParagraphId: StableId$1;
|
|
3563
|
+
formula: string;
|
|
3564
|
+
numFmt?: string;
|
|
3565
|
+
nodeIds: StableId$1[];
|
|
3566
|
+
}>, OperationDefinition<"sortTableRows", {
|
|
3567
|
+
cellParagraphId: StableId$1;
|
|
3568
|
+
colIdx: number;
|
|
3569
|
+
order: "asc" | "desc";
|
|
3570
|
+
/** "kind" would collide with the intent discriminant, hence "compare". */
|
|
3571
|
+
compare: "text" | "number";
|
|
3572
|
+
hasHeader?: boolean;
|
|
3573
|
+
}>, OperationDefinition<"convertTextToTable", {
|
|
3574
|
+
blockId: StableId$1;
|
|
3575
|
+
moreBlockIds?: StableId$1[];
|
|
3576
|
+
separator: "tab" | "comma";
|
|
3577
|
+
cellCount: number;
|
|
3578
|
+
nodeIds: StableId$1[];
|
|
3579
|
+
}>, OperationDefinition<"convertTableToText", {
|
|
3580
|
+
cellParagraphId: StableId$1;
|
|
3581
|
+
separator: "tab" | "comma";
|
|
3582
|
+
rowCount: number;
|
|
3583
|
+
nodeIds: StableId$1[];
|
|
3584
|
+
}>, OperationDefinition<"insertEndnote", {
|
|
3585
|
+
runId: StableId$1;
|
|
3586
|
+
text: string;
|
|
3587
|
+
nodeIds: StableId$1[];
|
|
3588
|
+
}>, OperationDefinition<"setCrop", {
|
|
3589
|
+
runId: StableId$1;
|
|
3590
|
+
objectIndex?: number;
|
|
3591
|
+
crop: ImageCrop;
|
|
3592
|
+
}>, OperationDefinition<"setModel3DRotation", {
|
|
3593
|
+
runId: StableId$1;
|
|
3594
|
+
objectIndex?: number;
|
|
3595
|
+
rotation: Model3DRotation;
|
|
3596
|
+
}>, OperationDefinition<"setDrawingTextFit", {
|
|
3597
|
+
runId: StableId$1;
|
|
3598
|
+
objectIndex?: number;
|
|
3599
|
+
mode: DrawingTextFitMode;
|
|
3600
|
+
fontScalePct?: number;
|
|
3601
|
+
}>, OperationDefinition<"insertMergeField", {
|
|
3602
|
+
runId: StableId$1;
|
|
3603
|
+
name: string;
|
|
3604
|
+
nodeIds: StableId$1[];
|
|
3605
|
+
}>, OperationDefinition<"insertCitation", {
|
|
3606
|
+
runId: StableId$1;
|
|
3607
|
+
tag: string;
|
|
3608
|
+
nodeIds: StableId$1[];
|
|
3609
|
+
}>, OperationDefinition<"insertBibliography", {
|
|
3610
|
+
runId: StableId$1;
|
|
3611
|
+
entryCount: number;
|
|
3612
|
+
nodeIds: StableId$1[];
|
|
3613
|
+
}>, OperationDefinition<"refreshBibliography", {
|
|
3614
|
+
entryCount: number;
|
|
3615
|
+
nodeIds: StableId$1[];
|
|
3616
|
+
}>, OperationDefinition<"createCitationSource", {
|
|
3617
|
+
source: CitationSourceSpec;
|
|
3618
|
+
}>, OperationDefinition<"editCitationSource", {
|
|
3619
|
+
tag: string;
|
|
3620
|
+
patch: CitationSourcePatch;
|
|
3621
|
+
}>, OperationDefinition<"deleteCitationSource", {
|
|
3622
|
+
tag: string;
|
|
3623
|
+
}>, OperationDefinition<"setCitationStyle", {
|
|
3624
|
+
style: CitationStyle;
|
|
3625
|
+
}>, OperationDefinition<"createBuildingBlock", {
|
|
3626
|
+
name: string;
|
|
3627
|
+
category?: string;
|
|
3628
|
+
blocksXml: string;
|
|
3629
|
+
}>, OperationDefinition<"insertBuildingBlock", {
|
|
3630
|
+
name: string;
|
|
3631
|
+
/** The carried-id budget, computed by the caller from the SAME already-
|
|
3632
|
+
* synced glossary state the apply side reads (buildingBlockNodeCount) —
|
|
3633
|
+
* the insertBibliography entryCount pattern. */
|
|
3634
|
+
blockCount: number;
|
|
3635
|
+
}>, OperationDefinition<"deleteBuildingBlock", {
|
|
3636
|
+
name: string;
|
|
3637
|
+
}>, OperationDefinition<"insertWatermark", {
|
|
3638
|
+
text: string;
|
|
3639
|
+
headerCount: number;
|
|
3640
|
+
diagonal?: boolean;
|
|
3641
|
+
color?: string;
|
|
3642
|
+
opacity?: number;
|
|
3643
|
+
nodeIds: StableId$1[];
|
|
3644
|
+
}>, OperationDefinition<"insertPictureWatermark", {
|
|
3645
|
+
blobSha: string;
|
|
3646
|
+
bytesLen: number;
|
|
3647
|
+
ext: string;
|
|
3648
|
+
iv?: string;
|
|
3649
|
+
naturalWidthPx: number;
|
|
3650
|
+
naturalHeightPx: number;
|
|
3651
|
+
headerCount: number;
|
|
3652
|
+
washout?: boolean;
|
|
3653
|
+
nodeIds: StableId$1[];
|
|
3654
|
+
}>, OperationDefinition<"removeWatermark", NoPayload>, OperationDefinition<"setTitlePage", {
|
|
3655
|
+
enabled: boolean;
|
|
3656
|
+
nodeIds: StableId$1[];
|
|
3657
|
+
}>, OperationDefinition<"setEvenOddHeaders", {
|
|
3658
|
+
enabled: boolean;
|
|
3659
|
+
nodeIds: StableId$1[];
|
|
3660
|
+
}>, OperationDefinition<"setPageNumberFormat", {
|
|
3661
|
+
fmt?: PageNumberFormat | null;
|
|
3662
|
+
start?: number | null;
|
|
3663
|
+
}>, OperationDefinition<"setHyphenation", {
|
|
3664
|
+
auto?: boolean;
|
|
3665
|
+
zonePt?: number | null;
|
|
3666
|
+
noCaps?: boolean;
|
|
3667
|
+
}>, OperationDefinition<"insertPageNumberPosition", {
|
|
3668
|
+
position: PageNumberGalleryPosition;
|
|
3669
|
+
align: PageNumberGalleryAlign;
|
|
3670
|
+
nodeIds: StableId$1[];
|
|
3671
|
+
}>, OperationDefinition<"removePageNumbers", Record<never, never>>, OperationDefinition<"insertHeaderFooterPreset", {
|
|
3672
|
+
hfKind: "header" | "footer";
|
|
3673
|
+
preset: HeaderFooterPreset;
|
|
3674
|
+
nodeIds: StableId$1[];
|
|
3675
|
+
}>, OperationDefinition<"setFootnoteOptions", {
|
|
3676
|
+
fmt?: NoteNumberFormat | null;
|
|
3677
|
+
start?: number | null;
|
|
3678
|
+
restart?: NoteRestart | null;
|
|
3679
|
+
pos?: "pageBottom" | "beneathText" | null;
|
|
3680
|
+
}>, OperationDefinition<"setEndnoteOptions", {
|
|
3681
|
+
fmt?: NoteNumberFormat | null;
|
|
3682
|
+
start?: number | null;
|
|
3683
|
+
restart?: NoteRestart | null;
|
|
3684
|
+
pos?: "sectEnd" | "docEnd" | null;
|
|
3685
|
+
}>];
|
|
3686
|
+
type AnyOperationDefinition = (typeof OPERATIONS)[number];
|
|
3687
|
+
/** Distributes: one body type per registered operation. */
|
|
3688
|
+
type BodyOf<D> = D extends OperationDefinition<infer Kind, infer Payload> ? {
|
|
3689
|
+
kind: Kind;
|
|
3690
|
+
} & Payload : never;
|
|
3691
|
+
type RegisteredOperationKind = AnyOperationDefinition["kind"];
|
|
3692
|
+
/**
|
|
3693
|
+
* The wire body of every registered operation. @wordinweb/collab intersects
|
|
3694
|
+
* this with its IntentBase bookkeeping to form the Intent variants, so the
|
|
3695
|
+
* payload is declared once and the wire shape follows.
|
|
3696
|
+
*/
|
|
3697
|
+
type RegisteredOperationBody = BodyOf<AnyOperationDefinition>;
|
|
3698
|
+
|
|
3699
|
+
interface SmartArtTextFormat {
|
|
3700
|
+
fontFamily: string;
|
|
3701
|
+
fontSizePt: number;
|
|
3702
|
+
color: string;
|
|
3703
|
+
bold: boolean;
|
|
3704
|
+
italic: boolean;
|
|
3705
|
+
alignment: "left" | "center" | "right";
|
|
3706
|
+
}
|
|
3707
|
+
|
|
3708
|
+
type ObjectArrangeAction = "alignLeft" | "alignCenter" | "alignRight" | "alignTop" | "alignMiddle" | "alignBottom" | "rotateLeft" | "rotateRight" | "bringToFront" | "sendToBack";
|
|
3709
|
+
type SelectedObjectKind = "shape" | "line" | "smartArt" | "chart" | "image" | "model3d";
|
|
3710
|
+
type SelectedObjectCommand = "altText" | "editText" | "fill" | "outline" | "lineStyle" | "rotate" | "size" | "position" | "crop" | "wrapInline" | "wrapSquare" | "wrapTopAndBottom" | "wrapFront" | "wrapBehind" | "autofitNone" | "autofitResizeShape" | "autofitShrinkText" | "bringForward" | "sendBackward" | "reset3d" | "delete";
|
|
3711
|
+
/** A local edit expressed as a replicable intent, emitted by the editor for
|
|
3712
|
+
* the collab layer. Positions are stable ids; the connection adds wire
|
|
3713
|
+
* bookkeeping (clientId/clientSeq/base). Mirrors the @wordinweb/collab intent
|
|
3714
|
+
* shapes without a dependency on that package — except for the registered
|
|
3715
|
+
* operations, whose single declaration in registry.ts feeds BOTH this type
|
|
3716
|
+
* and the collab intent union, so there is nothing left to mirror. */
|
|
3717
|
+
type EditorIntent = RegisteredOperationBody | {
|
|
3718
|
+
kind: "insertText";
|
|
3719
|
+
at: {
|
|
3720
|
+
blockId: number;
|
|
3721
|
+
runId: number;
|
|
3722
|
+
offset: number;
|
|
3723
|
+
};
|
|
3724
|
+
text: string;
|
|
3725
|
+
suggest?: {
|
|
3726
|
+
author: string;
|
|
3727
|
+
date: string;
|
|
3728
|
+
};
|
|
3729
|
+
} | {
|
|
3730
|
+
kind: "insertSeparator";
|
|
3731
|
+
at: {
|
|
3732
|
+
blockId: number;
|
|
3733
|
+
runId: number;
|
|
3734
|
+
offset: number;
|
|
3735
|
+
};
|
|
3736
|
+
separator: "br" | "tab";
|
|
3737
|
+
suggest?: {
|
|
3738
|
+
author: string;
|
|
3739
|
+
date: string;
|
|
3740
|
+
};
|
|
3741
|
+
} | {
|
|
3742
|
+
kind: "deleteSeparator";
|
|
3743
|
+
at: {
|
|
3744
|
+
blockId: number;
|
|
3745
|
+
runId: number;
|
|
3746
|
+
offset: number;
|
|
3747
|
+
};
|
|
3748
|
+
suggest?: {
|
|
3749
|
+
author: string;
|
|
3750
|
+
date: string;
|
|
3751
|
+
};
|
|
3752
|
+
} | {
|
|
3753
|
+
kind: "deleteText";
|
|
3754
|
+
blockId: number;
|
|
3755
|
+
runId: number;
|
|
3756
|
+
start: number;
|
|
3757
|
+
end: number;
|
|
3758
|
+
} | {
|
|
3759
|
+
kind: "splitParagraph";
|
|
3760
|
+
at: {
|
|
3761
|
+
blockId: number;
|
|
3762
|
+
runId: number;
|
|
3763
|
+
offset: number;
|
|
3764
|
+
};
|
|
3765
|
+
newBlockId: number;
|
|
3766
|
+
newRunId: number;
|
|
3767
|
+
suggest?: {
|
|
3768
|
+
author: string;
|
|
3769
|
+
date: string;
|
|
3770
|
+
};
|
|
3771
|
+
} | {
|
|
3772
|
+
kind: "formatRun";
|
|
3773
|
+
blockId: number;
|
|
3774
|
+
runId: number;
|
|
3775
|
+
patch: Record<string, unknown>;
|
|
3776
|
+
} | {
|
|
3777
|
+
kind: "formatRange";
|
|
3778
|
+
blockId: number;
|
|
3779
|
+
runId: number;
|
|
3780
|
+
start: number;
|
|
3781
|
+
end: number;
|
|
3782
|
+
patch: Record<string, unknown>;
|
|
3783
|
+
beforeId?: number;
|
|
3784
|
+
middleId: number;
|
|
3785
|
+
afterId?: number;
|
|
3786
|
+
} | {
|
|
3787
|
+
kind: "formatParagraph";
|
|
3788
|
+
blockId: number;
|
|
3789
|
+
align?: "left" | "center" | "right" | "justify";
|
|
3790
|
+
styleId?: string | null;
|
|
3791
|
+
} | {
|
|
3792
|
+
kind: "mergeParagraph";
|
|
3793
|
+
blockId: number;
|
|
3794
|
+
} | {
|
|
3795
|
+
kind: "setListLevel";
|
|
3796
|
+
blockId: number;
|
|
3797
|
+
delta: 1 | -1;
|
|
3798
|
+
} | {
|
|
3799
|
+
kind: "pasteBlocks";
|
|
3800
|
+
afterBlockId: number;
|
|
3801
|
+
blocksXml: string;
|
|
3802
|
+
nodeIds: number[];
|
|
3803
|
+
} | {
|
|
3804
|
+
kind: "suggestRevision";
|
|
3805
|
+
ranges?: {
|
|
3806
|
+
blockId: number;
|
|
3807
|
+
runId: number;
|
|
3808
|
+
start: number;
|
|
3809
|
+
end: number;
|
|
3810
|
+
}[];
|
|
3811
|
+
marks?: {
|
|
3812
|
+
blockId: number;
|
|
3813
|
+
glyph: "ins" | "del";
|
|
3814
|
+
}[];
|
|
3815
|
+
suggest: {
|
|
3816
|
+
author: string;
|
|
3817
|
+
date: string;
|
|
3818
|
+
};
|
|
3819
|
+
} | {
|
|
3820
|
+
kind: "acceptRevision";
|
|
3821
|
+
index: number;
|
|
3822
|
+
} | {
|
|
3823
|
+
kind: "rejectRevision";
|
|
3824
|
+
index: number;
|
|
3825
|
+
} | {
|
|
3826
|
+
kind: "acceptAllRevisions";
|
|
3827
|
+
author?: string;
|
|
3828
|
+
} | {
|
|
2360
3829
|
kind: "rejectAllRevisions";
|
|
3830
|
+
author?: string;
|
|
2361
3831
|
} | {
|
|
2362
3832
|
kind: "setImageWrap";
|
|
2363
3833
|
runId: number;
|
|
3834
|
+
objectIndex?: number;
|
|
2364
3835
|
mode: "inline" | "square" | "topAndBottom" | "none" | "behind";
|
|
2365
3836
|
} | {
|
|
2366
3837
|
kind: "setFloatingPagePosition";
|
|
2367
3838
|
runId: number;
|
|
3839
|
+
objectIndex?: number;
|
|
2368
3840
|
xPx: number;
|
|
2369
3841
|
yPx: number;
|
|
2370
3842
|
} | {
|
|
2371
3843
|
kind: "resizeDrawing";
|
|
2372
3844
|
runId: number;
|
|
3845
|
+
objectIndex?: number;
|
|
2373
3846
|
widthPx: number;
|
|
2374
3847
|
heightPx: number;
|
|
2375
3848
|
} | {
|
|
2376
3849
|
kind: "setDrawingRotation";
|
|
2377
3850
|
runId: number;
|
|
3851
|
+
objectIndex?: number;
|
|
2378
3852
|
degrees: number;
|
|
2379
3853
|
} | {
|
|
2380
3854
|
kind: "setDrawingOrder";
|
|
2381
3855
|
runId: number;
|
|
3856
|
+
objectIndex?: number;
|
|
2382
3857
|
order: "front" | "back";
|
|
2383
3858
|
} | {
|
|
2384
3859
|
kind: "setDrawingLineStyle";
|
|
2385
3860
|
runId: number;
|
|
3861
|
+
objectIndex?: number;
|
|
2386
3862
|
color: string;
|
|
2387
3863
|
widthPx: number;
|
|
2388
3864
|
dash: "solid" | "dashed" | "dotted";
|
|
2389
3865
|
} | {
|
|
2390
3866
|
kind: "setImageAltText";
|
|
2391
3867
|
runId: number;
|
|
3868
|
+
objectIndex?: number;
|
|
2392
3869
|
alt: string;
|
|
2393
3870
|
} | {
|
|
2394
3871
|
kind: "setDrawingFill";
|
|
2395
3872
|
runId: number;
|
|
3873
|
+
objectIndex?: number;
|
|
2396
3874
|
color: string | null;
|
|
2397
3875
|
} | {
|
|
2398
3876
|
kind: "setSmartArtFill";
|
|
2399
3877
|
runId: number;
|
|
3878
|
+
objectIndex?: number;
|
|
2400
3879
|
color: string | null;
|
|
2401
3880
|
nodeIndex?: number;
|
|
2402
3881
|
} | {
|
|
2403
3882
|
kind: "setSmartArtNodeText";
|
|
2404
3883
|
runId: number;
|
|
3884
|
+
objectIndex?: number;
|
|
2405
3885
|
index: number;
|
|
2406
3886
|
text: string;
|
|
2407
3887
|
} | {
|
|
2408
3888
|
kind: "setDrawingWordArtText";
|
|
2409
3889
|
runId: number;
|
|
3890
|
+
objectIndex?: number;
|
|
2410
3891
|
text: string;
|
|
2411
3892
|
} | {
|
|
2412
3893
|
kind: "insertBreak";
|
|
@@ -2419,11 +3900,6 @@ type EditorIntent = {
|
|
|
2419
3900
|
boundary: number;
|
|
2420
3901
|
deltaPx: number;
|
|
2421
3902
|
renderedWidths?: number[];
|
|
2422
|
-
} | {
|
|
2423
|
-
kind: "resizeTableRow";
|
|
2424
|
-
cellParagraphId: number;
|
|
2425
|
-
rowIdx: number;
|
|
2426
|
-
heightPx: number;
|
|
2427
3903
|
} | {
|
|
2428
3904
|
kind: "moveTable";
|
|
2429
3905
|
cellParagraphId: number;
|
|
@@ -2434,7 +3910,7 @@ type EditorIntent = {
|
|
|
2434
3910
|
} | {
|
|
2435
3911
|
kind: "tableOp";
|
|
2436
3912
|
cellParagraphId: number;
|
|
2437
|
-
op: {
|
|
3913
|
+
op: "deleteTable" | {
|
|
2438
3914
|
kind: "textWrapping";
|
|
2439
3915
|
wrapping: "none" | "around";
|
|
2440
3916
|
xPx: number;
|
|
@@ -2443,16 +3919,20 @@ type EditorIntent = {
|
|
|
2443
3919
|
} | {
|
|
2444
3920
|
kind: "removeDrawing";
|
|
2445
3921
|
runId: number;
|
|
3922
|
+
objectIndex?: number;
|
|
2446
3923
|
} | {
|
|
2447
3924
|
kind: "setMathLinear";
|
|
2448
3925
|
blockId: number;
|
|
3926
|
+
mathIndex: number;
|
|
2449
3927
|
mathText: string;
|
|
2450
3928
|
} | {
|
|
2451
3929
|
kind: "deleteMath";
|
|
2452
3930
|
blockId: number;
|
|
3931
|
+
mathIndex: number;
|
|
2453
3932
|
} | {
|
|
2454
3933
|
kind: "moveMath";
|
|
2455
3934
|
blockId: number;
|
|
3935
|
+
mathIndex: number;
|
|
2456
3936
|
at: {
|
|
2457
3937
|
blockId: number;
|
|
2458
3938
|
runId: number;
|
|
@@ -2465,6 +3945,76 @@ type EditorIntent = {
|
|
|
2465
3945
|
nodeIds: number[];
|
|
2466
3946
|
};
|
|
2467
3947
|
|
|
3948
|
+
/**
|
|
3949
|
+
* Compare Documents — Word's "legal blackline".
|
|
3950
|
+
*
|
|
3951
|
+
* Produces a THIRD document: `revised`, with every difference from `original`
|
|
3952
|
+
* expressed as an ordinary tracked change attributed to one reviewer. Nothing
|
|
3953
|
+
* here invents a revision format; it drives the same w:ins / w:del / *PrChange
|
|
3954
|
+
* vocabulary the suggesting editor writes, so the result is reviewable with
|
|
3955
|
+
* the accept/reject surface that already exists, and round-trips through it:
|
|
3956
|
+
*
|
|
3957
|
+
* accept every revision in the result → `revised`
|
|
3958
|
+
* reject every revision in the result → `original`
|
|
3959
|
+
*
|
|
3960
|
+
* (Equal modulo run coalescing — accepting a revision unwraps it without
|
|
3961
|
+
* re-merging the runs it split, which is true of Word too. The gate test in
|
|
3962
|
+
* test/compare-roundtrip.test.ts states the canonical form exactly.)
|
|
3963
|
+
*
|
|
3964
|
+
* ## Tiers, stated plainly
|
|
3965
|
+
*
|
|
3966
|
+
* **Text — full.** Paragraphs align by histogram diff over a text/style/
|
|
3967
|
+
* numbering fingerprint, then by Dice similarity inside the gaps; matched
|
|
3968
|
+
* paragraphs are diffed word by word. Insertions, deletions, paragraph splits
|
|
3969
|
+
* and merges, paragraph-property and run-property changes are all expressed
|
|
3970
|
+
* faithfully.
|
|
3971
|
+
*
|
|
3972
|
+
* **Tables — rows and cells.** A matched table pair aligns its ROWS by the
|
|
3973
|
+
* same histogram pass, so a mid-table insert does not cascade. Matched rows
|
|
3974
|
+
* with the same cell count recurse into each cell's paragraphs. A row that
|
|
3975
|
+
* matches nothing becomes a row insertion or deletion (w:trPr/w:ins, w:trPr/
|
|
3976
|
+
* w:del). A row pair whose cell COUNTS differ is coarse: the whole row is
|
|
3977
|
+
* struck and the whole new row inserted.
|
|
3978
|
+
*
|
|
3979
|
+
* **Drawings, fields, footnote references and other non-text run content —
|
|
3980
|
+
* atomic.** They match themselves byte for byte or they are a change. A
|
|
3981
|
+
* changed image is a struck image plus an inserted one, never a patched one.
|
|
3982
|
+
*
|
|
3983
|
+
* **Paragraphs holding a hyperlink, content control, smart tag or inline
|
|
3984
|
+
* math — coarse.** Word-level diffing rebuilds a paragraph's runs, and a
|
|
3985
|
+
* revision wrapper may not sit around a `w:hyperlink` (the schema puts w:ins
|
|
3986
|
+
* INSIDE it). Such a paragraph is never word-diffed: if it changed at all it
|
|
3987
|
+
* is struck whole and the new one inserted whole, and `onNote` says so.
|
|
3988
|
+
*
|
|
3989
|
+
* **Headers, footers, footnotes, endnotes, comments, styles and numbering —
|
|
3990
|
+
* NOT compared.** The result carries `revised`'s. `onNote` reports when
|
|
3991
|
+
* `original`'s differ, so a reviewer is never told "no change" about something
|
|
3992
|
+
* that was never looked at.
|
|
3993
|
+
*
|
|
3994
|
+
* **Moves — not detected, by architecture.** `RevisionKind` has no moveFrom /
|
|
3995
|
+
* moveTo member and nothing in suggest.ts writes those elements, so a move is
|
|
3996
|
+
* a new output primitive, not a smarter aligner. A moved paragraph comes out
|
|
3997
|
+
* as a deletion plus an insertion, which is what Word usually produces too.
|
|
3998
|
+
*/
|
|
3999
|
+
interface CompareNote {
|
|
4000
|
+
code:
|
|
4001
|
+
/** A paragraph pair too structured to word-diff; struck and reinserted whole. */
|
|
4002
|
+
"coarse-paragraph"
|
|
4003
|
+
/** A table row pair whose cell counts differ; struck and reinserted whole. */
|
|
4004
|
+
| "coarse-row"
|
|
4005
|
+
/** A block that is neither a paragraph nor a table, added or removed. */
|
|
4006
|
+
| "untracked-block"
|
|
4007
|
+
/** A paragraph mark whose run properties differ across the swap; see below. */
|
|
4008
|
+
| "paragraph-mark-props"
|
|
4009
|
+
/** A part outside the body differs and was not compared. */
|
|
4010
|
+
| "part-not-compared"
|
|
4011
|
+
/** The documents share no paragraph at all; one paragraph mark goes untracked. */
|
|
4012
|
+
| "no-common-paragraph"
|
|
4013
|
+
/** Original-only content referencing a relationship the result does not have. */
|
|
4014
|
+
| "unresolved-relationship";
|
|
4015
|
+
detail: string;
|
|
4016
|
+
}
|
|
4017
|
+
|
|
2468
4018
|
type ParagraphAlignment = "left" | "center" | "right" | "justify";
|
|
2469
4019
|
interface PageLayoutPatch {
|
|
2470
4020
|
/** Margins in inches. */
|
|
@@ -2495,47 +4045,58 @@ interface PageLayoutPatch {
|
|
|
2495
4045
|
}
|
|
2496
4046
|
|
|
2497
4047
|
/**
|
|
2498
|
-
*
|
|
2499
|
-
*
|
|
4048
|
+
* Find & replace and selection text transforms. Matching runs over the
|
|
4049
|
+
* parsed model — every story: the body (incl. tables), each header and
|
|
4050
|
+
* footer part, and each footnote and endnote. Positions map back to source
|
|
4051
|
+
* w:t elements so hits can be selected, replaced, or case-transformed.
|
|
2500
4052
|
*
|
|
2501
|
-
*
|
|
2502
|
-
*
|
|
4053
|
+
* Within one story, paragraphs concatenate with "\n" standing for the
|
|
4054
|
+
* paragraph mark (Word's ^p), so a query containing "\n" matches across
|
|
4055
|
+
* paragraph boundaries. A match never crosses a story boundary.
|
|
2503
4056
|
*/
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
interface
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
4057
|
+
/** Which story a match sits in. Every header part is "header" (and every
|
|
4058
|
+
* footer part "footer") regardless of which section references it. */
|
|
4059
|
+
type FindStory = "body" | "header" | "footer" | "footnote" | "endnote";
|
|
4060
|
+
interface FindOptions {
|
|
4061
|
+
/** Case-sensitive matching. Default: case-insensitive. */
|
|
4062
|
+
matchCase?: boolean;
|
|
4063
|
+
/** Match whole words only: the characters adjacent to the hit must not be
|
|
4064
|
+
* letters, digits, or underscores (Word's "Find whole words only"). */
|
|
4065
|
+
wholeWord?: boolean;
|
|
4066
|
+
/** Word's wildcard pattern language (the subset below). Like Word, wildcard
|
|
4067
|
+
* matching is always case-sensitive and ignores wholeWord — the pattern's
|
|
4068
|
+
* own `<` and `>` express word boundaries. */
|
|
4069
|
+
wildcards?: boolean;
|
|
4070
|
+
}
|
|
4071
|
+
interface ReplaceAllResult {
|
|
4072
|
+
total: number;
|
|
4073
|
+
byStory: Partial<Record<FindStory, number>>;
|
|
4074
|
+
}
|
|
4075
|
+
/** A wire range inside one run: the shape suggestRevision and presence use. */
|
|
4076
|
+
interface WireRange {
|
|
4077
|
+
blockId: number;
|
|
4078
|
+
runId: number;
|
|
4079
|
+
start: number;
|
|
4080
|
+
end: number;
|
|
2523
4081
|
}
|
|
2524
4082
|
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
4083
|
+
/** Every building block the glossary part holds, name and category, in
|
|
4084
|
+
* document order — the gallery listing the toolbar groups by category. Empty
|
|
4085
|
+
* when the package has no glossary part. */
|
|
4086
|
+
interface BuildingBlockInfo {
|
|
4087
|
+
name: string;
|
|
4088
|
+
category: string;
|
|
2529
4089
|
}
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
/**
|
|
2534
|
-
|
|
2535
|
-
/**
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
4090
|
+
|
|
4091
|
+
interface WatermarkSpec {
|
|
4092
|
+
text: string;
|
|
4093
|
+
/** Word's default 45° stamp. False lays the text flat across the page. */
|
|
4094
|
+
diagonal?: boolean;
|
|
4095
|
+
/** Glyph colour as RRGGBB, the form every other operation uses. Defaults to
|
|
4096
|
+
* Word's silver. */
|
|
4097
|
+
color?: string;
|
|
4098
|
+
/** v:fill opacity, 0..1. Defaults to Word's washed-out 0.5. */
|
|
4099
|
+
opacity?: number;
|
|
2539
4100
|
}
|
|
2540
4101
|
|
|
2541
4102
|
interface MissingFont {
|
|
@@ -2559,6 +4120,7 @@ interface MissingFont {
|
|
|
2559
4120
|
* against everything sequenced in `(base, seq)` before applying and
|
|
2560
4121
|
* broadcasting the canonical form (doc 03).
|
|
2561
4122
|
*/
|
|
4123
|
+
|
|
2562
4124
|
type StableId = number;
|
|
2563
4125
|
/** A caret/endpoint position within a run. */
|
|
2564
4126
|
interface Position {
|
|
@@ -2599,10 +4161,13 @@ interface SuggestRevisionIntent extends IntentBase {
|
|
|
2599
4161
|
blockId: StableId;
|
|
2600
4162
|
glyph: "ins" | "del";
|
|
2601
4163
|
}[];
|
|
2602
|
-
suggest:
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
4164
|
+
suggest: SuggestMeta;
|
|
4165
|
+
}
|
|
4166
|
+
/** Author + date of a tracked change, generated once by the originating
|
|
4167
|
+
* client so every replica writes the same w:author/w:date (rule a above). */
|
|
4168
|
+
interface SuggestMeta {
|
|
4169
|
+
author: string;
|
|
4170
|
+
date: string;
|
|
2606
4171
|
}
|
|
2607
4172
|
/** Insert `text` at a position. With `suggest`, the insertion is recorded as
|
|
2608
4173
|
* a tracked change (w:ins) carrying the author + date (revision tracking /
|
|
@@ -2617,6 +4182,37 @@ interface InsertTextIntent extends IntentBase {
|
|
|
2617
4182
|
date: string;
|
|
2618
4183
|
};
|
|
2619
4184
|
}
|
|
4185
|
+
/**
|
|
4186
|
+
* Insert an inline separator — a soft line break (w:br, Shift+Enter) or a
|
|
4187
|
+
* tab character (w:tab, Tab in a body paragraph) — at a position. The
|
|
4188
|
+
* mutation splits the addressed run's w:t IN PLACE (no new run, every stable
|
|
4189
|
+
* id preserved), and a separator counts ONE unit in the run's wire-offset
|
|
4190
|
+
* basis (core runWireLength), so the transform is exactly an insertText of
|
|
4191
|
+
* length one. With `suggest` the separator is recorded as a w:ins sibling
|
|
4192
|
+
* (insertSuggestedSeparator) like a typed suggestion.
|
|
4193
|
+
*/
|
|
4194
|
+
interface InsertSeparatorIntent extends IntentBase {
|
|
4195
|
+
kind: "insertSeparator";
|
|
4196
|
+
at: Position;
|
|
4197
|
+
separator: "br" | "tab";
|
|
4198
|
+
suggest?: SuggestMeta;
|
|
4199
|
+
}
|
|
4200
|
+
/**
|
|
4201
|
+
* Delete the inline separator (w:br / w:tab / w:cr) occupying wire unit
|
|
4202
|
+
* [at.offset, at.offset+1) of the addressed run — insertSeparator's inverse
|
|
4203
|
+
* (a separator-aware Backspace/Delete). The plain mutation removes the
|
|
4204
|
+
* separator element and joins the two w:t halves its insert split, so the
|
|
4205
|
+
* transform is exactly a deleteText of length one in the separator-counting
|
|
4206
|
+
* wire basis. With `suggest` the separator is recorded as a tracked deletion
|
|
4207
|
+
* instead (deleteSuggestedSeparator: a w:del around the separator's own run
|
|
4208
|
+
* slice, the host run splitting like a text strike). A unit that no longer
|
|
4209
|
+
* holds a separator (concurrent edit) is a clean no-op on every replica.
|
|
4210
|
+
*/
|
|
4211
|
+
interface DeleteSeparatorIntent extends IntentBase {
|
|
4212
|
+
kind: "deleteSeparator";
|
|
4213
|
+
at: Position;
|
|
4214
|
+
suggest?: SuggestMeta;
|
|
4215
|
+
}
|
|
2620
4216
|
/** Delete `[start, end)` characters within a single run. */
|
|
2621
4217
|
interface DeleteTextIntent extends IntentBase {
|
|
2622
4218
|
kind: "deleteText";
|
|
@@ -2658,6 +4254,9 @@ interface FormatRunIntent extends IntentBase {
|
|
|
2658
4254
|
/** RunFormatPatch (bold/italic/underline/strike/color/…). Structural shape
|
|
2659
4255
|
* mirrors @wordinweb/core's RunFormatPatch; carried verbatim. */
|
|
2660
4256
|
patch: Record<string, unknown>;
|
|
4257
|
+
/** Tracked-change (suggesting) metadata: the run records the properties it
|
|
4258
|
+
* had in a w:rPrChange instead of losing them. Omit for a direct format. */
|
|
4259
|
+
suggest?: SuggestMeta;
|
|
2661
4260
|
}
|
|
2662
4261
|
/**
|
|
2663
4262
|
* Paragraph-level formatting: alignment and/or paragraph style. Block-level —
|
|
@@ -2670,17 +4269,26 @@ interface FormatParagraphIntent extends IntentBase {
|
|
|
2670
4269
|
align?: "left" | "center" | "right" | "justify";
|
|
2671
4270
|
/** Paragraph style id; null clears to Normal. Omit to leave unchanged. */
|
|
2672
4271
|
styleId?: string | null;
|
|
4272
|
+
/** Tracked-change (suggesting) metadata: the paragraph records the
|
|
4273
|
+
* properties it had in a w:pPrChange. Omit for a direct format. */
|
|
4274
|
+
suggest?: SuggestMeta;
|
|
2673
4275
|
}
|
|
2674
4276
|
/**
|
|
2675
4277
|
* Turn a paragraph into a bullet/numbered list item, or clear its list
|
|
2676
4278
|
* formatting (kind null). Block-level: mutates w:pPr/numbering, preserves the
|
|
2677
4279
|
* block id, moves no text — transform identity.
|
|
4280
|
+
*
|
|
4281
|
+
* A multi-paragraph selection rides in ONE intent (optional `moreBlockIds`
|
|
4282
|
+
* beyond the addressed paragraph): the single apply mints ONE numbering
|
|
4283
|
+
* definition shared by every target, which is both Word's semantics (one
|
|
4284
|
+
* continuous list) and the only convergent shape — per-paragraph intents
|
|
4285
|
+
* each minted a fresh definition at apply, diverging from the originator's
|
|
4286
|
+
* single shared-definition local mutation.
|
|
4287
|
+
*
|
|
4288
|
+
* REGISTERED: shape and wiring come from the core operation registry (see
|
|
4289
|
+
* RegisteredIntent below). The alias keeps the published type name.
|
|
2678
4290
|
*/
|
|
2679
|
-
|
|
2680
|
-
kind: "setListType";
|
|
2681
|
-
blockId: StableId;
|
|
2682
|
-
listKind: "bullet" | "number" | null;
|
|
2683
|
-
}
|
|
4291
|
+
type SetListTypeIntent = RegisteredIntentOf<"setListType">;
|
|
2684
4292
|
/**
|
|
2685
4293
|
* Format a character sub-range of a single run (plan doc 03 F3). The run is
|
|
2686
4294
|
* split into up to three pieces — before [0,start), middle [start,end)
|
|
@@ -2701,19 +4309,23 @@ interface FormatRangeIntent extends IntentBase {
|
|
|
2701
4309
|
beforeId?: StableId;
|
|
2702
4310
|
middleId: StableId;
|
|
2703
4311
|
afterId?: StableId;
|
|
4312
|
+
/** Tracked-change (suggesting) metadata: the middle piece records the
|
|
4313
|
+
* properties it had in a w:rPrChange. Omit for a direct format. */
|
|
4314
|
+
suggest?: SuggestMeta;
|
|
2704
4315
|
}
|
|
2705
4316
|
/**
|
|
2706
|
-
* A table operation
|
|
2707
|
-
*
|
|
2708
|
-
*
|
|
2709
|
-
*
|
|
2710
|
-
*
|
|
4317
|
+
* A table operation addressed by the stable id of a paragraph inside the
|
|
4318
|
+
* target cell. Every op is position-stable (no surviving run's offsets move),
|
|
4319
|
+
* so the transform is identity; concurrent edits into removed cells fail
|
|
4320
|
+
* cleanly at apply (retired ids). Ops that create tracked nodes (the inserts,
|
|
4321
|
+
* mergeDown's fresh continuation paragraph, splitCell's new cells) take their
|
|
4322
|
+
* ids from `nodeIds`; ops that remove content prune the retired ids at apply.
|
|
2711
4323
|
*/
|
|
2712
4324
|
interface TableOpIntent extends IntentBase {
|
|
2713
4325
|
/** Stable id of a paragraph inside the target cell. */
|
|
2714
4326
|
cellParagraphId: StableId;
|
|
2715
4327
|
kind: "tableOp";
|
|
2716
|
-
op: "deleteRow" | "deleteCol" | "deleteTable" | "rowAbove" | "rowBelow" | "colLeft" | "colRight" | {
|
|
4328
|
+
op: "deleteRow" | "deleteCol" | "deleteTable" | "rowAbove" | "rowBelow" | "colLeft" | "colRight" | "mergeRight" | "mergeDown" | "splitCell" | {
|
|
2717
4329
|
kind: "cellShading";
|
|
2718
4330
|
fill: string | null;
|
|
2719
4331
|
} | {
|
|
@@ -2725,10 +4337,18 @@ interface TableOpIntent extends IntentBase {
|
|
|
2725
4337
|
xPx: number;
|
|
2726
4338
|
yPx: number;
|
|
2727
4339
|
};
|
|
2728
|
-
/** For
|
|
2729
|
-
* new
|
|
2730
|
-
* alike. */
|
|
4340
|
+
/** For ops that create tracked nodes (rowAbove/rowBelow/colLeft/colRight,
|
|
4341
|
+
* mergeDown, splitCell): carried ids for the new nodes (p / r) in document
|
|
4342
|
+
* order, so replicas address them alike. */
|
|
2731
4343
|
nodeIds?: StableId[];
|
|
4344
|
+
/**
|
|
4345
|
+
* Tracked-change (suggesting) metadata; see FormatParagraphIntent. Only the
|
|
4346
|
+
* three FORMATTING ops honour it — cellShading and cellVAlign record a
|
|
4347
|
+
* w:tcPrChange, textWrapping a w:tblPrChange. The structural ops have no
|
|
4348
|
+
* tracked form and ignore it, so the surfaces that enforce suggesting mode
|
|
4349
|
+
* refuse those outright rather than send one.
|
|
4350
|
+
*/
|
|
4351
|
+
suggest?: SuggestMeta;
|
|
2732
4352
|
}
|
|
2733
4353
|
/**
|
|
2734
4354
|
* Merge a paragraph into its predecessor (Backspace at paragraph start). The
|
|
@@ -2740,6 +4360,14 @@ interface MergeParagraphIntent extends IntentBase {
|
|
|
2740
4360
|
kind: "mergeParagraph";
|
|
2741
4361
|
/** The paragraph to merge into the one before it. */
|
|
2742
4362
|
blockId: StableId;
|
|
4363
|
+
/**
|
|
4364
|
+
* Tracked-change (suggesting) metadata. Word tracks a merge as a DELETED
|
|
4365
|
+
* PARAGRAPH MARK: the pilcrow that separates the two paragraphs — the
|
|
4366
|
+
* PREVIOUS paragraph's mark — gets a w:del in its pPr/rPr, and both
|
|
4367
|
+
* paragraphs stay in place until the reviewer accepts. Omit for a direct
|
|
4368
|
+
* merge.
|
|
4369
|
+
*/
|
|
4370
|
+
suggest?: SuggestMeta;
|
|
2743
4371
|
}
|
|
2744
4372
|
/**
|
|
2745
4373
|
* Add a review comment anchored to an entire run. Comment markers
|
|
@@ -2835,11 +4463,14 @@ interface InsertMathIntent extends IntentBase {
|
|
|
2835
4463
|
mathText: string;
|
|
2836
4464
|
nodeIds: StableId[];
|
|
2837
4465
|
}
|
|
2838
|
-
/** Insert a shape/textbox drawing at the end of a run (sibling — identity).
|
|
4466
|
+
/** Insert a shape/textbox drawing at the end of a run (sibling — identity).
|
|
4467
|
+
* `preset` is a legacy named preset (line/verticalLine/rectangle/
|
|
4468
|
+
* roundedRectangle/ellipse/diamond/textBox) or any ST_ShapeType name core's
|
|
4469
|
+
* preset-geometry table knows; validated with isValidShapePreset. */
|
|
2839
4470
|
interface InsertShapeIntent extends IntentBase {
|
|
2840
4471
|
kind: "insertShape";
|
|
2841
4472
|
runId: StableId;
|
|
2842
|
-
preset:
|
|
4473
|
+
preset: string;
|
|
2843
4474
|
text?: string;
|
|
2844
4475
|
nodeIds: StableId[];
|
|
2845
4476
|
}
|
|
@@ -2865,6 +4496,8 @@ interface AdjustIndentIntent extends IntentBase {
|
|
|
2865
4496
|
kind: "adjustIndent";
|
|
2866
4497
|
blockId: StableId;
|
|
2867
4498
|
direction: 1 | -1;
|
|
4499
|
+
/** Tracked-change (suggesting) metadata; see FormatParagraphIntent. */
|
|
4500
|
+
suggest?: SuggestMeta;
|
|
2868
4501
|
}
|
|
2869
4502
|
/** Set paragraph line/before/after spacing. Block-level, identity. */
|
|
2870
4503
|
interface SetSpacingIntent extends IntentBase {
|
|
@@ -2872,6 +4505,8 @@ interface SetSpacingIntent extends IntentBase {
|
|
|
2872
4505
|
blockId: StableId;
|
|
2873
4506
|
/** ParagraphSpacingPatch (before/after/line/lineRule) — carried verbatim. */
|
|
2874
4507
|
patch: Record<string, unknown>;
|
|
4508
|
+
/** Tracked-change (suggesting) metadata; see FormatParagraphIntent. */
|
|
4509
|
+
suggest?: SuggestMeta;
|
|
2875
4510
|
}
|
|
2876
4511
|
/** Insert a page-number field at the end of a run (sibling insertion,
|
|
2877
4512
|
* identity). Page fields are deterministic (no clock). */
|
|
@@ -2915,7 +4550,22 @@ interface InsertBookmarkIntent extends IntentBase {
|
|
|
2915
4550
|
runId: StableId;
|
|
2916
4551
|
name: string;
|
|
2917
4552
|
}
|
|
2918
|
-
|
|
4553
|
+
/**
|
|
4554
|
+
* Intents whose wire shape comes from the core operation registry. One
|
|
4555
|
+
* declaration in @wordinweb/core's edit/registry.ts produces the payload, the
|
|
4556
|
+
* apply, the validation, the carried-id budget, and the agent capability row;
|
|
4557
|
+
* here it just picks up the wire bookkeeping every intent carries.
|
|
4558
|
+
*
|
|
4559
|
+
* The registry admits only id-addressed, position-stable operations with no
|
|
4560
|
+
* wire inverse, so every registered intent's transform is identity and
|
|
4561
|
+
* collaborative undo skips it — see the registry's module comment.
|
|
4562
|
+
*/
|
|
4563
|
+
type RegisteredIntent = RegisteredOperationBody & IntentBase;
|
|
4564
|
+
/** One registered intent, by kind. */
|
|
4565
|
+
type RegisteredIntentOf<Kind extends RegisteredOperationKind> = Extract<RegisteredIntent, {
|
|
4566
|
+
kind: Kind;
|
|
4567
|
+
}>;
|
|
4568
|
+
type Intent = InsertTextIntent | InsertSeparatorIntent | DeleteSeparatorIntent | DeleteTextIntent | SplitParagraphIntent | FormatRunIntent | FormatParagraphIntent | SetListTypeIntent | FormatRangeIntent | TableOpIntent | MergeParagraphIntent | CommentRunIntent | PasteBlocksIntent | InsertImageIntent | SuggestRevisionIntent | InsertBreakIntent | InsertMathIntent | InsertShapeIntent | ReplyCommentIntent | AdjustIndentIntent | SetSpacingIntent | InsertPageFieldIntent | SetLinkIntent | InsertFootnoteIntent | SetDropCapIntent | SetDividerIntent | InsertBookmarkIntent | InsertBlankPageIntent | InsertSectionBreakIntent | InsertCrossRefIntent | InsertCoverPageIntent | SetPageLayoutIntent | SetListLevelIntent | InsertWordArtIntent | InsertChartIntent | InsertSmartArtIntent | SetLineNumberingIntent | InsertDateTimeFieldIntent | InsertFieldIntent | SetDrawingRotationIntent | SetDrawingFillIntent | SetChartDataIntent | SetSmartArtNodeTextIntent | SetDrawingWordArtTextIntent | SetDrawingWordArtStyleIntent | SetDrawingLineStyleIntent | SetImageAltTextIntent | RemoveLinkIntent | SetImageWrapIntent | SetDrawingOrderIntent | SetSmartArtDataIntent | SetSmartArtFillIntent | SetSmartArtTextFormatIntent | SetFloatingPagePositionIntent | ResizeDrawingIntent | ResizeTableColumnIntent | MoveTableIntent | RemoveDrawingIntent | SetMathLinearIntent | DeleteMathIntent | MoveMathIntent | EnsureHeaderFooterIntent | DeleteCommentIntent | ResolveCommentIntent | EditCommentIntent | InsertBookmarkRangeIntent | AcceptRevisionIntent | RejectRevisionIntent | AcceptAllRevisionsIntent | RejectAllRevisionsIntent | RegisteredIntent;
|
|
2919
4569
|
/** Insert a blank page at the end of a run. */
|
|
2920
4570
|
interface InsertBlankPageIntent extends IntentBase {
|
|
2921
4571
|
kind: "insertBlankPage";
|
|
@@ -2963,22 +4613,33 @@ interface InsertWordArtIntent extends IntentBase {
|
|
|
2963
4613
|
kind: "insertWordArt";
|
|
2964
4614
|
runId: StableId;
|
|
2965
4615
|
text: string;
|
|
2966
|
-
preset: "plain" | "archUp" | "archDown" | "wave" | "chevron";
|
|
4616
|
+
preset: "plain" | "archUp" | "archDown" | "wave" | "chevron" | "circle" | "button" | "chevronDown";
|
|
4617
|
+
/** Gallery style: glyph fill plus optional outline and shadow. */
|
|
4618
|
+
style?: {
|
|
4619
|
+
fill: string;
|
|
4620
|
+
outline?: {
|
|
4621
|
+
color: string;
|
|
4622
|
+
widthPt: number;
|
|
4623
|
+
};
|
|
4624
|
+
shadow?: boolean;
|
|
4625
|
+
};
|
|
2967
4626
|
nodeIds: StableId[];
|
|
2968
4627
|
}
|
|
2969
|
-
/** Insert a data chart
|
|
2970
|
-
*
|
|
4628
|
+
/** Insert a data chart at the end of a run. The chart data is carried
|
|
4629
|
+
* verbatim; the workbook part is generated deterministically. */
|
|
2971
4630
|
interface InsertChartIntent extends IntentBase {
|
|
2972
4631
|
kind: "insertChart";
|
|
2973
4632
|
runId: StableId;
|
|
2974
4633
|
chart: {
|
|
2975
|
-
type: "column" | "bar" | "line" | "pie";
|
|
4634
|
+
type: "column" | "bar" | "line" | "pie" | "doughnut" | "area" | "scatter";
|
|
2976
4635
|
title?: string;
|
|
2977
4636
|
categories: string[];
|
|
2978
4637
|
series: {
|
|
2979
4638
|
name: string;
|
|
2980
4639
|
values: number[];
|
|
2981
4640
|
}[];
|
|
4641
|
+
/** How bar/column/area series group; absent = clustered. */
|
|
4642
|
+
grouping?: "clustered" | "stacked" | "percentStacked";
|
|
2982
4643
|
};
|
|
2983
4644
|
nodeIds: StableId[];
|
|
2984
4645
|
}
|
|
@@ -3021,58 +4682,67 @@ interface InsertFieldIntent extends IntentBase {
|
|
|
3021
4682
|
cachedResult?: string;
|
|
3022
4683
|
nodeIds: StableId[];
|
|
3023
4684
|
}
|
|
4685
|
+
interface DrawingTarget {
|
|
4686
|
+
runId: StableId;
|
|
4687
|
+
/** Parsed run-content index. It disambiguates several drawings carried by one run. */
|
|
4688
|
+
objectIndex?: number;
|
|
4689
|
+
}
|
|
3024
4690
|
/** Rotate the drawing carried by a run. Identity transform (run-addressed). */
|
|
3025
|
-
interface SetDrawingRotationIntent extends IntentBase {
|
|
4691
|
+
interface SetDrawingRotationIntent extends IntentBase, DrawingTarget {
|
|
3026
4692
|
kind: "setDrawingRotation";
|
|
3027
4693
|
runId: StableId;
|
|
3028
4694
|
degrees: number;
|
|
3029
4695
|
}
|
|
3030
4696
|
/** Set/clear the solid fill of the drawing carried by a run. `color` is a
|
|
3031
4697
|
* 6-hex-digit RGB (no #) or null to clear. */
|
|
3032
|
-
interface SetDrawingFillIntent extends IntentBase {
|
|
4698
|
+
interface SetDrawingFillIntent extends IntentBase, DrawingTarget {
|
|
3033
4699
|
kind: "setDrawingFill";
|
|
3034
4700
|
runId: StableId;
|
|
3035
4701
|
color: string | null;
|
|
3036
4702
|
}
|
|
3037
4703
|
/** Replace the data of the chart carried by a run (same shape as insertChart's
|
|
3038
4704
|
* chart). Edits an existing chart in place. */
|
|
3039
|
-
interface SetChartDataIntent extends IntentBase {
|
|
4705
|
+
interface SetChartDataIntent extends IntentBase, DrawingTarget {
|
|
3040
4706
|
kind: "setChartData";
|
|
3041
4707
|
runId: StableId;
|
|
3042
|
-
chart:
|
|
3043
|
-
type: "column" | "bar" | "line" | "pie";
|
|
3044
|
-
title?: string;
|
|
3045
|
-
categories: string[];
|
|
3046
|
-
series: {
|
|
3047
|
-
name: string;
|
|
3048
|
-
values: number[];
|
|
3049
|
-
}[];
|
|
3050
|
-
};
|
|
4708
|
+
chart: InsertChartIntent["chart"];
|
|
3051
4709
|
}
|
|
3052
4710
|
/** Set the text of one node of the SmartArt diagram carried by a run. */
|
|
3053
|
-
interface SetSmartArtNodeTextIntent extends IntentBase {
|
|
4711
|
+
interface SetSmartArtNodeTextIntent extends IntentBase, DrawingTarget {
|
|
3054
4712
|
kind: "setSmartArtNodeText";
|
|
3055
4713
|
runId: StableId;
|
|
3056
4714
|
index: number;
|
|
3057
4715
|
text: string;
|
|
3058
4716
|
}
|
|
3059
4717
|
/** Replace the text of the WordArt drawing carried by a run. */
|
|
3060
|
-
interface SetDrawingWordArtTextIntent extends IntentBase {
|
|
4718
|
+
interface SetDrawingWordArtTextIntent extends IntentBase, DrawingTarget {
|
|
3061
4719
|
kind: "setDrawingWordArtText";
|
|
3062
4720
|
runId: StableId;
|
|
3063
4721
|
text: string;
|
|
3064
4722
|
}
|
|
3065
|
-
/** Set the
|
|
3066
|
-
interface
|
|
4723
|
+
/** Set the glyph fill and alpha of the WordArt drawing carried by a run. */
|
|
4724
|
+
interface SetDrawingWordArtStyleIntent extends IntentBase, DrawingTarget {
|
|
4725
|
+
kind: "setDrawingWordArtStyle";
|
|
4726
|
+
runId: StableId;
|
|
4727
|
+
color: string;
|
|
4728
|
+
opacity: number;
|
|
4729
|
+
}
|
|
4730
|
+
/** Set or clear the outline of the drawing carried by a run. */
|
|
4731
|
+
type SetDrawingLineStyleIntent = IntentBase & DrawingTarget & {
|
|
3067
4732
|
kind: "setDrawingLineStyle";
|
|
3068
4733
|
runId: StableId;
|
|
4734
|
+
} & ({
|
|
4735
|
+
color: null;
|
|
4736
|
+
widthPx?: number;
|
|
4737
|
+
dash?: "solid" | "dashed" | "dotted";
|
|
4738
|
+
} | {
|
|
3069
4739
|
color: string;
|
|
3070
4740
|
widthPx: number;
|
|
3071
4741
|
dash: "solid" | "dashed" | "dotted";
|
|
3072
|
-
}
|
|
4742
|
+
});
|
|
3073
4743
|
/** Set/clear the alt text (accessibility description) of the image/drawing
|
|
3074
4744
|
* carried by a run. Empty string clears it. */
|
|
3075
|
-
interface SetImageAltTextIntent extends IntentBase {
|
|
4745
|
+
interface SetImageAltTextIntent extends IntentBase, DrawingTarget {
|
|
3076
4746
|
kind: "setImageAltText";
|
|
3077
4747
|
runId: StableId;
|
|
3078
4748
|
alt: string;
|
|
@@ -3084,19 +4754,19 @@ interface RemoveLinkIntent extends IntentBase {
|
|
|
3084
4754
|
}
|
|
3085
4755
|
/** Set the text-wrap mode of the drawing carried by a run. A floating mode
|
|
3086
4756
|
* converts an inline drawing to an anchor. */
|
|
3087
|
-
interface SetImageWrapIntent extends IntentBase {
|
|
4757
|
+
interface SetImageWrapIntent extends IntentBase, DrawingTarget {
|
|
3088
4758
|
kind: "setImageWrap";
|
|
3089
4759
|
runId: StableId;
|
|
3090
4760
|
mode: "inline" | "square" | "topAndBottom" | "none" | "behind";
|
|
3091
4761
|
}
|
|
3092
4762
|
/** Bring the (floating) drawing carried by a run to front/back. */
|
|
3093
|
-
interface SetDrawingOrderIntent extends IntentBase {
|
|
4763
|
+
interface SetDrawingOrderIntent extends IntentBase, DrawingTarget {
|
|
3094
4764
|
kind: "setDrawingOrder";
|
|
3095
4765
|
runId: StableId;
|
|
3096
4766
|
order: "front" | "back";
|
|
3097
4767
|
}
|
|
3098
4768
|
/** Replace the whole SmartArt diagram (layout + items) carried by a run. */
|
|
3099
|
-
interface SetSmartArtDataIntent extends IntentBase {
|
|
4769
|
+
interface SetSmartArtDataIntent extends IntentBase, DrawingTarget {
|
|
3100
4770
|
kind: "setSmartArtData";
|
|
3101
4771
|
runId: StableId;
|
|
3102
4772
|
smartArt: {
|
|
@@ -3106,14 +4776,14 @@ interface SetSmartArtDataIntent extends IntentBase {
|
|
|
3106
4776
|
}
|
|
3107
4777
|
/** Set/clear the fill of a SmartArt node (or all nodes when nodeIndex omitted).
|
|
3108
4778
|
* `color` is 6-hex RGB (no #) or null to clear. */
|
|
3109
|
-
interface SetSmartArtFillIntent extends IntentBase {
|
|
4779
|
+
interface SetSmartArtFillIntent extends IntentBase, DrawingTarget {
|
|
3110
4780
|
kind: "setSmartArtFill";
|
|
3111
4781
|
runId: StableId;
|
|
3112
4782
|
color: string | null;
|
|
3113
4783
|
nodeIndex?: number;
|
|
3114
4784
|
}
|
|
3115
4785
|
/** Set the text format of a SmartArt node (or all nodes). */
|
|
3116
|
-
interface SetSmartArtTextFormatIntent extends IntentBase {
|
|
4786
|
+
interface SetSmartArtTextFormatIntent extends IntentBase, DrawingTarget {
|
|
3117
4787
|
kind: "setSmartArtTextFormat";
|
|
3118
4788
|
runId: StableId;
|
|
3119
4789
|
format: {
|
|
@@ -3127,7 +4797,7 @@ interface SetSmartArtTextFormatIntent extends IntentBase {
|
|
|
3127
4797
|
nodeIndex?: number;
|
|
3128
4798
|
}
|
|
3129
4799
|
/** Position the (floating) drawing carried by a run relative to the page. */
|
|
3130
|
-
interface SetFloatingPagePositionIntent extends IntentBase {
|
|
4800
|
+
interface SetFloatingPagePositionIntent extends IntentBase, DrawingTarget {
|
|
3131
4801
|
kind: "setFloatingPagePosition";
|
|
3132
4802
|
runId: StableId;
|
|
3133
4803
|
xPx: number;
|
|
@@ -3135,7 +4805,7 @@ interface SetFloatingPagePositionIntent extends IntentBase {
|
|
|
3135
4805
|
}
|
|
3136
4806
|
/** Resize the drawing carried by a run (extent in px; the mutation clamps to
|
|
3137
4807
|
* a 1px-EMU floor and keeps line geometry degenerate on its minor axis). */
|
|
3138
|
-
interface ResizeDrawingIntent extends IntentBase {
|
|
4808
|
+
interface ResizeDrawingIntent extends IntentBase, DrawingTarget {
|
|
3139
4809
|
kind: "resizeDrawing";
|
|
3140
4810
|
runId: StableId;
|
|
3141
4811
|
widthPx: number;
|
|
@@ -3151,13 +4821,6 @@ interface ResizeTableColumnIntent extends IntentBase {
|
|
|
3151
4821
|
deltaPx: number;
|
|
3152
4822
|
renderedWidths?: number[];
|
|
3153
4823
|
}
|
|
3154
|
-
/** Drag-resize a table row's height (trHeight atLeast). */
|
|
3155
|
-
interface ResizeTableRowIntent extends IntentBase {
|
|
3156
|
-
kind: "resizeTableRow";
|
|
3157
|
-
cellParagraphId: StableId;
|
|
3158
|
-
rowIdx: number;
|
|
3159
|
-
heightPx: number;
|
|
3160
|
-
}
|
|
3161
4824
|
/** Position a table at page coordinates (converts inline to float). */
|
|
3162
4825
|
interface MoveTableIntent extends IntentBase {
|
|
3163
4826
|
kind: "moveTable";
|
|
@@ -3167,30 +4830,37 @@ interface MoveTableIntent extends IntentBase {
|
|
|
3167
4830
|
preservePageStart: boolean;
|
|
3168
4831
|
pageDelta: number;
|
|
3169
4832
|
}
|
|
3170
|
-
/** Delete the drawing
|
|
3171
|
-
interface RemoveDrawingIntent extends IntentBase {
|
|
4833
|
+
/** Delete the drawing at the supplied run-content target. */
|
|
4834
|
+
interface RemoveDrawingIntent extends IntentBase, DrawingTarget {
|
|
3172
4835
|
kind: "removeDrawing";
|
|
3173
4836
|
runId: StableId;
|
|
3174
4837
|
}
|
|
3175
|
-
/**
|
|
4838
|
+
/**
|
|
4839
|
+
* Which equation inside a block a math intent means: its position among the
|
|
4840
|
+
* block's m:oMath elements in document order. Absent means the first one, so
|
|
4841
|
+
* an intent recorded before a block could hold more than one addressable
|
|
4842
|
+
* equation still names what it always named.
|
|
4843
|
+
*/
|
|
4844
|
+
interface MathTarget {
|
|
4845
|
+
blockId: StableId;
|
|
4846
|
+
mathIndex?: number;
|
|
4847
|
+
}
|
|
4848
|
+
/** Replace the equation of a math object in a paragraph (linear syntax).
|
|
3176
4849
|
* Math (m:oMath) lives at paragraph level, so this is block-addressed. */
|
|
3177
|
-
interface SetMathLinearIntent extends IntentBase {
|
|
4850
|
+
interface SetMathLinearIntent extends IntentBase, MathTarget {
|
|
3178
4851
|
kind: "setMathLinear";
|
|
3179
|
-
blockId: StableId;
|
|
3180
4852
|
mathText: string;
|
|
3181
4853
|
}
|
|
3182
|
-
/** Delete
|
|
3183
|
-
interface DeleteMathIntent extends IntentBase {
|
|
4854
|
+
/** Delete a math object in a paragraph. */
|
|
4855
|
+
interface DeleteMathIntent extends IntentBase, MathTarget {
|
|
3184
4856
|
kind: "deleteMath";
|
|
3185
|
-
blockId: StableId;
|
|
3186
4857
|
}
|
|
3187
4858
|
/** Drag-move the equation out of `blockId` to the text position `at`. The
|
|
3188
|
-
* equation is addressed like the other math intents (block +
|
|
4859
|
+
* equation is addressed like the other math intents (block + mathIndex); the
|
|
3189
4860
|
* destination is an ordinary wire caret. Dropping mid-text splits the
|
|
3190
4861
|
* destination run, so the split-off tail run takes a carried id. */
|
|
3191
|
-
interface MoveMathIntent extends IntentBase {
|
|
4862
|
+
interface MoveMathIntent extends IntentBase, MathTarget {
|
|
3192
4863
|
kind: "moveMath";
|
|
3193
|
-
blockId: StableId;
|
|
3194
4864
|
at: Position;
|
|
3195
4865
|
nodeIds: StableId[];
|
|
3196
4866
|
}
|
|
@@ -3206,11 +4876,36 @@ interface EnsureHeaderFooterIntent extends IntentBase {
|
|
|
3206
4876
|
hfKind: "header" | "footer";
|
|
3207
4877
|
nodeIds: StableId[];
|
|
3208
4878
|
}
|
|
3209
|
-
/** Delete a comment (and its reply thread) by id.
|
|
4879
|
+
/** Delete a comment (and its reply thread) by id. Addressed with a reply's
|
|
4880
|
+
* id it deletes just that reply — the thread/reply distinction is the id. */
|
|
3210
4881
|
interface DeleteCommentIntent extends IntentBase {
|
|
3211
4882
|
kind: "deleteComment";
|
|
3212
4883
|
commentId: string;
|
|
3213
4884
|
}
|
|
4885
|
+
/**
|
|
4886
|
+
* Resolve (true) or reopen (false) a comment thread. Addressed like
|
|
4887
|
+
* deleteComment, by the comment's deterministic string id (a reply id
|
|
4888
|
+
* resolves its thread's parent). The mutation writes w15:done on the thread
|
|
4889
|
+
* parent's commentsExtended entry; when the parent's body paragraph carries
|
|
4890
|
+
* no w14:paraId yet, the carried `paraId` candidate is consumed to mint one
|
|
4891
|
+
* (provenance rule a — generated once by the originator, identical XML on
|
|
4892
|
+
* every replica). No document run's text moves — identity transform.
|
|
4893
|
+
*/
|
|
4894
|
+
interface ResolveCommentIntent extends IntentBase {
|
|
4895
|
+
kind: "resolveComment";
|
|
4896
|
+
commentId: string;
|
|
4897
|
+
resolved: boolean;
|
|
4898
|
+
/** paraId candidate, consumed only when the thread parent lacks one. */
|
|
4899
|
+
paraId: string;
|
|
4900
|
+
}
|
|
4901
|
+
/** Replace a comment's body text (Word's edit-my-comment). Author, date, id,
|
|
4902
|
+
* anchors and threading stay; deterministic given the carried text — identity
|
|
4903
|
+
* transform, clean no-op for an unknown id or unchanged text. */
|
|
4904
|
+
interface EditCommentIntent extends IntentBase {
|
|
4905
|
+
kind: "editComment";
|
|
4906
|
+
commentId: string;
|
|
4907
|
+
text: string;
|
|
4908
|
+
}
|
|
3214
4909
|
/** Wrap a sub-range of a run's text in a named bookmark. */
|
|
3215
4910
|
interface InsertBookmarkRangeIntent extends IntentBase {
|
|
3216
4911
|
kind: "insertBookmarkRange";
|
|
@@ -3219,11 +4914,6 @@ interface InsertBookmarkRangeIntent extends IntentBase {
|
|
|
3219
4914
|
start: number;
|
|
3220
4915
|
end: number;
|
|
3221
4916
|
}
|
|
3222
|
-
/** Toggle the checkbox content control carried by a run. */
|
|
3223
|
-
interface ToggleCheckboxIntent extends IntentBase {
|
|
3224
|
-
kind: "toggleCheckbox";
|
|
3225
|
-
runId: StableId;
|
|
3226
|
-
}
|
|
3227
4917
|
/** Accept one tracked change, addressed by its position in document order
|
|
3228
4918
|
* (collectRevisions order — deterministic across replicas). */
|
|
3229
4919
|
interface AcceptRevisionIntent extends IntentBase {
|
|
@@ -3235,21 +4925,17 @@ interface RejectRevisionIntent extends IntentBase {
|
|
|
3235
4925
|
kind: "rejectRevision";
|
|
3236
4926
|
index: number;
|
|
3237
4927
|
}
|
|
3238
|
-
/** Accept every tracked change in the document
|
|
4928
|
+
/** Accept every tracked change in the document, or only one author's when
|
|
4929
|
+
* `author` is given — a surface that owns some of the revisions must not
|
|
4930
|
+
* resolve the rest. Absent means all, which is what older clients send. */
|
|
3239
4931
|
interface AcceptAllRevisionsIntent extends IntentBase {
|
|
3240
4932
|
kind: "acceptAllRevisions";
|
|
4933
|
+
author?: string;
|
|
3241
4934
|
}
|
|
3242
|
-
/** Reject every tracked change
|
|
4935
|
+
/** Reject every tracked change, or only one author's. See AcceptAll. */
|
|
3243
4936
|
interface RejectAllRevisionsIntent extends IntentBase {
|
|
3244
4937
|
kind: "rejectAllRevisions";
|
|
3245
|
-
|
|
3246
|
-
/** Insert a rows×cols table after the paragraph containing the anchor run. */
|
|
3247
|
-
interface InsertTableIntent extends IntentBase {
|
|
3248
|
-
kind: "insertTable";
|
|
3249
|
-
runId: StableId;
|
|
3250
|
-
rows: number;
|
|
3251
|
-
cols: number;
|
|
3252
|
-
nodeIds: StableId[];
|
|
4938
|
+
author?: string;
|
|
3253
4939
|
}
|
|
3254
4940
|
/** A sequenced log entry: an applied intent with its assigned seq, or a
|
|
3255
4941
|
* rejection no-op (doc 03) that still occupies a position in the total order
|
|
@@ -3287,8 +4973,13 @@ type IdSidecar = ReturnType<StableIds["exportSidecar"]>;
|
|
|
3287
4973
|
* nothing-to-undo the stack is empty
|
|
3288
4974
|
* unavailable this connection has no collaborative undo (plaintext rooms,
|
|
3289
4975
|
* whose authority is the server)
|
|
4976
|
+
* queued the press is HELD because this client's own edits are still
|
|
4977
|
+
* in flight and the undo stack cannot see them yet. It runs
|
|
4978
|
+
* when they confirm, or is dropped at the deadline — either
|
|
4979
|
+
* way onUndoQueue reports it (see
|
|
4980
|
+
* EncryptedCollabConnection.undoLast)
|
|
3290
4981
|
*/
|
|
3291
|
-
type UndoOutcome = "undone" | "cannot-undo" | "changed-since" | "nothing-to-undo" | "unavailable";
|
|
4982
|
+
type UndoOutcome = "undone" | "cannot-undo" | "changed-since" | "nothing-to-undo" | "unavailable" | "queued";
|
|
3292
4983
|
|
|
3293
4984
|
/**
|
|
3294
4985
|
* E2EE primitives for the blind-sequencer mode (plan doc 13). Pure WebCrypto
|
|
@@ -3503,6 +5194,8 @@ interface RosterEntry {
|
|
|
3503
5194
|
clientId: string;
|
|
3504
5195
|
profile: ParticipantProfile;
|
|
3505
5196
|
connected: boolean;
|
|
5197
|
+
/** Set by the server after a valid one-time AI invitation is redeemed. */
|
|
5198
|
+
participantType?: "human" | "agent";
|
|
3506
5199
|
/**
|
|
3507
5200
|
* Whether this participant may write, re-fanned on every transition.
|
|
3508
5201
|
*
|
|
@@ -3570,12 +5263,37 @@ type ClientMessage = {
|
|
|
3570
5263
|
* accounts: lose the bundle, lose the crown; re-seed to reclaim.
|
|
3571
5264
|
*/
|
|
3572
5265
|
ownerToken?: string;
|
|
5266
|
+
/** One-time room invitation created by an already joined participant. */
|
|
5267
|
+
agentInvite?: {
|
|
5268
|
+
inviteId: string;
|
|
5269
|
+
token: string;
|
|
5270
|
+
};
|
|
3573
5271
|
}
|
|
3574
5272
|
/** Update this connection's profile mid-session (rename / recolor). */
|
|
3575
5273
|
| {
|
|
3576
5274
|
t: "profile";
|
|
3577
5275
|
profile: ParticipantProfile;
|
|
3578
5276
|
}
|
|
5277
|
+
/** Register or revoke an AI invitation. The server binds it to this
|
|
5278
|
+
* connection's room identity and never broadcasts the token. */
|
|
5279
|
+
| {
|
|
5280
|
+
t: "agent-invite";
|
|
5281
|
+
inviteId: string;
|
|
5282
|
+
token: string;
|
|
5283
|
+
expiresAt: number;
|
|
5284
|
+
} | {
|
|
5285
|
+
t: "agent-invite-revoke";
|
|
5286
|
+
inviteId: string;
|
|
5287
|
+
}
|
|
5288
|
+
/** End-to-end encrypted private chat. The server only routes the envelope
|
|
5289
|
+
* between the invited agent and the participant who created its invite. */
|
|
5290
|
+
| {
|
|
5291
|
+
t: "agent-chat";
|
|
5292
|
+
agentClientId: string;
|
|
5293
|
+
messageId: string;
|
|
5294
|
+
iv: string;
|
|
5295
|
+
ciphertext: string;
|
|
5296
|
+
}
|
|
3579
5297
|
/**
|
|
3580
5298
|
* Owner admin channel (doc 14 §2.5) — only honored from a connection
|
|
3581
5299
|
* whose hello proved the owner token. All enforceable by a BLIND server
|
|
@@ -3813,6 +5531,26 @@ type ServerMessage = {
|
|
|
3813
5531
|
| {
|
|
3814
5532
|
t: "roster";
|
|
3815
5533
|
roster: RosterEntry[];
|
|
5534
|
+
} | {
|
|
5535
|
+
t: "agent-invite-registered";
|
|
5536
|
+
inviteId: string;
|
|
5537
|
+
expiresAt: number;
|
|
5538
|
+
} | {
|
|
5539
|
+
t: "agent-invite-refused";
|
|
5540
|
+
inviteId: string;
|
|
5541
|
+
reason: string;
|
|
5542
|
+
} | {
|
|
5543
|
+
t: "agent-connected";
|
|
5544
|
+
inviteId: string;
|
|
5545
|
+
agentClientId: string;
|
|
5546
|
+
profile: ParticipantProfile;
|
|
5547
|
+
} | {
|
|
5548
|
+
t: "agent-chat";
|
|
5549
|
+
agentClientId: string;
|
|
5550
|
+
messageId: string;
|
|
5551
|
+
sender: "inviter" | "agent";
|
|
5552
|
+
iv: string;
|
|
5553
|
+
ciphertext: string;
|
|
3816
5554
|
}
|
|
3817
5555
|
/**
|
|
3818
5556
|
* The session is going to END, and this is the grace period before it does
|
|
@@ -3886,13 +5624,28 @@ interface ToolbarMenuSelectProps {
|
|
|
3886
5624
|
menuWidth?: number;
|
|
3887
5625
|
className?: string;
|
|
3888
5626
|
style?: React.CSSProperties;
|
|
5627
|
+
/** Greys the control and refuses to open it. Distinct from an option's own
|
|
5628
|
+
* `disabled`, which only rules out that one choice. */
|
|
5629
|
+
disabled?: boolean;
|
|
5630
|
+
/**
|
|
5631
|
+
* `"bar"` (default) sits in the ribbon: no border, no background, 26px.
|
|
5632
|
+
* `"field"` sits in a popover or dialog beside a label, where the control
|
|
5633
|
+
* has to read as an input — visible box, full width, popover background.
|
|
5634
|
+
*
|
|
5635
|
+
* A preset rather than a style object at each call site: the 23 selects
|
|
5636
|
+
* this replaced carried four different near-identical style sources between
|
|
5637
|
+
* them, which is how they drifted apart in the first place.
|
|
5638
|
+
*/
|
|
5639
|
+
variant?: "bar" | "field";
|
|
5640
|
+
/** Fold priority for the bar's layout engine; see RibbonItem.fold. */
|
|
5641
|
+
fold?: number;
|
|
3889
5642
|
}
|
|
3890
5643
|
/** CSS-overridable replacement for visible native selects. An inert,
|
|
3891
5644
|
* transparent select is kept as an event bridge for existing integrations;
|
|
3892
5645
|
* every user-facing part is a button/listbox rendered by us. */
|
|
3893
|
-
declare function ToolbarMenuSelect({ value, options, onChange, placeholder, title, ariaLabel, triggerAriaLabel, width, menuWidth, className, style, }: ToolbarMenuSelectProps): react.JSX.Element;
|
|
5646
|
+
declare function ToolbarMenuSelect({ value, options, onChange, placeholder, title, ariaLabel, triggerAriaLabel, width, menuWidth, className, style, disabled, variant, fold, }: ToolbarMenuSelectProps): react.JSX.Element;
|
|
3894
5647
|
/** Toolbar control groups a host can disable via the `features` prop. */
|
|
3895
|
-
type ToolbarFeature = "history" | "styles" | "font" | "size" | "format" | "color" | "highlight" | "alignment" | "indent" | "spacing" | "link" | "lists" | "table" | "image" | "icon" | "screenshot" | "model3D" | "media" | "object" | "chart" | "smartArt" | "comment" | "footnote" | "bookmark" | "crossReference" | "dateTime" | "field" | "equation" | "symbol" | "shape" | "divider" | "textBox" | "wordArt" | "drawing" | "arrange" | "dropCap" | "headerFooter" | "coverPage" | "pageNumber" | "break" | "layout" | "help" | "download";
|
|
5648
|
+
type ToolbarFeature = "history" | "styles" | "charStyles" | "formatPainter" | "font" | "size" | "format" | "color" | "highlight" | "alignment" | "indent" | "spacing" | "link" | "lists" | "borders" | "table" | "image" | "icon" | "screenshot" | "model3D" | "media" | "object" | "chart" | "smartArt" | "comment" | "footnote" | "bookmark" | "crossReference" | "dateTime" | "field" | "citations" | "quickParts" | "equation" | "symbol" | "shape" | "divider" | "textBox" | "wordArt" | "drawing" | "arrange" | "dropCap" | "headerFooter" | "watermark" | "coverPage" | "pageNumber" | "break" | "layout" | "review" | "help" | "download";
|
|
3896
5649
|
/**
|
|
3897
5650
|
* Every `DocxViewApi` command that INSERTS content at the caret, paired with
|
|
3898
5651
|
* the toolbar feature group that gates its control.
|
|
@@ -3922,7 +5675,7 @@ type ToolbarMode = "simple" | "advanced";
|
|
|
3922
5675
|
interface DocxToolbarProps {
|
|
3923
5676
|
api: DocxViewApi | null;
|
|
3924
5677
|
onSave?: (bytes: Uint8Array) => void;
|
|
3925
|
-
/** Simple shows basic Home editing; advanced adds the Insert, Draw, and
|
|
5678
|
+
/** Simple shows basic Home editing; advanced adds the Insert, Draw, Layout, and Review ribbons. */
|
|
3926
5679
|
mode?: ToolbarMode;
|
|
3927
5680
|
/** Per-group overrides; every group defaults to enabled. */
|
|
3928
5681
|
features?: Partial<Record<ToolbarFeature, boolean>>;
|
|
@@ -3930,8 +5683,80 @@ interface DocxToolbarProps {
|
|
|
3930
5683
|
className?: string;
|
|
3931
5684
|
/** Inline overrides merged onto the toolbar root; wins over the defaults. */
|
|
3932
5685
|
style?: React.CSSProperties;
|
|
5686
|
+
/** Connected collaborator names offered as @mention shortcuts in comments. */
|
|
5687
|
+
commentMentions?: string[];
|
|
5688
|
+
/** Start with the toolbar expanded (all groups inline, wrapping onto extra
|
|
5689
|
+
* rows). A choice the user makes via the chevron toggle is persisted in
|
|
5690
|
+
* localStorage and wins over this default. */
|
|
5691
|
+
defaultExpanded?: boolean;
|
|
5692
|
+
/**
|
|
5693
|
+
* Shortcuts the embedding application owns, listed in the help guide
|
|
5694
|
+
* alongside the editor's own. A desktop menu accelerator is consumed by the
|
|
5695
|
+
* menu before the editor sees the key, so the engine cannot discover it;
|
|
5696
|
+
* the app declares it once and passes it here, and the reference stays
|
|
5697
|
+
* complete. Electron hosts can read the live menu rather than repeat it:
|
|
5698
|
+
* walk Menu.getApplicationMenu() for {label, accelerator} pairs.
|
|
5699
|
+
*/
|
|
5700
|
+
hostShortcuts?: HostShortcutSection[];
|
|
3933
5701
|
}
|
|
3934
|
-
declare function DocxToolbar({ api, onSave, mode, features, className, style, }: DocxToolbarProps): react.JSX.Element;
|
|
5702
|
+
declare function DocxToolbar({ api, onSave, mode, features, className, style, commentMentions, defaultExpanded, hostShortcuts, }: DocxToolbarProps): react.JSX.Element;
|
|
5703
|
+
|
|
5704
|
+
/**
|
|
5705
|
+
* The host affordance for Compare Documents — Word's "legal blackline".
|
|
5706
|
+
*
|
|
5707
|
+
* The engine call (`compareDocuments` in @wordinweb/core) is pure: two
|
|
5708
|
+
* documents in, a third out. Everything a browser has to do around it lives
|
|
5709
|
+
* here — pick a file, read it, hand the result somewhere — so the toolbar
|
|
5710
|
+
* entry is one button and the engine stays free of the DOM.
|
|
5711
|
+
*
|
|
5712
|
+
* The document on screen is the ORIGINAL and the picked file is the REVISED
|
|
5713
|
+
* one, which is the direction Word's dialog defaults to. The result is a new
|
|
5714
|
+
* document whose differences are tracked changes attributed to `author`;
|
|
5715
|
+
* accepting them all gives the picked file back, rejecting them all gives what
|
|
5716
|
+
* is on screen back.
|
|
5717
|
+
*/
|
|
5718
|
+
interface CompareResult {
|
|
5719
|
+
/** The compared document, as .docx bytes. */
|
|
5720
|
+
bytes: Uint8Array;
|
|
5721
|
+
/** What the comparison could not express as a tracked change. */
|
|
5722
|
+
notes: CompareNote[];
|
|
5723
|
+
/** The picked file's name, for whatever the host calls the result. */
|
|
5724
|
+
revisedName: string;
|
|
5725
|
+
}
|
|
5726
|
+
interface CompareWithFileOptions {
|
|
5727
|
+
/** Who the tracked changes are attributed to. */
|
|
5728
|
+
author?: string;
|
|
5729
|
+
/** Timestamp for every revision. Defaults to now. */
|
|
5730
|
+
date?: string;
|
|
5731
|
+
/** Compare formatting as well as text. Default true, as in Word. */
|
|
5732
|
+
formatting?: boolean;
|
|
5733
|
+
/** Report whitespace-only differences. Default true, as in Word. */
|
|
5734
|
+
whitespace?: boolean;
|
|
5735
|
+
}
|
|
5736
|
+
/**
|
|
5737
|
+
* Compare `originalBytes` with a .docx `file`. Returns the result and the list
|
|
5738
|
+
* of differences that could not be tracked, which a caller should show rather
|
|
5739
|
+
* than swallow — a comparison that quietly skipped something is worse than one
|
|
5740
|
+
* that says what it skipped.
|
|
5741
|
+
*/
|
|
5742
|
+
declare function compareWithFile(originalBytes: Uint8Array, file: File, options?: CompareWithFileOptions): Promise<CompareResult>;
|
|
5743
|
+
/** Ask for one .docx. Resolves to null when the picker is dismissed. */
|
|
5744
|
+
declare function pickDocx(): Promise<File | null>;
|
|
5745
|
+
/** Save bytes to the user's downloads under `name`. */
|
|
5746
|
+
declare function downloadDocx(bytes: Uint8Array, name: string): void;
|
|
5747
|
+
/**
|
|
5748
|
+
* The whole affordance behind one click: pick a file, compare, hand the result
|
|
5749
|
+
* to `onResult` (or download it), and report anything untrackable.
|
|
5750
|
+
*
|
|
5751
|
+
* Returns false when no file was picked, so a caller can tell "cancelled" from
|
|
5752
|
+
* "compared with nothing to say".
|
|
5753
|
+
*/
|
|
5754
|
+
declare function pickAndCompare(originalBytes: Uint8Array, options?: CompareWithFileOptions & {
|
|
5755
|
+
onResult?: (result: CompareResult) => void;
|
|
5756
|
+
onNotes?: (notes: CompareNote[]) => void;
|
|
5757
|
+
}): Promise<boolean>;
|
|
5758
|
+
/** "report.docx" → "report (compared).docx". */
|
|
5759
|
+
declare function comparedName(revisedName: string): string;
|
|
3935
5760
|
|
|
3936
5761
|
interface DocxViewApi {
|
|
3937
5762
|
/** Apply character formatting to the current browser selection. */
|
|
@@ -3940,6 +5765,8 @@ interface DocxViewApi {
|
|
|
3940
5765
|
addComment(text: string): boolean;
|
|
3941
5766
|
/** Insert a footnote at the caret. False without a caret. */
|
|
3942
5767
|
addFootnote(text: string): boolean;
|
|
5768
|
+
/** Insert an endnote at the caret. False without a caret. */
|
|
5769
|
+
addEndnote(text: string): boolean;
|
|
3943
5770
|
/** Insert a dynamic page-number field at the caret (body, header or footer). */
|
|
3944
5771
|
insertPageNumber(kind?: "page" | "pageOfTotal"): boolean;
|
|
3945
5772
|
/** Insert any Word field instruction supported by the renderer. */
|
|
@@ -3948,10 +5775,137 @@ interface DocxViewApi {
|
|
|
3948
5775
|
insertDateTime(kind: "date" | "time", picture?: string): boolean;
|
|
3949
5776
|
/** Named bookmarks in document order. */
|
|
3950
5777
|
listBookmarks(): string[];
|
|
5778
|
+
/**
|
|
5779
|
+
* How many entries a table of contents would find right now, and how many
|
|
5780
|
+
* index entries have been marked.
|
|
5781
|
+
*
|
|
5782
|
+
* A TOC and an INDEX are both built from something the user has to do first —
|
|
5783
|
+
* apply heading styles, or mark entries — and inserting one before that puts
|
|
5784
|
+
* Word's own "No table of contents entries found." into the document, which
|
|
5785
|
+
* is accurate and explains nothing. A surface that can ask beforehand can say
|
|
5786
|
+
* what is missing instead.
|
|
5787
|
+
*/
|
|
5788
|
+
contentsAvailability(): {
|
|
5789
|
+
headings: number;
|
|
5790
|
+
indexEntries: number;
|
|
5791
|
+
};
|
|
3951
5792
|
/** Add a bookmark around the selection, or a zero-length bookmark at the caret. */
|
|
3952
5793
|
addBookmark(name: string): boolean;
|
|
3953
5794
|
/** Insert a live text or page reference to a bookmark. */
|
|
3954
5795
|
insertCrossReference(bookmark: string, kind: "text" | "page"): boolean;
|
|
5796
|
+
/**
|
|
5797
|
+
* Cross-reference targets beyond plain bookmarks, in document order:
|
|
5798
|
+
* headings, captions (SEQ paragraphs), and numbered list items — what
|
|
5799
|
+
* Word's Cross-reference dialog lists per reference type. The keys stay
|
|
5800
|
+
* valid until the next call (or a document change).
|
|
5801
|
+
*/
|
|
5802
|
+
listCrossRefTargets(): {
|
|
5803
|
+
key: string;
|
|
5804
|
+
kind: "heading" | "caption" | "numberedItem";
|
|
5805
|
+
text: string;
|
|
5806
|
+
}[];
|
|
5807
|
+
/**
|
|
5808
|
+
* Insert a live text or page reference to a listed target. A target with
|
|
5809
|
+
* no hidden `_Ref` bookmark gets one first (Word's own mechanism), so the
|
|
5810
|
+
* REF/PAGEREF has something durable to point at.
|
|
5811
|
+
*/
|
|
5812
|
+
insertCrossRefToTarget(key: string, kind: "text" | "page"): boolean;
|
|
5813
|
+
/**
|
|
5814
|
+
* Insert a Word caption — "<label> <n>" in the Caption style, the number a
|
|
5815
|
+
* live SEQ field — below or above the selected object (or the caret's
|
|
5816
|
+
* block; a caret inside a table captions the table). updateFields
|
|
5817
|
+
* renumbers the whole label sequence.
|
|
5818
|
+
*/
|
|
5819
|
+
insertCaption(label: string, text?: string, position?: "below" | "above"): boolean;
|
|
5820
|
+
/**
|
|
5821
|
+
* Recompute every supported field's cached result — Word's F9, and what a
|
|
5822
|
+
* host calls before printing or exporting so the file it hands on carries
|
|
5823
|
+
* current page numbers, dates and cross-references. False when nothing
|
|
5824
|
+
* changed.
|
|
5825
|
+
*
|
|
5826
|
+
* `fileName` and `author` are the host's to supply: the engine has no
|
|
5827
|
+
* filesystem of its own, so FILENAME and AUTHOR fields keep their cached
|
|
5828
|
+
* results without them.
|
|
5829
|
+
*/
|
|
5830
|
+
updateFields(values?: {
|
|
5831
|
+
fileName?: string;
|
|
5832
|
+
author?: string;
|
|
5833
|
+
}): boolean;
|
|
5834
|
+
/**
|
|
5835
|
+
* Insert a native Word table of contents at the caret.
|
|
5836
|
+
*
|
|
5837
|
+
* Outside a room the page numbers are filled in immediately, from a layout
|
|
5838
|
+
* this call runs. IN a room the entries land with placeholders: page numbers
|
|
5839
|
+
* come from a layout, a layout depends on the host's font metrics, and that
|
|
5840
|
+
* is precisely the value `updateFields` carries as data instead of letting
|
|
5841
|
+
* each replica recompute it. Run the update pass to fill them.
|
|
5842
|
+
*/
|
|
5843
|
+
insertToc(options?: TocOptions): boolean;
|
|
5844
|
+
/**
|
|
5845
|
+
* Rebuild every table of contents from the document's current headings, then
|
|
5846
|
+
* repage it. Use after headings are added, removed or retitled; repaging an
|
|
5847
|
+
* unchanged heading set needs only updateFields. False in a shared document,
|
|
5848
|
+
* for the reason insertToc gives.
|
|
5849
|
+
*/
|
|
5850
|
+
refreshTocs(): boolean;
|
|
5851
|
+
/**
|
|
5852
|
+
* Every data column this document's MERGEFIELD fields name, in document
|
|
5853
|
+
* order, once each — headers and footers included.
|
|
5854
|
+
*
|
|
5855
|
+
* A mail-merge UI compares this against its data source's headers to report
|
|
5856
|
+
* which fields the data does not supply. Those keep their «Name» placeholder
|
|
5857
|
+
* while previewing, so the user sees an unbound field instead of a blank.
|
|
5858
|
+
*
|
|
5859
|
+
* Read-only, like the whole preview path: no operation, no undo entry, no
|
|
5860
|
+
* collab traffic. Set the values through the `mergeRecord` prop.
|
|
5861
|
+
*/
|
|
5862
|
+
listMergeFieldNames(): string[];
|
|
5863
|
+
/** The bibliography sources the document's sources part declares, in part
|
|
5864
|
+
* order — what a citation picker and the source manager list. */
|
|
5865
|
+
listCitationSources(): BibliographySource[];
|
|
5866
|
+
/** The selected citation style (b:Sources/@StyleName — "APA", "MLA", or
|
|
5867
|
+
* whatever an arriving document declares), or null with no sources part. */
|
|
5868
|
+
getCitationStyle(): string | null;
|
|
5869
|
+
/** Select the citation style (APA or MLA) for citations and the
|
|
5870
|
+
* bibliography, creating the sources part when the document has none.
|
|
5871
|
+
* Refreshes citation displays and bibliographies in the same call. */
|
|
5872
|
+
setCitationStyle(style: CitationStyle): boolean;
|
|
5873
|
+
/** Add a bibliography source (book, article, website, or report), creating
|
|
5874
|
+
* the sources part on first use. False when the tag is already taken. */
|
|
5875
|
+
createCitationSource(spec: CitationSourceSpec): boolean;
|
|
5876
|
+
/** Change a source's fields, by tag. Refreshes citation displays and
|
|
5877
|
+
* bibliographies in the same call. */
|
|
5878
|
+
editCitationSource(tag: string, patch: CitationSourcePatch): boolean;
|
|
5879
|
+
/** Delete a source. False while a CITATION field still cites it — remove
|
|
5880
|
+
* the citations first. */
|
|
5881
|
+
deleteCitationSource(tag: string): boolean;
|
|
5882
|
+
/** Insert a citation to an existing source at the caret, displayed in the
|
|
5883
|
+
* document's citation style. False for a tag the sources part lacks. */
|
|
5884
|
+
insertCitation(tag: string): boolean;
|
|
5885
|
+
/** Insert a bibliography at the caret: a BIBLIOGRAPHY field whose entries
|
|
5886
|
+
* are generated from the document's sources (regenerated by updateFields). */
|
|
5887
|
+
insertBibliography(): boolean;
|
|
5888
|
+
/** The Quick Parts (building blocks) the document's glossary part declares,
|
|
5889
|
+
* name and category, in part order — what the gallery lists. */
|
|
5890
|
+
listBuildingBlocks(): BuildingBlockInfo[];
|
|
5891
|
+
/** Save the current selection as a named Quick Part, creating the glossary
|
|
5892
|
+
* part on first use. False with nothing selected, a name already taken, or
|
|
5893
|
+
* a selection the paste-fragment gate refuses (the pasteBlocks gate). */
|
|
5894
|
+
createBuildingBlock(name: string, category?: string): boolean;
|
|
5895
|
+
/** Insert a named Quick Part at the caret, cloning its stored content.
|
|
5896
|
+
* False for a name the glossary part lacks. */
|
|
5897
|
+
insertBuildingBlock(name: string): boolean;
|
|
5898
|
+
/** Delete a Quick Part from the glossary part, by name. False when the name
|
|
5899
|
+
* names none. */
|
|
5900
|
+
deleteBuildingBlock(name: string): boolean;
|
|
5901
|
+
/** Mark an index entry: an invisible XE field after the selection (or the
|
|
5902
|
+
* caret). With no `entry` the selected text is the entry; a colon makes a
|
|
5903
|
+
* subentry ("Widgets:assembly"). False with nothing to mark. */
|
|
5904
|
+
addIndexEntry(entry?: string): boolean;
|
|
5905
|
+
/** Insert an index at the caret, built from the document's XE entry marks
|
|
5906
|
+
* (alphabetized; page numbers filled by the update pass). Rebuilt from the
|
|
5907
|
+
* current marks by updateFields. */
|
|
5908
|
+
insertIndex(): boolean;
|
|
3955
5909
|
/** Insert an editable inline equation from WordInWeb's linear math syntax. */
|
|
3956
5910
|
insertEquation(linear: string): boolean;
|
|
3957
5911
|
/** Insert a Unicode symbol through the normal undo/suggestion-aware typing path. */
|
|
@@ -3963,7 +5917,7 @@ interface DocxViewApi {
|
|
|
3963
5917
|
dash: DrawingLineDash;
|
|
3964
5918
|
}): boolean;
|
|
3965
5919
|
/** Insert editable DrawingML WordArt at the caret. */
|
|
3966
|
-
insertWordArt(text: string, preset?: WordArtPreset): boolean;
|
|
5920
|
+
insertWordArt(text: string, preset?: WordArtPreset, style?: WordArtStyle): boolean;
|
|
3967
5921
|
/** Insert a native editable ChartML chart at the caret. */
|
|
3968
5922
|
insertChart(data: ChartData): boolean;
|
|
3969
5923
|
/** Replace the selected native chart's type and data. */
|
|
@@ -4007,12 +5961,82 @@ interface DocxViewApi {
|
|
|
4007
5961
|
redo(): void;
|
|
4008
5962
|
canUndo(): boolean;
|
|
4009
5963
|
canRedo(): boolean;
|
|
5964
|
+
/**
|
|
5965
|
+
* Record the document's current state as an undo boundary.
|
|
5966
|
+
*
|
|
5967
|
+
* For a host that mutates the document THROUGH SOMETHING OTHER THAN THIS API
|
|
5968
|
+
* — an agent session applying intents to the same DocxDocument — and still
|
|
5969
|
+
* wants Cmd+Z to reach those changes. Every editing method here checkpoints
|
|
5970
|
+
* on its own; nothing outside can, so without this an external edit is
|
|
5971
|
+
* invisible to undo and leaves the history's shadow describing a document
|
|
5972
|
+
* that no longer exists.
|
|
5973
|
+
*/
|
|
5974
|
+
checkpoint(): void;
|
|
5975
|
+
/**
|
|
5976
|
+
* MAIL MERGE OUTPUT: this document with one record's values baked into its
|
|
5977
|
+
* MERGEFIELD results, as bytes. The open document is NOT modified — the
|
|
5978
|
+
* merge runs against a fresh parse of its serialized form, so a hundred
|
|
5979
|
+
* records produce a hundred files and leave the template on screen alone.
|
|
5980
|
+
*/
|
|
5981
|
+
mergeRecordToBytes(record: MergeRecord): Uint8Array;
|
|
4010
5982
|
/** Insert a rows×cols table at the caret's paragraph. */
|
|
4011
5983
|
insertTable(rows: number, cols: number): void;
|
|
4012
5984
|
/** Row/column/table operations on the table containing the caret. */
|
|
4013
5985
|
tableOp(op: TableOp): void;
|
|
4014
5986
|
/** Current table-cell fill, undefined when the caret is outside a table. */
|
|
4015
5987
|
getTableCellFill(): string | null | undefined;
|
|
5988
|
+
/** What a Table Properties dialog prefills from — the table's width, its
|
|
5989
|
+
* grid columns, the caret's column, the default cell margins and the header
|
|
5990
|
+
* band, in points. Undefined when the caret is outside a table. */
|
|
5991
|
+
getTableProperties(): TablePropertiesPt | undefined;
|
|
5992
|
+
/** Set or clear border edges on the caret's cell or its whole table. A null
|
|
5993
|
+
* `border` removes the edges so they inherit again; `{ style: "none" }`
|
|
5994
|
+
* instead suppresses them, which is Word's No Border. */
|
|
5995
|
+
setTableBorders(scope: "cell" | "table", edges: TableBorderEdge[], border: TableBorderSpec | null): void;
|
|
5996
|
+
/** The table styles this document's styles.xml defines — the whole valid
|
|
5997
|
+
* domain for setTableStyle, since an undefined id renders nothing. */
|
|
5998
|
+
listTableStyles(): {
|
|
5999
|
+
id: string;
|
|
6000
|
+
name: string;
|
|
6001
|
+
}[];
|
|
6002
|
+
/** Style id of the table containing the caret: null when it has none,
|
|
6003
|
+
* undefined when the caret is outside a table. */
|
|
6004
|
+
getTableStyleId(): string | null | undefined;
|
|
6005
|
+
/** Apply a table style, or with null remove the reference. */
|
|
6006
|
+
setTableStyle(styleId: string | null): void;
|
|
6007
|
+
/** Word's six table style options for the caret's table, undefined outside
|
|
6008
|
+
* a table. */
|
|
6009
|
+
getTableLook(): TableLookToggles | undefined;
|
|
6010
|
+
/** Set some of the six table style options. */
|
|
6011
|
+
setTableLook(patch: Partial<TableLookToggles>): void;
|
|
6012
|
+
/** Set the table's preferred width. `value` is points for "pt", 0-100 for
|
|
6013
|
+
* "pct", and ignored for "auto". */
|
|
6014
|
+
setTableWidth(unit: "pt" | "pct" | "auto", value?: number): void;
|
|
6015
|
+
/** Set one column to an exact width in points. */
|
|
6016
|
+
setTableColumnWidth(colIdx: number, widthPt: number): void;
|
|
6017
|
+
/** Switch the table between fixed column widths and autofit. Switching to
|
|
6018
|
+
* fixed freezes the columns as currently RENDERED, which is what the user
|
|
6019
|
+
* is looking at; switching to autofit measures them from content again. */
|
|
6020
|
+
setTableLayout(layout: "fixed" | "autofit"): void;
|
|
6021
|
+
/** Set the table's default cell margins, or the caret cell's override, in
|
|
6022
|
+
* points. A null patch drops the override. */
|
|
6023
|
+
setTableCellMargins(scope: "cell" | "table", margins: CellMarginsPt | null): void;
|
|
6024
|
+
/** Repeat the first `count` rows as a header band on every page. */
|
|
6025
|
+
setTableHeaderRows(count: number): void;
|
|
6026
|
+
/** Sort the caret table's body rows by one grid column, as text or as
|
|
6027
|
+
* numbers. The repeating header band always stays in place; `hasHeader`
|
|
6028
|
+
* additionally pins the first row. Refuses tables with merged cells. */
|
|
6029
|
+
sortTableRows(colIdx: number, order: "asc" | "desc", compare: "text" | "number", hasHeader?: boolean): void;
|
|
6030
|
+
/** Convert the selected paragraphs (or the caret paragraph) into a table,
|
|
6031
|
+
* one row per paragraph, cells split on the separator. */
|
|
6032
|
+
convertTextToTable(separator: "tab" | "comma"): boolean;
|
|
6033
|
+
/** Convert the caret's table into paragraphs, one per row, cell texts
|
|
6034
|
+
* joined by the separator. */
|
|
6035
|
+
convertTableToText(separator: "tab" | "comma"): boolean;
|
|
6036
|
+
/** Insert a table formula field ("=SUM(ABOVE)", "=A1+B2", …) at the caret's
|
|
6037
|
+
* cell paragraph, with an optional \# number format like "#,##0.00". The
|
|
6038
|
+
* result is evaluated immediately; updateFields recomputes it. */
|
|
6039
|
+
insertTableFormula(formula: string, numFmt?: string): boolean;
|
|
4016
6040
|
/** Insert an image file at the caret (inline, natural size clamped to column).
|
|
4017
6041
|
* The result is REPORTED rather than swallowed: a picker that accepts a file
|
|
4018
6042
|
* and then does nothing is indistinguishable from a broken button. */
|
|
@@ -4053,22 +6077,51 @@ interface DocxViewApi {
|
|
|
4053
6077
|
setParagraphDivider(divider: ParagraphDivider | null): boolean;
|
|
4054
6078
|
/** Direct bottom-border divider on the caret paragraph. */
|
|
4055
6079
|
getParagraphDivider(): ParagraphDivider | null;
|
|
6080
|
+
/** Replace the selected paragraphs' direct tab stops (w:tabs). An empty
|
|
6081
|
+
* list removes them, so style stops and the default grid apply again. */
|
|
6082
|
+
setTabStops(stops: TabStopSpec[]): boolean;
|
|
6083
|
+
/** Direct tab stops on the caret paragraph, sorted by position. */
|
|
6084
|
+
getTabStops(): TabStopSpec[];
|
|
6085
|
+
/** Patch the selected paragraphs' border edges (w:pBdr) and/or shading
|
|
6086
|
+
* fill (w:shd). Each named edge is set (spec) or cleared (null); absent
|
|
6087
|
+
* edges stay. `shading: null` removes the fill. */
|
|
6088
|
+
setParagraphBorders(patch: ParagraphBordersPatch): boolean;
|
|
6089
|
+
/** Direct borders and shading on the caret paragraph. */
|
|
6090
|
+
getParagraphBorders(): {
|
|
6091
|
+
borders: Partial<Record<ParagraphBorderEdge, TableBorderSpec>>;
|
|
6092
|
+
shading: string | null;
|
|
6093
|
+
};
|
|
4056
6094
|
/** Apply or remove a native Word drop cap on the caret paragraph. */
|
|
4057
6095
|
setDropCap(mode: "drop" | "margin" | null, lines?: number): boolean;
|
|
4058
6096
|
/** Remove direct character formatting from the selection. */
|
|
4059
6097
|
clearFormatting(): void;
|
|
4060
6098
|
/** Change the selection's case. */
|
|
4061
6099
|
changeCase(mode: "upper" | "lower" | "title"): void;
|
|
4062
|
-
/** Find matches for a query
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
}): number;
|
|
6100
|
+
/** Find matches for a query across every story (body, headers, footers,
|
|
6101
|
+
* footnotes, endnotes); selects the first and returns the count. */
|
|
6102
|
+
find(query: string, opts?: FindOptions): number;
|
|
4066
6103
|
/** Select the next/previous match; returns 1-based index or 0. */
|
|
4067
6104
|
findStep(delta: 1 | -1): number;
|
|
4068
6105
|
/** Replace the current match; returns remaining match count. */
|
|
4069
6106
|
replaceCurrent(replacement: string): number;
|
|
4070
|
-
/** Replace every match;
|
|
4071
|
-
replaceAll(query: string, replacement: string):
|
|
6107
|
+
/** Replace every match; reports how many were replaced, per story. */
|
|
6108
|
+
replaceAll(query: string, replacement: string, opts?: FindOptions): ReplaceAllResult;
|
|
6109
|
+
/** Go To: scroll the given 1-based page into view. */
|
|
6110
|
+
goToPage(page: number): boolean;
|
|
6111
|
+
/** Go To: move the caret to a named bookmark and scroll it into view. */
|
|
6112
|
+
goToBookmark(name: string): boolean;
|
|
6113
|
+
/**
|
|
6114
|
+
* Select an exact text range by stable address — the `{blockId, runId,
|
|
6115
|
+
* start, end}` shape the wire, presence, and suggestRevision already use
|
|
6116
|
+
* (offsets in the run's wire basis; see getEncodedCaret for the caret
|
|
6117
|
+
* half). Several ranges select together, for a word split across runs.
|
|
6118
|
+
* Selection and scroll ride find-navigation's machinery; the view only
|
|
6119
|
+
* scrolls when the range is off screen. In a local document the first call
|
|
6120
|
+
* populates the stable-id table (enableStableIds), so hosts — the desktop
|
|
6121
|
+
* spellcheck's select-and-replace — can address text without a collab
|
|
6122
|
+
* mount. False when no range resolves to text.
|
|
6123
|
+
*/
|
|
6124
|
+
selectRange(range: WireRange | WireRange[]): boolean;
|
|
4072
6125
|
/** Paragraph styles for the style menu (declared + Word built-ins). */
|
|
4073
6126
|
listParagraphStyles(): {
|
|
4074
6127
|
id: string;
|
|
@@ -4076,6 +6129,55 @@ interface DocxViewApi {
|
|
|
4076
6129
|
}[];
|
|
4077
6130
|
/** pStyle id of the caret paragraph (null = Normal). */
|
|
4078
6131
|
getParagraphStyleId(): string | null;
|
|
6132
|
+
/**
|
|
6133
|
+
* Every declared style with the data a gallery entry needs: identity,
|
|
6134
|
+
* cascade parent, quick-style flag, usage count, and resolved preview props.
|
|
6135
|
+
* Richer than listParagraphStyles, which is the flat menu the toolbar's
|
|
6136
|
+
* existing style dropdown reads.
|
|
6137
|
+
*/
|
|
6138
|
+
listStyles(filter?: {
|
|
6139
|
+
type?: StyleGalleryEntry["type"];
|
|
6140
|
+
quickStyleOnly?: boolean;
|
|
6141
|
+
}): StyleGalleryEntry[];
|
|
6142
|
+
/** Add a paragraph or character style definition. */
|
|
6143
|
+
createStyle(spec: StyleSpec): boolean;
|
|
6144
|
+
/** Patch an existing style definition; the cascade re-resolves live. */
|
|
6145
|
+
modifyStyle(styleId: string, patch: StylePatch): boolean;
|
|
6146
|
+
/** Delete a style definition; its users fall back to its basedOn. */
|
|
6147
|
+
deleteStyle(styleId: string): boolean;
|
|
6148
|
+
/**
|
|
6149
|
+
* Stamp a text watermark across every page. Word keeps a watermark in the
|
|
6150
|
+
* header parts, so a document with none gets one first.
|
|
6151
|
+
*/
|
|
6152
|
+
insertWatermark(spec: WatermarkSpec): boolean;
|
|
6153
|
+
/**
|
|
6154
|
+
* Stamp a PICTURE across every page — Word's Watermark > Picture. Replaces
|
|
6155
|
+
* whichever watermark is already there, text or picture.
|
|
6156
|
+
*
|
|
6157
|
+
* The picture is washed out (Word's own recolor) and fitted to the page.
|
|
6158
|
+
* Takes the same formats a shared document can carry, so SVG is refused;
|
|
6159
|
+
* `imageAccept()` is the list to hand a file picker.
|
|
6160
|
+
*/
|
|
6161
|
+
insertPictureWatermark(file: Blob): Promise<ImageInsertResult>;
|
|
6162
|
+
/** Take the watermark back off every page. False when there was none. */
|
|
6163
|
+
removeWatermark(): boolean;
|
|
6164
|
+
/** Apply (or with null remove) a character style over the selection. */
|
|
6165
|
+
setCharacterStyle(styleId: string | null): void;
|
|
6166
|
+
/** Change a list level's number format, label text, or indent. */
|
|
6167
|
+
setNumberingLevel(ilvl: number | null, patch: LevelPatch): boolean;
|
|
6168
|
+
/**
|
|
6169
|
+
* Apply a preset multilevel definition (Word's multilevel gallery) to the
|
|
6170
|
+
* caret's list — the paragraphs join a numbered list first when they are
|
|
6171
|
+
* not in one. Compiles onto the existing per-level patch operation, so it
|
|
6172
|
+
* rides the same wire ops and converges like any level edit.
|
|
6173
|
+
*/
|
|
6174
|
+
applyNumberingPreset(preset: NumberingPresetId): boolean;
|
|
6175
|
+
/** Restart list numbering at the caret, or (null) continue the preceding list. */
|
|
6176
|
+
setNumberingRestart(start: number | null): boolean;
|
|
6177
|
+
/** Format painter, half one: the selection's formatting, or null. */
|
|
6178
|
+
copyFormatting(): SelectionFormat | null;
|
|
6179
|
+
/** Format painter, half two: paint a copied format over the selection. */
|
|
6180
|
+
applyCopiedFormatting(format: SelectionFormat): void;
|
|
4079
6181
|
/** Change margins / page size / orientation (inches). */
|
|
4080
6182
|
setPageLayout(patch: PageLayoutPatch, scope?: "document" | "section"): void;
|
|
4081
6183
|
/** One-based logical section containing the caret or selection. */
|
|
@@ -4102,10 +6204,90 @@ interface DocxViewApi {
|
|
|
4102
6204
|
closeHeaderFooter(): void;
|
|
4103
6205
|
/** Enter and, if needed, create the header or footer on the caret's page. */
|
|
4104
6206
|
openHeaderFooter(kind: "header" | "footer"): boolean;
|
|
6207
|
+
/** Word's "Different First Page" (w:titlePg). Enabling creates the empty
|
|
6208
|
+
* first-page header/footer parts; disabling keeps them for re-enable. */
|
|
6209
|
+
setDifferentFirstPage(on: boolean): boolean;
|
|
6210
|
+
/** Whether any section requests a different first page. */
|
|
6211
|
+
getDifferentFirstPage(): boolean;
|
|
6212
|
+
/** Word's "Different Odd & Even Pages" (settings.xml w:evenAndOddHeaders).
|
|
6213
|
+
* Enabling creates the empty even-page header/footer parts. */
|
|
6214
|
+
setOddEvenHeaders(on: boolean): boolean;
|
|
6215
|
+
getOddEvenHeaders(): boolean;
|
|
6216
|
+
/** Page-number format and start-at (w:pgNumType): decimal / roman / letter
|
|
6217
|
+
* numbering, restart value. scope "section" targets the caret's section;
|
|
6218
|
+
* "document" (and any shared document) every section. */
|
|
6219
|
+
setPageNumberFormat(patch: PageNumberFormatPatch, scope?: "document" | "section"): boolean;
|
|
6220
|
+
/** Current page-number settings for the caret's section. */
|
|
6221
|
+
getPageNumberFormat(): {
|
|
6222
|
+
fmt: PageNumberFormat;
|
|
6223
|
+
start: number | null;
|
|
6224
|
+
};
|
|
6225
|
+
/** Patch the automatic-hyphenation settings (w:autoHyphenation,
|
|
6226
|
+
* w:hyphenationZone in points, w:doNotHyphenateCaps). Round-trip state:
|
|
6227
|
+
* this engine's layout does not hyphenate automatically — the settings
|
|
6228
|
+
* govern Word's own rendering of the document. */
|
|
6229
|
+
setHyphenation(patch: {
|
|
6230
|
+
auto?: boolean;
|
|
6231
|
+
zonePt?: number | null;
|
|
6232
|
+
noCaps?: boolean;
|
|
6233
|
+
}): boolean;
|
|
6234
|
+
/** Current hyphenation settings (zonePt null = Word's default 18pt). */
|
|
6235
|
+
getHyphenation(): {
|
|
6236
|
+
auto: boolean;
|
|
6237
|
+
zonePt: number | null;
|
|
6238
|
+
noCaps: boolean;
|
|
6239
|
+
};
|
|
6240
|
+
/** Word's page-number position gallery: a single live PAGE field in the
|
|
6241
|
+
* header (top) or footer (bottom), aligned left/center/right. Creates the
|
|
6242
|
+
* part on demand and replaces its content — a gallery pick, not a merge. */
|
|
6243
|
+
insertPageNumberPosition(position: PageNumberGalleryPosition, align: PageNumberGalleryAlign): boolean;
|
|
6244
|
+
/** Word's "Remove Page Numbers": strips PAGE/NUMPAGES fields from every
|
|
6245
|
+
* header and footer part. */
|
|
6246
|
+
removePageNumbers(): boolean;
|
|
6247
|
+
/** The Header & Footer preset gallery: replace a header or footer's
|
|
6248
|
+
* content with a preset layout (blank / centered title / title + date /
|
|
6249
|
+
* three-column). */
|
|
6250
|
+
insertHeaderFooterPreset(kind: "header" | "footer", preset: HeaderFooterPreset): boolean;
|
|
6251
|
+
/** Footnote options (w:footnotePr): number format, restart rule, start-at,
|
|
6252
|
+
* and position (§17.11.17/19/21). scope "section" targets the caret's
|
|
6253
|
+
* section; "document" (and any shared document) every section. Format and
|
|
6254
|
+
* start drive the painted marks; restart honors "eachSect" only; position
|
|
6255
|
+
* round-trips without changing where footnotes lay out (always page
|
|
6256
|
+
* bottom in this engine). */
|
|
6257
|
+
setFootnoteOptions(patch: FootnoteOptionsPatch, scope?: "document" | "section"): boolean;
|
|
6258
|
+
/** Current footnote options for the caret's section. */
|
|
6259
|
+
getFootnoteOptions(): ReturnType<typeof footnoteOptionsAt>;
|
|
6260
|
+
/** Same as setFootnoteOptions, for endnotes — position vocabulary differs
|
|
6261
|
+
* (sectEnd / docEnd). */
|
|
6262
|
+
setEndnoteOptions(patch: EndnoteOptionsPatch, scope?: "document" | "section"): boolean;
|
|
6263
|
+
getEndnoteOptions(): ReturnType<typeof endnoteOptionsAt>;
|
|
6264
|
+
/** Resolve (true) or reopen (false) a comment thread. */
|
|
6265
|
+
resolveComment(id: string, resolved: boolean): boolean;
|
|
6266
|
+
/** Replace a comment's body text (Word's edit-my-comment). */
|
|
6267
|
+
editComment(id: string, text: string): boolean;
|
|
6268
|
+
/** Select and scroll to the next/previous commented range (Review-tab
|
|
6269
|
+
* navigation). Returns the focused thread's comment id, or null when the
|
|
6270
|
+
* document has no anchored comments. */
|
|
6271
|
+
stepComment(delta: 1 | -1): string | null;
|
|
6272
|
+
/** Word Count: body text statistics from the model plus the page count
|
|
6273
|
+
* from the latest layout. */
|
|
6274
|
+
wordCount(): {
|
|
6275
|
+
words: number;
|
|
6276
|
+
characters: number;
|
|
6277
|
+
charactersWithSpaces: number;
|
|
6278
|
+
paragraphs: number;
|
|
6279
|
+
pages: number;
|
|
6280
|
+
};
|
|
4105
6281
|
/** Effective formatting of the current selection (toolbar state), or null. */
|
|
4106
6282
|
getSelectionFormat(): SelectionFormat | null;
|
|
4107
6283
|
/** Print the rendered pages (browser print dialog / save as PDF). */
|
|
4108
6284
|
print(): void;
|
|
6285
|
+
/**
|
|
6286
|
+
* The standalone print document (all pages plus styles) as an HTML string,
|
|
6287
|
+
* for hosts that produce the PDF themselves (e.g. a desktop shell).
|
|
6288
|
+
* Null before the first render.
|
|
6289
|
+
*/
|
|
6290
|
+
exportPrintHtml(): string | null;
|
|
4109
6291
|
/** Serialize the (edited) document back to .docx bytes. */
|
|
4110
6292
|
save(): Uint8Array;
|
|
4111
6293
|
/** Page count after the latest layout. */
|
|
@@ -4123,14 +6305,21 @@ interface DocxViewApi {
|
|
|
4123
6305
|
/** Reject the tracked change at the caret (drop insertion / restore deletion). */
|
|
4124
6306
|
rejectRevisionAtCaret(): boolean;
|
|
4125
6307
|
/** How many tracked changes (suggestions) the document currently holds. */
|
|
4126
|
-
|
|
6308
|
+
/** Tracked changes in the document, or only `author`'s when given. */
|
|
6309
|
+
revisionCount(author?: string): number;
|
|
4127
6310
|
/** Accept every tracked change (one undo step). Returns how many applied. */
|
|
4128
|
-
|
|
6311
|
+
/** Accept every tracked change, or only `author`'s. A surface that owns some
|
|
6312
|
+
* of the document's revisions must pass its own author, or it resolves work
|
|
6313
|
+
* it never made. */
|
|
6314
|
+
acceptAllRevisions(author?: string): number;
|
|
4129
6315
|
/** Reject every tracked change (one undo step). Returns how many applied. */
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
*
|
|
6316
|
+
/** Reject every tracked change, or only `author`'s. See acceptAllRevisions. */
|
|
6317
|
+
rejectAllRevisions(author?: string): number;
|
|
6318
|
+
/** Current caret as stable-id addresses, or null. The encoding survives a
|
|
6319
|
+
* reconciliation reload, so it can be captured from a view about to
|
|
6320
|
+
* remount and restored into its replacement. In a local document the first
|
|
6321
|
+
* call populates the stable-id table (like selectRange), so hosts can
|
|
6322
|
+
* capture addresses outside a collab mount too. */
|
|
4134
6323
|
getEncodedCaret(): EncodedCaret | null;
|
|
4135
6324
|
/** Restore a caret captured by getEncodedCaret. False when the position no
|
|
4136
6325
|
* longer resolves (or outside collab mode). */
|
|
@@ -4154,6 +6343,7 @@ interface DocxViewApi {
|
|
|
4154
6343
|
document: DocxDocument;
|
|
4155
6344
|
}
|
|
4156
6345
|
type ScreenshotInsertResult = "inserted" | "unsupported" | "cancelled" | "error" | "no-caret";
|
|
6346
|
+
|
|
4157
6347
|
/**
|
|
4158
6348
|
* Image formats a SHARED document accepts, and the single source of truth for
|
|
4159
6349
|
* both halves of that promise: the guard that declines an intent and the
|
|
@@ -4169,6 +6359,10 @@ type ScreenshotInsertResult = "inserted" | "unsupported" | "cancelled" | "error"
|
|
|
4169
6359
|
* it is an intent-shape change with an ENGINE_VERSION bump, not a UI edit.
|
|
4170
6360
|
*/
|
|
4171
6361
|
declare const COLLAB_IMAGE_EXTS: readonly ["png", "jpg", "jpeg", "gif", "bmp", "webp"];
|
|
6362
|
+
/** File-picker accept list for the raster formats. Also the picture
|
|
6363
|
+
* watermark's whole list: a VML `v:imagedata` cannot carry an SVG, in a
|
|
6364
|
+
* shared document or a local one. */
|
|
6365
|
+
declare const RASTER_IMAGE_ACCEPT = "image/png,image/jpeg,image/gif,image/bmp,image/webp";
|
|
4172
6366
|
/**
|
|
4173
6367
|
* Why an image insert did not happen, so the caller can SAY so. Every one of
|
|
4174
6368
|
* these was a bare `return` until a user hit the `unsupported-format` path and
|
|
@@ -4307,9 +6501,17 @@ interface DocxViewProps {
|
|
|
4307
6501
|
* stack would edit this replica with nothing on the wire. Absent ⇒ undo
|
|
4308
6502
|
* declines rather than mutating. */
|
|
4309
6503
|
undoLast?: () => void;
|
|
6504
|
+
/** Single-process session marker (useAgentDocumentSession over a
|
|
6505
|
+
* LocalDocumentSession). Its presence tells the editor there are NO peers,
|
|
6506
|
+
* so undo/redo replay the local history stack; it fires after each applied
|
|
6507
|
+
* undo/redo so the session can bump its revision. A REAL room must leave
|
|
6508
|
+
* this unset, or Cmd+Z would fork it. */
|
|
6509
|
+
noteLocalHistory?: () => void;
|
|
4310
6510
|
};
|
|
4311
6511
|
/** Author name stamped on comment replies (default "You"). */
|
|
4312
6512
|
commentAuthor?: string;
|
|
6513
|
+
/** Connected collaborator names offered as @mention shortcuts in comments. */
|
|
6514
|
+
commentMentions?: string[];
|
|
4313
6515
|
/** Render review comments (range highlights + margin balloons). Default true. */
|
|
4314
6516
|
showComments?: boolean;
|
|
4315
6517
|
/** Tracked-changes display: "final" (default) or "markup". */
|
|
@@ -4318,7 +6520,53 @@ interface DocxViewProps {
|
|
|
4318
6520
|
* render (unavailable, or lacking the document's script) — the page is
|
|
4319
6521
|
* silently substituting and may differ from Word. Empty array = all good. */
|
|
4320
6522
|
onMissingFonts?: (missing: MissingFont[]) => void;
|
|
6523
|
+
/**
|
|
6524
|
+
* Mail-merge PREVIEW: the active record's column values, painted into the
|
|
6525
|
+
* document's MERGEFIELD fields. Absent (or undefined) shows the «Name»
|
|
6526
|
+
* placeholders — that is preview "off".
|
|
6527
|
+
*
|
|
6528
|
+
* Nothing is written to the document. The values are resolved as the pages
|
|
6529
|
+
* are laid out, so they cannot reach a saved file, an undo entry or the
|
|
6530
|
+
* collab wire; preview is per-viewer state by construction. Changing this
|
|
6531
|
+
* prop relays the pages without re-parsing the .docx.
|
|
6532
|
+
*
|
|
6533
|
+
* A column the record does NOT carry keeps its «Name» placeholder, so the
|
|
6534
|
+
* user can see which fields the data leaves unbound. Word renders such a
|
|
6535
|
+
* field blank; this is a deliberate divergence. A column that IS present but
|
|
6536
|
+
* empty renders empty and suppresses the field's \b and \f switch texts.
|
|
6537
|
+
*/
|
|
6538
|
+
mergeRecord?: MergeRecord;
|
|
6539
|
+
}
|
|
6540
|
+
interface AgentDocumentViewBinding {
|
|
6541
|
+
subscribe(listener: () => void): () => void;
|
|
6542
|
+
getSnapshot(): number;
|
|
6543
|
+
doc: DocxDocument;
|
|
6544
|
+
submit(intent: EditorIntent): void;
|
|
6545
|
+
submitOp(intent: {
|
|
6546
|
+
kind: string;
|
|
6547
|
+
} & Record<string, unknown>): void;
|
|
6548
|
+
allocIds(count: number): number[];
|
|
6549
|
+
uploadMedia?(bytes: Uint8Array): Promise<{
|
|
6550
|
+
blobSha: string;
|
|
6551
|
+
bytesLen: number;
|
|
6552
|
+
iv?: string;
|
|
6553
|
+
} | null>;
|
|
6554
|
+
/** Bump the session revision after a local history undo/redo mutated the
|
|
6555
|
+
* document outside the intent path. See collab.noteLocalHistory. */
|
|
6556
|
+
noteHistory?(): void;
|
|
6557
|
+
takeRenderScope(): {
|
|
6558
|
+
kind: "doc";
|
|
6559
|
+
} | {
|
|
6560
|
+
kind: "block";
|
|
6561
|
+
blocks: XmlElement[];
|
|
6562
|
+
} | {
|
|
6563
|
+
kind: "split";
|
|
6564
|
+
before: XmlElement;
|
|
6565
|
+
after: XmlElement;
|
|
6566
|
+
} | null;
|
|
4321
6567
|
}
|
|
6568
|
+
/** Connect a framework-neutral local document session to DocxView. */
|
|
6569
|
+
declare function useAgentDocumentSession(binding: AgentDocumentViewBinding): Pick<DocxViewProps, "source" | "collab">;
|
|
4322
6570
|
/**
|
|
4323
6571
|
* High-fidelity paginated DOCX viewer (and, with `editable`, editor).
|
|
4324
6572
|
*
|
|
@@ -4327,6 +6575,6 @@ interface DocxViewProps {
|
|
|
4327
6575
|
* <DocxView source="/report.docx" editable onReady={setApi} /> // editing
|
|
4328
6576
|
* ```
|
|
4329
6577
|
*/
|
|
4330
|
-
declare function DocxView({ source, zoom, fitWidth, narrowWidth, editable, className, style, onLoad, onPageCountChange, onReady, onError, commentAuthor, showComments, revisions, onMissingFonts, collab, }: DocxViewProps): react.JSX.Element;
|
|
6578
|
+
declare function DocxView({ source, zoom, fitWidth, narrowWidth, editable, className, style, onLoad, onPageCountChange, onReady, onError, commentAuthor, commentMentions, showComments, revisions, onMissingFonts, mergeRecord, collab, }: DocxViewProps): react.JSX.Element;
|
|
4331
6579
|
|
|
4332
|
-
export { type
|
|
6580
|
+
export { downloadDocx as $, type AgentDocumentViewBinding as A, RASTER_IMAGE_ACCEPT as B, type ClientMessage as C, DocxDocument as D, type EncodedCaret as E, type RunFormatPatch as F, type ScreenshotInsertResult as G, type HostShortcutSection as H, type Intent as I, type SelectionFormat as J, type ShapePreset as K, type LineageHead as L, type MergeRecord as M, NUMBERING_PRESETS as N, ToolbarMenuSelect as O, type PresencePosition as P, type ToolbarMenuSelectOption as Q, type RosterEntry as R, type ServerMessage as S, type ToolbarFeature as T, type UndoOutcome as U, type ToolbarMenuSelectProps as V, type WriteStatus as W, type XmlElement as X, type WireRange as Y, compareWithFile as Z, comparedName as _, type ParticipantProfile as a, layoutDocument as a0, pickAndCompare as a1, pickDocx as a2, printPages as a3, renderToDom as a4, useAgentDocumentSession as a5, type IdSidecar as b, type ToolbarMode as c, type DocxViewApi as d, bytesToB64 as e, deriveEpochKeys as f, docKeyFromFragment as g, stretchShareCode as h, COLLAB_IMAGE_EXTS as i, type CompareResult as j, type CompareWithFileOptions as k, type CoverPageContent as l, mintDocKey as m, DocxToolbar as n, type DocxToolbarProps as o, DocxView as p, type DocxViewProps as q, type DrawingTool as r, sealCheckpoint as s, INSERT_COMMANDS as t, type ImageInsertResult as u, type InsertCommandSpec as v, type LineNumberingPatch as w, type NumberingPresetId as x, type PageLayoutPatch as y, type ParagraphAlignment as z };
|