@superdoc/mcp 1.3.0-next.1 → 1.3.0-next.3

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 +1297 -51
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -31316,7 +31316,7 @@ var init_host = __esm(() => {
31316
31316
  });
31317
31317
 
31318
31318
  // ../../packages/sdk/langs/node/src/runtime/sdk-version.generated.ts
31319
- var SDK_VERSION = "2.16.0-next.1";
31319
+ var SDK_VERSION = "2.16.0-next.3";
31320
31320
 
31321
31321
  // ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
31322
31322
  import { chmodSync, existsSync } from "node:fs";
@@ -106248,7 +106248,7 @@ function refConfigSchemas() {
106248
106248
  failure: refFailureSchema
106249
106249
  };
106250
106250
  }
106251
- var trackChangeTypeValues, sourcePathSchema, diagnosticPathSchema, conversionSourceRangeSchema, conversionSourceSchema, diagnosticProperties, sdDiagnosticSchema, sdConversionDiagnosticSchema, conversionReportSchema, receiptSuccessMetadataProperties, nodeTypeValues, blockNodeTypeValues, deletableBlockNodeTypeValues, inlineNodeTypeValues, knownTargetKindValues, SHARED_DEFS, rangeSchema, positionSchema, inlineAnchorSchema, targetKindSchema, textAddressSchema, textTargetSchema, commentTrackedChangeTargetSchema, textSearchCommentTargetSchema, blockNodeAddressSchema, deletableBlockNodeAddressSchema, tableAddressSchema, tableRowAddressSchema, tableCellAddressSchema, tableOrCellAddressSchema, paragraphAddressSchema, headingAddressSchema, listItemAddressSchema, listsV2BlockTargetSchema, paragraphTargetSchema, sectionAddressSchema, watermarkSlotTargetSchema, watermarkTargetSchema, watermarkAddressSchema, watermarkHorizontalPlacementSchema, watermarkVerticalPlacementSchema, watermarkPlacementSchema, textWatermarkSchema, pictureWatermarkInputSchema, retainedPictureWatermarkInputSchema, watermarksApplyTargetSchema, pictureWatermarkInfoSchema, watermarkInfoSchema, watermarksApplySuccessSchema, watermarksApplyFailureSchema, inlineNodeAddressSchema, nodeAddressSchema, commentAddressSchema, trackedChangeAddressSchema, entityAddressSchema, selectionTargetSchema, commentTrackedChangeLinkSchema, targetLocatorSchema, deleteBehaviorSchema, resolvedHandleSchema, pageInfoSchema, receiptSuccessSchema, commentsCreateSuccessSchema, textMutationRangeSchema, textMutationResolutionSchema, textMutationSuccessSchema, matchRunSchema, matchBlockSchema, storyLocatorSchema, bodyStoryLocatorSchema, markRunColorRefSchema, markRunFontsSchema, markRunLanguagesSchema, markRunUnderlineSchema, markRunShadingSchema, markRunBorderSchema, markRunPropsSchema, trackChangeRefSchema, createParagraphSuccessSchema, createHeadingSuccessSchema, createHeadingLevelSchema, semanticHeadingLevelSchema, listsInsertSuccessSchema, listsMutateItemSuccessSchema, listsExitSuccessSchema, nodeSummarySchema, nodeInfoSchema, matchContextSchema, unknownNodeDiagnosticSchema, textSelectorSchema, planTextSelectorSchema, nodeSelectorSchema, selectorShorthandSchema, sdTextSelectorSchema, sdNodeSelectorSchema, sdSelectorSchema, sdReadOptionsSchema, sdFindInputSchema, sdNodeResultSchema, sdFindResultSchema, sdMutationResolutionSchema, evaluatedRevisionSchema, sdMutationSuccessSchema, documentInfoCountsSchema, documentInfoOutlineItemSchema, documentInfoCapabilitiesSchema, documentStyleInfoSchema, documentStylesSchema, documentDefaultsSchema, documentInfoSchema, listKindSchema, listInsertPositionSchema, listItemInfoSchema, listItemDomainItemSchema, listsListResultSchema, sectionBreakTypeSchema, sectionOrientationSchema, sectionVerticalAlignSchema, sectionDirectionSchema, sectionHeaderFooterKindSchema, sectionHeaderFooterVariantSchema, sectionLineNumberRestartSchema, sectionPageNumberFormatSchema, sectionRangeDomainSchema, sectionPageMarginsSchema, sectionHeaderFooterMarginsSchema, sectionPageSetupSchema, sectionColumnsSchema, sectionLineNumberingSchema, sectionPageNumberingSchema, sectionHeaderFooterRefsSchema, sectionBorderSpecSchema, sectionPageBordersSchema, sectionInfoSchema, sectionResolvedHandleSchema, sectionDomainItemSchema, sectionsListResultSchema, sectionMutationSuccessSchema, documentMutationSuccessSchema, paragraphMutationTargetSchema, paragraphMutationSuccessSchema, createSectionBreakSuccessSchema, commentMetadataSchema, commentInfoSchema, commentDomainItemSchema, commentsListResultSchema, trackChangeWordRevisionIdsSchema, trackChangeSourceIdsSchema, trackChangeBroadTypeEnum, trackChangeGroupingEnum, trackChangeCanonicalizationKindEnum, trackChangeAddressKindEnum, trackChangeSourcePlatformEnum, trackChangeReplacementSideSchema, trackChangeReplacementSchema, trackChangeOverlapRelationshipSchema, trackChangeOverlapLayerSchema, trackChangeOverlapInfoSchema, trackChangeFormattingSnapshotSchema, trackChangeListDeltaKindEnum, trackChangeListDeltaSideSchema, trackChangeListMemberDeltaSchema, trackChangeListDeltaSummarySchema, trackChangeTargetSchema, trackChangeSnapshotSchema, trackChangeCustomAttributeSchema, trackChangeRewriteReviewGroupSchema, trackChangeInfoSchema, trackChangeDomainItemSchema, trackChangesListResultSchema, reviewDecideRangeTargetOptions, historyActionCollaborationSchema, capabilityReasonCodeSchema, capabilityReasonsSchema, capabilitySupportDecisionSchema, capabilityFlagSchema, operationRuntimeCapabilitySchema, operationCapabilitiesSchema, inlinePropertyCapabilitySchema, inlinePropertyCapabilitiesByKeySchema, formatCapabilitiesSchema, planEngineCapabilitiesSchema, capabilitiesOutputSchema, strictEmptyObjectSchema, tableBorderColorPattern, tableBorderSpecSchema, nullableTableBorderSpecSchema, sdFragmentSchema, conversionFragmentSchema, placementSchema, nestingPolicySchema, insertInputSchema, supportCheckRichInsertInputSchema, supportCheckRichReplaceInputSchema, supportCheckProjectionInputSchema, supportCheckInputSchema, supportCheckFailureSchema, supportCheckGuardSchema, supportCheckCommonProperties, supportCheckOutputSchema, tableLocatorSchema, cellLocatorSchema, cellOrTableScopedCellLocatorSchema, tableOrCellLocatorSchema, mergeRangeLocatorSchema, tableAnchorLocationMembers, tableAnchorLocationSchema, tableCreateLocationSchema, tableMutationSuccessSchema, createTableSuccessSchema, tableMutationFailureCodes, tableMutationFailureSchema, tableMutationResultSchema, createTableResultSchema, historyActionSuccessSchema, historyActionFailureSchema, formatInlineAliasOperationSchemas, tocMutationFailureCodes, tocMutationFailureSchema, tocMutationSuccessSchema, tocEntryMutationFailureCodes, tocEntryMutationFailureSchema, tocEntryMutationSuccessSchema, hyperlinkTargetSchema, hyperlinkReadPropertiesSchema, hyperlinkDestinationSchema, hyperlinkSpecSchema, hyperlinkPatchSchema, hyperlinkDomainSchema, hyperlinkMutationSuccessSchema, hyperlinkMutationFailureCodes, hyperlinkMutationFailureSchema, hyperlinkInfoSchema, contentControlTargetSchema, contentControlMoveDestinationSchema, contentControlMutationSuccessSchema, contentControlMutationFailureSchema, ccInfoSchema, ccListResultSchema, refListQueryProperties, refListQuerySchema, discoveryOutputSchema, receiptFailureSchema, refFailureSchema, bookmarkAddressSchema, bookmarkMutation, customXmlPartTargetSchema, customXmlPartMutation, customXmlPartCreateMutation, anchoredMetadataAttachMutation, anchoredMetadataMutation, footnoteAddressSchema, footnoteConfigScopeSchema, footnoteNumberingSchema, footnoteMutation, footnoteConfig, crossRefAddressSchema, crossRefTargetSchema, crossRefDisplaySchema, crossRefMutation, indexAddressSchema, indexEntryAddressSchema, indexConfigSchema, indexEntryDataSchema, indexEntryPatchSchema, indexMutation, indexEntryMutation, captionAddressSchema, captionMutation, captionConfig, fieldAddressSchema, fieldMutation, citationAddressSchema, citationSourceAddressSchema, bibliographyAddressSchema, citationMutation, citationSourceMutation, bibliographyMutation, citationPersonSchema, citationSourceFieldsSchema, tocCreateLocationSchema, authoritiesAddressSchema, authorityEntryAddressSchema, authoritiesConfigSchema, authorityEntryDataSchema, authorityEntryPatchSchema, authoritiesMutation, authorityEntryMutation, diffCoverageSchema, diffSummarySchema, diffSnapshotSchema, diffApplyEligibilityBlockerSchema, diffApplyModeEligibilitySchema, diffApplyEligibilitySchema, diffPayloadSchema, diffApplyResultSchema, operationSchemas;
106251
+ var trackChangeTypeValues, sourcePathSchema, diagnosticPathSchema, conversionSourceRangeSchema, conversionSourceSchema, diagnosticProperties, sdDiagnosticSchema, sdConversionDiagnosticSchema, conversionReportSchema, receiptSuccessMetadataProperties, nodeTypeValues, blockNodeTypeValues, deletableBlockNodeTypeValues, inlineNodeTypeValues, knownTargetKindValues, SHARED_DEFS, rangeSchema, positionSchema, inlineAnchorSchema, targetKindSchema, textAddressSchema, textTargetSchema, commentTrackedChangeTargetSchema, textSearchCommentTargetSchema, blockNodeAddressSchema, deletableBlockNodeAddressSchema, tableAddressSchema, tableRowAddressSchema, tableCellAddressSchema, tableOrCellAddressSchema, paragraphAddressSchema, headingAddressSchema, listItemAddressSchema, listsV2BlockTargetSchema, paragraphTargetSchema, sectionAddressSchema, watermarkSlotTargetSchema, watermarkTargetSchema, watermarkAddressSchema, watermarkHorizontalPlacementSchema, watermarkVerticalPlacementSchema, watermarkPlacementSchema, textWatermarkSchema, pictureWatermarkInputSchema, retainedPictureWatermarkInputSchema, watermarksApplyTargetSchema, pictureWatermarkInfoSchema, watermarkInfoSchema, watermarksApplySuccessSchema, watermarksApplyFailureSchema, inlineNodeAddressSchema, nodeAddressSchema, commentAddressSchema, trackedChangeAddressSchema, entityAddressSchema, selectionTargetSchema, commentTrackedChangeLinkSchema, targetLocatorSchema, deleteBehaviorSchema, resolvedHandleSchema, pageInfoSchema, receiptSuccessSchema, commentsCreateSuccessSchema, textMutationRangeSchema, textMutationResolutionSchema, textMutationSuccessSchema, matchRunSchema, matchBlockSchema, storyLocatorSchema, bodyStoryLocatorSchema, markRunColorRefSchema, markRunFontsSchema, markRunLanguagesSchema, markRunUnderlineSchema, markRunShadingSchema, markRunBorderSchema, markRunPropsSchema, trackChangeRefSchema, createParagraphSuccessSchema, createHeadingSuccessSchema, createHeadingLevelSchema, semanticHeadingLevelSchema, listsInsertSuccessSchema, listsMutateItemSuccessSchema, listsExitSuccessSchema, nodeSummarySchema, nodeInfoSchema, matchContextSchema, unknownNodeDiagnosticSchema, textSelectorSchema, planTextSelectorSchema, nodeSelectorSchema, selectorShorthandSchema, sdTextSelectorSchema, sdNodeSelectorSchema, sdSelectorSchema, sdReadOptionsSchema, sdFindInputSchema, sdNodeResultSchema, sdFindResultSchema, sdMutationResolutionSchema, evaluatedRevisionSchema, sdMutationSuccessSchema, documentInfoCountsSchema, documentInfoOutlineItemSchema, documentInfoCapabilitiesSchema, documentStyleInfoSchema, documentStylesSchema, documentDefaultsSchema, documentInfoSchema, listKindSchema, listInsertPositionSchema, listItemInfoSchema, listItemDomainItemSchema, listsListResultSchema, sectionBreakTypeSchema, sectionOrientationSchema, sectionVerticalAlignSchema, sectionDirectionSchema, sectionHeaderFooterKindSchema, sectionHeaderFooterVariantSchema, sectionLineNumberRestartSchema, sectionPageNumberFormatSchema, sectionRangeDomainSchema, sectionPageMarginsSchema, sectionHeaderFooterMarginsSchema, sectionPageSetupSchema, sectionColumnsSchema, sectionLineNumberingSchema, sectionPageNumberingSchema, sectionHeaderFooterRefsSchema, sectionBorderSpecSchema, sectionPageBordersSchema, sectionInfoSchema, sectionResolvedHandleSchema, sectionDomainItemSchema, sectionsListResultSchema, sectionMutationSuccessSchema, documentMutationSuccessSchema, paragraphMutationTargetSchema, paragraphMutationSuccessSchema, createSectionBreakSuccessSchema, commentMetadataSchema, commentInfoSchema, commentDomainItemSchema, commentsListResultSchema, trackChangeWordRevisionIdsSchema, trackChangeSourceIdsSchema, trackChangeBroadTypeEnum, trackChangeGroupingEnum, trackChangeCanonicalizationKindEnum, trackChangeAddressKindEnum, trackChangeSourcePlatformEnum, trackChangeReplacementSideSchema, trackChangeReplacementSchema, trackChangeOverlapRelationshipSchema, trackChangeOverlapLayerSchema, trackChangeOverlapInfoSchema, trackChangeFormattingSnapshotSchema, trackChangeListDeltaKindEnum, trackChangeListDeltaSideSchema, trackChangeListMemberDeltaSchema, trackChangeListDeltaSummarySchema, trackChangeTargetSchema, trackChangeSnapshotSchema, trackChangeCustomAttributeSchema, trackChangeRewriteReviewGroupSchema, trackChangeComparisonHunkReviewGroupSchema, trackChangeReviewGroupSchema, trackChangeInfoSchema, trackChangeDomainItemSchema, trackChangesListResultSchema, reviewDecideRangeTargetOptions, historyActionCollaborationSchema, capabilityReasonCodeSchema, capabilityReasonsSchema, capabilitySupportDecisionSchema, capabilityFlagSchema, operationRuntimeCapabilitySchema, operationCapabilitiesSchema, inlinePropertyCapabilitySchema, inlinePropertyCapabilitiesByKeySchema, formatCapabilitiesSchema, planEngineCapabilitiesSchema, capabilitiesOutputSchema, strictEmptyObjectSchema, tableBorderColorPattern, tableBorderSpecSchema, nullableTableBorderSpecSchema, sdFragmentSchema, conversionFragmentSchema, placementSchema, nestingPolicySchema, insertInputSchema, supportCheckRichInsertInputSchema, supportCheckRichReplaceInputSchema, supportCheckProjectionInputSchema, supportCheckInputSchema, supportCheckFailureSchema, supportCheckGuardSchema, supportCheckCommonProperties, supportCheckOutputSchema, tableLocatorSchema, cellLocatorSchema, cellOrTableScopedCellLocatorSchema, tableOrCellLocatorSchema, mergeRangeLocatorSchema, tableAnchorLocationMembers, tableAnchorLocationSchema, tableCreateLocationSchema, tableMutationSuccessSchema, createTableSuccessSchema, tableMutationFailureCodes, tableMutationFailureSchema, tableMutationResultSchema, createTableResultSchema, historyActionSuccessSchema, historyActionFailureSchema, formatInlineAliasOperationSchemas, tocMutationFailureCodes, tocMutationFailureSchema, tocMutationSuccessSchema, tocEntryMutationFailureCodes, tocEntryMutationFailureSchema, tocEntryMutationSuccessSchema, hyperlinkTargetSchema, hyperlinkReadPropertiesSchema, hyperlinkDestinationSchema, hyperlinkSpecSchema, hyperlinkPatchSchema, hyperlinkDomainSchema, hyperlinkMutationSuccessSchema, hyperlinkMutationFailureCodes, hyperlinkMutationFailureSchema, hyperlinkInfoSchema, contentControlTargetSchema, contentControlMoveDestinationSchema, contentControlMutationSuccessSchema, contentControlMutationFailureSchema, ccInfoSchema, ccListResultSchema, refListQueryProperties, refListQuerySchema, discoveryOutputSchema, receiptFailureSchema, refFailureSchema, bookmarkAddressSchema, bookmarkMutation, customXmlPartTargetSchema, customXmlPartMutation, customXmlPartCreateMutation, anchoredMetadataAttachMutation, anchoredMetadataMutation, footnoteAddressSchema, footnoteConfigScopeSchema, footnoteNumberingSchema, footnoteMutation, footnoteConfig, crossRefAddressSchema, crossRefTargetSchema, crossRefDisplaySchema, crossRefMutation, indexAddressSchema, indexEntryAddressSchema, indexConfigSchema, indexEntryDataSchema, indexEntryPatchSchema, indexMutation, indexEntryMutation, captionAddressSchema, captionMutation, captionConfig, fieldAddressSchema, fieldMutation, citationAddressSchema, citationSourceAddressSchema, bibliographyAddressSchema, citationMutation, citationSourceMutation, bibliographyMutation, citationPersonSchema, citationSourceFieldsSchema, tocCreateLocationSchema, authoritiesAddressSchema, authorityEntryAddressSchema, authoritiesConfigSchema, authorityEntryDataSchema, authorityEntryPatchSchema, authoritiesMutation, authorityEntryMutation, diffCoverageSchema, diffSummarySchema, diffSnapshotSchema, diffApplyEligibilityBlockerSchema, diffApplyModeEligibilitySchema, diffApplyEligibilitySchema, diffPayloadSchema, diffApplyResultSchema, operationSchemas;
106252
106252
  var init_schemas4 = __esm(() => {
106253
106253
  init_command_catalog();
106254
106254
  init_types4();
@@ -107794,6 +107794,7 @@ var init_schemas4 = __esm(() => {
107794
107794
  }, ["name", "namespaceUri", "localName", "value"]);
107795
107795
  trackChangeRewriteReviewGroupSchema = objectSchema2({
107796
107796
  kind: { const: "text-rewrite" },
107797
+ groupOrigin: { const: "authored-operation" },
107797
107798
  role: { enum: ["parent", "child"] },
107798
107799
  parentId: { type: "string" },
107799
107800
  childChangeIds: { type: "array", items: { type: "string" } },
@@ -107806,7 +107807,26 @@ var init_schemas4 = __esm(() => {
107806
107807
  sourceIds: trackChangeSourceIdsSchema
107807
107808
  }, ["id", "type", "subtype", "sourceIds"])
107808
107809
  }
107809
- }, ["kind", "role", "childChangeIds", "members"]);
107810
+ }, ["kind", "groupOrigin", "role", "childChangeIds", "members"]);
107811
+ trackChangeComparisonHunkReviewGroupSchema = objectSchema2({
107812
+ kind: { const: "comparison-hunk" },
107813
+ groupOrigin: { const: "comparison-hunk" },
107814
+ role: { enum: ["parent", "child"] },
107815
+ parentId: { type: "string" },
107816
+ childChangeIds: { type: "array", items: { type: "string" } },
107817
+ members: {
107818
+ type: "array",
107819
+ items: objectSchema2({
107820
+ id: { type: "string" },
107821
+ type: { enum: [...trackChangeBroadTypeEnum] },
107822
+ subtype: { type: "string" },
107823
+ sourceIds: trackChangeSourceIdsSchema
107824
+ }, ["id", "type", "subtype", "sourceIds"])
107825
+ }
107826
+ }, ["kind", "groupOrigin", "role", "childChangeIds", "members"]);
107827
+ trackChangeReviewGroupSchema = {
107828
+ oneOf: [trackChangeRewriteReviewGroupSchema, trackChangeComparisonHunkReviewGroupSchema]
107829
+ };
107810
107830
  trackChangeInfoSchema = objectSchema2({
107811
107831
  address: trackedChangeAddressSchema,
107812
107832
  id: { type: "string" },
@@ -107819,7 +107839,7 @@ var init_schemas4 = __esm(() => {
107819
107839
  sourceIds: trackChangeSourceIdsSchema,
107820
107840
  wordRevisionIds: trackChangeWordRevisionIdsSchema,
107821
107841
  revisionGroupId: { type: "string" },
107822
- reviewGroup: trackChangeRewriteReviewGroupSchema,
107842
+ reviewGroup: trackChangeReviewGroupSchema,
107823
107843
  splitFromId: { oneOf: [{ type: "string" }, { type: "null" }] },
107824
107844
  replacement: trackChangeReplacementSchema,
107825
107845
  author: { type: "string" },
@@ -107870,7 +107890,7 @@ var init_schemas4 = __esm(() => {
107870
107890
  sourceIds: trackChangeSourceIdsSchema,
107871
107891
  wordRevisionIds: trackChangeWordRevisionIdsSchema,
107872
107892
  revisionGroupId: { type: "string" },
107873
- reviewGroup: trackChangeRewriteReviewGroupSchema,
107893
+ reviewGroup: trackChangeReviewGroupSchema,
107874
107894
  author: { type: "string" },
107875
107895
  authorEmail: { type: "string" },
107876
107896
  authorImage: { type: "string" },
@@ -119891,7 +119911,7 @@ function capabilityFailureResult(operationId, capability, decision) {
119891
119911
  return operationId === "templates.apply" ? Promise.resolve(result) : result;
119892
119912
  }
119893
119913
  function installCapabilityPreflight(api2, adapter) {
119894
- if (!adapter.resolve)
119914
+ if (!adapter?.resolve)
119895
119915
  return;
119896
119916
  for (const operationId of OPERATION_IDS) {
119897
119917
  if (operationId.startsWith("capabilities."))
@@ -132248,6 +132268,7 @@ function createSDTxPerfProbe() {
132248
132268
  trackedChangeTextSplices: null,
132249
132269
  trackedChangeTextSpliceMs: null,
132250
132270
  trackedChangeTextNormalizeMs: null,
132271
+ trackedChangeRunMergeMs: null,
132251
132272
  trackedChangeTextEncodeMs: null,
132252
132273
  trackedChangeSubsumedTextFragments: null,
132253
132274
  trackedChangeSubsumedFormattingFragments: null,
@@ -171362,6 +171383,7 @@ function projectTextRewriteReviewGroup(entry, logical) {
171362
171383
  const group = entry.reviewGroup;
171363
171384
  return {
171364
171385
  kind: "text-rewrite",
171386
+ groupOrigin: "authored-operation",
171365
171387
  role: group.role,
171366
171388
  ...group.parentId ? { parentId: group.parentId } : {},
171367
171389
  childChangeIds: group.ownedChildIds,
@@ -171394,6 +171416,187 @@ var init_rewrite_groups = __esm(() => {
171394
171416
  init_logical_catalog();
171395
171417
  });
171396
171418
 
171419
+ // ../../../v2/editor-core/dist/document/transactions/tracked-changes/comparison-hunk-groups.js
171420
+ function readComparisonHunkOrigin(carrier) {
171421
+ const attrs = carrier.customAttributes?.filter((attribute) => attribute.namespaceUri === COMPARISON_HUNK_NAMESPACE);
171422
+ if (!attrs || attrs.length === 0)
171423
+ return null;
171424
+ const byLocalName = (localName2) => attrs.filter((attribute) => attribute.localName === localName2);
171425
+ const idAttrs = byLocalName("originId");
171426
+ const kindAttrs = byLocalName("originKind");
171427
+ if (idAttrs.length !== 1 || kindAttrs.length !== 1)
171428
+ return null;
171429
+ const idValue = idAttrs[0].value;
171430
+ const kindValue = kindAttrs[0].value;
171431
+ if (!/^[\w.:-]{1,200}$/.test(idValue))
171432
+ return null;
171433
+ if (kindValue !== "rewrite" && kindValue !== "comparison-hunk")
171434
+ return null;
171435
+ return { id: idValue, kind: kindValue };
171436
+ }
171437
+ function stampComparisonHunkOrigins(xml, originsByRsid, source) {
171438
+ if (originsByRsid.size === 0)
171439
+ return xml;
171440
+ if ([...originsByRsid.values()].some((id) => !/^[\w.:-]{1,200}$/.test(id)))
171441
+ return null;
171442
+ const replacements = [];
171443
+ const parsed = walkXmlElements(xml, {
171444
+ fragment: true,
171445
+ additionalNamespaces: xmlFragmentAdditionalNamespaces(xml, new Map, { w: NS_W }),
171446
+ onOpenTag: ({ tag, end, namespaceBindings }) => {
171447
+ if (tag.namespaceUri !== NS_W || tag.isSelfClosing || tag.localName !== "ins" && tag.localName !== "del")
171448
+ return;
171449
+ const rsid = tag.attributes.find((attribute) => attribute.namespaceUri === NS_W && attribute.localName === (tag.localName === "ins" ? "rsidR" : "rsidDel"))?.value;
171450
+ const id = rsid ? originsByRsid.get(rsid) : undefined;
171451
+ if (!id)
171452
+ return;
171453
+ const availablePrefix = (seed) => {
171454
+ let prefix2 = seed;
171455
+ for (let index = 1;namespaceBindings[prefix2]; index += 1)
171456
+ prefix2 = `${seed}${index}`;
171457
+ return prefix2;
171458
+ };
171459
+ const prefix = availablePrefix("sdReview");
171460
+ const mc = availablePrefix("sdReviewMc");
171461
+ replacements.push({
171462
+ at: end - 1,
171463
+ text: ` xmlns:${prefix}="${COMPARISON_HUNK_NAMESPACE}" xmlns:${mc}="${MC_NAMESPACE2}" ${mc}:Ignorable="${prefix}" ${prefix}:originId="${id}" ${prefix}:originKind="comparison-hunk"`
171464
+ });
171465
+ }
171466
+ });
171467
+ if (parsed.errors.length > 0)
171468
+ return null;
171469
+ let cursor = 0;
171470
+ const chunks = [];
171471
+ for (const replacement of replacements) {
171472
+ chunks.push(xml.slice(cursor, replacement.at), replacement.text);
171473
+ cursor = replacement.at;
171474
+ }
171475
+ chunks.push(xml.slice(cursor));
171476
+ return chunks.join("");
171477
+ }
171478
+ function buildComparisonHunkReviewGroupId(storyId, origin) {
171479
+ return buildLogicalId(storyId, "comparison-hunk-group", origin);
171480
+ }
171481
+ function projectComparisonHunkGroups(input) {
171482
+ const groups = new Map;
171483
+ for (const entry of input.byId.values()) {
171484
+ if (entry.reviewGroup)
171485
+ continue;
171486
+ if (!["insertion", "deletion", "replacement"].includes(entry.type))
171487
+ continue;
171488
+ const carriers = entry.fragments;
171489
+ if (carriers.length === 0)
171490
+ continue;
171491
+ const origin = readComparisonHunkOrigin(carriers[0]);
171492
+ if (!origin || origin.kind !== "comparison-hunk")
171493
+ continue;
171494
+ if (carriers.some((carrier) => readComparisonHunkOrigin(carrier)?.id !== origin.id))
171495
+ continue;
171496
+ const id = buildComparisonHunkReviewGroupId(entry.storyId, origin.id);
171497
+ const members = groups.get(id) ?? [];
171498
+ members.push(entry);
171499
+ groups.set(id, members);
171500
+ }
171501
+ for (const [id, children] of groups) {
171502
+ children.sort((a, b) => a.documentOrderStart - b.documentOrderStart || a.id.localeCompare(b.id));
171503
+ const first = children[0];
171504
+ const fragments = children.flatMap((child) => child.fragments).sort((a, b) => a.byteStart - b.byteStart);
171505
+ const inserted = fragments.filter((fragment2) => fragment2.kind === "ins");
171506
+ const deleted = fragments.filter((fragment2) => fragment2.kind === "del");
171507
+ const type = inserted.length === 0 ? "deletion" : deleted.length === 0 ? "insertion" : "replacement";
171508
+ const wordIdInsert = inserted.find((fragment2) => fragment2.wId)?.wId ?? children.find((child) => child.sourceIds.wordIdInsert)?.sourceIds.wordIdInsert;
171509
+ const wordIdDelete = deleted.find((fragment2) => fragment2.wId)?.wId ?? children.find((child) => child.sourceIds.wordIdDelete)?.sourceIds.wordIdDelete;
171510
+ const rsids = [...new Set(children.flatMap((child) => child.sourceIds.rsids))];
171511
+ const parent = {
171512
+ ...first,
171513
+ id,
171514
+ type,
171515
+ subtype: type === "replacement" ? "text-replacement" : type === "insertion" ? "text-insertion" : "text-deletion",
171516
+ revisionGroupId: id,
171517
+ splitFromId: null,
171518
+ documentOrderStart: children.reduce((start, child) => Math.min(start, child.documentOrderStart), first.documentOrderStart),
171519
+ documentOrderEnd: children.reduce((end, child) => Math.max(end, child.documentOrderEnd), first.documentOrderEnd),
171520
+ before: { text: children.map((child) => child.before.text ?? "").join("") },
171521
+ after: { text: children.map((child) => child.after.text ?? "").join("") },
171522
+ sides: null,
171523
+ contributingRsids: rsids,
171524
+ sourceIds: {
171525
+ wordIdInsert,
171526
+ wordIdDelete,
171527
+ wordIdOther: [
171528
+ ...new Set(children.flatMap((child) => [
171529
+ ...child.sourceIds.wordIdOther,
171530
+ ...child.sourceIds.wordIdInsert ? [child.sourceIds.wordIdInsert] : [],
171531
+ ...child.sourceIds.wordIdDelete ? [child.sourceIds.wordIdDelete] : []
171532
+ ]).filter((value) => Boolean(value) && value !== wordIdInsert && value !== wordIdDelete))
171533
+ ],
171534
+ rsids
171535
+ },
171536
+ fragments,
171537
+ structuralFragments: [],
171538
+ reviewGroup: {
171539
+ kind: "comparison-hunk",
171540
+ role: "parent",
171541
+ parentId: null,
171542
+ ownedChildIds: children.map((child) => child.id),
171543
+ duplicateDisplayPolicy: "subsumed",
171544
+ members: children.flatMap((child) => child.fragments.map((fragment2) => ({
171545
+ logicalId: child.id,
171546
+ carrier: "text",
171547
+ partUri: fragment2.partUri,
171548
+ storyId: fragment2.storyId,
171549
+ rsid: fragment2.rsid,
171550
+ wordId: fragment2.wId,
171551
+ subtype: child.subtype,
171552
+ byteStart: fragment2.byteStart,
171553
+ byteEnd: fragment2.byteEnd
171554
+ })))
171555
+ }
171556
+ };
171557
+ for (const child of children) {
171558
+ child.reviewGroup = {
171559
+ kind: "comparison-hunk",
171560
+ role: "child",
171561
+ parentId: id,
171562
+ ownedChildIds: [],
171563
+ duplicateDisplayPolicy: "subsumed",
171564
+ members: []
171565
+ };
171566
+ }
171567
+ input.byId.set(id, parent);
171568
+ input.byStory.get(first.storyId).push(parent);
171569
+ }
171570
+ }
171571
+ function projectComparisonHunkReviewGroup(entry, logical) {
171572
+ if (entry.reviewGroup?.kind !== "comparison-hunk")
171573
+ return;
171574
+ const group = entry.reviewGroup;
171575
+ return {
171576
+ kind: "comparison-hunk",
171577
+ groupOrigin: "comparison-hunk",
171578
+ role: group.role,
171579
+ ...group.parentId ? { parentId: group.parentId } : {},
171580
+ childChangeIds: group.ownedChildIds,
171581
+ members: group.ownedChildIds.flatMap((id) => {
171582
+ const child = logical.byId.get(id);
171583
+ return child ? [
171584
+ {
171585
+ id,
171586
+ type: child.type,
171587
+ subtype: child.subtype,
171588
+ sourceIds: child.sourceIds
171589
+ }
171590
+ ] : [];
171591
+ })
171592
+ };
171593
+ }
171594
+ var COMPARISON_HUNK_NAMESPACE = "urn:superdoc:tracked-review:1", MC_NAMESPACE2 = "http://schemas.openxmlformats.org/markup-compatibility/2006";
171595
+ var init_comparison_hunk_groups = __esm(() => {
171596
+ init_xml_sax();
171597
+ init_logical_catalog();
171598
+ });
171599
+
171397
171600
  // ../../../v2/editor-core/dist/document/transactions/tracked-changes/table-split-paragraph.js
171398
171601
  function isEmptyTableSplitParagraph(xml, excludedStart, excludedEnd) {
171399
171602
  const shell = /\s+|<[\w.-]+:(?:p|r)\b(?:"[^"]*"|'[^']*'|[^>"'])*>|<\/[\w.-]+:(?:p|r)>/y;
@@ -172134,6 +172337,7 @@ function buildLogicalCatalogWithLookupContext(lookupContext, raw, replacementMod
172134
172337
  partXmlByUri
172135
172338
  }, lookupContext);
172136
172339
  projectRewriteGroups({ byId, byStory });
172340
+ projectComparisonHunkGroups({ byId, byStory });
172137
172341
  projectWordFormattingGroups({
172138
172342
  byId,
172139
172343
  byStory,
@@ -175981,6 +176185,14 @@ function enrichLogicalChangeExcerpts(catalog, partXmlByUri) {
175981
176185
  parent.after = { text: children.map((child) => child.after.text).filter(Boolean).join(" … ") };
175982
176186
  parent.excerpt = parent.after.text || parent.before.text || "";
175983
176187
  }
176188
+ for (const parent of catalog.byId.values()) {
176189
+ if (parent.reviewGroup?.kind !== "comparison-hunk" || parent.reviewGroup.role !== "parent")
176190
+ continue;
176191
+ const children = parent.reviewGroup.ownedChildIds.map((id) => catalog.byId.get(id));
176192
+ parent.before = { text: children.map((child) => child.before.text ?? "").join("") };
176193
+ parent.after = { text: children.map((child) => child.after.text ?? "").join("") };
176194
+ parent.excerpt = parent.after.text || parent.before.text || "";
176195
+ }
175984
176196
  }
175985
176197
  function decodePartXmlForLogicalCatalog(raw, readPartBytes2) {
175986
176198
  const out = new Map;
@@ -176136,6 +176348,7 @@ var init_logical_catalog = __esm(() => {
176136
176348
  init_numbering_catalog();
176137
176349
  init_review_groups();
176138
176350
  init_rewrite_groups();
176351
+ init_comparison_hunk_groups();
176139
176352
  init_table_split_paragraph();
176140
176353
  init_list_deltas();
176141
176354
  init_comment_range_invariance();
@@ -194832,6 +195045,19 @@ function runTrackedEditTextBatchCommit(input, edits) {
194832
195045
  return rejected2(txId, "invalid-input");
194833
195046
  afterBytes = TE16.encode(stamped);
194834
195047
  }
195048
+ const comparisonHunkGroups = new Map;
195049
+ for (const edit of blockEdits) {
195050
+ if (!edit.comparisonHunkGroupId)
195051
+ continue;
195052
+ for (const rsid of emittedByEdit.get(edit) ?? [])
195053
+ comparisonHunkGroups.set(rsid, edit.comparisonHunkGroupId);
195054
+ }
195055
+ if (comparisonHunkGroups.size > 0) {
195056
+ const stamped = stampComparisonHunkOrigins(TD39.decode(afterBytes), comparisonHunkGroups, { partUri, storyId });
195057
+ if (stamped === null)
195058
+ return rejected2(txId, "invalid-input");
195059
+ afterBytes = TE16.encode(stamped);
195060
+ }
194835
195061
  if (!bytesEqual5(beforeBytes, afterBytes)) {
194836
195062
  trackedAnnotations.push(...captureBatchTrackedAnnotations(afterBytes, new Set(blockEdits.flatMap((edit) => emittedByEdit.get(edit) ?? []))));
194837
195063
  patches.push({
@@ -199569,6 +199795,7 @@ function collectPerPartRevisions(state, partUris) {
199569
199795
  var TD39, TE16, TRACKED_WRAPPER_OPEN_RE, INLINE_CONTROL_PLACEHOLDER = "";
199570
199796
  var init_compile_edit_text = __esm(() => {
199571
199797
  init_rewrite_groups();
199798
+ init_comparison_hunk_groups();
199572
199799
  init_word_text_payload();
199573
199800
  init_textbox_atom_replacement();
199574
199801
  init_part_payload();
@@ -202959,6 +203186,119 @@ function mergeAdjacentTableXml(lookupContext, firstTableXml, secondTableXml) {
202959
203186
  function isSingleParagraphXml2(xml) {
202960
203187
  return /^<[\w.-]+:p\b[^>]*\/>$/.test(xml) || /^<[\w.-]+:p\b[\s\S]*<\/[\w.-]+:p>$/.test(xml);
202961
203188
  }
203189
+ function mergeAdjacentIdenticallyFormattedRuns(xml, namespaceBindings) {
203190
+ const fragment2 = !xml.trimStart().startsWith("<?xml");
203191
+ const additionalNamespaces = xmlFragmentAdditionalNamespaces(xml, new Map(Object.entries(namespaceBindings ?? {})), { w: NS_W4 });
203192
+ const { ranges, errors: errors4 } = collectXmlElementRanges(xml, { fragment: fragment2, additionalNamespaces });
203193
+ if (errors4.length > 0)
203194
+ return xml;
203195
+ const entries = ranges.map((range) => ({
203196
+ start: range.start,
203197
+ end: range.end,
203198
+ openEnd: range.openEnd,
203199
+ closeStart: range.closeStart,
203200
+ localName: range.tag.localName,
203201
+ namespaceUri: range.tag.namespaceUri,
203202
+ isSelfClosing: range.tag.isSelfClosing,
203203
+ parent: null
203204
+ })).sort((a, b) => a.start - b.start || b.end - a.end);
203205
+ const stack = [];
203206
+ for (const entry of entries) {
203207
+ while (stack.length > 0 && stack[stack.length - 1].end <= entry.start)
203208
+ stack.pop();
203209
+ entry.parent = stack[stack.length - 1] ?? null;
203210
+ if (!entry.isSelfClosing)
203211
+ stack.push(entry);
203212
+ }
203213
+ const directChildren = (parent) => entries.filter((entry) => entry.parent === parent);
203214
+ function classifyRun(runEntry) {
203215
+ const children = directChildren(runEntry);
203216
+ if (children.length === 0)
203217
+ return null;
203218
+ let rPrChild = null;
203219
+ let tChild = null;
203220
+ for (const child of children) {
203221
+ if (child.namespaceUri === NS_W4 && child.localName === "rPr" && !rPrChild && !tChild) {
203222
+ rPrChild = child;
203223
+ continue;
203224
+ }
203225
+ if (child.namespaceUri === NS_W4 && child.localName === "t" && !tChild) {
203226
+ tChild = child;
203227
+ continue;
203228
+ }
203229
+ return null;
203230
+ }
203231
+ if (!tChild || runEntry.isSelfClosing)
203232
+ return null;
203233
+ const formattingKey = xml.slice(runEntry.start, rPrChild ? rPrChild.end : runEntry.openEnd);
203234
+ const rPrXml = rPrChild ? xml.slice(rPrChild.start, rPrChild.end) : "";
203235
+ const text = tChild.isSelfClosing ? "" : xml.slice(tChild.openEnd, tChild.closeStart);
203236
+ const tOpenTag = xml.slice(tChild.start, tChild.openEnd);
203237
+ const tQNameMatch = /^<([^\s/>]+)/.exec(tOpenTag);
203238
+ if (!tQNameMatch)
203239
+ return null;
203240
+ return {
203241
+ entry: runEntry,
203242
+ formattingKey,
203243
+ runOpenTag: xml.slice(runEntry.start, runEntry.openEnd),
203244
+ runCloseTag: xml.slice(runEntry.closeStart, runEntry.end),
203245
+ rPrXml,
203246
+ tQName: tQNameMatch[1],
203247
+ text
203248
+ };
203249
+ }
203250
+ const edits = [];
203251
+ const paragraphs = entries.filter((entry) => entry.namespaceUri === NS_W4 && entry.localName === "p" && !entry.isSelfClosing);
203252
+ for (const paragraph of paragraphs) {
203253
+ const children = directChildren(paragraph);
203254
+ let index = 0;
203255
+ while (index < children.length) {
203256
+ const child = children[index];
203257
+ if (child.namespaceUri !== NS_W4 || child.localName !== "r") {
203258
+ index += 1;
203259
+ continue;
203260
+ }
203261
+ const first = classifyRun(child);
203262
+ if (!first) {
203263
+ index += 1;
203264
+ continue;
203265
+ }
203266
+ const group = [first];
203267
+ let next = index + 1;
203268
+ while (next < children.length) {
203269
+ const candidate2 = children[next];
203270
+ if (candidate2.namespaceUri !== NS_W4 || candidate2.localName !== "r")
203271
+ break;
203272
+ const classified = classifyRun(candidate2);
203273
+ if (!classified || classified.formattingKey !== first.formattingKey)
203274
+ break;
203275
+ group.push(classified);
203276
+ next += 1;
203277
+ }
203278
+ if (group.length > 1) {
203279
+ const mergedText = group.map((run) => run.text).join("");
203280
+ const preserve = /^\s|\s$/.test(mergedText) ? ' xml:space="preserve"' : "";
203281
+ const replacement = `${first.runOpenTag}${first.rPrXml}` + `<${first.tQName}${preserve}>${mergedText}</${first.tQName}>` + first.runCloseTag;
203282
+ edits.push({
203283
+ start: group[0].entry.start,
203284
+ end: group[group.length - 1].entry.end,
203285
+ replacement
203286
+ });
203287
+ }
203288
+ index = next;
203289
+ }
203290
+ }
203291
+ if (edits.length === 0)
203292
+ return xml;
203293
+ edits.sort((a, b) => a.start - b.start);
203294
+ let cursor = 0;
203295
+ let output = "";
203296
+ for (const edit of edits) {
203297
+ output += xml.slice(cursor, edit.start) + edit.replacement;
203298
+ cursor = edit.end;
203299
+ }
203300
+ return output + xml.slice(cursor);
203301
+ }
202962
203302
  function applyFormattingDecisionToFragment(input, lookupContext) {
202963
203303
  return withStructuralLookupContext(lookupContext, (context) => applyFormattingDecisionToFragmentWithLookupContext(context, input));
202964
203304
  }
@@ -203569,7 +203909,9 @@ function tryRunLocalTrackedChangeDecideCommit(input) {
203569
203909
  for (const decision of [...orderedDecisions].reverse()) {
203570
203910
  rewrittenXml = rewrittenXml.slice(0, decision.localFragment.byteStart) + decision.result.replacement + rewrittenXml.slice(decision.localFragment.byteEnd);
203571
203911
  }
203572
- const afterXml = normalizeBlockDeletionText(rewrittenXml);
203912
+ const hasComparisonHunkDecision = orderedDecisions.some((decision) => readComparisonHunkOrigin(decision.localFragment)?.kind === "comparison-hunk");
203913
+ const normalizedXml = normalizeBlockDeletionText(rewrittenXml);
203914
+ const afterXml = hasComparisonHunkDecision ? mergeAdjacentIdenticallyFormattedRuns(normalizedXml, state.mainStorySourceOverlay?.rootNamespaceBindings) : normalizedXml;
203573
203915
  if (!sameNoteReferences(beforeXml, afterXml)) {
203574
203916
  return null;
203575
203917
  }
@@ -203950,6 +204292,7 @@ var init_compile_tracked_change_decide_local = __esm(() => {
203950
204292
  init_catalog3();
203951
204293
  init_logical_catalog();
203952
204294
  init_decide_engine();
204295
+ init_comparison_hunk_groups();
203953
204296
  init_block_deletion_text();
203954
204297
  init_structural_inline_decision();
203955
204298
  TD42 = new TextDecoder;
@@ -204184,6 +204527,7 @@ function compileBoundedPartDecisions(input) {
204184
204527
  const shiftCandidates = [];
204185
204528
  const stories = new Set;
204186
204529
  const markerIdsByRsid = new Map;
204530
+ let hasComparisonHunkDecision = false;
204187
204531
  for (const target of input.targets) {
204188
204532
  if (target.formatting || target.structural || target.derivedStructural)
204189
204533
  continue;
@@ -204211,6 +204555,8 @@ function compileBoundedPartDecisions(input) {
204211
204555
  return { ok: false, reason: "unsupported-context" };
204212
204556
  if ((fragment2.kind === "ins" && input.decision === "reject" || fragment2.kind === "del" && input.decision === "accept") && ownerContainsTrackedHyperlink(input.xml, local.byteStart, local.byteEnd))
204213
204557
  return { ok: false, reason: "unsupported-context" };
204558
+ if (readComparisonHunkOrigin(fragment2)?.kind === "comparison-hunk")
204559
+ hasComparisonHunkDecision = true;
204214
204560
  edits.push({ start: local.byteStart, end: local.byteEnd, replacement: result.replacement });
204215
204561
  if (result.visibleTextDelta !== 0) {
204216
204562
  shiftCandidates.push({
@@ -204252,6 +204598,8 @@ function compileBoundedPartDecisions(input) {
204252
204598
  });
204253
204599
  if (!result.ok)
204254
204600
  return result;
204601
+ if (readComparisonHunkOrigin(fragment2)?.kind === "comparison-hunk")
204602
+ hasComparisonHunkDecision = true;
204255
204603
  edits.push({ start: result.spliceStart, end: result.spliceEnd, replacement: result.replacement });
204256
204604
  invalidatedRefs.push({
204257
204605
  kind: "trackedChange",
@@ -204286,9 +204634,10 @@ function compileBoundedPartDecisions(input) {
204286
204634
  }
204287
204635
  }
204288
204636
  const dedupedEdits = dedupeEdits(edits);
204289
- const xml = assemble(input.xml, dedupedEdits);
204290
- if (xml == null)
204637
+ const assembled = assemble(input.xml, dedupedEdits);
204638
+ if (assembled == null)
204291
204639
  return { ok: false, reason: "unsupported-context" };
204640
+ const xml = dedupedEdits.length > 0 && hasComparisonHunkDecision ? mergeAdjacentIdenticallyFormattedRuns(assembled, input.namespaceBindings) : assembled;
204292
204641
  return {
204293
204642
  ok: true,
204294
204643
  changed: dedupedEdits.length > 0,
@@ -204461,6 +204810,7 @@ var init_compile_tracked_change_decide_fenced = __esm(() => {
204461
204810
  init_prepared_mutation();
204462
204811
  init_patch_substrate();
204463
204812
  init_decide_engine();
204813
+ init_comparison_hunk_groups();
204464
204814
  init_catalog3();
204465
204815
  init_source_inventory();
204466
204816
  TD43 = new TextDecoder;
@@ -206253,6 +206603,19 @@ function runTrackedChangeDecideCommitWithLookupContext(lookupContext, input) {
206253
206603
  }
206254
206604
  }
206255
206605
  }
206606
+ const partsWithComparisonHunkFragments = new Set;
206607
+ for (const fragments of fragmentsByPart.values()) {
206608
+ for (const fragment2 of fragments) {
206609
+ if (readComparisonHunkOrigin(fragment2)?.kind === "comparison-hunk") {
206610
+ partsWithComparisonHunkFragments.add(fragment2.partUri);
206611
+ }
206612
+ }
206613
+ }
206614
+ for (const fragment2 of formattingTargets) {
206615
+ if (readComparisonHunkOrigin(fragment2)?.kind === "comparison-hunk") {
206616
+ partsWithComparisonHunkFragments.add(fragment2.partUri);
206617
+ }
206618
+ }
206256
206619
  for (const [partUri, fragments] of fragmentsByPart.entries()) {
206257
206620
  const bytes = state.packageBytes.get(partUri);
206258
206621
  if (!bytes)
@@ -207170,6 +207533,16 @@ function runTrackedChangeDecideCommitWithLookupContext(lookupContext, input) {
207170
207533
  storyPartOwnership.set(groups[0].fragments[0].storyId, partUri);
207171
207534
  }
207172
207535
  }
207536
+ for (const partUri of partsWithComparisonHunkFragments) {
207537
+ const patch = firstReplacePatch(perPart[partUri]);
207538
+ if (!patch)
207539
+ continue;
207540
+ const mergedXml = measureSDTxPerf("trackedChangeRunMergeMs", () => mergeAdjacentIdenticallyFormattedRuns(TD47.decode(patch.bytes)));
207541
+ const mergedBytes = TE23.encode(mergedXml);
207542
+ if (mergedBytes.length === patch.bytes.length && bytesEqual8(mergedBytes, patch.bytes))
207543
+ continue;
207544
+ perPart[partUri] = { kind: "modify", patches: [{ ...patch, bytes: mergedBytes }] };
207545
+ }
207173
207546
  const hyperlinkRelationshipCleanup = applyRejectedHyperlinkRelationshipCleanup({
207174
207547
  state,
207175
207548
  removedHyperlinkRIdsByPart,
@@ -209041,7 +209414,7 @@ function buildLogicalIdByTextFragmentKey(logical) {
209041
209414
  }
209042
209415
  const out = new Map;
209043
209416
  for (const entry of logical.byId.values()) {
209044
- if (entry.reviewGroup?.kind === "text-rewrite" && entry.reviewGroup.role === "parent")
209417
+ if (entry.reviewGroup?.role === "parent" && (entry.reviewGroup.kind === "text-rewrite" || entry.reviewGroup.kind === "comparison-hunk"))
209045
209418
  continue;
209046
209419
  for (const fragment2 of entry.fragments) {
209047
209420
  if ((logicalIdsByRsid.get(fragment2.rsid)?.size ?? 0) <= 1)
@@ -209054,7 +209427,7 @@ function buildLogicalIdByTextFragmentKey(logical) {
209054
209427
  function buildExactLogicalIdByTextFragmentKey(logical) {
209055
209428
  const out = new Map;
209056
209429
  for (const entry of logical.byId.values()) {
209057
- if (entry.reviewGroup?.kind === "text-rewrite" && entry.reviewGroup.role === "parent")
209430
+ if (entry.reviewGroup?.role === "parent" && (entry.reviewGroup.kind === "text-rewrite" || entry.reviewGroup.kind === "comparison-hunk"))
209058
209431
  continue;
209059
209432
  for (const fragment2 of entry.fragments) {
209060
209433
  out.set(trackedChangeFragmentKey(fragment2), entry.id);
@@ -210525,6 +210898,7 @@ var init_compile_tracked_change_decide = __esm(() => {
210525
210898
  init_package_graph();
210526
210899
  init_decide_engine();
210527
210900
  init_block_deletion_text();
210901
+ init_comparison_hunk_groups();
210528
210902
  init_shared_table_grid_decision();
210529
210903
  init_structural_inline_decision();
210530
210904
  init_structural_groups();
@@ -220367,6 +220741,423 @@ var init_tracked_table_properties = __esm(() => {
220367
220741
  TOPOLOGY = new Set(["gridSpan", "hMerge", "vMerge", "gridBefore", "gridAfter"]);
220368
220742
  });
220369
220743
 
220744
+ // ../../../v2/editor-core/dist/document/transactions/word-diff.js
220745
+ function myersDiff(oldSeq, newSeq, isEqual, traceCellBudget = MAX_MYERS_TRACE_CELLS, keyOf) {
220746
+ const oldLen = oldSeq.length;
220747
+ const newLen = newSeq.length;
220748
+ if (oldLen === 0 && newLen === 0) {
220749
+ return [];
220750
+ }
220751
+ const max2 = oldLen + newLen;
220752
+ const size = 2 * max2 + 3;
220753
+ if (size > traceCellBudget)
220754
+ return linearSpaceDiff(oldSeq, newSeq, isEqual, keyOf);
220755
+ const offset = max2 + 1;
220756
+ const v = new Int32Array(size).fill(-1);
220757
+ v[offset + 1] = 0;
220758
+ const trace = [];
220759
+ let retainedCells = 0;
220760
+ let foundPath = false;
220761
+ for (let d = 0;d <= max2 && !foundPath; d += 1) {
220762
+ const nextCells = 2 * d + 1;
220763
+ if (retainedCells + nextCells > traceCellBudget)
220764
+ return linearSpaceDiff(oldSeq, newSeq, isEqual, keyOf);
220765
+ for (let k = -d;k <= d; k += 2) {
220766
+ const index = offset + k;
220767
+ let x2;
220768
+ if (k === -d || k !== d && v[index - 1] < v[index + 1]) {
220769
+ x2 = v[index + 1];
220770
+ } else {
220771
+ x2 = v[index - 1] + 1;
220772
+ }
220773
+ let y = x2 - k;
220774
+ while (x2 < oldLen && y < newLen && isEqual(oldSeq[x2], newSeq[y])) {
220775
+ x2 += 1;
220776
+ y += 1;
220777
+ }
220778
+ v[index] = x2;
220779
+ if (x2 >= oldLen && y >= newLen) {
220780
+ foundPath = true;
220781
+ break;
220782
+ }
220783
+ }
220784
+ trace.push(v.slice(offset - d, offset + d + 1));
220785
+ retainedCells += nextCells;
220786
+ }
220787
+ return backtrackMyers(trace, oldLen, newLen);
220788
+ }
220789
+ function diffWordTokens(oldSeq, newSeq) {
220790
+ const oldKeys = Array.from(oldSeq, (token) => token.text);
220791
+ const newKeys = Array.from(newSeq, (token) => token.text);
220792
+ const oldSet = new Set(oldKeys);
220793
+ const newSet = new Set(newKeys);
220794
+ let oldIndex = 0;
220795
+ let newIndex = 0;
220796
+ while (true) {
220797
+ while (oldIndex < oldKeys.length && !newSet.has(oldKeys[oldIndex]))
220798
+ oldIndex += 1;
220799
+ while (newIndex < newKeys.length && !oldSet.has(newKeys[newIndex]))
220800
+ newIndex += 1;
220801
+ if (oldIndex === oldKeys.length || newIndex === newKeys.length) {
220802
+ if (oldIndex !== oldKeys.length || newIndex !== newKeys.length)
220803
+ break;
220804
+ const operations = [];
220805
+ oldIndex = 0;
220806
+ newIndex = 0;
220807
+ while (oldIndex < oldKeys.length || newIndex < newKeys.length) {
220808
+ while (oldIndex < oldKeys.length && !newSet.has(oldKeys[oldIndex])) {
220809
+ operations.push("delete");
220810
+ oldIndex += 1;
220811
+ }
220812
+ while (newIndex < newKeys.length && !oldSet.has(newKeys[newIndex])) {
220813
+ operations.push("insert");
220814
+ newIndex += 1;
220815
+ }
220816
+ if (oldIndex < oldKeys.length && newIndex < newKeys.length) {
220817
+ operations.push("equal");
220818
+ oldIndex += 1;
220819
+ newIndex += 1;
220820
+ }
220821
+ }
220822
+ return operations;
220823
+ }
220824
+ if (oldKeys[oldIndex] !== newKeys[newIndex])
220825
+ break;
220826
+ oldIndex += 1;
220827
+ newIndex += 1;
220828
+ }
220829
+ return myersDiff(oldSeq, newSeq, (a, b) => a.text === b.text, MAX_MYERS_TRACE_CELLS, (item) => item.text);
220830
+ }
220831
+ function backtrackMyers(trace, oldLen, newLen) {
220832
+ const operations = [];
220833
+ let x2 = oldLen;
220834
+ let y = newLen;
220835
+ for (let d = trace.length - 1;d > 0; d -= 1) {
220836
+ const v = trace[d - 1];
220837
+ const k = x2 - y;
220838
+ const index = d - 1 + k;
220839
+ let prevK;
220840
+ if (k === -d || k !== d && v[index - 1] < v[index + 1]) {
220841
+ prevK = k + 1;
220842
+ } else {
220843
+ prevK = k - 1;
220844
+ }
220845
+ const prevIndex = d - 1 + prevK;
220846
+ const prevX = v[prevIndex];
220847
+ const prevY = prevX - prevK;
220848
+ while (x2 > prevX && y > prevY) {
220849
+ x2 -= 1;
220850
+ y -= 1;
220851
+ operations.push("equal");
220852
+ }
220853
+ if (x2 === prevX) {
220854
+ y -= 1;
220855
+ operations.push("insert");
220856
+ } else {
220857
+ x2 -= 1;
220858
+ operations.push("delete");
220859
+ }
220860
+ }
220861
+ while (x2 > 0 && y > 0) {
220862
+ x2 -= 1;
220863
+ y -= 1;
220864
+ operations.push("equal");
220865
+ }
220866
+ while (x2 > 0) {
220867
+ x2 -= 1;
220868
+ operations.push("delete");
220869
+ }
220870
+ while (y > 0) {
220871
+ y -= 1;
220872
+ operations.push("insert");
220873
+ }
220874
+ return operations.reverse();
220875
+ }
220876
+ function linearSpaceDiff(oldSeq, newSeq, isEqual, keyOf) {
220877
+ const result = [];
220878
+ function lcsRow(oldFrom, oldTo, newFrom, newTo, reverse) {
220879
+ const newLength = newTo - newFrom;
220880
+ let useBitset = Boolean(keyOf && newLength >= 64);
220881
+ if (useBitset) {
220882
+ const distinctKeys = new Set;
220883
+ for (let column = 0;column < newLength; column += 1) {
220884
+ const newIndex = reverse ? newTo - column - 1 : newFrom + column;
220885
+ distinctKeys.add(keyOf(newSeq[newIndex]));
220886
+ if (distinctKeys.size * newLength > MAX_BITSET_MASK_BITS) {
220887
+ useBitset = false;
220888
+ break;
220889
+ }
220890
+ }
220891
+ }
220892
+ if (useBitset && keyOf) {
220893
+ const masks = new Map;
220894
+ for (let column = 0;column < newLength; column += 1) {
220895
+ const newIndex = reverse ? newTo - column - 1 : newFrom + column;
220896
+ const key2 = keyOf(newSeq[newIndex]);
220897
+ masks.set(key2, (masks.get(key2) ?? 0n) | 1n << BigInt(column));
220898
+ }
220899
+ let bits2 = 0n;
220900
+ for (let oldIndex = oldFrom;oldIndex < oldTo; oldIndex += 1) {
220901
+ const oldValue = reverse ? oldSeq[oldTo - 1 - (oldIndex - oldFrom)] : oldSeq[oldIndex];
220902
+ const matches = masks.get(keyOf(oldValue)) ?? 0n;
220903
+ const x2 = matches | bits2;
220904
+ bits2 = x2 & ~(x2 - (bits2 << 1n | 1n));
220905
+ }
220906
+ const row2 = new Uint32Array(newLength + 1);
220907
+ for (let column = 1;column <= newLength; column += 1) {
220908
+ row2[column] = row2[column - 1] + Number(bits2 & 1n);
220909
+ bits2 >>= 1n;
220910
+ }
220911
+ return row2;
220912
+ }
220913
+ if (keyOf && newLength >= 64) {
220914
+ const positions = new Map;
220915
+ for (let column = 0;column < newLength; column += 1) {
220916
+ const newIndex = reverse ? newTo - column - 1 : newFrom + column;
220917
+ const key2 = keyOf(newSeq[newIndex]);
220918
+ const list = positions.get(key2);
220919
+ if (list)
220920
+ list.push(column);
220921
+ else
220922
+ positions.set(key2, [column]);
220923
+ }
220924
+ const bits2 = new Uint32Array(Math.ceil(newLength / 32));
220925
+ const x2 = new Uint32Array(bits2.length);
220926
+ for (let oldIndex = oldFrom;oldIndex < oldTo; oldIndex += 1) {
220927
+ const oldValue = reverse ? oldSeq[oldTo - 1 - (oldIndex - oldFrom)] : oldSeq[oldIndex];
220928
+ x2.set(bits2);
220929
+ for (const column of positions.get(keyOf(oldValue)) ?? [])
220930
+ x2[column >>> 5] |= 1 << (column & 31);
220931
+ let carry = 1;
220932
+ let borrow = 0;
220933
+ for (let word2 = 0;word2 < bits2.length; word2 += 1) {
220934
+ const previous = bits2[word2];
220935
+ const shifted = (previous << 1 | carry) >>> 0;
220936
+ carry = previous >>> 31;
220937
+ const subtrahend = shifted + borrow;
220938
+ const difference = x2[word2] - subtrahend >>> 0;
220939
+ borrow = x2[word2] < subtrahend ? 1 : 0;
220940
+ bits2[word2] = x2[word2] & ~difference;
220941
+ }
220942
+ }
220943
+ const row2 = new Uint32Array(newLength + 1);
220944
+ for (let column = 1;column <= newLength; column += 1) {
220945
+ row2[column] = row2[column - 1] + (bits2[column - 1 >>> 5] >>> (column - 1 & 31) & 1);
220946
+ }
220947
+ return row2;
220948
+ }
220949
+ const row = new Uint32Array(newLength + 1);
220950
+ for (let oldIndex = oldFrom;oldIndex < oldTo; oldIndex += 1) {
220951
+ const oldValue = reverse ? oldSeq[oldTo - 1 - (oldIndex - oldFrom)] : oldSeq[oldIndex];
220952
+ let diagonal = 0;
220953
+ for (let column = 1;column <= newLength; column += 1) {
220954
+ const previous = row[column];
220955
+ const newIndex = reverse ? newTo - column : newFrom + column - 1;
220956
+ row[column] = isEqual(oldValue, newSeq[newIndex]) ? diagonal + 1 : Math.max(row[column - 1], previous);
220957
+ diagonal = previous;
220958
+ }
220959
+ }
220960
+ return row;
220961
+ }
220962
+ function splitNew(oldFrom, oldMiddle, oldTo, newFrom, newTo) {
220963
+ const left = lcsRow(oldFrom, oldMiddle, newFrom, newTo, false);
220964
+ const right = lcsRow(oldMiddle, oldTo, newFrom, newTo, true);
220965
+ const newLength = newTo - newFrom;
220966
+ let bestColumn = 0;
220967
+ let bestLength = -1;
220968
+ for (let column = 0;column <= newLength; column += 1) {
220969
+ const length = left[column] + right[newLength - column];
220970
+ if (length > bestLength) {
220971
+ bestLength = length;
220972
+ bestColumn = column;
220973
+ }
220974
+ }
220975
+ return newFrom + bestColumn;
220976
+ }
220977
+ function emit(oldFrom, oldTo, newFrom, newTo) {
220978
+ while (oldFrom < oldTo && newFrom < newTo && isEqual(oldSeq[oldFrom], newSeq[newFrom])) {
220979
+ result.push("equal");
220980
+ oldFrom += 1;
220981
+ newFrom += 1;
220982
+ }
220983
+ let commonSuffix = 0;
220984
+ while (oldFrom + commonSuffix < oldTo && newFrom + commonSuffix < newTo && isEqual(oldSeq[oldTo - commonSuffix - 1], newSeq[newTo - commonSuffix - 1]))
220985
+ commonSuffix += 1;
220986
+ oldTo -= commonSuffix;
220987
+ newTo -= commonSuffix;
220988
+ const oldLength = oldTo - oldFrom;
220989
+ const newLength = newTo - newFrom;
220990
+ if (oldLength === 0) {
220991
+ for (let index = 0;index < newLength; index += 1)
220992
+ result.push("insert");
220993
+ } else if (newLength === 0) {
220994
+ for (let index = 0;index < oldLength; index += 1)
220995
+ result.push("delete");
220996
+ } else if (oldLength === 1) {
220997
+ let match = -1;
220998
+ for (let index = newFrom;index < newTo; index += 1) {
220999
+ if (isEqual(oldSeq[oldFrom], newSeq[index])) {
221000
+ match = index;
221001
+ break;
221002
+ }
221003
+ }
221004
+ if (match === -1) {
221005
+ result.push("delete");
221006
+ for (let index = 0;index < newLength; index += 1)
221007
+ result.push("insert");
221008
+ } else {
221009
+ for (let index = newFrom;index < match; index += 1)
221010
+ result.push("insert");
221011
+ result.push("equal");
221012
+ for (let index = match + 1;index < newTo; index += 1)
221013
+ result.push("insert");
221014
+ }
221015
+ } else {
221016
+ const middle = oldFrom + Math.floor(oldLength / 2);
221017
+ const newMiddle = splitNew(oldFrom, middle, oldTo, newFrom, newTo);
221018
+ emit(oldFrom, middle, newFrom, newMiddle);
221019
+ emit(middle, oldTo, newMiddle, newTo);
221020
+ }
221021
+ for (let index = 0;index < commonSuffix; index += 1)
221022
+ result.push("equal");
221023
+ }
221024
+ emit(0, oldSeq.length, 0, newSeq.length);
221025
+ return result;
221026
+ }
221027
+ function tokenizeWords(text) {
221028
+ const tokens = [];
221029
+ const regex = /(\s+|[\p{L}\p{N}_]+|[^\s\p{L}\p{N}_]+)/gu;
221030
+ let match;
221031
+ while ((match = regex.exec(text)) !== null) {
221032
+ tokens.push({ text: match[0], offset: match.index });
221033
+ }
221034
+ return tokens;
221035
+ }
221036
+ function necessarilyExceedsWordDiffRatio(oldText, newText, ratio) {
221037
+ const oldTokens = tokenizeWords(oldText);
221038
+ const newTokens = tokenizeWords(newText);
221039
+ const oldCounts = new Map;
221040
+ const newCounts = new Map;
221041
+ for (const token of oldTokens)
221042
+ oldCounts.set(token.text, (oldCounts.get(token.text) ?? 0) + 1);
221043
+ for (const token of newTokens)
221044
+ newCounts.set(token.text, (newCounts.get(token.text) ?? 0) + 1);
221045
+ let maxEqualChars = 0;
221046
+ for (const [text, count] of oldCounts) {
221047
+ maxEqualChars += Math.min(count, newCounts.get(text) ?? 0) * text.length;
221048
+ }
221049
+ const totalChars = oldText.length + newText.length;
221050
+ if (totalChars === 0)
221051
+ return false;
221052
+ if (1 - 2 * maxEqualChars / totalChars > ratio)
221053
+ return true;
221054
+ const uniqueOldPositions = new Map;
221055
+ let uniqueChars = 0;
221056
+ let longestUniqueWord = 0;
221057
+ for (const token of oldTokens) {
221058
+ const text = token.text;
221059
+ if (oldCounts.get(text) !== 1 || newCounts.get(text) !== 1 || !/^[\p{L}\p{N}_]+$/u.test(text))
221060
+ continue;
221061
+ uniqueOldPositions.set(text, uniqueOldPositions.size);
221062
+ uniqueChars += text.length;
221063
+ longestUniqueWord = Math.max(longestUniqueWord, text.length);
221064
+ }
221065
+ if (uniqueOldPositions.size === 0)
221066
+ return false;
221067
+ const tails = [];
221068
+ for (const token of newTokens) {
221069
+ const position = uniqueOldPositions.get(token.text);
221070
+ if (position === undefined)
221071
+ continue;
221072
+ let low = 0;
221073
+ let high = tails.length;
221074
+ while (low < high) {
221075
+ const middle = low + high >>> 1;
221076
+ if (tails[middle] < position)
221077
+ low = middle + 1;
221078
+ else
221079
+ high = middle;
221080
+ }
221081
+ tails[low] = position;
221082
+ }
221083
+ maxEqualChars -= uniqueChars - Math.min(uniqueChars, tails.length * longestUniqueWord);
221084
+ return 1 - 2 * maxEqualChars / totalChars > ratio;
221085
+ }
221086
+ function getWordChanges(oldText, newText) {
221087
+ if (oldText === newText) {
221088
+ return [];
221089
+ }
221090
+ const oldTokens = tokenizeWords(oldText);
221091
+ const newTokens = tokenizeWords(newText);
221092
+ if (oldTokens.length === 0 && newTokens.length === 0) {
221093
+ return [];
221094
+ }
221095
+ if (oldTokens.length === 0) {
221096
+ return [{ type: "insert", insertAt: 0, newText }];
221097
+ }
221098
+ if (newTokens.length === 0) {
221099
+ return [{ type: "delete", oldFrom: 0, oldTo: oldText.length }];
221100
+ }
221101
+ const ops = diffWordTokens(oldTokens, newTokens);
221102
+ const steps = [];
221103
+ let oldIdx = 0;
221104
+ let newIdx = 0;
221105
+ for (const op of ops) {
221106
+ steps.push({ type: op, oldIdx, newIdx });
221107
+ if (op === "equal") {
221108
+ oldIdx++;
221109
+ newIdx++;
221110
+ } else if (op === "delete") {
221111
+ oldIdx++;
221112
+ } else {
221113
+ newIdx++;
221114
+ }
221115
+ }
221116
+ const result = [];
221117
+ let i2 = 0;
221118
+ while (i2 < steps.length) {
221119
+ const step2 = steps[i2];
221120
+ if (step2.type === "equal") {
221121
+ i2++;
221122
+ continue;
221123
+ }
221124
+ const groupStart = i2;
221125
+ let deleteStart = -1;
221126
+ let deleteEnd = -1;
221127
+ let insertText = "";
221128
+ while (i2 < steps.length && (steps[i2].type === "delete" || steps[i2].type === "insert")) {
221129
+ const s = steps[i2];
221130
+ if (s.type === "delete") {
221131
+ const token = oldTokens[s.oldIdx];
221132
+ if (deleteStart === -1)
221133
+ deleteStart = token.offset;
221134
+ deleteEnd = token.offset + token.text.length;
221135
+ } else {
221136
+ insertText += newTokens[s.newIdx].text;
221137
+ }
221138
+ i2++;
221139
+ }
221140
+ if (deleteStart !== -1 && insertText.length > 0) {
221141
+ result.push({ type: "replace", oldFrom: deleteStart, oldTo: deleteEnd, newText: insertText });
221142
+ } else if (deleteStart !== -1) {
221143
+ result.push({ type: "delete", oldFrom: deleteStart, oldTo: deleteEnd });
221144
+ } else if (insertText.length > 0) {
221145
+ const prevStep = groupStart > 0 ? steps[groupStart - 1] : null;
221146
+ let insertAt = 0;
221147
+ if (prevStep && prevStep.type === "equal") {
221148
+ const prevToken = oldTokens[prevStep.oldIdx];
221149
+ insertAt = prevToken.offset + prevToken.text.length;
221150
+ } else if (result.length > 0) {
221151
+ const lastOp = result[result.length - 1];
221152
+ insertAt = "oldTo" in lastOp ? lastOp.oldTo : ("insertAt" in lastOp) ? lastOp.insertAt : 0;
221153
+ }
221154
+ result.push({ type: "insert", insertAt, newText: insertText });
221155
+ }
221156
+ }
221157
+ return result;
221158
+ }
221159
+ var MAX_MYERS_TRACE_CELLS = 4000000, MAX_BITSET_MASK_BITS = 4000000;
221160
+
220370
221161
  // ../../../v2/editor-core/dist/document/transactions/compare-table-block-replay.js
220371
221162
  function prepareCompareTableBlockReplay(bytes, step2) {
220372
221163
  const xml = TD58.decode(bytes);
@@ -220764,6 +221555,9 @@ function runCompareApplyCommit(input) {
220764
221555
  if (new Set(executableOperationIds).size !== executableOperationIds.length) {
220765
221556
  return rejected14(txId, "unsupported-context");
220766
221557
  }
221558
+ if (changeMode === "tracked" && referenceReplaySteps.some((step2) => (step2.kind === "field-topology" || step2.kind === "complex-field") && (!step2.beforeFragmentXml || !step2.afterFragmentXml || !isRunOnlyTrackedFieldFragment(step2.beforeFragmentXml, step2.beforeNamespaceBindings ?? {}) || !isRunOnlyTrackedFieldFragment(step2.afterFragmentXml, step2.afterNamespaceBindings ?? {})))) {
221559
+ return rejected14(txId, "unsupported-context");
221560
+ }
220767
221561
  if (changeMode === "tracked" && (groups.length > 0 || storyPackageOperations.length > 0 || tableTopologySteps.length > 0 || tableBlockSteps.length > 0 || tablePropertySteps.length > 0 || sectionReplaySteps.length > 0 || referenceReplaySteps.length > 0) && !(input.authorOverride ?? input.author)) {
220768
221562
  return rejected14(txId, "no-author-configured");
220769
221563
  }
@@ -221734,7 +222528,7 @@ function collectProtectedReferenceTokens(xml, referenceSteps) {
221734
222528
  }
221735
222529
  continue;
221736
222530
  }
221737
- if (step2.kind === "bookmark-range" || step2.kind === "complex-field") {
222531
+ if (step2.kind === "bookmark-range" || step2.kind === "complex-field" || step2.kind === "field-topology") {
221738
222532
  const fragment2 = step2.beforeFragmentXml;
221739
222533
  if (!fragment2)
221740
222534
  return null;
@@ -221901,6 +222695,9 @@ function runBodyStep(input, storyId, noteId, step2, changeMode, options, pushHis
221901
222695
  }
221902
222696
  return runCompareBodyEditCommit(input, storyId, step2, changeMode, options, pushHistory, referenceSteps);
221903
222697
  }
222698
+ const localizedEditOp = changeMode === "tracked" ? tryLocalizedCompareEditTextOp(state, storyId, step2.blockId, adjustedEdit.previousText, adjustedEdit.text, txId) : null;
222699
+ if (localizedEditOp)
222700
+ return runEditTextCommit({ ...subInput, op: localizedEditOp });
221904
222701
  const range = adjustedEdit.trimmedTrailingNoteMarkers > 0 ? resolveParagraphSliceRange(state, storyId, step2.blockId, 0, adjustedEdit.editableEndOffset) : resolveWholeParagraphRange(state, storyId, step2.blockId);
221905
222702
  if (!range)
221906
222703
  return rejected14(txId, "invalid-range");
@@ -222599,7 +223396,6 @@ function runCompareBodyEditCommit(input, storyId, step2, changeMode, options, pu
222599
223396
  const stamps = compareTrackedStampPair(input, paragraphPropertiesChanged);
222600
223397
  if (!stamps)
222601
223398
  return rejected14(txId, "no-author-configured");
222602
- createdRefs.push({ kind: "trackedChange", entityId: stamps.ins.rsid, storyId });
222603
223399
  if (stamps.paragraphProperties) {
222604
223400
  createdRefs.push({
222605
223401
  kind: "trackedChange",
@@ -222608,13 +223404,34 @@ function runCompareBodyEditCommit(input, storyId, step2, changeMode, options, pu
222608
223404
  });
222609
223405
  }
222610
223406
  const oldRunsDel = oldRunsRaw.replace(/<((?:[\w.-]+:)?)t(\b[^>]*)>/g, "<$1delText$2>").replace(/<\/((?:[\w.-]+:)?)t>/g, "</$1delText>");
222611
- const protectedRuns = renderTrackedRunsWithProtectedReferences(oldRunsRaw, newRuns, protectedReferenceSteps, stamps, paragraphWrapper.wordprocessingPrefix);
223407
+ const hunkStamps = makeCompareHunkStampSource(stamps, input);
223408
+ const protectedRuns = renderTrackedRunsWithProtectedReferences(oldRunsRaw, newRuns, protectedReferenceSteps, hunkStamps.next, paragraphWrapper.wordprocessingPrefix);
222612
223409
  if (!protectedRuns && stableBookmarkSteps?.length)
222613
223410
  return rejected14(txId, "unsupported-context");
222614
- const delXml = protectedRuns?.xml ?? (oldRunsDel ? wrapTracked("del", oldRunsDel, stamps.del, "rsidDel", paragraphWrapper.wordprocessingPrefix) : "");
222615
- const insXml = protectedRuns ? "" : newRuns ? wrapTracked("ins", newRuns, stamps.ins, "rsidR", paragraphWrapper.wordprocessingPrefix) : "";
223411
+ let delXml;
223412
+ let insXml;
223413
+ if (protectedRuns) {
223414
+ delXml = protectedRuns.xml;
223415
+ insXml = "";
223416
+ } else {
223417
+ const fallbackPair = hunkStamps.next();
223418
+ delXml = oldRunsDel ? wrapTracked("del", oldRunsDel, fallbackPair.del, "rsidDel", paragraphWrapper.wordprocessingPrefix) : "";
223419
+ insXml = newRuns ? wrapTracked("ins", newRuns, fallbackPair.ins, "rsidR", paragraphWrapper.wordprocessingPrefix) : "";
223420
+ }
222616
223421
  const trackedPPrXml = buildTrackedParagraphProperties(targetParagraphPropertiesXml, pPrXml, stamps.paragraphProperties ?? stamps.ins, paragraphWrapper.wordprocessingPrefix);
222617
- newParaXml = `${paragraphWrapper.openTag}${trackedPPrXml}${delXml}${insXml}${paragraphWrapper.closeTag}`;
223422
+ const assembledParaXml = `${paragraphWrapper.openTag}${trackedPPrXml}${delXml}${insXml}${paragraphWrapper.closeTag}`;
223423
+ if (hunkStamps.usedPairs.length === 0) {
223424
+ newParaXml = assembledParaXml;
223425
+ } else {
223426
+ for (const pair of hunkStamps.usedPairs) {
223427
+ createdRefs.push({ kind: "trackedChange", entityId: pair.del.rsid, storyId });
223428
+ }
223429
+ const hunkGroupsByRsid = new Map(hunkStamps.usedPairs.map((pair, ordinal) => [pair.del.rsid, `${txId}:${step2.blockId}:${ordinal}`]));
223430
+ const stamped = stampComparisonHunkOrigins(assembledParaXml, hunkGroupsByRsid, { partUri, storyId });
223431
+ if (stamped === null)
223432
+ return rejected14(txId, "invalid-input");
223433
+ newParaXml = stamped;
223434
+ }
222618
223435
  } else {
222619
223436
  newParaXml = `${paragraphWrapper.openTag}${targetParagraphPropertiesXml ?? pPrXml}${newRuns}${paragraphWrapper.closeTag}`;
222620
223437
  }
@@ -222639,10 +223456,10 @@ function runCompareBodyEditCommit(input, storyId, step2, changeMode, options, pu
222639
223456
  targetBlockIds: [step2.blockId]
222640
223457
  });
222641
223458
  }
222642
- function renderTrackedRunsWithProtectedReferences(oldRuns, targetRuns, referenceSteps, stamps, prefix) {
223459
+ function renderTrackedRunsWithProtectedReferences(oldRuns, targetRuns, referenceSteps, getStamp, prefix) {
222643
223460
  const oldTokens = collectProtectedReferenceTokens(oldRuns, referenceSteps);
222644
223461
  const targetTokens = collectProtectedReferenceTokens(targetRuns, referenceSteps);
222645
- if (!oldTokens || !targetTokens || oldTokens.length === 0 || oldTokens.length !== targetTokens.length)
223462
+ if (!oldTokens || !targetTokens || oldTokens.length !== targetTokens.length)
222646
223463
  return null;
222647
223464
  if (oldTokens.some((token, index) => token.key !== targetTokens[index].key))
222648
223465
  return null;
@@ -222657,11 +223474,19 @@ function renderTrackedRunsWithProtectedReferences(oldRuns, targetRuns, reference
222657
223474
  if (oldSegment === targetSegment) {
222658
223475
  xml += oldSegment;
222659
223476
  } else {
222660
- const deleted = oldSegment.replace(/<((?:[\w.-]+:)?)t(\b[^>]*)>/g, "<$1delText$2>").replace(/<\/((?:[\w.-]+:)?)t>/g, "</$1delText>");
222661
- if (deleted)
222662
- xml += wrapTracked("del", deleted, stamps.del, "rsidDel", prefix);
222663
- if (targetSegment)
222664
- xml += wrapTracked("ins", targetSegment, stamps.ins, "rsidR", prefix);
223477
+ const wordLevel = renderWordLevelTrackedRunSegment(oldSegment, targetSegment, getStamp, prefix);
223478
+ if (wordLevel) {
223479
+ xml += wordLevel.xml;
223480
+ } else {
223481
+ const deleted = oldSegment.replace(/<((?:[\w.-]+:)?)t(\b[^>]*)>/g, "<$1delText$2>").replace(/<\/((?:[\w.-]+:)?)t>/g, "</$1delText>");
223482
+ if (deleted || targetSegment) {
223483
+ const pair = getStamp();
223484
+ if (deleted)
223485
+ xml += wrapTracked("del", deleted, pair.del, "rsidDel", prefix);
223486
+ if (targetSegment)
223487
+ xml += wrapTracked("ins", targetSegment, pair.ins, "rsidR", prefix);
223488
+ }
223489
+ }
222665
223490
  }
222666
223491
  if (!oldToken || !targetToken)
222667
223492
  break;
@@ -222671,6 +223496,155 @@ function renderTrackedRunsWithProtectedReferences(oldRuns, targetRuns, reference
222671
223496
  }
222672
223497
  return { xml };
222673
223498
  }
223499
+ function shouldFallBackFromWordDiff(ops, oldLength, newLength) {
223500
+ const changedOldChars = ops.reduce((sum, op) => sum + (op.type === "insert" ? 0 : op.oldTo - op.oldFrom), 0);
223501
+ const changedNewChars = ops.reduce((sum, op) => sum + (op.type === "delete" ? 0 : op.newText.length), 0);
223502
+ const totalChars = oldLength + newLength;
223503
+ if (totalChars === 0)
223504
+ return false;
223505
+ const changedRatio = (changedOldChars + changedNewChars) / totalChars;
223506
+ return changedRatio > WORD_DIFF_FALLBACK_RATIO || ops.length > MAX_WORD_DIFF_HUNKS && changedRatio > DENSE_WORD_DIFF_RATIO;
223507
+ }
223508
+ function parseSimpleRunTokens(xml) {
223509
+ const runRe = /<([\w.-]+):r\b([^>]*)>([\s\S]*?)<\/\1:r>/g;
223510
+ const tokens = [];
223511
+ let cursor = 0;
223512
+ let visibleOffset = 0;
223513
+ let match;
223514
+ while (match = runRe.exec(xml)) {
223515
+ if (xml.slice(cursor, match.index).trim().length > 0)
223516
+ return null;
223517
+ const prefix = match[1];
223518
+ const runAttrs = match[2] ?? "";
223519
+ const inner = match[3] ?? "";
223520
+ const leadingWs = inner.match(/^\s*/)?.[0] ?? "";
223521
+ const rPrXml = matchLeadingElement(inner.slice(leadingWs.length), "rPr");
223522
+ const afterRPr = inner.slice(leadingWs.length + rPrXml.length);
223523
+ const tMatch = /^\s*<([\w.-]+):t\b([^>]*)>([\s\S]*?)<\/\1:t>\s*$/.exec(afterRPr);
223524
+ if (!tMatch)
223525
+ return null;
223526
+ const text = decodeCompareXmlText(tMatch[3] ?? "");
223527
+ tokens.push({
223528
+ rawXml: match[0],
223529
+ openTag: `<${prefix}:r${runAttrs}>${rPrXml}`,
223530
+ runPrefix: prefix,
223531
+ text,
223532
+ startOffset: visibleOffset
223533
+ });
223534
+ visibleOffset += text.length;
223535
+ cursor = runRe.lastIndex;
223536
+ }
223537
+ if (xml.slice(cursor).trim().length > 0)
223538
+ return null;
223539
+ return tokens;
223540
+ }
223541
+ function renderCompareRunTokenSpan(token, start, end, mode) {
223542
+ const tokenEnd = token.startOffset + token.text.length;
223543
+ if (mode === "passthrough" && start === token.startOffset && end === tokenEnd)
223544
+ return token.rawXml;
223545
+ const text = token.text.slice(start - token.startOffset, end - token.startOffset);
223546
+ if (!text)
223547
+ return "";
223548
+ const localName2 = mode === "del" ? "delText" : "t";
223549
+ const preserve = needsXmlSpacePreserve(text) ? ' xml:space="preserve"' : "";
223550
+ return `${token.openTag}<${token.runPrefix}:${localName2}${preserve}>${escapeXmlText(text)}</${token.runPrefix}:${localName2}></${token.runPrefix}:r>`;
223551
+ }
223552
+ function renderCompareRunRange(tokens, from, to, mode) {
223553
+ let xml = "";
223554
+ for (const token of tokens) {
223555
+ const tokenEnd = token.startOffset + token.text.length;
223556
+ const start = Math.max(from, token.startOffset);
223557
+ const end = Math.min(to, tokenEnd);
223558
+ if (start >= end)
223559
+ continue;
223560
+ xml += renderCompareRunTokenSpan(token, start, end, mode);
223561
+ }
223562
+ return xml;
223563
+ }
223564
+ function tokenizeCompareWordRuns(tokens) {
223565
+ const words = [];
223566
+ const regex = /(\s+|[\p{L}\p{N}_]+|[^\s\p{L}\p{N}_]+)/gu;
223567
+ for (const token of tokens) {
223568
+ let match;
223569
+ while ((match = regex.exec(token.text)) !== null) {
223570
+ words.push({
223571
+ text: match[0],
223572
+ openTag: token.openTag
223573
+ });
223574
+ }
223575
+ }
223576
+ return words;
223577
+ }
223578
+ function equalWordTokensPreserveFormatting(oldTokens, targetTokens) {
223579
+ const oldWords = tokenizeCompareWordRuns(oldTokens);
223580
+ const targetWords = tokenizeCompareWordRuns(targetTokens);
223581
+ const ops = diffWordTokens(oldWords, targetWords);
223582
+ let oldIndex = 0;
223583
+ let targetIndex = 0;
223584
+ for (const op of ops) {
223585
+ if (op === "equal") {
223586
+ if (oldWords[oldIndex]?.openTag !== targetWords[targetIndex]?.openTag)
223587
+ return false;
223588
+ oldIndex += 1;
223589
+ targetIndex += 1;
223590
+ continue;
223591
+ }
223592
+ if (op === "delete") {
223593
+ oldIndex += 1;
223594
+ continue;
223595
+ }
223596
+ targetIndex += 1;
223597
+ }
223598
+ return true;
223599
+ }
223600
+ function renderWordLevelTrackedRunSegment(oldSegment, targetSegment, getStamp, prefix) {
223601
+ const oldTokens = parseSimpleRunTokens(oldSegment);
223602
+ const targetTokens = parseSimpleRunTokens(targetSegment);
223603
+ if (!oldTokens || !targetTokens)
223604
+ return null;
223605
+ const oldText = oldTokens.map((token) => token.text).join("");
223606
+ const targetText = targetTokens.map((token) => token.text).join("");
223607
+ if (oldText === targetText)
223608
+ return null;
223609
+ if (necessarilyExceedsWordDiffRatio(oldText, targetText, WORD_DIFF_FALLBACK_RATIO))
223610
+ return null;
223611
+ if (!equalWordTokensPreserveFormatting(oldTokens, targetTokens))
223612
+ return null;
223613
+ const ops = getWordChanges(oldText, targetText);
223614
+ if (ops.length === 0)
223615
+ return null;
223616
+ if (shouldFallBackFromWordDiff(ops, oldText.length, targetText.length))
223617
+ return null;
223618
+ let xml = "";
223619
+ let oldCursor = 0;
223620
+ let newCursor = 0;
223621
+ for (const op of ops) {
223622
+ const opOldStart = op.type === "insert" ? op.insertAt : op.oldFrom;
223623
+ if (opOldStart > oldCursor) {
223624
+ xml += renderCompareRunRange(oldTokens, oldCursor, opOldStart, "passthrough");
223625
+ newCursor += opOldStart - oldCursor;
223626
+ oldCursor = opOldStart;
223627
+ }
223628
+ let opStamp = null;
223629
+ const stampForOp = () => opStamp ?? (opStamp = getStamp());
223630
+ if (op.type === "delete" || op.type === "replace") {
223631
+ const deletedXml = renderCompareRunRange(oldTokens, op.oldFrom, op.oldTo, "del");
223632
+ if (deletedXml)
223633
+ xml += wrapTracked("del", deletedXml, stampForOp().del, "rsidDel", prefix);
223634
+ oldCursor = op.oldTo;
223635
+ }
223636
+ if (op.type === "insert" || op.type === "replace") {
223637
+ const insertedXml = renderCompareRunRange(targetTokens, newCursor, newCursor + op.newText.length, "ins");
223638
+ if (insertedXml)
223639
+ xml += wrapTracked("ins", insertedXml, stampForOp().ins, "rsidR", prefix);
223640
+ newCursor += op.newText.length;
223641
+ }
223642
+ }
223643
+ if (oldCursor < oldText.length) {
223644
+ xml += renderCompareRunRange(oldTokens, oldCursor, oldText.length, "passthrough");
223645
+ }
223646
+ return { xml };
223647
+ }
222674
223648
  function runCompareBodyFormatEditCommit(input, storyId, step2, changeMode, options, pushHistory, referenceSteps) {
222675
223649
  const { state, txId } = input;
222676
223650
  const partUri = storyPartUriFromStoryId2(storyId);
@@ -222761,7 +223735,7 @@ function runCompareBodyFormatEditCommit(input, storyId, step2, changeMode, optio
222761
223735
  if (!stamps)
222762
223736
  return rejected14(txId, "no-author-configured");
222763
223737
  const oldRunsDel = oldRunsRaw.replace(/<((?:[\w.-]+:)?)t(\b[^>]*)>/g, "<$1delText$2>").replace(/<\/((?:[\w.-]+:)?)t>/g, "</$1delText>");
222764
- const protectedRuns = renderTrackedRunsWithProtectedReferences(oldRunsRaw, targetRunXml, protectedReferenceSteps, stamps, paragraphWrapper.wordprocessingPrefix);
223738
+ const protectedRuns = renderTrackedRunsWithProtectedReferences(oldRunsRaw, targetRunXml, protectedReferenceSteps, () => stamps, paragraphWrapper.wordprocessingPrefix);
222765
223739
  if (!protectedRuns && stableBookmarkSteps?.length)
222766
223740
  return rejected14(txId, "unsupported-context");
222767
223741
  const delXml = protectedRuns?.xml ?? (oldRunsDel ? wrapTracked("del", oldRunsDel, stamps.del, "rsidDel", paragraphWrapper.wordprocessingPrefix) : "");
@@ -222853,6 +223827,43 @@ function compareTrackedStampPair(input, includeParagraphProperties = false) {
222853
223827
  ...includeParagraphProperties ? { paragraphProperties: { rsid, wId: wId + 2, author, date: input.txTimestamp } } : {}
222854
223828
  };
222855
223829
  }
223830
+ function makeCompareHunkStampSource(primary, input) {
223831
+ const usedPairs = [];
223832
+ const reservedRsids = new Set([primary.del.rsid]);
223833
+ let issued = false;
223834
+ let pendingRsids = [];
223835
+ let batchOrdinal = 0;
223836
+ const nextRsid = () => {
223837
+ for (;; ) {
223838
+ const candidate2 = pendingRsids.shift();
223839
+ if (candidate2 !== undefined) {
223840
+ if (reservedRsids.has(candidate2))
223841
+ continue;
223842
+ return candidate2;
223843
+ }
223844
+ const batchSize = 2 ** batchOrdinal;
223845
+ pendingRsids = allocateDistinctBatchRsids(input.state, `${input.txId}:hunk-batch:${batchOrdinal}`, batchSize);
223846
+ batchOrdinal += 1;
223847
+ }
223848
+ };
223849
+ const next = () => {
223850
+ if (!issued) {
223851
+ issued = true;
223852
+ usedPairs.push(primary);
223853
+ return primary;
223854
+ }
223855
+ const wId = reserveRevisionWIdBlock(input.state, 2);
223856
+ const rsid = nextRsid();
223857
+ reservedRsids.add(rsid);
223858
+ const pair = {
223859
+ del: { rsid, wId, author: primary.del.author, date: primary.del.date },
223860
+ ins: { rsid, wId: wId + 1, author: primary.ins.author, date: primary.ins.date }
223861
+ };
223862
+ usedPairs.push(pair);
223863
+ return pair;
223864
+ };
223865
+ return { next, usedPairs };
223866
+ }
222856
223867
  function compareParagraphFormattingEntityKey(storyId, stamp) {
222857
223868
  return buildFormattingRevisionEntityKey({
222858
223869
  storyId,
@@ -223057,6 +224068,9 @@ function isSafeReferenceReplayStep(step2, context) {
223057
224068
  if (step2.kind === "bookmark-range") {
223058
224069
  return isBalancedAddedBookmarkFragment(afterFragment, beforeFragment, context.parentNamespaceBindings) || isBalancedAddedBookmarkFragment(beforeFragment, afterFragment, context.parentNamespaceBindings);
223059
224070
  }
224071
+ if (step2.kind === "field-topology") {
224072
+ return isSafeFieldTopologyFragment(beforeFragment, afterFragment, context.parentNamespaceBindings);
224073
+ }
223060
224074
  return isCompleteAddedRefFieldFragment(afterFragment, beforeFragment, context.parentNamespaceBindings);
223061
224075
  }
223062
224076
  function referenceReplayElementName(step2) {
@@ -223090,6 +224104,61 @@ function isCompleteAddedRefFieldFragment(xml, expectedResult, namespaceBindings)
223090
224104
  const instruction = parsed.ranges.filter((range) => range.tag.namespaceUri === NS_W && range.tag.localName === "instrText" && range.start > chars[0].end && range.end < chars[1].start).map((range) => xml.slice(range.start, range.end).replace(/^<[^>]+>|<\/[^>]+>$/g, "")).join("");
223091
224105
  return /^\s*REF\s+[A-Za-z_][A-Za-z0-9_.]*(?:\s|$)/i.test(instruction) && xml.slice(parentRunEnd(parsed.ranges, chars[1]), parentRunStart(parsed.ranges, chars[2])) === expectedResult;
223092
224106
  }
224107
+ function isSafeFieldTopologyFragment(before, after, namespaceBindings) {
224108
+ const field = isSimpleRefFieldFragment(after, before, namespaceBindings) || isCompleteAddedRefFieldFragment(after, before, namespaceBindings) || isSimpleRefFieldFragment(before, after, namespaceBindings) || isCompleteAddedRefFieldFragment(before, after, namespaceBindings);
224109
+ return field;
224110
+ }
224111
+ function isSimpleRefFieldFragment(fieldXml, expectedResult, namespaceBindings) {
224112
+ const parsed = collectXmlElementRanges(fieldXml, {
224113
+ fragment: true,
224114
+ additionalNamespaces: { ...namespaceBindings }
224115
+ });
224116
+ if (parsed.errors.length > 0)
224117
+ return false;
224118
+ const field = parsed.ranges.find((range) => range.start === 0 && range.end === fieldXml.length && range.tag.namespaceUri === NS_W && range.tag.localName === "fldSimple");
224119
+ if (!field || field.tag.isSelfClosing)
224120
+ return false;
224121
+ const instruction = readResolvedReplayAttribute(field, "instr");
224122
+ if (!instruction || !/^\s*REF\s+[A-Za-z_][A-Za-z0-9_.]*(?:\s|$)/i.test(instruction))
224123
+ return false;
224124
+ const disallowed = new Set([
224125
+ "fldSimple",
224126
+ "fldChar",
224127
+ "hyperlink",
224128
+ "drawing",
224129
+ "object",
224130
+ "pict",
224131
+ "sdt",
224132
+ "customXml",
224133
+ "ins",
224134
+ "del",
224135
+ "footnoteReference",
224136
+ "endnoteReference",
224137
+ "commentReference",
224138
+ "bookmarkStart",
224139
+ "bookmarkEnd"
224140
+ ]);
224141
+ if (parsed.ranges.some((range) => range !== field && (range.tag.namespaceUri !== NS_W || disallowed.has(range.tag.localName))))
224142
+ return false;
224143
+ return fieldXml.slice(field.openEnd, field.closeStart) === expectedResult && parsed.ranges.some((range) => range.tag.namespaceUri === NS_W && range.tag.localName === "r");
224144
+ }
224145
+ function isRunOnlyTrackedFieldFragment(xml, namespaceBindings) {
224146
+ const parsed = collectXmlElementRanges(xml, {
224147
+ fragment: true,
224148
+ additionalNamespaces: { ...namespaceBindings }
224149
+ });
224150
+ if (parsed.errors.length > 0)
224151
+ return false;
224152
+ let end = 0;
224153
+ for (const range of parsed.ranges.sort((left, right) => left.start - right.start || right.end - left.end)) {
224154
+ if (range.start < end)
224155
+ continue;
224156
+ if (range.start !== end || range.tag.namespaceUri !== NS_W || range.tag.localName !== "r")
224157
+ return false;
224158
+ end = range.end;
224159
+ }
224160
+ return end === xml.length;
224161
+ }
223093
224162
  function parentRunStart(ranges, child) {
223094
224163
  return ranges.find((range) => range.tag.namespaceUri === NS_W && range.tag.localName === "r" && range.start <= child.start && range.end >= child.end)?.start ?? -1;
223095
224164
  }
@@ -223220,7 +224289,7 @@ function renderTrackedSectionReplay(step2, stamp, context) {
223220
224289
  return step2.afterXml.slice(0, close) + marker + step2.afterXml.slice(close);
223221
224290
  }
223222
224291
  function renderTrackedReferenceReplay(step2, stamps, context) {
223223
- if (step2.kind === "bookmark-range" || step2.kind === "complex-field") {
224292
+ if (step2.kind === "bookmark-range" || step2.kind === "complex-field" || step2.kind === "field-topology") {
223224
224293
  const beforeFragment = step2.beforeFragmentXml;
223225
224294
  const afterFragment = step2.afterFragmentXml;
223226
224295
  const deletionXml2 = renameWordTextElementsToDeletedText(beforeFragment, context.parentNamespaceBindings);
@@ -223287,9 +224356,9 @@ function renameWordTextElementsToDeletedText(xml, namespaceBindings) {
223287
224356
  return xml;
223288
224357
  const edits = [];
223289
224358
  for (const range of parsed.ranges) {
223290
- if (range.tag.namespaceUri !== NS_W || range.tag.localName !== "t")
224359
+ if (range.tag.namespaceUri !== NS_W || range.tag.localName !== "t" && range.tag.localName !== "instrText")
223291
224360
  continue;
223292
- const replacementName = qualifiedName(range.tag.prefix, "delText");
224361
+ const replacementName = qualifiedName(range.tag.prefix, range.tag.localName === "t" ? "delText" : "delInstrText");
223293
224362
  edits.push({ start: range.start + 1, end: range.start + 1 + range.tag.name.length, value: replacementName });
223294
224363
  if (!range.tag.isSelfClosing) {
223295
224364
  edits.push({ start: range.closeStart + 2, end: range.closeStart + 2 + range.tag.name.length, value: replacementName });
@@ -224307,15 +225376,9 @@ function adjustCompareEditForTrailingNoteMarker(step2) {
224307
225376
  trimmedTrailingNoteMarkers: trailingMarkers
224308
225377
  };
224309
225378
  }
224310
- function resolveParagraphSliceRange(state, storyId, blockId, startOffset, endOffset) {
224311
- const index = getStoryParagraphIndexFromState(state, storyId);
224312
- const entry = index?.byParaId(blockId) ?? null;
224313
- if (!entry || startOffset < 0 || endOffset < startOffset || endOffset > entry.textLength)
225379
+ function sliceParagraphRangeFromOffsetMap(entry, offsetMap, blockId, startOffset, endOffset) {
225380
+ if (startOffset < 0 || endOffset < startOffset || endOffset > entry.textLength)
224314
225381
  return null;
224315
- const bytes = state.packageBytes.get(entry.partUri);
224316
- if (!bytes)
224317
- return null;
224318
- const offsetMap = buildParagraphOffsetMap(bytes, entry.byteStart, entry.byteEnd);
224319
225382
  const startByte = offsetMap.charToByte(startOffset);
224320
225383
  const endByte = offsetMap.charToByte(endOffset);
224321
225384
  if (startByte == null || endByte == null)
@@ -224336,6 +225399,54 @@ function resolveParagraphSliceRange(state, storyId, blockId, startOffset, endOff
224336
225399
  sourceAddress: { blockId, range: { start: startOffset, end: endOffset } }
224337
225400
  };
224338
225401
  }
225402
+ function resolveParagraphSliceRange(state, storyId, blockId, startOffset, endOffset) {
225403
+ const entry = getStoryParagraphIndexFromState(state, storyId)?.byParaId(blockId) ?? null;
225404
+ if (!entry)
225405
+ return null;
225406
+ const bytes = state.packageBytes.get(entry.partUri);
225407
+ if (!bytes)
225408
+ return null;
225409
+ const offsetMap = buildParagraphOffsetMap(bytes, entry.byteStart, entry.byteEnd);
225410
+ return sliceParagraphRangeFromOffsetMap(entry, offsetMap, blockId, startOffset, endOffset);
225411
+ }
225412
+ function tryLocalizedCompareEditTextOp(state, storyId, blockId, previousText, text, txId) {
225413
+ if (necessarilyExceedsWordDiffRatio(previousText, text, WORD_DIFF_FALLBACK_RATIO))
225414
+ return null;
225415
+ const ops = getWordChanges(previousText, text);
225416
+ if (ops.length === 0)
225417
+ return null;
225418
+ if (shouldFallBackFromWordDiff(ops, previousText.length, text.length))
225419
+ return null;
225420
+ const entry = getStoryParagraphIndexFromState(state, storyId)?.byParaId(blockId) ?? null;
225421
+ if (!entry)
225422
+ return null;
225423
+ const bytes = state.packageBytes.get(entry.partUri);
225424
+ if (!bytes)
225425
+ return null;
225426
+ const offsetMap = buildParagraphOffsetMap(bytes, entry.byteStart, entry.byteEnd);
225427
+ const edits = [];
225428
+ ops.forEach((op, ordinal) => {
225429
+ const start = op.type === "insert" ? op.insertAt : op.oldFrom;
225430
+ const end = op.type === "insert" ? op.insertAt : op.oldTo;
225431
+ const range = sliceParagraphRangeFromOffsetMap(entry, offsetMap, blockId, start, end);
225432
+ if (!range)
225433
+ return;
225434
+ edits.push({ on: range, newText: op.type === "delete" ? "" : op.newText, comparisonHunkGroupId: `${txId}:${blockId}:${ordinal}` });
225435
+ });
225436
+ if (edits.length !== ops.length)
225437
+ return null;
225438
+ const [first, ...rest] = edits;
225439
+ if (!first)
225440
+ return null;
225441
+ return {
225442
+ kind: "editText",
225443
+ changeMode: "tracked",
225444
+ on: first.on,
225445
+ newText: first.newText,
225446
+ rsid: allocateTxRsid(txId),
225447
+ edits: [first, ...rest]
225448
+ };
225449
+ }
224339
225450
  function deriveSimpleInlineFormatEdits(baseParagraphXml, targetRunXml) {
224340
225451
  const base2 = scanSimpleRunFormatting(extractCompareParagraphRunXml(baseParagraphXml));
224341
225452
  const target = scanSimpleRunFormatting(targetRunXml);
@@ -226201,7 +227312,7 @@ function committedNoOp2(txId, packageRevision) {
226201
227312
  function rejected14(txId, reason) {
226202
227313
  return { txId, status: "rejected", rejectedReason: reason };
226203
227314
  }
226204
- var EXACT_ROW_UNSAFE_REVISION_LOCAL_NAMES, NOTE_LIFECYCLE_PROVENANCE_NS2 = "urn:superdoc:note-lifecycle", MARKUP_COMPATIBILITY_NS = "http://schemas.openxmlformats.org/markup-compatibility/2006", UNDERSTOOD_NOTE_LIFECYCLE_MCE_NAMESPACES, XML_NCNAME_TOKEN, EXACT_ROW_UNSAFE_W14_REVISION_LOCAL_NAMES, SIGNAL_LANES, TE31, TD59, XML_TD2, DOCUMENT_PART_URI4 = "/word/document.xml", DOCUMENT_RELS_PART_URI6 = "/word/_rels/document.xml.rels", CONTENT_TYPES_PART_URI7 = "/[Content_Types].xml", RELATIONSHIPS_CONTENT_TYPE = "application/vnd.openxmlformats-package.relationships+xml", RELATIONSHIP_BACKED_SAVE_NOISE_PART_URIS, W_NS4 = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", REL_FOOTNOTES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes", REL_ENDNOTES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes", CT_FOOTNOTES = "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml", CT_ENDNOTES = "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml", PACKAGE_RELATIONSHIPS_NS2 = "http://schemas.openxmlformats.org/package/2006/relationships", CONTENT_TYPES_NS4 = "http://schemas.openxmlformats.org/package/2006/content-types", DRAWINGML_NS = "http://schemas.openxmlformats.org/drawingml/2006/main", CORE_PROPERTIES_NS = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties", DCTERMS_NS = "http://purl.org/dc/terms/", EXTENDED_PROPERTIES_NS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties", IMAGE_RELATIONSHIP_TYPES, HEADER_RELATIONSHIP_TYPES, FOOTER_RELATIONSHIP_TYPES, COMPARE_NOTE_MARKER = "", SIMPLE_INLINE_RUN_PROPERTY_ATTRIBUTES;
227315
+ var EXACT_ROW_UNSAFE_REVISION_LOCAL_NAMES, NOTE_LIFECYCLE_PROVENANCE_NS2 = "urn:superdoc:note-lifecycle", MARKUP_COMPATIBILITY_NS = "http://schemas.openxmlformats.org/markup-compatibility/2006", UNDERSTOOD_NOTE_LIFECYCLE_MCE_NAMESPACES, XML_NCNAME_TOKEN, EXACT_ROW_UNSAFE_W14_REVISION_LOCAL_NAMES, SIGNAL_LANES, TE31, TD59, XML_TD2, DOCUMENT_PART_URI4 = "/word/document.xml", DOCUMENT_RELS_PART_URI6 = "/word/_rels/document.xml.rels", CONTENT_TYPES_PART_URI7 = "/[Content_Types].xml", RELATIONSHIPS_CONTENT_TYPE = "application/vnd.openxmlformats-package.relationships+xml", RELATIONSHIP_BACKED_SAVE_NOISE_PART_URIS, W_NS4 = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", REL_FOOTNOTES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes", REL_ENDNOTES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes", CT_FOOTNOTES = "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml", CT_ENDNOTES = "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml", PACKAGE_RELATIONSHIPS_NS2 = "http://schemas.openxmlformats.org/package/2006/relationships", CONTENT_TYPES_NS4 = "http://schemas.openxmlformats.org/package/2006/content-types", DRAWINGML_NS = "http://schemas.openxmlformats.org/drawingml/2006/main", CORE_PROPERTIES_NS = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties", DCTERMS_NS = "http://purl.org/dc/terms/", EXTENDED_PROPERTIES_NS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties", IMAGE_RELATIONSHIP_TYPES, HEADER_RELATIONSHIP_TYPES, FOOTER_RELATIONSHIP_TYPES, WORD_DIFF_FALLBACK_RATIO = 0.6, MAX_WORD_DIFF_HUNKS = 1000, DENSE_WORD_DIFF_RATIO = 0.3, COMPARE_NOTE_MARKER = "", SIMPLE_INLINE_RUN_PROPERTY_ATTRIBUTES;
226205
227316
  var init_compile_compare_apply = __esm(() => {
226206
227317
  init_tracked_table_properties();
226207
227318
  init_sd_document_state();
@@ -226209,6 +227320,7 @@ var init_compile_compare_apply = __esm(() => {
226209
227320
  init_src2();
226210
227321
  init_xml_text();
226211
227322
  init_text_offset_mapping();
227323
+ init_comparison_hunk_groups();
226212
227324
  init_commit_prepared_mutation();
226213
227325
  init_apply_patch_group();
226214
227326
  init_compile_format_run_range();
@@ -261400,7 +262512,7 @@ function refConfigSchemas2() {
261400
262512
  failure: refFailureSchema2
261401
262513
  };
261402
262514
  }
261403
- var trackChangeTypeValues2, sourcePathSchema2, diagnosticPathSchema2, conversionSourceRangeSchema2, conversionSourceSchema2, diagnosticProperties2, sdDiagnosticSchema2, sdConversionDiagnosticSchema2, conversionReportSchema2, receiptSuccessMetadataProperties2, nodeTypeValues2, blockNodeTypeValues2, deletableBlockNodeTypeValues2, inlineNodeTypeValues2, knownTargetKindValues2, SHARED_DEFS2, rangeSchema2, positionSchema2, inlineAnchorSchema2, targetKindSchema2, textAddressSchema2, textTargetSchema2, commentTrackedChangeTargetSchema2, textSearchCommentTargetSchema2, blockNodeAddressSchema2, deletableBlockNodeAddressSchema2, tableAddressSchema2, tableRowAddressSchema2, tableCellAddressSchema2, tableOrCellAddressSchema2, paragraphAddressSchema2, headingAddressSchema2, listItemAddressSchema2, listsV2BlockTargetSchema2, paragraphTargetSchema2, sectionAddressSchema2, watermarkSlotTargetSchema2, watermarkTargetSchema2, watermarkAddressSchema2, watermarkHorizontalPlacementSchema2, watermarkVerticalPlacementSchema2, watermarkPlacementSchema2, textWatermarkSchema2, pictureWatermarkInputSchema2, retainedPictureWatermarkInputSchema2, watermarksApplyTargetSchema2, pictureWatermarkInfoSchema2, watermarkInfoSchema2, watermarksApplySuccessSchema2, watermarksApplyFailureSchema2, inlineNodeAddressSchema2, nodeAddressSchema2, commentAddressSchema2, trackedChangeAddressSchema2, entityAddressSchema2, selectionTargetSchema2, commentTrackedChangeLinkSchema2, targetLocatorSchema2, deleteBehaviorSchema2, resolvedHandleSchema2, pageInfoSchema2, receiptSuccessSchema2, commentsCreateSuccessSchema2, textMutationRangeSchema2, textMutationResolutionSchema2, textMutationSuccessSchema2, matchRunSchema2, matchBlockSchema2, storyLocatorSchema2, bodyStoryLocatorSchema2, markRunColorRefSchema2, markRunFontsSchema2, markRunLanguagesSchema2, markRunUnderlineSchema2, markRunShadingSchema2, markRunBorderSchema2, markRunPropsSchema2, trackChangeRefSchema2, createParagraphSuccessSchema2, createHeadingSuccessSchema2, createHeadingLevelSchema2, semanticHeadingLevelSchema2, listsInsertSuccessSchema2, listsMutateItemSuccessSchema2, listsExitSuccessSchema2, nodeSummarySchema2, nodeInfoSchema2, matchContextSchema2, unknownNodeDiagnosticSchema2, textSelectorSchema2, planTextSelectorSchema2, nodeSelectorSchema2, selectorShorthandSchema2, sdTextSelectorSchema2, sdNodeSelectorSchema2, sdSelectorSchema2, sdReadOptionsSchema2, sdFindInputSchema2, sdNodeResultSchema2, sdFindResultSchema2, sdMutationResolutionSchema2, evaluatedRevisionSchema2, sdMutationSuccessSchema2, documentInfoCountsSchema2, documentInfoOutlineItemSchema2, documentInfoCapabilitiesSchema2, documentStyleInfoSchema2, documentStylesSchema2, documentDefaultsSchema2, documentInfoSchema2, listKindSchema2, listInsertPositionSchema2, listItemInfoSchema2, listItemDomainItemSchema2, listsListResultSchema2, sectionBreakTypeSchema2, sectionOrientationSchema2, sectionVerticalAlignSchema2, sectionDirectionSchema2, sectionHeaderFooterKindSchema2, sectionHeaderFooterVariantSchema2, sectionLineNumberRestartSchema2, sectionPageNumberFormatSchema2, sectionRangeDomainSchema2, sectionPageMarginsSchema2, sectionHeaderFooterMarginsSchema2, sectionPageSetupSchema2, sectionColumnsSchema2, sectionLineNumberingSchema2, sectionPageNumberingSchema2, sectionHeaderFooterRefsSchema2, sectionBorderSpecSchema2, sectionPageBordersSchema2, sectionInfoSchema2, sectionResolvedHandleSchema2, sectionDomainItemSchema2, sectionsListResultSchema2, sectionMutationSuccessSchema2, documentMutationSuccessSchema2, paragraphMutationTargetSchema2, paragraphMutationSuccessSchema2, createSectionBreakSuccessSchema2, commentMetadataSchema2, commentInfoSchema2, commentDomainItemSchema2, commentsListResultSchema2, trackChangeWordRevisionIdsSchema2, trackChangeSourceIdsSchema2, trackChangeBroadTypeEnum2, trackChangeGroupingEnum2, trackChangeCanonicalizationKindEnum2, trackChangeAddressKindEnum2, trackChangeSourcePlatformEnum2, trackChangeReplacementSideSchema2, trackChangeReplacementSchema2, trackChangeOverlapRelationshipSchema2, trackChangeOverlapLayerSchema2, trackChangeOverlapInfoSchema2, trackChangeFormattingSnapshotSchema2, trackChangeListDeltaKindEnum2, trackChangeListDeltaSideSchema2, trackChangeListMemberDeltaSchema2, trackChangeListDeltaSummarySchema2, trackChangeTargetSchema2, trackChangeSnapshotSchema2, trackChangeCustomAttributeSchema2, trackChangeRewriteReviewGroupSchema2, trackChangeInfoSchema2, trackChangeDomainItemSchema2, trackChangesListResultSchema2, reviewDecideRangeTargetOptions2, historyActionCollaborationSchema2, capabilityReasonCodeSchema2, capabilityReasonsSchema2, capabilitySupportDecisionSchema2, capabilityFlagSchema2, operationRuntimeCapabilitySchema2, operationCapabilitiesSchema2, inlinePropertyCapabilitySchema2, inlinePropertyCapabilitiesByKeySchema2, formatCapabilitiesSchema2, planEngineCapabilitiesSchema2, capabilitiesOutputSchema2, strictEmptyObjectSchema2, tableBorderColorPattern2, tableBorderSpecSchema2, nullableTableBorderSpecSchema2, sdFragmentSchema2, conversionFragmentSchema2, placementSchema2, nestingPolicySchema2, insertInputSchema2, supportCheckRichInsertInputSchema2, supportCheckRichReplaceInputSchema2, supportCheckProjectionInputSchema2, supportCheckInputSchema2, supportCheckFailureSchema2, supportCheckGuardSchema2, supportCheckCommonProperties2, supportCheckOutputSchema2, tableLocatorSchema2, cellLocatorSchema2, cellOrTableScopedCellLocatorSchema2, tableOrCellLocatorSchema2, mergeRangeLocatorSchema2, tableAnchorLocationMembers2, tableAnchorLocationSchema2, tableCreateLocationSchema2, tableMutationSuccessSchema2, createTableSuccessSchema2, tableMutationFailureCodes2, tableMutationFailureSchema2, tableMutationResultSchema2, createTableResultSchema2, historyActionSuccessSchema2, historyActionFailureSchema2, formatInlineAliasOperationSchemas2, tocMutationFailureCodes2, tocMutationFailureSchema2, tocMutationSuccessSchema2, tocEntryMutationFailureCodes2, tocEntryMutationFailureSchema2, tocEntryMutationSuccessSchema2, hyperlinkTargetSchema2, hyperlinkReadPropertiesSchema2, hyperlinkDestinationSchema2, hyperlinkSpecSchema2, hyperlinkPatchSchema2, hyperlinkDomainSchema2, hyperlinkMutationSuccessSchema2, hyperlinkMutationFailureCodes2, hyperlinkMutationFailureSchema2, hyperlinkInfoSchema2, contentControlTargetSchema2, contentControlMoveDestinationSchema2, contentControlMutationSuccessSchema2, contentControlMutationFailureSchema2, ccInfoSchema2, ccListResultSchema2, refListQueryProperties2, refListQuerySchema2, discoveryOutputSchema2, receiptFailureSchema2, refFailureSchema2, bookmarkAddressSchema2, bookmarkMutation2, customXmlPartTargetSchema2, customXmlPartMutation2, customXmlPartCreateMutation2, anchoredMetadataAttachMutation2, anchoredMetadataMutation2, footnoteAddressSchema2, footnoteConfigScopeSchema2, footnoteNumberingSchema2, footnoteMutation2, footnoteConfig2, crossRefAddressSchema2, crossRefTargetSchema2, crossRefDisplaySchema2, crossRefMutation2, indexAddressSchema2, indexEntryAddressSchema2, indexConfigSchema2, indexEntryDataSchema2, indexEntryPatchSchema2, indexMutation2, indexEntryMutation2, captionAddressSchema2, captionMutation2, captionConfig2, fieldAddressSchema2, fieldMutation2, citationAddressSchema2, citationSourceAddressSchema2, bibliographyAddressSchema2, citationMutation2, citationSourceMutation2, bibliographyMutation2, citationPersonSchema2, citationSourceFieldsSchema2, tocCreateLocationSchema2, authoritiesAddressSchema2, authorityEntryAddressSchema2, authoritiesConfigSchema2, authorityEntryDataSchema2, authorityEntryPatchSchema2, authoritiesMutation2, authorityEntryMutation2, diffCoverageSchema2, diffSummarySchema2, diffSnapshotSchema2, diffApplyEligibilityBlockerSchema2, diffApplyModeEligibilitySchema2, diffApplyEligibilitySchema2, diffPayloadSchema2, diffApplyResultSchema2, operationSchemas2;
262515
+ var trackChangeTypeValues2, sourcePathSchema2, diagnosticPathSchema2, conversionSourceRangeSchema2, conversionSourceSchema2, diagnosticProperties2, sdDiagnosticSchema2, sdConversionDiagnosticSchema2, conversionReportSchema2, receiptSuccessMetadataProperties2, nodeTypeValues2, blockNodeTypeValues2, deletableBlockNodeTypeValues2, inlineNodeTypeValues2, knownTargetKindValues2, SHARED_DEFS2, rangeSchema2, positionSchema2, inlineAnchorSchema2, targetKindSchema2, textAddressSchema2, textTargetSchema2, commentTrackedChangeTargetSchema2, textSearchCommentTargetSchema2, blockNodeAddressSchema2, deletableBlockNodeAddressSchema2, tableAddressSchema2, tableRowAddressSchema2, tableCellAddressSchema2, tableOrCellAddressSchema2, paragraphAddressSchema2, headingAddressSchema2, listItemAddressSchema2, listsV2BlockTargetSchema2, paragraphTargetSchema2, sectionAddressSchema2, watermarkSlotTargetSchema2, watermarkTargetSchema2, watermarkAddressSchema2, watermarkHorizontalPlacementSchema2, watermarkVerticalPlacementSchema2, watermarkPlacementSchema2, textWatermarkSchema2, pictureWatermarkInputSchema2, retainedPictureWatermarkInputSchema2, watermarksApplyTargetSchema2, pictureWatermarkInfoSchema2, watermarkInfoSchema2, watermarksApplySuccessSchema2, watermarksApplyFailureSchema2, inlineNodeAddressSchema2, nodeAddressSchema2, commentAddressSchema2, trackedChangeAddressSchema2, entityAddressSchema2, selectionTargetSchema2, commentTrackedChangeLinkSchema2, targetLocatorSchema2, deleteBehaviorSchema2, resolvedHandleSchema2, pageInfoSchema2, receiptSuccessSchema2, commentsCreateSuccessSchema2, textMutationRangeSchema2, textMutationResolutionSchema2, textMutationSuccessSchema2, matchRunSchema2, matchBlockSchema2, storyLocatorSchema2, bodyStoryLocatorSchema2, markRunColorRefSchema2, markRunFontsSchema2, markRunLanguagesSchema2, markRunUnderlineSchema2, markRunShadingSchema2, markRunBorderSchema2, markRunPropsSchema2, trackChangeRefSchema2, createParagraphSuccessSchema2, createHeadingSuccessSchema2, createHeadingLevelSchema2, semanticHeadingLevelSchema2, listsInsertSuccessSchema2, listsMutateItemSuccessSchema2, listsExitSuccessSchema2, nodeSummarySchema2, nodeInfoSchema2, matchContextSchema2, unknownNodeDiagnosticSchema2, textSelectorSchema2, planTextSelectorSchema2, nodeSelectorSchema2, selectorShorthandSchema2, sdTextSelectorSchema2, sdNodeSelectorSchema2, sdSelectorSchema2, sdReadOptionsSchema2, sdFindInputSchema2, sdNodeResultSchema2, sdFindResultSchema2, sdMutationResolutionSchema2, evaluatedRevisionSchema2, sdMutationSuccessSchema2, documentInfoCountsSchema2, documentInfoOutlineItemSchema2, documentInfoCapabilitiesSchema2, documentStyleInfoSchema2, documentStylesSchema2, documentDefaultsSchema2, documentInfoSchema2, listKindSchema2, listInsertPositionSchema2, listItemInfoSchema2, listItemDomainItemSchema2, listsListResultSchema2, sectionBreakTypeSchema2, sectionOrientationSchema2, sectionVerticalAlignSchema2, sectionDirectionSchema2, sectionHeaderFooterKindSchema2, sectionHeaderFooterVariantSchema2, sectionLineNumberRestartSchema2, sectionPageNumberFormatSchema2, sectionRangeDomainSchema2, sectionPageMarginsSchema2, sectionHeaderFooterMarginsSchema2, sectionPageSetupSchema2, sectionColumnsSchema2, sectionLineNumberingSchema2, sectionPageNumberingSchema2, sectionHeaderFooterRefsSchema2, sectionBorderSpecSchema2, sectionPageBordersSchema2, sectionInfoSchema2, sectionResolvedHandleSchema2, sectionDomainItemSchema2, sectionsListResultSchema2, sectionMutationSuccessSchema2, documentMutationSuccessSchema2, paragraphMutationTargetSchema2, paragraphMutationSuccessSchema2, createSectionBreakSuccessSchema2, commentMetadataSchema2, commentInfoSchema2, commentDomainItemSchema2, commentsListResultSchema2, trackChangeWordRevisionIdsSchema2, trackChangeSourceIdsSchema2, trackChangeBroadTypeEnum2, trackChangeGroupingEnum2, trackChangeCanonicalizationKindEnum2, trackChangeAddressKindEnum2, trackChangeSourcePlatformEnum2, trackChangeReplacementSideSchema2, trackChangeReplacementSchema2, trackChangeOverlapRelationshipSchema2, trackChangeOverlapLayerSchema2, trackChangeOverlapInfoSchema2, trackChangeFormattingSnapshotSchema2, trackChangeListDeltaKindEnum2, trackChangeListDeltaSideSchema2, trackChangeListMemberDeltaSchema2, trackChangeListDeltaSummarySchema2, trackChangeTargetSchema2, trackChangeSnapshotSchema2, trackChangeCustomAttributeSchema2, trackChangeRewriteReviewGroupSchema2, trackChangeComparisonHunkReviewGroupSchema2, trackChangeReviewGroupSchema2, trackChangeInfoSchema2, trackChangeDomainItemSchema2, trackChangesListResultSchema2, reviewDecideRangeTargetOptions2, historyActionCollaborationSchema2, capabilityReasonCodeSchema2, capabilityReasonsSchema2, capabilitySupportDecisionSchema2, capabilityFlagSchema2, operationRuntimeCapabilitySchema2, operationCapabilitiesSchema2, inlinePropertyCapabilitySchema2, inlinePropertyCapabilitiesByKeySchema2, formatCapabilitiesSchema2, planEngineCapabilitiesSchema2, capabilitiesOutputSchema2, strictEmptyObjectSchema2, tableBorderColorPattern2, tableBorderSpecSchema2, nullableTableBorderSpecSchema2, sdFragmentSchema2, conversionFragmentSchema2, placementSchema2, nestingPolicySchema2, insertInputSchema2, supportCheckRichInsertInputSchema2, supportCheckRichReplaceInputSchema2, supportCheckProjectionInputSchema2, supportCheckInputSchema2, supportCheckFailureSchema2, supportCheckGuardSchema2, supportCheckCommonProperties2, supportCheckOutputSchema2, tableLocatorSchema2, cellLocatorSchema2, cellOrTableScopedCellLocatorSchema2, tableOrCellLocatorSchema2, mergeRangeLocatorSchema2, tableAnchorLocationMembers2, tableAnchorLocationSchema2, tableCreateLocationSchema2, tableMutationSuccessSchema2, createTableSuccessSchema2, tableMutationFailureCodes2, tableMutationFailureSchema2, tableMutationResultSchema2, createTableResultSchema2, historyActionSuccessSchema2, historyActionFailureSchema2, formatInlineAliasOperationSchemas2, tocMutationFailureCodes2, tocMutationFailureSchema2, tocMutationSuccessSchema2, tocEntryMutationFailureCodes2, tocEntryMutationFailureSchema2, tocEntryMutationSuccessSchema2, hyperlinkTargetSchema2, hyperlinkReadPropertiesSchema2, hyperlinkDestinationSchema2, hyperlinkSpecSchema2, hyperlinkPatchSchema2, hyperlinkDomainSchema2, hyperlinkMutationSuccessSchema2, hyperlinkMutationFailureCodes2, hyperlinkMutationFailureSchema2, hyperlinkInfoSchema2, contentControlTargetSchema2, contentControlMoveDestinationSchema2, contentControlMutationSuccessSchema2, contentControlMutationFailureSchema2, ccInfoSchema2, ccListResultSchema2, refListQueryProperties2, refListQuerySchema2, discoveryOutputSchema2, receiptFailureSchema2, refFailureSchema2, bookmarkAddressSchema2, bookmarkMutation2, customXmlPartTargetSchema2, customXmlPartMutation2, customXmlPartCreateMutation2, anchoredMetadataAttachMutation2, anchoredMetadataMutation2, footnoteAddressSchema2, footnoteConfigScopeSchema2, footnoteNumberingSchema2, footnoteMutation2, footnoteConfig2, crossRefAddressSchema2, crossRefTargetSchema2, crossRefDisplaySchema2, crossRefMutation2, indexAddressSchema2, indexEntryAddressSchema2, indexConfigSchema2, indexEntryDataSchema2, indexEntryPatchSchema2, indexMutation2, indexEntryMutation2, captionAddressSchema2, captionMutation2, captionConfig2, fieldAddressSchema2, fieldMutation2, citationAddressSchema2, citationSourceAddressSchema2, bibliographyAddressSchema2, citationMutation2, citationSourceMutation2, bibliographyMutation2, citationPersonSchema2, citationSourceFieldsSchema2, tocCreateLocationSchema2, authoritiesAddressSchema2, authorityEntryAddressSchema2, authoritiesConfigSchema2, authorityEntryDataSchema2, authorityEntryPatchSchema2, authoritiesMutation2, authorityEntryMutation2, diffCoverageSchema2, diffSummarySchema2, diffSnapshotSchema2, diffApplyEligibilityBlockerSchema2, diffApplyModeEligibilitySchema2, diffApplyEligibilitySchema2, diffPayloadSchema2, diffApplyResultSchema2, operationSchemas2;
261404
262516
  var init_schemas5 = __esm(() => {
261405
262517
  init_command_catalog2();
261406
262518
  init_types8();
@@ -262946,6 +264058,23 @@ var init_schemas5 = __esm(() => {
262946
264058
  }, ["name", "namespaceUri", "localName", "value"]);
262947
264059
  trackChangeRewriteReviewGroupSchema2 = objectSchema4({
262948
264060
  kind: { const: "text-rewrite" },
264061
+ groupOrigin: { const: "authored-operation" },
264062
+ role: { enum: ["parent", "child"] },
264063
+ parentId: { type: "string" },
264064
+ childChangeIds: { type: "array", items: { type: "string" } },
264065
+ members: {
264066
+ type: "array",
264067
+ items: objectSchema4({
264068
+ id: { type: "string" },
264069
+ type: { enum: [...trackChangeBroadTypeEnum2] },
264070
+ subtype: { type: "string" },
264071
+ sourceIds: trackChangeSourceIdsSchema2
264072
+ }, ["id", "type", "subtype", "sourceIds"])
264073
+ }
264074
+ }, ["kind", "groupOrigin", "role", "childChangeIds", "members"]);
264075
+ trackChangeComparisonHunkReviewGroupSchema2 = objectSchema4({
264076
+ kind: { const: "comparison-hunk" },
264077
+ groupOrigin: { const: "comparison-hunk" },
262949
264078
  role: { enum: ["parent", "child"] },
262950
264079
  parentId: { type: "string" },
262951
264080
  childChangeIds: { type: "array", items: { type: "string" } },
@@ -262958,7 +264087,10 @@ var init_schemas5 = __esm(() => {
262958
264087
  sourceIds: trackChangeSourceIdsSchema2
262959
264088
  }, ["id", "type", "subtype", "sourceIds"])
262960
264089
  }
262961
- }, ["kind", "role", "childChangeIds", "members"]);
264090
+ }, ["kind", "groupOrigin", "role", "childChangeIds", "members"]);
264091
+ trackChangeReviewGroupSchema2 = {
264092
+ oneOf: [trackChangeRewriteReviewGroupSchema2, trackChangeComparisonHunkReviewGroupSchema2]
264093
+ };
262962
264094
  trackChangeInfoSchema2 = objectSchema4({
262963
264095
  address: trackedChangeAddressSchema2,
262964
264096
  id: { type: "string" },
@@ -262971,7 +264103,7 @@ var init_schemas5 = __esm(() => {
262971
264103
  sourceIds: trackChangeSourceIdsSchema2,
262972
264104
  wordRevisionIds: trackChangeWordRevisionIdsSchema2,
262973
264105
  revisionGroupId: { type: "string" },
262974
- reviewGroup: trackChangeRewriteReviewGroupSchema2,
264106
+ reviewGroup: trackChangeReviewGroupSchema2,
262975
264107
  splitFromId: { oneOf: [{ type: "string" }, { type: "null" }] },
262976
264108
  replacement: trackChangeReplacementSchema2,
262977
264109
  author: { type: "string" },
@@ -263022,7 +264154,7 @@ var init_schemas5 = __esm(() => {
263022
264154
  sourceIds: trackChangeSourceIdsSchema2,
263023
264155
  wordRevisionIds: trackChangeWordRevisionIdsSchema2,
263024
264156
  revisionGroupId: { type: "string" },
263025
- reviewGroup: trackChangeRewriteReviewGroupSchema2,
264157
+ reviewGroup: trackChangeReviewGroupSchema2,
263026
264158
  author: { type: "string" },
263027
264159
  authorEmail: { type: "string" },
263028
264160
  authorImage: { type: "string" },
@@ -289719,6 +290851,7 @@ function normalizeTarget(target) {
289719
290851
  // ../../../v2/editor-core/dist/review-read-model.js
289720
290852
  var init_review_read_model = __esm(() => {
289721
290853
  init_rewrite_groups();
290854
+ init_comparison_hunk_groups();
289722
290855
  });
289723
290856
 
289724
290857
  // ../../../v2/document-api-v2-adapter/dist/interaction-trace.js
@@ -358901,8 +360034,9 @@ class V2TrackedChangesAdapter {
358901
360034
  continue;
358902
360035
  }
358903
360036
  if (entry.reviewGroup?.role === "parent") {
358904
- if (entry.reviewGroup.kind === "text-rewrite")
360037
+ if (entry.reviewGroup.kind === "text-rewrite" || entry.reviewGroup.kind === "comparison-hunk") {
358905
360038
  cascadeChildRefs.push({ kind: "trackedChange", entityId: entry.id, storyId: entry.storyId });
360039
+ }
358906
360040
  for (const fragment3 of entry.structuralFragments) {
358907
360041
  if (seenStructuralKeys.has(fragment3.entityKey))
358908
360042
  continue;
@@ -359169,7 +360303,7 @@ class V2TrackedChangesAdapter {
359169
360303
  continue;
359170
360304
  const id = logical.rsidToLogicalId.get(ref5.entityId) ?? ref5.entityId;
359171
360305
  const group = logical.byId.get(id)?.reviewGroup;
359172
- if (group?.kind === "text-rewrite")
360306
+ if (group?.kind === "text-rewrite" || group?.kind === "comparison-hunk")
359173
360307
  touchedGroups.add(group.parentId ?? id);
359174
360308
  }
359175
360309
  const survivingGroups = [...touchedGroups].filter((id) => getPostLogical().byId.has(id));
@@ -359207,7 +360341,7 @@ class V2TrackedChangesAdapter {
359207
360341
  if (!entry) {
359208
360342
  return failure17("TARGET_NOT_FOUND", `No tracked change with id "${target.range.anchor}".`);
359209
360343
  }
359210
- if (entry.reviewGroup && !(entry.reviewGroup.kind === "text-rewrite" && entry.reviewGroup.role === "child")) {
360344
+ if (entry.reviewGroup && !((entry.reviewGroup.kind === "text-rewrite" || entry.reviewGroup.kind === "comparison-hunk") && entry.reviewGroup.role === "child")) {
359211
360345
  return failure17("INVALID_INPUT", `trackChanges.decide range: tracked change "${entry.id}" is part of a grouped Word revision; ` + "decide it atomically by id.");
359212
360346
  }
359213
360347
  if (entry.type === "structural" || entry.type === "move") {
@@ -359374,7 +360508,7 @@ class V2TrackedChangesAdapter {
359374
360508
  if (!overlap.logical) {
359375
360509
  return failure17("INTERNAL_ERROR", `trackChanges.decide range: overlapped fragment "${overlap.fragment.rsid}" was not mapped to a logical tracked change.`);
359376
360510
  }
359377
- if (overlap.logical.reviewGroup && overlap.logical.reviewGroup.kind !== "text-rewrite") {
360511
+ if (overlap.logical.reviewGroup && overlap.logical.reviewGroup.kind !== "text-rewrite" && overlap.logical.reviewGroup.kind !== "comparison-hunk") {
359378
360512
  return failure17("INVALID_INPUT", `trackChanges.decide range: tracked change "${overlap.logical.id}" is part of a grouped multi-paragraph ` + "insertion; decide it atomically by id.");
359379
360513
  }
359380
360514
  }
@@ -359539,7 +360673,7 @@ function isTextCoordinateSpace(value2) {
359539
360673
  return value2 === undefined || value2 === "visible" || value2 === "tracked";
359540
360674
  }
359541
360675
  function selectFragmentForLogicalRange(entry, side) {
359542
- if (entry.reviewGroup?.kind === "text-rewrite" && entry.reviewGroup.role === "parent") {
360676
+ if (entry.reviewGroup?.role === "parent" && (entry.reviewGroup.kind === "text-rewrite" || entry.reviewGroup.kind === "comparison-hunk")) {
359543
360677
  const kind = side === "delete" || side === "deleted" || side === "source" ? "del" : "ins";
359544
360678
  return entry.fragments.find((fragment3) => fragment3.kind === kind) ?? entry.fragments[0] ?? null;
359545
360679
  }
@@ -359886,7 +361020,7 @@ function isVisibleLogicalChange(entry) {
359886
361020
  return isVisibleLogicalTrackedChange(entry);
359887
361021
  }
359888
361022
  function resolveSubsumedLogicalChange(logical, entry) {
359889
- if (entry.reviewGroup?.kind === "text-rewrite")
361023
+ if (entry.reviewGroup?.kind === "text-rewrite" || entry.reviewGroup?.kind === "comparison-hunk")
359890
361024
  return entry;
359891
361025
  if (entry.reviewGroup?.role === "child" && entry.reviewGroup.parentId) {
359892
361026
  return logical.byId.get(entry.reviewGroup.parentId) ?? entry;
@@ -359931,6 +361065,7 @@ function buildDiscoveryItem2(entry, context, logical, linkedCommentIds, resolveS
359931
361065
  ...structuralDescriptor ? { structuralDescriptor } : {},
359932
361066
  revisionGroupId: entry.revisionGroupId,
359933
361067
  ...entry.reviewGroup?.kind === "text-rewrite" && logical ? { reviewGroup: projectTextRewriteReviewGroup(entry, logical) } : {},
361068
+ ...entry.reviewGroup?.kind === "comparison-hunk" && logical ? { reviewGroup: projectComparisonHunkReviewGroup(entry, logical) } : {},
359934
361069
  splitFromId: entry.splitFromId,
359935
361070
  sourceIds: projectSourceIds(entry),
359936
361071
  wordRevisionIds: projectWordRevisionIdsAlias(entry),
@@ -360068,6 +361203,7 @@ function buildInfo(entry, context, logical, linkedCommentIds, resolveSession) {
360068
361203
  wordRevisionIds: projectWordRevisionIdsAlias(entry),
360069
361204
  revisionGroupId: entry.revisionGroupId,
360070
361205
  ...entry.reviewGroup?.kind === "text-rewrite" && logical ? { reviewGroup: projectTextRewriteReviewGroup(entry, logical) } : {},
361206
+ ...entry.reviewGroup?.kind === "comparison-hunk" && logical ? { reviewGroup: projectComparisonHunkReviewGroup(entry, logical) } : {},
360071
361207
  splitFromId: entry.splitFromId,
360072
361208
  ...structuralDescriptor ? { structuralDescriptor } : {},
360073
361209
  ...replacement ? { replacement } : {},
@@ -360175,8 +361311,9 @@ function isGoogleDocsLikePackage(session) {
360175
361311
  return getSDDocumentSessionInternalPartBytes(session, "/docProps/app.xml") == null && getSDDocumentSessionInternalPartBytes(session, "/docProps/core.xml") == null && getSDDocumentSessionInternalPartBytes(session, "/docProps/custom.xml") == null && getSDDocumentSessionInternalPartBytes(session, "/word/settings.xml") != null;
360176
361312
  }
360177
361313
  function projectGrouping(entry) {
360178
- if (entry.reviewGroup && !(entry.reviewGroup.kind === "text-rewrite" && entry.reviewGroup.role === "child"))
361314
+ if (entry.reviewGroup && !((entry.reviewGroup.kind === "text-rewrite" || entry.reviewGroup.kind === "comparison-hunk") && entry.reviewGroup.role === "child")) {
360179
361315
  return "unknown";
361316
+ }
360180
361317
  return entry.type === "replacement" || entry.sides ? "replacement-pair" : "standalone";
360181
361318
  }
360182
361319
  function projectInsertedText(entry, logical) {
@@ -364685,6 +365822,23 @@ var init_relationship_backed_body_replay = __esm(() => {
364685
365822
  });
364686
365823
 
364687
365824
  // ../../../v2/document-api-v2-adapter/dist/diff/sections-references-replay.js
365825
+ function hasUntrackableFieldReplayStep(steps) {
365826
+ return steps.some((step3) => (step3.kind === "field-topology" || step3.kind === "complex-field") && (!step3.beforeFragmentXml || !step3.afterFragmentXml || !isRunOnlyFieldFragment(step3.beforeFragmentXml, step3.beforeNamespaceBindings) || !isRunOnlyFieldFragment(step3.afterFragmentXml, step3.afterNamespaceBindings)));
365827
+ }
365828
+ function isRunOnlyFieldFragment(xml, namespaceBindings) {
365829
+ const parsed = collectXmlElementRanges(xml, { fragment: true, additionalNamespaces: namespaceBindings });
365830
+ if (parsed.errors.length > 0)
365831
+ return false;
365832
+ let end = 0;
365833
+ for (const range of parsed.ranges.sort((a, b) => a.start - b.start || b.end - a.end)) {
365834
+ if (range.start < end)
365835
+ continue;
365836
+ if (range.start !== end || range.tag.namespaceUri !== WORDPROCESSINGML_NS6 || range.tag.localName !== "r")
365837
+ return false;
365838
+ end = range.end;
365839
+ }
365840
+ return end === xml.length;
365841
+ }
364688
365842
  function buildSectionsReferencesReplayPlan(base3, target) {
364689
365843
  const unsafeReasons = [];
364690
365844
  const sectionSteps = buildSectionSteps(base3.xml, target.xml, unsafeReasons);
@@ -364886,7 +366040,10 @@ function buildReferenceSteps(baseXml, targetXml, unsafeReasons) {
364886
366040
  const baseFields = collectWordElements(baseXml, "fldSimple");
364887
366041
  const targetFields = collectWordElements(targetXml, "fldSimple");
364888
366042
  if (baseFields.length !== targetFields.length) {
364889
- unsafeReasons.push("simple-field topology changed");
366043
+ const topologySteps = buildFieldTopologySteps(baseXml, targetXml, unsafeReasons);
366044
+ if (topologySteps.length === 0)
366045
+ unsafeReasons.push("simple-field topology changed");
366046
+ steps.push(...topologySteps);
364890
366047
  return steps;
364891
366048
  }
364892
366049
  for (let index2 = 0;index2 < baseFields.length; index2 += 1) {
@@ -364913,8 +366070,87 @@ function buildReferenceSteps(baseXml, targetXml, unsafeReasons) {
364913
366070
  });
364914
366071
  }
364915
366072
  steps.push(...buildAddedComplexFieldSteps(baseXml, targetXml, unsafeReasons));
366073
+ steps.push(...buildFieldTopologySteps(baseXml, targetXml, unsafeReasons).filter((candidate2) => !steps.some((step3) => step3.beforeXml === candidate2.beforeXml)));
366074
+ return steps;
366075
+ }
366076
+ function buildFieldTopologySteps(baseXml, targetXml, unsafeReasons) {
366077
+ const baseParagraphs = collectWordElements(baseXml, "p");
366078
+ const targetParagraphs = collectWordElements(targetXml, "p");
366079
+ if (baseParagraphs.length !== targetParagraphs.length)
366080
+ return [];
366081
+ const steps = [];
366082
+ for (let index2 = 0;index2 < baseParagraphs.length; index2 += 1) {
366083
+ const before = baseParagraphs[index2];
366084
+ const after = targetParagraphs[index2];
366085
+ if (before.xml === after.xml)
366086
+ continue;
366087
+ const simple = simpleFieldTopologyFragment(before, after) ?? simpleFieldTopologyFragment(after, before);
366088
+ const complex = addedComplexRefField(before, after.xml) ?? addedComplexRefField(after, before.xml);
366089
+ const candidate2 = simple ? { fieldXml: simple.fieldXml, resultXml: simple.resultXml } : complex;
366090
+ if (!candidate2)
366091
+ continue;
366092
+ const addition = after.xml.includes(candidate2.fieldXml);
366093
+ const beforeFragmentXml = addition ? candidate2.resultXml : candidate2.fieldXml;
366094
+ const afterFragmentXml = addition ? candidate2.fieldXml : candidate2.resultXml;
366095
+ if (replaceUnique(before.xml, beforeFragmentXml, afterFragmentXml) !== after.xml)
366096
+ continue;
366097
+ const name = simple ? parseRefInstruction(simple.instruction)?.name : complex?.referenceName;
366098
+ const source = addition ? targetXml : baseXml;
366099
+ const matchingBookmarks = collectWordElements(source, "bookmarkStart", true).filter((bookmark) => readAttribute2(bookmark, "name") === name);
366100
+ if (!name || matchingBookmarks.length !== 1) {
366101
+ unsafeReasons.push(`field topology ${index2} has a missing or ambiguous REF target`);
366102
+ continue;
366103
+ }
366104
+ steps.push({
366105
+ kind: "field-topology",
366106
+ beforeXml: before.xml,
366107
+ afterXml: after.xml,
366108
+ beforeFragmentXml,
366109
+ afterFragmentXml,
366110
+ beforeNamespaceBindings: { ...before.range.namespaceBindings },
366111
+ afterNamespaceBindings: { ...after.range.namespaceBindings }
366112
+ });
366113
+ }
364916
366114
  return steps;
364917
366115
  }
366116
+ function simpleFieldTopologyFragment(fieldParagraph, resultParagraph) {
366117
+ const fields = collectWordElements(fieldParagraph.xml, "fldSimple", false, fieldParagraph.range.namespaceBindings);
366118
+ if (fields.length !== 1 || collectWordElements(fieldParagraph.xml, "fldChar", true, fieldParagraph.range.namespaceBindings).length > 0)
366119
+ return null;
366120
+ const field = fields[0];
366121
+ const instruction = readAttribute2(field, "instr");
366122
+ if (!instruction || !parseRefInstruction(instruction))
366123
+ return null;
366124
+ const resultXml = fieldParagraph.xml.slice(field.range.openEnd, field.range.closeStart);
366125
+ if (!resultXml || replaceUnique(fieldParagraph.xml, field.xml, resultXml) !== resultParagraph.xml)
366126
+ return null;
366127
+ const parsed = collectXmlElementRanges(field.xml, {
366128
+ fragment: true,
366129
+ additionalNamespaces: { ...fieldParagraph.range.namespaceBindings }
366130
+ });
366131
+ const disallowed = new Set([
366132
+ "fldSimple",
366133
+ "fldChar",
366134
+ "hyperlink",
366135
+ "drawing",
366136
+ "object",
366137
+ "pict",
366138
+ "sdt",
366139
+ "customXml",
366140
+ "ins",
366141
+ "del",
366142
+ "footnoteReference",
366143
+ "endnoteReference",
366144
+ "commentReference",
366145
+ "bookmarkStart",
366146
+ "bookmarkEnd"
366147
+ ]);
366148
+ if (parsed.errors.length > 0 || parsed.ranges.some((range) => range.start > 0 && (range.tag.namespaceUri !== WORDPROCESSINGML_NS6 || disallowed.has(range.tag.localName))))
366149
+ return null;
366150
+ if (collectWordElements(resultXml, "r", false, fieldParagraph.range.namespaceBindings).length === 0)
366151
+ return null;
366152
+ return { fieldXml: field.xml, resultXml, instruction };
366153
+ }
364918
366154
  function buildChangedBookmarkSteps(baseXml, targetXml, baseBookmarks, targetBookmarks, unsafeReasons) {
364919
366155
  const baseByName = bookmarkStartsByName(baseBookmarks);
364920
366156
  const targetByName = bookmarkStartsByName(targetBookmarks);
@@ -365751,6 +366987,9 @@ class V2DiffAdapter {
365751
366987
  unsupportedReason: "section-reference-replay-unsafe"
365752
366988
  });
365753
366989
  }
366990
+ if (reviewMarkup && hasUntrackableFieldReplayStep(sectionsReferencesPlan.referenceSteps)) {
366991
+ throw diffValidationError("CAPABILITY_UNSUPPORTED", "diff.apply: tracked field replay requires run-only fragments for a schema-valid review and exact target representation. No mutation was performed.", { changedFamilies: ["fields-references"], unsupportedReason: "section-reference-replay-unsafe" });
366992
+ }
365754
366993
  const usesLocalizedMainDocumentReplay = sectionsReferencesChanged && (sectionsReferencesPlan.sectionSteps.length > 0 || sectionsReferencesPlan.referenceSteps.length > 0);
365755
366994
  const localizedBodyOperations = usesLocalizedMainDocumentReplay ? buildLocalizedBodyOperations(payload.base.body, payload.target.body, sectionsReferencesPlan.sectionSteps, sectionsReferencesPlan.referenceSteps, { base: payload.base.definitions, target: payload.target.definitions }, canonicalBodyOperations) : [];
365756
366995
  if (usesLocalizedMainDocumentReplay) {
@@ -366243,6 +367482,13 @@ function buildCompareApplyEligibility(context, payload, plans) {
366243
367482
  }
366244
367483
  const sectionReferenceFamilies = payload.familyPolicy.filter((policy) => policy.applyRequired && (policy.family === "sections" || policy.family === "fields-references")).map((policy) => policy.family);
366245
367484
  addPlanHazards(hazards, plans.sectionsReferencesPlan.unsafeReasons, "section-reference-replay-unsafe", sectionReferenceFamilies, "Section/reference replay");
367485
+ if (hasUntrackableFieldReplayStep(plans.sectionsReferencesPlan.referenceSteps)) {
367486
+ hazards.tracked.push({
367487
+ code: "section-reference-replay-unsafe",
367488
+ message: "Tracked field replay requires run-only fragments for a schema-valid review and exact target representation.",
367489
+ families: ["fields-references"]
367490
+ });
367491
+ }
366246
367492
  addPlanHazards(hazards, plans.physicalPlan.unsafeReasons, "header-footer-physical-lifecycle-unsafe", ["header-footer-parts"], "Header/footer physical lifecycle");
366247
367493
  const headerFooterSlotsChanged = payload.familyPolicy.some((policy) => policy.family === "header-footer-slots" && policy.applyRequired);
366248
367494
  if (plans.physicalPlan.hasTopologyChanges || headerFooterSlotsChanged) {
@@ -366895,7 +368141,7 @@ function reverseReferenceAttribute(xml, step3) {
366895
368141
  const afterInner = step3.afterXml.slice(afterParagraph.openEnd, afterParagraph.closeStart);
366896
368142
  return stripReplayNamespaceDeclarations(xml) === stripReplayNamespaceDeclarations(afterInner) ? beforeInner : xml;
366897
368143
  }
366898
- if (step3.kind === "bookmark-range" || step3.kind === "complex-field") {
368144
+ if (step3.kind === "bookmark-range" || step3.kind === "complex-field" || step3.kind === "field-topology") {
366899
368145
  if (step3.beforeFragmentXml === undefined || step3.afterFragmentXml === undefined)
366900
368146
  return xml;
366901
368147
  const normalizedXml = stripReplayNamespaceDeclarations(xml);
@@ -367202,7 +368448,7 @@ function findUniqueReplayCarrier(xml, step3) {
367202
368448
  const start = xml.indexOf(marker);
367203
368449
  return start >= 0 && xml.indexOf(marker, start + marker.length) < 0 ? { start, end: start + marker.length } : null;
367204
368450
  }
367205
- if (step3.kind === "bookmark-range" || step3.kind === "complex-field") {
368451
+ if (step3.kind === "bookmark-range" || step3.kind === "complex-field" || step3.kind === "field-topology") {
367206
368452
  const fragment3 = step3.afterFragmentXml;
367207
368453
  if (!fragment3)
367208
368454
  return null;