docx 9.8.0 → 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.
package/dist/index.cjs CHANGED
@@ -30,7 +30,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  enumerable: true
31
31
  }) : target, mod));
32
32
  //#endregion
33
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/typeof.js
33
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/typeof.js
34
34
  function _typeof(o) {
35
35
  "@babel/helpers - typeof";
36
36
  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
@@ -40,7 +40,7 @@ function _typeof(o) {
40
40
  }, _typeof(o);
41
41
  }
42
42
  //#endregion
43
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/toPrimitive.js
43
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/toPrimitive.js
44
44
  function toPrimitive(t, r) {
45
45
  if ("object" != _typeof(t) || !t) return t;
46
46
  var e = t[Symbol.toPrimitive];
@@ -52,13 +52,13 @@ function toPrimitive(t, r) {
52
52
  return ("string" === r ? String : Number)(t);
53
53
  }
54
54
  //#endregion
55
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/toPropertyKey.js
55
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/toPropertyKey.js
56
56
  function toPropertyKey(t) {
57
57
  var i = toPrimitive(t, "string");
58
58
  return "symbol" == _typeof(i) ? i : i + "";
59
59
  }
60
60
  //#endregion
61
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/defineProperty.js
61
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/defineProperty.js
62
62
  function _defineProperty(e, r, t) {
63
63
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
64
64
  value: t,
@@ -268,7 +268,7 @@ var IgnoreIfEmptyXmlComponent = class extends XmlComponent {
268
268
  }
269
269
  };
270
270
  //#endregion
271
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/objectSpread2.js
271
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/objectSpread2.js
272
272
  function ownKeys(e, r) {
273
273
  var t = Object.keys(e);
274
274
  if (Object.getOwnPropertySymbols) {
@@ -8223,12 +8223,6 @@ var ImportedRootElementAttributes = class extends XmlComponent {
8223
8223
  }
8224
8224
  };
8225
8225
  //#endregion
8226
- //#region src/file/xml-components/xmlable-object.ts
8227
- /**
8228
- * @ignore
8229
- */
8230
- var WORKAROUND3 = "";
8231
- //#endregion
8232
8226
  //#region src/file/xml-components/initializable-xml-component.ts
8233
8227
  /**
8234
8228
  * Initializable XML Component module.
@@ -8956,11 +8950,11 @@ var BuilderElement = class extends XmlComponent {
8956
8950
  * @publicApi
8957
8951
  */
8958
8952
  var AlignmentType = {
8959
- /** Align Start */
8953
+ /** Align Start: the left in a left-to-right paragraph, and the right in a `bidirectional` (right-to-left) paragraph */
8960
8954
  START: "start",
8961
8955
  /** Align Center */
8962
8956
  CENTER: "center",
8963
- /** End */
8957
+ /** Align End: the right in a left-to-right paragraph, and the left in a `bidirectional` (right-to-left) paragraph */
8964
8958
  END: "end",
8965
8959
  /** Justified */
8966
8960
  BOTH: "both",
@@ -8976,9 +8970,9 @@ var AlignmentType = {
8976
8970
  LOW_KASHIDA: "lowKashida",
8977
8971
  /** Thai Language Justification */
8978
8972
  THAI_DISTRIBUTE: "thaiDistribute",
8979
- /** Align Left */
8973
+ /** Align Left: a paragraph stays on the left of the page even when it is `bidirectional` (right-to-left) */
8980
8974
  LEFT: "left",
8981
- /** Align Right */
8975
+ /** Align Right: a paragraph stays on the right of the page even when it is `bidirectional` (right-to-left) */
8982
8976
  RIGHT: "right",
8983
8977
  /** Justified */
8984
8978
  JUSTIFIED: "both"
@@ -9792,6 +9786,40 @@ var createFieldChar = (type, dirty) => new BuilderElement({
9792
9786
  * field instructions, an optional separate character, field result, and an end character.
9793
9787
  */
9794
9788
  var createBegin = (dirty) => createFieldChar(FieldCharacterType.BEGIN, dirty);
9789
+ /** The formatted begin characters of the fields that are dirty only when the document isn't given page numbers */
9790
+ var dirtyWithoutPageNumbers = /* @__PURE__ */ new WeakSet();
9791
+ /** The beginning of a field that is dirty, so Word updates it, unless the document is given page numbers */
9792
+ var BeginDirtyWithoutPageNumbers = class extends BuilderElement {
9793
+ constructor() {
9794
+ super({
9795
+ name: "w:fldChar",
9796
+ attributes: {
9797
+ type: {
9798
+ key: "w:fldCharType",
9799
+ value: FieldCharacterType.BEGIN
9800
+ },
9801
+ dirty: {
9802
+ key: "w:dirty",
9803
+ value: true
9804
+ }
9805
+ }
9806
+ });
9807
+ }
9808
+ prepForXml(context) {
9809
+ const xml = super.prepForXml(context);
9810
+ dirtyWithoutPageNumbers.add(xml);
9811
+ return xml;
9812
+ }
9813
+ };
9814
+ /**
9815
+ * Creates the beginning of a field whose result is written when the document is given page numbers, such as a page
9816
+ * reference or a SEQ field. It is written dirty, so Word updates the field when it opens the document, and asks to. When
9817
+ * the document is given page numbers, it is written clean (see {@link isDirtyWithoutPageNumbers}), so Word shows the
9818
+ * number written, or nothing when none could be worked out, and doesn't ask.
9819
+ */
9820
+ var createBeginDirtyWithoutPageNumbers = () => new BeginDirtyWithoutPageNumbers();
9821
+ /** Whether a formatted field character is the beginning of a field that is dirty only without page numbers */
9822
+ var isDirtyWithoutPageNumbers = (element) => typeof element === "object" && element !== null && dirtyWithoutPageNumbers.has(element);
9795
9823
  /**
9796
9824
  * Creates the separator between field code and field result in a complex field.
9797
9825
  *
@@ -9962,7 +9990,8 @@ var NumberFormat = {
9962
9990
  THAI_NUMBERS: "thaiNumbers",
9963
9991
  THAI_COUNTING: "thaiCounting",
9964
9992
  BAHT_TEXT: "bahtText",
9965
- DOLLAR_TEXT: "dollarText"
9993
+ DOLLAR_TEXT: "dollarText",
9994
+ CUSTOM: "custom"
9966
9995
  };
9967
9996
  //#endregion
9968
9997
  //#region src/file/shared/space-type.ts
@@ -11304,13 +11333,8 @@ var Symbol$1 = class extends XmlComponent {
11304
11333
  */
11305
11334
  var SymbolRun = class extends Run {
11306
11335
  constructor(options) {
11307
- if (typeof options === "string") {
11308
- super({});
11309
- this.root.push(new Symbol$1(options));
11310
- return this;
11311
- }
11312
- super(options);
11313
- this.root.push(new Symbol$1(options.char, options.symbolfont));
11336
+ super(typeof options === "string" ? {} : options);
11337
+ this.root.push(typeof options === "string" ? new Symbol$1(options) : new Symbol$1(options.char, options.symbolfont));
11314
11338
  }
11315
11339
  };
11316
11340
  //#endregion
@@ -14291,6 +14315,16 @@ var SourceRectangleAttributes = class extends XmlAttributeComponent {
14291
14315
  }
14292
14316
  };
14293
14317
  /**
14318
+ * Converts a crop percentage to thousandths of a percent.
14319
+ *
14320
+ * @throws If the percentage isn't a number from 0 to 100
14321
+ */
14322
+ var cropValue = (value, edge) => {
14323
+ if (value === void 0) return;
14324
+ if (!(value >= 0 && value <= 100)) throw new Error(`Invalid crop ${edge} ${value}. Expected a number from 0 to 100`);
14325
+ return Math.round(value * 1e3);
14326
+ };
14327
+ /**
14294
14328
  * Represents a source rectangle for blip fills.
14295
14329
  *
14296
14330
  * This element specifies a portion of the blip (image) to use as the fill.
@@ -14317,10 +14351,10 @@ var SourceRectangle = class extends XmlComponent {
14317
14351
  constructor(crop) {
14318
14352
  super("a:srcRect");
14319
14353
  if (crop) this.root.push(new SourceRectangleAttributes({
14320
- left: crop.left === void 0 ? void 0 : Math.round(crop.left * 1e3),
14321
- top: crop.top === void 0 ? void 0 : Math.round(crop.top * 1e3),
14322
- right: crop.right === void 0 ? void 0 : Math.round(crop.right * 1e3),
14323
- bottom: crop.bottom === void 0 ? void 0 : Math.round(crop.bottom * 1e3)
14354
+ left: cropValue(crop.left, "left"),
14355
+ top: cropValue(crop.top, "top"),
14356
+ right: cropValue(crop.right, "right"),
14357
+ bottom: cropValue(crop.bottom, "bottom")
14324
14358
  }));
14325
14359
  }
14326
14360
  };
@@ -14674,7 +14708,9 @@ var NonVisualProperties = class extends XmlComponent {
14674
14708
  this.root.push(createHyperlinkClick(element.linkId, false));
14675
14709
  break;
14676
14710
  }
14677
- return super.prepForXml(context);
14711
+ const result = super.prepForXml(context);
14712
+ this.root.splice(1);
14713
+ return result;
14678
14714
  }
14679
14715
  };
14680
14716
  //#endregion
@@ -15621,6 +15657,18 @@ var createEffectExtent = ({ top, right, bottom, left }) => new BuilderElement({
15621
15657
  * @module
15622
15658
  */
15623
15659
  /**
15660
+ * The largest width or height, in EMUs, Word opens a drawing at. The standard allows `ST_PositiveCoordinate` up to
15661
+ * 27273042316900, but Word and PowerPoint restrict it to 2147483647 and won't open a document with a larger drawing.
15662
+ *
15663
+ * Reference: [MS-OI29500] Part 1 Section 20.1.10.42, ST_PositiveCoordinate
15664
+ */
15665
+ var MAX_EXTENT = 2147483647;
15666
+ var EMUS_PER_PIXEL = 9525;
15667
+ var checkExtent = (dimension, value) => {
15668
+ if (value !== void 0 && value > MAX_EXTENT) throw new Error(`Invalid drawing ${dimension} ${value} EMUs (${Math.round(value / EMUS_PER_PIXEL)} pixels). Word won't open a drawing with a ${dimension} over ${MAX_EXTENT} EMUs (${Math.floor(MAX_EXTENT / EMUS_PER_PIXEL)} pixels). Sizes such as an ImageRun's transformation are in pixels, not EMUs`);
15669
+ return value;
15670
+ };
15671
+ /**
15624
15672
  * Creates an extent element for inline drawings.
15625
15673
  *
15626
15674
  * This element specifies the extents of the parent DrawingML object within
@@ -15644,17 +15692,19 @@ var createEffectExtent = ({ top, right, bottom, left }) => new BuilderElement({
15644
15692
  * y: 914400
15645
15693
  * });
15646
15694
  * ```
15695
+ *
15696
+ * @throws Error if the width or height is over 2147483647 EMUs, which Word won't open
15647
15697
  */
15648
15698
  var createExtent = ({ x, y }) => new BuilderElement({
15649
15699
  name: "wp:extent",
15650
15700
  attributes: {
15651
15701
  x: {
15652
15702
  key: "cx",
15653
- value: x
15703
+ value: checkExtent("width", x)
15654
15704
  },
15655
15705
  y: {
15656
15706
  key: "cy",
15657
- value: y
15707
+ value: checkExtent("height", y)
15658
15708
  }
15659
15709
  }
15660
15710
  });
@@ -16046,7 +16096,6 @@ var createDeletion = ({ id, author, date }, run) => new BuilderElement({
16046
16096
  var ImageRun = class extends XmlComponent {
16047
16097
  constructor(options) {
16048
16098
  var _options$insertion;
16049
- var _super = (..._args) => (super(..._args), _defineProperty(this, "imageData", void 0), this);
16050
16099
  const key = `${hashedId(options.data)}.${options.type}`;
16051
16100
  const imageData = options.type === "svg" ? _objectSpread2(_objectSpread2({ type: options.type }, createImageData(options, key)), {}, { fallback: _objectSpread2({ type: options.fallback.type }, createImageData(_objectSpread2(_objectSpread2({}, options.fallback), {}, { transformation: options.transformation }), `${hashedId(options.fallback.data)}.${options.fallback.type}`)) }) : _objectSpread2({ type: options.type }, createImageData(options, key));
16052
16101
  const drawing = new Drawing(imageData, {
@@ -16060,8 +16109,10 @@ var ImageRun = class extends XmlComponent {
16060
16109
  });
16061
16110
  const properties = new RunProperties(options.run);
16062
16111
  const revision = (_options$insertion = options.insertion) !== null && _options$insertion !== void 0 ? _options$insertion : options.deletion;
16112
+ const rootName = options.insertion ? "w:ins" : options.deletion ? "w:del" : "w:r";
16113
+ super(rootName);
16114
+ _defineProperty(this, "imageData", void 0);
16063
16115
  if (revision) {
16064
- _super(options.insertion ? "w:ins" : "w:del");
16065
16116
  this.root.push(new ChangeAttributes({
16066
16117
  id: revision.id,
16067
16118
  author: revision.author,
@@ -16073,7 +16124,6 @@ var ImageRun = class extends XmlComponent {
16073
16124
  });
16074
16125
  this.addChildElement(options.insertion && options.deletion ? createDeletion(options.deletion, run) : run);
16075
16126
  } else {
16076
- _super("w:r");
16077
16127
  this.root.push(properties);
16078
16128
  this.root.push(drawing);
16079
16129
  }
@@ -16226,6 +16276,10 @@ var SequentialIdentifierInstruction = class extends XmlComponent {
16226
16276
  * Each identifier maintains its own sequence, allowing you to have separate numbering
16227
16277
  * for figures, tables, equations, etc.
16228
16278
  *
16279
+ * It is written dirty, so Word numbers it when it opens the document, after asking to update the fields. When the
16280
+ * document is given `pageNumbers`, it is written clean, with its number counted as Word counts it, or blank where
16281
+ * Word's count isn't known, and Word doesn't ask.
16282
+ *
16229
16283
  * Reference: http://officeopenxml.com/WPrun.php
16230
16284
  *
16231
16285
  * @publicApi
@@ -16254,7 +16308,7 @@ var SequentialIdentifierInstruction = class extends XmlComponent {
16254
16308
  var SequentialIdentifier = class extends Run {
16255
16309
  constructor(identifier) {
16256
16310
  super({});
16257
- this.root.push(createBegin(true));
16311
+ this.root.push(createBeginDirtyWithoutPageNumbers());
16258
16312
  this.root.push(new SequentialIdentifierInstruction(identifier));
16259
16313
  this.root.push(createSeparate());
16260
16314
  this.root.push(createEnd());
@@ -16279,7 +16333,10 @@ var SequentialIdentifier = class extends Run {
16279
16333
  var FldSimpleAttrs = class extends XmlAttributeComponent {
16280
16334
  constructor(..._args) {
16281
16335
  super(..._args);
16282
- _defineProperty(this, "xmlKeys", { instr: "w:instr" });
16336
+ _defineProperty(this, "xmlKeys", {
16337
+ instr: "w:instr",
16338
+ fldLock: "w:fldLock"
16339
+ });
16283
16340
  }
16284
16341
  };
16285
16342
  /**
@@ -16312,12 +16369,18 @@ var FldSimpleAttrs = class extends XmlAttributeComponent {
16312
16369
  *
16313
16370
  * // Simple field with cached value
16314
16371
  * new SimpleField("DATE", "2024-01-01");
16372
+ *
16373
+ * // Locked field, Word keeps the cached value when fields are updated
16374
+ * new SimpleField("DATE", "2024-01-01", { locked: true });
16315
16375
  * ```
16316
16376
  */
16317
16377
  var SimpleField = class extends XmlComponent {
16318
- constructor(instruction, cachedValue) {
16378
+ constructor(instruction, cachedValue, options = {}) {
16319
16379
  super("w:fldSimple");
16320
- this.root.push(new FldSimpleAttrs({ instr: instruction }));
16380
+ this.root.push(new FldSimpleAttrs({
16381
+ instr: instruction,
16382
+ fldLock: options.locked ? true : void 0
16383
+ }));
16321
16384
  if (cachedValue !== void 0) this.root.push(new TextRun(cachedValue));
16322
16385
  }
16323
16386
  };
@@ -16342,6 +16405,1035 @@ var SimpleMailMergeField = class extends SimpleField {
16342
16405
  }
16343
16406
  };
16344
16407
  //#endregion
16408
+ //#region src/file/document/body/field-number-formats.ts
16409
+ var LARGEST_ROMAN = 32767;
16410
+ var LARGEST_LETTERS = 780;
16411
+ var ROMAN = [
16412
+ [1e3, "M"],
16413
+ [900, "CM"],
16414
+ [500, "D"],
16415
+ [400, "CD"],
16416
+ [100, "C"],
16417
+ [90, "XC"],
16418
+ [50, "L"],
16419
+ [40, "XL"],
16420
+ [10, "X"],
16421
+ [9, "IX"],
16422
+ [5, "V"],
16423
+ [4, "IV"],
16424
+ [1, "I"]
16425
+ ];
16426
+ var roman = (value) => value <= LARGEST_ROMAN ? ROMAN.reduce(({ rest, text }, [amount, numeral]) => ({
16427
+ rest: rest % amount,
16428
+ text: text + numeral.repeat(Math.floor(rest / amount))
16429
+ }), {
16430
+ rest: value,
16431
+ text: ""
16432
+ }).text : void 0;
16433
+ var letters = (value) => value === 0 ? "" : value <= LARGEST_LETTERS ? String.fromCharCode(65 + (value - 1) % 26).repeat(Math.ceil(value / 26)) : void 0;
16434
+ var ordinal = (value) => {
16435
+ var _ref;
16436
+ return `${value}${value % 100 >= 11 && value % 100 <= 13 ? "th" : (_ref = [
16437
+ "th",
16438
+ "st",
16439
+ "nd",
16440
+ "rd"
16441
+ ][value % 10]) !== null && _ref !== void 0 ? _ref : "th"}`;
16442
+ };
16443
+ /**
16444
+ * The number formats of a field's `\*` switch that are written as Word writes them, by their names in any capitals.
16445
+ * Word writes roman numerals and letters in small letters when the name starts with a small letter, as `roman`, and in
16446
+ * capitals otherwise, as `Roman` and `ROMAN`
16447
+ */
16448
+ var numberWriterOf = (format) => {
16449
+ const small = format.charAt(0) !== format.charAt(0).toUpperCase();
16450
+ const inCase = (write) => (value) => {
16451
+ var _write;
16452
+ return small ? (_write = write(value)) === null || _write === void 0 ? void 0 : _write.toLowerCase() : write(value);
16453
+ };
16454
+ switch (format.toLowerCase()) {
16455
+ case "arabic": return String;
16456
+ case "roman": return inCase(roman);
16457
+ case "alphabetic": return inCase(letters);
16458
+ case "ordinal": return (value) => value > 0 ? ordinal(value) : void 0;
16459
+ case "arabicdash": return (value) => `- ${value} -`;
16460
+ default: return;
16461
+ }
16462
+ };
16463
+ var PLAIN_FORMATS = /* @__PURE__ */ new Set([
16464
+ "mergeformat",
16465
+ "charformat",
16466
+ "mergeformatinet"
16467
+ ]);
16468
+ var CASE_FORMATS = /* @__PURE__ */ new Set([
16469
+ "upper",
16470
+ "lower",
16471
+ "firstcap",
16472
+ "caps"
16473
+ ]);
16474
+ /**
16475
+ * Whether Word's text for a picture of a field's `\#` switch is known: one of digits (`0`), digits only where the number
16476
+ * has them (`#`) and commas between thousands, as Word wrote `00`, `000`, `0`, `#` and `#,##0` for page numbers
16477
+ * (`scripts/layout-probes/word-page-fields.ts` PF5 to PF7)
16478
+ */
16479
+ var isNumberPicture = (picture) => /^[#0,]*[#0][#0,]*$/.test(picture);
16480
+ /**
16481
+ * A number with a picture: with as many digits as it has `0`s at least, which Word fills with 0s (5 is 05 with `00`), and
16482
+ * its thousands between commas when it has one (1234 is 1,234 with `#,##0`). Undefined where a `#` has no digit of the
16483
+ * number, which Word writes as a space, not yet seen
16484
+ */
16485
+ var inNumberPicture = (value, picture) => {
16486
+ const zeros = [...picture].filter((character) => character === "0").length;
16487
+ const places = zeros + [...picture].filter((character) => character === "#").length;
16488
+ const digits = String(value).padStart(zeros, "0");
16489
+ if (digits.length < places || zeros === 0 && value === 0) return;
16490
+ return picture.includes(",") ? digits.replace(/\B(?=(\d{3})+$)/g, ",") : digits;
16491
+ };
16492
+ /**
16493
+ * Text in the capitals of a field's switch, applied after its number's format, as Word wrote `\* roman \* Upper` as V,
16494
+ * `\* Ordinal \* Upper` as 5TH, and "above" with `\* Upper` as ABOVE (`word-page-fields.ts` PF3 and PF5)
16495
+ */
16496
+ var inCapitals = (text, capitals) => {
16497
+ switch (capitals) {
16498
+ case "upper": return text.toUpperCase();
16499
+ case "lower": return text.toLowerCase();
16500
+ case "firstcap": return text.charAt(0).toUpperCase() + text.slice(1);
16501
+ default: return text;
16502
+ }
16503
+ };
16504
+ //#endregion
16505
+ //#region src/file/document/body/page-number-fields.ts
16506
+ /**
16507
+ * Writes estimated page numbers into the fields of a tree of elements that show them: those docx formats to write a
16508
+ * document, and those `patchDocument` parses from a template. Not part of the public API.
16509
+ *
16510
+ * A page reference is a PAGEREF field, and the numbers of pages of the document and of a section are NUMPAGES and
16511
+ * SECTIONPAGES fields. Each field's result is written just after its `separate` field character, and any result it had
16512
+ * is taken out.
16513
+ *
16514
+ * @module
16515
+ */
16516
+ /** Reads a field that shows a page's number or a number of pages, or undefined for another field */
16517
+ var numberFieldOf = (instruction) => {
16518
+ var _match;
16519
+ const field = new RegExp("^\\s*(PAGEREF|NUMPAGES|SECTIONPAGES)\\b(.*)$", "is").exec(instruction);
16520
+ const reference = (field === null || field === void 0 ? void 0 : field[1].toUpperCase()) === "PAGEREF" ? new RegExp("^\\s*(\"?)([^\\s\"\\\\]+)\\1(.*)$", "s").exec(field[2]) : void 0;
16521
+ if (!field || field[1].toUpperCase() === "PAGEREF" && !reference) return;
16522
+ const parts = (_match = (reference ? reference[3] : field[2]).match(/"[^"]*"|\S+/g)) !== null && _match !== void 0 ? _match : [];
16523
+ let numberFormat;
16524
+ let picture;
16525
+ const capitals = [];
16526
+ let relative = false;
16527
+ let written = true;
16528
+ for (let index = 0; index < parts.length; index++) {
16529
+ const part = parts[index];
16530
+ const argument = () => {
16531
+ var _parts$index;
16532
+ return (part.length > 2 ? part.slice(2) : (_parts$index = parts[++index]) !== null && _parts$index !== void 0 ? _parts$index : "").replace(/^"(.*)"$/, "$1");
16533
+ };
16534
+ if (/^\\p$/i.test(part)) relative = true;
16535
+ else if (part.startsWith("\\#")) {
16536
+ var _picture;
16537
+ const value = argument();
16538
+ written && (written = picture === void 0 && isNumberPicture(value));
16539
+ (_picture = picture) !== null && _picture !== void 0 || (picture = value);
16540
+ } else if (part.startsWith("\\*")) {
16541
+ const name = argument();
16542
+ const lower = name.toLowerCase();
16543
+ if (CASE_FORMATS.has(lower)) capitals.push(lower);
16544
+ else if (name !== "" && !PLAIN_FORMATS.has(lower)) {
16545
+ var _numberFormat;
16546
+ written && (written = numberFormat === void 0 && numberWriterOf(name) !== void 0);
16547
+ (_numberFormat = numberFormat) !== null && _numberFormat !== void 0 || (numberFormat = name);
16548
+ }
16549
+ }
16550
+ }
16551
+ const own = _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, numberFormat === void 0 ? {} : { numberFormat }), picture === void 0 ? {} : { picture }), capitals.length === 0 ? {} : { capitals: capitals[0] }), {}, { written: written && capitals.length <= 1 && capitals[0] !== "caps" && (numberFormat === void 0 || picture === void 0) });
16552
+ return reference ? _objectSpread2({
16553
+ type: "pageReference",
16554
+ bookmark: reference[2],
16555
+ relative
16556
+ }, own) : _objectSpread2({
16557
+ type: "pageCount",
16558
+ scope: field[1].toUpperCase() === "NUMPAGES" ? "document" : "section"
16559
+ }, own);
16560
+ };
16561
+ /**
16562
+ * Whether a field is a table of contents that writes the number of a SEQ field before each page number (`\s`), such as
16563
+ * 2-5 for page 5 of chapter 2, which isn't written
16564
+ */
16565
+ var prefixesPageNumbers = (instruction) => new RegExp("^\\s*TOC\\b.*\\\\s\\b", "is").test(instruction);
16566
+ /**
16567
+ * The result of a field that shows a page's number or a number of pages, or undefined to leave it as it is. A field
16568
+ * the estimate has no number for is left as it is, or made blank, and so is a page number in a table of contents that
16569
+ * writes a SEQ field's number before it.
16570
+ */
16571
+ var resultFrom = (instruction, { enclosing, within, inTextBox }, { estimate, sectionPageCount, blank, relativeTo }) => {
16572
+ const field = numberFieldOf(instruction);
16573
+ if (field === void 0) return;
16574
+ const { bookmarks, pageCount, bookmarkPageNumbers } = estimate;
16575
+ const { numberFormat, picture, capitals, written } = field;
16576
+ const writesNumber = numberFormat !== void 0 || picture !== void 0;
16577
+ /** A number in the field's format of its own, or as it is */
16578
+ const inFormat = (value) => value === void 0 ? void 0 : picture === void 0 ? numberWriterOf(numberFormat !== null && numberFormat !== void 0 ? numberFormat : "arabic")(value) : inNumberPicture(value, picture);
16579
+ const position = field.type === "pageReference" && field.relative && within === "counted" && !inTextBox ? relativeTo === null || relativeTo === void 0 ? void 0 : relativeTo(field.bookmark) : void 0;
16580
+ let result;
16581
+ if (!written) result = void 0;
16582
+ else if (field.type === "pageCount") result = inFormat(field.scope === "document" ? pageCount : sectionPageCount);
16583
+ else if (enclosing.some(prefixesPageNumbers)) result = void 0;
16584
+ else if (writesNumber) result = inFormat(bookmarkPageNumbers === null || bookmarkPageNumbers === void 0 ? void 0 : bookmarkPageNumbers.get(field.bookmark));
16585
+ else result = field.relative ? position : bookmarks.get(field.bookmark);
16586
+ return result === void 0 ? blank ? "" : void 0 : inCapitals(result, capitals);
16587
+ };
16588
+ /** Where the content of an element is: in what an application that doesn't read Word's own shows, or in deleted text */
16589
+ var placeIn = (name, within) => name === "mc:Fallback" || within === "fallback" ? "fallback" : name === "w:del" || name === "w:moveFrom" ? "deleted" : within;
16590
+ /**
16591
+ * Writes the results the filling works out into the fields in the elements, in order.
16592
+ */
16593
+ var fillFields = (tree, elements, open, filling, within = "counted", inTextBox = false) => {
16594
+ for (let index = 0; index < elements.length; index++) {
16595
+ const element = elements[index];
16596
+ const name = tree.nameOf(element);
16597
+ if (name === void 0) continue;
16598
+ const current = open[open.length - 1];
16599
+ if (name === "w:fldChar") {
16600
+ const type = tree.attributeOf(element, "w:fldCharType");
16601
+ if (type === "begin") open.push({
16602
+ begin: element,
16603
+ instruction: "",
16604
+ inResult: false
16605
+ });
16606
+ else if (type === "separate" && current) {
16607
+ tree.writeClean(current.begin, current.instruction);
16608
+ current.inResult = true;
16609
+ current.result = filling.resultOf(current.instruction, {
16610
+ within,
16611
+ enclosing: open.slice(0, -1).map((field) => field.instruction),
16612
+ inTextBox
16613
+ });
16614
+ if (current.result !== void 0) {
16615
+ elements.splice(index + 1, 0, tree.textElement(current.result));
16616
+ index++;
16617
+ }
16618
+ } else if (type === "end") open.pop();
16619
+ } else if (name === "w:instrText" && current && !current.inResult) current.instruction += tree.textOf(element);
16620
+ else if ((name === "w:t" || name === "w:tab" || name === "w:br" || name === "w:cr") && (current === null || current === void 0 ? void 0 : current.result) !== void 0) {
16621
+ elements.splice(index, 1);
16622
+ index--;
16623
+ } else if (name === "w:fldSimple") {
16624
+ const result = filling.resultOf(String(tree.attributeOf(element, "w:instr")), {
16625
+ within,
16626
+ enclosing: open.map((field) => field.instruction),
16627
+ inTextBox
16628
+ });
16629
+ if (result === void 0) {
16630
+ var _tree$contentOf;
16631
+ fillFields(tree, (_tree$contentOf = tree.contentOf(element)) !== null && _tree$contentOf !== void 0 ? _tree$contentOf : [], [], filling, within, inTextBox);
16632
+ } else tree.setSimpleFieldResult(element, result);
16633
+ } else {
16634
+ var _tree$contentOf2;
16635
+ if (name === "w:p") {
16636
+ var _filling$beforeParagr;
16637
+ (_filling$beforeParagr = filling.beforeParagraph) === null || _filling$beforeParagr === void 0 || _filling$beforeParagr.call(filling, element);
16638
+ }
16639
+ fillFields(tree, (_tree$contentOf2 = tree.contentOf(element)) !== null && _tree$contentOf2 !== void 0 ? _tree$contentOf2 : [], open, filling, placeIn(name, within), inTextBox || name === "w:txbxContent");
16640
+ if (name === "w:p") filling.afterParagraph(element);
16641
+ }
16642
+ }
16643
+ };
16644
+ /** The section properties (`w:sectPr`) in the elements, in order: those of the paragraphs that end sections, and the last */
16645
+ var sectionPropertiesIn = (tree, elements) => elements.flatMap((element) => {
16646
+ var _tree$contentOf3;
16647
+ const name = tree.nameOf(element);
16648
+ if (name === void 0) return [];
16649
+ return name === "w:sectPr" ? [element] : sectionPropertiesIn(tree, (_tree$contentOf3 = tree.contentOf(element)) !== null && _tree$contentOf3 !== void 0 ? _tree$contentOf3 : []);
16650
+ });
16651
+ /** Whether a paragraph ends a section: whether its properties have the section's */
16652
+ var endsSection = (tree, paragraph) => {
16653
+ var _tree$contentOf4;
16654
+ return ((_tree$contentOf4 = tree.contentOf(paragraph)) !== null && _tree$contentOf4 !== void 0 ? _tree$contentOf4 : []).some((child) => {
16655
+ var _tree$contentOf5;
16656
+ return tree.nameOf(child) === "w:pPr" && ((_tree$contentOf5 = tree.contentOf(child)) !== null && _tree$contentOf5 !== void 0 ? _tree$contentOf5 : []).some((part) => tree.nameOf(part) === "w:sectPr");
16657
+ });
16658
+ };
16659
+ /**
16660
+ * The number of pages each header and footer shows in its SECTIONPAGES fields, by the id of the relationship to it:
16661
+ * that of the sections whose pages it is on, when they all have the same. A section without a header or footer of a kind
16662
+ * has the one of the section before, as Word lays them out.
16663
+ */
16664
+ var partPageCountsOf = (tree, body, sectionPageCounts) => {
16665
+ const countsOfParts = sectionPropertiesIn(tree, [body]).reduce((all, properties) => {
16666
+ var _tree$contentOf6, _all;
16667
+ const references = ((_tree$contentOf6 = tree.contentOf(properties)) !== null && _tree$contentOf6 !== void 0 ? _tree$contentOf6 : []).flatMap((child) => {
16668
+ const name = tree.nameOf(child);
16669
+ return name === "w:headerReference" || name === "w:footerReference" ? [[`${name} ${String(tree.attributeOf(child, "w:type"))}`, String(tree.attributeOf(child, "r:id"))]] : [];
16670
+ });
16671
+ return [...all, new Map([...(_all = all[all.length - 1]) !== null && _all !== void 0 ? _all : [], ...references])];
16672
+ }, []).reduce((counts, parts, section) => {
16673
+ for (const id of parts.values()) {
16674
+ var _counts$get;
16675
+ counts.set(id, [...(_counts$get = counts.get(id)) !== null && _counts$get !== void 0 ? _counts$get : [], sectionPageCounts[section]]);
16676
+ }
16677
+ return counts;
16678
+ }, /* @__PURE__ */ new Map());
16679
+ return new Map([...countsOfParts].flatMap(([id, [first, ...rest]]) => first !== void 0 && rest.every((count) => count === first) ? [[id, first]] : []));
16680
+ };
16681
+ /**
16682
+ * Writes the estimated page numbers into the fields of a document's body that show them: its PAGEREF fields, in its
16683
+ * tables of contents and elsewhere, and its NUMPAGES and SECTIONPAGES fields.
16684
+ *
16685
+ * @returns The number of pages each header and footer shows in its SECTIONPAGES fields, by the id of the relationship to it
16686
+ */
16687
+ var fillBodyFields = (tree, body, estimate, { blank }) => {
16688
+ const { sectionPageCounts = [], relativePositions } = estimate;
16689
+ let section = 0;
16690
+ const relativeCounts = /* @__PURE__ */ new Map();
16691
+ const relativeTo = (bookmark) => {
16692
+ var _relativeCounts$get, _relativePositions$ge;
16693
+ const count = (_relativeCounts$get = relativeCounts.get(bookmark)) !== null && _relativeCounts$get !== void 0 ? _relativeCounts$get : 0;
16694
+ relativeCounts.set(bookmark, count + 1);
16695
+ return relativePositions === null || relativePositions === void 0 || (_relativePositions$ge = relativePositions.get(bookmark)) === null || _relativePositions$ge === void 0 ? void 0 : _relativePositions$ge[count];
16696
+ };
16697
+ fillFields(tree, [body], [], {
16698
+ resultOf: (instruction, place) => resultFrom(instruction, place, {
16699
+ estimate,
16700
+ sectionPageCount: sectionPageCounts[section],
16701
+ blank,
16702
+ relativeTo
16703
+ }),
16704
+ afterParagraph: (paragraph) => {
16705
+ section += endsSection(tree, paragraph) ? 1 : 0;
16706
+ }
16707
+ });
16708
+ return partPageCountsOf(tree, body, sectionPageCounts);
16709
+ };
16710
+ /**
16711
+ * Writes the estimated page numbers into the fields of a header, footer, footnote or endnote that show them, with the
16712
+ * number of pages its SECTIONPAGES fields show, if it is known. A page reference with `\p` in a footnote or endnote
16713
+ * (`notes`) writes "on page" and its bookmark's page, whatever page it is on, as Word writes it
16714
+ * (`word-page-fields.docx` PF8f, PF8g)
16715
+ */
16716
+ var fillPartFields = (tree, part, estimate, { blank, sectionPageCount, notes = false }) => {
16717
+ const onPage = (bookmark) => {
16718
+ const page = estimate.bookmarks.get(bookmark);
16719
+ return page === void 0 ? void 0 : `on page ${page}`;
16720
+ };
16721
+ fillFields(tree, [part], [], {
16722
+ resultOf: (instruction, place) => resultFrom(instruction, place, _objectSpread2({
16723
+ estimate,
16724
+ sectionPageCount,
16725
+ blank
16726
+ }, notes ? { relativeTo: onPage } : {})),
16727
+ afterParagraph: () => void 0
16728
+ });
16729
+ };
16730
+ /** Writes the numbers of the SEQ fields of a document's body into them */
16731
+ var fillSequenceFields = (tree, body, { beforeParagraph, resultOf }) => fillFields(tree, [body], [], {
16732
+ resultOf: (instruction, { within }) => resultOf(instruction, within),
16733
+ beforeParagraph,
16734
+ afterParagraph: () => void 0
16735
+ });
16736
+ //#endregion
16737
+ //#region src/file/table-of-contents/field-instruction.ts
16738
+ /**
16739
+ * Field Instruction module for Table of Contents.
16740
+ *
16741
+ * This module handles the generation of TOC field instruction text
16742
+ * that controls how the table of contents is built.
16743
+ *
16744
+ * Reference: http://officeopenxml.com/WPfieldInstructions.php
16745
+ *
16746
+ * @module
16747
+ */
16748
+ /**
16749
+ * Represents a field instruction for a Table of Contents.
16750
+ *
16751
+ * The FieldInstruction class generates the TOC field code string that Word uses
16752
+ * to determine how to build the table of contents, including which headings to include,
16753
+ * formatting options, and other TOC-specific settings.
16754
+ *
16755
+ * Reference: http://officeopenxml.com/WPfieldInstructions.php
16756
+ *
16757
+ * ## XSD Schema
16758
+ * ```xml
16759
+ * <xsd:element name="instrText" type="CT_Text"/>
16760
+ * ```
16761
+ *
16762
+ * @example
16763
+ * ```typescript
16764
+ * // Basic TOC field instruction
16765
+ * new FieldInstruction({ headingStyleRange: "1-3" });
16766
+ *
16767
+ * // TOC with hyperlinks and custom styles
16768
+ * new FieldInstruction({
16769
+ * hyperlink: true,
16770
+ * headingStyleRange: "1-3",
16771
+ * stylesWithLevels: [new StyleLevel("CustomStyle", 2)],
16772
+ * });
16773
+ * ```
16774
+ */
16775
+ var FieldInstruction = class extends XmlComponent {
16776
+ constructor(properties = {}) {
16777
+ super("w:instrText");
16778
+ _defineProperty(this, "properties", void 0);
16779
+ this.properties = properties;
16780
+ this.root.push(new TextAttributes({ space: SpaceType.PRESERVE }));
16781
+ let instruction = "TOC";
16782
+ if (this.properties.captionLabel) instruction = `${instruction} \\a "${this.properties.captionLabel}"`;
16783
+ if (this.properties.entriesFromBookmark) instruction = `${instruction} \\b "${this.properties.entriesFromBookmark}"`;
16784
+ if (this.properties.captionLabelIncludingNumbers) instruction = `${instruction} \\c "${this.properties.captionLabelIncludingNumbers}"`;
16785
+ if (this.properties.sequenceAndPageNumbersSeparator) instruction = `${instruction} \\d "${this.properties.sequenceAndPageNumbersSeparator}"`;
16786
+ if (this.properties.tcFieldIdentifier) instruction = `${instruction} \\f "${this.properties.tcFieldIdentifier}"`;
16787
+ if (this.properties.hyperlink) instruction = `${instruction} \\h`;
16788
+ if (this.properties.tcFieldLevelRange) instruction = `${instruction} \\l "${this.properties.tcFieldLevelRange}"`;
16789
+ if (this.properties.pageNumbersEntryLevelsRange) instruction = `${instruction} \\n "${this.properties.pageNumbersEntryLevelsRange}"`;
16790
+ if (this.properties.headingStyleRange) instruction = `${instruction} \\o "${this.properties.headingStyleRange}"`;
16791
+ if (this.properties.entryAndPageNumberSeparator) instruction = `${instruction} \\p "${this.properties.entryAndPageNumberSeparator}"`;
16792
+ if (this.properties.seqFieldIdentifierForPrefix) instruction = `${instruction} \\s "${this.properties.seqFieldIdentifierForPrefix}"`;
16793
+ if (this.properties.stylesWithLevels && this.properties.stylesWithLevels.length) {
16794
+ const styles = this.properties.stylesWithLevels.map((sl) => `${sl.styleName},${sl.level}`).join(",");
16795
+ instruction = `${instruction} \\t "${styles}"`;
16796
+ }
16797
+ if (this.properties.useAppliedParagraphOutlineLevel) instruction = `${instruction} \\u`;
16798
+ if (this.properties.preserveTabInEntries) instruction = `${instruction} \\w`;
16799
+ if (this.properties.preserveNewLineInEntries) instruction = `${instruction} \\x`;
16800
+ if (this.properties.hideTabAndPageNumbersInWebView) instruction = `${instruction} \\z`;
16801
+ this.root.push(instruction);
16802
+ }
16803
+ };
16804
+ //#endregion
16805
+ //#region src/file/table-of-contents/sdt-content.ts
16806
+ /**
16807
+ * Structured Document Tag Content module.
16808
+ *
16809
+ * This module represents the content container for structured document tags,
16810
+ * including table of contents elements.
16811
+ *
16812
+ * Reference: http://officeopenxml.com/WPtableOfContents.php
16813
+ *
16814
+ * @module
16815
+ */
16816
+ /**
16817
+ * Represents the content portion of a Structured Document Tag.
16818
+ *
16819
+ * The StructuredDocumentTagContent contains the actual content elements
16820
+ * (paragraphs, tables, etc.) within a structured document tag, such as
16821
+ * the paragraphs that make up a table of contents.
16822
+ *
16823
+ * Reference: http://officeopenxml.com/WPtableOfContents.php
16824
+ *
16825
+ * ## XSD Schema
16826
+ * ```xml
16827
+ * <xsd:complexType name="CT_SdtContentBlock">
16828
+ * <xsd:group ref="EG_ContentBlockContent" minOccurs="0" maxOccurs="unbounded"/>
16829
+ * </xsd:complexType>
16830
+ * ```
16831
+ *
16832
+ * @example
16833
+ * ```typescript
16834
+ * const content = new StructuredDocumentTagContent();
16835
+ * content.addChildElement(new Paragraph("Content"));
16836
+ * ```
16837
+ */
16838
+ var StructuredDocumentTagContent = class extends XmlComponent {
16839
+ constructor() {
16840
+ super("w:sdtContent");
16841
+ }
16842
+ };
16843
+ //#endregion
16844
+ //#region src/file/table-of-contents/heading-entries.ts
16845
+ /**
16846
+ * Entries written into a table of contents from the headings of the document.
16847
+ *
16848
+ * A table of contents is a TOC field. Word fills in its entries when it updates the field. Until then, and in
16849
+ * applications that don't update it, such as LibreOffice, it shows the entries it was last filled in with, and without
16850
+ * any it is empty. So once the body is written, each table of contents that wasn't given `cachedEntries` or
16851
+ * `contentChildren` is filled in from the headings its switches include, the way Word fills it in: each heading is
16852
+ * bookmarked, and its entry links to the bookmark and gives its page with a PAGEREF field. The page numbers are left
16853
+ * empty, because they depend on how the document is laid out. Word fills them in when it updates the field, unless the
16854
+ * document's `pageNumbers` writes them.
16855
+ *
16856
+ * @module
16857
+ */
16858
+ /**
16859
+ * The beginning of a table of contents' field: dirty or clean, as the caller set it, or else dirty unless the document
16860
+ * is given page numbers
16861
+ */
16862
+ var beginOf = (beginDirty) => beginDirty === void 0 ? createBeginDirtyWithoutPageNumbers() : createBegin(beginDirty);
16863
+ /** The formatted tables of contents, with what each is filled in with, or undefined when it was given its content */
16864
+ var writtenTables = /* @__PURE__ */ new WeakMap();
16865
+ /**
16866
+ * Records a formatted table of contents, so the paragraphs in it aren't taken for headings, with what to fill it in
16867
+ * with from the headings once the body it is in is written. That is undefined when it was given its content.
16868
+ */
16869
+ var recordTableOfContents = (table, fillWith) => {
16870
+ writtenTables.set(table, fillWith);
16871
+ };
16872
+ /**
16873
+ * The ids of the bookmarks on a body's headings: the first for its first bookmarked heading, and so on. Each is taken
16874
+ * from the counter every bookmark shares, the first time it is needed, so a document packed again is written the same.
16875
+ */
16876
+ var HeadingBookmarkIds = class {
16877
+ constructor() {
16878
+ _defineProperty(this, "ids", []);
16879
+ }
16880
+ get(index) {
16881
+ var _this$ids, _this$ids$index;
16882
+ (_this$ids$index = (_this$ids = this.ids)[index]) !== null && _this$ids$index !== void 0 || (_this$ids[index] = bookmarkUniqueNumericId());
16883
+ return this.ids[index];
16884
+ }
16885
+ };
16886
+ /** The name of a formatted element, or `_attr` for its parent's attributes */
16887
+ var nameOf$2 = (element) => typeof element === "object" && element !== null ? Object.keys(element)[0] : void 0;
16888
+ /** The children of a formatted element. An element with only attributes has them as its one child */
16889
+ var childrenOf = (element) => {
16890
+ const name = nameOf$2(element);
16891
+ const content = name === void 0 ? void 0 : element[name];
16892
+ return Array.isArray(content) ? content : content === void 0 ? [] : [content];
16893
+ };
16894
+ var childOf = (element, name) => childrenOf(element).find((child) => nameOf$2(child) === name);
16895
+ var attributeOf = (element, attribute) => {
16896
+ var _childOf;
16897
+ return (_childOf = childOf(element, "_attr")) === null || _childOf === void 0 || (_childOf = _childOf._attr) === null || _childOf === void 0 ? void 0 : _childOf[attribute];
16898
+ };
16899
+ /** An attribute such as `w:val="2"` as a number. Imported XML gives it as a string */
16900
+ var numberAttributeOf = (element, attribute) => {
16901
+ const value = attributeOf(element, attribute);
16902
+ return value === void 0 ? void 0 : Number(value);
16903
+ };
16904
+ /** The block-level containers of paragraphs: tables, their rows and cells, and content controls */
16905
+ var BLOCK_CONTAINERS = /* @__PURE__ */ new Set([
16906
+ "w:tbl",
16907
+ "w:tr",
16908
+ "w:tc",
16909
+ "w:sdt",
16910
+ "w:sdtContent",
16911
+ "w:customXml"
16912
+ ]);
16913
+ /**
16914
+ * The paragraphs and the tables of contents, in the order they are in the body. A table of contents isn't looked into,
16915
+ * so the paragraphs in it aren't taken for headings. Nor are paragraphs in text boxes, as in Word.
16916
+ */
16917
+ var blocksOf = (elements) => elements.flatMap((element) => {
16918
+ const name = nameOf$2(element);
16919
+ if (name === "w:p" || writtenTables.has(element)) return [element];
16920
+ return name !== void 0 && BLOCK_CONTAINERS.has(name) ? blocksOf(childrenOf(element)) : [];
16921
+ });
16922
+ /** The elements in a paragraph that its text is in. Deleted text, field instructions and drawings aren't */
16923
+ var TEXT_CONTAINERS = /* @__PURE__ */ new Set([
16924
+ "w:r",
16925
+ "w:hyperlink",
16926
+ "w:ins",
16927
+ "w:moveTo",
16928
+ "w:smartTag",
16929
+ "w:customXml",
16930
+ "w:sdt",
16931
+ "w:sdtContent",
16932
+ "w:fldSimple",
16933
+ "w:dir",
16934
+ "w:bdo"
16935
+ ]);
16936
+ /** The text an element in a run stands for, such as `\t` for a tab. A page or column break isn't text */
16937
+ var textOfRunContent = (element) => {
16938
+ switch (nameOf$2(element)) {
16939
+ case "w:t": return childrenOf(element).filter((child) => typeof child === "string").join("");
16940
+ case "w:tab": return " ";
16941
+ case "w:br": return [void 0, "textWrapping"].includes(attributeOf(element, "w:type")) ? "\n" : "";
16942
+ case "w:cr": return "\n";
16943
+ case "w:noBreakHyphen": return "-";
16944
+ default: return "";
16945
+ }
16946
+ };
16947
+ /** The text of a paragraph. Of a field, only its result is text, not its instruction */
16948
+ var textOf = (paragraph) => {
16949
+ const fields = [];
16950
+ const read = (element) => {
16951
+ const name = nameOf$2(element);
16952
+ if (name !== void 0 && TEXT_CONTAINERS.has(name)) return childrenOf(element).map(read).join("");
16953
+ if (name === "w:fldChar") {
16954
+ const type = attributeOf(element, "w:fldCharType");
16955
+ if (type === "begin") fields.push(false);
16956
+ else if (type === "separate") fields[fields.length - 1] = true;
16957
+ else fields.pop();
16958
+ return "";
16959
+ }
16960
+ return fields.every(Boolean) ? textOfRunContent(element) : "";
16961
+ };
16962
+ return childrenOf(paragraph).map(read).join("");
16963
+ };
16964
+ /** The bookmarks started and ended in an element, in order */
16965
+ var bookmarkMarksOf = (element) => {
16966
+ const name = nameOf$2(element);
16967
+ if (name === "w:bookmarkStart") return [{
16968
+ start: true,
16969
+ id: attributeOf(element, "w:id"),
16970
+ name: attributeOf(element, "w:name")
16971
+ }];
16972
+ if (name === "w:bookmarkEnd") return [{
16973
+ start: false,
16974
+ id: attributeOf(element, "w:id")
16975
+ }];
16976
+ return name === void 0 || name === "_attr" ? [] : childrenOf(element).flatMap(bookmarkMarksOf);
16977
+ };
16978
+ /**
16979
+ * The names of the bookmarks each paragraph is in, for the `\b` switch: those open where it starts, followed through the
16980
+ * body, and those that start in it.
16981
+ */
16982
+ var bookmarksOf = (paragraphs) => {
16983
+ const open = /* @__PURE__ */ new Map();
16984
+ return paragraphs.map((paragraph) => {
16985
+ const marks = bookmarkMarksOf(paragraph);
16986
+ const names = /* @__PURE__ */ new Set([...open.values(), ...marks.flatMap((mark) => mark.start ? [mark.name] : [])]);
16987
+ for (const mark of marks) if (mark.start) open.set(mark.id, mark.name);
16988
+ else open.delete(mark.id);
16989
+ return names;
16990
+ });
16991
+ };
16992
+ /** The details of each paragraph that could be a heading. The bookmarks it is in are only followed when needed */
16993
+ var paragraphDetailsOf = (paragraphs, followBookmarks) => {
16994
+ const bookmarks = followBookmarks ? bookmarksOf(paragraphs) : [];
16995
+ return paragraphs.map((element, index) => {
16996
+ var _bookmarks$index;
16997
+ const properties = childOf(element, "w:pPr");
16998
+ return {
16999
+ element,
17000
+ styleId: attributeOf(childOf(properties, "w:pStyle"), "w:val"),
17001
+ outlineLevel: numberAttributeOf(childOf(properties, "w:outlineLvl"), "w:val"),
17002
+ text: textOf(element),
17003
+ bookmarks: (_bookmarks$index = bookmarks[index]) !== null && _bookmarks$index !== void 0 ? _bookmarks$index : /* @__PURE__ */ new Set()
17004
+ };
17005
+ });
17006
+ };
17007
+ /** The document's paragraph styles, by id, read from the styles as they are written */
17008
+ var stylesOf = (context) => {
17009
+ var _context$file;
17010
+ const styles = (_context$file = context.file) === null || _context$file === void 0 || (_context$file = _context$file.Styles) === null || _context$file === void 0 ? void 0 : _context$file.prepForXml(context);
17011
+ return new Map(childrenOf(styles).filter((style) => nameOf$2(style) === "w:style" && ["paragraph", void 0].includes(attributeOf(style, "w:type"))).map((style) => [attributeOf(style, "w:styleId"), {
17012
+ name: attributeOf(childOf(style, "w:name"), "w:val"),
17013
+ basedOn: attributeOf(childOf(style, "w:basedOn"), "w:val"),
17014
+ outlineLevel: numberAttributeOf(childOf(childOf(style, "w:pPr"), "w:outlineLvl"), "w:val")
17015
+ }]));
17016
+ };
17017
+ /** A range such as `1-3` */
17018
+ var parseRange = (range) => {
17019
+ const match = /^\s*(\d+)\s*-\s*(\d+)\s*$/.exec(range);
17020
+ return match ? [Number(match[1]), Number(match[2])] : void 0;
17021
+ };
17022
+ var isWithin = (level, [from, to]) => level >= from && level <= to;
17023
+ /** The level of a built-in heading style, Heading 1 to Heading 9, by its name, or by its id when it has no name */
17024
+ var headingLevelOf = (styleId, styles) => {
17025
+ var _styles$get$name, _styles$get;
17026
+ if (styleId === void 0) return;
17027
+ const match = /^heading ?([1-9])$/i.exec((_styles$get$name = (_styles$get = styles.get(styleId)) === null || _styles$get === void 0 ? void 0 : _styles$get.name) !== null && _styles$get$name !== void 0 ? _styles$get$name : styleId);
17028
+ return match ? Number(match[1]) : void 0;
17029
+ };
17030
+ /**
17031
+ * A style's outline level, from 0: its own, or else the one of the style it is based on. A built-in heading style has
17032
+ * its heading's. Following the styles it is based on stops after as many as there are, in case they loop.
17033
+ */
17034
+ var styleOutlineLevelOf = (styleId, styles, depth = 0) => {
17035
+ var _style$outlineLevel;
17036
+ if (styleId === void 0 || depth > styles.size) return;
17037
+ const style = styles.get(styleId);
17038
+ const heading = headingLevelOf(styleId, styles);
17039
+ return (_style$outlineLevel = style === null || style === void 0 ? void 0 : style.outlineLevel) !== null && _style$outlineLevel !== void 0 ? _style$outlineLevel : heading === void 0 ? styleOutlineLevelOf(style === null || style === void 0 ? void 0 : style.basedOn, styles, depth + 1) : heading - 1;
17040
+ };
17041
+ /**
17042
+ * Reads the heading level of the document's paragraphs, as the `\s` switch of a SEQ field follows it: the level of a
17043
+ * paragraph in a built-in heading style, Heading 1 to Heading 9. A paragraph whose outline level is another, or that has
17044
+ * one without a heading style, is `"unclear"`, as which of the two Word follows hasn't been checked. Other paragraphs
17045
+ * are undefined.
17046
+ */
17047
+ var headingLevels = (context) => {
17048
+ const styles = stylesOf(context);
17049
+ return (paragraph) => {
17050
+ const properties = childOf(paragraph, "w:pPr");
17051
+ const styleId = attributeOf(childOf(properties, "w:pStyle"), "w:val");
17052
+ const heading = headingLevelOf(styleId, styles);
17053
+ const outlineLevel = outlineLevelOf({
17054
+ styleId,
17055
+ outlineLevel: numberAttributeOf(childOf(properties, "w:outlineLvl"), "w:val")
17056
+ }, styles);
17057
+ const outline = outlineLevel === void 0 || outlineLevel >= 9 ? void 0 : outlineLevel + 1;
17058
+ if (heading !== void 0 && (outline === void 0 || outline === heading)) return heading;
17059
+ return outline === void 0 ? void 0 : "unclear";
17060
+ };
17061
+ };
17062
+ /** A paragraph's outline level, from 0: its own, or else its style's */
17063
+ var outlineLevelOf = (paragraph, styles) => {
17064
+ var _paragraph$outlineLev;
17065
+ return (_paragraph$outlineLev = paragraph.outlineLevel) !== null && _paragraph$outlineLev !== void 0 ? _paragraph$outlineLev : styleOutlineLevelOf(paragraph.styleId, styles);
17066
+ };
17067
+ /** The level a table of contents gives a paragraph, or undefined when it doesn't include it */
17068
+ var levelIn = (properties, paragraph, styles) => {
17069
+ var _styles$get2;
17070
+ const { entriesFromBookmark, headingStyleRange, stylesWithLevels = [], useAppliedParagraphOutlineLevel } = properties;
17071
+ if (paragraph.text.trim() === "" || entriesFromBookmark && !paragraph.bookmarks.has(entriesFromBookmark)) return;
17072
+ const names = [paragraph.styleId, paragraph.styleId === void 0 ? void 0 : (_styles$get2 = styles.get(paragraph.styleId)) === null || _styles$get2 === void 0 ? void 0 : _styles$get2.name].filter((name) => name !== void 0).map((name) => name.toLowerCase());
17073
+ const listed = stylesWithLevels.find((style) => names.includes(style.styleName.toLowerCase()));
17074
+ if (listed) return listed.level;
17075
+ const namesItsEntries = Boolean(headingStyleRange) || stylesWithLevels.length > 0 || Boolean(useAppliedParagraphOutlineLevel) || Boolean(properties.tcFieldIdentifier) || Boolean(properties.tcFieldLevelRange) || Boolean(properties.captionLabel) || Boolean(properties.captionLabelIncludingNumbers);
17076
+ const headingRange = headingStyleRange ? parseRange(headingStyleRange) : namesItsEntries ? void 0 : [1, 9];
17077
+ const heading = headingLevelOf(paragraph.styleId, styles);
17078
+ if (headingRange && heading !== void 0 && isWithin(heading, headingRange)) return heading;
17079
+ const outlineLevel = useAppliedParagraphOutlineLevel ? outlineLevelOf(paragraph, styles) : void 0;
17080
+ return outlineLevel !== void 0 && isWithin(outlineLevel + 1, headingRange !== null && headingRange !== void 0 ? headingRange : [1, 9]) ? outlineLevel + 1 : void 0;
17081
+ };
17082
+ /** The runs of an entry's title. Tabs and line breaks are kept only when the table of contents keeps them (\w and \x) */
17083
+ var titleRunsOf = (title, properties) => {
17084
+ const text = properties.preserveTabInEntries ? title : title.replace(/\t/g, " ");
17085
+ return (properties.preserveNewLineInEntries ? text.split("\n") : [text.replace(/\n/g, " ")]).map((line, index) => new TextRun({
17086
+ break: index > 0 ? 1 : void 0,
17087
+ children: line.split(" ").flatMap((part, partIndex) => [...partIndex > 0 ? [new Tab()] : [], ...part === "" ? [] : [part]])
17088
+ }));
17089
+ };
17090
+ /**
17091
+ * The paragraph style of the entries at a level: the built-in TOC style, found by its name, "toc 1" to "toc 9". When
17092
+ * the document doesn't have it, the entries are indented as Word's are, 220 twips a level.
17093
+ */
17094
+ var entryStyleOf = (level, styles) => {
17095
+ var _find;
17096
+ const named = (_find = [...styles].find(([, style]) => {
17097
+ var _style$name;
17098
+ return ((_style$name = style.name) === null || _style$name === void 0 ? void 0 : _style$name.toLowerCase()) === `toc ${level}`;
17099
+ })) === null || _find === void 0 ? void 0 : _find[0];
17100
+ const id = named !== null && named !== void 0 ? named : `TOC${level}`;
17101
+ return named !== void 0 || styles.has(id) || level === 1 ? { id } : {
17102
+ id,
17103
+ indent: (level - 1) * 220
17104
+ };
17105
+ };
17106
+ /** The formatted content of a table of contents with its entries */
17107
+ var contentOf = ({ properties, beginDirty, textWidth }, entries, styles, context) => {
17108
+ var _parseRange;
17109
+ const withoutPageNumbers = properties.pageNumbersEntryLevelsRange ? (_parseRange = parseRange(properties.pageNumbersEntryLevelsRange)) !== null && _parseRange !== void 0 ? _parseRange : [1, 9] : void 0;
17110
+ const content = new StructuredDocumentTagContent();
17111
+ entries.forEach((entry, index) => {
17112
+ const hasPageNumber = withoutPageNumbers === void 0 || !isWithin(entry.level, withoutPageNumbers);
17113
+ const children = [...titleRunsOf(entry.title, properties), ...hasPageNumber ? [new TextRun({ children: [properties.entryAndPageNumberSeparator || new Tab()] }), new PageReference(entry.bookmark, { hyperlink: properties.hyperlink })] : []];
17114
+ const style = entryStyleOf(entry.level, styles);
17115
+ content.addChildElement(new Paragraph({
17116
+ style: style.id,
17117
+ indent: style.indent === void 0 ? void 0 : { left: style.indent },
17118
+ tabStops: [{
17119
+ type: "right",
17120
+ position: textWidth,
17121
+ leader: "dot"
17122
+ }],
17123
+ children: [...index === 0 ? [new Run({ children: [
17124
+ beginOf(beginDirty),
17125
+ new FieldInstruction(properties),
17126
+ createSeparate()
17127
+ ] })] : [], ...properties.hyperlink ? [new InternalHyperlink({
17128
+ anchor: entry.bookmark,
17129
+ children
17130
+ })] : children]
17131
+ }));
17132
+ });
17133
+ content.addChildElement(new Paragraph({ children: [new Run({ children: [createEnd()] })] }));
17134
+ return content.prepForXml(context);
17135
+ };
17136
+ /** Puts a bookmark around the content of a formatted paragraph */
17137
+ var bookmark = (paragraph, name, id, context) => {
17138
+ const children = childrenOf(paragraph);
17139
+ const start = children.findIndex((child) => nameOf$2(child) === "w:pPr") + 1;
17140
+ paragraph["w:p"] = [
17141
+ ...children.slice(0, start),
17142
+ new BookmarkStart(name, id).prepForXml(context),
17143
+ ...children.slice(start),
17144
+ new BookmarkEnd(id).prepForXml(context)
17145
+ ];
17146
+ };
17147
+ /**
17148
+ * Fills in the tables of contents in a formatted body from its headings, and bookmarks the headings they list. A
17149
+ * table of contents that doesn't list any heading is left empty, for Word to fill in.
17150
+ */
17151
+ var fillTablesOfContents = (body, context, bookmarkIds) => {
17152
+ const blocks = blocksOf(childrenOf(body));
17153
+ const tables = blocks.flatMap((block) => {
17154
+ const options = writtenTables.get(block);
17155
+ return options ? [[block, options]] : [];
17156
+ });
17157
+ if (tables.length === 0) return;
17158
+ const styles = stylesOf(context);
17159
+ const followBookmarks = tables.some(([, { properties }]) => Boolean(properties.entriesFromBookmark));
17160
+ const headings = paragraphDetailsOf(blocks.filter((block) => nameOf$2(block) === "w:p"), followBookmarks).map((paragraph) => ({
17161
+ paragraph,
17162
+ levels: tables.map(([, { properties }]) => levelIn(properties, paragraph, styles))
17163
+ })).filter(({ levels }) => levels.some((level) => level !== void 0)).map((heading, index) => _objectSpread2(_objectSpread2({}, heading), {}, { id: bookmarkIds.get(index) }));
17164
+ for (const { paragraph, id } of headings) bookmark(paragraph.element, `_Toc${id}`, id, context);
17165
+ tables.forEach(([table, options], index) => {
17166
+ const entries = headings.flatMap(({ paragraph, levels, id }) => {
17167
+ const level = levels[index];
17168
+ return level === void 0 ? [] : [{
17169
+ title: paragraph.text,
17170
+ level,
17171
+ bookmark: `_Toc${id}`
17172
+ }];
17173
+ });
17174
+ if (entries.length === 0) return;
17175
+ table["w:sdt"] = childrenOf(table).map((child) => nameOf$2(child) === "w:sdtContent" ? contentOf(options, entries, styles, context) : child);
17176
+ });
17177
+ };
17178
+ //#endregion
17179
+ //#region src/file/document/body/sequence-numbers.ts
17180
+ /**
17181
+ * Caption numbers written into the SEQ fields of a document, such as the 2 of "Figure 2", when the document is given page
17182
+ * numbers.
17183
+ *
17184
+ * A SEQ field (`SequentialIdentifier`) shows how many SEQ fields of its identifier, such as "Figure", there are up to and
17185
+ * including it, so the number doesn't depend on how the pages are laid out. Its switches change the count: `\r 5` starts
17186
+ * it again from 5, `\c` repeats the number of the one before, `\s 1` starts it again after each Heading 1, `\h` hides the
17187
+ * number, and `\* ROMAN` writes it in roman numerals. `docx` writes SEQ fields dirty, for Word to number when it opens the
17188
+ * document, which makes Word ask to update the fields. When the document is given page numbers, each is written clean
17189
+ * with its number, counted as Word counts it. What Word does was read from its PDF of `scripts/layout-probes/word-seq.ts`.
17190
+ *
17191
+ * Word counts the SEQ fields of the body, those in text boxes and hidden text too, in order, and counts an identifier in
17192
+ * any capitals, or in quotes, as the same one. It writes the SEQ fields of headers, footers, footnotes and endnotes as an
17193
+ * error, "Error! Main Document Only.", and doesn't count them with the body's.
17194
+ *
17195
+ * Where Word's count isn't known, the field is left blank rather than given a number that could be wrong: a switch it
17196
+ * doesn't follow, a SEQ field in deleted text, and every SEQ field of an identifier that also has SEQ fields in a comment.
17197
+ * The fields of its identifier after one whose number isn't known are left blank too, until one starts the count again
17198
+ * with `\r`. A number in a format not followed is left blank, but the count goes on.
17199
+ *
17200
+ * @module
17201
+ */
17202
+ var IDENTIFIER = new RegExp("^\\p{L}[\\p{L}\\p{N}_]*$", "u");
17203
+ /** Reads the switches of a SEQ field, and a bookmark before them, or undefined when one of them isn't followed */
17204
+ var sequenceOf = (switches) => {
17205
+ var _step, _format;
17206
+ let step;
17207
+ let hidden = false;
17208
+ let format;
17209
+ let caseFormat = false;
17210
+ let picture = false;
17211
+ for (let index = 0; index < switches.length; index++) {
17212
+ var _switches, _next;
17213
+ const name = switches[index];
17214
+ const argument = (_switches = switches[index + 1]) !== null && _switches !== void 0 ? _switches : "";
17215
+ let next;
17216
+ if (index === 0 && !name.startsWith("\\")) next = { type: "bookmark" };
17217
+ else if (name === "\\c" || name === "\\n") next = { type: name === "\\c" ? "repeat" : "next" };
17218
+ else if ((name === "\\r" || name === "\\s") && /^\d+$/.test(argument)) {
17219
+ index++;
17220
+ next = name === "\\r" ? {
17221
+ type: "reset",
17222
+ to: Number(argument)
17223
+ } : {
17224
+ type: "heading",
17225
+ level: Number(argument)
17226
+ };
17227
+ } else if (name === "\\h") hidden = true;
17228
+ else if (name === "\\#" && index + 1 < switches.length) {
17229
+ index++;
17230
+ picture = true;
17231
+ } else if (name === "\\*" && index + 1 < switches.length) {
17232
+ const value = switches[++index];
17233
+ if (CASE_FORMATS.has(value.toLowerCase())) caseFormat = true;
17234
+ else if (!PLAIN_FORMATS.has(value.toLowerCase())) {
17235
+ if (format !== void 0) return;
17236
+ format = value;
17237
+ }
17238
+ } else return;
17239
+ if (next && step) return;
17240
+ step = (_next = next) !== null && _next !== void 0 ? _next : step;
17241
+ }
17242
+ if ((step === null || step === void 0 ? void 0 : step.type) === "bookmark" && switches.length > 1) return;
17243
+ const written = !picture && !(caseFormat && format !== void 0 && format.toLowerCase() !== "arabic");
17244
+ return {
17245
+ step: (_step = step) !== null && _step !== void 0 ? _step : { type: "next" },
17246
+ hidden: hidden && format === void 0,
17247
+ format: written ? (_format = format) !== null && _format !== void 0 ? _format : "ARABIC" : ""
17248
+ };
17249
+ };
17250
+ /** Reads a SEQ field's instruction, or undefined when the field isn't a SEQ field */
17251
+ var sequenceFieldOf = (instruction) => {
17252
+ var _match$1$match;
17253
+ const match = new RegExp("^\\s*SEQ\\b(.*)$", "is").exec(instruction);
17254
+ if (!match) return;
17255
+ const [written, ...switches] = (_match$1$match = match[1].match(/"[^"]*"|\S+/g)) !== null && _match$1$match !== void 0 ? _match$1$match : [];
17256
+ if (written === void 0) return {};
17257
+ const identifier = written.replace(/^"(.*)"$/, "$1");
17258
+ return IDENTIFIER.test(identifier) ? {
17259
+ identifier,
17260
+ sequence: sequenceOf(switches)
17261
+ } : { identifier };
17262
+ };
17263
+ /** Whether a field's instruction is that of a SEQ field */
17264
+ var isSequenceField = (instruction) => sequenceFieldOf(instruction) !== void 0;
17265
+ /** The identifier, in small letters, of each SEQ field in the formatted elements */
17266
+ var identifiersIn = (element) => {
17267
+ if (typeof element !== "object" || element === null) return [];
17268
+ if (Array.isArray(element)) return element.flatMap(identifiersIn);
17269
+ return Object.entries(element).flatMap(([name, content]) => {
17270
+ return [...(name === "w:instrText" && Array.isArray(content) ? content : name === "_attr" ? [content["w:instr"]] : []).flatMap((instruction) => {
17271
+ const field = typeof instruction === "string" ? sequenceFieldOf(instruction) : void 0;
17272
+ return (field === null || field === void 0 ? void 0 : field.identifier) === void 0 ? [] : [field.identifier.toLowerCase()];
17273
+ }), ...identifiersIn(content)];
17274
+ });
17275
+ };
17276
+ /** The identifiers, in small letters, of the SEQ fields in the document's comments, whose count in Word isn't known */
17277
+ var identifiersInCommentsOf = (context) => {
17278
+ var _context$file;
17279
+ const comments = (_context$file = context.file) === null || _context$file === void 0 ? void 0 : _context$file.Comments;
17280
+ if (!comments) return /* @__PURE__ */ new Set();
17281
+ const wrapper = {
17282
+ View: comments,
17283
+ Relationships: comments.Relationships
17284
+ };
17285
+ return new Set(identifiersIn(comments.prepForXml(_objectSpread2(_objectSpread2({}, context), {}, {
17286
+ viewWrapper: wrapper,
17287
+ stack: []
17288
+ }))));
17289
+ };
17290
+ /** Counts the SEQ fields of a document's body, in order, as Word counts them */
17291
+ var sequenceNumbering = (context) => {
17292
+ const levelOf = headingLevels(context);
17293
+ const numbers = /* @__PURE__ */ new Map();
17294
+ const counted = /* @__PURE__ */ new Map();
17295
+ const headingsAt = [];
17296
+ let unclearAt = -1;
17297
+ let paragraph = -1;
17298
+ let unknown;
17299
+ /**
17300
+ * The number of a field that starts the count again after headings of a level or a higher one (`\s`): the number of
17301
+ * fields of its identifier since the last of them, with it, as Word counts them. It isn't known when a paragraph
17302
+ * whose level isn't clear came after that heading, or a field since it whose number didn't follow as the next one's
17303
+ */
17304
+ const afterHeading = (key, level) => {
17305
+ var _counted$get;
17306
+ const headingAt = Math.max(-1, ...headingsAt.slice(1, level + 1).filter((at) => at !== void 0));
17307
+ const since = ((_counted$get = counted.get(key)) !== null && _counted$get !== void 0 ? _counted$get : []).filter((field) => field.paragraph >= headingAt);
17308
+ const followed = since.every(({ step }) => (step === null || step === void 0 ? void 0 : step.type) === "next" || (step === null || step === void 0 ? void 0 : step.type) === "heading" && step.level === level);
17309
+ if (unclearAt > headingAt || !followed) return;
17310
+ return since.length + 1;
17311
+ };
17312
+ return {
17313
+ startParagraph: (element) => {
17314
+ paragraph++;
17315
+ const level = levelOf(element);
17316
+ if (level === "unclear") unclearAt = paragraph;
17317
+ else if (level !== void 0) headingsAt[level] = paragraph;
17318
+ },
17319
+ numberOf: (instruction, place) => {
17320
+ var _unknown, _counted$get2, _numberWriterOf;
17321
+ const { identifier, sequence } = sequenceFieldOf(instruction);
17322
+ if (identifier === void 0 || place === "fallback") return;
17323
+ (_unknown = unknown) !== null && _unknown !== void 0 || (unknown = identifiersInCommentsOf(context));
17324
+ const key = identifier.toLowerCase();
17325
+ if ((sequence === null || sequence === void 0 ? void 0 : sequence.step.type) === "bookmark" && place === "counted" && !unknown.has(key)) return;
17326
+ const before = numbers.has(key) ? numbers.get(key) : 0;
17327
+ const step = unknown.has(key) || place === "deleted" ? void 0 : sequence === null || sequence === void 0 ? void 0 : sequence.step;
17328
+ const value = (step === null || step === void 0 ? void 0 : step.type) === "reset" ? step.to : (step === null || step === void 0 ? void 0 : step.type) === "repeat" ? before : (step === null || step === void 0 ? void 0 : step.type) === "heading" ? afterHeading(key, step.level) : (step === null || step === void 0 ? void 0 : step.type) === "next" && before !== void 0 ? before + 1 : void 0;
17329
+ numbers.set(key, value);
17330
+ counted.set(key, [...(_counted$get2 = counted.get(key)) !== null && _counted$get2 !== void 0 ? _counted$get2 : [], _objectSpread2({ paragraph }, value === void 0 ? {} : { step })]);
17331
+ return value === void 0 || sequence === void 0 ? void 0 : sequence.hidden ? "" : (_numberWriterOf = numberWriterOf(sequence.format)) === null || _numberWriterOf === void 0 ? void 0 : _numberWriterOf(value);
17332
+ }
17333
+ };
17334
+ };
17335
+ //#endregion
17336
+ //#region src/file/document/body/page-numbers.ts
17337
+ /**
17338
+ * Page numbers written into the fields of a document that show them, when it is written, from an estimate of its pages.
17339
+ *
17340
+ * A page reference is a PAGEREF field, such as the page number of an entry in a table of contents, and the numbers of
17341
+ * pages of the document and of a section are NUMPAGES and SECTIONPAGES fields. Word works their results out when it
17342
+ * updates the fields, or lays the pages out, and until then, and in applications that don't, the fields show the results
17343
+ * they were written with. `docx` doesn't lay out pages, so it writes the results empty, unless the document is given a
17344
+ * {@link PageNumberEstimator}, such as `estimatePageNumbers` from `docx/layout`. Then, once the body is written, each of
17345
+ * those fields in the body, and then in the headers and footers, is given the number the estimator worked out.
17346
+ *
17347
+ * Page references and tables of contents are written dirty, so Word updates them when it opens the document, and asks
17348
+ * "This document contains fields that may refer to other files. Do you want to update the fields in this document?".
17349
+ * When the document is given page numbers, they are written clean, so Word shows them as they are and doesn't ask. A
17350
+ * page number the estimator didn't work out is left blank, until the fields are updated. So are SEQ fields, the numbers
17351
+ * of captions, which are given their numbers then too.
17352
+ *
17353
+ * @module
17354
+ */
17355
+ var nameOf$1 = (element) => {
17356
+ const name = typeof element === "object" && element !== null && !Array.isArray(element) ? Object.keys(element)[0] : void 0;
17357
+ return name === "_attr" ? void 0 : name;
17358
+ };
17359
+ var textElement = (text) => ({ "w:t": [{ _attr: { "xml:space": "preserve" } }, text] });
17360
+ /** The elements docx formats to write a document */
17361
+ var FORMATTED = {
17362
+ nameOf: nameOf$1,
17363
+ contentOf: (element) => {
17364
+ const content = element[nameOf$1(element)];
17365
+ return Array.isArray(content) ? content : void 0;
17366
+ },
17367
+ attributeOf: (element, attribute) => {
17368
+ var _holder$_attr;
17369
+ const content = element[nameOf$1(element)];
17370
+ const holder = Array.isArray(content) ? content.find((child) => typeof child === "object" && child !== null && "_attr" in child) : content;
17371
+ return holder === null || holder === void 0 || (_holder$_attr = holder._attr) === null || _holder$_attr === void 0 ? void 0 : _holder$_attr[attribute];
17372
+ },
17373
+ textOf: (element) => FORMATTED.contentOf(element).filter((part) => typeof part === "string").join(""),
17374
+ textElement,
17375
+ writeClean: (begin) => {
17376
+ if (isDirtyWithoutPageNumbers(begin)) {
17377
+ const attributes = begin["w:fldChar"]._attr;
17378
+ begin["w:fldChar"] = { _attr: Object.fromEntries(Object.entries(attributes).filter(([key]) => key !== "w:dirty")) };
17379
+ }
17380
+ },
17381
+ setSimpleFieldResult: (element, text) => {
17382
+ const content = element["w:fldSimple"];
17383
+ element["w:fldSimple"] = [...(Array.isArray(content) ? content : [content]).filter((child) => typeof child === "object" && child !== null && "_attr" in child), { "w:r": [textElement(text)] }];
17384
+ }
17385
+ };
17386
+ /** The estimate of each document's pages, and the numbers of pages its headers and footers show, once its body is written */
17387
+ var estimates = /* @__PURE__ */ new WeakMap();
17388
+ /**
17389
+ * Writes the numbers of the SEQ fields of a formatted body into them, counted as Word counts them (see
17390
+ * {@link sequenceNumbering}), and writes them clean, whether or not their numbers were worked out. It is done after its
17391
+ * tables of contents are filled in from its headings, as Word leaves a heading's SEQ number out of its entry.
17392
+ */
17393
+ var fillSequenceNumbers = (body, context) => {
17394
+ const { startParagraph, numberOf } = sequenceNumbering(context);
17395
+ fillSequenceFields(FORMATTED, body, {
17396
+ beforeParagraph: (paragraph) => startParagraph(paragraph),
17397
+ resultOf: (instruction, within) => isSequenceField(instruction) ? numberOf(instruction, within) : void 0
17398
+ });
17399
+ };
17400
+ /**
17401
+ * Writes the page numbers the estimator works out into the fields of a formatted body that show them: the PAGEREF fields
17402
+ * in its tables of contents and elsewhere, those with `\p` and in number formats of their own, and its NUMPAGES and
17403
+ * SECTIONPAGES fields. A field whose number the estimator didn't work out is left as it is. Page references and tables
17404
+ * of contents are written clean, whether or not their numbers were worked out. The estimate is kept for the document's
17405
+ * headers and footers.
17406
+ */
17407
+ var fillPageNumbers = (body, context, estimator) => {
17408
+ const estimate = estimator(body, context);
17409
+ const partPageCounts = fillBodyFields(FORMATTED, body, estimate, { blank: false });
17410
+ if (context.file) estimates.set(context.file, {
17411
+ estimate,
17412
+ partPageCounts
17413
+ });
17414
+ };
17415
+ /**
17416
+ * Writes the page numbers worked out for the document a header, footer, footnote, endnote or comment is in into the
17417
+ * fields of the formatted part that show them, once the document's body is written. Its page references and SEQ fields
17418
+ * are written clean, and its SEQ fields are left blank: Word writes them as an error, "Error! Main Document Only.".
17419
+ *
17420
+ * @param part - The formatted part, if it has anything to write
17421
+ * @param context - The context it was formatted in, with the document it is in
17422
+ * @param referenceId - The number of the relationship to a header or footer. The SECTIONPAGES fields of the other parts
17423
+ * are left as they are
17424
+ */
17425
+ var fillPartPageNumbers = (part, context, referenceId) => {
17426
+ const written = context.file && estimates.get(context.file);
17427
+ if (!part || !written) return;
17428
+ const sectionPageCount = referenceId === void 0 ? void 0 : written.partPageCounts.get(`rId${referenceId}`);
17429
+ const notes = "w:footnotes" in part || "w:endnotes" in part;
17430
+ fillPartFields(FORMATTED, part, written.estimate, {
17431
+ blank: false,
17432
+ sectionPageCount,
17433
+ notes
17434
+ });
17435
+ };
17436
+ //#endregion
16345
17437
  //#region src/file/relationships/attributes.ts
16346
17438
  /**
16347
17439
  * Attributes for the Relationships element.
@@ -16391,7 +17483,7 @@ var RelationshipsAttributes = class extends XmlAttributeComponent {
16391
17483
  * );
16392
17484
  * ```
16393
17485
  */
16394
- var Relationships = class extends XmlComponent {
17486
+ var Relationships = class Relationships extends XmlComponent {
16395
17487
  constructor() {
16396
17488
  super("Relationships");
16397
17489
  this.root.push(new RelationshipsAttributes({ xmlns: "http://schemas.openxmlformats.org/package/2006/relationships" }));
@@ -16408,6 +17500,20 @@ var Relationships = class extends XmlComponent {
16408
17500
  this.root.push(createRelationship(`rId${id}`, type, target, targetMode));
16409
17501
  }
16410
17502
  /**
17503
+ * Creates a copy of the relationships given. Relationships added to the copy aren't added to them, so the compiler
17504
+ * adds the ones it writes for a part, such as to its images, to a copy, and packing a document again doesn't add
17505
+ * them a second time.
17506
+ *
17507
+ * Static, as `IContext` is public and has `Relationships`, so a new instance member would change the public API.
17508
+ *
17509
+ * @param relationships - The relationships to copy
17510
+ */
17511
+ static copy(relationships) {
17512
+ const copy = new Relationships();
17513
+ copy.root.push(...relationships.root.slice(1));
17514
+ return copy;
17515
+ }
17516
+ /**
16411
17517
  * Gets the count of relationships in this collection.
16412
17518
  * Excludes the attributes element from the count.
16413
17519
  */
@@ -16418,6 +17524,17 @@ var Relationships = class extends XmlComponent {
16418
17524
  //#endregion
16419
17525
  //#region src/file/paragraph/run/comment-run.ts
16420
17526
  /**
17527
+ * Comment module for WordprocessingML documents.
17528
+ *
17529
+ * This module provides support for comments (annotations) in documents. Comments
17530
+ * consist of comment ranges (start/end markers), comment references, and the
17531
+ * actual comment content.
17532
+ *
17533
+ * Reference: http://officeopenxml.com/WPrun.php
17534
+ *
17535
+ * @module
17536
+ */
17537
+ /**
16421
17538
  * @internal
16422
17539
  */
16423
17540
  var CommentAttributes = class extends XmlAttributeComponent {
@@ -16447,6 +17564,7 @@ var RootCommentsAttributes = class extends XmlAttributeComponent {
16447
17564
  constructor(..._args3) {
16448
17565
  super(..._args3);
16449
17566
  _defineProperty(this, "xmlKeys", {
17567
+ "xmlns:wpc": "xmlns:wpc",
16450
17568
  "xmlns:cx": "xmlns:cx",
16451
17569
  "xmlns:cx1": "xmlns:cx1",
16452
17570
  "xmlns:cx2": "xmlns:cx2",
@@ -16687,6 +17805,7 @@ var Comments = class extends XmlComponent {
16687
17805
  _defineProperty(this, "isEmpty", void 0);
16688
17806
  this.isEmpty = children.length === 0;
16689
17807
  this.root.push(new RootCommentsAttributes({
17808
+ "xmlns:wpc": "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas",
16690
17809
  "xmlns:cx": "http://schemas.microsoft.com/office/drawing/2014/chartex",
16691
17810
  "xmlns:cx1": "http://schemas.microsoft.com/office/drawing/2015/9/8/chartex",
16692
17811
  "xmlns:cx2": "http://schemas.microsoft.com/office/drawing/2015/10/21/chartex",
@@ -16755,6 +17874,15 @@ var Comments = class extends XmlComponent {
16755
17874
  get IsEmpty() {
16756
17875
  return this.isEmpty;
16757
17876
  }
17877
+ /**
17878
+ * Formats the comments, with the page numbers worked out for their document written into their fields, when the
17879
+ * document's body is written with an estimate of its pages.
17880
+ */
17881
+ prepForXml(context) {
17882
+ const xml = super.prepForXml(context);
17883
+ fillPartPageNumbers(xml, context);
17884
+ return xml;
17885
+ }
16758
17886
  };
16759
17887
  //#endregion
16760
17888
  //#region src/file/paragraph/run/comments-extended.ts
@@ -18053,7 +19181,7 @@ var BookmarkEndAttributes = class extends XmlAttributeComponent {
18053
19181
  * });
18054
19182
  * ```
18055
19183
  */
18056
- var Bookmark = class {
19184
+ var Bookmark = class Bookmark {
18057
19185
  constructor(options) {
18058
19186
  _defineProperty(this, "start", void 0);
18059
19187
  _defineProperty(this, "children", void 0);
@@ -18063,6 +19191,19 @@ var Bookmark = class {
18063
19191
  this.children = options.children;
18064
19192
  this.end = new BookmarkEnd(linkId);
18065
19193
  }
19194
+ /**
19195
+ * The components written in this bookmark's place: its start, its children and its end. A bookmark in its
19196
+ * children is written the same way, so one bookmark can hold another.
19197
+ *
19198
+ * @internal
19199
+ */
19200
+ get writtenAs() {
19201
+ return [
19202
+ this.start,
19203
+ ...this.children.flatMap((child) => child instanceof Bookmark ? child.writtenAs : [child]),
19204
+ this.end
19205
+ ];
19206
+ }
18066
19207
  };
18067
19208
  /**
18068
19209
  * Represents the start marker of a bookmark range.
@@ -18070,6 +19211,10 @@ var Bookmark = class {
18070
19211
  * This element marks the beginning of a bookmarked region in the document.
18071
19212
  * It must be paired with a corresponding BookmarkEnd element with the same id.
18072
19213
  *
19214
+ * The id must be unique in the document. `Bookmark` takes its ids from
19215
+ * `bookmarkUniqueNumericId`, so take this one from it too, or it can be the
19216
+ * same as a `Bookmark`'s.
19217
+ *
18073
19218
  * Reference: http://officeopenxml.com/WPbookmark.php
18074
19219
  *
18075
19220
  * ## XSD Schema
@@ -18087,7 +19232,10 @@ var Bookmark = class {
18087
19232
  *
18088
19233
  * @example
18089
19234
  * ```typescript
18090
- * new BookmarkStart("myBookmark", 1);
19235
+ * // A bookmark across two paragraphs
19236
+ * const id = bookmarkUniqueNumericId();
19237
+ * new Paragraph({ children: [new BookmarkStart("myBookmark", id), new TextRun("First")] });
19238
+ * new Paragraph({ children: [new TextRun("Last"), new BookmarkEnd(id)] });
18091
19239
  * ```
18092
19240
  */
18093
19241
  var BookmarkStart = class extends XmlComponent {
@@ -18104,7 +19252,8 @@ var BookmarkStart = class extends XmlComponent {
18104
19252
  * Represents the end marker of a bookmark range.
18105
19253
  *
18106
19254
  * This element marks the end of a bookmarked region in the document.
18107
- * It must be paired with a corresponding BookmarkStart element with the same id.
19255
+ * It must be paired with a corresponding BookmarkStart element with the same id,
19256
+ * taken from `bookmarkUniqueNumericId` (see `BookmarkStart`).
18108
19257
  *
18109
19258
  * Reference: http://officeopenxml.com/WPbookmark.php
18110
19259
  *
@@ -18123,7 +19272,9 @@ var BookmarkStart = class extends XmlComponent {
18123
19272
  *
18124
19273
  * @example
18125
19274
  * ```typescript
18126
- * new BookmarkEnd(1);
19275
+ * const id = bookmarkUniqueNumericId();
19276
+ * new BookmarkStart("myBookmark", id);
19277
+ * new BookmarkEnd(id);
18127
19278
  * ```
18128
19279
  */
18129
19280
  var BookmarkEnd = class extends XmlComponent {
@@ -18297,6 +19448,10 @@ var PageReferenceFieldInstruction = class extends XmlComponent {
18297
19448
  * The PAGEREF field displays the page number of the page containing
18298
19449
  * the specified bookmark, useful for cross-references like "see page 5".
18299
19450
  *
19451
+ * It is written dirty, so Word fills in the page number when it opens the document, after asking to. When the
19452
+ * document is given `pageNumbers`, it is written clean, with the number they work out, or blank when they couldn't,
19453
+ * and Word doesn't ask.
19454
+ *
18300
19455
  * @publicApi
18301
19456
  *
18302
19457
  * @example
@@ -18317,8 +19472,9 @@ var PageReferenceFieldInstruction = class extends XmlComponent {
18317
19472
  var PageReference = class extends Run {
18318
19473
  constructor(bookmarkId, options = {}) {
18319
19474
  super({ children: [
18320
- createBegin(true),
19475
+ createBeginDirtyWithoutPageNumbers(),
18321
19476
  new PageReferenceFieldInstruction(bookmarkId, options),
19477
+ createSeparate(),
18322
19478
  createEnd()
18323
19479
  ] });
18324
19480
  }
@@ -18833,17 +19989,18 @@ var createFrameProperties = (options) => {
18833
19989
  //#endregion
18834
19990
  //#region src/file/paragraph/properties.ts
18835
19991
  /**
18836
- * Paragraph properties module for WordprocessingML documents.
18837
- *
18838
- * This module provides the paragraph properties (pPr) element which specifies
18839
- * the formatting applied to a paragraph.
18840
- *
18841
- * Reference: http://officeopenxml.com/WPparagraphProperties.php
19992
+ * The alignment to write for each side of the page in a right-to-left paragraph.
18842
19993
  *
18843
- * @see https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_suppressLineNumbers_topic_ID0ECJAO.html
18844
- *
18845
- * @module
19994
+ * Word and LibreOffice read `w:jc` `left` and `right` as the start and end of the paragraph, the same as
19995
+ * `start` and `end` (ISO/IEC 29500-4 maps the transitional `left` and `right` onto the strict `start` and `end`,
19996
+ * and [MS-OE376] 2.3.1.13 notes the same for Word 2007). So in a `w:bidi` paragraph `left` lands on the right
19997
+ * side of the page. Swapping keeps `AlignmentType.LEFT` and `AlignmentType.RIGHT` on the side of the page they name.
19998
+ * `left` and `right` are written rather than `end` and `start` because Word 2007 does not know `start` and `end`.
18846
19999
  */
20000
+ var RIGHT_TO_LEFT_ALIGNMENTS = {
20001
+ left: "right",
20002
+ right: "left"
20003
+ };
18847
20004
  /**
18848
20005
  * Represents paragraph properties (pPr) in a WordprocessingML document.
18849
20006
  *
@@ -19007,7 +20164,7 @@ var ParagraphProperties = class extends IgnoreIfEmptyXmlComponent {
19007
20164
  if (options.spacing) this.push(createSpacing(options.spacing));
19008
20165
  if (options.indent) this.push(createIndent(options.indent));
19009
20166
  if (options.contextualSpacing !== void 0) this.push(new OnOffElement("w:contextualSpacing", options.contextualSpacing));
19010
- if (options.alignment) this.push(createAlignment(options.alignment));
20167
+ if (options.alignment) this.push(createAlignment(options.bidirectional && RIGHT_TO_LEFT_ALIGNMENTS[options.alignment] || options.alignment));
19011
20168
  if (options.outlineLevel !== void 0) this.push(createOutlineLevel(options.outlineLevel));
19012
20169
  if (options.suppressLineNumbers !== void 0) this.push(new OnOffElement("w:suppressLineNumbers", options.suppressLineNumbers));
19013
20170
  if (options.autoSpaceEastAsianText !== void 0) this.push(new OnOffElement("w:autoSpaceDN", options.autoSpaceEastAsianText));
@@ -19023,6 +20180,31 @@ var ParagraphProperties = class extends IgnoreIfEmptyXmlComponent {
19023
20180
  this.root.push(item);
19024
20181
  }
19025
20182
  /**
20183
+ * Adds the section properties (`w:sectPr`) of the section this paragraph ends.
20184
+ *
20185
+ * They go after the paragraph's run properties and before its revision (`w:pPrChange`),
20186
+ * the order CT_PPr gives them.
20187
+ *
20188
+ * @param sectionProperties - The properties of the section the paragraph ends
20189
+ */
20190
+ addSectionProperties(sectionProperties) {
20191
+ const revisionIndex = this.root.findIndex((item) => item instanceof ParagraphPropertiesChange);
20192
+ if (revisionIndex === -1) {
20193
+ this.root.push(sectionProperties);
20194
+ return;
20195
+ }
20196
+ this.root.splice(revisionIndex, 0, sectionProperties);
20197
+ }
20198
+ /**
20199
+ * Removes the section properties added with {@link addSectionProperties}.
20200
+ *
20201
+ * @param sectionProperties - The properties of the section to remove
20202
+ */
20203
+ removeSectionProperties(sectionProperties) {
20204
+ const index = this.root.indexOf(sectionProperties);
20205
+ if (index !== -1) this.root.splice(index, 1);
20206
+ }
20207
+ /**
19026
20208
  * Prepares the paragraph properties for XML serialization.
19027
20209
  *
19028
20210
  * This method creates concrete numbering instances for any numbering references
@@ -19050,13 +20232,6 @@ var ParagraphPropertiesChange = class extends XmlComponent {
19050
20232
  //#endregion
19051
20233
  //#region src/file/paragraph/paragraph.ts
19052
20234
  /**
19053
- * Paragraph module for WordprocessingML documents.
19054
- *
19055
- * Reference: http://officeopenxml.com/WPparagraph.php
19056
- *
19057
- * @module
19058
- */
19059
- /**
19060
20235
  * Represents a paragraph in a WordprocessingML document.
19061
20236
  *
19062
20237
  * A paragraph is the primary unit of block-level content in a document and can contain
@@ -19108,9 +20283,7 @@ var Paragraph = class extends FileChild {
19108
20283
  if (options.text) this.root.push(new TextRun(options.text));
19109
20284
  if (options.children) for (const child of options.children) {
19110
20285
  if (child instanceof Bookmark) {
19111
- this.root.push(child.start);
19112
- for (const textRun of child.children) this.root.push(textRun);
19113
- this.root.push(child.end);
20286
+ this.root.push(...child.writtenAs);
19114
20287
  continue;
19115
20288
  }
19116
20289
  this.root.push(child);
@@ -19125,6 +20298,28 @@ var Paragraph = class extends FileChild {
19125
20298
  }
19126
20299
  return super.prepForXml(context);
19127
20300
  }
20301
+ /**
20302
+ * Ends a section at this paragraph by adding the section's properties to the paragraph's properties,
20303
+ * as Word does with the last paragraph of each section but the last.
20304
+ *
20305
+ * The body adds them only while it is written and removes them afterwards with
20306
+ * {@link removeSectionProperties}, so the same paragraph can be used in other documents.
20307
+ *
20308
+ * @internal
20309
+ * @param sectionProperties - The properties of the section the paragraph ends
20310
+ */
20311
+ addSectionProperties(sectionProperties) {
20312
+ this.properties.addSectionProperties(sectionProperties);
20313
+ }
20314
+ /**
20315
+ * Removes the section properties added with {@link addSectionProperties}.
20316
+ *
20317
+ * @internal
20318
+ * @param sectionProperties - The properties of the section to remove
20319
+ */
20320
+ removeSectionProperties(sectionProperties) {
20321
+ this.properties.removeSectionProperties(sectionProperties);
20322
+ }
19128
20323
  addRunToFront(run) {
19129
20324
  this.root.splice(1, 0, run);
19130
20325
  return this;
@@ -19217,6 +20412,28 @@ var MathText = class extends XmlComponent {
19217
20412
  }
19218
20413
  };
19219
20414
  //#endregion
20415
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/objectWithoutPropertiesLoose.js
20416
+ function _objectWithoutPropertiesLoose(r, e) {
20417
+ if (null == r) return {};
20418
+ var t = {};
20419
+ for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
20420
+ if (e.includes(n)) continue;
20421
+ t[n] = r[n];
20422
+ }
20423
+ return t;
20424
+ }
20425
+ //#endregion
20426
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/objectWithoutProperties.js
20427
+ function _objectWithoutProperties(e, t) {
20428
+ if (null == e) return {};
20429
+ var o, r, i = _objectWithoutPropertiesLoose(e, t);
20430
+ if (Object.getOwnPropertySymbols) {
20431
+ var s = Object.getOwnPropertySymbols(e);
20432
+ for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
20433
+ }
20434
+ return i;
20435
+ }
20436
+ //#endregion
19220
20437
  //#region src/file/paragraph/math/math-run.ts
19221
20438
  /**
19222
20439
  * Math Run module for Office MathML.
@@ -19227,6 +20444,33 @@ var MathText = class extends XmlComponent {
19227
20444
  *
19228
20445
  * @module
19229
20446
  */
20447
+ var _excluded$3 = [
20448
+ "text",
20449
+ "normalText",
20450
+ "script",
20451
+ "literal"
20452
+ ];
20453
+ var STYLES = {
20454
+ plain: "p",
20455
+ bold: "b",
20456
+ italic: "i",
20457
+ boldItalic: "bi"
20458
+ };
20459
+ var SCRIPTS = {
20460
+ roman: "roman",
20461
+ script: "script",
20462
+ fraktur: "fraktur",
20463
+ doubleStruck: "double-struck",
20464
+ sansSerif: "sans-serif",
20465
+ monospace: "monospace"
20466
+ };
20467
+ var createValueElement = (name, value) => new BuilderElement({
20468
+ name,
20469
+ attributes: { value: {
20470
+ key: "m:val",
20471
+ value
20472
+ } }
20473
+ });
19230
20474
  /**
19231
20475
  * Represents a run of text within a math equation.
19232
20476
  *
@@ -19255,24 +20499,28 @@ var MathText = class extends XmlComponent {
19255
20499
  * ```typescript
19256
20500
  * new MathRun("x + y");
19257
20501
  * new MathRun({ text: "if ", normalText: true });
20502
+ * new MathRun({ text: "R", script: "doubleStruck" });
20503
+ * new MathRun({ text: "d", style: "plain" });
19258
20504
  * ```
19259
20505
  */
19260
20506
  var MathRun = class extends XmlComponent {
19261
20507
  constructor(options) {
20508
+ var _rest$style;
19262
20509
  super("m:r");
19263
- const { text, normalText } = typeof options === "string" ? {
19264
- text: options,
19265
- normalText: false
19266
- } : options;
19267
- if (normalText) this.root.push(new BuilderElement({
20510
+ const _ref = typeof options === "string" ? { text: options } : options, { text, normalText, script, literal } = _ref;
20511
+ const style = (_rest$style = _objectWithoutProperties(_ref, _excluded$3).style) !== null && _rest$style !== void 0 ? _rest$style : script === void 0 || script === "roman" ? void 0 : "plain";
20512
+ if (normalText && (style !== void 0 || script !== void 0)) throw new Error("MathRun: normalText can't be given with style or script, which are for math. Give one or the other");
20513
+ if (style !== void 0 && !Object.keys(STYLES).includes(style)) throw new Error(`MathRun: style is "${style}", which isn't one of ${Object.keys(STYLES).join(", ")}`);
20514
+ if (script !== void 0 && !Object.keys(SCRIPTS).includes(script)) throw new Error(`MathRun: script is "${script}", which isn't one of ${Object.keys(SCRIPTS).join(", ")}`);
20515
+ const properties = [
20516
+ ...literal ? [createValueElement("m:lit", 1)] : [],
20517
+ ...normalText ? [createValueElement("m:nor", 1)] : [],
20518
+ ...script === void 0 ? [] : [createValueElement("m:scr", SCRIPTS[script])],
20519
+ ...style === void 0 ? [] : [createValueElement("m:sty", STYLES[style])]
20520
+ ];
20521
+ if (properties.length > 0) this.root.push(new BuilderElement({
19268
20522
  name: "m:rPr",
19269
- children: [new BuilderElement({
19270
- name: "m:nor",
19271
- attributes: { on: {
19272
- key: "m:val",
19273
- value: 1
19274
- } }
19275
- })]
20523
+ children: properties
19276
20524
  }));
19277
20525
  this.root.push(new MathText(text));
19278
20526
  }
@@ -19328,6 +20576,12 @@ var MathNumerator = class extends XmlComponent {
19328
20576
  *
19329
20577
  * @module
19330
20578
  */
20579
+ var TYPES = {
20580
+ stacked: "bar",
20581
+ skewed: "skw",
20582
+ linear: "lin",
20583
+ noBar: "noBar"
20584
+ };
19331
20585
  /**
19332
20586
  * Represents a fraction in a math equation.
19333
20587
  *
@@ -19354,11 +20608,29 @@ var MathNumerator = class extends XmlComponent {
19354
20608
  * numerator: [new MathRun("a + b")],
19355
20609
  * denominator: [new MathRun("c")],
19356
20610
  * });
20611
+ *
20612
+ * // n over k, as a binomial coefficient, in brackets
20613
+ * new MathRoundBrackets({
20614
+ * children: [new MathFraction({ numerator: [new MathRun("n")], denominator: [new MathRun("k")], type: "noBar" })],
20615
+ * });
19357
20616
  * ```
19358
20617
  */
19359
20618
  var MathFraction = class extends XmlComponent {
19360
20619
  constructor(options) {
19361
20620
  super("m:f");
20621
+ if (options.type !== void 0) {
20622
+ if (!Object.keys(TYPES).includes(options.type)) throw new Error(`MathFraction: type is "${options.type}", which isn't one of ${Object.keys(TYPES).join(", ")}`);
20623
+ this.root.push(new BuilderElement({
20624
+ name: "m:fPr",
20625
+ children: [new BuilderElement({
20626
+ name: "m:type",
20627
+ attributes: { value: {
20628
+ key: "m:val",
20629
+ value: TYPES[options.type]
20630
+ } }
20631
+ })]
20632
+ }));
20633
+ }
19362
20634
  this.root.push(new MathNumerator(options.numerator));
19363
20635
  this.root.push(new MathDenominator(options.denominator));
19364
20636
  }
@@ -19608,6 +20880,22 @@ var createMathSubScriptElement = ({ children }) => new BuilderElement({
19608
20880
  children
19609
20881
  });
19610
20882
  //#endregion
20883
+ //#region src/file/paragraph/math/n-ary/limit-location-value.ts
20884
+ var LOCATIONS = {
20885
+ aboveBelow: "undOvr",
20886
+ side: "subSup"
20887
+ };
20888
+ /**
20889
+ * The value of `m:limLoc` for where limits go, or the default when none is given.
20890
+ *
20891
+ * @throws If the position isn't one of those allowed, for code that isn't type checked
20892
+ */
20893
+ var limitLocationValue = (owner, limits, defaultValue) => {
20894
+ if (limits === void 0) return defaultValue;
20895
+ if (!Object.keys(LOCATIONS).includes(limits)) throw new Error(`${owner}: limits is "${limits}", which isn't one of ${Object.keys(LOCATIONS).join(", ")}`);
20896
+ return LOCATIONS[limits];
20897
+ };
20898
+ //#endregion
19611
20899
  //#region src/file/paragraph/math/n-ary/math-super-script.ts
19612
20900
  /**
19613
20901
  * Math SuperScript Element module for Office MathML.
@@ -19690,7 +20978,8 @@ var MathSum = class extends XmlComponent {
19690
20978
  this.root.push(createMathNAryProperties({
19691
20979
  accent: "∑",
19692
20980
  hasSuperScript: !!options.superScript,
19693
- hasSubScript: !!options.subScript
20981
+ hasSubScript: !!options.subScript,
20982
+ limitLocationVal: limitLocationValue("MathSum", options.limits, "undOvr")
19694
20983
  }));
19695
20984
  this.root.push(createMathSubScriptElement({ children: (_options$subScript = options.subScript) !== null && _options$subScript !== void 0 ? _options$subScript : [] }));
19696
20985
  this.root.push(createMathSuperScriptElement({ children: (_options$superScript = options.superScript) !== null && _options$superScript !== void 0 ? _options$superScript : [] }));
@@ -19747,7 +21036,7 @@ var MathIntegral = class extends XmlComponent {
19747
21036
  accent: "",
19748
21037
  hasSuperScript: !!options.superScript,
19749
21038
  hasSubScript: !!options.subScript,
19750
- limitLocationVal: "subSup"
21039
+ limitLocationVal: limitLocationValue("MathIntegral", options.limits, "subSup")
19751
21040
  }));
19752
21041
  this.root.push(createMathSubScriptElement({ children: (_options$subScript = options.subScript) !== null && _options$subScript !== void 0 ? _options$subScript : [] }));
19753
21042
  this.root.push(createMathSuperScriptElement({ children: (_options$superScript = options.superScript) !== null && _options$superScript !== void 0 ? _options$superScript : [] }));
@@ -20207,12 +21496,6 @@ var MathPreSubSuperScript = class extends BuilderElement {
20207
21496
  }
20208
21497
  };
20209
21498
  //#endregion
20210
- //#region src/file/paragraph/math/math-component.ts
20211
- /**
20212
- * @ignore
20213
- */
20214
- var WORKAROUND4 = "";
20215
- //#endregion
20216
21499
  //#region src/file/paragraph/math/radical/math-degree.ts
20217
21500
  /**
20218
21501
  * Math Degree module for Office MathML.
@@ -21093,6 +22376,168 @@ var createLineNumberType = ({ countBy, start, restart, distance }) => new Builde
21093
22376
  }
21094
22377
  });
21095
22378
  //#endregion
22379
+ //#region src/file/document/body/section-properties/properties/note-properties.ts
22380
+ /**
22381
+ * Where the footnotes of a section are placed.
22382
+ *
22383
+ * ## XSD Schema
22384
+ * ```xml
22385
+ * <xsd:simpleType name="ST_FtnPos">
22386
+ * <xsd:restriction base="xsd:string">
22387
+ * <xsd:enumeration value="pageBottom"/>
22388
+ * <xsd:enumeration value="beneathText"/>
22389
+ * <xsd:enumeration value="sectEnd"/>
22390
+ * <xsd:enumeration value="docEnd"/>
22391
+ * </xsd:restriction>
22392
+ * </xsd:simpleType>
22393
+ * ```
22394
+ *
22395
+ * @publicApi
22396
+ */
22397
+ var FootnotePosition = {
22398
+ /** At the bottom of each page */
22399
+ PAGE_BOTTOM: "pageBottom",
22400
+ /** Directly below the text on each page */
22401
+ BENEATH_TEXT: "beneathText",
22402
+ /** At the end of the section */
22403
+ SECTION_END: "sectEnd",
22404
+ /** At the end of the document */
22405
+ DOCUMENT_END: "docEnd"
22406
+ };
22407
+ /**
22408
+ * Where the endnotes of a section are placed.
22409
+ *
22410
+ * ## XSD Schema
22411
+ * ```xml
22412
+ * <xsd:simpleType name="ST_EdnPos">
22413
+ * <xsd:restriction base="xsd:string">
22414
+ * <xsd:enumeration value="sectEnd"/>
22415
+ * <xsd:enumeration value="docEnd"/>
22416
+ * </xsd:restriction>
22417
+ * </xsd:simpleType>
22418
+ * ```
22419
+ *
22420
+ * @publicApi
22421
+ */
22422
+ var EndnotePosition = {
22423
+ /** At the end of the section */
22424
+ SECTION_END: "sectEnd",
22425
+ /** At the end of the document */
22426
+ DOCUMENT_END: "docEnd"
22427
+ };
22428
+ /**
22429
+ * When the footnote or endnote numbering restarts.
22430
+ *
22431
+ * ## XSD Schema
22432
+ * ```xml
22433
+ * <xsd:simpleType name="ST_RestartNumber">
22434
+ * <xsd:restriction base="xsd:string">
22435
+ * <xsd:enumeration value="continuous"/>
22436
+ * <xsd:enumeration value="eachSect"/>
22437
+ * <xsd:enumeration value="eachPage"/>
22438
+ * </xsd:restriction>
22439
+ * </xsd:simpleType>
22440
+ * ```
22441
+ *
22442
+ * @publicApi
22443
+ */
22444
+ var NoteNumberRestart = {
22445
+ /** Numbering never restarts */
22446
+ CONTINUOUS: "continuous",
22447
+ /** Numbering restarts in each section */
22448
+ EACH_SECTION: "eachSect",
22449
+ /** Numbering restarts on each page */
22450
+ EACH_PAGE: "eachPage"
22451
+ };
22452
+ var createNoteProperties = ({ name, position, numberFormat, start, restart }) => new BuilderElement({
22453
+ name,
22454
+ children: [
22455
+ ...position === void 0 ? [] : [new BuilderElement({
22456
+ name: "w:pos",
22457
+ attributes: { val: {
22458
+ key: "w:val",
22459
+ value: position
22460
+ } }
22461
+ })],
22462
+ ...numberFormat ? [new BuilderElement({
22463
+ name: "w:numFmt",
22464
+ attributes: {
22465
+ val: {
22466
+ key: "w:val",
22467
+ value: numberFormat.type
22468
+ },
22469
+ format: {
22470
+ key: "w:format",
22471
+ value: numberFormat.format
22472
+ }
22473
+ }
22474
+ })] : [],
22475
+ ...start === void 0 ? [] : [new BuilderElement({
22476
+ name: "w:numStart",
22477
+ attributes: { val: {
22478
+ key: "w:val",
22479
+ value: decimalNumber(start)
22480
+ } }
22481
+ })],
22482
+ ...restart === void 0 ? [] : [new BuilderElement({
22483
+ name: "w:numRestart",
22484
+ attributes: { val: {
22485
+ key: "w:val",
22486
+ value: restart
22487
+ } }
22488
+ })]
22489
+ ]
22490
+ });
22491
+ /**
22492
+ * Creates the footnote properties (footnotePr) of a section.
22493
+ *
22494
+ * ## XSD Schema
22495
+ * ```xml
22496
+ * <xsd:complexType name="CT_FtnProps">
22497
+ * <xsd:sequence>
22498
+ * <xsd:element name="pos" type="CT_FtnPos" minOccurs="0"/>
22499
+ * <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0"/>
22500
+ * <xsd:group ref="EG_FtnEdnNumProps" minOccurs="0"/>
22501
+ * </xsd:sequence>
22502
+ * </xsd:complexType>
22503
+ * ```
22504
+ *
22505
+ * @example
22506
+ * ```typescript
22507
+ * // Footnotes at the end of the section, numbered a, b, c and restarting in each section
22508
+ * createFootnoteProperties({
22509
+ * position: FootnotePosition.SECTION_END,
22510
+ * numberFormat: { type: NumberFormat.LOWER_LETTER },
22511
+ * restart: NoteNumberRestart.EACH_SECTION,
22512
+ * });
22513
+ * ```
22514
+ */
22515
+ var createFootnoteProperties = (options) => createNoteProperties(_objectSpread2({ name: "w:footnotePr" }, options));
22516
+ /**
22517
+ * Creates the endnote properties (endnotePr) of a section.
22518
+ *
22519
+ * ## XSD Schema
22520
+ * ```xml
22521
+ * <xsd:complexType name="CT_EdnProps">
22522
+ * <xsd:sequence>
22523
+ * <xsd:element name="pos" type="CT_EdnPos" minOccurs="0"/>
22524
+ * <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0"/>
22525
+ * <xsd:group ref="EG_FtnEdnNumProps" minOccurs="0"/>
22526
+ * </xsd:sequence>
22527
+ * </xsd:complexType>
22528
+ * ```
22529
+ *
22530
+ * @example
22531
+ * ```typescript
22532
+ * // Endnotes at the end of the document, numbered 001, 002, 003
22533
+ * createEndnoteProperties({
22534
+ * position: EndnotePosition.DOCUMENT_END,
22535
+ * numberFormat: { type: NumberFormat.CUSTOM, format: "001" },
22536
+ * });
22537
+ * ```
22538
+ */
22539
+ var createEndnoteProperties = (options) => createNoteProperties(_objectSpread2({ name: "w:endnotePr" }, options));
22540
+ //#endregion
21096
22541
  //#region src/file/document/body/section-properties/properties/page-borders.ts
21097
22542
  /**
21098
22543
  * Page borders module for WordprocessingML section properties.
@@ -21332,7 +22777,7 @@ var PageNumberSeparator = {
21332
22777
  COLON: "colon",
21333
22778
  /** Em dash separator (—) */
21334
22779
  EM_DASH: "emDash",
21335
- /** En dash separator (–) */
22780
+ /** En dash separator (–), written as `enDash` */
21336
22781
  EN_DASH: "endash"
21337
22782
  };
21338
22783
  /**
@@ -21362,7 +22807,7 @@ var PageNumberSeparator = {
21362
22807
  * });
21363
22808
  * ```
21364
22809
  */
21365
- var createPageNumberType = ({ start, formatType, separator }) => new BuilderElement({
22810
+ var createPageNumberType = ({ start, formatType, separator, chapterHeadingLevel }) => new BuilderElement({
21366
22811
  name: "w:pgNumType",
21367
22812
  attributes: {
21368
22813
  start: {
@@ -21375,7 +22820,11 @@ var createPageNumberType = ({ start, formatType, separator }) => new BuilderElem
21375
22820
  },
21376
22821
  separator: {
21377
22822
  key: "w:chapSep",
21378
- value: separator
22823
+ value: separator === PageNumberSeparator.EN_DASH ? "enDash" : separator
22824
+ },
22825
+ chapterHeadingLevel: {
22826
+ key: "w:chapStyle",
22827
+ value: chapterHeadingLevel === void 0 ? void 0 : decimalNumber(chapterHeadingLevel)
21379
22828
  }
21380
22829
  }
21381
22830
  });
@@ -21679,7 +23128,7 @@ var sectionPageSizeDefaults = {
21679
23128
  * ```
21680
23129
  */
21681
23130
  var SectionProperties = class SectionProperties extends XmlComponent {
21682
- 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 } = {}) {
23131
+ 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 } = {}) {
21683
23132
  super("w:sectPr");
21684
23133
  _defineProperty(
21685
23134
  this,
@@ -21702,6 +23151,8 @@ var SectionProperties = class SectionProperties extends XmlComponent {
21702
23151
  });
21703
23152
  this.addHeaderFooterGroup(HeaderFooterType.HEADER, headerWrapperGroup);
21704
23153
  this.addHeaderFooterGroup(HeaderFooterType.FOOTER, footerWrapperGroup);
23154
+ if (footnoteProperties) this.root.push(createFootnoteProperties(footnoteProperties));
23155
+ if (endnoteProperties) this.root.push(createEndnoteProperties(endnoteProperties));
21705
23156
  if (type) this.root.push(createSectionType(type));
21706
23157
  this.root.push(createPageSize({
21707
23158
  width,
@@ -21826,7 +23277,7 @@ var SectionPropertiesChange = class extends XmlComponent {
21826
23277
  * ```
21827
23278
  */
21828
23279
  var Body = class extends XmlComponent {
21829
- constructor() {
23280
+ constructor({ pageNumbers } = {}) {
21830
23281
  super("w:body");
21831
23282
  _defineProperty(this, "sections", []);
21832
23283
  _defineProperty(
@@ -21834,11 +23285,15 @@ var Body = class extends XmlComponent {
21834
23285
  /**
21835
23286
  * Section properties that were moved into a paragraph at the end of their section
21836
23287
  * by {@link addSection}, keyed by that paragraph. Used to find the section that
21837
- * governs a given child of the body.
23288
+ * governs a given child of the body, and to write each section's properties into
23289
+ * its paragraph while the body is written.
21838
23290
  */
21839
23291
  "sectionParagraphs",
21840
23292
  /* @__PURE__ */ new Map()
21841
23293
  );
23294
+ _defineProperty(this, "headingBookmarkIds", new HeadingBookmarkIds());
23295
+ _defineProperty(this, "pageNumbers", void 0);
23296
+ this.pageNumbers = pageNumbers;
21842
23297
  }
21843
23298
  /**
21844
23299
  * Finds the section properties that govern a top-level child of the body.
@@ -21853,7 +23308,7 @@ var Body = class extends XmlComponent {
21853
23308
  * @returns The governing section properties, or undefined if the body has no sections
21854
23309
  */
21855
23310
  getSectionPropertiesFor(child) {
21856
- const start = child ? this.root.indexOf(child) + 1 : 0;
23311
+ const start = child ? Math.max(this.root.indexOf(child), 0) : 0;
21857
23312
  for (let i = start; i < this.root.length; i++) {
21858
23313
  const component = this.root[i];
21859
23314
  if (component instanceof SectionProperties) return component;
@@ -21865,8 +23320,10 @@ var Body = class extends XmlComponent {
21865
23320
  /**
21866
23321
  * Adds new section properties to the document body.
21867
23322
  *
21868
- * Creates a new section by moving the previous section's properties into a paragraph
21869
- * at the end of that section, and then adding the new section as the current section.
23323
+ * Creates a new section by moving the previous section's properties into the last
23324
+ * paragraph of that section, and then adding the new section as the current section.
23325
+ * When that section doesn't end with a paragraph of its own (it ends with a table, or
23326
+ * it is empty), an empty paragraph is added to hold its properties.
21870
23327
  *
21871
23328
  * According to the OOXML specification:
21872
23329
  * - Section properties for all sections except the last must be stored in a paragraph's
@@ -21877,16 +23334,24 @@ var Body = class extends XmlComponent {
21877
23334
  */
21878
23335
  addSection(options) {
21879
23336
  const currentSection = this.sections.pop();
21880
- const sectionParagraph = this.createSectionParagraph(currentSection);
21881
- this.root.push(sectionParagraph);
21882
- if (currentSection) this.sectionParagraphs.set(sectionParagraph, currentSection);
23337
+ const lastParagraph = this.lastParagraphOfSection();
23338
+ if (currentSection && lastParagraph) this.sectionParagraphs.set(lastParagraph, currentSection);
23339
+ else {
23340
+ const sectionParagraph = this.createSectionParagraph();
23341
+ this.root.push(sectionParagraph);
23342
+ if (currentSection) this.sectionParagraphs.set(sectionParagraph, currentSection);
23343
+ }
21883
23344
  this.sections.push(new SectionProperties(options));
21884
23345
  }
21885
23346
  /**
21886
23347
  * Prepares the body element for XML serialization.
21887
23348
  *
21888
23349
  * Ensures that the last section's properties are placed as a direct child of the body
21889
- * element, as required by the OOXML specification.
23350
+ * element, as required by the OOXML specification. Once the body is written, its tables
23351
+ * of contents are filled in from its headings, and, when the body has a page number
23352
+ * estimator, its page references are given their page numbers. Its SEQ fields are given
23353
+ * their numbers after the tables of contents are filled in, as Word leaves a heading's SEQ
23354
+ * number out of its entry.
21890
23355
  *
21891
23356
  * @param context - The XML serialization context
21892
23357
  * @returns The prepared XML object or undefined
@@ -21896,7 +23361,19 @@ var Body = class extends XmlComponent {
21896
23361
  this.root.splice(0, 1);
21897
23362
  this.root.push(this.sections.pop());
21898
23363
  }
21899
- return super.prepForXml(context);
23364
+ for (const [paragraph, section] of this.sectionParagraphs) paragraph.addSectionProperties(section);
23365
+ let xml;
23366
+ try {
23367
+ xml = super.prepForXml(context);
23368
+ } finally {
23369
+ for (const [paragraph, section] of this.sectionParagraphs) paragraph.removeSectionProperties(section);
23370
+ }
23371
+ fillTablesOfContents(xml, context, this.headingBookmarkIds);
23372
+ if (this.pageNumbers) {
23373
+ fillSequenceNumbers(xml, context);
23374
+ fillPageNumbers(xml, context, this.pageNumbers);
23375
+ }
23376
+ return xml;
21900
23377
  }
21901
23378
  /**
21902
23379
  * Adds a block-level component to the body.
@@ -21907,14 +23384,32 @@ var Body = class extends XmlComponent {
21907
23384
  * @param component - The XML component to add (paragraph, table, etc.)
21908
23385
  */
21909
23386
  push(component) {
23387
+ const section = component instanceof Paragraph ? this.sectionParagraphs.get(component) : void 0;
23388
+ if (section) {
23389
+ const sectionParagraph = this.createSectionParagraph();
23390
+ this.root.splice(this.root.indexOf(component) + 1, 0, sectionParagraph);
23391
+ this.sectionParagraphs.delete(component);
23392
+ this.sectionParagraphs.set(sectionParagraph, section);
23393
+ }
21910
23394
  this.root.push(component);
21911
23395
  }
21912
- createSectionParagraph(section) {
21913
- const paragraph = new Paragraph({});
21914
- const properties = new ParagraphProperties({});
21915
- properties.push(section);
21916
- paragraph.addChildElement(properties);
21917
- return paragraph;
23396
+ /**
23397
+ * The paragraph the current section ends with, which can hold its properties.
23398
+ *
23399
+ * There is none when the section ends with something other than a paragraph, or is empty:
23400
+ * its last child is then the placeholder at the start of the body (removed when the body is
23401
+ * written) or the paragraph that ends the section before, which has properties of its own.
23402
+ */
23403
+ lastParagraphOfSection() {
23404
+ const last = this.root[this.root.length - 1];
23405
+ return last instanceof Paragraph && last !== this.root[0] && !this.sectionParagraphs.has(last) && this.root.indexOf(last) === this.root.length - 1 ? last : void 0;
23406
+ }
23407
+ /**
23408
+ * An empty paragraph to end a section that has no paragraph of its own to end it. The section's
23409
+ * properties are written into it with the others, when the body is written.
23410
+ */
23411
+ createSectionParagraph() {
23412
+ return new Paragraph({});
21918
23413
  }
21919
23414
  };
21920
23415
  //#endregion
@@ -23026,6 +24521,9 @@ var TDirection = class extends XmlComponent {
23026
24521
  var TableCellProperties = class extends IgnoreIfEmptyXmlComponent {
23027
24522
  constructor(options) {
23028
24523
  super("w:tcPr", options.includeIfEmpty);
24524
+ _defineProperty(this, "hasWidth", void 0);
24525
+ _defineProperty(this, "hasColumnWidth", false);
24526
+ this.hasWidth = options.width !== void 0;
23029
24527
  if (options.width) this.root.push(createTableWidthElement("w:tcW", options.width));
23030
24528
  if (options.columnSpan) this.root.push(new GridSpan(options.columnSpan));
23031
24529
  if (options.verticalMerge) this.root.push(new VerticalMerge(options.verticalMerge));
@@ -23043,6 +24541,19 @@ var TableCellProperties = class extends IgnoreIfEmptyXmlComponent {
23043
24541
  if (options.cellMerge) this.root.push(new CellMerge(options.cellMerge));
23044
24542
  if (options.revision) this.root.push(new TableCellPropertiesChange(options.revision));
23045
24543
  }
24544
+ /**
24545
+ * Gives a cell without a width of its own the width of the table's columns it spans, in twips.
24546
+ *
24547
+ * @internal
24548
+ */
24549
+ setColumnWidth(twips) {
24550
+ if (this.hasWidth) return;
24551
+ this.root.splice(0, this.hasColumnWidth ? 1 : 0, createTableWidthElement("w:tcW", {
24552
+ size: twips,
24553
+ type: WidthType.DXA
24554
+ }));
24555
+ this.hasColumnWidth = true;
24556
+ }
23046
24557
  };
23047
24558
  var TableCellPropertiesChange = class extends XmlComponent {
23048
24559
  constructor(options) {
@@ -23101,10 +24612,20 @@ var TableCell = class extends XmlComponent {
23101
24612
  "options",
23102
24613
  void 0
23103
24614
  );
24615
+ _defineProperty(this, "properties", void 0);
23104
24616
  this.options = options;
23105
- this.root.push(new TableCellProperties(options));
24617
+ this.properties = new TableCellProperties(options);
24618
+ this.root.push(this.properties);
23106
24619
  for (const child of options.children) this.root.push(child);
23107
24620
  }
24621
+ /**
24622
+ * Gives the cell, unless it has a width of its own, the width of the table's columns it spans, in twips.
24623
+ *
24624
+ * @internal
24625
+ */
24626
+ setColumnWidth(twips) {
24627
+ this.properties.setColumnWidth(twips);
24628
+ }
23108
24629
  prepForXml(context) {
23109
24630
  if (!(this.root[this.root.length - 1] instanceof Paragraph)) this.root.push(new Paragraph({}));
23110
24631
  return super.prepForXml(context);
@@ -23968,6 +25489,7 @@ var Table = class Table extends FileChild {
23968
25489
  columnIndex += cell.options.columnSpan || 1;
23969
25490
  });
23970
25491
  });
25492
+ this.setCellWidths(DEFAULT_AVAILABLE_WIDTH);
23971
25493
  this.resolvedColumnWidths = columnWidths !== null && columnWidths !== void 0 ? columnWidths : resolveColumnWidths({
23972
25494
  rows,
23973
25495
  width: this.width,
@@ -24024,6 +25546,7 @@ var Table = class Table extends FileChild {
24024
25546
  * serializing.
24025
25547
  */
24026
25548
  prepForXml(context) {
25549
+ this.setCellWidths(this.resolveAvailableWidth(context));
24027
25550
  if (this.columnWidths === void 0) {
24028
25551
  this.resolvedColumnWidths = resolveColumnWidths({
24029
25552
  rows: this.rows,
@@ -24036,6 +25559,29 @@ var Table = class Table extends FileChild {
24036
25559
  return super.prepForXml(context);
24037
25560
  }
24038
25561
  /**
25562
+ * Gives each cell without a width of its own the width of the `columnWidths` it spans, as Word sizes the columns of
25563
+ * cells without a width to their content, whatever the grid says. When the table's width is wider than the columns
25564
+ * add up to, they are scaled up to fill it, as Word and LibreOffice lay them out, so columns given as proportions
25565
+ * keep them.
25566
+ */
25567
+ setCellWidths(availableWidth) {
25568
+ var _resolvePreferredWidt;
25569
+ if (this.columnWidths === void 0) return;
25570
+ const total = this.columnWidths.reduce((sum, columnWidth) => sum + columnWidth, 0);
25571
+ const tableWidth = (_resolvePreferredWidt = resolvePreferredWidth(this.width, availableWidth)) !== null && _resolvePreferredWidt !== void 0 ? _resolvePreferredWidt : 0;
25572
+ const scale = total > 0 && tableWidth > total ? tableWidth / total : 1;
25573
+ for (const row of this.rows) {
25574
+ let column = 0;
25575
+ for (const cell of row.cells) {
25576
+ const span = cell.options.columnSpan || 1;
25577
+ const spanned = this.columnWidths.slice(column, column + span);
25578
+ const cellWidth = Math.round(spanned.reduce((sum, columnWidth) => sum + columnWidth, 0) * scale);
25579
+ if (spanned.length === span && cellWidth > 0) cell.setColumnWidth(cellWidth);
25580
+ column += span;
25581
+ }
25582
+ }
25583
+ }
25584
+ /**
24039
25585
  * Finds the width in twips available to this table from the serialization context:
24040
25586
  * the parent cell for a nested table, otherwise the text width of the section the
24041
25587
  * table belongs to (the first section for headers, footers and other parts). Falls
@@ -24648,7 +26194,7 @@ var CustomProperties = class extends XmlComponent {
24648
26194
  for (const property of properties) this.addCustomProperty(property);
24649
26195
  }
24650
26196
  prepForXml(context) {
24651
- this.properties.forEach((x) => this.root.push(x));
26197
+ this.root.splice(1, this.root.length - 1, ...this.properties);
24652
26198
  return super.prepForXml(context);
24653
26199
  }
24654
26200
  addCustomProperty(property) {
@@ -24910,7 +26456,7 @@ var Document = class extends XmlComponent {
24910
26456
  "w16sdtdh",
24911
26457
  "w16se"
24912
26458
  ], "w14 w15 wp14"));
24913
- this.body = new Body();
26459
+ this.body = new Body({ pageNumbers: options.pageNumbers });
24914
26460
  if (options.background) this.root.push(new DocumentBackground(options.background));
24915
26461
  this.root.push(this.body);
24916
26462
  }
@@ -25208,6 +26754,15 @@ var Endnotes = class extends XmlComponent {
25208
26754
  });
25209
26755
  this.root.push(endnote);
25210
26756
  }
26757
+ /**
26758
+ * Formats the endnotes, with the page numbers worked out for their document written into their fields, when the
26759
+ * document's body is written with an estimate of its pages.
26760
+ */
26761
+ prepForXml(context) {
26762
+ const xml = super.prepForXml(context);
26763
+ fillPartPageNumbers(xml, context);
26764
+ return xml;
26765
+ }
25211
26766
  };
25212
26767
  //#endregion
25213
26768
  //#region src/file/endnotes-wrapper.ts
@@ -25349,6 +26904,15 @@ var Footer$1 = class extends InitializableXmlComponent {
25349
26904
  add(item) {
25350
26905
  this.root.push(item);
25351
26906
  }
26907
+ /**
26908
+ * Formats the footer, with the page numbers worked out for its document written into its fields, when the document's
26909
+ * body is written with an estimate of its pages.
26910
+ */
26911
+ prepForXml(context) {
26912
+ const xml = super.prepForXml(context);
26913
+ fillPartPageNumbers(xml, context, this.refId);
26914
+ return xml;
26915
+ }
25352
26916
  };
25353
26917
  //#endregion
25354
26918
  //#region src/file/footer-wrapper.ts
@@ -25699,6 +27263,15 @@ var FootNotes = class extends XmlComponent {
25699
27263
  });
25700
27264
  this.root.push(footnote);
25701
27265
  }
27266
+ /**
27267
+ * Formats the footnotes, with the page numbers worked out for their document written into their fields, when the
27268
+ * document's body is written with an estimate of its pages.
27269
+ */
27270
+ prepForXml(context) {
27271
+ const xml = super.prepForXml(context);
27272
+ fillPartPageNumbers(xml, context);
27273
+ return xml;
27274
+ }
25702
27275
  };
25703
27276
  //#endregion
25704
27277
  //#region src/file/footnotes-wrapper.ts
@@ -25872,6 +27445,15 @@ var Header$1 = class extends InitializableXmlComponent {
25872
27445
  add(item) {
25873
27446
  this.root.push(item);
25874
27447
  }
27448
+ /**
27449
+ * Formats the header, with the page numbers worked out for its document written into its fields, when the document's
27450
+ * body is written with an estimate of its pages.
27451
+ */
27452
+ prepForXml(context) {
27453
+ const xml = super.prepForXml(context);
27454
+ fillPartPageNumbers(xml, context, this.refId);
27455
+ return xml;
27456
+ }
25875
27457
  };
25876
27458
  //#endregion
25877
27459
  //#region src/file/header-wrapper.ts
@@ -25967,12 +27549,6 @@ var Media = class {
25967
27549
  }
25968
27550
  };
25969
27551
  //#endregion
25970
- //#region src/file/media/data.ts
25971
- /**
25972
- * @ignore
25973
- */
25974
- var WORKAROUND2 = "";
25975
- //#endregion
25976
27552
  //#region src/file/numbering/level.ts
25977
27553
  /**
25978
27554
  * Numbering level definitions module for WordprocessingML documents.
@@ -26882,8 +28458,7 @@ var Numbering = class extends XmlComponent {
26882
28458
  * @returns The prepared XML object
26883
28459
  */
26884
28460
  prepForXml(context) {
26885
- for (const numbering of this.abstractNumberingMap.values()) this.root.push(numbering);
26886
- for (const numbering of this.concreteNumberingMap.values()) this.root.push(numbering);
28461
+ this.root.splice(1, this.root.length - 1, ...this.abstractNumberingMap.values(), ...this.concreteNumberingMap.values());
26887
28462
  return super.prepForXml(context);
26888
28463
  }
26889
28464
  /**
@@ -26937,6 +28512,7 @@ var Numbering = class extends XmlComponent {
26937
28512
  };
26938
28513
  //#endregion
26939
28514
  //#region src/file/package-part/package-part.ts
28515
+ var PATH_PART = /^[\w-]+$/;
26940
28516
  var RESERVED_FOLDERS = /* @__PURE__ */ new Set([
26941
28517
  "_rels",
26942
28518
  "fonts",
@@ -26975,6 +28551,7 @@ var RESERVED_FOLDERS = /* @__PURE__ */ new Set([
26975
28551
  var PackagePart = class {
26976
28552
  /**
26977
28553
  * @throws If the folder isn't a single folder name, or is one of the folders docx writes parts of its own in
28554
+ * @throws If the name or the extension isn't a single part of a file name, which could lead out of the folder
26978
28555
  */
26979
28556
  constructor(options) {
26980
28557
  _defineProperty(this, "options", void 0);
@@ -26987,7 +28564,9 @@ var PackagePart = class {
26987
28564
  );
26988
28565
  _defineProperty(this, "addedTo", /* @__PURE__ */ new WeakSet());
26989
28566
  this.options = options;
26990
- 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"`);
28567
+ 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"`);
28568
+ if (!PATH_PART.test(options.name)) throw new Error(`Invalid package part name "${options.name}". Expected letters, digits, "_" and "-", such as "chart"`);
28569
+ if (!PATH_PART.test(options.extension)) throw new Error(`Invalid package part extension "${options.extension}". Expected letters, digits, "_" and "-", such as "xml"`);
26991
28570
  }
26992
28571
  /**
26993
28572
  * Adds the part to the package being written, once, and a relationship to it from the part being written.
@@ -27009,7 +28588,7 @@ var PackageParts = class {
27009
28588
  /**
27010
28589
  * @param contentTypes - Where each part's content type is added
27011
28590
  * @param existingPaths - The paths under word/ of the parts the package already has, such as a template's charts,
27012
- * which new parts are numbered after
28591
+ * which new parts don't take
27013
28592
  */
27014
28593
  constructor(contentTypes, existingPaths = /* @__PURE__ */ new Set()) {
27015
28594
  _defineProperty(this, "contentTypes", void 0);
@@ -27308,6 +28887,7 @@ var SettingsAttributes = class extends XmlAttributeComponent {
27308
28887
  * ```xml
27309
28888
  * <xsd:complexType name="CT_Settings">
27310
28889
  * <xsd:sequence>
28890
+ * <xsd:element name="embedTrueTypeFonts" type="CT_OnOff" minOccurs="0"/>
27311
28891
  * <xsd:element name="trackRevisions" type="CT_OnOff" minOccurs="0"/>
27312
28892
  * <xsd:element name="defaultTabStop" type="CT_TwipsMeasure" minOccurs="0"/>
27313
28893
  * <xsd:element name="autoHyphenation" type="CT_OnOff" minOccurs="0"/>
@@ -27366,6 +28946,7 @@ var Settings = class extends XmlComponent {
27366
28946
  Ignorable: "w14 w15 wp14"
27367
28947
  }));
27368
28948
  this.root.push(new OnOffElement("w:displayBackgroundShape", true));
28949
+ if (options.embedFonts !== void 0) this.root.push(new OnOffElement("w:embedTrueTypeFonts", options.embedFonts));
27369
28950
  if (options.trackRevisions !== void 0) this.root.push(new OnOffElement("w:trackRevisions", options.trackRevisions));
27370
28951
  if (options.defaultTabStop !== void 0) this.root.push(new NumberValueElement("w:defaultTabStop", options.defaultTabStop));
27371
28952
  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));
@@ -27954,6 +29535,39 @@ var HyperlinkStyle = class extends StyleForCharacter {
27954
29535
  }, options));
27955
29536
  }
27956
29537
  };
29538
+ /**
29539
+ * Represents the Normal Table style, the default style of tables.
29540
+ *
29541
+ * It gives cells the margins Word gives the tables it makes: 108 twips (0.075 inches) on the left and right. Without a
29542
+ * default table style, Word gives cells no margins, so their text touches the borders, where LibreOffice and other
29543
+ * applications use these margins.
29544
+ */
29545
+ var NormalTableStyle = class extends Style {
29546
+ constructor() {
29547
+ super({
29548
+ type: "table",
29549
+ styleId: "TableNormal",
29550
+ default: true
29551
+ }, {
29552
+ name: "Normal Table",
29553
+ uiPriority: 99,
29554
+ semiHidden: true,
29555
+ unhideWhenUsed: true
29556
+ });
29557
+ this.root.push(new TableProperties({
29558
+ indent: {
29559
+ size: 0,
29560
+ type: WidthType.DXA
29561
+ },
29562
+ cellMargin: {
29563
+ top: 0,
29564
+ left: 108,
29565
+ bottom: 0,
29566
+ right: 108
29567
+ }
29568
+ }));
29569
+ }
29570
+ };
27957
29571
  //#endregion
27958
29572
  //#region src/file/styles/styles.ts
27959
29573
  /** The name of a formatted element, such as `w:style`, or `_attr` for its parent's attributes */
@@ -28246,6 +29860,7 @@ var createDefaultStyles = (options = {}) => {
28246
29860
  name: "Normal",
28247
29861
  quickFormat: true
28248
29862
  }),
29863
+ normalTable: new NormalTableStyle(),
28249
29864
  document: new DocumentDefaults((_options$document = options.document) !== null && _options$document !== void 0 ? _options$document : {}),
28250
29865
  title: new TitleStyle(_objectSpread2({ run: { size: 56 } }, options.title)),
28251
29866
  heading1: new Heading1Style(_objectSpread2({ run: {
@@ -28920,7 +30535,7 @@ var Theme = class extends XmlComponent {
28920
30535
  */
28921
30536
  var File = class {
28922
30537
  constructor(options) {
28923
- 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;
30538
+ 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;
28924
30539
  _defineProperty(this, "currentRelationshipId", 1);
28925
30540
  _defineProperty(this, "documentWrapper", void 0);
28926
30541
  _defineProperty(this, "headers", []);
@@ -28968,13 +30583,17 @@ var File = class {
28968
30583
  this.endnotesWrapper = new EndnotesWrapper();
28969
30584
  this.contentTypes = new ContentTypes();
28970
30585
  this.packageParts = new PackageParts(this.contentTypes);
28971
- this.documentWrapper = new DocumentWrapper({ background: options.background });
30586
+ this.documentWrapper = new DocumentWrapper({
30587
+ background: options.background,
30588
+ pageNumbers: options.pageNumbers
30589
+ });
28972
30590
  this.settings = new Settings({
28973
30591
  compatibilityModeVersion: options.compatabilityModeVersion,
28974
30592
  compatibility: options.compatibility,
28975
30593
  evenAndOddHeaders: options.evenAndOddHeaderAndFooters ? true : false,
28976
30594
  trackRevisions: (_options$features = options.features) === null || _options$features === void 0 ? void 0 : _options$features.trackRevisions,
28977
30595
  updateFields: (_options$features2 = options.features) === null || _options$features2 === void 0 ? void 0 : _options$features2.updateFields,
30596
+ embedFonts: ((_options$fonts = options.fonts) === null || _options$fonts === void 0 ? void 0 : _options$fonts.length) ? true : void 0,
28978
30597
  defaultTabStop: options.defaultTabStop,
28979
30598
  hyphenation: {
28980
30599
  autoHyphenation: (_options$hyphenation = options.hyphenation) === null || _options$hyphenation === void 0 ? void 0 : _options$hyphenation.autoHyphenation,
@@ -28985,16 +30604,20 @@ var File = class {
28985
30604
  });
28986
30605
  this.media = new Media();
28987
30606
  if (options.externalStyles !== void 0) {
28988
- var _options$styles$defau, _options$styles;
30607
+ var _options$styles$defau, _options$styles, _options$styles2, _options$styles3;
28989
30608
  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 : {};
28990
30609
  const defaultStyles = Object.entries(createDefaultStyles(given));
28991
30610
  const isGiven = ([key]) => given[key] !== void 0;
28992
30611
  const externalStyles = new ExternalStylesFactory().newInstance(options.externalStyles);
28993
- this.styles = new Styles(_objectSpread2(_objectSpread2({}, externalStyles), {}, { importedStyles: [
28994
- ...defaultStyles.filter((entry) => !isGiven(entry)).map(([, style]) => style),
28995
- ...externalStyles.importedStyles,
28996
- ...defaultStyles.filter(isGiven).map(([, style]) => style)
28997
- ] }));
30612
+ this.styles = new Styles(_objectSpread2(_objectSpread2({}, externalStyles), {}, {
30613
+ paragraphStyles: (_options$styles2 = options.styles) === null || _options$styles2 === void 0 ? void 0 : _options$styles2.paragraphStyles,
30614
+ characterStyles: (_options$styles3 = options.styles) === null || _options$styles3 === void 0 ? void 0 : _options$styles3.characterStyles,
30615
+ importedStyles: [
30616
+ ...defaultStyles.filter((entry) => !isGiven(entry)).map(([, style]) => style),
30617
+ ...externalStyles.importedStyles,
30618
+ ...defaultStyles.filter(isGiven).map(([, style]) => style)
30619
+ ]
30620
+ }));
28998
30621
  } else if (options.styles) {
28999
30622
  const defaultStyles = new DefaultStylesFactory().newInstance(options.styles.default);
29000
30623
  this.styles = new Styles(_objectSpread2(_objectSpread2({}, defaultStyles), options.styles));
@@ -29006,7 +30629,7 @@ var File = class {
29006
30629
  for (const section of options.sections) this.addSection(section);
29007
30630
  if (options.footnotes) for (const key in options.footnotes) this.footnotesWrapper.View.createFootNote(parseFloat(key), options.footnotes[key].children);
29008
30631
  if (options.endnotes) for (const key in options.endnotes) this.endnotesWrapper.View.createEndnote(parseFloat(key), options.endnotes[key].children);
29009
- this.fontWrapper = new FontWrapper((_options$fonts = options.fonts) !== null && _options$fonts !== void 0 ? _options$fonts : []);
30632
+ this.fontWrapper = new FontWrapper((_options$fonts2 = options.fonts) !== null && _options$fonts2 !== void 0 ? _options$fonts2 : []);
29010
30633
  this.theme = new Theme(options.theme);
29011
30634
  this.documentWrapper.Relationships.addRelationship(this.currentRelationshipId++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme", "theme/theme1.xml");
29012
30635
  }
@@ -29142,113 +30765,6 @@ var File = class {
29142
30765
  }
29143
30766
  };
29144
30767
  //#endregion
29145
- //#region src/file/table-of-contents/field-instruction.ts
29146
- /**
29147
- * Field Instruction module for Table of Contents.
29148
- *
29149
- * This module handles the generation of TOC field instruction text
29150
- * that controls how the table of contents is built.
29151
- *
29152
- * Reference: http://officeopenxml.com/WPfieldInstructions.php
29153
- *
29154
- * @module
29155
- */
29156
- /**
29157
- * Represents a field instruction for a Table of Contents.
29158
- *
29159
- * The FieldInstruction class generates the TOC field code string that Word uses
29160
- * to determine how to build the table of contents, including which headings to include,
29161
- * formatting options, and other TOC-specific settings.
29162
- *
29163
- * Reference: http://officeopenxml.com/WPfieldInstructions.php
29164
- *
29165
- * ## XSD Schema
29166
- * ```xml
29167
- * <xsd:element name="instrText" type="CT_Text"/>
29168
- * ```
29169
- *
29170
- * @example
29171
- * ```typescript
29172
- * // Basic TOC field instruction
29173
- * new FieldInstruction({ headingStyleRange: "1-3" });
29174
- *
29175
- * // TOC with hyperlinks and custom styles
29176
- * new FieldInstruction({
29177
- * hyperlink: true,
29178
- * headingStyleRange: "1-3",
29179
- * stylesWithLevels: [new StyleLevel("CustomStyle", 2)],
29180
- * });
29181
- * ```
29182
- */
29183
- var FieldInstruction = class extends XmlComponent {
29184
- constructor(properties = {}) {
29185
- super("w:instrText");
29186
- _defineProperty(this, "properties", void 0);
29187
- this.properties = properties;
29188
- this.root.push(new TextAttributes({ space: SpaceType.PRESERVE }));
29189
- let instruction = "TOC";
29190
- if (this.properties.captionLabel) instruction = `${instruction} \\a "${this.properties.captionLabel}"`;
29191
- if (this.properties.entriesFromBookmark) instruction = `${instruction} \\b "${this.properties.entriesFromBookmark}"`;
29192
- if (this.properties.captionLabelIncludingNumbers) instruction = `${instruction} \\c "${this.properties.captionLabelIncludingNumbers}"`;
29193
- if (this.properties.sequenceAndPageNumbersSeparator) instruction = `${instruction} \\d "${this.properties.sequenceAndPageNumbersSeparator}"`;
29194
- if (this.properties.tcFieldIdentifier) instruction = `${instruction} \\f "${this.properties.tcFieldIdentifier}"`;
29195
- if (this.properties.hyperlink) instruction = `${instruction} \\h`;
29196
- if (this.properties.tcFieldLevelRange) instruction = `${instruction} \\l "${this.properties.tcFieldLevelRange}"`;
29197
- if (this.properties.pageNumbersEntryLevelsRange) instruction = `${instruction} \\n "${this.properties.pageNumbersEntryLevelsRange}"`;
29198
- if (this.properties.headingStyleRange) instruction = `${instruction} \\o "${this.properties.headingStyleRange}"`;
29199
- if (this.properties.entryAndPageNumberSeparator) instruction = `${instruction} \\p "${this.properties.entryAndPageNumberSeparator}"`;
29200
- if (this.properties.seqFieldIdentifierForPrefix) instruction = `${instruction} \\s "${this.properties.seqFieldIdentifierForPrefix}"`;
29201
- if (this.properties.stylesWithLevels && this.properties.stylesWithLevels.length) {
29202
- const styles = this.properties.stylesWithLevels.map((sl) => `${sl.styleName},${sl.level}`).join(",");
29203
- instruction = `${instruction} \\t "${styles}"`;
29204
- }
29205
- if (this.properties.useAppliedParagraphOutlineLevel) instruction = `${instruction} \\u`;
29206
- if (this.properties.preserveTabInEntries) instruction = `${instruction} \\w`;
29207
- if (this.properties.preserveNewLineInEntries) instruction = `${instruction} \\x`;
29208
- if (this.properties.hideTabAndPageNumbersInWebView) instruction = `${instruction} \\z`;
29209
- this.root.push(instruction);
29210
- }
29211
- };
29212
- //#endregion
29213
- //#region src/file/table-of-contents/sdt-content.ts
29214
- /**
29215
- * Structured Document Tag Content module.
29216
- *
29217
- * This module represents the content container for structured document tags,
29218
- * including table of contents elements.
29219
- *
29220
- * Reference: http://officeopenxml.com/WPtableOfContents.php
29221
- *
29222
- * @module
29223
- */
29224
- /**
29225
- * Represents the content portion of a Structured Document Tag.
29226
- *
29227
- * The StructuredDocumentTagContent contains the actual content elements
29228
- * (paragraphs, tables, etc.) within a structured document tag, such as
29229
- * the paragraphs that make up a table of contents.
29230
- *
29231
- * Reference: http://officeopenxml.com/WPtableOfContents.php
29232
- *
29233
- * ## XSD Schema
29234
- * ```xml
29235
- * <xsd:complexType name="CT_SdtContentBlock">
29236
- * <xsd:group ref="EG_ContentBlockContent" minOccurs="0" maxOccurs="unbounded"/>
29237
- * </xsd:complexType>
29238
- * ```
29239
- *
29240
- * @example
29241
- * ```typescript
29242
- * const content = new StructuredDocumentTagContent();
29243
- * content.addChildElement(new Paragraph("Content"));
29244
- * ```
29245
- */
29246
- var StructuredDocumentTagContent = class extends XmlComponent {
29247
- constructor() {
29248
- super("w:sdtContent");
29249
- }
29250
- };
29251
- //#endregion
29252
30768
  //#region src/file/table-of-contents/sdt-properties.ts
29253
30769
  /**
29254
30770
  * Structured Document Tag Properties module.
@@ -29306,28 +30822,6 @@ var StructuredDocumentTagProperties = class extends XmlComponent {
29306
30822
  }
29307
30823
  };
29308
30824
  //#endregion
29309
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/objectWithoutPropertiesLoose.js
29310
- function _objectWithoutPropertiesLoose(r, e) {
29311
- if (null == r) return {};
29312
- var t = {};
29313
- for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
29314
- if (e.includes(n)) continue;
29315
- t[n] = r[n];
29316
- }
29317
- return t;
29318
- }
29319
- //#endregion
29320
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/objectWithoutProperties.js
29321
- function _objectWithoutProperties(e, t) {
29322
- if (null == e) return {};
29323
- var o, r, i = _objectWithoutPropertiesLoose(e, t);
29324
- if (Object.getOwnPropertySymbols) {
29325
- var s = Object.getOwnPropertySymbols(e);
29326
- for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
29327
- }
29328
- return i;
29329
- }
29330
- //#endregion
29331
30825
  //#region src/file/table-of-contents/table-of-contents.ts
29332
30826
  /**
29333
30827
  * Table of Contents module for WordprocessingML documents.
@@ -29350,6 +30844,12 @@ var _excluded$2 = [
29350
30844
  * TableOfContents creates an auto-generated list of document headings
29351
30845
  * with page numbers. It uses a TOC field code to generate entries.
29352
30846
  *
30847
+ * Unless it is given `cachedEntries` or `contentChildren`, it is written with an
30848
+ * entry for each heading its options include, linked to a bookmark on the heading,
30849
+ * so it isn't empty before Word updates it or in applications that don't update it.
30850
+ * The page numbers are left for Word to fill in when it updates the field, unless the document's `pageNumbers`
30851
+ * writes them.
30852
+ *
29353
30853
  * Reference: http://officeopenxml.com/WPtableOfContents.php
29354
30854
  *
29355
30855
  * @publicApi
@@ -29375,12 +30875,18 @@ var _excluded$2 = [
29375
30875
  */
29376
30876
  var TableOfContents = class extends FileChild {
29377
30877
  constructor(alias = "Table of Contents", _ref = {}) {
29378
- let { contentChildren = [], cachedEntries = [], beginDirty = true } = _ref, properties = _objectWithoutProperties(_ref, _excluded$2);
30878
+ let { contentChildren = [], cachedEntries = [], beginDirty } = _ref, properties = _objectWithoutProperties(_ref, _excluded$2);
29379
30879
  super("w:sdt");
30880
+ _defineProperty(
30881
+ this,
30882
+ /** What it is filled in with from the headings, when it isn't given its content */
30883
+ "fromHeadings",
30884
+ void 0
30885
+ );
29380
30886
  this.root.push(new StructuredDocumentTagProperties(alias));
29381
30887
  const content = new StructuredDocumentTagContent();
29382
30888
  const beginParagraphMandatoryChildren = [new Run({ children: [
29383
- createBegin(beginDirty),
30889
+ beginOf(beginDirty),
29384
30890
  new FieldInstruction(properties),
29385
30891
  createSeparate()
29386
30892
  ] })];
@@ -29407,9 +30913,27 @@ var TableOfContents = class extends FileChild {
29407
30913
  for (const child of contentChildren) content.addChildElement(child);
29408
30914
  const endParagraph = new Paragraph({ children: endParagraphMandatoryChildren });
29409
30915
  content.addChildElement(endParagraph);
30916
+ if (contentChildren.length === 0) this.fromHeadings = {
30917
+ properties,
30918
+ beginDirty
30919
+ };
29410
30920
  }
29411
30921
  this.root.push(content);
29412
30922
  }
30923
+ /**
30924
+ * Written empty, and filled in from the headings once the body it is in is written, unless it was given its content.
30925
+ * The page numbers are aligned to the right of the text in its section.
30926
+ */
30927
+ prepForXml(context) {
30928
+ const xml = super.prepForXml(context);
30929
+ recordTableOfContents(xml, this.fromHeadings && _objectSpread2(_objectSpread2({}, this.fromHeadings), {}, { textWidth: this.textWidthIn(context) }));
30930
+ return xml;
30931
+ }
30932
+ /** The width of the text in the section it is in */
30933
+ textWidthIn(context) {
30934
+ var _context$file$Documen, _context$file;
30935
+ 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;
30936
+ }
29413
30937
  getTabStopsForLevel(level, pageWidth = 9025) {
29414
30938
  return [{
29415
30939
  type: "clear",
@@ -33823,11 +35347,11 @@ var NumberingReplacer = class {
33823
35347
  *
33824
35348
  * @module
33825
35349
  */
33826
- var formatter$2 = new Formatter();
35350
+ var formatter$3 = new Formatter();
33827
35351
  /**
33828
35352
  * Formats a part's XML, with the relationships that anything in it that refers to other parts adds to.
33829
35353
  */
33830
- var xmlifyPart = (file, content, prettify, relationships, standalone = true) => (0, import_xml.default)(formatter$2.format(content, {
35354
+ var xmlifyPart = (file, content, prettify, relationships, standalone = true) => (0, import_xml.default)(formatter$3.format(content, {
33831
35355
  viewWrapper: {
33832
35356
  View: content,
33833
35357
  Relationships: relationships
@@ -33948,7 +35472,6 @@ var Compiler = class {
33948
35472
  return zip;
33949
35473
  }
33950
35474
  xmlifyFile(file, prettify) {
33951
- const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1;
33952
35475
  const documentXmlData = (0, import_xml.default)(this.formatter.format(file.Document.View, {
33953
35476
  viewWrapper: file.Document,
33954
35477
  file,
@@ -33960,7 +35483,6 @@ var Compiler = class {
33960
35483
  encoding: "UTF-8"
33961
35484
  }
33962
35485
  });
33963
- const commentRelationshipCount = file.Comments.Relationships.RelationshipCount + 1;
33964
35486
  const commentXmlData = (0, import_xml.default)(this.formatter.format(file.Comments, {
33965
35487
  viewWrapper: {
33966
35488
  View: file.Comments,
@@ -33975,7 +35497,6 @@ var Compiler = class {
33975
35497
  encoding: "UTF-8"
33976
35498
  }
33977
35499
  });
33978
- const footnoteRelationshipCount = file.FootNotes.Relationships.RelationshipCount + 1;
33979
35500
  const footnoteXmlData = (0, import_xml.default)(this.formatter.format(file.FootNotes.View, {
33980
35501
  viewWrapper: file.FootNotes,
33981
35502
  file,
@@ -33987,17 +35508,31 @@ var Compiler = class {
33987
35508
  encoding: "UTF-8"
33988
35509
  }
33989
35510
  });
35511
+ const endnoteXmlData = (0, import_xml.default)(this.formatter.format(file.Endnotes.View, {
35512
+ viewWrapper: file.Endnotes,
35513
+ file,
35514
+ stack: []
35515
+ }), {
35516
+ indent: prettify,
35517
+ declaration: { encoding: "UTF-8" }
35518
+ });
35519
+ const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1;
35520
+ const commentRelationshipCount = file.Comments.Relationships.RelationshipCount + 1;
35521
+ const footnoteRelationshipCount = file.FootNotes.Relationships.RelationshipCount + 1;
35522
+ const endnoteRelationshipCount = file.Endnotes.Relationships.RelationshipCount + 1;
33990
35523
  const documentMediaDatas = this.imageReplacer.getMediaData(documentXmlData, file.Media);
33991
35524
  const commentMediaDatas = this.imageReplacer.getMediaData(commentXmlData, file.Media);
33992
35525
  const footnoteMediaDatas = this.imageReplacer.getMediaData(footnoteXmlData, file.Media);
35526
+ const endnoteMediaDatas = this.imageReplacer.getMediaData(endnoteXmlData, file.Media);
33993
35527
  return _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({
33994
35528
  Relationships: {
33995
35529
  data: (() => {
35530
+ const relationships = Relationships.copy(file.Document.Relationships);
33996
35531
  documentMediaDatas.forEach((mediaData, i) => {
33997
- file.Document.Relationships.addRelationship(documentRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35532
+ relationships.addRelationship(documentRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
33998
35533
  });
33999
- file.Document.Relationships.addRelationship(file.Document.Relationships.RelationshipCount + 1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable", "fontTable.xml");
34000
- return (0, import_xml.default)(this.formatter.format(file.Document.Relationships, {
35534
+ relationships.addRelationship(relationships.RelationshipCount + 1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable", "fontTable.xml");
35535
+ return (0, import_xml.default)(this.formatter.format(relationships, {
34001
35536
  viewWrapper: file.Document,
34002
35537
  file,
34003
35538
  stack: []
@@ -34046,20 +35581,6 @@ var Compiler = class {
34046
35581
  }),
34047
35582
  path: "docProps/core.xml"
34048
35583
  },
34049
- Numbering: {
34050
- data: (0, import_xml.default)(this.formatter.format(file.Numbering, {
34051
- viewWrapper: file.Document,
34052
- file,
34053
- stack: []
34054
- }), {
34055
- indent: prettify,
34056
- declaration: {
34057
- standalone: "yes",
34058
- encoding: "UTF-8"
34059
- }
34060
- }),
34061
- path: "word/numbering.xml"
34062
- },
34063
35584
  FileRelationships: {
34064
35585
  data: (0, import_xml.default)(this.formatter.format(file.FileRelationships, {
34065
35586
  viewWrapper: file.Document,
@@ -34080,11 +35601,13 @@ var Compiler = class {
34080
35601
  indent: prettify,
34081
35602
  declaration: { encoding: "UTF-8" }
34082
35603
  });
34083
- this.imageReplacer.getMediaData(xmlData, file.Media).forEach((mediaData, i) => {
34084
- headerWrapper.Relationships.addRelationship(i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35604
+ const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
35605
+ const relationships = Relationships.copy(headerWrapper.Relationships);
35606
+ mediaDatas.forEach((mediaData, i) => {
35607
+ relationships.addRelationship(i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
34085
35608
  });
34086
35609
  return {
34087
- data: (0, import_xml.default)(this.formatter.format(headerWrapper.Relationships, {
35610
+ data: (0, import_xml.default)(this.formatter.format(relationships, {
34088
35611
  viewWrapper: headerWrapper,
34089
35612
  file,
34090
35613
  stack: []
@@ -34104,11 +35627,13 @@ var Compiler = class {
34104
35627
  indent: prettify,
34105
35628
  declaration: { encoding: "UTF-8" }
34106
35629
  });
34107
- this.imageReplacer.getMediaData(xmlData, file.Media).forEach((mediaData, i) => {
34108
- footerWrapper.Relationships.addRelationship(i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35630
+ const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
35631
+ const relationships = Relationships.copy(footerWrapper.Relationships);
35632
+ mediaDatas.forEach((mediaData, i) => {
35633
+ relationships.addRelationship(i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
34109
35634
  });
34110
35635
  return {
34111
- data: (0, import_xml.default)(this.formatter.format(footerWrapper.Relationships, {
35636
+ data: (0, import_xml.default)(this.formatter.format(relationships, {
34112
35637
  viewWrapper: footerWrapper,
34113
35638
  file,
34114
35639
  stack: []
@@ -34188,10 +35713,11 @@ var Compiler = class {
34188
35713
  },
34189
35714
  FootNotesRelationships: {
34190
35715
  data: (() => {
35716
+ const relationships = Relationships.copy(file.FootNotes.Relationships);
34191
35717
  footnoteMediaDatas.forEach((mediaData, i) => {
34192
- file.FootNotes.Relationships.addRelationship(footnoteRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35718
+ relationships.addRelationship(footnoteRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
34193
35719
  });
34194
- return (0, import_xml.default)(this.formatter.format(file.FootNotes.Relationships, {
35720
+ return (0, import_xml.default)(this.formatter.format(relationships, {
34195
35721
  viewWrapper: file.FootNotes,
34196
35722
  file,
34197
35723
  stack: []
@@ -34203,25 +35729,27 @@ var Compiler = class {
34203
35729
  path: "word/_rels/footnotes.xml.rels"
34204
35730
  },
34205
35731
  Endnotes: {
34206
- data: (0, import_xml.default)(this.formatter.format(file.Endnotes.View, {
34207
- viewWrapper: file.Endnotes,
34208
- file,
34209
- stack: []
34210
- }), {
34211
- indent: prettify,
34212
- declaration: { encoding: "UTF-8" }
34213
- }),
35732
+ data: (() => {
35733
+ const xmlData = this.imageReplacer.replace(endnoteXmlData, endnoteMediaDatas, endnoteRelationshipCount);
35734
+ return this.numberingReplacer.replace(xmlData, file.Numbering.ConcreteNumbering);
35735
+ })(),
34214
35736
  path: "word/endnotes.xml"
34215
35737
  },
34216
35738
  EndnotesRelationships: {
34217
- data: (0, import_xml.default)(this.formatter.format(file.Endnotes.Relationships, {
34218
- viewWrapper: file.Endnotes,
34219
- file,
34220
- stack: []
34221
- }), {
34222
- indent: prettify,
34223
- declaration: { encoding: "UTF-8" }
34224
- }),
35739
+ data: (() => {
35740
+ const relationships = Relationships.copy(file.Endnotes.Relationships);
35741
+ endnoteMediaDatas.forEach((mediaData, i) => {
35742
+ relationships.addRelationship(endnoteRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35743
+ });
35744
+ return (0, import_xml.default)(this.formatter.format(relationships, {
35745
+ viewWrapper: file.Endnotes,
35746
+ file,
35747
+ stack: []
35748
+ }), {
35749
+ indent: prettify,
35750
+ declaration: { encoding: "UTF-8" }
35751
+ });
35752
+ })(),
34225
35753
  path: "word/_rels/endnotes.xml.rels"
34226
35754
  },
34227
35755
  Settings: {
@@ -34248,10 +35776,11 @@ var Compiler = class {
34248
35776
  },
34249
35777
  CommentsRelationships: {
34250
35778
  data: (() => {
35779
+ const relationships = Relationships.copy(file.Comments.Relationships);
34251
35780
  commentMediaDatas.forEach((mediaData, i) => {
34252
- file.Comments.Relationships.addRelationship(commentRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
35781
+ relationships.addRelationship(commentRelationshipCount + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`);
34253
35782
  });
34254
- return (0, import_xml.default)(this.formatter.format(file.Comments.Relationships, {
35783
+ return (0, import_xml.default)(this.formatter.format(relationships, {
34255
35784
  viewWrapper: {
34256
35785
  View: file.Comments,
34257
35786
  Relationships: file.Comments.Relationships
@@ -34338,6 +35867,20 @@ var Compiler = class {
34338
35867
  path: "word/theme/theme1.xml"
34339
35868
  },
34340
35869
  PackageParts: xmlifyPackageParts(file, prettify),
35870
+ Numbering: {
35871
+ data: (0, import_xml.default)(this.formatter.format(file.Numbering, {
35872
+ viewWrapper: file.Document,
35873
+ file,
35874
+ stack: []
35875
+ }), {
35876
+ indent: prettify,
35877
+ declaration: {
35878
+ standalone: "yes",
35879
+ encoding: "UTF-8"
35880
+ }
35881
+ }),
35882
+ path: "word/numbering.xml"
35883
+ },
34341
35884
  ContentTypes: {
34342
35885
  data: (0, import_xml.default)(this.formatter.format(file.ContentTypes, {
34343
35886
  viewWrapper: file.Document,
@@ -34353,7 +35896,7 @@ var Compiler = class {
34353
35896
  }
34354
35897
  };
34355
35898
  //#endregion
34356
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/asyncToGenerator.js
35899
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/asyncToGenerator.js
34357
35900
  function asyncGeneratorStep(n, t, e, r, o, a, c) {
34358
35901
  try {
34359
35902
  var i = n[a](c), u = i.value;
@@ -34523,13 +36066,62 @@ var Packer = class Packer {
34523
36066
  };
34524
36067
  _defineProperty(Packer, "compiler", new Compiler());
34525
36068
  //#endregion
36069
+ //#region src/patcher/bookmark-ids.ts
36070
+ var bookmarkIdOf = (element) => {
36071
+ var _element$attributes;
36072
+ if (element.name !== "w:bookmarkStart" && element.name !== "w:bookmarkEnd") return;
36073
+ const id = Number((_element$attributes = element.attributes) === null || _element$attributes === void 0 ? void 0 : _element$attributes["w:id"]);
36074
+ return Number.isInteger(id) ? id : void 0;
36075
+ };
36076
+ /**
36077
+ * Finds the id of every bookmark in an element, at any depth.
36078
+ *
36079
+ * @param element - The element to search, such as a part's root
36080
+ * @returns The ids, once for each bookmarkStart and bookmarkEnd
36081
+ */
36082
+ var findBookmarkIds = (element) => {
36083
+ var _element$elements;
36084
+ const id = bookmarkIdOf(element);
36085
+ return [...id === void 0 ? [] : [id], ...((_element$elements = element.elements) !== null && _element$elements !== void 0 ? _element$elements : []).flatMap(findBookmarkIds)];
36086
+ };
36087
+ /**
36088
+ * Creates a function that renumbers the bookmarks in content being inserted, so none takes an id the document
36089
+ * already uses. Bookmark ids must be unique within a document, but a bookmark's id is chosen when it is created,
36090
+ * without knowing which ids the template has.
36091
+ *
36092
+ * A bookmark keeps its id if nothing in the document uses it yet, and otherwise gets the next unused one. An id is
36093
+ * renumbered the same way each time, so a bookmark's start and end still share one, even in separate patches.
36094
+ *
36095
+ * @param idsInDocument - The ids of the bookmarks already in the document
36096
+ * @returns A function that returns the elements with their bookmarks renumbered
36097
+ */
36098
+ var renumberBookmarksAvoiding = (idsInDocument) => {
36099
+ const usedIds = new Set(idsInDocument);
36100
+ const newIds = /* @__PURE__ */ new Map();
36101
+ let highestId = idsInDocument.reduce((highest, id) => Math.max(highest, id), 0);
36102
+ const newIdFor = (id) => {
36103
+ const knownId = newIds.get(id);
36104
+ if (knownId !== void 0) return knownId;
36105
+ const newId = usedIds.has(id) ? highestId + 1 : id;
36106
+ highestId = Math.max(highestId, newId);
36107
+ usedIds.add(newId);
36108
+ newIds.set(id, newId);
36109
+ return newId;
36110
+ };
36111
+ const renumber = (element) => {
36112
+ const id = bookmarkIdOf(element);
36113
+ 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) });
36114
+ };
36115
+ return (elements) => elements.map(renumber);
36116
+ };
36117
+ //#endregion
34526
36118
  //#region src/patcher/util.ts
34527
36119
  /**
34528
36120
  * Utility functions for XML manipulation in document patching.
34529
36121
  *
34530
36122
  * @module
34531
36123
  */
34532
- var formatter$1 = new Formatter();
36124
+ var formatter$2 = new Formatter();
34533
36125
  /**
34534
36126
  * Converts XML string to JSON element structure.
34535
36127
  *
@@ -34569,7 +36161,7 @@ var toJson = (xmlData) => {
34569
36161
  */
34570
36162
  var createTextElementContents = (text) => {
34571
36163
  var _textJson$elements$0$;
34572
- 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$ : [];
36164
+ 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$ : [];
34573
36165
  };
34574
36166
  /**
34575
36167
  * Adds xml:space="preserve" attribute to an element.
@@ -34704,6 +36296,11 @@ var PatchType = {
34704
36296
  /** Replace content within paragraphs (inline replacement) */
34705
36297
  PARAGRAPH: "paragraph",
34706
36298
  /**
36299
+ * Repeat the rows of a table that hold the placeholder's fields, such as `{{items.name}}`, once for each row of
36300
+ * data. See {@link TableRowsPatch}
36301
+ */
36302
+ TABLE_ROWS: "tableRows",
36303
+ /**
34707
36304
  * Change a drawing whose alt text holds the placeholder, and the parts it refers to, such as the data of a chart made
34708
36305
  * in Word. See {@link DrawingPatch}
34709
36306
  */
@@ -35017,6 +36614,291 @@ var patchDrawings = ({ parts, binaryParts, file, patches, delimiters }, createCo
35017
36614
  for (const { drawing, patch } of found) patch.patch(drawing, createTemplatePackage(parts, binaryParts, file, createContext(drawing.part.path)));
35018
36615
  };
35019
36616
  //#endregion
36617
+ //#region src/patcher/notes.ts
36618
+ /**
36619
+ * Footnotes and endnotes for content inserted into an existing document.
36620
+ *
36621
+ * @module
36622
+ */
36623
+ var formatter$1 = new Formatter();
36624
+ var DOCUMENT_PATH = "word/document.xml";
36625
+ var FOOTNOTES = {
36626
+ path: "word/footnotes.xml",
36627
+ rootName: "w:footnotes",
36628
+ noteName: "w:footnote",
36629
+ referenceName: "w:footnoteReference",
36630
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml",
36631
+ relationshipType: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",
36632
+ create: {
36633
+ part: () => new FootNotes(),
36634
+ mark: () => new FootnoteRefRun(),
36635
+ styles: () => [
36636
+ new FootnoteText({}),
36637
+ new FootnoteTextChar({}),
36638
+ new FootnoteReferenceStyle({})
36639
+ ]
36640
+ }
36641
+ };
36642
+ var ENDNOTES = {
36643
+ path: "word/endnotes.xml",
36644
+ rootName: "w:endnotes",
36645
+ noteName: "w:endnote",
36646
+ referenceName: "w:endnoteReference",
36647
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml",
36648
+ relationshipType: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes",
36649
+ create: {
36650
+ part: () => new Endnotes(),
36651
+ mark: () => new EndnoteRefRun(),
36652
+ styles: () => [
36653
+ new EndnoteText({}),
36654
+ new EndnoteTextChar({}),
36655
+ new EndnoteReferenceStyle({})
36656
+ ]
36657
+ }
36658
+ };
36659
+ var formatElement = (component, context) => toJson((0, import_xml.default)(formatter$1.format(component, context))).elements[0];
36660
+ var findIds = (element, names) => {
36661
+ var _element$name, _element$attributes, _element$elements;
36662
+ 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;
36663
+ return [...Number.isInteger(id) ? [id] : [], ...((_element$elements = element.elements) !== null && _element$elements !== void 0 ? _element$elements : []).flatMap((child) => findIds(child, names))];
36664
+ };
36665
+ var withMark = (paragraph, mark) => {
36666
+ var _paragraph$elements, _elements$;
36667
+ const elements = (_paragraph$elements = paragraph.elements) !== null && _paragraph$elements !== void 0 ? _paragraph$elements : [];
36668
+ const index = ((_elements$ = elements[0]) === null || _elements$ === void 0 ? void 0 : _elements$.name) === "w:pPr" ? 1 : 0;
36669
+ return _objectSpread2(_objectSpread2({}, paragraph), {}, { elements: [
36670
+ ...elements.slice(0, index),
36671
+ mark,
36672
+ ...elements.slice(index)
36673
+ ] });
36674
+ };
36675
+ var patchNotesOfKind = (kind, notes, parts, { createContext, addContentTypeOverride, renumberBookmarks }) => {
36676
+ const givenNotes = new Map(Object.entries(notes).map(([id, note]) => [Number(id), note]));
36677
+ const noteOfId = /* @__PURE__ */ new Map();
36678
+ let highestId;
36679
+ const renumber = (element) => {
36680
+ var _element$attributes2, _highestId;
36681
+ 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;
36682
+ if (note === void 0) return element.elements === void 0 ? element : _objectSpread2(_objectSpread2({}, element), {}, { elements: element.elements.map(renumber) });
36683
+ 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;
36684
+ noteOfId.set(highestId, note);
36685
+ return _objectSpread2(_objectSpread2({}, element), {}, { attributes: _objectSpread2(_objectSpread2({}, element.attributes), {}, { "w:id": String(highestId) }) });
36686
+ };
36687
+ const findOrAddPart = () => {
36688
+ var _parts$get;
36689
+ const relationship = getFirstLevelElements((_parts$get = parts.get(relationshipsPathOf(DOCUMENT_PATH))) !== null && _parts$get !== void 0 ? _parts$get : {}, "Relationships").find((element) => {
36690
+ var _element$attributes3;
36691
+ return ((_element$attributes3 = element.attributes) === null || _element$attributes3 === void 0 ? void 0 : _element$attributes3.Type) === kind.relationshipType;
36692
+ });
36693
+ const path = relationship ? resolveTarget(DOCUMENT_PATH, String(relationship.attributes.Target)) : kind.path;
36694
+ if (!parts.has(path)) {
36695
+ parts.set(path, {
36696
+ declaration: { attributes: {
36697
+ version: "1.0",
36698
+ encoding: "UTF-8",
36699
+ standalone: "yes"
36700
+ } },
36701
+ elements: [formatElement(kind.create.part(), createContext(path))]
36702
+ });
36703
+ addContentTypeOverride(kind.contentType, `/${path}`);
36704
+ }
36705
+ if (!relationship) createContext(DOCUMENT_PATH).viewWrapper.Relationships.addRelationship(uniqueId(), kind.relationshipType, relativeTarget(DOCUMENT_PATH, path));
36706
+ return path;
36707
+ };
36708
+ const write = () => {
36709
+ if (noteOfId.size === 0) return;
36710
+ const path = findOrAddPart();
36711
+ const context = createContext(path);
36712
+ const contentOfNote = new Map([...new Set(noteOfId.values())].map((note) => {
36713
+ const mark = formatElement(kind.create.mark(), context);
36714
+ return [note, renumberBookmarks(note.children.map((paragraph) => formatElement(paragraph, context)).map((paragraph, index) => index === 0 ? withMark(paragraph, mark) : paragraph))];
36715
+ }));
36716
+ getFirstLevelElements(parts.get(path), kind.rootName).push(...[...noteOfId].map(([id, note]) => ({
36717
+ type: "element",
36718
+ name: kind.noteName,
36719
+ attributes: { "w:id": String(id) },
36720
+ elements: [...contentOfNote.get(note)]
36721
+ })));
36722
+ const stylesPart = parts.get("word/styles.xml");
36723
+ if (stylesPart) {
36724
+ const styles = getFirstLevelElements(stylesPart, "w:styles");
36725
+ const styleIds = new Set(styles.map((style) => {
36726
+ var _style$attributes;
36727
+ return (_style$attributes = style.attributes) === null || _style$attributes === void 0 ? void 0 : _style$attributes["w:styleId"];
36728
+ }));
36729
+ styles.push(...kind.create.styles().map((style) => formatElement(style, context)).filter((style) => {
36730
+ var _style$attributes2;
36731
+ return !styleIds.has((_style$attributes2 = style.attributes) === null || _style$attributes2 === void 0 ? void 0 : _style$attributes2["w:styleId"]);
36732
+ }));
36733
+ }
36734
+ };
36735
+ return {
36736
+ renumber: (elements) => elements.map(renumber),
36737
+ write
36738
+ };
36739
+ };
36740
+ /**
36741
+ * Creates the writer of the footnotes and endnotes that patches refer to.
36742
+ *
36743
+ * A patch refers to a note with a reference run, such as `new FootnoteReferenceRun(1)`, whose id is the note's in
36744
+ * `footnotes`. Only references to the given notes are renumbered, and only the notes that are referred to are written.
36745
+ *
36746
+ * @param notes - The footnotes and endnotes, by the id the patches' reference runs are given
36747
+ * @param parts - The document's XML parts, parsed, by their paths, which the notes are written to
36748
+ * @param helpers - The patcher's helpers for what the notes refer to
36749
+ */
36750
+ var patchNotes = ({ footnotes = {}, endnotes = {} }, parts, helpers) => {
36751
+ const patchers = [patchNotesOfKind(FOOTNOTES, footnotes, parts, helpers), patchNotesOfKind(ENDNOTES, endnotes, parts, helpers)];
36752
+ return {
36753
+ renumber: (elements) => patchers.reduce((renumbered, patcher) => patcher.renumber(renumbered), elements),
36754
+ write: () => {
36755
+ for (const patcher of patchers) patcher.write();
36756
+ }
36757
+ };
36758
+ };
36759
+ //#endregion
36760
+ //#region src/patcher/page-numbers.ts
36761
+ /**
36762
+ * Page numbers written into a template's fields once `patchDocument` has patched it, from an estimate of its pages, as
36763
+ * a document's are when it is written with `pageNumbers`.
36764
+ *
36765
+ * @module
36766
+ */
36767
+ /** The elements of a template, as xml-js parses them */
36768
+ var PARSED = {
36769
+ nameOf: (element) => element.type === "element" ? element.name : void 0,
36770
+ contentOf: (element) => element.elements,
36771
+ attributeOf: (element, attribute) => {
36772
+ var _element$attributes;
36773
+ return (_element$attributes = element.attributes) === null || _element$attributes === void 0 ? void 0 : _element$attributes[attribute];
36774
+ },
36775
+ textOf: (element) => {
36776
+ var _element$elements;
36777
+ return ((_element$elements = element.elements) !== null && _element$elements !== void 0 ? _element$elements : []).filter(({ type }) => type === "text").map(({ text }) => String(text)).join("");
36778
+ },
36779
+ textElement: (text) => ({
36780
+ type: "element",
36781
+ name: "w:t",
36782
+ attributes: { "xml:space": "preserve" },
36783
+ elements: [{
36784
+ type: "text",
36785
+ text
36786
+ }]
36787
+ }),
36788
+ writeClean: (begin, instruction) => {
36789
+ var _begin$attributes;
36790
+ 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"));
36791
+ },
36792
+ setSimpleFieldResult: (element, text) => {
36793
+ element.elements = [{
36794
+ type: "element",
36795
+ name: "w:r",
36796
+ elements: [PARSED.textElement(text)]
36797
+ }];
36798
+ }
36799
+ };
36800
+ var DOCUMENT = "word/document.xml";
36801
+ var IMPORT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk";
36802
+ var ZIP = [
36803
+ 80,
36804
+ 75,
36805
+ 3,
36806
+ 4
36807
+ ];
36808
+ /** A package's parts, from a zip file: its XML parts parsed, as patchDocument parses a template's, and the rest as bytes */
36809
+ var readPackage = function() {
36810
+ var _ref = _asyncToGenerator(function* (data) {
36811
+ if (!ZIP.every((byte, index) => data[index] === byte)) return;
36812
+ try {
36813
+ const zip = yield import_jszip_min.default.loadAsync(data);
36814
+ const parts = /* @__PURE__ */ new Map();
36815
+ const binaryParts = /* @__PURE__ */ new Map();
36816
+ for (const [path, file] of Object.entries(zip.files)) {
36817
+ if (file.dir) continue;
36818
+ if (/\.(xml|rels)$/.test(path)) parts.set(path, toJson(yield file.async("text")));
36819
+ else binaryParts.set(path, yield file.async("uint8array"));
36820
+ }
36821
+ const importedDocuments = yield readImportedDocuments(parts, binaryParts);
36822
+ return _objectSpread2({
36823
+ parts,
36824
+ binaryParts
36825
+ }, importedDocuments.size > 0 ? { importedDocuments } : {});
36826
+ } catch (_unused) {
36827
+ return;
36828
+ }
36829
+ });
36830
+ return function readPackage(_x) {
36831
+ return _ref.apply(this, arguments);
36832
+ };
36833
+ }();
36834
+ /**
36835
+ * Each .docx the parts of a package import (`w:altChunk`), by its path: the parts the relationships of each part refer to
36836
+ * as imported, which are zip files that can be read. Those in other formats, such as HTML, are left to the layout.
36837
+ */
36838
+ var readImportedDocuments = function() {
36839
+ var _ref2 = _asyncToGenerator(function* (parts, binaryParts) {
36840
+ const imported = /* @__PURE__ */ new Map();
36841
+ for (const [path, relationships] of parts) {
36842
+ var _rootOf$elements, _rootOf;
36843
+ if (!path.endsWith(".rels")) continue;
36844
+ for (const { attributes = {} } of (_rootOf$elements = (_rootOf = rootOf(relationships)) === null || _rootOf === void 0 ? void 0 : _rootOf.elements) !== null && _rootOf$elements !== void 0 ? _rootOf$elements : []) {
36845
+ const target = resolveTarget(sourceOfRelationships(path), String(attributes.Target));
36846
+ const data = binaryParts.get(target);
36847
+ const read = attributes.Type === IMPORT && attributes.TargetMode !== "External" && data ? yield readPackage(data) : void 0;
36848
+ if (read) imported.set(target, read);
36849
+ }
36850
+ }
36851
+ return imported;
36852
+ });
36853
+ return function readImportedDocuments(_x2, _x3) {
36854
+ return _ref2.apply(this, arguments);
36855
+ };
36856
+ }();
36857
+ /** The root element of a part, such as `w:document` */
36858
+ var rootOf = (part) => {
36859
+ var _part$elements;
36860
+ return part === null || part === void 0 || (_part$elements = part.elements) === null || _part$elements === void 0 ? void 0 : _part$elements.find(({ type }) => type === "element");
36861
+ };
36862
+ /**
36863
+ * Writes the page numbers the estimator works out for a patched template into the fields of its body, headers and
36864
+ * footers that show them: its PAGEREF fields, in its tables of contents and elsewhere, and its NUMPAGES and SECTIONPAGES
36865
+ * fields. The results a field was written with are those of the template before it was patched, so a field whose number
36866
+ * the estimator doesn't work out is left blank, as it is in a document written with `pageNumbers`. Page references and
36867
+ * tables of contents are written clean, as they are in a document written with `pageNumbers`, so Word shows their numbers
36868
+ * as they are and doesn't ask to update the fields.
36869
+ *
36870
+ * The documents it imports (`w:altChunk`) as .docx files are unzipped for the estimator to read, as Word turns them into
36871
+ * paragraphs and tables of the template's own when it opens it.
36872
+ *
36873
+ * @param parts - The template's XML parts, parsed, by their paths, which are changed in place
36874
+ * @param binaryParts - Its other parts, by their paths, for the estimator to read the fonts it embeds and the documents
36875
+ * it imports
36876
+ */
36877
+ var fillTemplatePageNumbers = function() {
36878
+ var _ref3 = _asyncToGenerator(function* (parts, estimator, binaryParts = /* @__PURE__ */ new Map()) {
36879
+ var _rootOf$elements2, _rootOf2;
36880
+ const document = rootOf(parts.get(DOCUMENT));
36881
+ if (!document) return;
36882
+ const importedDocuments = yield readImportedDocuments(parts, binaryParts);
36883
+ const estimate = estimator(_objectSpread2({
36884
+ parts,
36885
+ binaryParts
36886
+ }, importedDocuments.size > 0 ? { importedDocuments } : {}));
36887
+ const partPageCounts = fillBodyFields(PARSED, document, estimate, { blank: true });
36888
+ 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 : [];
36889
+ for (const { attributes = {} } of relationships) {
36890
+ const part = /\/(header|footer)$/.test(String(attributes.Type)) ? rootOf(parts.get(resolveTarget(DOCUMENT, String(attributes.Target)))) : void 0;
36891
+ if (part) fillPartFields(PARSED, part, estimate, {
36892
+ blank: true,
36893
+ sectionPageCount: partPageCounts.get(String(attributes.Id))
36894
+ });
36895
+ }
36896
+ });
36897
+ return function fillTemplatePageNumbers(_x4, _x5) {
36898
+ return _ref3.apply(this, arguments);
36899
+ };
36900
+ }();
36901
+ //#endregion
35020
36902
  //#region src/patcher/paragraph-split-inject.ts
35021
36903
  var TokenNotFoundError = class extends Error {
35022
36904
  constructor(token) {
@@ -35318,9 +37200,11 @@ var SPLIT_TOKEN = "
35318
37200
  * @param context - The document context for formatting
35319
37201
  * @param keepOriginalStyles - Whether to preserve original text formatting
35320
37202
  * @param recursive - Whether to replace every occurrence in a paragraph, rather than only the first
37203
+ * @param renumberIds - Renumbers the bookmarks and note references the patch inserts, so they don't take an id the
37204
+ * document uses
35321
37205
  * @returns Result containing the modified element and whether a replacement occurred
35322
37206
  */
35323
- var replacer = ({ json, patch, patchText, context, keepOriginalStyles = true, recursive = true }) => {
37207
+ var replacer = ({ json, patch, patchText, context, keepOriginalStyles = true, recursive = true, renumberIds = (elements) => elements }) => {
35324
37208
  const renderedParagraphs = findLocationOfText(json, patchText);
35325
37209
  if (renderedParagraphs.length === 0) return {
35326
37210
  element: json,
@@ -35330,9 +37214,15 @@ var replacer = ({ json, patch, patchText, context, keepOriginalStyles = true, re
35330
37214
  const paragraphsToPatch = patch.type === PatchType.DOCUMENT ? withoutNestedParagraphs(paragraphsInPatchOrder) : paragraphsInPatchOrder;
35331
37215
  for (const renderedParagraph of paragraphsToPatch) switch (patch.type) {
35332
37216
  case PatchType.DOCUMENT: {
37217
+ var _children;
35333
37218
  const parentElement = goToParentElementFromPath(json, renderedParagraph.pathToParagraph);
35334
37219
  const elementIndex = getLastElementIndexFromPath(renderedParagraph.pathToParagraph);
35335
- parentElement.elements.splice(elementIndex, 1, ...formatChildren(patch, context));
37220
+ const children = formatChildren(patch, context, renumberIds);
37221
+ 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" ? [{
37222
+ type: "element",
37223
+ name: "w:p"
37224
+ }] : [];
37225
+ parentElement.elements.splice(elementIndex, 1, ...children, ...endParagraph);
35336
37226
  break;
35337
37227
  }
35338
37228
  case PatchType.PARAGRAPH:
@@ -35346,7 +37236,7 @@ var replacer = ({ json, patch, patchText, context, keepOriginalStyles = true, re
35346
37236
  renderedParagraph: paragraph,
35347
37237
  patchText,
35348
37238
  fromIndex,
35349
- children: formatChildren(patch, context),
37239
+ children: formatChildren(patch, context, renumberIds),
35350
37240
  keepOriginalStyles
35351
37241
  });
35352
37242
  paragraph = renderParagraphNode({
@@ -35364,10 +37254,10 @@ var replacer = ({ json, patch, patchText, context, keepOriginalStyles = true, re
35364
37254
  didFindOccurrence: true
35365
37255
  };
35366
37256
  };
35367
- var formatChildren = (patch, context) => patch.children.flatMap((c) => {
37257
+ var formatChildren = (patch, context, renumberIds) => renumberIds(patch.children.flatMap((c) => {
35368
37258
  var _c$writtenAs;
35369
37259
  return (_c$writtenAs = c.writtenAs) !== null && _c$writtenAs !== void 0 ? _c$writtenAs : c;
35370
- }).map((c) => toJson((0, import_xml.default)(formatter.format(c, context)))).map((c) => c.elements[0]);
37260
+ }).map((c) => toJson((0, import_xml.default)(formatter.format(c, context)))).map((c) => c.elements[0]));
35371
37261
  /**
35372
37262
  * Replaces the first occurrence of the placeholder from `fromIndex` on, splitting the run it starts in.
35373
37263
  *
@@ -35385,12 +37275,21 @@ var replaceOccurrenceInParagraph = ({ paragraphElement, renderedParagraph, patch
35385
37275
  const runElementToBeReplaced = paragraphElement.elements[index];
35386
37276
  const { left, right } = splitRunElement(runElementToBeReplaced, SPLIT_TOKEN);
35387
37277
  const runProperties = runElementToBeReplaced.elements.find((e) => e.type === "element" && e.name === "w:rPr");
35388
- const newRunElements = keepOriginalStyles && runProperties ? children.map((e) => e.name === "w:r" ? withRunProperties(e, runProperties) : e) : children;
37278
+ const newRunElements = keepOriginalStyles && runProperties ? children.map((e) => withRunPropertiesOnRuns(e, runProperties)) : children;
35389
37279
  const patchedRightElement = runProperties ? _objectSpread2(_objectSpread2({}, right), {}, { elements: [runProperties, ...right.elements] }) : right;
35390
37280
  paragraphElement.elements.splice(index, 1, left, ...newRunElements, patchedRightElement);
35391
37281
  return index + 1 + newRunElements.length;
35392
37282
  };
35393
37283
  /**
37284
+ * Gives the runs of inserted content the placeholder's run properties. Content such as a hyperlink can't take run
37285
+ * properties itself, so its runs take them, and its text is formatted as the text around it is. Runs inside a run, such
37286
+ * as in its text box, are that content's own, and are left alone.
37287
+ */
37288
+ var withRunPropertiesOnRuns = (element, originalRunProperties) => {
37289
+ if (element.name === "w:r") return withRunProperties(element, originalRunProperties);
37290
+ return element.elements ? _objectSpread2(_objectSpread2({}, element), {}, { elements: element.elements.map((e) => withRunPropertiesOnRuns(e, originalRunProperties)) }) : element;
37291
+ };
37292
+ /**
35394
37293
  * Gives a run the placeholder's run properties. A run can only have one w:rPr, so properties the run
35395
37294
  * sets itself are kept, and the placeholder's fill in the rest.
35396
37295
  */
@@ -35482,6 +37381,118 @@ var goToElementFromPath = (json, path) => {
35482
37381
  var goToParentElementFromPath = (json, path) => goToElementFromPath(json, path.slice(0, path.length - 1));
35483
37382
  var getLastElementIndexFromPath = (path) => path[path.length - 1];
35484
37383
  //#endregion
37384
+ //#region src/patcher/table-rows.ts
37385
+ var EMPTY = {
37386
+ type: PatchType.PARAGRAPH,
37387
+ children: []
37388
+ };
37389
+ /**
37390
+ * Repeats the rows of the tables in an element that hold the patch's fields, such as `{{items.name}}` for the key
37391
+ * "items", once for each of the patch's rows, and patches the fields in each copy with the row's patches.
37392
+ *
37393
+ * @param json - The element to patch, such as a part's root
37394
+ * @param key - The patch's key, such as "items"
37395
+ * @param patch - The rows of data
37396
+ * @param delimiters - The placeholders' delimiters
37397
+ * @param patchPlaceholder - Patches a field in a copy of the rows, as `patchDocument` patches a placeholder
37398
+ */
37399
+ var patchTableRows = ({ json, key, patch, delimiters: { start, end }, patchPlaceholder }) => {
37400
+ const fieldStart = `${start}${key}.`;
37401
+ for (const rows of findRowsToRepeat(json, fieldStart)) {
37402
+ const fields = fieldsIn(rows.elements, fieldStart, end);
37403
+ const copies = patch.rows.flatMap((row, index) => {
37404
+ const copy = {
37405
+ type: "element",
37406
+ name: "w:tbl",
37407
+ elements: [...index === 0 ? rows.elements.map(copyOf) : withoutIds(rows.elements)]
37408
+ };
37409
+ const fieldPatches = new Map(Object.entries(row).flatMap(([field, p]) => p === void 0 ? [] : [[field, p]]));
37410
+ for (const [field, fieldPatch] of fieldPatches) patchPlaceholder(copy, `${key}.${field}`, fieldPatch);
37411
+ for (const field of fields.filter((f) => !fieldPatches.has(f))) patchPlaceholder(copy, `${key}.${field}`, EMPTY);
37412
+ return copy.elements;
37413
+ });
37414
+ rows.parent.elements.splice(rows.parent.elements.indexOf(rows.elements[0]), rows.elements.length, ...copies);
37415
+ if (rows.table && !hasRows(rows.table.element)) rows.table.parent.elements.splice(rows.table.parent.elements.indexOf(rows.table.element), 1);
37416
+ }
37417
+ };
37418
+ /**
37419
+ * The rows that hold a field, grouped into the rows next to each other in a table, which are repeated together.
37420
+ */
37421
+ var findRowsToRepeat = (json, fieldStart) => {
37422
+ const found = findLocationOfText(json, fieldStart).flatMap((paragraph) => {
37423
+ const row = rowHolding(json, paragraph.pathToParagraph);
37424
+ return row ? [row] : [];
37425
+ });
37426
+ 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);
37427
+ return [...new Set(rows.map((row) => row.parent))].flatMap((parent) => {
37428
+ const siblingRows = parent.elements.filter((e) => e.name === "w:tr");
37429
+ const positions = rows.filter((row) => row.parent === parent).map((row) => siblingRows.indexOf(row.row)).sort((a, b) => a - b);
37430
+ const { table } = rows.find((row) => row.parent === parent);
37431
+ return positions.reduce((all, position) => {
37432
+ const previous = all[all.length - 1];
37433
+ return (previous === null || previous === void 0 ? void 0 : previous[previous.length - 1]) === position - 1 ? [...all.slice(0, -1), [...previous, position]] : [...all, [position]];
37434
+ }, []).map((group) => {
37435
+ const first = parent.elements.indexOf(siblingRows[group[0]]);
37436
+ const last = parent.elements.indexOf(siblingRows[group[group.length - 1]]);
37437
+ return {
37438
+ parent,
37439
+ table,
37440
+ elements: parent.elements.slice(first, last + 1)
37441
+ };
37442
+ });
37443
+ });
37444
+ };
37445
+ /**
37446
+ * The row nearest to the paragraph at the end of the path that holds it, if it is in a table.
37447
+ */
37448
+ var rowHolding = (json, pathToParagraph) => {
37449
+ let element = json;
37450
+ let row;
37451
+ let table;
37452
+ for (let i = 1; i < pathToParagraph.length; i++) {
37453
+ const child = element.elements[pathToParagraph[i]];
37454
+ if (child.name === "w:tbl") table = {
37455
+ element: child,
37456
+ parent: element
37457
+ };
37458
+ if (child.name === "w:tr") row = {
37459
+ parent: element,
37460
+ table,
37461
+ row: child,
37462
+ path: pathToParagraph.slice(0, i + 1)
37463
+ };
37464
+ element = child;
37465
+ }
37466
+ return row;
37467
+ };
37468
+ var isInside = (path, ancestorPath) => path.length > ancestorPath.length && ancestorPath.every((index, i) => path[i] === index);
37469
+ var hasRows = (table) => {
37470
+ var _table$elements;
37471
+ 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));
37472
+ };
37473
+ /**
37474
+ * The names of the fields in the elements, such as "name" for `{{items.name}}`.
37475
+ */
37476
+ var fieldsIn = (elements, fieldStart, end) => {
37477
+ const fields = findLocationOfText({ elements: [...elements] }, fieldStart).flatMap(({ text }) => text.split(fieldStart).slice(1).flatMap((after) => {
37478
+ const fieldEnd = after.indexOf(end);
37479
+ return fieldEnd > 0 ? [after.slice(0, fieldEnd)] : [];
37480
+ }));
37481
+ return [...new Set(fields)];
37482
+ };
37483
+ var copyOf = (element) => JSON.parse(JSON.stringify(element));
37484
+ var ATTRIBUTES_TO_REMOVE = ["w14:paraId", "w14:textId"];
37485
+ var ELEMENTS_TO_REMOVE = ["w:bookmarkStart", "w:bookmarkEnd"];
37486
+ /**
37487
+ * A copy of elements without what must be unique in a document, so they can be in the document more than once.
37488
+ *
37489
+ * @param parent - The elements' parent, as a content control's id is an element in its properties
37490
+ */
37491
+ var withoutIds = (elements, parent) => elements.filter((e) => {
37492
+ var _e$name;
37493
+ 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");
37494
+ }).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)] }));
37495
+ //#endregion
35485
37496
  //#region src/patcher/theme-colors.ts
35486
37497
  var THEME_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
35487
37498
  var COLOR_NAMES = /* @__PURE__ */ new Map([
@@ -35540,7 +37551,7 @@ var readTheme = function() {
35540
37551
  return ((_item$attributes3 = item.attributes) === null || _item$attributes3 === void 0 ? void 0 : _item$attributes3.Type) === THEME_RELATIONSHIP_TYPE;
35541
37552
  });
35542
37553
  const target = theme === null || theme === void 0 || (_theme$attributes = theme.attributes) === null || _theme$attributes === void 0 ? void 0 : _theme$attributes.Target;
35543
- return typeof target === "string" ? readPart(zip, target.startsWith("/") ? target.slice(1) : `word/${target}`) : void 0;
37554
+ return typeof target === "string" ? readPart(zip, resolveTarget("word/document.xml", target)) : void 0;
35544
37555
  });
35545
37556
  return function readTheme(_x3) {
35546
37557
  return _ref2.apply(this, arguments);
@@ -35579,6 +37590,23 @@ var readThemeColors = function() {
35579
37590
  *
35580
37591
  * @module
35581
37592
  */
37593
+ /**
37594
+ * 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
37595
+ * from JavaScript without its children.
37596
+ *
37597
+ * @param key - The patch's key, such as "items", or for a field of a row, such as "items.name"
37598
+ * @param inTableRow - Whether the patch is for a field of a row, where a drawing patch can't be
37599
+ */
37600
+ var assertValidPatch = (key, patch, { inTableRow }) => {
37601
+ if ((patch === null || patch === void 0 ? void 0 : patch.type) === PatchType.TABLE_ROWS && Array.isArray(patch.rows)) {
37602
+ for (const row of patch.rows) {
37603
+ 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`);
37604
+ for (const [field, fieldPatch] of Object.entries(row)) if (fieldPatch !== void 0) assertValidPatch(`${key}.${field}`, fieldPatch, { inTableRow: true });
37605
+ }
37606
+ return;
37607
+ }
37608
+ 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"}`);
37609
+ };
35582
37610
  var imageReplacer = new ImageReplacer();
35583
37611
  var UTF16LE = new Uint8Array([255, 254]);
35584
37612
  var UTF16BE = new Uint8Array([254, 255]);
@@ -35626,7 +37654,7 @@ var patchDocument = function() {
35626
37654
  var _ref = _asyncToGenerator(function* ({ outputType, data, patches, keepOriginalStyles, placeholderDelimiters = {
35627
37655
  start: "{{",
35628
37656
  end: "}}"
35629
- }, recursive = true }) {
37657
+ }, recursive = true, footnotes, endnotes, pageNumbers }) {
35630
37658
  const zipContent = data instanceof import_jszip_min.default ? data : yield import_jszip_min.default.loadAsync(data);
35631
37659
  const contexts = /* @__PURE__ */ new Map();
35632
37660
  const themeColors = yield readThemeColors(zipContent);
@@ -35646,7 +37674,7 @@ var patchDocument = function() {
35646
37674
  const binaryContentMap = /* @__PURE__ */ new Map();
35647
37675
  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.");
35648
37676
  const { start, end } = placeholderDelimiters;
35649
- 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`);
37677
+ for (const [key, patch] of Object.entries(patches)) assertValidPatch(key, patch, { inTableRow: false });
35650
37678
  for (const [key, value] of Object.entries(zipContent.files)) {
35651
37679
  const binaryValue = yield value.async("uint8array");
35652
37680
  const startBytes = binaryValue.slice(0, 2);
@@ -35675,6 +37703,7 @@ var patchDocument = function() {
35675
37703
  }
35676
37704
  map.set(key, json);
35677
37705
  }
37706
+ const renumberBookmarks = renumberBookmarksAvoiding([...map.values()].flatMap(findBookmarkIds));
35678
37707
  const createContext = (key) => ({
35679
37708
  file,
35680
37709
  viewWrapper: { Relationships: { addRelationship: (id, type, target, targetMode) => {
@@ -35688,6 +37717,17 @@ var patchDocument = function() {
35688
37717
  } } },
35689
37718
  stack: []
35690
37719
  });
37720
+ const notes = patchNotes({
37721
+ footnotes,
37722
+ endnotes
37723
+ }, map, {
37724
+ createContext,
37725
+ addContentTypeOverride: (contentType, partName) => contentTypeOverrides.push({
37726
+ contentType,
37727
+ partName
37728
+ }),
37729
+ renumberBookmarks
37730
+ });
35691
37731
  patchDrawings({
35692
37732
  parts: map,
35693
37733
  binaryParts: binaryContentMap,
@@ -35698,35 +37738,56 @@ var patchDocument = function() {
35698
37738
  end
35699
37739
  }
35700
37740
  }, createContext);
37741
+ const textPatches = Object.entries(patches).flatMap(([key, patch]) => patch.type === PatchType.DRAWING ? [] : [[key, patch]]);
37742
+ const patchesInOrder = [...textPatches.filter(([, patch]) => patch.type === PatchType.TABLE_ROWS), ...textPatches.filter(([, patch]) => patch.type !== PatchType.TABLE_ROWS)];
35701
37743
  for (const [key, json] of [...map]) {
35702
37744
  if (!key.startsWith("word/") || key.endsWith(".xml.rels")) continue;
35703
37745
  const context = createContext(key);
35704
37746
  contexts.set(key, context);
35705
- for (const [patchKey, patchValue] of Object.entries(patches)) {
35706
- if (patchValue.type === PatchType.DRAWING) continue;
35707
- const patchText = `${start}${patchKey}${end}`;
35708
- replacer({
35709
- json,
35710
- patch: _objectSpread2(_objectSpread2({}, patchValue), {}, { children: patchValue.children.map((element) => {
35711
- if (element instanceof ExternalHyperlink) {
35712
- const concreteHyperlink = new ConcreteHyperlink(element.options.children, uniqueId());
35713
- relationshipAdditions.push({
37747
+ const patchPlaceholder = (element, patchKey, patchValue) => {
37748
+ if (patchValue.type === PatchType.TABLE_ROWS) {
37749
+ patchTableRows({
37750
+ json: element,
37751
+ key: patchKey,
37752
+ patch: patchValue,
37753
+ delimiters: {
37754
+ start,
37755
+ end
37756
+ },
37757
+ patchPlaceholder
37758
+ });
37759
+ return;
37760
+ }
37761
+ const hyperlinkRelationships = [];
37762
+ const { didFindOccurrence } = replacer({
37763
+ json: element,
37764
+ patch: _objectSpread2(_objectSpread2({}, patchValue), {}, { children: patchValue.children.flatMap((child) => child instanceof Bookmark ? child.writtenAs : [child]).map((child) => {
37765
+ if (child instanceof ExternalHyperlink) {
37766
+ const concreteHyperlink = new ConcreteHyperlink(child.options.children, uniqueId());
37767
+ hyperlinkRelationships.push({
35714
37768
  key,
35715
37769
  id: concreteHyperlink.linkId,
35716
37770
  type: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
35717
- target: element.options.link,
37771
+ target: child.options.link,
35718
37772
  targetMode: TargetModeType.EXTERNAL
35719
37773
  });
35720
37774
  return concreteHyperlink;
35721
- } else return element;
37775
+ } else return child;
35722
37776
  }) }),
35723
- patchText,
37777
+ patchText: `${start}${patchKey}${end}`,
35724
37778
  context,
35725
37779
  keepOriginalStyles,
35726
- recursive
37780
+ recursive,
37781
+ renumberIds: (elements) => notes.renumber(renumberBookmarks(elements))
35727
37782
  });
35728
- }
35729
- const mediaDatas = imageReplacer.getMediaData(JSON.stringify(json), context.file.Media);
37783
+ if (didFindOccurrence) relationshipAdditions.push(...hyperlinkRelationships);
37784
+ };
37785
+ for (const [patchKey, patchValue] of patchesInOrder) patchPlaceholder(json, patchKey, patchValue);
37786
+ }
37787
+ notes.write();
37788
+ for (const [key, json] of map) {
37789
+ if (!key.startsWith("word/") || key.endsWith(".xml.rels")) continue;
37790
+ const mediaDatas = imageReplacer.getMediaData(JSON.stringify(json), file.Media);
35730
37791
  if (mediaDatas.length > 0) {
35731
37792
  hasMedia = true;
35732
37793
  imageRelationshipAdditions.push({
@@ -35755,6 +37816,7 @@ var patchDocument = function() {
35755
37816
  map.set(relationshipKey, relationshipsJson);
35756
37817
  appendRelationship(relationshipsJson, id, type, target, targetMode);
35757
37818
  }
37819
+ if (pageNumbers) yield fillTemplatePageNumbers(map, pageNumbers, binaryContentMap);
35758
37820
  const packageParts = xmlifyPackageParts(file, void 0);
35759
37821
  if (hasMedia || contentTypeOverrides.length > 0) {
35760
37822
  const contentTypesJson = map.get("[Content_Types].xml");
@@ -35788,12 +37850,13 @@ var patchDocument = function() {
35788
37850
  };
35789
37851
  }();
35790
37852
  /**
35791
- * The element with an extra escape on each "&" in its text. xml-js reads "&amp;" in text as an "&" already escaped, and
35792
- * would write a text's literal "&amp;", such as in a document about HTML, as "&".
37853
+ * The element with an extra escape on each "&" in its text and attributes. xml-js reads "&amp;" in text as an "&"
37854
+ * already escaped, and would write a text's literal "&amp;", such as in a document about HTML, as "&". It escapes the
37855
+ * quotes in an attribute before `attributeValueFn` is given it, so that can't tell its "&quot;" from a literal one.
35793
37856
  */
35794
- 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)) });
37857
+ 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)) });
35795
37858
  var toXml = (jsonObj) => {
35796
- 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;") });
37859
+ return (0, import_lib.js2xml)(withAmpersandsEscaped(jsonObj), { attributeValueFn: (str) => String(str).replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/'/g, "&apos;") });
35797
37860
  };
35798
37861
  //#endregion
35799
37862
  //#region src/patcher/patch-detector.ts
@@ -35908,6 +37971,7 @@ exports.EMPTY_OBJECT = EMPTY_OBJECT;
35908
37971
  exports.EmphasisMarkType = EmphasisMarkType;
35909
37972
  exports.EmptyElement = EmptyElement;
35910
37973
  exports.EndnoteIdReference = EndnoteIdReference;
37974
+ exports.EndnotePosition = EndnotePosition;
35911
37975
  exports.EndnoteReference = EndnoteReference;
35912
37976
  exports.EndnoteReferenceRun = EndnoteReferenceRun;
35913
37977
  exports.EndnoteReferenceRunAttributes = EndnoteReferenceRunAttributes;
@@ -35919,6 +37983,7 @@ exports.FootNoteReferenceRunAttributes = FootNoteReferenceRunAttributes;
35919
37983
  exports.FootNotes = FootNotes;
35920
37984
  exports.Footer = Footer;
35921
37985
  exports.FooterWrapper = FooterWrapper;
37986
+ exports.FootnotePosition = FootnotePosition;
35922
37987
  exports.FootnoteReference = FootnoteReference;
35923
37988
  exports.FootnoteReferenceElement = FootnoteReferenceElement;
35924
37989
  exports.FootnoteReferenceRun = FootnoteReferenceRun;
@@ -35985,6 +38050,7 @@ exports.MonthShort = MonthShort;
35985
38050
  exports.NextAttributeComponent = NextAttributeComponent;
35986
38051
  exports.NoBreakHyphen = NoBreakHyphen;
35987
38052
  exports.NonVisualDrawingProperties = NonVisualDrawingProperties;
38053
+ exports.NoteNumberRestart = NoteNumberRestart;
35988
38054
  exports.NumberFormat = NumberFormat;
35989
38055
  exports.NumberProperties = NumberProperties;
35990
38056
  exports.NumberValueElement = NumberValueElement;
@@ -36077,9 +38143,6 @@ exports.VerticalMergeRevisionType = VerticalMergeRevisionType;
36077
38143
  exports.VerticalMergeType = VerticalMergeType;
36078
38144
  exports.VerticalPositionAlign = VerticalPositionAlign;
36079
38145
  exports.VerticalPositionRelativeFrom = VerticalPositionRelativeFrom;
36080
- exports.WORKAROUND2 = WORKAROUND2;
36081
- exports.WORKAROUND3 = WORKAROUND3;
36082
- exports.WORKAROUND4 = WORKAROUND4;
36083
38146
  exports.WidthType = WidthType;
36084
38147
  exports.WpgGroupRun = WpgGroupRun;
36085
38148
  exports.WpsShapeRun = WpsShapeRun;
@@ -36102,6 +38165,8 @@ exports.createColumns = createColumns;
36102
38165
  exports.createDocumentGrid = createDocumentGrid;
36103
38166
  exports.createDotEmphasisMark = createDotEmphasisMark;
36104
38167
  exports.createEmphasisMark = createEmphasisMark;
38168
+ exports.createEndnoteProperties = createEndnoteProperties;
38169
+ exports.createFootnoteProperties = createFootnoteProperties;
36105
38170
  exports.createFrameProperties = createFrameProperties;
36106
38171
  exports.createHeaderFooterReference = createHeaderFooterReference;
36107
38172
  exports.createHorizontalPosition = createHorizontalPosition;
@@ -36151,6 +38216,9 @@ exports.docPropertiesUniqueNumericId = docPropertiesUniqueNumericId;
36151
38216
  exports.docPropertiesUniqueNumericIdGen = docPropertiesUniqueNumericIdGen;
36152
38217
  exports.eighthPointMeasureValue = eighthPointMeasureValue;
36153
38218
  exports.encodeUtf8 = encodeUtf8;
38219
+ exports.fillPageNumbers = fillPageNumbers;
38220
+ exports.fillPartPageNumbers = fillPartPageNumbers;
38221
+ exports.fillSequenceNumbers = fillSequenceNumbers;
36154
38222
  exports.hashedId = hashedId;
36155
38223
  exports.hexColorValue = hexColorValue;
36156
38224
  exports.hpsMeasureValue = hpsMeasureValue;