@superdoc/mcp 1.0.0-next.5 → 1.0.0-next.7

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 +1409 -398
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -199498,6 +199498,93 @@ var init_contract = __esm(() => {
199498
199498
  revisionGroupId: {
199499
199499
  type: "string"
199500
199500
  },
199501
+ reviewGroup: {
199502
+ type: "object",
199503
+ properties: {
199504
+ kind: {
199505
+ const: "text-rewrite"
199506
+ },
199507
+ role: {
199508
+ enum: [
199509
+ "parent",
199510
+ "child"
199511
+ ]
199512
+ },
199513
+ parentId: {
199514
+ type: "string"
199515
+ },
199516
+ childChangeIds: {
199517
+ type: "array",
199518
+ items: {
199519
+ type: "string"
199520
+ }
199521
+ },
199522
+ members: {
199523
+ type: "array",
199524
+ items: {
199525
+ type: "object",
199526
+ properties: {
199527
+ id: {
199528
+ type: "string"
199529
+ },
199530
+ type: {
199531
+ enum: [
199532
+ "insertion",
199533
+ "deletion",
199534
+ "replacement"
199535
+ ]
199536
+ },
199537
+ subtype: {
199538
+ type: "string"
199539
+ },
199540
+ sourceIds: {
199541
+ type: "object",
199542
+ properties: {
199543
+ wordIdInsert: {
199544
+ type: "string",
199545
+ description: "Word `w:id` value from the insertion side of this logical change."
199546
+ },
199547
+ wordIdDelete: {
199548
+ type: "string",
199549
+ description: "Word `w:id` value from the deletion side of this logical change."
199550
+ },
199551
+ wordIdOther: {
199552
+ type: "array",
199553
+ items: {
199554
+ type: "string"
199555
+ },
199556
+ description: "Word `w:id` values from other wrappers (for example moveFrom/moveTo)."
199557
+ },
199558
+ rsids: {
199559
+ type: "array",
199560
+ items: {
199561
+ type: "string"
199562
+ },
199563
+ description: "Word revision-save ids (`w:rsidR` / `w:rsidDel`) seen on contributing wrappers."
199564
+ }
199565
+ },
199566
+ additionalProperties: false,
199567
+ description: "Canonical multi-side source provenance. Provenance metadata only; never the canonical SuperDoc tracked-change id."
199568
+ }
199569
+ },
199570
+ additionalProperties: false,
199571
+ required: [
199572
+ "id",
199573
+ "type",
199574
+ "subtype",
199575
+ "sourceIds"
199576
+ ]
199577
+ }
199578
+ }
199579
+ },
199580
+ additionalProperties: false,
199581
+ required: [
199582
+ "kind",
199583
+ "role",
199584
+ "childChangeIds",
199585
+ "members"
199586
+ ]
199587
+ },
199501
199588
  author: {
199502
199589
  type: "string"
199503
199590
  },
@@ -200406,6 +200493,93 @@ var init_contract = __esm(() => {
200406
200493
  revisionGroupId: {
200407
200494
  type: "string"
200408
200495
  },
200496
+ reviewGroup: {
200497
+ type: "object",
200498
+ properties: {
200499
+ kind: {
200500
+ const: "text-rewrite"
200501
+ },
200502
+ role: {
200503
+ enum: [
200504
+ "parent",
200505
+ "child"
200506
+ ]
200507
+ },
200508
+ parentId: {
200509
+ type: "string"
200510
+ },
200511
+ childChangeIds: {
200512
+ type: "array",
200513
+ items: {
200514
+ type: "string"
200515
+ }
200516
+ },
200517
+ members: {
200518
+ type: "array",
200519
+ items: {
200520
+ type: "object",
200521
+ properties: {
200522
+ id: {
200523
+ type: "string"
200524
+ },
200525
+ type: {
200526
+ enum: [
200527
+ "insertion",
200528
+ "deletion",
200529
+ "replacement"
200530
+ ]
200531
+ },
200532
+ subtype: {
200533
+ type: "string"
200534
+ },
200535
+ sourceIds: {
200536
+ type: "object",
200537
+ properties: {
200538
+ wordIdInsert: {
200539
+ type: "string",
200540
+ description: "Word `w:id` value from the insertion side of this logical change."
200541
+ },
200542
+ wordIdDelete: {
200543
+ type: "string",
200544
+ description: "Word `w:id` value from the deletion side of this logical change."
200545
+ },
200546
+ wordIdOther: {
200547
+ type: "array",
200548
+ items: {
200549
+ type: "string"
200550
+ },
200551
+ description: "Word `w:id` values from other wrappers (for example moveFrom/moveTo)."
200552
+ },
200553
+ rsids: {
200554
+ type: "array",
200555
+ items: {
200556
+ type: "string"
200557
+ },
200558
+ description: "Word revision-save ids (`w:rsidR` / `w:rsidDel`) seen on contributing wrappers."
200559
+ }
200560
+ },
200561
+ additionalProperties: false,
200562
+ description: "Canonical multi-side source provenance. Provenance metadata only; never the canonical SuperDoc tracked-change id."
200563
+ }
200564
+ },
200565
+ additionalProperties: false,
200566
+ required: [
200567
+ "id",
200568
+ "type",
200569
+ "subtype",
200570
+ "sourceIds"
200571
+ ]
200572
+ }
200573
+ }
200574
+ },
200575
+ additionalProperties: false,
200576
+ required: [
200577
+ "kind",
200578
+ "role",
200579
+ "childChangeIds",
200580
+ "members"
200581
+ ]
200582
+ },
200409
200583
  splitFromId: {
200410
200584
  oneOf: [
200411
200585
  {
@@ -349641,7 +349815,7 @@ var init_host = __esm(() => {
349641
349815
  });
349642
349816
 
349643
349817
  // ../../packages/sdk/langs/node/src/runtime/sdk-version.generated.ts
349644
- var SDK_VERSION = "2.13.0-next.7";
349818
+ var SDK_VERSION = "2.13.0-next.9";
349645
349819
 
349646
349820
  // ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
349647
349821
  import { chmodSync, existsSync } from "node:fs";
@@ -389676,7 +389850,6 @@ async function runReplaceTextUnchecked(doc2, args) {
389676
389850
  let skippedEdits = [];
389677
389851
  let steps;
389678
389852
  let applyExpectedRevision;
389679
- const preserveTargets = [];
389680
389853
  if (args.selector) {
389681
389854
  const target = selectorToBlockTarget(args.selector, pre);
389682
389855
  if (!target) {
@@ -389715,13 +389888,6 @@ async function runReplaceTextUnchecked(doc2, args) {
389715
389888
  ];
389716
389889
  applyExpectedRevision = pre.revision;
389717
389890
  selectedTargets.push({ selector: args.selector, matched: [target.nodeId] });
389718
- preserveTargets.push({
389719
- nodeId: target.nodeId,
389720
- nodeType: target.nodeType ?? "paragraph",
389721
- oldText: target.text,
389722
- newText: rewrittenText,
389723
- runs: await captureBlockRuns(doc2, target.nodeId, target.text)
389724
- });
389725
389891
  } else {
389726
389892
  let candidates = args.edits.map((edit, editIndex) => ({
389727
389893
  edit,
@@ -389778,12 +389944,6 @@ async function runReplaceTextUnchecked(doc2, args) {
389778
389944
  steps = candidates.map((candidate) => candidate.step);
389779
389945
  }
389780
389946
  const result = await executeMutations(doc2, steps, args.changeMode, applyExpectedRevision);
389781
- const preserved = [];
389782
- for (const entry of preserveTargets) {
389783
- const restored = await preserveRunPatternAfterRewrite(doc2, entry.nodeId, entry.oldText, entry.runs, entry.newText);
389784
- if (restored)
389785
- preserved.push({ nodeId: entry.nodeId, ...restored });
389786
- }
389787
389947
  if (args.selector && selectedTargets[0]) {
389788
389948
  const post = await buildMutationSnapshot(doc2, { includeDomains: selectorDomains ?? ["blocks"] });
389789
389949
  const blockId = selectedTargets[0].matched[0];
@@ -389812,10 +389972,7 @@ async function runReplaceTextUnchecked(doc2, args) {
389812
389972
  preSnapshot: { revision: pre.revision, counts: pre.counts },
389813
389973
  postSnapshot: { revision: post.revision, counts: post.counts },
389814
389974
  selectedTargets,
389815
- executedOperations: [
389816
- { operationId: "doc.mutations.apply", result },
389817
- ...preserved.length > 0 ? [{ operationId: "doc.format.apply", result: { preserved } }] : []
389818
- ],
389975
+ executedOperations: [{ operationId: "doc.mutations.apply", result }],
389819
389976
  verification: verification2
389820
389977
  };
389821
389978
  }
@@ -389836,8 +389993,7 @@ async function runReplaceTextUnchecked(doc2, args) {
389836
389993
  operationId: "doc.mutations.apply",
389837
389994
  ...skippedEditRationale ? { rationale: skippedEditRationale } : {},
389838
389995
  result
389839
- },
389840
- ...preserved.length > 0 ? [{ operationId: "doc.format.apply", result: { preserved } }] : []
389996
+ }
389841
389997
  ],
389842
389998
  verification
389843
389999
  };
@@ -390811,7 +390967,6 @@ async function runRewriteBlock(doc2, args) {
390811
390967
  throw new Error("selector did not resolve to a body block");
390812
390968
  context.selectedTargets.push({ selector: args.selector, matched: [target.nodeId] });
390813
390969
  const text = normalizeTitleLikeRewriteText(target.text, args.text);
390814
- const runs = await captureBlockRuns(doc2, target.nodeId, target.text);
390815
390970
  await executeMutations(context.document, [
390816
390971
  {
390817
390972
  id: "rewrite-block-1",
@@ -390820,7 +390975,6 @@ async function runRewriteBlock(doc2, args) {
390820
390975
  args: { replacement: { text }, style: preserveRewriteStyle() }
390821
390976
  }
390822
390977
  ], args.changeMode, pre.revision);
390823
- await preserveRunPatternAfterRewrite(context.document, target.nodeId, target.text, runs, text);
390824
390978
  const post = await context.finish();
390825
390979
  const rewritten = await post.block(target.nodeId);
390826
390980
  const verification = [
@@ -390951,57 +391105,6 @@ async function preserveScopedRunPattern(doc2, nodeId, oldText, oldRuns, spans) {
390951
391105
  return { skipped: reasonOf(err) };
390952
391106
  }
390953
391107
  }
390954
- async function preserveRunPatternAfterRewrite(doc2, nodeId, oldText, oldRuns, newText) {
390955
- if (!oldRuns || oldRuns.length === 0)
390956
- return null;
390957
- if (!oldRuns.some((run) => Object.keys(inlineFromSnapshotRun(run, new Set)).length > 0))
390958
- return null;
390959
- const formatFn = maybeMethod2(doc2, ["format", "apply"]);
390960
- if (!formatFn)
390961
- return null;
390962
- const normalize = new Set(RUN_BOOL_MARKS.filter((key) => oldRuns.some((run) => run[key])));
390963
- const oldTrim = oldText.trim();
390964
- const newTrimStart = newText.length - newText.trimStart().length;
390965
- const newTrim = newText.trim();
390966
- let prefix = 0;
390967
- const maxCommon = Math.min(oldTrim.length, newTrim.length);
390968
- while (prefix < maxCommon && oldTrim[prefix] === newTrim[prefix])
390969
- prefix += 1;
390970
- let suffix = 0;
390971
- while (suffix < maxCommon - prefix && oldTrim[oldTrim.length - 1 - suffix] === newTrim[newTrim.length - 1 - suffix])
390972
- suffix += 1;
390973
- const delta = newTrim.length - oldTrim.length;
390974
- let applied = 0;
390975
- const applyRange = async (start, end, inline) => {
390976
- if (end <= start || Object.keys(inline).length === 0)
390977
- return;
390978
- const changed = await applyInlineQuiet(formatFn, {
390979
- blockId: nodeId,
390980
- start: newTrimStart + start,
390981
- end: newTrimStart + end,
390982
- inline
390983
- });
390984
- if (changed)
390985
- applied += 1;
390986
- };
390987
- try {
390988
- for (const run of oldRuns) {
390989
- const inline = inlineFromSnapshotRun(run, normalize);
390990
- await applyRange(run.start, Math.min(run.end, prefix), inline);
390991
- const sufStart = Math.max(run.start, oldTrim.length - suffix);
390992
- if (run.end > sufStart)
390993
- await applyRange(sufStart + delta, run.end + delta, inline);
390994
- }
390995
- const middleEnd = newTrim.length - suffix;
390996
- if (middleEnd > prefix) {
390997
- const anchorRun = oldRuns.find((run) => prefix > run.start && prefix <= run.end) ?? oldRuns[oldRuns.length - 1];
390998
- await applyRange(prefix, middleEnd, inlineFromSnapshotRun(anchorRun, normalize));
390999
- }
391000
- return applied > 0 ? { restoredRunRanges: applied } : null;
391001
- } catch (err) {
391002
- return { skipped: reasonOf(err) };
391003
- }
391004
- }
391005
391108
  function normalizeColor(raw) {
391006
391109
  const trimmed = raw.trim();
391007
391110
  if (trimmed.length === 0)
@@ -394856,7 +394959,7 @@ var init_actions = __esm(() => {
394856
394959
  delete_blocks: 'selectors[] (each resolving to ONE inspected block: list item, paragraph or heading), changeMode? — THE way to DELETE a whole LIST ITEM, paragraph or heading, bullet/number included. Use for "remove the first item under Article II" / "delete that clause". delete_text only strikes the text and leaves an empty numbered item behind. Deletes several blocks in ONE call; use delete_table for a whole table and delete_text to clear a table cell (a cell must keep a paragraph)',
394857
394960
  append_list: 'items[], kind?: ordered|bullet, headingText?, headingLevel?, placement? {at:"after"|"before",selector} builds the list at that block instead of document end',
394858
394961
  create_table: 'rows, columns, cellTexts? (2D: rows of cells; each cell is a plain string OR a STYLED object {runs:[{text,marks}], marks?} to format the cell — marks: bold/italic/underline/strikethrough/fontFamily/fontSize(points)/color(hex)/highlight), placement?, changeMode? — style cells HERE, do not format_text afterward; changeMode:"tracked" makes the table insertion itself a tracked change',
394859
- rewrite_block: "selector, text, changeMode? — REPLACES the whole block text; the block's intra-paragraph run pattern is preserved best-effort over the unchanged prefix/suffix. For appending a NEW paragraph/clause use insert_paragraphs, and for small wording edits prefer replace_text with a minimal find span",
394962
+ rewrite_block: "selector, text, changeMode? — REPLACES the whole block text using the document API's formatting preservation. For appending a NEW paragraph/clause use insert_paragraphs, and for small wording edits prefer replace_text with a minimal find span",
394860
394963
  fill_placeholders: "values[] and/or fields[{label?,value}], changeMode?",
394861
394964
  move_range: `fromText (text in the FIRST block of the range to move), toText? (text in the LAST block — omit to auto-extend across the whole VISUAL SECTION: from fromText up to the next heading-like/ALL-CAPS/bold title), then exactly ONE destination: afterText OR beforeText (text in the block to land after/before). Direct-only today: changeMode:"tracked" fails with no mutation because block-range deletion cannot be tracked. Moves plain paragraph/heading text only; a range containing a table, list, or image is refused with nothing changed. THE way to MOVE a contiguous block range or a visual "section" identified BY TEXT (works on styled-paragraph sections like PREAMBLE / SCHEDULE A that are NOT Word heading nodes). afterText on a heading-like block lands the range after that block's WHOLE section.`,
394862
394965
  comment_paragraphs: "commentText, scope?: all|body, excludeBlockQuotes?",
@@ -407310,7 +407413,7 @@ function refConfigSchemas() {
407310
407413
  failure: refFailureSchema
407311
407414
  };
407312
407415
  }
407313
- 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, pictureWatermarkInfoSchema, watermarkInfoSchema, 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, trackChangeInfoSchema, trackChangeDomainItemSchema, trackChangesListResultSchema, reviewDecideRangeTargetOptions, historyActionCollaborationSchema, capabilityReasonCodeSchema, capabilityReasonsSchema, 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;
407416
+ 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, pictureWatermarkInfoSchema, watermarkInfoSchema, 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, 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;
407314
407417
  var init_schemas4 = __esm(() => {
407315
407418
  init_command_catalog();
407316
407419
  init_types4();
@@ -408827,6 +408930,21 @@ var init_schemas4 = __esm(() => {
408827
408930
  localName: { type: "string" },
408828
408931
  value: { type: "string" }
408829
408932
  }, ["name", "namespaceUri", "localName", "value"]);
408933
+ trackChangeRewriteReviewGroupSchema = objectSchema2({
408934
+ kind: { const: "text-rewrite" },
408935
+ role: { enum: ["parent", "child"] },
408936
+ parentId: { type: "string" },
408937
+ childChangeIds: { type: "array", items: { type: "string" } },
408938
+ members: {
408939
+ type: "array",
408940
+ items: objectSchema2({
408941
+ id: { type: "string" },
408942
+ type: { enum: ["insertion", "deletion", "replacement"] },
408943
+ subtype: { type: "string" },
408944
+ sourceIds: trackChangeSourceIdsSchema
408945
+ }, ["id", "type", "subtype", "sourceIds"])
408946
+ }
408947
+ }, ["kind", "role", "childChangeIds", "members"]);
408830
408948
  trackChangeInfoSchema = objectSchema2({
408831
408949
  address: trackedChangeAddressSchema,
408832
408950
  id: { type: "string" },
@@ -408839,6 +408957,7 @@ var init_schemas4 = __esm(() => {
408839
408957
  sourceIds: trackChangeSourceIdsSchema,
408840
408958
  wordRevisionIds: trackChangeWordRevisionIdsSchema,
408841
408959
  revisionGroupId: { type: "string" },
408960
+ reviewGroup: trackChangeRewriteReviewGroupSchema,
408842
408961
  splitFromId: { oneOf: [{ type: "string" }, { type: "null" }] },
408843
408962
  replacement: trackChangeReplacementSchema,
408844
408963
  author: { type: "string" },
@@ -408889,6 +409008,7 @@ var init_schemas4 = __esm(() => {
408889
409008
  sourceIds: trackChangeSourceIdsSchema,
408890
409009
  wordRevisionIds: trackChangeWordRevisionIdsSchema,
408891
409010
  revisionGroupId: { type: "string" },
409011
+ reviewGroup: trackChangeRewriteReviewGroupSchema,
408892
409012
  author: { type: "string" },
408893
409013
  authorEmail: { type: "string" },
408894
409014
  authorImage: { type: "string" },
@@ -469788,6 +469908,214 @@ var init_review_groups = __esm(() => {
469788
469908
  init_numbering_catalog();
469789
469909
  });
469790
469910
 
469911
+ // ../../../v2/editor-core/dist/document/transactions/tracked-changes/rewrite-groups.js
469912
+ function readRewriteGroupId(carrier) {
469913
+ const values = carrier.customAttributes?.filter((attribute) => attribute.namespaceUri === REWRITE_NAMESPACE && attribute.localName === "id");
469914
+ if (values?.length !== 1)
469915
+ return null;
469916
+ const value = values[0].value;
469917
+ return /^[\w.:-]{1,200}$/.test(value) ? value : null;
469918
+ }
469919
+ function stampRewriteGroups(xml, groupsByRsid, source) {
469920
+ if (groupsByRsid.size === 0)
469921
+ return xml;
469922
+ if ([...groupsByRsid.values()].some((id) => !/^[\w.:-]{1,200}$/.test(id)))
469923
+ return null;
469924
+ const raw = buildTrackedChangeCatalogFromPartXml({ xml, ...source });
469925
+ const independentOrigins = new Set;
469926
+ for (const fragment2 of collectIndependentRewriteFragments(raw.byPart.get(source.partUri) ?? [], xml)) {
469927
+ const origin = fragment2.rsid ? groupsByRsid.get(fragment2.rsid) : undefined;
469928
+ if (origin)
469929
+ independentOrigins.add(origin);
469930
+ }
469931
+ const replacements = [];
469932
+ const parsed = walkXmlElements(xml, {
469933
+ fragment: true,
469934
+ additionalNamespaces: xmlFragmentAdditionalNamespaces(xml, new Map, { w: NS_W }),
469935
+ onOpenTag: ({ tag, end, namespaceBindings }) => {
469936
+ if (tag.namespaceUri !== NS_W || tag.isSelfClosing || tag.localName !== "ins" && tag.localName !== "del")
469937
+ return;
469938
+ const rsid = tag.attributes.find((attribute) => attribute.namespaceUri === NS_W && attribute.localName === (tag.localName === "ins" ? "rsidR" : "rsidDel"))?.value;
469939
+ const id = rsid ? groupsByRsid.get(rsid) : undefined;
469940
+ if (!id)
469941
+ return;
469942
+ const availablePrefix = (seed) => {
469943
+ let prefix2 = seed;
469944
+ for (let index = 1;namespaceBindings[prefix2]; index += 1)
469945
+ prefix2 = `${seed}${index}`;
469946
+ return prefix2;
469947
+ };
469948
+ const prefix = availablePrefix("sdRewrite");
469949
+ const mc = availablePrefix("sdRewriteMc");
469950
+ replacements.push({
469951
+ at: end - 1,
469952
+ text: ` xmlns:${prefix}="${REWRITE_NAMESPACE}" xmlns:${mc}="${MC_NAMESPACE}" ${mc}:Ignorable="${prefix}" ${prefix}:id="${id}"${independentOrigins.has(id) ? ` ${prefix}:display="children"` : ""}`
469953
+ });
469954
+ }
469955
+ });
469956
+ if (parsed.errors.length > 0)
469957
+ return null;
469958
+ let cursor = 0;
469959
+ const chunks = [];
469960
+ for (const replacement of replacements) {
469961
+ chunks.push(xml.slice(cursor, replacement.at), replacement.text);
469962
+ cursor = replacement.at;
469963
+ }
469964
+ chunks.push(xml.slice(cursor));
469965
+ return chunks.join("");
469966
+ }
469967
+ function buildTextRewriteReviewGroupId(storyId, origin, noteId) {
469968
+ return buildLogicalId(storyId, "rewrite-group", `${noteId ?? ""}:${origin}`);
469969
+ }
469970
+ function projectRewriteGroups(input) {
469971
+ const groups = new Map;
469972
+ for (const entry of input.byId.values()) {
469973
+ if (entry.reviewGroup || entry.fragments.length === 0 || !["insertion", "deletion", "replacement"].includes(entry.type))
469974
+ continue;
469975
+ const origin = readRewriteGroupId(entry.fragments[0]);
469976
+ if (!origin || entry.fragments.some((fragment2) => readRewriteGroupId(fragment2) !== origin))
469977
+ continue;
469978
+ const id = buildTextRewriteReviewGroupId(entry.storyId, origin, entry.noteId);
469979
+ const members = groups.get(id) ?? [];
469980
+ members.push(entry);
469981
+ groups.set(id, members);
469982
+ }
469983
+ for (const [id, children] of groups) {
469984
+ children.sort((a, b) => a.documentOrderStart - b.documentOrderStart || a.id.localeCompare(b.id));
469985
+ const first = children[0];
469986
+ const display = children.some((child) => child.fragments.some((fragment2) => fragment2.customAttributes?.some((attribute) => attribute.namespaceUri === REWRITE_NAMESPACE && attribute.localName === "display" && attribute.value === "children"))) ? { display: "children" } : {};
469987
+ const fragments = children.flatMap((child) => child.fragments).sort((a, b) => a.byteStart - b.byteStart);
469988
+ const inserted = fragments.filter((fragment2) => fragment2.kind === "ins");
469989
+ const deleted = fragments.filter((fragment2) => fragment2.kind === "del");
469990
+ const type = inserted.length === 0 ? "deletion" : deleted.length === 0 ? "insertion" : "replacement";
469991
+ const wordIdInsert = inserted.find((fragment2) => fragment2.wId)?.wId;
469992
+ const wordIdDelete = deleted.find((fragment2) => fragment2.wId)?.wId;
469993
+ const rsids = [
469994
+ ...new Set(fragments.map((fragment2) => fragment2.rsid).filter((value) => Boolean(value)))
469995
+ ];
469996
+ const parent = {
469997
+ ...first,
469998
+ id,
469999
+ type,
470000
+ subtype: type === "replacement" ? "text-replacement" : type === "insertion" ? "text-insertion" : "text-deletion",
470001
+ revisionGroupId: id,
470002
+ splitFromId: null,
470003
+ documentOrderStart: children.reduce((start, child) => Math.min(start, child.documentOrderStart), first.documentOrderStart),
470004
+ documentOrderEnd: children.reduce((end, child) => Math.max(end, child.documentOrderEnd), first.documentOrderEnd),
470005
+ before: { text: children.map((child) => child.before.text ?? "").join("") },
470006
+ after: { text: children.map((child) => child.after.text ?? "").join("") },
470007
+ sides: null,
470008
+ contributingRsids: rsids,
470009
+ sourceIds: {
470010
+ wordIdInsert,
470011
+ wordIdDelete,
470012
+ wordIdOther: [
470013
+ ...new Set(fragments.map((fragment2) => fragment2.wId).filter((value) => Boolean(value) && value !== wordIdInsert && value !== wordIdDelete))
470014
+ ],
470015
+ rsids
470016
+ },
470017
+ fragments,
470018
+ reviewGroup: {
470019
+ kind: "text-rewrite",
470020
+ ...display,
470021
+ role: "parent",
470022
+ parentId: null,
470023
+ ownedChildIds: children.map((child) => child.id),
470024
+ duplicateDisplayPolicy: "subsumed",
470025
+ members: children.flatMap((child) => child.fragments.map((fragment2) => ({
470026
+ logicalId: child.id,
470027
+ carrier: "text",
470028
+ partUri: fragment2.partUri,
470029
+ storyId: fragment2.storyId,
470030
+ rsid: fragment2.rsid,
470031
+ wordId: fragment2.wId,
470032
+ subtype: child.subtype,
470033
+ byteStart: fragment2.byteStart,
470034
+ byteEnd: fragment2.byteEnd
470035
+ })))
470036
+ }
470037
+ };
470038
+ for (const child of children)
470039
+ child.reviewGroup = {
470040
+ kind: "text-rewrite",
470041
+ ...display,
470042
+ role: "child",
470043
+ parentId: id,
470044
+ ownedChildIds: [],
470045
+ duplicateDisplayPolicy: "subsumed",
470046
+ members: []
470047
+ };
470048
+ input.byId.set(id, parent);
470049
+ input.byStory.get(first.storyId).push(parent);
470050
+ }
470051
+ }
470052
+ function projectTextRewriteReviewGroup(entry, logical) {
470053
+ if (entry.reviewGroup?.kind !== "text-rewrite")
470054
+ return;
470055
+ const group = entry.reviewGroup;
470056
+ return {
470057
+ kind: "text-rewrite",
470058
+ role: group.role,
470059
+ ...group.parentId ? { parentId: group.parentId } : {},
470060
+ childChangeIds: group.ownedChildIds,
470061
+ members: group.ownedChildIds.flatMap((id) => {
470062
+ const child = logical.byId.get(id);
470063
+ return child ? [
470064
+ {
470065
+ id,
470066
+ type: child.type,
470067
+ subtype: child.subtype,
470068
+ sourceIds: child.sourceIds
470069
+ }
470070
+ ] : [];
470071
+ })
470072
+ };
470073
+ }
470074
+ function isVisibleLogicalTrackedChange(entry) {
470075
+ const group = entry.reviewGroup;
470076
+ if (group?.display === "children" ? group.role === "parent" : group?.role === "child")
470077
+ return false;
470078
+ return entry.subsumption?.role !== "child";
470079
+ }
470080
+ function reviewGroupDisplayParentId(entry) {
470081
+ return entry.reviewGroup?.role === "child" && entry.reviewGroup.display !== "children" ? entry.reviewGroup.parentId : null;
470082
+ }
470083
+ var REWRITE_NAMESPACE = "urn:superdoc:tracked-rewrite:1", MC_NAMESPACE = "http://schemas.openxmlformats.org/markup-compatibility/2006";
470084
+ var init_rewrite_groups = __esm(() => {
470085
+ init_xml_sax();
470086
+ init_catalog3();
470087
+ init_logical_catalog();
470088
+ });
470089
+
470090
+ // ../../../v2/editor-core/dist/document/transactions/tracked-changes/table-split-paragraph.js
470091
+ function isEmptyTableSplitParagraph(xml, excludedStart, excludedEnd) {
470092
+ const shell = /\s+|<[\w.-]+:(?:p|r)\b(?:"[^"]*"|'[^']*'|[^>"'])*>|<\/[\w.-]+:(?:p|r)>/y;
470093
+ const property = /<(?:[\w.-]+:)?(pPr|rPr)(?=[\s/>])/y;
470094
+ let cursor = 0;
470095
+ while (cursor < xml.length) {
470096
+ if (cursor === excludedStart) {
470097
+ cursor = excludedEnd;
470098
+ continue;
470099
+ }
470100
+ property.lastIndex = cursor;
470101
+ const propertyMatch = property.exec(xml);
470102
+ if (propertyMatch) {
470103
+ const element = matchLeadingElement(xml.slice(cursor), propertyMatch[1]);
470104
+ if (!element)
470105
+ return false;
470106
+ cursor += element.length;
470107
+ continue;
470108
+ }
470109
+ shell.lastIndex = cursor;
470110
+ const shellMatch = shell.exec(xml);
470111
+ if (!shellMatch)
470112
+ return false;
470113
+ cursor += shellMatch[0].length;
470114
+ }
470115
+ return true;
470116
+ }
470117
+ var init_table_split_paragraph = () => {};
470118
+
469791
470119
  // ../../../v2/editor-core/dist/document/transactions/tracked-changes/list-deltas.js
469792
470120
  function createListEffectiveSideResolver(input) {
469793
470121
  return (pPrInnerXml) => {
@@ -470456,6 +470784,7 @@ function buildLogicalCatalog(raw, replacementMode, partXmlByUri, splitLineage, o
470456
470784
  structuralKeyToLogicalId,
470457
470785
  partXmlByUri
470458
470786
  });
470787
+ projectRewriteGroups({ byId, byStory });
470459
470788
  projectWordFormattingGroups({
470460
470789
  byId,
470461
470790
  byStory,
@@ -470820,6 +471149,8 @@ function projectOverlapRelationships(byId, partXmlByUri) {
470820
471149
  return;
470821
471150
  const fragmentsByPart = new Map;
470822
471151
  for (const logical of byId.values()) {
471152
+ if (logical.reviewGroup?.kind === "text-rewrite" && logical.reviewGroup.role === "parent")
471153
+ continue;
470823
471154
  if (!isOverlapEligibleType(logical.type))
470824
471155
  continue;
470825
471156
  for (const fragment2 of logical.fragments) {
@@ -471519,6 +471850,10 @@ function resolveReplacementMode(override) {
471519
471850
  return "paired";
471520
471851
  }
471521
471852
  function isReplacementPairCandidate(a, b, noteIdA, noteIdB) {
471853
+ const originA = readRewriteGroupId(a);
471854
+ const originB = readRewriteGroupId(b);
471855
+ if (originA !== originB || originA !== null && a.rsid !== b.rsid)
471856
+ return false;
471522
471857
  const opposites = a.kind === "del" && b.kind === "ins" || a.kind === "ins" && b.kind === "del";
471523
471858
  if (!opposites)
471524
471859
  return false;
@@ -471538,6 +471873,33 @@ function isReplacementPairCandidate(a, b, noteIdA, noteIdB) {
471538
471873
  return false;
471539
471874
  return true;
471540
471875
  }
471876
+ function collectIndependentRewriteFragments(fragments, partXml) {
471877
+ const ordered = [...fragments].sort((a, b) => a.byteStart - b.byteStart || b.byteEnd - a.byteEnd);
471878
+ const independent = new Set;
471879
+ const ancestors = [];
471880
+ const unconsumed = new Set;
471881
+ for (const [index, first] of ordered.entries()) {
471882
+ while (ancestors.length && !isStrictlyNestedIn(first, ancestors[ancestors.length - 1]))
471883
+ ancestors.pop();
471884
+ if (ancestors.some((parent) => parent.author.name !== first.author.name))
471885
+ independent.add(first);
471886
+ ancestors.push(first);
471887
+ const second = findAdjacentTrackedSiblingAfter(ordered, index, partXml, unconsumed);
471888
+ if (!second || !isReplacementPairCandidate(first, second, null, null))
471889
+ continue;
471890
+ const secondIndex = ordered.indexOf(second, index + 1);
471891
+ if (!isChildReplacementInsideDeletion({
471892
+ previous: findAdjacentTrackedSiblingBefore(ordered, index, partXml, unconsumed),
471893
+ first,
471894
+ second,
471895
+ next: findAdjacentTrackedSiblingAfter(ordered, secondIndex, partXml, unconsumed)
471896
+ }))
471897
+ continue;
471898
+ independent.add(first);
471899
+ independent.add(second);
471900
+ }
471901
+ return independent;
471902
+ }
471541
471903
  function isChildReplacementInsideDeletion(input) {
471542
471904
  const childAuthor = input.first.author.name || "";
471543
471905
  const touchesDifferentAuthorDeletionBefore = input.previous?.kind === "del" && (input.previous.author.name || "") !== childAuthor;
@@ -471681,6 +472043,8 @@ function collectAdjacentSameRevisionRun(head, index, fragmentsInPart, partXml, c
471681
472043
  if (run.some((fragment2) => isStrictlyNestedIn(candidate, fragment2)))
471682
472044
  continue;
471683
472045
  const candidateNoteId = noteIdFor(candidate);
472046
+ if ((readRewriteGroupId(head) || readRewriteGroupId(candidate)) && (readRewriteGroupId(head) !== readRewriteGroupId(candidate) || head.wId !== candidate.wId))
472047
+ break;
471684
472048
  if (isSameRevisionFragment(head, candidate, headNoteId, candidateNoteId)) {
471685
472049
  if (maybeBuildDerivedStructuralLogical(candidate, candidateNoteId, partXml))
471686
472050
  break;
@@ -473755,9 +474119,7 @@ function isTableSplitTextInsertion(fragment2, partXml) {
473755
474119
  const paragraphXml2 = partXml.slice(localStart, localEnd);
473756
474120
  const relativeStart2 = fragment2.byteStart - localStart;
473757
474121
  const relativeEnd2 = fragment2.byteEnd - localStart;
473758
- const paragraphWithoutFragment2 = paragraphXml2.slice(0, relativeStart2) + paragraphXml2.slice(relativeEnd2);
473759
- const stripped2 = stripElements(stripElements(paragraphWithoutFragment2, "pPr"), "rPr").replace(/<[\w.-]+:p\b[^>]*>/g, "").replace(/<\/[\w.-]+:p>/g, "").replace(/<[\w.-]+:r\b[^>]*>/g, "").replace(/<\/[\w.-]+:r>/g, "").replace(/\s+/g, "");
473760
- if (stripped2.length !== 0)
474122
+ if (!isEmptyTableSplitParagraph(paragraphXml2, relativeStart2, relativeEnd2))
473761
474123
  return false;
473762
474124
  }
473763
474125
  }
@@ -473782,9 +474144,7 @@ function isTableSplitTextInsertion(fragment2, partXml) {
473782
474144
  const paragraphXml = partXml.slice(paragraph.start, paragraph.end);
473783
474145
  const relativeStart = fragment2.byteStart - paragraph.start;
473784
474146
  const relativeEnd = fragment2.byteEnd - paragraph.start;
473785
- const paragraphWithoutFragment = paragraphXml.slice(0, relativeStart) + paragraphXml.slice(relativeEnd);
473786
- const stripped = stripElements(stripElements(paragraphWithoutFragment, "pPr"), "rPr").replace(/<[\w.-]+:p\b[^>]*>/g, "").replace(/<\/[\w.-]+:p>/g, "").replace(/<[\w.-]+:r\b[^>]*>/g, "").replace(/<\/[\w.-]+:r>/g, "").replace(/\s+/g, "");
473787
- return stripped.length === 0;
474147
+ return isEmptyTableSplitParagraph(paragraphXml, relativeStart, relativeEnd);
473788
474148
  }
473789
474149
  function isSingleParagraphXml(xml) {
473790
474150
  return /^<[\w.-]+:p\b[^>]*\/>$/.test(xml) || /^<[\w.-]+:p\b[\s\S]*<\/[\w.-]+:p>$/.test(xml);
@@ -474045,6 +474405,14 @@ function enrichLogicalChangeExcerpts(catalog, partXmlByUri) {
474045
474405
  const before = logical.before.text ?? "";
474046
474406
  logical.excerpt = after || before;
474047
474407
  }
474408
+ for (const parent of catalog.byId.values()) {
474409
+ if (parent.reviewGroup?.kind !== "text-rewrite" || parent.reviewGroup.role !== "parent")
474410
+ continue;
474411
+ const children = parent.reviewGroup.ownedChildIds.map((id) => catalog.byId.get(id));
474412
+ parent.before = { text: children.map((child) => child.before.text).filter(Boolean).join(" … ") };
474413
+ parent.after = { text: children.map((child) => child.after.text).filter(Boolean).join(" … ") };
474414
+ parent.excerpt = parent.after.text || parent.before.text || "";
474415
+ }
474048
474416
  }
474049
474417
  function decodePartXmlForLogicalCatalog(raw, readPartBytes2) {
474050
474418
  const out = new Map;
@@ -474194,6 +474562,8 @@ var init_logical_catalog = __esm(() => {
474194
474562
  init_structural_groups();
474195
474563
  init_numbering_catalog();
474196
474564
  init_review_groups();
474565
+ init_rewrite_groups();
474566
+ init_table_split_paragraph();
474197
474567
  init_list_deltas();
474198
474568
  init_comment_range_invariance();
474199
474569
  PARAGRAPH_SEMANTIC_KEYS = [
@@ -476281,6 +476651,32 @@ function reviewReplicaChainIsContiguous(commits, previousPackageRevision, nextPa
476281
476651
  }
476282
476652
  return expected === nextPackageRevision;
476283
476653
  }
476654
+ function textEditDirtyBlock(op) {
476655
+ if (!op.edits) {
476656
+ return {
476657
+ storyId: op.on.storyId,
476658
+ blockId: op.on.startBlockId,
476659
+ targetRange: { start: op.on.startOffset, end: op.on.endOffset },
476660
+ insertedTextLength: op.newText.length
476661
+ };
476662
+ }
476663
+ let start = Infinity;
476664
+ let end = 0;
476665
+ let delta = 0;
476666
+ for (const edit of op.edits) {
476667
+ if (edit.on.storyId !== op.on.storyId || edit.on.startBlockId !== op.on.startBlockId || edit.on.endBlockId !== op.on.startBlockId || edit.on.coordinateSpace === "tracked")
476668
+ return;
476669
+ start = Math.min(start, edit.on.startOffset);
476670
+ end = Math.max(end, edit.on.endOffset);
476671
+ delta += edit.newText.length - (edit.on.endOffset - edit.on.startOffset);
476672
+ }
476673
+ return {
476674
+ storyId: op.on.storyId,
476675
+ blockId: op.on.startBlockId,
476676
+ targetRange: { start, end },
476677
+ insertedTextLength: end - start + delta
476678
+ };
476679
+ }
476284
476680
  function buildBaseEnvelope(txId, prepared, result, dirtyBlockOverride) {
476285
476681
  if (result.status !== "committed" || result.documentEpoch == null || result.commitSequence == null || result.previousPackageRevision == null || result.packageRevision == null) {
476286
476682
  return null;
@@ -476288,12 +476684,7 @@ function buildBaseEnvelope(txId, prepared, result, dirtyBlockOverride) {
476288
476684
  const semantic = prepared.semanticDelta;
476289
476685
  const trackedAnnotations = captureTrackedAnnotationDelta(prepared);
476290
476686
  const op = prepared.source;
476291
- const dirtyBlock = dirtyBlockOverride ?? (op.kind === "editText" ? {
476292
- storyId: op.on.storyId,
476293
- blockId: op.on.startBlockId,
476294
- targetRange: { start: op.on.startOffset, end: op.on.endOffset },
476295
- insertedTextLength: op.newText.length
476296
- } : op.kind === "paragraphSplit" ? {
476687
+ const dirtyBlock = dirtyBlockOverride ?? (op.kind === "editText" ? textEditDirtyBlock(op) : op.kind === "paragraphSplit" ? {
476297
476688
  storyId: op.target.storyId,
476298
476689
  blockId: op.target.paraId,
476299
476690
  targetRange: { start: op.offset, end: op.offset },
@@ -491658,7 +492049,6 @@ function runDirectEditTextBatchCommit(input, edits) {
491658
492049
  });
491659
492050
  if (!commentCascade.ok)
491660
492051
  return rejected2(txId, commentCascade.reason);
491661
- const { edits: _edits, ...retainedSource } = op;
491662
492052
  const storiesTouched = [...new Set([
491663
492053
  ...textEditTouchedStories(state, storyId, partUri),
491664
492054
  ...commentCascade.storiesTouched
@@ -491699,6 +492089,8 @@ function runDirectEditTextBatchCommit(input, edits) {
491699
492089
  wId: revision.wId
491700
492090
  }))
491701
492091
  ]);
492092
+ const { edits: _edits, ...primarySource } = op;
492093
+ const retainedSource = { ...primarySource, batchSpanCount: edits.length };
491702
492094
  const forwardPatchGroup = {
491703
492095
  source: retainedSource,
491704
492096
  baseRevisions: {
@@ -491726,7 +492118,7 @@ function runDirectEditTextBatchCommit(input, edits) {
491726
492118
  };
491727
492119
  const prepared = {
491728
492120
  txId,
491729
- source: retainedSource,
492121
+ source: op,
491730
492122
  resolvedTargets: {
491731
492123
  partUris: Object.keys(perPart),
491732
492124
  stories: storiesTouched,
@@ -491842,6 +492234,34 @@ function rewritePlainTrackedTextBatch(paragraphBytes, edits, stampByEdit, stampi
491842
492234
  rewritten = rewritten.slice(0, op.start) + op.xml + rewritten.slice(op.end);
491843
492235
  return TE16.encode(rewritten);
491844
492236
  }
492237
+ function captureBatchTrackedAnnotations(paragraphBytes, createdIds) {
492238
+ if (createdIds.size === 0)
492239
+ return [];
492240
+ const pending = [...parseParagraphInlineMap(TD38.decode(paragraphBytes)).pieces];
492241
+ const seen = new Set;
492242
+ const annotations = [];
492243
+ while (pending.length > 0) {
492244
+ const piece = pending.pop();
492245
+ if ("children" in piece) {
492246
+ for (const child of piece.children)
492247
+ pending.push(child);
492248
+ }
492249
+ if (piece.kind !== "tracked" || piece.trackedKind !== "ins" && piece.trackedKind !== "del" || !piece.rsid || !createdIds.has(piece.rsid) || piece.revisionId == null || piece.author == null || piece.date == null)
492250
+ continue;
492251
+ const key2 = `${piece.rsid}:${piece.revisionId}:${piece.trackedKind}`;
492252
+ if (seen.has(key2))
492253
+ continue;
492254
+ seen.add(key2);
492255
+ annotations.push({
492256
+ changeId: piece.rsid,
492257
+ wId: piece.revisionId,
492258
+ kind: piece.trackedKind === "ins" ? "insert" : "delete",
492259
+ author: { name: piece.author, initials: piece.initials, email: piece.email },
492260
+ date: piece.date
492261
+ });
492262
+ }
492263
+ return annotations;
492264
+ }
491845
492265
  function runTrackedEditTextBatchCommit(input, edits) {
491846
492266
  const { state, txId, op } = input;
491847
492267
  const stamping = pickStamping(input);
@@ -491951,7 +492371,9 @@ function runTrackedEditTextBatchCommit(input, edits) {
491951
492371
  on: edit.on,
491952
492372
  newText: edit.newText,
491953
492373
  rsid: stamp.rsid,
491954
- insRsid: stamp.insRsid
492374
+ insRsid: stamp.insRsid,
492375
+ rewriteGroupId: edit.rewriteGroupId,
492376
+ preserveExistingRevisions: edit.preserveExistingRevisions
491955
492377
  };
491956
492378
  const paragraphWindow = { byteStart: 0, byteEnd: afterBytes.byteLength, isSelfClosing: false };
491957
492379
  const localized = edit.on.coordinateSpace === "tracked" ? null : rewriteLocalizedTracked(afterBytes, paragraphWindow, batchOp, {
@@ -491963,7 +492385,7 @@ function runTrackedEditTextBatchCommit(input, edits) {
491963
492385
  newText: edit.newText,
491964
492386
  allocateWIdBlock: () => null
491965
492387
  });
491966
- if (localized?.ok) {
492388
+ if (localized?.ok && !(edit.preserveExistingRevisions && localized.foldedInsRsid)) {
491967
492389
  afterBytes = localized.bytes;
491968
492390
  if (localized.foldedInsRsid) {
491969
492391
  emittedByEdit.set(edit, []);
@@ -491990,7 +492412,7 @@ function runTrackedEditTextBatchCommit(input, edits) {
491990
492412
  }
491991
492413
  continue;
491992
492414
  }
491993
- if (localized && localized.reason !== "text-range-in-unsupported-tracked-wrapper") {
492415
+ if (localized && !localized.ok && localized.reason !== "text-range-in-unsupported-tracked-wrapper") {
491994
492416
  return rejected2(txId, localized.reason);
491995
492417
  }
491996
492418
  const overlap = tryOverlapRewriteTracked({ ...input, op: batchOp }, afterBytes, paragraphWindow, paragraph.byteStart, {
@@ -492008,19 +492430,6 @@ function runTrackedEditTextBatchCommit(input, edits) {
492008
492430
  for (const rsid of overlap.updatedRsids)
492009
492431
  updatedRsids.add(rsid);
492010
492432
  resolvedInsertionRevisions.push(...overlap.resolvedInsertionRevisions);
492011
- for (const revision of overlap.authoredTrackedRevisions ?? []) {
492012
- trackedAnnotations.push({
492013
- changeId: revision.rsid,
492014
- wId: revision.wId,
492015
- kind: revision.kind,
492016
- author: {
492017
- name: stamping.author.name,
492018
- initials: stamping.author.initials ?? null,
492019
- email: stamping.author.email ?? null
492020
- },
492021
- date: stamping.date
492022
- });
492023
- }
492024
492433
  }
492025
492434
  }
492026
492435
  for (const edit of blockEdits) {
@@ -492051,7 +492460,21 @@ function runTrackedEditTextBatchCommit(input, edits) {
492051
492460
  });
492052
492461
  }
492053
492462
  }
492463
+ const rewriteGroups = new Map;
492464
+ for (const edit of blockEdits) {
492465
+ if (!edit.rewriteGroupId)
492466
+ continue;
492467
+ for (const rsid of emittedByEdit.get(edit) ?? [])
492468
+ rewriteGroups.set(rsid, edit.rewriteGroupId);
492469
+ }
492470
+ if (rewriteGroups.size > 0) {
492471
+ const stamped = stampRewriteGroups(TD38.decode(afterBytes), rewriteGroups, { partUri, storyId });
492472
+ if (stamped === null)
492473
+ return rejected2(txId, "invalid-input");
492474
+ afterBytes = TE16.encode(stamped);
492475
+ }
492054
492476
  if (!bytesEqual5(beforeBytes, afterBytes)) {
492477
+ trackedAnnotations.push(...captureBatchTrackedAnnotations(afterBytes, new Set(blockEdits.flatMap((edit) => emittedByEdit.get(edit) ?? []))));
492055
492478
  patches.push({
492056
492479
  kind: "replaceBytes",
492057
492480
  order: patches.length,
@@ -492069,7 +492492,6 @@ function runTrackedEditTextBatchCommit(input, edits) {
492069
492492
  patches.forEach((patch, order) => {
492070
492493
  patch.order = order;
492071
492494
  });
492072
- const { edits: _edits, ...retainedSource } = op;
492073
492495
  const storiesTouched = textEditTouchedStories(state, storyId, partUri);
492074
492496
  const storyPartOwnership = storyPartOwnershipForTouchedStories(state, storiesTouched, partUri);
492075
492497
  const perPart = {
@@ -492078,6 +492500,8 @@ function runTrackedEditTextBatchCommit(input, edits) {
492078
492500
  const patchMaps = {
492079
492501
  [partUri]: { partUri, ranges: [] }
492080
492502
  };
492503
+ const { edits: _edits, ...primarySource } = op;
492504
+ const retainedSource = { ...primarySource, batchSpanCount: edits.length };
492081
492505
  const forwardPatchGroup = {
492082
492506
  source: retainedSource,
492083
492507
  baseRevisions: {
@@ -492105,7 +492529,7 @@ function runTrackedEditTextBatchCommit(input, edits) {
492105
492529
  };
492106
492530
  const prepared = {
492107
492531
  txId,
492108
- source: retainedSource,
492532
+ source: op,
492109
492533
  resolvedTargets: {
492110
492534
  partUris: [partUri],
492111
492535
  stories: storiesTouched,
@@ -493940,6 +494364,7 @@ function tryOverlapRewriteTracked(input, bytes, window2, byteBase, stamp, inline
493940
494364
  newText: op.newText,
493941
494365
  changeMode: "tracked",
493942
494366
  currentAuthor: stamp.author,
494367
+ ...op.preserveExistingRevisions ? { existingRevisionOwnership: "foreign" } : {},
493943
494368
  txTimestamp: stamp.date,
493944
494369
  rsid: stamp.rsid,
493945
494370
  insRsid: stamp.insRsid,
@@ -496669,6 +497094,7 @@ function collectPerPartRevisions(state, partUris) {
496669
497094
  }
496670
497095
  var TD38, TE16, TRACKED_WRAPPER_OPEN_RE, INLINE_CONTROL_PLACEHOLDER = "";
496671
497096
  var init_compile_edit_text = __esm(() => {
497097
+ init_rewrite_groups();
496672
497098
  init_word_text_payload();
496673
497099
  init_textbox_atom_replacement();
496674
497100
  init_sd_document_state();
@@ -499901,6 +500327,46 @@ var init_decide_engine = __esm(() => {
499901
500327
  init_xml_sax();
499902
500328
  });
499903
500329
 
500330
+ // ../../../v2/editor-core/dist/document/transactions/tracked-changes/structural-inline-decision.js
500331
+ function hasSessionSyncStructuralInlineDeletion(xml, fragments, namespaceBindings = new Map) {
500332
+ const selectedRanges = fragments.filter((fragment2) => fragment2.kind === "del").map((fragment2) => ({ start: fragment2.byteStart, end: fragment2.byteEnd })).sort((left, right) => left.start - right.start || right.end - left.end);
500333
+ if (selectedRanges.length === 0)
500334
+ return false;
500335
+ const prefixMaxEnds = [];
500336
+ for (const range of selectedRanges) {
500337
+ prefixMaxEnds.push(Math.max(prefixMaxEnds.at(-1) ?? -1, range.end));
500338
+ }
500339
+ const isInsideSelectedDeletion = (start, end) => {
500340
+ let low = 0;
500341
+ let high = selectedRanges.length;
500342
+ while (low < high) {
500343
+ const middle = low + high >>> 1;
500344
+ if (selectedRanges[middle].start < start)
500345
+ low = middle + 1;
500346
+ else
500347
+ high = middle;
500348
+ }
500349
+ return low > 0 && prefixMaxEnds[low - 1] > end;
500350
+ };
500351
+ let matched = false;
500352
+ walkXmlElements(xml, {
500353
+ additionalNamespaces: xmlFragmentAdditionalNamespaces(xml, namespaceBindings, {
500354
+ w: NS_W,
500355
+ m: OFFICE_MATH_NAMESPACE
500356
+ }),
500357
+ onOpenTag({ tag, start, end }) {
500358
+ if (matched || !isInsideSelectedDeletion(start, end))
500359
+ return;
500360
+ matched = tag.namespaceUri === NS_W ? tag.localName === "smartTag" || tag.localName === "dir" || tag.localName === "bdo" : tag.namespaceUri === OFFICE_MATH_NAMESPACE && tag.localName === "oMath";
500361
+ }
500362
+ });
500363
+ return matched;
500364
+ }
500365
+ var OFFICE_MATH_NAMESPACE = "http://schemas.openxmlformats.org/officeDocument/2006/math";
500366
+ var init_structural_inline_decision = __esm(() => {
500367
+ init_xml_sax();
500368
+ });
500369
+
499904
500370
  // ../../../v2/editor-core/dist/document/transactions/compile-tracked-change-decide-local.js
499905
500371
  function tryRunLocalTrackedChangeDecideCommit(input) {
499906
500372
  const { state, txId, op } = input;
@@ -500075,6 +500541,7 @@ function tryRunLocalTrackedChangeDecideCommit(input) {
500075
500541
  };
500076
500542
  })
500077
500543
  };
500544
+ const sessionSyncedTextDecision = hasSessionSyncStructuralInlineDeletion(beforeXml, decisions.map(({ localFragment }) => localFragment), new Map(Object.entries(state.mainStorySourceOverlay?.rootNamespaceBindings ?? {})));
500078
500545
  const prepared = {
500079
500546
  txId,
500080
500547
  source: op,
@@ -500107,7 +500574,8 @@ function tryRunLocalTrackedChangeDecideCommit(input) {
500107
500574
  storyLocal: true,
500108
500575
  targetBlockIds: [paragraph.blockId],
500109
500576
  atomCarrierContract: SD_DEFAULT_ATOM_CARRIER_CONTRACT,
500110
- trackedTextDecide
500577
+ trackedTextDecide,
500578
+ ...sessionSyncedTextDecision ? { sessionSync: { reason: "structural-inline-edit" } } : {}
500111
500579
  }
500112
500580
  }
500113
500581
  };
@@ -500372,6 +500840,7 @@ var init_compile_tracked_change_decide_local = __esm(() => {
500372
500840
  init_logical_catalog();
500373
500841
  init_decide_engine();
500374
500842
  init_block_deletion_text();
500843
+ init_structural_inline_decision();
500375
500844
  TD41 = new TextDecoder;
500376
500845
  TE19 = new TextEncoder;
500377
500846
  });
@@ -502640,7 +503109,7 @@ function runTrackedChangeDecideCommit(input) {
502640
503109
  fragmentsByPart,
502641
503110
  structuralTargets
502642
503111
  });
502643
- const nestedTextDecision = trackedTextDecide && hasNestedTextDecision(catalog, fragmentsByPart);
503112
+ const sessionSyncedTextDecision = trackedTextDecide && (hasNestedTextDecision(catalog, fragmentsByPart) || hasStructuralInlineDeletionDecision(state, fragmentsByPart));
502644
503113
  const prepared = {
502645
503114
  txId,
502646
503115
  source: op,
@@ -502674,7 +503143,7 @@ function runTrackedChangeDecideCommit(input) {
502674
503143
  targetBlockIds: trackedTextDecide?.targets.map((target) => target.blockId) ?? [],
502675
503144
  atomCarrierContract: SD_DEFAULT_ATOM_CARRIER_CONTRACT,
502676
503145
  ...trackedTextDecide ? { trackedTextDecide } : {},
502677
- ...nestedTextDecision ? { sessionSync: { reason: "structural-inline-edit" } } : {}
503146
+ ...sessionSyncedTextDecision ? { sessionSync: { reason: "structural-inline-edit" } } : {}
502678
503147
  }
502679
503148
  }
502680
503149
  };
@@ -503000,6 +503469,16 @@ function hasNestedTextDecision(catalog, fragmentsByPart) {
503000
503469
  }
503001
503470
  return false;
503002
503471
  }
503472
+ function hasStructuralInlineDeletionDecision(state, fragmentsByPart) {
503473
+ for (const [partUri, fragments] of fragmentsByPart) {
503474
+ const bytes = state.packageBytes.get(partUri);
503475
+ if (!bytes)
503476
+ continue;
503477
+ if (hasSessionSyncStructuralInlineDeletion(TD44.decode(bytes), fragments))
503478
+ return true;
503479
+ }
503480
+ return false;
503481
+ }
503003
503482
  function buildPreparedTrackedTextDecide(input) {
503004
503483
  if (input.op.targets.some((target) => target.partial || target.formatting || target.derivedStructural || (target.moveRangeMarkers?.ids.length ?? 0) > 0)) {
503005
503484
  return;
@@ -504271,6 +504750,8 @@ function buildLogicalIdByTextFragmentKey(logical) {
504271
504750
  }
504272
504751
  const out = new Map;
504273
504752
  for (const entry of logical.byId.values()) {
504753
+ if (entry.reviewGroup?.kind === "text-rewrite" && entry.reviewGroup.role === "parent")
504754
+ continue;
504274
504755
  for (const fragment2 of entry.fragments) {
504275
504756
  if ((logicalIdsByRsid.get(fragment2.rsid)?.size ?? 0) <= 1)
504276
504757
  continue;
@@ -504282,6 +504763,8 @@ function buildLogicalIdByTextFragmentKey(logical) {
504282
504763
  function buildExactLogicalIdByTextFragmentKey(logical) {
504283
504764
  const out = new Map;
504284
504765
  for (const entry of logical.byId.values()) {
504766
+ if (entry.reviewGroup?.kind === "text-rewrite" && entry.reviewGroup.role === "parent")
504767
+ continue;
504285
504768
  for (const fragment2 of entry.fragments) {
504286
504769
  out.set(trackedChangeFragmentKey(fragment2), entry.id);
504287
504770
  }
@@ -505495,6 +505978,7 @@ var init_compile_tracked_change_decide = __esm(() => {
505495
505978
  init_package_graph();
505496
505979
  init_decide_engine();
505497
505980
  init_block_deletion_text();
505981
+ init_structural_inline_decision();
505498
505982
  init_structural_groups();
505499
505983
  init_comment_cascade();
505500
505984
  init_exact_part_mutation_proof();
@@ -532477,7 +532961,7 @@ function buildProjectionFact(change, tableCatalogs) {
532477
532961
  return {
532478
532962
  logicalId: change.id,
532479
532963
  reviewOwnerId: reviewOwnerId(change),
532480
- visible: change.reviewGroup?.role !== "child" && change.subsumption?.role !== "child",
532964
+ visible: isVisibleLogicalTrackedChange(change),
532481
532965
  type: change.type,
532482
532966
  subtype: change.subtype,
532483
532967
  storyId: change.storyId,
@@ -532495,8 +532979,9 @@ function buildProjectionFact(change, tableCatalogs) {
532495
532979
  };
532496
532980
  }
532497
532981
  function reviewOwnerId(change) {
532498
- if (change.reviewGroup?.role === "child" && change.reviewGroup.parentId) {
532499
- return change.reviewGroup.parentId;
532982
+ const groupParentId = reviewGroupDisplayParentId(change);
532983
+ if (groupParentId) {
532984
+ return groupParentId;
532500
532985
  }
532501
532986
  if (change.subsumption?.role === "child")
532502
532987
  return change.subsumption.parentId;
@@ -532715,6 +533200,7 @@ function rangesOverlap5(leftStart, leftEnd, rightStart, rightEnd) {
532715
533200
  return leftStart < rightEnd && rightStart < leftEnd;
532716
533201
  }
532717
533202
  var init_review_projection_overlay = __esm(() => {
533203
+ init_rewrite_groups();
532718
533204
  init_review_decision_semantics();
532719
533205
  });
532720
533206
 
@@ -539243,6 +539729,8 @@ function prepareExactHistoryRenderInput(state, prepared, entry, direction) {
539243
539729
  }
539244
539730
  if (source.kind !== "editText" && source.kind !== "formatRunRange" || source.changeMode !== "direct")
539245
539731
  return null;
539732
+ if (source.kind === "editText" && (source.edits || source.batchSpanCount != null))
539733
+ return null;
539246
539734
  if (source.kind === "formatRunRange" && entry.semanticDelta.textRangeShifts.length !== 0)
539247
539735
  return null;
539248
539736
  const index = state.paragraphIndexes.get(source.on.storyId);
@@ -550539,7 +551027,7 @@ function refConfigSchemas2() {
550539
551027
  failure: refFailureSchema2
550540
551028
  };
550541
551029
  }
550542
- 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, pictureWatermarkInfoSchema2, watermarkInfoSchema2, 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, trackChangeInfoSchema2, trackChangeDomainItemSchema2, trackChangesListResultSchema2, reviewDecideRangeTargetOptions2, historyActionCollaborationSchema2, capabilityReasonCodeSchema2, capabilityReasonsSchema2, 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;
551030
+ 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, pictureWatermarkInfoSchema2, watermarkInfoSchema2, 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, 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;
550543
551031
  var init_schemas5 = __esm(() => {
550544
551032
  init_command_catalog2();
550545
551033
  init_types8();
@@ -552056,6 +552544,21 @@ var init_schemas5 = __esm(() => {
552056
552544
  localName: { type: "string" },
552057
552545
  value: { type: "string" }
552058
552546
  }, ["name", "namespaceUri", "localName", "value"]);
552547
+ trackChangeRewriteReviewGroupSchema2 = objectSchema4({
552548
+ kind: { const: "text-rewrite" },
552549
+ role: { enum: ["parent", "child"] },
552550
+ parentId: { type: "string" },
552551
+ childChangeIds: { type: "array", items: { type: "string" } },
552552
+ members: {
552553
+ type: "array",
552554
+ items: objectSchema4({
552555
+ id: { type: "string" },
552556
+ type: { enum: ["insertion", "deletion", "replacement"] },
552557
+ subtype: { type: "string" },
552558
+ sourceIds: trackChangeSourceIdsSchema2
552559
+ }, ["id", "type", "subtype", "sourceIds"])
552560
+ }
552561
+ }, ["kind", "role", "childChangeIds", "members"]);
552059
552562
  trackChangeInfoSchema2 = objectSchema4({
552060
552563
  address: trackedChangeAddressSchema2,
552061
552564
  id: { type: "string" },
@@ -552068,6 +552571,7 @@ var init_schemas5 = __esm(() => {
552068
552571
  sourceIds: trackChangeSourceIdsSchema2,
552069
552572
  wordRevisionIds: trackChangeWordRevisionIdsSchema2,
552070
552573
  revisionGroupId: { type: "string" },
552574
+ reviewGroup: trackChangeRewriteReviewGroupSchema2,
552071
552575
  splitFromId: { oneOf: [{ type: "string" }, { type: "null" }] },
552072
552576
  replacement: trackChangeReplacementSchema2,
552073
552577
  author: { type: "string" },
@@ -552118,6 +552622,7 @@ var init_schemas5 = __esm(() => {
552118
552622
  sourceIds: trackChangeSourceIdsSchema2,
552119
552623
  wordRevisionIds: trackChangeWordRevisionIdsSchema2,
552120
552624
  revisionGroupId: { type: "string" },
552625
+ reviewGroup: trackChangeRewriteReviewGroupSchema2,
552121
552626
  author: { type: "string" },
552122
552627
  authorEmail: { type: "string" },
552123
552628
  authorImage: { type: "string" },
@@ -558230,6 +558735,58 @@ var init_src3 = __esm(() => {
558230
558735
  init_protection_types2();
558231
558736
  });
558232
558737
 
558738
+ // ../../../v2/document-api-v2-adapter/dist/history/rewrite-group-effects.js
558739
+ function applyHistoryGroupEffects(result, effects2, direction) {
558740
+ if (!effects2)
558741
+ return result;
558742
+ const inserted = direction === "undo" ? effects2.removed : effects2.created;
558743
+ const removed = direction === "undo" ? effects2.created : effects2.removed;
558744
+ const refs = (ids) => ids.map((entityId) => ({
558745
+ kind: "entity",
558746
+ entityType: "trackedChange",
558747
+ entityId
558748
+ }));
558749
+ return {
558750
+ ...result,
558751
+ inserted: [...result.inserted ?? [], ...refs(inserted)],
558752
+ updated: [...result.updated ?? [], ...refs(effects2.updated)],
558753
+ removed: [...result.removed ?? [], ...refs(removed)],
558754
+ invalidatedRefs: [...result.invalidatedRefs ?? [], ...refs(removed)]
558755
+ };
558756
+ }
558757
+ function composeHistoryGroupEffects(effects2) {
558758
+ const states = new Map;
558759
+ for (const effect of effects2) {
558760
+ if (!effect)
558761
+ continue;
558762
+ for (const kind of ["created", "updated", "removed"]) {
558763
+ for (const id of effect[kind]) {
558764
+ const previous = states.get(id);
558765
+ states.set(id, {
558766
+ before: previous?.before ?? kind !== "created",
558767
+ after: kind !== "removed"
558768
+ });
558769
+ }
558770
+ }
558771
+ }
558772
+ if (states.size === 0)
558773
+ return;
558774
+ const result = {
558775
+ created: [],
558776
+ updated: [],
558777
+ removed: []
558778
+ };
558779
+ for (const [id, state] of states) {
558780
+ if (state.before && state.after)
558781
+ result.updated.push(id);
558782
+ else if (state.after)
558783
+ result.created.push(id);
558784
+ else if (state.before)
558785
+ result.removed.push(id);
558786
+ }
558787
+ return result;
558788
+ }
558789
+
558233
558790
  // ../../../v2/document-api-v2-adapter/dist/policy/source.js
558234
558791
  function v2Coverage(operationId, wiredVia, workerWired, completenessStatus, completenessReason) {
558235
558792
  return {
@@ -560765,7 +561322,7 @@ class V2HistoryAdapter {
560765
561322
  applied.push({
560766
561323
  entry,
560767
561324
  result,
560768
- projected: projectUndoToHistoryResult(entry, result, this.context.session, priorLogicalIds)
561325
+ projected: applyHistoryGroupEffects(projectUndoToHistoryResult(entry, result, this.context.session, priorLogicalIds), this.context.getHistoryTrackedChangeGroupEffects(entry.txId), "undo")
560769
561326
  });
560770
561327
  }
560771
561328
  return aggregateHistoryResults(this.context, group, applied);
@@ -560795,7 +561352,7 @@ class V2HistoryAdapter {
560795
561352
  applied.push({
560796
561353
  entry,
560797
561354
  result,
560798
- projected: projectRedoToHistoryResult(entry, result, this.context.session, priorLogicalIds)
561355
+ projected: applyHistoryGroupEffects(projectRedoToHistoryResult(entry, result, this.context.session, priorLogicalIds), this.context.getHistoryTrackedChangeGroupEffects(entry.txId), "redo")
560799
561356
  });
560800
561357
  }
560801
561358
  return aggregateHistoryResults(this.context, group, applied);
@@ -561474,45 +562031,65 @@ var init_xml = __esm(() => {
561474
562031
  });
561475
562032
 
561476
562033
  // ../../../v2/document-api-v2-adapter/dist/address/painted-offsets.js
561477
- function paintedRangeContainedObjectOrdinals(paraXml, paintedStart, paintedEnd) {
561478
- if (paintedEnd <= paintedStart)
561479
- return [];
561480
- const contained = [];
561481
- for (const run of paintedRuns(paraXml)) {
561482
- if (run.objectOrdinal !== null && paintedStart <= run.paintedStart && run.paintedStart + 1 <= paintedEnd) {
561483
- contained.push(run.objectOrdinal);
562034
+ function preparePaintedOffsets(paraXml) {
562035
+ const runs = paintedRuns(paraXml);
562036
+ const objects = runs.filter((run) => run.objectOrdinal !== null);
562037
+ return {
562038
+ containedObjectOrdinals(start, end) {
562039
+ const contained = [];
562040
+ for (let i2 = lowerBound(objects, start, "start");i2 < objects.length; i2++) {
562041
+ const run = objects[i2];
562042
+ if (run.paintedStart + 1 > end)
562043
+ break;
562044
+ contained.push(run.objectOrdinal);
562045
+ }
562046
+ return contained;
562047
+ },
562048
+ containsObject(start, end) {
562049
+ const run = objects[lowerBound(objects, start, "start")];
562050
+ return run !== undefined && run.paintedStart + 1 <= end;
562051
+ },
562052
+ toKernelOffset(offset) {
562053
+ if (offset <= 0)
562054
+ return offset;
562055
+ const run = runs[lowerBound(runs, offset, "end")];
562056
+ if (!run) {
562057
+ const last = runs.at(-1);
562058
+ return last ? last.kernelStart + last.kernelLength : 0;
562059
+ }
562060
+ return run.objectOrdinal === null ? run.kernelStart + Math.max(0, offset - run.paintedStart) : run.kernelStart;
562061
+ },
562062
+ caretObjectBoundary(offset) {
562063
+ const run = objects[lowerBound(objects, offset, "end")];
562064
+ if (!run)
562065
+ return;
562066
+ if (offset === run.paintedStart)
562067
+ return { objectOrdinal: run.objectOrdinal, edge: "before" };
562068
+ if (offset === run.paintedStart + 1)
562069
+ return { objectOrdinal: run.objectOrdinal, edge: "after" };
562070
+ return;
561484
562071
  }
562072
+ };
562073
+ }
562074
+ function lowerBound(runs, offset, edge) {
562075
+ let low = 0;
562076
+ let high = runs.length;
562077
+ while (low < high) {
562078
+ const mid = low + Math.floor((high - low) / 2);
562079
+ const run = runs[mid];
562080
+ const boundary = run.paintedStart + (edge === "end" ? run.paintedLength : 0);
562081
+ if (boundary < offset)
562082
+ low = mid + 1;
562083
+ else
562084
+ high = mid;
561485
562085
  }
561486
- return contained;
562086
+ return low;
561487
562087
  }
561488
- function paintedRangeContainsObject(paraXml, paintedStart, paintedEnd) {
561489
- return paintedRangeContainedObjectOrdinals(paraXml, paintedStart, paintedEnd).length > 0;
562088
+ function paintedRangeContainedObjectOrdinals(paraXml, paintedStart, paintedEnd) {
562089
+ return preparePaintedOffsets(paraXml).containedObjectOrdinals(paintedStart, paintedEnd);
561490
562090
  }
561491
562091
  function paintedToKernelOffset(paraXml, paintedOffset) {
561492
- if (paintedOffset <= 0)
561493
- return paintedOffset;
561494
- let kernelLength = 0;
561495
- for (const run of paintedRuns(paraXml)) {
561496
- kernelLength = run.kernelStart + run.kernelLength;
561497
- if (paintedOffset <= run.paintedStart + run.paintedLength) {
561498
- const within = Math.max(0, paintedOffset - run.paintedStart);
561499
- return run.objectOrdinal === null ? run.kernelStart + within : run.kernelStart;
561500
- }
561501
- }
561502
- return kernelLength;
561503
- }
561504
- function paintedCaretObjectBoundary(paraXml, paintedOffset) {
561505
- for (const run of paintedRuns(paraXml)) {
561506
- if (run.objectOrdinal === null)
561507
- continue;
561508
- if (paintedOffset === run.paintedStart) {
561509
- return { objectOrdinal: run.objectOrdinal, edge: "before" };
561510
- }
561511
- if (paintedOffset === run.paintedStart + 1) {
561512
- return { objectOrdinal: run.objectOrdinal, edge: "after" };
561513
- }
561514
- }
561515
- return;
562092
+ return preparePaintedOffsets(paraXml).toKernelOffset(paintedOffset);
561516
562093
  }
561517
562094
  function paintedRuns(paraXml) {
561518
562095
  const runs = [];
@@ -561541,6 +562118,12 @@ var init_painted_offsets = __esm(() => {
561541
562118
 
561542
562119
  // ../../../v2/document-api-v2-adapter/dist/address/selection-target.js
561543
562120
  function resolveSelectionTargetToRange(input) {
562121
+ const prepared = prepareSelectionTargetResolution(input);
562122
+ if ("error" in prepared)
562123
+ return prepared;
562124
+ return prepared.resolveOffsets();
562125
+ }
562126
+ function prepareSelectionTargetResolution(input) {
561544
562127
  const target = input.target;
561545
562128
  if (target.kind !== "selection") {
561546
562129
  return { error: "INVALID_TARGET", message: "expected a SelectionTarget." };
@@ -561588,80 +562171,69 @@ function resolveSelectionTargetToRange(input) {
561588
562171
  totalBytes: () => localOffsetMap.totalBytes()
561589
562172
  };
561590
562173
  const kernelTextLength = coordinateSpace === "tracked" ? offsetMap.totalChars() : entry.textLength;
561591
- let startOffset = target.start.offset;
561592
- let endOffset = target.end.offset;
561593
- let paintedObjectContained = false;
561594
- let collapsedObjectBoundary;
561595
- if (coordinateSpace === "visible" && input.offsetSpace === "selection") {
561596
- const paraXml = SELECTION_TARGET_TD.decode(paragraphBytes);
561597
- const objectRuns = (paraXml.match(/<[\w.-]+:(?:drawing|pict|object)\b/g) ?? []).length;
561598
- if (objectRuns > 0) {
561599
- if (entry.textLength > 0) {
562174
+ const paraXml = coordinateSpace === "visible" && input.offsetSpace === "selection" ? SELECTION_TARGET_TD.decode(paragraphBytes) : "";
562175
+ const objectRuns = (paraXml.match(/<[\w.-]+:(?:drawing|pict|object)\b/g) ?? []).length;
562176
+ const painted = objectRuns > 0 ? preparePaintedOffsets(paraXml) : null;
562177
+ const originalStart = target.start.offset;
562178
+ const originalEnd = target.end.offset;
562179
+ return {
562180
+ resolveOffsets(paintedStartOffset = originalStart, paintedEndOffset = originalEnd) {
562181
+ if (paintedStartOffset > paintedEndOffset) {
562182
+ return { error: "INVALID_TARGET", message: "selection end precedes selection start." };
562183
+ }
562184
+ let startOffset = paintedStartOffset;
562185
+ let endOffset = paintedEndOffset;
562186
+ let paintedObjectContained = false;
562187
+ let collapsedObjectBoundary;
562188
+ if (painted) {
561600
562189
  if (startOffset < 0 || endOffset > entry.textLength + objectRuns) {
561601
- return {
561602
- error: "INVALID_TARGET",
561603
- message: "selection offsets exceed paragraph text."
561604
- };
561605
- }
561606
- paintedObjectContained = paintedRangeContainsObject(paraXml, startOffset, endOffset);
561607
- if (startOffset === endOffset) {
561608
- collapsedObjectBoundary = paintedCaretObjectBoundary(paraXml, startOffset);
561609
- }
561610
- startOffset = paintedToKernelOffset(paraXml, startOffset);
561611
- endOffset = paintedToKernelOffset(paraXml, endOffset);
561612
- } else {
561613
- if (startOffset < 0 || endOffset > objectRuns) {
561614
- return {
561615
- error: "INVALID_TARGET",
561616
- message: "selection offsets exceed paragraph text."
561617
- };
562190
+ return { error: "INVALID_TARGET", message: "selection offsets exceed paragraph text." };
561618
562191
  }
562192
+ paintedObjectContained = painted.containsObject(startOffset, endOffset);
561619
562193
  if (startOffset === endOffset) {
561620
- collapsedObjectBoundary = paintedCaretObjectBoundary(paraXml, startOffset);
561621
- } else {
561622
- paintedObjectContained = paintedRangeContainsObject(paraXml, startOffset, endOffset);
562194
+ collapsedObjectBoundary = painted.caretObjectBoundary(startOffset);
561623
562195
  }
561624
- startOffset = paintedToKernelOffset(paraXml, startOffset);
561625
- endOffset = paintedToKernelOffset(paraXml, endOffset);
562196
+ startOffset = painted.toKernelOffset(startOffset);
562197
+ endOffset = painted.toKernelOffset(endOffset);
561626
562198
  }
562199
+ if (startOffset < 0 || endOffset > kernelTextLength) {
562200
+ return {
562201
+ error: "INVALID_TARGET",
562202
+ message: "selection offsets exceed paragraph text."
562203
+ };
562204
+ }
562205
+ const startByte = offsetMap.charToByte(Math.min(startOffset, kernelTextLength));
562206
+ const endByte = offsetMap.charToByte(Math.min(endOffset, kernelTextLength));
562207
+ if (startByte == null || endByte == null || startByte > endByte) {
562208
+ return {
562209
+ error: "INVALID_TARGET",
562210
+ message: "selection could not be resolved to source bytes."
562211
+ };
562212
+ }
562213
+ return {
562214
+ storyId: entry.storyId,
562215
+ storyRevision: entry.storyRevision,
562216
+ partUri: entry.partUri,
562217
+ partRevision: entry.partRevision,
562218
+ startByte,
562219
+ endByte,
562220
+ paragraphByteStart: entry.byteStart,
562221
+ paragraphByteEnd: entry.byteEnd,
562222
+ startBlockId: startBlock,
562223
+ endBlockId: endBlock,
562224
+ startOffset,
562225
+ endOffset,
562226
+ ...coordinateSpace === "tracked" ? { coordinateSpace } : {},
562227
+ sourceAddress: {
562228
+ blockId: startBlock,
562229
+ range: { start: startOffset, end: endOffset }
562230
+ },
562231
+ paintedStartOffset,
562232
+ paintedEndOffset,
562233
+ paintedObjectContained,
562234
+ ...collapsedObjectBoundary ? { collapsedObjectBoundary } : {}
562235
+ };
561627
562236
  }
561628
- }
561629
- if (startOffset < 0 || endOffset > kernelTextLength) {
561630
- return {
561631
- error: "INVALID_TARGET",
561632
- message: "selection offsets exceed paragraph text."
561633
- };
561634
- }
561635
- const startByte = offsetMap.charToByte(Math.min(startOffset, kernelTextLength));
561636
- const endByte = offsetMap.charToByte(Math.min(endOffset, kernelTextLength));
561637
- if (startByte == null || endByte == null || startByte > endByte) {
561638
- return {
561639
- error: "INVALID_TARGET",
561640
- message: "selection could not be resolved to source bytes."
561641
- };
561642
- }
561643
- return {
561644
- storyId: entry.storyId,
561645
- storyRevision: entry.storyRevision,
561646
- partUri: entry.partUri,
561647
- partRevision: entry.partRevision,
561648
- startByte,
561649
- endByte,
561650
- paragraphByteStart: entry.byteStart,
561651
- paragraphByteEnd: entry.byteEnd,
561652
- startBlockId: startBlock,
561653
- endBlockId: endBlock,
561654
- startOffset,
561655
- endOffset,
561656
- ...coordinateSpace === "tracked" ? { coordinateSpace } : {},
561657
- sourceAddress: {
561658
- blockId: startBlock,
561659
- range: { start: startOffset, end: endOffset }
561660
- },
561661
- paintedStartOffset: target.start.offset,
561662
- paintedEndOffset: target.end.offset,
561663
- paintedObjectContained,
561664
- ...collapsedObjectBoundary ? { collapsedObjectBoundary } : {}
561665
562237
  };
561666
562238
  }
561667
562239
  function selectionTargetCoordinateSpace(target) {
@@ -573888,8 +574460,8 @@ function tocFieldSdtByteSpan(context, field) {
573888
574460
  byteEnd: encodeXml(xml.slice(0, close.sdtEndChar)).length
573889
574461
  };
573890
574462
  }
573891
- function findEnclosingParagraphStart(xml, pos, lowerBound) {
573892
- for (let i2 = Math.min(pos, xml.length - 1);i2 >= lowerBound; i2 -= 1) {
574463
+ function findEnclosingParagraphStart(xml, pos, lowerBound2) {
574464
+ for (let i2 = Math.min(pos, xml.length - 1);i2 >= lowerBound2; i2 -= 1) {
573893
574465
  if (xml.startsWith("<w:p", i2)) {
573894
574466
  const next = xml[i2 + 4];
573895
574467
  if (next === " " || next === ">" || next === "/")
@@ -578508,6 +579080,11 @@ function normalizeTarget(target) {
578508
579080
  };
578509
579081
  }
578510
579082
 
579083
+ // ../../../v2/editor-core/dist/review-read-model.js
579084
+ var init_review_read_model = __esm(() => {
579085
+ init_rewrite_groups();
579086
+ });
579087
+
578511
579088
  // ../../../v2/document-api-v2-adapter/dist/interaction-trace.js
578512
579089
  function safeTraceCollector() {
578513
579090
  try {
@@ -579057,6 +579634,7 @@ function publishCapturedHistory(context, txIds, compositeTxIdPrefix) {
579057
579634
  recordCommittedTxIdForHistory(context, entry.txId);
579058
579635
  return historyEntryToReceipt(entry);
579059
579636
  }
579637
+ const trackedChangeGroupEffects = composeHistoryGroupEffects(txIds.map((txId) => context.getHistoryTrackedChangeGroupEffects(txId)));
579060
579638
  let receipt3;
579061
579639
  try {
579062
579640
  receipt3 = composeSDDocumentSessionInternalCapturedHistory(context.session, {
@@ -579069,7 +579647,8 @@ function publishCapturedHistory(context, txIds, compositeTxIdPrefix) {
579069
579647
  if (!receipt3)
579070
579648
  return null;
579071
579649
  context.invalidate(receipt3);
579072
- recordCommittedTxIdForHistory(context, receipt3.txId);
579650
+ recordCommittedTxIdForHistory(context, receipt3.txId, { trackedChangeGroupEffects });
579651
+ context.discardHistoryMetadata(txIds);
579073
579652
  return receipt3;
579074
579653
  }
579075
579654
  function rollbackCapturedHistory(context, txIds) {
@@ -579077,6 +579656,7 @@ function rollbackCapturedHistory(context, txIds) {
579077
579656
  return;
579078
579657
  try {
579079
579658
  rollbackSDDocumentSessionInternalCapturedHistory(context.session, txIds);
579659
+ context.discardHistoryMetadata(txIds);
579080
579660
  } catch (error48) {
579081
579661
  throw new DocumentApiValidationError2("PRECONDITION_FAILED", error48 instanceof Error ? error48.message : "captured history rollback failed.");
579082
579662
  }
@@ -580270,6 +580850,195 @@ var init_adapter5 = __esm(() => {
580270
580850
  ]);
580271
580851
  });
580272
580852
 
580853
+ // ../../../v2/document-api-v2-adapter/dist/selection-mutation/replacement-span.js
580854
+ function uniqueTokenAnchors(before, after) {
580855
+ const uniquePositions = (tokens) => {
580856
+ const positions = new Map;
580857
+ tokens.forEach((token, index) => positions.set(token, positions.has(token) ? -1 : index));
580858
+ return positions;
580859
+ };
580860
+ const oldPositions = uniquePositions(before);
580861
+ const newPositions = uniquePositions(after);
580862
+ const candidates = [];
580863
+ for (const [token, oldIndex] of oldPositions) {
580864
+ const newIndex = newPositions.get(token);
580865
+ if (oldIndex >= 0 && newIndex !== undefined && newIndex >= 0)
580866
+ candidates.push([oldIndex, newIndex]);
580867
+ }
580868
+ const tails = [];
580869
+ const previous = new Int32Array(candidates.length).fill(-1);
580870
+ candidates.forEach(([, newIndex], index) => {
580871
+ let low = 0;
580872
+ let high = tails.length;
580873
+ while (low < high) {
580874
+ const middle = low + high >>> 1;
580875
+ if (candidates[tails[middle]][1] < newIndex)
580876
+ low = middle + 1;
580877
+ else
580878
+ high = middle;
580879
+ }
580880
+ if (low > 0)
580881
+ previous[index] = tails[low - 1];
580882
+ tails[low] = index;
580883
+ });
580884
+ const anchors = [];
580885
+ for (let index = tails.at(-1) ?? -1;index >= 0; index = previous[index])
580886
+ anchors.push(candidates[index]);
580887
+ return anchors.reverse();
580888
+ }
580889
+ function greedyTokenMatches(before, after, aStart, aEnd, bStart, bEnd) {
580890
+ const positions = new Map;
580891
+ for (let index = bStart;index < bEnd; index += 1) {
580892
+ const token = after[index];
580893
+ const indices = positions.get(token);
580894
+ if (indices)
580895
+ indices.push(index);
580896
+ else
580897
+ positions.set(token, [index]);
580898
+ }
580899
+ const matches = [];
580900
+ let cursor = bStart;
580901
+ for (let index = aStart;index < aEnd && cursor < bEnd; index += 1) {
580902
+ const indices = positions.get(before[index]);
580903
+ if (!indices)
580904
+ continue;
580905
+ let low = 0;
580906
+ let high = indices.length;
580907
+ while (low < high) {
580908
+ const middle = low + high >>> 1;
580909
+ if (indices[middle] < cursor)
580910
+ low = middle + 1;
580911
+ else
580912
+ high = middle;
580913
+ }
580914
+ if (low < indices.length) {
580915
+ matches.push([index, indices[low]]);
580916
+ cursor = indices[low] + 1;
580917
+ }
580918
+ }
580919
+ return matches;
580920
+ }
580921
+ function narrowTextReplacement(before, after) {
580922
+ if (before === after)
580923
+ return null;
580924
+ const tokens = /[\p{L}\p{N}\p{M}_]+|\s+|[^\p{L}\p{N}\p{M}_\s]/gu;
580925
+ const oldTokens = before.match(tokens) ?? [];
580926
+ const newTokens = after.match(tokens) ?? [];
580927
+ let prefix = 0;
580928
+ let start = 0;
580929
+ while (prefix < oldTokens.length && prefix < newTokens.length && oldTokens[prefix] === newTokens[prefix]) {
580930
+ start += oldTokens[prefix].length;
580931
+ prefix += 1;
580932
+ }
580933
+ let oldEnd = oldTokens.length;
580934
+ let newEnd = newTokens.length;
580935
+ let suffixLength = 0;
580936
+ while (oldEnd > prefix && newEnd > prefix && oldTokens[oldEnd - 1] === newTokens[newEnd - 1]) {
580937
+ suffixLength += oldTokens[oldEnd - 1].length;
580938
+ oldEnd -= 1;
580939
+ newEnd -= 1;
580940
+ }
580941
+ return { start, end: before.length - suffixLength, text: after.slice(start, after.length - suffixLength) };
580942
+ }
580943
+ function planTextReplacement(before, after) {
580944
+ const boundary = narrowTextReplacement(before, after);
580945
+ if (!boundary)
580946
+ return [];
580947
+ const tokens = /[\p{L}\p{N}\p{M}_]+|\s+|[^\p{L}\p{N}\p{M}_\s]/gu;
580948
+ const oldTokens = before.slice(boundary.start, boundary.end).match(tokens) ?? [];
580949
+ const newTokens = boundary.text.match(tokens) ?? [];
580950
+ const matches = [];
580951
+ const oldValues = new Set(oldTokens);
580952
+ if (!newTokens.some((token) => oldValues.has(token)))
580953
+ return [boundary];
580954
+ const row = (aStart, aEnd, bStart, bEnd, reverse) => {
580955
+ const lengths = new Uint32Array(bEnd - bStart + 1);
580956
+ for (let i2 = 0;i2 < aEnd - aStart; i2 += 1) {
580957
+ let diagonal = 0;
580958
+ const token = oldTokens[reverse ? aEnd - i2 - 1 : aStart + i2];
580959
+ for (let j = 1;j <= bEnd - bStart; j += 1) {
580960
+ const previous = lengths[j];
580961
+ lengths[j] = token === newTokens[reverse ? bEnd - j : bStart + j - 1] ? diagonal + 1 : Math.max(lengths[j], lengths[j - 1]);
580962
+ diagonal = previous;
580963
+ }
580964
+ }
580965
+ return lengths;
580966
+ };
580967
+ const align = (aStart, aEnd, bStart, bEnd) => {
580968
+ if (aStart === aEnd || bStart === bEnd)
580969
+ return;
580970
+ if (aEnd - aStart === 1) {
580971
+ for (let j = bStart;j < bEnd; j += 1) {
580972
+ if (oldTokens[aStart] === newTokens[j]) {
580973
+ matches.push([aStart, j]);
580974
+ break;
580975
+ }
580976
+ }
580977
+ return;
580978
+ }
580979
+ const middle = Math.floor((aStart + aEnd) / 2);
580980
+ const left = row(aStart, middle, bStart, bEnd, false);
580981
+ const right = row(middle, aEnd, bStart, bEnd, true);
580982
+ let split = 0;
580983
+ let best = -1;
580984
+ for (let j = 0;j <= bEnd - bStart; j += 1) {
580985
+ const score = left[j] + right[bEnd - bStart - j];
580986
+ if (score > best) {
580987
+ best = score;
580988
+ split = j;
580989
+ }
580990
+ }
580991
+ align(aStart, middle, bStart, bStart + split);
580992
+ align(middle, aEnd, bStart + split, bEnd);
580993
+ };
580994
+ let remainingCells = 2000000;
580995
+ const alignGap = (aStart, aEnd, bStart, bEnd) => {
580996
+ if (aStart === aEnd || bStart === bEnd)
580997
+ return;
580998
+ const values = new Set(oldTokens.slice(aStart, aEnd));
580999
+ if (!newTokens.slice(bStart, bEnd).some((token) => values.has(token)))
581000
+ return;
581001
+ const cells = 3 * (aEnd - aStart) * (bEnd - bStart);
581002
+ if (cells <= remainingCells) {
581003
+ remainingCells -= cells;
581004
+ align(aStart, aEnd, bStart, bEnd);
581005
+ } else {
581006
+ for (const match of greedyTokenMatches(oldTokens, newTokens, aStart, aEnd, bStart, bEnd))
581007
+ matches.push(match);
581008
+ }
581009
+ };
581010
+ if (3 * oldTokens.length * newTokens.length <= remainingCells) {
581011
+ alignGap(0, oldTokens.length, 0, newTokens.length);
581012
+ } else {
581013
+ const anchors = uniqueTokenAnchors(oldTokens, newTokens);
581014
+ let oldCursor2 = 0;
581015
+ let newCursor2 = 0;
581016
+ for (const [oldIndex, newIndex] of [...anchors, [oldTokens.length, newTokens.length]]) {
581017
+ alignGap(oldCursor2, oldIndex, newCursor2, newIndex);
581018
+ if (oldIndex < oldTokens.length)
581019
+ matches.push([oldIndex, newIndex]);
581020
+ oldCursor2 = oldIndex + 1;
581021
+ newCursor2 = newIndex + 1;
581022
+ }
581023
+ }
581024
+ matches.push([oldTokens.length, newTokens.length]);
581025
+ const spans = [];
581026
+ let oldCursor = 0;
581027
+ let newCursor = 0;
581028
+ let offset = boundary.start;
581029
+ for (const [oldIndex, newIndex] of matches) {
581030
+ const removed = oldTokens.slice(oldCursor, oldIndex).join("");
581031
+ const inserted = newTokens.slice(newCursor, newIndex).join("");
581032
+ if (removed || inserted) {
581033
+ spans.push({ start: offset, end: offset + removed.length, text: inserted });
581034
+ }
581035
+ offset += removed.length + (oldTokens[oldIndex]?.length ?? 0);
581036
+ oldCursor = oldIndex + 1;
581037
+ newCursor = newIndex + 1;
581038
+ }
581039
+ return spans;
581040
+ }
581041
+
580273
581042
  // ../../../v2/document-api-v2-adapter/dist/ranges/adapter.js
580274
581043
  class V2RangesAdapter {
580275
581044
  constructor(context) {
@@ -581437,23 +582206,66 @@ class V2SelectionMutationAdapter {
581437
582206
  if ("failure" in begun) {
581438
582207
  return { success: false, failure: begun.failure, resolution: edits[0].resolution };
581439
582208
  }
582209
+ const preparedByBlock = new Map;
582210
+ const planned = [];
582211
+ for (const [editIndex, edit] of edits.entries()) {
582212
+ const { on, newText, resolution } = edit;
582213
+ const spans = on.coordinateSpace !== "tracked" && resolution.text.length === on.endOffset - on.startOffset && isPlannableTextPayload(newText) ? planTextReplacement(resolution.text, newText) : [{ start: 0, end: on.endOffset - on.startOffset, text: newText }];
582214
+ const index = isMainStoryId(on.storyId) ? getSDDocumentSessionInternalParagraphIndex(this.context.session) : getSDDocumentSessionInternalStoryParagraphIndex(this.context.session, on.storyId);
582215
+ if (!index)
582216
+ return { success: false, failure: { code: "TARGET_NOT_FOUND", message: "rewrite paragraph index unavailable" }, resolution };
582217
+ const preparedKey = `${on.storyId}:${on.startBlockId}:${on.coordinateSpace ?? "visible"}`;
582218
+ const prepared = preparedByBlock.get(preparedKey) ?? prepareSelectionTargetResolution({
582219
+ target: {
582220
+ kind: "selection",
582221
+ start: { kind: "text", blockId: on.startBlockId, offset: on.startOffset },
582222
+ end: { kind: "text", blockId: on.endBlockId, offset: on.endOffset },
582223
+ ...on.coordinateSpace ? { coordinateSpace: on.coordinateSpace } : {}
582224
+ },
582225
+ index,
582226
+ readPartBytes: (partUri) => getSDDocumentSessionInternalPartBytes(this.context.session, partUri),
582227
+ readPartRange: (partUri, start, end) => getSDDocumentSessionInternalPartRange(this.context.session, partUri, start, end),
582228
+ buildOffsetMap: buildOffsetMapForCoordinateSpace3
582229
+ });
582230
+ if ("error" in prepared)
582231
+ return { success: false, failure: { code: prepared.error, message: prepared.message }, resolution };
582232
+ preparedByBlock.set(preparedKey, prepared);
582233
+ for (const span of spans) {
582234
+ const narrowed = prepared.resolveOffsets(on.startOffset + span.start, on.startOffset + span.end);
582235
+ if ("error" in narrowed)
582236
+ return { success: false, failure: { code: narrowed.error, message: narrowed.message }, resolution };
582237
+ if (narrowed.paintedObjectContained)
582238
+ return { success: false, failure: { code: "INVALID_CONTEXT", message: "rewrite contains an inline object" }, resolution };
582239
+ planned.push({ on: narrowed, newText: span.text, resolution: { ...resolution, text: resolution.text.slice(span.start, span.end) }, resultKey: String(editIndex), owner: edit.ownerStepId ?? "", rewriteIntent: edit.rewriteIntent === true });
582240
+ }
582241
+ }
582242
+ if (planned.length === 0)
582243
+ return { success: false, failure: { code: "NO_OP", message: "rewrite produced no change" }, resolution: edits[0].resolution };
582244
+ const ownerIds = new Map;
582245
+ for (const edit of planned) {
582246
+ if (!ownerIds.has(edit.owner))
582247
+ ownerIds.set(edit.owner, `${begun.tx.txId}:${ownerIds.size}`);
582248
+ }
581440
582249
  const fieldEntries = listCanonicalFieldEntries(this.context);
581441
582250
  const retiredFieldIds = [];
581442
582251
  const independentTracked = options?.changeMode === "tracked" && this.context.trackedChangesReplacementMode === "independent";
581443
582252
  let trackedFieldDeletion = false;
581444
- const kernelEdits = edits.map(({ on, newText, resolution }, index) => {
581445
- const stamps = independentTracked && on.startOffset < on.endOffset && newText.length > 0 ? {
581446
- rsid: deriveRsid(`${begun.tx.txId}:${index}`, "del"),
581447
- insRsid: deriveRsid(`${begun.tx.txId}:${index}`, "ins")
581448
- } : {};
582253
+ const kernelEdits = planned.map(({ on, newText, resolution, resultKey, owner, rewriteIntent }, index) => {
582254
+ const stamps = {
582255
+ ...options?.changeMode === "tracked" && rewriteIntent ? { rewriteGroupId: ownerIds.get(owner), preserveExistingRevisions: true } : {},
582256
+ ...independentTracked && on.startOffset < on.endOffset && newText.length > 0 ? {
582257
+ rsid: deriveRsid(`${begun.tx.txId}:${index}`, "del"),
582258
+ insRsid: deriveRsid(`${begun.tx.txId}:${index}`, "ins")
582259
+ } : {}
582260
+ };
581449
582261
  if (newText.length !== 0)
581450
- return { on, newText, ...stamps, resultKey: String(index) };
582262
+ return { on, newText, ...stamps, resultKey };
581451
582263
  const matchingFields = fieldEntries.filter((entry) => entry.storyId === on.storyId && entry.blockId === on.startBlockId && entry.descriptor.resultText === resolution.text && rangesOverlap8(on.startByte, on.endByte, entry.descriptor.byteStart, entry.descriptor.byteEnd));
581452
582264
  if (matchingFields.length !== 1)
581453
- return { on, newText, ...stamps, resultKey: String(index) };
582265
+ return { on, newText, ...stamps, resultKey };
581454
582266
  if (options?.changeMode === "tracked") {
581455
582267
  trackedFieldDeletion = true;
581456
- return { on, newText, ...stamps, resultKey: String(index) };
582268
+ return { on, newText, ...stamps, resultKey };
581457
582269
  }
581458
582270
  const field = matchingFields[0];
581459
582271
  retiredFieldIds.push(field.stableFieldId);
@@ -581461,7 +582273,7 @@ class V2SelectionMutationAdapter {
581461
582273
  on,
581462
582274
  newText,
581463
582275
  ...stamps,
581464
- resultKey: String(index),
582276
+ resultKey,
581465
582277
  deleteFieldRange: {
581466
582278
  startByte: field.descriptor.byteStart,
581467
582279
  endByte: field.descriptor.byteEnd
@@ -581497,7 +582309,17 @@ class V2SelectionMutationAdapter {
581497
582309
  for (const stableFieldId of retiredFieldIds) {
581498
582310
  retireStableFieldIdForSession(this.context.session, stableFieldId);
581499
582311
  }
581500
- recordCommittedTxIdForHistory(this.context, receipt3.txId);
582312
+ const createdRewriteGroups = new Set;
582313
+ for (const outcome of receipt3.trackedTextEditOutcomes ?? []) {
582314
+ const source = edits[Number(outcome.resultKey)];
582315
+ const origin = source.rewriteIntent ? ownerIds.get(source.ownerStepId ?? "") : undefined;
582316
+ if (origin && outcome.createdRsids.length > 0) {
582317
+ createdRewriteGroups.add(rewriteReviewId(source.on, source.resolution, origin));
582318
+ }
582319
+ }
582320
+ recordCommittedTxIdForHistory(this.context, receipt3.txId, createdRewriteGroups.size > 0 ? {
582321
+ trackedChangeGroupEffects: { created: [...createdRewriteGroups], updated: [], removed: [] }
582322
+ } : undefined);
581501
582323
  const story = edits[0].resolution.target.story;
581502
582324
  const createdRefs = receipt3.createdRefs ?? [];
581503
582325
  const updatedRefs = receipt3.updatedRefs ?? [];
@@ -581509,7 +582331,10 @@ class V2SelectionMutationAdapter {
581509
582331
  ]));
581510
582332
  const trackedOutcomeLogicalView = trackedOutcomeRawIds.size <= 100 && trackedOutcomeRawIds.size > 0 ? buildCachedTrackedChangeLogicalView(this.context).logical : null;
581511
582333
  const trackedChangeOutcomes = (receipt3.trackedTextEditOutcomes ?? []).map((outcome) => {
581512
- const refs = dedupeTrackedChangeReceiptEntities([...outcome.createdRsids, ...outcome.updatedRsids].map((rawId) => ({
582334
+ const source = edits[Number(outcome.resultKey)];
582335
+ const origin = source.rewriteIntent ? ownerIds.get(source.ownerStepId ?? "") : undefined;
582336
+ const parentId = origin ? rewriteReviewId(source.on, source.resolution, origin) : undefined;
582337
+ const refs = parentId && (outcome.createdRsids.length > 0 || outcome.updatedRsids.length > 0) ? [{ kind: "entity", entityType: "trackedChange", entityId: parentId }] : dedupeTrackedChangeReceiptEntities([...outcome.createdRsids, ...outcome.updatedRsids].map((rawId) => ({
581513
582338
  kind: "entity",
581514
582339
  entityType: "trackedChange",
581515
582340
  entityId: trackedOutcomeLogicalView?.rsidToLogicalId.get(rawId) ?? rawId
@@ -581540,11 +582365,11 @@ class V2SelectionMutationAdapter {
581540
582365
  readEffectiveInlineUniformity(input) {
581541
582366
  return readEffectiveInlineUniformity(this.context, input);
581542
582367
  }
581543
- execute(request, options) {
582368
+ execute(request, options, rewriteIntent = false) {
581544
582369
  const offsetSpace = selectionOffsetSpace(options);
581545
582370
  switch (request.kind) {
581546
582371
  case "replace":
581547
- return this.executeReplace(request, options, offsetSpace);
582372
+ return this.executeReplace(request, options, offsetSpace, rewriteIntent);
581548
582373
  case "insert":
581549
582374
  return this.executeReplace({
581550
582375
  kind: "replace",
@@ -581552,7 +582377,7 @@ class V2SelectionMutationAdapter {
581552
582377
  ref: request.ref,
581553
582378
  text: request.text,
581554
582379
  in: request.in
581555
- }, options, offsetSpace);
582380
+ }, options, offsetSpace, false);
581556
582381
  case "delete":
581557
582382
  return this.executeReplace({
581558
582383
  kind: "replace",
@@ -581560,15 +582385,15 @@ class V2SelectionMutationAdapter {
581560
582385
  ref: request.ref,
581561
582386
  text: "",
581562
582387
  in: request.in
581563
- }, options, offsetSpace);
582388
+ }, options, offsetSpace, false);
581564
582389
  case "format":
581565
582390
  return this.executeFormat(request, options, offsetSpace);
581566
582391
  }
581567
582392
  }
581568
- executeReplace(request, options, offsetSpace) {
582393
+ executeReplace(request, options, offsetSpace, isRewrite = false) {
581569
582394
  const startedAt = nowMs6();
581570
582395
  if (request.ref !== undefined && request.target === undefined) {
581571
- return this.executeRefBasedReplace(request, options);
582396
+ return this.executeRefBasedReplace(request, options, isRewrite);
581572
582397
  }
581573
582398
  const target = request.target;
581574
582399
  if (!target) {
@@ -581590,6 +582415,14 @@ class V2SelectionMutationAdapter {
581590
582415
  const revisionFailure = validateExpectedRevision(this.context, options?.expectedRevision);
581591
582416
  if (revisionFailure)
581592
582417
  return failureWithoutResolution(revisionFailure.code, revisionFailure.message);
582418
+ const policyFailure = this.context.getMutationPolicyFailure();
582419
+ if (policyFailure)
582420
+ return failureWithoutResolution(policyFailure.code, policyFailure.message);
582421
+ if (!options?.dryRun && initialStory.materialization?.sourcePartUri) {
582422
+ const preflight = this.executeReplace(request, { ...options, dryRun: true }, offsetSpace, isRewrite);
582423
+ if (!preflight.success)
582424
+ return preflight;
582425
+ }
581593
582426
  const materialized = options?.dryRun ? { ok: true, resolved: initialStory } : storyLocator ? materializeHeaderFooterSlotIfInherited(this.context, initialStory, storyLocator) : { ok: true, resolved: initialStory };
581594
582427
  if (!materialized.ok) {
581595
582428
  return failureWithoutResolution(materialized.failure.code, materialized.failure.message);
@@ -581670,7 +582503,7 @@ class V2SelectionMutationAdapter {
581670
582503
  });
581671
582504
  }
581672
582505
  const resolveSelectionTargetStartedAt = nowMs6();
581673
- const resolved = resolveSelectionTargetToRange({
582506
+ const prepared = prepareSelectionTargetResolution({
581674
582507
  target,
581675
582508
  index,
581676
582509
  readPartBytes: (partUri) => getSDDocumentSessionInternalPartBytes(this.context.session, partUri),
@@ -581678,6 +582511,9 @@ class V2SelectionMutationAdapter {
581678
582511
  buildOffsetMap: buildOffsetMapForCoordinateSpace3,
581679
582512
  ...offsetSpace ? { offsetSpace } : {}
581680
582513
  });
582514
+ if ("error" in prepared)
582515
+ return failureWithoutResolution(prepared.error, prepared.message);
582516
+ const resolved = prepared.resolveOffsets();
581681
582517
  if ("error" in resolved) {
581682
582518
  return failureWithoutResolution(resolved.error, resolved.message);
581683
582519
  }
@@ -581706,6 +582542,30 @@ class V2SelectionMutationAdapter {
581706
582542
  resolved
581707
582543
  });
581708
582544
  const buildResolutionMs = nowMs6() - buildResolutionStartedAt;
582545
+ let replacements = resolved.coordinateSpace !== "tracked" && resolved.startOffset < resolved.endOffset && selectedText.length === resolved.endOffset - resolved.startOffset && isPlannableTextPayload(request.text) ? planTextReplacement(selectedText, request.text) : [{ start: 0, end: resolved.endOffset - resolved.startOffset, text: request.text }];
582546
+ if (story.storyKind === "textbox" && replacements.length > 1) {
582547
+ const boundary = narrowTextReplacement(selectedText, request.text);
582548
+ replacements = boundary ? [boundary] : [];
582549
+ }
582550
+ if (replacements.length === 0) {
582551
+ return { success: false, failure: { code: "NO_OP", message: "replace produced no change." }, resolution };
582552
+ }
582553
+ const edits = [];
582554
+ for (const replacement of replacements) {
582555
+ let editRange = resolved;
582556
+ if (replacement.start !== 0 || replacement.end !== selectedText.length) {
582557
+ const baseOffset = offsetSpace === "selection" ? resolved.paintedStartOffset : resolved.startOffset;
582558
+ const narrowed = prepared.resolveOffsets(baseOffset + replacement.start, baseOffset + replacement.end);
582559
+ if ("error" in narrowed)
582560
+ return failureWithoutResolution(narrowed.error, narrowed.message);
582561
+ editRange = {
582562
+ ...narrowed,
582563
+ paintedStartOffset: resolved.paintedStartOffset + replacement.start,
582564
+ paintedEndOffset: resolved.paintedStartOffset + replacement.end
582565
+ };
582566
+ }
582567
+ edits.push({ on: editRange, newText: replacement.text });
582568
+ }
581709
582569
  if (options?.dryRun) {
581710
582570
  return {
581711
582571
  success: true,
@@ -581725,13 +582585,20 @@ class V2SelectionMutationAdapter {
581725
582585
  const tx = begun.tx;
581726
582586
  const editTextStartedAt = nowMs6();
581727
582587
  const collapsedInlineAffinity = selectionCollapsedInlineAffinity(options);
581728
- const resolvedForEdit = collapsedInlineAffinity && resolved.startOffset === resolved.endOffset ? { ...resolved, collapsedInlineAffinity } : resolved;
581729
- tx.editText({
581730
- changeMode: options?.changeMode ?? "direct",
581731
- on: resolvedForEdit,
581732
- newText: request.text,
581733
- ...trackedTextStampForMode(this.context, tx.txId, options, resolved, request.text)
581734
- });
582588
+ const kernelEdits = edits.map((edit, index2) => ({
582589
+ on: collapsedInlineAffinity && edit.on.startOffset === edit.on.endOffset ? { ...edit.on, collapsedInlineAffinity } : edit.on,
582590
+ newText: edit.newText,
582591
+ ...options?.changeMode === "tracked" && (isRewrite || edits.length > 1) && !typingHistoryMetadata(options) && story.storyKind !== "textbox" ? { rewriteGroupId: `${tx.txId}:0`, preserveExistingRevisions: isRewrite } : {},
582592
+ ...trackedTextStampForMode(this.context, `${tx.txId}:${index2}`, options, edit.on, edit.newText)
582593
+ }));
582594
+ if (kernelEdits.length === 1 && !kernelEdits[0].rewriteGroupId) {
582595
+ tx.editText({ changeMode: options?.changeMode ?? "direct", ...kernelEdits[0] });
582596
+ } else {
582597
+ tx.editTextRanges({
582598
+ changeMode: options?.changeMode ?? "direct",
582599
+ edits: kernelEdits
582600
+ });
582601
+ }
581735
582602
  const editTextMs = nowMs6() - editTextStartedAt;
581736
582603
  const txPerf = createSDTxPerfProbe();
581737
582604
  const commitStartedAt = nowMs6();
@@ -581751,7 +582618,17 @@ class V2SelectionMutationAdapter {
581751
582618
  const invalidateStartedAt = nowMs6();
581752
582619
  this.context.invalidate(receipt3);
581753
582620
  const adapterInvalidateMs = nowMs6() - invalidateStartedAt;
581754
- recordCommittedTxIdForHistory(this.context, receipt3.txId, typingHistoryMetadata(options));
582621
+ const createdRewriteOrigin = kernelEdits.find((edit) => edit.rewriteGroupId)?.rewriteGroupId;
582622
+ recordCommittedTxIdForHistory(this.context, receipt3.txId, {
582623
+ ...typingHistoryMetadata(options),
582624
+ ...createdRewriteOrigin && receipt3.createdRefs?.some((ref5) => ref5.kind === "trackedChange") ? {
582625
+ trackedChangeGroupEffects: {
582626
+ created: [rewriteReviewId(resolved, resolution, createdRewriteOrigin)],
582627
+ updated: [],
582628
+ removed: []
582629
+ }
582630
+ } : {}
582631
+ });
581755
582632
  const textRangeShiftsStartedAt = nowMs6();
581756
582633
  const textRangeShifts = projectTextRangeShifts(receipt3.textRangeShifts ?? [], this.context.session, effectiveStory);
581757
582634
  const projectTextRangeShiftsMs = nowMs6() - textRangeShiftsStartedAt;
@@ -581769,20 +582646,32 @@ class V2SelectionMutationAdapter {
581769
582646
  const remappedRefs = projectTrackedTextReviewGroupRemappings(this.context, inserted);
581770
582647
  const projectTrackedTextEntitiesMs = nowMs6() - trackedProjectionStartedAt;
581771
582648
  const effectsStartedAt = nowMs6();
581772
- const effects2 = buildInsertedTextEffect({
581773
- blockId: resolved.startBlockId,
581774
- baseOffset: resolved.startOffset,
581775
- paintedBaseOffset: resolved.paintedStartOffset,
581776
- text: request.text,
581777
- story: effectiveStory,
581778
- changeMode: options?.changeMode ?? "direct",
581779
- coordinateSpace: resolved.coordinateSpace,
581780
- storyId: resolved.storyId,
581781
- createdSpanProof: getSDCreatedVisibleTextSpanProof(receipt3)
582649
+ let offsetDelta = 0;
582650
+ const insertedTextEffects = edits.flatMap((edit) => {
582651
+ const effects3 = buildInsertedTextEffect({
582652
+ blockId: edit.on.startBlockId,
582653
+ baseOffset: edit.on.startOffset + offsetDelta,
582654
+ paintedBaseOffset: edit.on.paintedStartOffset + offsetDelta,
582655
+ text: edit.newText,
582656
+ story: effectiveStory,
582657
+ changeMode: options?.changeMode ?? "direct",
582658
+ coordinateSpace: edit.on.coordinateSpace,
582659
+ storyId: edit.on.storyId,
582660
+ createdSpanProof: getSDCreatedVisibleTextSpanProof(receipt3)
582661
+ });
582662
+ offsetDelta += edit.newText.length - (edit.on.endOffset - edit.on.startOffset);
582663
+ return effects3?.insertedText ?? [];
581782
582664
  });
582665
+ const effects2 = insertedTextEffects.length > 0 ? { insertedText: insertedTextEffects } : undefined;
581783
582666
  const buildInsertedTextEffectMs = nowMs6() - effectsStartedAt;
582667
+ const rewriteOrigin = isRewrite ? kernelEdits.find((edit) => edit.rewriteGroupId)?.rewriteGroupId : undefined;
581784
582668
  const successReceipt = {
581785
582669
  success: true,
582670
+ ...rewriteOrigin ? { trackedChangeCount: 1, trackedChangeRefs: [{
582671
+ kind: "entity",
582672
+ entityType: "trackedChange",
582673
+ entityId: rewriteReviewId(resolved, resolution, rewriteOrigin)
582674
+ }] } : {},
581786
582675
  affectedStories,
581787
582676
  textRangeShifts,
581788
582677
  txId: receipt3.txId,
@@ -582136,7 +583025,7 @@ class V2SelectionMutationAdapter {
582136
583025
  ...remappedRefs ? { remappedRefs } : {}
582137
583026
  };
582138
583027
  }
582139
- executeRefBasedReplace(request, options) {
583028
+ executeRefBasedReplace(request, options, isRewrite = false) {
582140
583029
  const ref5 = request.ref;
582141
583030
  if (isV2RangeRef(ref5)) {
582142
583031
  const resolvedRange = this.resolveRangeRefSelectionTarget(ref5, request.in);
@@ -582150,7 +583039,7 @@ class V2SelectionMutationAdapter {
582150
583039
  target: resolvedRange.target,
582151
583040
  text: request.text,
582152
583041
  in: resolvedRange.story
582153
- }, options, "kernel");
583042
+ }, options, "kernel", isRewrite);
582154
583043
  }
582155
583044
  if (!isV2SearchRef(ref5)) {
582156
583045
  const raw = resolveRawBlockRefTarget(this.context, ref5, request.in);
@@ -582162,7 +583051,7 @@ class V2SelectionMutationAdapter {
582162
583051
  target: raw.target,
582163
583052
  text: request.text,
582164
583053
  in: request.in
582165
- }, options, "kernel");
583054
+ }, options, "kernel", isRewrite);
582166
583055
  }
582167
583056
  const outcome = resolveV2SearchRef({
582168
583057
  ref: ref5,
@@ -582194,75 +583083,12 @@ class V2SelectionMutationAdapter {
582194
583083
  resolution
582195
583084
  };
582196
583085
  }
582197
- if (options?.dryRun) {
582198
- return {
582199
- success: true,
582200
- resolution
582201
- };
582202
- }
582203
- const fieldDelete = tryDeleteMatchedFieldRef(this.context, request.text, outcome, resolution);
582204
- if (fieldDelete) {
582205
- return fieldDelete;
583086
+ if (!options?.dryRun) {
583087
+ const fieldDelete = tryDeleteMatchedFieldRef(this.context, request.text, outcome, resolution);
583088
+ if (fieldDelete)
583089
+ return fieldDelete;
582206
583090
  }
582207
- const begun = this.context.beginMutation({
582208
- expectedRevision: options?.expectedRevision
582209
- });
582210
- if ("failure" in begun) {
582211
- return {
582212
- success: false,
582213
- failure: begun.failure,
582214
- resolution
582215
- };
582216
- }
582217
- const tx = begun.tx;
582218
- tx.editText({
582219
- changeMode: options?.changeMode ?? "direct",
582220
- on: outcome.resolved,
582221
- newText: request.text,
582222
- ...trackedTextStampForMode(this.context, tx.txId, options, outcome.resolved, request.text)
582223
- });
582224
- const receipt3 = tx.commit();
582225
- if (receipt3.status === "rejected") {
582226
- const code = mapRejectionReason(receipt3.rejectedReason ?? "internal-error");
582227
- return {
582228
- success: false,
582229
- failure: {
582230
- code,
582231
- message: receipt3.rejectedReason ?? "internal-error"
582232
- },
582233
- resolution
582234
- };
582235
- }
582236
- this.context.invalidate(receipt3);
582237
- recordCommittedTxIdForHistory(this.context, receipt3.txId);
582238
- const textRangeShifts = projectTextRangeShifts(receipt3.textRangeShifts ?? [], this.context.session, outcome.storyLocator);
582239
- const affectedStories = projectAffectedStories(receipt3.storiesChanged ?? [], this.context.session, receipt3.partsChanged, outcome.storyLocator);
582240
- const inserted = projectTrackedTextEntities(this.context, receipt3.createdRefs ?? []);
582241
- const updated = projectTrackedTextEntities(this.context, receipt3.updatedRefs ?? []);
582242
- const invalidatedRefs = projectAffectedRefs2(receipt3.invalidatedRefs ?? []);
582243
- const remappedRefs = projectTrackedTextReviewGroupRemappings(this.context, inserted);
582244
- const effects2 = buildInsertedTextEffect({
582245
- blockId: outcome.resolved.startBlockId,
582246
- baseOffset: outcome.resolved.startOffset,
582247
- text: request.text,
582248
- story: outcome.storyLocator,
582249
- changeMode: options?.changeMode ?? "direct",
582250
- coordinateSpace: outcome.resolved.coordinateSpace,
582251
- storyId: outcome.resolved.storyId,
582252
- createdSpanProof: getSDCreatedVisibleTextSpanProof(receipt3)
582253
- });
582254
- return {
582255
- success: true,
582256
- affectedStories,
582257
- textRangeShifts,
582258
- txId: receipt3.txId,
582259
- resolution,
582260
- ...inserted ? { inserted } : {},
582261
- ...updated ? { updated } : {},
582262
- ...invalidatedRefs.length > 0 ? { invalidatedRefs } : {},
582263
- ...remappedRefs ? { remappedRefs } : {},
582264
- ...effects2 ? { effects: effects2 } : {}
582265
- };
583091
+ return this.executeReplace({ kind: "replace", target: outcome.selectionTarget, text: request.text, in: outcome.storyLocator }, options, "kernel", isRewrite);
582266
583092
  }
582267
583093
  trackedTextMove(input, options) {
582268
583094
  const destination = input.destination;
@@ -583329,6 +584155,14 @@ function isDirectTextPayload(text) {
583329
584155
  }
583330
584156
  return true;
583331
584157
  }
584158
+ function isPlannableTextPayload(text) {
584159
+ for (let i2 = 0;i2 < text.length; i2 += 1) {
584160
+ const code = text.charCodeAt(i2);
584161
+ if (code < 32 && code !== 9)
584162
+ return false;
584163
+ }
584164
+ return true;
584165
+ }
583332
584166
  function trackedTextStampForMode(context, txId, options, resolved, newText) {
583333
584167
  if (options?.changeMode !== "tracked")
583334
584168
  return {};
@@ -583504,8 +584338,14 @@ function readTrailingBodySectPr(bodyInner) {
583504
584338
  function buildOffsetMapForCoordinateSpace3(bytes, byteStart, byteEnd, coordinateSpace) {
583505
584339
  return coordinateSpace === "tracked" ? buildSDDocumentSessionInternalTrackedParagraphOffsetMap(bytes, byteStart, byteEnd) : buildSDDocumentSessionInternalParagraphOffsetMap(bytes, byteStart, byteEnd);
583506
584340
  }
584341
+ function rewriteReviewId(on, resolution, origin) {
584342
+ const story = resolution.target.story;
584343
+ const noteId = story && "noteId" in story ? story.noteId : undefined;
584344
+ return buildTextRewriteReviewGroupId(on.storyId, origin, noteId);
584345
+ }
583507
584346
  var TD79, TE41, PERMISSION_DENIED_DOC_PROTECTION = "document protection permits edits only within an everyone permission range.", FORMAT_STRADDLE_MARKER_KINDS;
583508
584347
  var init_adapter7 = __esm(() => {
584348
+ init_review_read_model();
583509
584349
  init_src3();
583510
584350
  init_sd_document_session_internal();
583511
584351
  init_logical_view_cache();
@@ -584191,6 +585031,7 @@ function createV2AdapterContext(session, options = {}) {
584191
585031
  const undoGroups = [];
584192
585032
  const redoGroups = [];
584193
585033
  const historyTrackedChangeLogicalIds = new Map;
585034
+ const historyTrackedChangeGroupEffects = new Map;
584194
585035
  const historyCaptureStack = [];
584195
585036
  let historyGeneration = getSDDocumentSessionInternalHistoryGeneration(session);
584196
585037
  const ensureHistoryGeneration = () => {
@@ -584203,6 +585044,7 @@ function createV2AdapterContext(session, options = {}) {
584203
585044
  undoGroups.length = 0;
584204
585045
  redoGroups.length = 0;
584205
585046
  historyTrackedChangeLogicalIds.clear();
585047
+ historyTrackedChangeGroupEffects.clear();
584206
585048
  fieldContext = copyScalarFieldContext(undefined);
584207
585049
  };
584208
585050
  const renderCommitCaptureStack = [];
@@ -584424,6 +585266,13 @@ function createV2AdapterContext(session, options = {}) {
584424
585266
  historyTrackedChangeLogicalIds.delete(oldestTxId);
584425
585267
  }
584426
585268
  }
585269
+ const groupEffects = metadata?.trackedChangeGroupEffects;
585270
+ if (groupEffects)
585271
+ historyTrackedChangeGroupEffects.set(txId, {
585272
+ created: [...groupEffects.created],
585273
+ updated: [...groupEffects.updated],
585274
+ removed: [...groupEffects.removed]
585275
+ });
584427
585276
  const activeCapture = historyCaptureStack[historyCaptureStack.length - 1];
584428
585277
  if (activeCapture) {
584429
585278
  activeCapture.push(txId);
@@ -584443,8 +585292,7 @@ function createV2AdapterContext(session, options = {}) {
584443
585292
  ...logicalGroup ? { logicalGroup: { ...logicalGroup } } : {}
584444
585293
  });
584445
585294
  }
584446
- for (const redoTxId of redoStack)
584447
- historyTrackedChangeLogicalIds.delete(redoTxId);
585295
+ this.discardHistoryMetadata(redoStack);
584448
585296
  redoStack.length = 0;
584449
585297
  redoGroups.length = 0;
584450
585298
  const evicted = [];
@@ -584458,7 +585306,7 @@ function createV2AdapterContext(session, options = {}) {
584458
585306
  }
584459
585307
  for (const dropped of droppedTxIds) {
584460
585308
  evicted.push(dropped);
584461
- historyTrackedChangeLogicalIds.delete(dropped);
585309
+ this.discardHistoryMetadata([dropped]);
584462
585310
  if (onEvict)
584463
585311
  onEvict(dropped);
584464
585312
  }
@@ -584468,6 +585316,15 @@ function createV2AdapterContext(session, options = {}) {
584468
585316
  getHistoryTrackedChangeLogicalIds(txId) {
584469
585317
  return historyTrackedChangeLogicalIds.get(txId) ?? null;
584470
585318
  },
585319
+ getHistoryTrackedChangeGroupEffects(txId) {
585320
+ return historyTrackedChangeGroupEffects.get(txId) ?? null;
585321
+ },
585322
+ discardHistoryMetadata(txIds) {
585323
+ for (const txId of txIds) {
585324
+ historyTrackedChangeLogicalIds.delete(txId);
585325
+ historyTrackedChangeGroupEffects.delete(txId);
585326
+ }
585327
+ },
584471
585328
  captureCommittedHistory(callback) {
584472
585329
  const capturedTxIds = [];
584473
585330
  historyCaptureStack.push(capturedTxIds);
@@ -622115,8 +622972,6 @@ function buildTrackedChangeThreadLookup(context) {
622115
622972
  function buildVisibleLogicalIdByFragment(logical) {
622116
622973
  const out = new WeakMap;
622117
622974
  for (const entry of logical.byId.values()) {
622118
- if (entry.reviewGroup?.role === "child")
622119
- continue;
622120
622975
  const visibleEntry = resolveVisibleLogicalOwner(logical, entry);
622121
622976
  if (!visibleEntry)
622122
622977
  continue;
@@ -622132,15 +622987,15 @@ function buildVisibleLogicalIdByFragment(logical) {
622132
622987
  return out;
622133
622988
  }
622134
622989
  function resolveVisibleLogicalOwner(logical, entry) {
622135
- const reviewParentId = entry.reviewGroup?.role === "child" ? entry.reviewGroup.parentId : null;
622990
+ const reviewParentId = reviewGroupDisplayParentId(entry);
622136
622991
  const subsumptionParentId = entry.subsumption?.role === "child" ? entry.subsumption.parentId : null;
622137
- if (entry.reviewGroup?.role === "child" && !reviewParentId)
622992
+ if (entry.reviewGroup?.role === "child" && !reviewParentId && !isVisibleLogicalTrackedChange(entry))
622138
622993
  return null;
622139
622994
  if (reviewParentId && subsumptionParentId && reviewParentId !== subsumptionParentId)
622140
622995
  return null;
622141
622996
  const ownerId = reviewParentId ?? subsumptionParentId;
622142
622997
  const owner = ownerId ? logical.byId.get(ownerId) : entry;
622143
- if (!owner || owner.reviewGroup?.role === "child" || owner.subsumption?.role === "child")
622998
+ if (!owner || !isVisibleLogicalTrackedChange(owner))
622144
622999
  return null;
622145
623000
  return owner;
622146
623001
  }
@@ -622914,6 +623769,7 @@ function structuredError3(code2, message) {
622914
623769
  }
622915
623770
  var LIVE_TRACKED_CHANGE_COMMENT_ID_PREFIX = "tc-comment:", trackedChangeAssociationCache, commentLinksCache;
622916
623771
  var init_read = __esm(() => {
623772
+ init_review_read_model();
622917
623773
  init_src3();
622918
623774
  init_sd_document_session_internal();
622919
623775
  init_logical_view_cache();
@@ -629656,7 +630512,7 @@ class V2InfoAdapter {
629656
630512
  const commentsCatalog = getSDDocumentSessionInternalCommentsCatalog(this.context.session);
629657
630513
  const comments = commentsCatalog?.orderedWIds.length ?? 0;
629658
630514
  const tcCatalog = getSDDocumentSessionInternalTrackedChangeCatalog(this.context.session);
629659
- const trackedChanges = tcCatalog ? Array.from(buildCachedTrackedChangeLogicalView(this.context).logical.byId.values()).filter((entry) => entry.reviewGroup?.role !== "child" && entry.subsumption?.role !== "child").length : 0;
630515
+ const trackedChanges = tcCatalog ? Array.from(buildCachedTrackedChangeLogicalView(this.context).logical.byId.values()).filter(isVisibleLogicalTrackedChange).length : 0;
629660
630516
  const lists2 = countDistinctLists(paragraphs);
629661
630517
  const outline = paragraphs.filter((p) => p.headingLevel > 0).map((p) => ({ level: p.headingLevel, text: p.text, nodeId: p.blockId }));
629662
630518
  return {
@@ -630160,6 +631016,7 @@ function findTrackedParagraphEntry(context, storyId, partUri, start, end) {
630160
631016
  }
630161
631017
  var WORD_RE;
630162
631018
  var init_read_adapters = __esm(() => {
631019
+ init_review_read_model();
630163
631020
  init_src3();
630164
631021
  init_sd_document_session_internal();
630165
631022
  init_story_locator();
@@ -636487,6 +637344,8 @@ class V2TrackedChangesAdapter {
636487
637344
  continue;
636488
637345
  }
636489
637346
  if (entry.reviewGroup?.role === "parent") {
637347
+ if (entry.reviewGroup.kind === "text-rewrite")
637348
+ cascadeChildRefs.push({ kind: "trackedChange", entityId: entry.id, storyId: entry.storyId });
636490
637349
  for (const fragment3 of entry.structuralFragments) {
636491
637350
  if (seenStructuralKeys.has(fragment3.entityKey))
636492
637351
  continue;
@@ -636730,9 +637589,7 @@ class V2TrackedChangesAdapter {
636730
637589
  withSpan("documentApi.trackChanges.adapter.invalidate", "document-api", {
636731
637590
  txId: receipt3.txId
636732
637591
  }, () => {
636733
- const trackedChangeLogicalIds = collectHistoryTrackedChangeLogicalIds(receipt3, logical);
636734
637592
  this.context.invalidate(receipt3);
636735
- recordCommittedTxIdForHistory(this.context, receipt3.txId, trackedChangeLogicalIds.size > 0 ? { trackedChangeLogicalIds } : undefined);
636736
637593
  });
636737
637594
  let postLogical = null;
636738
637595
  const getPostLogical = () => {
@@ -636749,11 +637606,36 @@ class V2TrackedChangesAdapter {
636749
637606
  createdRefCount: receipt3.createdRefs?.length ?? 0
636750
637607
  }, () => {
636751
637608
  const mergedInvalidated = mergeInvalidatedRefs(receipt3.invalidatedRefs ?? [], cascadeChildRefs);
637609
+ const touchedGroups = new Set;
637610
+ for (const ref5 of mergedInvalidated) {
637611
+ if (ref5.kind !== "trackedChange")
637612
+ continue;
637613
+ const id = logical.rsidToLogicalId.get(ref5.entityId) ?? ref5.entityId;
637614
+ const group = logical.byId.get(id)?.reviewGroup;
637615
+ if (group?.kind === "text-rewrite")
637616
+ touchedGroups.add(group.parentId ?? id);
637617
+ }
637618
+ const survivingGroups = [...touchedGroups].filter((id) => getPostLogical().byId.has(id));
637619
+ for (const id of touchedGroups) {
637620
+ if (!getPostLogical().byId.has(id) && !mergedInvalidated.some((ref5) => ref5.kind === "trackedChange" && ref5.entityId === id)) {
637621
+ mergedInvalidated.push({ kind: "trackedChange", entityId: id, storyId: logical.byId.get(id).storyId });
637622
+ }
637623
+ }
636752
637624
  const createdRefs = receipt3.createdRefs ?? [];
637625
+ const trackedChangeLogicalIds = collectHistoryTrackedChangeLogicalIds(receipt3, logical);
637626
+ recordCommittedTxIdForHistory(this.context, receipt3.txId, {
637627
+ ...trackedChangeLogicalIds.size > 0 ? { trackedChangeLogicalIds } : {},
637628
+ ...touchedGroups.size > 0 ? { trackedChangeGroupEffects: {
637629
+ created: [],
637630
+ updated: survivingGroups,
637631
+ removed: [...touchedGroups].filter((id) => !survivingGroups.includes(id))
637632
+ } } : {}
637633
+ });
636753
637634
  return {
636754
637635
  success: true,
636755
637636
  inserted: createdRefs.length > 0 ? projectInsertedEntitiesWithLogicalIds(createdRefs, getPostLogical()) : [],
636756
637637
  removed: projectRemovedEntitiesWithLogicalIds(mergedInvalidated, logical),
637638
+ ...survivingGroups.length ? { updated: survivingGroups.map((entityId) => ({ kind: "entity", entityType: "trackedChange", entityId })) } : {},
636757
637639
  invalidatedRefs: projectAffectedRefsWithLogicalIds(mergedInvalidated, logical),
636758
637640
  remappedRefs: projectRemappedRefsWithLogicalIds(receipt3.remappedRefs ?? [], logical),
636759
637641
  affectedStories: projectAffectedStories(receipt3.storiesChanged ?? [], this.context.session, receipt3.partsChanged),
@@ -636768,7 +637650,7 @@ class V2TrackedChangesAdapter {
636768
637650
  if (!entry) {
636769
637651
  return failure17("TARGET_NOT_FOUND", `No tracked change with id "${target.range.anchor}".`);
636770
637652
  }
636771
- if (entry.reviewGroup) {
637653
+ if (entry.reviewGroup && !(entry.reviewGroup.kind === "text-rewrite" && entry.reviewGroup.role === "child")) {
636772
637654
  return failure17("INVALID_INPUT", `trackChanges.decide range: tracked change "${entry.id}" is part of a grouped Word revision; ` + "decide it atomically by id.");
636773
637655
  }
636774
637656
  if (entry.type === "structural" || entry.type === "move") {
@@ -636935,7 +637817,7 @@ class V2TrackedChangesAdapter {
636935
637817
  if (!overlap.logical) {
636936
637818
  return failure17("INTERNAL_ERROR", `trackChanges.decide range: overlapped fragment "${overlap.fragment.rsid}" was not mapped to a logical tracked change.`);
636937
637819
  }
636938
- if (overlap.logical.reviewGroup) {
637820
+ if (overlap.logical.reviewGroup && overlap.logical.reviewGroup.kind !== "text-rewrite") {
636939
637821
  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.");
636940
637822
  }
636941
637823
  }
@@ -637100,6 +637982,10 @@ function isTextCoordinateSpace(value2) {
637100
637982
  return value2 === undefined || value2 === "visible" || value2 === "tracked";
637101
637983
  }
637102
637984
  function selectFragmentForLogicalRange(entry, side) {
637985
+ if (entry.reviewGroup?.kind === "text-rewrite" && entry.reviewGroup.role === "parent") {
637986
+ const kind = side === "delete" || side === "deleted" || side === "source" ? "del" : "ins";
637987
+ return entry.fragments.find((fragment3) => fragment3.kind === kind) ?? entry.fragments[0] ?? null;
637988
+ }
637103
637989
  if (entry.type === "replacement") {
637104
637990
  if (side === "delete" || side === "deleted" || side === "source") {
637105
637991
  const deletedRsid = entry.sides?.deleted?.rsid;
@@ -637433,11 +638319,11 @@ function logicalEntryMatchesStoryFilter(entry, filter) {
637433
638319
  return !filter.noteId || entry.noteId === filter.noteId;
637434
638320
  }
637435
638321
  function isVisibleLogicalChange(entry) {
637436
- if (entry.reviewGroup?.role === "child")
637437
- return false;
637438
- return entry.subsumption?.role !== "child";
638322
+ return isVisibleLogicalTrackedChange(entry);
637439
638323
  }
637440
638324
  function resolveSubsumedLogicalChange(logical, entry) {
638325
+ if (entry.reviewGroup?.kind === "text-rewrite")
638326
+ return entry;
637441
638327
  if (entry.reviewGroup?.role === "child" && entry.reviewGroup.parentId) {
637442
638328
  return logical.byId.get(entry.reviewGroup.parentId) ?? entry;
637443
638329
  }
@@ -637480,6 +638366,7 @@ function buildDiscoveryItem2(entry, context, logical, linkedCommentIds, resolveS
637480
638366
  ...navigationTarget ? { navigationTarget } : {},
637481
638367
  ...structuralDescriptor ? { structuralDescriptor } : {},
637482
638368
  revisionGroupId: entry.revisionGroupId,
638369
+ ...entry.reviewGroup?.kind === "text-rewrite" && logical ? { reviewGroup: projectTextRewriteReviewGroup(entry, logical) } : {},
637483
638370
  splitFromId: entry.splitFromId,
637484
638371
  sourceIds: projectSourceIds(entry),
637485
638372
  wordRevisionIds: projectWordRevisionIdsAlias(entry),
@@ -637616,6 +638503,7 @@ function buildInfo(entry, context, logical, linkedCommentIds, resolveSession) {
637616
638503
  sourceIds: projectSourceIds(entry),
637617
638504
  wordRevisionIds: projectWordRevisionIdsAlias(entry),
637618
638505
  revisionGroupId: entry.revisionGroupId,
638506
+ ...entry.reviewGroup?.kind === "text-rewrite" && logical ? { reviewGroup: projectTextRewriteReviewGroup(entry, logical) } : {},
637619
638507
  splitFromId: entry.splitFromId,
637620
638508
  ...structuralDescriptor ? { structuralDescriptor } : {},
637621
638509
  ...replacement ? { replacement } : {},
@@ -637723,7 +638611,7 @@ function isGoogleDocsLikePackage(session) {
637723
638611
  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;
637724
638612
  }
637725
638613
  function projectGrouping(entry) {
637726
- if (entry.reviewGroup)
638614
+ if (entry.reviewGroup && !(entry.reviewGroup.kind === "text-rewrite" && entry.reviewGroup.role === "child"))
637727
638615
  return "unknown";
637728
638616
  return entry.type === "replacement" || entry.sides ? "replacement-pair" : "standalone";
637729
638617
  }
@@ -638725,6 +639613,8 @@ function createSuccessorRsidAllocator(raw) {
638725
639613
  }
638726
639614
  var resolvedTrackedChangeIdsBySession, TEXT_DECODER6, TEXT_ENCODER, EMUS_PER_CSS_PIXEL = 9525, BROWSER_RENDERABLE_IMAGE_CONTENT_TYPES, DocumentApiAdapterError, STRUCTURAL_DESCRIPTOR_OPERATIONS;
638727
639615
  var init_adapter21 = __esm(() => {
639616
+ init_review_read_model();
639617
+ init_review_read_model();
638728
639618
  init_src3();
638729
639619
  init_sd_document_session_internal();
638730
639620
  init_story_surface();
@@ -648718,17 +649608,17 @@ class V2GetTextAdapter {
648718
649608
  if (!bytes)
648719
649609
  return "";
648720
649610
  const scopedBytes = resolved.descriptor.storyByteRange ? bytes.subarray(resolved.descriptor.storyByteRange[0], resolved.descriptor.storyByteRange[1]) : bytes;
648721
- return extractVisibleTextFromXml3(TD100.decode(scopedBytes));
649611
+ return extractVisibleTextFromXml4(TD100.decode(scopedBytes));
648722
649612
  }
648723
649613
  }
648724
- var TD100, extractVisibleTextFromXml3;
649614
+ var TD100, extractVisibleTextFromXml4;
648725
649615
  var init_adapter26 = __esm(() => {
648726
649616
  init_sd_document_session_internal();
648727
649617
  init_story_identity();
648728
649618
  init_story_surface();
648729
649619
  init_visible_text();
648730
649620
  TD100 = new TextDecoder;
648731
- extractVisibleTextFromXml3 = extractVisibleTextFromXml2;
649621
+ extractVisibleTextFromXml4 = extractVisibleTextFromXml2;
648732
649622
  });
648733
649623
 
648734
649624
  // ../../../v2/document-api-v2-adapter/dist/search/node-discovery.js
@@ -648826,7 +649716,7 @@ function collectRunNodes(context, resolved, story) {
648826
649716
  const paragraphXml = stripPendingDeletions(TD101.decode(bytes.subarray(entry.byteStart, entry.byteEnd)));
648827
649717
  let offset = 0;
648828
649718
  for (const runXml of scanRunSpans(paragraphXml)) {
648829
- const text4 = extractVisibleTextFromXml3(runXml);
649719
+ const text4 = extractVisibleTextFromXml4(runXml);
648830
649720
  if (text4.length === 0)
648831
649721
  continue;
648832
649722
  const start = offset;
@@ -648997,7 +649887,7 @@ function readCellText(context, storyId, bodyStart, bodyEnd) {
648997
649887
  return "";
648998
649888
  if (bodyEnd > bytes.length || bodyStart < 0 || bodyEnd <= bodyStart)
648999
649889
  return "";
649000
- return extractVisibleTextFromXml3(TD101.decode(bytes.subarray(bodyStart, bodyEnd)));
649890
+ return extractVisibleTextFromXml4(TD101.decode(bytes.subarray(bodyStart, bodyEnd)));
649001
649891
  }
649002
649892
  function addressStory(locator, resolved) {
649003
649893
  if (resolved.storyKind === "main")
@@ -650433,7 +651323,7 @@ async function compileOrderedAtomicTextPlan(context, input, evaluatedRevision) {
650433
651323
  };
650434
651324
  }
650435
651325
  try {
650436
- const compiled = await compileOrderedTextProgram(context, textSteps, input.in, evaluatedRevision);
651326
+ const compiled = await compileOrderedTextProgram(context, textSteps, input.in, evaluatedRevision, input.changeMode === "tracked");
650437
651327
  steps.push(...compiled.steps);
650438
651328
  return { evaluatedRevision, steps, failures, atomicTextProgram: { edits: compiled.edits } };
650439
651329
  } catch (error48) {
@@ -650449,7 +651339,7 @@ async function compileOrderedAtomicTextPlan(context, input, evaluatedRevision) {
650449
651339
  return { evaluatedRevision, steps, failures };
650450
651340
  }
650451
651341
  }
650452
- async function compileOrderedTextProgram(context, sourceSteps, story, evaluatedRevision) {
651342
+ async function compileOrderedTextProgram(context, sourceSteps, story, evaluatedRevision, preserveReviewOrigins) {
650453
651343
  const cache = {
650454
651344
  offsetMaps: new WeakMap,
650455
651345
  paragraphBytes: new Map,
@@ -650527,7 +651417,10 @@ async function compileOrderedTextProgram(context, sourceSteps, story, evaluatedR
650527
651417
  for (const match of matches.slice().reverse()) {
650528
651418
  const replacement = sourceStep.op === "text.delete" ? "" : replacementTextForMatch(sourceStep, match.text, match.groups);
650529
651419
  if (replacement !== match.text) {
650530
- replaceStagedText(paragraph4, match.from, match.to, replacement, sourceStep.id, sourceStepOrder);
651420
+ const spans = paragraph4.coordinateSpace !== "tracked" ? planTextReplacement(match.text, replacement) : [{ start: 0, end: match.text.length, text: replacement }];
651421
+ for (const span of spans.slice().reverse()) {
651422
+ replaceStagedText(paragraph4, match.from + span.start, match.from + span.end, span.text, sourceStep.id, sourceStepOrder, preserveReviewOrigins);
651423
+ }
650531
651424
  }
650532
651425
  }
650533
651426
  }
@@ -650546,12 +651439,13 @@ async function compileOrderedTextProgram(context, sourceSteps, story, evaluatedR
650546
651439
  }
650547
651440
  const edits = [];
650548
651441
  for (const paragraph4 of staged.values()) {
650549
- for (const edit of materializeStagedEdits(paragraph4)) {
651442
+ for (const edit of materializeStagedEdits(paragraph4, preserveReviewOrigins)) {
650550
651443
  const on = resolveOriginalParagraphRange(context, paragraph4, edit.from, edit.to);
650551
651444
  edits.push({
650552
651445
  on,
650553
651446
  newText: edit.text,
650554
651447
  ownerStepId: edit.ownerStepId,
651448
+ rewriteIntent: compiledSteps.find((step3) => step3.stepId === edit.ownerStepId)?.op === "text.rewrite",
650555
651449
  resolution: {
650556
651450
  target: {
650557
651451
  kind: "text",
@@ -650656,13 +651550,19 @@ function isStringWordBoundary(text4, at, length) {
650656
651550
  const after = at + length < text4.length ? text4.charCodeAt(at + length) : -1;
650657
651551
  return !isWord(before) && !isWord(after);
650658
651552
  }
650659
- function replaceStagedText(paragraph4, from, to, replacement, ownerStepId, ownerOrder) {
651553
+ function overlappingTrackedStep(stepId) {
651554
+ return new DocumentApiValidationError2("CAPABILITY_UNSUPPORTED", `step "${stepId}" overlaps an earlier tracked step; this atomic plan cannot preserve separate review origins.`);
651555
+ }
651556
+ function replaceStagedText(paragraph4, from, to, replacement, ownerStepId, ownerOrder, preserveReviewOrigins) {
650660
651557
  const { pieces } = paragraph4;
650661
651558
  const startIndex = splitStagedPiecesAt(pieces, from);
650662
651559
  const endIndex = splitStagedPiecesAt(pieces, to);
650663
651560
  const removed = pieces.slice(startIndex, endIndex);
650664
651561
  const anchor = removed.length > 0 ? Math.min(...removed.map((piece) => piece.sourceStart)) : stagedBoundarySourceOffset(pieces, startIndex);
650665
651562
  const sourceEnd = removed.reduce((maximum, piece) => Math.max(maximum, piece.sourceEnd), anchor);
651563
+ if (preserveReviewOrigins && (removed.some((piece) => piece.ownerStepId && piece.ownerStepId !== ownerStepId) || paragraph4.rangeOwners.some((owner) => owner.stepId !== ownerStepId && owner.from < sourceEnd && owner.to > anchor))) {
651564
+ throw overlappingTrackedStep(ownerStepId);
651565
+ }
650666
651566
  if (sourceEnd > anchor) {
650667
651567
  paragraph4.rangeOwners = paragraph4.rangeOwners.filter((owner) => owner.to <= anchor || owner.from >= sourceEnd);
650668
651568
  paragraph4.rangeOwners.push({ from: anchor, to: sourceEnd, stepId: ownerStepId, order: ownerOrder });
@@ -650720,7 +651620,7 @@ function stagedBoundarySourceOffset(pieces, index2) {
650720
651620
  }
650721
651621
  return 0;
650722
651622
  }
650723
- function materializeStagedEdits(paragraph4) {
651623
+ function materializeStagedEdits(paragraph4, preserveReviewOrigins) {
650724
651624
  const edits = [];
650725
651625
  let sourceCursor = 0;
650726
651626
  let replacements = [];
@@ -650736,13 +651636,17 @@ function materializeStagedEdits(paragraph4) {
650736
651636
  const intervalInserted = inserted.filter((piece) => piece.sourceStart >= start && (piece.sourceStart < end || index2 === points.length - 2 && piece.sourceStart === end));
650737
651637
  const text4 = intervalInserted.map((piece) => piece.text).join("");
650738
651638
  if (paragraph4.originalText.slice(start, end) !== text4) {
650739
- const owner = [
651639
+ const owners = [
650740
651640
  ...paragraph4.rangeOwners.filter((owner2) => owner2.from < end && owner2.to > start).map((owner2) => ({ stepId: owner2.stepId, order: owner2.order })),
650741
651641
  ...intervalInserted.flatMap((piece) => piece.ownerStepId && piece.ownerOrder != null ? [{ stepId: piece.ownerStepId, order: piece.ownerOrder }] : [])
650742
- ].sort((left, right) => right.order - left.order)[0];
651642
+ ].sort((left, right) => right.order - left.order);
651643
+ const owner = owners[0];
650743
651644
  if (!owner) {
650744
651645
  throw new DocumentApiValidationError2("INTERNAL_ERROR", "projected text edit has no owning mutation step.");
650745
651646
  }
651647
+ if (preserveReviewOrigins && owners.some((candidate) => candidate.stepId !== owner.stepId)) {
651648
+ throw overlappingTrackedStep(owner.stepId);
651649
+ }
650746
651650
  edits.push({ from: start, to: end, text: text4, ownerStepId: owner.stepId });
650747
651651
  }
650748
651652
  }
@@ -651371,7 +652275,8 @@ function commitStep(selectionMutation, paragraphs, compiled, changeMode) {
651371
652275
  const edits = changedIndexes.map((index2) => ({
651372
652276
  on: compiled.kernelRanges[index2],
651373
652277
  newText: requests[index2].text,
651374
- resolution: resolutions[index2]
652278
+ resolution: resolutions[index2],
652279
+ rewriteIntent: compiled.op === "text.rewrite"
651375
652280
  }));
651376
652281
  return selectionMutation.executeResolvedTextRewrites(edits, { changeMode });
651377
652282
  }
@@ -651379,7 +652284,7 @@ function commitStep(selectionMutation, paragraphs, compiled, changeMode) {
651379
652284
  let hasSuccessfulRequest = false;
651380
652285
  const trackedChangeRefs = [];
651381
652286
  for (const request of requests) {
651382
- const receipt3 = commitRequest(selectionMutation, paragraphs, request, changeMode);
652287
+ const receipt3 = commitRequest(selectionMutation, paragraphs, request, changeMode, compiled.op === "text.rewrite");
651383
652288
  if (receipt3.success) {
651384
652289
  hasSuccessfulRequest = true;
651385
652290
  appendUniqueTrackedChangeRefs(trackedChangeRefs, readTrackedChangeRefs3(receipt3));
@@ -651398,7 +652303,7 @@ function commitStep(selectionMutation, paragraphs, compiled, changeMode) {
651398
652303
  ...trackedChangeRefs.length > 0 ? { trackedChangeRefs } : {}
651399
652304
  };
651400
652305
  }
651401
- function commitRequest(selectionMutation, paragraphs, request, changeMode) {
652306
+ function commitRequest(selectionMutation, paragraphs, request, changeMode, rewriteIntent = false) {
651402
652307
  if (request.kind === "format") {
651403
652308
  const trackedChangeRefs = [];
651404
652309
  if (request.inline) {
@@ -651457,14 +652362,14 @@ function commitRequest(selectionMutation, paragraphs, request, changeMode) {
651457
652362
  target: request.target,
651458
652363
  text: request.text,
651459
652364
  ...request.in ? { in: request.in } : {}
651460
- }, { changeMode });
652365
+ }, { changeMode }, rewriteIntent);
651461
652366
  }
651462
652367
  return selectionMutation.execute({
651463
652368
  kind: "replace",
651464
652369
  ref: request.ref,
651465
652370
  text: request.text,
651466
652371
  ...request.in ? { in: request.in } : {}
651467
- }, { changeMode });
652372
+ }, { changeMode }, rewriteIntent);
651468
652373
  }
651469
652374
  function buildStepOutcome(compiled, effect, trackedChanges = [], trackedChangeCount = trackedChanges.length) {
651470
652375
  const resolutions = compiled.resolutions ?? (compiled.resolution ? [compiled.resolution] : []);
@@ -651505,8 +652410,7 @@ function readTrackedChangeRefs3(receipt3) {
651505
652410
  if (!receipt3 || typeof receipt3 !== "object")
651506
652411
  return [];
651507
652412
  const record3 = receipt3;
651508
- const candidates = [
651509
- ...Array.isArray(record3.trackedChangeRefs) ? record3.trackedChangeRefs : [],
652413
+ const candidates = Array.isArray(record3.trackedChangeRefs) ? record3.trackedChangeRefs : [
651510
652414
  ...Array.isArray(record3.inserted) ? record3.inserted : [],
651511
652415
  ...Array.isArray(record3.updated) ? record3.updated : []
651512
652416
  ];
@@ -707726,6 +708630,12 @@ function createStorySurfaceExecutionBackend(options) {
707726
708630
  rejectedReason: "unsupported-context"
707727
708631
  };
707728
708632
  }
708633
+ if (options.strictMirror && !hasStrictMirrorPrerequisites(prepared, options)) {
708634
+ return {
708635
+ status: "rejected",
708636
+ rejectedReason: "internal-error"
708637
+ };
708638
+ }
707729
708639
  const undo2 = prepared.backendExtensions.storySurface?.historyReplay?.direction === "undo";
707730
708640
  const paragraphOnlyReviewStoryIds = undo2 ? null : readParagraphOnlyReviewStoryIds(options.session, prepared);
707731
708641
  const result = delegate.apply(prepared);
@@ -707844,7 +708754,39 @@ function runStorySurfaceMirror(prepared, options, admission, paragraphOnlyReview
707844
708754
  function resolvePackagePartHandoff(prepared, extension2) {
707845
708755
  const ownedStoryParts = new Set(prepared.resolvedTargets.storyPartOwnership.map((entry) => String(entry.partUri)));
707846
708756
  const touchesPackageSidecar = prepared.resolvedTargets.partUris.some((partUri) => !ownedStoryParts.has(String(partUri)));
707847
- return touchesPackageSidecar || extension2?.storyLocal === false;
708757
+ const retiresOwnedStoryPart = prepared.resolvedTargets.storyPartOwnership.some((entry) => prepared.localApplyBundle.perPart?.[String(entry.partUri)]?.kind === "remove");
708758
+ return touchesPackageSidecar || retiresOwnedStoryPart || extension2?.storyLocal === false;
708759
+ }
708760
+ function hasStrictMirrorPrerequisites(prepared, options) {
708761
+ const extension2 = prepared.backendExtensions.storySurface;
708762
+ if (!extension2)
708763
+ return false;
708764
+ if (!touchesOwnedStoryPart(prepared))
708765
+ return true;
708766
+ if (extension2.headerFooterSlotMaterialization)
708767
+ return options.session != null;
708768
+ switch (extension2.family) {
708769
+ case "storyText":
708770
+ return !extension2.historyReplay && !extension2.resyncFromSession && !extension2.sessionSync ? true : options.session != null;
708771
+ case "storyTrackedDecide":
708772
+ return !usesTrackedDecisionSessionSync(prepared, extension2) || options.session != null;
708773
+ case "storyTable":
708774
+ return true;
708775
+ case "storyBlocks":
708776
+ case "storyPaste":
708777
+ case "storyFormat":
708778
+ case "storyList":
708779
+ case "storyHyperlink":
708780
+ case "storyImage":
708781
+ case "storyAnchor":
708782
+ return options.session != null;
708783
+ case "compareApply":
708784
+ return false;
708785
+ default: {
708786
+ const exhaustive = extension2.family;
708787
+ return exhaustive;
708788
+ }
708789
+ }
707848
708790
  }
707849
708791
  function runFamilyMirror(prepared, extension2, options, directStoryText, paragraphOnlyReviewStoryIds) {
707850
708792
  if (!options.resolveStoryShard) {
@@ -707909,6 +708851,7 @@ function runFamilyMirror(prepared, extension2, options, directStoryText, paragra
707909
708851
  session: options.session,
707910
708852
  prepared,
707911
708853
  extension: extension2,
708854
+ storyIds: storyIdsRequiringShards(prepared, extension2),
707912
708855
  paragraphOnlyReviewStoryIds,
707913
708856
  resolveStoryShard: options.resolveStoryShard
707914
708857
  });
@@ -707942,6 +708885,7 @@ function runFamilyMirror(prepared, extension2, options, directStoryText, paragra
707942
708885
  session: options.session,
707943
708886
  prepared,
707944
708887
  extension: extension2,
708888
+ storyIds: storyIdsRequiringShards(prepared, extension2),
707945
708889
  resolveStoryShard: options.resolveStoryShard
707946
708890
  });
707947
708891
  return { ...sessionSync, mirrorPath: "session-sync" };
@@ -708985,7 +709929,10 @@ function storyIdsRequiringShards(prepared, extension2) {
708985
709929
  if (extension2.family === "storyText" && prepared.source.kind === "editText") {
708986
709930
  return [String(prepared.source.on.storyId)];
708987
709931
  }
708988
- return [...new Set(prepared.resolvedTargets.stories.map((storyId) => String(storyId)))];
709932
+ const retiredStoryIds = new Set(prepared.resolvedTargets.storyPartOwnership.filter((entry) => prepared.localApplyBundle.perPart?.[String(entry.partUri)]?.kind === "remove").map((entry) => String(entry.storyId)));
709933
+ return [
709934
+ ...new Set(prepared.resolvedTargets.stories.map((storyId) => String(storyId)).filter((storyId) => !retiredStoryIds.has(storyId)))
709935
+ ];
708989
709936
  }
708990
709937
  function hasSourceStoryOwnership(prepared, sourceStoryId, sourcePartUri) {
708991
709938
  const ownership = prepared.resolvedTargets.storyPartOwnership;
@@ -712131,6 +713078,11 @@ function createHeadlessCollabRoomCoordinator(options) {
712131
713078
  const usesImagePackageSync = isImageSourceKind(prepared.source.kind) || storySurfaceFamily === "storyImage";
712132
713079
  const syncedListSidecarParts = syncPreparedListSidecar(prepared.backendExtensions.packagePart?.listSidecar);
712133
713080
  const storyPartUris = new Set(prepared.resolvedTargets.storyPartOwnership.map((entry) => String(entry.partUri)));
713081
+ for (const partUri of storyPartUris) {
713082
+ if (prepared.localApplyBundle.perPart[partUri]?.kind === "remove") {
713083
+ retireStoryPart(partUri);
713084
+ }
713085
+ }
712134
713086
  const packagePartUris = Array.from(new Set(prepared.resolvedTargets.partUris.filter((partUri) => !storyPartUris.has(String(partUri)))));
712135
713087
  for (const partUri of packagePartUris) {
712136
713088
  if (syncedListSidecarParts.has(partUri))
@@ -712441,7 +713393,7 @@ function createHeadlessCollabRoomCoordinator(options) {
712441
713393
  if (isCommentsFamilyPartUri(String(partUri)))
712442
713394
  out.add(String(partUri));
712443
713395
  }
712444
- out.add(COMMENTS_PART_URI4);
713396
+ out.add(COMMENTS_PART_URI5);
712445
713397
  return Array.from(out).sort();
712446
713398
  }
712447
713399
  function syncRelationshipsPart(partUri, bytes) {
@@ -712743,8 +713695,11 @@ function createHeadlessCollabRoomCoordinator(options) {
712743
713695
  ensurePartHandlesFromManifest(descriptor);
712744
713696
  }
712745
713697
  ensureStoryHandlesFromManifest();
712746
- if (replacingPackage)
713698
+ if (replacingPackage) {
712747
713699
  reconcileReplacementStories();
713700
+ } else {
713701
+ pruneStoryHandlesMissingFromManifest();
713702
+ }
712748
713703
  pruneProjectionHandlesMissingFromManifest(activeProjectionShardIdsFromManifest(descriptors), replacingPackage);
712749
713704
  } finally {
712750
713705
  syncingManifest = false;
@@ -712835,6 +713790,34 @@ function createHeadlessCollabRoomCoordinator(options) {
712835
713790
  notifyRegistryChangedIfActive();
712836
713791
  }
712837
713792
  }
713793
+ function pruneStoryHandlesMissingFromManifest() {
713794
+ const snapshot3 = readRoomManifest(options.rootDoc).snapshot;
713795
+ if (!snapshot3)
713796
+ return;
713797
+ const active = new Set(snapshot3.shards.filter((descriptor) => descriptor.shardKind === SHARD_KIND.story).map((descriptor) => descriptor.shardId));
713798
+ let changed = false;
713799
+ for (const [storyId, info] of storyInfos) {
713800
+ if (active.has(info.shardId))
713801
+ continue;
713802
+ storyInfos.delete(storyId);
713803
+ changed = true;
713804
+ }
713805
+ for (const [storyId, handle] of options.graph.storyHandlesByStoryId) {
713806
+ if (active.has(handle.shardId))
713807
+ continue;
713808
+ options.graph.storyHandlesByStoryId.delete(storyId);
713809
+ changed = true;
713810
+ }
713811
+ for (const shardId of options.graph.storyHandles.keys()) {
713812
+ if (active.has(shardId))
713813
+ continue;
713814
+ options.graph.storyHandles.delete(shardId);
713815
+ options.graph.requiredShardIds.delete(shardId);
713816
+ changed = true;
713817
+ }
713818
+ if (changed)
713819
+ notifyRegistryChangedIfActive();
713820
+ }
712838
713821
  function syncHeaderFooterMaterialization(prepared) {
712839
713822
  const proof = prepared.backendExtensions.storySurface?.headerFooterSlotMaterialization;
712840
713823
  if (!proof)
@@ -712930,7 +713913,7 @@ function createHeadlessCollabRoomCoordinator(options) {
712930
713913
  return [packageShardId(options.rootId, SHARD_KIND.settings, SETTINGS_PART_URI5)];
712931
713914
  }
712932
713915
  if (isCommentsFamilyPartKind(descriptor.partKind)) {
712933
- return [packageShardId(options.rootId, SHARD_KIND.comments, COMMENTS_PART_URI4)];
713916
+ return [packageShardId(options.rootId, SHARD_KIND.comments, COMMENTS_PART_URI5)];
712934
713917
  }
712935
713918
  if (descriptor.partKind === "image" || descriptor.partKind === "media") {
712936
713919
  return [
@@ -714186,7 +715169,7 @@ function createHeadlessCollabRoomCoordinator(options) {
714186
715169
  seedCommentsShardIfNeeded(collabUnitTargetOrDoc(options.graph.commentsHandle), pairedPartKeys);
714187
715170
  return options.graph.commentsHandle;
714188
715171
  }
714189
- const shardId = packageShardId(options.rootId, SHARD_KIND.comments, COMMENTS_PART_URI4);
715172
+ const shardId = packageShardId(options.rootId, SHARD_KIND.comments, COMMENTS_PART_URI5);
714190
715173
  const { unit } = materializeSubtreePackageHandle(shardId, SHARD_KIND.comments);
714191
715174
  const handle = {
714192
715175
  shardId,
@@ -714212,12 +715195,12 @@ function createHeadlessCollabRoomCoordinator(options) {
714212
715195
  function allocateCommentIdFromSharedShard(input) {
714213
715196
  if (disposed)
714214
715197
  return null;
714215
- const handle = options.graph.commentsHandle ?? ensureCommentsShard([encodeLogicalOwnerKey(COMMENTS_PART_URI4)]);
715198
+ const handle = options.graph.commentsHandle ?? ensureCommentsShard([encodeLogicalOwnerKey(COMMENTS_PART_URI5)]);
714216
715199
  if (!handle)
714217
715200
  return null;
714218
715201
  let allocated = null;
714219
715202
  handle.doc.transact(() => {
714220
- seedCommentsShardIfNeeded(collabUnitTargetOrDoc(handle), [encodeLogicalOwnerKey(COMMENTS_PART_URI4)]);
715203
+ seedCommentsShardIfNeeded(collabUnitTargetOrDoc(handle), [encodeLogicalOwnerKey(COMMENTS_PART_URI5)]);
714221
715204
  const commentsMap = getPartRecordsMap(collabUnitTargetOrDoc(handle)).get("comments");
714222
715205
  const inUse = new Set;
714223
715206
  if (commentsMap instanceof YMap) {
@@ -714240,14 +715223,14 @@ function createHeadlessCollabRoomCoordinator(options) {
714240
715223
  return allocated;
714241
715224
  }
714242
715225
  function seedCommentsShardIfNeeded(doc2, pairedPartKeys) {
714243
- const shardId = packageShardId(options.rootId, SHARD_KIND.comments, COMMENTS_PART_URI4);
715226
+ const shardId = packageShardId(options.rootId, SHARD_KIND.comments, COMMENTS_PART_URI5);
714244
715227
  try {
714245
715228
  seedCommentsShard({
714246
715229
  doc: doc2,
714247
715230
  shardId,
714248
- ownerPartKey: encodeLogicalOwnerKey(COMMENTS_PART_URI4),
714249
- ownerPartUri: COMMENTS_PART_URI4,
714250
- pairedPartKeys: pairedPartKeys.length > 0 ? Array.from(new Set(pairedPartKeys)).sort() : [encodeLogicalOwnerKey(COMMENTS_PART_URI4)],
715231
+ ownerPartKey: encodeLogicalOwnerKey(COMMENTS_PART_URI5),
715232
+ ownerPartUri: COMMENTS_PART_URI5,
715233
+ pairedPartKeys: pairedPartKeys.length > 0 ? Array.from(new Set(pairedPartKeys)).sort() : [encodeLogicalOwnerKey(COMMENTS_PART_URI5)],
714251
715234
  comments: [],
714252
715235
  people: []
714253
715236
  });
@@ -714273,7 +715256,7 @@ function createHeadlessCollabRoomCoordinator(options) {
714273
715256
  meta4.set(PACKAGE_PART_META_KEY.pairedPartKeys, Array.from(merged).sort());
714274
715257
  }
714275
715258
  function connectCommentsHandleIfNeeded(pairedPartKeys) {
714276
- const shardId = packageShardId(options.rootId, SHARD_KIND.comments, COMMENTS_PART_URI4);
715259
+ const shardId = packageShardId(options.rootId, SHARD_KIND.comments, COMMENTS_PART_URI5);
714277
715260
  if (disposed)
714278
715261
  return;
714279
715262
  if (options.graph.commentsHandle) {
@@ -714409,13 +715392,13 @@ function createHeadlessCollabRoomCoordinator(options) {
714409
715392
  const descriptorKind = part.partKind === "rels" ? SHARD_KIND.relationships : part.partKind === "contentTypes" ? SHARD_KIND.contentTypes : part.partKind === "styles" ? SHARD_KIND.styles : part.partKind === "numbering" ? SHARD_KIND.numbering : part.partKind === "settings" || part.partKind === "webSettings" ? SHARD_KIND.settings : isCommentsFamilyPartKind(part.partKind) ? SHARD_KIND.comments : part.partKind === "image" || part.partKind === "media" ? SHARD_KIND.mediaManifest : isOpaqueManifestPartKind(part.partKind) ? SHARD_KIND.opaquePart : null;
714410
715393
  if (!descriptorKind)
714411
715394
  return;
714412
- if (descriptorKind === SHARD_KIND.comments && part.partUri !== COMMENTS_PART_URI4)
715395
+ if (descriptorKind === SHARD_KIND.comments && part.partUri !== COMMENTS_PART_URI5)
714413
715396
  return;
714414
715397
  upsertShardDescriptor(options.rootDoc, makeShardDescriptor({
714415
715398
  rootId: options.rootId,
714416
715399
  shardKind: descriptorKind,
714417
- logicalOwner: descriptorKind === SHARD_KIND.comments ? COMMENTS_PART_URI4 : part.partKey,
714418
- logicalOwnerDisplay: descriptorKind === SHARD_KIND.comments ? COMMENTS_PART_URI4 : part.partUri,
715400
+ logicalOwner: descriptorKind === SHARD_KIND.comments ? COMMENTS_PART_URI5 : part.partKey,
715401
+ logicalOwnerDisplay: descriptorKind === SHARD_KIND.comments ? COMMENTS_PART_URI5 : part.partUri,
714419
715402
  loadPolicy: descriptorKind === SHARD_KIND.relationships || descriptorKind === SHARD_KIND.contentTypes || descriptorKind === SHARD_KIND.styles || descriptorKind === SHARD_KIND.numbering || descriptorKind === SHARD_KIND.settings || descriptorKind === SHARD_KIND.comments ? SHARD_LOAD_POLICY.eager : SHARD_LOAD_POLICY.lazy,
714420
715403
  requirement: descriptorKind === SHARD_KIND.relationships || descriptorKind === SHARD_KIND.contentTypes || descriptorKind === SHARD_KIND.styles || descriptorKind === SHARD_KIND.numbering || descriptorKind === SHARD_KIND.settings || descriptorKind === SHARD_KIND.comments ? SHARD_REQUIREMENT.required : SHARD_REQUIREMENT.optional,
714421
715404
  bootstrapStatus: SHARD_BOOTSTRAP_STATUS.seeded,
@@ -714550,8 +715533,36 @@ function createHeadlessCollabRoomCoordinator(options) {
714550
715533
  options.graph.requiredShardIds.delete(shardId);
714551
715534
  options.onRegistryChanged();
714552
715535
  }
715536
+ function retireStoryPart(partUri) {
715537
+ const partKey = encodeLogicalOwnerKey(partUri);
715538
+ const shardIds = new Set([...storyInfos.values()].filter((info) => info.partUri === partUri).map((info) => info.shardId));
715539
+ const snapshot3 = readRoomManifest(options.rootDoc).snapshot;
715540
+ for (const descriptor of snapshot3?.shards ?? []) {
715541
+ if (descriptor.shardKind === SHARD_KIND.story && descriptor.story?.sourcePartKey === partKey) {
715542
+ shardIds.add(descriptor.shardId);
715543
+ }
715544
+ }
715545
+ options.rootDoc.transact(() => {
715546
+ getPackagePartsMap(options.rootDoc).delete(partKey);
715547
+ for (const shardId of shardIds)
715548
+ deleteShardDescriptor(options.rootDoc, shardId);
715549
+ }, "headless:collab-v2:manifest-retire-story");
715550
+ for (const [storyId, info] of storyInfos) {
715551
+ if (info.partUri === partUri)
715552
+ storyInfos.delete(storyId);
715553
+ }
715554
+ for (const [storyId, handle] of options.graph.storyHandlesByStoryId) {
715555
+ if (shardIds.has(handle.shardId))
715556
+ options.graph.storyHandlesByStoryId.delete(storyId);
715557
+ }
715558
+ for (const shardId of shardIds) {
715559
+ options.graph.storyHandles.delete(shardId);
715560
+ options.graph.requiredShardIds.delete(shardId);
715561
+ }
715562
+ options.onRegistryChanged();
715563
+ }
714553
715564
  function retireCommentsFamilyPart(partUri) {
714554
- if (partUri === COMMENTS_PART_URI4 && options.graph.commentsHandle) {
715565
+ if (partUri === COMMENTS_PART_URI5 && options.graph.commentsHandle) {
714555
715566
  resetPackagePartPayload(collabUnitTargetOrDoc(options.graph.commentsHandle));
714556
715567
  options.graph.commentsHandle = null;
714557
715568
  }
@@ -714645,7 +715656,7 @@ function isMediaPartUri(partUri) {
714645
715656
  return /\/word\/media\/image\d+\.(?:png|jpe?g|jfif)$/i.test(partUri);
714646
715657
  }
714647
715658
  function isCommentsFamilyPartUri(partUri) {
714648
- return partUri === COMMENTS_PART_URI4 || partUri === COMMENTS_EXTENDED_PART_URI4 || partUri === COMMENTS_IDS_PART_URI4 || partUri === PEOPLE_PART_URI;
715659
+ return partUri === COMMENTS_PART_URI5 || partUri === COMMENTS_EXTENDED_PART_URI5 || partUri === COMMENTS_IDS_PART_URI5 || partUri === PEOPLE_PART_URI;
714649
715660
  }
714650
715661
  function isCommentsFamilyPartKind(partKind) {
714651
715662
  return partKind === "comments" || partKind === "comments-extended" || partKind === "comments-ids" || partKind === "people";
@@ -714670,11 +715681,11 @@ function partKindForPackagePartUri(partUri) {
714670
715681
  return "settings";
714671
715682
  if (partUri === WEB_SETTINGS_PART_URI)
714672
715683
  return "webSettings";
714673
- if (partUri === COMMENTS_PART_URI4)
715684
+ if (partUri === COMMENTS_PART_URI5)
714674
715685
  return "comments";
714675
- if (partUri === COMMENTS_EXTENDED_PART_URI4)
715686
+ if (partUri === COMMENTS_EXTENDED_PART_URI5)
714676
715687
  return "comments-extended";
714677
- if (partUri === COMMENTS_IDS_PART_URI4)
715688
+ if (partUri === COMMENTS_IDS_PART_URI5)
714678
715689
  return "comments-ids";
714679
715690
  if (partUri === PEOPLE_PART_URI)
714680
715691
  return "people";
@@ -714762,11 +715773,11 @@ function relTargetForPart(ownerPartUri2, targetPartUri) {
714762
715773
  function contentTypeForPackagePart(partUri) {
714763
715774
  if (partUri.endsWith(".rels"))
714764
715775
  return REL_CONTENT_TYPE;
714765
- if (partUri === COMMENTS_PART_URI4)
715776
+ if (partUri === COMMENTS_PART_URI5)
714766
715777
  return COMMENTS_CONTENT_TYPE;
714767
- if (partUri === COMMENTS_EXTENDED_PART_URI4)
715778
+ if (partUri === COMMENTS_EXTENDED_PART_URI5)
714768
715779
  return COMMENTS_EXTENDED_CONTENT_TYPE;
714769
- if (partUri === COMMENTS_IDS_PART_URI4)
715780
+ if (partUri === COMMENTS_IDS_PART_URI5)
714770
715781
  return COMMENTS_IDS_CONTENT_TYPE;
714771
715782
  if (partUri === PEOPLE_PART_URI)
714772
715783
  return PEOPLE_CONTENT_TYPE;
@@ -715398,7 +716409,7 @@ function listManifestPartUris(rootDoc, partKinds) {
715398
716409
  }
715399
716410
  return out;
715400
716411
  }
715401
- var TEXT_DECODER11, CONTENT_TYPES_PART_URI16 = "/[Content_Types].xml", NUMBERING_PART_URI6 = "/word/numbering.xml", SETTINGS_PART_URI5 = "/word/settings.xml", WEB_SETTINGS_PART_URI = "/word/webSettings.xml", MAIN_DOCUMENT_PART_URI2 = "/word/document.xml", MAIN_DOCUMENT_RELS_PART_URI = "/word/_rels/document.xml.rels", ROOT_RELS_PART_URI = "/_rels/.rels", COMMENTS_PART_URI4 = "/word/comments.xml", COMMENTS_EXTENDED_PART_URI4 = "/word/commentsExtended.xml", COMMENTS_IDS_PART_URI4 = "/word/commentsIds.xml", PEOPLE_PART_URI = "/word/people.xml", MEDIA_OWNER_URI = "/word/media", REL_CONTENT_TYPE = "application/vnd.openxmlformats-package.relationships+xml", COMMENTS_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml", COMMENTS_EXTENDED_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml", COMMENTS_IDS_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsIds+xml", PEOPLE_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.people+xml", NUMBERING_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", IMAGE_REL_TYPE4 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", HYPERLINK_REL_TYPE4 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", NUMBERING_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering", FIRST_LIST_LEVEL_OPAQUE_XML = '<w:lvlJc w:val="left"/><w:pPr><w:ind w:left="720" w:hanging="360"/></w:pPr>';
716412
+ var TEXT_DECODER11, CONTENT_TYPES_PART_URI16 = "/[Content_Types].xml", NUMBERING_PART_URI6 = "/word/numbering.xml", SETTINGS_PART_URI5 = "/word/settings.xml", WEB_SETTINGS_PART_URI = "/word/webSettings.xml", MAIN_DOCUMENT_PART_URI2 = "/word/document.xml", MAIN_DOCUMENT_RELS_PART_URI = "/word/_rels/document.xml.rels", ROOT_RELS_PART_URI = "/_rels/.rels", COMMENTS_PART_URI5 = "/word/comments.xml", COMMENTS_EXTENDED_PART_URI5 = "/word/commentsExtended.xml", COMMENTS_IDS_PART_URI5 = "/word/commentsIds.xml", PEOPLE_PART_URI = "/word/people.xml", MEDIA_OWNER_URI = "/word/media", REL_CONTENT_TYPE = "application/vnd.openxmlformats-package.relationships+xml", COMMENTS_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml", COMMENTS_EXTENDED_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml", COMMENTS_IDS_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsIds+xml", PEOPLE_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.people+xml", NUMBERING_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", IMAGE_REL_TYPE4 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", HYPERLINK_REL_TYPE4 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", NUMBERING_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering", FIRST_LIST_LEVEL_OPAQUE_XML = '<w:lvlJc w:val="left"/><w:pPr><w:ind w:left="720" w:hanging="360"/></w:pPr>';
715402
716413
  var init_collaboration_v2_room_coordinator = __esm(() => {
715403
716414
  init_yjs();
715404
716415
  init_dist9();
@@ -716291,7 +717302,7 @@ async function buildCanonicalShardGraph(input) {
716291
717302
  input.trace?.mark("canonical:settings");
716292
717303
  const commentsFamily = buildCommentsFamily(roomInventory);
716293
717304
  let commentsHandle = null;
716294
- const commentsShardId = packageShardId2(input.runtime.rootId, SHARD_KIND.comments, COMMENTS_PART_URI5);
717305
+ const commentsShardId = packageShardId2(input.runtime.rootId, SHARD_KIND.comments, COMMENTS_PART_URI6);
716295
717306
  {
716296
717307
  const unit = createCollabUnitHandle({ rootDoc, shardId: commentsShardId, shardKind: SHARD_KIND.comments });
716297
717308
  if (commentsFamily != null) {
@@ -716408,7 +717419,7 @@ function buildSettingsFamily(inventory) {
716408
717419
  return { settings, webSettings };
716409
717420
  }
716410
717421
  function buildCommentsFamily(inventory) {
716411
- const family = [COMMENTS_PART_URI5, COMMENTS_EXTENDED_PART_URI5, COMMENTS_IDS_PART_URI5, PEOPLE_PART_URI2].map((partUri) => inventory.get(partUri)).filter(Boolean);
717422
+ const family = [COMMENTS_PART_URI6, COMMENTS_EXTENDED_PART_URI6, COMMENTS_IDS_PART_URI6, PEOPLE_PART_URI2].map((partUri) => inventory.get(partUri)).filter(Boolean);
716412
717423
  if (family.length === 0)
716413
717424
  return null;
716414
717425
  return {
@@ -716771,8 +717782,8 @@ function trySeedCommentsShard(doc2, shardId, catalog, pairedPartKeys, sourcePart
716771
717782
  seedCommentsShard({
716772
717783
  doc: doc2,
716773
717784
  shardId,
716774
- ownerPartKey: encodeLogicalOwnerKey(COMMENTS_PART_URI5),
716775
- ownerPartUri: COMMENTS_PART_URI5,
717785
+ ownerPartKey: encodeLogicalOwnerKey(COMMENTS_PART_URI6),
717786
+ ownerPartUri: COMMENTS_PART_URI6,
716776
717787
  pairedPartKeys,
716777
717788
  comments,
716778
717789
  people: [],
@@ -716788,8 +717799,8 @@ function trySeedEmptyCommentsShard(doc2, shardId) {
716788
717799
  seedCommentsShard({
716789
717800
  doc: doc2,
716790
717801
  shardId,
716791
- ownerPartKey: encodeLogicalOwnerKey(COMMENTS_PART_URI5),
716792
- ownerPartUri: COMMENTS_PART_URI5,
717802
+ ownerPartKey: encodeLogicalOwnerKey(COMMENTS_PART_URI6),
717803
+ ownerPartUri: COMMENTS_PART_URI6,
716793
717804
  pairedPartKeys: [],
716794
717805
  comments: [],
716795
717806
  people: []
@@ -717032,7 +718043,7 @@ function formatLateJoinValidationFailure(validation) {
717032
718043
  const diagnostics = validation.diagnostics.length > 0 ? validation.diagnostics.map((diagnostic2) => `${diagnostic2.code}: ${diagnostic2.message}`).join("; ") : "no diagnostics reported";
717033
718044
  return `v2 collaboration late-join validation failed (${validation.classification.classification}, ${readiness}): ${diagnostics}`;
717034
718045
  }
717035
- var TEXT_DECODER12, DEFAULT_CLAIMER_ID = "headless-open", REPLACEMENT_REQUEST_KEY_PREFIX = "replaceFile:", REPLACEMENT_HEARTBEAT_INTERVAL_MS = 5000, REPLACEMENT_LEASE_TIMEOUT_MS = 30000, SETTINGS_PART_URI6 = "/word/settings.xml", WEB_SETTINGS_PART_URI2 = "/word/webSettings.xml", COMMENTS_PART_URI5 = "/word/comments.xml", COMMENTS_EXTENDED_PART_URI5 = "/word/commentsExtended.xml", COMMENTS_IDS_PART_URI5 = "/word/commentsIds.xml", PEOPLE_PART_URI2 = "/word/people.xml", MEDIA_OWNER_URI2 = "/word/media", INLINE_BINARY_FAMILIES, OPAQUE_PART_FAMILIES, DEFAULT_OPEN_INTENT, POST_SYNC_SETTLE_MAX_MS = 1000, POST_SYNC_QUIET_WINDOW_MS = 20, replacementSequence = 0, replacementHeartbeatObservations;
718046
+ var TEXT_DECODER12, DEFAULT_CLAIMER_ID = "headless-open", REPLACEMENT_REQUEST_KEY_PREFIX = "replaceFile:", REPLACEMENT_HEARTBEAT_INTERVAL_MS = 5000, REPLACEMENT_LEASE_TIMEOUT_MS = 30000, SETTINGS_PART_URI6 = "/word/settings.xml", WEB_SETTINGS_PART_URI2 = "/word/webSettings.xml", COMMENTS_PART_URI6 = "/word/comments.xml", COMMENTS_EXTENDED_PART_URI6 = "/word/commentsExtended.xml", COMMENTS_IDS_PART_URI6 = "/word/commentsIds.xml", PEOPLE_PART_URI2 = "/word/people.xml", MEDIA_OWNER_URI2 = "/word/media", INLINE_BINARY_FAMILIES, OPAQUE_PART_FAMILIES, DEFAULT_OPEN_INTENT, POST_SYNC_SETTLE_MAX_MS = 1000, POST_SYNC_QUIET_WINDOW_MS = 20, replacementSequence = 0, replacementHeartbeatObservations;
717036
718047
  var init_collaboration_v2_open = __esm(() => {
717037
718048
  init_dist9();
717038
718049
  init_setup();