docx 9.8.1 → 9.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -31,7 +31,7 @@ var docx = (function(exports) {
31
31
  enumerable: true
32
32
  }) : target, mod));
33
33
  //#endregion
34
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/typeof.js
34
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/typeof.js
35
35
  function _typeof(o) {
36
36
  "@babel/helpers - typeof";
37
37
  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
@@ -41,7 +41,7 @@ var docx = (function(exports) {
41
41
  }, _typeof(o);
42
42
  }
43
43
  //#endregion
44
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/toPrimitive.js
44
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/toPrimitive.js
45
45
  function toPrimitive(t, r) {
46
46
  if ("object" != _typeof(t) || !t) return t;
47
47
  var e = t[Symbol.toPrimitive];
@@ -53,13 +53,13 @@ var docx = (function(exports) {
53
53
  return ("string" === r ? String : Number)(t);
54
54
  }
55
55
  //#endregion
56
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/toPropertyKey.js
56
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/toPropertyKey.js
57
57
  function toPropertyKey(t) {
58
58
  var i = toPrimitive(t, "string");
59
59
  return "symbol" == _typeof(i) ? i : i + "";
60
60
  }
61
61
  //#endregion
62
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/defineProperty.js
62
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/defineProperty.js
63
63
  function _defineProperty(e, r, t) {
64
64
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
65
65
  value: t,
@@ -269,7 +269,7 @@ var docx = (function(exports) {
269
269
  }
270
270
  };
271
271
  //#endregion
272
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/objectSpread2.js
272
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/objectSpread2.js
273
273
  function ownKeys(e, r) {
274
274
  var t = Object.keys(e);
275
275
  if (Object.getOwnPropertySymbols) {
@@ -8951,11 +8951,11 @@ var docx = (function(exports) {
8951
8951
  * @publicApi
8952
8952
  */
8953
8953
  var AlignmentType = {
8954
- /** Align Start */
8954
+ /** Align Start: the left in a left-to-right paragraph, and the right in a `bidirectional` (right-to-left) paragraph */
8955
8955
  START: "start",
8956
8956
  /** Align Center */
8957
8957
  CENTER: "center",
8958
- /** End */
8958
+ /** Align End: the right in a left-to-right paragraph, and the left in a `bidirectional` (right-to-left) paragraph */
8959
8959
  END: "end",
8960
8960
  /** Justified */
8961
8961
  BOTH: "both",
@@ -8971,9 +8971,9 @@ var docx = (function(exports) {
8971
8971
  LOW_KASHIDA: "lowKashida",
8972
8972
  /** Thai Language Justification */
8973
8973
  THAI_DISTRIBUTE: "thaiDistribute",
8974
- /** Align Left */
8974
+ /** Align Left: a paragraph stays on the left of the page even when it is `bidirectional` (right-to-left) */
8975
8975
  LEFT: "left",
8976
- /** Align Right */
8976
+ /** Align Right: a paragraph stays on the right of the page even when it is `bidirectional` (right-to-left) */
8977
8977
  RIGHT: "right",
8978
8978
  /** Justified */
8979
8979
  JUSTIFIED: "both"
@@ -9787,6 +9787,40 @@ var docx = (function(exports) {
9787
9787
  * field instructions, an optional separate character, field result, and an end character.
9788
9788
  */
9789
9789
  var createBegin = (dirty) => createFieldChar(FieldCharacterType.BEGIN, dirty);
9790
+ /** The formatted begin characters of the fields that are dirty only when the document isn't given page numbers */
9791
+ var dirtyWithoutPageNumbers = /* @__PURE__ */ new WeakSet();
9792
+ /** The beginning of a field that is dirty, so Word updates it, unless the document is given page numbers */
9793
+ var BeginDirtyWithoutPageNumbers = class extends BuilderElement {
9794
+ constructor() {
9795
+ super({
9796
+ name: "w:fldChar",
9797
+ attributes: {
9798
+ type: {
9799
+ key: "w:fldCharType",
9800
+ value: FieldCharacterType.BEGIN
9801
+ },
9802
+ dirty: {
9803
+ key: "w:dirty",
9804
+ value: true
9805
+ }
9806
+ }
9807
+ });
9808
+ }
9809
+ prepForXml(context) {
9810
+ const xml = super.prepForXml(context);
9811
+ dirtyWithoutPageNumbers.add(xml);
9812
+ return xml;
9813
+ }
9814
+ };
9815
+ /**
9816
+ * Creates the beginning of a field whose result is written when the document is given page numbers, such as a page
9817
+ * reference or a SEQ field. It is written dirty, so Word updates the field when it opens the document, and asks to. When
9818
+ * the document is given page numbers, it is written clean (see {@link isDirtyWithoutPageNumbers}), so Word shows the
9819
+ * number written, or nothing when none could be worked out, and doesn't ask.
9820
+ */
9821
+ var createBeginDirtyWithoutPageNumbers = () => new BeginDirtyWithoutPageNumbers();
9822
+ /** Whether a formatted field character is the beginning of a field that is dirty only without page numbers */
9823
+ var isDirtyWithoutPageNumbers = (element) => typeof element === "object" && element !== null && dirtyWithoutPageNumbers.has(element);
9790
9824
  /**
9791
9825
  * Creates the separator between field code and field result in a complex field.
9792
9826
  *
@@ -9957,7 +9991,8 @@ var docx = (function(exports) {
9957
9991
  THAI_NUMBERS: "thaiNumbers",
9958
9992
  THAI_COUNTING: "thaiCounting",
9959
9993
  BAHT_TEXT: "bahtText",
9960
- DOLLAR_TEXT: "dollarText"
9994
+ DOLLAR_TEXT: "dollarText",
9995
+ CUSTOM: "custom"
9961
9996
  };
9962
9997
  //#endregion
9963
9998
  //#region src/file/shared/space-type.ts
@@ -11299,13 +11334,8 @@ DOT: "dot" };
11299
11334
  */
11300
11335
  var SymbolRun = class extends Run {
11301
11336
  constructor(options) {
11302
- if (typeof options === "string") {
11303
- super({});
11304
- this.root.push(new Symbol$1(options));
11305
- return this;
11306
- }
11307
- super(options);
11308
- this.root.push(new Symbol$1(options.char, options.symbolfont));
11337
+ super(typeof options === "string" ? {} : options);
11338
+ this.root.push(typeof options === "string" ? new Symbol$1(options) : new Symbol$1(options.char, options.symbolfont));
11309
11339
  }
11310
11340
  };
11311
11341
  //#endregion
@@ -14286,6 +14316,16 @@ DOT: "dot" };
14286
14316
  }
14287
14317
  };
14288
14318
  /**
14319
+ * Converts a crop percentage to thousandths of a percent.
14320
+ *
14321
+ * @throws If the percentage isn't a number from 0 to 100
14322
+ */
14323
+ var cropValue = (value, edge) => {
14324
+ if (value === void 0) return;
14325
+ if (!(value >= 0 && value <= 100)) throw new Error(`Invalid crop ${edge} ${value}. Expected a number from 0 to 100`);
14326
+ return Math.round(value * 1e3);
14327
+ };
14328
+ /**
14289
14329
  * Represents a source rectangle for blip fills.
14290
14330
  *
14291
14331
  * This element specifies a portion of the blip (image) to use as the fill.
@@ -14312,10 +14352,10 @@ DOT: "dot" };
14312
14352
  constructor(crop) {
14313
14353
  super("a:srcRect");
14314
14354
  if (crop) this.root.push(new SourceRectangleAttributes({
14315
- left: crop.left === void 0 ? void 0 : Math.round(crop.left * 1e3),
14316
- top: crop.top === void 0 ? void 0 : Math.round(crop.top * 1e3),
14317
- right: crop.right === void 0 ? void 0 : Math.round(crop.right * 1e3),
14318
- bottom: crop.bottom === void 0 ? void 0 : Math.round(crop.bottom * 1e3)
14355
+ left: cropValue(crop.left, "left"),
14356
+ top: cropValue(crop.top, "top"),
14357
+ right: cropValue(crop.right, "right"),
14358
+ bottom: cropValue(crop.bottom, "bottom")
14319
14359
  }));
14320
14360
  }
14321
14361
  };
@@ -14669,7 +14709,9 @@ DOT: "dot" };
14669
14709
  this.root.push(createHyperlinkClick(element.linkId, false));
14670
14710
  break;
14671
14711
  }
14672
- return super.prepForXml(context);
14712
+ const result = super.prepForXml(context);
14713
+ this.root.splice(1);
14714
+ return result;
14673
14715
  }
14674
14716
  };
14675
14717
  //#endregion
@@ -15616,6 +15658,18 @@ EXTERNAL: "External" };
15616
15658
  * @module
15617
15659
  */
15618
15660
  /**
15661
+ * The largest width or height, in EMUs, Word opens a drawing at. The standard allows `ST_PositiveCoordinate` up to
15662
+ * 27273042316900, but Word and PowerPoint restrict it to 2147483647 and won't open a document with a larger drawing.
15663
+ *
15664
+ * Reference: [MS-OI29500] Part 1 Section 20.1.10.42, ST_PositiveCoordinate
15665
+ */
15666
+ var MAX_EXTENT = 2147483647;
15667
+ var EMUS_PER_PIXEL = 9525;
15668
+ var checkExtent = (dimension, value) => {
15669
+ 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`);
15670
+ return value;
15671
+ };
15672
+ /**
15619
15673
  * Creates an extent element for inline drawings.
15620
15674
  *
15621
15675
  * This element specifies the extents of the parent DrawingML object within
@@ -15639,17 +15693,19 @@ EXTERNAL: "External" };
15639
15693
  * y: 914400
15640
15694
  * });
15641
15695
  * ```
15696
+ *
15697
+ * @throws Error if the width or height is over 2147483647 EMUs, which Word won't open
15642
15698
  */
15643
15699
  var createExtent = ({ x, y }) => new BuilderElement({
15644
15700
  name: "wp:extent",
15645
15701
  attributes: {
15646
15702
  x: {
15647
15703
  key: "cx",
15648
- value: x
15704
+ value: checkExtent("width", x)
15649
15705
  },
15650
15706
  y: {
15651
15707
  key: "cy",
15652
- value: y
15708
+ value: checkExtent("height", y)
15653
15709
  }
15654
15710
  }
15655
15711
  });
@@ -16041,7 +16097,6 @@ EXTERNAL: "External" };
16041
16097
  var ImageRun = class extends XmlComponent {
16042
16098
  constructor(options) {
16043
16099
  var _options$insertion;
16044
- var _super = (..._args) => (super(..._args), _defineProperty(this, "imageData", void 0), this);
16045
16100
  const key = `${hashedId(options.data)}.${options.type}`;
16046
16101
  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));
16047
16102
  const drawing = new Drawing(imageData, {
@@ -16055,8 +16110,10 @@ EXTERNAL: "External" };
16055
16110
  });
16056
16111
  const properties = new RunProperties(options.run);
16057
16112
  const revision = (_options$insertion = options.insertion) !== null && _options$insertion !== void 0 ? _options$insertion : options.deletion;
16113
+ const rootName = options.insertion ? "w:ins" : options.deletion ? "w:del" : "w:r";
16114
+ super(rootName);
16115
+ _defineProperty(this, "imageData", void 0);
16058
16116
  if (revision) {
16059
- _super(options.insertion ? "w:ins" : "w:del");
16060
16117
  this.root.push(new ChangeAttributes({
16061
16118
  id: revision.id,
16062
16119
  author: revision.author,
@@ -16068,7 +16125,6 @@ EXTERNAL: "External" };
16068
16125
  });
16069
16126
  this.addChildElement(options.insertion && options.deletion ? createDeletion(options.deletion, run) : run);
16070
16127
  } else {
16071
- _super("w:r");
16072
16128
  this.root.push(properties);
16073
16129
  this.root.push(drawing);
16074
16130
  }
@@ -16221,6 +16277,10 @@ EXTERNAL: "External" };
16221
16277
  * Each identifier maintains its own sequence, allowing you to have separate numbering
16222
16278
  * for figures, tables, equations, etc.
16223
16279
  *
16280
+ * It is written dirty, so Word numbers it when it opens the document, after asking to update the fields. When the
16281
+ * document is given `pageNumbers`, it is written clean, with its number counted as Word counts it, or blank where
16282
+ * Word's count isn't known, and Word doesn't ask.
16283
+ *
16224
16284
  * Reference: http://officeopenxml.com/WPrun.php
16225
16285
  *
16226
16286
  * @publicApi
@@ -16249,7 +16309,7 @@ EXTERNAL: "External" };
16249
16309
  var SequentialIdentifier = class extends Run {
16250
16310
  constructor(identifier) {
16251
16311
  super({});
16252
- this.root.push(createBegin(true));
16312
+ this.root.push(createBeginDirtyWithoutPageNumbers());
16253
16313
  this.root.push(new SequentialIdentifierInstruction(identifier));
16254
16314
  this.root.push(createSeparate());
16255
16315
  this.root.push(createEnd());
@@ -16274,7 +16334,10 @@ EXTERNAL: "External" };
16274
16334
  var FldSimpleAttrs = class extends XmlAttributeComponent {
16275
16335
  constructor(..._args) {
16276
16336
  super(..._args);
16277
- _defineProperty(this, "xmlKeys", { instr: "w:instr" });
16337
+ _defineProperty(this, "xmlKeys", {
16338
+ instr: "w:instr",
16339
+ fldLock: "w:fldLock"
16340
+ });
16278
16341
  }
16279
16342
  };
16280
16343
  /**
@@ -16307,12 +16370,18 @@ EXTERNAL: "External" };
16307
16370
  *
16308
16371
  * // Simple field with cached value
16309
16372
  * new SimpleField("DATE", "2024-01-01");
16373
+ *
16374
+ * // Locked field, Word keeps the cached value when fields are updated
16375
+ * new SimpleField("DATE", "2024-01-01", { locked: true });
16310
16376
  * ```
16311
16377
  */
16312
16378
  var SimpleField = class extends XmlComponent {
16313
- constructor(instruction, cachedValue) {
16379
+ constructor(instruction, cachedValue, options = {}) {
16314
16380
  super("w:fldSimple");
16315
- this.root.push(new FldSimpleAttrs({ instr: instruction }));
16381
+ this.root.push(new FldSimpleAttrs({
16382
+ instr: instruction,
16383
+ fldLock: options.locked ? true : void 0
16384
+ }));
16316
16385
  if (cachedValue !== void 0) this.root.push(new TextRun(cachedValue));
16317
16386
  }
16318
16387
  };
@@ -16337,6 +16406,1035 @@ EXTERNAL: "External" };
16337
16406
  }
16338
16407
  };
16339
16408
  //#endregion
16409
+ //#region src/file/document/body/field-number-formats.ts
16410
+ var LARGEST_ROMAN = 32767;
16411
+ var LARGEST_LETTERS = 780;
16412
+ var ROMAN = [
16413
+ [1e3, "M"],
16414
+ [900, "CM"],
16415
+ [500, "D"],
16416
+ [400, "CD"],
16417
+ [100, "C"],
16418
+ [90, "XC"],
16419
+ [50, "L"],
16420
+ [40, "XL"],
16421
+ [10, "X"],
16422
+ [9, "IX"],
16423
+ [5, "V"],
16424
+ [4, "IV"],
16425
+ [1, "I"]
16426
+ ];
16427
+ var roman = (value) => value <= LARGEST_ROMAN ? ROMAN.reduce(({ rest, text }, [amount, numeral]) => ({
16428
+ rest: rest % amount,
16429
+ text: text + numeral.repeat(Math.floor(rest / amount))
16430
+ }), {
16431
+ rest: value,
16432
+ text: ""
16433
+ }).text : void 0;
16434
+ var letters = (value) => value === 0 ? "" : value <= LARGEST_LETTERS ? String.fromCharCode(65 + (value - 1) % 26).repeat(Math.ceil(value / 26)) : void 0;
16435
+ var ordinal = (value) => {
16436
+ var _ref;
16437
+ return `${value}${value % 100 >= 11 && value % 100 <= 13 ? "th" : (_ref = [
16438
+ "th",
16439
+ "st",
16440
+ "nd",
16441
+ "rd"
16442
+ ][value % 10]) !== null && _ref !== void 0 ? _ref : "th"}`;
16443
+ };
16444
+ /**
16445
+ * The number formats of a field's `\*` switch that are written as Word writes them, by their names in any capitals.
16446
+ * Word writes roman numerals and letters in small letters when the name starts with a small letter, as `roman`, and in
16447
+ * capitals otherwise, as `Roman` and `ROMAN`
16448
+ */
16449
+ var numberWriterOf = (format) => {
16450
+ const small = format.charAt(0) !== format.charAt(0).toUpperCase();
16451
+ const inCase = (write) => (value) => {
16452
+ var _write;
16453
+ return small ? (_write = write(value)) === null || _write === void 0 ? void 0 : _write.toLowerCase() : write(value);
16454
+ };
16455
+ switch (format.toLowerCase()) {
16456
+ case "arabic": return String;
16457
+ case "roman": return inCase(roman);
16458
+ case "alphabetic": return inCase(letters);
16459
+ case "ordinal": return (value) => value > 0 ? ordinal(value) : void 0;
16460
+ case "arabicdash": return (value) => `- ${value} -`;
16461
+ default: return;
16462
+ }
16463
+ };
16464
+ var PLAIN_FORMATS = /* @__PURE__ */ new Set([
16465
+ "mergeformat",
16466
+ "charformat",
16467
+ "mergeformatinet"
16468
+ ]);
16469
+ var CASE_FORMATS = /* @__PURE__ */ new Set([
16470
+ "upper",
16471
+ "lower",
16472
+ "firstcap",
16473
+ "caps"
16474
+ ]);
16475
+ /**
16476
+ * Whether Word's text for a picture of a field's `\#` switch is known: one of digits (`0`), digits only where the number
16477
+ * has them (`#`) and commas between thousands, as Word wrote `00`, `000`, `0`, `#` and `#,##0` for page numbers
16478
+ * (`scripts/layout-probes/word-page-fields.ts` PF5 to PF7)
16479
+ */
16480
+ var isNumberPicture = (picture) => /^[#0,]*[#0][#0,]*$/.test(picture);
16481
+ /**
16482
+ * 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
16483
+ * its thousands between commas when it has one (1234 is 1,234 with `#,##0`). Undefined where a `#` has no digit of the
16484
+ * number, which Word writes as a space, not yet seen
16485
+ */
16486
+ var inNumberPicture = (value, picture) => {
16487
+ const zeros = [...picture].filter((character) => character === "0").length;
16488
+ const places = zeros + [...picture].filter((character) => character === "#").length;
16489
+ const digits = String(value).padStart(zeros, "0");
16490
+ if (digits.length < places || zeros === 0 && value === 0) return;
16491
+ return picture.includes(",") ? digits.replace(/\B(?=(\d{3})+$)/g, ",") : digits;
16492
+ };
16493
+ /**
16494
+ * Text in the capitals of a field's switch, applied after its number's format, as Word wrote `\* roman \* Upper` as V,
16495
+ * `\* Ordinal \* Upper` as 5TH, and "above" with `\* Upper` as ABOVE (`word-page-fields.ts` PF3 and PF5)
16496
+ */
16497
+ var inCapitals = (text, capitals) => {
16498
+ switch (capitals) {
16499
+ case "upper": return text.toUpperCase();
16500
+ case "lower": return text.toLowerCase();
16501
+ case "firstcap": return text.charAt(0).toUpperCase() + text.slice(1);
16502
+ default: return text;
16503
+ }
16504
+ };
16505
+ //#endregion
16506
+ //#region src/file/document/body/page-number-fields.ts
16507
+ /**
16508
+ * Writes estimated page numbers into the fields of a tree of elements that show them: those docx formats to write a
16509
+ * document, and those `patchDocument` parses from a template. Not part of the public API.
16510
+ *
16511
+ * A page reference is a PAGEREF field, and the numbers of pages of the document and of a section are NUMPAGES and
16512
+ * SECTIONPAGES fields. Each field's result is written just after its `separate` field character, and any result it had
16513
+ * is taken out.
16514
+ *
16515
+ * @module
16516
+ */
16517
+ /** Reads a field that shows a page's number or a number of pages, or undefined for another field */
16518
+ var numberFieldOf = (instruction) => {
16519
+ var _match;
16520
+ const field = new RegExp("^\\s*(PAGEREF|NUMPAGES|SECTIONPAGES)\\b(.*)$", "is").exec(instruction);
16521
+ const reference = (field === null || field === void 0 ? void 0 : field[1].toUpperCase()) === "PAGEREF" ? new RegExp("^\\s*(\"?)([^\\s\"\\\\]+)\\1(.*)$", "s").exec(field[2]) : void 0;
16522
+ if (!field || field[1].toUpperCase() === "PAGEREF" && !reference) return;
16523
+ const parts = (_match = (reference ? reference[3] : field[2]).match(/"[^"]*"|\S+/g)) !== null && _match !== void 0 ? _match : [];
16524
+ let numberFormat;
16525
+ let picture;
16526
+ const capitals = [];
16527
+ let relative = false;
16528
+ let written = true;
16529
+ for (let index = 0; index < parts.length; index++) {
16530
+ const part = parts[index];
16531
+ const argument = () => {
16532
+ var _parts$index;
16533
+ return (part.length > 2 ? part.slice(2) : (_parts$index = parts[++index]) !== null && _parts$index !== void 0 ? _parts$index : "").replace(/^"(.*)"$/, "$1");
16534
+ };
16535
+ if (/^\\p$/i.test(part)) relative = true;
16536
+ else if (part.startsWith("\\#")) {
16537
+ var _picture;
16538
+ const value = argument();
16539
+ written && (written = picture === void 0 && isNumberPicture(value));
16540
+ (_picture = picture) !== null && _picture !== void 0 || (picture = value);
16541
+ } else if (part.startsWith("\\*")) {
16542
+ const name = argument();
16543
+ const lower = name.toLowerCase();
16544
+ if (CASE_FORMATS.has(lower)) capitals.push(lower);
16545
+ else if (name !== "" && !PLAIN_FORMATS.has(lower)) {
16546
+ var _numberFormat;
16547
+ written && (written = numberFormat === void 0 && numberWriterOf(name) !== void 0);
16548
+ (_numberFormat = numberFormat) !== null && _numberFormat !== void 0 || (numberFormat = name);
16549
+ }
16550
+ }
16551
+ }
16552
+ 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) });
16553
+ return reference ? _objectSpread2({
16554
+ type: "pageReference",
16555
+ bookmark: reference[2],
16556
+ relative
16557
+ }, own) : _objectSpread2({
16558
+ type: "pageCount",
16559
+ scope: field[1].toUpperCase() === "NUMPAGES" ? "document" : "section"
16560
+ }, own);
16561
+ };
16562
+ /**
16563
+ * Whether a field is a table of contents that writes the number of a SEQ field before each page number (`\s`), such as
16564
+ * 2-5 for page 5 of chapter 2, which isn't written
16565
+ */
16566
+ var prefixesPageNumbers = (instruction) => new RegExp("^\\s*TOC\\b.*\\\\s\\b", "is").test(instruction);
16567
+ /**
16568
+ * 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
16569
+ * 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
16570
+ * writes a SEQ field's number before it.
16571
+ */
16572
+ var resultFrom = (instruction, { enclosing, within, inTextBox }, { estimate, sectionPageCount, blank, relativeTo }) => {
16573
+ const field = numberFieldOf(instruction);
16574
+ if (field === void 0) return;
16575
+ const { bookmarks, pageCount, bookmarkPageNumbers } = estimate;
16576
+ const { numberFormat, picture, capitals, written } = field;
16577
+ const writesNumber = numberFormat !== void 0 || picture !== void 0;
16578
+ /** A number in the field's format of its own, or as it is */
16579
+ const inFormat = (value) => value === void 0 ? void 0 : picture === void 0 ? numberWriterOf(numberFormat !== null && numberFormat !== void 0 ? numberFormat : "arabic")(value) : inNumberPicture(value, picture);
16580
+ const position = field.type === "pageReference" && field.relative && within === "counted" && !inTextBox ? relativeTo === null || relativeTo === void 0 ? void 0 : relativeTo(field.bookmark) : void 0;
16581
+ let result;
16582
+ if (!written) result = void 0;
16583
+ else if (field.type === "pageCount") result = inFormat(field.scope === "document" ? pageCount : sectionPageCount);
16584
+ else if (enclosing.some(prefixesPageNumbers)) result = void 0;
16585
+ else if (writesNumber) result = inFormat(bookmarkPageNumbers === null || bookmarkPageNumbers === void 0 ? void 0 : bookmarkPageNumbers.get(field.bookmark));
16586
+ else result = field.relative ? position : bookmarks.get(field.bookmark);
16587
+ return result === void 0 ? blank ? "" : void 0 : inCapitals(result, capitals);
16588
+ };
16589
+ /** Where the content of an element is: in what an application that doesn't read Word's own shows, or in deleted text */
16590
+ var placeIn = (name, within) => name === "mc:Fallback" || within === "fallback" ? "fallback" : name === "w:del" || name === "w:moveFrom" ? "deleted" : within;
16591
+ /**
16592
+ * Writes the results the filling works out into the fields in the elements, in order.
16593
+ */
16594
+ var fillFields = (tree, elements, open, filling, within = "counted", inTextBox = false) => {
16595
+ for (let index = 0; index < elements.length; index++) {
16596
+ const element = elements[index];
16597
+ const name = tree.nameOf(element);
16598
+ if (name === void 0) continue;
16599
+ const current = open[open.length - 1];
16600
+ if (name === "w:fldChar") {
16601
+ const type = tree.attributeOf(element, "w:fldCharType");
16602
+ if (type === "begin") open.push({
16603
+ begin: element,
16604
+ instruction: "",
16605
+ inResult: false
16606
+ });
16607
+ else if (type === "separate" && current) {
16608
+ tree.writeClean(current.begin, current.instruction);
16609
+ current.inResult = true;
16610
+ current.result = filling.resultOf(current.instruction, {
16611
+ within,
16612
+ enclosing: open.slice(0, -1).map((field) => field.instruction),
16613
+ inTextBox
16614
+ });
16615
+ if (current.result !== void 0) {
16616
+ elements.splice(index + 1, 0, tree.textElement(current.result));
16617
+ index++;
16618
+ }
16619
+ } else if (type === "end") open.pop();
16620
+ } else if (name === "w:instrText" && current && !current.inResult) current.instruction += tree.textOf(element);
16621
+ 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) {
16622
+ elements.splice(index, 1);
16623
+ index--;
16624
+ } else if (name === "w:fldSimple") {
16625
+ const result = filling.resultOf(String(tree.attributeOf(element, "w:instr")), {
16626
+ within,
16627
+ enclosing: open.map((field) => field.instruction),
16628
+ inTextBox
16629
+ });
16630
+ if (result === void 0) {
16631
+ var _tree$contentOf;
16632
+ fillFields(tree, (_tree$contentOf = tree.contentOf(element)) !== null && _tree$contentOf !== void 0 ? _tree$contentOf : [], [], filling, within, inTextBox);
16633
+ } else tree.setSimpleFieldResult(element, result);
16634
+ } else {
16635
+ var _tree$contentOf2;
16636
+ if (name === "w:p") {
16637
+ var _filling$beforeParagr;
16638
+ (_filling$beforeParagr = filling.beforeParagraph) === null || _filling$beforeParagr === void 0 || _filling$beforeParagr.call(filling, element);
16639
+ }
16640
+ fillFields(tree, (_tree$contentOf2 = tree.contentOf(element)) !== null && _tree$contentOf2 !== void 0 ? _tree$contentOf2 : [], open, filling, placeIn(name, within), inTextBox || name === "w:txbxContent");
16641
+ if (name === "w:p") filling.afterParagraph(element);
16642
+ }
16643
+ }
16644
+ };
16645
+ /** The section properties (`w:sectPr`) in the elements, in order: those of the paragraphs that end sections, and the last */
16646
+ var sectionPropertiesIn = (tree, elements) => elements.flatMap((element) => {
16647
+ var _tree$contentOf3;
16648
+ const name = tree.nameOf(element);
16649
+ if (name === void 0) return [];
16650
+ return name === "w:sectPr" ? [element] : sectionPropertiesIn(tree, (_tree$contentOf3 = tree.contentOf(element)) !== null && _tree$contentOf3 !== void 0 ? _tree$contentOf3 : []);
16651
+ });
16652
+ /** Whether a paragraph ends a section: whether its properties have the section's */
16653
+ var endsSection = (tree, paragraph) => {
16654
+ var _tree$contentOf4;
16655
+ return ((_tree$contentOf4 = tree.contentOf(paragraph)) !== null && _tree$contentOf4 !== void 0 ? _tree$contentOf4 : []).some((child) => {
16656
+ var _tree$contentOf5;
16657
+ 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");
16658
+ });
16659
+ };
16660
+ /**
16661
+ * The number of pages each header and footer shows in its SECTIONPAGES fields, by the id of the relationship to it:
16662
+ * 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
16663
+ * has the one of the section before, as Word lays them out.
16664
+ */
16665
+ var partPageCountsOf = (tree, body, sectionPageCounts) => {
16666
+ const countsOfParts = sectionPropertiesIn(tree, [body]).reduce((all, properties) => {
16667
+ var _tree$contentOf6, _all;
16668
+ const references = ((_tree$contentOf6 = tree.contentOf(properties)) !== null && _tree$contentOf6 !== void 0 ? _tree$contentOf6 : []).flatMap((child) => {
16669
+ const name = tree.nameOf(child);
16670
+ return name === "w:headerReference" || name === "w:footerReference" ? [[`${name} ${String(tree.attributeOf(child, "w:type"))}`, String(tree.attributeOf(child, "r:id"))]] : [];
16671
+ });
16672
+ return [...all, new Map([...(_all = all[all.length - 1]) !== null && _all !== void 0 ? _all : [], ...references])];
16673
+ }, []).reduce((counts, parts, section) => {
16674
+ for (const id of parts.values()) {
16675
+ var _counts$get;
16676
+ counts.set(id, [...(_counts$get = counts.get(id)) !== null && _counts$get !== void 0 ? _counts$get : [], sectionPageCounts[section]]);
16677
+ }
16678
+ return counts;
16679
+ }, /* @__PURE__ */ new Map());
16680
+ return new Map([...countsOfParts].flatMap(([id, [first, ...rest]]) => first !== void 0 && rest.every((count) => count === first) ? [[id, first]] : []));
16681
+ };
16682
+ /**
16683
+ * Writes the estimated page numbers into the fields of a document's body that show them: its PAGEREF fields, in its
16684
+ * tables of contents and elsewhere, and its NUMPAGES and SECTIONPAGES fields.
16685
+ *
16686
+ * @returns The number of pages each header and footer shows in its SECTIONPAGES fields, by the id of the relationship to it
16687
+ */
16688
+ var fillBodyFields = (tree, body, estimate, { blank }) => {
16689
+ const { sectionPageCounts = [], relativePositions } = estimate;
16690
+ let section = 0;
16691
+ const relativeCounts = /* @__PURE__ */ new Map();
16692
+ const relativeTo = (bookmark) => {
16693
+ var _relativeCounts$get, _relativePositions$ge;
16694
+ const count = (_relativeCounts$get = relativeCounts.get(bookmark)) !== null && _relativeCounts$get !== void 0 ? _relativeCounts$get : 0;
16695
+ relativeCounts.set(bookmark, count + 1);
16696
+ return relativePositions === null || relativePositions === void 0 || (_relativePositions$ge = relativePositions.get(bookmark)) === null || _relativePositions$ge === void 0 ? void 0 : _relativePositions$ge[count];
16697
+ };
16698
+ fillFields(tree, [body], [], {
16699
+ resultOf: (instruction, place) => resultFrom(instruction, place, {
16700
+ estimate,
16701
+ sectionPageCount: sectionPageCounts[section],
16702
+ blank,
16703
+ relativeTo
16704
+ }),
16705
+ afterParagraph: (paragraph) => {
16706
+ section += endsSection(tree, paragraph) ? 1 : 0;
16707
+ }
16708
+ });
16709
+ return partPageCountsOf(tree, body, sectionPageCounts);
16710
+ };
16711
+ /**
16712
+ * Writes the estimated page numbers into the fields of a header, footer, footnote or endnote that show them, with the
16713
+ * number of pages its SECTIONPAGES fields show, if it is known. A page reference with `\p` in a footnote or endnote
16714
+ * (`notes`) writes "on page" and its bookmark's page, whatever page it is on, as Word writes it
16715
+ * (`word-page-fields.docx` PF8f, PF8g)
16716
+ */
16717
+ var fillPartFields = (tree, part, estimate, { blank, sectionPageCount, notes = false }) => {
16718
+ const onPage = (bookmark) => {
16719
+ const page = estimate.bookmarks.get(bookmark);
16720
+ return page === void 0 ? void 0 : `on page ${page}`;
16721
+ };
16722
+ fillFields(tree, [part], [], {
16723
+ resultOf: (instruction, place) => resultFrom(instruction, place, _objectSpread2({
16724
+ estimate,
16725
+ sectionPageCount,
16726
+ blank
16727
+ }, notes ? { relativeTo: onPage } : {})),
16728
+ afterParagraph: () => void 0
16729
+ });
16730
+ };
16731
+ /** Writes the numbers of the SEQ fields of a document's body into them */
16732
+ var fillSequenceFields = (tree, body, { beforeParagraph, resultOf }) => fillFields(tree, [body], [], {
16733
+ resultOf: (instruction, { within }) => resultOf(instruction, within),
16734
+ beforeParagraph,
16735
+ afterParagraph: () => void 0
16736
+ });
16737
+ //#endregion
16738
+ //#region src/file/table-of-contents/field-instruction.ts
16739
+ /**
16740
+ * Field Instruction module for Table of Contents.
16741
+ *
16742
+ * This module handles the generation of TOC field instruction text
16743
+ * that controls how the table of contents is built.
16744
+ *
16745
+ * Reference: http://officeopenxml.com/WPfieldInstructions.php
16746
+ *
16747
+ * @module
16748
+ */
16749
+ /**
16750
+ * Represents a field instruction for a Table of Contents.
16751
+ *
16752
+ * The FieldInstruction class generates the TOC field code string that Word uses
16753
+ * to determine how to build the table of contents, including which headings to include,
16754
+ * formatting options, and other TOC-specific settings.
16755
+ *
16756
+ * Reference: http://officeopenxml.com/WPfieldInstructions.php
16757
+ *
16758
+ * ## XSD Schema
16759
+ * ```xml
16760
+ * <xsd:element name="instrText" type="CT_Text"/>
16761
+ * ```
16762
+ *
16763
+ * @example
16764
+ * ```typescript
16765
+ * // Basic TOC field instruction
16766
+ * new FieldInstruction({ headingStyleRange: "1-3" });
16767
+ *
16768
+ * // TOC with hyperlinks and custom styles
16769
+ * new FieldInstruction({
16770
+ * hyperlink: true,
16771
+ * headingStyleRange: "1-3",
16772
+ * stylesWithLevels: [new StyleLevel("CustomStyle", 2)],
16773
+ * });
16774
+ * ```
16775
+ */
16776
+ var FieldInstruction = class extends XmlComponent {
16777
+ constructor(properties = {}) {
16778
+ super("w:instrText");
16779
+ _defineProperty(this, "properties", void 0);
16780
+ this.properties = properties;
16781
+ this.root.push(new TextAttributes({ space: SpaceType.PRESERVE }));
16782
+ let instruction = "TOC";
16783
+ if (this.properties.captionLabel) instruction = `${instruction} \\a "${this.properties.captionLabel}"`;
16784
+ if (this.properties.entriesFromBookmark) instruction = `${instruction} \\b "${this.properties.entriesFromBookmark}"`;
16785
+ if (this.properties.captionLabelIncludingNumbers) instruction = `${instruction} \\c "${this.properties.captionLabelIncludingNumbers}"`;
16786
+ if (this.properties.sequenceAndPageNumbersSeparator) instruction = `${instruction} \\d "${this.properties.sequenceAndPageNumbersSeparator}"`;
16787
+ if (this.properties.tcFieldIdentifier) instruction = `${instruction} \\f "${this.properties.tcFieldIdentifier}"`;
16788
+ if (this.properties.hyperlink) instruction = `${instruction} \\h`;
16789
+ if (this.properties.tcFieldLevelRange) instruction = `${instruction} \\l "${this.properties.tcFieldLevelRange}"`;
16790
+ if (this.properties.pageNumbersEntryLevelsRange) instruction = `${instruction} \\n "${this.properties.pageNumbersEntryLevelsRange}"`;
16791
+ if (this.properties.headingStyleRange) instruction = `${instruction} \\o "${this.properties.headingStyleRange}"`;
16792
+ if (this.properties.entryAndPageNumberSeparator) instruction = `${instruction} \\p "${this.properties.entryAndPageNumberSeparator}"`;
16793
+ if (this.properties.seqFieldIdentifierForPrefix) instruction = `${instruction} \\s "${this.properties.seqFieldIdentifierForPrefix}"`;
16794
+ if (this.properties.stylesWithLevels && this.properties.stylesWithLevels.length) {
16795
+ const styles = this.properties.stylesWithLevels.map((sl) => `${sl.styleName},${sl.level}`).join(",");
16796
+ instruction = `${instruction} \\t "${styles}"`;
16797
+ }
16798
+ if (this.properties.useAppliedParagraphOutlineLevel) instruction = `${instruction} \\u`;
16799
+ if (this.properties.preserveTabInEntries) instruction = `${instruction} \\w`;
16800
+ if (this.properties.preserveNewLineInEntries) instruction = `${instruction} \\x`;
16801
+ if (this.properties.hideTabAndPageNumbersInWebView) instruction = `${instruction} \\z`;
16802
+ this.root.push(instruction);
16803
+ }
16804
+ };
16805
+ //#endregion
16806
+ //#region src/file/table-of-contents/sdt-content.ts
16807
+ /**
16808
+ * Structured Document Tag Content module.
16809
+ *
16810
+ * This module represents the content container for structured document tags,
16811
+ * including table of contents elements.
16812
+ *
16813
+ * Reference: http://officeopenxml.com/WPtableOfContents.php
16814
+ *
16815
+ * @module
16816
+ */
16817
+ /**
16818
+ * Represents the content portion of a Structured Document Tag.
16819
+ *
16820
+ * The StructuredDocumentTagContent contains the actual content elements
16821
+ * (paragraphs, tables, etc.) within a structured document tag, such as
16822
+ * the paragraphs that make up a table of contents.
16823
+ *
16824
+ * Reference: http://officeopenxml.com/WPtableOfContents.php
16825
+ *
16826
+ * ## XSD Schema
16827
+ * ```xml
16828
+ * <xsd:complexType name="CT_SdtContentBlock">
16829
+ * <xsd:group ref="EG_ContentBlockContent" minOccurs="0" maxOccurs="unbounded"/>
16830
+ * </xsd:complexType>
16831
+ * ```
16832
+ *
16833
+ * @example
16834
+ * ```typescript
16835
+ * const content = new StructuredDocumentTagContent();
16836
+ * content.addChildElement(new Paragraph("Content"));
16837
+ * ```
16838
+ */
16839
+ var StructuredDocumentTagContent = class extends XmlComponent {
16840
+ constructor() {
16841
+ super("w:sdtContent");
16842
+ }
16843
+ };
16844
+ //#endregion
16845
+ //#region src/file/table-of-contents/heading-entries.ts
16846
+ /**
16847
+ * Entries written into a table of contents from the headings of the document.
16848
+ *
16849
+ * A table of contents is a TOC field. Word fills in its entries when it updates the field. Until then, and in
16850
+ * applications that don't update it, such as LibreOffice, it shows the entries it was last filled in with, and without
16851
+ * any it is empty. So once the body is written, each table of contents that wasn't given `cachedEntries` or
16852
+ * `contentChildren` is filled in from the headings its switches include, the way Word fills it in: each heading is
16853
+ * bookmarked, and its entry links to the bookmark and gives its page with a PAGEREF field. The page numbers are left
16854
+ * empty, because they depend on how the document is laid out. Word fills them in when it updates the field, unless the
16855
+ * document's `pageNumbers` writes them.
16856
+ *
16857
+ * @module
16858
+ */
16859
+ /**
16860
+ * The beginning of a table of contents' field: dirty or clean, as the caller set it, or else dirty unless the document
16861
+ * is given page numbers
16862
+ */
16863
+ var beginOf = (beginDirty) => beginDirty === void 0 ? createBeginDirtyWithoutPageNumbers() : createBegin(beginDirty);
16864
+ /** The formatted tables of contents, with what each is filled in with, or undefined when it was given its content */
16865
+ var writtenTables = /* @__PURE__ */ new WeakMap();
16866
+ /**
16867
+ * Records a formatted table of contents, so the paragraphs in it aren't taken for headings, with what to fill it in
16868
+ * with from the headings once the body it is in is written. That is undefined when it was given its content.
16869
+ */
16870
+ var recordTableOfContents = (table, fillWith) => {
16871
+ writtenTables.set(table, fillWith);
16872
+ };
16873
+ /**
16874
+ * The ids of the bookmarks on a body's headings: the first for its first bookmarked heading, and so on. Each is taken
16875
+ * from the counter every bookmark shares, the first time it is needed, so a document packed again is written the same.
16876
+ */
16877
+ var HeadingBookmarkIds = class {
16878
+ constructor() {
16879
+ _defineProperty(this, "ids", []);
16880
+ }
16881
+ get(index) {
16882
+ var _this$ids, _this$ids$index;
16883
+ (_this$ids$index = (_this$ids = this.ids)[index]) !== null && _this$ids$index !== void 0 || (_this$ids[index] = bookmarkUniqueNumericId());
16884
+ return this.ids[index];
16885
+ }
16886
+ };
16887
+ /** The name of a formatted element, or `_attr` for its parent's attributes */
16888
+ var nameOf$2 = (element) => typeof element === "object" && element !== null ? Object.keys(element)[0] : void 0;
16889
+ /** The children of a formatted element. An element with only attributes has them as its one child */
16890
+ var childrenOf = (element) => {
16891
+ const name = nameOf$2(element);
16892
+ const content = name === void 0 ? void 0 : element[name];
16893
+ return Array.isArray(content) ? content : content === void 0 ? [] : [content];
16894
+ };
16895
+ var childOf = (element, name) => childrenOf(element).find((child) => nameOf$2(child) === name);
16896
+ var attributeOf = (element, attribute) => {
16897
+ var _childOf;
16898
+ return (_childOf = childOf(element, "_attr")) === null || _childOf === void 0 || (_childOf = _childOf._attr) === null || _childOf === void 0 ? void 0 : _childOf[attribute];
16899
+ };
16900
+ /** An attribute such as `w:val="2"` as a number. Imported XML gives it as a string */
16901
+ var numberAttributeOf = (element, attribute) => {
16902
+ const value = attributeOf(element, attribute);
16903
+ return value === void 0 ? void 0 : Number(value);
16904
+ };
16905
+ /** The block-level containers of paragraphs: tables, their rows and cells, and content controls */
16906
+ var BLOCK_CONTAINERS = /* @__PURE__ */ new Set([
16907
+ "w:tbl",
16908
+ "w:tr",
16909
+ "w:tc",
16910
+ "w:sdt",
16911
+ "w:sdtContent",
16912
+ "w:customXml"
16913
+ ]);
16914
+ /**
16915
+ * The paragraphs and the tables of contents, in the order they are in the body. A table of contents isn't looked into,
16916
+ * so the paragraphs in it aren't taken for headings. Nor are paragraphs in text boxes, as in Word.
16917
+ */
16918
+ var blocksOf = (elements) => elements.flatMap((element) => {
16919
+ const name = nameOf$2(element);
16920
+ if (name === "w:p" || writtenTables.has(element)) return [element];
16921
+ return name !== void 0 && BLOCK_CONTAINERS.has(name) ? blocksOf(childrenOf(element)) : [];
16922
+ });
16923
+ /** The elements in a paragraph that its text is in. Deleted text, field instructions and drawings aren't */
16924
+ var TEXT_CONTAINERS = /* @__PURE__ */ new Set([
16925
+ "w:r",
16926
+ "w:hyperlink",
16927
+ "w:ins",
16928
+ "w:moveTo",
16929
+ "w:smartTag",
16930
+ "w:customXml",
16931
+ "w:sdt",
16932
+ "w:sdtContent",
16933
+ "w:fldSimple",
16934
+ "w:dir",
16935
+ "w:bdo"
16936
+ ]);
16937
+ /** The text an element in a run stands for, such as `\t` for a tab. A page or column break isn't text */
16938
+ var textOfRunContent = (element) => {
16939
+ switch (nameOf$2(element)) {
16940
+ case "w:t": return childrenOf(element).filter((child) => typeof child === "string").join("");
16941
+ case "w:tab": return " ";
16942
+ case "w:br": return [void 0, "textWrapping"].includes(attributeOf(element, "w:type")) ? "\n" : "";
16943
+ case "w:cr": return "\n";
16944
+ case "w:noBreakHyphen": return "-";
16945
+ default: return "";
16946
+ }
16947
+ };
16948
+ /** The text of a paragraph. Of a field, only its result is text, not its instruction */
16949
+ var textOf = (paragraph) => {
16950
+ const fields = [];
16951
+ const read = (element) => {
16952
+ const name = nameOf$2(element);
16953
+ if (name !== void 0 && TEXT_CONTAINERS.has(name)) return childrenOf(element).map(read).join("");
16954
+ if (name === "w:fldChar") {
16955
+ const type = attributeOf(element, "w:fldCharType");
16956
+ if (type === "begin") fields.push(false);
16957
+ else if (type === "separate") fields[fields.length - 1] = true;
16958
+ else fields.pop();
16959
+ return "";
16960
+ }
16961
+ return fields.every(Boolean) ? textOfRunContent(element) : "";
16962
+ };
16963
+ return childrenOf(paragraph).map(read).join("");
16964
+ };
16965
+ /** The bookmarks started and ended in an element, in order */
16966
+ var bookmarkMarksOf = (element) => {
16967
+ const name = nameOf$2(element);
16968
+ if (name === "w:bookmarkStart") return [{
16969
+ start: true,
16970
+ id: attributeOf(element, "w:id"),
16971
+ name: attributeOf(element, "w:name")
16972
+ }];
16973
+ if (name === "w:bookmarkEnd") return [{
16974
+ start: false,
16975
+ id: attributeOf(element, "w:id")
16976
+ }];
16977
+ return name === void 0 || name === "_attr" ? [] : childrenOf(element).flatMap(bookmarkMarksOf);
16978
+ };
16979
+ /**
16980
+ * The names of the bookmarks each paragraph is in, for the `\b` switch: those open where it starts, followed through the
16981
+ * body, and those that start in it.
16982
+ */
16983
+ var bookmarksOf = (paragraphs) => {
16984
+ const open = /* @__PURE__ */ new Map();
16985
+ return paragraphs.map((paragraph) => {
16986
+ const marks = bookmarkMarksOf(paragraph);
16987
+ const names = /* @__PURE__ */ new Set([...open.values(), ...marks.flatMap((mark) => mark.start ? [mark.name] : [])]);
16988
+ for (const mark of marks) if (mark.start) open.set(mark.id, mark.name);
16989
+ else open.delete(mark.id);
16990
+ return names;
16991
+ });
16992
+ };
16993
+ /** The details of each paragraph that could be a heading. The bookmarks it is in are only followed when needed */
16994
+ var paragraphDetailsOf = (paragraphs, followBookmarks) => {
16995
+ const bookmarks = followBookmarks ? bookmarksOf(paragraphs) : [];
16996
+ return paragraphs.map((element, index) => {
16997
+ var _bookmarks$index;
16998
+ const properties = childOf(element, "w:pPr");
16999
+ return {
17000
+ element,
17001
+ styleId: attributeOf(childOf(properties, "w:pStyle"), "w:val"),
17002
+ outlineLevel: numberAttributeOf(childOf(properties, "w:outlineLvl"), "w:val"),
17003
+ text: textOf(element),
17004
+ bookmarks: (_bookmarks$index = bookmarks[index]) !== null && _bookmarks$index !== void 0 ? _bookmarks$index : /* @__PURE__ */ new Set()
17005
+ };
17006
+ });
17007
+ };
17008
+ /** The document's paragraph styles, by id, read from the styles as they are written */
17009
+ var stylesOf = (context) => {
17010
+ var _context$file;
17011
+ 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);
17012
+ 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"), {
17013
+ name: attributeOf(childOf(style, "w:name"), "w:val"),
17014
+ basedOn: attributeOf(childOf(style, "w:basedOn"), "w:val"),
17015
+ outlineLevel: numberAttributeOf(childOf(childOf(style, "w:pPr"), "w:outlineLvl"), "w:val")
17016
+ }]));
17017
+ };
17018
+ /** A range such as `1-3` */
17019
+ var parseRange = (range) => {
17020
+ const match = /^\s*(\d+)\s*-\s*(\d+)\s*$/.exec(range);
17021
+ return match ? [Number(match[1]), Number(match[2])] : void 0;
17022
+ };
17023
+ var isWithin = (level, [from, to]) => level >= from && level <= to;
17024
+ /** 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 */
17025
+ var headingLevelOf = (styleId, styles) => {
17026
+ var _styles$get$name, _styles$get;
17027
+ if (styleId === void 0) return;
17028
+ 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);
17029
+ return match ? Number(match[1]) : void 0;
17030
+ };
17031
+ /**
17032
+ * 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
17033
+ * its heading's. Following the styles it is based on stops after as many as there are, in case they loop.
17034
+ */
17035
+ var styleOutlineLevelOf = (styleId, styles, depth = 0) => {
17036
+ var _style$outlineLevel;
17037
+ if (styleId === void 0 || depth > styles.size) return;
17038
+ const style = styles.get(styleId);
17039
+ const heading = headingLevelOf(styleId, styles);
17040
+ 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;
17041
+ };
17042
+ /**
17043
+ * Reads the heading level of the document's paragraphs, as the `\s` switch of a SEQ field follows it: the level of a
17044
+ * paragraph in a built-in heading style, Heading 1 to Heading 9. A paragraph whose outline level is another, or that has
17045
+ * one without a heading style, is `"unclear"`, as which of the two Word follows hasn't been checked. Other paragraphs
17046
+ * are undefined.
17047
+ */
17048
+ var headingLevels = (context) => {
17049
+ const styles = stylesOf(context);
17050
+ return (paragraph) => {
17051
+ const properties = childOf(paragraph, "w:pPr");
17052
+ const styleId = attributeOf(childOf(properties, "w:pStyle"), "w:val");
17053
+ const heading = headingLevelOf(styleId, styles);
17054
+ const outlineLevel = outlineLevelOf({
17055
+ styleId,
17056
+ outlineLevel: numberAttributeOf(childOf(properties, "w:outlineLvl"), "w:val")
17057
+ }, styles);
17058
+ const outline = outlineLevel === void 0 || outlineLevel >= 9 ? void 0 : outlineLevel + 1;
17059
+ if (heading !== void 0 && (outline === void 0 || outline === heading)) return heading;
17060
+ return outline === void 0 ? void 0 : "unclear";
17061
+ };
17062
+ };
17063
+ /** A paragraph's outline level, from 0: its own, or else its style's */
17064
+ var outlineLevelOf = (paragraph, styles) => {
17065
+ var _paragraph$outlineLev;
17066
+ return (_paragraph$outlineLev = paragraph.outlineLevel) !== null && _paragraph$outlineLev !== void 0 ? _paragraph$outlineLev : styleOutlineLevelOf(paragraph.styleId, styles);
17067
+ };
17068
+ /** The level a table of contents gives a paragraph, or undefined when it doesn't include it */
17069
+ var levelIn = (properties, paragraph, styles) => {
17070
+ var _styles$get2;
17071
+ const { entriesFromBookmark, headingStyleRange, stylesWithLevels = [], useAppliedParagraphOutlineLevel } = properties;
17072
+ if (paragraph.text.trim() === "" || entriesFromBookmark && !paragraph.bookmarks.has(entriesFromBookmark)) return;
17073
+ 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());
17074
+ const listed = stylesWithLevels.find((style) => names.includes(style.styleName.toLowerCase()));
17075
+ if (listed) return listed.level;
17076
+ const namesItsEntries = Boolean(headingStyleRange) || stylesWithLevels.length > 0 || Boolean(useAppliedParagraphOutlineLevel) || Boolean(properties.tcFieldIdentifier) || Boolean(properties.tcFieldLevelRange) || Boolean(properties.captionLabel) || Boolean(properties.captionLabelIncludingNumbers);
17077
+ const headingRange = headingStyleRange ? parseRange(headingStyleRange) : namesItsEntries ? void 0 : [1, 9];
17078
+ const heading = headingLevelOf(paragraph.styleId, styles);
17079
+ if (headingRange && heading !== void 0 && isWithin(heading, headingRange)) return heading;
17080
+ const outlineLevel = useAppliedParagraphOutlineLevel ? outlineLevelOf(paragraph, styles) : void 0;
17081
+ return outlineLevel !== void 0 && isWithin(outlineLevel + 1, headingRange !== null && headingRange !== void 0 ? headingRange : [1, 9]) ? outlineLevel + 1 : void 0;
17082
+ };
17083
+ /** The runs of an entry's title. Tabs and line breaks are kept only when the table of contents keeps them (\w and \x) */
17084
+ var titleRunsOf = (title, properties) => {
17085
+ const text = properties.preserveTabInEntries ? title : title.replace(/\t/g, " ");
17086
+ return (properties.preserveNewLineInEntries ? text.split("\n") : [text.replace(/\n/g, " ")]).map((line, index) => new TextRun({
17087
+ break: index > 0 ? 1 : void 0,
17088
+ children: line.split(" ").flatMap((part, partIndex) => [...partIndex > 0 ? [new Tab()] : [], ...part === "" ? [] : [part]])
17089
+ }));
17090
+ };
17091
+ /**
17092
+ * The paragraph style of the entries at a level: the built-in TOC style, found by its name, "toc 1" to "toc 9". When
17093
+ * the document doesn't have it, the entries are indented as Word's are, 220 twips a level.
17094
+ */
17095
+ var entryStyleOf = (level, styles) => {
17096
+ var _find;
17097
+ const named = (_find = [...styles].find(([, style]) => {
17098
+ var _style$name;
17099
+ return ((_style$name = style.name) === null || _style$name === void 0 ? void 0 : _style$name.toLowerCase()) === `toc ${level}`;
17100
+ })) === null || _find === void 0 ? void 0 : _find[0];
17101
+ const id = named !== null && named !== void 0 ? named : `TOC${level}`;
17102
+ return named !== void 0 || styles.has(id) || level === 1 ? { id } : {
17103
+ id,
17104
+ indent: (level - 1) * 220
17105
+ };
17106
+ };
17107
+ /** The formatted content of a table of contents with its entries */
17108
+ var contentOf = ({ properties, beginDirty, textWidth }, entries, styles, context) => {
17109
+ var _parseRange;
17110
+ const withoutPageNumbers = properties.pageNumbersEntryLevelsRange ? (_parseRange = parseRange(properties.pageNumbersEntryLevelsRange)) !== null && _parseRange !== void 0 ? _parseRange : [1, 9] : void 0;
17111
+ const content = new StructuredDocumentTagContent();
17112
+ entries.forEach((entry, index) => {
17113
+ const hasPageNumber = withoutPageNumbers === void 0 || !isWithin(entry.level, withoutPageNumbers);
17114
+ const children = [...titleRunsOf(entry.title, properties), ...hasPageNumber ? [new TextRun({ children: [properties.entryAndPageNumberSeparator || new Tab()] }), new PageReference(entry.bookmark, { hyperlink: properties.hyperlink })] : []];
17115
+ const style = entryStyleOf(entry.level, styles);
17116
+ content.addChildElement(new Paragraph({
17117
+ style: style.id,
17118
+ indent: style.indent === void 0 ? void 0 : { left: style.indent },
17119
+ tabStops: [{
17120
+ type: "right",
17121
+ position: textWidth,
17122
+ leader: "dot"
17123
+ }],
17124
+ children: [...index === 0 ? [new Run({ children: [
17125
+ beginOf(beginDirty),
17126
+ new FieldInstruction(properties),
17127
+ createSeparate()
17128
+ ] })] : [], ...properties.hyperlink ? [new InternalHyperlink({
17129
+ anchor: entry.bookmark,
17130
+ children
17131
+ })] : children]
17132
+ }));
17133
+ });
17134
+ content.addChildElement(new Paragraph({ children: [new Run({ children: [createEnd()] })] }));
17135
+ return content.prepForXml(context);
17136
+ };
17137
+ /** Puts a bookmark around the content of a formatted paragraph */
17138
+ var bookmark = (paragraph, name, id, context) => {
17139
+ const children = childrenOf(paragraph);
17140
+ const start = children.findIndex((child) => nameOf$2(child) === "w:pPr") + 1;
17141
+ paragraph["w:p"] = [
17142
+ ...children.slice(0, start),
17143
+ new BookmarkStart(name, id).prepForXml(context),
17144
+ ...children.slice(start),
17145
+ new BookmarkEnd(id).prepForXml(context)
17146
+ ];
17147
+ };
17148
+ /**
17149
+ * Fills in the tables of contents in a formatted body from its headings, and bookmarks the headings they list. A
17150
+ * table of contents that doesn't list any heading is left empty, for Word to fill in.
17151
+ */
17152
+ var fillTablesOfContents = (body, context, bookmarkIds) => {
17153
+ const blocks = blocksOf(childrenOf(body));
17154
+ const tables = blocks.flatMap((block) => {
17155
+ const options = writtenTables.get(block);
17156
+ return options ? [[block, options]] : [];
17157
+ });
17158
+ if (tables.length === 0) return;
17159
+ const styles = stylesOf(context);
17160
+ const followBookmarks = tables.some(([, { properties }]) => Boolean(properties.entriesFromBookmark));
17161
+ const headings = paragraphDetailsOf(blocks.filter((block) => nameOf$2(block) === "w:p"), followBookmarks).map((paragraph) => ({
17162
+ paragraph,
17163
+ levels: tables.map(([, { properties }]) => levelIn(properties, paragraph, styles))
17164
+ })).filter(({ levels }) => levels.some((level) => level !== void 0)).map((heading, index) => _objectSpread2(_objectSpread2({}, heading), {}, { id: bookmarkIds.get(index) }));
17165
+ for (const { paragraph, id } of headings) bookmark(paragraph.element, `_Toc${id}`, id, context);
17166
+ tables.forEach(([table, options], index) => {
17167
+ const entries = headings.flatMap(({ paragraph, levels, id }) => {
17168
+ const level = levels[index];
17169
+ return level === void 0 ? [] : [{
17170
+ title: paragraph.text,
17171
+ level,
17172
+ bookmark: `_Toc${id}`
17173
+ }];
17174
+ });
17175
+ if (entries.length === 0) return;
17176
+ table["w:sdt"] = childrenOf(table).map((child) => nameOf$2(child) === "w:sdtContent" ? contentOf(options, entries, styles, context) : child);
17177
+ });
17178
+ };
17179
+ //#endregion
17180
+ //#region src/file/document/body/sequence-numbers.ts
17181
+ /**
17182
+ * Caption numbers written into the SEQ fields of a document, such as the 2 of "Figure 2", when the document is given page
17183
+ * numbers.
17184
+ *
17185
+ * A SEQ field (`SequentialIdentifier`) shows how many SEQ fields of its identifier, such as "Figure", there are up to and
17186
+ * including it, so the number doesn't depend on how the pages are laid out. Its switches change the count: `\r 5` starts
17187
+ * it again from 5, `\c` repeats the number of the one before, `\s 1` starts it again after each Heading 1, `\h` hides the
17188
+ * number, and `\* ROMAN` writes it in roman numerals. `docx` writes SEQ fields dirty, for Word to number when it opens the
17189
+ * document, which makes Word ask to update the fields. When the document is given page numbers, each is written clean
17190
+ * with its number, counted as Word counts it. What Word does was read from its PDF of `scripts/layout-probes/word-seq.ts`.
17191
+ *
17192
+ * Word counts the SEQ fields of the body, those in text boxes and hidden text too, in order, and counts an identifier in
17193
+ * any capitals, or in quotes, as the same one. It writes the SEQ fields of headers, footers, footnotes and endnotes as an
17194
+ * error, "Error! Main Document Only.", and doesn't count them with the body's.
17195
+ *
17196
+ * Where Word's count isn't known, the field is left blank rather than given a number that could be wrong: a switch it
17197
+ * doesn't follow, a SEQ field in deleted text, and every SEQ field of an identifier that also has SEQ fields in a comment.
17198
+ * The fields of its identifier after one whose number isn't known are left blank too, until one starts the count again
17199
+ * with `\r`. A number in a format not followed is left blank, but the count goes on.
17200
+ *
17201
+ * @module
17202
+ */
17203
+ var IDENTIFIER = new RegExp("^\\p{L}[\\p{L}\\p{N}_]*$", "u");
17204
+ /** Reads the switches of a SEQ field, and a bookmark before them, or undefined when one of them isn't followed */
17205
+ var sequenceOf = (switches) => {
17206
+ var _step, _format;
17207
+ let step;
17208
+ let hidden = false;
17209
+ let format;
17210
+ let caseFormat = false;
17211
+ let picture = false;
17212
+ for (let index = 0; index < switches.length; index++) {
17213
+ var _switches, _next;
17214
+ const name = switches[index];
17215
+ const argument = (_switches = switches[index + 1]) !== null && _switches !== void 0 ? _switches : "";
17216
+ let next;
17217
+ if (index === 0 && !name.startsWith("\\")) next = { type: "bookmark" };
17218
+ else if (name === "\\c" || name === "\\n") next = { type: name === "\\c" ? "repeat" : "next" };
17219
+ else if ((name === "\\r" || name === "\\s") && /^\d+$/.test(argument)) {
17220
+ index++;
17221
+ next = name === "\\r" ? {
17222
+ type: "reset",
17223
+ to: Number(argument)
17224
+ } : {
17225
+ type: "heading",
17226
+ level: Number(argument)
17227
+ };
17228
+ } else if (name === "\\h") hidden = true;
17229
+ else if (name === "\\#" && index + 1 < switches.length) {
17230
+ index++;
17231
+ picture = true;
17232
+ } else if (name === "\\*" && index + 1 < switches.length) {
17233
+ const value = switches[++index];
17234
+ if (CASE_FORMATS.has(value.toLowerCase())) caseFormat = true;
17235
+ else if (!PLAIN_FORMATS.has(value.toLowerCase())) {
17236
+ if (format !== void 0) return;
17237
+ format = value;
17238
+ }
17239
+ } else return;
17240
+ if (next && step) return;
17241
+ step = (_next = next) !== null && _next !== void 0 ? _next : step;
17242
+ }
17243
+ if ((step === null || step === void 0 ? void 0 : step.type) === "bookmark" && switches.length > 1) return;
17244
+ const written = !picture && !(caseFormat && format !== void 0 && format.toLowerCase() !== "arabic");
17245
+ return {
17246
+ step: (_step = step) !== null && _step !== void 0 ? _step : { type: "next" },
17247
+ hidden: hidden && format === void 0,
17248
+ format: written ? (_format = format) !== null && _format !== void 0 ? _format : "ARABIC" : ""
17249
+ };
17250
+ };
17251
+ /** Reads a SEQ field's instruction, or undefined when the field isn't a SEQ field */
17252
+ var sequenceFieldOf = (instruction) => {
17253
+ var _match$1$match;
17254
+ const match = new RegExp("^\\s*SEQ\\b(.*)$", "is").exec(instruction);
17255
+ if (!match) return;
17256
+ const [written, ...switches] = (_match$1$match = match[1].match(/"[^"]*"|\S+/g)) !== null && _match$1$match !== void 0 ? _match$1$match : [];
17257
+ if (written === void 0) return {};
17258
+ const identifier = written.replace(/^"(.*)"$/, "$1");
17259
+ return IDENTIFIER.test(identifier) ? {
17260
+ identifier,
17261
+ sequence: sequenceOf(switches)
17262
+ } : { identifier };
17263
+ };
17264
+ /** Whether a field's instruction is that of a SEQ field */
17265
+ var isSequenceField = (instruction) => sequenceFieldOf(instruction) !== void 0;
17266
+ /** The identifier, in small letters, of each SEQ field in the formatted elements */
17267
+ var identifiersIn = (element) => {
17268
+ if (typeof element !== "object" || element === null) return [];
17269
+ if (Array.isArray(element)) return element.flatMap(identifiersIn);
17270
+ return Object.entries(element).flatMap(([name, content]) => {
17271
+ return [...(name === "w:instrText" && Array.isArray(content) ? content : name === "_attr" ? [content["w:instr"]] : []).flatMap((instruction) => {
17272
+ const field = typeof instruction === "string" ? sequenceFieldOf(instruction) : void 0;
17273
+ return (field === null || field === void 0 ? void 0 : field.identifier) === void 0 ? [] : [field.identifier.toLowerCase()];
17274
+ }), ...identifiersIn(content)];
17275
+ });
17276
+ };
17277
+ /** The identifiers, in small letters, of the SEQ fields in the document's comments, whose count in Word isn't known */
17278
+ var identifiersInCommentsOf = (context) => {
17279
+ var _context$file;
17280
+ const comments = (_context$file = context.file) === null || _context$file === void 0 ? void 0 : _context$file.Comments;
17281
+ if (!comments) return /* @__PURE__ */ new Set();
17282
+ const wrapper = {
17283
+ View: comments,
17284
+ Relationships: comments.Relationships
17285
+ };
17286
+ return new Set(identifiersIn(comments.prepForXml(_objectSpread2(_objectSpread2({}, context), {}, {
17287
+ viewWrapper: wrapper,
17288
+ stack: []
17289
+ }))));
17290
+ };
17291
+ /** Counts the SEQ fields of a document's body, in order, as Word counts them */
17292
+ var sequenceNumbering = (context) => {
17293
+ const levelOf = headingLevels(context);
17294
+ const numbers = /* @__PURE__ */ new Map();
17295
+ const counted = /* @__PURE__ */ new Map();
17296
+ const headingsAt = [];
17297
+ let unclearAt = -1;
17298
+ let paragraph = -1;
17299
+ let unknown;
17300
+ /**
17301
+ * The number of a field that starts the count again after headings of a level or a higher one (`\s`): the number of
17302
+ * fields of its identifier since the last of them, with it, as Word counts them. It isn't known when a paragraph
17303
+ * whose level isn't clear came after that heading, or a field since it whose number didn't follow as the next one's
17304
+ */
17305
+ const afterHeading = (key, level) => {
17306
+ var _counted$get;
17307
+ const headingAt = Math.max(-1, ...headingsAt.slice(1, level + 1).filter((at) => at !== void 0));
17308
+ const since = ((_counted$get = counted.get(key)) !== null && _counted$get !== void 0 ? _counted$get : []).filter((field) => field.paragraph >= headingAt);
17309
+ 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);
17310
+ if (unclearAt > headingAt || !followed) return;
17311
+ return since.length + 1;
17312
+ };
17313
+ return {
17314
+ startParagraph: (element) => {
17315
+ paragraph++;
17316
+ const level = levelOf(element);
17317
+ if (level === "unclear") unclearAt = paragraph;
17318
+ else if (level !== void 0) headingsAt[level] = paragraph;
17319
+ },
17320
+ numberOf: (instruction, place) => {
17321
+ var _unknown, _counted$get2, _numberWriterOf;
17322
+ const { identifier, sequence } = sequenceFieldOf(instruction);
17323
+ if (identifier === void 0 || place === "fallback") return;
17324
+ (_unknown = unknown) !== null && _unknown !== void 0 || (unknown = identifiersInCommentsOf(context));
17325
+ const key = identifier.toLowerCase();
17326
+ if ((sequence === null || sequence === void 0 ? void 0 : sequence.step.type) === "bookmark" && place === "counted" && !unknown.has(key)) return;
17327
+ const before = numbers.has(key) ? numbers.get(key) : 0;
17328
+ const step = unknown.has(key) || place === "deleted" ? void 0 : sequence === null || sequence === void 0 ? void 0 : sequence.step;
17329
+ 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;
17330
+ numbers.set(key, value);
17331
+ counted.set(key, [...(_counted$get2 = counted.get(key)) !== null && _counted$get2 !== void 0 ? _counted$get2 : [], _objectSpread2({ paragraph }, value === void 0 ? {} : { step })]);
17332
+ return value === void 0 || sequence === void 0 ? void 0 : sequence.hidden ? "" : (_numberWriterOf = numberWriterOf(sequence.format)) === null || _numberWriterOf === void 0 ? void 0 : _numberWriterOf(value);
17333
+ }
17334
+ };
17335
+ };
17336
+ //#endregion
17337
+ //#region src/file/document/body/page-numbers.ts
17338
+ /**
17339
+ * Page numbers written into the fields of a document that show them, when it is written, from an estimate of its pages.
17340
+ *
17341
+ * A page reference is a PAGEREF field, such as the page number of an entry in a table of contents, and the numbers of
17342
+ * pages of the document and of a section are NUMPAGES and SECTIONPAGES fields. Word works their results out when it
17343
+ * updates the fields, or lays the pages out, and until then, and in applications that don't, the fields show the results
17344
+ * they were written with. `docx` doesn't lay out pages, so it writes the results empty, unless the document is given a
17345
+ * {@link PageNumberEstimator}, such as `estimatePageNumbers` from `docx/layout`. Then, once the body is written, each of
17346
+ * those fields in the body, and then in the headers and footers, is given the number the estimator worked out.
17347
+ *
17348
+ * Page references and tables of contents are written dirty, so Word updates them when it opens the document, and asks
17349
+ * "This document contains fields that may refer to other files. Do you want to update the fields in this document?".
17350
+ * When the document is given page numbers, they are written clean, so Word shows them as they are and doesn't ask. A
17351
+ * page number the estimator didn't work out is left blank, until the fields are updated. So are SEQ fields, the numbers
17352
+ * of captions, which are given their numbers then too.
17353
+ *
17354
+ * @module
17355
+ */
17356
+ var nameOf$1 = (element) => {
17357
+ const name = typeof element === "object" && element !== null && !Array.isArray(element) ? Object.keys(element)[0] : void 0;
17358
+ return name === "_attr" ? void 0 : name;
17359
+ };
17360
+ var textElement = (text) => ({ "w:t": [{ _attr: { "xml:space": "preserve" } }, text] });
17361
+ /** The elements docx formats to write a document */
17362
+ var FORMATTED = {
17363
+ nameOf: nameOf$1,
17364
+ contentOf: (element) => {
17365
+ const content = element[nameOf$1(element)];
17366
+ return Array.isArray(content) ? content : void 0;
17367
+ },
17368
+ attributeOf: (element, attribute) => {
17369
+ var _holder$_attr;
17370
+ const content = element[nameOf$1(element)];
17371
+ const holder = Array.isArray(content) ? content.find((child) => typeof child === "object" && child !== null && "_attr" in child) : content;
17372
+ return holder === null || holder === void 0 || (_holder$_attr = holder._attr) === null || _holder$_attr === void 0 ? void 0 : _holder$_attr[attribute];
17373
+ },
17374
+ textOf: (element) => FORMATTED.contentOf(element).filter((part) => typeof part === "string").join(""),
17375
+ textElement,
17376
+ writeClean: (begin) => {
17377
+ if (isDirtyWithoutPageNumbers(begin)) {
17378
+ const attributes = begin["w:fldChar"]._attr;
17379
+ begin["w:fldChar"] = { _attr: Object.fromEntries(Object.entries(attributes).filter(([key]) => key !== "w:dirty")) };
17380
+ }
17381
+ },
17382
+ setSimpleFieldResult: (element, text) => {
17383
+ const content = element["w:fldSimple"];
17384
+ element["w:fldSimple"] = [...(Array.isArray(content) ? content : [content]).filter((child) => typeof child === "object" && child !== null && "_attr" in child), { "w:r": [textElement(text)] }];
17385
+ }
17386
+ };
17387
+ /** The estimate of each document's pages, and the numbers of pages its headers and footers show, once its body is written */
17388
+ var estimates = /* @__PURE__ */ new WeakMap();
17389
+ /**
17390
+ * Writes the numbers of the SEQ fields of a formatted body into them, counted as Word counts them (see
17391
+ * {@link sequenceNumbering}), and writes them clean, whether or not their numbers were worked out. It is done after its
17392
+ * tables of contents are filled in from its headings, as Word leaves a heading's SEQ number out of its entry.
17393
+ */
17394
+ var fillSequenceNumbers = (body, context) => {
17395
+ const { startParagraph, numberOf } = sequenceNumbering(context);
17396
+ fillSequenceFields(FORMATTED, body, {
17397
+ beforeParagraph: (paragraph) => startParagraph(paragraph),
17398
+ resultOf: (instruction, within) => isSequenceField(instruction) ? numberOf(instruction, within) : void 0
17399
+ });
17400
+ };
17401
+ /**
17402
+ * Writes the page numbers the estimator works out into the fields of a formatted body that show them: the PAGEREF fields
17403
+ * in its tables of contents and elsewhere, those with `\p` and in number formats of their own, and its NUMPAGES and
17404
+ * SECTIONPAGES fields. A field whose number the estimator didn't work out is left as it is. Page references and tables
17405
+ * of contents are written clean, whether or not their numbers were worked out. The estimate is kept for the document's
17406
+ * headers and footers.
17407
+ */
17408
+ var fillPageNumbers = (body, context, estimator) => {
17409
+ const estimate = estimator(body, context);
17410
+ const partPageCounts = fillBodyFields(FORMATTED, body, estimate, { blank: false });
17411
+ if (context.file) estimates.set(context.file, {
17412
+ estimate,
17413
+ partPageCounts
17414
+ });
17415
+ };
17416
+ /**
17417
+ * Writes the page numbers worked out for the document a header, footer, footnote, endnote or comment is in into the
17418
+ * fields of the formatted part that show them, once the document's body is written. Its page references and SEQ fields
17419
+ * are written clean, and its SEQ fields are left blank: Word writes them as an error, "Error! Main Document Only.".
17420
+ *
17421
+ * @param part - The formatted part, if it has anything to write
17422
+ * @param context - The context it was formatted in, with the document it is in
17423
+ * @param referenceId - The number of the relationship to a header or footer. The SECTIONPAGES fields of the other parts
17424
+ * are left as they are
17425
+ */
17426
+ var fillPartPageNumbers = (part, context, referenceId) => {
17427
+ const written = context.file && estimates.get(context.file);
17428
+ if (!part || !written) return;
17429
+ const sectionPageCount = referenceId === void 0 ? void 0 : written.partPageCounts.get(`rId${referenceId}`);
17430
+ const notes = "w:footnotes" in part || "w:endnotes" in part;
17431
+ fillPartFields(FORMATTED, part, written.estimate, {
17432
+ blank: false,
17433
+ sectionPageCount,
17434
+ notes
17435
+ });
17436
+ };
17437
+ //#endregion
16340
17438
  //#region src/file/relationships/attributes.ts
16341
17439
  /**
16342
17440
  * Attributes for the Relationships element.
@@ -16386,7 +17484,7 @@ EXTERNAL: "External" };
16386
17484
  * );
16387
17485
  * ```
16388
17486
  */
16389
- var Relationships = class extends XmlComponent {
17487
+ var Relationships = class Relationships extends XmlComponent {
16390
17488
  constructor() {
16391
17489
  super("Relationships");
16392
17490
  this.root.push(new RelationshipsAttributes({ xmlns: "http://schemas.openxmlformats.org/package/2006/relationships" }));
@@ -16403,6 +17501,20 @@ EXTERNAL: "External" };
16403
17501
  this.root.push(createRelationship(`rId${id}`, type, target, targetMode));
16404
17502
  }
16405
17503
  /**
17504
+ * Creates a copy of the relationships given. Relationships added to the copy aren't added to them, so the compiler
17505
+ * adds the ones it writes for a part, such as to its images, to a copy, and packing a document again doesn't add
17506
+ * them a second time.
17507
+ *
17508
+ * Static, as `IContext` is public and has `Relationships`, so a new instance member would change the public API.
17509
+ *
17510
+ * @param relationships - The relationships to copy
17511
+ */
17512
+ static copy(relationships) {
17513
+ const copy = new Relationships();
17514
+ copy.root.push(...relationships.root.slice(1));
17515
+ return copy;
17516
+ }
17517
+ /**
16406
17518
  * Gets the count of relationships in this collection.
16407
17519
  * Excludes the attributes element from the count.
16408
17520
  */
@@ -16413,6 +17525,17 @@ EXTERNAL: "External" };
16413
17525
  //#endregion
16414
17526
  //#region src/file/paragraph/run/comment-run.ts
16415
17527
  /**
17528
+ * Comment module for WordprocessingML documents.
17529
+ *
17530
+ * This module provides support for comments (annotations) in documents. Comments
17531
+ * consist of comment ranges (start/end markers), comment references, and the
17532
+ * actual comment content.
17533
+ *
17534
+ * Reference: http://officeopenxml.com/WPrun.php
17535
+ *
17536
+ * @module
17537
+ */
17538
+ /**
16416
17539
  * @internal
16417
17540
  */
16418
17541
  var CommentAttributes = class extends XmlAttributeComponent {
@@ -16442,6 +17565,7 @@ EXTERNAL: "External" };
16442
17565
  constructor(..._args3) {
16443
17566
  super(..._args3);
16444
17567
  _defineProperty(this, "xmlKeys", {
17568
+ "xmlns:wpc": "xmlns:wpc",
16445
17569
  "xmlns:cx": "xmlns:cx",
16446
17570
  "xmlns:cx1": "xmlns:cx1",
16447
17571
  "xmlns:cx2": "xmlns:cx2",
@@ -16682,6 +17806,7 @@ EXTERNAL: "External" };
16682
17806
  _defineProperty(this, "isEmpty", void 0);
16683
17807
  this.isEmpty = children.length === 0;
16684
17808
  this.root.push(new RootCommentsAttributes({
17809
+ "xmlns:wpc": "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas",
16685
17810
  "xmlns:cx": "http://schemas.microsoft.com/office/drawing/2014/chartex",
16686
17811
  "xmlns:cx1": "http://schemas.microsoft.com/office/drawing/2015/9/8/chartex",
16687
17812
  "xmlns:cx2": "http://schemas.microsoft.com/office/drawing/2015/10/21/chartex",
@@ -16750,6 +17875,15 @@ EXTERNAL: "External" };
16750
17875
  get IsEmpty() {
16751
17876
  return this.isEmpty;
16752
17877
  }
17878
+ /**
17879
+ * Formats the comments, with the page numbers worked out for their document written into their fields, when the
17880
+ * document's body is written with an estimate of its pages.
17881
+ */
17882
+ prepForXml(context) {
17883
+ const xml = super.prepForXml(context);
17884
+ fillPartPageNumbers(xml, context);
17885
+ return xml;
17886
+ }
16753
17887
  };
16754
17888
  //#endregion
16755
17889
  //#region src/file/paragraph/run/comments-extended.ts
@@ -18048,7 +19182,7 @@ MAX: 9026 };
18048
19182
  * });
18049
19183
  * ```
18050
19184
  */
18051
- var Bookmark = class {
19185
+ var Bookmark = class Bookmark {
18052
19186
  constructor(options) {
18053
19187
  _defineProperty(this, "start", void 0);
18054
19188
  _defineProperty(this, "children", void 0);
@@ -18058,6 +19192,19 @@ MAX: 9026 };
18058
19192
  this.children = options.children;
18059
19193
  this.end = new BookmarkEnd(linkId);
18060
19194
  }
19195
+ /**
19196
+ * The components written in this bookmark's place: its start, its children and its end. A bookmark in its
19197
+ * children is written the same way, so one bookmark can hold another.
19198
+ *
19199
+ * @internal
19200
+ */
19201
+ get writtenAs() {
19202
+ return [
19203
+ this.start,
19204
+ ...this.children.flatMap((child) => child instanceof Bookmark ? child.writtenAs : [child]),
19205
+ this.end
19206
+ ];
19207
+ }
18061
19208
  };
18062
19209
  /**
18063
19210
  * Represents the start marker of a bookmark range.
@@ -18065,6 +19212,10 @@ MAX: 9026 };
18065
19212
  * This element marks the beginning of a bookmarked region in the document.
18066
19213
  * It must be paired with a corresponding BookmarkEnd element with the same id.
18067
19214
  *
19215
+ * The id must be unique in the document. `Bookmark` takes its ids from
19216
+ * `bookmarkUniqueNumericId`, so take this one from it too, or it can be the
19217
+ * same as a `Bookmark`'s.
19218
+ *
18068
19219
  * Reference: http://officeopenxml.com/WPbookmark.php
18069
19220
  *
18070
19221
  * ## XSD Schema
@@ -18082,7 +19233,10 @@ MAX: 9026 };
18082
19233
  *
18083
19234
  * @example
18084
19235
  * ```typescript
18085
- * new BookmarkStart("myBookmark", 1);
19236
+ * // A bookmark across two paragraphs
19237
+ * const id = bookmarkUniqueNumericId();
19238
+ * new Paragraph({ children: [new BookmarkStart("myBookmark", id), new TextRun("First")] });
19239
+ * new Paragraph({ children: [new TextRun("Last"), new BookmarkEnd(id)] });
18086
19240
  * ```
18087
19241
  */
18088
19242
  var BookmarkStart = class extends XmlComponent {
@@ -18099,7 +19253,8 @@ MAX: 9026 };
18099
19253
  * Represents the end marker of a bookmark range.
18100
19254
  *
18101
19255
  * This element marks the end of a bookmarked region in the document.
18102
- * It must be paired with a corresponding BookmarkStart element with the same id.
19256
+ * It must be paired with a corresponding BookmarkStart element with the same id,
19257
+ * taken from `bookmarkUniqueNumericId` (see `BookmarkStart`).
18103
19258
  *
18104
19259
  * Reference: http://officeopenxml.com/WPbookmark.php
18105
19260
  *
@@ -18118,7 +19273,9 @@ MAX: 9026 };
18118
19273
  *
18119
19274
  * @example
18120
19275
  * ```typescript
18121
- * new BookmarkEnd(1);
19276
+ * const id = bookmarkUniqueNumericId();
19277
+ * new BookmarkStart("myBookmark", id);
19278
+ * new BookmarkEnd(id);
18122
19279
  * ```
18123
19280
  */
18124
19281
  var BookmarkEnd = class extends XmlComponent {
@@ -18292,6 +19449,10 @@ MAX: 9026 };
18292
19449
  * The PAGEREF field displays the page number of the page containing
18293
19450
  * the specified bookmark, useful for cross-references like "see page 5".
18294
19451
  *
19452
+ * It is written dirty, so Word fills in the page number when it opens the document, after asking to. When the
19453
+ * document is given `pageNumbers`, it is written clean, with the number they work out, or blank when they couldn't,
19454
+ * and Word doesn't ask.
19455
+ *
18295
19456
  * @publicApi
18296
19457
  *
18297
19458
  * @example
@@ -18312,8 +19473,9 @@ MAX: 9026 };
18312
19473
  var PageReference = class extends Run {
18313
19474
  constructor(bookmarkId, options = {}) {
18314
19475
  super({ children: [
18315
- createBegin(true),
19476
+ createBeginDirtyWithoutPageNumbers(),
18316
19477
  new PageReferenceFieldInstruction(bookmarkId, options),
19478
+ createSeparate(),
18317
19479
  createEnd()
18318
19480
  ] });
18319
19481
  }
@@ -18828,17 +19990,18 @@ MAX: 9026 };
18828
19990
  //#endregion
18829
19991
  //#region src/file/paragraph/properties.ts
18830
19992
  /**
18831
- * Paragraph properties module for WordprocessingML documents.
18832
- *
18833
- * This module provides the paragraph properties (pPr) element which specifies
18834
- * the formatting applied to a paragraph.
18835
- *
18836
- * Reference: http://officeopenxml.com/WPparagraphProperties.php
18837
- *
18838
- * @see https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_suppressLineNumbers_topic_ID0ECJAO.html
19993
+ * The alignment to write for each side of the page in a right-to-left paragraph.
18839
19994
  *
18840
- * @module
19995
+ * Word and LibreOffice read `w:jc` `left` and `right` as the start and end of the paragraph, the same as
19996
+ * `start` and `end` (ISO/IEC 29500-4 maps the transitional `left` and `right` onto the strict `start` and `end`,
19997
+ * and [MS-OE376] 2.3.1.13 notes the same for Word 2007). So in a `w:bidi` paragraph `left` lands on the right
19998
+ * side of the page. Swapping keeps `AlignmentType.LEFT` and `AlignmentType.RIGHT` on the side of the page they name.
19999
+ * `left` and `right` are written rather than `end` and `start` because Word 2007 does not know `start` and `end`.
18841
20000
  */
20001
+ var RIGHT_TO_LEFT_ALIGNMENTS = {
20002
+ left: "right",
20003
+ right: "left"
20004
+ };
18842
20005
  /**
18843
20006
  * Represents paragraph properties (pPr) in a WordprocessingML document.
18844
20007
  *
@@ -19002,7 +20165,7 @@ MAX: 9026 };
19002
20165
  if (options.spacing) this.push(createSpacing(options.spacing));
19003
20166
  if (options.indent) this.push(createIndent(options.indent));
19004
20167
  if (options.contextualSpacing !== void 0) this.push(new OnOffElement("w:contextualSpacing", options.contextualSpacing));
19005
- if (options.alignment) this.push(createAlignment(options.alignment));
20168
+ if (options.alignment) this.push(createAlignment(options.bidirectional && RIGHT_TO_LEFT_ALIGNMENTS[options.alignment] || options.alignment));
19006
20169
  if (options.outlineLevel !== void 0) this.push(createOutlineLevel(options.outlineLevel));
19007
20170
  if (options.suppressLineNumbers !== void 0) this.push(new OnOffElement("w:suppressLineNumbers", options.suppressLineNumbers));
19008
20171
  if (options.autoSpaceEastAsianText !== void 0) this.push(new OnOffElement("w:autoSpaceDN", options.autoSpaceEastAsianText));
@@ -19018,6 +20181,31 @@ MAX: 9026 };
19018
20181
  this.root.push(item);
19019
20182
  }
19020
20183
  /**
20184
+ * Adds the section properties (`w:sectPr`) of the section this paragraph ends.
20185
+ *
20186
+ * They go after the paragraph's run properties and before its revision (`w:pPrChange`),
20187
+ * the order CT_PPr gives them.
20188
+ *
20189
+ * @param sectionProperties - The properties of the section the paragraph ends
20190
+ */
20191
+ addSectionProperties(sectionProperties) {
20192
+ const revisionIndex = this.root.findIndex((item) => item instanceof ParagraphPropertiesChange);
20193
+ if (revisionIndex === -1) {
20194
+ this.root.push(sectionProperties);
20195
+ return;
20196
+ }
20197
+ this.root.splice(revisionIndex, 0, sectionProperties);
20198
+ }
20199
+ /**
20200
+ * Removes the section properties added with {@link addSectionProperties}.
20201
+ *
20202
+ * @param sectionProperties - The properties of the section to remove
20203
+ */
20204
+ removeSectionProperties(sectionProperties) {
20205
+ const index = this.root.indexOf(sectionProperties);
20206
+ if (index !== -1) this.root.splice(index, 1);
20207
+ }
20208
+ /**
19021
20209
  * Prepares the paragraph properties for XML serialization.
19022
20210
  *
19023
20211
  * This method creates concrete numbering instances for any numbering references
@@ -19045,13 +20233,6 @@ MAX: 9026 };
19045
20233
  //#endregion
19046
20234
  //#region src/file/paragraph/paragraph.ts
19047
20235
  /**
19048
- * Paragraph module for WordprocessingML documents.
19049
- *
19050
- * Reference: http://officeopenxml.com/WPparagraph.php
19051
- *
19052
- * @module
19053
- */
19054
- /**
19055
20236
  * Represents a paragraph in a WordprocessingML document.
19056
20237
  *
19057
20238
  * A paragraph is the primary unit of block-level content in a document and can contain
@@ -19103,9 +20284,7 @@ MAX: 9026 };
19103
20284
  if (options.text) this.root.push(new TextRun(options.text));
19104
20285
  if (options.children) for (const child of options.children) {
19105
20286
  if (child instanceof Bookmark) {
19106
- this.root.push(child.start);
19107
- for (const textRun of child.children) this.root.push(textRun);
19108
- this.root.push(child.end);
20287
+ this.root.push(...child.writtenAs);
19109
20288
  continue;
19110
20289
  }
19111
20290
  this.root.push(child);
@@ -19120,6 +20299,28 @@ MAX: 9026 };
19120
20299
  }
19121
20300
  return super.prepForXml(context);
19122
20301
  }
20302
+ /**
20303
+ * Ends a section at this paragraph by adding the section's properties to the paragraph's properties,
20304
+ * as Word does with the last paragraph of each section but the last.
20305
+ *
20306
+ * The body adds them only while it is written and removes them afterwards with
20307
+ * {@link removeSectionProperties}, so the same paragraph can be used in other documents.
20308
+ *
20309
+ * @internal
20310
+ * @param sectionProperties - The properties of the section the paragraph ends
20311
+ */
20312
+ addSectionProperties(sectionProperties) {
20313
+ this.properties.addSectionProperties(sectionProperties);
20314
+ }
20315
+ /**
20316
+ * Removes the section properties added with {@link addSectionProperties}.
20317
+ *
20318
+ * @internal
20319
+ * @param sectionProperties - The properties of the section to remove
20320
+ */
20321
+ removeSectionProperties(sectionProperties) {
20322
+ this.properties.removeSectionProperties(sectionProperties);
20323
+ }
19123
20324
  addRunToFront(run) {
19124
20325
  this.root.splice(1, 0, run);
19125
20326
  return this;
@@ -19212,7 +20413,7 @@ MAX: 9026 };
19212
20413
  }
19213
20414
  };
19214
20415
  //#endregion
19215
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/objectWithoutPropertiesLoose.js
20416
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/objectWithoutPropertiesLoose.js
19216
20417
  function _objectWithoutPropertiesLoose(r, e) {
19217
20418
  if (null == r) return {};
19218
20419
  var t = {};
@@ -19223,7 +20424,7 @@ MAX: 9026 };
19223
20424
  return t;
19224
20425
  }
19225
20426
  //#endregion
19226
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/objectWithoutProperties.js
20427
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/objectWithoutProperties.js
19227
20428
  function _objectWithoutProperties(e, t) {
19228
20429
  if (null == e) return {};
19229
20430
  var o, r, i = _objectWithoutPropertiesLoose(e, t);
@@ -21176,6 +22377,168 @@ MAX: 9026 };
21176
22377
  }
21177
22378
  });
21178
22379
  //#endregion
22380
+ //#region src/file/document/body/section-properties/properties/note-properties.ts
22381
+ /**
22382
+ * Where the footnotes of a section are placed.
22383
+ *
22384
+ * ## XSD Schema
22385
+ * ```xml
22386
+ * <xsd:simpleType name="ST_FtnPos">
22387
+ * <xsd:restriction base="xsd:string">
22388
+ * <xsd:enumeration value="pageBottom"/>
22389
+ * <xsd:enumeration value="beneathText"/>
22390
+ * <xsd:enumeration value="sectEnd"/>
22391
+ * <xsd:enumeration value="docEnd"/>
22392
+ * </xsd:restriction>
22393
+ * </xsd:simpleType>
22394
+ * ```
22395
+ *
22396
+ * @publicApi
22397
+ */
22398
+ var FootnotePosition = {
22399
+ /** At the bottom of each page */
22400
+ PAGE_BOTTOM: "pageBottom",
22401
+ /** Directly below the text on each page */
22402
+ BENEATH_TEXT: "beneathText",
22403
+ /** At the end of the section */
22404
+ SECTION_END: "sectEnd",
22405
+ /** At the end of the document */
22406
+ DOCUMENT_END: "docEnd"
22407
+ };
22408
+ /**
22409
+ * Where the endnotes of a section are placed.
22410
+ *
22411
+ * ## XSD Schema
22412
+ * ```xml
22413
+ * <xsd:simpleType name="ST_EdnPos">
22414
+ * <xsd:restriction base="xsd:string">
22415
+ * <xsd:enumeration value="sectEnd"/>
22416
+ * <xsd:enumeration value="docEnd"/>
22417
+ * </xsd:restriction>
22418
+ * </xsd:simpleType>
22419
+ * ```
22420
+ *
22421
+ * @publicApi
22422
+ */
22423
+ var EndnotePosition = {
22424
+ /** At the end of the section */
22425
+ SECTION_END: "sectEnd",
22426
+ /** At the end of the document */
22427
+ DOCUMENT_END: "docEnd"
22428
+ };
22429
+ /**
22430
+ * When the footnote or endnote numbering restarts.
22431
+ *
22432
+ * ## XSD Schema
22433
+ * ```xml
22434
+ * <xsd:simpleType name="ST_RestartNumber">
22435
+ * <xsd:restriction base="xsd:string">
22436
+ * <xsd:enumeration value="continuous"/>
22437
+ * <xsd:enumeration value="eachSect"/>
22438
+ * <xsd:enumeration value="eachPage"/>
22439
+ * </xsd:restriction>
22440
+ * </xsd:simpleType>
22441
+ * ```
22442
+ *
22443
+ * @publicApi
22444
+ */
22445
+ var NoteNumberRestart = {
22446
+ /** Numbering never restarts */
22447
+ CONTINUOUS: "continuous",
22448
+ /** Numbering restarts in each section */
22449
+ EACH_SECTION: "eachSect",
22450
+ /** Numbering restarts on each page */
22451
+ EACH_PAGE: "eachPage"
22452
+ };
22453
+ var createNoteProperties = ({ name, position, numberFormat, start, restart }) => new BuilderElement({
22454
+ name,
22455
+ children: [
22456
+ ...position === void 0 ? [] : [new BuilderElement({
22457
+ name: "w:pos",
22458
+ attributes: { val: {
22459
+ key: "w:val",
22460
+ value: position
22461
+ } }
22462
+ })],
22463
+ ...numberFormat ? [new BuilderElement({
22464
+ name: "w:numFmt",
22465
+ attributes: {
22466
+ val: {
22467
+ key: "w:val",
22468
+ value: numberFormat.type
22469
+ },
22470
+ format: {
22471
+ key: "w:format",
22472
+ value: numberFormat.format
22473
+ }
22474
+ }
22475
+ })] : [],
22476
+ ...start === void 0 ? [] : [new BuilderElement({
22477
+ name: "w:numStart",
22478
+ attributes: { val: {
22479
+ key: "w:val",
22480
+ value: decimalNumber(start)
22481
+ } }
22482
+ })],
22483
+ ...restart === void 0 ? [] : [new BuilderElement({
22484
+ name: "w:numRestart",
22485
+ attributes: { val: {
22486
+ key: "w:val",
22487
+ value: restart
22488
+ } }
22489
+ })]
22490
+ ]
22491
+ });
22492
+ /**
22493
+ * Creates the footnote properties (footnotePr) of a section.
22494
+ *
22495
+ * ## XSD Schema
22496
+ * ```xml
22497
+ * <xsd:complexType name="CT_FtnProps">
22498
+ * <xsd:sequence>
22499
+ * <xsd:element name="pos" type="CT_FtnPos" minOccurs="0"/>
22500
+ * <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0"/>
22501
+ * <xsd:group ref="EG_FtnEdnNumProps" minOccurs="0"/>
22502
+ * </xsd:sequence>
22503
+ * </xsd:complexType>
22504
+ * ```
22505
+ *
22506
+ * @example
22507
+ * ```typescript
22508
+ * // Footnotes at the end of the section, numbered a, b, c and restarting in each section
22509
+ * createFootnoteProperties({
22510
+ * position: FootnotePosition.SECTION_END,
22511
+ * numberFormat: { type: NumberFormat.LOWER_LETTER },
22512
+ * restart: NoteNumberRestart.EACH_SECTION,
22513
+ * });
22514
+ * ```
22515
+ */
22516
+ var createFootnoteProperties = (options) => createNoteProperties(_objectSpread2({ name: "w:footnotePr" }, options));
22517
+ /**
22518
+ * Creates the endnote properties (endnotePr) of a section.
22519
+ *
22520
+ * ## XSD Schema
22521
+ * ```xml
22522
+ * <xsd:complexType name="CT_EdnProps">
22523
+ * <xsd:sequence>
22524
+ * <xsd:element name="pos" type="CT_EdnPos" minOccurs="0"/>
22525
+ * <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0"/>
22526
+ * <xsd:group ref="EG_FtnEdnNumProps" minOccurs="0"/>
22527
+ * </xsd:sequence>
22528
+ * </xsd:complexType>
22529
+ * ```
22530
+ *
22531
+ * @example
22532
+ * ```typescript
22533
+ * // Endnotes at the end of the document, numbered 001, 002, 003
22534
+ * createEndnoteProperties({
22535
+ * position: EndnotePosition.DOCUMENT_END,
22536
+ * numberFormat: { type: NumberFormat.CUSTOM, format: "001" },
22537
+ * });
22538
+ * ```
22539
+ */
22540
+ var createEndnoteProperties = (options) => createNoteProperties(_objectSpread2({ name: "w:endnotePr" }, options));
22541
+ //#endregion
21179
22542
  //#region src/file/document/body/section-properties/properties/page-borders.ts
21180
22543
  /**
21181
22544
  * Page borders module for WordprocessingML section properties.
@@ -21415,7 +22778,7 @@ MAX: 9026 };
21415
22778
  COLON: "colon",
21416
22779
  /** Em dash separator (—) */
21417
22780
  EM_DASH: "emDash",
21418
- /** En dash separator (–) */
22781
+ /** En dash separator (–), written as `enDash` */
21419
22782
  EN_DASH: "endash"
21420
22783
  };
21421
22784
  /**
@@ -21445,7 +22808,7 @@ MAX: 9026 };
21445
22808
  * });
21446
22809
  * ```
21447
22810
  */
21448
- var createPageNumberType = ({ start, formatType, separator }) => new BuilderElement({
22811
+ var createPageNumberType = ({ start, formatType, separator, chapterHeadingLevel }) => new BuilderElement({
21449
22812
  name: "w:pgNumType",
21450
22813
  attributes: {
21451
22814
  start: {
@@ -21458,7 +22821,11 @@ MAX: 9026 };
21458
22821
  },
21459
22822
  separator: {
21460
22823
  key: "w:chapSep",
21461
- value: separator
22824
+ value: separator === PageNumberSeparator.EN_DASH ? "enDash" : separator
22825
+ },
22826
+ chapterHeadingLevel: {
22827
+ key: "w:chapStyle",
22828
+ value: chapterHeadingLevel === void 0 ? void 0 : decimalNumber(chapterHeadingLevel)
21462
22829
  }
21463
22830
  }
21464
22831
  });
@@ -21762,7 +23129,7 @@ MAX: 9026 };
21762
23129
  * ```
21763
23130
  */
21764
23131
  var SectionProperties = class SectionProperties extends XmlComponent {
21765
- 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 } = {}) {
23132
+ 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 } = {}) {
21766
23133
  super("w:sectPr");
21767
23134
  _defineProperty(
21768
23135
  this,
@@ -21785,6 +23152,8 @@ MAX: 9026 };
21785
23152
  });
21786
23153
  this.addHeaderFooterGroup(HeaderFooterType.HEADER, headerWrapperGroup);
21787
23154
  this.addHeaderFooterGroup(HeaderFooterType.FOOTER, footerWrapperGroup);
23155
+ if (footnoteProperties) this.root.push(createFootnoteProperties(footnoteProperties));
23156
+ if (endnoteProperties) this.root.push(createEndnoteProperties(endnoteProperties));
21788
23157
  if (type) this.root.push(createSectionType(type));
21789
23158
  this.root.push(createPageSize({
21790
23159
  width,
@@ -21909,7 +23278,7 @@ MAX: 9026 };
21909
23278
  * ```
21910
23279
  */
21911
23280
  var Body = class extends XmlComponent {
21912
- constructor() {
23281
+ constructor({ pageNumbers } = {}) {
21913
23282
  super("w:body");
21914
23283
  _defineProperty(this, "sections", []);
21915
23284
  _defineProperty(
@@ -21917,11 +23286,15 @@ MAX: 9026 };
21917
23286
  /**
21918
23287
  * Section properties that were moved into a paragraph at the end of their section
21919
23288
  * by {@link addSection}, keyed by that paragraph. Used to find the section that
21920
- * governs a given child of the body.
23289
+ * governs a given child of the body, and to write each section's properties into
23290
+ * its paragraph while the body is written.
21921
23291
  */
21922
23292
  "sectionParagraphs",
21923
23293
  /* @__PURE__ */ new Map()
21924
23294
  );
23295
+ _defineProperty(this, "headingBookmarkIds", new HeadingBookmarkIds());
23296
+ _defineProperty(this, "pageNumbers", void 0);
23297
+ this.pageNumbers = pageNumbers;
21925
23298
  }
21926
23299
  /**
21927
23300
  * Finds the section properties that govern a top-level child of the body.
@@ -21936,7 +23309,7 @@ MAX: 9026 };
21936
23309
  * @returns The governing section properties, or undefined if the body has no sections
21937
23310
  */
21938
23311
  getSectionPropertiesFor(child) {
21939
- const start = child ? this.root.indexOf(child) + 1 : 0;
23312
+ const start = child ? Math.max(this.root.indexOf(child), 0) : 0;
21940
23313
  for (let i = start; i < this.root.length; i++) {
21941
23314
  const component = this.root[i];
21942
23315
  if (component instanceof SectionProperties) return component;
@@ -21948,8 +23321,10 @@ MAX: 9026 };
21948
23321
  /**
21949
23322
  * Adds new section properties to the document body.
21950
23323
  *
21951
- * Creates a new section by moving the previous section's properties into a paragraph
21952
- * at the end of that section, and then adding the new section as the current section.
23324
+ * Creates a new section by moving the previous section's properties into the last
23325
+ * paragraph of that section, and then adding the new section as the current section.
23326
+ * When that section doesn't end with a paragraph of its own (it ends with a table, or
23327
+ * it is empty), an empty paragraph is added to hold its properties.
21953
23328
  *
21954
23329
  * According to the OOXML specification:
21955
23330
  * - Section properties for all sections except the last must be stored in a paragraph's
@@ -21960,16 +23335,24 @@ MAX: 9026 };
21960
23335
  */
21961
23336
  addSection(options) {
21962
23337
  const currentSection = this.sections.pop();
21963
- const sectionParagraph = this.createSectionParagraph(currentSection);
21964
- this.root.push(sectionParagraph);
21965
- if (currentSection) this.sectionParagraphs.set(sectionParagraph, currentSection);
23338
+ const lastParagraph = this.lastParagraphOfSection();
23339
+ if (currentSection && lastParagraph) this.sectionParagraphs.set(lastParagraph, currentSection);
23340
+ else {
23341
+ const sectionParagraph = this.createSectionParagraph();
23342
+ this.root.push(sectionParagraph);
23343
+ if (currentSection) this.sectionParagraphs.set(sectionParagraph, currentSection);
23344
+ }
21966
23345
  this.sections.push(new SectionProperties(options));
21967
23346
  }
21968
23347
  /**
21969
23348
  * Prepares the body element for XML serialization.
21970
23349
  *
21971
23350
  * Ensures that the last section's properties are placed as a direct child of the body
21972
- * element, as required by the OOXML specification.
23351
+ * element, as required by the OOXML specification. Once the body is written, its tables
23352
+ * of contents are filled in from its headings, and, when the body has a page number
23353
+ * estimator, its page references are given their page numbers. Its SEQ fields are given
23354
+ * their numbers after the tables of contents are filled in, as Word leaves a heading's SEQ
23355
+ * number out of its entry.
21973
23356
  *
21974
23357
  * @param context - The XML serialization context
21975
23358
  * @returns The prepared XML object or undefined
@@ -21979,7 +23362,19 @@ MAX: 9026 };
21979
23362
  this.root.splice(0, 1);
21980
23363
  this.root.push(this.sections.pop());
21981
23364
  }
21982
- return super.prepForXml(context);
23365
+ for (const [paragraph, section] of this.sectionParagraphs) paragraph.addSectionProperties(section);
23366
+ let xml;
23367
+ try {
23368
+ xml = super.prepForXml(context);
23369
+ } finally {
23370
+ for (const [paragraph, section] of this.sectionParagraphs) paragraph.removeSectionProperties(section);
23371
+ }
23372
+ fillTablesOfContents(xml, context, this.headingBookmarkIds);
23373
+ if (this.pageNumbers) {
23374
+ fillSequenceNumbers(xml, context);
23375
+ fillPageNumbers(xml, context, this.pageNumbers);
23376
+ }
23377
+ return xml;
21983
23378
  }
21984
23379
  /**
21985
23380
  * Adds a block-level component to the body.
@@ -21990,14 +23385,32 @@ MAX: 9026 };
21990
23385
  * @param component - The XML component to add (paragraph, table, etc.)
21991
23386
  */
21992
23387
  push(component) {
23388
+ const section = component instanceof Paragraph ? this.sectionParagraphs.get(component) : void 0;
23389
+ if (section) {
23390
+ const sectionParagraph = this.createSectionParagraph();
23391
+ this.root.splice(this.root.indexOf(component) + 1, 0, sectionParagraph);
23392
+ this.sectionParagraphs.delete(component);
23393
+ this.sectionParagraphs.set(sectionParagraph, section);
23394
+ }
21993
23395
  this.root.push(component);
21994
23396
  }
21995
- createSectionParagraph(section) {
21996
- const paragraph = new Paragraph({});
21997
- const properties = new ParagraphProperties({});
21998
- properties.push(section);
21999
- paragraph.addChildElement(properties);
22000
- return paragraph;
23397
+ /**
23398
+ * The paragraph the current section ends with, which can hold its properties.
23399
+ *
23400
+ * There is none when the section ends with something other than a paragraph, or is empty:
23401
+ * its last child is then the placeholder at the start of the body (removed when the body is
23402
+ * written) or the paragraph that ends the section before, which has properties of its own.
23403
+ */
23404
+ lastParagraphOfSection() {
23405
+ const last = this.root[this.root.length - 1];
23406
+ return last instanceof Paragraph && last !== this.root[0] && !this.sectionParagraphs.has(last) && this.root.indexOf(last) === this.root.length - 1 ? last : void 0;
23407
+ }
23408
+ /**
23409
+ * An empty paragraph to end a section that has no paragraph of its own to end it. The section's
23410
+ * properties are written into it with the others, when the body is written.
23411
+ */
23412
+ createSectionParagraph() {
23413
+ return new Paragraph({});
22001
23414
  }
22002
23415
  };
22003
23416
  //#endregion
@@ -23109,6 +24522,9 @@ MAX: 9026 };
23109
24522
  var TableCellProperties = class extends IgnoreIfEmptyXmlComponent {
23110
24523
  constructor(options) {
23111
24524
  super("w:tcPr", options.includeIfEmpty);
24525
+ _defineProperty(this, "hasWidth", void 0);
24526
+ _defineProperty(this, "hasColumnWidth", false);
24527
+ this.hasWidth = options.width !== void 0;
23112
24528
  if (options.width) this.root.push(createTableWidthElement("w:tcW", options.width));
23113
24529
  if (options.columnSpan) this.root.push(new GridSpan(options.columnSpan));
23114
24530
  if (options.verticalMerge) this.root.push(new VerticalMerge(options.verticalMerge));
@@ -23126,6 +24542,19 @@ MAX: 9026 };
23126
24542
  if (options.cellMerge) this.root.push(new CellMerge(options.cellMerge));
23127
24543
  if (options.revision) this.root.push(new TableCellPropertiesChange(options.revision));
23128
24544
  }
24545
+ /**
24546
+ * Gives a cell without a width of its own the width of the table's columns it spans, in twips.
24547
+ *
24548
+ * @internal
24549
+ */
24550
+ setColumnWidth(twips) {
24551
+ if (this.hasWidth) return;
24552
+ this.root.splice(0, this.hasColumnWidth ? 1 : 0, createTableWidthElement("w:tcW", {
24553
+ size: twips,
24554
+ type: WidthType.DXA
24555
+ }));
24556
+ this.hasColumnWidth = true;
24557
+ }
23129
24558
  };
23130
24559
  var TableCellPropertiesChange = class extends XmlComponent {
23131
24560
  constructor(options) {
@@ -23184,10 +24613,20 @@ MAX: 9026 };
23184
24613
  "options",
23185
24614
  void 0
23186
24615
  );
24616
+ _defineProperty(this, "properties", void 0);
23187
24617
  this.options = options;
23188
- this.root.push(new TableCellProperties(options));
24618
+ this.properties = new TableCellProperties(options);
24619
+ this.root.push(this.properties);
23189
24620
  for (const child of options.children) this.root.push(child);
23190
24621
  }
24622
+ /**
24623
+ * Gives the cell, unless it has a width of its own, the width of the table's columns it spans, in twips.
24624
+ *
24625
+ * @internal
24626
+ */
24627
+ setColumnWidth(twips) {
24628
+ this.properties.setColumnWidth(twips);
24629
+ }
23191
24630
  prepForXml(context) {
23192
24631
  if (!(this.root[this.root.length - 1] instanceof Paragraph)) this.root.push(new Paragraph({}));
23193
24632
  return super.prepForXml(context);
@@ -24051,6 +25490,7 @@ MAX: 9026 };
24051
25490
  columnIndex += cell.options.columnSpan || 1;
24052
25491
  });
24053
25492
  });
25493
+ this.setCellWidths(DEFAULT_AVAILABLE_WIDTH);
24054
25494
  this.resolvedColumnWidths = columnWidths !== null && columnWidths !== void 0 ? columnWidths : resolveColumnWidths({
24055
25495
  rows,
24056
25496
  width: this.width,
@@ -24107,6 +25547,7 @@ MAX: 9026 };
24107
25547
  * serializing.
24108
25548
  */
24109
25549
  prepForXml(context) {
25550
+ this.setCellWidths(this.resolveAvailableWidth(context));
24110
25551
  if (this.columnWidths === void 0) {
24111
25552
  this.resolvedColumnWidths = resolveColumnWidths({
24112
25553
  rows: this.rows,
@@ -24119,6 +25560,29 @@ MAX: 9026 };
24119
25560
  return super.prepForXml(context);
24120
25561
  }
24121
25562
  /**
25563
+ * Gives each cell without a width of its own the width of the `columnWidths` it spans, as Word sizes the columns of
25564
+ * cells without a width to their content, whatever the grid says. When the table's width is wider than the columns
25565
+ * add up to, they are scaled up to fill it, as Word and LibreOffice lay them out, so columns given as proportions
25566
+ * keep them.
25567
+ */
25568
+ setCellWidths(availableWidth) {
25569
+ var _resolvePreferredWidt;
25570
+ if (this.columnWidths === void 0) return;
25571
+ const total = this.columnWidths.reduce((sum, columnWidth) => sum + columnWidth, 0);
25572
+ const tableWidth = (_resolvePreferredWidt = resolvePreferredWidth(this.width, availableWidth)) !== null && _resolvePreferredWidt !== void 0 ? _resolvePreferredWidt : 0;
25573
+ const scale = total > 0 && tableWidth > total ? tableWidth / total : 1;
25574
+ for (const row of this.rows) {
25575
+ let column = 0;
25576
+ for (const cell of row.cells) {
25577
+ const span = cell.options.columnSpan || 1;
25578
+ const spanned = this.columnWidths.slice(column, column + span);
25579
+ const cellWidth = Math.round(spanned.reduce((sum, columnWidth) => sum + columnWidth, 0) * scale);
25580
+ if (spanned.length === span && cellWidth > 0) cell.setColumnWidth(cellWidth);
25581
+ column += span;
25582
+ }
25583
+ }
25584
+ }
25585
+ /**
24122
25586
  * Finds the width in twips available to this table from the serialization context:
24123
25587
  * the parent cell for a nested table, otherwise the text width of the section the
24124
25588
  * table belongs to (the first section for headers, footers and other parts). Falls
@@ -24731,7 +26195,7 @@ MAX: 9026 };
24731
26195
  for (const property of properties) this.addCustomProperty(property);
24732
26196
  }
24733
26197
  prepForXml(context) {
24734
- this.properties.forEach((x) => this.root.push(x));
26198
+ this.root.splice(1, this.root.length - 1, ...this.properties);
24735
26199
  return super.prepForXml(context);
24736
26200
  }
24737
26201
  addCustomProperty(property) {
@@ -24993,7 +26457,7 @@ MAX: 9026 };
24993
26457
  "w16sdtdh",
24994
26458
  "w16se"
24995
26459
  ], "w14 w15 wp14"));
24996
- this.body = new Body();
26460
+ this.body = new Body({ pageNumbers: options.pageNumbers });
24997
26461
  if (options.background) this.root.push(new DocumentBackground(options.background));
24998
26462
  this.root.push(this.body);
24999
26463
  }
@@ -25291,6 +26755,15 @@ MAX: 9026 };
25291
26755
  });
25292
26756
  this.root.push(endnote);
25293
26757
  }
26758
+ /**
26759
+ * Formats the endnotes, with the page numbers worked out for their document written into their fields, when the
26760
+ * document's body is written with an estimate of its pages.
26761
+ */
26762
+ prepForXml(context) {
26763
+ const xml = super.prepForXml(context);
26764
+ fillPartPageNumbers(xml, context);
26765
+ return xml;
26766
+ }
25294
26767
  };
25295
26768
  //#endregion
25296
26769
  //#region src/file/endnotes-wrapper.ts
@@ -25432,6 +26905,15 @@ MAX: 9026 };
25432
26905
  add(item) {
25433
26906
  this.root.push(item);
25434
26907
  }
26908
+ /**
26909
+ * Formats the footer, with the page numbers worked out for its document written into its fields, when the document's
26910
+ * body is written with an estimate of its pages.
26911
+ */
26912
+ prepForXml(context) {
26913
+ const xml = super.prepForXml(context);
26914
+ fillPartPageNumbers(xml, context, this.refId);
26915
+ return xml;
26916
+ }
25435
26917
  };
25436
26918
  //#endregion
25437
26919
  //#region src/file/footer-wrapper.ts
@@ -25782,6 +27264,15 @@ MAX: 9026 };
25782
27264
  });
25783
27265
  this.root.push(footnote);
25784
27266
  }
27267
+ /**
27268
+ * Formats the footnotes, with the page numbers worked out for their document written into their fields, when the
27269
+ * document's body is written with an estimate of its pages.
27270
+ */
27271
+ prepForXml(context) {
27272
+ const xml = super.prepForXml(context);
27273
+ fillPartPageNumbers(xml, context);
27274
+ return xml;
27275
+ }
25785
27276
  };
25786
27277
  //#endregion
25787
27278
  //#region src/file/footnotes-wrapper.ts
@@ -25955,6 +27446,15 @@ MAX: 9026 };
25955
27446
  add(item) {
25956
27447
  this.root.push(item);
25957
27448
  }
27449
+ /**
27450
+ * Formats the header, with the page numbers worked out for its document written into its fields, when the document's
27451
+ * body is written with an estimate of its pages.
27452
+ */
27453
+ prepForXml(context) {
27454
+ const xml = super.prepForXml(context);
27455
+ fillPartPageNumbers(xml, context, this.refId);
27456
+ return xml;
27457
+ }
25958
27458
  };
25959
27459
  //#endregion
25960
27460
  //#region src/file/header-wrapper.ts
@@ -26959,8 +28459,7 @@ MAX: 9026 };
26959
28459
  * @returns The prepared XML object
26960
28460
  */
26961
28461
  prepForXml(context) {
26962
- for (const numbering of this.abstractNumberingMap.values()) this.root.push(numbering);
26963
- for (const numbering of this.concreteNumberingMap.values()) this.root.push(numbering);
28462
+ this.root.splice(1, this.root.length - 1, ...this.abstractNumberingMap.values(), ...this.concreteNumberingMap.values());
26964
28463
  return super.prepForXml(context);
26965
28464
  }
26966
28465
  /**
@@ -27014,6 +28513,7 @@ MAX: 9026 };
27014
28513
  };
27015
28514
  //#endregion
27016
28515
  //#region src/file/package-part/package-part.ts
28516
+ var PATH_PART = /^[\w-]+$/;
27017
28517
  var RESERVED_FOLDERS = /* @__PURE__ */ new Set([
27018
28518
  "_rels",
27019
28519
  "fonts",
@@ -27052,6 +28552,7 @@ MAX: 9026 };
27052
28552
  var PackagePart = class {
27053
28553
  /**
27054
28554
  * @throws If the folder isn't a single folder name, or is one of the folders docx writes parts of its own in
28555
+ * @throws If the name or the extension isn't a single part of a file name, which could lead out of the folder
27055
28556
  */
27056
28557
  constructor(options) {
27057
28558
  _defineProperty(this, "options", void 0);
@@ -27064,7 +28565,9 @@ MAX: 9026 };
27064
28565
  );
27065
28566
  _defineProperty(this, "addedTo", /* @__PURE__ */ new WeakSet());
27066
28567
  this.options = options;
27067
- 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"`);
28568
+ 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"`);
28569
+ if (!PATH_PART.test(options.name)) throw new Error(`Invalid package part name "${options.name}". Expected letters, digits, "_" and "-", such as "chart"`);
28570
+ if (!PATH_PART.test(options.extension)) throw new Error(`Invalid package part extension "${options.extension}". Expected letters, digits, "_" and "-", such as "xml"`);
27068
28571
  }
27069
28572
  /**
27070
28573
  * Adds the part to the package being written, once, and a relationship to it from the part being written.
@@ -27086,7 +28589,7 @@ MAX: 9026 };
27086
28589
  /**
27087
28590
  * @param contentTypes - Where each part's content type is added
27088
28591
  * @param existingPaths - The paths under word/ of the parts the package already has, such as a template's charts,
27089
- * which new parts are numbered after
28592
+ * which new parts don't take
27090
28593
  */
27091
28594
  constructor(contentTypes, existingPaths = /* @__PURE__ */ new Set()) {
27092
28595
  _defineProperty(this, "contentTypes", void 0);
@@ -27385,6 +28888,7 @@ MAX: 9026 };
27385
28888
  * ```xml
27386
28889
  * <xsd:complexType name="CT_Settings">
27387
28890
  * <xsd:sequence>
28891
+ * <xsd:element name="embedTrueTypeFonts" type="CT_OnOff" minOccurs="0"/>
27388
28892
  * <xsd:element name="trackRevisions" type="CT_OnOff" minOccurs="0"/>
27389
28893
  * <xsd:element name="defaultTabStop" type="CT_TwipsMeasure" minOccurs="0"/>
27390
28894
  * <xsd:element name="autoHyphenation" type="CT_OnOff" minOccurs="0"/>
@@ -27443,6 +28947,7 @@ MAX: 9026 };
27443
28947
  Ignorable: "w14 w15 wp14"
27444
28948
  }));
27445
28949
  this.root.push(new OnOffElement("w:displayBackgroundShape", true));
28950
+ if (options.embedFonts !== void 0) this.root.push(new OnOffElement("w:embedTrueTypeFonts", options.embedFonts));
27446
28951
  if (options.trackRevisions !== void 0) this.root.push(new OnOffElement("w:trackRevisions", options.trackRevisions));
27447
28952
  if (options.defaultTabStop !== void 0) this.root.push(new NumberValueElement("w:defaultTabStop", options.defaultTabStop));
27448
28953
  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));
@@ -28031,6 +29536,39 @@ MAX: 9026 };
28031
29536
  }, options));
28032
29537
  }
28033
29538
  };
29539
+ /**
29540
+ * Represents the Normal Table style, the default style of tables.
29541
+ *
29542
+ * It gives cells the margins Word gives the tables it makes: 108 twips (0.075 inches) on the left and right. Without a
29543
+ * default table style, Word gives cells no margins, so their text touches the borders, where LibreOffice and other
29544
+ * applications use these margins.
29545
+ */
29546
+ var NormalTableStyle = class extends Style {
29547
+ constructor() {
29548
+ super({
29549
+ type: "table",
29550
+ styleId: "TableNormal",
29551
+ default: true
29552
+ }, {
29553
+ name: "Normal Table",
29554
+ uiPriority: 99,
29555
+ semiHidden: true,
29556
+ unhideWhenUsed: true
29557
+ });
29558
+ this.root.push(new TableProperties({
29559
+ indent: {
29560
+ size: 0,
29561
+ type: WidthType.DXA
29562
+ },
29563
+ cellMargin: {
29564
+ top: 0,
29565
+ left: 108,
29566
+ bottom: 0,
29567
+ right: 108
29568
+ }
29569
+ }));
29570
+ }
29571
+ };
28034
29572
  //#endregion
28035
29573
  //#region src/file/styles/styles.ts
28036
29574
  /** The name of a formatted element, such as `w:style`, or `_attr` for its parent's attributes */
@@ -28323,6 +29861,7 @@ MAX: 9026 };
28323
29861
  name: "Normal",
28324
29862
  quickFormat: true
28325
29863
  }),
29864
+ normalTable: new NormalTableStyle(),
28326
29865
  document: new DocumentDefaults((_options$document = options.document) !== null && _options$document !== void 0 ? _options$document : {}),
28327
29866
  title: new TitleStyle(_objectSpread2({ run: { size: 56 } }, options.title)),
28328
29867
  heading1: new Heading1Style(_objectSpread2({ run: {
@@ -28997,7 +30536,7 @@ MAX: 9026 };
28997
30536
  */
28998
30537
  var File = class {
28999
30538
  constructor(options) {
29000
- 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;
30539
+ 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;
29001
30540
  _defineProperty(this, "currentRelationshipId", 1);
29002
30541
  _defineProperty(this, "documentWrapper", void 0);
29003
30542
  _defineProperty(this, "headers", []);
@@ -29045,13 +30584,17 @@ MAX: 9026 };
29045
30584
  this.endnotesWrapper = new EndnotesWrapper();
29046
30585
  this.contentTypes = new ContentTypes();
29047
30586
  this.packageParts = new PackageParts(this.contentTypes);
29048
- this.documentWrapper = new DocumentWrapper({ background: options.background });
30587
+ this.documentWrapper = new DocumentWrapper({
30588
+ background: options.background,
30589
+ pageNumbers: options.pageNumbers
30590
+ });
29049
30591
  this.settings = new Settings({
29050
30592
  compatibilityModeVersion: options.compatabilityModeVersion,
29051
30593
  compatibility: options.compatibility,
29052
30594
  evenAndOddHeaders: options.evenAndOddHeaderAndFooters ? true : false,
29053
30595
  trackRevisions: (_options$features = options.features) === null || _options$features === void 0 ? void 0 : _options$features.trackRevisions,
29054
30596
  updateFields: (_options$features2 = options.features) === null || _options$features2 === void 0 ? void 0 : _options$features2.updateFields,
30597
+ embedFonts: ((_options$fonts = options.fonts) === null || _options$fonts === void 0 ? void 0 : _options$fonts.length) ? true : void 0,
29055
30598
  defaultTabStop: options.defaultTabStop,
29056
30599
  hyphenation: {
29057
30600
  autoHyphenation: (_options$hyphenation = options.hyphenation) === null || _options$hyphenation === void 0 ? void 0 : _options$hyphenation.autoHyphenation,
@@ -29062,16 +30605,20 @@ MAX: 9026 };
29062
30605
  });
29063
30606
  this.media = new Media();
29064
30607
  if (options.externalStyles !== void 0) {
29065
- var _options$styles$defau, _options$styles;
30608
+ var _options$styles$defau, _options$styles, _options$styles2, _options$styles3;
29066
30609
  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 : {};
29067
30610
  const defaultStyles = Object.entries(createDefaultStyles(given));
29068
30611
  const isGiven = ([key]) => given[key] !== void 0;
29069
30612
  const externalStyles = new ExternalStylesFactory().newInstance(options.externalStyles);
29070
- this.styles = new Styles(_objectSpread2(_objectSpread2({}, externalStyles), {}, { importedStyles: [
29071
- ...defaultStyles.filter((entry) => !isGiven(entry)).map(([, style]) => style),
29072
- ...externalStyles.importedStyles,
29073
- ...defaultStyles.filter(isGiven).map(([, style]) => style)
29074
- ] }));
30613
+ this.styles = new Styles(_objectSpread2(_objectSpread2({}, externalStyles), {}, {
30614
+ paragraphStyles: (_options$styles2 = options.styles) === null || _options$styles2 === void 0 ? void 0 : _options$styles2.paragraphStyles,
30615
+ characterStyles: (_options$styles3 = options.styles) === null || _options$styles3 === void 0 ? void 0 : _options$styles3.characterStyles,
30616
+ importedStyles: [
30617
+ ...defaultStyles.filter((entry) => !isGiven(entry)).map(([, style]) => style),
30618
+ ...externalStyles.importedStyles,
30619
+ ...defaultStyles.filter(isGiven).map(([, style]) => style)
30620
+ ]
30621
+ }));
29075
30622
  } else if (options.styles) {
29076
30623
  const defaultStyles = new DefaultStylesFactory().newInstance(options.styles.default);
29077
30624
  this.styles = new Styles(_objectSpread2(_objectSpread2({}, defaultStyles), options.styles));
@@ -29083,7 +30630,7 @@ MAX: 9026 };
29083
30630
  for (const section of options.sections) this.addSection(section);
29084
30631
  if (options.footnotes) for (const key in options.footnotes) this.footnotesWrapper.View.createFootNote(parseFloat(key), options.footnotes[key].children);
29085
30632
  if (options.endnotes) for (const key in options.endnotes) this.endnotesWrapper.View.createEndnote(parseFloat(key), options.endnotes[key].children);
29086
- this.fontWrapper = new FontWrapper((_options$fonts = options.fonts) !== null && _options$fonts !== void 0 ? _options$fonts : []);
30633
+ this.fontWrapper = new FontWrapper((_options$fonts2 = options.fonts) !== null && _options$fonts2 !== void 0 ? _options$fonts2 : []);
29087
30634
  this.theme = new Theme(options.theme);
29088
30635
  this.documentWrapper.Relationships.addRelationship(this.currentRelationshipId++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme", "theme/theme1.xml");
29089
30636
  }
@@ -29219,113 +30766,6 @@ MAX: 9026 };
29219
30766
  }
29220
30767
  };
29221
30768
  //#endregion
29222
- //#region src/file/table-of-contents/field-instruction.ts
29223
- /**
29224
- * Field Instruction module for Table of Contents.
29225
- *
29226
- * This module handles the generation of TOC field instruction text
29227
- * that controls how the table of contents is built.
29228
- *
29229
- * Reference: http://officeopenxml.com/WPfieldInstructions.php
29230
- *
29231
- * @module
29232
- */
29233
- /**
29234
- * Represents a field instruction for a Table of Contents.
29235
- *
29236
- * The FieldInstruction class generates the TOC field code string that Word uses
29237
- * to determine how to build the table of contents, including which headings to include,
29238
- * formatting options, and other TOC-specific settings.
29239
- *
29240
- * Reference: http://officeopenxml.com/WPfieldInstructions.php
29241
- *
29242
- * ## XSD Schema
29243
- * ```xml
29244
- * <xsd:element name="instrText" type="CT_Text"/>
29245
- * ```
29246
- *
29247
- * @example
29248
- * ```typescript
29249
- * // Basic TOC field instruction
29250
- * new FieldInstruction({ headingStyleRange: "1-3" });
29251
- *
29252
- * // TOC with hyperlinks and custom styles
29253
- * new FieldInstruction({
29254
- * hyperlink: true,
29255
- * headingStyleRange: "1-3",
29256
- * stylesWithLevels: [new StyleLevel("CustomStyle", 2)],
29257
- * });
29258
- * ```
29259
- */
29260
- var FieldInstruction = class extends XmlComponent {
29261
- constructor(properties = {}) {
29262
- super("w:instrText");
29263
- _defineProperty(this, "properties", void 0);
29264
- this.properties = properties;
29265
- this.root.push(new TextAttributes({ space: SpaceType.PRESERVE }));
29266
- let instruction = "TOC";
29267
- if (this.properties.captionLabel) instruction = `${instruction} \\a "${this.properties.captionLabel}"`;
29268
- if (this.properties.entriesFromBookmark) instruction = `${instruction} \\b "${this.properties.entriesFromBookmark}"`;
29269
- if (this.properties.captionLabelIncludingNumbers) instruction = `${instruction} \\c "${this.properties.captionLabelIncludingNumbers}"`;
29270
- if (this.properties.sequenceAndPageNumbersSeparator) instruction = `${instruction} \\d "${this.properties.sequenceAndPageNumbersSeparator}"`;
29271
- if (this.properties.tcFieldIdentifier) instruction = `${instruction} \\f "${this.properties.tcFieldIdentifier}"`;
29272
- if (this.properties.hyperlink) instruction = `${instruction} \\h`;
29273
- if (this.properties.tcFieldLevelRange) instruction = `${instruction} \\l "${this.properties.tcFieldLevelRange}"`;
29274
- if (this.properties.pageNumbersEntryLevelsRange) instruction = `${instruction} \\n "${this.properties.pageNumbersEntryLevelsRange}"`;
29275
- if (this.properties.headingStyleRange) instruction = `${instruction} \\o "${this.properties.headingStyleRange}"`;
29276
- if (this.properties.entryAndPageNumberSeparator) instruction = `${instruction} \\p "${this.properties.entryAndPageNumberSeparator}"`;
29277
- if (this.properties.seqFieldIdentifierForPrefix) instruction = `${instruction} \\s "${this.properties.seqFieldIdentifierForPrefix}"`;
29278
- if (this.properties.stylesWithLevels && this.properties.stylesWithLevels.length) {
29279
- const styles = this.properties.stylesWithLevels.map((sl) => `${sl.styleName},${sl.level}`).join(",");
29280
- instruction = `${instruction} \\t "${styles}"`;
29281
- }
29282
- if (this.properties.useAppliedParagraphOutlineLevel) instruction = `${instruction} \\u`;
29283
- if (this.properties.preserveTabInEntries) instruction = `${instruction} \\w`;
29284
- if (this.properties.preserveNewLineInEntries) instruction = `${instruction} \\x`;
29285
- if (this.properties.hideTabAndPageNumbersInWebView) instruction = `${instruction} \\z`;
29286
- this.root.push(instruction);
29287
- }
29288
- };
29289
- //#endregion
29290
- //#region src/file/table-of-contents/sdt-content.ts
29291
- /**
29292
- * Structured Document Tag Content module.
29293
- *
29294
- * This module represents the content container for structured document tags,
29295
- * including table of contents elements.
29296
- *
29297
- * Reference: http://officeopenxml.com/WPtableOfContents.php
29298
- *
29299
- * @module
29300
- */
29301
- /**
29302
- * Represents the content portion of a Structured Document Tag.
29303
- *
29304
- * The StructuredDocumentTagContent contains the actual content elements
29305
- * (paragraphs, tables, etc.) within a structured document tag, such as
29306
- * the paragraphs that make up a table of contents.
29307
- *
29308
- * Reference: http://officeopenxml.com/WPtableOfContents.php
29309
- *
29310
- * ## XSD Schema
29311
- * ```xml
29312
- * <xsd:complexType name="CT_SdtContentBlock">
29313
- * <xsd:group ref="EG_ContentBlockContent" minOccurs="0" maxOccurs="unbounded"/>
29314
- * </xsd:complexType>
29315
- * ```
29316
- *
29317
- * @example
29318
- * ```typescript
29319
- * const content = new StructuredDocumentTagContent();
29320
- * content.addChildElement(new Paragraph("Content"));
29321
- * ```
29322
- */
29323
- var StructuredDocumentTagContent = class extends XmlComponent {
29324
- constructor() {
29325
- super("w:sdtContent");
29326
- }
29327
- };
29328
- //#endregion
29329
30769
  //#region src/file/table-of-contents/sdt-properties.ts
29330
30770
  /**
29331
30771
  * Structured Document Tag Properties module.
@@ -29405,6 +30845,12 @@ MAX: 9026 };
29405
30845
  * TableOfContents creates an auto-generated list of document headings
29406
30846
  * with page numbers. It uses a TOC field code to generate entries.
29407
30847
  *
30848
+ * Unless it is given `cachedEntries` or `contentChildren`, it is written with an
30849
+ * entry for each heading its options include, linked to a bookmark on the heading,
30850
+ * so it isn't empty before Word updates it or in applications that don't update it.
30851
+ * The page numbers are left for Word to fill in when it updates the field, unless the document's `pageNumbers`
30852
+ * writes them.
30853
+ *
29408
30854
  * Reference: http://officeopenxml.com/WPtableOfContents.php
29409
30855
  *
29410
30856
  * @publicApi
@@ -29430,12 +30876,18 @@ MAX: 9026 };
29430
30876
  */
29431
30877
  var TableOfContents = class extends FileChild {
29432
30878
  constructor(alias = "Table of Contents", _ref = {}) {
29433
- let { contentChildren = [], cachedEntries = [], beginDirty = true } = _ref, properties = _objectWithoutProperties(_ref, _excluded$2);
30879
+ let { contentChildren = [], cachedEntries = [], beginDirty } = _ref, properties = _objectWithoutProperties(_ref, _excluded$2);
29434
30880
  super("w:sdt");
30881
+ _defineProperty(
30882
+ this,
30883
+ /** What it is filled in with from the headings, when it isn't given its content */
30884
+ "fromHeadings",
30885
+ void 0
30886
+ );
29435
30887
  this.root.push(new StructuredDocumentTagProperties(alias));
29436
30888
  const content = new StructuredDocumentTagContent();
29437
30889
  const beginParagraphMandatoryChildren = [new Run({ children: [
29438
- createBegin(beginDirty),
30890
+ beginOf(beginDirty),
29439
30891
  new FieldInstruction(properties),
29440
30892
  createSeparate()
29441
30893
  ] })];
@@ -29462,9 +30914,27 @@ MAX: 9026 };
29462
30914
  for (const child of contentChildren) content.addChildElement(child);
29463
30915
  const endParagraph = new Paragraph({ children: endParagraphMandatoryChildren });
29464
30916
  content.addChildElement(endParagraph);
30917
+ if (contentChildren.length === 0) this.fromHeadings = {
30918
+ properties,
30919
+ beginDirty
30920
+ };
29465
30921
  }
29466
30922
  this.root.push(content);
29467
30923
  }
30924
+ /**
30925
+ * Written empty, and filled in from the headings once the body it is in is written, unless it was given its content.
30926
+ * The page numbers are aligned to the right of the text in its section.
30927
+ */
30928
+ prepForXml(context) {
30929
+ const xml = super.prepForXml(context);
30930
+ recordTableOfContents(xml, this.fromHeadings && _objectSpread2(_objectSpread2({}, this.fromHeadings), {}, { textWidth: this.textWidthIn(context) }));
30931
+ return xml;
30932
+ }
30933
+ /** The width of the text in the section it is in */
30934
+ textWidthIn(context) {
30935
+ var _context$file$Documen, _context$file;
30936
+ 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;
30937
+ }
29468
30938
  getTabStopsForLevel(level, pageWidth = 9025) {
29469
30939
  return [{
29470
30940
  type: "clear",
@@ -33878,11 +35348,11 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
33878
35348
  *
33879
35349
  * @module
33880
35350
  */
33881
- var formatter$2 = new Formatter();
35351
+ var formatter$3 = new Formatter();
33882
35352
  /**
33883
35353
  * Formats a part's XML, with the relationships that anything in it that refers to other parts adds to.
33884
35354
  */
33885
- var xmlifyPart = (file, content, prettify, relationships, standalone = true) => (0, import_xml.default)(formatter$2.format(content, {
35355
+ var xmlifyPart = (file, content, prettify, relationships, standalone = true) => (0, import_xml.default)(formatter$3.format(content, {
33886
35356
  viewWrapper: {
33887
35357
  View: content,
33888
35358
  Relationships: relationships
@@ -34003,7 +35473,6 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
34003
35473
  return zip;
34004
35474
  }
34005
35475
  xmlifyFile(file, prettify) {
34006
- const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1;
34007
35476
  const documentXmlData = (0, import_xml.default)(this.formatter.format(file.Document.View, {
34008
35477
  viewWrapper: file.Document,
34009
35478
  file,
@@ -34015,7 +35484,6 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
34015
35484
  encoding: "UTF-8"
34016
35485
  }
34017
35486
  });
34018
- const commentRelationshipCount = file.Comments.Relationships.RelationshipCount + 1;
34019
35487
  const commentXmlData = (0, import_xml.default)(this.formatter.format(file.Comments, {
34020
35488
  viewWrapper: {
34021
35489
  View: file.Comments,
@@ -34030,7 +35498,6 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
34030
35498
  encoding: "UTF-8"
34031
35499
  }
34032
35500
  });
34033
- const footnoteRelationshipCount = file.FootNotes.Relationships.RelationshipCount + 1;
34034
35501
  const footnoteXmlData = (0, import_xml.default)(this.formatter.format(file.FootNotes.View, {
34035
35502
  viewWrapper: file.FootNotes,
34036
35503
  file,
@@ -34042,17 +35509,31 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
34042
35509
  encoding: "UTF-8"
34043
35510
  }
34044
35511
  });
35512
+ const endnoteXmlData = (0, import_xml.default)(this.formatter.format(file.Endnotes.View, {
35513
+ viewWrapper: file.Endnotes,
35514
+ file,
35515
+ stack: []
35516
+ }), {
35517
+ indent: prettify,
35518
+ declaration: { encoding: "UTF-8" }
35519
+ });
35520
+ const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1;
35521
+ const commentRelationshipCount = file.Comments.Relationships.RelationshipCount + 1;
35522
+ const footnoteRelationshipCount = file.FootNotes.Relationships.RelationshipCount + 1;
35523
+ const endnoteRelationshipCount = file.Endnotes.Relationships.RelationshipCount + 1;
34045
35524
  const documentMediaDatas = this.imageReplacer.getMediaData(documentXmlData, file.Media);
34046
35525
  const commentMediaDatas = this.imageReplacer.getMediaData(commentXmlData, file.Media);
34047
35526
  const footnoteMediaDatas = this.imageReplacer.getMediaData(footnoteXmlData, file.Media);
35527
+ const endnoteMediaDatas = this.imageReplacer.getMediaData(endnoteXmlData, file.Media);
34048
35528
  return _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({
34049
35529
  Relationships: {
34050
35530
  data: (() => {
35531
+ const relationships = Relationships.copy(file.Document.Relationships);
34051
35532
  documentMediaDatas.forEach((mediaData, i) => {
34052
- file.Document.Relationships.addRelationship(documentRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35533
+ relationships.addRelationship(documentRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
34053
35534
  });
34054
- file.Document.Relationships.addRelationship(file.Document.Relationships.RelationshipCount + 1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable", "fontTable.xml");
34055
- return (0, import_xml.default)(this.formatter.format(file.Document.Relationships, {
35535
+ relationships.addRelationship(relationships.RelationshipCount + 1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable", "fontTable.xml");
35536
+ return (0, import_xml.default)(this.formatter.format(relationships, {
34056
35537
  viewWrapper: file.Document,
34057
35538
  file,
34058
35539
  stack: []
@@ -34101,20 +35582,6 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
34101
35582
  }),
34102
35583
  path: "docProps/core.xml"
34103
35584
  },
34104
- Numbering: {
34105
- data: (0, import_xml.default)(this.formatter.format(file.Numbering, {
34106
- viewWrapper: file.Document,
34107
- file,
34108
- stack: []
34109
- }), {
34110
- indent: prettify,
34111
- declaration: {
34112
- standalone: "yes",
34113
- encoding: "UTF-8"
34114
- }
34115
- }),
34116
- path: "word/numbering.xml"
34117
- },
34118
35585
  FileRelationships: {
34119
35586
  data: (0, import_xml.default)(this.formatter.format(file.FileRelationships, {
34120
35587
  viewWrapper: file.Document,
@@ -34135,11 +35602,13 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
34135
35602
  indent: prettify,
34136
35603
  declaration: { encoding: "UTF-8" }
34137
35604
  });
34138
- this.imageReplacer.getMediaData(xmlData, file.Media).forEach((mediaData, i) => {
34139
- headerWrapper.Relationships.addRelationship(i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35605
+ const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
35606
+ const relationships = Relationships.copy(headerWrapper.Relationships);
35607
+ mediaDatas.forEach((mediaData, i) => {
35608
+ relationships.addRelationship(i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
34140
35609
  });
34141
35610
  return {
34142
- data: (0, import_xml.default)(this.formatter.format(headerWrapper.Relationships, {
35611
+ data: (0, import_xml.default)(this.formatter.format(relationships, {
34143
35612
  viewWrapper: headerWrapper,
34144
35613
  file,
34145
35614
  stack: []
@@ -34159,11 +35628,13 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
34159
35628
  indent: prettify,
34160
35629
  declaration: { encoding: "UTF-8" }
34161
35630
  });
34162
- this.imageReplacer.getMediaData(xmlData, file.Media).forEach((mediaData, i) => {
34163
- footerWrapper.Relationships.addRelationship(i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35631
+ const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
35632
+ const relationships = Relationships.copy(footerWrapper.Relationships);
35633
+ mediaDatas.forEach((mediaData, i) => {
35634
+ relationships.addRelationship(i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
34164
35635
  });
34165
35636
  return {
34166
- data: (0, import_xml.default)(this.formatter.format(footerWrapper.Relationships, {
35637
+ data: (0, import_xml.default)(this.formatter.format(relationships, {
34167
35638
  viewWrapper: footerWrapper,
34168
35639
  file,
34169
35640
  stack: []
@@ -34243,10 +35714,11 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
34243
35714
  },
34244
35715
  FootNotesRelationships: {
34245
35716
  data: (() => {
35717
+ const relationships = Relationships.copy(file.FootNotes.Relationships);
34246
35718
  footnoteMediaDatas.forEach((mediaData, i) => {
34247
- file.FootNotes.Relationships.addRelationship(footnoteRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35719
+ relationships.addRelationship(footnoteRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
34248
35720
  });
34249
- return (0, import_xml.default)(this.formatter.format(file.FootNotes.Relationships, {
35721
+ return (0, import_xml.default)(this.formatter.format(relationships, {
34250
35722
  viewWrapper: file.FootNotes,
34251
35723
  file,
34252
35724
  stack: []
@@ -34258,25 +35730,27 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
34258
35730
  path: "word/_rels/footnotes.xml.rels"
34259
35731
  },
34260
35732
  Endnotes: {
34261
- data: (0, import_xml.default)(this.formatter.format(file.Endnotes.View, {
34262
- viewWrapper: file.Endnotes,
34263
- file,
34264
- stack: []
34265
- }), {
34266
- indent: prettify,
34267
- declaration: { encoding: "UTF-8" }
34268
- }),
35733
+ data: (() => {
35734
+ const xmlData = this.imageReplacer.replace(endnoteXmlData, endnoteMediaDatas, endnoteRelationshipCount);
35735
+ return this.numberingReplacer.replace(xmlData, file.Numbering.ConcreteNumbering);
35736
+ })(),
34269
35737
  path: "word/endnotes.xml"
34270
35738
  },
34271
35739
  EndnotesRelationships: {
34272
- data: (0, import_xml.default)(this.formatter.format(file.Endnotes.Relationships, {
34273
- viewWrapper: file.Endnotes,
34274
- file,
34275
- stack: []
34276
- }), {
34277
- indent: prettify,
34278
- declaration: { encoding: "UTF-8" }
34279
- }),
35740
+ data: (() => {
35741
+ const relationships = Relationships.copy(file.Endnotes.Relationships);
35742
+ endnoteMediaDatas.forEach((mediaData, i) => {
35743
+ relationships.addRelationship(endnoteRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35744
+ });
35745
+ return (0, import_xml.default)(this.formatter.format(relationships, {
35746
+ viewWrapper: file.Endnotes,
35747
+ file,
35748
+ stack: []
35749
+ }), {
35750
+ indent: prettify,
35751
+ declaration: { encoding: "UTF-8" }
35752
+ });
35753
+ })(),
34280
35754
  path: "word/_rels/endnotes.xml.rels"
34281
35755
  },
34282
35756
  Settings: {
@@ -34303,10 +35777,11 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
34303
35777
  },
34304
35778
  CommentsRelationships: {
34305
35779
  data: (() => {
35780
+ const relationships = Relationships.copy(file.Comments.Relationships);
34306
35781
  commentMediaDatas.forEach((mediaData, i) => {
34307
- file.Comments.Relationships.addRelationship(commentRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35782
+ relationships.addRelationship(commentRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
34308
35783
  });
34309
- return (0, import_xml.default)(this.formatter.format(file.Comments.Relationships, {
35784
+ return (0, import_xml.default)(this.formatter.format(relationships, {
34310
35785
  viewWrapper: {
34311
35786
  View: file.Comments,
34312
35787
  Relationships: file.Comments.Relationships
@@ -34393,6 +35868,20 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
34393
35868
  path: "word/theme/theme1.xml"
34394
35869
  },
34395
35870
  PackageParts: xmlifyPackageParts(file, prettify),
35871
+ Numbering: {
35872
+ data: (0, import_xml.default)(this.formatter.format(file.Numbering, {
35873
+ viewWrapper: file.Document,
35874
+ file,
35875
+ stack: []
35876
+ }), {
35877
+ indent: prettify,
35878
+ declaration: {
35879
+ standalone: "yes",
35880
+ encoding: "UTF-8"
35881
+ }
35882
+ }),
35883
+ path: "word/numbering.xml"
35884
+ },
34396
35885
  ContentTypes: {
34397
35886
  data: (0, import_xml.default)(this.formatter.format(file.ContentTypes, {
34398
35887
  viewWrapper: file.Document,
@@ -34408,7 +35897,7 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
34408
35897
  }
34409
35898
  };
34410
35899
  //#endregion
34411
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/asyncToGenerator.js
35900
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/asyncToGenerator.js
34412
35901
  function asyncGeneratorStep(n, t, e, r, o, a, c) {
34413
35902
  try {
34414
35903
  var i = n[a](c), u = i.value;
@@ -34578,13 +36067,62 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
34578
36067
  };
34579
36068
  _defineProperty(Packer, "compiler", new Compiler());
34580
36069
  //#endregion
36070
+ //#region src/patcher/bookmark-ids.ts
36071
+ var bookmarkIdOf = (element) => {
36072
+ var _element$attributes;
36073
+ if (element.name !== "w:bookmarkStart" && element.name !== "w:bookmarkEnd") return;
36074
+ const id = Number((_element$attributes = element.attributes) === null || _element$attributes === void 0 ? void 0 : _element$attributes["w:id"]);
36075
+ return Number.isInteger(id) ? id : void 0;
36076
+ };
36077
+ /**
36078
+ * Finds the id of every bookmark in an element, at any depth.
36079
+ *
36080
+ * @param element - The element to search, such as a part's root
36081
+ * @returns The ids, once for each bookmarkStart and bookmarkEnd
36082
+ */
36083
+ var findBookmarkIds = (element) => {
36084
+ var _element$elements;
36085
+ const id = bookmarkIdOf(element);
36086
+ return [...id === void 0 ? [] : [id], ...((_element$elements = element.elements) !== null && _element$elements !== void 0 ? _element$elements : []).flatMap(findBookmarkIds)];
36087
+ };
36088
+ /**
36089
+ * Creates a function that renumbers the bookmarks in content being inserted, so none takes an id the document
36090
+ * already uses. Bookmark ids must be unique within a document, but a bookmark's id is chosen when it is created,
36091
+ * without knowing which ids the template has.
36092
+ *
36093
+ * A bookmark keeps its id if nothing in the document uses it yet, and otherwise gets the next unused one. An id is
36094
+ * renumbered the same way each time, so a bookmark's start and end still share one, even in separate patches.
36095
+ *
36096
+ * @param idsInDocument - The ids of the bookmarks already in the document
36097
+ * @returns A function that returns the elements with their bookmarks renumbered
36098
+ */
36099
+ var renumberBookmarksAvoiding = (idsInDocument) => {
36100
+ const usedIds = new Set(idsInDocument);
36101
+ const newIds = /* @__PURE__ */ new Map();
36102
+ let highestId = idsInDocument.reduce((highest, id) => Math.max(highest, id), 0);
36103
+ const newIdFor = (id) => {
36104
+ const knownId = newIds.get(id);
36105
+ if (knownId !== void 0) return knownId;
36106
+ const newId = usedIds.has(id) ? highestId + 1 : id;
36107
+ highestId = Math.max(highestId, newId);
36108
+ usedIds.add(newId);
36109
+ newIds.set(id, newId);
36110
+ return newId;
36111
+ };
36112
+ const renumber = (element) => {
36113
+ const id = bookmarkIdOf(element);
36114
+ 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) });
36115
+ };
36116
+ return (elements) => elements.map(renumber);
36117
+ };
36118
+ //#endregion
34581
36119
  //#region src/patcher/util.ts
34582
36120
  /**
34583
36121
  * Utility functions for XML manipulation in document patching.
34584
36122
  *
34585
36123
  * @module
34586
36124
  */
34587
- var formatter$1 = new Formatter();
36125
+ var formatter$2 = new Formatter();
34588
36126
  /**
34589
36127
  * Converts XML string to JSON element structure.
34590
36128
  *
@@ -34624,7 +36162,7 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
34624
36162
  */
34625
36163
  var createTextElementContents = (text) => {
34626
36164
  var _textJson$elements$0$;
34627
- 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$ : [];
36165
+ 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$ : [];
34628
36166
  };
34629
36167
  /**
34630
36168
  * Adds xml:space="preserve" attribute to an element.
@@ -34759,6 +36297,11 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
34759
36297
  /** Replace content within paragraphs (inline replacement) */
34760
36298
  PARAGRAPH: "paragraph",
34761
36299
  /**
36300
+ * Repeat the rows of a table that hold the placeholder's fields, such as `{{items.name}}`, once for each row of
36301
+ * data. See {@link TableRowsPatch}
36302
+ */
36303
+ TABLE_ROWS: "tableRows",
36304
+ /**
34762
36305
  * Change a drawing whose alt text holds the placeholder, and the parts it refers to, such as the data of a chart made
34763
36306
  * in Word. See {@link DrawingPatch}
34764
36307
  */
@@ -35072,6 +36615,291 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35072
36615
  for (const { drawing, patch } of found) patch.patch(drawing, createTemplatePackage(parts, binaryParts, file, createContext(drawing.part.path)));
35073
36616
  };
35074
36617
  //#endregion
36618
+ //#region src/patcher/notes.ts
36619
+ /**
36620
+ * Footnotes and endnotes for content inserted into an existing document.
36621
+ *
36622
+ * @module
36623
+ */
36624
+ var formatter$1 = new Formatter();
36625
+ var DOCUMENT_PATH = "word/document.xml";
36626
+ var FOOTNOTES = {
36627
+ path: "word/footnotes.xml",
36628
+ rootName: "w:footnotes",
36629
+ noteName: "w:footnote",
36630
+ referenceName: "w:footnoteReference",
36631
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml",
36632
+ relationshipType: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",
36633
+ create: {
36634
+ part: () => new FootNotes(),
36635
+ mark: () => new FootnoteRefRun(),
36636
+ styles: () => [
36637
+ new FootnoteText({}),
36638
+ new FootnoteTextChar({}),
36639
+ new FootnoteReferenceStyle({})
36640
+ ]
36641
+ }
36642
+ };
36643
+ var ENDNOTES = {
36644
+ path: "word/endnotes.xml",
36645
+ rootName: "w:endnotes",
36646
+ noteName: "w:endnote",
36647
+ referenceName: "w:endnoteReference",
36648
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml",
36649
+ relationshipType: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes",
36650
+ create: {
36651
+ part: () => new Endnotes(),
36652
+ mark: () => new EndnoteRefRun(),
36653
+ styles: () => [
36654
+ new EndnoteText({}),
36655
+ new EndnoteTextChar({}),
36656
+ new EndnoteReferenceStyle({})
36657
+ ]
36658
+ }
36659
+ };
36660
+ var formatElement = (component, context) => toJson((0, import_xml.default)(formatter$1.format(component, context))).elements[0];
36661
+ var findIds = (element, names) => {
36662
+ var _element$name, _element$attributes, _element$elements;
36663
+ 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;
36664
+ return [...Number.isInteger(id) ? [id] : [], ...((_element$elements = element.elements) !== null && _element$elements !== void 0 ? _element$elements : []).flatMap((child) => findIds(child, names))];
36665
+ };
36666
+ var withMark = (paragraph, mark) => {
36667
+ var _paragraph$elements, _elements$;
36668
+ const elements = (_paragraph$elements = paragraph.elements) !== null && _paragraph$elements !== void 0 ? _paragraph$elements : [];
36669
+ const index = ((_elements$ = elements[0]) === null || _elements$ === void 0 ? void 0 : _elements$.name) === "w:pPr" ? 1 : 0;
36670
+ return _objectSpread2(_objectSpread2({}, paragraph), {}, { elements: [
36671
+ ...elements.slice(0, index),
36672
+ mark,
36673
+ ...elements.slice(index)
36674
+ ] });
36675
+ };
36676
+ var patchNotesOfKind = (kind, notes, parts, { createContext, addContentTypeOverride, renumberBookmarks }) => {
36677
+ const givenNotes = new Map(Object.entries(notes).map(([id, note]) => [Number(id), note]));
36678
+ const noteOfId = /* @__PURE__ */ new Map();
36679
+ let highestId;
36680
+ const renumber = (element) => {
36681
+ var _element$attributes2, _highestId;
36682
+ 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;
36683
+ if (note === void 0) return element.elements === void 0 ? element : _objectSpread2(_objectSpread2({}, element), {}, { elements: element.elements.map(renumber) });
36684
+ 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;
36685
+ noteOfId.set(highestId, note);
36686
+ return _objectSpread2(_objectSpread2({}, element), {}, { attributes: _objectSpread2(_objectSpread2({}, element.attributes), {}, { "w:id": String(highestId) }) });
36687
+ };
36688
+ const findOrAddPart = () => {
36689
+ var _parts$get;
36690
+ const relationship = getFirstLevelElements((_parts$get = parts.get(relationshipsPathOf(DOCUMENT_PATH))) !== null && _parts$get !== void 0 ? _parts$get : {}, "Relationships").find((element) => {
36691
+ var _element$attributes3;
36692
+ return ((_element$attributes3 = element.attributes) === null || _element$attributes3 === void 0 ? void 0 : _element$attributes3.Type) === kind.relationshipType;
36693
+ });
36694
+ const path = relationship ? resolveTarget(DOCUMENT_PATH, String(relationship.attributes.Target)) : kind.path;
36695
+ if (!parts.has(path)) {
36696
+ parts.set(path, {
36697
+ declaration: { attributes: {
36698
+ version: "1.0",
36699
+ encoding: "UTF-8",
36700
+ standalone: "yes"
36701
+ } },
36702
+ elements: [formatElement(kind.create.part(), createContext(path))]
36703
+ });
36704
+ addContentTypeOverride(kind.contentType, `/${path}`);
36705
+ }
36706
+ if (!relationship) createContext(DOCUMENT_PATH).viewWrapper.Relationships.addRelationship(uniqueId(), kind.relationshipType, relativeTarget(DOCUMENT_PATH, path));
36707
+ return path;
36708
+ };
36709
+ const write = () => {
36710
+ if (noteOfId.size === 0) return;
36711
+ const path = findOrAddPart();
36712
+ const context = createContext(path);
36713
+ const contentOfNote = new Map([...new Set(noteOfId.values())].map((note) => {
36714
+ const mark = formatElement(kind.create.mark(), context);
36715
+ return [note, renumberBookmarks(note.children.map((paragraph) => formatElement(paragraph, context)).map((paragraph, index) => index === 0 ? withMark(paragraph, mark) : paragraph))];
36716
+ }));
36717
+ getFirstLevelElements(parts.get(path), kind.rootName).push(...[...noteOfId].map(([id, note]) => ({
36718
+ type: "element",
36719
+ name: kind.noteName,
36720
+ attributes: { "w:id": String(id) },
36721
+ elements: [...contentOfNote.get(note)]
36722
+ })));
36723
+ const stylesPart = parts.get("word/styles.xml");
36724
+ if (stylesPart) {
36725
+ const styles = getFirstLevelElements(stylesPart, "w:styles");
36726
+ const styleIds = new Set(styles.map((style) => {
36727
+ var _style$attributes;
36728
+ return (_style$attributes = style.attributes) === null || _style$attributes === void 0 ? void 0 : _style$attributes["w:styleId"];
36729
+ }));
36730
+ styles.push(...kind.create.styles().map((style) => formatElement(style, context)).filter((style) => {
36731
+ var _style$attributes2;
36732
+ return !styleIds.has((_style$attributes2 = style.attributes) === null || _style$attributes2 === void 0 ? void 0 : _style$attributes2["w:styleId"]);
36733
+ }));
36734
+ }
36735
+ };
36736
+ return {
36737
+ renumber: (elements) => elements.map(renumber),
36738
+ write
36739
+ };
36740
+ };
36741
+ /**
36742
+ * Creates the writer of the footnotes and endnotes that patches refer to.
36743
+ *
36744
+ * A patch refers to a note with a reference run, such as `new FootnoteReferenceRun(1)`, whose id is the note's in
36745
+ * `footnotes`. Only references to the given notes are renumbered, and only the notes that are referred to are written.
36746
+ *
36747
+ * @param notes - The footnotes and endnotes, by the id the patches' reference runs are given
36748
+ * @param parts - The document's XML parts, parsed, by their paths, which the notes are written to
36749
+ * @param helpers - The patcher's helpers for what the notes refer to
36750
+ */
36751
+ var patchNotes = ({ footnotes = {}, endnotes = {} }, parts, helpers) => {
36752
+ const patchers = [patchNotesOfKind(FOOTNOTES, footnotes, parts, helpers), patchNotesOfKind(ENDNOTES, endnotes, parts, helpers)];
36753
+ return {
36754
+ renumber: (elements) => patchers.reduce((renumbered, patcher) => patcher.renumber(renumbered), elements),
36755
+ write: () => {
36756
+ for (const patcher of patchers) patcher.write();
36757
+ }
36758
+ };
36759
+ };
36760
+ //#endregion
36761
+ //#region src/patcher/page-numbers.ts
36762
+ /**
36763
+ * Page numbers written into a template's fields once `patchDocument` has patched it, from an estimate of its pages, as
36764
+ * a document's are when it is written with `pageNumbers`.
36765
+ *
36766
+ * @module
36767
+ */
36768
+ /** The elements of a template, as xml-js parses them */
36769
+ var PARSED = {
36770
+ nameOf: (element) => element.type === "element" ? element.name : void 0,
36771
+ contentOf: (element) => element.elements,
36772
+ attributeOf: (element, attribute) => {
36773
+ var _element$attributes;
36774
+ return (_element$attributes = element.attributes) === null || _element$attributes === void 0 ? void 0 : _element$attributes[attribute];
36775
+ },
36776
+ textOf: (element) => {
36777
+ var _element$elements;
36778
+ return ((_element$elements = element.elements) !== null && _element$elements !== void 0 ? _element$elements : []).filter(({ type }) => type === "text").map(({ text }) => String(text)).join("");
36779
+ },
36780
+ textElement: (text) => ({
36781
+ type: "element",
36782
+ name: "w:t",
36783
+ attributes: { "xml:space": "preserve" },
36784
+ elements: [{
36785
+ type: "text",
36786
+ text
36787
+ }]
36788
+ }),
36789
+ writeClean: (begin, instruction) => {
36790
+ var _begin$attributes;
36791
+ 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"));
36792
+ },
36793
+ setSimpleFieldResult: (element, text) => {
36794
+ element.elements = [{
36795
+ type: "element",
36796
+ name: "w:r",
36797
+ elements: [PARSED.textElement(text)]
36798
+ }];
36799
+ }
36800
+ };
36801
+ var DOCUMENT = "word/document.xml";
36802
+ var IMPORT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk";
36803
+ var ZIP = [
36804
+ 80,
36805
+ 75,
36806
+ 3,
36807
+ 4
36808
+ ];
36809
+ /** A package's parts, from a zip file: its XML parts parsed, as patchDocument parses a template's, and the rest as bytes */
36810
+ var readPackage = function() {
36811
+ var _ref = _asyncToGenerator(function* (data) {
36812
+ if (!ZIP.every((byte, index) => data[index] === byte)) return;
36813
+ try {
36814
+ const zip = yield import_jszip_min.default.loadAsync(data);
36815
+ const parts = /* @__PURE__ */ new Map();
36816
+ const binaryParts = /* @__PURE__ */ new Map();
36817
+ for (const [path, file] of Object.entries(zip.files)) {
36818
+ if (file.dir) continue;
36819
+ if (/\.(xml|rels)$/.test(path)) parts.set(path, toJson(yield file.async("text")));
36820
+ else binaryParts.set(path, yield file.async("uint8array"));
36821
+ }
36822
+ const importedDocuments = yield readImportedDocuments(parts, binaryParts);
36823
+ return _objectSpread2({
36824
+ parts,
36825
+ binaryParts
36826
+ }, importedDocuments.size > 0 ? { importedDocuments } : {});
36827
+ } catch (_unused) {
36828
+ return;
36829
+ }
36830
+ });
36831
+ return function readPackage(_x) {
36832
+ return _ref.apply(this, arguments);
36833
+ };
36834
+ }();
36835
+ /**
36836
+ * Each .docx the parts of a package import (`w:altChunk`), by its path: the parts the relationships of each part refer to
36837
+ * as imported, which are zip files that can be read. Those in other formats, such as HTML, are left to the layout.
36838
+ */
36839
+ var readImportedDocuments = function() {
36840
+ var _ref2 = _asyncToGenerator(function* (parts, binaryParts) {
36841
+ const imported = /* @__PURE__ */ new Map();
36842
+ for (const [path, relationships] of parts) {
36843
+ var _rootOf$elements, _rootOf;
36844
+ if (!path.endsWith(".rels")) continue;
36845
+ for (const { attributes = {} } of (_rootOf$elements = (_rootOf = rootOf(relationships)) === null || _rootOf === void 0 ? void 0 : _rootOf.elements) !== null && _rootOf$elements !== void 0 ? _rootOf$elements : []) {
36846
+ const target = resolveTarget(sourceOfRelationships(path), String(attributes.Target));
36847
+ const data = binaryParts.get(target);
36848
+ const read = attributes.Type === IMPORT && attributes.TargetMode !== "External" && data ? yield readPackage(data) : void 0;
36849
+ if (read) imported.set(target, read);
36850
+ }
36851
+ }
36852
+ return imported;
36853
+ });
36854
+ return function readImportedDocuments(_x2, _x3) {
36855
+ return _ref2.apply(this, arguments);
36856
+ };
36857
+ }();
36858
+ /** The root element of a part, such as `w:document` */
36859
+ var rootOf = (part) => {
36860
+ var _part$elements;
36861
+ return part === null || part === void 0 || (_part$elements = part.elements) === null || _part$elements === void 0 ? void 0 : _part$elements.find(({ type }) => type === "element");
36862
+ };
36863
+ /**
36864
+ * Writes the page numbers the estimator works out for a patched template into the fields of its body, headers and
36865
+ * footers that show them: its PAGEREF fields, in its tables of contents and elsewhere, and its NUMPAGES and SECTIONPAGES
36866
+ * fields. The results a field was written with are those of the template before it was patched, so a field whose number
36867
+ * the estimator doesn't work out is left blank, as it is in a document written with `pageNumbers`. Page references and
36868
+ * tables of contents are written clean, as they are in a document written with `pageNumbers`, so Word shows their numbers
36869
+ * as they are and doesn't ask to update the fields.
36870
+ *
36871
+ * The documents it imports (`w:altChunk`) as .docx files are unzipped for the estimator to read, as Word turns them into
36872
+ * paragraphs and tables of the template's own when it opens it.
36873
+ *
36874
+ * @param parts - The template's XML parts, parsed, by their paths, which are changed in place
36875
+ * @param binaryParts - Its other parts, by their paths, for the estimator to read the fonts it embeds and the documents
36876
+ * it imports
36877
+ */
36878
+ var fillTemplatePageNumbers = function() {
36879
+ var _ref3 = _asyncToGenerator(function* (parts, estimator, binaryParts = /* @__PURE__ */ new Map()) {
36880
+ var _rootOf$elements2, _rootOf2;
36881
+ const document = rootOf(parts.get(DOCUMENT));
36882
+ if (!document) return;
36883
+ const importedDocuments = yield readImportedDocuments(parts, binaryParts);
36884
+ const estimate = estimator(_objectSpread2({
36885
+ parts,
36886
+ binaryParts
36887
+ }, importedDocuments.size > 0 ? { importedDocuments } : {}));
36888
+ const partPageCounts = fillBodyFields(PARSED, document, estimate, { blank: true });
36889
+ 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 : [];
36890
+ for (const { attributes = {} } of relationships) {
36891
+ const part = /\/(header|footer)$/.test(String(attributes.Type)) ? rootOf(parts.get(resolveTarget(DOCUMENT, String(attributes.Target)))) : void 0;
36892
+ if (part) fillPartFields(PARSED, part, estimate, {
36893
+ blank: true,
36894
+ sectionPageCount: partPageCounts.get(String(attributes.Id))
36895
+ });
36896
+ }
36897
+ });
36898
+ return function fillTemplatePageNumbers(_x4, _x5) {
36899
+ return _ref3.apply(this, arguments);
36900
+ };
36901
+ }();
36902
+ //#endregion
35075
36903
  //#region src/patcher/paragraph-split-inject.ts
35076
36904
  var TokenNotFoundError = class extends Error {
35077
36905
  constructor(token) {
@@ -35373,9 +37201,11 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35373
37201
  * @param context - The document context for formatting
35374
37202
  * @param keepOriginalStyles - Whether to preserve original text formatting
35375
37203
  * @param recursive - Whether to replace every occurrence in a paragraph, rather than only the first
37204
+ * @param renumberIds - Renumbers the bookmarks and note references the patch inserts, so they don't take an id the
37205
+ * document uses
35376
37206
  * @returns Result containing the modified element and whether a replacement occurred
35377
37207
  */
35378
- var replacer = ({ json, patch, patchText, context, keepOriginalStyles = true, recursive = true }) => {
37208
+ var replacer = ({ json, patch, patchText, context, keepOriginalStyles = true, recursive = true, renumberIds = (elements) => elements }) => {
35379
37209
  const renderedParagraphs = findLocationOfText(json, patchText);
35380
37210
  if (renderedParagraphs.length === 0) return {
35381
37211
  element: json,
@@ -35385,9 +37215,15 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35385
37215
  const paragraphsToPatch = patch.type === PatchType.DOCUMENT ? withoutNestedParagraphs(paragraphsInPatchOrder) : paragraphsInPatchOrder;
35386
37216
  for (const renderedParagraph of paragraphsToPatch) switch (patch.type) {
35387
37217
  case PatchType.DOCUMENT: {
37218
+ var _children;
35388
37219
  const parentElement = goToParentElementFromPath(json, renderedParagraph.pathToParagraph);
35389
37220
  const elementIndex = getLastElementIndexFromPath(renderedParagraph.pathToParagraph);
35390
- parentElement.elements.splice(elementIndex, 1, ...formatChildren(patch, context));
37221
+ const children = formatChildren(patch, context, renumberIds);
37222
+ 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" ? [{
37223
+ type: "element",
37224
+ name: "w:p"
37225
+ }] : [];
37226
+ parentElement.elements.splice(elementIndex, 1, ...children, ...endParagraph);
35391
37227
  break;
35392
37228
  }
35393
37229
  case PatchType.PARAGRAPH:
@@ -35401,7 +37237,7 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35401
37237
  renderedParagraph: paragraph,
35402
37238
  patchText,
35403
37239
  fromIndex,
35404
- children: formatChildren(patch, context),
37240
+ children: formatChildren(patch, context, renumberIds),
35405
37241
  keepOriginalStyles
35406
37242
  });
35407
37243
  paragraph = renderParagraphNode({
@@ -35419,10 +37255,10 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35419
37255
  didFindOccurrence: true
35420
37256
  };
35421
37257
  };
35422
- var formatChildren = (patch, context) => patch.children.flatMap((c) => {
37258
+ var formatChildren = (patch, context, renumberIds) => renumberIds(patch.children.flatMap((c) => {
35423
37259
  var _c$writtenAs;
35424
37260
  return (_c$writtenAs = c.writtenAs) !== null && _c$writtenAs !== void 0 ? _c$writtenAs : c;
35425
- }).map((c) => toJson((0, import_xml.default)(formatter.format(c, context)))).map((c) => c.elements[0]);
37261
+ }).map((c) => toJson((0, import_xml.default)(formatter.format(c, context)))).map((c) => c.elements[0]));
35426
37262
  /**
35427
37263
  * Replaces the first occurrence of the placeholder from `fromIndex` on, splitting the run it starts in.
35428
37264
  *
@@ -35440,12 +37276,21 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35440
37276
  const runElementToBeReplaced = paragraphElement.elements[index];
35441
37277
  const { left, right } = splitRunElement(runElementToBeReplaced, SPLIT_TOKEN);
35442
37278
  const runProperties = runElementToBeReplaced.elements.find((e) => e.type === "element" && e.name === "w:rPr");
35443
- const newRunElements = keepOriginalStyles && runProperties ? children.map((e) => e.name === "w:r" ? withRunProperties(e, runProperties) : e) : children;
37279
+ const newRunElements = keepOriginalStyles && runProperties ? children.map((e) => withRunPropertiesOnRuns(e, runProperties)) : children;
35444
37280
  const patchedRightElement = runProperties ? _objectSpread2(_objectSpread2({}, right), {}, { elements: [runProperties, ...right.elements] }) : right;
35445
37281
  paragraphElement.elements.splice(index, 1, left, ...newRunElements, patchedRightElement);
35446
37282
  return index + 1 + newRunElements.length;
35447
37283
  };
35448
37284
  /**
37285
+ * Gives the runs of inserted content the placeholder's run properties. Content such as a hyperlink can't take run
37286
+ * properties itself, so its runs take them, and its text is formatted as the text around it is. Runs inside a run, such
37287
+ * as in its text box, are that content's own, and are left alone.
37288
+ */
37289
+ var withRunPropertiesOnRuns = (element, originalRunProperties) => {
37290
+ if (element.name === "w:r") return withRunProperties(element, originalRunProperties);
37291
+ return element.elements ? _objectSpread2(_objectSpread2({}, element), {}, { elements: element.elements.map((e) => withRunPropertiesOnRuns(e, originalRunProperties)) }) : element;
37292
+ };
37293
+ /**
35449
37294
  * Gives a run the placeholder's run properties. A run can only have one w:rPr, so properties the run
35450
37295
  * sets itself are kept, and the placeholder's fill in the rest.
35451
37296
  */
@@ -35537,6 +37382,118 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35537
37382
  var goToParentElementFromPath = (json, path) => goToElementFromPath(json, path.slice(0, path.length - 1));
35538
37383
  var getLastElementIndexFromPath = (path) => path[path.length - 1];
35539
37384
  //#endregion
37385
+ //#region src/patcher/table-rows.ts
37386
+ var EMPTY = {
37387
+ type: PatchType.PARAGRAPH,
37388
+ children: []
37389
+ };
37390
+ /**
37391
+ * Repeats the rows of the tables in an element that hold the patch's fields, such as `{{items.name}}` for the key
37392
+ * "items", once for each of the patch's rows, and patches the fields in each copy with the row's patches.
37393
+ *
37394
+ * @param json - The element to patch, such as a part's root
37395
+ * @param key - The patch's key, such as "items"
37396
+ * @param patch - The rows of data
37397
+ * @param delimiters - The placeholders' delimiters
37398
+ * @param patchPlaceholder - Patches a field in a copy of the rows, as `patchDocument` patches a placeholder
37399
+ */
37400
+ var patchTableRows = ({ json, key, patch, delimiters: { start, end }, patchPlaceholder }) => {
37401
+ const fieldStart = `${start}${key}.`;
37402
+ for (const rows of findRowsToRepeat(json, fieldStart)) {
37403
+ const fields = fieldsIn(rows.elements, fieldStart, end);
37404
+ const copies = patch.rows.flatMap((row, index) => {
37405
+ const copy = {
37406
+ type: "element",
37407
+ name: "w:tbl",
37408
+ elements: [...index === 0 ? rows.elements.map(copyOf) : withoutIds(rows.elements)]
37409
+ };
37410
+ const fieldPatches = new Map(Object.entries(row).flatMap(([field, p]) => p === void 0 ? [] : [[field, p]]));
37411
+ for (const [field, fieldPatch] of fieldPatches) patchPlaceholder(copy, `${key}.${field}`, fieldPatch);
37412
+ for (const field of fields.filter((f) => !fieldPatches.has(f))) patchPlaceholder(copy, `${key}.${field}`, EMPTY);
37413
+ return copy.elements;
37414
+ });
37415
+ rows.parent.elements.splice(rows.parent.elements.indexOf(rows.elements[0]), rows.elements.length, ...copies);
37416
+ if (rows.table && !hasRows(rows.table.element)) rows.table.parent.elements.splice(rows.table.parent.elements.indexOf(rows.table.element), 1);
37417
+ }
37418
+ };
37419
+ /**
37420
+ * The rows that hold a field, grouped into the rows next to each other in a table, which are repeated together.
37421
+ */
37422
+ var findRowsToRepeat = (json, fieldStart) => {
37423
+ const found = findLocationOfText(json, fieldStart).flatMap((paragraph) => {
37424
+ const row = rowHolding(json, paragraph.pathToParagraph);
37425
+ return row ? [row] : [];
37426
+ });
37427
+ 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);
37428
+ return [...new Set(rows.map((row) => row.parent))].flatMap((parent) => {
37429
+ const siblingRows = parent.elements.filter((e) => e.name === "w:tr");
37430
+ const positions = rows.filter((row) => row.parent === parent).map((row) => siblingRows.indexOf(row.row)).sort((a, b) => a - b);
37431
+ const { table } = rows.find((row) => row.parent === parent);
37432
+ return positions.reduce((all, position) => {
37433
+ const previous = all[all.length - 1];
37434
+ return (previous === null || previous === void 0 ? void 0 : previous[previous.length - 1]) === position - 1 ? [...all.slice(0, -1), [...previous, position]] : [...all, [position]];
37435
+ }, []).map((group) => {
37436
+ const first = parent.elements.indexOf(siblingRows[group[0]]);
37437
+ const last = parent.elements.indexOf(siblingRows[group[group.length - 1]]);
37438
+ return {
37439
+ parent,
37440
+ table,
37441
+ elements: parent.elements.slice(first, last + 1)
37442
+ };
37443
+ });
37444
+ });
37445
+ };
37446
+ /**
37447
+ * The row nearest to the paragraph at the end of the path that holds it, if it is in a table.
37448
+ */
37449
+ var rowHolding = (json, pathToParagraph) => {
37450
+ let element = json;
37451
+ let row;
37452
+ let table;
37453
+ for (let i = 1; i < pathToParagraph.length; i++) {
37454
+ const child = element.elements[pathToParagraph[i]];
37455
+ if (child.name === "w:tbl") table = {
37456
+ element: child,
37457
+ parent: element
37458
+ };
37459
+ if (child.name === "w:tr") row = {
37460
+ parent: element,
37461
+ table,
37462
+ row: child,
37463
+ path: pathToParagraph.slice(0, i + 1)
37464
+ };
37465
+ element = child;
37466
+ }
37467
+ return row;
37468
+ };
37469
+ var isInside = (path, ancestorPath) => path.length > ancestorPath.length && ancestorPath.every((index, i) => path[i] === index);
37470
+ var hasRows = (table) => {
37471
+ var _table$elements;
37472
+ 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));
37473
+ };
37474
+ /**
37475
+ * The names of the fields in the elements, such as "name" for `{{items.name}}`.
37476
+ */
37477
+ var fieldsIn = (elements, fieldStart, end) => {
37478
+ const fields = findLocationOfText({ elements: [...elements] }, fieldStart).flatMap(({ text }) => text.split(fieldStart).slice(1).flatMap((after) => {
37479
+ const fieldEnd = after.indexOf(end);
37480
+ return fieldEnd > 0 ? [after.slice(0, fieldEnd)] : [];
37481
+ }));
37482
+ return [...new Set(fields)];
37483
+ };
37484
+ var copyOf = (element) => JSON.parse(JSON.stringify(element));
37485
+ var ATTRIBUTES_TO_REMOVE = ["w14:paraId", "w14:textId"];
37486
+ var ELEMENTS_TO_REMOVE = ["w:bookmarkStart", "w:bookmarkEnd"];
37487
+ /**
37488
+ * A copy of elements without what must be unique in a document, so they can be in the document more than once.
37489
+ *
37490
+ * @param parent - The elements' parent, as a content control's id is an element in its properties
37491
+ */
37492
+ var withoutIds = (elements, parent) => elements.filter((e) => {
37493
+ var _e$name;
37494
+ 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");
37495
+ }).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)] }));
37496
+ //#endregion
35540
37497
  //#region src/patcher/theme-colors.ts
35541
37498
  var THEME_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
35542
37499
  var COLOR_NAMES = /* @__PURE__ */ new Map([
@@ -35595,7 +37552,7 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35595
37552
  return ((_item$attributes3 = item.attributes) === null || _item$attributes3 === void 0 ? void 0 : _item$attributes3.Type) === THEME_RELATIONSHIP_TYPE;
35596
37553
  });
35597
37554
  const target = theme === null || theme === void 0 || (_theme$attributes = theme.attributes) === null || _theme$attributes === void 0 ? void 0 : _theme$attributes.Target;
35598
- return typeof target === "string" ? readPart(zip, target.startsWith("/") ? target.slice(1) : `word/${target}`) : void 0;
37555
+ return typeof target === "string" ? readPart(zip, resolveTarget("word/document.xml", target)) : void 0;
35599
37556
  });
35600
37557
  return function readTheme(_x3) {
35601
37558
  return _ref2.apply(this, arguments);
@@ -35634,6 +37591,23 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35634
37591
  *
35635
37592
  * @module
35636
37593
  */
37594
+ /**
37595
+ * 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
37596
+ * from JavaScript without its children.
37597
+ *
37598
+ * @param key - The patch's key, such as "items", or for a field of a row, such as "items.name"
37599
+ * @param inTableRow - Whether the patch is for a field of a row, where a drawing patch can't be
37600
+ */
37601
+ var assertValidPatch = (key, patch, { inTableRow }) => {
37602
+ if ((patch === null || patch === void 0 ? void 0 : patch.type) === PatchType.TABLE_ROWS && Array.isArray(patch.rows)) {
37603
+ for (const row of patch.rows) {
37604
+ 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`);
37605
+ for (const [field, fieldPatch] of Object.entries(row)) if (fieldPatch !== void 0) assertValidPatch(`${key}.${field}`, fieldPatch, { inTableRow: true });
37606
+ }
37607
+ return;
37608
+ }
37609
+ 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"}`);
37610
+ };
35637
37611
  var imageReplacer = new ImageReplacer();
35638
37612
  var UTF16LE = new Uint8Array([255, 254]);
35639
37613
  var UTF16BE = new Uint8Array([254, 255]);
@@ -35681,7 +37655,7 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35681
37655
  var _ref = _asyncToGenerator(function* ({ outputType, data, patches, keepOriginalStyles, placeholderDelimiters = {
35682
37656
  start: "{{",
35683
37657
  end: "}}"
35684
- }, recursive = true }) {
37658
+ }, recursive = true, footnotes, endnotes, pageNumbers }) {
35685
37659
  const zipContent = data instanceof import_jszip_min.default ? data : yield import_jszip_min.default.loadAsync(data);
35686
37660
  const contexts = /* @__PURE__ */ new Map();
35687
37661
  const themeColors = yield readThemeColors(zipContent);
@@ -35701,7 +37675,7 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35701
37675
  const binaryContentMap = /* @__PURE__ */ new Map();
35702
37676
  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.");
35703
37677
  const { start, end } = placeholderDelimiters;
35704
- 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`);
37678
+ for (const [key, patch] of Object.entries(patches)) assertValidPatch(key, patch, { inTableRow: false });
35705
37679
  for (const [key, value] of Object.entries(zipContent.files)) {
35706
37680
  const binaryValue = yield value.async("uint8array");
35707
37681
  const startBytes = binaryValue.slice(0, 2);
@@ -35730,6 +37704,7 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35730
37704
  }
35731
37705
  map.set(key, json);
35732
37706
  }
37707
+ const renumberBookmarks = renumberBookmarksAvoiding([...map.values()].flatMap(findBookmarkIds));
35733
37708
  const createContext = (key) => ({
35734
37709
  file,
35735
37710
  viewWrapper: { Relationships: { addRelationship: (id, type, target, targetMode) => {
@@ -35743,6 +37718,17 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35743
37718
  } } },
35744
37719
  stack: []
35745
37720
  });
37721
+ const notes = patchNotes({
37722
+ footnotes,
37723
+ endnotes
37724
+ }, map, {
37725
+ createContext,
37726
+ addContentTypeOverride: (contentType, partName) => contentTypeOverrides.push({
37727
+ contentType,
37728
+ partName
37729
+ }),
37730
+ renumberBookmarks
37731
+ });
35746
37732
  patchDrawings({
35747
37733
  parts: map,
35748
37734
  binaryParts: binaryContentMap,
@@ -35753,35 +37739,56 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35753
37739
  end
35754
37740
  }
35755
37741
  }, createContext);
37742
+ const textPatches = Object.entries(patches).flatMap(([key, patch]) => patch.type === PatchType.DRAWING ? [] : [[key, patch]]);
37743
+ const patchesInOrder = [...textPatches.filter(([, patch]) => patch.type === PatchType.TABLE_ROWS), ...textPatches.filter(([, patch]) => patch.type !== PatchType.TABLE_ROWS)];
35756
37744
  for (const [key, json] of [...map]) {
35757
37745
  if (!key.startsWith("word/") || key.endsWith(".xml.rels")) continue;
35758
37746
  const context = createContext(key);
35759
37747
  contexts.set(key, context);
35760
- for (const [patchKey, patchValue] of Object.entries(patches)) {
35761
- if (patchValue.type === PatchType.DRAWING) continue;
35762
- const patchText = `${start}${patchKey}${end}`;
35763
- replacer({
35764
- json,
35765
- patch: _objectSpread2(_objectSpread2({}, patchValue), {}, { children: patchValue.children.map((element) => {
35766
- if (element instanceof ExternalHyperlink) {
35767
- const concreteHyperlink = new ConcreteHyperlink(element.options.children, uniqueId());
35768
- relationshipAdditions.push({
37748
+ const patchPlaceholder = (element, patchKey, patchValue) => {
37749
+ if (patchValue.type === PatchType.TABLE_ROWS) {
37750
+ patchTableRows({
37751
+ json: element,
37752
+ key: patchKey,
37753
+ patch: patchValue,
37754
+ delimiters: {
37755
+ start,
37756
+ end
37757
+ },
37758
+ patchPlaceholder
37759
+ });
37760
+ return;
37761
+ }
37762
+ const hyperlinkRelationships = [];
37763
+ const { didFindOccurrence } = replacer({
37764
+ json: element,
37765
+ patch: _objectSpread2(_objectSpread2({}, patchValue), {}, { children: patchValue.children.flatMap((child) => child instanceof Bookmark ? child.writtenAs : [child]).map((child) => {
37766
+ if (child instanceof ExternalHyperlink) {
37767
+ const concreteHyperlink = new ConcreteHyperlink(child.options.children, uniqueId());
37768
+ hyperlinkRelationships.push({
35769
37769
  key,
35770
37770
  id: concreteHyperlink.linkId,
35771
37771
  type: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
35772
- target: element.options.link,
37772
+ target: child.options.link,
35773
37773
  targetMode: TargetModeType.EXTERNAL
35774
37774
  });
35775
37775
  return concreteHyperlink;
35776
- } else return element;
37776
+ } else return child;
35777
37777
  }) }),
35778
- patchText,
37778
+ patchText: `${start}${patchKey}${end}`,
35779
37779
  context,
35780
37780
  keepOriginalStyles,
35781
- recursive
37781
+ recursive,
37782
+ renumberIds: (elements) => notes.renumber(renumberBookmarks(elements))
35782
37783
  });
35783
- }
35784
- const mediaDatas = imageReplacer.getMediaData(JSON.stringify(json), context.file.Media);
37784
+ if (didFindOccurrence) relationshipAdditions.push(...hyperlinkRelationships);
37785
+ };
37786
+ for (const [patchKey, patchValue] of patchesInOrder) patchPlaceholder(json, patchKey, patchValue);
37787
+ }
37788
+ notes.write();
37789
+ for (const [key, json] of map) {
37790
+ if (!key.startsWith("word/") || key.endsWith(".xml.rels")) continue;
37791
+ const mediaDatas = imageReplacer.getMediaData(JSON.stringify(json), file.Media);
35785
37792
  if (mediaDatas.length > 0) {
35786
37793
  hasMedia = true;
35787
37794
  imageRelationshipAdditions.push({
@@ -35810,6 +37817,7 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35810
37817
  map.set(relationshipKey, relationshipsJson);
35811
37818
  appendRelationship(relationshipsJson, id, type, target, targetMode);
35812
37819
  }
37820
+ if (pageNumbers) yield fillTemplatePageNumbers(map, pageNumbers, binaryContentMap);
35813
37821
  const packageParts = xmlifyPackageParts(file, void 0);
35814
37822
  if (hasMedia || contentTypeOverrides.length > 0) {
35815
37823
  const contentTypesJson = map.get("[Content_Types].xml");
@@ -35843,12 +37851,13 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35843
37851
  };
35844
37852
  }();
35845
37853
  /**
35846
- * The element with an extra escape on each "&" in its text. xml-js reads "&amp;" in text as an "&" already escaped, and
35847
- * would write a text's literal "&amp;", such as in a document about HTML, as "&".
37854
+ * The element with an extra escape on each "&" in its text and attributes. xml-js reads "&amp;" in text as an "&"
37855
+ * already escaped, and would write a text's literal "&amp;", such as in a document about HTML, as "&". It escapes the
37856
+ * quotes in an attribute before `attributeValueFn` is given it, so that can't tell its "&quot;" from a literal one.
35848
37857
  */
35849
- 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)) });
37858
+ 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)) });
35850
37859
  var toXml = (jsonObj) => {
35851
- 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;") });
37860
+ return (0, import_lib.js2xml)(withAmpersandsEscaped(jsonObj), { attributeValueFn: (str) => String(str).replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/'/g, "&apos;") });
35852
37861
  };
35853
37862
  //#endregion
35854
37863
  //#region src/patcher/patch-detector.ts
@@ -35963,6 +37972,7 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35963
37972
  exports.EmphasisMarkType = EmphasisMarkType;
35964
37973
  exports.EmptyElement = EmptyElement;
35965
37974
  exports.EndnoteIdReference = EndnoteIdReference;
37975
+ exports.EndnotePosition = EndnotePosition;
35966
37976
  exports.EndnoteReference = EndnoteReference;
35967
37977
  exports.EndnoteReferenceRun = EndnoteReferenceRun;
35968
37978
  exports.EndnoteReferenceRunAttributes = EndnoteReferenceRunAttributes;
@@ -35974,6 +37984,7 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
35974
37984
  exports.FootNotes = FootNotes;
35975
37985
  exports.Footer = Footer;
35976
37986
  exports.FooterWrapper = FooterWrapper;
37987
+ exports.FootnotePosition = FootnotePosition;
35977
37988
  exports.FootnoteReference = FootnoteReference;
35978
37989
  exports.FootnoteReferenceElement = FootnoteReferenceElement;
35979
37990
  exports.FootnoteReferenceRun = FootnoteReferenceRun;
@@ -36040,6 +38051,7 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
36040
38051
  exports.NextAttributeComponent = NextAttributeComponent;
36041
38052
  exports.NoBreakHyphen = NoBreakHyphen;
36042
38053
  exports.NonVisualDrawingProperties = NonVisualDrawingProperties;
38054
+ exports.NoteNumberRestart = NoteNumberRestart;
36043
38055
  exports.NumberFormat = NumberFormat;
36044
38056
  exports.NumberProperties = NumberProperties;
36045
38057
  exports.NumberValueElement = NumberValueElement;
@@ -36154,6 +38166,8 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
36154
38166
  exports.createDocumentGrid = createDocumentGrid;
36155
38167
  exports.createDotEmphasisMark = createDotEmphasisMark;
36156
38168
  exports.createEmphasisMark = createEmphasisMark;
38169
+ exports.createEndnoteProperties = createEndnoteProperties;
38170
+ exports.createFootnoteProperties = createFootnoteProperties;
36157
38171
  exports.createFrameProperties = createFrameProperties;
36158
38172
  exports.createHeaderFooterReference = createHeaderFooterReference;
36159
38173
  exports.createHorizontalPosition = createHorizontalPosition;
@@ -36203,6 +38217,9 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
36203
38217
  exports.docPropertiesUniqueNumericIdGen = docPropertiesUniqueNumericIdGen;
36204
38218
  exports.eighthPointMeasureValue = eighthPointMeasureValue;
36205
38219
  exports.encodeUtf8 = encodeUtf8;
38220
+ exports.fillPageNumbers = fillPageNumbers;
38221
+ exports.fillPartPageNumbers = fillPartPageNumbers;
38222
+ exports.fillSequenceNumbers = fillSequenceNumbers;
36206
38223
  exports.hashedId = hashedId;
36207
38224
  exports.hexColorValue = hexColorValue;
36208
38225
  exports.hpsMeasureValue = hpsMeasureValue;