docx 9.8.1 → 9.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -30,7 +30,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  enumerable: true
31
31
  }) : target, mod));
32
32
  //#endregion
33
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/typeof.js
33
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/typeof.js
34
34
  function _typeof(o) {
35
35
  "@babel/helpers - typeof";
36
36
  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
@@ -40,7 +40,7 @@ function _typeof(o) {
40
40
  }, _typeof(o);
41
41
  }
42
42
  //#endregion
43
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/toPrimitive.js
43
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/toPrimitive.js
44
44
  function toPrimitive(t, r) {
45
45
  if ("object" != _typeof(t) || !t) return t;
46
46
  var e = t[Symbol.toPrimitive];
@@ -52,13 +52,13 @@ function toPrimitive(t, r) {
52
52
  return ("string" === r ? String : Number)(t);
53
53
  }
54
54
  //#endregion
55
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/toPropertyKey.js
55
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/toPropertyKey.js
56
56
  function toPropertyKey(t) {
57
57
  var i = toPrimitive(t, "string");
58
58
  return "symbol" == _typeof(i) ? i : i + "";
59
59
  }
60
60
  //#endregion
61
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/defineProperty.js
61
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/defineProperty.js
62
62
  function _defineProperty(e, r, t) {
63
63
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
64
64
  value: t,
@@ -268,7 +268,7 @@ var IgnoreIfEmptyXmlComponent = class extends XmlComponent {
268
268
  }
269
269
  };
270
270
  //#endregion
271
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/objectSpread2.js
271
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/objectSpread2.js
272
272
  function ownKeys(e, r) {
273
273
  var t = Object.keys(e);
274
274
  if (Object.getOwnPropertySymbols) {
@@ -8950,11 +8950,11 @@ var BuilderElement = class extends XmlComponent {
8950
8950
  * @publicApi
8951
8951
  */
8952
8952
  var AlignmentType = {
8953
- /** Align Start */
8953
+ /** Align Start: the left in a left-to-right paragraph, and the right in a `bidirectional` (right-to-left) paragraph */
8954
8954
  START: "start",
8955
8955
  /** Align Center */
8956
8956
  CENTER: "center",
8957
- /** End */
8957
+ /** Align End: the right in a left-to-right paragraph, and the left in a `bidirectional` (right-to-left) paragraph */
8958
8958
  END: "end",
8959
8959
  /** Justified */
8960
8960
  BOTH: "both",
@@ -8970,9 +8970,9 @@ var AlignmentType = {
8970
8970
  LOW_KASHIDA: "lowKashida",
8971
8971
  /** Thai Language Justification */
8972
8972
  THAI_DISTRIBUTE: "thaiDistribute",
8973
- /** Align Left */
8973
+ /** Align Left: a paragraph stays on the left of the page even when it is `bidirectional` (right-to-left) */
8974
8974
  LEFT: "left",
8975
- /** Align Right */
8975
+ /** Align Right: a paragraph stays on the right of the page even when it is `bidirectional` (right-to-left) */
8976
8976
  RIGHT: "right",
8977
8977
  /** Justified */
8978
8978
  JUSTIFIED: "both"
@@ -9786,6 +9786,40 @@ var createFieldChar = (type, dirty) => new BuilderElement({
9786
9786
  * field instructions, an optional separate character, field result, and an end character.
9787
9787
  */
9788
9788
  var createBegin = (dirty) => createFieldChar(FieldCharacterType.BEGIN, dirty);
9789
+ /** The formatted begin characters of the fields that are dirty only when the document isn't given page numbers */
9790
+ var dirtyWithoutPageNumbers = /* @__PURE__ */ new WeakSet();
9791
+ /** The beginning of a field that is dirty, so Word updates it, unless the document is given page numbers */
9792
+ var BeginDirtyWithoutPageNumbers = class extends BuilderElement {
9793
+ constructor() {
9794
+ super({
9795
+ name: "w:fldChar",
9796
+ attributes: {
9797
+ type: {
9798
+ key: "w:fldCharType",
9799
+ value: FieldCharacterType.BEGIN
9800
+ },
9801
+ dirty: {
9802
+ key: "w:dirty",
9803
+ value: true
9804
+ }
9805
+ }
9806
+ });
9807
+ }
9808
+ prepForXml(context) {
9809
+ const xml = super.prepForXml(context);
9810
+ dirtyWithoutPageNumbers.add(xml);
9811
+ return xml;
9812
+ }
9813
+ };
9814
+ /**
9815
+ * Creates the beginning of a field whose result is written when the document is given page numbers, such as a page
9816
+ * reference or a SEQ field. It is written dirty, so Word updates the field when it opens the document, and asks to. When
9817
+ * the document is given page numbers, it is written clean (see {@link isDirtyWithoutPageNumbers}), so Word shows the
9818
+ * number written, or nothing when none could be worked out, and doesn't ask.
9819
+ */
9820
+ var createBeginDirtyWithoutPageNumbers = () => new BeginDirtyWithoutPageNumbers();
9821
+ /** Whether a formatted field character is the beginning of a field that is dirty only without page numbers */
9822
+ var isDirtyWithoutPageNumbers = (element) => typeof element === "object" && element !== null && dirtyWithoutPageNumbers.has(element);
9789
9823
  /**
9790
9824
  * Creates the separator between field code and field result in a complex field.
9791
9825
  *
@@ -9956,7 +9990,8 @@ var NumberFormat = {
9956
9990
  THAI_NUMBERS: "thaiNumbers",
9957
9991
  THAI_COUNTING: "thaiCounting",
9958
9992
  BAHT_TEXT: "bahtText",
9959
- DOLLAR_TEXT: "dollarText"
9993
+ DOLLAR_TEXT: "dollarText",
9994
+ CUSTOM: "custom"
9960
9995
  };
9961
9996
  //#endregion
9962
9997
  //#region src/file/shared/space-type.ts
@@ -11298,13 +11333,8 @@ var Symbol$1 = class extends XmlComponent {
11298
11333
  */
11299
11334
  var SymbolRun = class extends Run {
11300
11335
  constructor(options) {
11301
- if (typeof options === "string") {
11302
- super({});
11303
- this.root.push(new Symbol$1(options));
11304
- return this;
11305
- }
11306
- super(options);
11307
- this.root.push(new Symbol$1(options.char, options.symbolfont));
11336
+ super(typeof options === "string" ? {} : options);
11337
+ this.root.push(typeof options === "string" ? new Symbol$1(options) : new Symbol$1(options.char, options.symbolfont));
11308
11338
  }
11309
11339
  };
11310
11340
  //#endregion
@@ -12756,7 +12786,7 @@ var import_hash = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((expor
12756
12786
  hash.sha512 = hash.sha.sha512;
12757
12787
  hash.ripemd160 = hash.ripemd.ripemd160;
12758
12788
  })))(), 1);
12759
- var urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
12789
+ var urlAlphabet = "57X6y3wQZNzYjJB2L_10pxbackgroundhimselfUTF-8DEMOGRAPHICSVqvt4KW9";
12760
12790
  //#endregion
12761
12791
  //#region node_modules/nanoid/non-secure/index.js
12762
12792
  var customAlphabet = (alphabet, defaultSize = 21) => {
@@ -14285,6 +14315,16 @@ var SourceRectangleAttributes = class extends XmlAttributeComponent {
14285
14315
  }
14286
14316
  };
14287
14317
  /**
14318
+ * Converts a crop percentage to thousandths of a percent.
14319
+ *
14320
+ * @throws If the percentage isn't a number from 0 to 100
14321
+ */
14322
+ var cropValue = (value, edge) => {
14323
+ if (value === void 0) return;
14324
+ if (!(value >= 0 && value <= 100)) throw new Error(`Invalid crop ${edge} ${value}. Expected a number from 0 to 100`);
14325
+ return Math.round(value * 1e3);
14326
+ };
14327
+ /**
14288
14328
  * Represents a source rectangle for blip fills.
14289
14329
  *
14290
14330
  * This element specifies a portion of the blip (image) to use as the fill.
@@ -14311,10 +14351,10 @@ var SourceRectangle = class extends XmlComponent {
14311
14351
  constructor(crop) {
14312
14352
  super("a:srcRect");
14313
14353
  if (crop) this.root.push(new SourceRectangleAttributes({
14314
- left: crop.left === void 0 ? void 0 : Math.round(crop.left * 1e3),
14315
- top: crop.top === void 0 ? void 0 : Math.round(crop.top * 1e3),
14316
- right: crop.right === void 0 ? void 0 : Math.round(crop.right * 1e3),
14317
- bottom: crop.bottom === void 0 ? void 0 : Math.round(crop.bottom * 1e3)
14354
+ left: cropValue(crop.left, "left"),
14355
+ top: cropValue(crop.top, "top"),
14356
+ right: cropValue(crop.right, "right"),
14357
+ bottom: cropValue(crop.bottom, "bottom")
14318
14358
  }));
14319
14359
  }
14320
14360
  };
@@ -14543,48 +14583,6 @@ var ChildNonVisualProperties = class extends XmlComponent {
14543
14583
  }
14544
14584
  };
14545
14585
  //#endregion
14546
- //#region src/file/drawing/doc-properties/doc-properties-children.ts
14547
- /**
14548
- * Child elements for document properties.
14549
- *
14550
- * This module provides hyperlink elements that can be attached to
14551
- * drawing elements for interactive behavior.
14552
- *
14553
- * @module
14554
- */
14555
- /**
14556
- * Creates a click hyperlink element for a drawing.
14557
- *
14558
- * This element defines what happens when a user clicks on a drawing element.
14559
- *
14560
- * ## XSD Schema
14561
- * ```xml
14562
- * <xsd:complexType name="CT_Hyperlink">
14563
- * <xsd:group ref="EG_PContent" minOccurs="0" maxOccurs="unbounded"/>
14564
- * <xsd:attribute name="tgtFrame" type="s:ST_String"/>
14565
- * <xsd:attribute name="tooltip" type="s:ST_String"/>
14566
- * <xsd:attribute name="docLocation" type="s:ST_String"/>
14567
- * <xsd:attribute name="history" type="s:ST_OnOff"/>
14568
- * <xsd:attribute name="anchor" type="s:ST_String"/>
14569
- * <xsd:attribute ref="r:id"/>
14570
- * </xsd:complexType>
14571
- * ```
14572
- *
14573
- * @param linkId - The relationship ID for the hyperlink target
14574
- * @param hasXmlNs - Whether to include the XML namespace declaration
14575
- * @returns An XML component representing the click hyperlink
14576
- */
14577
- var createHyperlinkClick = (linkId, hasXmlNs) => new BuilderElement({
14578
- name: "a:hlinkClick",
14579
- attributes: _objectSpread2(_objectSpread2({}, hasXmlNs ? { xmlns: {
14580
- key: "xmlns:a",
14581
- value: "http://schemas.openxmlformats.org/drawingml/2006/main"
14582
- } } : {}), {}, { id: {
14583
- key: "r:id",
14584
- value: `rId${linkId}`
14585
- } })
14586
- });
14587
- //#endregion
14588
14586
  //#region src/file/drawing/inline/graphic/graphic-data/pic/non-visual-pic-properties/non-visual-properties/non-visual-properties-attributes.ts
14589
14587
  /**
14590
14588
  * Non-visual properties attributes module.
@@ -14665,10 +14663,12 @@ var NonVisualProperties = class extends XmlComponent {
14665
14663
  for (let i = context.stack.length - 1; i >= 0; i--) {
14666
14664
  const element = context.stack[i];
14667
14665
  if (!(element instanceof ConcreteHyperlink)) continue;
14668
- this.root.push(createHyperlinkClick(element.linkId, false));
14666
+ this.root.push(element.createDrawingClick(context, false));
14669
14667
  break;
14670
14668
  }
14671
- return super.prepForXml(context);
14669
+ const result = super.prepForXml(context);
14670
+ this.root.splice(1);
14671
+ return result;
14672
14672
  }
14673
14673
  };
14674
14674
  //#endregion
@@ -15333,6 +15333,48 @@ var createRelationship = (id, type, target, targetMode) => new BuilderElement({
15333
15333
  }
15334
15334
  });
15335
15335
  //#endregion
15336
+ //#region src/file/drawing/doc-properties/doc-properties-children.ts
15337
+ /**
15338
+ * Child elements for document properties.
15339
+ *
15340
+ * This module provides hyperlink elements that can be attached to
15341
+ * drawing elements for interactive behavior.
15342
+ *
15343
+ * @module
15344
+ */
15345
+ /**
15346
+ * Creates a click hyperlink element for a drawing.
15347
+ *
15348
+ * This element defines what happens when a user clicks on a drawing element.
15349
+ *
15350
+ * ## XSD Schema
15351
+ * ```xml
15352
+ * <xsd:complexType name="CT_Hyperlink">
15353
+ * <xsd:group ref="EG_PContent" minOccurs="0" maxOccurs="unbounded"/>
15354
+ * <xsd:attribute name="tgtFrame" type="s:ST_String"/>
15355
+ * <xsd:attribute name="tooltip" type="s:ST_String"/>
15356
+ * <xsd:attribute name="docLocation" type="s:ST_String"/>
15357
+ * <xsd:attribute name="history" type="s:ST_OnOff"/>
15358
+ * <xsd:attribute name="anchor" type="s:ST_String"/>
15359
+ * <xsd:attribute ref="r:id"/>
15360
+ * </xsd:complexType>
15361
+ * ```
15362
+ *
15363
+ * @param linkId - The relationship ID for the hyperlink target
15364
+ * @param hasXmlNs - Whether to include the XML namespace declaration
15365
+ * @returns An XML component representing the click hyperlink
15366
+ */
15367
+ var createHyperlinkClick = (linkId, hasXmlNs) => new BuilderElement({
15368
+ name: "a:hlinkClick",
15369
+ attributes: _objectSpread2(_objectSpread2({}, hasXmlNs ? { xmlns: {
15370
+ key: "xmlns:a",
15371
+ value: "http://schemas.openxmlformats.org/drawingml/2006/main"
15372
+ } } : {}), {}, { id: {
15373
+ key: "r:id",
15374
+ value: `rId${linkId}`
15375
+ } })
15376
+ });
15377
+ //#endregion
15336
15378
  //#region src/file/drawing/doc-properties/non-visual-drawing-properties.ts
15337
15379
  /**
15338
15380
  * Non-visual drawing properties (`CT_NonVisualDrawingProps`) of the shapes, pictures and groups inside a drawing:
@@ -15527,7 +15569,7 @@ var DocProperties = class extends XmlComponent {
15527
15569
  } else for (let i = context.stack.length - 1; i >= 0; i--) {
15528
15570
  const element = context.stack[i];
15529
15571
  if (!(element instanceof ConcreteHyperlink)) continue;
15530
- this.root.push(createHyperlinkClick(element.linkId, true));
15572
+ this.root.push(element.createDrawingClick(context, true));
15531
15573
  break;
15532
15574
  }
15533
15575
  if (this.decorative) this.root.push(createDecorativeExtensionList(true));
@@ -15615,6 +15657,18 @@ var createEffectExtent = ({ top, right, bottom, left }) => new BuilderElement({
15615
15657
  * @module
15616
15658
  */
15617
15659
  /**
15660
+ * The largest width or height, in EMUs, Word opens a drawing at. The standard allows `ST_PositiveCoordinate` up to
15661
+ * 27273042316900, but Word and PowerPoint restrict it to 2147483647 and won't open a document with a larger drawing.
15662
+ *
15663
+ * Reference: [MS-OI29500] Part 1 Section 20.1.10.42, ST_PositiveCoordinate
15664
+ */
15665
+ var MAX_EXTENT = 2147483647;
15666
+ var EMUS_PER_PIXEL = 9525;
15667
+ var checkExtent = (dimension, value) => {
15668
+ if (value !== void 0 && value > MAX_EXTENT) throw new Error(`Invalid drawing ${dimension} ${value} EMUs (${Math.round(value / EMUS_PER_PIXEL)} pixels). Word won't open a drawing with a ${dimension} over ${MAX_EXTENT} EMUs (${Math.floor(MAX_EXTENT / EMUS_PER_PIXEL)} pixels). Sizes such as an ImageRun's transformation are in pixels, not EMUs`);
15669
+ return value;
15670
+ };
15671
+ /**
15618
15672
  * Creates an extent element for inline drawings.
15619
15673
  *
15620
15674
  * This element specifies the extents of the parent DrawingML object within
@@ -15638,17 +15692,19 @@ var createEffectExtent = ({ top, right, bottom, left }) => new BuilderElement({
15638
15692
  * y: 914400
15639
15693
  * });
15640
15694
  * ```
15695
+ *
15696
+ * @throws Error if the width or height is over 2147483647 EMUs, which Word won't open
15641
15697
  */
15642
15698
  var createExtent = ({ x, y }) => new BuilderElement({
15643
15699
  name: "wp:extent",
15644
15700
  attributes: {
15645
15701
  x: {
15646
15702
  key: "cx",
15647
- value: x
15703
+ value: checkExtent("width", x)
15648
15704
  },
15649
15705
  y: {
15650
15706
  key: "cy",
15651
- value: y
15707
+ value: checkExtent("height", y)
15652
15708
  }
15653
15709
  }
15654
15710
  });
@@ -16040,7 +16096,6 @@ var createDeletion = ({ id, author, date }, run) => new BuilderElement({
16040
16096
  var ImageRun = class extends XmlComponent {
16041
16097
  constructor(options) {
16042
16098
  var _options$insertion;
16043
- var _super = (..._args) => (super(..._args), _defineProperty(this, "imageData", void 0), this);
16044
16099
  const key = `${hashedId(options.data)}.${options.type}`;
16045
16100
  const imageData = options.type === "svg" ? _objectSpread2(_objectSpread2({ type: options.type }, createImageData(options, key)), {}, { fallback: _objectSpread2({ type: options.fallback.type }, createImageData(_objectSpread2(_objectSpread2({}, options.fallback), {}, { transformation: options.transformation }), `${hashedId(options.fallback.data)}.${options.fallback.type}`)) }) : _objectSpread2({ type: options.type }, createImageData(options, key));
16046
16101
  const drawing = new Drawing(imageData, {
@@ -16054,8 +16109,10 @@ var ImageRun = class extends XmlComponent {
16054
16109
  });
16055
16110
  const properties = new RunProperties(options.run);
16056
16111
  const revision = (_options$insertion = options.insertion) !== null && _options$insertion !== void 0 ? _options$insertion : options.deletion;
16112
+ const rootName = options.insertion ? "w:ins" : options.deletion ? "w:del" : "w:r";
16113
+ super(rootName);
16114
+ _defineProperty(this, "imageData", void 0);
16057
16115
  if (revision) {
16058
- _super(options.insertion ? "w:ins" : "w:del");
16059
16116
  this.root.push(new ChangeAttributes({
16060
16117
  id: revision.id,
16061
16118
  author: revision.author,
@@ -16067,7 +16124,6 @@ var ImageRun = class extends XmlComponent {
16067
16124
  });
16068
16125
  this.addChildElement(options.insertion && options.deletion ? createDeletion(options.deletion, run) : run);
16069
16126
  } else {
16070
- _super("w:r");
16071
16127
  this.root.push(properties);
16072
16128
  this.root.push(drawing);
16073
16129
  }
@@ -16220,6 +16276,10 @@ var SequentialIdentifierInstruction = class extends XmlComponent {
16220
16276
  * Each identifier maintains its own sequence, allowing you to have separate numbering
16221
16277
  * for figures, tables, equations, etc.
16222
16278
  *
16279
+ * It is written dirty, so Word numbers it when it opens the document, after asking to update the fields. When the
16280
+ * document is given `pageNumbers`, it is written clean, with its number counted as Word counts it, or blank where
16281
+ * Word's count isn't known, and Word doesn't ask.
16282
+ *
16223
16283
  * Reference: http://officeopenxml.com/WPrun.php
16224
16284
  *
16225
16285
  * @publicApi
@@ -16248,7 +16308,7 @@ var SequentialIdentifierInstruction = class extends XmlComponent {
16248
16308
  var SequentialIdentifier = class extends Run {
16249
16309
  constructor(identifier) {
16250
16310
  super({});
16251
- this.root.push(createBegin(true));
16311
+ this.root.push(createBeginDirtyWithoutPageNumbers());
16252
16312
  this.root.push(new SequentialIdentifierInstruction(identifier));
16253
16313
  this.root.push(createSeparate());
16254
16314
  this.root.push(createEnd());
@@ -16273,7 +16333,10 @@ var SequentialIdentifier = class extends Run {
16273
16333
  var FldSimpleAttrs = class extends XmlAttributeComponent {
16274
16334
  constructor(..._args) {
16275
16335
  super(..._args);
16276
- _defineProperty(this, "xmlKeys", { instr: "w:instr" });
16336
+ _defineProperty(this, "xmlKeys", {
16337
+ instr: "w:instr",
16338
+ fldLock: "w:fldLock"
16339
+ });
16277
16340
  }
16278
16341
  };
16279
16342
  /**
@@ -16306,12 +16369,18 @@ var FldSimpleAttrs = class extends XmlAttributeComponent {
16306
16369
  *
16307
16370
  * // Simple field with cached value
16308
16371
  * new SimpleField("DATE", "2024-01-01");
16372
+ *
16373
+ * // Locked field, Word keeps the cached value when fields are updated
16374
+ * new SimpleField("DATE", "2024-01-01", { locked: true });
16309
16375
  * ```
16310
16376
  */
16311
16377
  var SimpleField = class extends XmlComponent {
16312
- constructor(instruction, cachedValue) {
16378
+ constructor(instruction, cachedValue, options = {}) {
16313
16379
  super("w:fldSimple");
16314
- this.root.push(new FldSimpleAttrs({ instr: instruction }));
16380
+ this.root.push(new FldSimpleAttrs({
16381
+ instr: instruction,
16382
+ fldLock: options.locked ? true : void 0
16383
+ }));
16315
16384
  if (cachedValue !== void 0) this.root.push(new TextRun(cachedValue));
16316
16385
  }
16317
16386
  };
@@ -16336,6 +16405,1035 @@ var SimpleMailMergeField = class extends SimpleField {
16336
16405
  }
16337
16406
  };
16338
16407
  //#endregion
16408
+ //#region src/file/document/body/field-number-formats.ts
16409
+ var LARGEST_ROMAN = 32767;
16410
+ var LARGEST_LETTERS = 780;
16411
+ var ROMAN = [
16412
+ [1e3, "M"],
16413
+ [900, "CM"],
16414
+ [500, "D"],
16415
+ [400, "CD"],
16416
+ [100, "C"],
16417
+ [90, "XC"],
16418
+ [50, "L"],
16419
+ [40, "XL"],
16420
+ [10, "X"],
16421
+ [9, "IX"],
16422
+ [5, "V"],
16423
+ [4, "IV"],
16424
+ [1, "I"]
16425
+ ];
16426
+ var roman = (value) => value <= LARGEST_ROMAN ? ROMAN.reduce(({ rest, text }, [amount, numeral]) => ({
16427
+ rest: rest % amount,
16428
+ text: text + numeral.repeat(Math.floor(rest / amount))
16429
+ }), {
16430
+ rest: value,
16431
+ text: ""
16432
+ }).text : void 0;
16433
+ var letters = (value) => value === 0 ? "" : value <= LARGEST_LETTERS ? String.fromCharCode(65 + (value - 1) % 26).repeat(Math.ceil(value / 26)) : void 0;
16434
+ var ordinal = (value) => {
16435
+ var _ref;
16436
+ return `${value}${value % 100 >= 11 && value % 100 <= 13 ? "th" : (_ref = [
16437
+ "th",
16438
+ "st",
16439
+ "nd",
16440
+ "rd"
16441
+ ][value % 10]) !== null && _ref !== void 0 ? _ref : "th"}`;
16442
+ };
16443
+ /**
16444
+ * The number formats of a field's `\*` switch that are written as Word writes them, by their names in any capitals.
16445
+ * Word writes roman numerals and letters in small letters when the name starts with a small letter, as `roman`, and in
16446
+ * capitals otherwise, as `Roman` and `ROMAN`
16447
+ */
16448
+ var numberWriterOf = (format) => {
16449
+ const small = format.charAt(0) !== format.charAt(0).toUpperCase();
16450
+ const inCase = (write) => (value) => {
16451
+ var _write;
16452
+ return small ? (_write = write(value)) === null || _write === void 0 ? void 0 : _write.toLowerCase() : write(value);
16453
+ };
16454
+ switch (format.toLowerCase()) {
16455
+ case "arabic": return String;
16456
+ case "roman": return inCase(roman);
16457
+ case "alphabetic": return inCase(letters);
16458
+ case "ordinal": return (value) => value > 0 ? ordinal(value) : void 0;
16459
+ case "arabicdash": return (value) => `- ${value} -`;
16460
+ default: return;
16461
+ }
16462
+ };
16463
+ var PLAIN_FORMATS = /* @__PURE__ */ new Set([
16464
+ "mergeformat",
16465
+ "charformat",
16466
+ "mergeformatinet"
16467
+ ]);
16468
+ var CASE_FORMATS = /* @__PURE__ */ new Set([
16469
+ "upper",
16470
+ "lower",
16471
+ "firstcap",
16472
+ "caps"
16473
+ ]);
16474
+ /**
16475
+ * Whether Word's text for a picture of a field's `\#` switch is known: one of digits (`0`), digits only where the number
16476
+ * has them (`#`) and commas between thousands, as Word wrote `00`, `000`, `0`, `#` and `#,##0` for page numbers
16477
+ * (`scripts/layout-probes/word-page-fields.ts` PF5 to PF7)
16478
+ */
16479
+ var isNumberPicture = (picture) => /^[#0,]*[#0][#0,]*$/.test(picture);
16480
+ /**
16481
+ * A number with a picture: with as many digits as it has `0`s at least, which Word fills with 0s (5 is 05 with `00`), and
16482
+ * its thousands between commas when it has one (1234 is 1,234 with `#,##0`). Undefined where a `#` has no digit of the
16483
+ * number, which Word writes as a space, not yet seen
16484
+ */
16485
+ var inNumberPicture = (value, picture) => {
16486
+ const zeros = [...picture].filter((character) => character === "0").length;
16487
+ const places = zeros + [...picture].filter((character) => character === "#").length;
16488
+ const digits = String(value).padStart(zeros, "0");
16489
+ if (digits.length < places || zeros === 0 && value === 0) return;
16490
+ return picture.includes(",") ? digits.replace(/\B(?=(\d{3})+$)/g, ",") : digits;
16491
+ };
16492
+ /**
16493
+ * Text in the capitals of a field's switch, applied after its number's format, as Word wrote `\* roman \* Upper` as V,
16494
+ * `\* Ordinal \* Upper` as 5TH, and "above" with `\* Upper` as ABOVE (`word-page-fields.ts` PF3 and PF5)
16495
+ */
16496
+ var inCapitals = (text, capitals) => {
16497
+ switch (capitals) {
16498
+ case "upper": return text.toUpperCase();
16499
+ case "lower": return text.toLowerCase();
16500
+ case "firstcap": return text.charAt(0).toUpperCase() + text.slice(1);
16501
+ default: return text;
16502
+ }
16503
+ };
16504
+ //#endregion
16505
+ //#region src/file/document/body/page-number-fields.ts
16506
+ /**
16507
+ * Writes estimated page numbers into the fields of a tree of elements that show them: those docx formats to write a
16508
+ * document, and those `patchDocument` parses from a template. Not part of the public API.
16509
+ *
16510
+ * A page reference is a PAGEREF field, and the numbers of pages of the document and of a section are NUMPAGES and
16511
+ * SECTIONPAGES fields. Each field's result is written just after its `separate` field character, and any result it had
16512
+ * is taken out.
16513
+ *
16514
+ * @module
16515
+ */
16516
+ /** Reads a field that shows a page's number or a number of pages, or undefined for another field */
16517
+ var numberFieldOf = (instruction) => {
16518
+ var _match;
16519
+ const field = new RegExp("^\\s*(PAGEREF|NUMPAGES|SECTIONPAGES)\\b(.*)$", "is").exec(instruction);
16520
+ const reference = (field === null || field === void 0 ? void 0 : field[1].toUpperCase()) === "PAGEREF" ? new RegExp("^\\s*(\"?)([^\\s\"\\\\]+)\\1(.*)$", "s").exec(field[2]) : void 0;
16521
+ if (!field || field[1].toUpperCase() === "PAGEREF" && !reference) return;
16522
+ const parts = (_match = (reference ? reference[3] : field[2]).match(/"[^"]*"|\S+/g)) !== null && _match !== void 0 ? _match : [];
16523
+ let numberFormat;
16524
+ let picture;
16525
+ const capitals = [];
16526
+ let relative = false;
16527
+ let written = true;
16528
+ for (let index = 0; index < parts.length; index++) {
16529
+ const part = parts[index];
16530
+ const argument = () => {
16531
+ var _parts$index;
16532
+ return (part.length > 2 ? part.slice(2) : (_parts$index = parts[++index]) !== null && _parts$index !== void 0 ? _parts$index : "").replace(/^"(.*)"$/, "$1");
16533
+ };
16534
+ if (/^\\p$/i.test(part)) relative = true;
16535
+ else if (part.startsWith("\\#")) {
16536
+ var _picture;
16537
+ const value = argument();
16538
+ written && (written = picture === void 0 && isNumberPicture(value));
16539
+ (_picture = picture) !== null && _picture !== void 0 || (picture = value);
16540
+ } else if (part.startsWith("\\*")) {
16541
+ const name = argument();
16542
+ const lower = name.toLowerCase();
16543
+ if (CASE_FORMATS.has(lower)) capitals.push(lower);
16544
+ else if (name !== "" && !PLAIN_FORMATS.has(lower)) {
16545
+ var _numberFormat;
16546
+ written && (written = numberFormat === void 0 && numberWriterOf(name) !== void 0);
16547
+ (_numberFormat = numberFormat) !== null && _numberFormat !== void 0 || (numberFormat = name);
16548
+ }
16549
+ }
16550
+ }
16551
+ const own = _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, numberFormat === void 0 ? {} : { numberFormat }), picture === void 0 ? {} : { picture }), capitals.length === 0 ? {} : { capitals: capitals[0] }), {}, { written: written && capitals.length <= 1 && capitals[0] !== "caps" && (numberFormat === void 0 || picture === void 0) });
16552
+ return reference ? _objectSpread2({
16553
+ type: "pageReference",
16554
+ bookmark: reference[2],
16555
+ relative
16556
+ }, own) : _objectSpread2({
16557
+ type: "pageCount",
16558
+ scope: field[1].toUpperCase() === "NUMPAGES" ? "document" : "section"
16559
+ }, own);
16560
+ };
16561
+ /**
16562
+ * Whether a field is a table of contents that writes the number of a SEQ field before each page number (`\s`), such as
16563
+ * 2-5 for page 5 of chapter 2, which isn't written
16564
+ */
16565
+ var prefixesPageNumbers = (instruction) => new RegExp("^\\s*TOC\\b.*\\\\s\\b", "is").test(instruction);
16566
+ /**
16567
+ * The result of a field that shows a page's number or a number of pages, or undefined to leave it as it is. A field
16568
+ * the estimate has no number for is left as it is, or made blank, and so is a page number in a table of contents that
16569
+ * writes a SEQ field's number before it.
16570
+ */
16571
+ var resultFrom = (instruction, { enclosing, within, inTextBox }, { estimate, sectionPageCount, blank, relativeTo }) => {
16572
+ const field = numberFieldOf(instruction);
16573
+ if (field === void 0) return;
16574
+ const { bookmarks, pageCount, bookmarkPageNumbers } = estimate;
16575
+ const { numberFormat, picture, capitals, written } = field;
16576
+ const writesNumber = numberFormat !== void 0 || picture !== void 0;
16577
+ /** A number in the field's format of its own, or as it is */
16578
+ const inFormat = (value) => value === void 0 ? void 0 : picture === void 0 ? numberWriterOf(numberFormat !== null && numberFormat !== void 0 ? numberFormat : "arabic")(value) : inNumberPicture(value, picture);
16579
+ const position = field.type === "pageReference" && field.relative && within === "counted" && !inTextBox ? relativeTo === null || relativeTo === void 0 ? void 0 : relativeTo(field.bookmark) : void 0;
16580
+ let result;
16581
+ if (!written) result = void 0;
16582
+ else if (field.type === "pageCount") result = inFormat(field.scope === "document" ? pageCount : sectionPageCount);
16583
+ else if (enclosing.some(prefixesPageNumbers)) result = void 0;
16584
+ else if (writesNumber) result = inFormat(bookmarkPageNumbers === null || bookmarkPageNumbers === void 0 ? void 0 : bookmarkPageNumbers.get(field.bookmark));
16585
+ else result = field.relative ? position : bookmarks.get(field.bookmark);
16586
+ return result === void 0 ? blank ? "" : void 0 : inCapitals(result, capitals);
16587
+ };
16588
+ /** Where the content of an element is: in what an application that doesn't read Word's own shows, or in deleted text */
16589
+ var placeIn = (name, within) => name === "mc:Fallback" || within === "fallback" ? "fallback" : name === "w:del" || name === "w:moveFrom" ? "deleted" : within;
16590
+ /**
16591
+ * Writes the results the filling works out into the fields in the elements, in order.
16592
+ */
16593
+ var fillFields = (tree, elements, open, filling, within = "counted", inTextBox = false) => {
16594
+ for (let index = 0; index < elements.length; index++) {
16595
+ const element = elements[index];
16596
+ const name = tree.nameOf(element);
16597
+ if (name === void 0) continue;
16598
+ const current = open[open.length - 1];
16599
+ if (name === "w:fldChar") {
16600
+ const type = tree.attributeOf(element, "w:fldCharType");
16601
+ if (type === "begin") open.push({
16602
+ begin: element,
16603
+ instruction: "",
16604
+ inResult: false
16605
+ });
16606
+ else if (type === "separate" && current) {
16607
+ tree.writeClean(current.begin, current.instruction);
16608
+ current.inResult = true;
16609
+ current.result = filling.resultOf(current.instruction, {
16610
+ within,
16611
+ enclosing: open.slice(0, -1).map((field) => field.instruction),
16612
+ inTextBox
16613
+ });
16614
+ if (current.result !== void 0) {
16615
+ elements.splice(index + 1, 0, tree.textElement(current.result));
16616
+ index++;
16617
+ }
16618
+ } else if (type === "end") open.pop();
16619
+ } else if (name === "w:instrText" && current && !current.inResult) current.instruction += tree.textOf(element);
16620
+ else if ((name === "w:t" || name === "w:tab" || name === "w:br" || name === "w:cr") && (current === null || current === void 0 ? void 0 : current.result) !== void 0) {
16621
+ elements.splice(index, 1);
16622
+ index--;
16623
+ } else if (name === "w:fldSimple") {
16624
+ const result = filling.resultOf(String(tree.attributeOf(element, "w:instr")), {
16625
+ within,
16626
+ enclosing: open.map((field) => field.instruction),
16627
+ inTextBox
16628
+ });
16629
+ if (result === void 0) {
16630
+ var _tree$contentOf;
16631
+ fillFields(tree, (_tree$contentOf = tree.contentOf(element)) !== null && _tree$contentOf !== void 0 ? _tree$contentOf : [], [], filling, within, inTextBox);
16632
+ } else tree.setSimpleFieldResult(element, result);
16633
+ } else {
16634
+ var _tree$contentOf2;
16635
+ if (name === "w:p") {
16636
+ var _filling$beforeParagr;
16637
+ (_filling$beforeParagr = filling.beforeParagraph) === null || _filling$beforeParagr === void 0 || _filling$beforeParagr.call(filling, element);
16638
+ }
16639
+ fillFields(tree, (_tree$contentOf2 = tree.contentOf(element)) !== null && _tree$contentOf2 !== void 0 ? _tree$contentOf2 : [], open, filling, placeIn(name, within), inTextBox || name === "w:txbxContent");
16640
+ if (name === "w:p") filling.afterParagraph(element);
16641
+ }
16642
+ }
16643
+ };
16644
+ /** The section properties (`w:sectPr`) in the elements, in order: those of the paragraphs that end sections, and the last */
16645
+ var sectionPropertiesIn = (tree, elements) => elements.flatMap((element) => {
16646
+ var _tree$contentOf3;
16647
+ const name = tree.nameOf(element);
16648
+ if (name === void 0) return [];
16649
+ return name === "w:sectPr" ? [element] : sectionPropertiesIn(tree, (_tree$contentOf3 = tree.contentOf(element)) !== null && _tree$contentOf3 !== void 0 ? _tree$contentOf3 : []);
16650
+ });
16651
+ /** Whether a paragraph ends a section: whether its properties have the section's */
16652
+ var endsSection = (tree, paragraph) => {
16653
+ var _tree$contentOf4;
16654
+ return ((_tree$contentOf4 = tree.contentOf(paragraph)) !== null && _tree$contentOf4 !== void 0 ? _tree$contentOf4 : []).some((child) => {
16655
+ var _tree$contentOf5;
16656
+ return tree.nameOf(child) === "w:pPr" && ((_tree$contentOf5 = tree.contentOf(child)) !== null && _tree$contentOf5 !== void 0 ? _tree$contentOf5 : []).some((part) => tree.nameOf(part) === "w:sectPr");
16657
+ });
16658
+ };
16659
+ /**
16660
+ * The number of pages each header and footer shows in its SECTIONPAGES fields, by the id of the relationship to it:
16661
+ * that of the sections whose pages it is on, when they all have the same. A section without a header or footer of a kind
16662
+ * has the one of the section before, as Word lays them out.
16663
+ */
16664
+ var partPageCountsOf = (tree, body, sectionPageCounts) => {
16665
+ const countsOfParts = sectionPropertiesIn(tree, [body]).reduce((all, properties) => {
16666
+ var _tree$contentOf6, _all;
16667
+ const references = ((_tree$contentOf6 = tree.contentOf(properties)) !== null && _tree$contentOf6 !== void 0 ? _tree$contentOf6 : []).flatMap((child) => {
16668
+ const name = tree.nameOf(child);
16669
+ return name === "w:headerReference" || name === "w:footerReference" ? [[`${name} ${String(tree.attributeOf(child, "w:type"))}`, String(tree.attributeOf(child, "r:id"))]] : [];
16670
+ });
16671
+ return [...all, new Map([...(_all = all[all.length - 1]) !== null && _all !== void 0 ? _all : [], ...references])];
16672
+ }, []).reduce((counts, parts, section) => {
16673
+ for (const id of parts.values()) {
16674
+ var _counts$get;
16675
+ counts.set(id, [...(_counts$get = counts.get(id)) !== null && _counts$get !== void 0 ? _counts$get : [], sectionPageCounts[section]]);
16676
+ }
16677
+ return counts;
16678
+ }, /* @__PURE__ */ new Map());
16679
+ return new Map([...countsOfParts].flatMap(([id, [first, ...rest]]) => first !== void 0 && rest.every((count) => count === first) ? [[id, first]] : []));
16680
+ };
16681
+ /**
16682
+ * Writes the estimated page numbers into the fields of a document's body that show them: its PAGEREF fields, in its
16683
+ * tables of contents and elsewhere, and its NUMPAGES and SECTIONPAGES fields.
16684
+ *
16685
+ * @returns The number of pages each header and footer shows in its SECTIONPAGES fields, by the id of the relationship to it
16686
+ */
16687
+ var fillBodyFields = (tree, body, estimate, { blank }) => {
16688
+ const { sectionPageCounts = [], relativePositions } = estimate;
16689
+ let section = 0;
16690
+ const relativeCounts = /* @__PURE__ */ new Map();
16691
+ const relativeTo = (bookmark) => {
16692
+ var _relativeCounts$get, _relativePositions$ge;
16693
+ const count = (_relativeCounts$get = relativeCounts.get(bookmark)) !== null && _relativeCounts$get !== void 0 ? _relativeCounts$get : 0;
16694
+ relativeCounts.set(bookmark, count + 1);
16695
+ return relativePositions === null || relativePositions === void 0 || (_relativePositions$ge = relativePositions.get(bookmark)) === null || _relativePositions$ge === void 0 ? void 0 : _relativePositions$ge[count];
16696
+ };
16697
+ fillFields(tree, [body], [], {
16698
+ resultOf: (instruction, place) => resultFrom(instruction, place, {
16699
+ estimate,
16700
+ sectionPageCount: sectionPageCounts[section],
16701
+ blank,
16702
+ relativeTo
16703
+ }),
16704
+ afterParagraph: (paragraph) => {
16705
+ section += endsSection(tree, paragraph) ? 1 : 0;
16706
+ }
16707
+ });
16708
+ return partPageCountsOf(tree, body, sectionPageCounts);
16709
+ };
16710
+ /**
16711
+ * Writes the estimated page numbers into the fields of a header, footer, footnote or endnote that show them, with the
16712
+ * number of pages its SECTIONPAGES fields show, if it is known. A page reference with `\p` in a footnote or endnote
16713
+ * (`notes`) writes "on page" and its bookmark's page, whatever page it is on, as Word writes it
16714
+ * (`word-page-fields.docx` PF8f, PF8g)
16715
+ */
16716
+ var fillPartFields = (tree, part, estimate, { blank, sectionPageCount, notes = false }) => {
16717
+ const onPage = (bookmark) => {
16718
+ const page = estimate.bookmarks.get(bookmark);
16719
+ return page === void 0 ? void 0 : `on page ${page}`;
16720
+ };
16721
+ fillFields(tree, [part], [], {
16722
+ resultOf: (instruction, place) => resultFrom(instruction, place, _objectSpread2({
16723
+ estimate,
16724
+ sectionPageCount,
16725
+ blank
16726
+ }, notes ? { relativeTo: onPage } : {})),
16727
+ afterParagraph: () => void 0
16728
+ });
16729
+ };
16730
+ /** Writes the numbers of the SEQ fields of a document's body into them */
16731
+ var fillSequenceFields = (tree, body, { beforeParagraph, resultOf }) => fillFields(tree, [body], [], {
16732
+ resultOf: (instruction, { within }) => resultOf(instruction, within),
16733
+ beforeParagraph,
16734
+ afterParagraph: () => void 0
16735
+ });
16736
+ //#endregion
16737
+ //#region src/file/table-of-contents/field-instruction.ts
16738
+ /**
16739
+ * Field Instruction module for Table of Contents.
16740
+ *
16741
+ * This module handles the generation of TOC field instruction text
16742
+ * that controls how the table of contents is built.
16743
+ *
16744
+ * Reference: http://officeopenxml.com/WPfieldInstructions.php
16745
+ *
16746
+ * @module
16747
+ */
16748
+ /**
16749
+ * Represents a field instruction for a Table of Contents.
16750
+ *
16751
+ * The FieldInstruction class generates the TOC field code string that Word uses
16752
+ * to determine how to build the table of contents, including which headings to include,
16753
+ * formatting options, and other TOC-specific settings.
16754
+ *
16755
+ * Reference: http://officeopenxml.com/WPfieldInstructions.php
16756
+ *
16757
+ * ## XSD Schema
16758
+ * ```xml
16759
+ * <xsd:element name="instrText" type="CT_Text"/>
16760
+ * ```
16761
+ *
16762
+ * @example
16763
+ * ```typescript
16764
+ * // Basic TOC field instruction
16765
+ * new FieldInstruction({ headingStyleRange: "1-3" });
16766
+ *
16767
+ * // TOC with hyperlinks and custom styles
16768
+ * new FieldInstruction({
16769
+ * hyperlink: true,
16770
+ * headingStyleRange: "1-3",
16771
+ * stylesWithLevels: [new StyleLevel("CustomStyle", 2)],
16772
+ * });
16773
+ * ```
16774
+ */
16775
+ var FieldInstruction = class extends XmlComponent {
16776
+ constructor(properties = {}) {
16777
+ super("w:instrText");
16778
+ _defineProperty(this, "properties", void 0);
16779
+ this.properties = properties;
16780
+ this.root.push(new TextAttributes({ space: SpaceType.PRESERVE }));
16781
+ let instruction = "TOC";
16782
+ if (this.properties.captionLabel) instruction = `${instruction} \\a "${this.properties.captionLabel}"`;
16783
+ if (this.properties.entriesFromBookmark) instruction = `${instruction} \\b "${this.properties.entriesFromBookmark}"`;
16784
+ if (this.properties.captionLabelIncludingNumbers) instruction = `${instruction} \\c "${this.properties.captionLabelIncludingNumbers}"`;
16785
+ if (this.properties.sequenceAndPageNumbersSeparator) instruction = `${instruction} \\d "${this.properties.sequenceAndPageNumbersSeparator}"`;
16786
+ if (this.properties.tcFieldIdentifier) instruction = `${instruction} \\f "${this.properties.tcFieldIdentifier}"`;
16787
+ if (this.properties.hyperlink) instruction = `${instruction} \\h`;
16788
+ if (this.properties.tcFieldLevelRange) instruction = `${instruction} \\l "${this.properties.tcFieldLevelRange}"`;
16789
+ if (this.properties.pageNumbersEntryLevelsRange) instruction = `${instruction} \\n "${this.properties.pageNumbersEntryLevelsRange}"`;
16790
+ if (this.properties.headingStyleRange) instruction = `${instruction} \\o "${this.properties.headingStyleRange}"`;
16791
+ if (this.properties.entryAndPageNumberSeparator) instruction = `${instruction} \\p "${this.properties.entryAndPageNumberSeparator}"`;
16792
+ if (this.properties.seqFieldIdentifierForPrefix) instruction = `${instruction} \\s "${this.properties.seqFieldIdentifierForPrefix}"`;
16793
+ if (this.properties.stylesWithLevels && this.properties.stylesWithLevels.length) {
16794
+ const styles = this.properties.stylesWithLevels.map((sl) => `${sl.styleName},${sl.level}`).join(",");
16795
+ instruction = `${instruction} \\t "${styles}"`;
16796
+ }
16797
+ if (this.properties.useAppliedParagraphOutlineLevel) instruction = `${instruction} \\u`;
16798
+ if (this.properties.preserveTabInEntries) instruction = `${instruction} \\w`;
16799
+ if (this.properties.preserveNewLineInEntries) instruction = `${instruction} \\x`;
16800
+ if (this.properties.hideTabAndPageNumbersInWebView) instruction = `${instruction} \\z`;
16801
+ this.root.push(instruction);
16802
+ }
16803
+ };
16804
+ //#endregion
16805
+ //#region src/file/table-of-contents/sdt-content.ts
16806
+ /**
16807
+ * Structured Document Tag Content module.
16808
+ *
16809
+ * This module represents the content container for structured document tags,
16810
+ * including table of contents elements.
16811
+ *
16812
+ * Reference: http://officeopenxml.com/WPtableOfContents.php
16813
+ *
16814
+ * @module
16815
+ */
16816
+ /**
16817
+ * Represents the content portion of a Structured Document Tag.
16818
+ *
16819
+ * The StructuredDocumentTagContent contains the actual content elements
16820
+ * (paragraphs, tables, etc.) within a structured document tag, such as
16821
+ * the paragraphs that make up a table of contents.
16822
+ *
16823
+ * Reference: http://officeopenxml.com/WPtableOfContents.php
16824
+ *
16825
+ * ## XSD Schema
16826
+ * ```xml
16827
+ * <xsd:complexType name="CT_SdtContentBlock">
16828
+ * <xsd:group ref="EG_ContentBlockContent" minOccurs="0" maxOccurs="unbounded"/>
16829
+ * </xsd:complexType>
16830
+ * ```
16831
+ *
16832
+ * @example
16833
+ * ```typescript
16834
+ * const content = new StructuredDocumentTagContent();
16835
+ * content.addChildElement(new Paragraph("Content"));
16836
+ * ```
16837
+ */
16838
+ var StructuredDocumentTagContent = class extends XmlComponent {
16839
+ constructor() {
16840
+ super("w:sdtContent");
16841
+ }
16842
+ };
16843
+ //#endregion
16844
+ //#region src/file/table-of-contents/heading-entries.ts
16845
+ /**
16846
+ * Entries written into a table of contents from the headings of the document.
16847
+ *
16848
+ * A table of contents is a TOC field. Word fills in its entries when it updates the field. Until then, and in
16849
+ * applications that don't update it, such as LibreOffice, it shows the entries it was last filled in with, and without
16850
+ * any it is empty. So once the body is written, each table of contents that wasn't given `cachedEntries` or
16851
+ * `contentChildren` is filled in from the headings its switches include, the way Word fills it in: each heading is
16852
+ * bookmarked, and its entry links to the bookmark and gives its page with a PAGEREF field. The page numbers are left
16853
+ * empty, because they depend on how the document is laid out. Word fills them in when it updates the field, unless the
16854
+ * document's `pageNumbers` writes them.
16855
+ *
16856
+ * @module
16857
+ */
16858
+ /**
16859
+ * The beginning of a table of contents' field: dirty or clean, as the caller set it, or else dirty unless the document
16860
+ * is given page numbers
16861
+ */
16862
+ var beginOf = (beginDirty) => beginDirty === void 0 ? createBeginDirtyWithoutPageNumbers() : createBegin(beginDirty);
16863
+ /** The formatted tables of contents, with what each is filled in with, or undefined when it was given its content */
16864
+ var writtenTables = /* @__PURE__ */ new WeakMap();
16865
+ /**
16866
+ * Records a formatted table of contents, so the paragraphs in it aren't taken for headings, with what to fill it in
16867
+ * with from the headings once the body it is in is written. That is undefined when it was given its content.
16868
+ */
16869
+ var recordTableOfContents = (table, fillWith) => {
16870
+ writtenTables.set(table, fillWith);
16871
+ };
16872
+ /**
16873
+ * The ids of the bookmarks on a body's headings: the first for its first bookmarked heading, and so on. Each is taken
16874
+ * from the counter every bookmark shares, the first time it is needed, so a document packed again is written the same.
16875
+ */
16876
+ var HeadingBookmarkIds = class {
16877
+ constructor() {
16878
+ _defineProperty(this, "ids", []);
16879
+ }
16880
+ get(index) {
16881
+ var _this$ids, _this$ids$index;
16882
+ (_this$ids$index = (_this$ids = this.ids)[index]) !== null && _this$ids$index !== void 0 || (_this$ids[index] = bookmarkUniqueNumericId());
16883
+ return this.ids[index];
16884
+ }
16885
+ };
16886
+ /** The name of a formatted element, or `_attr` for its parent's attributes */
16887
+ var nameOf$2 = (element) => typeof element === "object" && element !== null ? Object.keys(element)[0] : void 0;
16888
+ /** The children of a formatted element. An element with only attributes has them as its one child */
16889
+ var childrenOf = (element) => {
16890
+ const name = nameOf$2(element);
16891
+ const content = name === void 0 ? void 0 : element[name];
16892
+ return Array.isArray(content) ? content : content === void 0 ? [] : [content];
16893
+ };
16894
+ var childOf = (element, name) => childrenOf(element).find((child) => nameOf$2(child) === name);
16895
+ var attributeOf = (element, attribute) => {
16896
+ var _childOf;
16897
+ return (_childOf = childOf(element, "_attr")) === null || _childOf === void 0 || (_childOf = _childOf._attr) === null || _childOf === void 0 ? void 0 : _childOf[attribute];
16898
+ };
16899
+ /** An attribute such as `w:val="2"` as a number. Imported XML gives it as a string */
16900
+ var numberAttributeOf = (element, attribute) => {
16901
+ const value = attributeOf(element, attribute);
16902
+ return value === void 0 ? void 0 : Number(value);
16903
+ };
16904
+ /** The block-level containers of paragraphs: tables, their rows and cells, and content controls */
16905
+ var BLOCK_CONTAINERS = /* @__PURE__ */ new Set([
16906
+ "w:tbl",
16907
+ "w:tr",
16908
+ "w:tc",
16909
+ "w:sdt",
16910
+ "w:sdtContent",
16911
+ "w:customXml"
16912
+ ]);
16913
+ /**
16914
+ * The paragraphs and the tables of contents, in the order they are in the body. A table of contents isn't looked into,
16915
+ * so the paragraphs in it aren't taken for headings. Nor are paragraphs in text boxes, as in Word.
16916
+ */
16917
+ var blocksOf = (elements) => elements.flatMap((element) => {
16918
+ const name = nameOf$2(element);
16919
+ if (name === "w:p" || writtenTables.has(element)) return [element];
16920
+ return name !== void 0 && BLOCK_CONTAINERS.has(name) ? blocksOf(childrenOf(element)) : [];
16921
+ });
16922
+ /** The elements in a paragraph that its text is in. Deleted text, field instructions and drawings aren't */
16923
+ var TEXT_CONTAINERS = /* @__PURE__ */ new Set([
16924
+ "w:r",
16925
+ "w:hyperlink",
16926
+ "w:ins",
16927
+ "w:moveTo",
16928
+ "w:smartTag",
16929
+ "w:customXml",
16930
+ "w:sdt",
16931
+ "w:sdtContent",
16932
+ "w:fldSimple",
16933
+ "w:dir",
16934
+ "w:bdo"
16935
+ ]);
16936
+ /** The text an element in a run stands for, such as `\t` for a tab. A page or column break isn't text */
16937
+ var textOfRunContent = (element) => {
16938
+ switch (nameOf$2(element)) {
16939
+ case "w:t": return childrenOf(element).filter((child) => typeof child === "string").join("");
16940
+ case "w:tab": return " ";
16941
+ case "w:br": return [void 0, "textWrapping"].includes(attributeOf(element, "w:type")) ? "\n" : "";
16942
+ case "w:cr": return "\n";
16943
+ case "w:noBreakHyphen": return "-";
16944
+ default: return "";
16945
+ }
16946
+ };
16947
+ /** The text of a paragraph. Of a field, only its result is text, not its instruction */
16948
+ var textOf = (paragraph) => {
16949
+ const fields = [];
16950
+ const read = (element) => {
16951
+ const name = nameOf$2(element);
16952
+ if (name !== void 0 && TEXT_CONTAINERS.has(name)) return childrenOf(element).map(read).join("");
16953
+ if (name === "w:fldChar") {
16954
+ const type = attributeOf(element, "w:fldCharType");
16955
+ if (type === "begin") fields.push(false);
16956
+ else if (type === "separate") fields[fields.length - 1] = true;
16957
+ else fields.pop();
16958
+ return "";
16959
+ }
16960
+ return fields.every(Boolean) ? textOfRunContent(element) : "";
16961
+ };
16962
+ return childrenOf(paragraph).map(read).join("");
16963
+ };
16964
+ /** The bookmarks started and ended in an element, in order */
16965
+ var bookmarkMarksOf = (element) => {
16966
+ const name = nameOf$2(element);
16967
+ if (name === "w:bookmarkStart") return [{
16968
+ start: true,
16969
+ id: attributeOf(element, "w:id"),
16970
+ name: attributeOf(element, "w:name")
16971
+ }];
16972
+ if (name === "w:bookmarkEnd") return [{
16973
+ start: false,
16974
+ id: attributeOf(element, "w:id")
16975
+ }];
16976
+ return name === void 0 || name === "_attr" ? [] : childrenOf(element).flatMap(bookmarkMarksOf);
16977
+ };
16978
+ /**
16979
+ * The names of the bookmarks each paragraph is in, for the `\b` switch: those open where it starts, followed through the
16980
+ * body, and those that start in it.
16981
+ */
16982
+ var bookmarksOf = (paragraphs) => {
16983
+ const open = /* @__PURE__ */ new Map();
16984
+ return paragraphs.map((paragraph) => {
16985
+ const marks = bookmarkMarksOf(paragraph);
16986
+ const names = /* @__PURE__ */ new Set([...open.values(), ...marks.flatMap((mark) => mark.start ? [mark.name] : [])]);
16987
+ for (const mark of marks) if (mark.start) open.set(mark.id, mark.name);
16988
+ else open.delete(mark.id);
16989
+ return names;
16990
+ });
16991
+ };
16992
+ /** The details of each paragraph that could be a heading. The bookmarks it is in are only followed when needed */
16993
+ var paragraphDetailsOf = (paragraphs, followBookmarks) => {
16994
+ const bookmarks = followBookmarks ? bookmarksOf(paragraphs) : [];
16995
+ return paragraphs.map((element, index) => {
16996
+ var _bookmarks$index;
16997
+ const properties = childOf(element, "w:pPr");
16998
+ return {
16999
+ element,
17000
+ styleId: attributeOf(childOf(properties, "w:pStyle"), "w:val"),
17001
+ outlineLevel: numberAttributeOf(childOf(properties, "w:outlineLvl"), "w:val"),
17002
+ text: textOf(element),
17003
+ bookmarks: (_bookmarks$index = bookmarks[index]) !== null && _bookmarks$index !== void 0 ? _bookmarks$index : /* @__PURE__ */ new Set()
17004
+ };
17005
+ });
17006
+ };
17007
+ /** The document's paragraph styles, by id, read from the styles as they are written */
17008
+ var stylesOf = (context) => {
17009
+ var _context$file;
17010
+ const styles = (_context$file = context.file) === null || _context$file === void 0 || (_context$file = _context$file.Styles) === null || _context$file === void 0 ? void 0 : _context$file.prepForXml(context);
17011
+ return new Map(childrenOf(styles).filter((style) => nameOf$2(style) === "w:style" && ["paragraph", void 0].includes(attributeOf(style, "w:type"))).map((style) => [attributeOf(style, "w:styleId"), {
17012
+ name: attributeOf(childOf(style, "w:name"), "w:val"),
17013
+ basedOn: attributeOf(childOf(style, "w:basedOn"), "w:val"),
17014
+ outlineLevel: numberAttributeOf(childOf(childOf(style, "w:pPr"), "w:outlineLvl"), "w:val")
17015
+ }]));
17016
+ };
17017
+ /** A range such as `1-3` */
17018
+ var parseRange = (range) => {
17019
+ const match = /^\s*(\d+)\s*-\s*(\d+)\s*$/.exec(range);
17020
+ return match ? [Number(match[1]), Number(match[2])] : void 0;
17021
+ };
17022
+ var isWithin = (level, [from, to]) => level >= from && level <= to;
17023
+ /** The level of a built-in heading style, Heading 1 to Heading 9, by its name, or by its id when it has no name */
17024
+ var headingLevelOf = (styleId, styles) => {
17025
+ var _styles$get$name, _styles$get;
17026
+ if (styleId === void 0) return;
17027
+ const match = /^heading ?([1-9])$/i.exec((_styles$get$name = (_styles$get = styles.get(styleId)) === null || _styles$get === void 0 ? void 0 : _styles$get.name) !== null && _styles$get$name !== void 0 ? _styles$get$name : styleId);
17028
+ return match ? Number(match[1]) : void 0;
17029
+ };
17030
+ /**
17031
+ * A style's outline level, from 0: its own, or else the one of the style it is based on. A built-in heading style has
17032
+ * its heading's. Following the styles it is based on stops after as many as there are, in case they loop.
17033
+ */
17034
+ var styleOutlineLevelOf = (styleId, styles, depth = 0) => {
17035
+ var _style$outlineLevel;
17036
+ if (styleId === void 0 || depth > styles.size) return;
17037
+ const style = styles.get(styleId);
17038
+ const heading = headingLevelOf(styleId, styles);
17039
+ return (_style$outlineLevel = style === null || style === void 0 ? void 0 : style.outlineLevel) !== null && _style$outlineLevel !== void 0 ? _style$outlineLevel : heading === void 0 ? styleOutlineLevelOf(style === null || style === void 0 ? void 0 : style.basedOn, styles, depth + 1) : heading - 1;
17040
+ };
17041
+ /**
17042
+ * Reads the heading level of the document's paragraphs, as the `\s` switch of a SEQ field follows it: the level of a
17043
+ * paragraph in a built-in heading style, Heading 1 to Heading 9. A paragraph whose outline level is another, or that has
17044
+ * one without a heading style, is `"unclear"`, as which of the two Word follows hasn't been checked. Other paragraphs
17045
+ * are undefined.
17046
+ */
17047
+ var headingLevels = (context) => {
17048
+ const styles = stylesOf(context);
17049
+ return (paragraph) => {
17050
+ const properties = childOf(paragraph, "w:pPr");
17051
+ const styleId = attributeOf(childOf(properties, "w:pStyle"), "w:val");
17052
+ const heading = headingLevelOf(styleId, styles);
17053
+ const outlineLevel = outlineLevelOf({
17054
+ styleId,
17055
+ outlineLevel: numberAttributeOf(childOf(properties, "w:outlineLvl"), "w:val")
17056
+ }, styles);
17057
+ const outline = outlineLevel === void 0 || outlineLevel >= 9 ? void 0 : outlineLevel + 1;
17058
+ if (heading !== void 0 && (outline === void 0 || outline === heading)) return heading;
17059
+ return outline === void 0 ? void 0 : "unclear";
17060
+ };
17061
+ };
17062
+ /** A paragraph's outline level, from 0: its own, or else its style's */
17063
+ var outlineLevelOf = (paragraph, styles) => {
17064
+ var _paragraph$outlineLev;
17065
+ return (_paragraph$outlineLev = paragraph.outlineLevel) !== null && _paragraph$outlineLev !== void 0 ? _paragraph$outlineLev : styleOutlineLevelOf(paragraph.styleId, styles);
17066
+ };
17067
+ /** The level a table of contents gives a paragraph, or undefined when it doesn't include it */
17068
+ var levelIn = (properties, paragraph, styles) => {
17069
+ var _styles$get2;
17070
+ const { entriesFromBookmark, headingStyleRange, stylesWithLevels = [], useAppliedParagraphOutlineLevel } = properties;
17071
+ if (paragraph.text.trim() === "" || entriesFromBookmark && !paragraph.bookmarks.has(entriesFromBookmark)) return;
17072
+ const names = [paragraph.styleId, paragraph.styleId === void 0 ? void 0 : (_styles$get2 = styles.get(paragraph.styleId)) === null || _styles$get2 === void 0 ? void 0 : _styles$get2.name].filter((name) => name !== void 0).map((name) => name.toLowerCase());
17073
+ const listed = stylesWithLevels.find((style) => names.includes(style.styleName.toLowerCase()));
17074
+ if (listed) return listed.level;
17075
+ const namesItsEntries = Boolean(headingStyleRange) || stylesWithLevels.length > 0 || Boolean(useAppliedParagraphOutlineLevel) || Boolean(properties.tcFieldIdentifier) || Boolean(properties.tcFieldLevelRange) || Boolean(properties.captionLabel) || Boolean(properties.captionLabelIncludingNumbers);
17076
+ const headingRange = headingStyleRange ? parseRange(headingStyleRange) : namesItsEntries ? void 0 : [1, 9];
17077
+ const heading = headingLevelOf(paragraph.styleId, styles);
17078
+ if (headingRange && heading !== void 0 && isWithin(heading, headingRange)) return heading;
17079
+ const outlineLevel = useAppliedParagraphOutlineLevel ? outlineLevelOf(paragraph, styles) : void 0;
17080
+ return outlineLevel !== void 0 && isWithin(outlineLevel + 1, headingRange !== null && headingRange !== void 0 ? headingRange : [1, 9]) ? outlineLevel + 1 : void 0;
17081
+ };
17082
+ /** The runs of an entry's title. Tabs and line breaks are kept only when the table of contents keeps them (\w and \x) */
17083
+ var titleRunsOf = (title, properties) => {
17084
+ const text = properties.preserveTabInEntries ? title : title.replace(/\t/g, " ");
17085
+ return (properties.preserveNewLineInEntries ? text.split("\n") : [text.replace(/\n/g, " ")]).map((line, index) => new TextRun({
17086
+ break: index > 0 ? 1 : void 0,
17087
+ children: line.split(" ").flatMap((part, partIndex) => [...partIndex > 0 ? [new Tab()] : [], ...part === "" ? [] : [part]])
17088
+ }));
17089
+ };
17090
+ /**
17091
+ * The paragraph style of the entries at a level: the built-in TOC style, found by its name, "toc 1" to "toc 9". When
17092
+ * the document doesn't have it, the entries are indented as Word's are, 220 twips a level.
17093
+ */
17094
+ var entryStyleOf = (level, styles) => {
17095
+ var _find;
17096
+ const named = (_find = [...styles].find(([, style]) => {
17097
+ var _style$name;
17098
+ return ((_style$name = style.name) === null || _style$name === void 0 ? void 0 : _style$name.toLowerCase()) === `toc ${level}`;
17099
+ })) === null || _find === void 0 ? void 0 : _find[0];
17100
+ const id = named !== null && named !== void 0 ? named : `TOC${level}`;
17101
+ return named !== void 0 || styles.has(id) || level === 1 ? { id } : {
17102
+ id,
17103
+ indent: (level - 1) * 220
17104
+ };
17105
+ };
17106
+ /** The formatted content of a table of contents with its entries */
17107
+ var contentOf = ({ properties, beginDirty, textWidth }, entries, styles, context) => {
17108
+ var _parseRange;
17109
+ const withoutPageNumbers = properties.pageNumbersEntryLevelsRange ? (_parseRange = parseRange(properties.pageNumbersEntryLevelsRange)) !== null && _parseRange !== void 0 ? _parseRange : [1, 9] : void 0;
17110
+ const content = new StructuredDocumentTagContent();
17111
+ entries.forEach((entry, index) => {
17112
+ const hasPageNumber = withoutPageNumbers === void 0 || !isWithin(entry.level, withoutPageNumbers);
17113
+ const children = [...titleRunsOf(entry.title, properties), ...hasPageNumber ? [new TextRun({ children: [properties.entryAndPageNumberSeparator || new Tab()] }), new PageReference(entry.bookmark, { hyperlink: properties.hyperlink })] : []];
17114
+ const style = entryStyleOf(entry.level, styles);
17115
+ content.addChildElement(new Paragraph({
17116
+ style: style.id,
17117
+ indent: style.indent === void 0 ? void 0 : { left: style.indent },
17118
+ tabStops: [{
17119
+ type: "right",
17120
+ position: textWidth,
17121
+ leader: "dot"
17122
+ }],
17123
+ children: [...index === 0 ? [new Run({ children: [
17124
+ beginOf(beginDirty),
17125
+ new FieldInstruction(properties),
17126
+ createSeparate()
17127
+ ] })] : [], ...properties.hyperlink ? [new InternalHyperlink({
17128
+ anchor: entry.bookmark,
17129
+ children
17130
+ })] : children]
17131
+ }));
17132
+ });
17133
+ content.addChildElement(new Paragraph({ children: [new Run({ children: [createEnd()] })] }));
17134
+ return content.prepForXml(context);
17135
+ };
17136
+ /** Puts a bookmark around the content of a formatted paragraph */
17137
+ var bookmark = (paragraph, name, id, context) => {
17138
+ const children = childrenOf(paragraph);
17139
+ const start = children.findIndex((child) => nameOf$2(child) === "w:pPr") + 1;
17140
+ paragraph["w:p"] = [
17141
+ ...children.slice(0, start),
17142
+ new BookmarkStart(name, id).prepForXml(context),
17143
+ ...children.slice(start),
17144
+ new BookmarkEnd(id).prepForXml(context)
17145
+ ];
17146
+ };
17147
+ /**
17148
+ * Fills in the tables of contents in a formatted body from its headings, and bookmarks the headings they list. A
17149
+ * table of contents that doesn't list any heading is left empty, for Word to fill in.
17150
+ */
17151
+ var fillTablesOfContents = (body, context, bookmarkIds) => {
17152
+ const blocks = blocksOf(childrenOf(body));
17153
+ const tables = blocks.flatMap((block) => {
17154
+ const options = writtenTables.get(block);
17155
+ return options ? [[block, options]] : [];
17156
+ });
17157
+ if (tables.length === 0) return;
17158
+ const styles = stylesOf(context);
17159
+ const followBookmarks = tables.some(([, { properties }]) => Boolean(properties.entriesFromBookmark));
17160
+ const headings = paragraphDetailsOf(blocks.filter((block) => nameOf$2(block) === "w:p"), followBookmarks).map((paragraph) => ({
17161
+ paragraph,
17162
+ levels: tables.map(([, { properties }]) => levelIn(properties, paragraph, styles))
17163
+ })).filter(({ levels }) => levels.some((level) => level !== void 0)).map((heading, index) => _objectSpread2(_objectSpread2({}, heading), {}, { id: bookmarkIds.get(index) }));
17164
+ for (const { paragraph, id } of headings) bookmark(paragraph.element, `_Toc${id}`, id, context);
17165
+ tables.forEach(([table, options], index) => {
17166
+ const entries = headings.flatMap(({ paragraph, levels, id }) => {
17167
+ const level = levels[index];
17168
+ return level === void 0 ? [] : [{
17169
+ title: paragraph.text,
17170
+ level,
17171
+ bookmark: `_Toc${id}`
17172
+ }];
17173
+ });
17174
+ if (entries.length === 0) return;
17175
+ table["w:sdt"] = childrenOf(table).map((child) => nameOf$2(child) === "w:sdtContent" ? contentOf(options, entries, styles, context) : child);
17176
+ });
17177
+ };
17178
+ //#endregion
17179
+ //#region src/file/document/body/sequence-numbers.ts
17180
+ /**
17181
+ * Caption numbers written into the SEQ fields of a document, such as the 2 of "Figure 2", when the document is given page
17182
+ * numbers.
17183
+ *
17184
+ * A SEQ field (`SequentialIdentifier`) shows how many SEQ fields of its identifier, such as "Figure", there are up to and
17185
+ * including it, so the number doesn't depend on how the pages are laid out. Its switches change the count: `\r 5` starts
17186
+ * it again from 5, `\c` repeats the number of the one before, `\s 1` starts it again after each Heading 1, `\h` hides the
17187
+ * number, and `\* ROMAN` writes it in roman numerals. `docx` writes SEQ fields dirty, for Word to number when it opens the
17188
+ * document, which makes Word ask to update the fields. When the document is given page numbers, each is written clean
17189
+ * with its number, counted as Word counts it. What Word does was read from its PDF of `scripts/layout-probes/word-seq.ts`.
17190
+ *
17191
+ * Word counts the SEQ fields of the body, those in text boxes and hidden text too, in order, and counts an identifier in
17192
+ * any capitals, or in quotes, as the same one. It writes the SEQ fields of headers, footers, footnotes and endnotes as an
17193
+ * error, "Error! Main Document Only.", and doesn't count them with the body's.
17194
+ *
17195
+ * Where Word's count isn't known, the field is left blank rather than given a number that could be wrong: a switch it
17196
+ * doesn't follow, a SEQ field in deleted text, and every SEQ field of an identifier that also has SEQ fields in a comment.
17197
+ * The fields of its identifier after one whose number isn't known are left blank too, until one starts the count again
17198
+ * with `\r`. A number in a format not followed is left blank, but the count goes on.
17199
+ *
17200
+ * @module
17201
+ */
17202
+ var IDENTIFIER = new RegExp("^\\p{L}[\\p{L}\\p{N}_]*$", "u");
17203
+ /** Reads the switches of a SEQ field, and a bookmark before them, or undefined when one of them isn't followed */
17204
+ var sequenceOf = (switches) => {
17205
+ var _step, _format;
17206
+ let step;
17207
+ let hidden = false;
17208
+ let format;
17209
+ let caseFormat = false;
17210
+ let picture = false;
17211
+ for (let index = 0; index < switches.length; index++) {
17212
+ var _switches, _next;
17213
+ const name = switches[index];
17214
+ const argument = (_switches = switches[index + 1]) !== null && _switches !== void 0 ? _switches : "";
17215
+ let next;
17216
+ if (index === 0 && !name.startsWith("\\")) next = { type: "bookmark" };
17217
+ else if (name === "\\c" || name === "\\n") next = { type: name === "\\c" ? "repeat" : "next" };
17218
+ else if ((name === "\\r" || name === "\\s") && /^\d+$/.test(argument)) {
17219
+ index++;
17220
+ next = name === "\\r" ? {
17221
+ type: "reset",
17222
+ to: Number(argument)
17223
+ } : {
17224
+ type: "heading",
17225
+ level: Number(argument)
17226
+ };
17227
+ } else if (name === "\\h") hidden = true;
17228
+ else if (name === "\\#" && index + 1 < switches.length) {
17229
+ index++;
17230
+ picture = true;
17231
+ } else if (name === "\\*" && index + 1 < switches.length) {
17232
+ const value = switches[++index];
17233
+ if (CASE_FORMATS.has(value.toLowerCase())) caseFormat = true;
17234
+ else if (!PLAIN_FORMATS.has(value.toLowerCase())) {
17235
+ if (format !== void 0) return;
17236
+ format = value;
17237
+ }
17238
+ } else return;
17239
+ if (next && step) return;
17240
+ step = (_next = next) !== null && _next !== void 0 ? _next : step;
17241
+ }
17242
+ if ((step === null || step === void 0 ? void 0 : step.type) === "bookmark" && switches.length > 1) return;
17243
+ const written = !picture && !(caseFormat && format !== void 0 && format.toLowerCase() !== "arabic");
17244
+ return {
17245
+ step: (_step = step) !== null && _step !== void 0 ? _step : { type: "next" },
17246
+ hidden: hidden && format === void 0,
17247
+ format: written ? (_format = format) !== null && _format !== void 0 ? _format : "ARABIC" : ""
17248
+ };
17249
+ };
17250
+ /** Reads a SEQ field's instruction, or undefined when the field isn't a SEQ field */
17251
+ var sequenceFieldOf = (instruction) => {
17252
+ var _match$1$match;
17253
+ const match = new RegExp("^\\s*SEQ\\b(.*)$", "is").exec(instruction);
17254
+ if (!match) return;
17255
+ const [written, ...switches] = (_match$1$match = match[1].match(/"[^"]*"|\S+/g)) !== null && _match$1$match !== void 0 ? _match$1$match : [];
17256
+ if (written === void 0) return {};
17257
+ const identifier = written.replace(/^"(.*)"$/, "$1");
17258
+ return IDENTIFIER.test(identifier) ? {
17259
+ identifier,
17260
+ sequence: sequenceOf(switches)
17261
+ } : { identifier };
17262
+ };
17263
+ /** Whether a field's instruction is that of a SEQ field */
17264
+ var isSequenceField = (instruction) => sequenceFieldOf(instruction) !== void 0;
17265
+ /** The identifier, in small letters, of each SEQ field in the formatted elements */
17266
+ var identifiersIn = (element) => {
17267
+ if (typeof element !== "object" || element === null) return [];
17268
+ if (Array.isArray(element)) return element.flatMap(identifiersIn);
17269
+ return Object.entries(element).flatMap(([name, content]) => {
17270
+ return [...(name === "w:instrText" && Array.isArray(content) ? content : name === "_attr" ? [content["w:instr"]] : []).flatMap((instruction) => {
17271
+ const field = typeof instruction === "string" ? sequenceFieldOf(instruction) : void 0;
17272
+ return (field === null || field === void 0 ? void 0 : field.identifier) === void 0 ? [] : [field.identifier.toLowerCase()];
17273
+ }), ...identifiersIn(content)];
17274
+ });
17275
+ };
17276
+ /** The identifiers, in small letters, of the SEQ fields in the document's comments, whose count in Word isn't known */
17277
+ var identifiersInCommentsOf = (context) => {
17278
+ var _context$file;
17279
+ const comments = (_context$file = context.file) === null || _context$file === void 0 ? void 0 : _context$file.Comments;
17280
+ if (!comments) return /* @__PURE__ */ new Set();
17281
+ const wrapper = {
17282
+ View: comments,
17283
+ Relationships: comments.Relationships
17284
+ };
17285
+ return new Set(identifiersIn(comments.prepForXml(_objectSpread2(_objectSpread2({}, context), {}, {
17286
+ viewWrapper: wrapper,
17287
+ stack: []
17288
+ }))));
17289
+ };
17290
+ /** Counts the SEQ fields of a document's body, in order, as Word counts them */
17291
+ var sequenceNumbering = (context) => {
17292
+ const levelOf = headingLevels(context);
17293
+ const numbers = /* @__PURE__ */ new Map();
17294
+ const counted = /* @__PURE__ */ new Map();
17295
+ const headingsAt = [];
17296
+ let unclearAt = -1;
17297
+ let paragraph = -1;
17298
+ let unknown;
17299
+ /**
17300
+ * The number of a field that starts the count again after headings of a level or a higher one (`\s`): the number of
17301
+ * fields of its identifier since the last of them, with it, as Word counts them. It isn't known when a paragraph
17302
+ * whose level isn't clear came after that heading, or a field since it whose number didn't follow as the next one's
17303
+ */
17304
+ const afterHeading = (key, level) => {
17305
+ var _counted$get;
17306
+ const headingAt = Math.max(-1, ...headingsAt.slice(1, level + 1).filter((at) => at !== void 0));
17307
+ const since = ((_counted$get = counted.get(key)) !== null && _counted$get !== void 0 ? _counted$get : []).filter((field) => field.paragraph >= headingAt);
17308
+ const followed = since.every(({ step }) => (step === null || step === void 0 ? void 0 : step.type) === "next" || (step === null || step === void 0 ? void 0 : step.type) === "heading" && step.level === level);
17309
+ if (unclearAt > headingAt || !followed) return;
17310
+ return since.length + 1;
17311
+ };
17312
+ return {
17313
+ startParagraph: (element) => {
17314
+ paragraph++;
17315
+ const level = levelOf(element);
17316
+ if (level === "unclear") unclearAt = paragraph;
17317
+ else if (level !== void 0) headingsAt[level] = paragraph;
17318
+ },
17319
+ numberOf: (instruction, place) => {
17320
+ var _unknown, _counted$get2, _numberWriterOf;
17321
+ const { identifier, sequence } = sequenceFieldOf(instruction);
17322
+ if (identifier === void 0 || place === "fallback") return;
17323
+ (_unknown = unknown) !== null && _unknown !== void 0 || (unknown = identifiersInCommentsOf(context));
17324
+ const key = identifier.toLowerCase();
17325
+ if ((sequence === null || sequence === void 0 ? void 0 : sequence.step.type) === "bookmark" && place === "counted" && !unknown.has(key)) return;
17326
+ const before = numbers.has(key) ? numbers.get(key) : 0;
17327
+ const step = unknown.has(key) || place === "deleted" ? void 0 : sequence === null || sequence === void 0 ? void 0 : sequence.step;
17328
+ const value = (step === null || step === void 0 ? void 0 : step.type) === "reset" ? step.to : (step === null || step === void 0 ? void 0 : step.type) === "repeat" ? before : (step === null || step === void 0 ? void 0 : step.type) === "heading" ? afterHeading(key, step.level) : (step === null || step === void 0 ? void 0 : step.type) === "next" && before !== void 0 ? before + 1 : void 0;
17329
+ numbers.set(key, value);
17330
+ counted.set(key, [...(_counted$get2 = counted.get(key)) !== null && _counted$get2 !== void 0 ? _counted$get2 : [], _objectSpread2({ paragraph }, value === void 0 ? {} : { step })]);
17331
+ return value === void 0 || sequence === void 0 ? void 0 : sequence.hidden ? "" : (_numberWriterOf = numberWriterOf(sequence.format)) === null || _numberWriterOf === void 0 ? void 0 : _numberWriterOf(value);
17332
+ }
17333
+ };
17334
+ };
17335
+ //#endregion
17336
+ //#region src/file/document/body/page-numbers.ts
17337
+ /**
17338
+ * Page numbers written into the fields of a document that show them, when it is written, from an estimate of its pages.
17339
+ *
17340
+ * A page reference is a PAGEREF field, such as the page number of an entry in a table of contents, and the numbers of
17341
+ * pages of the document and of a section are NUMPAGES and SECTIONPAGES fields. Word works their results out when it
17342
+ * updates the fields, or lays the pages out, and until then, and in applications that don't, the fields show the results
17343
+ * they were written with. `docx` doesn't lay out pages, so it writes the results empty, unless the document is given a
17344
+ * {@link PageNumberEstimator}, such as `estimatePageNumbers` from `docx/layout`. Then, once the body is written, each of
17345
+ * those fields in the body, and then in the headers and footers, is given the number the estimator worked out.
17346
+ *
17347
+ * Page references and tables of contents are written dirty, so Word updates them when it opens the document, and asks
17348
+ * "This document contains fields that may refer to other files. Do you want to update the fields in this document?".
17349
+ * When the document is given page numbers, they are written clean, so Word shows them as they are and doesn't ask. A
17350
+ * page number the estimator didn't work out is left blank, until the fields are updated. So are SEQ fields, the numbers
17351
+ * of captions, which are given their numbers then too.
17352
+ *
17353
+ * @module
17354
+ */
17355
+ var nameOf$1 = (element) => {
17356
+ const name = typeof element === "object" && element !== null && !Array.isArray(element) ? Object.keys(element)[0] : void 0;
17357
+ return name === "_attr" ? void 0 : name;
17358
+ };
17359
+ var textElement = (text) => ({ "w:t": [{ _attr: { "xml:space": "preserve" } }, text] });
17360
+ /** The elements docx formats to write a document */
17361
+ var FORMATTED = {
17362
+ nameOf: nameOf$1,
17363
+ contentOf: (element) => {
17364
+ const content = element[nameOf$1(element)];
17365
+ return Array.isArray(content) ? content : void 0;
17366
+ },
17367
+ attributeOf: (element, attribute) => {
17368
+ var _holder$_attr;
17369
+ const content = element[nameOf$1(element)];
17370
+ const holder = Array.isArray(content) ? content.find((child) => typeof child === "object" && child !== null && "_attr" in child) : content;
17371
+ return holder === null || holder === void 0 || (_holder$_attr = holder._attr) === null || _holder$_attr === void 0 ? void 0 : _holder$_attr[attribute];
17372
+ },
17373
+ textOf: (element) => FORMATTED.contentOf(element).filter((part) => typeof part === "string").join(""),
17374
+ textElement,
17375
+ writeClean: (begin) => {
17376
+ if (isDirtyWithoutPageNumbers(begin)) {
17377
+ const attributes = begin["w:fldChar"]._attr;
17378
+ begin["w:fldChar"] = { _attr: Object.fromEntries(Object.entries(attributes).filter(([key]) => key !== "w:dirty")) };
17379
+ }
17380
+ },
17381
+ setSimpleFieldResult: (element, text) => {
17382
+ const content = element["w:fldSimple"];
17383
+ element["w:fldSimple"] = [...(Array.isArray(content) ? content : [content]).filter((child) => typeof child === "object" && child !== null && "_attr" in child), { "w:r": [textElement(text)] }];
17384
+ }
17385
+ };
17386
+ /** The estimate of each document's pages, and the numbers of pages its headers and footers show, once its body is written */
17387
+ var estimates = /* @__PURE__ */ new WeakMap();
17388
+ /**
17389
+ * Writes the numbers of the SEQ fields of a formatted body into them, counted as Word counts them (see
17390
+ * {@link sequenceNumbering}), and writes them clean, whether or not their numbers were worked out. It is done after its
17391
+ * tables of contents are filled in from its headings, as Word leaves a heading's SEQ number out of its entry.
17392
+ */
17393
+ var fillSequenceNumbers = (body, context) => {
17394
+ const { startParagraph, numberOf } = sequenceNumbering(context);
17395
+ fillSequenceFields(FORMATTED, body, {
17396
+ beforeParagraph: (paragraph) => startParagraph(paragraph),
17397
+ resultOf: (instruction, within) => isSequenceField(instruction) ? numberOf(instruction, within) : void 0
17398
+ });
17399
+ };
17400
+ /**
17401
+ * Writes the page numbers the estimator works out into the fields of a formatted body that show them: the PAGEREF fields
17402
+ * in its tables of contents and elsewhere, those with `\p` and in number formats of their own, and its NUMPAGES and
17403
+ * SECTIONPAGES fields. A field whose number the estimator didn't work out is left as it is. Page references and tables
17404
+ * of contents are written clean, whether or not their numbers were worked out. The estimate is kept for the document's
17405
+ * headers and footers.
17406
+ */
17407
+ var fillPageNumbers = (body, context, estimator) => {
17408
+ const estimate = estimator(body, context);
17409
+ const partPageCounts = fillBodyFields(FORMATTED, body, estimate, { blank: false });
17410
+ if (context.file) estimates.set(context.file, {
17411
+ estimate,
17412
+ partPageCounts
17413
+ });
17414
+ };
17415
+ /**
17416
+ * Writes the page numbers worked out for the document a header, footer, footnote, endnote or comment is in into the
17417
+ * fields of the formatted part that show them, once the document's body is written. Its page references and SEQ fields
17418
+ * are written clean, and its SEQ fields are left blank: Word writes them as an error, "Error! Main Document Only.".
17419
+ *
17420
+ * @param part - The formatted part, if it has anything to write
17421
+ * @param context - The context it was formatted in, with the document it is in
17422
+ * @param referenceId - The number of the relationship to a header or footer. The SECTIONPAGES fields of the other parts
17423
+ * are left as they are
17424
+ */
17425
+ var fillPartPageNumbers = (part, context, referenceId) => {
17426
+ const written = context.file && estimates.get(context.file);
17427
+ if (!part || !written) return;
17428
+ const sectionPageCount = referenceId === void 0 ? void 0 : written.partPageCounts.get(`rId${referenceId}`);
17429
+ const notes = "w:footnotes" in part || "w:endnotes" in part;
17430
+ fillPartFields(FORMATTED, part, written.estimate, {
17431
+ blank: false,
17432
+ sectionPageCount,
17433
+ notes
17434
+ });
17435
+ };
17436
+ //#endregion
16339
17437
  //#region src/file/relationships/attributes.ts
16340
17438
  /**
16341
17439
  * Attributes for the Relationships element.
@@ -16385,7 +17483,7 @@ var RelationshipsAttributes = class extends XmlAttributeComponent {
16385
17483
  * );
16386
17484
  * ```
16387
17485
  */
16388
- var Relationships = class extends XmlComponent {
17486
+ var Relationships = class Relationships extends XmlComponent {
16389
17487
  constructor() {
16390
17488
  super("Relationships");
16391
17489
  this.root.push(new RelationshipsAttributes({ xmlns: "http://schemas.openxmlformats.org/package/2006/relationships" }));
@@ -16402,6 +17500,20 @@ var Relationships = class extends XmlComponent {
16402
17500
  this.root.push(createRelationship(`rId${id}`, type, target, targetMode));
16403
17501
  }
16404
17502
  /**
17503
+ * Creates a copy of the relationships given. Relationships added to the copy aren't added to them, so the compiler
17504
+ * adds the ones it writes for a part, such as to its images, to a copy, and packing a document again doesn't add
17505
+ * them a second time.
17506
+ *
17507
+ * Static, as `IContext` is public and has `Relationships`, so a new instance member would change the public API.
17508
+ *
17509
+ * @param relationships - The relationships to copy
17510
+ */
17511
+ static copy(relationships) {
17512
+ const copy = new Relationships();
17513
+ copy.root.push(...relationships.root.slice(1));
17514
+ return copy;
17515
+ }
17516
+ /**
16405
17517
  * Gets the count of relationships in this collection.
16406
17518
  * Excludes the attributes element from the count.
16407
17519
  */
@@ -16412,6 +17524,17 @@ var Relationships = class extends XmlComponent {
16412
17524
  //#endregion
16413
17525
  //#region src/file/paragraph/run/comment-run.ts
16414
17526
  /**
17527
+ * Comment module for WordprocessingML documents.
17528
+ *
17529
+ * This module provides support for comments (annotations) in documents. Comments
17530
+ * consist of comment ranges (start/end markers), comment references, and the
17531
+ * actual comment content.
17532
+ *
17533
+ * Reference: http://officeopenxml.com/WPrun.php
17534
+ *
17535
+ * @module
17536
+ */
17537
+ /**
16415
17538
  * @internal
16416
17539
  */
16417
17540
  var CommentAttributes = class extends XmlAttributeComponent {
@@ -16441,6 +17564,7 @@ var RootCommentsAttributes = class extends XmlAttributeComponent {
16441
17564
  constructor(..._args3) {
16442
17565
  super(..._args3);
16443
17566
  _defineProperty(this, "xmlKeys", {
17567
+ "xmlns:wpc": "xmlns:wpc",
16444
17568
  "xmlns:cx": "xmlns:cx",
16445
17569
  "xmlns:cx1": "xmlns:cx1",
16446
17570
  "xmlns:cx2": "xmlns:cx2",
@@ -16681,6 +17805,7 @@ var Comments = class extends XmlComponent {
16681
17805
  _defineProperty(this, "isEmpty", void 0);
16682
17806
  this.isEmpty = children.length === 0;
16683
17807
  this.root.push(new RootCommentsAttributes({
17808
+ "xmlns:wpc": "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas",
16684
17809
  "xmlns:cx": "http://schemas.microsoft.com/office/drawing/2014/chartex",
16685
17810
  "xmlns:cx1": "http://schemas.microsoft.com/office/drawing/2015/9/8/chartex",
16686
17811
  "xmlns:cx2": "http://schemas.microsoft.com/office/drawing/2015/10/21/chartex",
@@ -16749,6 +17874,15 @@ var Comments = class extends XmlComponent {
16749
17874
  get IsEmpty() {
16750
17875
  return this.isEmpty;
16751
17876
  }
17877
+ /**
17878
+ * Formats the comments, with the page numbers worked out for their document written into their fields, when the
17879
+ * document's body is written with an estimate of its pages.
17880
+ */
17881
+ prepForXml(context) {
17882
+ const xml = super.prepForXml(context);
17883
+ fillPartPageNumbers(xml, context);
17884
+ return xml;
17885
+ }
16752
17886
  };
16753
17887
  //#endregion
16754
17888
  //#region src/file/paragraph/run/comments-extended.ts
@@ -17823,20 +18957,44 @@ var HyperlinkType = {
17823
18957
  * ```
17824
18958
  */
17825
18959
  var ConcreteHyperlink = class extends XmlComponent {
17826
- constructor(children, relationshipId, anchor) {
18960
+ /**
18961
+ * @param children - Inline content of the hyperlink
18962
+ * @param relationshipId - Id of the external relationship, without the rId prefix
18963
+ * @param anchor - Bookmark name or external URL fragment
18964
+ * @param externalLink - The full address of an external hyperlink, so the relationship id is kept alongside its anchor
18965
+ */
18966
+ constructor(children, relationshipId, anchor, externalLink) {
17827
18967
  super("w:hyperlink");
17828
18968
  _defineProperty(this, "linkId", void 0);
18969
+ _defineProperty(this, "drawingLink", void 0);
17829
18970
  this.linkId = relationshipId;
18971
+ this.drawingLink = anchor && externalLink !== void 0 ? new DrawingLink(externalLink) : void 0;
17830
18972
  const attributes = new HyperlinkAttributes({
17831
18973
  history: 1,
17832
18974
  anchor: anchor ? anchor : void 0,
17833
- id: !anchor ? `rId${this.linkId}` : void 0
18975
+ id: !anchor || externalLink !== void 0 ? `rId${this.linkId}` : void 0
17834
18976
  });
17835
18977
  this.root.push(attributes);
17836
18978
  children.forEach((child) => {
17837
18979
  this.root.push(child);
17838
18980
  });
17839
18981
  }
18982
+ /**
18983
+ * Creates the `a:hlinkClick` of a picture in the hyperlink, which links to the same address.
18984
+ *
18985
+ * The hyperlink decides which relationship its pictures use, rather than the pictures reading `linkId`, because only it
18986
+ * knows whether that relationship has lost the fragment to `w:anchor`. The picture's relationship is added as the
18987
+ * picture is written, through the context's relationships, so it lands in the part the picture is in, both when
18988
+ * packing and when patching.
18989
+ *
18990
+ * @param context - The context the picture is written in, whose relationships get the picture's link if it has its own
18991
+ * @param declareNamespace - Declares the DrawingML namespace, for elements outside `a:graphic` such as `wp:docPr`
18992
+ */
18993
+ createDrawingClick(context, declareNamespace) {
18994
+ if (!this.drawingLink) return createHyperlinkClick(this.linkId, declareNamespace);
18995
+ this.drawingLink.addRelationship(context);
18996
+ return this.drawingLink.createClick(declareNamespace);
18997
+ }
17840
18998
  };
17841
18999
  /**
17842
19000
  * Represents an internal hyperlink to a bookmark within the document.
@@ -17885,6 +19043,11 @@ var InternalHyperlink = class extends ConcreteHyperlink {
17885
19043
  * External hyperlinks create a relationship to an external resource (URL).
17886
19044
  * The relationship is created during document preparation and the hyperlink
17887
19045
  * is converted to a ConcreteHyperlink with the relationship ID.
19046
+ * URL fragments of at most 255 UTF-16 units are written as anchors, preserving any additional # characters.
19047
+ * Longer fragments stay in the original relationship URI to avoid exceeding Word's anchor limit;
19048
+ * those links retain the existing limitations for fragments with multiple # characters.
19049
+ * Word appends the anchor to the relationship target as described in MS-OI29500 §17.16.22:
19050
+ * https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oi29500/df06e423-11a6-4a36-bfb3-82139e531781
17888
19051
  *
17889
19052
  * Reference: http://officeopenxml.com/WPhyperlink.php
17890
19053
  *
@@ -17898,6 +19061,7 @@ var InternalHyperlink = class extends ConcreteHyperlink {
17898
19061
  * <xsd:group ref="EG_PContent" minOccurs="0" maxOccurs="unbounded"/>
17899
19062
  * <xsd:attribute ref="r:id"/>
17900
19063
  * <xsd:attribute name="history" type="s:ST_OnOff" use="optional"/>
19064
+ * <xsd:attribute name="anchor" type="s:ST_String" use="optional"/>
17901
19065
  * </xsd:complexType>
17902
19066
  * ```
17903
19067
  *
@@ -18047,7 +19211,7 @@ var BookmarkEndAttributes = class extends XmlAttributeComponent {
18047
19211
  * });
18048
19212
  * ```
18049
19213
  */
18050
- var Bookmark = class {
19214
+ var Bookmark = class Bookmark {
18051
19215
  constructor(options) {
18052
19216
  _defineProperty(this, "start", void 0);
18053
19217
  _defineProperty(this, "children", void 0);
@@ -18057,6 +19221,19 @@ var Bookmark = class {
18057
19221
  this.children = options.children;
18058
19222
  this.end = new BookmarkEnd(linkId);
18059
19223
  }
19224
+ /**
19225
+ * The components written in this bookmark's place: its start, its children and its end. A bookmark in its
19226
+ * children is written the same way, so one bookmark can hold another.
19227
+ *
19228
+ * @internal
19229
+ */
19230
+ get writtenAs() {
19231
+ return [
19232
+ this.start,
19233
+ ...this.children.flatMap((child) => child instanceof Bookmark ? child.writtenAs : [child]),
19234
+ this.end
19235
+ ];
19236
+ }
18060
19237
  };
18061
19238
  /**
18062
19239
  * Represents the start marker of a bookmark range.
@@ -18064,6 +19241,10 @@ var Bookmark = class {
18064
19241
  * This element marks the beginning of a bookmarked region in the document.
18065
19242
  * It must be paired with a corresponding BookmarkEnd element with the same id.
18066
19243
  *
19244
+ * The id must be unique in the document. `Bookmark` takes its ids from
19245
+ * `bookmarkUniqueNumericId`, so take this one from it too, or it can be the
19246
+ * same as a `Bookmark`'s.
19247
+ *
18067
19248
  * Reference: http://officeopenxml.com/WPbookmark.php
18068
19249
  *
18069
19250
  * ## XSD Schema
@@ -18081,7 +19262,10 @@ var Bookmark = class {
18081
19262
  *
18082
19263
  * @example
18083
19264
  * ```typescript
18084
- * new BookmarkStart("myBookmark", 1);
19265
+ * // A bookmark across two paragraphs
19266
+ * const id = bookmarkUniqueNumericId();
19267
+ * new Paragraph({ children: [new BookmarkStart("myBookmark", id), new TextRun("First")] });
19268
+ * new Paragraph({ children: [new TextRun("Last"), new BookmarkEnd(id)] });
18085
19269
  * ```
18086
19270
  */
18087
19271
  var BookmarkStart = class extends XmlComponent {
@@ -18098,7 +19282,8 @@ var BookmarkStart = class extends XmlComponent {
18098
19282
  * Represents the end marker of a bookmark range.
18099
19283
  *
18100
19284
  * This element marks the end of a bookmarked region in the document.
18101
- * It must be paired with a corresponding BookmarkStart element with the same id.
19285
+ * It must be paired with a corresponding BookmarkStart element with the same id,
19286
+ * taken from `bookmarkUniqueNumericId` (see `BookmarkStart`).
18102
19287
  *
18103
19288
  * Reference: http://officeopenxml.com/WPbookmark.php
18104
19289
  *
@@ -18117,7 +19302,9 @@ var BookmarkStart = class extends XmlComponent {
18117
19302
  *
18118
19303
  * @example
18119
19304
  * ```typescript
18120
- * new BookmarkEnd(1);
19305
+ * const id = bookmarkUniqueNumericId();
19306
+ * new BookmarkStart("myBookmark", id);
19307
+ * new BookmarkEnd(id);
18121
19308
  * ```
18122
19309
  */
18123
19310
  var BookmarkEnd = class extends XmlComponent {
@@ -18291,6 +19478,10 @@ var PageReferenceFieldInstruction = class extends XmlComponent {
18291
19478
  * The PAGEREF field displays the page number of the page containing
18292
19479
  * the specified bookmark, useful for cross-references like "see page 5".
18293
19480
  *
19481
+ * It is written dirty, so Word fills in the page number when it opens the document, after asking to. When the
19482
+ * document is given `pageNumbers`, it is written clean, with the number they work out, or blank when they couldn't,
19483
+ * and Word doesn't ask.
19484
+ *
18294
19485
  * @publicApi
18295
19486
  *
18296
19487
  * @example
@@ -18311,13 +19502,37 @@ var PageReferenceFieldInstruction = class extends XmlComponent {
18311
19502
  var PageReference = class extends Run {
18312
19503
  constructor(bookmarkId, options = {}) {
18313
19504
  super({ children: [
18314
- createBegin(true),
19505
+ createBeginDirtyWithoutPageNumbers(),
18315
19506
  new PageReferenceFieldInstruction(bookmarkId, options),
19507
+ createSeparate(),
18316
19508
  createEnd()
18317
19509
  ] });
18318
19510
  }
18319
19511
  };
18320
19512
  //#endregion
19513
+ //#region src/file/paragraph/links/external-hyperlink-target.ts
19514
+ /**
19515
+ * External hyperlink targets and fragments for WordprocessingML.
19516
+ *
19517
+ * Word appends the anchor to the relationship target, separated by a # character.
19518
+ * Reference: https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oi29500/df06e423-11a6-4a36-bfb3-82139e531781
19519
+ *
19520
+ * @module
19521
+ */
19522
+ var MAX_ANCHOR_LENGTH = 255;
19523
+ /**
19524
+ * Splits a nonempty fragment that fits Word's anchor limit without decoding or normalizing either part.
19525
+ * Longer fragments stay in the original relationship URI, retaining its existing multi-hash limitations.
19526
+ */
19527
+ var externalHyperlinkTarget = (link) => {
19528
+ const index = link.indexOf("#");
19529
+ const fragmentLength = link.length - index - 1;
19530
+ return index > 0 && fragmentLength > 0 && fragmentLength <= MAX_ANCHOR_LENGTH ? {
19531
+ target: link.slice(0, index),
19532
+ anchor: link.slice(index + 1)
19533
+ } : { target: link };
19534
+ };
19535
+ //#endregion
18321
19536
  //#region src/file/fonts/font.ts
18322
19537
  /**
18323
19538
  * Font module for WordprocessingML documents.
@@ -18456,32 +19671,26 @@ var createFont = ({ name, altName, panose1, charset, family, notTrueType, pitch,
18456
19671
  ]
18457
19672
  });
18458
19673
  //#endregion
18459
- //#region src/file/fonts/create-regular-font.ts
19674
+ //#region src/file/fonts/create-embedded-font.ts
18460
19675
  /**
18461
- * Creates a regular embedded font with default settings.
19676
+ * Creates an embedded font with default settings.
18462
19677
  *
18463
19678
  * This helper function creates a font definition with standard font signature
18464
19679
  * values that work for most common fonts. The signature specifies Unicode
18465
19680
  * and code page ranges supported by the font.
18466
19681
  *
18467
- * @param options - Font creation options
18468
- * @param options.name - Font name
18469
- * @param options.index - Font relationship index
18470
- * @param options.fontKey - Unique font key (GUID) for obfuscation
18471
- * @param options.characterSet - Optional character set identifier
18472
- *
18473
19682
  * @returns XmlComponent representing the font definition
18474
19683
  *
18475
19684
  * @example
18476
19685
  * ```typescript
18477
- * const font = createRegularFont({
19686
+ * const font = createEmbeddedFont({
18478
19687
  * name: "Arial",
18479
- * index: 1,
18480
- * fontKey: "12345678-1234-1234-1234-123456789012"
19688
+ * embedRegular: { id: "rId1", fontKey: "12345678-1234-1234-1234-123456789012" },
19689
+ * embedBold: { id: "rId2", fontKey: "12345678-1234-1234-1234-123456789013" },
18481
19690
  * });
18482
19691
  * ```
18483
19692
  */
18484
- var createRegularFont = ({ name, index, fontKey, characterSet }) => createFont({
19693
+ var createEmbeddedFont = ({ name, characterSet, embedRegular, embedBold, embedItalic, embedBoldItalic }) => createFont({
18485
19694
  name,
18486
19695
  sig: {
18487
19696
  usb0: "E0002AFF",
@@ -18494,10 +19703,10 @@ var createRegularFont = ({ name, index, fontKey, characterSet }) => createFont({
18494
19703
  charset: characterSet,
18495
19704
  family: "auto",
18496
19705
  pitch: "variable",
18497
- embedRegular: {
18498
- fontKey,
18499
- id: `rId${index}`
18500
- }
19706
+ embedRegular,
19707
+ embedBold,
19708
+ embedItalic,
19709
+ embedBoldItalic
18501
19710
  });
18502
19711
  //#endregion
18503
19712
  //#region src/file/fonts/font-table.ts
@@ -18575,25 +19784,47 @@ var createFontTable = (fonts) => new BuilderElement({
18575
19784
  value: "w14 w15 w16se w16cid w16 w16cex w16sdtdh"
18576
19785
  }
18577
19786
  },
18578
- children: fonts.map((font, i) => createRegularFont({
18579
- name: font.name,
18580
- index: i + 1,
18581
- fontKey: font.fontKey,
18582
- characterSet: font.characterSet
18583
- }))
19787
+ children: fonts.map(createEmbeddedFont)
18584
19788
  });
18585
19789
  //#endregion
18586
19790
  //#region src/file/fonts/font-wrapper.ts
19791
+ var FACES = [
19792
+ {
19793
+ option: "data",
19794
+ element: "embedRegular",
19795
+ bold: false,
19796
+ italic: false
19797
+ },
19798
+ {
19799
+ option: "bold",
19800
+ element: "embedBold",
19801
+ bold: true,
19802
+ italic: false
19803
+ },
19804
+ {
19805
+ option: "italic",
19806
+ element: "embedItalic",
19807
+ bold: false,
19808
+ italic: true
19809
+ },
19810
+ {
19811
+ option: "boldItalic",
19812
+ element: "embedBoldItalic",
19813
+ bold: true,
19814
+ italic: true
19815
+ }
19816
+ ];
18587
19817
  /**
18588
19818
  * Wrapper class for managing the font table and its relationships.
18589
19819
  *
18590
19820
  * Creates a font table with embedded font files and manages the relationships
18591
- * required for font embedding. Each font is assigned a unique key for obfuscation.
19821
+ * required for font embedding. Each face of a font is embedded as a file of its own,
19822
+ * with a unique key for obfuscation.
18592
19823
  *
18593
19824
  * @example
18594
19825
  * ```typescript
18595
19826
  * const fontWrapper = new FontWrapper([
18596
- * { name: "CustomFont", data: fontBuffer }
19827
+ * { name: "CustomFont", data: fontBuffer, bold: boldFontBuffer }
18597
19828
  * ]);
18598
19829
  * ```
18599
19830
  */
@@ -18602,12 +19833,43 @@ var FontWrapper = class {
18602
19833
  _defineProperty(this, "options", void 0);
18603
19834
  _defineProperty(this, "fontTable", void 0);
18604
19835
  _defineProperty(this, "relationships", void 0);
18605
- _defineProperty(this, "fontOptionsWithKey", []);
19836
+ _defineProperty(
19837
+ this,
19838
+ /** @deprecated Use `files`, which has the file and key of each face a font embeds, not only the regular face's key */
19839
+ "fontOptionsWithKey",
19840
+ []
19841
+ );
19842
+ _defineProperty(
19843
+ this,
19844
+ /** The files of the faces the fonts embed, in order: the Nth is `fonts/font<N>.odttf`, with the relationship `rId<N>` */
19845
+ "files",
19846
+ []
19847
+ );
18606
19848
  this.options = options;
18607
- this.fontOptionsWithKey = options.map((o) => _objectSpread2(_objectSpread2({}, o), {}, { fontKey: uniqueUuid() }));
18608
- this.fontTable = createFontTable(this.fontOptionsWithKey);
19849
+ const faces = options.map((font) => FACES.flatMap(({ option, element, bold, italic }) => {
19850
+ const data = font[option];
19851
+ return data ? [{
19852
+ element,
19853
+ file: {
19854
+ name: font.name,
19855
+ data,
19856
+ bold,
19857
+ italic,
19858
+ fontKey: uniqueUuid()
19859
+ }
19860
+ }] : [];
19861
+ }));
19862
+ this.files = faces.flatMap((ofFont) => ofFont.map(({ file }) => file));
19863
+ this.fontOptionsWithKey = options.map((font, index) => _objectSpread2(_objectSpread2({}, font), {}, { fontKey: faces[index][0].file.fontKey }));
19864
+ this.fontTable = createFontTable(options.map((font, index) => _objectSpread2({
19865
+ name: font.name,
19866
+ characterSet: font.characterSet
19867
+ }, Object.fromEntries(faces[index].map(({ element, file }) => [element, {
19868
+ id: `rId${this.files.indexOf(file) + 1}`,
19869
+ fontKey: file.fontKey
19870
+ }])))));
18609
19871
  this.relationships = new Relationships();
18610
- for (let i = 0; i < options.length; i++) this.relationships.addRelationship(i + 1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/font", `fonts/font${i + 1}.odttf`);
19872
+ for (let i = 0; i < this.files.length; i++) this.relationships.addRelationship(i + 1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/font", `fonts/font${i + 1}.odttf`);
18611
19873
  }
18612
19874
  get View() {
18613
19875
  return this.fontTable;
@@ -18827,17 +20089,18 @@ var createFrameProperties = (options) => {
18827
20089
  //#endregion
18828
20090
  //#region src/file/paragraph/properties.ts
18829
20091
  /**
18830
- * Paragraph properties module for WordprocessingML documents.
18831
- *
18832
- * This module provides the paragraph properties (pPr) element which specifies
18833
- * the formatting applied to a paragraph.
18834
- *
18835
- * Reference: http://officeopenxml.com/WPparagraphProperties.php
20092
+ * The alignment to write for each side of the page in a right-to-left paragraph.
18836
20093
  *
18837
- * @see https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_suppressLineNumbers_topic_ID0ECJAO.html
18838
- *
18839
- * @module
20094
+ * Word and LibreOffice read `w:jc` `left` and `right` as the start and end of the paragraph, the same as
20095
+ * `start` and `end` (ISO/IEC 29500-4 maps the transitional `left` and `right` onto the strict `start` and `end`,
20096
+ * and [MS-OE376] 2.3.1.13 notes the same for Word 2007). So in a `w:bidi` paragraph `left` lands on the right
20097
+ * side of the page. Swapping keeps `AlignmentType.LEFT` and `AlignmentType.RIGHT` on the side of the page they name.
20098
+ * `left` and `right` are written rather than `end` and `start` because Word 2007 does not know `start` and `end`.
18840
20099
  */
20100
+ var RIGHT_TO_LEFT_ALIGNMENTS = {
20101
+ left: "right",
20102
+ right: "left"
20103
+ };
18841
20104
  /**
18842
20105
  * Represents paragraph properties (pPr) in a WordprocessingML document.
18843
20106
  *
@@ -19001,7 +20264,7 @@ var ParagraphProperties = class extends IgnoreIfEmptyXmlComponent {
19001
20264
  if (options.spacing) this.push(createSpacing(options.spacing));
19002
20265
  if (options.indent) this.push(createIndent(options.indent));
19003
20266
  if (options.contextualSpacing !== void 0) this.push(new OnOffElement("w:contextualSpacing", options.contextualSpacing));
19004
- if (options.alignment) this.push(createAlignment(options.alignment));
20267
+ if (options.alignment) this.push(createAlignment(options.bidirectional && RIGHT_TO_LEFT_ALIGNMENTS[options.alignment] || options.alignment));
19005
20268
  if (options.outlineLevel !== void 0) this.push(createOutlineLevel(options.outlineLevel));
19006
20269
  if (options.suppressLineNumbers !== void 0) this.push(new OnOffElement("w:suppressLineNumbers", options.suppressLineNumbers));
19007
20270
  if (options.autoSpaceEastAsianText !== void 0) this.push(new OnOffElement("w:autoSpaceDN", options.autoSpaceEastAsianText));
@@ -19017,6 +20280,31 @@ var ParagraphProperties = class extends IgnoreIfEmptyXmlComponent {
19017
20280
  this.root.push(item);
19018
20281
  }
19019
20282
  /**
20283
+ * Adds the section properties (`w:sectPr`) of the section this paragraph ends.
20284
+ *
20285
+ * They go after the paragraph's run properties and before its revision (`w:pPrChange`),
20286
+ * the order CT_PPr gives them.
20287
+ *
20288
+ * @param sectionProperties - The properties of the section the paragraph ends
20289
+ */
20290
+ addSectionProperties(sectionProperties) {
20291
+ const revisionIndex = this.root.findIndex((item) => item instanceof ParagraphPropertiesChange);
20292
+ if (revisionIndex === -1) {
20293
+ this.root.push(sectionProperties);
20294
+ return;
20295
+ }
20296
+ this.root.splice(revisionIndex, 0, sectionProperties);
20297
+ }
20298
+ /**
20299
+ * Removes the section properties added with {@link addSectionProperties}.
20300
+ *
20301
+ * @param sectionProperties - The properties of the section to remove
20302
+ */
20303
+ removeSectionProperties(sectionProperties) {
20304
+ const index = this.root.indexOf(sectionProperties);
20305
+ if (index !== -1) this.root.splice(index, 1);
20306
+ }
20307
+ /**
19020
20308
  * Prepares the paragraph properties for XML serialization.
19021
20309
  *
19022
20310
  * This method creates concrete numbering instances for any numbering references
@@ -19044,13 +20332,6 @@ var ParagraphPropertiesChange = class extends XmlComponent {
19044
20332
  //#endregion
19045
20333
  //#region src/file/paragraph/paragraph.ts
19046
20334
  /**
19047
- * Paragraph module for WordprocessingML documents.
19048
- *
19049
- * Reference: http://officeopenxml.com/WPparagraph.php
19050
- *
19051
- * @module
19052
- */
19053
- /**
19054
20335
  * Represents a paragraph in a WordprocessingML document.
19055
20336
  *
19056
20337
  * A paragraph is the primary unit of block-level content in a document and can contain
@@ -19102,9 +20383,7 @@ var Paragraph = class extends FileChild {
19102
20383
  if (options.text) this.root.push(new TextRun(options.text));
19103
20384
  if (options.children) for (const child of options.children) {
19104
20385
  if (child instanceof Bookmark) {
19105
- this.root.push(child.start);
19106
- for (const textRun of child.children) this.root.push(textRun);
19107
- this.root.push(child.end);
20386
+ this.root.push(...child.writtenAs);
19108
20387
  continue;
19109
20388
  }
19110
20389
  this.root.push(child);
@@ -19113,12 +20392,35 @@ var Paragraph = class extends FileChild {
19113
20392
  prepForXml(context) {
19114
20393
  for (const element of this.root) if (element instanceof ExternalHyperlink) {
19115
20394
  const index = this.root.indexOf(element);
19116
- const concreteHyperlink = new ConcreteHyperlink(element.options.children, uniqueId());
19117
- context.viewWrapper.Relationships.addRelationship(concreteHyperlink.linkId, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", element.options.link, TargetModeType.EXTERNAL);
20395
+ const { target, anchor } = externalHyperlinkTarget(element.options.link);
20396
+ const concreteHyperlink = new ConcreteHyperlink(element.options.children, uniqueId(), anchor, element.options.link);
20397
+ context.viewWrapper.Relationships.addRelationship(concreteHyperlink.linkId, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", target, TargetModeType.EXTERNAL);
19118
20398
  this.root[index] = concreteHyperlink;
19119
20399
  }
19120
20400
  return super.prepForXml(context);
19121
20401
  }
20402
+ /**
20403
+ * Ends a section at this paragraph by adding the section's properties to the paragraph's properties,
20404
+ * as Word does with the last paragraph of each section but the last.
20405
+ *
20406
+ * The body adds them only while it is written and removes them afterwards with
20407
+ * {@link removeSectionProperties}, so the same paragraph can be used in other documents.
20408
+ *
20409
+ * @internal
20410
+ * @param sectionProperties - The properties of the section the paragraph ends
20411
+ */
20412
+ addSectionProperties(sectionProperties) {
20413
+ this.properties.addSectionProperties(sectionProperties);
20414
+ }
20415
+ /**
20416
+ * Removes the section properties added with {@link addSectionProperties}.
20417
+ *
20418
+ * @internal
20419
+ * @param sectionProperties - The properties of the section to remove
20420
+ */
20421
+ removeSectionProperties(sectionProperties) {
20422
+ this.properties.removeSectionProperties(sectionProperties);
20423
+ }
19122
20424
  addRunToFront(run) {
19123
20425
  this.root.splice(1, 0, run);
19124
20426
  return this;
@@ -19211,7 +20513,7 @@ var MathText = class extends XmlComponent {
19211
20513
  }
19212
20514
  };
19213
20515
  //#endregion
19214
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/objectWithoutPropertiesLoose.js
20516
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/objectWithoutPropertiesLoose.js
19215
20517
  function _objectWithoutPropertiesLoose(r, e) {
19216
20518
  if (null == r) return {};
19217
20519
  var t = {};
@@ -19222,7 +20524,7 @@ function _objectWithoutPropertiesLoose(r, e) {
19222
20524
  return t;
19223
20525
  }
19224
20526
  //#endregion
19225
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/objectWithoutProperties.js
20527
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/objectWithoutProperties.js
19226
20528
  function _objectWithoutProperties(e, t) {
19227
20529
  if (null == e) return {};
19228
20530
  var o, r, i = _objectWithoutPropertiesLoose(e, t);
@@ -21175,6 +22477,168 @@ var createLineNumberType = ({ countBy, start, restart, distance }) => new Builde
21175
22477
  }
21176
22478
  });
21177
22479
  //#endregion
22480
+ //#region src/file/document/body/section-properties/properties/note-properties.ts
22481
+ /**
22482
+ * Where the footnotes of a section are placed.
22483
+ *
22484
+ * ## XSD Schema
22485
+ * ```xml
22486
+ * <xsd:simpleType name="ST_FtnPos">
22487
+ * <xsd:restriction base="xsd:string">
22488
+ * <xsd:enumeration value="pageBottom"/>
22489
+ * <xsd:enumeration value="beneathText"/>
22490
+ * <xsd:enumeration value="sectEnd"/>
22491
+ * <xsd:enumeration value="docEnd"/>
22492
+ * </xsd:restriction>
22493
+ * </xsd:simpleType>
22494
+ * ```
22495
+ *
22496
+ * @publicApi
22497
+ */
22498
+ var FootnotePosition = {
22499
+ /** At the bottom of each page */
22500
+ PAGE_BOTTOM: "pageBottom",
22501
+ /** Directly below the text on each page */
22502
+ BENEATH_TEXT: "beneathText",
22503
+ /** At the end of the section */
22504
+ SECTION_END: "sectEnd",
22505
+ /** At the end of the document */
22506
+ DOCUMENT_END: "docEnd"
22507
+ };
22508
+ /**
22509
+ * Where the endnotes of a section are placed.
22510
+ *
22511
+ * ## XSD Schema
22512
+ * ```xml
22513
+ * <xsd:simpleType name="ST_EdnPos">
22514
+ * <xsd:restriction base="xsd:string">
22515
+ * <xsd:enumeration value="sectEnd"/>
22516
+ * <xsd:enumeration value="docEnd"/>
22517
+ * </xsd:restriction>
22518
+ * </xsd:simpleType>
22519
+ * ```
22520
+ *
22521
+ * @publicApi
22522
+ */
22523
+ var EndnotePosition = {
22524
+ /** At the end of the section */
22525
+ SECTION_END: "sectEnd",
22526
+ /** At the end of the document */
22527
+ DOCUMENT_END: "docEnd"
22528
+ };
22529
+ /**
22530
+ * When the footnote or endnote numbering restarts.
22531
+ *
22532
+ * ## XSD Schema
22533
+ * ```xml
22534
+ * <xsd:simpleType name="ST_RestartNumber">
22535
+ * <xsd:restriction base="xsd:string">
22536
+ * <xsd:enumeration value="continuous"/>
22537
+ * <xsd:enumeration value="eachSect"/>
22538
+ * <xsd:enumeration value="eachPage"/>
22539
+ * </xsd:restriction>
22540
+ * </xsd:simpleType>
22541
+ * ```
22542
+ *
22543
+ * @publicApi
22544
+ */
22545
+ var NoteNumberRestart = {
22546
+ /** Numbering never restarts */
22547
+ CONTINUOUS: "continuous",
22548
+ /** Numbering restarts in each section */
22549
+ EACH_SECTION: "eachSect",
22550
+ /** Numbering restarts on each page */
22551
+ EACH_PAGE: "eachPage"
22552
+ };
22553
+ var createNoteProperties = ({ name, position, numberFormat, start, restart }) => new BuilderElement({
22554
+ name,
22555
+ children: [
22556
+ ...position === void 0 ? [] : [new BuilderElement({
22557
+ name: "w:pos",
22558
+ attributes: { val: {
22559
+ key: "w:val",
22560
+ value: position
22561
+ } }
22562
+ })],
22563
+ ...numberFormat ? [new BuilderElement({
22564
+ name: "w:numFmt",
22565
+ attributes: {
22566
+ val: {
22567
+ key: "w:val",
22568
+ value: numberFormat.type
22569
+ },
22570
+ format: {
22571
+ key: "w:format",
22572
+ value: numberFormat.format
22573
+ }
22574
+ }
22575
+ })] : [],
22576
+ ...start === void 0 ? [] : [new BuilderElement({
22577
+ name: "w:numStart",
22578
+ attributes: { val: {
22579
+ key: "w:val",
22580
+ value: decimalNumber(start)
22581
+ } }
22582
+ })],
22583
+ ...restart === void 0 ? [] : [new BuilderElement({
22584
+ name: "w:numRestart",
22585
+ attributes: { val: {
22586
+ key: "w:val",
22587
+ value: restart
22588
+ } }
22589
+ })]
22590
+ ]
22591
+ });
22592
+ /**
22593
+ * Creates the footnote properties (footnotePr) of a section.
22594
+ *
22595
+ * ## XSD Schema
22596
+ * ```xml
22597
+ * <xsd:complexType name="CT_FtnProps">
22598
+ * <xsd:sequence>
22599
+ * <xsd:element name="pos" type="CT_FtnPos" minOccurs="0"/>
22600
+ * <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0"/>
22601
+ * <xsd:group ref="EG_FtnEdnNumProps" minOccurs="0"/>
22602
+ * </xsd:sequence>
22603
+ * </xsd:complexType>
22604
+ * ```
22605
+ *
22606
+ * @example
22607
+ * ```typescript
22608
+ * // Footnotes at the end of the section, numbered a, b, c and restarting in each section
22609
+ * createFootnoteProperties({
22610
+ * position: FootnotePosition.SECTION_END,
22611
+ * numberFormat: { type: NumberFormat.LOWER_LETTER },
22612
+ * restart: NoteNumberRestart.EACH_SECTION,
22613
+ * });
22614
+ * ```
22615
+ */
22616
+ var createFootnoteProperties = (options) => createNoteProperties(_objectSpread2({ name: "w:footnotePr" }, options));
22617
+ /**
22618
+ * Creates the endnote properties (endnotePr) of a section.
22619
+ *
22620
+ * ## XSD Schema
22621
+ * ```xml
22622
+ * <xsd:complexType name="CT_EdnProps">
22623
+ * <xsd:sequence>
22624
+ * <xsd:element name="pos" type="CT_EdnPos" minOccurs="0"/>
22625
+ * <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0"/>
22626
+ * <xsd:group ref="EG_FtnEdnNumProps" minOccurs="0"/>
22627
+ * </xsd:sequence>
22628
+ * </xsd:complexType>
22629
+ * ```
22630
+ *
22631
+ * @example
22632
+ * ```typescript
22633
+ * // Endnotes at the end of the document, numbered 001, 002, 003
22634
+ * createEndnoteProperties({
22635
+ * position: EndnotePosition.DOCUMENT_END,
22636
+ * numberFormat: { type: NumberFormat.CUSTOM, format: "001" },
22637
+ * });
22638
+ * ```
22639
+ */
22640
+ var createEndnoteProperties = (options) => createNoteProperties(_objectSpread2({ name: "w:endnotePr" }, options));
22641
+ //#endregion
21178
22642
  //#region src/file/document/body/section-properties/properties/page-borders.ts
21179
22643
  /**
21180
22644
  * Page borders module for WordprocessingML section properties.
@@ -21414,7 +22878,7 @@ var PageNumberSeparator = {
21414
22878
  COLON: "colon",
21415
22879
  /** Em dash separator (—) */
21416
22880
  EM_DASH: "emDash",
21417
- /** En dash separator (–) */
22881
+ /** En dash separator (–), written as `enDash` */
21418
22882
  EN_DASH: "endash"
21419
22883
  };
21420
22884
  /**
@@ -21444,7 +22908,7 @@ var PageNumberSeparator = {
21444
22908
  * });
21445
22909
  * ```
21446
22910
  */
21447
- var createPageNumberType = ({ start, formatType, separator }) => new BuilderElement({
22911
+ var createPageNumberType = ({ start, formatType, separator, chapterHeadingLevel }) => new BuilderElement({
21448
22912
  name: "w:pgNumType",
21449
22913
  attributes: {
21450
22914
  start: {
@@ -21457,7 +22921,11 @@ var createPageNumberType = ({ start, formatType, separator }) => new BuilderElem
21457
22921
  },
21458
22922
  separator: {
21459
22923
  key: "w:chapSep",
21460
- value: separator
22924
+ value: separator === PageNumberSeparator.EN_DASH ? "enDash" : separator
22925
+ },
22926
+ chapterHeadingLevel: {
22927
+ key: "w:chapStyle",
22928
+ value: chapterHeadingLevel === void 0 ? void 0 : decimalNumber(chapterHeadingLevel)
21461
22929
  }
21462
22930
  }
21463
22931
  });
@@ -21761,7 +23229,7 @@ var sectionPageSizeDefaults = {
21761
23229
  * ```
21762
23230
  */
21763
23231
  var SectionProperties = class SectionProperties extends XmlComponent {
21764
- constructor({ page: { size: { width = sectionPageSizeDefaults.WIDTH, height = sectionPageSizeDefaults.HEIGHT, orientation = sectionPageSizeDefaults.ORIENTATION, code } = {}, 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 } = {}, grid: { linePitch = 360, charSpace, type: gridType } = {}, headerWrapperGroup = {}, footerWrapperGroup = {}, lineNumbers, titlePage, verticalAlign, column, type, revision } = {}) {
23232
+ constructor({ page: { size: { width = sectionPageSizeDefaults.WIDTH, height = sectionPageSizeDefaults.HEIGHT, orientation = sectionPageSizeDefaults.ORIENTATION, code } = {}, 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 } = {}, grid: { linePitch = 360, charSpace, type: gridType } = {}, headerWrapperGroup = {}, footerWrapperGroup = {}, lineNumbers, titlePage, verticalAlign, column, type, footnoteProperties, endnoteProperties, revision } = {}) {
21765
23233
  super("w:sectPr");
21766
23234
  _defineProperty(
21767
23235
  this,
@@ -21784,6 +23252,8 @@ var SectionProperties = class SectionProperties extends XmlComponent {
21784
23252
  });
21785
23253
  this.addHeaderFooterGroup(HeaderFooterType.HEADER, headerWrapperGroup);
21786
23254
  this.addHeaderFooterGroup(HeaderFooterType.FOOTER, footerWrapperGroup);
23255
+ if (footnoteProperties) this.root.push(createFootnoteProperties(footnoteProperties));
23256
+ if (endnoteProperties) this.root.push(createEndnoteProperties(endnoteProperties));
21787
23257
  if (type) this.root.push(createSectionType(type));
21788
23258
  this.root.push(createPageSize({
21789
23259
  width,
@@ -21908,7 +23378,7 @@ var SectionPropertiesChange = class extends XmlComponent {
21908
23378
  * ```
21909
23379
  */
21910
23380
  var Body = class extends XmlComponent {
21911
- constructor() {
23381
+ constructor({ pageNumbers } = {}) {
21912
23382
  super("w:body");
21913
23383
  _defineProperty(this, "sections", []);
21914
23384
  _defineProperty(
@@ -21916,11 +23386,15 @@ var Body = class extends XmlComponent {
21916
23386
  /**
21917
23387
  * Section properties that were moved into a paragraph at the end of their section
21918
23388
  * by {@link addSection}, keyed by that paragraph. Used to find the section that
21919
- * governs a given child of the body.
23389
+ * governs a given child of the body, and to write each section's properties into
23390
+ * its paragraph while the body is written.
21920
23391
  */
21921
23392
  "sectionParagraphs",
21922
23393
  /* @__PURE__ */ new Map()
21923
23394
  );
23395
+ _defineProperty(this, "headingBookmarkIds", new HeadingBookmarkIds());
23396
+ _defineProperty(this, "pageNumbers", void 0);
23397
+ this.pageNumbers = pageNumbers;
21924
23398
  }
21925
23399
  /**
21926
23400
  * Finds the section properties that govern a top-level child of the body.
@@ -21935,7 +23409,7 @@ var Body = class extends XmlComponent {
21935
23409
  * @returns The governing section properties, or undefined if the body has no sections
21936
23410
  */
21937
23411
  getSectionPropertiesFor(child) {
21938
- const start = child ? this.root.indexOf(child) + 1 : 0;
23412
+ const start = child ? Math.max(this.root.indexOf(child), 0) : 0;
21939
23413
  for (let i = start; i < this.root.length; i++) {
21940
23414
  const component = this.root[i];
21941
23415
  if (component instanceof SectionProperties) return component;
@@ -21947,8 +23421,10 @@ var Body = class extends XmlComponent {
21947
23421
  /**
21948
23422
  * Adds new section properties to the document body.
21949
23423
  *
21950
- * Creates a new section by moving the previous section's properties into a paragraph
21951
- * at the end of that section, and then adding the new section as the current section.
23424
+ * Creates a new section by moving the previous section's properties into the last
23425
+ * paragraph of that section, and then adding the new section as the current section.
23426
+ * When that section doesn't end with a paragraph of its own (it ends with a table, or
23427
+ * it is empty), an empty paragraph is added to hold its properties.
21952
23428
  *
21953
23429
  * According to the OOXML specification:
21954
23430
  * - Section properties for all sections except the last must be stored in a paragraph's
@@ -21959,16 +23435,24 @@ var Body = class extends XmlComponent {
21959
23435
  */
21960
23436
  addSection(options) {
21961
23437
  const currentSection = this.sections.pop();
21962
- const sectionParagraph = this.createSectionParagraph(currentSection);
21963
- this.root.push(sectionParagraph);
21964
- if (currentSection) this.sectionParagraphs.set(sectionParagraph, currentSection);
23438
+ const lastParagraph = this.lastParagraphOfSection();
23439
+ if (currentSection && lastParagraph) this.sectionParagraphs.set(lastParagraph, currentSection);
23440
+ else {
23441
+ const sectionParagraph = this.createSectionParagraph();
23442
+ this.root.push(sectionParagraph);
23443
+ if (currentSection) this.sectionParagraphs.set(sectionParagraph, currentSection);
23444
+ }
21965
23445
  this.sections.push(new SectionProperties(options));
21966
23446
  }
21967
23447
  /**
21968
23448
  * Prepares the body element for XML serialization.
21969
23449
  *
21970
23450
  * Ensures that the last section's properties are placed as a direct child of the body
21971
- * element, as required by the OOXML specification.
23451
+ * element, as required by the OOXML specification. Once the body is written, its tables
23452
+ * of contents are filled in from its headings, and, when the body has a page number
23453
+ * estimator, its page references are given their page numbers. Its SEQ fields are given
23454
+ * their numbers after the tables of contents are filled in, as Word leaves a heading's SEQ
23455
+ * number out of its entry.
21972
23456
  *
21973
23457
  * @param context - The XML serialization context
21974
23458
  * @returns The prepared XML object or undefined
@@ -21978,7 +23462,19 @@ var Body = class extends XmlComponent {
21978
23462
  this.root.splice(0, 1);
21979
23463
  this.root.push(this.sections.pop());
21980
23464
  }
21981
- return super.prepForXml(context);
23465
+ for (const [paragraph, section] of this.sectionParagraphs) paragraph.addSectionProperties(section);
23466
+ let xml;
23467
+ try {
23468
+ xml = super.prepForXml(context);
23469
+ } finally {
23470
+ for (const [paragraph, section] of this.sectionParagraphs) paragraph.removeSectionProperties(section);
23471
+ }
23472
+ fillTablesOfContents(xml, context, this.headingBookmarkIds);
23473
+ if (this.pageNumbers) {
23474
+ fillSequenceNumbers(xml, context);
23475
+ fillPageNumbers(xml, context, this.pageNumbers);
23476
+ }
23477
+ return xml;
21982
23478
  }
21983
23479
  /**
21984
23480
  * Adds a block-level component to the body.
@@ -21989,14 +23485,32 @@ var Body = class extends XmlComponent {
21989
23485
  * @param component - The XML component to add (paragraph, table, etc.)
21990
23486
  */
21991
23487
  push(component) {
23488
+ const section = component instanceof Paragraph ? this.sectionParagraphs.get(component) : void 0;
23489
+ if (section) {
23490
+ const sectionParagraph = this.createSectionParagraph();
23491
+ this.root.splice(this.root.indexOf(component) + 1, 0, sectionParagraph);
23492
+ this.sectionParagraphs.delete(component);
23493
+ this.sectionParagraphs.set(sectionParagraph, section);
23494
+ }
21992
23495
  this.root.push(component);
21993
23496
  }
21994
- createSectionParagraph(section) {
21995
- const paragraph = new Paragraph({});
21996
- const properties = new ParagraphProperties({});
21997
- properties.push(section);
21998
- paragraph.addChildElement(properties);
21999
- return paragraph;
23497
+ /**
23498
+ * The paragraph the current section ends with, which can hold its properties.
23499
+ *
23500
+ * There is none when the section ends with something other than a paragraph, or is empty:
23501
+ * its last child is then the placeholder at the start of the body (removed when the body is
23502
+ * written) or the paragraph that ends the section before, which has properties of its own.
23503
+ */
23504
+ lastParagraphOfSection() {
23505
+ const last = this.root[this.root.length - 1];
23506
+ return last instanceof Paragraph && last !== this.root[0] && !this.sectionParagraphs.has(last) && this.root.indexOf(last) === this.root.length - 1 ? last : void 0;
23507
+ }
23508
+ /**
23509
+ * An empty paragraph to end a section that has no paragraph of its own to end it. The section's
23510
+ * properties are written into it with the others, when the body is written.
23511
+ */
23512
+ createSectionParagraph() {
23513
+ return new Paragraph({});
22000
23514
  }
22001
23515
  };
22002
23516
  //#endregion
@@ -23108,6 +24622,9 @@ var TDirection = class extends XmlComponent {
23108
24622
  var TableCellProperties = class extends IgnoreIfEmptyXmlComponent {
23109
24623
  constructor(options) {
23110
24624
  super("w:tcPr", options.includeIfEmpty);
24625
+ _defineProperty(this, "hasWidth", void 0);
24626
+ _defineProperty(this, "hasColumnWidth", false);
24627
+ this.hasWidth = options.width !== void 0;
23111
24628
  if (options.width) this.root.push(createTableWidthElement("w:tcW", options.width));
23112
24629
  if (options.columnSpan) this.root.push(new GridSpan(options.columnSpan));
23113
24630
  if (options.verticalMerge) this.root.push(new VerticalMerge(options.verticalMerge));
@@ -23125,6 +24642,19 @@ var TableCellProperties = class extends IgnoreIfEmptyXmlComponent {
23125
24642
  if (options.cellMerge) this.root.push(new CellMerge(options.cellMerge));
23126
24643
  if (options.revision) this.root.push(new TableCellPropertiesChange(options.revision));
23127
24644
  }
24645
+ /**
24646
+ * Gives a cell without a width of its own the width of the table's columns it spans, in twips.
24647
+ *
24648
+ * @internal
24649
+ */
24650
+ setColumnWidth(twips) {
24651
+ if (this.hasWidth) return;
24652
+ this.root.splice(0, this.hasColumnWidth ? 1 : 0, createTableWidthElement("w:tcW", {
24653
+ size: twips,
24654
+ type: WidthType.DXA
24655
+ }));
24656
+ this.hasColumnWidth = true;
24657
+ }
23128
24658
  };
23129
24659
  var TableCellPropertiesChange = class extends XmlComponent {
23130
24660
  constructor(options) {
@@ -23183,10 +24713,20 @@ var TableCell = class extends XmlComponent {
23183
24713
  "options",
23184
24714
  void 0
23185
24715
  );
24716
+ _defineProperty(this, "properties", void 0);
23186
24717
  this.options = options;
23187
- this.root.push(new TableCellProperties(options));
24718
+ this.properties = new TableCellProperties(options);
24719
+ this.root.push(this.properties);
23188
24720
  for (const child of options.children) this.root.push(child);
23189
24721
  }
24722
+ /**
24723
+ * Gives the cell, unless it has a width of its own, the width of the table's columns it spans, in twips.
24724
+ *
24725
+ * @internal
24726
+ */
24727
+ setColumnWidth(twips) {
24728
+ this.properties.setColumnWidth(twips);
24729
+ }
23190
24730
  prepForXml(context) {
23191
24731
  if (!(this.root[this.root.length - 1] instanceof Paragraph)) this.root.push(new Paragraph({}));
23192
24732
  return super.prepForXml(context);
@@ -24050,6 +25590,7 @@ var Table = class Table extends FileChild {
24050
25590
  columnIndex += cell.options.columnSpan || 1;
24051
25591
  });
24052
25592
  });
25593
+ this.setCellWidths(DEFAULT_AVAILABLE_WIDTH);
24053
25594
  this.resolvedColumnWidths = columnWidths !== null && columnWidths !== void 0 ? columnWidths : resolveColumnWidths({
24054
25595
  rows,
24055
25596
  width: this.width,
@@ -24106,6 +25647,7 @@ var Table = class Table extends FileChild {
24106
25647
  * serializing.
24107
25648
  */
24108
25649
  prepForXml(context) {
25650
+ this.setCellWidths(this.resolveAvailableWidth(context));
24109
25651
  if (this.columnWidths === void 0) {
24110
25652
  this.resolvedColumnWidths = resolveColumnWidths({
24111
25653
  rows: this.rows,
@@ -24118,6 +25660,29 @@ var Table = class Table extends FileChild {
24118
25660
  return super.prepForXml(context);
24119
25661
  }
24120
25662
  /**
25663
+ * Gives each cell without a width of its own the width of the `columnWidths` it spans, as Word sizes the columns of
25664
+ * cells without a width to their content, whatever the grid says. When the table's width is wider than the columns
25665
+ * add up to, they are scaled up to fill it, as Word and LibreOffice lay them out, so columns given as proportions
25666
+ * keep them.
25667
+ */
25668
+ setCellWidths(availableWidth) {
25669
+ var _resolvePreferredWidt;
25670
+ if (this.columnWidths === void 0) return;
25671
+ const total = this.columnWidths.reduce((sum, columnWidth) => sum + columnWidth, 0);
25672
+ const tableWidth = (_resolvePreferredWidt = resolvePreferredWidth(this.width, availableWidth)) !== null && _resolvePreferredWidt !== void 0 ? _resolvePreferredWidt : 0;
25673
+ const scale = total > 0 && tableWidth > total ? tableWidth / total : 1;
25674
+ for (const row of this.rows) {
25675
+ let column = 0;
25676
+ for (const cell of row.cells) {
25677
+ const span = cell.options.columnSpan || 1;
25678
+ const spanned = this.columnWidths.slice(column, column + span);
25679
+ const cellWidth = Math.round(spanned.reduce((sum, columnWidth) => sum + columnWidth, 0) * scale);
25680
+ if (spanned.length === span && cellWidth > 0) cell.setColumnWidth(cellWidth);
25681
+ column += span;
25682
+ }
25683
+ }
25684
+ }
25685
+ /**
24121
25686
  * Finds the width in twips available to this table from the serialization context:
24122
25687
  * the parent cell for a nested table, otherwise the text width of the section the
24123
25688
  * table belongs to (the first section for headers, footers and other parts). Falls
@@ -24730,7 +26295,7 @@ var CustomProperties = class extends XmlComponent {
24730
26295
  for (const property of properties) this.addCustomProperty(property);
24731
26296
  }
24732
26297
  prepForXml(context) {
24733
- this.properties.forEach((x) => this.root.push(x));
26298
+ this.root.splice(1, this.root.length - 1, ...this.properties);
24734
26299
  return super.prepForXml(context);
24735
26300
  }
24736
26301
  addCustomProperty(property) {
@@ -24992,7 +26557,7 @@ var Document = class extends XmlComponent {
24992
26557
  "w16sdtdh",
24993
26558
  "w16se"
24994
26559
  ], "w14 w15 wp14"));
24995
- this.body = new Body();
26560
+ this.body = new Body({ pageNumbers: options.pageNumbers });
24996
26561
  if (options.background) this.root.push(new DocumentBackground(options.background));
24997
26562
  this.root.push(this.body);
24998
26563
  }
@@ -25290,6 +26855,15 @@ var Endnotes = class extends XmlComponent {
25290
26855
  });
25291
26856
  this.root.push(endnote);
25292
26857
  }
26858
+ /**
26859
+ * Formats the endnotes, with the page numbers worked out for their document written into their fields, when the
26860
+ * document's body is written with an estimate of its pages.
26861
+ */
26862
+ prepForXml(context) {
26863
+ const xml = super.prepForXml(context);
26864
+ fillPartPageNumbers(xml, context);
26865
+ return xml;
26866
+ }
25293
26867
  };
25294
26868
  //#endregion
25295
26869
  //#region src/file/endnotes-wrapper.ts
@@ -25431,6 +27005,15 @@ var Footer$1 = class extends InitializableXmlComponent {
25431
27005
  add(item) {
25432
27006
  this.root.push(item);
25433
27007
  }
27008
+ /**
27009
+ * Formats the footer, with the page numbers worked out for its document written into its fields, when the document's
27010
+ * body is written with an estimate of its pages.
27011
+ */
27012
+ prepForXml(context) {
27013
+ const xml = super.prepForXml(context);
27014
+ fillPartPageNumbers(xml, context, this.refId);
27015
+ return xml;
27016
+ }
25434
27017
  };
25435
27018
  //#endregion
25436
27019
  //#region src/file/footer-wrapper.ts
@@ -25781,6 +27364,15 @@ var FootNotes = class extends XmlComponent {
25781
27364
  });
25782
27365
  this.root.push(footnote);
25783
27366
  }
27367
+ /**
27368
+ * Formats the footnotes, with the page numbers worked out for their document written into their fields, when the
27369
+ * document's body is written with an estimate of its pages.
27370
+ */
27371
+ prepForXml(context) {
27372
+ const xml = super.prepForXml(context);
27373
+ fillPartPageNumbers(xml, context);
27374
+ return xml;
27375
+ }
25784
27376
  };
25785
27377
  //#endregion
25786
27378
  //#region src/file/footnotes-wrapper.ts
@@ -25954,6 +27546,15 @@ var Header$1 = class extends InitializableXmlComponent {
25954
27546
  add(item) {
25955
27547
  this.root.push(item);
25956
27548
  }
27549
+ /**
27550
+ * Formats the header, with the page numbers worked out for its document written into its fields, when the document's
27551
+ * body is written with an estimate of its pages.
27552
+ */
27553
+ prepForXml(context) {
27554
+ const xml = super.prepForXml(context);
27555
+ fillPartPageNumbers(xml, context, this.refId);
27556
+ return xml;
27557
+ }
25957
27558
  };
25958
27559
  //#endregion
25959
27560
  //#region src/file/header-wrapper.ts
@@ -26958,8 +28559,7 @@ var Numbering = class extends XmlComponent {
26958
28559
  * @returns The prepared XML object
26959
28560
  */
26960
28561
  prepForXml(context) {
26961
- for (const numbering of this.abstractNumberingMap.values()) this.root.push(numbering);
26962
- for (const numbering of this.concreteNumberingMap.values()) this.root.push(numbering);
28562
+ this.root.splice(1, this.root.length - 1, ...this.abstractNumberingMap.values(), ...this.concreteNumberingMap.values());
26963
28563
  return super.prepForXml(context);
26964
28564
  }
26965
28565
  /**
@@ -27013,6 +28613,7 @@ var Numbering = class extends XmlComponent {
27013
28613
  };
27014
28614
  //#endregion
27015
28615
  //#region src/file/package-part/package-part.ts
28616
+ var PATH_PART = /^[\w-]+$/;
27016
28617
  var RESERVED_FOLDERS = /* @__PURE__ */ new Set([
27017
28618
  "_rels",
27018
28619
  "fonts",
@@ -27051,6 +28652,7 @@ var RESERVED_FOLDERS = /* @__PURE__ */ new Set([
27051
28652
  var PackagePart = class {
27052
28653
  /**
27053
28654
  * @throws If the folder isn't a single folder name, or is one of the folders docx writes parts of its own in
28655
+ * @throws If the name or the extension isn't a single part of a file name, which could lead out of the folder
27054
28656
  */
27055
28657
  constructor(options) {
27056
28658
  _defineProperty(this, "options", void 0);
@@ -27063,7 +28665,9 @@ var PackagePart = class {
27063
28665
  );
27064
28666
  _defineProperty(this, "addedTo", /* @__PURE__ */ new WeakSet());
27065
28667
  this.options = options;
27066
- if (!/^[\w-]+$/.test(options.folder) || RESERVED_FOLDERS.has(options.folder)) throw new Error(`Invalid package part folder "${options.folder}". Expected a folder name docx doesn't use, such as "charts"`);
28668
+ if (!PATH_PART.test(options.folder) || RESERVED_FOLDERS.has(options.folder)) throw new Error(`Invalid package part folder "${options.folder}". Expected a folder name docx doesn't use, such as "charts"`);
28669
+ if (!PATH_PART.test(options.name)) throw new Error(`Invalid package part name "${options.name}". Expected letters, digits, "_" and "-", such as "chart"`);
28670
+ if (!PATH_PART.test(options.extension)) throw new Error(`Invalid package part extension "${options.extension}". Expected letters, digits, "_" and "-", such as "xml"`);
27067
28671
  }
27068
28672
  /**
27069
28673
  * Adds the part to the package being written, once, and a relationship to it from the part being written.
@@ -27085,7 +28689,7 @@ var PackageParts = class {
27085
28689
  /**
27086
28690
  * @param contentTypes - Where each part's content type is added
27087
28691
  * @param existingPaths - The paths under word/ of the parts the package already has, such as a template's charts,
27088
- * which new parts are numbered after
28692
+ * which new parts don't take
27089
28693
  */
27090
28694
  constructor(contentTypes, existingPaths = /* @__PURE__ */ new Set()) {
27091
28695
  _defineProperty(this, "contentTypes", void 0);
@@ -27384,6 +28988,7 @@ var SettingsAttributes = class extends XmlAttributeComponent {
27384
28988
  * ```xml
27385
28989
  * <xsd:complexType name="CT_Settings">
27386
28990
  * <xsd:sequence>
28991
+ * <xsd:element name="embedTrueTypeFonts" type="CT_OnOff" minOccurs="0"/>
27387
28992
  * <xsd:element name="trackRevisions" type="CT_OnOff" minOccurs="0"/>
27388
28993
  * <xsd:element name="defaultTabStop" type="CT_TwipsMeasure" minOccurs="0"/>
27389
28994
  * <xsd:element name="autoHyphenation" type="CT_OnOff" minOccurs="0"/>
@@ -27442,6 +29047,7 @@ var Settings = class extends XmlComponent {
27442
29047
  Ignorable: "w14 w15 wp14"
27443
29048
  }));
27444
29049
  this.root.push(new OnOffElement("w:displayBackgroundShape", true));
29050
+ if (options.embedFonts !== void 0) this.root.push(new OnOffElement("w:embedTrueTypeFonts", options.embedFonts));
27445
29051
  if (options.trackRevisions !== void 0) this.root.push(new OnOffElement("w:trackRevisions", options.trackRevisions));
27446
29052
  if (options.defaultTabStop !== void 0) this.root.push(new NumberValueElement("w:defaultTabStop", options.defaultTabStop));
27447
29053
  if (((_options$hyphenation = options.hyphenation) === null || _options$hyphenation === void 0 ? void 0 : _options$hyphenation.autoHyphenation) !== void 0) this.root.push(new OnOffElement("w:autoHyphenation", options.hyphenation.autoHyphenation));
@@ -28030,6 +29636,39 @@ var HyperlinkStyle = class extends StyleForCharacter {
28030
29636
  }, options));
28031
29637
  }
28032
29638
  };
29639
+ /**
29640
+ * Represents the Normal Table style, the default style of tables.
29641
+ *
29642
+ * It gives cells the margins Word gives the tables it makes: 108 twips (0.075 inches) on the left and right. Without a
29643
+ * default table style, Word gives cells no margins, so their text touches the borders, where LibreOffice and other
29644
+ * applications use these margins.
29645
+ */
29646
+ var NormalTableStyle = class extends Style {
29647
+ constructor() {
29648
+ super({
29649
+ type: "table",
29650
+ styleId: "TableNormal",
29651
+ default: true
29652
+ }, {
29653
+ name: "Normal Table",
29654
+ uiPriority: 99,
29655
+ semiHidden: true,
29656
+ unhideWhenUsed: true
29657
+ });
29658
+ this.root.push(new TableProperties({
29659
+ indent: {
29660
+ size: 0,
29661
+ type: WidthType.DXA
29662
+ },
29663
+ cellMargin: {
29664
+ top: 0,
29665
+ left: 108,
29666
+ bottom: 0,
29667
+ right: 108
29668
+ }
29669
+ }));
29670
+ }
29671
+ };
28033
29672
  //#endregion
28034
29673
  //#region src/file/styles/styles.ts
28035
29674
  /** The name of a formatted element, such as `w:style`, or `_attr` for its parent's attributes */
@@ -28322,6 +29961,7 @@ var createDefaultStyles = (options = {}) => {
28322
29961
  name: "Normal",
28323
29962
  quickFormat: true
28324
29963
  }),
29964
+ normalTable: new NormalTableStyle(),
28325
29965
  document: new DocumentDefaults((_options$document = options.document) !== null && _options$document !== void 0 ? _options$document : {}),
28326
29966
  title: new TitleStyle(_objectSpread2({ run: { size: 56 } }, options.title)),
28327
29967
  heading1: new Heading1Style(_objectSpread2({ run: {
@@ -28996,7 +30636,7 @@ var Theme = class extends XmlComponent {
28996
30636
  */
28997
30637
  var File = class {
28998
30638
  constructor(options) {
28999
- var _options$creator, _options$revision, _options$lastModified, _options$comments, _options$customProper, _options$features, _options$features2, _options$hyphenation, _options$hyphenation2, _options$hyphenation3, _options$hyphenation4, _options$fonts;
30639
+ var _options$creator, _options$revision, _options$lastModified, _options$comments, _options$customProper, _options$features, _options$features2, _options$fonts, _options$hyphenation, _options$hyphenation2, _options$hyphenation3, _options$hyphenation4, _options$fonts2;
29000
30640
  _defineProperty(this, "currentRelationshipId", 1);
29001
30641
  _defineProperty(this, "documentWrapper", void 0);
29002
30642
  _defineProperty(this, "headers", []);
@@ -29044,13 +30684,17 @@ var File = class {
29044
30684
  this.endnotesWrapper = new EndnotesWrapper();
29045
30685
  this.contentTypes = new ContentTypes();
29046
30686
  this.packageParts = new PackageParts(this.contentTypes);
29047
- this.documentWrapper = new DocumentWrapper({ background: options.background });
30687
+ this.documentWrapper = new DocumentWrapper({
30688
+ background: options.background,
30689
+ pageNumbers: options.pageNumbers
30690
+ });
29048
30691
  this.settings = new Settings({
29049
30692
  compatibilityModeVersion: options.compatabilityModeVersion,
29050
30693
  compatibility: options.compatibility,
29051
30694
  evenAndOddHeaders: options.evenAndOddHeaderAndFooters ? true : false,
29052
30695
  trackRevisions: (_options$features = options.features) === null || _options$features === void 0 ? void 0 : _options$features.trackRevisions,
29053
30696
  updateFields: (_options$features2 = options.features) === null || _options$features2 === void 0 ? void 0 : _options$features2.updateFields,
30697
+ embedFonts: ((_options$fonts = options.fonts) === null || _options$fonts === void 0 ? void 0 : _options$fonts.length) ? true : void 0,
29054
30698
  defaultTabStop: options.defaultTabStop,
29055
30699
  hyphenation: {
29056
30700
  autoHyphenation: (_options$hyphenation = options.hyphenation) === null || _options$hyphenation === void 0 ? void 0 : _options$hyphenation.autoHyphenation,
@@ -29061,16 +30705,20 @@ var File = class {
29061
30705
  });
29062
30706
  this.media = new Media();
29063
30707
  if (options.externalStyles !== void 0) {
29064
- var _options$styles$defau, _options$styles;
30708
+ var _options$styles$defau, _options$styles, _options$styles2, _options$styles3;
29065
30709
  const given = (_options$styles$defau = (_options$styles = options.styles) === null || _options$styles === void 0 ? void 0 : _options$styles.default) !== null && _options$styles$defau !== void 0 ? _options$styles$defau : {};
29066
30710
  const defaultStyles = Object.entries(createDefaultStyles(given));
29067
30711
  const isGiven = ([key]) => given[key] !== void 0;
29068
30712
  const externalStyles = new ExternalStylesFactory().newInstance(options.externalStyles);
29069
- this.styles = new Styles(_objectSpread2(_objectSpread2({}, externalStyles), {}, { importedStyles: [
29070
- ...defaultStyles.filter((entry) => !isGiven(entry)).map(([, style]) => style),
29071
- ...externalStyles.importedStyles,
29072
- ...defaultStyles.filter(isGiven).map(([, style]) => style)
29073
- ] }));
30713
+ this.styles = new Styles(_objectSpread2(_objectSpread2({}, externalStyles), {}, {
30714
+ paragraphStyles: (_options$styles2 = options.styles) === null || _options$styles2 === void 0 ? void 0 : _options$styles2.paragraphStyles,
30715
+ characterStyles: (_options$styles3 = options.styles) === null || _options$styles3 === void 0 ? void 0 : _options$styles3.characterStyles,
30716
+ importedStyles: [
30717
+ ...defaultStyles.filter((entry) => !isGiven(entry)).map(([, style]) => style),
30718
+ ...externalStyles.importedStyles,
30719
+ ...defaultStyles.filter(isGiven).map(([, style]) => style)
30720
+ ]
30721
+ }));
29074
30722
  } else if (options.styles) {
29075
30723
  const defaultStyles = new DefaultStylesFactory().newInstance(options.styles.default);
29076
30724
  this.styles = new Styles(_objectSpread2(_objectSpread2({}, defaultStyles), options.styles));
@@ -29082,7 +30730,7 @@ var File = class {
29082
30730
  for (const section of options.sections) this.addSection(section);
29083
30731
  if (options.footnotes) for (const key in options.footnotes) this.footnotesWrapper.View.createFootNote(parseFloat(key), options.footnotes[key].children);
29084
30732
  if (options.endnotes) for (const key in options.endnotes) this.endnotesWrapper.View.createEndnote(parseFloat(key), options.endnotes[key].children);
29085
- this.fontWrapper = new FontWrapper((_options$fonts = options.fonts) !== null && _options$fonts !== void 0 ? _options$fonts : []);
30733
+ this.fontWrapper = new FontWrapper((_options$fonts2 = options.fonts) !== null && _options$fonts2 !== void 0 ? _options$fonts2 : []);
29086
30734
  this.theme = new Theme(options.theme);
29087
30735
  this.documentWrapper.Relationships.addRelationship(this.currentRelationshipId++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme", "theme/theme1.xml");
29088
30736
  }
@@ -29218,113 +30866,6 @@ var File = class {
29218
30866
  }
29219
30867
  };
29220
30868
  //#endregion
29221
- //#region src/file/table-of-contents/field-instruction.ts
29222
- /**
29223
- * Field Instruction module for Table of Contents.
29224
- *
29225
- * This module handles the generation of TOC field instruction text
29226
- * that controls how the table of contents is built.
29227
- *
29228
- * Reference: http://officeopenxml.com/WPfieldInstructions.php
29229
- *
29230
- * @module
29231
- */
29232
- /**
29233
- * Represents a field instruction for a Table of Contents.
29234
- *
29235
- * The FieldInstruction class generates the TOC field code string that Word uses
29236
- * to determine how to build the table of contents, including which headings to include,
29237
- * formatting options, and other TOC-specific settings.
29238
- *
29239
- * Reference: http://officeopenxml.com/WPfieldInstructions.php
29240
- *
29241
- * ## XSD Schema
29242
- * ```xml
29243
- * <xsd:element name="instrText" type="CT_Text"/>
29244
- * ```
29245
- *
29246
- * @example
29247
- * ```typescript
29248
- * // Basic TOC field instruction
29249
- * new FieldInstruction({ headingStyleRange: "1-3" });
29250
- *
29251
- * // TOC with hyperlinks and custom styles
29252
- * new FieldInstruction({
29253
- * hyperlink: true,
29254
- * headingStyleRange: "1-3",
29255
- * stylesWithLevels: [new StyleLevel("CustomStyle", 2)],
29256
- * });
29257
- * ```
29258
- */
29259
- var FieldInstruction = class extends XmlComponent {
29260
- constructor(properties = {}) {
29261
- super("w:instrText");
29262
- _defineProperty(this, "properties", void 0);
29263
- this.properties = properties;
29264
- this.root.push(new TextAttributes({ space: SpaceType.PRESERVE }));
29265
- let instruction = "TOC";
29266
- if (this.properties.captionLabel) instruction = `${instruction} \\a "${this.properties.captionLabel}"`;
29267
- if (this.properties.entriesFromBookmark) instruction = `${instruction} \\b "${this.properties.entriesFromBookmark}"`;
29268
- if (this.properties.captionLabelIncludingNumbers) instruction = `${instruction} \\c "${this.properties.captionLabelIncludingNumbers}"`;
29269
- if (this.properties.sequenceAndPageNumbersSeparator) instruction = `${instruction} \\d "${this.properties.sequenceAndPageNumbersSeparator}"`;
29270
- if (this.properties.tcFieldIdentifier) instruction = `${instruction} \\f "${this.properties.tcFieldIdentifier}"`;
29271
- if (this.properties.hyperlink) instruction = `${instruction} \\h`;
29272
- if (this.properties.tcFieldLevelRange) instruction = `${instruction} \\l "${this.properties.tcFieldLevelRange}"`;
29273
- if (this.properties.pageNumbersEntryLevelsRange) instruction = `${instruction} \\n "${this.properties.pageNumbersEntryLevelsRange}"`;
29274
- if (this.properties.headingStyleRange) instruction = `${instruction} \\o "${this.properties.headingStyleRange}"`;
29275
- if (this.properties.entryAndPageNumberSeparator) instruction = `${instruction} \\p "${this.properties.entryAndPageNumberSeparator}"`;
29276
- if (this.properties.seqFieldIdentifierForPrefix) instruction = `${instruction} \\s "${this.properties.seqFieldIdentifierForPrefix}"`;
29277
- if (this.properties.stylesWithLevels && this.properties.stylesWithLevels.length) {
29278
- const styles = this.properties.stylesWithLevels.map((sl) => `${sl.styleName},${sl.level}`).join(",");
29279
- instruction = `${instruction} \\t "${styles}"`;
29280
- }
29281
- if (this.properties.useAppliedParagraphOutlineLevel) instruction = `${instruction} \\u`;
29282
- if (this.properties.preserveTabInEntries) instruction = `${instruction} \\w`;
29283
- if (this.properties.preserveNewLineInEntries) instruction = `${instruction} \\x`;
29284
- if (this.properties.hideTabAndPageNumbersInWebView) instruction = `${instruction} \\z`;
29285
- this.root.push(instruction);
29286
- }
29287
- };
29288
- //#endregion
29289
- //#region src/file/table-of-contents/sdt-content.ts
29290
- /**
29291
- * Structured Document Tag Content module.
29292
- *
29293
- * This module represents the content container for structured document tags,
29294
- * including table of contents elements.
29295
- *
29296
- * Reference: http://officeopenxml.com/WPtableOfContents.php
29297
- *
29298
- * @module
29299
- */
29300
- /**
29301
- * Represents the content portion of a Structured Document Tag.
29302
- *
29303
- * The StructuredDocumentTagContent contains the actual content elements
29304
- * (paragraphs, tables, etc.) within a structured document tag, such as
29305
- * the paragraphs that make up a table of contents.
29306
- *
29307
- * Reference: http://officeopenxml.com/WPtableOfContents.php
29308
- *
29309
- * ## XSD Schema
29310
- * ```xml
29311
- * <xsd:complexType name="CT_SdtContentBlock">
29312
- * <xsd:group ref="EG_ContentBlockContent" minOccurs="0" maxOccurs="unbounded"/>
29313
- * </xsd:complexType>
29314
- * ```
29315
- *
29316
- * @example
29317
- * ```typescript
29318
- * const content = new StructuredDocumentTagContent();
29319
- * content.addChildElement(new Paragraph("Content"));
29320
- * ```
29321
- */
29322
- var StructuredDocumentTagContent = class extends XmlComponent {
29323
- constructor() {
29324
- super("w:sdtContent");
29325
- }
29326
- };
29327
- //#endregion
29328
30869
  //#region src/file/table-of-contents/sdt-properties.ts
29329
30870
  /**
29330
30871
  * Structured Document Tag Properties module.
@@ -29404,6 +30945,12 @@ var _excluded$2 = [
29404
30945
  * TableOfContents creates an auto-generated list of document headings
29405
30946
  * with page numbers. It uses a TOC field code to generate entries.
29406
30947
  *
30948
+ * Unless it is given `cachedEntries` or `contentChildren`, it is written with an
30949
+ * entry for each heading its options include, linked to a bookmark on the heading,
30950
+ * so it isn't empty before Word updates it or in applications that don't update it.
30951
+ * The page numbers are left for Word to fill in when it updates the field, unless the document's `pageNumbers`
30952
+ * writes them.
30953
+ *
29407
30954
  * Reference: http://officeopenxml.com/WPtableOfContents.php
29408
30955
  *
29409
30956
  * @publicApi
@@ -29429,12 +30976,18 @@ var _excluded$2 = [
29429
30976
  */
29430
30977
  var TableOfContents = class extends FileChild {
29431
30978
  constructor(alias = "Table of Contents", _ref = {}) {
29432
- let { contentChildren = [], cachedEntries = [], beginDirty = true } = _ref, properties = _objectWithoutProperties(_ref, _excluded$2);
30979
+ let { contentChildren = [], cachedEntries = [], beginDirty } = _ref, properties = _objectWithoutProperties(_ref, _excluded$2);
29433
30980
  super("w:sdt");
30981
+ _defineProperty(
30982
+ this,
30983
+ /** What it is filled in with from the headings, when it isn't given its content */
30984
+ "fromHeadings",
30985
+ void 0
30986
+ );
29434
30987
  this.root.push(new StructuredDocumentTagProperties(alias));
29435
30988
  const content = new StructuredDocumentTagContent();
29436
30989
  const beginParagraphMandatoryChildren = [new Run({ children: [
29437
- createBegin(beginDirty),
30990
+ beginOf(beginDirty),
29438
30991
  new FieldInstruction(properties),
29439
30992
  createSeparate()
29440
30993
  ] })];
@@ -29461,9 +31014,27 @@ var TableOfContents = class extends FileChild {
29461
31014
  for (const child of contentChildren) content.addChildElement(child);
29462
31015
  const endParagraph = new Paragraph({ children: endParagraphMandatoryChildren });
29463
31016
  content.addChildElement(endParagraph);
31017
+ if (contentChildren.length === 0) this.fromHeadings = {
31018
+ properties,
31019
+ beginDirty
31020
+ };
29464
31021
  }
29465
31022
  this.root.push(content);
29466
31023
  }
31024
+ /**
31025
+ * Written empty, and filled in from the headings once the body it is in is written, unless it was given its content.
31026
+ * The page numbers are aligned to the right of the text in its section.
31027
+ */
31028
+ prepForXml(context) {
31029
+ const xml = super.prepForXml(context);
31030
+ recordTableOfContents(xml, this.fromHeadings && _objectSpread2(_objectSpread2({}, this.fromHeadings), {}, { textWidth: this.textWidthIn(context) }));
31031
+ return xml;
31032
+ }
31033
+ /** The width of the text in the section it is in */
31034
+ textWidthIn(context) {
31035
+ var _context$file$Documen, _context$file;
31036
+ return (_context$file$Documen = (_context$file = context.file) === null || _context$file === void 0 || (_context$file = _context$file.Document) === null || _context$file === void 0 || (_context$file = _context$file.View.Body.getSectionPropertiesFor(this)) === null || _context$file === void 0 ? void 0 : _context$file.AvailableTextWidth) !== null && _context$file$Documen !== void 0 ? _context$file$Documen : DEFAULT_AVAILABLE_WIDTH;
31037
+ }
29467
31038
  getTabStopsForLevel(level, pageWidth = 9025) {
29468
31039
  return [{
29469
31040
  type: "clear",
@@ -33877,11 +35448,11 @@ var NumberingReplacer = class {
33877
35448
  *
33878
35449
  * @module
33879
35450
  */
33880
- var formatter$2 = new Formatter();
35451
+ var formatter$3 = new Formatter();
33881
35452
  /**
33882
35453
  * Formats a part's XML, with the relationships that anything in it that refers to other parts adds to.
33883
35454
  */
33884
- var xmlifyPart = (file, content, prettify, relationships, standalone = true) => (0, import_xml.default)(formatter$2.format(content, {
35455
+ var xmlifyPart = (file, content, prettify, relationships, standalone = true) => (0, import_xml.default)(formatter$3.format(content, {
33885
35456
  viewWrapper: {
33886
35457
  View: content,
33887
35458
  Relationships: relationships
@@ -33998,11 +35569,10 @@ var Compiler = class {
33998
35569
  zip.file(`word/media/${data.fileName}`, data.data);
33999
35570
  zip.file(`word/media/${data.fallback.fileName}`, data.fallback.data);
34000
35571
  }
34001
- for (const [i, { data: buffer, fontKey }] of file.FontTable.fontOptionsWithKey.entries()) zip.file(`word/fonts/font${i + 1}.odttf`, obfuscate(buffer, fontKey));
35572
+ for (const [i, { data: buffer, fontKey }] of file.FontTable.files.entries()) zip.file(`word/fonts/font${i + 1}.odttf`, obfuscate(buffer, fontKey));
34002
35573
  return zip;
34003
35574
  }
34004
35575
  xmlifyFile(file, prettify) {
34005
- const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1;
34006
35576
  const documentXmlData = (0, import_xml.default)(this.formatter.format(file.Document.View, {
34007
35577
  viewWrapper: file.Document,
34008
35578
  file,
@@ -34014,7 +35584,6 @@ var Compiler = class {
34014
35584
  encoding: "UTF-8"
34015
35585
  }
34016
35586
  });
34017
- const commentRelationshipCount = file.Comments.Relationships.RelationshipCount + 1;
34018
35587
  const commentXmlData = (0, import_xml.default)(this.formatter.format(file.Comments, {
34019
35588
  viewWrapper: {
34020
35589
  View: file.Comments,
@@ -34029,7 +35598,6 @@ var Compiler = class {
34029
35598
  encoding: "UTF-8"
34030
35599
  }
34031
35600
  });
34032
- const footnoteRelationshipCount = file.FootNotes.Relationships.RelationshipCount + 1;
34033
35601
  const footnoteXmlData = (0, import_xml.default)(this.formatter.format(file.FootNotes.View, {
34034
35602
  viewWrapper: file.FootNotes,
34035
35603
  file,
@@ -34041,17 +35609,31 @@ var Compiler = class {
34041
35609
  encoding: "UTF-8"
34042
35610
  }
34043
35611
  });
35612
+ const endnoteXmlData = (0, import_xml.default)(this.formatter.format(file.Endnotes.View, {
35613
+ viewWrapper: file.Endnotes,
35614
+ file,
35615
+ stack: []
35616
+ }), {
35617
+ indent: prettify,
35618
+ declaration: { encoding: "UTF-8" }
35619
+ });
35620
+ const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1;
35621
+ const commentRelationshipCount = file.Comments.Relationships.RelationshipCount + 1;
35622
+ const footnoteRelationshipCount = file.FootNotes.Relationships.RelationshipCount + 1;
35623
+ const endnoteRelationshipCount = file.Endnotes.Relationships.RelationshipCount + 1;
34044
35624
  const documentMediaDatas = this.imageReplacer.getMediaData(documentXmlData, file.Media);
34045
35625
  const commentMediaDatas = this.imageReplacer.getMediaData(commentXmlData, file.Media);
34046
35626
  const footnoteMediaDatas = this.imageReplacer.getMediaData(footnoteXmlData, file.Media);
35627
+ const endnoteMediaDatas = this.imageReplacer.getMediaData(endnoteXmlData, file.Media);
34047
35628
  return _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({
34048
35629
  Relationships: {
34049
35630
  data: (() => {
35631
+ const relationships = Relationships.copy(file.Document.Relationships);
34050
35632
  documentMediaDatas.forEach((mediaData, i) => {
34051
- file.Document.Relationships.addRelationship(documentRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35633
+ relationships.addRelationship(documentRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
34052
35634
  });
34053
- file.Document.Relationships.addRelationship(file.Document.Relationships.RelationshipCount + 1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable", "fontTable.xml");
34054
- return (0, import_xml.default)(this.formatter.format(file.Document.Relationships, {
35635
+ relationships.addRelationship(relationships.RelationshipCount + 1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable", "fontTable.xml");
35636
+ return (0, import_xml.default)(this.formatter.format(relationships, {
34055
35637
  viewWrapper: file.Document,
34056
35638
  file,
34057
35639
  stack: []
@@ -34100,20 +35682,6 @@ var Compiler = class {
34100
35682
  }),
34101
35683
  path: "docProps/core.xml"
34102
35684
  },
34103
- Numbering: {
34104
- data: (0, import_xml.default)(this.formatter.format(file.Numbering, {
34105
- viewWrapper: file.Document,
34106
- file,
34107
- stack: []
34108
- }), {
34109
- indent: prettify,
34110
- declaration: {
34111
- standalone: "yes",
34112
- encoding: "UTF-8"
34113
- }
34114
- }),
34115
- path: "word/numbering.xml"
34116
- },
34117
35685
  FileRelationships: {
34118
35686
  data: (0, import_xml.default)(this.formatter.format(file.FileRelationships, {
34119
35687
  viewWrapper: file.Document,
@@ -34134,11 +35702,13 @@ var Compiler = class {
34134
35702
  indent: prettify,
34135
35703
  declaration: { encoding: "UTF-8" }
34136
35704
  });
34137
- this.imageReplacer.getMediaData(xmlData, file.Media).forEach((mediaData, i) => {
34138
- headerWrapper.Relationships.addRelationship(i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35705
+ const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
35706
+ const relationships = Relationships.copy(headerWrapper.Relationships);
35707
+ mediaDatas.forEach((mediaData, i) => {
35708
+ relationships.addRelationship(i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
34139
35709
  });
34140
35710
  return {
34141
- data: (0, import_xml.default)(this.formatter.format(headerWrapper.Relationships, {
35711
+ data: (0, import_xml.default)(this.formatter.format(relationships, {
34142
35712
  viewWrapper: headerWrapper,
34143
35713
  file,
34144
35714
  stack: []
@@ -34158,11 +35728,13 @@ var Compiler = class {
34158
35728
  indent: prettify,
34159
35729
  declaration: { encoding: "UTF-8" }
34160
35730
  });
34161
- this.imageReplacer.getMediaData(xmlData, file.Media).forEach((mediaData, i) => {
34162
- footerWrapper.Relationships.addRelationship(i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35731
+ const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
35732
+ const relationships = Relationships.copy(footerWrapper.Relationships);
35733
+ mediaDatas.forEach((mediaData, i) => {
35734
+ relationships.addRelationship(i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
34163
35735
  });
34164
35736
  return {
34165
- data: (0, import_xml.default)(this.formatter.format(footerWrapper.Relationships, {
35737
+ data: (0, import_xml.default)(this.formatter.format(relationships, {
34166
35738
  viewWrapper: footerWrapper,
34167
35739
  file,
34168
35740
  stack: []
@@ -34242,10 +35814,11 @@ var Compiler = class {
34242
35814
  },
34243
35815
  FootNotesRelationships: {
34244
35816
  data: (() => {
35817
+ const relationships = Relationships.copy(file.FootNotes.Relationships);
34245
35818
  footnoteMediaDatas.forEach((mediaData, i) => {
34246
- file.FootNotes.Relationships.addRelationship(footnoteRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35819
+ relationships.addRelationship(footnoteRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
34247
35820
  });
34248
- return (0, import_xml.default)(this.formatter.format(file.FootNotes.Relationships, {
35821
+ return (0, import_xml.default)(this.formatter.format(relationships, {
34249
35822
  viewWrapper: file.FootNotes,
34250
35823
  file,
34251
35824
  stack: []
@@ -34257,25 +35830,27 @@ var Compiler = class {
34257
35830
  path: "word/_rels/footnotes.xml.rels"
34258
35831
  },
34259
35832
  Endnotes: {
34260
- data: (0, import_xml.default)(this.formatter.format(file.Endnotes.View, {
34261
- viewWrapper: file.Endnotes,
34262
- file,
34263
- stack: []
34264
- }), {
34265
- indent: prettify,
34266
- declaration: { encoding: "UTF-8" }
34267
- }),
35833
+ data: (() => {
35834
+ const xmlData = this.imageReplacer.replace(endnoteXmlData, endnoteMediaDatas, endnoteRelationshipCount);
35835
+ return this.numberingReplacer.replace(xmlData, file.Numbering.ConcreteNumbering);
35836
+ })(),
34268
35837
  path: "word/endnotes.xml"
34269
35838
  },
34270
35839
  EndnotesRelationships: {
34271
- data: (0, import_xml.default)(this.formatter.format(file.Endnotes.Relationships, {
34272
- viewWrapper: file.Endnotes,
34273
- file,
34274
- stack: []
34275
- }), {
34276
- indent: prettify,
34277
- declaration: { encoding: "UTF-8" }
34278
- }),
35840
+ data: (() => {
35841
+ const relationships = Relationships.copy(file.Endnotes.Relationships);
35842
+ endnoteMediaDatas.forEach((mediaData, i) => {
35843
+ relationships.addRelationship(endnoteRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35844
+ });
35845
+ return (0, import_xml.default)(this.formatter.format(relationships, {
35846
+ viewWrapper: file.Endnotes,
35847
+ file,
35848
+ stack: []
35849
+ }), {
35850
+ indent: prettify,
35851
+ declaration: { encoding: "UTF-8" }
35852
+ });
35853
+ })(),
34279
35854
  path: "word/_rels/endnotes.xml.rels"
34280
35855
  },
34281
35856
  Settings: {
@@ -34302,10 +35877,11 @@ var Compiler = class {
34302
35877
  },
34303
35878
  CommentsRelationships: {
34304
35879
  data: (() => {
35880
+ const relationships = Relationships.copy(file.Comments.Relationships);
34305
35881
  commentMediaDatas.forEach((mediaData, i) => {
34306
- file.Comments.Relationships.addRelationship(commentRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35882
+ relationships.addRelationship(commentRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
34307
35883
  });
34308
- return (0, import_xml.default)(this.formatter.format(file.Comments.Relationships, {
35884
+ return (0, import_xml.default)(this.formatter.format(relationships, {
34309
35885
  viewWrapper: {
34310
35886
  View: file.Comments,
34311
35887
  Relationships: file.Comments.Relationships
@@ -34392,6 +35968,20 @@ var Compiler = class {
34392
35968
  path: "word/theme/theme1.xml"
34393
35969
  },
34394
35970
  PackageParts: xmlifyPackageParts(file, prettify),
35971
+ Numbering: {
35972
+ data: (0, import_xml.default)(this.formatter.format(file.Numbering, {
35973
+ viewWrapper: file.Document,
35974
+ file,
35975
+ stack: []
35976
+ }), {
35977
+ indent: prettify,
35978
+ declaration: {
35979
+ standalone: "yes",
35980
+ encoding: "UTF-8"
35981
+ }
35982
+ }),
35983
+ path: "word/numbering.xml"
35984
+ },
34395
35985
  ContentTypes: {
34396
35986
  data: (0, import_xml.default)(this.formatter.format(file.ContentTypes, {
34397
35987
  viewWrapper: file.Document,
@@ -34407,7 +35997,7 @@ var Compiler = class {
34407
35997
  }
34408
35998
  };
34409
35999
  //#endregion
34410
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/asyncToGenerator.js
36000
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/asyncToGenerator.js
34411
36001
  function asyncGeneratorStep(n, t, e, r, o, a, c) {
34412
36002
  try {
34413
36003
  var i = n[a](c), u = i.value;
@@ -34577,13 +36167,62 @@ var Packer = class Packer {
34577
36167
  };
34578
36168
  _defineProperty(Packer, "compiler", new Compiler());
34579
36169
  //#endregion
36170
+ //#region src/patcher/bookmark-ids.ts
36171
+ var bookmarkIdOf = (element) => {
36172
+ var _element$attributes;
36173
+ if (element.name !== "w:bookmarkStart" && element.name !== "w:bookmarkEnd") return;
36174
+ const id = Number((_element$attributes = element.attributes) === null || _element$attributes === void 0 ? void 0 : _element$attributes["w:id"]);
36175
+ return Number.isInteger(id) ? id : void 0;
36176
+ };
36177
+ /**
36178
+ * Finds the id of every bookmark in an element, at any depth.
36179
+ *
36180
+ * @param element - The element to search, such as a part's root
36181
+ * @returns The ids, once for each bookmarkStart and bookmarkEnd
36182
+ */
36183
+ var findBookmarkIds = (element) => {
36184
+ var _element$elements;
36185
+ const id = bookmarkIdOf(element);
36186
+ return [...id === void 0 ? [] : [id], ...((_element$elements = element.elements) !== null && _element$elements !== void 0 ? _element$elements : []).flatMap(findBookmarkIds)];
36187
+ };
36188
+ /**
36189
+ * Creates a function that renumbers the bookmarks in content being inserted, so none takes an id the document
36190
+ * already uses. Bookmark ids must be unique within a document, but a bookmark's id is chosen when it is created,
36191
+ * without knowing which ids the template has.
36192
+ *
36193
+ * A bookmark keeps its id if nothing in the document uses it yet, and otherwise gets the next unused one. An id is
36194
+ * renumbered the same way each time, so a bookmark's start and end still share one, even in separate patches.
36195
+ *
36196
+ * @param idsInDocument - The ids of the bookmarks already in the document
36197
+ * @returns A function that returns the elements with their bookmarks renumbered
36198
+ */
36199
+ var renumberBookmarksAvoiding = (idsInDocument) => {
36200
+ const usedIds = new Set(idsInDocument);
36201
+ const newIds = /* @__PURE__ */ new Map();
36202
+ let highestId = idsInDocument.reduce((highest, id) => Math.max(highest, id), 0);
36203
+ const newIdFor = (id) => {
36204
+ const knownId = newIds.get(id);
36205
+ if (knownId !== void 0) return knownId;
36206
+ const newId = usedIds.has(id) ? highestId + 1 : id;
36207
+ highestId = Math.max(highestId, newId);
36208
+ usedIds.add(newId);
36209
+ newIds.set(id, newId);
36210
+ return newId;
36211
+ };
36212
+ const renumber = (element) => {
36213
+ const id = bookmarkIdOf(element);
36214
+ return _objectSpread2(_objectSpread2(_objectSpread2({}, element), id === void 0 ? {} : { attributes: _objectSpread2(_objectSpread2({}, element.attributes), {}, { "w:id": String(newIdFor(id)) }) }), element.elements === void 0 ? {} : { elements: element.elements.map(renumber) });
36215
+ };
36216
+ return (elements) => elements.map(renumber);
36217
+ };
36218
+ //#endregion
34580
36219
  //#region src/patcher/util.ts
34581
36220
  /**
34582
36221
  * Utility functions for XML manipulation in document patching.
34583
36222
  *
34584
36223
  * @module
34585
36224
  */
34586
- var formatter$1 = new Formatter();
36225
+ var formatter$2 = new Formatter();
34587
36226
  /**
34588
36227
  * Converts XML string to JSON element structure.
34589
36228
  *
@@ -34623,7 +36262,7 @@ var toJson = (xmlData) => {
34623
36262
  */
34624
36263
  var createTextElementContents = (text) => {
34625
36264
  var _textJson$elements$0$;
34626
- return (_textJson$elements$0$ = toJson((0, import_xml.default)(formatter$1.format(new Text({ text })))).elements[0].elements) !== null && _textJson$elements$0$ !== void 0 ? _textJson$elements$0$ : [];
36265
+ return (_textJson$elements$0$ = toJson((0, import_xml.default)(formatter$2.format(new Text({ text })))).elements[0].elements) !== null && _textJson$elements$0$ !== void 0 ? _textJson$elements$0$ : [];
34627
36266
  };
34628
36267
  /**
34629
36268
  * Adds xml:space="preserve" attribute to an element.
@@ -34758,6 +36397,11 @@ var PatchType = {
34758
36397
  /** Replace content within paragraphs (inline replacement) */
34759
36398
  PARAGRAPH: "paragraph",
34760
36399
  /**
36400
+ * Repeat the rows of a table that hold the placeholder's fields, such as `{{items.name}}`, once for each row of
36401
+ * data. See {@link TableRowsPatch}
36402
+ */
36403
+ TABLE_ROWS: "tableRows",
36404
+ /**
34761
36405
  * Change a drawing whose alt text holds the placeholder, and the parts it refers to, such as the data of a chart made
34762
36406
  * in Word. See {@link DrawingPatch}
34763
36407
  */
@@ -35071,6 +36715,291 @@ var patchDrawings = ({ parts, binaryParts, file, patches, delimiters }, createCo
35071
36715
  for (const { drawing, patch } of found) patch.patch(drawing, createTemplatePackage(parts, binaryParts, file, createContext(drawing.part.path)));
35072
36716
  };
35073
36717
  //#endregion
36718
+ //#region src/patcher/notes.ts
36719
+ /**
36720
+ * Footnotes and endnotes for content inserted into an existing document.
36721
+ *
36722
+ * @module
36723
+ */
36724
+ var formatter$1 = new Formatter();
36725
+ var DOCUMENT_PATH = "word/document.xml";
36726
+ var FOOTNOTES = {
36727
+ path: "word/footnotes.xml",
36728
+ rootName: "w:footnotes",
36729
+ noteName: "w:footnote",
36730
+ referenceName: "w:footnoteReference",
36731
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml",
36732
+ relationshipType: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",
36733
+ create: {
36734
+ part: () => new FootNotes(),
36735
+ mark: () => new FootnoteRefRun(),
36736
+ styles: () => [
36737
+ new FootnoteText({}),
36738
+ new FootnoteTextChar({}),
36739
+ new FootnoteReferenceStyle({})
36740
+ ]
36741
+ }
36742
+ };
36743
+ var ENDNOTES = {
36744
+ path: "word/endnotes.xml",
36745
+ rootName: "w:endnotes",
36746
+ noteName: "w:endnote",
36747
+ referenceName: "w:endnoteReference",
36748
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml",
36749
+ relationshipType: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes",
36750
+ create: {
36751
+ part: () => new Endnotes(),
36752
+ mark: () => new EndnoteRefRun(),
36753
+ styles: () => [
36754
+ new EndnoteText({}),
36755
+ new EndnoteTextChar({}),
36756
+ new EndnoteReferenceStyle({})
36757
+ ]
36758
+ }
36759
+ };
36760
+ var formatElement = (component, context) => toJson((0, import_xml.default)(formatter$1.format(component, context))).elements[0];
36761
+ var findIds = (element, names) => {
36762
+ var _element$name, _element$attributes, _element$elements;
36763
+ const id = names.includes((_element$name = element.name) !== null && _element$name !== void 0 ? _element$name : "") ? Number((_element$attributes = element.attributes) === null || _element$attributes === void 0 ? void 0 : _element$attributes["w:id"]) : NaN;
36764
+ return [...Number.isInteger(id) ? [id] : [], ...((_element$elements = element.elements) !== null && _element$elements !== void 0 ? _element$elements : []).flatMap((child) => findIds(child, names))];
36765
+ };
36766
+ var withMark = (paragraph, mark) => {
36767
+ var _paragraph$elements, _elements$;
36768
+ const elements = (_paragraph$elements = paragraph.elements) !== null && _paragraph$elements !== void 0 ? _paragraph$elements : [];
36769
+ const index = ((_elements$ = elements[0]) === null || _elements$ === void 0 ? void 0 : _elements$.name) === "w:pPr" ? 1 : 0;
36770
+ return _objectSpread2(_objectSpread2({}, paragraph), {}, { elements: [
36771
+ ...elements.slice(0, index),
36772
+ mark,
36773
+ ...elements.slice(index)
36774
+ ] });
36775
+ };
36776
+ var patchNotesOfKind = (kind, notes, parts, { createContext, addContentTypeOverride, renumberBookmarks }) => {
36777
+ const givenNotes = new Map(Object.entries(notes).map(([id, note]) => [Number(id), note]));
36778
+ const noteOfId = /* @__PURE__ */ new Map();
36779
+ let highestId;
36780
+ const renumber = (element) => {
36781
+ var _element$attributes2, _highestId;
36782
+ const note = element.name === kind.referenceName ? givenNotes.get(Number((_element$attributes2 = element.attributes) === null || _element$attributes2 === void 0 ? void 0 : _element$attributes2["w:id"])) : void 0;
36783
+ if (note === void 0) return element.elements === void 0 ? element : _objectSpread2(_objectSpread2({}, element), {}, { elements: element.elements.map(renumber) });
36784
+ highestId = ((_highestId = highestId) !== null && _highestId !== void 0 ? _highestId : [...parts.values()].flatMap((part) => findIds(part, [kind.noteName, kind.referenceName])).reduce((highest, id) => Math.max(highest, id), 0)) + 1;
36785
+ noteOfId.set(highestId, note);
36786
+ return _objectSpread2(_objectSpread2({}, element), {}, { attributes: _objectSpread2(_objectSpread2({}, element.attributes), {}, { "w:id": String(highestId) }) });
36787
+ };
36788
+ const findOrAddPart = () => {
36789
+ var _parts$get;
36790
+ const relationship = getFirstLevelElements((_parts$get = parts.get(relationshipsPathOf(DOCUMENT_PATH))) !== null && _parts$get !== void 0 ? _parts$get : {}, "Relationships").find((element) => {
36791
+ var _element$attributes3;
36792
+ return ((_element$attributes3 = element.attributes) === null || _element$attributes3 === void 0 ? void 0 : _element$attributes3.Type) === kind.relationshipType;
36793
+ });
36794
+ const path = relationship ? resolveTarget(DOCUMENT_PATH, String(relationship.attributes.Target)) : kind.path;
36795
+ if (!parts.has(path)) {
36796
+ parts.set(path, {
36797
+ declaration: { attributes: {
36798
+ version: "1.0",
36799
+ encoding: "UTF-8",
36800
+ standalone: "yes"
36801
+ } },
36802
+ elements: [formatElement(kind.create.part(), createContext(path))]
36803
+ });
36804
+ addContentTypeOverride(kind.contentType, `/${path}`);
36805
+ }
36806
+ if (!relationship) createContext(DOCUMENT_PATH).viewWrapper.Relationships.addRelationship(uniqueId(), kind.relationshipType, relativeTarget(DOCUMENT_PATH, path));
36807
+ return path;
36808
+ };
36809
+ const write = () => {
36810
+ if (noteOfId.size === 0) return;
36811
+ const path = findOrAddPart();
36812
+ const context = createContext(path);
36813
+ const contentOfNote = new Map([...new Set(noteOfId.values())].map((note) => {
36814
+ const mark = formatElement(kind.create.mark(), context);
36815
+ return [note, renumberBookmarks(note.children.map((paragraph) => formatElement(paragraph, context)).map((paragraph, index) => index === 0 ? withMark(paragraph, mark) : paragraph))];
36816
+ }));
36817
+ getFirstLevelElements(parts.get(path), kind.rootName).push(...[...noteOfId].map(([id, note]) => ({
36818
+ type: "element",
36819
+ name: kind.noteName,
36820
+ attributes: { "w:id": String(id) },
36821
+ elements: [...contentOfNote.get(note)]
36822
+ })));
36823
+ const stylesPart = parts.get("word/styles.xml");
36824
+ if (stylesPart) {
36825
+ const styles = getFirstLevelElements(stylesPart, "w:styles");
36826
+ const styleIds = new Set(styles.map((style) => {
36827
+ var _style$attributes;
36828
+ return (_style$attributes = style.attributes) === null || _style$attributes === void 0 ? void 0 : _style$attributes["w:styleId"];
36829
+ }));
36830
+ styles.push(...kind.create.styles().map((style) => formatElement(style, context)).filter((style) => {
36831
+ var _style$attributes2;
36832
+ return !styleIds.has((_style$attributes2 = style.attributes) === null || _style$attributes2 === void 0 ? void 0 : _style$attributes2["w:styleId"]);
36833
+ }));
36834
+ }
36835
+ };
36836
+ return {
36837
+ renumber: (elements) => elements.map(renumber),
36838
+ write
36839
+ };
36840
+ };
36841
+ /**
36842
+ * Creates the writer of the footnotes and endnotes that patches refer to.
36843
+ *
36844
+ * A patch refers to a note with a reference run, such as `new FootnoteReferenceRun(1)`, whose id is the note's in
36845
+ * `footnotes`. Only references to the given notes are renumbered, and only the notes that are referred to are written.
36846
+ *
36847
+ * @param notes - The footnotes and endnotes, by the id the patches' reference runs are given
36848
+ * @param parts - The document's XML parts, parsed, by their paths, which the notes are written to
36849
+ * @param helpers - The patcher's helpers for what the notes refer to
36850
+ */
36851
+ var patchNotes = ({ footnotes = {}, endnotes = {} }, parts, helpers) => {
36852
+ const patchers = [patchNotesOfKind(FOOTNOTES, footnotes, parts, helpers), patchNotesOfKind(ENDNOTES, endnotes, parts, helpers)];
36853
+ return {
36854
+ renumber: (elements) => patchers.reduce((renumbered, patcher) => patcher.renumber(renumbered), elements),
36855
+ write: () => {
36856
+ for (const patcher of patchers) patcher.write();
36857
+ }
36858
+ };
36859
+ };
36860
+ //#endregion
36861
+ //#region src/patcher/page-numbers.ts
36862
+ /**
36863
+ * Page numbers written into a template's fields once `patchDocument` has patched it, from an estimate of its pages, as
36864
+ * a document's are when it is written with `pageNumbers`.
36865
+ *
36866
+ * @module
36867
+ */
36868
+ /** The elements of a template, as xml-js parses them */
36869
+ var PARSED = {
36870
+ nameOf: (element) => element.type === "element" ? element.name : void 0,
36871
+ contentOf: (element) => element.elements,
36872
+ attributeOf: (element, attribute) => {
36873
+ var _element$attributes;
36874
+ return (_element$attributes = element.attributes) === null || _element$attributes === void 0 ? void 0 : _element$attributes[attribute];
36875
+ },
36876
+ textOf: (element) => {
36877
+ var _element$elements;
36878
+ return ((_element$elements = element.elements) !== null && _element$elements !== void 0 ? _element$elements : []).filter(({ type }) => type === "text").map(({ text }) => String(text)).join("");
36879
+ },
36880
+ textElement: (text) => ({
36881
+ type: "element",
36882
+ name: "w:t",
36883
+ attributes: { "xml:space": "preserve" },
36884
+ elements: [{
36885
+ type: "text",
36886
+ text
36887
+ }]
36888
+ }),
36889
+ writeClean: (begin, instruction) => {
36890
+ var _begin$attributes;
36891
+ if (/^\s*(PAGEREF|TOC)\b/i.test(instruction) && ((_begin$attributes = begin.attributes) === null || _begin$attributes === void 0 ? void 0 : _begin$attributes["w:dirty"]) !== void 0) begin.attributes = Object.fromEntries(Object.entries(begin.attributes).filter(([key]) => key !== "w:dirty"));
36892
+ },
36893
+ setSimpleFieldResult: (element, text) => {
36894
+ element.elements = [{
36895
+ type: "element",
36896
+ name: "w:r",
36897
+ elements: [PARSED.textElement(text)]
36898
+ }];
36899
+ }
36900
+ };
36901
+ var DOCUMENT = "word/document.xml";
36902
+ var IMPORT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk";
36903
+ var ZIP = [
36904
+ 80,
36905
+ 75,
36906
+ 3,
36907
+ 4
36908
+ ];
36909
+ /** A package's parts, from a zip file: its XML parts parsed, as patchDocument parses a template's, and the rest as bytes */
36910
+ var readPackage = function() {
36911
+ var _ref = _asyncToGenerator(function* (data) {
36912
+ if (!ZIP.every((byte, index) => data[index] === byte)) return;
36913
+ try {
36914
+ const zip = yield import_jszip_min.default.loadAsync(data);
36915
+ const parts = /* @__PURE__ */ new Map();
36916
+ const binaryParts = /* @__PURE__ */ new Map();
36917
+ for (const [path, file] of Object.entries(zip.files)) {
36918
+ if (file.dir) continue;
36919
+ if (/\.(xml|rels)$/.test(path)) parts.set(path, toJson(yield file.async("text")));
36920
+ else binaryParts.set(path, yield file.async("uint8array"));
36921
+ }
36922
+ const importedDocuments = yield readImportedDocuments(parts, binaryParts);
36923
+ return _objectSpread2({
36924
+ parts,
36925
+ binaryParts
36926
+ }, importedDocuments.size > 0 ? { importedDocuments } : {});
36927
+ } catch (_unused) {
36928
+ return;
36929
+ }
36930
+ });
36931
+ return function readPackage(_x) {
36932
+ return _ref.apply(this, arguments);
36933
+ };
36934
+ }();
36935
+ /**
36936
+ * Each .docx the parts of a package import (`w:altChunk`), by its path: the parts the relationships of each part refer to
36937
+ * as imported, which are zip files that can be read. Those in other formats, such as HTML, are left to the layout.
36938
+ */
36939
+ var readImportedDocuments = function() {
36940
+ var _ref2 = _asyncToGenerator(function* (parts, binaryParts) {
36941
+ const imported = /* @__PURE__ */ new Map();
36942
+ for (const [path, relationships] of parts) {
36943
+ var _rootOf$elements, _rootOf;
36944
+ if (!path.endsWith(".rels")) continue;
36945
+ for (const { attributes = {} } of (_rootOf$elements = (_rootOf = rootOf(relationships)) === null || _rootOf === void 0 ? void 0 : _rootOf.elements) !== null && _rootOf$elements !== void 0 ? _rootOf$elements : []) {
36946
+ const target = resolveTarget(sourceOfRelationships(path), String(attributes.Target));
36947
+ const data = binaryParts.get(target);
36948
+ const read = attributes.Type === IMPORT && attributes.TargetMode !== "External" && data ? yield readPackage(data) : void 0;
36949
+ if (read) imported.set(target, read);
36950
+ }
36951
+ }
36952
+ return imported;
36953
+ });
36954
+ return function readImportedDocuments(_x2, _x3) {
36955
+ return _ref2.apply(this, arguments);
36956
+ };
36957
+ }();
36958
+ /** The root element of a part, such as `w:document` */
36959
+ var rootOf = (part) => {
36960
+ var _part$elements;
36961
+ return part === null || part === void 0 || (_part$elements = part.elements) === null || _part$elements === void 0 ? void 0 : _part$elements.find(({ type }) => type === "element");
36962
+ };
36963
+ /**
36964
+ * Writes the page numbers the estimator works out for a patched template into the fields of its body, headers and
36965
+ * footers that show them: its PAGEREF fields, in its tables of contents and elsewhere, and its NUMPAGES and SECTIONPAGES
36966
+ * fields. The results a field was written with are those of the template before it was patched, so a field whose number
36967
+ * the estimator doesn't work out is left blank, as it is in a document written with `pageNumbers`. Page references and
36968
+ * tables of contents are written clean, as they are in a document written with `pageNumbers`, so Word shows their numbers
36969
+ * as they are and doesn't ask to update the fields.
36970
+ *
36971
+ * The documents it imports (`w:altChunk`) as .docx files are unzipped for the estimator to read, as Word turns them into
36972
+ * paragraphs and tables of the template's own when it opens it.
36973
+ *
36974
+ * @param parts - The template's XML parts, parsed, by their paths, which are changed in place
36975
+ * @param binaryParts - Its other parts, by their paths, for the estimator to read the fonts it embeds and the documents
36976
+ * it imports
36977
+ */
36978
+ var fillTemplatePageNumbers = function() {
36979
+ var _ref3 = _asyncToGenerator(function* (parts, estimator, binaryParts = /* @__PURE__ */ new Map()) {
36980
+ var _rootOf$elements2, _rootOf2;
36981
+ const document = rootOf(parts.get(DOCUMENT));
36982
+ if (!document) return;
36983
+ const importedDocuments = yield readImportedDocuments(parts, binaryParts);
36984
+ const estimate = estimator(_objectSpread2({
36985
+ parts,
36986
+ binaryParts
36987
+ }, importedDocuments.size > 0 ? { importedDocuments } : {}));
36988
+ const partPageCounts = fillBodyFields(PARSED, document, estimate, { blank: true });
36989
+ const relationships = (_rootOf$elements2 = (_rootOf2 = rootOf(parts.get(relationshipsPathOf(DOCUMENT)))) === null || _rootOf2 === void 0 ? void 0 : _rootOf2.elements) !== null && _rootOf$elements2 !== void 0 ? _rootOf$elements2 : [];
36990
+ for (const { attributes = {} } of relationships) {
36991
+ const part = /\/(header|footer)$/.test(String(attributes.Type)) ? rootOf(parts.get(resolveTarget(DOCUMENT, String(attributes.Target)))) : void 0;
36992
+ if (part) fillPartFields(PARSED, part, estimate, {
36993
+ blank: true,
36994
+ sectionPageCount: partPageCounts.get(String(attributes.Id))
36995
+ });
36996
+ }
36997
+ });
36998
+ return function fillTemplatePageNumbers(_x4, _x5) {
36999
+ return _ref3.apply(this, arguments);
37000
+ };
37001
+ }();
37002
+ //#endregion
35074
37003
  //#region src/patcher/paragraph-split-inject.ts
35075
37004
  var TokenNotFoundError = class extends Error {
35076
37005
  constructor(token) {
@@ -35372,9 +37301,11 @@ var SPLIT_TOKEN = "
35372
37301
  * @param context - The document context for formatting
35373
37302
  * @param keepOriginalStyles - Whether to preserve original text formatting
35374
37303
  * @param recursive - Whether to replace every occurrence in a paragraph, rather than only the first
37304
+ * @param renumberIds - Renumbers the bookmarks and note references the patch inserts, so they don't take an id the
37305
+ * document uses
35375
37306
  * @returns Result containing the modified element and whether a replacement occurred
35376
37307
  */
35377
- var replacer = ({ json, patch, patchText, context, keepOriginalStyles = true, recursive = true }) => {
37308
+ var replacer = ({ json, patch, patchText, context, keepOriginalStyles = true, recursive = true, renumberIds = (elements) => elements }) => {
35378
37309
  const renderedParagraphs = findLocationOfText(json, patchText);
35379
37310
  if (renderedParagraphs.length === 0) return {
35380
37311
  element: json,
@@ -35384,9 +37315,15 @@ var replacer = ({ json, patch, patchText, context, keepOriginalStyles = true, re
35384
37315
  const paragraphsToPatch = patch.type === PatchType.DOCUMENT ? withoutNestedParagraphs(paragraphsInPatchOrder) : paragraphsInPatchOrder;
35385
37316
  for (const renderedParagraph of paragraphsToPatch) switch (patch.type) {
35386
37317
  case PatchType.DOCUMENT: {
37318
+ var _children;
35387
37319
  const parentElement = goToParentElementFromPath(json, renderedParagraph.pathToParagraph);
35388
37320
  const elementIndex = getLastElementIndexFromPath(renderedParagraph.pathToParagraph);
35389
- parentElement.elements.splice(elementIndex, 1, ...formatChildren(patch, context));
37321
+ const children = formatChildren(patch, context, renumberIds);
37322
+ const endParagraph = parentElement.name === "w:tc" && elementIndex === parentElement.elements.length - 1 && ((_children = children[children.length - 1]) === null || _children === void 0 ? void 0 : _children.name) !== "w:p" ? [{
37323
+ type: "element",
37324
+ name: "w:p"
37325
+ }] : [];
37326
+ parentElement.elements.splice(elementIndex, 1, ...children, ...endParagraph);
35390
37327
  break;
35391
37328
  }
35392
37329
  case PatchType.PARAGRAPH:
@@ -35400,7 +37337,7 @@ var replacer = ({ json, patch, patchText, context, keepOriginalStyles = true, re
35400
37337
  renderedParagraph: paragraph,
35401
37338
  patchText,
35402
37339
  fromIndex,
35403
- children: formatChildren(patch, context),
37340
+ children: formatChildren(patch, context, renumberIds),
35404
37341
  keepOriginalStyles
35405
37342
  });
35406
37343
  paragraph = renderParagraphNode({
@@ -35418,10 +37355,10 @@ var replacer = ({ json, patch, patchText, context, keepOriginalStyles = true, re
35418
37355
  didFindOccurrence: true
35419
37356
  };
35420
37357
  };
35421
- var formatChildren = (patch, context) => patch.children.flatMap((c) => {
37358
+ var formatChildren = (patch, context, renumberIds) => renumberIds(patch.children.flatMap((c) => {
35422
37359
  var _c$writtenAs;
35423
37360
  return (_c$writtenAs = c.writtenAs) !== null && _c$writtenAs !== void 0 ? _c$writtenAs : c;
35424
- }).map((c) => toJson((0, import_xml.default)(formatter.format(c, context)))).map((c) => c.elements[0]);
37361
+ }).map((c) => toJson((0, import_xml.default)(formatter.format(c, context)))).map((c) => c.elements[0]));
35425
37362
  /**
35426
37363
  * Replaces the first occurrence of the placeholder from `fromIndex` on, splitting the run it starts in.
35427
37364
  *
@@ -35439,12 +37376,21 @@ var replaceOccurrenceInParagraph = ({ paragraphElement, renderedParagraph, patch
35439
37376
  const runElementToBeReplaced = paragraphElement.elements[index];
35440
37377
  const { left, right } = splitRunElement(runElementToBeReplaced, SPLIT_TOKEN);
35441
37378
  const runProperties = runElementToBeReplaced.elements.find((e) => e.type === "element" && e.name === "w:rPr");
35442
- const newRunElements = keepOriginalStyles && runProperties ? children.map((e) => e.name === "w:r" ? withRunProperties(e, runProperties) : e) : children;
37379
+ const newRunElements = keepOriginalStyles && runProperties ? children.map((e) => withRunPropertiesOnRuns(e, runProperties)) : children;
35443
37380
  const patchedRightElement = runProperties ? _objectSpread2(_objectSpread2({}, right), {}, { elements: [runProperties, ...right.elements] }) : right;
35444
37381
  paragraphElement.elements.splice(index, 1, left, ...newRunElements, patchedRightElement);
35445
37382
  return index + 1 + newRunElements.length;
35446
37383
  };
35447
37384
  /**
37385
+ * Gives the runs of inserted content the placeholder's run properties. Content such as a hyperlink can't take run
37386
+ * properties itself, so its runs take them, and its text is formatted as the text around it is. Runs inside a run, such
37387
+ * as in its text box, are that content's own, and are left alone.
37388
+ */
37389
+ var withRunPropertiesOnRuns = (element, originalRunProperties) => {
37390
+ if (element.name === "w:r") return withRunProperties(element, originalRunProperties);
37391
+ return element.elements ? _objectSpread2(_objectSpread2({}, element), {}, { elements: element.elements.map((e) => withRunPropertiesOnRuns(e, originalRunProperties)) }) : element;
37392
+ };
37393
+ /**
35448
37394
  * Gives a run the placeholder's run properties. A run can only have one w:rPr, so properties the run
35449
37395
  * sets itself are kept, and the placeholder's fill in the rest.
35450
37396
  */
@@ -35536,6 +37482,118 @@ var goToElementFromPath = (json, path) => {
35536
37482
  var goToParentElementFromPath = (json, path) => goToElementFromPath(json, path.slice(0, path.length - 1));
35537
37483
  var getLastElementIndexFromPath = (path) => path[path.length - 1];
35538
37484
  //#endregion
37485
+ //#region src/patcher/table-rows.ts
37486
+ var EMPTY = {
37487
+ type: PatchType.PARAGRAPH,
37488
+ children: []
37489
+ };
37490
+ /**
37491
+ * Repeats the rows of the tables in an element that hold the patch's fields, such as `{{items.name}}` for the key
37492
+ * "items", once for each of the patch's rows, and patches the fields in each copy with the row's patches.
37493
+ *
37494
+ * @param json - The element to patch, such as a part's root
37495
+ * @param key - The patch's key, such as "items"
37496
+ * @param patch - The rows of data
37497
+ * @param delimiters - The placeholders' delimiters
37498
+ * @param patchPlaceholder - Patches a field in a copy of the rows, as `patchDocument` patches a placeholder
37499
+ */
37500
+ var patchTableRows = ({ json, key, patch, delimiters: { start, end }, patchPlaceholder }) => {
37501
+ const fieldStart = `${start}${key}.`;
37502
+ for (const rows of findRowsToRepeat(json, fieldStart)) {
37503
+ const fields = fieldsIn(rows.elements, fieldStart, end);
37504
+ const copies = patch.rows.flatMap((row, index) => {
37505
+ const copy = {
37506
+ type: "element",
37507
+ name: "w:tbl",
37508
+ elements: [...index === 0 ? rows.elements.map(copyOf) : withoutIds(rows.elements)]
37509
+ };
37510
+ const fieldPatches = new Map(Object.entries(row).flatMap(([field, p]) => p === void 0 ? [] : [[field, p]]));
37511
+ for (const [field, fieldPatch] of fieldPatches) patchPlaceholder(copy, `${key}.${field}`, fieldPatch);
37512
+ for (const field of fields.filter((f) => !fieldPatches.has(f))) patchPlaceholder(copy, `${key}.${field}`, EMPTY);
37513
+ return copy.elements;
37514
+ });
37515
+ rows.parent.elements.splice(rows.parent.elements.indexOf(rows.elements[0]), rows.elements.length, ...copies);
37516
+ if (rows.table && !hasRows(rows.table.element)) rows.table.parent.elements.splice(rows.table.parent.elements.indexOf(rows.table.element), 1);
37517
+ }
37518
+ };
37519
+ /**
37520
+ * The rows that hold a field, grouped into the rows next to each other in a table, which are repeated together.
37521
+ */
37522
+ var findRowsToRepeat = (json, fieldStart) => {
37523
+ const found = findLocationOfText(json, fieldStart).flatMap((paragraph) => {
37524
+ const row = rowHolding(json, paragraph.pathToParagraph);
37525
+ return row ? [row] : [];
37526
+ });
37527
+ const rows = found.filter((row) => !found.some((other) => isInside(row.path, other.path))).filter((row, index, all) => all.findIndex((other) => other.row === row.row) === index);
37528
+ return [...new Set(rows.map((row) => row.parent))].flatMap((parent) => {
37529
+ const siblingRows = parent.elements.filter((e) => e.name === "w:tr");
37530
+ const positions = rows.filter((row) => row.parent === parent).map((row) => siblingRows.indexOf(row.row)).sort((a, b) => a - b);
37531
+ const { table } = rows.find((row) => row.parent === parent);
37532
+ return positions.reduce((all, position) => {
37533
+ const previous = all[all.length - 1];
37534
+ return (previous === null || previous === void 0 ? void 0 : previous[previous.length - 1]) === position - 1 ? [...all.slice(0, -1), [...previous, position]] : [...all, [position]];
37535
+ }, []).map((group) => {
37536
+ const first = parent.elements.indexOf(siblingRows[group[0]]);
37537
+ const last = parent.elements.indexOf(siblingRows[group[group.length - 1]]);
37538
+ return {
37539
+ parent,
37540
+ table,
37541
+ elements: parent.elements.slice(first, last + 1)
37542
+ };
37543
+ });
37544
+ });
37545
+ };
37546
+ /**
37547
+ * The row nearest to the paragraph at the end of the path that holds it, if it is in a table.
37548
+ */
37549
+ var rowHolding = (json, pathToParagraph) => {
37550
+ let element = json;
37551
+ let row;
37552
+ let table;
37553
+ for (let i = 1; i < pathToParagraph.length; i++) {
37554
+ const child = element.elements[pathToParagraph[i]];
37555
+ if (child.name === "w:tbl") table = {
37556
+ element: child,
37557
+ parent: element
37558
+ };
37559
+ if (child.name === "w:tr") row = {
37560
+ parent: element,
37561
+ table,
37562
+ row: child,
37563
+ path: pathToParagraph.slice(0, i + 1)
37564
+ };
37565
+ element = child;
37566
+ }
37567
+ return row;
37568
+ };
37569
+ var isInside = (path, ancestorPath) => path.length > ancestorPath.length && ancestorPath.every((index, i) => path[i] === index);
37570
+ var hasRows = (table) => {
37571
+ var _table$elements;
37572
+ return ((_table$elements = table.elements) !== null && _table$elements !== void 0 ? _table$elements : []).some((e) => e.name === "w:tr" || e.name !== "w:tblPr" && e.name !== "w:tblGrid" && hasRows(e));
37573
+ };
37574
+ /**
37575
+ * The names of the fields in the elements, such as "name" for `{{items.name}}`.
37576
+ */
37577
+ var fieldsIn = (elements, fieldStart, end) => {
37578
+ const fields = findLocationOfText({ elements: [...elements] }, fieldStart).flatMap(({ text }) => text.split(fieldStart).slice(1).flatMap((after) => {
37579
+ const fieldEnd = after.indexOf(end);
37580
+ return fieldEnd > 0 ? [after.slice(0, fieldEnd)] : [];
37581
+ }));
37582
+ return [...new Set(fields)];
37583
+ };
37584
+ var copyOf = (element) => JSON.parse(JSON.stringify(element));
37585
+ var ATTRIBUTES_TO_REMOVE = ["w14:paraId", "w14:textId"];
37586
+ var ELEMENTS_TO_REMOVE = ["w:bookmarkStart", "w:bookmarkEnd"];
37587
+ /**
37588
+ * A copy of elements without what must be unique in a document, so they can be in the document more than once.
37589
+ *
37590
+ * @param parent - The elements' parent, as a content control's id is an element in its properties
37591
+ */
37592
+ var withoutIds = (elements, parent) => elements.filter((e) => {
37593
+ var _e$name;
37594
+ return !ELEMENTS_TO_REMOVE.includes((_e$name = e.name) !== null && _e$name !== void 0 ? _e$name : "") && !((parent === null || parent === void 0 ? void 0 : parent.name) === "w:sdtPr" && e.name === "w:id");
37595
+ }).map((e) => _objectSpread2(_objectSpread2(_objectSpread2({}, e), e.attributes === void 0 ? {} : { attributes: Object.fromEntries(Object.entries(e.attributes).filter(([name]) => !ATTRIBUTES_TO_REMOVE.includes(name))) }), e.elements === void 0 ? {} : { elements: [...withoutIds(e.elements, e)] }));
37596
+ //#endregion
35539
37597
  //#region src/patcher/theme-colors.ts
35540
37598
  var THEME_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
35541
37599
  var COLOR_NAMES = /* @__PURE__ */ new Map([
@@ -35594,7 +37652,7 @@ var readTheme = function() {
35594
37652
  return ((_item$attributes3 = item.attributes) === null || _item$attributes3 === void 0 ? void 0 : _item$attributes3.Type) === THEME_RELATIONSHIP_TYPE;
35595
37653
  });
35596
37654
  const target = theme === null || theme === void 0 || (_theme$attributes = theme.attributes) === null || _theme$attributes === void 0 ? void 0 : _theme$attributes.Target;
35597
- return typeof target === "string" ? readPart(zip, target.startsWith("/") ? target.slice(1) : `word/${target}`) : void 0;
37655
+ return typeof target === "string" ? readPart(zip, resolveTarget("word/document.xml", target)) : void 0;
35598
37656
  });
35599
37657
  return function readTheme(_x3) {
35600
37658
  return _ref2.apply(this, arguments);
@@ -35633,6 +37691,23 @@ var readThemeColors = function() {
35633
37691
  *
35634
37692
  * @module
35635
37693
  */
37694
+ /**
37695
+ * Throws if a patch, or a patch for a field of one of its rows, isn't one `patchDocument` can apply, such as a patch
37696
+ * from JavaScript without its children.
37697
+ *
37698
+ * @param key - The patch's key, such as "items", or for a field of a row, such as "items.name"
37699
+ * @param inTableRow - Whether the patch is for a field of a row, where a drawing patch can't be
37700
+ */
37701
+ var assertValidPatch = (key, patch, { inTableRow }) => {
37702
+ if ((patch === null || patch === void 0 ? void 0 : patch.type) === PatchType.TABLE_ROWS && Array.isArray(patch.rows)) {
37703
+ for (const row of patch.rows) {
37704
+ if (typeof row !== "object" || row === null) throw new Error(`Invalid patch "${key}". Expected each of its rows to be an object of patches, by the name of their field`);
37705
+ for (const [field, fieldPatch] of Object.entries(row)) if (fieldPatch !== void 0) assertValidPatch(`${key}.${field}`, fieldPatch, { inTableRow: true });
37706
+ }
37707
+ return;
37708
+ }
37709
+ if (!((patch === null || patch === void 0 ? void 0 : patch.type) === PatchType.DRAWING ? !inTableRow && typeof patch.patch === "function" : (patch === null || patch === void 0 ? void 0 : patch.type) !== PatchType.TABLE_ROWS && Array.isArray(patch === null || patch === void 0 ? void 0 : patch.children))) throw new Error(`Invalid patch "${key}". Expected { type: PatchType.PARAGRAPH or PatchType.DOCUMENT, children: [...] }, ${inTableRow ? "or { type: PatchType.TABLE_ROWS, rows: [...] }" : "{ type: PatchType.TABLE_ROWS, rows: [...] }, or a drawing patch such as ChartDataPatch from docx/charts"}`);
37710
+ };
35636
37711
  var imageReplacer = new ImageReplacer();
35637
37712
  var UTF16LE = new Uint8Array([255, 254]);
35638
37713
  var UTF16BE = new Uint8Array([254, 255]);
@@ -35680,7 +37755,7 @@ var patchDocument = function() {
35680
37755
  var _ref = _asyncToGenerator(function* ({ outputType, data, patches, keepOriginalStyles, placeholderDelimiters = {
35681
37756
  start: "{{",
35682
37757
  end: "}}"
35683
- }, recursive = true }) {
37758
+ }, recursive = true, footnotes, endnotes, pageNumbers }) {
35684
37759
  const zipContent = data instanceof import_jszip_min.default ? data : yield import_jszip_min.default.loadAsync(data);
35685
37760
  const contexts = /* @__PURE__ */ new Map();
35686
37761
  const themeColors = yield readThemeColors(zipContent);
@@ -35700,7 +37775,7 @@ var patchDocument = function() {
35700
37775
  const binaryContentMap = /* @__PURE__ */ new Map();
35701
37776
  if (!(placeholderDelimiters === null || placeholderDelimiters === void 0 ? void 0 : placeholderDelimiters.start.trim()) || !(placeholderDelimiters === null || placeholderDelimiters === void 0 ? void 0 : placeholderDelimiters.end.trim())) throw new Error("Both start and end delimiters must be non-empty strings.");
35702
37777
  const { start, end } = placeholderDelimiters;
35703
- for (const [key, patch] of Object.entries(patches)) if (!((patch === null || patch === void 0 ? void 0 : patch.type) === PatchType.DRAWING ? typeof patch.patch === "function" : Array.isArray(patch === null || patch === void 0 ? void 0 : patch.children))) throw new Error(`Invalid patch "${key}". Expected { type: PatchType.PARAGRAPH or PatchType.DOCUMENT, children: [...] }, or a drawing patch such as ChartDataPatch from docx/charts`);
37778
+ for (const [key, patch] of Object.entries(patches)) assertValidPatch(key, patch, { inTableRow: false });
35704
37779
  for (const [key, value] of Object.entries(zipContent.files)) {
35705
37780
  const binaryValue = yield value.async("uint8array");
35706
37781
  const startBytes = binaryValue.slice(0, 2);
@@ -35729,6 +37804,7 @@ var patchDocument = function() {
35729
37804
  }
35730
37805
  map.set(key, json);
35731
37806
  }
37807
+ const renumberBookmarks = renumberBookmarksAvoiding([...map.values()].flatMap(findBookmarkIds));
35732
37808
  const createContext = (key) => ({
35733
37809
  file,
35734
37810
  viewWrapper: { Relationships: { addRelationship: (id, type, target, targetMode) => {
@@ -35742,6 +37818,17 @@ var patchDocument = function() {
35742
37818
  } } },
35743
37819
  stack: []
35744
37820
  });
37821
+ const notes = patchNotes({
37822
+ footnotes,
37823
+ endnotes
37824
+ }, map, {
37825
+ createContext,
37826
+ addContentTypeOverride: (contentType, partName) => contentTypeOverrides.push({
37827
+ contentType,
37828
+ partName
37829
+ }),
37830
+ renumberBookmarks
37831
+ });
35745
37832
  patchDrawings({
35746
37833
  parts: map,
35747
37834
  binaryParts: binaryContentMap,
@@ -35752,35 +37839,57 @@ var patchDocument = function() {
35752
37839
  end
35753
37840
  }
35754
37841
  }, createContext);
37842
+ const textPatches = Object.entries(patches).flatMap(([key, patch]) => patch.type === PatchType.DRAWING ? [] : [[key, patch]]);
37843
+ const patchesInOrder = [...textPatches.filter(([, patch]) => patch.type === PatchType.TABLE_ROWS), ...textPatches.filter(([, patch]) => patch.type !== PatchType.TABLE_ROWS)];
35755
37844
  for (const [key, json] of [...map]) {
35756
37845
  if (!key.startsWith("word/") || key.endsWith(".xml.rels")) continue;
35757
37846
  const context = createContext(key);
35758
37847
  contexts.set(key, context);
35759
- for (const [patchKey, patchValue] of Object.entries(patches)) {
35760
- if (patchValue.type === PatchType.DRAWING) continue;
35761
- const patchText = `${start}${patchKey}${end}`;
35762
- replacer({
35763
- json,
35764
- patch: _objectSpread2(_objectSpread2({}, patchValue), {}, { children: patchValue.children.map((element) => {
35765
- if (element instanceof ExternalHyperlink) {
35766
- const concreteHyperlink = new ConcreteHyperlink(element.options.children, uniqueId());
35767
- relationshipAdditions.push({
37848
+ const patchPlaceholder = (element, patchKey, patchValue) => {
37849
+ if (patchValue.type === PatchType.TABLE_ROWS) {
37850
+ patchTableRows({
37851
+ json: element,
37852
+ key: patchKey,
37853
+ patch: patchValue,
37854
+ delimiters: {
37855
+ start,
37856
+ end
37857
+ },
37858
+ patchPlaceholder
37859
+ });
37860
+ return;
37861
+ }
37862
+ const hyperlinkRelationships = [];
37863
+ const { didFindOccurrence } = replacer({
37864
+ json: element,
37865
+ patch: _objectSpread2(_objectSpread2({}, patchValue), {}, { children: patchValue.children.flatMap((child) => child instanceof Bookmark ? child.writtenAs : [child]).map((child) => {
37866
+ if (child instanceof ExternalHyperlink) {
37867
+ const { target, anchor } = externalHyperlinkTarget(child.options.link);
37868
+ const concreteHyperlink = new ConcreteHyperlink(child.options.children, uniqueId(), anchor, child.options.link);
37869
+ hyperlinkRelationships.push({
35768
37870
  key,
35769
37871
  id: concreteHyperlink.linkId,
35770
37872
  type: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
35771
- target: element.options.link,
37873
+ target,
35772
37874
  targetMode: TargetModeType.EXTERNAL
35773
37875
  });
35774
37876
  return concreteHyperlink;
35775
- } else return element;
37877
+ } else return child;
35776
37878
  }) }),
35777
- patchText,
37879
+ patchText: `${start}${patchKey}${end}`,
35778
37880
  context,
35779
37881
  keepOriginalStyles,
35780
- recursive
37882
+ recursive,
37883
+ renumberIds: (elements) => notes.renumber(renumberBookmarks(elements))
35781
37884
  });
35782
- }
35783
- const mediaDatas = imageReplacer.getMediaData(JSON.stringify(json), context.file.Media);
37885
+ if (didFindOccurrence) relationshipAdditions.push(...hyperlinkRelationships);
37886
+ };
37887
+ for (const [patchKey, patchValue] of patchesInOrder) patchPlaceholder(json, patchKey, patchValue);
37888
+ }
37889
+ notes.write();
37890
+ for (const [key, json] of map) {
37891
+ if (!key.startsWith("word/") || key.endsWith(".xml.rels")) continue;
37892
+ const mediaDatas = imageReplacer.getMediaData(JSON.stringify(json), file.Media);
35784
37893
  if (mediaDatas.length > 0) {
35785
37894
  hasMedia = true;
35786
37895
  imageRelationshipAdditions.push({
@@ -35809,6 +37918,7 @@ var patchDocument = function() {
35809
37918
  map.set(relationshipKey, relationshipsJson);
35810
37919
  appendRelationship(relationshipsJson, id, type, target, targetMode);
35811
37920
  }
37921
+ if (pageNumbers) yield fillTemplatePageNumbers(map, pageNumbers, binaryContentMap);
35812
37922
  const packageParts = xmlifyPackageParts(file, void 0);
35813
37923
  if (hasMedia || contentTypeOverrides.length > 0) {
35814
37924
  const contentTypesJson = map.get("[Content_Types].xml");
@@ -35842,12 +37952,13 @@ var patchDocument = function() {
35842
37952
  };
35843
37953
  }();
35844
37954
  /**
35845
- * The element with an extra escape on each "&" in its text. xml-js reads "&amp;" in text as an "&" already escaped, and
35846
- * would write a text's literal "&amp;", such as in a document about HTML, as "&".
37955
+ * The element with an extra escape on each "&" in its text and attributes. xml-js reads "&amp;" in text as an "&"
37956
+ * already escaped, and would write a text's literal "&amp;", such as in a document about HTML, as "&". It escapes the
37957
+ * quotes in an attribute before `attributeValueFn` is given it, so that can't tell its "&quot;" from a literal one.
35847
37958
  */
35848
- var withAmpersandsEscaped = (element) => _objectSpread2(_objectSpread2({}, element), element.elements === void 0 ? {} : { elements: element.elements.map((child) => child.type === "text" ? _objectSpread2(_objectSpread2({}, child), {}, { text: String(child.text).replace(/&/g, "&amp;") }) : withAmpersandsEscaped(child)) });
37959
+ var withAmpersandsEscaped = (element) => _objectSpread2(_objectSpread2(_objectSpread2({}, element), element.attributes === void 0 ? {} : { attributes: Object.fromEntries(Object.entries(element.attributes).map(([key, value]) => [key, value === void 0 ? value : String(value).replace(/&/g, "&amp;")])) }), element.elements === void 0 ? {} : { elements: element.elements.map((child) => child.type === "text" ? _objectSpread2(_objectSpread2({}, child), {}, { text: String(child.text).replace(/&/g, "&amp;") }) : withAmpersandsEscaped(child)) });
35849
37960
  var toXml = (jsonObj) => {
35850
- return (0, import_lib.js2xml)(withAmpersandsEscaped(jsonObj), { attributeValueFn: (str) => String(str).replace(/&(?!amp;|lt;|gt;|quot;|apos;)/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;") });
37961
+ return (0, import_lib.js2xml)(withAmpersandsEscaped(jsonObj), { attributeValueFn: (str) => String(str).replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/'/g, "&apos;") });
35851
37962
  };
35852
37963
  //#endregion
35853
37964
  //#region src/patcher/patch-detector.ts
@@ -35962,6 +38073,7 @@ exports.EMPTY_OBJECT = EMPTY_OBJECT;
35962
38073
  exports.EmphasisMarkType = EmphasisMarkType;
35963
38074
  exports.EmptyElement = EmptyElement;
35964
38075
  exports.EndnoteIdReference = EndnoteIdReference;
38076
+ exports.EndnotePosition = EndnotePosition;
35965
38077
  exports.EndnoteReference = EndnoteReference;
35966
38078
  exports.EndnoteReferenceRun = EndnoteReferenceRun;
35967
38079
  exports.EndnoteReferenceRunAttributes = EndnoteReferenceRunAttributes;
@@ -35973,6 +38085,7 @@ exports.FootNoteReferenceRunAttributes = FootNoteReferenceRunAttributes;
35973
38085
  exports.FootNotes = FootNotes;
35974
38086
  exports.Footer = Footer;
35975
38087
  exports.FooterWrapper = FooterWrapper;
38088
+ exports.FootnotePosition = FootnotePosition;
35976
38089
  exports.FootnoteReference = FootnoteReference;
35977
38090
  exports.FootnoteReferenceElement = FootnoteReferenceElement;
35978
38091
  exports.FootnoteReferenceRun = FootnoteReferenceRun;
@@ -36039,6 +38152,7 @@ exports.MonthShort = MonthShort;
36039
38152
  exports.NextAttributeComponent = NextAttributeComponent;
36040
38153
  exports.NoBreakHyphen = NoBreakHyphen;
36041
38154
  exports.NonVisualDrawingProperties = NonVisualDrawingProperties;
38155
+ exports.NoteNumberRestart = NoteNumberRestart;
36042
38156
  exports.NumberFormat = NumberFormat;
36043
38157
  exports.NumberProperties = NumberProperties;
36044
38158
  exports.NumberValueElement = NumberValueElement;
@@ -36153,6 +38267,8 @@ exports.createColumns = createColumns;
36153
38267
  exports.createDocumentGrid = createDocumentGrid;
36154
38268
  exports.createDotEmphasisMark = createDotEmphasisMark;
36155
38269
  exports.createEmphasisMark = createEmphasisMark;
38270
+ exports.createEndnoteProperties = createEndnoteProperties;
38271
+ exports.createFootnoteProperties = createFootnoteProperties;
36156
38272
  exports.createFrameProperties = createFrameProperties;
36157
38273
  exports.createHeaderFooterReference = createHeaderFooterReference;
36158
38274
  exports.createHorizontalPosition = createHorizontalPosition;
@@ -36202,6 +38318,9 @@ exports.docPropertiesUniqueNumericId = docPropertiesUniqueNumericId;
36202
38318
  exports.docPropertiesUniqueNumericIdGen = docPropertiesUniqueNumericIdGen;
36203
38319
  exports.eighthPointMeasureValue = eighthPointMeasureValue;
36204
38320
  exports.encodeUtf8 = encodeUtf8;
38321
+ exports.fillPageNumbers = fillPageNumbers;
38322
+ exports.fillPartPageNumbers = fillPartPageNumbers;
38323
+ exports.fillSequenceNumbers = fillSequenceNumbers;
36205
38324
  exports.hashedId = hashedId;
36206
38325
  exports.hexColorValue = hexColorValue;
36207
38326
  exports.hpsMeasureValue = hpsMeasureValue;