@wordinweb/agent 0.2.2 → 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("/")) : "";
@@ -4618,6 +4634,10 @@ function parseCell(tc, ctx) {
4618
4634
  if (tcW && attr(tcW, "type") === "dxa") {
4619
4635
  const w = intAttr(tcW, "w");
4620
4636
  if (w) props.width = twipsToPx(w);
4637
+ } else if (tcW && attr(tcW, "type") === "pct") {
4638
+ const raw = attr(tcW, "w");
4639
+ const num = raw !== void 0 ? parseFloat(raw) : NaN;
4640
+ if (Number.isFinite(num) && num > 0) props.widthPct = raw.trim().endsWith("%") ? num / 100 : num / 5e3;
4621
4641
  } else if (tcW && attr(tcW, "type") === "auto") {
4622
4642
  props.widthAuto = true;
4623
4643
  }
@@ -7021,6 +7041,10 @@ var _DocxDocument = class _DocxDocument {
7021
7041
  /** The header part roots, in package order. A watermark is authored into
7022
7042
  * every one of them: Word paints it on every page, and a document with a
7023
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
+ }
7024
7048
  headerRoots() {
7025
7049
  return this.hfParts.filter((p) => p.isHeader).map((p) => p.root);
7026
7050
  }
@@ -7184,6 +7208,22 @@ var _DocxDocument = class _DocxDocument {
7184
7208
  this.saveJournal = null;
7185
7209
  }
7186
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
+ }
7187
7227
  saveAsync() {
7188
7228
  const journal = [];
7189
7229
  this.saveJournal = journal;
@@ -7385,8 +7425,91 @@ var _DocxDocument = class _DocxDocument {
7385
7425
  return this.relsRoot;
7386
7426
  }
7387
7427
  /** Register an external hyperlink relationship and return its rId. */
7388
- addHyperlinkRel(url) {
7389
- 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;
7390
7513
  let maxId = 0;
7391
7514
  for (const r of rels.children) {
7392
7515
  const m = /^rId(\d+)$/.exec(r.attrs["Id"] ?? "");
@@ -7404,7 +7527,7 @@ var _DocxDocument = class _DocxDocument {
7404
7527
  children: [],
7405
7528
  text: ""
7406
7529
  });
7407
- this.documentRels.set(id, { id, type: "hyperlink", target: url, external: true });
7530
+ owner.relationships.set(id, { id, type: "hyperlink", target: url, external: true });
7408
7531
  return id;
7409
7532
  }
7410
7533
  /** Retarget an existing external relationship (hyperlink href edit). */
@@ -7416,6 +7539,23 @@ var _DocxDocument = class _DocxDocument {
7416
7539
  if (el26) el26.attrs["Target"] = url;
7417
7540
  return true;
7418
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
+ }
7419
7559
  /** The relationships of the part that holds `source`: a header or footer
7420
7560
  * part when the element is inside one, else the document part. */
7421
7561
  imageRelsOwner(source) {
@@ -8778,7 +8918,11 @@ var WORD_FONT_METRICS = {
8778
8918
  // lineGap 99 / upem 2048 = 1.2734em (14.0pt at 11pt - phase23's sub-bullet
8779
8919
  // lists run 14.0pt/line among 13.5pt Calibri text).
8780
8920
  symbol: { asc: 1.005371, desc: 0.219727, gap: 0.04834 },
8781
- symbolmt: { asc: 1.005371, desc: 0.219727, gap: 0.04834 },
8921
+ // A Symbol bullet LABEL (the engine's metrics face) sizes its line without
8922
+ // the lineGap: Word runs an 11pt bullet at 13.5pt among 11pt Times New
8923
+ // Roman (wild-termsheet-behinddoc) and a 10pt one at 12.25pt, both
8924
+ // asc + desc; with the gap they would be 14.0pt and 12.75pt.
8925
+ symbolmt: { asc: 1.005371, desc: 0.219727, gap: 0 },
8782
8926
  "pingfang sc": { asc: 2.27, desc: 0.7627, gap: 0 },
8783
8927
  "songti sc": { asc: 2.27, desc: 0.7627, gap: 0 },
8784
8928
  "heiti sc": { asc: 2.27, desc: 0.7627, gap: 0 },
@@ -8805,13 +8949,19 @@ function quantizeQuarterPt(px2) {
8805
8949
  return Math.round(px2 / QUARTER_PT_PX) * QUARTER_PT_PX;
8806
8950
  }
8807
8951
  var FACE_SUFFIX = /\s+(bold italic|italic bold|bold|italic)$/i;
8952
+ var WORD_REPLACES = {
8953
+ "liberation serif": "Times New Roman",
8954
+ "liberation sans": "Arial",
8955
+ "liberation mono": "Courier New"
8956
+ };
8808
8957
  function normalizeFamily(family, bold, italic) {
8809
8958
  if (family === "\u5B8B\u4F53") family = "SimSun";
8959
+ const replaced = (f) => WORD_REPLACES[f.toLowerCase()] ?? f;
8810
8960
  const m = FACE_SUFFIX.exec(family);
8811
- if (!m) return { family, bold, italic };
8961
+ if (!m) return { family: replaced(family), bold, italic };
8812
8962
  const suffix = m[1].toLowerCase();
8813
8963
  return {
8814
- family: family.slice(0, m.index).trim() || family,
8964
+ family: replaced(family.slice(0, m.index).trim() || family),
8815
8965
  bold: bold || suffix.includes("bold"),
8816
8966
  italic: italic || suffix.includes("italic")
8817
8967
  };
@@ -16832,7 +16982,9 @@ var Engine = class {
16832
16982
  if (tbl.props.layout === "fixed") return base;
16833
16983
  const gridTotal = tbl.grid.reduce((a, b) => a + b, 0);
16834
16984
  const target = base.reduce((a, b) => a + b, 0);
16835
- const cellsDeclareWidths = tbl.rows.some((r) => r.cells.some((c) => c.props.width !== void 0));
16985
+ const cellsDeclareWidths = tbl.rows.some(
16986
+ (r) => r.cells.some((c) => c.props.width !== void 0 || c.props.widthPct !== void 0)
16987
+ );
16836
16988
  const containsHyperlink = tbl.rows.some(
16837
16989
  (row) => row.cells.some(
16838
16990
  (cell) => cell.blocks.some(
@@ -17407,15 +17559,20 @@ var Engine = class {
17407
17559
  while (out.length < nCols) out.push(bw(fallback));
17408
17560
  return out;
17409
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
+ };
17410
17566
  const boundary = (k) => {
17411
17567
  if (k === 0) return Math.max(0, ...colWidths(0, "top", tb?.top));
17412
17568
  if (k === rows.length)
17413
17569
  return Math.max(0, ...colWidths(rows.length - 1, "bottom", tb?.bottom));
17414
17570
  const above = colWidths(k - 1, "bottom", tb?.insideH);
17415
17571
  const below = colWidths(k, "top", tb?.insideH);
17572
+ const topPads = colTopPads(k);
17416
17573
  const n = Math.max(above.length, below.length);
17417
17574
  let w = 0;
17418
- 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));
17419
17576
  return w;
17420
17577
  };
17421
17578
  return { top: boundary(ri), bottom: boundary(ri + 1) };
@@ -17991,7 +18148,14 @@ var Engine = class {
17991
18148
  if (boundaryPara === void 0) continue;
17992
18149
  const above = keptTops.filter((t) => paraOfTop(part.keep, t) === boundaryPara);
17993
18150
  const below = restTops.filter((t) => paraOfTop(part.rest, t) === boundaryPara);
17994
- if (below.length !== 1 || above.length === 0) continue;
18151
+ if (above.length === 0) continue;
18152
+ if (above.length === 1 && below.length > 1) {
18153
+ const moved2 = part.keep.filter((it) => topOf(it) >= above[0] - 0.01);
18154
+ part.keep = part.keep.filter((it) => topOf(it) < above[0] - 0.01);
18155
+ part.rest = [...moved2, ...part.rest];
18156
+ continue;
18157
+ }
18158
+ if (below.length !== 1) continue;
17995
18159
  const moveTop = above.length >= 3 ? above[above.length - 1] : above[0];
17996
18160
  const moved = part.keep.filter((it) => topOf(it) >= moveTop - 0.01);
17997
18161
  part.keep = part.keep.filter((it) => topOf(it) < moveTop - 0.01);
@@ -19183,7 +19347,8 @@ function ensurePPrRPr(pEl) {
19183
19347
  let rPr = pPr.children.find((c) => localName(c.name) === "rPr");
19184
19348
  if (!rPr) {
19185
19349
  rPr = el2(`${w}rPr`);
19186
- 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);
19187
19352
  }
19188
19353
  return rPr;
19189
19354
  }
@@ -19321,6 +19486,8 @@ function convertDelTextToText(el26) {
19321
19486
  const walk2 = (e) => {
19322
19487
  if (localName(e.name) === "delText") {
19323
19488
  e.name = e.name.replace(/delText$/, "t");
19489
+ } else if (localName(e.name) === "delInstrText") {
19490
+ e.name = e.name.replace(/delInstrText$/, "instrText");
19324
19491
  }
19325
19492
  for (const c of e.children) walk2(c);
19326
19493
  };
@@ -19342,7 +19509,7 @@ function removeEl(doc, el26) {
19342
19509
  parent.children.splice(idx, 1);
19343
19510
  return true;
19344
19511
  }
19345
- var RUN_CONTAINERS = ["hyperlink", "smartTag", "dir", "bdo"];
19512
+ var RUN_CONTAINERS = ["hyperlink", "smartTag", "dir", "bdo", "fldSimple"];
19346
19513
  function removeRevisionAndEmptyHost(doc, el26) {
19347
19514
  const parent = doc.findParentOf(el26);
19348
19515
  if (!removeEl(doc, el26)) return false;
@@ -19351,26 +19518,57 @@ function removeRevisionAndEmptyHost(doc, el26) {
19351
19518
  }
19352
19519
  return true;
19353
19520
  }
19354
- function joinWithNext(doc, pEl) {
19521
+ function joinWithNext(doc, pEl, gone) {
19355
19522
  const parent = doc.findParentOf(pEl);
19356
19523
  if (!parent) return false;
19357
19524
  const idx = parent.children.indexOf(pEl);
19358
- const next = parent.children[idx + 1];
19359
- 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);
19360
19538
  const moved = next.children.filter((c) => localName(c.name) !== "pPr");
19361
- pEl.children.push(...moved);
19362
- parent.children.splice(idx + 1, 1);
19539
+ pEl.children.push(...between, ...moved);
19540
+ parent.children.splice(idx + 1, at - idx);
19541
+ carrySectionBreak(pEl, next);
19363
19542
  return true;
19364
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
+ }
19365
19563
  function collectRevisions(doc) {
19366
19564
  const out = [];
19367
19565
  const walk2 = (el26) => {
19368
19566
  const ln = localName(el26.name);
19369
19567
  if (ln === "pPr") return;
19370
- if (ln === "ins" || ln === "del") {
19568
+ if (ln === "ins" || ln === "del" || ln === "moveTo" || ln === "moveFrom") {
19371
19569
  out.push({
19372
19570
  el: el26,
19373
- kind: ln === "ins" ? "insertion" : "deletion",
19571
+ kind: ln === "ins" || ln === "moveTo" ? "insertion" : "deletion",
19374
19572
  author: attrByLocal(el26, "author")
19375
19573
  });
19376
19574
  }
@@ -19404,10 +19602,10 @@ function collectRevisions(doc) {
19404
19602
  const rPr = pPr?.children.find((c) => localName(c.name) === "rPr");
19405
19603
  for (const c of rPr?.children ?? []) {
19406
19604
  const cn = localName(c.name);
19407
- if (cn === "ins" || cn === "del") {
19605
+ if (cn === "ins" || cn === "del" || cn === "moveTo" || cn === "moveFrom") {
19408
19606
  out.push({
19409
19607
  el: c,
19410
- kind: cn === "ins" ? "markInsertion" : "markDeletion",
19608
+ kind: cn === "ins" || cn === "moveTo" ? "markInsertion" : "markDeletion",
19411
19609
  paragraph: el26,
19412
19610
  author: attrByLocal(c, "author")
19413
19611
  });
@@ -19429,7 +19627,7 @@ function applyAccept(doc, ref) {
19429
19627
  case "markDeletion":
19430
19628
  if (!ref.paragraph) return false;
19431
19629
  removeMarkRevision(ref);
19432
- return joinWithNext(doc, ref.paragraph);
19630
+ return joinWithNext(doc, ref.paragraph, "del");
19433
19631
  case "rowInsertion":
19434
19632
  return removeRowRevision(doc, ref);
19435
19633
  case "rowDeletion":
@@ -19500,7 +19698,7 @@ function applyReject(doc, ref) {
19500
19698
  case "markInsertion":
19501
19699
  if (!ref.paragraph) return false;
19502
19700
  removeMarkRevision(ref);
19503
- return joinWithNext(doc, ref.paragraph);
19701
+ return joinWithNext(doc, ref.paragraph, "ins");
19504
19702
  case "markDeletion":
19505
19703
  return removeMarkRevision(ref);
19506
19704
  case "rowInsertion":
@@ -19551,11 +19749,23 @@ function applyToAll(doc, apply, author) {
19551
19749
  for (const part of held) notes.add(part);
19552
19750
  }
19553
19751
  if (n > 0) {
19752
+ dropSettledMoveRanges(doc);
19554
19753
  doc.markNotePartsChanged([...notes]);
19555
19754
  doc.refresh();
19556
19755
  }
19557
19756
  return n;
19558
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
+ }
19559
19769
  function removeMarkRevision(ref) {
19560
19770
  const pPr = ref.paragraph?.children.find((c) => localName(c.name) === "pPr");
19561
19771
  const rPr = pPr?.children.find((c) => localName(c.name) === "rPr");
@@ -19587,9 +19797,24 @@ function removeRow(doc, ref) {
19587
19797
  const idx = tbl.children.indexOf(ref.row);
19588
19798
  if (idx === -1) return false;
19589
19799
  tbl.children.splice(idx, 1);
19590
- 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
+ }
19591
19805
  return true;
19592
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
+ }
19593
19818
 
19594
19819
  // ../core/src/edit/blocks.ts
19595
19820
  function el3(name, attrs = {}, children2 = [], text = "") {
@@ -36956,6 +37181,9 @@ function nearestInstance(list, near) {
36956
37181
  return best;
36957
37182
  }
36958
37183
 
37184
+ // ../core/src/edit/compare/index.ts
37185
+ var GAP_PAIR_CAP = 200 * 200;
37186
+
36959
37187
  // ../core/src/edit/comments.ts
36960
37188
  function el24(name, attrs = {}, children2 = [], text = "") {
36961
37189
  return { name, attrs, children: children2, text };
@@ -45395,4 +45623,4 @@ export {
45395
45623
  AgentDocument,
45396
45624
  collaborativeAgentTarget
45397
45625
  };
45398
- //# sourceMappingURL=chunk-ATE5QKBU.js.map
45626
+ //# sourceMappingURL=chunk-JK7OGOJB.js.map