@superdoc/mcp 1.3.0-next.12 → 1.3.0-next.14

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.
Files changed (2) hide show
  1. package/dist/index.js +489 -114
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -31318,7 +31318,7 @@ var init_host = __esm(() => {
31318
31318
  });
31319
31319
 
31320
31320
  // ../../packages/sdk/langs/node/src/runtime/sdk-version.generated.ts
31321
- var SDK_VERSION = "2.16.0-next.12";
31321
+ var SDK_VERSION = "2.16.0-next.14";
31322
31322
 
31323
31323
  // ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
31324
31324
  import { chmodSync, existsSync } from "node:fs";
@@ -134761,6 +134761,20 @@ function isValidRevisionDate(value) {
134761
134761
  const daysInMonth = [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
134762
134762
  return day <= daysInMonth[month - 1];
134763
134763
  }
134764
+ function parseRevisionMarkerAttributes(attributes) {
134765
+ const idAttributes = attributes.filter((attribute) => attribute.local === "id");
134766
+ const authorAttributes = attributes.filter((attribute) => attribute.local === "author");
134767
+ const dateAttributes = attributes.filter((attribute) => attribute.local === "date");
134768
+ const hasValidIdAttribute = idAttributes.length === 1 && idAttributes[0].uri === W_NS;
134769
+ const id = hasValidIdAttribute ? parseRevisionWId(idAttributes[0].value) : null;
134770
+ const hasValidAuthorAttribute = authorAttributes.length === 1 && authorAttributes[0].uri === W_NS;
134771
+ const author = hasValidAuthorAttribute ? authorAttributes[0].value : "";
134772
+ const hasValidDateAttributes = dateAttributes.every((attribute) => attribute.uri === W_NS && isValidRevisionDate(attribute.value));
134773
+ if (!hasValidIdAttribute || !hasValidAuthorAttribute || id === null || !author || !hasValidDateAttributes) {
134774
+ return null;
134775
+ }
134776
+ return { id, author, date: dateAttributes[0]?.value };
134777
+ }
134764
134778
  function parseDirectRunSequence(xml, allowRevisions) {
134765
134779
  const revisions = [];
134766
134780
  const stack = [];
@@ -134815,21 +134829,13 @@ function parseDirectRunSequence(xml, allowRevisions) {
134815
134829
  return;
134816
134830
  }
134817
134831
  if (allowRevisions && tag.uri === W_NS && (tag.local === "ins" || tag.local === "del") && !tag.isSelfClosing) {
134818
- const attributes = Object.values(tag.attributes);
134819
- const idAttributes = attributes.filter((attribute) => attribute.local === "id");
134820
- const authorAttributes = attributes.filter((attribute) => attribute.local === "author");
134821
- const dateAttributes = attributes.filter((attribute) => attribute.local === "date");
134822
- const hasValidIdAttribute = idAttributes.length === 1 && idAttributes[0].uri === W_NS;
134823
- const idValue = hasValidIdAttribute ? idAttributes[0].value : "";
134824
- const id = parseRevisionWId(idValue);
134825
- const hasValidAuthorAttribute = authorAttributes.length === 1 && authorAttributes[0].uri === W_NS;
134826
- const author = hasValidAuthorAttribute ? authorAttributes[0].value : "";
134827
- if (!hasValidIdAttribute || !hasValidAuthorAttribute || id === null || !author || dateAttributes.some((attribute) => attribute.uri !== W_NS || !isValidRevisionDate(attribute.value)))
134832
+ const marker = parseRevisionMarkerAttributes(Object.values(tag.attributes));
134833
+ if (!marker)
134828
134834
  valid = false;
134829
134835
  activeRevision = tag.local;
134830
134836
  activeRevisionRunCount = 0;
134831
- if (id !== null)
134832
- revisions.push({ kind: tag.local, wId: id, author });
134837
+ if (marker)
134838
+ revisions.push({ kind: tag.local, wId: marker.id, author: marker.author });
134833
134839
  stack.push("revision");
134834
134840
  return;
134835
134841
  }
@@ -134922,9 +134928,171 @@ function parseDirectRunSequence(xml, allowRevisions) {
134922
134928
  return null;
134923
134929
  return { currentText, originalText, revisions };
134924
134930
  }
134931
+ function splitLeadingNoteMarkerRun(xml, family) {
134932
+ const firstRun = /^\s*<((?:[A-Za-z_][\w.-]*:)?r)\b(?:"[^"]*"|'[^']*'|[^>"'])*>[\s\S]*?<\/\1>/.exec(xml);
134933
+ if (!firstRun)
134934
+ return null;
134935
+ const markerRunXml = firstRun[0];
134936
+ const localName2 = family === "footnotes" ? "footnoteRef" : "endnoteRef";
134937
+ const markerTag = new RegExp(`<((?:[A-Za-z_][\\w.-]*:)?)${localName2}\\s*\\/>`, "g");
134938
+ const markers = [...markerRunXml.matchAll(markerTag)];
134939
+ if (markers.length !== 1)
134940
+ return null;
134941
+ let valid = true;
134942
+ let depth = 0;
134943
+ let markerCount = 0;
134944
+ const parser = new import_saxes3.SaxesParser({
134945
+ xmlns: true,
134946
+ additionalNamespaces: replayAdditionalNamespaces(markerRunXml)
134947
+ });
134948
+ parser.on("error", () => {
134949
+ valid = false;
134950
+ });
134951
+ parser.on("opentag", (tag) => {
134952
+ depth += 1;
134953
+ if (depth === 1 && tag.local === "replay")
134954
+ return;
134955
+ if (depth === 2 && tag.uri === W_NS && tag.local === "r")
134956
+ return;
134957
+ if (depth === 3 && tag.uri === W_NS && tag.local === "rPr")
134958
+ return;
134959
+ if (depth === 3 && tag.uri === W_NS && tag.local === localName2 && tag.isSelfClosing && Object.keys(tag.attributes).length === 0) {
134960
+ markerCount += 1;
134961
+ return;
134962
+ }
134963
+ if (depth === 3 || (tag.local === "footnoteRef" || tag.local === "endnoteRef"))
134964
+ valid = false;
134965
+ });
134966
+ parser.on("closetag", () => {
134967
+ depth -= 1;
134968
+ });
134969
+ try {
134970
+ parser.write(`<replay>${markerRunXml}</replay>`).close();
134971
+ } catch {
134972
+ valid = false;
134973
+ }
134974
+ const withoutMarker = markerRunXml.replace(markerTag, "<w:t/>");
134975
+ if (!valid || depth !== 0 || markerCount !== 1 || parseDirectRunSequence(withoutMarker, false)?.currentText !== "")
134976
+ return null;
134977
+ return { markerRunXml, remainingRunXml: xml.slice(markerRunXml.length) };
134978
+ }
134979
+ function sameNoteMarkerRunXml(base2, target) {
134980
+ const withoutRedundantWordNamespace = (xml) => xml.split(` xmlns:w="${W_NS}"`).join("").split(` xmlns:w='${W_NS}'`).join("");
134981
+ return withoutRedundantWordNamespace(base2) === withoutRedundantWordNamespace(target);
134982
+ }
134925
134983
  function inspectDirectParagraphRevisionRuns(xml) {
134926
134984
  return parseDirectRunSequence(xml, true);
134927
134985
  }
134986
+ function inspectDirectRunSequence(xml) {
134987
+ return parseDirectRunSequence(xml, false);
134988
+ }
134989
+ function parseParagraphMarkRevisionMarker(pPrXml) {
134990
+ if (pPrXml === "")
134991
+ return null;
134992
+ let valid = true;
134993
+ const stack = [];
134994
+ let hasSectPr = false;
134995
+ let markerCount = 0;
134996
+ let marker = null;
134997
+ const parser = new import_saxes3.SaxesParser({
134998
+ xmlns: true,
134999
+ additionalNamespaces: replayAdditionalNamespaces(pPrXml)
135000
+ });
135001
+ parser.on("error", () => {
135002
+ valid = false;
135003
+ });
135004
+ parser.on("opentag", (tag) => {
135005
+ const parent = stack.at(-1);
135006
+ const grandparent = stack.at(-2);
135007
+ if (parent === undefined && (tag.local !== "pPr" || tag.uri !== W_NS))
135008
+ valid = false;
135009
+ if (tag.uri === W_NS && tag.local === "sectPr")
135010
+ hasSectPr = true;
135011
+ const parentIsLiveRPr = stack.length === 2 && parent !== undefined && parent.uri === W_NS && parent.local === "rPr" && grandparent !== undefined && grandparent.uri === W_NS && grandparent.local === "pPr";
135012
+ if (parentIsLiveRPr && tag.uri === W_NS && (tag.local === "ins" || tag.local === "del")) {
135013
+ markerCount += 1;
135014
+ if (!tag.isSelfClosing) {
135015
+ valid = false;
135016
+ } else {
135017
+ const attrs = parseRevisionMarkerAttributes(Object.values(tag.attributes));
135018
+ if (!attrs || marker !== null) {
135019
+ valid = false;
135020
+ } else {
135021
+ marker = { kind: tag.local, wId: attrs.id, author: attrs.author, date: attrs.date };
135022
+ }
135023
+ }
135024
+ } else if (parentIsLiveRPr && tag.uri === W_NS && (tag.local === "moveFrom" || tag.local === "moveTo")) {
135025
+ valid = false;
135026
+ }
135027
+ stack.push({ uri: tag.uri ?? "", local: tag.local ?? "" });
135028
+ });
135029
+ parser.on("closetag", () => {
135030
+ stack.pop();
135031
+ });
135032
+ try {
135033
+ parser.write(pPrXml).close();
135034
+ } catch {
135035
+ valid = false;
135036
+ }
135037
+ if (!valid || stack.length !== 0 || hasSectPr || markerCount !== 1 || marker === null)
135038
+ return null;
135039
+ return marker;
135040
+ }
135041
+ function removeProvenParagraphMarkMarker(xml, marker) {
135042
+ const baseBindings = new Map([["w", W_NS]]);
135043
+ const stack = [];
135044
+ let removal = null;
135045
+ let position = 0;
135046
+ while (position < xml.length) {
135047
+ const start = xml.indexOf("<", position);
135048
+ if (start < 0)
135049
+ break;
135050
+ if (xml.startsWith("<!--", start) || xml.startsWith("<![CDATA[", start) || xml.startsWith("<?", start)) {
135051
+ return null;
135052
+ }
135053
+ const end = findXmlTagEnd2(xml, start);
135054
+ if (end < 0)
135055
+ return null;
135056
+ const rawTag = xml.slice(start, end + 1);
135057
+ if (rawTag.startsWith("</")) {
135058
+ const close = /^<\/\s*([A-Za-z_][\w.-]*(?::[A-Za-z_][\w.-]*)?)\s*>$/.exec(rawTag);
135059
+ if (!close || stack.pop()?.qname !== close[1])
135060
+ return null;
135061
+ position = end + 1;
135062
+ continue;
135063
+ }
135064
+ const parsed = parseXmlStartTag(rawTag);
135065
+ if (!parsed)
135066
+ return null;
135067
+ const bindings = new Map(stack.at(-1)?.bindings ?? baseBindings);
135068
+ for (const attribute of parsed.attributes) {
135069
+ if (attribute.qname === "xmlns")
135070
+ bindings.set("", attribute.value);
135071
+ else if (attribute.prefix === "xmlns")
135072
+ bindings.set(attribute.localName, attribute.value);
135073
+ }
135074
+ const namespaceUri = bindings.get(parsed.prefix) ?? "";
135075
+ const parentEntry = stack.at(-1);
135076
+ const grandparentEntry = stack.at(-2);
135077
+ const isLiveRPrChild = stack.length === 2 && parentEntry?.localName === "rPr" && grandparentEntry?.localName === "pPr";
135078
+ if (isLiveRPrChild && namespaceUri === W_NS && parsed.localName === marker.kind && parsed.selfClosing) {
135079
+ const idValue = parsed.attributes.find((attribute) => attribute.localName === "id" && (bindings.get(attribute.prefix) ?? "") === W_NS)?.value;
135080
+ const authorValue = parsed.attributes.find((attribute) => attribute.localName === "author" && (bindings.get(attribute.prefix) ?? "") === W_NS)?.value;
135081
+ const dateValue = parsed.attributes.find((attribute) => attribute.localName === "date" && (bindings.get(attribute.prefix) ?? "") === W_NS)?.value;
135082
+ if (parseRevisionWId(idValue ?? "") === marker.wId && authorValue === marker.author && dateValue === marker.date) {
135083
+ if (removal !== null)
135084
+ return null;
135085
+ removal = { start, end: end + 1 };
135086
+ }
135087
+ }
135088
+ if (!parsed.selfClosing)
135089
+ stack.push({ qname: parsed.qname, localName: parsed.localName, bindings });
135090
+ position = end + 1;
135091
+ }
135092
+ if (stack.length > 0 || removal === null)
135093
+ return null;
135094
+ return xml.slice(0, removal.start) + xml.slice(removal.end);
135095
+ }
134928
135096
  function trackedAnnotationEntries(annotations) {
134929
135097
  return annotations?.find((capture) => capture.family === "tracked-changes")?.entries ?? [];
134930
135098
  }
@@ -135265,9 +135433,21 @@ function parseXmlStartTag(rawTag) {
135265
135433
  return null;
135266
135434
  }
135267
135435
  function validateRunContents(xml, options) {
135268
- if (xml === "")
135436
+ const baseHasNoteMarker = options.baseRunXml !== undefined && /<(?:[A-Za-z_][\w.-]*:)?(?:footnoteRef|endnoteRef)\b/.test(options.baseRunXml);
135437
+ const targetHasNoteMarker = /<(?:[A-Za-z_][\w.-]*:)?(?:footnoteRef|endnoteRef)\b/.test(xml);
135438
+ let runs = xml;
135439
+ if (baseHasNoteMarker || targetHasNoteMarker) {
135440
+ const family = options.noteMarkerFamily;
135441
+ const target = family && splitLeadingNoteMarkerRun(xml, family);
135442
+ const base2 = family && options.baseRunXml !== undefined ? splitLeadingNoteMarkerRun(options.baseRunXml, family) : undefined;
135443
+ if (!target || options.baseRunXml !== undefined && (!base2 || !sameNoteMarkerRunXml(base2.markerRunXml, target.markerRunXml))) {
135444
+ return { ok: false, reason: "target runs change or misplace the note marker" };
135445
+ }
135446
+ runs = target.remainingRunXml;
135447
+ }
135448
+ if (runs === "")
135269
135449
  return { ok: true };
135270
- const replayXml = stripAllowedNoteReferences(xml, options);
135450
+ const replayXml = stripAllowedNoteReferences(runs, options);
135271
135451
  const withoutCarriers = replayXml !== null && options.baseRunXml ? stripRetainedCarrier(replayXml, options.baseRunXml, options.allowNamespaceDeclarationDifference === true) : replayXml;
135272
135452
  const withoutBookmarks = withoutCarriers !== null && /<(?:[\w.-]+:)?bookmark(?:Start|End)\b/.test(withoutCarriers) ? preservedBookmarkRunTokens(withoutCarriers)?.strippedXml ?? null : withoutCarriers;
135273
135453
  if (withoutBookmarks === null || UNSUPPORTED_XML.test(withoutBookmarks) || RELATIONSHIP_REFERENCE.test(withoutBookmarks)) {
@@ -135303,9 +135483,27 @@ function validateCompareReplayPayload(payload, options = {}) {
135303
135483
  if (!dependencyResult.ok)
135304
135484
  return dependencyResult;
135305
135485
  if (payload.targetParagraphPropertiesXml !== undefined) {
135306
- const result = validateParagraphProperties(payload.targetParagraphPropertiesXml);
135307
- if (!result.ok)
135308
- return result;
135486
+ if (payload.targetParagraphMarkRevisionReplay !== undefined) {
135487
+ const proof = payload.targetParagraphMarkRevisionReplay;
135488
+ if (proof.policy !== "preserve-target-paragraph-mark-revision") {
135489
+ return { ok: false, reason: "target paragraph mark revision replay policy is incomplete" };
135490
+ }
135491
+ const marker = parseParagraphMarkRevisionMarker(payload.targetParagraphPropertiesXml);
135492
+ if (!marker || marker.kind !== proof.kind || marker.wId !== proof.wId || marker.author !== proof.author || marker.date !== proof.date) {
135493
+ return { ok: false, reason: "target paragraph mark revision replay proof does not match the target paragraph properties" };
135494
+ }
135495
+ const strippedXml = removeProvenParagraphMarkMarker(payload.targetParagraphPropertiesXml, marker);
135496
+ if (strippedXml === null) {
135497
+ return { ok: false, reason: "target paragraph mark revision replay proof could not be isolated from the target paragraph properties" };
135498
+ }
135499
+ const result = validateParagraphProperties(strippedXml);
135500
+ if (!result.ok)
135501
+ return result;
135502
+ } else {
135503
+ const result = validateParagraphProperties(payload.targetParagraphPropertiesXml);
135504
+ if (!result.ok)
135505
+ return result;
135506
+ }
135309
135507
  }
135310
135508
  if (payload.targetRevisionReplay !== undefined) {
135311
135509
  if (payload.targetRevisionReplay.policy !== "preserve-target-revision-set" || payload.targetRunXml === undefined) {
@@ -136103,14 +136301,27 @@ function validateBodyOperation(operation, label, problems, replayOptions = {}) {
136103
136301
  }
136104
136302
  }
136105
136303
  }
136106
- const carriesReplayPayload = operation.targetParagraphPropertiesXml !== undefined || operation.targetRunXml !== undefined || operation.replayDependencies !== undefined || operation.replayDependencyProofFailed !== undefined;
136107
- if (carriesReplayPayload && hasValidReplayPayloadShape && hasValidReplayShape) {
136304
+ let hasValidParagraphMarkReplayShape = operation.targetParagraphMarkRevisionReplay === undefined;
136305
+ if (operation.targetParagraphMarkRevisionReplay !== undefined) {
136306
+ const replay = operation.targetParagraphMarkRevisionReplay;
136307
+ const hasValidShape = isRecord9(replay) && replay.policy === "preserve-target-paragraph-mark-revision" && (replay.kind === "ins" || replay.kind === "del") && typeof replay.wId === "number" && Number.isSafeInteger(replay.wId) && isNonEmptyString2(replay.author) && (replay.date === undefined || typeof replay.date === "string");
136308
+ hasValidParagraphMarkReplayShape = hasValidShape;
136309
+ if (!hasValidShape) {
136310
+ problems.push(`${label}.targetParagraphMarkRevisionReplay: invalid target paragraph mark revision replay`);
136311
+ }
136312
+ if (operation.kind === "edit" || operation.kind === "formatEdit") {
136313
+ problems.push(`${label}.targetParagraphMarkRevisionReplay: ${operation.kind} does not support paragraph mark revision replay`);
136314
+ hasValidParagraphMarkReplayShape = false;
136315
+ }
136316
+ }
136317
+ const carriesReplayPayload = operation.kind !== "delete" && (operation.targetParagraphPropertiesXml !== undefined || operation.targetRunXml !== undefined || operation.replayDependencies !== undefined || operation.replayDependencyProofFailed !== undefined || operation.targetParagraphMarkRevisionReplay !== undefined);
136318
+ if (carriesReplayPayload && hasValidReplayPayloadShape && hasValidReplayShape && hasValidParagraphMarkReplayShape) {
136108
136319
  const proof = validateCompareReplayPayload(operation, {
136109
136320
  ...replayOptions,
136110
136321
  expectedCurrentText: operation.kind !== "delete" && typeof operation.text === "string" ? operation.text : undefined
136111
136322
  });
136112
136323
  if (!proof.ok) {
136113
- const field = operation.targetRevisionReplay === undefined ? "replayPayload" : "targetRevisionReplay";
136324
+ const field = operation.targetRevisionReplay === undefined ? operation.targetParagraphMarkRevisionReplay === undefined ? "replayPayload" : "targetParagraphMarkRevisionReplay" : "targetRevisionReplay";
136114
136325
  problems.push(`${label}.${field}: ${proof.reason}`);
136115
136326
  }
136116
136327
  }
@@ -136876,8 +137087,8 @@ function validatePlanDispositions(value, steps, problems) {
136876
137087
  }
136877
137088
  });
136878
137089
  }
136879
- const bodyHasTargetRevisionReplay = Array.isArray(value.bodyOperations) && value.bodyOperations.some((operation) => isRecord9(operation) && operation.targetRevisionReplay !== undefined);
136880
- const storyHasTargetRevisionReplay = Array.isArray(value.storyOperations) && value.storyOperations.some((group) => isRecord9(group) && Array.isArray(group.operations) && group.operations.some((operation) => isRecord9(operation) && operation.targetRevisionReplay !== undefined));
137090
+ const bodyHasTargetRevisionReplay = Array.isArray(value.bodyOperations) && value.bodyOperations.some((operation) => isRecord9(operation) && (operation.targetRevisionReplay !== undefined || operation.targetParagraphMarkRevisionReplay !== undefined));
137091
+ const storyHasTargetRevisionReplay = Array.isArray(value.storyOperations) && value.storyOperations.some((group) => isRecord9(group) && Array.isArray(group.operations) && group.operations.some((operation) => isRecord9(operation) && (operation.targetRevisionReplay !== undefined || operation.targetParagraphMarkRevisionReplay !== undefined)));
136881
137092
  if ((bodyHasTargetRevisionReplay || storyHasTargetRevisionReplay) && dispositions.get("tracked-changes") !== "supported") {
136882
137093
  problems.push("target revision replay requires a supported tracked-changes step");
136883
137094
  }
@@ -136990,7 +137201,8 @@ function validateCompareApplyPlan(value, baseBody = []) {
136990
137201
  if (!isRecord9(group) || !Array.isArray(group.operations))
136991
137202
  return;
136992
137203
  group.operations.forEach((operation, operationIndex) => {
136993
- validateBodyOperation(operation, `storyOperations[${index}].operations[${operationIndex}]`, problems);
137204
+ const noteMarkerFamily = (group.family === "footnotes" || group.family === "endnotes") && isRecord9(operation) && (operation.kind === "edit" || operation.kind === "formatEdit") ? group.family : undefined;
137205
+ validateBodyOperation(operation, `storyOperations[${index}].operations[${operationIndex}]`, problems, { noteMarkerFamily });
136994
137206
  });
136995
137207
  });
136996
137208
  }
@@ -138970,6 +139182,33 @@ function matchingRevisionAnnotationKeys(annotations, revisions, partUri, paragra
138970
139182
  }
138971
139183
  return keys;
138972
139184
  }
139185
+ function matchingParagraphMarkAnnotationKey(annotations, marker, structuralKind, paragraphStructuralAnnotationKeys) {
139186
+ const entries = annotations?.find((capture) => capture.family === "tracked-changes")?.entries ?? [];
139187
+ const exactKeys = paragraphStructuralAnnotationKeys === undefined ? null : new Set(paragraphStructuralAnnotationKeys);
139188
+ const matches = entries.filter((entry) => entry.label === `structural revision ${structuralKind}` && (entry.semanticKey?.startsWith(`structural:${structuralKind}|`) ?? false) && entry.key.includes(`|${marker.wId}|`) && (exactKeys === null || exactKeys.has(entry.key)));
139189
+ return matches.length === 1 ? matches[0].key : null;
139190
+ }
139191
+ function paragraphMarkTargetRevisionReplay(entry, annotations) {
139192
+ if (!entry)
139193
+ return null;
139194
+ const marker = parseParagraphMarkRevisionMarker(entry.paragraphPropertiesXml ?? "");
139195
+ if (!marker)
139196
+ return null;
139197
+ const structuralKind = marker.kind === "ins" ? "paragraph-mark-insertion" : "paragraph-mark-deletion";
139198
+ const key2 = matchingParagraphMarkAnnotationKey(annotations, marker, structuralKind, entry.structuralChangeAnnotationKeys);
139199
+ if (!key2)
139200
+ return null;
139201
+ return {
139202
+ key: key2,
139203
+ replay: {
139204
+ policy: "preserve-target-paragraph-mark-revision",
139205
+ kind: marker.kind,
139206
+ wId: marker.wId,
139207
+ author: marker.author,
139208
+ date: marker.date
139209
+ }
139210
+ };
139211
+ }
138973
139212
  function attachExactTargetRevisionReplay(operations, baseEntries, targetEntries, entityMatch, baseAnnotations, targetAnnotations, basePartUri, targetPartUri, entityId = (blockId) => blockId) {
138974
139213
  if (!entityMatch) {
138975
139214
  return {
@@ -138988,51 +139227,69 @@ function attachExactTargetRevisionReplay(operations, baseEntries, targetEntries,
138988
139227
  const replayOperations = operations.map((operation) => {
138989
139228
  if (operation.kind === "insert" || operation.kind === "insertAtStart") {
138990
139229
  const targetEntry2 = targetById.get(entityId(operation.blockId));
138991
- if (!targetEntry2)
138992
- return operation;
138993
- const targetInspection2 = inspectDirectParagraphRevisionRuns(targetEntry2.runXml ?? "");
138994
- if (!targetInspection2 || targetInspection2.revisions.length === 0 || targetInspection2.currentText !== targetEntry2.text) {
138995
- return operation;
139230
+ let targetRevisionReplayPatch;
139231
+ let targetParagraphMarkRevisionReplayPatch;
139232
+ if (targetEntry2) {
139233
+ const targetInspection2 = inspectDirectParagraphRevisionRuns(targetEntry2.runXml ?? "");
139234
+ if (targetInspection2 && targetInspection2.revisions.length > 0 && targetInspection2.currentText === targetEntry2.text) {
139235
+ const targetAnnotationKeys2 = matchingRevisionAnnotationKeys(targetAnnotations, targetInspection2.revisions, targetPartUri, targetEntry2.trackedChangeAnnotationKeys);
139236
+ if (targetAnnotationKeys2) {
139237
+ for (const key2 of targetAnnotationKeys2)
139238
+ coveredTargetAnnotations.add(key2);
139239
+ changedTrackedXmlReplayed = true;
139240
+ targetRevisionReplayPatch = {
139241
+ targetRevisionReplay: {
139242
+ policy: "preserve-target-revision-set",
139243
+ structuralAction: "insert",
139244
+ originalText: targetInspection2.originalText,
139245
+ revisionWIds: targetInspection2.revisions.map((revision) => revision.wId)
139246
+ }
139247
+ };
139248
+ }
139249
+ }
139250
+ const markResult = paragraphMarkTargetRevisionReplay(targetEntry2, targetAnnotations);
139251
+ if (markResult) {
139252
+ coveredTargetAnnotations.add(markResult.key);
139253
+ changedTrackedXmlReplayed = true;
139254
+ targetParagraphMarkRevisionReplayPatch = { targetParagraphMarkRevisionReplay: markResult.replay };
139255
+ }
138996
139256
  }
138997
- const targetAnnotationKeys2 = matchingRevisionAnnotationKeys(targetAnnotations, targetInspection2.revisions, targetPartUri, targetEntry2.trackedChangeAnnotationKeys);
138998
- if (!targetAnnotationKeys2)
139257
+ if (!targetRevisionReplayPatch && !targetParagraphMarkRevisionReplayPatch)
138999
139258
  return operation;
139000
- for (const key2 of targetAnnotationKeys2)
139001
- coveredTargetAnnotations.add(key2);
139002
- changedTrackedXmlReplayed = true;
139003
- return {
139004
- ...operation,
139005
- targetRevisionReplay: {
139006
- policy: "preserve-target-revision-set",
139007
- structuralAction: "insert",
139008
- originalText: targetInspection2.originalText,
139009
- revisionWIds: targetInspection2.revisions.map((revision) => revision.wId)
139010
- }
139011
- };
139259
+ return { ...operation, ...targetRevisionReplayPatch, ...targetParagraphMarkRevisionReplayPatch };
139012
139260
  }
139013
139261
  if (operation.kind === "delete") {
139014
139262
  const baseEntry2 = baseById.get(entityId(operation.blockId));
139015
- if (!baseEntry2)
139016
- return operation;
139017
- const baseInspection2 = inspectDirectParagraphRevisionRuns(baseEntry2.runXml ?? "");
139018
- if (!baseInspection2 || baseInspection2.revisions.length === 0 || baseInspection2.currentText !== baseEntry2.text) {
139019
- return operation;
139263
+ let targetRevisionReplayPatch;
139264
+ let targetParagraphMarkRevisionReplayPatch;
139265
+ if (baseEntry2) {
139266
+ const baseInspection2 = inspectDirectParagraphRevisionRuns(baseEntry2.runXml ?? "");
139267
+ if (baseInspection2 && baseInspection2.revisions.length > 0 && baseInspection2.currentText === baseEntry2.text) {
139268
+ const baseAnnotationKeys2 = matchingRevisionAnnotationKeys(baseAnnotations, baseInspection2.revisions, basePartUri, baseEntry2.trackedChangeAnnotationKeys);
139269
+ if (baseAnnotationKeys2) {
139270
+ for (const key2 of baseAnnotationKeys2)
139271
+ coveredBaseAnnotations.add(key2);
139272
+ changedTrackedXmlReplayed = true;
139273
+ targetRevisionReplayPatch = {
139274
+ targetRevisionReplay: {
139275
+ policy: "preserve-target-revision-set",
139276
+ structuralAction: "delete",
139277
+ originalText: baseInspection2.originalText,
139278
+ revisionWIds: baseInspection2.revisions.map((revision) => revision.wId)
139279
+ }
139280
+ };
139281
+ }
139282
+ }
139283
+ const markResult = paragraphMarkTargetRevisionReplay(baseEntry2, baseAnnotations);
139284
+ if (markResult) {
139285
+ coveredBaseAnnotations.add(markResult.key);
139286
+ changedTrackedXmlReplayed = true;
139287
+ targetParagraphMarkRevisionReplayPatch = { targetParagraphMarkRevisionReplay: markResult.replay };
139288
+ }
139020
139289
  }
139021
- const baseAnnotationKeys2 = matchingRevisionAnnotationKeys(baseAnnotations, baseInspection2.revisions, basePartUri, baseEntry2.trackedChangeAnnotationKeys);
139022
- if (!baseAnnotationKeys2)
139290
+ if (!targetRevisionReplayPatch && !targetParagraphMarkRevisionReplayPatch)
139023
139291
  return operation;
139024
- for (const key2 of baseAnnotationKeys2)
139025
- coveredBaseAnnotations.add(key2);
139026
- changedTrackedXmlReplayed = true;
139027
- return {
139028
- ...operation,
139029
- targetRevisionReplay: {
139030
- policy: "preserve-target-revision-set",
139031
- structuralAction: "delete",
139032
- originalText: baseInspection2.originalText,
139033
- revisionWIds: baseInspection2.revisions.map((revision) => revision.wId)
139034
- }
139035
- };
139292
+ return { ...operation, ...targetRevisionReplayPatch, ...targetParagraphMarkRevisionReplayPatch };
139036
139293
  }
139037
139294
  const baseEntryId = entityId(operation.blockId);
139038
139295
  const baseEntry = baseById.get(baseEntryId);
@@ -139106,7 +139363,7 @@ function attachExactTargetRevisionReplayToStories(groups, base2, target, matchRe
139106
139363
  });
139107
139364
  return { groups: replayGroups, coveredBaseAnnotations, coveredTargetAnnotations, changedTrackedXmlReplayed };
139108
139365
  }
139109
- function firstUnsafeReplayReason(operations, noteLifecycle = [], targetStories = [], baseBody = []) {
139366
+ function firstUnsafeReplayReason(operations, noteLifecycle = [], targetStories = [], baseBody = [], noteMarkerFamily) {
139110
139367
  const createdNoteReferences = noteLifecycle.filter((operation) => operation.kind === "create-note-definition" || operation.kind === "create-note-story").map((operation) => ({ family: operation.family, noteId: operation.noteId }));
139111
139368
  const retainedNoteReferences = targetStories.flatMap((story) => (story.family === "footnotes" || story.family === "endnotes") && story.noteId ? [{ family: story.family, noteId: story.noteId }] : []);
139112
139369
  const allowedNoteReferences = [...createdNoteReferences, ...retainedNoteReferences];
@@ -139116,7 +139373,7 @@ function firstUnsafeReplayReason(operations, noteLifecycle = [], targetStories =
139116
139373
  continue;
139117
139374
  const result = validateCompareReplayPayload(operation, {
139118
139375
  allowedNoteReferences,
139119
- ...operation.kind === "edit" || operation.kind === "formatEdit" ? { baseRunXml: baseRunByBlockId.get(operation.blockId) } : {}
139376
+ ...operation.kind === "edit" || operation.kind === "formatEdit" ? { baseRunXml: baseRunByBlockId.get(operation.blockId), noteMarkerFamily } : {}
139120
139377
  });
139121
139378
  if (!result.ok)
139122
139379
  return result.reason;
@@ -139310,7 +139567,9 @@ function planCompare(base2, target) {
139310
139567
  for (const group of storyOperations) {
139311
139568
  if (!replayableStoryFamilies.has(group.family))
139312
139569
  continue;
139313
- const unsafeStoryReason = firstUnsafeReplayReason(group.operations);
139570
+ const noteMarkerFamily = group.family === "footnotes" || group.family === "endnotes" ? group.family : undefined;
139571
+ const baseStory = noteMarkerFamily ? base2.stories?.find((story) => story.storyId === group.storyId && story.family === group.family && story.noteId === group.noteId) : undefined;
139572
+ const unsafeStoryReason = firstUnsafeReplayReason(group.operations, [], [], baseStory?.entries ?? [], noteMarkerFamily);
139314
139573
  if (!unsafeStoryReason || unsafeStoryFamilies.has(group.family))
139315
139574
  continue;
139316
139575
  unsafeStoryFamilies.add(group.family);
@@ -222476,7 +222735,7 @@ function hasTerminalTrackedParagraphDeletion(state, groups, storyPackageOperatio
222476
222735
  if (!index)
222477
222736
  return false;
222478
222737
  return group.bodySteps.some((step2, stepIndex) => {
222479
- if (step2.kind !== "delete" || step2.targetRevisionReplay !== undefined)
222738
+ if (step2.kind !== "delete" || step2.targetRevisionReplay !== undefined || step2.targetParagraphMarkRevisionReplay !== undefined)
222480
222739
  return false;
222481
222740
  if (isBodyReplayNoteReferenceRemoval(state, group.storyId, step2, storyPackageOperations))
222482
222741
  return false;
@@ -222582,7 +222841,10 @@ function normalizeCompareBodyStep(step2, sectionSteps, referenceSteps, allowedNo
222582
222841
  return step2.targetRevisionReplay === undefined || step2.targetRevisionReplay.structuralAction === "delete" ? step2 : null;
222583
222842
  }
222584
222843
  const baseRunXml = step2.kind === "edit" || step2.kind === "formatEdit" ? liveCompareBodyRunXml(state, storyId, step2.blockId) : undefined;
222585
- if (!validateCompareBodyReplayPayload(step2, sectionSteps, referenceSteps, allowedNoteReferences, step2.text, baseRunXml))
222844
+ const noteMarkerFamily = step2.kind === "edit" || step2.kind === "formatEdit" ? storyId.startsWith("footnotes:") ? "footnotes" : storyId.startsWith("endnotes:") ? "endnotes" : undefined : undefined;
222845
+ if (noteMarkerFamily && baseRunXml && /<(?:[A-Za-z_][\w.-]*:)?(?:footnoteRef|endnoteRef)\b/.test(baseRunXml) && step2.targetRunXml === undefined)
222846
+ return null;
222847
+ if (!validateCompareBodyReplayPayload(step2, sectionSteps, referenceSteps, allowedNoteReferences, step2.text, baseRunXml, noteMarkerFamily))
222586
222848
  return null;
222587
222849
  const targetParagraphPropertiesXml = step2.targetParagraphPropertiesXml === undefined ? undefined : canonicalizeCompareBodyParagraphPropertiesXml(step2.targetParagraphPropertiesXml, sectionSteps);
222588
222850
  const targetRunXml = step2.targetRunXml === undefined ? undefined : (step2.targetRunXml.includes("<w:drawing") || step2.targetRunXml.includes("<w:fldSimple")) && baseRunXml && referenceSteps.length === 0 ? step2.targetRunXml : canonicalizeCompareBodyRunXml(step2.targetRunXml, referenceSteps);
@@ -222597,8 +222859,9 @@ function normalizeCompareBodyStep(step2, sectionSteps, referenceSteps, allowedNo
222597
222859
  targetParagraphPropertiesXml,
222598
222860
  targetRunXml,
222599
222861
  replayDependencies: "replayDependencies" in step2 ? step2.replayDependencies : undefined,
222600
- targetRevisionReplay: "targetRevisionReplay" in step2 ? step2.targetRevisionReplay : undefined
222601
- }, sectionSteps, referenceSteps, allowedNoteReferences, step2.text, baseRunXml) ? normalized : null;
222862
+ targetRevisionReplay: "targetRevisionReplay" in step2 ? step2.targetRevisionReplay : undefined,
222863
+ targetParagraphMarkRevisionReplay: "targetParagraphMarkRevisionReplay" in step2 ? step2.targetParagraphMarkRevisionReplay : undefined
222864
+ }, sectionSteps, referenceSteps, allowedNoteReferences, step2.text, baseRunXml, noteMarkerFamily) ? normalized : null;
222602
222865
  }
222603
222866
  function liveCompareBodyRunXml(state, storyId, blockId) {
222604
222867
  const entry = getStoryParagraphIndexFromState(state, storyId)?.byParaId(blockId);
@@ -222731,7 +222994,7 @@ function sourceProofBindsReference(proof, family) {
222731
222994
  const childXml = wrappedSource.slice(child.start, child.end);
222732
222995
  return isValidNoteReferenceReplayRunXml(childXml, family, proof.noteId, child.namespaceBindings) && replayCarrierXmlEquals(childXml, proof.referenceRunXml);
222733
222996
  }
222734
- function validateCompareBodyReplayPayload(payload, sectionSteps, referenceSteps, allowedNoteReferences, expectedCurrentText, baseRunXml) {
222997
+ function validateCompareBodyReplayPayload(payload, sectionSteps, referenceSteps, allowedNoteReferences, expectedCurrentText, baseRunXml, noteMarkerFamily) {
222735
222998
  if (payload.targetRunXml !== undefined && expectedCurrentText !== undefined && projectCompareReplayCurrentText(payload.targetRunXml) !== expectedCurrentText.replace(/\uFFFC/g, "")) {
222736
222999
  return false;
222737
223000
  }
@@ -222739,7 +223002,12 @@ function validateCompareBodyReplayPayload(payload, sectionSteps, referenceSteps,
222739
223002
  if (targetParagraphPropertiesXml === null)
222740
223003
  return false;
222741
223004
  const targetRunXml = payload.targetRunXml === undefined ? undefined : stripProtectedReferenceTokens(payload.targetRunXml, referenceSteps);
222742
- return targetRunXml !== null && validateCompareReplayPayload({ ...payload, targetParagraphPropertiesXml, targetRunXml }, { allowedNoteReferences, baseRunXml, allowNamespaceDeclarationDifference: baseRunXml !== undefined }).ok;
223005
+ return targetRunXml !== null && validateCompareReplayPayload({ ...payload, targetParagraphPropertiesXml, targetRunXml }, {
223006
+ allowedNoteReferences,
223007
+ baseRunXml,
223008
+ noteMarkerFamily,
223009
+ allowNamespaceDeclarationDifference: baseRunXml !== undefined
223010
+ }).ok;
222743
223011
  }
222744
223012
  function stripProtectedSectionTokens(xml, sectionSteps) {
222745
223013
  const tokens = collectProtectedSectionTokens(xml, sectionSteps);
@@ -223090,8 +223358,8 @@ function runBodyStep(input, storyId, noteId, step2, changeMode, options, pushHis
223090
223358
  if (!hasSuccessor)
223091
223359
  return rejected14(txId, "unsupported-context");
223092
223360
  }
223093
- if (step2.targetRevisionReplay !== undefined) {
223094
- if (step2.targetRevisionReplay.structuralAction !== "delete") {
223361
+ if (step2.targetRevisionReplay !== undefined || step2.targetParagraphMarkRevisionReplay !== undefined) {
223362
+ if (step2.targetRevisionReplay !== undefined && step2.targetRevisionReplay.structuralAction !== "delete") {
223095
223363
  return rejected14(txId, "unsupported-context");
223096
223364
  }
223097
223365
  const entry = getStoryParagraphIndexFromState(state, storyId)?.byParaId(step2.blockId);
@@ -223230,7 +223498,10 @@ function prepareTrackedTerminalParagraphDeleteAtState(input) {
223230
223498
  }
223231
223499
  function resolveExactStructuralRevisionDeletion(state, storyId, step2) {
223232
223500
  const replay = step2.targetRevisionReplay;
223233
- if (!replay || replay.structuralAction !== "delete")
223501
+ const markReplay = step2.targetParagraphMarkRevisionReplay;
223502
+ if (replay !== undefined && replay.structuralAction !== "delete")
223503
+ return null;
223504
+ if (replay === undefined && markReplay === undefined)
223234
223505
  return null;
223235
223506
  const entry = getStoryParagraphIndexFromState(state, storyId)?.byParaId(step2.blockId);
223236
223507
  const bytes = entry ? state.packageBytes.get(entry.partUri) : undefined;
@@ -223238,9 +223509,22 @@ function resolveExactStructuralRevisionDeletion(state, storyId, step2) {
223238
223509
  return null;
223239
223510
  const paraXml = TD59.decode(bytes.subarray(entry.byteStart, entry.byteEnd));
223240
223511
  const wrapper = readParagraphWrapper(paraXml, step2.blockId, bytes, entry.byteStart);
223241
- const inspection = inspectDirectParagraphRevisionRuns(stripElements(paraXml.slice(wrapper.contentStart, paraXml.lastIndexOf("</")), "pPr"));
223242
- if (!inspection || inspection.originalText !== replay.originalText || JSON.stringify(inspection.revisions.map((revision) => revision.wId)) !== JSON.stringify(replay.revisionWIds))
223243
- return null;
223512
+ const runContent = stripElements(paraXml.slice(wrapper.contentStart, paraXml.lastIndexOf("</")), "pPr");
223513
+ if (replay !== undefined && replay.structuralAction === "delete") {
223514
+ const inspection = inspectDirectParagraphRevisionRuns(runContent);
223515
+ if (!inspection || inspection.originalText !== replay.originalText || JSON.stringify(inspection.revisions.map((revision) => revision.wId)) !== JSON.stringify(replay.revisionWIds))
223516
+ return null;
223517
+ } else {
223518
+ const inspection = inspectDirectRunSequence(runContent);
223519
+ if (!inspection || inspection.revisions.length > 0)
223520
+ return null;
223521
+ }
223522
+ if (markReplay !== undefined) {
223523
+ const pPrXml = findFirstElement(paraXml, "pPr")?.xml ?? "";
223524
+ const marker = parseParagraphMarkRevisionMarker(pPrXml);
223525
+ if (!marker || marker.kind !== markReplay.kind || marker.wId !== markReplay.wId || marker.author !== markReplay.author || marker.date !== markReplay.date)
223526
+ return null;
223527
+ }
223244
223528
  const parsedPart = collectXmlElementRanges(TD59.decode(bytes));
223245
223529
  const paragraphCharStart = TD59.decode(bytes.subarray(0, entry.byteStart)).length;
223246
223530
  const paragraphRange = parsedPart.ranges.find((range) => range.start === paragraphCharStart && range.tag.namespaceUri === NS_W && range.tag.localName === "p");
@@ -223255,7 +223539,7 @@ function resolveExactStructuralRevisionDeletion(state, storyId, step2) {
223255
223539
  byteEnd: entry.byteEnd,
223256
223540
  charStart: paragraphRange.start,
223257
223541
  charEnd: paragraphRange.end,
223258
- revisionWIds: replay.revisionWIds
223542
+ revisionWIds: [...replay?.revisionWIds ?? [], ...markReplay ? [markReplay.wId] : []]
223259
223543
  };
223260
223544
  }
223261
223545
  function runTargetRevisionReplayCommit(input, storyId, step2, options, pushHistory) {
@@ -223383,7 +223667,7 @@ function incomingRevisionIdsCollide(input, targetPartUri, targetStart, targetEnd
223383
223667
  return true;
223384
223668
  if (liveTargetRunXml) {
223385
223669
  const previousOwner = parseTargetRevisionReplayOwner(transferFrom);
223386
- const previousInspection = previousOwner ? inspectDirectParagraphRevisionRuns(previousOwner.targetRunXml) : null;
223670
+ const previousInspection = previousOwner?.targetRunXml !== undefined ? inspectDirectParagraphRevisionRuns(previousOwner.targetRunXml) : null;
223387
223671
  if (!previousInspection)
223388
223672
  return true;
223389
223673
  for (const { wId } of previousInspection.revisions) {
@@ -223425,7 +223709,7 @@ function transferableInPlaceRevisionReplayOwner(input) {
223425
223709
  return null;
223426
223710
  const previousKey = parseTargetRevisionReplayOwner(previousOwner);
223427
223711
  const nextKey = parseTargetRevisionReplayOwner(input.replayOwner);
223428
- if (!previousKey || !nextKey || previousKey.partUri !== input.targetPartUri || nextKey.partUri !== input.targetPartUri || previousKey.blockId !== nextKey.blockId || previousKey.targetParagraphPropertiesXml !== nextKey.targetParagraphPropertiesXml || !sameTargetRevisionReplayProvenance(previousKey.targetRevisionReplay, nextKey.targetRevisionReplay))
223712
+ if (!previousKey || !nextKey || previousKey.partUri !== input.targetPartUri || nextKey.partUri !== input.targetPartUri || previousKey.blockId !== nextKey.blockId || previousKey.targetParagraphPropertiesXml !== nextKey.targetParagraphPropertiesXml || !sameTargetRevisionReplayProvenance(previousKey.targetRevisionReplay, nextKey.targetRevisionReplay) || !sameTargetParagraphMarkRevisionReplay(previousKey.targetParagraphMarkRevisionReplay, nextKey.targetParagraphMarkRevisionReplay) || previousKey.targetRunXml === undefined || nextKey.targetRunXml === undefined)
223429
223713
  return null;
223430
223714
  const previousInspection = inspectDirectParagraphRevisionRuns(previousKey.targetRunXml);
223431
223715
  if (!previousInspection || !liveInspection || JSON.stringify(previousInspection) !== JSON.stringify(liveInspection)) {
@@ -223459,7 +223743,7 @@ function transferableRevisionReplayOwner(input) {
223459
223743
  const nextKey = parseTargetRevisionReplayOwner(input.replayOwner);
223460
223744
  if (!previousKey || !nextKey || previousKey.blockId !== nextKey.blockId)
223461
223745
  return null;
223462
- if (previousKey.targetParagraphPropertiesXml !== nextKey.targetParagraphPropertiesXml || previousKey.targetRunXml !== nextKey.targetRunXml || !sameTargetRevisionReplaySet(previousKey.targetRevisionReplay, nextKey.targetRevisionReplay))
223746
+ if (previousKey.targetParagraphPropertiesXml !== nextKey.targetParagraphPropertiesXml || previousKey.targetRunXml !== nextKey.targetRunXml || !sameTargetRevisionReplaySet(previousKey.targetRevisionReplay, nextKey.targetRevisionReplay) || !sameTargetParagraphMarkRevisionReplay(previousKey.targetParagraphMarkRevisionReplay, nextKey.targetParagraphMarkRevisionReplay))
223463
223747
  return null;
223464
223748
  const previousDeletion = input.scheduledDeletions.find((deletion) => deletion.partUri === previousKey.partUri && deletion.blockId === previousKey.blockId && JSON.stringify(deletion.revisionWIds) === JSON.stringify(input.revisionWIds));
223465
223749
  return previousDeletion && input.revisionWIds.every((id) => previousDeletion.completeLiveCarrierWIds?.includes(id)) ? previousOwner : null;
@@ -223467,21 +223751,24 @@ function transferableRevisionReplayOwner(input) {
223467
223751
  function parseTargetRevisionReplayOwner(owner) {
223468
223752
  try {
223469
223753
  const key2 = JSON.parse(owner);
223470
- if (!Array.isArray(key2) || key2.length !== 5 || typeof key2[0] !== "string" || typeof key2[1] !== "string" || typeof key2[3] !== "string") {
223754
+ if (!Array.isArray(key2) || key2.length !== 6 || typeof key2[0] !== "string" || typeof key2[1] !== "string" || key2[3] !== null && typeof key2[3] !== "string") {
223471
223755
  return null;
223472
223756
  }
223473
223757
  return {
223474
223758
  partUri: key2[0],
223475
223759
  blockId: key2[1],
223476
223760
  targetParagraphPropertiesXml: key2[2],
223477
- targetRunXml: key2[3],
223478
- targetRevisionReplay: key2[4]
223761
+ targetRunXml: key2[3] === null ? undefined : key2[3],
223762
+ targetRevisionReplay: key2[4] === null ? undefined : key2[4],
223763
+ targetParagraphMarkRevisionReplay: key2[5] === null ? undefined : key2[5]
223479
223764
  };
223480
223765
  } catch {
223481
223766
  return null;
223482
223767
  }
223483
223768
  }
223484
223769
  function sameTargetRevisionReplayProvenance(left, right) {
223770
+ if (left === undefined && right === undefined)
223771
+ return true;
223485
223772
  if (!left || typeof left !== "object" || !right || typeof right !== "object")
223486
223773
  return false;
223487
223774
  const leftReplay = left;
@@ -223489,12 +223776,23 @@ function sameTargetRevisionReplayProvenance(left, right) {
223489
223776
  return leftReplay.policy === "preserve-target-revision-set" && rightReplay.policy === "preserve-target-revision-set" && leftReplay.originalText === rightReplay.originalText;
223490
223777
  }
223491
223778
  function sameTargetRevisionReplaySet(left, right) {
223779
+ if (left === undefined && right === undefined)
223780
+ return true;
223492
223781
  if (!sameTargetRevisionReplayProvenance(left, right))
223493
223782
  return false;
223494
223783
  const leftReplay = left;
223495
223784
  const rightReplay = right;
223496
223785
  return Array.isArray(leftReplay.revisionWIds) && Array.isArray(rightReplay.revisionWIds) && JSON.stringify(leftReplay.revisionWIds) === JSON.stringify(rightReplay.revisionWIds);
223497
223786
  }
223787
+ function sameTargetParagraphMarkRevisionReplay(left, right) {
223788
+ if (left === undefined && right === undefined)
223789
+ return true;
223790
+ if (!left || typeof left !== "object" || !right || typeof right !== "object")
223791
+ return false;
223792
+ const leftReplay = left;
223793
+ const rightReplay = right;
223794
+ return leftReplay.policy === "preserve-target-paragraph-mark-revision" && rightReplay.policy === "preserve-target-paragraph-mark-revision" && leftReplay.kind === rightReplay.kind && leftReplay.wId === rightReplay.wId && leftReplay.author === rightReplay.author && leftReplay.date === rightReplay.date;
223795
+ }
223498
223796
  function applyRevisionReplayOwnershipTransfers(state, transfers) {
223499
223797
  const reservations = state.idReservations.revisionWIds.replayOwners;
223500
223798
  for (const transfer of transfers) {
@@ -223580,22 +223878,36 @@ function targetRevisionReplayOwner(partUri, step2, fallbackParagraphPropertiesXm
223580
223878
  step2.blockId,
223581
223879
  step2.targetParagraphPropertiesXml ?? fallbackParagraphPropertiesXml ?? null,
223582
223880
  step2.targetRunXml,
223583
- step2.targetRevisionReplay
223881
+ step2.targetRevisionReplay,
223882
+ "targetParagraphMarkRevisionReplay" in step2 ? step2.targetParagraphMarkRevisionReplay : undefined
223584
223883
  ]);
223585
223884
  }
223586
223885
  function prepareExactTargetRevisionInsert(input, partUri, insertByte, step2) {
223587
223886
  const replay = step2.targetRevisionReplay;
223588
- if (!replay)
223887
+ const markReplay = step2.targetParagraphMarkRevisionReplay;
223888
+ if (!replay && !markReplay)
223589
223889
  return null;
223590
- if (replay.structuralAction !== "insert" || !step2.targetRunXml)
223591
- return false;
223890
+ const revisionWIds = [];
223891
+ if (replay !== undefined) {
223892
+ if (replay.structuralAction !== "insert" || !step2.targetRunXml)
223893
+ return false;
223894
+ const inspection = inspectDirectParagraphRevisionRuns(step2.targetRunXml);
223895
+ if (!inspection || inspection.currentText !== step2.text || inspection.originalText !== replay.originalText || JSON.stringify(inspection.revisions.map((revision) => revision.wId)) !== JSON.stringify(replay.revisionWIds))
223896
+ return false;
223897
+ revisionWIds.push(...replay.revisionWIds);
223898
+ }
223899
+ if (markReplay !== undefined) {
223900
+ const marker = parseParagraphMarkRevisionMarker(step2.targetParagraphPropertiesXml ?? "");
223901
+ if (!marker || marker.kind !== markReplay.kind || marker.wId !== markReplay.wId || marker.author !== markReplay.author || marker.date !== markReplay.date)
223902
+ return false;
223903
+ revisionWIds.push(markReplay.wId);
223904
+ }
223592
223905
  const replayOwner = targetRevisionReplayOwner(partUri, step2);
223593
223906
  const ownershipTransfers = [];
223594
- const inspection = inspectDirectParagraphRevisionRuns(step2.targetRunXml);
223595
- if (!inspection || inspection.currentText !== step2.text || inspection.originalText !== replay.originalText || JSON.stringify(inspection.revisions.map((revision) => revision.wId)) !== JSON.stringify(replay.revisionWIds) || incomingRevisionIdsCollide(input, partUri, insertByte, insertByte, replay.revisionWIds, replayOwner, ownershipTransfers))
223907
+ if (incomingRevisionIdsCollide(input, partUri, insertByte, insertByte, revisionWIds, replayOwner, ownershipTransfers))
223596
223908
  return false;
223597
223909
  applyRevisionReplayOwnershipTransfers(input.state, ownershipTransfers);
223598
- for (const wId of replay.revisionWIds)
223910
+ for (const wId of revisionWIds)
223599
223911
  reserveRevisionWIdForReplay(input.state, wId, replayOwner);
223600
223912
  return true;
223601
223913
  }
@@ -223717,6 +224029,24 @@ function unchangedBookmarkReferenceSteps(oldRuns, targetRuns) {
223717
224029
  afterNamespaceBindings: bookmarkBindings
223718
224030
  }];
223719
224031
  }
224032
+ function retainedNoteMarkerRuns(oldRuns, targetRuns, storyId) {
224033
+ const markerPattern = /<(?:[A-Za-z_][\w.-]*:)?(?:footnoteRef|endnoteRef)\b/;
224034
+ if (!markerPattern.test(oldRuns) && !markerPattern.test(targetRuns)) {
224035
+ return { markerRunXml: "", oldRuns, targetRuns };
224036
+ }
224037
+ const family = storyId.startsWith("footnotes:") ? "footnotes" : storyId.startsWith("endnotes:") ? "endnotes" : null;
224038
+ if (!family)
224039
+ return null;
224040
+ const oldMarker = splitLeadingNoteMarkerRun(oldRuns, family);
224041
+ const targetMarker = splitLeadingNoteMarkerRun(targetRuns, family);
224042
+ if (!oldMarker || !targetMarker || !sameNoteMarkerRunXml(oldMarker.markerRunXml, targetMarker.markerRunXml))
224043
+ return null;
224044
+ return {
224045
+ markerRunXml: oldMarker.markerRunXml,
224046
+ oldRuns: oldMarker.remainingRunXml,
224047
+ targetRuns: targetMarker.remainingRunXml
224048
+ };
224049
+ }
223720
224050
  function runCompareBodyEditCommit(input, storyId, step2, changeMode, options, pushHistory, referenceSteps) {
223721
224051
  const { state, txId } = input;
223722
224052
  const partUri = storyPartUriFromStoryId2(storyId);
@@ -223738,6 +224068,9 @@ function runCompareBodyEditCommit(input, storyId, step2, changeMode, options, pu
223738
224068
  const closeStart = paraXml.lastIndexOf("</");
223739
224069
  const innerXml = closeStart > openEnd ? paraXml.slice(openEnd, closeStart) : "";
223740
224070
  const oldRunsRaw = stripElements(innerXml, "pPr");
224071
+ const retainedMarker = retainedNoteMarkerRuns(oldRunsRaw, newRuns, storyId);
224072
+ if (!retainedMarker)
224073
+ return rejected14(txId, "unsupported-context");
223741
224074
  const stableBookmarkSteps = unchangedBookmarkReferenceSteps(oldRunsRaw, newRuns);
223742
224075
  if (stableBookmarkSteps === null && referenceSteps.length === 0)
223743
224076
  return rejected14(txId, "unsupported-context");
@@ -223756,10 +224089,10 @@ function runCompareBodyEditCommit(input, storyId, step2, changeMode, options, pu
223756
224089
  storyId
223757
224090
  });
223758
224091
  }
223759
- const oldRunsDel = oldRunsRaw.replace(/<((?:[\w.-]+:)?)t(\b[^>]*)>/g, "<$1delText$2>").replace(/<\/((?:[\w.-]+:)?)t>/g, "</$1delText>");
224092
+ const oldRunsDel = retainedMarker.oldRuns.replace(/<((?:[\w.-]+:)?)t(\b[^>]*)>/g, "<$1delText$2>").replace(/<\/((?:[\w.-]+:)?)t>/g, "</$1delText>");
223760
224093
  const hunkStamps = makeCompareHunkStampSource(stamps, input);
223761
- const retainedCarrier = newRuns.includes("<w:drawing") || newRuns.includes("<w:fldSimple") && protectedReferenceSteps.length === 0;
223762
- const protectedRuns = retainedCarrier ? protectedReferenceSteps.length === 0 ? renderTrackedRunsWithRetainedCarrier(oldRunsRaw, newRuns, hunkStamps.next, paragraphWrapper.wordprocessingPrefix, bytes, entry.byteStart, entry.byteEnd) : null : renderTrackedRunsWithProtectedReferences(oldRunsRaw, newRuns, protectedReferenceSteps, hunkStamps.next, paragraphWrapper.wordprocessingPrefix);
224094
+ const retainedCarrier = retainedMarker.targetRuns.includes("<w:drawing") || retainedMarker.targetRuns.includes("<w:fldSimple") && protectedReferenceSteps.length === 0;
224095
+ const protectedRuns = retainedCarrier ? protectedReferenceSteps.length === 0 ? renderTrackedRunsWithRetainedCarrier(retainedMarker.oldRuns, retainedMarker.targetRuns, hunkStamps.next, paragraphWrapper.wordprocessingPrefix, bytes, entry.byteStart, entry.byteEnd) : null : renderTrackedRunsWithProtectedReferences(retainedMarker.oldRuns, retainedMarker.targetRuns, protectedReferenceSteps, hunkStamps.next, paragraphWrapper.wordprocessingPrefix);
223763
224096
  if (retainedCarrier && !protectedRuns)
223764
224097
  return rejected14(txId, "unsupported-context");
223765
224098
  if (!protectedRuns && stableBookmarkSteps?.length)
@@ -223772,10 +224105,10 @@ function runCompareBodyEditCommit(input, storyId, step2, changeMode, options, pu
223772
224105
  } else {
223773
224106
  const fallbackPair = hunkStamps.next();
223774
224107
  delXml = oldRunsDel ? wrapTracked("del", oldRunsDel, fallbackPair.del, "rsidDel", paragraphWrapper.wordprocessingPrefix) : "";
223775
- insXml = newRuns ? wrapTracked("ins", newRuns, fallbackPair.ins, "rsidR", paragraphWrapper.wordprocessingPrefix) : "";
224108
+ insXml = retainedMarker.targetRuns ? wrapTracked("ins", retainedMarker.targetRuns, fallbackPair.ins, "rsidR", paragraphWrapper.wordprocessingPrefix) : "";
223776
224109
  }
223777
224110
  const trackedPPrXml = buildTrackedParagraphProperties(targetParagraphPropertiesXml, pPrXml, stamps.paragraphProperties ?? stamps.ins, paragraphWrapper.wordprocessingPrefix);
223778
- const assembledParaXml = `${paragraphWrapper.openTag}${trackedPPrXml}${delXml}${insXml}${paragraphWrapper.closeTag}`;
224111
+ const assembledParaXml = `${paragraphWrapper.openTag}${trackedPPrXml}` + `${retainedMarker.markerRunXml}${delXml}${insXml}${paragraphWrapper.closeTag}`;
223779
224112
  if (hunkStamps.usedPairs.length === 0) {
223780
224113
  newParaXml = assembledParaXml;
223781
224114
  } else {
@@ -224068,6 +224401,9 @@ function runCompareBodyFormatEditCommit(input, storyId, step2, changeMode, optio
224068
224401
  const closeStart = paraXml.lastIndexOf("</");
224069
224402
  const innerXml = closeStart > openEnd ? paraXml.slice(openEnd, closeStart) : "";
224070
224403
  const oldRunsRaw = stripElements(innerXml, "pPr");
224404
+ const retainedMarker = retainedNoteMarkerRuns(oldRunsRaw, targetRunXml, storyId);
224405
+ if (!retainedMarker)
224406
+ return rejected14(txId, "unsupported-context");
224071
224407
  const paragraphPropertiesChanged = !equivalentParagraphProperties(targetPPrXml, pPrXml);
224072
224408
  const stableBookmarkSteps = unchangedBookmarkReferenceSteps(oldRunsRaw, targetRunXml);
224073
224409
  if (stableBookmarkSteps === null && referenceSteps.length === 0)
@@ -224135,12 +224471,12 @@ function runCompareBodyFormatEditCommit(input, storyId, step2, changeMode, optio
224135
224471
  const stamps = compareTrackedStampPair(input, paragraphPropertiesChanged);
224136
224472
  if (!stamps)
224137
224473
  return rejected14(txId, "no-author-configured");
224138
- const oldRunsDel = oldRunsRaw.replace(/<((?:[\w.-]+:)?)t(\b[^>]*)>/g, "<$1delText$2>").replace(/<\/((?:[\w.-]+:)?)t>/g, "</$1delText>");
224139
- const protectedRuns = renderTrackedRunsWithProtectedReferences(oldRunsRaw, targetRunXml, protectedReferenceSteps, () => stamps, paragraphWrapper.wordprocessingPrefix);
224474
+ const oldRunsDel = retainedMarker.oldRuns.replace(/<((?:[\w.-]+:)?)t(\b[^>]*)>/g, "<$1delText$2>").replace(/<\/((?:[\w.-]+:)?)t>/g, "</$1delText>");
224475
+ const protectedRuns = renderTrackedRunsWithProtectedReferences(retainedMarker.oldRuns, retainedMarker.targetRuns, protectedReferenceSteps, () => stamps, paragraphWrapper.wordprocessingPrefix);
224140
224476
  if (!protectedRuns && stableBookmarkSteps?.length)
224141
224477
  return rejected14(txId, "unsupported-context");
224142
224478
  const delXml = protectedRuns?.xml ?? (oldRunsDel ? wrapTracked("del", oldRunsDel, stamps.del, "rsidDel", paragraphWrapper.wordprocessingPrefix) : "");
224143
- const insXml = protectedRuns ? "" : targetRunXml ? wrapTracked("ins", targetRunXml, stamps.ins, "rsidR", paragraphWrapper.wordprocessingPrefix) : "";
224479
+ const insXml = protectedRuns ? "" : retainedMarker.targetRuns ? wrapTracked("ins", retainedMarker.targetRuns, stamps.ins, "rsidR", paragraphWrapper.wordprocessingPrefix) : "";
224144
224480
  if (delXml || insXml) {
224145
224481
  createdRefs.push({ kind: "trackedChange", entityId: stamps.ins.rsid, storyId });
224146
224482
  }
@@ -224152,7 +224488,7 @@ function runCompareBodyFormatEditCommit(input, storyId, step2, changeMode, optio
224152
224488
  });
224153
224489
  }
224154
224490
  const trackedPPrXml = buildTrackedParagraphProperties(targetParagraphPropertiesXml, pPrXml, stamps.paragraphProperties ?? stamps.ins, paragraphWrapper.wordprocessingPrefix);
224155
- newParaXml = `${paragraphWrapper.openTag}${trackedPPrXml}${delXml}${insXml}${paragraphWrapper.closeTag}`;
224491
+ newParaXml = `${paragraphWrapper.openTag}${trackedPPrXml}` + `${retainedMarker.markerRunXml}${delXml}${insXml}${paragraphWrapper.closeTag}`;
224156
224492
  }
224157
224493
  } else {
224158
224494
  newParaXml = `${paragraphWrapper.openTag}${targetPPrXml}${targetRunXml}${paragraphWrapper.closeTag}`;
@@ -358786,6 +359122,10 @@ function trackedChangeAnnotationKeysForParagraph(context, paragraph4) {
358786
359122
  const fragments = getSDDocumentSessionInternalTrackedChangeCatalog(context.session).byPart.get(paragraph4.partUri) ?? [];
358787
359123
  return fragments.filter((fragment3) => fragment3.storyId === paragraph4.storyId && fragment3.sourceByteStart >= paragraph4.byteStart && fragment3.sourceByteEnd <= paragraph4.byteEnd).map(trackedChangeAnnotationKey);
358788
359124
  }
359125
+ function structuralChangeAnnotationKeysForParagraph(context, paragraph4) {
359126
+ const fragments = getSDDocumentSessionInternalTrackedChangeCatalog(context.session).structuralByPart.get(paragraph4.partUri) ?? [];
359127
+ return fragments.filter((fragment3) => fragment3.storyId === paragraph4.storyId && (fragment3.sourceByteStart ?? fragment3.byteStart) >= paragraph4.byteStart && (fragment3.sourceByteEnd ?? fragment3.byteEnd) <= paragraph4.byteEnd).map((fragment3) => fragment3.entityKey);
359128
+ }
358789
359129
  function projectFieldsReferences(context) {
358790
359130
  const entries = [];
358791
359131
  let ordinal = 0;
@@ -359731,6 +360071,7 @@ function projectStories(context, slots) {
359731
360071
  runSignature: runSignatureByOrdinal.get(p.ordinal),
359732
360072
  runXml,
359733
360073
  trackedChangeAnnotationKeys: trackedChangeAnnotationKeysForParagraph(context, p),
360074
+ structuralChangeAnnotationKeys: structuralChangeAnnotationKeysForParagraph(context, p),
359734
360075
  paragraphPropertiesXml,
359735
360076
  paragraphPropertiesSignature: computeParagraphPropertiesSignature2(paragraphPropertiesXml)
359736
360077
  };
@@ -359816,6 +360157,7 @@ function projectBody(context) {
359816
360157
  runSignature: runSignatures[ordinal],
359817
360158
  runXml,
359818
360159
  trackedChangeAnnotationKeys: trackedChangeAnnotationKeysForParagraph(context, p),
360160
+ structuralChangeAnnotationKeys: structuralChangeAnnotationKeysForParagraph(context, p),
359819
360161
  paragraphPropertiesXml,
359820
360162
  paragraphPropertiesSignature: computeParagraphPropertiesSignature2(paragraphPropertiesXml)
359821
360163
  };
@@ -360040,7 +360382,7 @@ function applyComparePlan(context, plan, options = {}) {
360040
360382
  const appliedFamilySet = new Set;
360041
360383
  if (plan.bodyOperations.length > 0)
360042
360384
  appliedFamilySet.add("body");
360043
- const appliedTargetRevisionReplay = plan.bodyOperations.some((operation) => ("targetRevisionReplay" in operation) && operation.targetRevisionReplay !== undefined) || storyGroups.some((group) => group.bodySteps.some((step3) => step3.targetRevisionReplay !== undefined));
360385
+ const appliedTargetRevisionReplay = plan.bodyOperations.some((operation) => ("targetRevisionReplay" in operation) && operation.targetRevisionReplay !== undefined || ("targetParagraphMarkRevisionReplay" in operation) && operation.targetParagraphMarkRevisionReplay !== undefined) || storyGroups.some((group) => group.bodySteps.some((step3) => step3.targetRevisionReplay !== undefined || ("targetParagraphMarkRevisionReplay" in step3) && step3.targetParagraphMarkRevisionReplay !== undefined));
360044
360386
  if (appliedTargetRevisionReplay)
360045
360387
  appliedFamilySet.add("tracked-changes");
360046
360388
  for (const group of storyGroups) {
@@ -363370,7 +363712,8 @@ function buildHeaderFooterLifecyclePlan(base3, target) {
363370
363712
  const after = targetParts.get(partUri);
363371
363713
  const kind = after?.kind ?? before.kind;
363372
363714
  const relationshipsChanged = !headerFooterPartRelationshipsEqual(before?.relationshipsBytes ?? null, after?.relationshipsBytes ?? null);
363373
- const changed = !before || !after || !numbersEqual(before.bytes, after.bytes) || relationshipsChanged;
363715
+ const contentChanged = Boolean(before && after && (before.bytes.length !== after.bytes.length || before.bytes.some((value2, index2) => value2 !== after.bytes[index2])));
363716
+ const changed = !before || !after || contentChanged || relationshipsChanged;
363374
363717
  if (!changed)
363375
363718
  continue;
363376
363719
  if (hasUnsafeRelationshipDependencyChange(before, after, relationshipsChanged)) {
@@ -363387,7 +363730,7 @@ function buildHeaderFooterLifecyclePlan(base3, target) {
363387
363730
  });
363388
363731
  } else if (before && !after) {
363389
363732
  rewrites.push({ family: "header-footer-parts", partUri, kind: "remove" });
363390
- } else if (before && after && !numbersEqual(before.bytes, after.bytes)) {
363733
+ } else if (before && after && contentChanged) {
363391
363734
  contentRewrites.push({
363392
363735
  family: "header-footer-parts",
363393
363736
  partUri,
@@ -365053,6 +365396,17 @@ function isCommentRelationshipSemanticKey(semanticKey) {
365053
365396
  const relType = semanticKey.slice(sep + 1);
365054
365397
  return /\/relationships\/(?:comments|commentsExtended|commentsIds|commentsExtensible|threadedComments|people)$/i.test(relType);
365055
365398
  }
365399
+ function isResolutionSidecarAddition(key2, targetEntry) {
365400
+ if (!targetEntry)
365401
+ return false;
365402
+ if (key2 === "ct:override:/word/commentsExtended.xml") {
365403
+ return targetEntry.semanticKey === key2 && targetEntry.contentSignature === sha256HexSync(TE62.encode("override:/word/commentsExtended.xml=" + "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml"));
365404
+ }
365405
+ if (!key2.startsWith("rel:/word/document.xml|"))
365406
+ return false;
365407
+ const type = "http://schemas.microsoft.com/office/2011/relationships/commentsExtended";
365408
+ return targetEntry.semanticKey === `/word/document.xml|${type}` && targetEntry.contentSignature === sha256HexSync(TE62.encode(`type:${type}#mode:Internal#target:/word/commentsExtended.xml`));
365409
+ }
365056
365410
  function isCommentScopedPackageKey(context, key2, presentInBase, hasCommentCreate, targetEntry) {
365057
365411
  if (key2.startsWith("ct:")) {
365058
365412
  const uri = key2.slice(key2.indexOf(":", 3) + 1);
@@ -365088,10 +365442,15 @@ function packageGraphKeysNotCoveredByComments(context, base3, target, steps) {
365088
365442
  changedKeys.add(key2);
365089
365443
  const hasCommentCreate = steps.some((s) => s.kind === "create");
365090
365444
  const hasCommentDelete = steps.some((s) => s.kind === "delete");
365445
+ const hasRootResolution = steps.some((s) => s.kind === "set-resolved" && s.resolved && !s.targetIsReply && s.targetParentParaId === null);
365446
+ const addedResolutionSidecarKeys = [...changedKeys].filter((key2) => !baseSigs.has(key2) && targetSigs.has(key2) && isResolutionSidecarAddition(key2, targetEntries.get(key2)));
365447
+ const coversResolutionSidecar = hasRootResolution && addedResolutionSidecarKeys.length === 2 && addedResolutionSidecarKeys.includes("ct:override:/word/commentsExtended.xml");
365091
365448
  const notCovered = [];
365092
365449
  for (const key2 of changedKeys) {
365093
365450
  const presentInBase = baseSigs.has(key2);
365094
365451
  const presentInTarget = targetSigs.has(key2);
365452
+ if (coversResolutionSidecar && addedResolutionSidecarKeys.includes(key2))
365453
+ continue;
365095
365454
  let lifecycleCoversEntry = false;
365096
365455
  if (presentInBase !== presentInTarget) {
365097
365456
  lifecycleCoversEntry = presentInBase ? hasCommentDelete : hasCommentCreate;
@@ -369701,16 +370060,19 @@ function validateFullDiffApplyConsistency(diff, payload, physicalPlan, canonical
369701
370060
  }
369702
370061
  return problems;
369703
370062
  }
370063
+ function hasAnyTargetRevisionReplay(operation) {
370064
+ return "targetRevisionReplay" in operation && operation.targetRevisionReplay !== undefined || "targetParagraphMarkRevisionReplay" in operation && operation.targetParagraphMarkRevisionReplay !== undefined;
370065
+ }
369704
370066
  function buildApplyOperationCounts(applyPlan) {
369705
370067
  const counts = new Map;
369706
370068
  let revisionReplayCount = 0;
369707
370069
  if (applyPlan.bodyOperations.length > 0) {
369708
370070
  counts.set("body", applyPlan.bodyOperations.length);
369709
- revisionReplayCount += applyPlan.bodyOperations.filter((operation) => ("targetRevisionReplay" in operation) && operation.targetRevisionReplay !== undefined).length;
370071
+ revisionReplayCount += applyPlan.bodyOperations.filter(hasAnyTargetRevisionReplay).length;
369710
370072
  }
369711
370073
  for (const group of applyPlan.storyOperations ?? []) {
369712
370074
  counts.set(group.family, (counts.get(group.family) ?? 0) + group.operations.length);
369713
- revisionReplayCount += group.operations.filter((operation) => ("targetRevisionReplay" in operation) && operation.targetRevisionReplay !== undefined).length;
370075
+ revisionReplayCount += group.operations.filter(hasAnyTargetRevisionReplay).length;
369714
370076
  }
369715
370077
  if (revisionReplayCount > 0)
369716
370078
  counts.set("tracked-changes", revisionReplayCount);
@@ -369721,8 +370083,8 @@ function buildApplyOperationCounts(applyPlan) {
369721
370083
  }
369722
370084
  function setRuntimeBodyOperationCounts(counts, applyPlan, bodyOperations) {
369723
370085
  counts.set("body", bodyOperations.length);
369724
- const storyRevisionReplayCount = (applyPlan.storyOperations ?? []).reduce((total, group) => total + group.operations.filter((operation) => operation.targetRevisionReplay !== undefined).length, 0);
369725
- const bodyRevisionReplayCount = bodyOperations.filter((operation) => operation.targetRevisionReplay !== undefined).length;
370086
+ const storyRevisionReplayCount = (applyPlan.storyOperations ?? []).reduce((total, group) => total + group.operations.filter(hasAnyTargetRevisionReplay).length, 0);
370087
+ const bodyRevisionReplayCount = bodyOperations.filter(hasAnyTargetRevisionReplay).length;
369726
370088
  const revisionReplayCount = storyRevisionReplayCount + bodyRevisionReplayCount;
369727
370089
  if (revisionReplayCount > 0)
369728
370090
  counts.set("tracked-changes", revisionReplayCount);
@@ -369770,16 +370132,27 @@ function throwLocalizedBodyCorrespondenceError(sectionSteps, referenceSteps) {
369770
370132
  unsupportedReason: "section-reference-replay-unsafe"
369771
370133
  });
369772
370134
  }
370135
+ function paragraphMarkReplayOf(operation) {
370136
+ return operation.kind === "insert" || operation.kind === "insertAtStart" || operation.kind === "delete" ? operation.targetParagraphMarkRevisionReplay : undefined;
370137
+ }
369773
370138
  function mergeCanonicalRevisionReplay(derivedOperations, canonicalOperations) {
369774
370139
  return derivedOperations.map((derived) => {
369775
- const candidates = canonicalOperations.filter((canonical) => sameBodyOperationIdentity(derived, canonical));
370140
+ const candidates = canonicalOperations.filter((canonical2) => sameBodyOperationIdentity(derived, canonical2));
369776
370141
  if (candidates.length !== 1)
369777
370142
  return derived;
369778
- const replay = candidates[0].targetRevisionReplay;
369779
- if (replay === undefined || derived.targetRevisionReplay !== undefined)
370143
+ const canonical = candidates[0];
370144
+ const replay = canonical.targetRevisionReplay;
370145
+ const markReplay = paragraphMarkReplayOf(canonical);
370146
+ const wantsReplay = replay !== undefined && derived.targetRevisionReplay === undefined;
370147
+ const wantsMarkReplay = markReplay !== undefined && paragraphMarkReplayOf(derived) === undefined;
370148
+ if (!wantsReplay && !wantsMarkReplay)
369780
370149
  return derived;
369781
- const merged = { ...derived, targetRevisionReplay: replay };
369782
- if (derived.kind === "delete" && replay.structuralAction === "delete")
370150
+ const merged = {
370151
+ ...derived,
370152
+ ...wantsReplay ? { targetRevisionReplay: replay } : {},
370153
+ ...wantsMarkReplay ? { targetParagraphMarkRevisionReplay: markReplay } : {}
370154
+ };
370155
+ if (derived.kind === "delete" && (merged.targetRevisionReplay === undefined || merged.targetRevisionReplay.structuralAction === "delete"))
369783
370156
  return merged;
369784
370157
  return validateCompareReplayPayload(merged).ok ? merged : derived;
369785
370158
  });
@@ -370104,8 +370477,9 @@ function findStructurallyUnsupportedOperationFamilies(context, runtimeApplyPlan,
370104
370477
  return bodyStructuralIds.editDelete.has(op.blockId.toUpperCase()) && !localizedReferenceEditIsProtected(op.targetRunXml, referenceSteps) && !(referenceSteps.length === 0 && localizedRetainedFieldEditIsProtected(op.targetRunXml));
370105
370478
  }
370106
370479
  if (op.kind === "delete") {
370107
- if (op.targetRevisionReplay?.structuralAction === "delete")
370480
+ if (op.targetRevisionReplay?.structuralAction === "delete" || op.targetParagraphMarkRevisionReplay !== undefined) {
370108
370481
  return false;
370482
+ }
370109
370483
  return bodyStructuralIds.editDelete.has(op.blockId.toUpperCase());
370110
370484
  }
370111
370485
  if (op.kind === "formatEdit")
@@ -370135,8 +370509,9 @@ function findStructurallyUnsupportedOperationFamilies(context, runtimeApplyPlan,
370135
370509
  return storyStructuralIds.editDelete.has(op.blockId.toUpperCase());
370136
370510
  }
370137
370511
  if (op.kind === "delete") {
370138
- if (op.targetRevisionReplay?.structuralAction === "delete")
370512
+ if (op.targetRevisionReplay?.structuralAction === "delete" || op.targetParagraphMarkRevisionReplay !== undefined) {
370139
370513
  return false;
370514
+ }
370140
370515
  return storyStructuralIds.editDelete.has(op.blockId.toUpperCase());
370141
370516
  }
370142
370517
  if (op.kind === "formatEdit")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superdoc/mcp",
3
- "version": "1.3.0-next.12",
3
+ "version": "1.3.0-next.14",
4
4
  "description": "Model Context Protocol server for SuperDoc, giving an AI agent tools to read and edit .docx files.",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0",
@@ -24,13 +24,13 @@
24
24
  ],
25
25
  "dependencies": {
26
26
  "@modelcontextprotocol/sdk": "^1.26.0",
27
- "@superdoc/sdk": "2.16.0-next.12",
27
+ "@superdoc/sdk": "2.16.0-next.14",
28
28
  "debug": "^4.4.3",
29
29
  "zod": "^4.3.6"
30
30
  },
31
31
  "devDependencies": {
32
- "superdoc": "2.19.0-next.11",
33
- "@superdoc/docx-engine": "0.18.0-next.11",
32
+ "superdoc": "2.19.0-next.13",
33
+ "@superdoc/docx-engine": "0.18.0-next.13",
34
34
  "@superdoc/document-api": "0.1.0-alpha.0",
35
35
  "@types/bun": "^1.3.8",
36
36
  "@types/node": "22.19.2",