@wordinweb/agent 0.2.3 → 0.2.4

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.
@@ -407,6 +407,9 @@ function serializeXml(el26, declaration = false) {
407
407
  write2(el26);
408
408
  return out.join("");
409
409
  }
410
+ function isEmptyPlaceholder(e) {
411
+ return !!e.omitWhenEmpty && Object.keys(e.attrs).length === 0 && e.text.length === 0 && e.children.length === 1 && localName(e.children[0].name) === "t" && e.children[0].children.length === 0 && e.children[0].text.length === 0 && Object.keys(e.children[0].attrs).every((key) => key === "xml:space" && e.children[0].attrs[key] === "preserve");
412
+ }
410
413
  function cloneXml(el26) {
411
414
  return {
412
415
  name: el26.name,
@@ -452,6 +455,12 @@ var Package = class _Package {
452
455
  static from(data) {
453
456
  return new _Package(data instanceof Uint8Array ? data : new Uint8Array(data));
454
457
  }
458
+ /** A package over an already-unzipped entry map (DocxDocument.clone). */
459
+ static fromFiles(files) {
460
+ const pkg = Object.create(_Package.prototype);
461
+ pkg.files = files;
462
+ return pkg;
463
+ }
455
464
  has(name) {
456
465
  return this.normalize(name) in this.files;
457
466
  }
@@ -474,6 +483,13 @@ var Package = class _Package {
474
483
  return name.startsWith("/") ? name.slice(1) : name;
475
484
  }
476
485
  };
486
+ function relativePartPath(fromPart, toPart) {
487
+ const fromDir = fromPart.split("/").slice(0, -1);
488
+ const to = toPart.split("/");
489
+ let i = 0;
490
+ while (i < fromDir.length && i < to.length - 1 && fromDir[i] === to[i]) i++;
491
+ return [...fromDir.slice(i).map(() => ".."), ...to.slice(i)].join("/");
492
+ }
477
493
  function resolvePartPath(sourcePart, target) {
478
494
  if (target.startsWith("/")) return target.slice(1);
479
495
  const baseDir = sourcePart.includes("/") ? sourcePart.slice(0, sourcePart.lastIndexOf("/")) : "";
@@ -7025,6 +7041,10 @@ var _DocxDocument = class _DocxDocument {
7025
7041
  /** The header part roots, in package order. A watermark is authored into
7026
7042
  * every one of them: Word paints it on every page, and a document with a
7027
7043
  * first-page or even-page header has more than one header part. */
7044
+ /** The root of the header or footer part at `target`, if this document has one. */
7045
+ headerFooterRoot(target) {
7046
+ return this.hfParts.find((p) => p.target === target)?.root;
7047
+ }
7028
7048
  headerRoots() {
7029
7049
  return this.hfParts.filter((p) => p.isHeader).map((p) => p.root);
7030
7050
  }
@@ -7188,6 +7208,22 @@ var _DocxDocument = class _DocxDocument {
7188
7208
  this.saveJournal = null;
7189
7209
  }
7190
7210
  }
7211
+ /**
7212
+ * An independent copy: what `DocxDocument.load(doc.save())` gives, without
7213
+ * zipping the package and unzipping it again. compareDocuments starts from a
7214
+ * copy of the revised document, and the round trip through the zip was a
7215
+ * third of its time on a document that had not changed at all.
7216
+ */
7217
+ clone() {
7218
+ const journal = [];
7219
+ this.saveJournal = journal;
7220
+ try {
7221
+ return new _DocxDocument(Package.fromFiles(this.buildPackageFiles()));
7222
+ } finally {
7223
+ for (let i = journal.length - 1; i >= 0; i--) journal[i]();
7224
+ this.saveJournal = null;
7225
+ }
7226
+ }
7191
7227
  saveAsync() {
7192
7228
  const journal = [];
7193
7229
  this.saveJournal = journal;
@@ -7389,8 +7425,91 @@ var _DocxDocument = class _DocxDocument {
7389
7425
  return this.relsRoot;
7390
7426
  }
7391
7427
  /** Register an external hyperlink relationship and return its rId. */
7392
- addHyperlinkRel(url) {
7393
- const rels = this.ensureRelsRoot();
7428
+ /**
7429
+ * Copy the part that `source`'s main-document relationship `relId` points
7430
+ * at into this package, with every part it references in turn (a chart's
7431
+ * embedded workbook, SmartArt's layout, style and colour parts) and their
7432
+ * content types, and add a relationship to it. Returns the new
7433
+ * relationship id, or null when the source has no such internal part.
7434
+ *
7435
+ * compareDocuments needs this for struck content: a removed picture keeps
7436
+ * its w:drawing, and without its image part the result's reject-all
7437
+ * brought the picture back as an empty frame.
7438
+ */
7439
+ adoptRelFrom(source, relId, scope = {}) {
7440
+ const rel = source.relationshipsOf(scope.from).get(relId);
7441
+ if (!rel || rel.external) return null;
7442
+ const copied = /* @__PURE__ */ new Map();
7443
+ const sameBytes = (path2, bytes) => {
7444
+ const have = this.pkg.binary(path2);
7445
+ return !!have && have.length === bytes.length && have.every((b, i) => b === bytes[i]);
7446
+ };
7447
+ const copyPart = (from) => {
7448
+ const known = copied.get(from);
7449
+ if (known) return known;
7450
+ const bytes = source.pkg.binary(from);
7451
+ if (!bytes) return null;
7452
+ let to = from;
7453
+ for (let n = 2; this.pkg.has(to) && !sameBytes(to, bytes); n++) to = from.replace(/(\.[^./]+)?$/, `-${n}$1`);
7454
+ copied.set(from, to);
7455
+ if (this.pkg.has(to)) return to;
7456
+ this.pkg.raw()[to] = bytes;
7457
+ this.adoptContentType(source, from, to);
7458
+ const relsXml = source.pkg.text(relsPathFor(from));
7459
+ if (relsXml) {
7460
+ const root = parseXml(relsXml);
7461
+ for (const r of root.children) {
7462
+ if (r.attrs.TargetMode === "External" || !r.attrs.Target) continue;
7463
+ const sub = copyPart(resolvePartPath(from, r.attrs.Target));
7464
+ if (sub) r.attrs.Target = relativePartPath(to, sub);
7465
+ }
7466
+ this.pkg.raw()[relsPathFor(to)] = strToU82(serializeXml(root, true));
7467
+ }
7468
+ return to;
7469
+ };
7470
+ const part = copyPart(rel.target);
7471
+ if (!part) return null;
7472
+ const owner = this.relsOwnerOf(scope.into);
7473
+ const rels = owner.relsRoot;
7474
+ let maxId = 0;
7475
+ for (const r of rels.children) {
7476
+ const m = /^rId(\d+)$/.exec(r.attrs["Id"] ?? "");
7477
+ if (m) maxId = Math.max(maxId, parseInt(m[1], 10));
7478
+ }
7479
+ const id = `rId${maxId + 1}`;
7480
+ rels.children.push({
7481
+ name: "Relationship",
7482
+ attrs: { Id: id, Type: rel.type, Target: relativePartPath(owner.partPath, part) },
7483
+ children: [],
7484
+ text: ""
7485
+ });
7486
+ owner.relationships.set(id, { id, type: rel.type, target: part, external: false });
7487
+ return id;
7488
+ }
7489
+ /** Give a part copied from `source` the content type it had there. */
7490
+ adoptContentType(source, from, to) {
7491
+ const types = this.contentTypesRoot;
7492
+ const theirs = source.contentTypesRoot;
7493
+ if (!types || !theirs) return;
7494
+ const override = theirs.children.find((c) => localName(c.name) === "Override" && c.attrs.PartName === `/${from}`);
7495
+ const prefixEnd = types.name.indexOf(":") + 1;
7496
+ const prefix = prefixEnd > 0 ? types.name.slice(0, prefixEnd) : "";
7497
+ if (override) {
7498
+ if (!types.children.some((c) => localName(c.name) === "Override" && c.attrs.PartName === `/${to}`)) {
7499
+ types.children.push({ name: `${prefix}Override`, attrs: { PartName: `/${to}`, ContentType: override.attrs.ContentType }, children: [], text: "" });
7500
+ }
7501
+ return;
7502
+ }
7503
+ const ext = from.slice(from.lastIndexOf(".") + 1).toLowerCase();
7504
+ const byExt = (root) => root.children.find((c) => localName(c.name) === "Default" && c.attrs.Extension?.toLowerCase() === ext);
7505
+ const fallback = byExt(theirs);
7506
+ if (fallback && !byExt(types)) {
7507
+ types.children.unshift({ name: `${prefix}Default`, attrs: { Extension: ext, ContentType: fallback.attrs.ContentType }, children: [], text: "" });
7508
+ }
7509
+ }
7510
+ addHyperlinkRel(url, ownerPart) {
7511
+ const owner = this.relsOwnerOf(ownerPart);
7512
+ const rels = owner.relsRoot;
7394
7513
  let maxId = 0;
7395
7514
  for (const r of rels.children) {
7396
7515
  const m = /^rId(\d+)$/.exec(r.attrs["Id"] ?? "");
@@ -7408,7 +7527,7 @@ var _DocxDocument = class _DocxDocument {
7408
7527
  children: [],
7409
7528
  text: ""
7410
7529
  });
7411
- this.documentRels.set(id, { id, type: "hyperlink", target: url, external: true });
7530
+ owner.relationships.set(id, { id, type: "hyperlink", target: url, external: true });
7412
7531
  return id;
7413
7532
  }
7414
7533
  /** Retarget an existing external relationship (hyperlink href edit). */
@@ -7420,6 +7539,23 @@ var _DocxDocument = class _DocxDocument {
7420
7539
  if (el26) el26.attrs["Target"] = url;
7421
7540
  return true;
7422
7541
  }
7542
+ /** The relationships owned by `part` (a header or footer part), or by the
7543
+ * document part when null; a header or footer gets a rels root on demand. */
7544
+ relsOwnerOf(part) {
7545
+ const owner = part ? this.hfParts.find((p) => p.target === part) : void 0;
7546
+ if (!owner) return { relsRoot: this.ensureRelsRoot(), relationships: this.documentRels, partPath: this.docPart };
7547
+ owner.relsRoot ?? (owner.relsRoot = {
7548
+ name: "Relationships",
7549
+ attrs: { xmlns: "http://schemas.openxmlformats.org/package/2006/relationships" },
7550
+ children: [],
7551
+ text: ""
7552
+ });
7553
+ return { relsRoot: owner.relsRoot, relationships: owner.rels, partPath: owner.target };
7554
+ }
7555
+ /** The relationships of `part` (a header or footer), or of the document part. */
7556
+ relationshipsOf(part) {
7557
+ return (part ? this.hfParts.find((p) => p.target === part)?.rels : void 0) ?? this.documentRels;
7558
+ }
7423
7559
  /** The relationships of the part that holds `source`: a header or footer
7424
7560
  * part when the element is inside one, else the document part. */
7425
7561
  imageRelsOwner(source) {
@@ -17423,15 +17559,20 @@ var Engine = class {
17423
17559
  while (out.length < nCols) out.push(bw(fallback));
17424
17560
  return out;
17425
17561
  };
17562
+ const colTopPads = (r) => {
17563
+ const fallback = this.cellMarginsOf(tbl, false).top ?? 0;
17564
+ return rows[r].cells.flatMap((c) => Array(Math.max(1, c.props.gridSpan)).fill(c.props.margins?.top ?? fallback));
17565
+ };
17426
17566
  const boundary = (k) => {
17427
17567
  if (k === 0) return Math.max(0, ...colWidths(0, "top", tb?.top));
17428
17568
  if (k === rows.length)
17429
17569
  return Math.max(0, ...colWidths(rows.length - 1, "bottom", tb?.bottom));
17430
17570
  const above = colWidths(k - 1, "bottom", tb?.insideH);
17431
17571
  const below = colWidths(k, "top", tb?.insideH);
17572
+ const topPads = colTopPads(k);
17432
17573
  const n = Math.max(above.length, below.length);
17433
17574
  let w = 0;
17434
- for (let i = 0; i < n; i++) w = Math.max(w, Math.max(above[i] ?? 0, below[i] ?? 0));
17575
+ for (let i = 0; i < n; i++) w = Math.max(w, below[i] ?? 0, (above[i] ?? 0) - (topPads[i] ?? 0));
17435
17576
  return w;
17436
17577
  };
17437
17578
  return { top: boundary(ri), bottom: boundary(ri + 1) };
@@ -19206,7 +19347,8 @@ function ensurePPrRPr(pEl) {
19206
19347
  let rPr = pPr.children.find((c) => localName(c.name) === "rPr");
19207
19348
  if (!rPr) {
19208
19349
  rPr = el2(`${w}rPr`);
19209
- pPr.children.push(rPr);
19350
+ const at = pPr.children.findIndex((c) => localName(c.name) === "sectPr" || localName(c.name) === "pPrChange");
19351
+ pPr.children.splice(at === -1 ? pPr.children.length : at, 0, rPr);
19210
19352
  }
19211
19353
  return rPr;
19212
19354
  }
@@ -19344,6 +19486,8 @@ function convertDelTextToText(el26) {
19344
19486
  const walk2 = (e) => {
19345
19487
  if (localName(e.name) === "delText") {
19346
19488
  e.name = e.name.replace(/delText$/, "t");
19489
+ } else if (localName(e.name) === "delInstrText") {
19490
+ e.name = e.name.replace(/delInstrText$/, "instrText");
19347
19491
  }
19348
19492
  for (const c of e.children) walk2(c);
19349
19493
  };
@@ -19365,7 +19509,7 @@ function removeEl(doc, el26) {
19365
19509
  parent.children.splice(idx, 1);
19366
19510
  return true;
19367
19511
  }
19368
- var RUN_CONTAINERS = ["hyperlink", "smartTag", "dir", "bdo"];
19512
+ var RUN_CONTAINERS = ["hyperlink", "smartTag", "dir", "bdo", "fldSimple"];
19369
19513
  function removeRevisionAndEmptyHost(doc, el26) {
19370
19514
  const parent = doc.findParentOf(el26);
19371
19515
  if (!removeEl(doc, el26)) return false;
@@ -19374,26 +19518,57 @@ function removeRevisionAndEmptyHost(doc, el26) {
19374
19518
  }
19375
19519
  return true;
19376
19520
  }
19377
- function joinWithNext(doc, pEl) {
19521
+ function joinWithNext(doc, pEl, gone) {
19378
19522
  const parent = doc.findParentOf(pEl);
19379
19523
  if (!parent) return false;
19380
19524
  const idx = parent.children.indexOf(pEl);
19381
- const next = parent.children[idx + 1];
19382
- if (!next || localName(next.name) !== "p") return false;
19525
+ let at = idx + 1;
19526
+ while (at < parent.children.length && MARKERS.includes(localName(parent.children[at].name))) at++;
19527
+ const next = parent.children[at];
19528
+ if (!next || localName(next.name) !== "p") {
19529
+ const goes = gone === "del" ? ["pPr", "del", "moveFrom", "proofErr", ...MOVE_RANGES] : ["pPr", "ins", "moveTo", "proofErr", ...MOVE_RANGES];
19530
+ const stays = MARKERS.filter((m) => m !== "proofErr");
19531
+ const removable = (c) => goes.includes(localName(c.name)) || stays.includes(localName(c.name)) || isEmptyPlaceholder(c) || RUN_CONTAINERS.includes(localName(c.name)) && c.children.every(removable);
19532
+ if (!pEl.children.every(removable)) return false;
19533
+ parent.children.splice(idx, 1, ...pEl.children.filter((c) => stays.includes(localName(c.name))));
19534
+ dropEmptiedControl(doc, parent);
19535
+ return true;
19536
+ }
19537
+ const between = parent.children.slice(idx + 1, at);
19383
19538
  const moved = next.children.filter((c) => localName(c.name) !== "pPr");
19384
- pEl.children.push(...moved);
19385
- parent.children.splice(idx + 1, 1);
19539
+ pEl.children.push(...between, ...moved);
19540
+ parent.children.splice(idx + 1, at - idx);
19541
+ carrySectionBreak(pEl, next);
19386
19542
  return true;
19387
19543
  }
19544
+ var MARKERS = ["bookmarkStart", "bookmarkEnd", "commentRangeStart", "commentRangeEnd", "permStart", "permEnd", "proofErr"];
19545
+ function carrySectionBreak(pEl, next) {
19546
+ const pPrOf = (p) => p.children.find((c) => localName(c.name) === "pPr");
19547
+ const sectOf = (p) => pPrOf(p)?.children.find((c) => localName(c.name) === "sectPr");
19548
+ const mine = sectOf(pEl);
19549
+ const theirs = sectOf(next);
19550
+ if (!mine && !theirs) return;
19551
+ let pPr = pPrOf(pEl);
19552
+ if (!pPr) {
19553
+ pPr = { name: "w:pPr", attrs: {}, children: [], text: "" };
19554
+ pEl.children.unshift(pPr);
19555
+ }
19556
+ pPr.children = pPr.children.filter((c) => c !== mine);
19557
+ if (theirs) {
19558
+ const at = pPr.children.findIndex((c) => localName(c.name) === "pPrChange");
19559
+ pPr.children.splice(at === -1 ? pPr.children.length : at, 0, theirs);
19560
+ }
19561
+ if (pPr.children.length === 0) pEl.children.splice(pEl.children.indexOf(pPr), 1);
19562
+ }
19388
19563
  function collectRevisions(doc) {
19389
19564
  const out = [];
19390
19565
  const walk2 = (el26) => {
19391
19566
  const ln = localName(el26.name);
19392
19567
  if (ln === "pPr") return;
19393
- if (ln === "ins" || ln === "del") {
19568
+ if (ln === "ins" || ln === "del" || ln === "moveTo" || ln === "moveFrom") {
19394
19569
  out.push({
19395
19570
  el: el26,
19396
- kind: ln === "ins" ? "insertion" : "deletion",
19571
+ kind: ln === "ins" || ln === "moveTo" ? "insertion" : "deletion",
19397
19572
  author: attrByLocal(el26, "author")
19398
19573
  });
19399
19574
  }
@@ -19427,10 +19602,10 @@ function collectRevisions(doc) {
19427
19602
  const rPr = pPr?.children.find((c) => localName(c.name) === "rPr");
19428
19603
  for (const c of rPr?.children ?? []) {
19429
19604
  const cn = localName(c.name);
19430
- if (cn === "ins" || cn === "del") {
19605
+ if (cn === "ins" || cn === "del" || cn === "moveTo" || cn === "moveFrom") {
19431
19606
  out.push({
19432
19607
  el: c,
19433
- kind: cn === "ins" ? "markInsertion" : "markDeletion",
19608
+ kind: cn === "ins" || cn === "moveTo" ? "markInsertion" : "markDeletion",
19434
19609
  paragraph: el26,
19435
19610
  author: attrByLocal(c, "author")
19436
19611
  });
@@ -19452,7 +19627,7 @@ function applyAccept(doc, ref) {
19452
19627
  case "markDeletion":
19453
19628
  if (!ref.paragraph) return false;
19454
19629
  removeMarkRevision(ref);
19455
- return joinWithNext(doc, ref.paragraph);
19630
+ return joinWithNext(doc, ref.paragraph, "del");
19456
19631
  case "rowInsertion":
19457
19632
  return removeRowRevision(doc, ref);
19458
19633
  case "rowDeletion":
@@ -19523,7 +19698,7 @@ function applyReject(doc, ref) {
19523
19698
  case "markInsertion":
19524
19699
  if (!ref.paragraph) return false;
19525
19700
  removeMarkRevision(ref);
19526
- return joinWithNext(doc, ref.paragraph);
19701
+ return joinWithNext(doc, ref.paragraph, "ins");
19527
19702
  case "markDeletion":
19528
19703
  return removeMarkRevision(ref);
19529
19704
  case "rowInsertion":
@@ -19574,11 +19749,23 @@ function applyToAll(doc, apply, author) {
19574
19749
  for (const part of held) notes.add(part);
19575
19750
  }
19576
19751
  if (n > 0) {
19752
+ dropSettledMoveRanges(doc);
19577
19753
  doc.markNotePartsChanged([...notes]);
19578
19754
  doc.refresh();
19579
19755
  }
19580
19756
  return n;
19581
19757
  }
19758
+ var MOVE_RANGES = ["moveFromRangeStart", "moveFromRangeEnd", "moveToRangeStart", "moveToRangeEnd"];
19759
+ function dropSettledMoveRanges(doc) {
19760
+ const roots = doc.revisionRoots();
19761
+ const has = (el26) => ["moveFrom", "moveTo"].includes(localName(el26.name)) || el26.children.some(has);
19762
+ if (roots.some(has)) return;
19763
+ const strip = (el26) => {
19764
+ el26.children = el26.children.filter((c) => !MOVE_RANGES.includes(localName(c.name)));
19765
+ for (const c of el26.children) strip(c);
19766
+ };
19767
+ for (const root of roots) strip(root);
19768
+ }
19582
19769
  function removeMarkRevision(ref) {
19583
19770
  const pPr = ref.paragraph?.children.find((c) => localName(c.name) === "pPr");
19584
19771
  const rPr = pPr?.children.find((c) => localName(c.name) === "rPr");
@@ -19610,9 +19797,24 @@ function removeRow(doc, ref) {
19610
19797
  const idx = tbl.children.indexOf(ref.row);
19611
19798
  if (idx === -1) return false;
19612
19799
  tbl.children.splice(idx, 1);
19613
- if (!tbl.children.some((c) => localName(c.name) === "tr")) removeEl(doc, tbl);
19800
+ if (!tbl.children.some((c) => localName(c.name) === "tr")) {
19801
+ const holder = doc.findParentOf(tbl);
19802
+ removeEl(doc, tbl);
19803
+ if (holder) dropEmptiedControl(doc, holder);
19804
+ }
19614
19805
  return true;
19615
19806
  }
19807
+ function dropEmptiedControl(doc, container) {
19808
+ const ln = localName(container.name);
19809
+ const control = ln === "sdtContent" ? doc.findParentOf(container) : ln === "customXml" ? container : void 0;
19810
+ if (!control) return;
19811
+ const left = container.children.filter((c) => localName(c.name) !== "customXmlPr");
19812
+ if (left.some((c) => !MARKERS.includes(localName(c.name)))) return;
19813
+ const holder = doc.findParentOf(control);
19814
+ if (!holder) return;
19815
+ holder.children.splice(holder.children.indexOf(control), 1, ...left.filter((c) => localName(c.name) !== "proofErr"));
19816
+ dropEmptiedControl(doc, holder);
19817
+ }
19616
19818
 
19617
19819
  // ../core/src/edit/blocks.ts
19618
19820
  function el3(name, attrs = {}, children2 = [], text = "") {
@@ -36979,6 +37181,9 @@ function nearestInstance(list, near) {
36979
37181
  return best;
36980
37182
  }
36981
37183
 
37184
+ // ../core/src/edit/compare/index.ts
37185
+ var GAP_PAIR_CAP = 200 * 200;
37186
+
36982
37187
  // ../core/src/edit/comments.ts
36983
37188
  function el24(name, attrs = {}, children2 = [], text = "") {
36984
37189
  return { name, attrs, children: children2, text };
@@ -45418,4 +45623,4 @@ export {
45418
45623
  AgentDocument,
45419
45624
  collaborativeAgentTarget
45420
45625
  };
45421
- //# sourceMappingURL=chunk-RQ74KQML.js.map
45626
+ //# sourceMappingURL=chunk-JK7OGOJB.js.map