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