@office-open/docx 0.8.1 → 0.9.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.
@@ -0,0 +1,4404 @@
1
+ import { TargetModeType, convertEmuToPixels, convertPixelsToEmu, convertToEmu, convertToTwip, convertUniversalMeasureToEmu, decimalNumber, eighthPointMeasureValue, hexColorValue, hpsMeasureValue, measurementOrPercentValue, pointMeasureValue, signedTwipsMeasureValue, toUint8Array, twipsMeasureValue, uCharHexNumber, uniqueId, uniqueNumericIdCreator, xsdVerticalMergeRev } from "@office-open/core";
2
+ import { attr, attrBool, attrNum, children, element, escapeXml, findChild, findDeep, textOf } from "@office-open/xml";
3
+ import { calculateEffectExtent, createEffectDag, createScene3D, createShape3D, customGeometryDesc, effectListDesc, extractBlipFillMedia, fillDesc, outlineDesc, scene3DDesc, shape3DDesc, transform2DDesc } from "@office-open/core/drawingml";
4
+ import { chartSpaceDesc } from "@office-open/core/chart";
5
+ import { createDataModel } from "@office-open/core/smartart";
6
+ //#region src/shared/media/media.ts
7
+ /**
8
+ * Converts user-facing transformation options (pixels or universal measure) to internal
9
+ * transformation data (pixels + EMUs).
10
+ *
11
+ * @param options - User-facing transformation in pixels or universal measure
12
+ * @returns Internal transformation data with both pixel and EMU values
13
+ */
14
+ const createTransformation = (options) => ({
15
+ emus: {
16
+ x: typeof options.width === "string" ? convertUniversalMeasureToEmu(options.width) : convertPixelsToEmu(options.width),
17
+ y: typeof options.height === "string" ? convertUniversalMeasureToEmu(options.height) : convertPixelsToEmu(options.height)
18
+ },
19
+ flip: options.flip,
20
+ offset: {
21
+ emus: {
22
+ x: typeof options.offset?.left === "string" ? convertUniversalMeasureToEmu(options.offset.left) : convertPixelsToEmu(options.offset?.left ?? 0),
23
+ y: typeof options.offset?.top === "string" ? convertUniversalMeasureToEmu(options.offset.top) : convertPixelsToEmu(options.offset?.top ?? 0)
24
+ },
25
+ pixels: {
26
+ x: typeof options.offset?.left === "number" ? Math.round(options.offset.left) : 0,
27
+ y: typeof options.offset?.top === "number" ? Math.round(options.offset.top) : 0
28
+ }
29
+ },
30
+ pixels: {
31
+ x: typeof options.width === "number" ? Math.round(options.width) : 0,
32
+ y: typeof options.height === "number" ? Math.round(options.height) : 0
33
+ },
34
+ rotation: options.rotation ? options.rotation * 6e4 : void 0
35
+ });
36
+ /**
37
+ * Manages embedded media (images) in a document.
38
+ *
39
+ * Media stores all images referenced in the document and provides
40
+ * access to their data for packaging into the DOCX file. Each image
41
+ * is stored with a unique key for retrieval.
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * const media = new Media();
46
+ * media.addImage("image1", {
47
+ * type: "png",
48
+ * fileName: "image1.png",
49
+ * transformation: {
50
+ * pixels: { x: 200, y: 100 },
51
+ * emus: { x: 1828800, y: 914400 }
52
+ * },
53
+ * data: imageBuffer
54
+ * });
55
+ * const allImages = media.Array;
56
+ * ```
57
+ */
58
+ var Media = class {
59
+ map;
60
+ constructor() {
61
+ this.map = /* @__PURE__ */ new Map();
62
+ }
63
+ /**
64
+ * Adds an image to the media collection.
65
+ *
66
+ * @param key - Unique identifier for this image
67
+ * @param mediaData - Complete image data including file name, transformation, and raw data
68
+ */
69
+ addImage(key, mediaData) {
70
+ this.map.set(key, mediaData);
71
+ }
72
+ /**
73
+ * Gets all images as an array.
74
+ *
75
+ * @returns Read-only array of all media data in the collection
76
+ */
77
+ get array() {
78
+ return [...this.map.values()];
79
+ }
80
+ };
81
+ //#endregion
82
+ //#region src/shared/media/data.ts
83
+ /**
84
+ * @ignore
85
+ */
86
+ const WORKAROUND2 = "";
87
+ //#endregion
88
+ //#region src/parts/drawing/inline/graphic/graphic-data/wps/body-properties.ts
89
+ /**
90
+ * Text anchoring type (ST_TextAnchoringType).
91
+ *
92
+ * ## XSD Schema
93
+ * ```xml
94
+ * <xsd:simpleType name="ST_TextAnchoringType">
95
+ * <xsd:restriction base="xsd:token">
96
+ * <xsd:enumeration value="t"/>
97
+ * <xsd:enumeration value="ctr"/>
98
+ * <xsd:enumeration value="b"/>
99
+ * <xsd:enumeration value="just"/>
100
+ * <xsd:enumeration value="dist"/>
101
+ * </xsd:restriction>
102
+ * </xsd:simpleType>
103
+ * ```
104
+ *
105
+ * @publicApi
106
+ */
107
+ let VerticalAnchor = /* @__PURE__ */ function(VerticalAnchor) {
108
+ VerticalAnchor["TOP"] = "t";
109
+ VerticalAnchor["CENTER"] = "ctr";
110
+ VerticalAnchor["BOTTOM"] = "b";
111
+ VerticalAnchor["JUSTIFY"] = "just";
112
+ VerticalAnchor["DISTRIBUTED"] = "dist";
113
+ return VerticalAnchor;
114
+ }({});
115
+ /**
116
+ * Text vertical overflow type (ST_TextVertOverflowType).
117
+ */
118
+ const TextVertOverflowType = {
119
+ OVERFLOW: "overflow",
120
+ ELLIPSIS: "ellipsis",
121
+ CLIP: "clip"
122
+ };
123
+ /**
124
+ * Text horizontal overflow type (ST_TextHorzOverflowType).
125
+ */
126
+ const TextHorzOverflowType = {
127
+ OVERFLOW: "overflow",
128
+ CLIP: "clip"
129
+ };
130
+ /**
131
+ * Text vertical type (ST_TextVerticalType).
132
+ *
133
+ * ## XSD Schema
134
+ * ```xml
135
+ * <xsd:simpleType name="ST_TextVerticalType">
136
+ * <xsd:restriction base="xsd:token">
137
+ * <xsd:enumeration value="horz"/>
138
+ * <xsd:enumeration value="vert"/>
139
+ * <xsd:enumeration value="vert270"/>
140
+ * <xsd:enumeration value="wordArtVert"/>
141
+ * <xsd:enumeration value="eaVert"/>
142
+ * <xsd:enumeration value="mongolianVert"/>
143
+ * <xsd:enumeration value="wordArtVertRtl"/>
144
+ * </xsd:restriction>
145
+ * </xsd:simpleType>
146
+ * ```
147
+ */
148
+ const TextVerticalType = {
149
+ HORIZONTAL: "horz",
150
+ VERTICAL: "vert",
151
+ VERTICAL_270: "vert270",
152
+ WORD_ART_VERTICAL: "wordArtVert",
153
+ EAST_ASIAN_VERTICAL: "eaVert",
154
+ MONGOLIAN_VERTICAL: "mongolianVert",
155
+ WORD_ART_VERTICAL_RTL: "wordArtVertRtl"
156
+ };
157
+ /**
158
+ * Text body wrapping type (ST_TextWrappingType).
159
+ *
160
+ * This is different from text wrapping around shapes (ST_WrapText).
161
+ */
162
+ const TextBodyWrappingType = {
163
+ NONE: "none",
164
+ SQUARE: "square"
165
+ };
166
+ const filterAttrs = (options) => {
167
+ const attrs = {};
168
+ for (const [key, value] of Object.entries(options)) if (value !== void 0) attrs[key] = value;
169
+ return Object.keys(attrs).length > 0 ? attrs : void 0;
170
+ };
171
+ const createPresetTextShape = (options) => {
172
+ const adjChildren = [];
173
+ if (options.adjustments) for (const adj of options.adjustments) adjChildren.push(`<a:gd name="${adj.name}" fmla="${adj.formula}"/>`);
174
+ return element("a:prstTxWarp", { prst: options.preset }, adjChildren.length > 0 ? [element("a:avLst", void 0, adjChildren)] : void 0);
175
+ };
176
+ /**
177
+ * Creates a text body properties element (wps:bodyPr).
178
+ *
179
+ * Supports all 19 CT_TextBodyProperties attributes and all child elements
180
+ * including preset text warp, autofit variants, 3D scene, and text 3D.
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * // Simple margins and anchor
185
+ * createBodyProperties({
186
+ * margins: { top: 100, bottom: 100, left: 200, right: 200 },
187
+ * verticalAnchor: VerticalAnchor.CENTER,
188
+ * });
189
+ *
190
+ * // Full options with vertical text and autofit
191
+ * createBodyProperties({
192
+ * vert: TextVerticalType.VERTICAL,
193
+ * wrap: TextBodyWrappingType.NONE,
194
+ * normAutofit: { fontScale: 80000 },
195
+ * numCol: 2,
196
+ * anchor: VerticalAnchor.TOP,
197
+ * });
198
+ * ```
199
+ */
200
+ const createBodyProperties = (options = {}) => {
201
+ const anchor = options.anchor ?? options.verticalAnchor;
202
+ const lIns = options.lIns ?? options.margins?.left;
203
+ const tIns = options.tIns ?? options.margins?.top;
204
+ const rIns = options.rIns ?? options.margins?.right;
205
+ const bIns = options.bIns ?? options.margins?.bottom;
206
+ const attrs = filterAttrs({
207
+ rot: options.rotation,
208
+ spcFirstLastPara: options.spcFirstLastPara,
209
+ vertOverflow: options.vertOverflow,
210
+ horzOverflow: options.horzOverflow,
211
+ vert: options.vert,
212
+ wrap: options.wrap,
213
+ lIns: lIns !== void 0 ? convertToEmu(lIns) : void 0,
214
+ tIns: tIns !== void 0 ? convertToEmu(tIns) : void 0,
215
+ rIns: rIns !== void 0 ? convertToEmu(rIns) : void 0,
216
+ bIns: bIns !== void 0 ? convertToEmu(bIns) : void 0,
217
+ numCol: options.numCol,
218
+ spcCol: options.spcCol !== void 0 ? convertToEmu(options.spcCol) : void 0,
219
+ rtlCol: options.rtlCol,
220
+ fromWordArt: options.fromWordArt,
221
+ anchor,
222
+ anchorCtr: options.anchorCtr,
223
+ forceAA: options.forceAA,
224
+ upright: options.upright,
225
+ compatLnSpc: options.compatLnSpc
226
+ });
227
+ const children = [];
228
+ if (options.prstTxWarp) children.push(createPresetTextShape(options.prstTxWarp));
229
+ if (options.noAutoFit) children.push(`<a:noAutofit/>`);
230
+ else if (options.normAutofit) {
231
+ const normAttrs = filterAttrs({
232
+ fontScale: options.normAutofit.fontScale,
233
+ lnSpcReduction: options.normAutofit.lnSpcReduction
234
+ });
235
+ children.push(element("a:normAutofit", normAttrs));
236
+ } else if (options.spAutoFit) children.push(`<a:spAutoFit/>`);
237
+ if (options.scene3d) children.push(createScene3D(options.scene3d));
238
+ if (options.sp3d) children.push(createShape3D(options.sp3d));
239
+ else if (options.flatTx) {
240
+ const flatAttrs = filterAttrs({ z: options.flatTx.z });
241
+ children.push(element("a:flatTx", flatAttrs));
242
+ }
243
+ return element("wps:bodyPr", attrs, children.length > 0 ? children : void 0);
244
+ };
245
+ //#endregion
246
+ //#region src/parts/table/table-cell/table-cell-components.ts
247
+ /**
248
+ * Vertical merge types for table cells.
249
+ *
250
+ * Defines the merge behavior for vertically merged cells (row span).
251
+ */
252
+ const VerticalMergeType = {
253
+ /**
254
+ * Cell that is merged with upper one.
255
+ */
256
+ CONTINUE: "continue",
257
+ /**
258
+ * Cell that is starting the vertical merge.
259
+ */
260
+ RESTART: "restart"
261
+ };
262
+ /**
263
+ * Text direction values for table cells.
264
+ *
265
+ * Specifies the direction in which text flows within a table cell.
266
+ */
267
+ const TextDirection = {
268
+ /** Text flows from bottom to top, left to right */
269
+ BOTTOM_TO_TOP_LEFT_TO_RIGHT: "btLr",
270
+ /** Text flows from left to right, top to bottom (default) */
271
+ LEFT_TO_RIGHT_TOP_TO_BOTTOM: "lrTb",
272
+ /** Text flows from top to bottom, right to left */
273
+ TOP_TO_BOTTOM_RIGHT_TO_LEFT: "tbRl"
274
+ };
275
+ //#endregion
276
+ //#region src/shared/border.ts
277
+ /**
278
+ * Table borders are defined with the <w:tblBorders> element. Child elements of this element specify the kinds of `border`:
279
+ *
280
+ * `bottom`, `end` (`right` in the previous version of the standard), `insideH`, `insideV`, `start` (`left` in the previous version of the standard), and `top`.
281
+ *
282
+ * Reference: http://officeopenxml.com/WPtableBorders.php
283
+ *
284
+ * ## XSD Schema
285
+ * ```xml
286
+ * <xsd:simpleType name="ST_Border">
287
+ * <xsd:restriction base="xsd:string">
288
+ * <xsd:enumeration value="single"/>
289
+ * <xsd:enumeration value="dashDotStroked"/>
290
+ * <xsd:enumeration value="dashed"/>
291
+ * <xsd:enumeration value="dashSmallGap"/>
292
+ * <xsd:enumeration value="dotDash"/>
293
+ * <xsd:enumeration value="dotDotDash"/>
294
+ * <xsd:enumeration value="dotted"/>
295
+ * <xsd:enumeration value="double"/>
296
+ * <xsd:enumeration value="doubleWave"/>
297
+ * <xsd:enumeration value="inset"/>
298
+ * <xsd:enumeration value="nil"/>
299
+ * <xsd:enumeration value="none"/>
300
+ * <xsd:enumeration value="outset"/>
301
+ * <xsd:enumeration value="thick"/>
302
+ * <xsd:enumeration value="thickThinLargeGap"/>
303
+ * <xsd:enumeration value="thickThinMediumGap"/>
304
+ * <xsd:enumeration value="thickThinSmallGap"/>
305
+ * <xsd:enumeration value="thinThickLargeGap"/>
306
+ * <xsd:enumeration value="thinThickMediumGap"/>
307
+ * <xsd:enumeration value="thinThickSmallGap"/>
308
+ * <xsd:enumeration value="thinThickThinLargeGap"/>
309
+ * <xsd:enumeration value="thinThickThinMediumGap"/>
310
+ * <xsd:enumeration value="thinThickThinSmallGap"/>
311
+ * <xsd:enumeration value="threeDEmboss"/>
312
+ * <xsd:enumeration value="threeDEngrave"/>
313
+ * <xsd:enumeration value="triple"/>
314
+ * <xsd:enumeration value="wave"/>
315
+ * </xsd:restriction>
316
+ * </xsd:simpleType>
317
+ * ```
318
+ *
319
+ * @publicApi
320
+ */
321
+ const BorderStyle = {
322
+ /** A single line */
323
+ SINGLE: "single",
324
+ /** A line with a series of alternating thin and thick strokes */
325
+ DASH_DOT_STROKED: "dashDotStroked",
326
+ /** A dashed line */
327
+ DASHED: "dashed",
328
+ /** A dashed line with small gaps */
329
+ DASH_SMALL_GAP: "dashSmallGap",
330
+ /** A line with alternating dots and dashes */
331
+ DOT_DASH: "dotDash",
332
+ /** A line with a repeating dot - dot - dash sequence */
333
+ DOT_DOT_DASH: "dotDotDash",
334
+ /** A dotted line */
335
+ DOTTED: "dotted",
336
+ /** A double line */
337
+ DOUBLE: "double",
338
+ /** A double wavy line */
339
+ DOUBLE_WAVE: "doubleWave",
340
+ /** An inset set of lines */
341
+ INSET: "inset",
342
+ /** No border */
343
+ NIL: "nil",
344
+ /** No border */
345
+ NONE: "none",
346
+ /** An outset set of lines */
347
+ OUTSET: "outset",
348
+ /** A single line */
349
+ THICK: "thick",
350
+ /** A thick line contained within a thin line with a large-sized intermediate gap */
351
+ THICK_THIN_LARGE_GAP: "thickThinLargeGap",
352
+ /** A thick line contained within a thin line with a medium-sized intermediate gap */
353
+ THICK_THIN_MEDIUM_GAP: "thickThinMediumGap",
354
+ /** A thick line contained within a thin line with a small intermediate gap */
355
+ THICK_THIN_SMALL_GAP: "thickThinSmallGap",
356
+ /** A thin line contained within a thick line with a large-sized intermediate gap */
357
+ THIN_THICK_LARGE_GAP: "thinThickLargeGap",
358
+ /** A thick line contained within a thin line with a medium-sized intermediate gap */
359
+ THIN_THICK_MEDIUM_GAP: "thinThickMediumGap",
360
+ /** A thick line contained within a thin line with a small intermediate gap */
361
+ THIN_THICK_SMALL_GAP: "thinThickSmallGap",
362
+ /** A thin-thick-thin line with a large gap */
363
+ THIN_THICK_THIN_LARGE_GAP: "thinThickThinLargeGap",
364
+ /** A thin-thick-thin line with a medium gap */
365
+ THIN_THICK_THIN_MEDIUM_GAP: "thinThickThinMediumGap",
366
+ /** A thin-thick-thin line with a small gap */
367
+ THIN_THICK_THIN_SMALL_GAP: "thinThickThinSmallGap",
368
+ /** A three-staged gradient line, getting darker towards the paragraph */
369
+ THREE_D_EMBOSS: "threeDEmboss",
370
+ /** A three-staged gradient like, getting darker away from the paragraph */
371
+ THREE_D_ENGRAVE: "threeDEngrave",
372
+ /** A triple line */
373
+ TRIPLE: "triple",
374
+ /** A wavy line */
375
+ WAVE: "wave"
376
+ };
377
+ //#endregion
378
+ //#region src/parts/table/table-width.ts
379
+ /**
380
+ * Width type values for tables and cells.
381
+ *
382
+ * ## XSD Schema
383
+ * ```xml
384
+ * <xsd:simpleType name="ST_TblWidth">
385
+ * <xsd:restriction base="xsd:string">
386
+ * <xsd:enumeration value="nil"/>
387
+ * <xsd:enumeration value="pct"/>
388
+ * <xsd:enumeration value="dxa"/>
389
+ * <xsd:enumeration value="auto"/>
390
+ * </xsd:restriction>
391
+ * </xsd:simpleType>
392
+ * ```
393
+ *
394
+ * @publicApi
395
+ */
396
+ const WidthType = {
397
+ /** Auto. */
398
+ AUTO: "auto",
399
+ /** Value is in twentieths of a point */
400
+ DXA: "dxa",
401
+ /** No (empty) value. */
402
+ NIL: "nil",
403
+ /** Value is in percentage. */
404
+ PERCENTAGE: "pct"
405
+ };
406
+ //#endregion
407
+ //#region src/parts/drawing/text-wrap/text-wrapping.ts
408
+ /**
409
+ * Enumeration of text wrapping types for floating drawings.
410
+ *
411
+ * Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
412
+ *
413
+ * @publicApi
414
+ */
415
+ const TextWrappingType = {
416
+ NONE: 0,
417
+ SQUARE: 1,
418
+ TIGHT: 2,
419
+ TOP_AND_BOTTOM: 3,
420
+ THROUGH: 4
421
+ };
422
+ /**
423
+ * Enumeration of text wrapping sides for floating drawings.
424
+ *
425
+ * Specifies on which side(s) text can wrap around the drawing.
426
+ *
427
+ * Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
428
+ *
429
+ * @publicApi
430
+ */
431
+ const TextWrappingSide = {
432
+ /** Text wraps on both sides of the drawing */
433
+ BOTH_SIDES: "bothSides",
434
+ /** Text wraps only on the left side */
435
+ LEFT: "left",
436
+ /** Text wraps only on the right side */
437
+ RIGHT: "right",
438
+ /** Text wraps on the side with more space */
439
+ LARGEST: "largest"
440
+ };
441
+ //#endregion
442
+ //#region src/parts/drawing/text-wrap/wrap-tight.ts
443
+ /**
444
+ * Wrap Tight module for DrawingML text wrapping.
445
+ *
446
+ * This module provides tight text wrapping for floating drawings
447
+ * where text wraps closely around the image shape.
448
+ *
449
+ * Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
450
+ *
451
+ * @module
452
+ */
453
+ /**
454
+ * Creates a default rectangular wrap polygon matching the image extent.
455
+ *
456
+ * Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
457
+ *
458
+ * ## XSD Schema
459
+ * ```xml
460
+ * <xsd:complexType name="CT_WrapPath">
461
+ * <xsd:sequence>
462
+ * <xsd:element name="start" type="a:CT_Point2D" minOccurs="1" maxOccurs="1"/>
463
+ * <xsd:element name="lineTo" type="a:CT_Point2D" minOccurs="2" maxOccurs="unbounded"/>
464
+ * </xsd:sequence>
465
+ * <xsd:attribute name="edited" type="xsd:boolean" use="optional"/>
466
+ * </xsd:complexType>
467
+ * ```
468
+ */
469
+ const createWrapPolygon$1 = (cx, cy) => element("wp:wrapPolygon", { edited: "0" }, [
470
+ `<wp:start x="0" y="0"/>`,
471
+ `<wp:lineTo x="0" y="${-cy}"/>`,
472
+ `<wp:lineTo x="${cx}" y="${-cy}"/>`,
473
+ `<wp:lineTo x="${cx}" y="0"/>`,
474
+ `<wp:lineTo x="0" y="0"/>`
475
+ ]);
476
+ /**
477
+ * Creates tight text wrapping for a floating drawing.
478
+ *
479
+ * WrapTight causes text to wrap closely around the contours
480
+ * of the drawing rather than its rectangular bounding box.
481
+ * A default rectangular wrap polygon matching the image extent is generated.
482
+ *
483
+ * Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
484
+ *
485
+ * ## XSD Schema
486
+ * ```xml
487
+ * <xsd:complexType name="CT_WrapTight">
488
+ * <xsd:sequence>
489
+ * <xsd:element name="wrapPolygon" type="CT_WrapPath" minOccurs="1" maxOccurs="1"/>
490
+ * </xsd:sequence>
491
+ * <xsd:attribute name="wrapText" type="ST_WrapText" use="required"/>
492
+ * <xsd:attribute name="distL" type="ST_WrapDistance"/>
493
+ * <xsd:attribute name="distR" type="ST_WrapDistance"/>
494
+ * </xsd:complexType>
495
+ * ```
496
+ */
497
+ const createWrapTight = (textWrapping, margins = {
498
+ bottom: 0,
499
+ left: 0,
500
+ right: 0,
501
+ top: 0
502
+ }, extent) => element("wp:wrapTight", {
503
+ distL: margins.left,
504
+ distR: margins.right,
505
+ wrapText: textWrapping.side || TextWrappingSide.BOTH_SIDES
506
+ }, [createWrapPolygon$1(extent.x, extent.y)]);
507
+ //#endregion
508
+ //#region src/parts/drawing/text-wrap/wrap-through.ts
509
+ /**
510
+ * Wrap Through module for DrawingML text wrapping.
511
+ *
512
+ * This module provides "through" text wrapping for floating drawings
513
+ * where text wraps through the image contours, filling any concave areas.
514
+ *
515
+ * Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
516
+ *
517
+ * @module
518
+ */
519
+ /**
520
+ * Creates a default rectangular wrap polygon matching the image extent.
521
+ *
522
+ * Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
523
+ *
524
+ * ## XSD Schema
525
+ * ```xml
526
+ * <xsd:complexType name="CT_WrapPath">
527
+ * <xsd:sequence>
528
+ * <xsd:element name="start" type="a:CT_Point2D" minOccurs="1" maxOccurs="1"/>
529
+ * <xsd:element name="lineTo" type="a:CT_Point2D" minOccurs="2" maxOccurs="unbounded"/>
530
+ * </xsd:sequence>
531
+ * <xsd:attribute name="edited" type="xsd:boolean" use="optional"/>
532
+ * </xsd:complexType>
533
+ * ```
534
+ */
535
+ const createWrapPolygon = (cx, cy) => element("wp:wrapPolygon", { edited: "0" }, [
536
+ `<wp:start x="0" y="0"/>`,
537
+ `<wp:lineTo x="0" y="${-cy}"/>`,
538
+ `<wp:lineTo x="${cx}" y="${-cy}"/>`,
539
+ `<wp:lineTo x="${cx}" y="0"/>`,
540
+ `<wp:lineTo x="0" y="0"/>`
541
+ ]);
542
+ /**
543
+ * Creates "through" text wrapping for a floating drawing.
544
+ *
545
+ * WrapThrough is similar to WrapTight but allows text to wrap through
546
+ * the concave portions of the drawing shape (e.g., the inside of the letter "O").
547
+ * A default rectangular wrap polygon matching the image extent is generated.
548
+ *
549
+ * Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
550
+ *
551
+ * ## XSD Schema
552
+ * ```xml
553
+ * <xsd:complexType name="CT_WrapThrough">
554
+ * <xsd:sequence>
555
+ * <xsd:element name="wrapPolygon" type="CT_WrapPath" minOccurs="1" maxOccurs="1"/>
556
+ * </xsd:sequence>
557
+ * <xsd:attribute name="wrapText" type="ST_WrapText" use="required"/>
558
+ * <xsd:attribute name="distL" type="ST_WrapDistance"/>
559
+ * <xsd:attribute name="distR" type="ST_WrapDistance"/>
560
+ * </xsd:complexType>
561
+ * ```
562
+ */
563
+ const createWrapThrough = (textWrapping, margins = {
564
+ bottom: 0,
565
+ left: 0,
566
+ right: 0,
567
+ top: 0
568
+ }, extent) => element("wp:wrapThrough", {
569
+ distL: margins.left,
570
+ distR: margins.right,
571
+ wrapText: textWrapping.side || TextWrappingSide.BOTH_SIDES
572
+ }, [createWrapPolygon(extent.x, extent.y)]);
573
+ //#endregion
574
+ //#region src/shared/constants.ts
575
+ /**
576
+ * Shared constants for WordprocessingML documents.
577
+ *
578
+ * Provides alignment, number format, and space type constants
579
+ * used across multiple document components.
580
+ *
581
+ * @module
582
+ */
583
+ /**
584
+ * Horizontal alignment options for floating drawings.
585
+ *
586
+ * Reference: https://www.datypic.com/sc/ooxml/t-wp_ST_AlignH.html
587
+ *
588
+ * @publicApi
589
+ */
590
+ const HorizontalPositionAlign = {
591
+ CENTER: "center",
592
+ INSIDE: "inside",
593
+ LEFT: "left",
594
+ OUTSIDE: "outside",
595
+ RIGHT: "right"
596
+ };
597
+ /**
598
+ * Vertical alignment options for floating drawings.
599
+ *
600
+ * Reference: https://www.datypic.com/sc/ooxml/t-wp_ST_AlignV.html
601
+ *
602
+ * @publicApi
603
+ */
604
+ const VerticalPositionAlign = {
605
+ BOTTOM: "bottom",
606
+ CENTER: "center",
607
+ INSIDE: "inside",
608
+ OUTSIDE: "outside",
609
+ TOP: "top"
610
+ };
611
+ /**
612
+ * Number format types for page numbers and list numbering.
613
+ *
614
+ * Reference: http://officeopenxml.com/WPnumbering-numFmt.php
615
+ *
616
+ * @publicApi
617
+ */
618
+ const NumberFormat = {
619
+ AIUEO: "aiueo",
620
+ AIUEO_FULL_WIDTH: "aiueoFullWidth",
621
+ ARABIC_ABJAD: "arabicAbjad",
622
+ ARABIC_ALPHA: "arabicAlpha",
623
+ BAHT_TEXT: "bahtText",
624
+ BULLET: "bullet",
625
+ CARDINAL_TEXT: "cardinalText",
626
+ CHICAGO: "chicago",
627
+ CHINESE_COUNTING: "chineseCounting",
628
+ CHINESE_COUNTING_TEN_THOUSAND: "chineseCountingThousand",
629
+ CHINESE_LEGAL_SIMPLIFIED: "chineseLegalSimplified",
630
+ CHOSUNG: "chosung",
631
+ DECIMAL: "decimal",
632
+ DECIMAL_ENCLOSED_CIRCLE: "decimalEnclosedCircle",
633
+ DECIMAL_ENCLOSED_CIRCLE_CHINESE: "decimalEnclosedCircleChinese",
634
+ DECIMAL_ENCLOSED_FULL_STOP: "decimalEnclosedFullstop",
635
+ DECIMAL_ENCLOSED_PAREN: "decimalEnclosedParen",
636
+ DECIMAL_FULL_WIDTH: "decimalFullWidth",
637
+ DECIMAL_FULL_WIDTH_2: "decimalFullWidth2",
638
+ DECIMAL_HALF_WIDTH: "decimalHalfWidth",
639
+ DECIMAL_ZERO: "decimalZero",
640
+ DOLLAR_TEXT: "dollarText",
641
+ GANADA: "ganada",
642
+ HEBREW_1: "hebrew1",
643
+ HEBREW_2: "hebrew2",
644
+ HEX: "hex",
645
+ HINDI_CONSONANTS: "hindiConsonants",
646
+ HINDI_COUNTING: "hindiCounting",
647
+ HINDI_NUMBERS: "hindiNumbers",
648
+ HINDI_VOWELS: "hindiVowels",
649
+ IDEOGRAPH_DIGITAL: "ideographDigital",
650
+ IDEOGRAPH_ENCLOSED_CIRCLE: "ideographEnclosedCircle",
651
+ IDEOGRAPH_LEGAL_TRADITIONAL: "ideographLegalTraditional",
652
+ IDEOGRAPH_TRADITIONAL: "ideographTraditional",
653
+ IDEOGRAPH_ZODIAC: "ideographZodiac",
654
+ IDEOGRAPH_ZODIAC_TRADITIONAL: "ideographZodiacTraditional",
655
+ IROHA: "iroha",
656
+ IROHA_FULL_WIDTH: "irohaFullWidth",
657
+ JAPANESE_COUNTING: "japaneseCounting",
658
+ JAPANESE_DIGITAL_TEN_THOUSAND: "japaneseDigitalTenThousand",
659
+ JAPANESE_LEGAL: "japaneseLegal",
660
+ KOREAN_COUNTING: "koreanCounting",
661
+ KOREAN_DIGITAL: "koreanDigital",
662
+ KOREAN_DIGITAL_2: "koreanDigital2",
663
+ KOREAN_LEGAL: "koreanLegal",
664
+ LOWER_LETTER: "lowerLetter",
665
+ LOWER_ROMAN: "lowerRoman",
666
+ NONE: "none",
667
+ NUMBER_IN_DASH: "numberInDash",
668
+ ORDINAL: "ordinal",
669
+ ORDINAL_TEXT: "ordinalText",
670
+ RUSSIAN_LOWER: "russianLower",
671
+ RUSSIAN_UPPER: "russianUpper",
672
+ TAIWANESE_COUNTING: "taiwaneseCounting",
673
+ TAIWANESE_COUNTING_THOUSAND: "taiwaneseCountingThousand",
674
+ TAIWANESE_DIGITAL: "taiwaneseDigital",
675
+ THAI_COUNTING: "thaiCounting",
676
+ THAI_LETTERS: "thaiLetters",
677
+ THAI_NUMBERS: "thaiNumbers",
678
+ UPPER_LETTER: "upperLetter",
679
+ UPPER_ROMAN: "upperRoman",
680
+ VIETNAMESE_COUNTING: "vietnameseCounting"
681
+ };
682
+ /**
683
+ * XML space handling modes.
684
+ *
685
+ * @publicApi
686
+ */
687
+ const SpaceType = {
688
+ DEFAULT: "default",
689
+ PRESERVE: "preserve"
690
+ };
691
+ //#endregion
692
+ //#region src/parts/drawing/floating/floating-position.ts
693
+ /**
694
+ * Horizontal Relative Positioning.
695
+ *
696
+ * Specifies the horizontal base from which the drawing position is calculated.
697
+ *
698
+ * Reference: https://www.datypic.com/sc/ooxml/t-wp_ST_RelFromH.html
699
+ *
700
+ * ## XSD Schema
701
+ * ```xml
702
+ * <xsd:simpleType name="ST_RelFromH">
703
+ * <xsd:restriction base="xsd:token">
704
+ * <xsd:enumeration value="margin"/>
705
+ * <xsd:enumeration value="page"/>
706
+ * <xsd:enumeration value="column"/>
707
+ * <xsd:enumeration value="character"/>
708
+ * <xsd:enumeration value="leftMargin"/>
709
+ * <xsd:enumeration value="rightMargin"/>
710
+ * <xsd:enumeration value="insideMargin"/>
711
+ * <xsd:enumeration value="outsideMargin"/>
712
+ * </xsd:restriction>
713
+ * </xsd:simpleType>
714
+ * ```
715
+ *
716
+ * @publicApi
717
+ */
718
+ const HorizontalPositionRelativeFrom = {
719
+ /**
720
+ * ## Character
721
+ *
722
+ * Specifies that the horizontal positioning shall be relative to the position of the anchor within its run content.
723
+ */
724
+ CHARACTER: "character",
725
+ /**
726
+ * ## Column
727
+ *
728
+ * Specifies that the horizontal positioning shall be relative to the extents of the column which contains its anchor.
729
+ */
730
+ COLUMN: "column",
731
+ /**
732
+ * ## Inside Margin
733
+ *
734
+ * Specifies that the horizontal positioning shall be relative to the inside margin of the current page (the left margin on odd pages, right on even pages).
735
+ */
736
+ INSIDE_MARGIN: "insideMargin",
737
+ /**
738
+ * ## Left Margin
739
+ *
740
+ * Specifies that the horizontal positioning shall be relative to the left margin of the page.
741
+ */
742
+ LEFT_MARGIN: "leftMargin",
743
+ /**
744
+ * ## Page Margin
745
+ *
746
+ * Specifies that the horizontal positioning shall be relative to the page margins.
747
+ */
748
+ MARGIN: "margin",
749
+ /**
750
+ * ## Outside Margin
751
+ *
752
+ * Specifies that the horizontal positioning shall be relative to the outside margin of the current page (the right margin on odd pages, left on even pages).
753
+ */
754
+ OUTSIDE_MARGIN: "outsideMargin",
755
+ /**
756
+ * ## Page Edge
757
+ *
758
+ * Specifies that the horizontal positioning shall be relative to the edge of the page.
759
+ */
760
+ PAGE: "page",
761
+ /**
762
+ * ## Right Margin
763
+ *
764
+ * Specifies that the horizontal positioning shall be relative to the right margin of the page.
765
+ */
766
+ RIGHT_MARGIN: "rightMargin"
767
+ };
768
+ /**
769
+ * Vertical Relative Positioning.
770
+ *
771
+ * Specifies the vertical base from which the drawing position is calculated.
772
+ *
773
+ * Reference: https://www.datypic.com/sc/ooxml/t-wp_ST_RelFromV.html
774
+ *
775
+ * ## XSD Schema
776
+ * ```xml
777
+ * <xsd:simpleType name="ST_RelFromV">
778
+ * <xsd:restriction base="xsd:token">
779
+ * <xsd:enumeration value="margin"/>
780
+ * <xsd:enumeration value="page"/>
781
+ * <xsd:enumeration value="paragraph"/>
782
+ * <xsd:enumeration value="line"/>
783
+ * <xsd:enumeration value="topMargin"/>
784
+ * <xsd:enumeration value="bottomMargin"/>
785
+ * <xsd:enumeration value="insideMargin"/>
786
+ * <xsd:enumeration value="outsideMargin"/>
787
+ * </xsd:restriction>
788
+ * </xsd:simpleType>
789
+ * ```
790
+ *
791
+ * @publicApi
792
+ */
793
+ const VerticalPositionRelativeFrom = {
794
+ /**
795
+ * ## Bottom Margin
796
+ *
797
+ * Specifies that the vertical positioning shall be relative to the bottom margin of the current page.
798
+ */
799
+ BOTTOM_MARGIN: "bottomMargin",
800
+ /**
801
+ * ## Inside Margin
802
+ *
803
+ * Specifies that the vertical positioning shall be relative to the inside margin of the current page.
804
+ */
805
+ INSIDE_MARGIN: "insideMargin",
806
+ /**
807
+ * ## Line
808
+ *
809
+ * Specifies that the vertical positioning shall be relative to the line containing the anchor character.
810
+ */
811
+ LINE: "line",
812
+ /**
813
+ * ## Page Margin
814
+ *
815
+ * Specifies that the vertical positioning shall be relative to the page margins.
816
+ */
817
+ MARGIN: "margin",
818
+ /**
819
+ * ## Outside Margin
820
+ *
821
+ * Specifies that the vertical positioning shall be relative to the outside margin of the current page.
822
+ */
823
+ OUTSIDE_MARGIN: "outsideMargin",
824
+ /**
825
+ * ## Page Edge
826
+ *
827
+ * Specifies that the vertical positioning shall be relative to the edge of the page.
828
+ */
829
+ PAGE: "page",
830
+ /**
831
+ * ## Paragraph
832
+ *
833
+ * Specifies that the vertical positioning shall be relative to the paragraph which contains the drawing anchor.
834
+ */
835
+ PARAGRAPH: "paragraph",
836
+ /**
837
+ * ## Top Margin
838
+ *
839
+ * Specifies that the vertical positioning shall be relative to the top margin of the current page.
840
+ */
841
+ TOP_MARGIN: "topMargin"
842
+ };
843
+ //#endregion
844
+ //#region src/parts/drawing/floating/horizontal-position.ts
845
+ /**
846
+ * Horizontal position module for floating drawings in WordprocessingML documents.
847
+ *
848
+ * This module provides horizontal positioning for floating drawing objects,
849
+ * specifying the horizontal placement relative to a base element.
850
+ *
851
+ * Reference: http://officeopenxml.com/drwPicFloating-position.php
852
+ *
853
+ * @module
854
+ */
855
+ /**
856
+ * Creates a horizontal position element for floating drawings.
857
+ *
858
+ * The positionH element specifies the horizontal positioning of a floating
859
+ * object relative to a base element (page, margin, column, etc.).
860
+ *
861
+ * Reference: https://www.datypic.com/sc/ooxml/e-wp_positionH-1.html
862
+ *
863
+ * ## XSD Schema
864
+ * ```xml
865
+ * <xsd:complexType name="CT_PosH">
866
+ * <xsd:choice>
867
+ * <xsd:element name="align" type="ST_AlignH"/>
868
+ * <xsd:element name="posOffset" type="ST_PositionOffset"/>
869
+ * </xsd:choice>
870
+ * <xsd:attribute name="relativeFrom" type="ST_RelFromH" use="required"/>
871
+ * </xsd:complexType>
872
+ * ```
873
+ *
874
+ * @param options - Horizontal position configuration
875
+ * @returns The positionH XML string
876
+ *
877
+ * @example
878
+ * ```typescript
879
+ * // Align to the left of the page
880
+ * createHorizontalPosition({
881
+ * relative: HorizontalPositionRelativeFrom.PAGE,
882
+ * align: HorizontalPositionAlign.LEFT,
883
+ * });
884
+ *
885
+ * // Offset from the margin
886
+ * createHorizontalPosition({
887
+ * relative: HorizontalPositionRelativeFrom.MARGIN,
888
+ * offset: 914400, // 1 inch in EMUs
889
+ * });
890
+ * ```
891
+ */
892
+ const createHorizontalPosition = ({ relative, align, offset }) => {
893
+ const child = align ? `<wp:align>${align}</wp:align>` : offset !== void 0 ? `<wp:posOffset>${offset}</wp:posOffset>` : `<wp:align>${HorizontalPositionAlign.LEFT}</wp:align>`;
894
+ return element("wp:positionH", { relativeFrom: relative ?? HorizontalPositionRelativeFrom.PAGE }, [child]);
895
+ };
896
+ //#endregion
897
+ //#region src/parts/drawing/floating/vertical-position.ts
898
+ /**
899
+ * Vertical position module for floating drawings in WordprocessingML documents.
900
+ *
901
+ * This module provides vertical positioning for floating drawing objects,
902
+ * specifying the vertical placement relative to a base element.
903
+ *
904
+ * Reference: http://officeopenxml.com/drwPicFloating-position.php
905
+ *
906
+ * @module
907
+ */
908
+ /**
909
+ * Creates a vertical position element for floating drawings.
910
+ *
911
+ * The positionV element specifies the vertical positioning of a floating
912
+ * object relative to a base element (page, margin, paragraph, line, etc.).
913
+ *
914
+ * Reference: https://www.datypic.com/sc/ooxml/e-wp_positionV-1.html
915
+ *
916
+ * ## XSD Schema
917
+ * ```xml
918
+ * <xsd:complexType name="CT_PosV">
919
+ * <xsd:choice>
920
+ * <xsd:element name="align" type="ST_AlignV"/>
921
+ * <xsd:element name="posOffset" type="ST_PositionOffset"/>
922
+ * </xsd:choice>
923
+ * <xsd:attribute name="relativeFrom" type="ST_RelFromV" use="required"/>
924
+ * </xsd:complexType>
925
+ * ```
926
+ *
927
+ * @param options - Vertical position configuration
928
+ * @returns The positionV XML string
929
+ *
930
+ * @example
931
+ * ```typescript
932
+ * // Align to the top of the page
933
+ * createVerticalPosition({
934
+ * relative: VerticalPositionRelativeFrom.PAGE,
935
+ * align: VerticalPositionAlign.TOP,
936
+ * });
937
+ *
938
+ * // Offset from the paragraph
939
+ * createVerticalPosition({
940
+ * relative: VerticalPositionRelativeFrom.PARAGRAPH,
941
+ * offset: 457200, // 0.5 inch in EMUs
942
+ * });
943
+ * ```
944
+ */
945
+ const createVerticalPosition = ({ relative, align, offset }) => {
946
+ const child = align ? `<wp:align>${align}</wp:align>` : offset !== void 0 ? `<wp:posOffset>${offset}</wp:posOffset>` : `<wp:align>${VerticalPositionAlign.TOP}</wp:align>`;
947
+ return element("wp:positionV", { relativeFrom: relative ?? VerticalPositionRelativeFrom.PAGE }, [child]);
948
+ };
949
+ //#endregion
950
+ //#region src/parts/drawing/drawing-parse.ts
951
+ /**
952
+ * Drawing parser for DOCX documents.
953
+ *
954
+ * Parses w:drawing elements and extracts image, chart, or SmartArt data.
955
+ *
956
+ * @module
957
+ */
958
+ /**
959
+ * Parse a w:drawing element and dispatch to the correct parser
960
+ * based on the graphicData URI.
961
+ */
962
+ function parseDrawingRun(el, ctx) {
963
+ const graphicData = findDeep(el, "a:graphicData")[0];
964
+ if (!graphicData) return void 0;
965
+ const uri = attr(graphicData, "uri") ?? "";
966
+ if (uri.includes("/chart")) return parseChartDrawing(el, ctx);
967
+ if (uri.includes("/diagram")) return parseSmartArtDrawing(el, ctx);
968
+ return parseImageRun(el, ctx);
969
+ }
970
+ /**
971
+ * Determine image type from file extension or MIME type.
972
+ */
973
+ function imageTypeFromPath(path) {
974
+ switch (path.split(".").pop()?.toLowerCase() ?? "") {
975
+ case "jpg":
976
+ case "jpeg": return "jpg";
977
+ case "png": return "png";
978
+ case "gif": return "gif";
979
+ case "bmp": return "bmp";
980
+ case "tif":
981
+ case "tiff": return "tif";
982
+ case "ico": return "ico";
983
+ case "emf": return "emf";
984
+ case "wmf": return "wmf";
985
+ default: return "png";
986
+ }
987
+ }
988
+ /**
989
+ * Parse a w:drawing element and return image data wrapped in { image: ... }.
990
+ */
991
+ function parseImageRun(el, ctx) {
992
+ const inline = findDeep(el, "wp:inline")[0];
993
+ const anchor = inline ? void 0 : findDeep(el, "wp:anchor")[0];
994
+ const parent = inline ?? anchor;
995
+ if (!parent) return void 0;
996
+ const extent = findChild(parent, "wp:extent");
997
+ let width;
998
+ let height;
999
+ if (extent) {
1000
+ const cxEmu = attrNum(extent, "cx");
1001
+ const cyEmu = attrNum(extent, "cy");
1002
+ if (cxEmu !== void 0) width = convertEmuToPixels(cxEmu);
1003
+ if (cyEmu !== void 0) height = convertEmuToPixels(cyEmu);
1004
+ }
1005
+ const blip = findDeep(parent, "a:blip")[0];
1006
+ if (!blip) return void 0;
1007
+ const rEmbed = attr(blip, "r:embed");
1008
+ if (!rEmbed) return void 0;
1009
+ const mediaPath = ctx.docx.partRefs.media.get(rEmbed);
1010
+ if (!mediaPath) return void 0;
1011
+ const imageData = ctx.docx.doc.getRaw(mediaPath);
1012
+ if (!imageData) return void 0;
1013
+ const imageOpts = {
1014
+ type: imageTypeFromPath(mediaPath),
1015
+ data: imageData,
1016
+ transformation: {
1017
+ ...width !== void 0 ? { width } : {},
1018
+ ...height !== void 0 ? { height } : {}
1019
+ }
1020
+ };
1021
+ const docPr = findChild(parent, "wp:docPr");
1022
+ if (docPr) {
1023
+ const name = attr(docPr, "name");
1024
+ const descr = attr(docPr, "descr");
1025
+ const title = attr(docPr, "title");
1026
+ if (name || descr || title) imageOpts.altText = {
1027
+ ...name ? { name } : {},
1028
+ ...descr ? { description: descr } : {},
1029
+ ...title ? { title } : {}
1030
+ };
1031
+ }
1032
+ if (anchor && !inline) {
1033
+ const floating = {};
1034
+ const posH = findChild(anchor, "wp:positionH");
1035
+ if (posH) {
1036
+ const align = findChild(posH, "wp:align");
1037
+ const posOffset = findChild(posH, "wp:posOffset");
1038
+ if (align) floating.horizontalPosition = { align: textOf(align) };
1039
+ else if (posOffset) {
1040
+ const val = Number(textOf(posOffset));
1041
+ if (!isNaN(val)) floating.horizontalPosition = { offset: val };
1042
+ }
1043
+ }
1044
+ const posV = findChild(anchor, "wp:positionV");
1045
+ if (posV) {
1046
+ const align = findChild(posV, "wp:align");
1047
+ const posOffset = findChild(posV, "wp:posOffset");
1048
+ if (align) floating.verticalPosition = { align: textOf(align) };
1049
+ else if (posOffset) {
1050
+ const val = Number(textOf(posOffset));
1051
+ if (!isNaN(val)) floating.verticalPosition = { offset: val };
1052
+ }
1053
+ }
1054
+ for (const wrapType of [
1055
+ "wrapSquare",
1056
+ "wrapTight",
1057
+ "wrapTopAndBottom",
1058
+ "wrapNone"
1059
+ ]) if (findChild(anchor, `wp:${wrapType}`)) {
1060
+ floating.wrap = wrapType;
1061
+ break;
1062
+ }
1063
+ if (attrBool(anchor, "behindDoc")) floating.behindDocument = true;
1064
+ if (Object.keys(floating).length > 0) imageOpts.floating = floating;
1065
+ }
1066
+ return { image: imageOpts };
1067
+ }
1068
+ function getDrawingExtent(el) {
1069
+ const inline = findDeep(el, "wp:inline")[0];
1070
+ const anchor = inline ? void 0 : findDeep(el, "wp:anchor")[0];
1071
+ const parent = inline ?? anchor;
1072
+ if (!parent) return {};
1073
+ const extent = findChild(parent, "wp:extent");
1074
+ if (!extent) return {};
1075
+ const cxEmu = attrNum(extent, "cx");
1076
+ const cyEmu = attrNum(extent, "cy");
1077
+ return {
1078
+ ...cxEmu !== void 0 ? { width: convertEmuToPixels(cxEmu) } : {},
1079
+ ...cyEmu !== void 0 ? { height: convertEmuToPixels(cyEmu) } : {}
1080
+ };
1081
+ }
1082
+ /**
1083
+ * Look up a relationship ID in a map, with fallback for double "rId" prefix
1084
+ * that the library's generation code produces (e.g. "rIdrId7" → "rId7").
1085
+ */
1086
+ function lookupRId(map, rId) {
1087
+ if (!rId) return void 0;
1088
+ const direct = map.get(rId);
1089
+ if (direct) return direct;
1090
+ if (rId.startsWith("rIdrId")) return map.get(rId.slice(3));
1091
+ }
1092
+ function parseChartDrawing(el, ctx) {
1093
+ const chartRef = findDeep(el, "c:chart")[0];
1094
+ if (!chartRef) return void 0;
1095
+ const rId = attr(chartRef, "r:id");
1096
+ const chartPath = lookupRId(ctx.docx.partRefs.charts, rId);
1097
+ if (!chartPath) return void 0;
1098
+ const chartXml = ctx.docx.doc.get(chartPath);
1099
+ if (!chartXml) return void 0;
1100
+ const opts = parseChartXml(chartXml);
1101
+ if (!opts) return void 0;
1102
+ const ext = getDrawingExtent(el);
1103
+ if (ext.width !== void 0 || ext.height !== void 0) opts.transformation = { ...ext };
1104
+ return { chart: opts };
1105
+ }
1106
+ /**
1107
+ * Parse c:chartSpace element into ChartOptions.
1108
+ */
1109
+ function parseChartXml(el) {
1110
+ const chart = findChild(el, "c:chart");
1111
+ if (!chart) return void 0;
1112
+ const opts = {};
1113
+ const titleEl = findChild(chart, "c:title");
1114
+ if (titleEl) {
1115
+ const rich = findDeep(titleEl, "c:rich")[0];
1116
+ if (rich) {
1117
+ const t = findDeep(rich, "a:t")[0];
1118
+ if (t) {
1119
+ const title = textOf(t);
1120
+ if (title) opts.title = title;
1121
+ }
1122
+ }
1123
+ }
1124
+ const plotArea = findChild(chart, "c:plotArea");
1125
+ if (!plotArea) return void 0;
1126
+ let chartType;
1127
+ let typeElement;
1128
+ for (const child of plotArea.elements ?? []) {
1129
+ switch (child.name) {
1130
+ case "c:barChart": {
1131
+ const barDir = findChild(child, "c:barDir");
1132
+ chartType = barDir && attr(barDir, "val") === "bar" ? "bar" : "column";
1133
+ typeElement = child;
1134
+ break;
1135
+ }
1136
+ case "c:lineChart":
1137
+ chartType = "line";
1138
+ typeElement = child;
1139
+ break;
1140
+ case "c:pieChart":
1141
+ chartType = "pie";
1142
+ typeElement = child;
1143
+ break;
1144
+ case "c:areaChart":
1145
+ chartType = "area";
1146
+ typeElement = child;
1147
+ break;
1148
+ case "c:scatterChart":
1149
+ chartType = "scatter";
1150
+ typeElement = child;
1151
+ break;
1152
+ }
1153
+ if (chartType) break;
1154
+ }
1155
+ if (!chartType || !typeElement) return void 0;
1156
+ opts.type = chartType;
1157
+ const series = [];
1158
+ let categories;
1159
+ for (const serEl of typeElement.elements ?? []) {
1160
+ if (serEl.name !== "c:ser") continue;
1161
+ const nameParts = extractStrCache(serEl, "c:tx");
1162
+ const cats = extractStrCache(serEl, "c:cat");
1163
+ if (cats.length > 0 && !categories) categories = cats;
1164
+ const vals = extractNumCache(serEl);
1165
+ series.push({
1166
+ name: nameParts[0] ?? "",
1167
+ values: vals
1168
+ });
1169
+ }
1170
+ opts.categories = categories ?? [];
1171
+ opts.series = series;
1172
+ opts.showLegend = findChild(chart, "c:legend") !== void 0;
1173
+ const styleEl = findChild(el, "c:style");
1174
+ if (styleEl) {
1175
+ const val = attrNum(styleEl, "val");
1176
+ if (val !== void 0) opts.style = val;
1177
+ }
1178
+ return opts;
1179
+ }
1180
+ /**
1181
+ * Extract string values from c:strCache within a container element.
1182
+ */
1183
+ function extractStrCache(parent, containerName) {
1184
+ const container = findChild(parent, containerName);
1185
+ if (!container) return [];
1186
+ const cache = findDeep(container, "c:strCache")[0];
1187
+ if (!cache) return [];
1188
+ const values = [];
1189
+ for (const pt of cache.elements ?? []) {
1190
+ if (pt.name !== "c:pt") continue;
1191
+ const v = findChild(pt, "c:v");
1192
+ if (v) values.push(textOf(v) ?? "");
1193
+ }
1194
+ return values;
1195
+ }
1196
+ /**
1197
+ * Extract numeric values from c:numCache within a c:val container.
1198
+ */
1199
+ function extractNumCache(parent) {
1200
+ const valEl = findChild(parent, "c:val");
1201
+ if (!valEl) return [];
1202
+ const cache = findDeep(valEl, "c:numCache")[0];
1203
+ if (!cache) return [];
1204
+ const values = [];
1205
+ for (const pt of cache.elements ?? []) {
1206
+ if (pt.name !== "c:pt") continue;
1207
+ const v = findChild(pt, "c:v");
1208
+ if (v) {
1209
+ const num = Number(textOf(v));
1210
+ if (!isNaN(num)) values.push(num);
1211
+ }
1212
+ }
1213
+ return values;
1214
+ }
1215
+ function parseSmartArtDrawing(el, ctx) {
1216
+ const relIds = findDeep(el, "dgm:relIds")[0];
1217
+ if (!relIds) return void 0;
1218
+ const rId = attr(relIds, "r:dm");
1219
+ const dataPath = lookupRId(ctx.docx.partRefs.diagramData, rId);
1220
+ if (!dataPath) return void 0;
1221
+ const dataEl = ctx.docx.doc.get(dataPath);
1222
+ if (!dataEl) return void 0;
1223
+ const opts = parseSmartArtDataXml(dataEl);
1224
+ if (!opts) return void 0;
1225
+ const ext = getDrawingExtent(el);
1226
+ if (ext.width !== void 0 || ext.height !== void 0) opts.transformation = { ...ext };
1227
+ return { smartArt: opts };
1228
+ }
1229
+ /**
1230
+ * Parse dgm:dataModel element into SmartArtOptions.
1231
+ */
1232
+ function parseSmartArtDataXml(el) {
1233
+ const ptLst = findChild(el, "dgm:ptLst");
1234
+ if (!ptLst) return void 0;
1235
+ const opts = {};
1236
+ const nodeMap = /* @__PURE__ */ new Map();
1237
+ for (const pt of ptLst.elements ?? []) {
1238
+ if (pt.name !== "dgm:pt") continue;
1239
+ const type = attr(pt, "type");
1240
+ const modelId = attr(pt, "modelId");
1241
+ if (type === "doc") {
1242
+ const prSet = findChild(pt, "dgm:prSet");
1243
+ if (prSet) {
1244
+ const loTypeId = attr(prSet, "loTypeId") ?? "";
1245
+ const qsTypeId = attr(prSet, "qsTypeId") ?? "";
1246
+ const csTypeId = attr(prSet, "csTypeId") ?? "";
1247
+ const layout = loTypeId.split("/").pop();
1248
+ if (layout) opts.layout = layout;
1249
+ const style = qsTypeId.split("/").pop();
1250
+ if (style) opts.style = style;
1251
+ const color = csTypeId.split("/").pop();
1252
+ if (color) opts.color = color;
1253
+ }
1254
+ } else if (type === "node" && modelId) {
1255
+ const t = findDeep(pt, "a:t")[0];
1256
+ nodeMap.set(modelId, t ? textOf(t) ?? "" : "");
1257
+ }
1258
+ }
1259
+ const cxnLst = findChild(el, "dgm:cxnLst");
1260
+ if (!cxnLst) {
1261
+ opts.data = { nodes: [] };
1262
+ return opts;
1263
+ }
1264
+ const childrenMap = /* @__PURE__ */ new Map();
1265
+ for (const cxn of cxnLst.elements ?? []) {
1266
+ if (cxn.name !== "dgm:cxn") continue;
1267
+ const srcId = attr(cxn, "srcId");
1268
+ const destId = attr(cxn, "destId");
1269
+ if (!srcId || !destId || !nodeMap.has(destId)) continue;
1270
+ let arr = childrenMap.get(srcId);
1271
+ if (!arr) {
1272
+ arr = [];
1273
+ childrenMap.set(srcId, arr);
1274
+ }
1275
+ arr.push(destId);
1276
+ }
1277
+ opts.data = { nodes: (childrenMap.get("0") ?? []).map((id) => buildSmartArtNode(id, nodeMap, childrenMap)) };
1278
+ return opts;
1279
+ }
1280
+ function buildSmartArtNode(id, nodeMap, childrenMap) {
1281
+ const text = nodeMap.get(id) ?? "";
1282
+ const childIds = childrenMap.get(id) ?? [];
1283
+ if (childIds.length === 0) return { text };
1284
+ return {
1285
+ text,
1286
+ children: childIds.map((cid) => buildSmartArtNode(cid, nodeMap, childrenMap))
1287
+ };
1288
+ }
1289
+ //#endregion
1290
+ //#region src/parts/drawing/descriptor.ts
1291
+ /**
1292
+ * Drawing descriptor for DOCX documents.
1293
+ *
1294
+ * Produces `<w:drawing>` XML directly from media data and options,
1295
+ * eliminating the Drawing/Inline/Anchor/Graphic/GraphicData/Pic XmlComponent
1296
+ * class chain (~10 instances per drawing in the old path).
1297
+ *
1298
+ * Common path (inline image/chart/smartart without advanced properties):
1299
+ * zero XmlComponent instances — pure string concatenation.
1300
+ *
1301
+ * Advanced properties (outline, fill, effects on images) and floating
1302
+ * positioning use core `create*()` + `.toXml({stack:[]})` for sub-elements
1303
+ * (lightweight BuilderElement instances, not deep hierarchies).
1304
+ *
1305
+ * Reference: ISO/IEC 29500-4, wml.xsd, CT_Drawing
1306
+ *
1307
+ * @module
1308
+ */
1309
+ const NOOP_CTX = {
1310
+ addRelationship: () => "",
1311
+ addMedia: () => ""
1312
+ };
1313
+ let _docPropsIdGen = uniqueNumericIdCreator();
1314
+ /** Reset the doc properties ID generator (for testing). */
1315
+ const resetDrawingIdGen = () => {
1316
+ _docPropsIdGen = uniqueNumericIdCreator();
1317
+ };
1318
+ const GRAPHIC_NS = "xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\"";
1319
+ const PIC_URI = "http://schemas.openxmlformats.org/drawingml/2006/picture";
1320
+ const CHART_URI = "http://schemas.openxmlformats.org/drawingml/2006/chart";
1321
+ const DGM_URI = "http://schemas.openxmlformats.org/drawingml/2006/diagram";
1322
+ const WPS_URI = "http://schemas.microsoft.com/office/word/2010/wordprocessingShape";
1323
+ const WPG_URI = "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup";
1324
+ const HYPERLINK_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
1325
+ function registerHyperlinks(hyperlink, ctx) {
1326
+ if (!hyperlink) return {};
1327
+ const result = {};
1328
+ if (hyperlink.click) {
1329
+ const linkId = uniqueId();
1330
+ ctx.viewWrapper.relationships.addRelationship(linkId, HYPERLINK_REL, hyperlink.click, TargetModeType.EXTERNAL);
1331
+ result.clickId = `rId${linkId}`;
1332
+ }
1333
+ if (hyperlink.hover) {
1334
+ const linkId = uniqueId();
1335
+ ctx.viewWrapper.relationships.addRelationship(linkId, HYPERLINK_REL, hyperlink.hover, TargetModeType.EXTERNAL);
1336
+ result.hoverId = `rId${linkId}`;
1337
+ }
1338
+ return result;
1339
+ }
1340
+ function buildHyperlinkChildren(ids) {
1341
+ const parts = [];
1342
+ const aNs = "xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\"";
1343
+ if (ids.clickId) parts.push(`<a:hlinkClick r:id="${ids.clickId}" ${aNs}/>`);
1344
+ if (ids.hoverId) parts.push(`<a:hlinkHover r:id="${ids.hoverId}" ${aNs}/>`);
1345
+ return parts.join("");
1346
+ }
1347
+ function stringifyDocPr(opts, hlIds) {
1348
+ const id = opts?.id ?? _docPropsIdGen();
1349
+ const name = opts?.name ?? "";
1350
+ const attrs = [`id="${id}"`, `name="${escapeXml(name)}"`];
1351
+ if (opts?.description != null && opts.description !== void 0) attrs.push(`descr="${escapeXml(opts.description)}"`);
1352
+ if (opts?.title != null && opts.title !== void 0) attrs.push(`title="${escapeXml(opts.title)}"`);
1353
+ const hlXml = buildHyperlinkChildren(hlIds);
1354
+ if (hlXml) return `<wp:docPr ${attrs.join(" ")}>${hlXml}</wp:docPr>`;
1355
+ return `<wp:docPr ${attrs.join(" ")}/>`;
1356
+ }
1357
+ function stringifyBlipFill(mediaData, blipEffects, tile) {
1358
+ const fileName = mediaData.type === "svg" && "fallback" in mediaData ? mediaData.fallback.fileName : mediaData.fileName;
1359
+ const parts = [];
1360
+ const blipAttrs = [`r:embed="{${escapeXml(fileName)}}"`, "cstate=\"none\""];
1361
+ const blipContent = (mediaData.type === "svg" ? `<a:extLst><a:ext uri="{96DAC541-7B7A-43D3-8B79-37D633B846F1}"><asvg:svgBlip xmlns:asvg="http://schemas.microsoft.com/office/drawing/2016/SVG/main" r:embed="{${escapeXml(mediaData.fileName)}}"/></a:ext></a:extLst>` : "") + (blipEffects ? buildBlipEffectsXml(blipEffects) : "");
1362
+ if (blipContent) parts.push(`<a:blip ${blipAttrs.join(" ")}>${blipContent}</a:blip>`);
1363
+ else parts.push(`<a:blip ${blipAttrs.join(" ")}/>`);
1364
+ if (mediaData.srcRect) {
1365
+ const srAttrs = [];
1366
+ if (mediaData.srcRect.left !== void 0) srAttrs.push(`l="${mediaData.srcRect.left}"`);
1367
+ if (mediaData.srcRect.top !== void 0) srAttrs.push(`t="${mediaData.srcRect.top}"`);
1368
+ if (mediaData.srcRect.right !== void 0) srAttrs.push(`r="${mediaData.srcRect.right}"`);
1369
+ if (mediaData.srcRect.bottom !== void 0) srAttrs.push(`b="${mediaData.srcRect.bottom}"`);
1370
+ if (srAttrs.length) parts.push(`<a:srcRect ${srAttrs.join(" ")}/>`);
1371
+ }
1372
+ if (tile) {
1373
+ const tileAttrs = [];
1374
+ if (tile.tx !== void 0) tileAttrs.push(`tx="${tile.tx}"`);
1375
+ if (tile.ty !== void 0) tileAttrs.push(`ty="${tile.ty}"`);
1376
+ if (tile.sx !== void 0) tileAttrs.push(`sx="${tile.sx}"`);
1377
+ if (tile.sy !== void 0) tileAttrs.push(`sy="${tile.sy}"`);
1378
+ const tileAttrStr = tileAttrs.length ? " " + tileAttrs.join(" ") : "";
1379
+ parts.push(`<a:tile${tileAttrStr}/>`);
1380
+ } else parts.push("<a:stretch><a:fillRect/></a:stretch>");
1381
+ return `<pic:blipFill>${parts.join("")}</pic:blipFill>`;
1382
+ }
1383
+ function buildBlipEffectsXml(opts) {
1384
+ const parts = [];
1385
+ if (opts.grayscale) parts.push("<a:grayscl/>");
1386
+ if (opts.luminance) {
1387
+ const a = [];
1388
+ if (opts.luminance.bright !== void 0) a.push(`bright="${opts.luminance.bright}%"`);
1389
+ if (opts.luminance.contrast !== void 0) a.push(`contrast="${opts.luminance.contrast}%"`);
1390
+ parts.push(`<a:lum${a.length ? " " + a.join(" ") : ""}/>`);
1391
+ }
1392
+ if (opts.biLevel) parts.push(`<a:biLevel thresh="${opts.biLevel.threshold}%"/>`);
1393
+ if (opts.blur) {
1394
+ const a = [];
1395
+ if (opts.blur.radius !== void 0) a.push(`rad="${opts.blur.radius}"`);
1396
+ if (opts.blur.grow === false) a.push("grow=\"0\"");
1397
+ parts.push(`<a:blur${a.length ? " " + a.join(" ") : ""}/>`);
1398
+ }
1399
+ return parts.join("");
1400
+ }
1401
+ function stringifyShapeProps(transform, outline, fill, effects) {
1402
+ const parts = [];
1403
+ parts.push(transform2DDesc.stringify({
1404
+ x: transform.offset?.emus?.x ?? 0,
1405
+ y: transform.offset?.emus?.y ?? 0,
1406
+ width: transform.emus.x,
1407
+ height: transform.emus.y,
1408
+ flipHorizontal: transform.flip?.horizontal,
1409
+ flipVertical: transform.flip?.vertical,
1410
+ rotation: transform.rotation
1411
+ }, NOOP_CTX) ?? "");
1412
+ parts.push("<a:prstGeom prst=\"rect\"><a:avLst/></a:prstGeom>");
1413
+ if (fill) parts.push(fillDesc.stringify(fill, NOOP_CTX) ?? "");
1414
+ if (outline) parts.push(outlineDesc.stringify(outline, NOOP_CTX) ?? "");
1415
+ if (effects) parts.push(effectListDesc.stringify(effects, NOOP_CTX) ?? "");
1416
+ return `<pic:spPr bwMode="auto">${parts.join("")}</pic:spPr>`;
1417
+ }
1418
+ function stringifyNvPicPr(hlIds) {
1419
+ const hlXml = buildHyperlinkChildren(hlIds);
1420
+ return `<pic:nvPicPr><pic:cNvPr id="0" name="" descr=""${hlXml ? `>${hlXml}</pic:cNvPr>` : "/>"}<pic:cNvPicPr preferRelativeResize="1"><a:picLocks noChangeArrowheads="1" noChangeAspect="1"/></pic:cNvPicPr></pic:nvPicPr>`;
1421
+ }
1422
+ function stringifyGroupTransform2D(transform, chOff, chExt) {
1423
+ const attrs = [];
1424
+ if (transform.flip?.horizontal !== void 0) attrs.push(`flipH="${transform.flip.horizontal}"`);
1425
+ if (transform.flip?.vertical !== void 0) attrs.push(`flipV="${transform.flip.vertical}"`);
1426
+ if (transform.rotation !== void 0) attrs.push(`rot="${transform.rotation}"`);
1427
+ return `<a:xfrm${attrs.length ? " " + attrs.join(" ") : ""}>${`<a:off x="${transform.offset?.emus?.x ?? 0}" y="${transform.offset?.emus?.y ?? 0}"/>`}${`<a:ext cx="${transform.emus.x}" cy="${transform.emus.y}"/>`}${chOff ? `<a:chOff x="${chOff.x}" y="${chOff.y}"/>` : ""}${chExt ? `<a:chExt cx="${chExt.cx}" cy="${chExt.cy}"/>` : ""}</a:xfrm>`;
1428
+ }
1429
+ function stringifyWpsShape(opts, ctx) {
1430
+ const transform = opts.transformation;
1431
+ const spPrParts = [];
1432
+ spPrParts.push(transform2DDesc.stringify({
1433
+ x: transform.offset?.emus?.x ?? 0,
1434
+ y: transform.offset?.emus?.y ?? 0,
1435
+ width: transform.emus.x,
1436
+ height: transform.emus.y,
1437
+ flipHorizontal: transform.flip?.horizontal,
1438
+ flipVertical: transform.flip?.vertical,
1439
+ rotation: transform.rotation
1440
+ }, NOOP_CTX) ?? "");
1441
+ if (opts.customGeometry) spPrParts.push(customGeometryDesc.stringify(opts.customGeometry, NOOP_CTX) ?? "");
1442
+ else spPrParts.push("<a:prstGeom prst=\"rect\"><a:avLst/></a:prstGeom>");
1443
+ if (opts.fill) spPrParts.push(fillDesc.stringify(opts.fill, NOOP_CTX) ?? "");
1444
+ if (opts.outline) spPrParts.push(outlineDesc.stringify(opts.outline, NOOP_CTX) ?? "");
1445
+ if (opts.effectDag) spPrParts.push(createEffectDag(opts.effectDag));
1446
+ else if (opts.effects) spPrParts.push(effectListDesc.stringify(opts.effects, NOOP_CTX) ?? "");
1447
+ if (opts.scene3d) spPrParts.push(scene3DDesc.stringify(opts.scene3d, NOOP_CTX) ?? "");
1448
+ if (opts.shape3d) spPrParts.push(shape3DDesc.stringify(opts.shape3d, NOOP_CTX) ?? "");
1449
+ const cNvSpPr = opts.nonVisualProperties ? stringifyNonVisualShapeProperties(opts.nonVisualProperties) : "<wps:cNvSpPr txBox=\"1\"/>";
1450
+ const childXml = opts.children?.map((c) => stringifyParagraphInline(c, ctx)).join("") ?? "";
1451
+ return "<wps:wsp>" + cNvSpPr + `<wps:spPr bwMode="auto">${spPrParts.join("")}</wps:spPr><wps:txbx><wps:txbxContent>${childXml}</wps:txbxContent></wps:txbx>` + stringifyBodyPr(opts.bodyProperties) + "</wps:wsp>";
1452
+ }
1453
+ function stringifyNonVisualShapeProperties(opts) {
1454
+ if (!opts.txBox) return "<wps:cNvSpPr/>";
1455
+ return `<wps:cNvSpPr txBox="${opts.txBox}"/>`;
1456
+ }
1457
+ function stringifyBodyPr(opts) {
1458
+ if (!opts) return "<wps:bodyPr/>";
1459
+ const attrs = [];
1460
+ if (opts.anchor !== void 0) attrs.push(`anchor="${opts.anchor}"`);
1461
+ if (opts.vert !== void 0) attrs.push(`vert="${opts.vert}"`);
1462
+ if (opts.wrap !== void 0) attrs.push(`wrap="${opts.wrap}"`);
1463
+ if (opts.lIns !== void 0) attrs.push(`lIns="${opts.lIns}"`);
1464
+ if (opts.tIns !== void 0) attrs.push(`tIns="${opts.tIns}"`);
1465
+ if (opts.rIns !== void 0) attrs.push(`rIns="${opts.rIns}"`);
1466
+ if (opts.bIns !== void 0) attrs.push(`bIns="${opts.bIns}"`);
1467
+ if (opts.numCol !== void 0) attrs.push(`numCol="${opts.numCol}"`);
1468
+ if (opts.rotation !== void 0) attrs.push(`rot="${opts.rotation}"`);
1469
+ const attrStr = attrs.length ? " " + attrs.join(" ") : "";
1470
+ const parts = [];
1471
+ if (opts.normAutofit) {
1472
+ const afAttrs = [];
1473
+ if (opts.normAutofit.fontScale !== void 0) afAttrs.push(`fontScale="${opts.normAutofit.fontScale}"`);
1474
+ if (opts.normAutofit.lnSpcReduction !== void 0) afAttrs.push(`lnSpcReduction="${opts.normAutofit.lnSpcReduction}"`);
1475
+ parts.push(`<a:normAutofit ${afAttrs.join(" ")}/>`);
1476
+ }
1477
+ const body = parts.join("");
1478
+ return body ? `<wps:bodyPr${attrStr}>${body}</wps:bodyPr>` : `<wps:bodyPr${attrStr}/>`;
1479
+ }
1480
+ function stringifyWpgGroup(opts, ctx) {
1481
+ const transform = opts.transformation;
1482
+ const grpSpPrParts = [];
1483
+ grpSpPrParts.push(stringifyGroupTransform2D(transform, opts.chOff, opts.chExt));
1484
+ if (opts.fill) grpSpPrParts.push(fillDesc.stringify(opts.fill, NOOP_CTX) ?? "");
1485
+ if (opts.effects) grpSpPrParts.push(effectListDesc.stringify(opts.effects, NOOP_CTX) ?? "");
1486
+ const childXml = opts.children.map((child) => {
1487
+ if (child.type === "wps") {
1488
+ const wpsData = child;
1489
+ return stringifyWpsShape({
1490
+ ...wpsData.data,
1491
+ outline: wpsData.outline ?? wpsData.data.outline,
1492
+ fill: wpsData.fill ?? wpsData.data.fill,
1493
+ transformation: wpsData.transformation
1494
+ }, ctx);
1495
+ }
1496
+ const picData = child;
1497
+ const picParts = [];
1498
+ picParts.push("<pic:nvPicPr><pic:cNvPr id=\"0\" name=\"\" descr=\"\"/><pic:cNvPicPr preferRelativeResize=\"1\"><a:picLocks noChangeAspect=\"1\"/></pic:cNvPicPr></pic:nvPicPr>");
1499
+ picParts.push(`<pic:blipFill><a:blip r:embed="{${picData.fileName}}" cstate="none"/><a:stretch><a:fillRect/></a:stretch></pic:blipFill>`);
1500
+ picParts.push(`<pic:spPr bwMode="auto">${transform2DDesc.stringify({
1501
+ x: picData.transformation.offset?.emus?.x ?? 0,
1502
+ y: picData.transformation.offset?.emus?.y ?? 0,
1503
+ width: picData.transformation.emus.x,
1504
+ height: picData.transformation.emus.y
1505
+ }, NOOP_CTX) ?? "<a:xfrm/>"}<a:prstGeom prst="rect"><a:avLst/></a:prstGeom></pic:spPr>`);
1506
+ return `<pic:pic xmlns:pic="${PIC_URI}">${picParts.join("")}</pic:pic>`;
1507
+ }).join("");
1508
+ return `<wpg:wgp><wpg:cNvGrpSpPr/><wpg:grpSpPr>${grpSpPrParts.join("")}</wpg:grpSpPr>` + childXml + "</wpg:wgp>";
1509
+ }
1510
+ function stringifyGraphicDataContent(mediaData, opts, hlIds, ctx) {
1511
+ const { outline, fill, effects, blipEffects, tile } = opts;
1512
+ const transform = mediaData.transformation;
1513
+ if (mediaData.type === "chart") return `<a:graphicData uri="${CHART_URI}"><c:chart xmlns:c="${CHART_URI}" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:id="{chart:${mediaData.chartKey}}"/></a:graphicData>`;
1514
+ if (mediaData.type === "smartart") {
1515
+ const md = mediaData;
1516
+ return `<a:graphicData uri="${DGM_URI}"><dgm:relIds xmlns:dgm="${DGM_URI}" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:dm="{smartart:${md.smartArtKey}}" r:lo="{smartart-lo:${md.smartArtKey}}" r:qs="{smartart-qs:${md.smartArtKey}}" r:cs="{smartart-cs:${md.smartArtKey}}"/></a:graphicData>`;
1517
+ }
1518
+ if (mediaData.type === "wps") return `<a:graphicData uri="${WPS_URI}">${stringifyWpsShape({
1519
+ ...mediaData.data,
1520
+ outline,
1521
+ fill,
1522
+ transformation: transform
1523
+ }, ctx)}</a:graphicData>`;
1524
+ if (mediaData.type === "wpg") {
1525
+ const md = mediaData;
1526
+ return `<a:graphicData uri="${WPG_URI}">${stringifyWpgGroup({
1527
+ children: md.children,
1528
+ transformation: transform,
1529
+ chOff: md.chOff,
1530
+ chExt: md.chExt,
1531
+ fill: md.fill,
1532
+ effects: md.effects
1533
+ }, ctx)}</a:graphicData>`;
1534
+ }
1535
+ const md = mediaData;
1536
+ return `<a:graphicData uri="${PIC_URI}"><pic:pic xmlns:pic="${PIC_URI}">` + stringifyNvPicPr(hlIds) + stringifyBlipFill(md, blipEffects, tile) + stringifyShapeProps(transform, outline, fill, effects) + `</pic:pic></a:graphicData>`;
1537
+ }
1538
+ function stringifyPositionH(opts) {
1539
+ return `<wp:positionH relativeFrom="${opts.relative ?? HorizontalPositionRelativeFrom.PAGE}">${opts.align ? `<wp:align>${opts.align}</wp:align>` : opts.offset !== void 0 ? `<wp:posOffset>${opts.offset}</wp:posOffset>` : "<wp:align>left</wp:align>"}</wp:positionH>`;
1540
+ }
1541
+ function stringifyPositionV(opts) {
1542
+ return `<wp:positionV relativeFrom="${opts.relative ?? VerticalPositionRelativeFrom.PAGE}">${opts.align ? `<wp:align>${opts.align}</wp:align>` : opts.offset !== void 0 ? `<wp:posOffset>${opts.offset}</wp:posOffset>` : "<wp:align>top</wp:align>"}</wp:positionV>`;
1543
+ }
1544
+ function wrapPolygonStr(cx, cy) {
1545
+ return `<wp:wrapPolygon edited="0"><wp:start x="0" y="0"/><wp:lineTo x="0" y="${-cy}"/><wp:lineTo x="${cx}" y="${-cy}"/><wp:lineTo x="${cx}" y="0"/><wp:lineTo x="0" y="0"/></wp:wrapPolygon>`;
1546
+ }
1547
+ function wrapSquareStr(textWrapping, margins) {
1548
+ const side = textWrapping.side ?? TextWrappingSide.BOTH_SIDES;
1549
+ const m = margins ?? {};
1550
+ return `<wp:wrapSquare ${[
1551
+ `wrapText="${side}"`,
1552
+ ...m.top != null ? [`distT="${m.top}"`] : [],
1553
+ ...m.bottom != null ? [`distB="${m.bottom}"`] : [],
1554
+ ...m.left != null ? [`distL="${m.left}"`] : [],
1555
+ ...m.right != null ? [`distR="${m.right}"`] : []
1556
+ ].join(" ")}/>`;
1557
+ }
1558
+ function wrapTightStr(textWrapping, margins, cx, cy) {
1559
+ const a = [`wrapText="${textWrapping.side ?? TextWrappingSide.BOTH_SIDES}"`];
1560
+ if (margins.left != null) a.push(`distL="${margins.left}"`);
1561
+ if (margins.right != null) a.push(`distR="${margins.right}"`);
1562
+ return `<wp:wrapTight ${a.join(" ")}>${wrapPolygonStr(cx, cy)}</wp:wrapTight>`;
1563
+ }
1564
+ function wrapThroughStr(textWrapping, margins, cx, cy) {
1565
+ const a = [`wrapText="${textWrapping.side ?? TextWrappingSide.BOTH_SIDES}"`];
1566
+ if (margins.left != null) a.push(`distL="${margins.left}"`);
1567
+ if (margins.right != null) a.push(`distR="${margins.right}"`);
1568
+ return `<wp:wrapThrough ${a.join(" ")}>${wrapPolygonStr(cx, cy)}</wp:wrapThrough>`;
1569
+ }
1570
+ function wrapTopAndBottomStr(margins) {
1571
+ const m = margins ?? {};
1572
+ const a = [...m.top != null ? [`distT="${m.top}"`] : [], ...m.bottom != null ? [`distB="${m.bottom}"`] : []].join(" ");
1573
+ return a ? `<wp:wrapTopAndBottom ${a}/>` : "<wp:wrapTopAndBottom/>";
1574
+ }
1575
+ function stringifyInline(opts, hlIds, ctx) {
1576
+ const { mediaData, effects, docProperties } = opts;
1577
+ const cx = mediaData.transformation.emus.x;
1578
+ const cy = mediaData.transformation.emus.y;
1579
+ const effectExtent = calculateEffectExtent(effects);
1580
+ const graphicDataXml = stringifyGraphicDataContent(mediaData, opts, hlIds, ctx);
1581
+ return `<w:drawing><wp:inline distT="0" distB="0" distL="0" distR="0"><wp:extent cx="${cx}" cy="${cy}"/><wp:effectExtent l="${effectExtent.l}" t="${effectExtent.t}" r="${effectExtent.r}" b="${effectExtent.b}"/>` + stringifyDocPr(docProperties, hlIds) + `<wp:cNvGraphicFramePr><a:graphicFrameLocks noChangeAspect="1" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"/></wp:cNvGraphicFramePr><a:graphic ${GRAPHIC_NS}>${graphicDataXml}</a:graphic></wp:inline></w:drawing>`;
1582
+ }
1583
+ function stringifyAnchor(opts, hlIds, ctx) {
1584
+ const { mediaData, floating: rawFloating, docProperties } = opts;
1585
+ const cx = mediaData.transformation.emus.x;
1586
+ const cy = mediaData.transformation.emus.y;
1587
+ const floating = {
1588
+ allowOverlap: true,
1589
+ behindDocument: false,
1590
+ horizontalPosition: {},
1591
+ layoutInCell: true,
1592
+ lockAnchor: false,
1593
+ verticalPosition: {},
1594
+ zIndex: mediaData.transformation.emus.y,
1595
+ margins: {},
1596
+ wrap: { type: TextWrappingType.NONE },
1597
+ ...rawFloating
1598
+ };
1599
+ const attrParts = [
1600
+ `distT="${floating.margins?.top ?? 0}"`,
1601
+ `distB="${floating.margins?.bottom ?? 0}"`,
1602
+ `distL="${floating.margins?.left ?? 0}"`,
1603
+ `distR="${floating.margins?.right ?? 0}"`,
1604
+ "simplePos=\"0\"",
1605
+ `allowOverlap="${floating.allowOverlap ? 1 : 0}"`,
1606
+ `behindDoc="${floating.behindDocument ? 1 : 0}"`,
1607
+ `locked="${floating.lockAnchor ? 1 : 0}"`,
1608
+ `layoutInCell="${floating.layoutInCell ? 1 : 0}"`,
1609
+ `relativeHeight="${floating.zIndex}"`
1610
+ ];
1611
+ let wrapXml;
1612
+ const rawWrap = rawFloating?.wrap;
1613
+ if (rawWrap?.type === TextWrappingType.SQUARE) wrapXml = wrapSquareStr(rawWrap, floating.margins);
1614
+ else if (rawWrap?.type === TextWrappingType.TIGHT) wrapXml = wrapTightStr(rawWrap, floating.margins, cx, cy);
1615
+ else if (rawWrap?.type === TextWrappingType.THROUGH) wrapXml = wrapThroughStr(rawWrap, floating.margins, cx, cy);
1616
+ else if (rawWrap?.type === TextWrappingType.TOP_AND_BOTTOM) wrapXml = wrapTopAndBottomStr(floating.margins);
1617
+ else wrapXml = "<wp:wrapNone/>";
1618
+ const graphicDataXml = stringifyGraphicDataContent(mediaData, opts, hlIds, ctx);
1619
+ return `<w:drawing><wp:anchor ${attrParts.join(" ")}><wp:simplePos x="0" y="0"/>` + stringifyPositionH(floating.horizontalPosition) + stringifyPositionV(floating.verticalPosition) + `<wp:extent cx="${cx}" cy="${cy}"/><wp:effectExtent l="0" t="0" r="0" b="0"/>` + wrapXml + stringifyDocPr(docProperties, hlIds) + `<wp:cNvGraphicFramePr><a:graphicFrameLocks noChangeAspect="1" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"/></wp:cNvGraphicFramePr><a:graphic ${GRAPHIC_NS}>${graphicDataXml}</a:graphic></wp:anchor></w:drawing>`;
1620
+ }
1621
+ /**
1622
+ * Drawing descriptor for DOCX `<w:drawing>` elements.
1623
+ *
1624
+ * Eliminates the Drawing/Inline/Anchor/Graphic/GraphicData/Pic XmlComponent
1625
+ * class chain. Inline images, charts, and smartarts produce XML via pure
1626
+ * string concatenation — zero XmlComponent instances.
1627
+ *
1628
+ * @example
1629
+ * ```typescript
1630
+ * const xml = drawingDesc.stringify({ mediaData, docProperties: opts.altText, floating: opts.floating }, ctx);
1631
+ * ```
1632
+ */
1633
+ const drawingDesc = {
1634
+ kind: "custom",
1635
+ stringify(opts, ctx) {
1636
+ if (opts.fill) {
1637
+ const media = extractBlipFillMedia(opts.fill);
1638
+ if (media) ctx.file.media.addImage(media.fileName, {
1639
+ data: media.data,
1640
+ fileName: media.fileName,
1641
+ type: media.type,
1642
+ transformation: {
1643
+ pixels: {
1644
+ x: 0,
1645
+ y: 0
1646
+ },
1647
+ emus: {
1648
+ x: 0,
1649
+ y: 0
1650
+ }
1651
+ }
1652
+ });
1653
+ }
1654
+ const hlIds = registerHyperlinks(opts.docProperties?.hyperlink, ctx);
1655
+ if (opts.floating) return stringifyAnchor(opts, hlIds, ctx);
1656
+ return stringifyInline(opts, hlIds, ctx);
1657
+ },
1658
+ parse(el, ctx) {
1659
+ return parseDrawingRun(el, ctx) ?? {};
1660
+ }
1661
+ };
1662
+ //#endregion
1663
+ //#region src/parts/paragraph/math/stringify.ts
1664
+ /**
1665
+ * Direct XML string builders for Office MathML (OMML).
1666
+ *
1667
+ * Replaces `coerceMathInput()` + `new Math().toXml()` recursive class chain
1668
+ * with direct string concatenation — zero XmlComponent instances.
1669
+ *
1670
+ * Processes `MathInput` discriminated union directly to XML strings.
1671
+ *
1672
+ * @module
1673
+ */
1674
+ function mathRunPropsStr(opts) {
1675
+ const parts = [];
1676
+ if (opts.lit) parts.push("<m:lit m:val=\"1\"/>");
1677
+ if (opts.normal) parts.push("<m:nor m:val=\"1\"/>");
1678
+ if (opts.script) parts.push(`<m:scr m:val="${opts.script}"/>`);
1679
+ if (opts.style) parts.push(`<m:sty m:val="${opts.style}"/>`);
1680
+ if (opts.breakAlignment) parts.push(`<m:brk m:alnAt="${opts.breakAlignment}"/>`);
1681
+ if (opts.align) parts.push("<m:aln m:val=\"1\"/>");
1682
+ return parts.length ? `<m:rPr>${parts.join("")}</m:rPr>` : "";
1683
+ }
1684
+ function stringifyChildren(items) {
1685
+ return items.map(stringifyMathInput).join("");
1686
+ }
1687
+ function stringifyMathInput(value) {
1688
+ if (typeof value === "string") return `<m:r><m:t>${escapeXml(value)}</m:t></m:r>`;
1689
+ if (typeof value !== "object" || value === null) return "";
1690
+ if ("subSuperScript" in value) {
1691
+ const opts = value.subSuperScript;
1692
+ return `<m:sSubSup><m:sSubSupPr/><m:e>${stringifyChildren(opts.children)}</m:e><m:sub>${stringifyChildren(opts.subScript)}</m:sub><m:sup>${stringifyChildren(opts.superScript)}</m:sup></m:sSubSup>`;
1693
+ }
1694
+ if ("preSubSuperScript" in value) {
1695
+ const opts = value.preSubSuperScript;
1696
+ return `<m:sPre><m:sPrePr/><m:sub>${stringifyChildren(opts.subScript)}</m:sub><m:sup>${stringifyChildren(opts.superScript)}</m:sup><m:e>${stringifyChildren(opts.children)}</m:e></m:sPre>`;
1697
+ }
1698
+ if ("superScript" in value) {
1699
+ const opts = value.superScript;
1700
+ return `<m:sSup><m:sSupPr/><m:e>${stringifyChildren(opts.children)}</m:e><m:sup>${stringifyChildren(opts.superScript)}</m:sup></m:sSup>`;
1701
+ }
1702
+ if ("subScript" in value) {
1703
+ const opts = value.subScript;
1704
+ return `<m:sSub><m:sSubPr/><m:e>${stringifyChildren(opts.children)}</m:e><m:sub>${stringifyChildren(opts.subScript)}</m:sub></m:sSub>`;
1705
+ }
1706
+ if ("fraction" in value) {
1707
+ const opts = value.fraction;
1708
+ return `<m:f>${opts.fractionType ? `<m:fPr><m:type m:val="${opts.fractionType}"/></m:fPr>` : ""}<m:num>${stringifyChildren(opts.numerator)}</m:num><m:den>${stringifyChildren(opts.denominator)}</m:den></m:f>`;
1709
+ }
1710
+ if ("radical" in value) {
1711
+ const opts = value.radical;
1712
+ const hasDegree = opts.degree && opts.degree.length > 0;
1713
+ return `<m:rad>${!hasDegree ? "<m:radPr><m:degHide m:val=\"1\"/></m:radPr>" : "<m:radPr/>"}${hasDegree ? `<m:deg>${stringifyChildren(opts.degree)}</m:deg>` : "<m:deg/>"}<m:e>${stringifyChildren(opts.children)}</m:e></m:rad>`;
1714
+ }
1715
+ if ("sum" in value) return stringifyNAry(value.sum, "∑");
1716
+ if ("integral" in value) return stringifyNAry(value.integral, "∫");
1717
+ if ("limitLower" in value) {
1718
+ const opts = value.limitLower;
1719
+ return `<m:limLow>${opts.properties ? "" : ""}<m:e>${stringifyChildren(opts.children)}</m:e><m:lim>${stringifyChildren(opts.limit)}</m:lim></m:limLow>`;
1720
+ }
1721
+ if ("limitUpper" in value) {
1722
+ const opts = value.limitUpper;
1723
+ return `<m:limUpp>${opts.properties ? "" : ""}<m:e>${stringifyChildren(opts.children)}</m:e><m:lim>${stringifyChildren(opts.limit)}</m:lim></m:limUpp>`;
1724
+ }
1725
+ if ("function" in value) {
1726
+ const opts = value.function;
1727
+ return `<m:func>${opts.properties ? "" : ""}<m:fName>${stringifyChildren(opts.name)}</m:fName><m:e>${stringifyChildren(opts.children)}</m:e></m:func>`;
1728
+ }
1729
+ if ("matrix" in value) {
1730
+ const opts = value.matrix;
1731
+ const rows = opts.rows.map((row) => `<m:mr>${row.map((cell) => `<m:e>${stringifyMathInput(cell)}</m:e>`).join("")}</m:mr>`).join("");
1732
+ let pr = "";
1733
+ if (opts.properties) {
1734
+ const p = opts.properties;
1735
+ const prParts = [];
1736
+ if (p.baseJc) prParts.push(`<m:baseJc m:val="${p.baseJc}"/>`);
1737
+ if (p.plcHide) prParts.push("<m:plcHide m:val=\"1\"/>");
1738
+ if (p.rSpRule) prParts.push(`<m:rSpRule m:val="${p.rSpRule}"/>`);
1739
+ if (p.cGpRule) prParts.push(`<m:cGpRule m:val="${p.cGpRule}"/>`);
1740
+ if (p.rSp) prParts.push(`<m:rSp m:val="${p.rSp}"/>`);
1741
+ if (p.cSp) prParts.push(`<m:cSp m:val="${p.cSp}"/>`);
1742
+ if (p.cGp) prParts.push(`<m:cGp m:val="${p.cGp}"/>`);
1743
+ if (p.mcs) {
1744
+ const mcItems = p.mcs.map((mc) => `<m:mc><m:mcPr><m:count m:val="${mc.count}"/><m:mcJc m:val="${mc.mcJc}"/></m:mcPr></m:mc>`).join("");
1745
+ prParts.push(`<m:mcs>${mcItems}</m:mcs>`);
1746
+ }
1747
+ if (prParts.length) pr = `<m:mPr>${prParts.join("")}</m:mPr>`;
1748
+ }
1749
+ return `<m:m>${pr}${rows}</m:m>`;
1750
+ }
1751
+ if ("roundBrackets" in value) return stringifyDelimiters(bracketChildren(value.roundBrackets), "(", ")");
1752
+ if ("curlyBrackets" in value) return stringifyDelimiters(bracketChildren(value.curlyBrackets), "{", "}");
1753
+ if ("angledBrackets" in value) return stringifyDelimiters(bracketChildren(value.angledBrackets), "〈", "〉");
1754
+ if ("squareBrackets" in value) return stringifyDelimiters(bracketChildren(value.squareBrackets), "[", "]");
1755
+ if ("borderBox" in value) {
1756
+ const opts = value.borderBox;
1757
+ let pr = "";
1758
+ if (opts.properties) {
1759
+ const p = opts.properties;
1760
+ const parts = [];
1761
+ if (p.hideTop) parts.push("<m:hideTop m:val=\"1\"/>");
1762
+ if (p.hideBottom) parts.push("<m:hideBot m:val=\"1\"/>");
1763
+ if (p.hideLeft) parts.push("<m:hideLeft m:val=\"1\"/>");
1764
+ if (p.hideRight) parts.push("<m:hideRight m:val=\"1\"/>");
1765
+ if (p.strikeHorizontal) parts.push("<m:strikeH m:val=\"1\"/>");
1766
+ if (p.strikeVertical) parts.push("<m:strikeV m:val=\"1\"/>");
1767
+ if (p.strikeDiagonalUp) parts.push("<m:strikeBLTR m:val=\"1\"/>");
1768
+ if (p.strikeDiagonalDown) parts.push("<m:strikeTLBR m:val=\"1\"/>");
1769
+ if (parts.length) pr = `<m:borderBoxPr>${parts.join("")}</m:borderBoxPr>`;
1770
+ }
1771
+ return `<m:borderBox>${pr}<m:e>${stringifyChildren(opts.children)}</m:e></m:borderBox>`;
1772
+ }
1773
+ if ("box" in value) {
1774
+ const opts = value.box;
1775
+ let pr = "";
1776
+ if (opts.properties) {
1777
+ const p = opts.properties;
1778
+ const parts = [];
1779
+ if (p.opEmu) parts.push("<m:opEmu m:val=\"1\"/>");
1780
+ if (p.noBreak) parts.push("<m:noBreak m:val=\"1\"/>");
1781
+ if (p.diff) parts.push("<m:diff m:val=\"1\"/>");
1782
+ if (p.aln) parts.push("<m:aln m:val=\"1\"/>");
1783
+ if (parts.length) pr = `<m:boxPr>${parts.join("")}</m:boxPr>`;
1784
+ }
1785
+ return `<m:box>${pr}<m:e>${stringifyChildren(opts.children)}</m:e></m:box>`;
1786
+ }
1787
+ if ("groupChr" in value) {
1788
+ const opts = value.groupChr;
1789
+ let pr = "";
1790
+ if (opts.properties) {
1791
+ const p = opts.properties;
1792
+ const parts = [];
1793
+ if (p.chr) parts.push(`<m:chr m:val="${p.chr}"/>`);
1794
+ if (p.pos) parts.push(`<m:pos m:val="${p.pos}"/>`);
1795
+ if (p.vertJc) parts.push(`<m:vertJc m:val="${p.vertJc}"/>`);
1796
+ if (parts.length) pr = `<m:groupChrPr>${parts.join("")}</m:groupChrPr>`;
1797
+ }
1798
+ return `<m:groupChr>${pr}<m:e>${stringifyChildren(opts.children)}</m:e></m:groupChr>`;
1799
+ }
1800
+ if ("phant" in value) {
1801
+ const opts = value.phant;
1802
+ let pr = "";
1803
+ if (opts.properties) {
1804
+ const p = opts.properties;
1805
+ const parts = [];
1806
+ if (p.show !== void 0) parts.push(`<m:show m:val="${p.show ? 1 : 0}"/>`);
1807
+ if (p.zeroWid) parts.push("<m:zeroWid m:val=\"1\"/>");
1808
+ if (p.zeroAsc) parts.push("<m:zeroAsc m:val=\"1\"/>");
1809
+ if (p.zeroDesc) parts.push("<m:zeroDesc m:val=\"1\"/>");
1810
+ if (p.transp) parts.push("<m:transp m:val=\"1\"/>");
1811
+ if (parts.length) pr = `<m:phantPr>${parts.join("")}</m:phantPr>`;
1812
+ }
1813
+ return `<m:phant>${pr}<m:e>${stringifyChildren(opts.children)}</m:e></m:phant>`;
1814
+ }
1815
+ if ("eqArr" in value) {
1816
+ const opts = value.eqArr;
1817
+ let pr = "";
1818
+ if (opts.properties) {
1819
+ const p = opts.properties;
1820
+ const parts = [];
1821
+ if (p.baseJc) parts.push(`<m:baseJc m:val="${p.baseJc}"/>`);
1822
+ if (p.maxDist) parts.push("<m:maxDist m:val=\"1\"/>");
1823
+ if (p.objDist) parts.push("<m:objDist m:val=\"1\"/>");
1824
+ if (p.rSpRule) parts.push(`<m:rSpRule m:val="${p.rSpRule}"/>`);
1825
+ if (p.rSp) parts.push(`<m:rSp m:val="${p.rSp}"/>`);
1826
+ if (parts.length) pr = `<m:eqArrPr>${parts.join("")}</m:eqArrPr>`;
1827
+ }
1828
+ const rows = opts.rows.map((row) => `<m:e>${stringifyChildren(row)}</m:e>`).join("");
1829
+ return `<m:eqArr>${pr}${rows}</m:eqArr>`;
1830
+ }
1831
+ if ("accent" in value) {
1832
+ const opts = value.accent;
1833
+ return `<m:acc>${opts.accentCharacter ? `<m:accPr><m:chr m:val="${opts.accentCharacter}"/></m:accPr>` : ""}<m:e>${stringifyChildren(opts.children)}</m:e></m:acc>`;
1834
+ }
1835
+ if ("bar" in value) {
1836
+ const opts = value.bar;
1837
+ return `<m:bar><m:barPr><m:pos m:val="${opts.type}"/></m:barPr><m:e>${stringifyChildren(opts.children)}</m:e></m:bar>`;
1838
+ }
1839
+ if ("text" in value) return `<m:r>${value.properties ? mathRunPropsStr(value.properties) : ""}<m:t>${escapeXml(value.text)}</m:t></m:r>`;
1840
+ return "";
1841
+ }
1842
+ function stringifyNAry(opts, chr) {
1843
+ const hasSub = opts.subScript && opts.subScript.length > 0;
1844
+ const hasSup = opts.superScript && opts.superScript.length > 0;
1845
+ const prParts = [`<m:chr m:val="${chr}"/>`];
1846
+ if (!hasSub) prParts.push("<m:subHide m:val=\"1\"/>");
1847
+ if (!hasSup) prParts.push("<m:supHide m:val=\"1\"/>");
1848
+ return `<m:nary>${`<m:naryPr>${prParts.join("")}</m:naryPr>`}${hasSub ? `<m:sub>${stringifyChildren(opts.subScript)}</m:sub>` : "<m:sub/>"}${hasSup ? `<m:sup>${stringifyChildren(opts.superScript)}</m:sup>` : "<m:sup/>"}<m:e>${stringifyChildren(opts.children)}</m:e></m:nary>`;
1849
+ }
1850
+ function stringifyDelimiters(children, begChr, endChr) {
1851
+ return `<m:d><m:dPr><m:begChr m:val="${begChr}"/><m:endChr m:val="${endChr}"/></m:dPr><m:e>${stringifyChildren(children)}</m:e></m:d>`;
1852
+ }
1853
+ function bracketChildren(v) {
1854
+ if (Array.isArray(v)) return v;
1855
+ return v.children;
1856
+ }
1857
+ function stringifyMath(children) {
1858
+ return `<m:oMath>${children.map((c) => stringifyMathInput(c)).join("")}</m:oMath>`;
1859
+ }
1860
+ /**
1861
+ * Parse all math children from an m:oMath (or similar container) element.
1862
+ */
1863
+ function parseMathChildren(el) {
1864
+ const result = [];
1865
+ for (const child of el.elements ?? []) {
1866
+ const parsed = parseMathElement(child);
1867
+ if (parsed !== void 0) result.push(parsed);
1868
+ }
1869
+ return result;
1870
+ }
1871
+ function parseMathElement(el) {
1872
+ switch (el.name) {
1873
+ case "m:r": return parseMathRun(el);
1874
+ case "m:f": return parseMathFraction(el);
1875
+ case "m:rad": return parseMathRadical(el);
1876
+ case "m:sSup": return parseMathSuperScript(el);
1877
+ case "m:sSub": return parseMathSubScript(el);
1878
+ case "m:sSubSup": return parseMathSubSuperScript(el);
1879
+ case "m:nary": return parseMathNAry(el);
1880
+ case "m:func": return parseMathFunction(el);
1881
+ case "m:d": return parseMathDelimiter(el);
1882
+ case "m:m": return parseMathMatrix(el);
1883
+ case "m:acc": return parseMathAccent(el);
1884
+ case "m:bar": return parseMathBar(el);
1885
+ case "m:borderBox": return { borderBox: { children: parseMathArg(el, "m:e") } };
1886
+ case "m:box": return { box: { children: parseMathArg(el, "m:e") } };
1887
+ case "m:groupChr": return { groupChr: { children: parseMathArg(el, "m:e") } };
1888
+ case "m:phant": return { phant: { children: parseMathArg(el, "m:e") } };
1889
+ case "m:eqArr": return parseMathEqArr(el);
1890
+ case "m:limLow": return parseMathLimitLower(el);
1891
+ case "m:limUpp": return parseMathLimitUpper(el);
1892
+ case "m:rPr":
1893
+ case "m:fPr":
1894
+ case "m:radPr":
1895
+ case "m:sSupPr":
1896
+ case "m:sSubPr":
1897
+ case "m:sSubSupPr":
1898
+ case "m:naryPr":
1899
+ case "m:funcPr":
1900
+ case "m:dPr":
1901
+ case "m:mPr":
1902
+ case "m:accPr":
1903
+ case "m:barPr":
1904
+ case "m:borderBoxPr":
1905
+ case "m:boxPr":
1906
+ case "m:groupChrPr":
1907
+ case "m:phantPr":
1908
+ case "m:eqArrPr":
1909
+ case "m:limLowPr":
1910
+ case "m:limUppPr":
1911
+ case "m:ctrlPr": return;
1912
+ default: return;
1913
+ }
1914
+ }
1915
+ function parseMathRun(el) {
1916
+ return textOf(findChild(el, "m:t")) ?? "";
1917
+ }
1918
+ function parseMathFraction(el) {
1919
+ return { fraction: {
1920
+ numerator: parseMathArg(el, "m:num"),
1921
+ denominator: parseMathArg(el, "m:den")
1922
+ } };
1923
+ }
1924
+ function parseMathRadical(el) {
1925
+ const degree = parseMathArg(el, "m:deg");
1926
+ return { radical: {
1927
+ children: parseMathArg(el, "m:e"),
1928
+ ...degree.length > 0 ? { degree } : {}
1929
+ } };
1930
+ }
1931
+ function parseMathSuperScript(el) {
1932
+ return { superScript: {
1933
+ children: parseMathArg(el, "m:e"),
1934
+ superScript: parseMathArg(el, "m:sup")
1935
+ } };
1936
+ }
1937
+ function parseMathSubScript(el) {
1938
+ return { subScript: {
1939
+ children: parseMathArg(el, "m:e"),
1940
+ subScript: parseMathArg(el, "m:sub")
1941
+ } };
1942
+ }
1943
+ function parseMathSubSuperScript(el) {
1944
+ return { subSuperScript: {
1945
+ children: parseMathArg(el, "m:e"),
1946
+ subScript: parseMathArg(el, "m:sub"),
1947
+ superScript: parseMathArg(el, "m:sup")
1948
+ } };
1949
+ }
1950
+ function parseMathNAry(el) {
1951
+ const naryPr = findChild(el, "m:naryPr");
1952
+ const chrEl = naryPr ? findChild(naryPr, "m:chr") : void 0;
1953
+ const chrVal = chrEl ? attr(chrEl, "m:val") : void 0;
1954
+ const baseChildren = parseMathArg(el, "m:e");
1955
+ const sub = parseMathArg(el, "m:sub");
1956
+ const sup = parseMathArg(el, "m:sup");
1957
+ const common = {
1958
+ children: baseChildren,
1959
+ ...sub.length > 0 ? { subScript: sub } : {},
1960
+ ...sup.length > 0 ? { superScript: sup } : {}
1961
+ };
1962
+ if (chrVal === "∑") return { sum: common };
1963
+ return { integral: common };
1964
+ }
1965
+ function parseMathFunction(el) {
1966
+ return { function: {
1967
+ name: parseMathArg(el, "m:fName"),
1968
+ children: parseMathArg(el, "m:e")
1969
+ } };
1970
+ }
1971
+ function parseMathDelimiter(el) {
1972
+ const dPr = findChild(el, "m:dPr");
1973
+ const begChrEl = dPr ? findChild(dPr, "m:begChr") : void 0;
1974
+ const begChr = begChrEl ? attr(begChrEl, "m:val") : "(";
1975
+ const mathChildren = parseMathArg(el, "m:e");
1976
+ switch (begChr) {
1977
+ case "[": return { squareBrackets: mathChildren };
1978
+ case "{": return { curlyBrackets: mathChildren };
1979
+ case "<":
1980
+ case "⟨": return { angledBrackets: mathChildren };
1981
+ default: return { roundBrackets: mathChildren };
1982
+ }
1983
+ }
1984
+ function parseMathMatrix(el) {
1985
+ const rows = [];
1986
+ for (const mr of children(el, "m:mr")) rows.push(parseMathArg(mr, "m:e"));
1987
+ return { matrix: { rows } };
1988
+ }
1989
+ function parseMathAccent(el) {
1990
+ const accPr = findChild(el, "m:accPr");
1991
+ const chrEl = accPr ? findChild(accPr, "m:chr") : void 0;
1992
+ const accentChar = chrEl ? attr(chrEl, "m:val") : void 0;
1993
+ return { accent: {
1994
+ children: parseMathArg(el, "m:e"),
1995
+ ...accentChar ? { accentCharacter: accentChar } : {}
1996
+ } };
1997
+ }
1998
+ function parseMathBar(el) {
1999
+ const barPr = findChild(el, "m:barPr");
2000
+ const posEl = barPr ? findChild(barPr, "m:pos") : void 0;
2001
+ const pos = posEl ? attr(posEl, "m:val") : "top";
2002
+ return { bar: {
2003
+ children: parseMathArg(el, "m:e"),
2004
+ type: pos ?? "top"
2005
+ } };
2006
+ }
2007
+ function parseMathEqArr(el) {
2008
+ const rows = [];
2009
+ for (const e of children(el, "m:e")) rows.push(parseMathChildren(e));
2010
+ return { eqArr: { rows } };
2011
+ }
2012
+ function parseMathLimitLower(el) {
2013
+ return { limitLower: {
2014
+ children: parseMathArg(el, "m:e"),
2015
+ limit: parseMathArg(el, "m:lim")
2016
+ } };
2017
+ }
2018
+ function parseMathLimitUpper(el) {
2019
+ return { limitUpper: {
2020
+ children: parseMathArg(el, "m:e"),
2021
+ limit: parseMathArg(el, "m:lim")
2022
+ } };
2023
+ }
2024
+ function parseMathArg(parent, childName) {
2025
+ const container = findChild(parent, childName);
2026
+ if (!container) return [];
2027
+ return parseMathChildren(container);
2028
+ }
2029
+ //#endregion
2030
+ //#region src/parts/paragraph/stringify.ts
2031
+ /**
2032
+ * Direct XML string builders for paragraph and run properties.
2033
+ *
2034
+ * Replaces `buildParagraphProperties() + xml()` and `buildRunProperties() + xml()`
2035
+ * with direct string concatenation — zero intermediate IXmlableObject allocation,
2036
+ * zero recursive xml() traversal. Follows PPTX/XLSX pattern.
2037
+ *
2038
+ * @module
2039
+ */
2040
+ /** On/off: `<w:name/>` for true, `<w:name w:val="0"/>` for false */
2041
+ function onOff(name, val) {
2042
+ return val ? `<${name}/>` : `<${name} w:val="0"/>`;
2043
+ }
2044
+ /** Build attrs string from key-value pairs, skipping undefined */
2045
+ function attrParts(attrs) {
2046
+ const parts = [];
2047
+ for (const [key, val] of Object.entries(attrs)) if (val !== void 0) parts.push(`${key}="${val}"`);
2048
+ return parts.join(" ");
2049
+ }
2050
+ function borderStr(name, opts) {
2051
+ return `<${name} ${attrParts({
2052
+ "w:val": opts.style,
2053
+ "w:color": opts.color !== void 0 ? hexColorValue(opts.color) : void 0,
2054
+ "w:sz": opts.size !== void 0 ? eighthPointMeasureValue(opts.size) : void 0,
2055
+ "w:space": opts.space !== void 0 ? pointMeasureValue(opts.space) : void 0,
2056
+ "w:themeColor": opts.themeColor,
2057
+ "w:themeTint": opts.themeTint !== void 0 ? uCharHexNumber(opts.themeTint) : void 0,
2058
+ "w:themeShade": opts.themeShade !== void 0 ? uCharHexNumber(opts.themeShade) : void 0,
2059
+ "w:shadow": opts.shadow !== void 0 ? opts.shadow ? 1 : 0 : void 0,
2060
+ "w:frame": opts.frame !== void 0 ? opts.frame ? 1 : 0 : void 0
2061
+ })}/>`;
2062
+ }
2063
+ function shadingStr(opts) {
2064
+ return `<w:shd ${attrParts({
2065
+ "w:val": opts.type ?? "clear",
2066
+ "w:color": opts.color !== void 0 ? hexColorValue(opts.color) : void 0,
2067
+ "w:fill": opts.fill !== void 0 ? hexColorValue(opts.fill) : void 0,
2068
+ "w:themeColor": opts.themeColor,
2069
+ "w:themeTint": opts.themeTint !== void 0 ? uCharHexNumber(opts.themeTint) : void 0,
2070
+ "w:themeShade": opts.themeShade !== void 0 ? uCharHexNumber(opts.themeShade) : void 0,
2071
+ "w:themeFill": opts.themeFill,
2072
+ "w:themeFillTint": opts.themeFillTint !== void 0 ? uCharHexNumber(opts.themeFillTint) : void 0,
2073
+ "w:themeFillShade": opts.themeFillShade !== void 0 ? uCharHexNumber(opts.themeFillShade) : void 0
2074
+ })}/>`;
2075
+ }
2076
+ function spacingStr(opts) {
2077
+ return `<w:spacing ${attrParts({
2078
+ "w:after": opts.after,
2079
+ "w:afterAutospacing": opts.afterAutoSpacing !== void 0 ? opts.afterAutoSpacing ? 1 : 0 : void 0,
2080
+ "w:afterLines": opts.afterLines !== void 0 ? decimalNumber(opts.afterLines) : void 0,
2081
+ "w:before": opts.before,
2082
+ "w:beforeAutospacing": opts.beforeAutoSpacing !== void 0 ? opts.beforeAutoSpacing ? 1 : 0 : void 0,
2083
+ "w:beforeLines": opts.beforeLines !== void 0 ? decimalNumber(opts.beforeLines) : void 0,
2084
+ "w:line": opts.line,
2085
+ "w:lineRule": opts.lineRule
2086
+ })}/>`;
2087
+ }
2088
+ function indentStr(opts) {
2089
+ return `<w:ind ${attrParts({
2090
+ "w:start": opts.start !== void 0 ? signedTwipsMeasureValue(opts.start) : void 0,
2091
+ "w:startChars": opts.startChars !== void 0 ? decimalNumber(opts.startChars) : void 0,
2092
+ "w:end": opts.end !== void 0 ? signedTwipsMeasureValue(opts.end) : void 0,
2093
+ "w:endChars": opts.endChars !== void 0 ? decimalNumber(opts.endChars) : void 0,
2094
+ "w:left": opts.left !== void 0 ? signedTwipsMeasureValue(opts.left) : void 0,
2095
+ "w:leftChars": opts.leftChars !== void 0 ? decimalNumber(opts.leftChars) : void 0,
2096
+ "w:right": opts.right !== void 0 ? signedTwipsMeasureValue(opts.right) : void 0,
2097
+ "w:rightChars": opts.rightChars !== void 0 ? decimalNumber(opts.rightChars) : void 0,
2098
+ "w:hanging": opts.hanging !== void 0 ? twipsMeasureValue(opts.hanging) : void 0,
2099
+ "w:hangingChars": opts.hangingChars !== void 0 ? decimalNumber(opts.hangingChars) : void 0,
2100
+ "w:firstLine": opts.firstLine !== void 0 ? twipsMeasureValue(opts.firstLine) : void 0,
2101
+ "w:firstLineChars": opts.firstLineChars !== void 0 ? decimalNumber(opts.firstLineChars) : void 0
2102
+ })}/>`;
2103
+ }
2104
+ function tabStopsStr(defs) {
2105
+ return `<w:tabs>${defs.map(({ type, position, leader }) => {
2106
+ return `<w:tab ${attrParts({
2107
+ "w:val": type,
2108
+ "w:pos": position,
2109
+ "w:leader": leader
2110
+ })}/>`;
2111
+ }).join("")}</w:tabs>`;
2112
+ }
2113
+ function cnfStyleStr(opts) {
2114
+ return `<w:cnfStyle ${attrParts({
2115
+ "w:firstRow": opts.firstRow ? "1" : "0",
2116
+ "w:lastRow": opts.lastRow ? "1" : "0",
2117
+ "w:firstColumn": opts.firstColumn ? "1" : "0",
2118
+ "w:lastColumn": opts.lastColumn ? "1" : "0",
2119
+ "w:oddVBand": opts.oddVBand ? "1" : "0",
2120
+ "w:evenVBand": opts.evenVBand ? "1" : "0",
2121
+ "w:oddHBand": opts.oddHBand ? "1" : "0",
2122
+ "w:evenHBand": opts.evenHBand ? "1" : "0",
2123
+ "w:firstRowFirstColumn": opts.firstRowFirstColumn ? "1" : "0",
2124
+ "w:firstRowLastColumn": opts.firstRowLastColumn ? "1" : "0",
2125
+ "w:lastRowFirstColumn": opts.lastRowFirstColumn ? "1" : "0",
2126
+ "w:lastRowLastColumn": opts.lastRowLastColumn ? "1" : "0"
2127
+ })}/>`;
2128
+ }
2129
+ function framePrStr(opts) {
2130
+ const alignment = opts.alignment;
2131
+ const position = opts.position;
2132
+ return `<w:framePr ${attrParts({
2133
+ "w:xAlign": alignment?.x,
2134
+ "w:yAlign": alignment?.y,
2135
+ "w:hAnchor": opts.anchor?.horizontal,
2136
+ "w:anchorLock": opts.anchorLock,
2137
+ "w:vAnchor": opts.anchor?.vertical,
2138
+ "w:dropCap": opts.dropCap,
2139
+ "w:h": opts.height,
2140
+ "w:lines": opts.lines,
2141
+ "w:hRule": opts.rule,
2142
+ "w:hSpace": opts.space?.horizontal,
2143
+ "w:vSpace": opts.space?.vertical,
2144
+ "w:w": opts.width,
2145
+ "w:wrap": opts.wrap,
2146
+ "w:x": position?.x,
2147
+ "w:y": position?.y
2148
+ })}/>`;
2149
+ }
2150
+ function numPrStr(numberId, indentLevel, numberingChange) {
2151
+ const idVal = typeof numberId === "string" ? `{${numberId}}` : numberId;
2152
+ const parts = [`<w:ilvl w:val="${Math.min(indentLevel, 9)}"/>`, `<w:numId w:val="${idVal}"/>`];
2153
+ if (numberingChange) {
2154
+ const a = attrParts({
2155
+ "w:original": numberingChange.original,
2156
+ "w:id": numberingChange.id,
2157
+ "w:author": numberingChange.author,
2158
+ "w:date": numberingChange.date
2159
+ });
2160
+ parts.push(`<w:numberingChange ${a}/>`);
2161
+ }
2162
+ return `<w:numPr>${parts.join("")}</w:numPr>`;
2163
+ }
2164
+ function colorStr(colorOrOptions) {
2165
+ if (typeof colorOrOptions === "string") return `<w:color w:val="${hexColorValue(colorOrOptions)}"/>`;
2166
+ const opts = colorOrOptions;
2167
+ return `<w:color ${attrParts({
2168
+ "w:val": opts.val !== void 0 ? hexColorValue(opts.val) : void 0,
2169
+ "w:themeColor": opts.themeColor,
2170
+ "w:themeTint": opts.themeTint !== void 0 ? uCharHexNumber(opts.themeTint) : void 0,
2171
+ "w:themeShade": opts.themeShade !== void 0 ? uCharHexNumber(opts.themeShade) : void 0
2172
+ })}/>`;
2173
+ }
2174
+ function runFontsStr(nameOrAttrs, hint) {
2175
+ if (typeof nameOrAttrs === "string") return `<w:rFonts ${attrParts({
2176
+ "w:ascii": nameOrAttrs,
2177
+ "w:cs": nameOrAttrs,
2178
+ "w:eastAsia": nameOrAttrs,
2179
+ "w:hAnsi": nameOrAttrs,
2180
+ "w:hint": hint
2181
+ })}/>`;
2182
+ const attrs = nameOrAttrs;
2183
+ return `<w:rFonts ${attrParts({
2184
+ "w:ascii": attrs.ascii,
2185
+ "w:asciiTheme": attrs.asciiTheme,
2186
+ "w:cs": attrs.cs,
2187
+ "w:cstheme": attrs.cstheme,
2188
+ "w:eastAsia": attrs.eastAsia,
2189
+ "w:eastAsiaTheme": attrs.eastAsiaTheme,
2190
+ "w:hAnsi": attrs.hAnsi,
2191
+ "w:hAnsiTheme": attrs.hAnsiTheme,
2192
+ "w:hint": attrs.hint
2193
+ })}/>`;
2194
+ }
2195
+ function underlineStr(type, color) {
2196
+ return `<w:u ${attrParts({
2197
+ "w:val": type ?? "single",
2198
+ "w:color": color !== void 0 ? hexColorValue(color) : void 0
2199
+ })}/>`;
2200
+ }
2201
+ function eastAsianLayoutStr(opts) {
2202
+ return `<w:eastAsianLayout ${attrParts({
2203
+ "w:id": opts.id !== void 0 ? decimalNumber(opts.id) : void 0,
2204
+ "w:combine": opts.combine !== void 0 ? opts.combine ? 1 : 0 : void 0,
2205
+ "w:combineBrackets": opts.combineBrackets,
2206
+ "w:vert": opts.vert !== void 0 ? opts.vert ? 1 : 0 : void 0,
2207
+ "w:vertCompress": opts.vertCompress !== void 0 ? opts.vertCompress ? 1 : 0 : void 0
2208
+ })}/>`;
2209
+ }
2210
+ function languageStr(opts) {
2211
+ return `<w:lang ${attrParts({
2212
+ "w:val": opts.value,
2213
+ "w:eastAsia": opts.eastAsia,
2214
+ "w:bidi": opts.bidirectional
2215
+ })}/>`;
2216
+ }
2217
+ /**
2218
+ * Build `<w:pPr>` XML string directly from options — zero IXmlableObject allocation.
2219
+ *
2220
+ * Replaces `buildParagraphProperties() + xml()` with a single-pass string builder.
2221
+ */
2222
+ function stringifyParagraphProperties(options) {
2223
+ const numberingReferences = [];
2224
+ if (!options) return {
2225
+ xml: void 0,
2226
+ numberingReferences
2227
+ };
2228
+ const parts = [];
2229
+ if (options.heading) parts.push(`<w:pStyle w:val="${escapeXml(options.heading)}"/>`);
2230
+ if (options.bullet) parts.push("<w:pStyle w:val=\"ListParagraph\"/>");
2231
+ if (options.numbering) {
2232
+ if (!options.style && !options.heading) {
2233
+ if (!options.numbering.custom) parts.push("<w:pStyle w:val=\"ListParagraph\"/>");
2234
+ }
2235
+ }
2236
+ if (options.style) parts.push(`<w:pStyle w:val="${escapeXml(options.style)}"/>`);
2237
+ if (options.keepNext !== void 0) parts.push(onOff("w:keepNext", options.keepNext));
2238
+ if (options.keepLines !== void 0) parts.push(onOff("w:keepLines", options.keepLines));
2239
+ if (options.pageBreakBefore) parts.push("<w:pageBreakBefore/>");
2240
+ if (options.frame) parts.push(framePrStr(options.frame));
2241
+ if (options.widowControl !== void 0) parts.push(onOff("w:widowControl", options.widowControl));
2242
+ if (options.bullet) parts.push(`<w:numPr><w:ilvl w:val="${Math.min(options.bullet.level, 9)}"/><w:numId w:val="1"/></w:numPr>`);
2243
+ if (options.numbering) {
2244
+ numberingReferences.push({
2245
+ instance: options.numbering.instance ?? 0,
2246
+ reference: options.numbering.reference
2247
+ });
2248
+ const numId = `${options.numbering.reference}-${options.numbering.instance ?? 0}`;
2249
+ parts.push(numPrStr(numId, options.numbering.level, options.numbering.numberingChange));
2250
+ } else if (options.numbering === false) parts.push(numPrStr(0, 0));
2251
+ if (options.border) {
2252
+ const bParts = [];
2253
+ if (options.border.top) bParts.push(borderStr("w:top", options.border.top));
2254
+ if (options.border.left) bParts.push(borderStr("w:left", options.border.left));
2255
+ if (options.border.bottom) bParts.push(borderStr("w:bottom", options.border.bottom));
2256
+ if (options.border.right) bParts.push(borderStr("w:right", options.border.right));
2257
+ if (options.border.between) bParts.push(borderStr("w:between", options.border.between));
2258
+ if (options.border.bar) bParts.push(borderStr("w:bar", options.border.bar));
2259
+ if (bParts.length) parts.push(`<w:pBdr>${bParts.join("")}</w:pBdr>`);
2260
+ }
2261
+ if (options.thematicBreak) parts.push(`<w:pBdr>${borderStr("w:bottom", {
2262
+ color: "auto",
2263
+ size: 6,
2264
+ space: 1,
2265
+ style: BorderStyle.SINGLE
2266
+ })}</w:pBdr>`);
2267
+ if (options.shading) parts.push(shadingStr(options.shading));
2268
+ if (options.wordWrap) parts.push("<w:wordWrap w:val=\"0\"/>");
2269
+ if (options.overflowPunctuation) parts.push(onOff("w:overflowPunct", options.overflowPunctuation));
2270
+ const tabDefs = [
2271
+ ...options.rightTabStop !== void 0 ? [{
2272
+ position: options.rightTabStop,
2273
+ type: "right"
2274
+ }] : [],
2275
+ ...options.tabStops ? options.tabStops : [],
2276
+ ...options.leftTabStop !== void 0 ? [{
2277
+ position: options.leftTabStop,
2278
+ type: "left"
2279
+ }] : []
2280
+ ];
2281
+ if (tabDefs.length > 0) parts.push(tabStopsStr(tabDefs));
2282
+ if (options.bidirectional !== void 0) parts.push(onOff("w:bidi", options.bidirectional));
2283
+ if (options.spacing) parts.push(spacingStr(options.spacing));
2284
+ if (options.indent) parts.push(indentStr(options.indent));
2285
+ if (options.contextualSpacing !== void 0) parts.push(onOff("w:contextualSpacing", options.contextualSpacing));
2286
+ if (options.alignment) parts.push(`<w:jc w:val="${options.alignment}"/>`);
2287
+ if (options.outlineLevel !== void 0) parts.push(`<w:outlineLvl w:val="${options.outlineLevel}"/>`);
2288
+ if (options.divId !== void 0) parts.push(`<w:divId w:val="${options.divId}"/>`);
2289
+ if (options.cnfStyle) parts.push(cnfStyleStr(options.cnfStyle));
2290
+ if (options.suppressLineNumbers !== void 0) parts.push(onOff("w:suppressLineNumbers", options.suppressLineNumbers));
2291
+ if (options.autoSpaceEastAsianText !== void 0) parts.push(onOff("w:autoSpaceDN", options.autoSpaceEastAsianText));
2292
+ if (options.suppressAutoHyphens !== void 0) parts.push(onOff("w:suppressAutoHyphens", options.suppressAutoHyphens));
2293
+ if (options.adjustRightInd !== void 0) parts.push(onOff("w:adjustRightInd", options.adjustRightInd));
2294
+ if (options.snapToGrid !== void 0) parts.push(onOff("w:snapToGrid", options.snapToGrid));
2295
+ if (options.mirrorIndents !== void 0) parts.push(onOff("w:mirrorIndents", options.mirrorIndents));
2296
+ if (options.kinsoku !== void 0) parts.push(onOff("w:kinsoku", options.kinsoku));
2297
+ if (options.topLinePunct !== void 0) parts.push(onOff("w:topLinePunct", options.topLinePunct));
2298
+ if (options.autoSpaceDE !== void 0) parts.push(onOff("w:autoSpaceDE", options.autoSpaceDE));
2299
+ if (options.textAlignment !== void 0) parts.push(`<w:textAlignment w:val="${options.textAlignment}"/>`);
2300
+ if (options.textboxTightWrap !== void 0) parts.push(`<w:textboxTightWrap w:val="${options.textboxTightWrap}"/>`);
2301
+ if (options.textDirection !== void 0) parts.push(`<w:textDirection w:val="${options.textDirection}"/>`);
2302
+ if (options.suppressOverlap !== void 0) parts.push(onOff("w:suppressOverlap", options.suppressOverlap));
2303
+ if (options.run) {
2304
+ const inner = stringifyRunPropertiesInner(options.run);
2305
+ if (inner !== void 0) {
2306
+ const extra = [];
2307
+ const runOpts = options.run;
2308
+ if (runOpts.insertion) {
2309
+ const { id, author, date } = runOpts.insertion;
2310
+ extra.push(`<w:ins w:id="${id}" w:author="${escapeXml(author)}" w:date="${date}"/>`);
2311
+ }
2312
+ if (runOpts.deletion) {
2313
+ const { id, author, date } = runOpts.deletion;
2314
+ extra.push(`<w:del w:id="${id}" w:author="${escapeXml(author)}" w:date="${date}"/>`);
2315
+ }
2316
+ const body = inner + extra.join("");
2317
+ parts.push(`<w:rPr>${body}</w:rPr>`);
2318
+ }
2319
+ }
2320
+ if (options.revision) {
2321
+ const rev = options.revision;
2322
+ const { author: _a, date: _d, id: _i, ...originalProps } = rev;
2323
+ const inner = stringifyParagraphProperties({
2324
+ ...originalProps,
2325
+ includeIfEmpty: true
2326
+ });
2327
+ parts.push(`<w:pPrChange w:author="${escapeXml(rev.author)}" w:date="${rev.date}" w:id="${rev.id}">${inner.xml ?? "<w:pPr/>"}</w:pPrChange>`);
2328
+ }
2329
+ const body = parts.join("");
2330
+ return {
2331
+ xml: options.includeIfEmpty || body.length > 0 ? `<w:pPr>${body}</w:pPr>` : void 0,
2332
+ numberingReferences
2333
+ };
2334
+ }
2335
+ /**
2336
+ * Build the inner content of `<w:rPr>` as a string.
2337
+ * Returns undefined if no properties are set.
2338
+ */
2339
+ function stringifyRunPropertiesInner(opts) {
2340
+ if (!opts) return void 0;
2341
+ const parts = [];
2342
+ if (opts.style) parts.push(`<w:rStyle w:val="${escapeXml(opts.style)}"/>`);
2343
+ if (opts.font) if (typeof opts.font === "string") parts.push(runFontsStr(opts.font));
2344
+ else if ("name" in opts.font) parts.push(runFontsStr(opts.font.name, opts.font.hint));
2345
+ else parts.push(runFontsStr(opts.font));
2346
+ if (opts.bold !== void 0) parts.push(onOff("w:b", opts.bold));
2347
+ if ((opts.boldComplexScript === void 0 && opts.bold !== void 0 || opts.boldComplexScript) !== void 0) parts.push(onOff("w:bCs", opts.boldComplexScript ?? opts.bold));
2348
+ if (opts.italic !== void 0) parts.push(onOff("w:i", opts.italic));
2349
+ if ((opts.italicComplexScript === void 0 && opts.italic !== void 0 || opts.italicComplexScript) !== void 0) parts.push(onOff("w:iCs", opts.italicComplexScript ?? opts.italic));
2350
+ if (opts.smallCaps !== void 0) parts.push(onOff("w:smallCaps", opts.smallCaps));
2351
+ else if (opts.allCaps !== void 0) parts.push(onOff("w:caps", opts.allCaps));
2352
+ if (opts.strike !== void 0) parts.push(onOff("w:strike", opts.strike));
2353
+ if (opts.doubleStrike !== void 0) parts.push(onOff("w:dstrike", opts.doubleStrike));
2354
+ if (opts.emboss !== void 0) parts.push(onOff("w:emboss", opts.emboss));
2355
+ if (opts.imprint !== void 0) parts.push(onOff("w:imprint", opts.imprint));
2356
+ if (opts.outline !== void 0) parts.push(onOff("w:outline", opts.outline));
2357
+ if (opts.shadow !== void 0) parts.push(onOff("w:shadow", opts.shadow));
2358
+ if (opts.webHidden !== void 0) parts.push(onOff("w:webHidden", opts.webHidden));
2359
+ if (opts.noProof !== void 0) parts.push(onOff("w:noProof", opts.noProof));
2360
+ if (opts.snapToGrid !== void 0) parts.push(onOff("w:snapToGrid", opts.snapToGrid));
2361
+ if (opts.vanish) parts.push(onOff("w:vanish", opts.vanish));
2362
+ if (opts.color) parts.push(colorStr(opts.color));
2363
+ if (opts.characterSpacing) parts.push(`<w:spacing w:val="${signedTwipsMeasureValue(opts.characterSpacing)}"/>`);
2364
+ if (opts.scale !== void 0) parts.push(`<w:w w:val="${opts.scale}"/>`);
2365
+ if (opts.kern) parts.push(`<w:kern w:val="${hpsMeasureValue(opts.kern)}"/>`);
2366
+ if (opts.position) parts.push(`<w:position w:val="${opts.position}"/>`);
2367
+ if (opts.size !== void 0) parts.push(`<w:sz w:val="${hpsMeasureValue(opts.size * 2)}"/>`);
2368
+ const szCs = opts.sizeComplexScript === void 0 || opts.sizeComplexScript === true ? opts.size : opts.sizeComplexScript;
2369
+ if (szCs) parts.push(`<w:szCs w:val="${hpsMeasureValue(szCs * 2)}"/>`);
2370
+ if (opts.highlight) parts.push(`<w:highlight w:val="${opts.highlight}"/>`);
2371
+ if (opts.highlightComplexScript === true) {
2372
+ if (opts.highlight) parts.push(`<w:highlightCs w:val="${opts.highlight}"/>`);
2373
+ } else if (opts.highlightComplexScript !== void 0 && opts.highlightComplexScript !== false) parts.push(`<w:highlightCs w:val="${opts.highlightComplexScript}"/>`);
2374
+ if (opts.underline) parts.push(underlineStr(opts.underline.type, opts.underline.color));
2375
+ if (opts.effect) parts.push(`<w:effect w:val="${opts.effect}"/>`);
2376
+ if (opts.border) parts.push(borderStr("w:bdr", opts.border));
2377
+ if (opts.shading) parts.push(shadingStr(opts.shading));
2378
+ if (opts.subScript) parts.push("<w:vertAlign w:val=\"subscript\"/>");
2379
+ if (opts.superScript) parts.push("<w:vertAlign w:val=\"superscript\"/>");
2380
+ if (opts.rightToLeft !== void 0) parts.push(onOff("w:rtl", opts.rightToLeft));
2381
+ if (opts.emphasisMark) parts.push(`<w:em w:val="${opts.emphasisMark.type ?? "dot"}"/>`);
2382
+ if (opts.language) parts.push(languageStr(opts.language));
2383
+ if (opts.specVanish) parts.push("<w:specVanish/>");
2384
+ if (opts.math) parts.push(onOff("w:oMath", opts.math));
2385
+ if (opts.fitText !== void 0) parts.push(`<w:fitText w:val="${opts.fitText}"/>`);
2386
+ if (opts.complexScript !== void 0) parts.push(onOff("w:cs", opts.complexScript));
2387
+ if (opts.eastAsianLayout) parts.push(eastAsianLayoutStr(opts.eastAsianLayout));
2388
+ if (opts.contentPartRId) parts.push(`<w:contentPart r:id="${opts.contentPartRId}"/>`);
2389
+ if (opts.revision) {
2390
+ const rev = opts.revision;
2391
+ const { author: _a, date: _d, id: _i, ...originalProps } = rev;
2392
+ const inner = stringifyRunPropertiesInner(originalProps);
2393
+ parts.push(`<w:rPrChange w:author="${escapeXml(rev.author)}" w:date="${rev.date}" w:id="${rev.id}"><w:rPr>${inner ?? ""}</w:rPr></w:rPrChange>`);
2394
+ }
2395
+ return parts.length > 0 ? parts.join("") : void 0;
2396
+ }
2397
+ /**
2398
+ * Build `<w:rPr>` XML string directly from options — zero IXmlableObject allocation.
2399
+ *
2400
+ * Replaces `buildRunProperties() + xml()` with a single-pass string builder.
2401
+ */
2402
+ function stringifyRunProperties(opts) {
2403
+ const inner = stringifyRunPropertiesInner(opts);
2404
+ return inner ? `<w:rPr>${inner}</w:rPr>` : void 0;
2405
+ }
2406
+ //#endregion
2407
+ //#region src/parts/inline.ts
2408
+ /**
2409
+ * Shared inline run/paragraph stringification for DOCX descriptors.
2410
+ *
2411
+ * Used by table.ts, comments.ts, body.ts, and other descriptors that need to
2412
+ * serialize paragraph/run content. Includes JSON child dispatch for all
2413
+ * IParagraphJsonChild variants (image, chart, hyperlink, etc.).
2414
+ *
2415
+ * Pure string concatenation — zero IXmlableObject, zero BaseXmlComponent.
2416
+ *
2417
+ * @module
2418
+ */
2419
+ function stringifyRunInline(opts, ctx) {
2420
+ const parts = [];
2421
+ const rPr = stringifyRunProperties(opts);
2422
+ if (rPr) parts.push(rPr);
2423
+ if (opts.break) for (let i = 0; i < opts.break; i++) parts.push("<w:br/>");
2424
+ if (opts.children) for (const child of opts.children) if (typeof child === "string") parts.push(`<w:t xml:space="preserve">${escapeXml(child)}</w:t>`);
2425
+ else {
2426
+ const jsonResult = stringifyJsonChild(child, ctx);
2427
+ if (jsonResult !== void 0) if (Array.isArray(jsonResult)) parts.push(...jsonResult);
2428
+ else parts.push(jsonResult);
2429
+ else if ("text" in child || "children" in child || "break" in child) parts.push(stringifyRunInline(child, ctx));
2430
+ }
2431
+ else if (opts.text !== void 0) parts.push(`<w:t xml:space="preserve">${escapeXml(String(opts.text))}</w:t>`);
2432
+ const rsidAttrs = [];
2433
+ if (opts.rsidRPr) rsidAttrs.push(` w:rsidRPr="${opts.rsidRPr}"`);
2434
+ if (opts.rsidDel) rsidAttrs.push(` w:rsidDel="${opts.rsidDel}"`);
2435
+ const attr = rsidAttrs.join("");
2436
+ const body = parts.join("");
2437
+ return body.length === 0 ? attr ? `<w:r${attr}/>` : "<w:r/>" : `<w:r${attr}>${body}</w:r>`;
2438
+ }
2439
+ function createImageData(data, transformation, key, srcRect) {
2440
+ return {
2441
+ data,
2442
+ fileName: key,
2443
+ srcRect,
2444
+ transformation: createTransformation(transformation)
2445
+ };
2446
+ }
2447
+ let nextChartId = 1;
2448
+ function stringifyJsonChild(child, ctx) {
2449
+ if ("pageBreak" in child) return "<w:r><w:br w:type=\"page\"/></w:r>";
2450
+ if ("columnBreak" in child) return "<w:r><w:br w:type=\"column\"/></w:r>";
2451
+ if ("tab" in child) return "<w:r><w:tab/></w:r>";
2452
+ if ("footnoteReference" in child) return `<w:r><w:rPr><w:rStyle w:val="FootnoteReference"/></w:rPr><w:footnoteReference w:id="${child.footnoteReference}"/></w:r>`;
2453
+ if ("endnoteReference" in child) return `<w:r><w:rPr><w:rStyle w:val="EndnoteReference"/></w:rPr><w:endnoteReference w:id="${child.endnoteReference}"/></w:r>`;
2454
+ if ("commentRangeStart" in child) return `<w:commentRangeStart w:id="${child.commentRangeStart}"/>`;
2455
+ if ("commentRangeEnd" in child) return `<w:commentRangeEnd w:id="${child.commentRangeEnd}"/>`;
2456
+ if ("commentReference" in child) return `<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="${child.commentReference}"/></w:r>`;
2457
+ if ("bookmarkStart" in child) return `<w:bookmarkStart w:id="${child.bookmarkStart.id}" w:name="${child.bookmarkStart.name}"/>`;
2458
+ if ("bookmarkEnd" in child) return `<w:bookmarkEnd w:id="${child.bookmarkEnd}"/>`;
2459
+ if ("symbolRun" in child) {
2460
+ const opts = child.symbolRun;
2461
+ return stringifyRunInline({
2462
+ ...opts,
2463
+ children: [`<w:sym w:char="${opts.char}" w:font="${opts.symbolfont ?? "Wingdings"}"/>`]
2464
+ }, ctx);
2465
+ }
2466
+ if ("image" in child) {
2467
+ const opts = child.image;
2468
+ const key = `${uniqueId()}.${opts.type}`;
2469
+ const rawData = toUint8Array(opts.data);
2470
+ let mediaData;
2471
+ if (opts.type === "svg") {
2472
+ const fallbackData = toUint8Array(opts.fallback.data);
2473
+ mediaData = {
2474
+ type: "svg",
2475
+ ...createImageData(rawData, opts.transformation, key, opts.srcRect),
2476
+ fallback: {
2477
+ type: opts.fallback.type,
2478
+ ...createImageData(fallbackData, opts.transformation, `${uniqueId()}.${opts.fallback.type}`)
2479
+ }
2480
+ };
2481
+ } else mediaData = {
2482
+ type: opts.type,
2483
+ ...createImageData(rawData, opts.transformation, key, opts.srcRect)
2484
+ };
2485
+ ctx.file.media.addImage(mediaData.fileName, mediaData);
2486
+ if (mediaData.type === "svg") ctx.file.media.addImage(mediaData.fallback.fileName, mediaData.fallback);
2487
+ return `<w:r>${drawingDesc.stringify({
2488
+ mediaData,
2489
+ docProperties: opts.altText,
2490
+ floating: opts.floating
2491
+ }, ctx)}</w:r>`;
2492
+ }
2493
+ if ("chart" in child) {
2494
+ const opts = child.chart;
2495
+ const chartKey = `chart_${nextChartId++}`;
2496
+ const mediaData = {
2497
+ chartKey,
2498
+ transformation: createTransformation(opts.transformation),
2499
+ type: "chart"
2500
+ };
2501
+ const chartXml = chartSpaceDesc.stringify({
2502
+ categories: opts.categories,
2503
+ series: opts.series,
2504
+ showLegend: opts.showLegend,
2505
+ style: opts.style,
2506
+ title: opts.title,
2507
+ type: opts.type,
2508
+ threeD: opts.threeD
2509
+ }, ctx.file);
2510
+ ctx.file.charts.addChart(chartKey, {
2511
+ key: chartKey,
2512
+ chartSpaceXml: chartXml ?? ""
2513
+ });
2514
+ return `<w:r>${drawingDesc.stringify({
2515
+ mediaData,
2516
+ docProperties: opts.altText,
2517
+ floating: opts.floating
2518
+ }, ctx)}</w:r>`;
2519
+ }
2520
+ if ("smartArt" in child) {
2521
+ const opts = child.smartArt;
2522
+ const smartArtKey = `smartart_${hashSmartArtData(opts)}`;
2523
+ const mediaData = {
2524
+ smartArtKey,
2525
+ transformation: createTransformation(opts.transformation),
2526
+ type: "smartart"
2527
+ };
2528
+ const layoutId = opts.layout ?? "default";
2529
+ const styleId = opts.style ?? "simple1";
2530
+ const colorId = opts.color ?? "accent1_2";
2531
+ const dataModelXml = createDataModel(opts.data.nodes, layoutId, styleId, colorId);
2532
+ ctx.file.smartArts.addSmartArt(smartArtKey, {
2533
+ dataModelXml,
2534
+ key: smartArtKey,
2535
+ layout: layoutId,
2536
+ style: styleId,
2537
+ color: colorId
2538
+ });
2539
+ return `<w:r>${drawingDesc.stringify({
2540
+ mediaData,
2541
+ docProperties: opts.altText,
2542
+ floating: opts.floating
2543
+ }, ctx)}</w:r>`;
2544
+ }
2545
+ if ("wpsShape" in child) {
2546
+ const opts = child.wpsShape;
2547
+ const mediaData = {
2548
+ data: opts,
2549
+ transformation: createTransformation(opts.transformation),
2550
+ type: "wps"
2551
+ };
2552
+ return `<w:r>${drawingDesc.stringify({
2553
+ mediaData,
2554
+ docProperties: opts.altText,
2555
+ floating: opts.floating,
2556
+ outline: opts.outline,
2557
+ fill: opts.fill
2558
+ }, ctx)}</w:r>`;
2559
+ }
2560
+ if ("ruby" in child && typeof child.ruby === "object" && child.ruby !== null) {
2561
+ const r = child.ruby;
2562
+ const align = r.alignment ?? "center";
2563
+ const hps = (r.fontSize ?? 10) * 2;
2564
+ const hpsRaise = (r.raise ?? 10) * 2;
2565
+ const hpsBaseText = (r.baseFontSize ?? 20) * 2;
2566
+ const lid = r.languageId ?? "ja-JP";
2567
+ const prParts = [
2568
+ `<w:rubyAlign w:val="${align}"/>`,
2569
+ `<w:hps w:val="${hps}"/>`,
2570
+ `<w:hpsRaise w:val="${hpsRaise}"/>`,
2571
+ `<w:hpsBaseText w:val="${hpsBaseText}"/>`,
2572
+ `<w:lid w:val="${lid}"/>`
2573
+ ];
2574
+ if (r.dirty) prParts.push("<w:dirty/>");
2575
+ const rt = `<w:rt><w:r><w:t xml:space="preserve">${escapeXml(r.text)}</w:t></w:r></w:rt>`;
2576
+ const rubyBase = `<w:rubyBase><w:r><w:t xml:space="preserve">${escapeXml(r.base)}</w:t></w:r></w:rubyBase>`;
2577
+ return `<w:ruby><w:rubyPr>${prParts.join("")}</w:rubyPr>${rt}${rubyBase}</w:ruby>`;
2578
+ }
2579
+ if ("math" in child && typeof child.math === "object" && child.math !== null) return stringifyMath(child.math.children ?? []);
2580
+ if ("insertion" in child) {
2581
+ const { id, author, date, ...runOpts } = child.insertion;
2582
+ const runXml = stringifyRunInline(runOpts, ctx);
2583
+ return `<w:ins w:id="${id}" w:author="${escapeXml(String(author))}" w:date="${date}">${runXml}</w:ins>`;
2584
+ }
2585
+ if ("deletion" in child) {
2586
+ const { id, author, date, ...runOpts } = child.deletion;
2587
+ const parts = [];
2588
+ const rPr = stringifyRunProperties(runOpts);
2589
+ if (rPr) parts.push(rPr);
2590
+ if (runOpts.break) for (let i = 0; i < runOpts.break; i++) parts.push("<w:br/>");
2591
+ if (runOpts.children) {
2592
+ for (const c of runOpts.children) if (typeof c === "string") {
2593
+ const instrText = {
2594
+ CURRENT: "PAGE",
2595
+ TOTAL_PAGES: "NUMPAGES",
2596
+ TOTAL_PAGES_IN_SECTION: "SECTIONPAGES"
2597
+ }[c];
2598
+ if (instrText) parts.push(`<w:fldChar w:fldCharType="begin"/><w:delInstrText xml:space="preserve">${instrText}</w:delInstrText><w:fldChar w:fldCharType="separate"/><w:fldChar w:fldCharType="end"/>`);
2599
+ else parts.push(`<w:delText xml:space="preserve">${escapeXml(c)}</w:delText>`);
2600
+ }
2601
+ } else if (runOpts.text) parts.push(`<w:delText xml:space="preserve">${escapeXml(String(runOpts.text))}</w:delText>`);
2602
+ const runBody = parts.join("");
2603
+ return `<w:del w:id="${id}" w:author="${escapeXml(String(author))}" w:date="${date}"><w:r>${runBody}</w:r></w:del>`;
2604
+ }
2605
+ if ("hyperlink" in child) {
2606
+ const hl = child.hyperlink;
2607
+ const childParts = [];
2608
+ if (hl.children) for (const rc of hl.children) if (typeof rc === "string") childParts.push(stringifyRunInline({ text: rc }, ctx));
2609
+ else childParts.push(stringifyRunInline(rc, ctx));
2610
+ const body = childParts.join("");
2611
+ if (hl.link) {
2612
+ const linkId = uniqueId();
2613
+ ctx.viewWrapper.relationships.addRelationship(linkId, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", hl.link, TargetModeType.EXTERNAL);
2614
+ const attrs = [`r:id="rId${linkId}"`, "w:history=\"1\""];
2615
+ if (hl.tooltip) attrs.push(`w:tooltip="${escapeXml(hl.tooltip)}"`);
2616
+ return `<w:hyperlink ${attrs.join(" ")}>${body}</w:hyperlink>`;
2617
+ }
2618
+ if (hl.anchor) {
2619
+ const attrs = [`w:anchor="${escapeXml(hl.anchor)}"`, "w:history=\"1\""];
2620
+ if (hl.tooltip) attrs.push(`w:tooltip="${escapeXml(hl.tooltip)}"`);
2621
+ return `<w:hyperlink ${attrs.join(" ")}>${body}</w:hyperlink>`;
2622
+ }
2623
+ return "";
2624
+ }
2625
+ if ("proofErr" in child) return `<w:proofErr w:type="${child.proofErr}"/>`;
2626
+ if ("positionalTab" in child) {
2627
+ const pt = child.positionalTab;
2628
+ return `<w:ptab w:alignment="${pt.alignment}" w:leader="${pt.leader}" w:relativeTo="${pt.relativeTo}"/>`;
2629
+ }
2630
+ if ("permStart" in child) {
2631
+ const ps = child.permStart;
2632
+ const a = [`w:id="${ps.id}"`];
2633
+ if (ps.ed !== void 0) a.push(`w:ed="${escapeXml(String(ps.ed))}"`);
2634
+ if (ps.editGroup !== void 0) a.push(`w:edGrp="${ps.editGroup}"`);
2635
+ if (ps.colFirst !== void 0) a.push(`w:colFirst="${ps.colFirst}"`);
2636
+ if (ps.colLast !== void 0) a.push(`w:colLast="${ps.colLast}"`);
2637
+ return `<w:permStart ${a.join(" ")}/>`;
2638
+ }
2639
+ if ("permEnd" in child) return `<w:permEnd w:id="${child.permEnd}"/>`;
2640
+ if ("moveFromRangeStart" in child) {
2641
+ const m = child.moveFromRangeStart;
2642
+ const a = [`w:id="${m.id}"`];
2643
+ if (m.name) a.push(`w:name="${escapeXml(m.name)}"`);
2644
+ if (m.author) a.push(`w:author="${escapeXml(m.author)}"`);
2645
+ if (m.date) a.push(`w:date="${m.date}"`);
2646
+ return `<w:moveFromRangeStart ${a.join(" ")}/>`;
2647
+ }
2648
+ if ("moveFromRangeEnd" in child) return `<w:moveFromRangeEnd w:id="${child.moveFromRangeEnd}"/>`;
2649
+ if ("moveToRangeStart" in child) {
2650
+ const m = child.moveToRangeStart;
2651
+ const a = [`w:id="${m.id}"`];
2652
+ if (m.name) a.push(`w:name="${escapeXml(m.name)}"`);
2653
+ if (m.author) a.push(`w:author="${escapeXml(m.author)}"`);
2654
+ if (m.date) a.push(`w:date="${m.date}"`);
2655
+ return `<w:moveToRangeStart ${a.join(" ")}/>`;
2656
+ }
2657
+ if ("moveToRangeEnd" in child) return `<w:moveToRangeEnd w:id="${child.moveToRangeEnd}"/>`;
2658
+ if ("movedFrom" in child) {
2659
+ const { id, author, date, ...runOpts } = child.movedFrom;
2660
+ const runXml = stringifyRunInline(runOpts, ctx);
2661
+ return `<w:moveFrom w:id="${id}" w:author="${escapeXml(String(author))}" w:date="${date}">${runXml}</w:moveFrom>`;
2662
+ }
2663
+ if ("movedTo" in child) {
2664
+ const { id, author, date, ...runOpts } = child.movedTo;
2665
+ const runXml = stringifyRunInline(runOpts, ctx);
2666
+ return `<w:moveTo w:id="${id}" w:author="${escapeXml(String(author))}" w:date="${date}">${runXml}</w:moveTo>`;
2667
+ }
2668
+ if ("customXmlInsRangeStart" in child) {
2669
+ const o = child.customXmlInsRangeStart;
2670
+ return `<w:customXmlInsRangeStart w:id="${o.id}" w:author="${escapeXml(o.author)}"${o.date ? ` w:date="${o.date}"` : ""}/>`;
2671
+ }
2672
+ if ("customXmlInsRangeEnd" in child) return `<w:customXmlInsRangeEnd w:id="${child.customXmlInsRangeEnd}"/>`;
2673
+ if ("customXmlDelRangeStart" in child) {
2674
+ const o = child.customXmlDelRangeStart;
2675
+ return `<w:customXmlDelRangeStart w:id="${o.id}" w:author="${escapeXml(o.author)}"${o.date ? ` w:date="${o.date}"` : ""}/>`;
2676
+ }
2677
+ if ("customXmlDelRangeEnd" in child) return `<w:customXmlDelRangeEnd w:id="${child.customXmlDelRangeEnd}"/>`;
2678
+ if ("customXmlMoveFromRangeStart" in child) {
2679
+ const o = child.customXmlMoveFromRangeStart;
2680
+ return `<w:customXmlMoveFromRangeStart w:id="${o.id}" w:author="${escapeXml(o.author)}"${o.date ? ` w:date="${o.date}"` : ""}/>`;
2681
+ }
2682
+ if ("customXmlMoveFromRangeEnd" in child) return `<w:customXmlMoveFromRangeEnd w:id="${child.customXmlMoveFromRangeEnd}"/>`;
2683
+ if ("customXmlMoveToRangeStart" in child) {
2684
+ const o = child.customXmlMoveToRangeStart;
2685
+ return `<w:customXmlMoveToRangeStart w:id="${o.id}" w:author="${escapeXml(o.author)}"${o.date ? ` w:date="${o.date}"` : ""}/>`;
2686
+ }
2687
+ if ("customXmlMoveToRangeEnd" in child) return `<w:customXmlMoveToRangeEnd w:id="${child.customXmlMoveToRangeEnd}"/>`;
2688
+ if ("simpleField" in child) {
2689
+ const sf = child.simpleField;
2690
+ if (sf.cachedValue !== void 0) return `<w:fldSimple w:instr="${escapeXml(sf.instruction)}"><w:r><w:t>${escapeXml(sf.cachedValue)}</w:t></w:r></w:fldSimple>`;
2691
+ return `<w:fldSimple w:instr="${escapeXml(sf.instruction)}"/>`;
2692
+ }
2693
+ if ("seqIdentifier" in child) {
2694
+ const id = child.seqIdentifier;
2695
+ return `<w:r><w:fldChar w:fldCharType="begin"/><w:instrText xml:space="preserve"> SEQ ${escapeXml(id)} </w:instrText><w:fldChar w:fldCharType="separate"/><w:fldChar w:fldCharType="end"/></w:r>`;
2696
+ }
2697
+ if ("pageReference" in child) {
2698
+ const pr = child.pageReference;
2699
+ let instr = ` PAGEREF ${escapeXml(pr.bookmarkId)} `;
2700
+ if (pr.hyperlink) instr += "\\h ";
2701
+ if (pr.useRelativePosition) instr += "\\p ";
2702
+ return `<w:r><w:fldChar w:fldCharType="begin"/><w:instrText xml:space="preserve">${instr}</w:instrText><w:fldChar w:fldCharType="end"/></w:r>`;
2703
+ }
2704
+ if ("dir" in child) {
2705
+ const d = child.dir;
2706
+ const childXml = serializeDirChildren(d.children, ctx);
2707
+ return `<w:dir w:val="${d.val}">${childXml}</w:dir>`;
2708
+ }
2709
+ if ("bdo" in child) {
2710
+ const b = child.bdo;
2711
+ const childXml = serializeDirChildren(b.children, ctx);
2712
+ return `<w:bdo w:val="${b.val}">${childXml}</w:bdo>`;
2713
+ }
2714
+ if ("smartTag" in child) {
2715
+ const st = child.smartTag;
2716
+ const attrs = [];
2717
+ if (st.uri) attrs.push(`w:uri="${escapeXml(st.uri)}"`);
2718
+ attrs.push(`w:element="${escapeXml(st.element)}"`);
2719
+ const parts = [];
2720
+ if (st.properties?.length) {
2721
+ const propParts = [];
2722
+ for (const p of st.properties) {
2723
+ const pa = [];
2724
+ if (p.uri) pa.push(`w:uri="${escapeXml(p.uri)}"`);
2725
+ pa.push(`w:name="${escapeXml(p.name)}"`, `w:val="${escapeXml(p.val)}"`);
2726
+ propParts.push(`<w:attr ${pa.join(" ")}/>`);
2727
+ }
2728
+ parts.push(`<w:smartTagPr>${propParts.join("")}</w:smartTagPr>`);
2729
+ }
2730
+ if (st.children) for (const c of st.children) parts.push(typeof c === "string" ? stringifyRunInline({ text: c }, ctx) : stringifyRunInline(c, ctx));
2731
+ return `<w:smartTag ${attrs.join(" ")}>${parts.join("")}</w:smartTag>`;
2732
+ }
2733
+ if ("customXml" in child) {
2734
+ const cx = child.customXml;
2735
+ const attrs = [`w:element="${escapeXml(cx.element)}"`];
2736
+ if (cx.uri) attrs.push(`w:uri="${escapeXml(cx.uri)}"`);
2737
+ const parts = [];
2738
+ if (cx.customXmlPr) {
2739
+ const prParts = [];
2740
+ if (cx.customXmlPr.placeholder) prParts.push(`<w:placeholder w:val="${escapeXml(cx.customXmlPr.placeholder)}"/>`);
2741
+ if (cx.customXmlPr.attrs?.length) for (const a of cx.customXmlPr.attrs) {
2742
+ const aa = [`w:name="${escapeXml(a.name)}"`, `w:val="${escapeXml(a.val)}"`];
2743
+ if (a.uri) aa.push(`w:uri="${escapeXml(a.uri)}"`);
2744
+ prParts.push(`<w:attr ${aa.join(" ")}/>`);
2745
+ }
2746
+ if (prParts.length) parts.push(`<w:customXmlPr>${prParts.join("")}</w:customXmlPr>`);
2747
+ }
2748
+ if (cx.children) for (const c of cx.children) if (typeof c === "string") parts.push(stringifyRunInline({ text: c }, ctx));
2749
+ else {
2750
+ const jr = stringifyJsonChild(c, ctx);
2751
+ if (jr !== void 0) parts.push(Array.isArray(jr) ? jr.join("") : jr);
2752
+ else parts.push(stringifyRunInline(c, ctx));
2753
+ }
2754
+ return `<w:customXml ${attrs.join(" ")}>${parts.join("")}</w:customXml>`;
2755
+ }
2756
+ }
2757
+ /** Serialize children of Dir/Bdo containers. */
2758
+ function serializeDirChildren(children, ctx) {
2759
+ if (!children) return "";
2760
+ const parts = [];
2761
+ for (const c of children) if (typeof c === "string") parts.push(stringifyRunInline({ text: c }, ctx));
2762
+ else parts.push(stringifyRunInline(c, ctx));
2763
+ return parts.join("");
2764
+ }
2765
+ /** Hash SmartArt data for unique key generation (duplicated from SmartArtRun). */
2766
+ function hashSmartArtData(options) {
2767
+ const data = JSON.stringify(options.data);
2768
+ let hash = 0;
2769
+ for (let i = 0; i < data.length; i++) {
2770
+ const char = data.charCodeAt(i);
2771
+ hash = (hash << 5) - hash + char | 0;
2772
+ }
2773
+ return Math.abs(hash);
2774
+ }
2775
+ function stringifyParagraphInline(opts, ctx) {
2776
+ const resolved = typeof opts === "string" ? { text: opts } : opts;
2777
+ const parts = [];
2778
+ const props = stringifyParagraphProperties(resolved);
2779
+ if (props.xml) parts.push(props.xml);
2780
+ if (props.numberingReferences.length > 0) for (const ref of props.numberingReferences) ctx.file.numbering.createConcreteNumberingInstance(ref.reference, ref.instance);
2781
+ if (resolved.text !== void 0) parts.push(stringifyRunInline({ text: resolved.text }, ctx));
2782
+ if (resolved.children) {
2783
+ for (const child of resolved.children) if (typeof child === "string") parts.push(stringifyRunInline({ text: child }, ctx));
2784
+ else if (typeof child === "object" && child !== null) {
2785
+ const jsonResult = stringifyJsonChild(child, ctx);
2786
+ if (jsonResult !== void 0) if (Array.isArray(jsonResult)) parts.push(...jsonResult);
2787
+ else parts.push(jsonResult);
2788
+ else if ("text" in child || "children" in child || "break" in child) parts.push(stringifyRunInline(child, ctx));
2789
+ }
2790
+ }
2791
+ const body = parts.join("");
2792
+ return body ? `<w:p>${body}</w:p>` : "<w:p/>";
2793
+ }
2794
+ //#endregion
2795
+ //#region src/parts/table/stringify.ts
2796
+ /**
2797
+ * Direct XML string builders for table properties.
2798
+ *
2799
+ * Replaces `buildTableProperties() + xml()`, `buildTableRowProperties() + xml()`,
2800
+ * `buildTableCellProperties() + xml()`, and `new TablePropertyExceptions().toXml()`
2801
+ * with direct string concatenation — zero IXmlableObject allocation.
2802
+ *
2803
+ * @module
2804
+ */
2805
+ function tableWidthStr(name, opts) {
2806
+ const type = opts.type ?? WidthType.AUTO;
2807
+ let w = opts.size;
2808
+ if (type === WidthType.PERCENTAGE && typeof w === "number") w = `${w}%`;
2809
+ return `<${name} ${attrParts({
2810
+ "w:w": w !== void 0 ? measurementOrPercentValue(w) : void 0,
2811
+ "w:type": type
2812
+ })}/>`;
2813
+ }
2814
+ function cellMarginChildrenStr(opts) {
2815
+ const unitType = opts.marginUnitType ?? WidthType.DXA;
2816
+ const parts = [];
2817
+ if (opts.top !== void 0) parts.push(tableWidthStr("w:top", {
2818
+ size: opts.top,
2819
+ type: unitType
2820
+ }));
2821
+ if (opts.left !== void 0) parts.push(tableWidthStr("w:left", {
2822
+ size: opts.left,
2823
+ type: unitType
2824
+ }));
2825
+ if (opts.bottom !== void 0) parts.push(tableWidthStr("w:bottom", {
2826
+ size: opts.bottom,
2827
+ type: unitType
2828
+ }));
2829
+ if (opts.right !== void 0) parts.push(tableWidthStr("w:right", {
2830
+ size: opts.right,
2831
+ type: unitType
2832
+ }));
2833
+ return parts.join("");
2834
+ }
2835
+ function cellMarginStr(tag, opts) {
2836
+ const inner = cellMarginChildrenStr(opts);
2837
+ return inner ? `<${tag}>${inner}</${tag}>` : void 0;
2838
+ }
2839
+ const DEFAULT_BORDER = {
2840
+ color: "auto",
2841
+ size: 4,
2842
+ style: BorderStyle.SINGLE
2843
+ };
2844
+ function tableBordersStr(opts) {
2845
+ const parts = [];
2846
+ parts.push(borderStr("w:top", opts.top ?? DEFAULT_BORDER));
2847
+ parts.push(borderStr("w:left", opts.left ?? DEFAULT_BORDER));
2848
+ parts.push(borderStr("w:bottom", opts.bottom ?? DEFAULT_BORDER));
2849
+ parts.push(borderStr("w:right", opts.right ?? DEFAULT_BORDER));
2850
+ parts.push(borderStr("w:insideH", opts.insideHorizontal ?? DEFAULT_BORDER));
2851
+ parts.push(borderStr("w:insideV", opts.insideVertical ?? DEFAULT_BORDER));
2852
+ return `<w:tblBorders>${parts.join("")}</w:tblBorders>`;
2853
+ }
2854
+ function cellBordersStr(opts) {
2855
+ const parts = [];
2856
+ if (opts.top) parts.push(borderStr("w:top", opts.top));
2857
+ if (opts.start) parts.push(borderStr("w:start", opts.start));
2858
+ if (opts.left) parts.push(borderStr("w:left", opts.left));
2859
+ if (opts.bottom) parts.push(borderStr("w:bottom", opts.bottom));
2860
+ if (opts.end) parts.push(borderStr("w:end", opts.end));
2861
+ if (opts.right) parts.push(borderStr("w:right", opts.right));
2862
+ if (opts.topLeftToBottomRight) parts.push(borderStr("w:tl2br", opts.topLeftToBottomRight));
2863
+ if (opts.topRightToBottomLeft) parts.push(borderStr("w:tr2bl", opts.topRightToBottomLeft));
2864
+ return parts.length > 0 ? `<w:tcBorders>${parts.join("")}</w:tcBorders>` : void 0;
2865
+ }
2866
+ function floatPropertiesStr(opts) {
2867
+ return `<w:tblpPr ${attrParts({
2868
+ "w:horzAnchor": opts.horizontalAnchor,
2869
+ "w:vertAnchor": opts.verticalAnchor,
2870
+ "w:tblpX": opts.absoluteHorizontalPosition !== void 0 ? signedTwipsMeasureValue(opts.absoluteHorizontalPosition) : void 0,
2871
+ "w:tblpXSpec": opts.relativeHorizontalPosition,
2872
+ "w:tblpY": opts.absoluteVerticalPosition !== void 0 ? signedTwipsMeasureValue(opts.absoluteVerticalPosition) : void 0,
2873
+ "w:tblpYSpec": opts.relativeVerticalPosition,
2874
+ "w:bottomFromText": opts.bottomFromText !== void 0 ? twipsMeasureValue(opts.bottomFromText) : void 0,
2875
+ "w:topFromText": opts.topFromText !== void 0 ? twipsMeasureValue(opts.topFromText) : void 0,
2876
+ "w:leftFromText": opts.leftFromText !== void 0 ? twipsMeasureValue(opts.leftFromText) : void 0,
2877
+ "w:rightFromText": opts.rightFromText !== void 0 ? twipsMeasureValue(opts.rightFromText) : void 0
2878
+ })}/>`;
2879
+ }
2880
+ function tableLookStr(opts) {
2881
+ return `<w:tblLook ${attrParts({
2882
+ "w:firstRow": opts.firstRow,
2883
+ "w:lastRow": opts.lastRow,
2884
+ "w:firstColumn": opts.firstColumn,
2885
+ "w:lastColumn": opts.lastColumn,
2886
+ "w:noHBand": opts.noHBand,
2887
+ "w:noVBand": opts.noVBand
2888
+ })}/>`;
2889
+ }
2890
+ function changeAttrStr(tag, opts) {
2891
+ return `<${tag} ${attrParts({
2892
+ "w:author": opts.author,
2893
+ "w:date": opts.date,
2894
+ "w:id": opts.id
2895
+ })}/>`;
2896
+ }
2897
+ function cellMergeStr(opts) {
2898
+ const attrs = {
2899
+ "w:author": opts.author,
2900
+ "w:date": opts.date,
2901
+ "w:id": opts.id
2902
+ };
2903
+ if (opts.verticalMerge !== void 0) attrs["w:vMerge"] = xsdVerticalMergeRev.to(opts.verticalMerge);
2904
+ if (opts.verticalMergeOriginal !== void 0) attrs["w:vMergeOrig"] = xsdVerticalMergeRev.to(opts.verticalMergeOriginal);
2905
+ return `<w:cellMerge ${attrParts(attrs)}/>`;
2906
+ }
2907
+ function cellSpacingStr(opts) {
2908
+ return `<w:tblCellSpacing ${attrParts({
2909
+ "w:type": opts.type,
2910
+ "w:w": measurementOrPercentValue(opts.value)
2911
+ })}/>`;
2912
+ }
2913
+ function stringifyTablePropertiesChangeInner(options) {
2914
+ const inner = stringifyTablePropertiesInner({
2915
+ ...options,
2916
+ includeIfEmpty: true
2917
+ });
2918
+ return `<w:tblPrChange ${attrParts({
2919
+ "w:author": options.author,
2920
+ "w:date": options.date,
2921
+ "w:id": options.id
2922
+ })}><w:tblPr>${inner}</w:tblPr></w:tblPrChange>`;
2923
+ }
2924
+ function stringifyTablePropertiesInner(options) {
2925
+ const parts = [];
2926
+ if (options.style) parts.push(`<w:tblStyle w:val="${options.style}"/>`);
2927
+ if (options.float) {
2928
+ parts.push(floatPropertiesStr(options.float));
2929
+ if (options.float.overlap) parts.push(`<w:tblOverlap w:val="${options.float.overlap}"/>`);
2930
+ }
2931
+ if (options.visuallyRightToLeft !== void 0) parts.push(onOff("w:bidiVisual", options.visuallyRightToLeft));
2932
+ if (options.styleRowBandSize !== void 0) parts.push(`<w:tblStyleRowBandSize w:val="${options.styleRowBandSize}"/>`);
2933
+ if (options.styleColBandSize !== void 0) parts.push(`<w:tblStyleColBandSize w:val="${options.styleColBandSize}"/>`);
2934
+ if (options.width) parts.push(tableWidthStr("w:tblW", options.width));
2935
+ if (options.alignment) parts.push(`<w:jc w:val="${options.alignment}"/>`);
2936
+ if (options.indent) parts.push(tableWidthStr("w:tblInd", options.indent));
2937
+ if (options.borders) parts.push(tableBordersStr(options.borders));
2938
+ if (options.shading) parts.push(shadingStr(options.shading));
2939
+ if (options.layout) parts.push(`<w:tblLayout w:type="${options.layout}"/>`);
2940
+ if (options.cellMargin) {
2941
+ const cm = cellMarginStr("w:tblCellMar", options.cellMargin);
2942
+ if (cm) parts.push(cm);
2943
+ }
2944
+ if (options.tableLook) parts.push(tableLookStr(options.tableLook));
2945
+ if (options.cellSpacing) parts.push(cellSpacingStr(options.cellSpacing));
2946
+ if (options.caption !== void 0) parts.push(`<w:tblCaption w:val="${options.caption}"/>`);
2947
+ if (options.description !== void 0) parts.push(`<w:tblDescription w:val="${options.description}"/>`);
2948
+ if (options.revision) parts.push(stringifyTablePropertiesChangeInner(options.revision));
2949
+ return parts.join("");
2950
+ }
2951
+ function stringifyTableProperties(options) {
2952
+ const inner = stringifyTablePropertiesInner(options);
2953
+ if (options.includeIfEmpty || inner) return `<w:tblPr>${inner}</w:tblPr>`;
2954
+ }
2955
+ function stringifyTableRowPropertiesChangeInner(options) {
2956
+ const inner = stringifyTableRowPropertiesInner({
2957
+ ...options,
2958
+ includeIfEmpty: true
2959
+ });
2960
+ return `<w:trPrChange ${attrParts({
2961
+ "w:author": options.author,
2962
+ "w:date": options.date,
2963
+ "w:id": options.id
2964
+ })}><w:trPr>${inner}</w:trPr></w:trPrChange>`;
2965
+ }
2966
+ function stringifyTableRowPropertiesInner(options) {
2967
+ const parts = [];
2968
+ if (options.cnfStyle !== void 0) {
2969
+ const a = attrParts({
2970
+ "w:val": options.cnfStyle.val,
2971
+ "w:changed": options.cnfStyle.changed
2972
+ });
2973
+ parts.push(`<w:cnfStyle ${a}/>`);
2974
+ }
2975
+ if (options.divId !== void 0) parts.push(`<w:divId w:val="${options.divId}"/>`);
2976
+ if (options.gridBefore !== void 0) parts.push(`<w:gridBefore w:val="${options.gridBefore}"/>`);
2977
+ if (options.gridAfter !== void 0) parts.push(`<w:gridAfter w:val="${options.gridAfter}"/>`);
2978
+ if (options.widthBefore) parts.push(tableWidthStr("w:wBefore", options.widthBefore));
2979
+ if (options.widthAfter) parts.push(tableWidthStr("w:wAfter", options.widthAfter));
2980
+ if (options.cantSplit !== void 0) parts.push(onOff("w:cantSplit", options.cantSplit));
2981
+ if (options.tableHeader !== void 0) parts.push(onOff("w:tblHeader", options.tableHeader));
2982
+ if (options.height) {
2983
+ const a = attrParts({
2984
+ "w:val": twipsMeasureValue(options.height.value),
2985
+ "w:hRule": options.height.rule
2986
+ });
2987
+ parts.push(`<w:trHeight ${a}/>`);
2988
+ }
2989
+ if (options.cellSpacing) parts.push(cellSpacingStr(options.cellSpacing));
2990
+ if (options.rowAlignment) parts.push(`<w:jc w:val="${options.rowAlignment}"/>`);
2991
+ if (options.hidden !== void 0) parts.push(onOff("w:hidden", options.hidden));
2992
+ if (options.insertion) parts.push(changeAttrStr("w:ins", options.insertion));
2993
+ if (options.deletion) parts.push(changeAttrStr("w:del", options.deletion));
2994
+ if (options.revision) parts.push(stringifyTableRowPropertiesChangeInner(options.revision));
2995
+ return parts.join("");
2996
+ }
2997
+ function stringifyTableRowProperties(options) {
2998
+ const inner = stringifyTableRowPropertiesInner(options);
2999
+ if (options.includeIfEmpty || inner) return `<w:trPr>${inner}</w:trPr>`;
3000
+ }
3001
+ function stringifyTableCellPropertiesChangeInner(options) {
3002
+ const inner = stringifyTableCellPropertiesInner({
3003
+ ...options,
3004
+ includeIfEmpty: true
3005
+ });
3006
+ return `<w:tcPrChange ${attrParts({
3007
+ "w:author": options.author,
3008
+ "w:date": options.date,
3009
+ "w:id": options.id
3010
+ })}><w:tcPr>${inner}</w:tcPr></w:tcPrChange>`;
3011
+ }
3012
+ function stringifyTableCellPropertiesInner(options) {
3013
+ const parts = [];
3014
+ if (options.cnfStyle !== void 0) {
3015
+ const a = attrParts({
3016
+ "w:val": options.cnfStyle.val,
3017
+ "w:changed": options.cnfStyle.changed
3018
+ });
3019
+ parts.push(`<w:cnfStyle ${a}/>`);
3020
+ }
3021
+ if (options.width) parts.push(tableWidthStr("w:tcW", options.width));
3022
+ if (options.columnSpan) parts.push(`<w:gridSpan w:val="${options.columnSpan}"/>`);
3023
+ if (options.verticalMerge) parts.push(`<w:vMerge w:val="${options.verticalMerge}"/>`);
3024
+ else if (options.rowSpan && options.rowSpan > 1) parts.push(`<w:vMerge w:val="${VerticalMergeType.RESTART}"/>`);
3025
+ if (options.borders) {
3026
+ const bs = cellBordersStr(options.borders);
3027
+ if (bs) parts.push(bs);
3028
+ }
3029
+ if (options.shading) parts.push(shadingStr(options.shading));
3030
+ if (options.margins) {
3031
+ const cm = cellMarginStr("w:tcMar", options.margins);
3032
+ if (cm) parts.push(cm);
3033
+ }
3034
+ if (options.textDirection) parts.push(`<w:textDirection w:val="${options.textDirection}"/>`);
3035
+ if (options.verticalAlign) parts.push(`<w:vAlign w:val="${options.verticalAlign}"/>`);
3036
+ if (options.horizontalMerge !== void 0) if (options.horizontalMerge === "restart") parts.push(`<w:hMerge w:val="restart"/>`);
3037
+ else parts.push(`<w:hMerge/>`);
3038
+ if (options.noWrap !== void 0) parts.push(onOff("w:noWrap", options.noWrap));
3039
+ if (options.fitText !== void 0) parts.push(onOff("w:tcFitText", options.fitText));
3040
+ if (options.hideMark !== void 0) parts.push(onOff("w:hideMark", options.hideMark));
3041
+ if (options.headers !== void 0) {
3042
+ const headerParts = options.headers.map((h) => `<w:header w:val="${h}"/>`).join("");
3043
+ parts.push(`<w:headers>${headerParts}</w:headers>`);
3044
+ }
3045
+ if (options.insertion) parts.push(changeAttrStr("w:cellIns", options.insertion));
3046
+ if (options.deletion) parts.push(changeAttrStr("w:cellDel", options.deletion));
3047
+ if (options.revision) parts.push(stringifyTableCellPropertiesChangeInner(options.revision));
3048
+ if (options.cellMerge) parts.push(cellMergeStr(options.cellMerge));
3049
+ return parts.join("");
3050
+ }
3051
+ function stringifyTableCellProperties(options) {
3052
+ const inner = stringifyTableCellPropertiesInner(options);
3053
+ if (options.includeIfEmpty || inner) return `<w:tcPr>${inner}</w:tcPr>`;
3054
+ }
3055
+ function stringifyTablePropertyExceptions(options) {
3056
+ const parts = [];
3057
+ if (options.width) parts.push(tableWidthStr("w:tblW", options.width));
3058
+ if (options.alignment) parts.push(`<w:jc w:val="${options.alignment}"/>`);
3059
+ if (options.cellSpacing) parts.push(cellSpacingStr(options.cellSpacing));
3060
+ if (options.indent) parts.push(tableWidthStr("w:tblInd", options.indent));
3061
+ if (options.borders) parts.push(tableBordersStr(options.borders));
3062
+ if (options.shading) parts.push(shadingStr(options.shading));
3063
+ if (options.layout) parts.push(`<w:tblLayout w:type="${options.layout}"/>`);
3064
+ if (options.cellMargin) {
3065
+ const cm = cellMarginStr("w:tblCellMar", options.cellMargin);
3066
+ if (cm) parts.push(cm);
3067
+ }
3068
+ if (options.tableLook) parts.push(tableLookStr(options.tableLook));
3069
+ if (options.tblPrExChange) {
3070
+ const change = options.tblPrExChange;
3071
+ const attrs = {
3072
+ "w:author": change.author,
3073
+ "w:id": change.id
3074
+ };
3075
+ if (change.date !== void 0) attrs["w:date"] = change.date;
3076
+ const a = attrParts(attrs);
3077
+ parts.push(`<w:tblPrExChange ${a}/>`);
3078
+ }
3079
+ return `<w:tblPrEx>${parts.join("")}</w:tblPrEx>`;
3080
+ }
3081
+ //#endregion
3082
+ //#region src/parts/table/descriptor.ts
3083
+ function buildTableGridXml(widths, revision) {
3084
+ const cols = widths.map((w) => `<w:gridCol w:w="${w}"/>`).join("");
3085
+ if (revision) {
3086
+ const revCols = revision.columnWidths.map((w) => `<w:gridCol w:w="${w}"/>`).join("");
3087
+ return `<w:tblGrid>${cols}<w:tblGridChange w:id="${revision.id}"><w:tblGrid>${revCols}</w:tblGrid></w:tblGridChange></w:tblGrid>`;
3088
+ }
3089
+ return `<w:tblGrid>${cols}</w:tblGrid>`;
3090
+ }
3091
+ /** Extract column/row span from a plain-object cell. */
3092
+ function getCellSpans(cell) {
3093
+ return {
3094
+ columnSpan: cell.columnSpan ?? 1,
3095
+ rowSpan: cell.rowSpan ?? 1
3096
+ };
3097
+ }
3098
+ /**
3099
+ * Stringify a cell child (SectionChild) inline.
3100
+ * Handles strings and plain objects (paragraph/table).
3101
+ */
3102
+ function stringifyCellChild(child, ctx) {
3103
+ if (typeof child === "string") return stringifyParagraphInline(child, ctx);
3104
+ if ("paragraph" in child) return stringifyParagraphInline(child.paragraph, ctx);
3105
+ if ("table" in child) return tableDesc.stringify(child.table, ctx) ?? "";
3106
+ return "";
3107
+ }
3108
+ function stringifyTableCell(cell, ctx) {
3109
+ const parts = [];
3110
+ const tcPr = stringifyTableCellProperties(cell);
3111
+ if (tcPr) parts.push(tcPr);
3112
+ const children = cell.children;
3113
+ if (children) for (const child of children) parts.push(stringifyCellChild(child, ctx));
3114
+ const last = children?.[children.length - 1];
3115
+ if (!(last && typeof last !== "string" && ("paragraph" in last || "table" in last))) parts.push("<w:p/>");
3116
+ return `<w:tc>${parts.join("")}</w:tc>`;
3117
+ }
3118
+ function stringifyTableRow(row, ctx, extraCells) {
3119
+ const parts = [];
3120
+ if (row.propertyExceptions) parts.push(stringifyTablePropertyExceptions(row.propertyExceptions));
3121
+ const trPr = stringifyTableRowProperties(row);
3122
+ if (trPr) parts.push(trPr);
3123
+ const prefixCount = parts.length;
3124
+ for (const cell of row.cells) parts.push(stringifyTableCell(cell, ctx));
3125
+ if (extraCells && extraCells.length > 0) for (const { cell, columnIndex } of extraCells) {
3126
+ const insertIdx = findInsertIndex(row.cells, columnIndex, prefixCount);
3127
+ parts.splice(insertIdx, 0, stringifyTableCell(cell, ctx));
3128
+ }
3129
+ const rsidAttrs = [];
3130
+ if (row.rsidRPr) rsidAttrs.push(` w:rsidRPr="${row.rsidRPr}"`);
3131
+ if (row.rsidR) rsidAttrs.push(` w:rsidR="${row.rsidR}"`);
3132
+ if (row.rsidDel) rsidAttrs.push(` w:rsidDel="${row.rsidDel}"`);
3133
+ if (row.rsidTr) rsidAttrs.push(` w:rsidTr="${row.rsidTr}"`);
3134
+ const attr = rsidAttrs.join("");
3135
+ const body = parts.join("");
3136
+ return body ? `<w:tr${attr}>${body}</w:tr>` : attr ? `<w:tr${attr}/>` : "<w:tr/>";
3137
+ }
3138
+ function findInsertIndex(cells, columnIndex, prefixCount) {
3139
+ let colIdx = 0;
3140
+ for (let i = 0; i < cells.length; i++) {
3141
+ const { columnSpan } = getCellSpans(cells[i]);
3142
+ colIdx += columnSpan;
3143
+ if (colIdx > columnIndex) return i + prefixCount;
3144
+ }
3145
+ return cells.length + prefixCount;
3146
+ }
3147
+ /**
3148
+ * Pre-process rows to compute CONTINUE cells for vertical merge.
3149
+ */
3150
+ function computeVerticalMergeCells(rows) {
3151
+ const extraMap = /* @__PURE__ */ new Map();
3152
+ for (let ri = 0; ri < rows.length - 1; ri++) {
3153
+ const cells = rows[ri].cells;
3154
+ let colIdx = 0;
3155
+ for (const cell of cells) {
3156
+ const typedCell = cell;
3157
+ const { columnSpan, rowSpan } = getCellSpans(typedCell);
3158
+ if (rowSpan > 1) {
3159
+ const continueCell = {
3160
+ borders: typedCell.borders,
3161
+ children: [],
3162
+ columnSpan,
3163
+ rowSpan: rowSpan - 1,
3164
+ verticalMerge: VerticalMergeType.CONTINUE
3165
+ };
3166
+ if (!extraMap.has(ri + 1)) extraMap.set(ri + 1, []);
3167
+ extraMap.get(ri + 1).push({
3168
+ cell: continueCell,
3169
+ columnIndex: colIdx
3170
+ });
3171
+ }
3172
+ colIdx += columnSpan;
3173
+ }
3174
+ }
3175
+ return extraMap;
3176
+ }
3177
+ const tableDesc = {
3178
+ kind: "custom",
3179
+ stringify(opts, ctx) {
3180
+ const parts = [];
3181
+ const tblPr = stringifyTableProperties({
3182
+ alignment: opts.alignment,
3183
+ borders: opts.borders ?? {},
3184
+ caption: opts.caption,
3185
+ cellMargin: opts.margins,
3186
+ cellSpacing: opts.cellSpacing,
3187
+ description: opts.description,
3188
+ float: opts.float,
3189
+ indent: opts.indent,
3190
+ layout: opts.layout,
3191
+ revision: opts.revision,
3192
+ style: opts.style,
3193
+ styleColBandSize: opts.styleColBandSize,
3194
+ styleRowBandSize: opts.styleRowBandSize,
3195
+ tableLook: opts.tableLook,
3196
+ visuallyRightToLeft: opts.visuallyRightToLeft,
3197
+ width: opts.width ?? { size: 100 }
3198
+ });
3199
+ if (tblPr) parts.push(tblPr);
3200
+ const columnWidths = opts.columnWidths ?? Array(Math.max(...opts.rows.map((r) => r.cells.length))).fill(100);
3201
+ parts.push(buildTableGridXml(columnWidths, opts.columnWidthsRevision));
3202
+ const extraCells = computeVerticalMergeCells(opts.rows);
3203
+ for (let ri = 0; ri < opts.rows.length; ri++) {
3204
+ const row = opts.rows[ri];
3205
+ const extras = extraCells.get(ri);
3206
+ parts.push(stringifyTableRow(row, ctx, extras));
3207
+ }
3208
+ return `<w:tbl>${parts.join("")}</w:tbl>`;
3209
+ },
3210
+ parse(el, ctx) {
3211
+ return parseTableEl(el, ctx);
3212
+ }
3213
+ };
3214
+ /** Callback used by table parser to parse body children. */
3215
+ let _parseChild;
3216
+ /** Set the child parser callback (called from parseBody). */
3217
+ function setTableParseChild(fn) {
3218
+ _parseChild = fn;
3219
+ }
3220
+ function parseTablePropertiesEl(el) {
3221
+ const opts = {};
3222
+ const style = findChild(el, "w:tblStyle");
3223
+ if (style) {
3224
+ const val = attr(style, "w:val");
3225
+ if (val) opts.style = val;
3226
+ }
3227
+ const tblW = findChild(el, "w:tblW");
3228
+ if (tblW) {
3229
+ const rawSize = attr(tblW, "w:w");
3230
+ const type = attr(tblW, "w:type");
3231
+ const size = type === "pct" ? rawSize : attrNum(tblW, "w:w");
3232
+ if (size !== void 0 || type) opts.width = {
3233
+ size: size ?? 0,
3234
+ ...type ? { type } : {}
3235
+ };
3236
+ }
3237
+ const jc = findChild(el, "w:jc");
3238
+ if (jc) {
3239
+ const val = attr(jc, "w:val");
3240
+ if (val) opts.alignment = val;
3241
+ }
3242
+ const layout = findChild(el, "w:tblLayout");
3243
+ if (layout) {
3244
+ const val = attr(layout, "w:type");
3245
+ if (val === "autofit" || val === "fixed") opts.layout = val;
3246
+ }
3247
+ const tblBorders = findChild(el, "w:tblBorders");
3248
+ if (tblBorders) {
3249
+ const borders = {};
3250
+ for (const side of [
3251
+ "top",
3252
+ "bottom",
3253
+ "left",
3254
+ "right",
3255
+ "insideH",
3256
+ "insideV"
3257
+ ]) {
3258
+ const sideEl = findChild(tblBorders, `w:${side}`);
3259
+ if (sideEl) {
3260
+ const b = {};
3261
+ const val = attr(sideEl, "w:val");
3262
+ if (val) b.style = val;
3263
+ const color = attr(sideEl, "w:color");
3264
+ if (color) b.color = color;
3265
+ const sz = attrNum(sideEl, "w:sz");
3266
+ if (sz !== void 0) b.size = sz;
3267
+ const space = attrNum(sideEl, "w:space");
3268
+ if (space !== void 0) b.space = space;
3269
+ borders[side] = b;
3270
+ }
3271
+ }
3272
+ if (Object.keys(borders).length > 0) opts.borders = borders;
3273
+ }
3274
+ const tblCellMar = findChild(el, "w:tblCellMar");
3275
+ if (tblCellMar) {
3276
+ const margins = {};
3277
+ for (const side of [
3278
+ "top",
3279
+ "bottom",
3280
+ "left",
3281
+ "right"
3282
+ ]) {
3283
+ const sideEl = findChild(tblCellMar, `w:${side}`);
3284
+ if (sideEl) {
3285
+ const size = attrNum(sideEl, "w:w");
3286
+ const type = attr(sideEl, "w:type");
3287
+ if (size !== void 0) margins[side] = {
3288
+ size,
3289
+ type: type ?? "dxa"
3290
+ };
3291
+ }
3292
+ }
3293
+ if (Object.keys(margins).length > 0) opts.margins = margins;
3294
+ }
3295
+ const shd = findChild(el, "w:shd");
3296
+ if (shd) {
3297
+ const shading = {};
3298
+ const fill = attr(shd, "w:fill");
3299
+ if (fill) shading.fill = fill;
3300
+ const color = attr(shd, "w:color");
3301
+ if (color) shading.color = color;
3302
+ const val = attr(shd, "w:val");
3303
+ if (val) shading.type = val;
3304
+ if (Object.keys(shading).length > 0) opts.shading = shading;
3305
+ }
3306
+ return opts;
3307
+ }
3308
+ function parseColumnWidthsEl(el) {
3309
+ const cols = [];
3310
+ const tblGrid = findChild(el, "w:tblGrid");
3311
+ if (!tblGrid) return cols;
3312
+ for (const col of children(tblGrid, "w:gridCol")) {
3313
+ const w = attrNum(col, "w:w");
3314
+ cols.push(w ?? 100);
3315
+ }
3316
+ return cols;
3317
+ }
3318
+ function parseTableRowPropertiesEl(el) {
3319
+ const opts = {};
3320
+ const trHeight = findChild(el, "w:trHeight");
3321
+ if (trHeight) {
3322
+ const val = attrNum(trHeight, "w:val");
3323
+ const rule = attr(trHeight, "w:hRule");
3324
+ if (val !== void 0) opts.height = {
3325
+ value: val,
3326
+ rule: rule ?? "atLeast"
3327
+ };
3328
+ }
3329
+ const tblHeader = findChild(el, "w:tblHeader");
3330
+ if (tblHeader) opts.tableHeader = attrBool(tblHeader, "w:val") ?? true;
3331
+ const cantSplit = findChild(el, "w:cantSplit");
3332
+ if (cantSplit) opts.cantSplit = attrBool(cantSplit, "w:val") ?? true;
3333
+ return opts;
3334
+ }
3335
+ function parseTableCellPropertiesEl(el) {
3336
+ const opts = {};
3337
+ const tcW = findChild(el, "w:tcW");
3338
+ if (tcW) {
3339
+ const size = attrNum(tcW, "w:w");
3340
+ const type = attr(tcW, "w:type");
3341
+ if (size !== void 0) opts.width = {
3342
+ size,
3343
+ type: type ?? "dxa"
3344
+ };
3345
+ }
3346
+ const gridSpan = findChild(el, "w:gridSpan");
3347
+ if (gridSpan) {
3348
+ const val = attrNum(gridSpan, "w:val");
3349
+ if (val !== void 0) opts.columnSpan = val;
3350
+ }
3351
+ const vMerge = findChild(el, "w:vMerge");
3352
+ if (vMerge) opts.verticalMerge = attr(vMerge, "w:val") === "restart" ? "restart" : "continue";
3353
+ const vAlign = findChild(el, "w:vAlign");
3354
+ if (vAlign) {
3355
+ const val = attr(vAlign, "w:val");
3356
+ if (val) opts.verticalAlign = val;
3357
+ }
3358
+ const shd = findChild(el, "w:shd");
3359
+ if (shd) {
3360
+ const shading = {};
3361
+ const fill = attr(shd, "w:fill");
3362
+ if (fill) shading.fill = fill;
3363
+ const color = attr(shd, "w:color");
3364
+ if (color) shading.color = color;
3365
+ const val = attr(shd, "w:val");
3366
+ if (val) shading.type = val;
3367
+ if (Object.keys(shading).length > 0) opts.shading = shading;
3368
+ }
3369
+ const tcBorders = findChild(el, "w:tcBorders");
3370
+ if (tcBorders) {
3371
+ const borders = {};
3372
+ for (const side of [
3373
+ "top",
3374
+ "bottom",
3375
+ "left",
3376
+ "right"
3377
+ ]) {
3378
+ const sideEl = findChild(tcBorders, `w:${side}`);
3379
+ if (sideEl) {
3380
+ const b = {};
3381
+ const val = attr(sideEl, "w:val");
3382
+ if (val) b.style = val;
3383
+ const color = attr(sideEl, "w:color");
3384
+ if (color) b.color = color;
3385
+ const sz = attrNum(sideEl, "w:sz");
3386
+ if (sz !== void 0) b.size = sz;
3387
+ borders[side] = b;
3388
+ }
3389
+ }
3390
+ if (Object.keys(borders).length > 0) opts.borders = borders;
3391
+ }
3392
+ if (findChild(el, "w:noWrap")) opts.noWrap = true;
3393
+ const tcMar = findChild(el, "w:tcMar");
3394
+ if (tcMar) {
3395
+ const margins = {};
3396
+ let marginUnitType;
3397
+ for (const side of [
3398
+ "top",
3399
+ "bottom",
3400
+ "left",
3401
+ "right"
3402
+ ]) {
3403
+ const sideEl = findChild(tcMar, `w:${side}`);
3404
+ if (sideEl) {
3405
+ const size = attrNum(sideEl, "w:w");
3406
+ const type = attr(sideEl, "w:type");
3407
+ if (size !== void 0) {
3408
+ margins[side] = size;
3409
+ if (type && !marginUnitType) marginUnitType = type;
3410
+ }
3411
+ }
3412
+ }
3413
+ if (marginUnitType) margins.marginUnitType = marginUnitType;
3414
+ if (Object.keys(margins).length > 0) opts.margins = margins;
3415
+ }
3416
+ const textDirection = findChild(el, "w:textDirection");
3417
+ if (textDirection) {
3418
+ const val = attr(textDirection, "w:val");
3419
+ if (val) opts.textDirection = val;
3420
+ }
3421
+ return opts;
3422
+ }
3423
+ function parseTableCellEl(el, ctx) {
3424
+ const opts = {};
3425
+ const tcPr = findChild(el, "w:tcPr");
3426
+ if (tcPr) Object.assign(opts, parseTableCellPropertiesEl(tcPr));
3427
+ const childElements = [];
3428
+ for (const child of el.elements ?? []) switch (child.name) {
3429
+ case "w:tcPr": break;
3430
+ case "w:p":
3431
+ case "w:tbl":
3432
+ if (_parseChild) childElements.push(_parseChild(child, ctx));
3433
+ break;
3434
+ default: break;
3435
+ }
3436
+ opts.children = childElements;
3437
+ return opts;
3438
+ }
3439
+ function parseTableRowEl(el, ctx) {
3440
+ const opts = {};
3441
+ const trPr = findChild(el, "w:trPr");
3442
+ if (trPr) Object.assign(opts, parseTableRowPropertiesEl(trPr));
3443
+ const childCells = [];
3444
+ for (const child of el.elements ?? []) if (child.name === "w:tc") childCells.push(parseTableCellEl(child, ctx));
3445
+ opts.cells = childCells;
3446
+ return opts;
3447
+ }
3448
+ function parseTableEl(el, ctx) {
3449
+ const opts = {};
3450
+ const tblPr = findChild(el, "w:tblPr");
3451
+ if (tblPr) Object.assign(opts, parseTablePropertiesEl(tblPr));
3452
+ const colWidths = parseColumnWidthsEl(el);
3453
+ if (colWidths.length > 0) opts.columnWidths = colWidths;
3454
+ const rows = [];
3455
+ for (const child of el.elements ?? []) if (child.name === "w:tr") rows.push(parseTableRowEl(child, ctx));
3456
+ opts.rows = rows;
3457
+ return opts;
3458
+ }
3459
+ //#endregion
3460
+ //#region src/parts/document/document-attributes.ts
3461
+ /**
3462
+ * Document attributes module for WordprocessingML documents.
3463
+ *
3464
+ * This module defines the XML namespace declarations used in OOXML documents.
3465
+ * These namespaces are required for proper document parsing and generation.
3466
+ *
3467
+ * Reference: http://officeopenxml.com/anatomyofOOXML.php
3468
+ *
3469
+ * @module
3470
+ */
3471
+ /**
3472
+ * XML namespace URIs used in WordprocessingML documents.
3473
+ *
3474
+ * These namespaces define the various XML schemas that can be referenced
3475
+ * in a document, including WordprocessingML, DrawingML, VML, and others.
3476
+ */
3477
+ const DocumentAttributeNamespaces = {
3478
+ aink: "http://schemas.microsoft.com/office/drawing/2016/ink",
3479
+ am3d: "http://schemas.microsoft.com/office/drawing/2017/model3d",
3480
+ cp: "http://schemas.openxmlformats.org/package/2006/metadata/core-properties",
3481
+ cx: "http://schemas.microsoft.com/office/drawing/2014/chartex",
3482
+ cx1: "http://schemas.microsoft.com/office/drawing/2015/9/8/chartex",
3483
+ cx2: "http://schemas.microsoft.com/office/drawing/2015/10/21/chartex",
3484
+ cx3: "http://schemas.microsoft.com/office/drawing/2016/5/9/chartex",
3485
+ cx4: "http://schemas.microsoft.com/office/drawing/2016/5/10/chartex",
3486
+ cx5: "http://schemas.microsoft.com/office/drawing/2016/5/11/chartex",
3487
+ cx6: "http://schemas.microsoft.com/office/drawing/2016/5/12/chartex",
3488
+ cx7: "http://schemas.microsoft.com/office/drawing/2016/5/13/chartex",
3489
+ cx8: "http://schemas.microsoft.com/office/drawing/2016/5/14/chartex",
3490
+ dc: "http://purl.org/dc/elements/1.1/",
3491
+ dcmitype: "http://purl.org/dc/dcmitype/",
3492
+ dcterms: "http://purl.org/dc/terms/",
3493
+ m: "http://schemas.openxmlformats.org/officeDocument/2006/math",
3494
+ mc: "http://schemas.openxmlformats.org/markup-compatibility/2006",
3495
+ o: "urn:schemas-microsoft-com:office:office",
3496
+ r: "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
3497
+ v: "urn:schemas-microsoft-com:vml",
3498
+ w: "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
3499
+ w10: "urn:schemas-microsoft-com:office:word",
3500
+ w14: "http://schemas.microsoft.com/office/word/2010/wordml",
3501
+ w15: "http://schemas.microsoft.com/office/word/2012/wordml",
3502
+ w16: "http://schemas.microsoft.com/office/word/2018/wordml",
3503
+ w16cex: "http://schemas.microsoft.com/office/word/2018/wordml/cex",
3504
+ w16cid: "http://schemas.microsoft.com/office/word/2016/wordml/cid",
3505
+ w16sdtdh: "http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash",
3506
+ w16se: "http://schemas.microsoft.com/office/word/2015/wordml/symex",
3507
+ wne: "http://schemas.microsoft.com/office/word/2006/wordml",
3508
+ wp: "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing",
3509
+ wp14: "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing",
3510
+ wpc: "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas",
3511
+ wpg: "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup",
3512
+ wpi: "http://schemas.microsoft.com/office/word/2010/wordprocessingInk",
3513
+ wps: "http://schemas.microsoft.com/office/word/2010/wordprocessingShape",
3514
+ xsi: "http://www.w3.org/2001/XMLSchema-instance"
3515
+ };
3516
+ //#endregion
3517
+ //#region src/parts/document/body/section-properties/properties/page-size.ts
3518
+ /**
3519
+ * This simple type specifies the orientation of all pages in the parent section. This information is used to determine the actual paper size to use when printing the file.
3520
+ *
3521
+ * Reference: https://c-rex.net/samples/ooxml/e1/Part4/OOXML_P4_DOCX_ST_PageOrientation_topic_ID0EKBK3.html
3522
+ *
3523
+ * ## XSD Schema
3524
+ *
3525
+ * ```xml
3526
+ * <xsd:simpleType name="ST_PageOrientation">
3527
+ * <xsd:restriction base="xsd:string">
3528
+ * <xsd:enumeration value="portrait"/>
3529
+ * <xsd:enumeration value="landscape"/>
3530
+ * </xsd:restriction>
3531
+ * </xsd:simpleType>
3532
+ * ```
3533
+ *
3534
+ * @publicApi
3535
+ */
3536
+ const PageOrientation = {
3537
+ /**
3538
+ * ## Portrait Mode
3539
+ *
3540
+ * Specifies that pages in this section shall be printed in portrait mode.
3541
+ */
3542
+ PORTRAIT: "portrait",
3543
+ /**
3544
+ * ## Landscape Mode
3545
+ *
3546
+ * Specifies that pages in this section shall be printed in landscape mode, which prints the page contents with a 90 degree rotation with respect to the normal page orientation.
3547
+ */
3548
+ LANDSCAPE: "landscape"
3549
+ };
3550
+ /**
3551
+ * This element specifies the properties (size and orientation) for all pages in the current section.
3552
+ *
3553
+ * Reference: https://c-rex.net/samples/ooxml/e1/Part4/OOXML_P4_DOCX_pgSz_topic_ID0ENEDT.html?hl=pgsz%2Cpage%2Csize
3554
+ *
3555
+ * ## XSD Schema
3556
+ *
3557
+ * ```xml
3558
+ * <xsd:complexType name="CT_PageSz">
3559
+ * <xsd:attribute name="w" type="s:ST_TwipsMeasure"/>
3560
+ * <xsd:attribute name="h" type="s:ST_TwipsMeasure"/>
3561
+ * <xsd:attribute name="orient" type="ST_PageOrientation" use="optional"/>
3562
+ * <xsd:attribute name="code" type="ST_DecimalNumber" use="optional"/>
3563
+ * </xsd:complexType>
3564
+ * ```
3565
+ */
3566
+ const createPageSize = ({ width, height, orientation, code }) => {
3567
+ const widthTwips = twipsMeasureValue(width);
3568
+ const heightTwips = twipsMeasureValue(height);
3569
+ return element("w:pgSz", {
3570
+ "w:code": code,
3571
+ "w:h": orientation === PageOrientation.LANDSCAPE ? widthTwips : heightTwips,
3572
+ "w:orient": orientation,
3573
+ "w:w": orientation === PageOrientation.LANDSCAPE ? heightTwips : widthTwips
3574
+ });
3575
+ };
3576
+ //#endregion
3577
+ //#region src/parts/document/body/section-properties/properties/page-text-direction.ts
3578
+ /**
3579
+ * Page text direction module for WordprocessingML section properties.
3580
+ *
3581
+ * Defines text flow direction for pages in a section.
3582
+ *
3583
+ * Reference: http://officeopenxml.com/WPsectionPr.php
3584
+ *
3585
+ * @module
3586
+ */
3587
+ /**
3588
+ * Specifies the text flow direction for pages in a section.
3589
+ *
3590
+ * This controls whether text flows horizontally (left-to-right) or
3591
+ * vertically (top-to-bottom), commonly used for East Asian languages.
3592
+ */
3593
+ const PageTextDirectionType = {
3594
+ /** Left-to-right, top-to-bottom (standard Western text flow) */
3595
+ LEFT_TO_RIGHT_TOP_TO_BOTTOM: "lrTb",
3596
+ /** Top-to-bottom, right-to-left (vertical East Asian text flow) */
3597
+ TOP_TO_BOTTOM_RIGHT_TO_LEFT: "tbRl"
3598
+ };
3599
+ //#endregion
3600
+ //#region src/parts/document/body/section-properties/section-properties.ts
3601
+ const sectionMarginDefaults = {
3602
+ TOP: 1440,
3603
+ RIGHT: 1800,
3604
+ BOTTOM: 1440,
3605
+ LEFT: 1800,
3606
+ HEADER: 851,
3607
+ FOOTER: 992,
3608
+ GUTTER: 0
3609
+ };
3610
+ const sectionPageSizeDefaults = {
3611
+ WIDTH: 11906,
3612
+ HEIGHT: 16838,
3613
+ ORIENTATION: PageOrientation.PORTRAIT
3614
+ };
3615
+ //#endregion
3616
+ //#region src/parts/document/body/section-properties/properties/doc-grid.ts
3617
+ /**
3618
+ * Specifies the type of the current document grid, which defines the grid behavior.
3619
+ *
3620
+ * The grid can define a grid which snaps all East Asian characters to grid positions, but leaves Latin text with its default spacing; a grid which adds the specified character pitch to all characters on each row; or a grid which affects only the line pitch for the current section.
3621
+ *
3622
+ * Reference: https://c-rex.net/samples/ooxml/e1/Part4/OOXML_P4_DOCX_ST_DocGrid_topic_ID0ELYP2.html
3623
+ *
3624
+ * ## XSD Schema
3625
+ * ```xml
3626
+ * <xsd:simpleType name="ST_DocGrid">
3627
+ * <xsd:restriction base="xsd:string">
3628
+ * <xsd:enumeration value="default"/>
3629
+ * <xsd:enumeration value="lines"/>
3630
+ * <xsd:enumeration value="linesAndChars"/>
3631
+ * <xsd:enumeration value="snapToChars"/>
3632
+ * </xsd:restriction>
3633
+ * </xsd:simpleType>
3634
+ * ```
3635
+ */
3636
+ const DocumentGridType = {
3637
+ /**
3638
+ * Specifies that no document grid shall be applied to the contents of the current section in the document.
3639
+ */
3640
+ DEFAULT: "default",
3641
+ /**
3642
+ * Specifies that the parent section shall have additional line pitch added to each line within it (as specified on the <docGrid> element (§2.6.5)) in order to maintain the specified number of lines per page.
3643
+ */
3644
+ LINES: "lines",
3645
+ /**
3646
+ * Specifies that the parent section shall have both the additional line pitch and character pitch added to each line and character within it (as specified on the <docGrid> element (§2.6.5)) in order to maintain a specific number of lines per page and characters per line.
3647
+ *
3648
+ * When this value is set, the input specified via the user interface may be allowed in exact number of line/character pitch units. */
3649
+ LINES_AND_CHARS: "linesAndChars",
3650
+ /**
3651
+ * Specifies that the parent section shall have both the additional line pitch and character pitch added to each line and character within it (as specified on the <docGrid> element (§2.6.5)) in order to maintain a specific number of lines per page and characters per line.
3652
+ *
3653
+ * When this value is set, the input specified via the user interface may be restricted to the number of lines per page and characters per line, with the consumer or producer translating this information based on the current font data to get the resulting line and character pitch values
3654
+ */
3655
+ SNAP_TO_CHARS: "snapToChars"
3656
+ };
3657
+ /**
3658
+ * This element specifies the settings for the document grid, which enables precise layout of full-width East Asian language characters within a document by specifying the desired number of characters per line and lines per page for all East Asian text content in this section.
3659
+ *
3660
+ * Reference: https://c-rex.net/samples/ooxml/e1/Part4/OOXML_P4_DOCX_docGrid_topic_ID0EHU5S.html
3661
+ *
3662
+ * ```xml
3663
+ * <xsd:complexType name="CT_DocGrid">
3664
+ * <xsd:attribute name="type" type="ST_DocGrid"/>
3665
+ * <xsd:attribute name="linePitch" type="ST_DecimalNumber"/>
3666
+ * <xsd:attribute name="charSpace" type="ST_DecimalNumber"/>
3667
+ * </xsd:complexType>
3668
+ * ```
3669
+ * @returns
3670
+ */
3671
+ const createDocumentGrid = ({ type, linePitch, charSpace }) => element("w:docGrid", {
3672
+ "w:charSpace": charSpace ? decimalNumber(charSpace) : void 0,
3673
+ "w:linePitch": decimalNumber(linePitch),
3674
+ "w:type": type
3675
+ });
3676
+ //#endregion
3677
+ //#region src/parts/document/body/section-properties/properties/page-number.ts
3678
+ /**
3679
+ * Specifies the separator character between chapter number and page number.
3680
+ *
3681
+ * ## XSD Schema
3682
+ * ```xml
3683
+ * <xsd:simpleType name="ST_ChapterSep">
3684
+ * <xsd:restriction base="xsd:string">
3685
+ * <xsd:enumeration value="hyphen"/>
3686
+ * <xsd:enumeration value="period"/>
3687
+ * <xsd:enumeration value="colon"/>
3688
+ * <xsd:enumeration value="emDash"/>
3689
+ * <xsd:enumeration value="enDash"/>
3690
+ * </xsd:restriction>
3691
+ * </xsd:simpleType>
3692
+ * ```
3693
+ *
3694
+ * @publicApi
3695
+ */
3696
+ const PageNumberSeparator = {
3697
+ /** Hyphen separator (-) */
3698
+ HYPHEN: "hyphen",
3699
+ /** Period separator (.) */
3700
+ PERIOD: "period",
3701
+ /** Colon separator (:) */
3702
+ COLON: "colon",
3703
+ /** Em dash separator (—) */
3704
+ EM_DASH: "emDash",
3705
+ /** En dash separator (–) */
3706
+ EN_DASH: "enDash"
3707
+ };
3708
+ /**
3709
+ * Creates page numbering settings (pgNumType) for a document section.
3710
+ *
3711
+ * This element specifies the page numbering format and starting value
3712
+ * for all pages in a section.
3713
+ *
3714
+ * Reference: http://officeopenxml.com/WPSectionPgNumType.php
3715
+ *
3716
+ * ## XSD Schema
3717
+ * ```xml
3718
+ * <xsd:complexType name="CT_PageNumber">
3719
+ * <xsd:attribute name="fmt" type="ST_NumberFormat" use="optional" default="decimal"/>
3720
+ * <xsd:attribute name="start" type="ST_DecimalNumber" use="optional"/>
3721
+ * <xsd:attribute name="chapStyle" type="ST_DecimalNumber" use="optional"/>
3722
+ * <xsd:attribute name="chapSep" type="ST_ChapterSep" use="optional" default="hyphen"/>
3723
+ * </xsd:complexType>
3724
+ * ```
3725
+ *
3726
+ * @example
3727
+ * ```typescript
3728
+ * // Start page numbering at 5 with lowercase roman numerals
3729
+ * createPageNumberType({
3730
+ * start: 5,
3731
+ * formatType: NumberFormat.LOWER_ROMAN
3732
+ * });
3733
+ * ```
3734
+ */
3735
+ const createPageNumberType = ({ start, formatType, separator, chapStyle }) => element("w:pgNumType", {
3736
+ "w:chapStyle": chapStyle === void 0 ? void 0 : decimalNumber(chapStyle),
3737
+ "w:fmt": formatType,
3738
+ "w:chapSep": separator,
3739
+ "w:start": start === void 0 ? void 0 : decimalNumber(start)
3740
+ });
3741
+ //#endregion
3742
+ //#region src/parts/document/body/section-properties/properties/page-borders.ts
3743
+ /**
3744
+ * Specifies which pages display the page border.
3745
+ *
3746
+ * ## XSD Schema
3747
+ * ```xml
3748
+ * <xsd:simpleType name="ST_PageBorderDisplay">
3749
+ * <xsd:restriction base="xsd:string">
3750
+ * <xsd:enumeration value="allPages"/>
3751
+ * <xsd:enumeration value="firstPage"/>
3752
+ * <xsd:enumeration value="notFirstPage"/>
3753
+ * </xsd:restriction>
3754
+ * </xsd:simpleType>
3755
+ * ```
3756
+ *
3757
+ * @publicApi
3758
+ */
3759
+ const PageBorderDisplay = {
3760
+ /** Display border on all pages */
3761
+ ALL_PAGES: "allPages",
3762
+ /** Display border only on first page */
3763
+ FIRST_PAGE: "firstPage",
3764
+ /** Display border on all pages except first page */
3765
+ NOT_FIRST_PAGE: "notFirstPage"
3766
+ };
3767
+ /**
3768
+ * Specifies whether page border is positioned relative to page edge or text.
3769
+ *
3770
+ * ## XSD Schema
3771
+ * ```xml
3772
+ * <xsd:simpleType name="ST_PageBorderOffset">
3773
+ * <xsd:restriction base="xsd:string">
3774
+ * <xsd:enumeration value="page"/>
3775
+ * <xsd:enumeration value="text"/>
3776
+ * </xsd:restriction>
3777
+ * </xsd:simpleType>
3778
+ * ```
3779
+ *
3780
+ * @publicApi
3781
+ */
3782
+ const PageBorderOffsetFrom = {
3783
+ /** Position border relative to page edge */
3784
+ PAGE: "page",
3785
+ /** Position border relative to text (default) */
3786
+ TEXT: "text"
3787
+ };
3788
+ /**
3789
+ * Specifies z-order of page border relative to intersecting objects.
3790
+ *
3791
+ * ## XSD Schema
3792
+ * ```xml
3793
+ * <xsd:simpleType name="ST_PageBorderZOrder">
3794
+ * <xsd:restriction base="xsd:string">
3795
+ * <xsd:enumeration value="front"/>
3796
+ * <xsd:enumeration value="back"/>
3797
+ * </xsd:restriction>
3798
+ * </xsd:simpleType>
3799
+ * ```
3800
+ *
3801
+ * @publicApi
3802
+ */
3803
+ const PageBorderZOrder = {
3804
+ /** Display border behind page contents */
3805
+ BACK: "back",
3806
+ /** Display border in front of page contents (default) */
3807
+ FRONT: "front"
3808
+ };
3809
+ //#endregion
3810
+ //#region src/parts/document/body/section-properties/properties/page-margin.ts
3811
+ /**
3812
+ * Page margin module for WordprocessingML section properties.
3813
+ *
3814
+ * Defines page margins for document sections.
3815
+ *
3816
+ * Reference: http://officeopenxml.com/WPsectionPr.php
3817
+ *
3818
+ * @module
3819
+ */
3820
+ /**
3821
+ * Creates page margins (pgMar) for a document section.
3822
+ *
3823
+ * This element specifies the page margins for all pages in a section,
3824
+ * including top, bottom, left, right, header, footer, and gutter margins.
3825
+ *
3826
+ * Reference: http://officeopenxml.com/WPsectionPr.php
3827
+ *
3828
+ * ## XSD Schema
3829
+ * ```xml
3830
+ * <xsd:complexType name="CT_PageMar">
3831
+ * <xsd:attribute name="top" type="ST_SignedTwipsMeasure" use="required"/>
3832
+ * <xsd:attribute name="right" type="s:ST_TwipsMeasure" use="required"/>
3833
+ * <xsd:attribute name="bottom" type="ST_SignedTwipsMeasure" use="required"/>
3834
+ * <xsd:attribute name="left" type="s:ST_TwipsMeasure" use="required"/>
3835
+ * <xsd:attribute name="header" type="s:ST_TwipsMeasure" use="required"/>
3836
+ * <xsd:attribute name="footer" type="s:ST_TwipsMeasure" use="required"/>
3837
+ * <xsd:attribute name="gutter" type="s:ST_TwipsMeasure" use="required"/>
3838
+ * </xsd:complexType>
3839
+ * ```
3840
+ *
3841
+ * @example
3842
+ * ```typescript
3843
+ * // Create page margins with 1 inch margins (1440 twips = 1 inch)
3844
+ * createPageMargin(1440, 1440, 1440, 1440, 720, 720, 0);
3845
+ * ```
3846
+ */
3847
+ const createPageMargin = (top, right, bottom, left, header, footer, gutter) => `<w:pgMar w:bottom="${signedTwipsMeasureValue(bottom)}" w:footer="${twipsMeasureValue(footer)}" w:gutter="${twipsMeasureValue(gutter)}" w:header="${twipsMeasureValue(header)}" w:left="${twipsMeasureValue(left)}" w:right="${twipsMeasureValue(right)}" w:top="${signedTwipsMeasureValue(top)}"/>`;
3848
+ //#endregion
3849
+ //#region src/parts/document/body/section-properties/properties/line-number.ts
3850
+ /**
3851
+ * This simple type specifies when the line numbering in the parent section shall be reset to its restart value. The line numbering increments for each line (even if the line number itself is not displayed) until it reaches the restart point specified by this element.
3852
+ *
3853
+ * Reference: https://c-rex.net/samples/ooxml/e1/Part4/OOXML_P4_DOCX_ST_LineNumberRestart_topic_ID0EUS42.html
3854
+ *
3855
+ * ## XSD Schema
3856
+ *
3857
+ * ```xml
3858
+ * <xsd:simpleType name="ST_LineNumberRestart">
3859
+ * <xsd:restriction base="xsd:string">
3860
+ * <xsd:enumeration value="newPage"/>
3861
+ * <xsd:enumeration value="newSection"/>
3862
+ * <xsd:enumeration value="continuous"/>
3863
+ * </xsd:restriction>
3864
+ * </xsd:simpleType>
3865
+ * ```
3866
+ *
3867
+ * @publicApi
3868
+ */
3869
+ const LineNumberRestartFormat = {
3870
+ /**
3871
+ * ## Restart Line Numbering on Each Page
3872
+ *
3873
+ * Specifies that line numbering for the parent section shall restart to the starting value whenever a new page is displayed.
3874
+ */
3875
+ NEW_PAGE: "newPage",
3876
+ /**
3877
+ * ## Restart Line Numbering for Each Section
3878
+ *
3879
+ * Specifies that line numbering for the parent section shall restart to the starting value whenever the parent begins.
3880
+ */
3881
+ NEW_SECTION: "newSection",
3882
+ /**
3883
+ * ## Continue Line Numbering From Previous Section
3884
+ *
3885
+ * Specifies that line numbering for the parent section shall continue from the line numbering from the end of the previous section, if any.
3886
+ */
3887
+ CONTINUOUS: "continuous"
3888
+ };
3889
+ /**
3890
+ * This element specifies the settings for line numbering to be displayed before each column of text in this section in the document.
3891
+ *
3892
+ * References:
3893
+ * - https://c-rex.net/samples/ooxml/e1/Part4/OOXML_P4_DOCX_lnNumType_topic_ID0EVRAT.html
3894
+ * - http://officeopenxml.com/WPsectionLineNumbering.php
3895
+ *
3896
+ * ## XSD Schema
3897
+ *
3898
+ * ```xml
3899
+ * <xsd:complexType name="CT_LineNumber">
3900
+ * <xsd:attribute name="countBy" type="ST_DecimalNumber" use="optional"/>
3901
+ * <xsd:attribute name="start" type="ST_DecimalNumber" use="optional" default="1"/>
3902
+ * <xsd:attribute name="distance" type="s:ST_TwipsMeasure" use="optional"/>
3903
+ * <xsd:attribute name="restart" type="ST_LineNumberRestart" use="optional" default="newPage"/>
3904
+ * </xsd:complexType>
3905
+ * ```
3906
+ */
3907
+ const createLineNumberType = ({ countBy, start, restart, distance }) => element("w:lnNumType", {
3908
+ "w:countBy": countBy === void 0 ? void 0 : decimalNumber(countBy),
3909
+ "w:distance": distance === void 0 ? void 0 : twipsMeasureValue(distance),
3910
+ "w:restart": restart,
3911
+ "w:start": start === void 0 ? void 0 : decimalNumber(start)
3912
+ });
3913
+ //#endregion
3914
+ //#region src/parts/document/body/section-properties/properties/section-type.ts
3915
+ /**
3916
+ * Section type module for WordprocessingML section properties.
3917
+ *
3918
+ * Defines how a section begins relative to the previous section.
3919
+ *
3920
+ * Reference: http://officeopenxml.com/WPsection.php
3921
+ *
3922
+ * @module
3923
+ */
3924
+ /**
3925
+ * Specifies the type of section break.
3926
+ *
3927
+ * This determines where the section begins relative to the previous section.
3928
+ *
3929
+ * ## XSD Schema
3930
+ * ```xml
3931
+ * <xsd:simpleType name="ST_SectionMark">
3932
+ * <xsd:restriction base="xsd:string">
3933
+ * <xsd:enumeration value="nextPage"/>
3934
+ * <xsd:enumeration value="nextColumn"/>
3935
+ * <xsd:enumeration value="continuous"/>
3936
+ * <xsd:enumeration value="evenPage"/>
3937
+ * <xsd:enumeration value="oddPage"/>
3938
+ * </xsd:restriction>
3939
+ * </xsd:simpleType>
3940
+ * ```
3941
+ *
3942
+ * @publicApi
3943
+ */
3944
+ const SectionType = {
3945
+ /** Section begins on the next page */
3946
+ NEXT_PAGE: "nextPage",
3947
+ /** Section begins on the next column */
3948
+ NEXT_COLUMN: "nextColumn",
3949
+ /** Section begins immediately following the previous section */
3950
+ CONTINUOUS: "continuous",
3951
+ /** Section begins on the next even-numbered page */
3952
+ EVEN_PAGE: "evenPage",
3953
+ /** Section begins on the next odd-numbered page */
3954
+ ODD_PAGE: "oddPage"
3955
+ };
3956
+ /**
3957
+ * Creates section type (type) for a document section.
3958
+ *
3959
+ * This element specifies the type of section break, which determines
3960
+ * where the new section begins relative to the previous section.
3961
+ *
3962
+ * Reference: http://officeopenxml.com/WPsection.php
3963
+ *
3964
+ * ## XSD Schema
3965
+ * ```xml
3966
+ * <xsd:complexType name="CT_SectType">
3967
+ * <xsd:attribute name="val" type="ST_SectionMark"/>
3968
+ * </xsd:complexType>
3969
+ * ```
3970
+ *
3971
+ * @example
3972
+ * ```typescript
3973
+ * // Create a continuous section (no page break)
3974
+ * createSectionType(SectionType.CONTINUOUS);
3975
+ *
3976
+ * // Create a section that starts on next odd page
3977
+ * createSectionType(SectionType.ODD_PAGE);
3978
+ * ```
3979
+ */
3980
+ const createSectionType = (value) => `<w:type w:val="${value}"/>`;
3981
+ //#endregion
3982
+ //#region src/parts/document/body/section-properties/properties/header-footer-reference.ts
3983
+ /**
3984
+ * This simple type specifies the possible types of headers and footers which may be specified for a given header or footer reference in a document. This value determines the page(s) on which the current header or footer shall be displayed.
3985
+ *
3986
+ * Reference: https://c-rex.net/samples/ooxml/e1/Part4/OOXML_P4_DOCX_ST_HdrFtr_topic_ID0E2UW2.html
3987
+ *
3988
+ * ## XSD Schema
3989
+ * ```xml
3990
+ * <xsd:simpleType name="ST_HdrFtr">
3991
+ * <xsd:restriction base="xsd:string">
3992
+ * <xsd:enumeration value="even"/>
3993
+ * <xsd:enumeration value="default"/>
3994
+ * <xsd:enumeration value="first"/>
3995
+ * </xsd:restriction>
3996
+ * </xsd:simpleType>
3997
+ * ```
3998
+ */
3999
+ const HeaderFooterReferenceType = {
4000
+ /** Specifies that this header or footer shall appear on every page in this section which is not overridden with a specific `even` or `first` page header/footer. In a section with all three types specified, this type shall be used on all odd numbered pages (counting from the `first` page in the section, not the section numbering). */
4001
+ DEFAULT: "default",
4002
+ /** Specifies that this header or footer shall appear on the first page in this section. The appearance of this header or footer is contingent on the setting of the `titlePg` element (§2.10.6). */
4003
+ FIRST: "first",
4004
+ /** Specifies that this header or footer shall appear on all even numbered pages in this section (counting from the first page in the section, not the section numbering). The appearance of this header or footer is contingent on the setting of the `evenAndOddHeaders` element (§2.10.1). */
4005
+ EVEN: "even"
4006
+ };
4007
+ const HeaderFooterType = {
4008
+ FOOTER: "w:footerReference",
4009
+ HEADER: "w:headerReference"
4010
+ };
4011
+ const createHeaderFooterReference = (type, options) => `<${type} r:id="rId${options.id}" w:type="${options.type || HeaderFooterReferenceType.DEFAULT}"/>`;
4012
+ //#endregion
4013
+ //#region src/parts/document/body/section-properties/descriptor.ts
4014
+ /**
4015
+ * Section properties descriptor for DOCX documents.
4016
+ *
4017
+ * Produces `<w:sectPr>` XML directly from options, eliminating all
4018
+ * intermediate XmlComponent instances (create* + toXml pattern).
4019
+ *
4020
+ * Reference: ISO/IEC 29500-4, wml.xsd, CT_SectPr
4021
+ *
4022
+ * @module
4023
+ */
4024
+ function stringifyBorderXml(tag, opts) {
4025
+ const attrs = [];
4026
+ if (opts.style !== void 0) attrs.push(`w:val="${opts.style}"`);
4027
+ if (opts.color !== void 0) attrs.push(`w:color="${opts.color}"`);
4028
+ if (opts.size !== void 0) attrs.push(`w:sz="${opts.size}"`);
4029
+ if (opts.space !== void 0) attrs.push(`w:space="${opts.space}"`);
4030
+ if (opts.themeColor !== void 0) attrs.push(`w:themeColor="${opts.themeColor}"`);
4031
+ if (opts.themeTint !== void 0) attrs.push(`w:themeTint="${opts.themeTint}"`);
4032
+ if (opts.themeShade !== void 0) attrs.push(`w:themeShade="${opts.themeShade}"`);
4033
+ if (opts.shadow !== void 0) attrs.push(`w:shadow="${opts.shadow ? 1 : 0}"`);
4034
+ if (opts.frame !== void 0) attrs.push(`w:frame="${opts.frame ? 1 : 0}"`);
4035
+ return `<${tag} ${attrs.join(" ")}/>`;
4036
+ }
4037
+ function pageSizeXml(w, h, orient, code) {
4038
+ const attrs = [`w:w="${w}"`, `w:h="${h}"`];
4039
+ if (orient) attrs.push(`w:orient="${orient}"`);
4040
+ if (code !== void 0) attrs.push(`w:code="${code}"`);
4041
+ return `<w:pgSz ${attrs.join(" ")}/>`;
4042
+ }
4043
+ function pageMarginXml(top, right, bottom, left, header, footer, gutter) {
4044
+ return `<w:pgMar w:top="${top}" w:right="${right}" w:bottom="${bottom}" w:left="${left}" w:header="${header}" w:footer="${footer}" w:gutter="${gutter}"/>`;
4045
+ }
4046
+ function headerFooterRefXml(tag, id, type) {
4047
+ return `<${tag} r:id="rId${id}" w:type="${type}"/>`;
4048
+ }
4049
+ function sectionTypeXml(val) {
4050
+ return `<w:type w:val="${val}"/>`;
4051
+ }
4052
+ function verticalAlignXml(val) {
4053
+ return `<w:vAlign w:val="${val}"/>`;
4054
+ }
4055
+ function lineNumberXml(opts) {
4056
+ const attrs = [];
4057
+ if (opts.countBy !== void 0) attrs.push(`w:countBy="${opts.countBy}"`);
4058
+ if (opts.start !== void 0) attrs.push(`w:start="${opts.start}"`);
4059
+ if (opts.restart !== void 0) attrs.push(`w:restart="${opts.restart}"`);
4060
+ if (opts.distance !== void 0) attrs.push(`w:distance="${opts.distance}"`);
4061
+ return attrs.length ? `<w:lnNumType ${attrs.join(" ")}/>` : "<w:lnNumType/>";
4062
+ }
4063
+ function pageNumberXml(opts) {
4064
+ const attrs = [];
4065
+ if (opts.start !== void 0) attrs.push(`w:start="${opts.start}"`);
4066
+ if (opts.formatType !== void 0) attrs.push(`w:fmt="${opts.formatType}"`);
4067
+ if (opts.separator !== void 0) attrs.push(`w:chapSep="${opts.separator}"`);
4068
+ if (opts.chapStyle !== void 0) attrs.push(`w:chapStyle="${opts.chapStyle}"`);
4069
+ return attrs.length ? `<w:pgNumType ${attrs.join(" ")}/>` : "<w:pgNumType/>";
4070
+ }
4071
+ function docGridXml(linePitch, charSpace, type) {
4072
+ const attrs = [`w:linePitch="${linePitch}"`];
4073
+ if (charSpace !== void 0) attrs.push(`w:charSpace="${charSpace}"`);
4074
+ if (type !== void 0) attrs.push(`w:type="${type}"`);
4075
+ return `<w:docGrid ${attrs.join(" ")}/>`;
4076
+ }
4077
+ function columnsXml(opts) {
4078
+ const attrs = [];
4079
+ if (opts.space !== void 0) attrs.push(`w:space="${twipsMeasureValue(opts.space)}"`);
4080
+ if (opts.count !== void 0) attrs.push(`w:num="${opts.count}"`);
4081
+ if (opts.separate !== void 0) attrs.push(`w:sep="${opts.separate ? 1 : 0}"`);
4082
+ if (opts.equalWidth !== void 0) attrs.push(`w:equalWidth="${opts.equalWidth ? 1 : 0}"`);
4083
+ const attrStr = attrs.join(" ");
4084
+ if (!opts.equalWidth && opts.children) {
4085
+ const colParts = [];
4086
+ for (const col of opts.children) {
4087
+ const colAttrs = [`w:w="${twipsMeasureValue(col.width)}"`];
4088
+ if (col.space !== void 0) colAttrs.push(`w:space="${twipsMeasureValue(col.space)}"`);
4089
+ colParts.push(`<w:col ${colAttrs.join(" ")}/>`);
4090
+ }
4091
+ return `<w:cols ${attrStr}>${colParts.join("")}</w:cols>`;
4092
+ }
4093
+ return `<w:cols ${attrStr}/>`;
4094
+ }
4095
+ function footnotePrXml(tag, opts) {
4096
+ const parts = [];
4097
+ if (opts.pos !== void 0) parts.push(`<w:pos w:val="${opts.pos}"/>`);
4098
+ if (opts.formatType !== void 0 || opts.format !== void 0) {
4099
+ const fmtAttrs = [];
4100
+ if (opts.formatType !== void 0) fmtAttrs.push(`w:fmt="${opts.formatType}"`);
4101
+ if (opts.format !== void 0) fmtAttrs.push(`w:format="${opts.format}"`);
4102
+ parts.push(`<w:numFmt ${fmtAttrs.join(" ")}/>`);
4103
+ }
4104
+ if (opts.numStart !== void 0) parts.push(`<w:numStart w:val="${opts.numStart}"/>`);
4105
+ if (opts.numRestart !== void 0) parts.push(`<w:numRestart w:val="${opts.numRestart}"/>`);
4106
+ const body = parts.join("");
4107
+ return body ? `<${tag}>${body}</${tag}>` : `<${tag}/>`;
4108
+ }
4109
+ function pageBordersXml(opts) {
4110
+ const attrs = [];
4111
+ if (opts.display !== void 0) attrs.push(`w:display="${opts.display}"`);
4112
+ if (opts.offsetFrom !== void 0) attrs.push(`w:offsetFrom="${opts.offsetFrom}"`);
4113
+ if (opts.zOrder !== void 0) attrs.push(`w:zOrder="${opts.zOrder}"`);
4114
+ const parts = [];
4115
+ if (opts.top) parts.push(stringifyBorderXml("w:top", opts.top));
4116
+ if (opts.left) parts.push(stringifyBorderXml("w:left", opts.left));
4117
+ if (opts.bottom) parts.push(stringifyBorderXml("w:bottom", opts.bottom));
4118
+ if (opts.right) parts.push(stringifyBorderXml("w:right", opts.right));
4119
+ const attrStr = attrs.join(" ");
4120
+ const body = parts.join("");
4121
+ if (!body && !attrStr) return "<w:pgBorders/>";
4122
+ return body ? `<w:pgBorders ${attrStr}>${body}</w:pgBorders>` : `<w:pgBorders ${attrStr}/>`;
4123
+ }
4124
+ function appendHeaderFooterRefs(parts, type, group) {
4125
+ if (!group) return;
4126
+ if (group.default) parts.push(headerFooterRefXml(type, group.default.referenceId, "default"));
4127
+ if (group.first) parts.push(headerFooterRefXml(type, group.first.referenceId, "first"));
4128
+ if (group.even) parts.push(headerFooterRefXml(type, group.even.referenceId, "even"));
4129
+ }
4130
+ function stringifySectionPropertiesChange(opts) {
4131
+ const { author, date, id, ...inner } = opts;
4132
+ return `<w:sectPrChange w:author="${author}" w:date="${date}" w:id="${id}"><w:sectPr>${stringifySectionPropertiesInner(inner)}</w:sectPr></w:sectPrChange>`;
4133
+ }
4134
+ function stringifySectionPropertiesInner(opts) {
4135
+ const parts = [];
4136
+ appendHeaderFooterRefs(parts, "w:headerReference", opts.headerWrapperGroup);
4137
+ appendHeaderFooterRefs(parts, "w:footerReference", opts.footerWrapperGroup);
4138
+ const { size: { width = sectionPageSizeDefaults.WIDTH, height = sectionPageSizeDefaults.HEIGHT, orientation = sectionPageSizeDefaults.ORIENTATION } = {}, margin: { top = sectionMarginDefaults.TOP, right = sectionMarginDefaults.RIGHT, bottom = sectionMarginDefaults.BOTTOM, left = sectionMarginDefaults.LEFT, header = sectionMarginDefaults.HEADER, footer = sectionMarginDefaults.FOOTER, gutter = sectionMarginDefaults.GUTTER } = {}, pageNumbers = {}, borders, textDirection } = opts.page ?? {};
4139
+ const { linePitch = 312, charSpace = 0, type: gridType = "lines" } = opts.grid ?? {};
4140
+ if (opts.footnotePr) parts.push(footnotePrXml("w:footnotePr", opts.footnotePr));
4141
+ if (opts.endnotePr) parts.push(footnotePrXml("w:endnotePr", opts.endnotePr));
4142
+ if (opts.type) parts.push(sectionTypeXml(opts.type));
4143
+ const pgW = orientation === "landscape" ? convertToTwip(height) : width;
4144
+ const pgH = orientation === "landscape" ? convertToTwip(width) : height;
4145
+ parts.push(pageSizeXml(pgW, pgH, orientation));
4146
+ parts.push(pageMarginXml(top, right, bottom, left, header, footer, gutter));
4147
+ if (borders) parts.push(pageBordersXml(borders));
4148
+ if (opts.lineNumbers) parts.push(lineNumberXml(opts.lineNumbers));
4149
+ parts.push(pageNumberXml(pageNumbers));
4150
+ if (opts.column) parts.push(columnsXml(opts.column));
4151
+ if (opts.verticalAlign) parts.push(verticalAlignXml(opts.verticalAlign));
4152
+ if (opts.titlePage !== void 0) parts.push(opts.titlePage ? "<w:titlePg/>" : "<w:titlePg w:val=\"0\"/>");
4153
+ if (textDirection) parts.push(`<w:textDirection w:val="${textDirection}"/>`);
4154
+ if (opts.noEndnote !== void 0) parts.push(opts.noEndnote ? "<w:noEndnote/>" : "<w:noEndnote w:val=\"0\"/>");
4155
+ if (opts.formProtection !== void 0) parts.push(opts.formProtection ? "<w:formProt/>" : "<w:formProt w:val=\"0\"/>");
4156
+ if (opts.bidi !== void 0) parts.push(opts.bidi ? "<w:bidi/>" : "<w:bidi w:val=\"0\"/>");
4157
+ if (opts.rtlGutter !== void 0) parts.push(opts.rtlGutter ? "<w:rtlGutter/>" : "<w:rtlGutter w:val=\"0\"/>");
4158
+ if (opts.paperSrc) {
4159
+ const psAttr = [];
4160
+ if (opts.paperSrc.first !== void 0) psAttr.push(`w:first="${opts.paperSrc.first}"`);
4161
+ if (opts.paperSrc.other !== void 0) psAttr.push(`w:other="${opts.paperSrc.other}"`);
4162
+ parts.push(`<w:paperSrc ${psAttr.join(" ")}/>`);
4163
+ }
4164
+ if (opts.printerSettingsId !== void 0) parts.push(`<w:printerSettings r:id="${opts.printerSettingsId}"/>`);
4165
+ parts.push(docGridXml(linePitch, charSpace, gridType));
4166
+ if (opts.revision) parts.push(stringifySectionPropertiesChange(opts.revision));
4167
+ return parts.join("");
4168
+ }
4169
+ /**
4170
+ * Section properties descriptor for DOCX `<w:sectPr>` elements.
4171
+ *
4172
+ * Produces complete XML directly from options — zero XmlComponent instances
4173
+ * in the hot path. All `create*()` + `.toXml()` calls eliminated in favor
4174
+ * of direct string concatenation.
4175
+ *
4176
+ * @example
4177
+ * ```typescript
4178
+ * const xml = sectionPropertiesDesc.stringify(sectPrOpts, ctx);
4179
+ * ```
4180
+ */
4181
+ const sectionPropertiesDesc = {
4182
+ kind: "custom",
4183
+ stringify(opts, _ctx) {
4184
+ return stringifySectionPropertiesXml(opts);
4185
+ },
4186
+ parse(el, _ctx) {
4187
+ return parseSectionPropertiesEl(el);
4188
+ }
4189
+ };
4190
+ /** Standalone stringify — no context needed, pure options → XML. */
4191
+ function stringifySectionPropertiesXml(opts) {
4192
+ const inner = stringifySectionPropertiesInner(opts);
4193
+ const attrs = [];
4194
+ if (opts.rsidRPr !== void 0) attrs.push(`w:rsidRPr="${opts.rsidRPr}"`);
4195
+ if (opts.rsidDel !== void 0) attrs.push(`w:rsidDel="${opts.rsidDel}"`);
4196
+ if (opts.rsidR !== void 0) attrs.push(`w:rsidR="${opts.rsidR}"`);
4197
+ if (opts.rsidSect !== void 0) attrs.push(`w:rsidSect="${opts.rsidSect}"`);
4198
+ return `<w:sectPr${attrs.length ? " " + attrs.join(" ") : ""}>${inner}</w:sectPr>`;
4199
+ }
4200
+ /** Parse a w:sectPr element into ISectionPropertiesOptions. */
4201
+ function parseSectionPropertiesEl(el) {
4202
+ const opts = {};
4203
+ for (const [attrName, optKey] of [
4204
+ ["w:rsidR", "rsidR"],
4205
+ ["w:rsidRPr", "rsidRPr"],
4206
+ ["w:rsidDel", "rsidDel"],
4207
+ ["w:rsidSect", "rsidSect"]
4208
+ ]) {
4209
+ const val = attr(el, attrName);
4210
+ if (val) opts[optKey] = val;
4211
+ }
4212
+ const pgSz = findChild(el, "w:pgSz");
4213
+ if (pgSz) {
4214
+ const page = {};
4215
+ const size = {};
4216
+ const w = attrNum(pgSz, "w:w");
4217
+ const h = attrNum(pgSz, "w:h");
4218
+ const orient = attr(pgSz, "w:orient");
4219
+ if (orient === "landscape" && w !== void 0 && h !== void 0) {
4220
+ size.width = h;
4221
+ size.height = w;
4222
+ } else {
4223
+ if (w !== void 0) size.width = w;
4224
+ if (h !== void 0) size.height = h;
4225
+ }
4226
+ if (orient) size.orientation = orient;
4227
+ if (Object.keys(size).length > 0) page.size = size;
4228
+ const pgMar = findChild(el, "w:pgMar");
4229
+ if (pgMar) {
4230
+ const margin = {};
4231
+ for (const [a, o] of [
4232
+ ["w:top", "top"],
4233
+ ["w:right", "right"],
4234
+ ["w:bottom", "bottom"],
4235
+ ["w:left", "left"],
4236
+ ["w:header", "header"],
4237
+ ["w:footer", "footer"],
4238
+ ["w:gutter", "gutter"]
4239
+ ]) {
4240
+ const val = attrNum(pgMar, a);
4241
+ if (val !== void 0) margin[o] = val;
4242
+ }
4243
+ if (Object.keys(margin).length > 0) page.margin = margin;
4244
+ }
4245
+ const pgNumType = findChild(el, "w:pgNumType");
4246
+ if (pgNumType) {
4247
+ const pageNumbers = {};
4248
+ const start = attrNum(pgNumType, "w:start");
4249
+ if (start !== void 0) pageNumbers.start = start;
4250
+ const fmt = attr(pgNumType, "w:fmt");
4251
+ if (fmt) pageNumbers.formatType = fmt;
4252
+ if (Object.keys(pageNumbers).length > 0) page.pageNumbers = pageNumbers;
4253
+ }
4254
+ if (Object.keys(page).length > 0) opts.page = page;
4255
+ }
4256
+ const cols = findChild(el, "w:cols");
4257
+ if (cols) {
4258
+ const column = {};
4259
+ const count = attrNum(cols, "w:num");
4260
+ if (count !== void 0) column.count = count;
4261
+ const space = attrNum(cols, "w:space");
4262
+ if (space !== void 0) column.space = space;
4263
+ if (attrBool(cols, "w:sep")) column.separator = true;
4264
+ if (Object.keys(column).length > 0) opts.column = column;
4265
+ }
4266
+ const type = findChild(el, "w:type");
4267
+ if (type) {
4268
+ const val = attr(type, "w:val");
4269
+ if (val) opts.type = val;
4270
+ }
4271
+ const titlePg = findChild(el, "w:titlePg");
4272
+ if (titlePg) opts.titlePage = attrBool(titlePg, "w:val") ?? true;
4273
+ for (const [name, optKey] of [
4274
+ ["w:noEndnote", "noEndnote"],
4275
+ ["w:formProt", "formProtection"],
4276
+ ["w:bidi", "bidi"],
4277
+ ["w:rtlGutter", "rtlGutter"]
4278
+ ]) {
4279
+ const child = findChild(el, name);
4280
+ if (child) opts[optKey] = attrBool(child, "w:val") ?? true;
4281
+ }
4282
+ const docGrid = findChild(el, "w:docGrid");
4283
+ if (docGrid) {
4284
+ const grid = {};
4285
+ const type = attr(docGrid, "w:type");
4286
+ if (type) grid.type = type;
4287
+ const linePitch = attrNum(docGrid, "w:linePitch");
4288
+ if (linePitch !== void 0) grid.linePitch = linePitch;
4289
+ const charSpace = attrNum(docGrid, "w:charSpace");
4290
+ if (charSpace !== void 0) grid.charSpace = charSpace;
4291
+ if (Object.keys(grid).length > 0) opts.grid = grid;
4292
+ }
4293
+ const lnNumType = findChild(el, "w:lnNumType");
4294
+ if (lnNumType) {
4295
+ const lineNumbers = {};
4296
+ const countBy = attrNum(lnNumType, "w:countBy");
4297
+ if (countBy !== void 0) lineNumbers.countBy = countBy;
4298
+ const start = attrNum(lnNumType, "w:start");
4299
+ if (start !== void 0) lineNumbers.start = start;
4300
+ const restart = attr(lnNumType, "w:restart");
4301
+ if (restart) lineNumbers.restart = restart;
4302
+ const distance = attrNum(lnNumType, "w:distance");
4303
+ if (distance !== void 0) lineNumbers.distance = distance;
4304
+ if (Object.keys(lineNumbers).length > 0) opts.lineNumbers = lineNumbers;
4305
+ }
4306
+ const pgBorders = findChild(el, "w:pgBorders");
4307
+ if (pgBorders) {
4308
+ const borders = {};
4309
+ for (const side of [
4310
+ "top",
4311
+ "left",
4312
+ "bottom",
4313
+ "right"
4314
+ ]) {
4315
+ const sideEl = findChild(pgBorders, `w:${side}`);
4316
+ if (sideEl) {
4317
+ const b = {};
4318
+ const val = attr(sideEl, "w:val");
4319
+ if (val) b.style = val;
4320
+ const color = attr(sideEl, "w:color");
4321
+ if (color) b.color = color;
4322
+ const sz = attrNum(sideEl, "w:sz");
4323
+ if (sz !== void 0) b.size = sz;
4324
+ const space = attrNum(sideEl, "w:space");
4325
+ if (space !== void 0) b.space = space;
4326
+ borders[side] = b;
4327
+ }
4328
+ }
4329
+ const display = attr(pgBorders, "w:display");
4330
+ if (display) borders.display = display;
4331
+ const offsetFrom = attr(pgBorders, "w:offsetFrom");
4332
+ if (offsetFrom) borders.offsetFrom = offsetFrom;
4333
+ const zOrder = attr(pgBorders, "w:zOrder");
4334
+ if (zOrder) borders.zOrder = zOrder;
4335
+ if (Object.keys(borders).length > 0) {
4336
+ const page = opts.page ?? {};
4337
+ page.borders = borders;
4338
+ opts.page = page;
4339
+ }
4340
+ }
4341
+ const vAlign = findChild(el, "w:vAlign");
4342
+ if (vAlign) {
4343
+ const val = attr(vAlign, "w:val");
4344
+ if (val) opts.verticalAlign = val;
4345
+ }
4346
+ const textDirection = findChild(el, "w:textDirection");
4347
+ if (textDirection) {
4348
+ const val = attr(textDirection, "w:val");
4349
+ if (val) {
4350
+ const page = opts.page ?? {};
4351
+ page.textDirection = val;
4352
+ opts.page = page;
4353
+ }
4354
+ }
4355
+ const footnotePr = findChild(el, "w:footnotePr");
4356
+ if (footnotePr) opts.footnotePr = parseNotePropertiesEl(footnotePr);
4357
+ const endnotePr = findChild(el, "w:endnotePr");
4358
+ if (endnotePr) opts.endnotePr = parseNotePropertiesEl(endnotePr);
4359
+ const paperSrc = findChild(el, "w:paperSrc");
4360
+ if (paperSrc) {
4361
+ const ps = {};
4362
+ const first = attrNum(paperSrc, "w:first");
4363
+ if (first !== void 0) ps.first = first;
4364
+ const other = attrNum(paperSrc, "w:other");
4365
+ if (other !== void 0) ps.other = other;
4366
+ if (Object.keys(ps).length > 0) opts.paperSrc = ps;
4367
+ }
4368
+ const printerSettings = findChild(el, "w:printerSettings");
4369
+ if (printerSettings) {
4370
+ const rId = attr(printerSettings, "r:id");
4371
+ if (rId) opts.printerSettingsId = rId;
4372
+ }
4373
+ return opts;
4374
+ }
4375
+ function parseNotePropertiesEl(el) {
4376
+ const opts = {};
4377
+ const posEl = findChild(el, "w:pos");
4378
+ if (posEl) {
4379
+ const val = attr(posEl, "w:val");
4380
+ if (val) opts.pos = val;
4381
+ }
4382
+ const numFmt = findChild(el, "w:numFmt");
4383
+ if (numFmt) {
4384
+ const fmt = attr(numFmt, "w:fmt");
4385
+ if (fmt) opts.formatType = fmt;
4386
+ const format = attr(numFmt, "w:format");
4387
+ if (format) opts.format = format;
4388
+ }
4389
+ const numStart = findChild(el, "w:numStart");
4390
+ if (numStart) {
4391
+ const val = attrNum(numStart, "w:val");
4392
+ if (val !== void 0) opts.numStart = val;
4393
+ }
4394
+ const numRestart = findChild(el, "w:numRestart");
4395
+ if (numRestart) {
4396
+ const val = attr(numRestart, "w:val");
4397
+ if (val) opts.numRestart = val;
4398
+ }
4399
+ return opts;
4400
+ }
4401
+ //#endregion
4402
+ export { TextHorzOverflowType as $, stringifyParagraphProperties as A, HorizontalPositionAlign as B, createPageSize as C, stringifyJsonChild as D, tableDesc as E, parseDrawingRun as F, createWrapTight as G, SpaceType as H, createVerticalPosition as I, WidthType as J, TextWrappingSide as K, createHorizontalPosition as L, parseMathChildren as M, drawingDesc as N, stringifyParagraphInline as O, resetDrawingIdGen as P, TextBodyWrappingType as Q, HorizontalPositionRelativeFrom as R, PageOrientation as S, setTableParseChild as T, VerticalPositionAlign as U, NumberFormat as V, createWrapThrough as W, TextDirection as X, BorderStyle as Y, VerticalMergeType as Z, DocumentGridType as _, HeaderFooterType as a, Media as at, sectionPageSizeDefaults as b, createSectionType as c, createPageMargin as d, TextVertOverflowType as et, PageBorderDisplay as f, createPageNumberType as g, PageNumberSeparator as h, HeaderFooterReferenceType as i, WORKAROUND2 as it, stringifyRunProperties as j, stringifyRunInline as k, LineNumberRestartFormat as l, PageBorderZOrder as m, sectionPropertiesDesc as n, VerticalAnchor as nt, createHeaderFooterReference as o, createTransformation as ot, PageBorderOffsetFrom as p, TextWrappingType as q, stringifySectionPropertiesXml as r, createBodyProperties as rt, SectionType as s, parseSectionPropertiesEl as t, TextVerticalType as tt, createLineNumberType as u, createDocumentGrid as v, DocumentAttributeNamespaces as w, PageTextDirectionType as x, sectionMarginDefaults as y, VerticalPositionRelativeFrom as z };
4403
+
4404
+ //# sourceMappingURL=document-CWr8C_OX.mjs.map