@beyondwork/docx-react-component 1.0.121 → 1.0.123

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 (102) hide show
  1. package/dist/api/public-types.cjs +318 -32
  2. package/dist/api/public-types.d.cts +2 -2
  3. package/dist/api/public-types.d.ts +2 -2
  4. package/dist/api/public-types.js +3 -3
  5. package/dist/api/v3.cjs +349 -62
  6. package/dist/api/v3.d.cts +3 -3
  7. package/dist/api/v3.d.ts +3 -3
  8. package/dist/api/v3.js +10 -10
  9. package/dist/{canonical-document-ByIqTd4s.d.cts → canonical-document-CG2TgAzj.d.cts} +1 -1
  10. package/dist/{canonical-document-ByIqTd4s.d.ts → canonical-document-CG2TgAzj.d.ts} +1 -1
  11. package/dist/{chunk-B4YHWFE3.js → chunk-32ZAOQ54.js} +1 -1
  12. package/dist/{chunk-QNGJRZ2D.js → chunk-4IPEZYQX.js} +1 -1
  13. package/dist/{chunk-3OFSP2IX.js → chunk-BOHHIVQ2.js} +3 -3
  14. package/dist/{chunk-EMDH4IQN.js → chunk-E5IBDE5E.js} +4 -3
  15. package/dist/{chunk-TFSXOIAI.js → chunk-FNWKE74J.js} +43 -3
  16. package/dist/{chunk-IT2DK3A7.js → chunk-H2YQKA55.js} +9 -7
  17. package/dist/{chunk-3TUQCHYT.js → chunk-H6IL5ABU.js} +47 -7
  18. package/dist/{chunk-GON2DNTE.js → chunk-HXHQA4BU.js} +1 -1
  19. package/dist/{chunk-3OHVK2D6.js → chunk-IR7QV2BX.js} +17 -1
  20. package/dist/{chunk-ZKSDVHGH.js → chunk-KOHQFZMM.js} +1 -1
  21. package/dist/{chunk-XVFENXLK.js → chunk-LGWNN3L2.js} +2 -2
  22. package/dist/{chunk-TMU7JMXX.js → chunk-MB7RJBSN.js} +9 -21
  23. package/dist/{chunk-UWDWGQH5.js → chunk-ML4A4WUN.js} +1 -1
  24. package/dist/{chunk-GZW2ERUO.js → chunk-N4VIXI2Z.js} +3 -3
  25. package/dist/{chunk-S4ANOS2M.js → chunk-NNPVA5VL.js} +2 -2
  26. package/dist/{chunk-QFU7ZOAD.js → chunk-PFYUJU3Q.js} +176 -36
  27. package/dist/{chunk-37SEJQ3G.js → chunk-RSYN6FTS.js} +2 -2
  28. package/dist/{chunk-OBCP6VTG.js → chunk-RWERZWHR.js} +1 -1
  29. package/dist/{chunk-UHQOUTAX.js → chunk-SGSJ4DQA.js} +377 -50
  30. package/dist/{chunk-PCXTMEGY.js → chunk-UHJLCPLU.js} +24 -14
  31. package/dist/{chunk-G3B2OBCZ.js → chunk-ZRHLLPSJ.js} +271 -26
  32. package/dist/compare.d.cts +1 -1
  33. package/dist/compare.d.ts +1 -1
  34. package/dist/core/commands/formatting-commands.d.cts +2 -2
  35. package/dist/core/commands/formatting-commands.d.ts +2 -2
  36. package/dist/core/commands/image-commands.cjs +50 -9
  37. package/dist/core/commands/image-commands.d.cts +2 -2
  38. package/dist/core/commands/image-commands.d.ts +2 -2
  39. package/dist/core/commands/image-commands.js +5 -5
  40. package/dist/core/commands/section-layout-commands.d.cts +2 -2
  41. package/dist/core/commands/section-layout-commands.d.ts +2 -2
  42. package/dist/core/commands/style-commands.d.cts +2 -2
  43. package/dist/core/commands/style-commands.d.ts +2 -2
  44. package/dist/core/commands/table-structure-commands.cjs +50 -9
  45. package/dist/core/commands/table-structure-commands.d.cts +2 -2
  46. package/dist/core/commands/table-structure-commands.d.ts +2 -2
  47. package/dist/core/commands/table-structure-commands.js +4 -4
  48. package/dist/core/commands/text-commands.cjs +66 -9
  49. package/dist/core/commands/text-commands.d.cts +3 -2
  50. package/dist/core/commands/text-commands.d.ts +3 -2
  51. package/dist/core/commands/text-commands.js +5 -5
  52. package/dist/core/selection/mapping.d.cts +2 -2
  53. package/dist/core/selection/mapping.d.ts +2 -2
  54. package/dist/core/state/editor-state.d.cts +2 -2
  55. package/dist/core/state/editor-state.d.ts +2 -2
  56. package/dist/index.cjs +1196 -197
  57. package/dist/index.d.cts +5 -5
  58. package/dist/index.d.ts +5 -5
  59. package/dist/index.js +278 -85
  60. package/dist/io/docx-session.cjs +10 -21
  61. package/dist/io/docx-session.d.cts +4 -4
  62. package/dist/io/docx-session.d.ts +4 -4
  63. package/dist/io/docx-session.js +4 -4
  64. package/dist/legal.cjs +8 -20
  65. package/dist/legal.d.cts +1 -1
  66. package/dist/legal.d.ts +1 -1
  67. package/dist/legal.js +3 -3
  68. package/dist/{loader-BF8ju_LK.d.ts → loader-D9KCtj4m.d.cts} +4 -22
  69. package/dist/{loader-g54WRvj1.d.cts → loader-D9y4ZRjj.d.ts} +4 -22
  70. package/dist/{public-types-Dl1jiWjk.d.ts → public-types-CNnMHZM9.d.ts} +263 -213
  71. package/dist/{public-types-D_y4Ptcj.d.cts → public-types-DajNGKV4.d.cts} +263 -213
  72. package/dist/public-types.cjs +318 -32
  73. package/dist/public-types.d.cts +2 -2
  74. package/dist/public-types.d.ts +2 -2
  75. package/dist/public-types.js +3 -3
  76. package/dist/runtime/collab.d.cts +3 -3
  77. package/dist/runtime/collab.d.ts +3 -3
  78. package/dist/runtime/document-runtime.cjs +752 -77
  79. package/dist/runtime/document-runtime.d.cts +2 -2
  80. package/dist/runtime/document-runtime.d.ts +2 -2
  81. package/dist/runtime/document-runtime.js +14 -14
  82. package/dist/{session-C1EPAkcI.d.ts → session-DEmaOEjA.d.ts} +3 -3
  83. package/dist/{session-D15QOO0Q.d.cts → session-DyQGlryH.d.cts} +3 -3
  84. package/dist/session.cjs +12 -618
  85. package/dist/session.d.cts +5 -5
  86. package/dist/session.d.ts +5 -5
  87. package/dist/session.js +7 -9
  88. package/dist/tailwind.cjs +489 -63
  89. package/dist/tailwind.d.cts +2 -2
  90. package/dist/tailwind.d.ts +2 -2
  91. package/dist/tailwind.js +7 -7
  92. package/dist/{types-BoSRp2Vg.d.cts → types-CxE1aZiv.d.cts} +2 -2
  93. package/dist/{types-DEvRwq9C.d.ts → types-DjJNaE9c.d.ts} +2 -2
  94. package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +3 -3
  95. package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +3 -3
  96. package/dist/ui-tailwind/editor-surface/search-plugin.js +4 -4
  97. package/dist/ui-tailwind/theme/tokens.css +387 -0
  98. package/dist/ui-tailwind.cjs +489 -63
  99. package/dist/ui-tailwind.d.cts +3 -3
  100. package/dist/ui-tailwind.d.ts +3 -3
  101. package/dist/ui-tailwind.js +7 -7
  102. package/package.json +7 -3
@@ -4885,6 +4885,28 @@ function collectEditableTargetRefs(doc, cache) {
4885
4885
  collectReviewEditableTargets(doc, targets);
4886
4886
  return targets;
4887
4887
  }
4888
+ function collectEditableTargetRefsForStoryBlockRanges(doc, storyKey2, ranges, cache) {
4889
+ const targets = [];
4890
+ const context = collectStoryBlockContexts(doc).find((entry) => entry.storyKey === storyKey2);
4891
+ if (!context) return targets;
4892
+ const normalized = normalizeEditableTargetRanges(ranges, context.blocks.length);
4893
+ for (const range of normalized) {
4894
+ collectEditableTargetsInBlocks(
4895
+ context.blocks.slice(range.start, range.end),
4896
+ {
4897
+ storyKey: context.storyKey,
4898
+ basePath: context.basePath,
4899
+ insideSdt: false,
4900
+ insideTextBox: false,
4901
+ tableDepth: 0
4902
+ },
4903
+ targets,
4904
+ cache,
4905
+ range.start
4906
+ );
4907
+ }
4908
+ return targets;
4909
+ }
4888
4910
  function createEditableTargetBlockCache() {
4889
4911
  const map = /* @__PURE__ */ new WeakMap();
4890
4912
  return {
@@ -4920,12 +4942,13 @@ function buildBlockCacheSignature(context, blockIndex) {
4920
4942
  owner?.targetKey ?? ""
4921
4943
  ].join("|");
4922
4944
  }
4923
- function collectEditableTargetsInBlocks(blocks, context, targets, cache) {
4945
+ function collectEditableTargetsInBlocks(blocks, context, targets, cache, blockIndexOffset = 0) {
4924
4946
  for (let blockIndex = 0; blockIndex < blocks.length; blockIndex += 1) {
4925
4947
  const block = blocks[blockIndex];
4926
4948
  if (!block) continue;
4927
- const blockPath = `${context.basePath}/block[${blockIndex}]`;
4928
- const signature = cache !== void 0 ? buildBlockCacheSignature(context, blockIndex) : "";
4949
+ const absoluteBlockIndex = blockIndex + blockIndexOffset;
4950
+ const blockPath = `${context.basePath}/block[${absoluteBlockIndex}]`;
4951
+ const signature = cache !== void 0 ? buildBlockCacheSignature(context, absoluteBlockIndex) : "";
4929
4952
  if (cache !== void 0) {
4930
4953
  const cached = cache.get(block);
4931
4954
  if (cached !== void 0 && cached.blockPath === blockPath && cached.signature === signature) {
@@ -5109,6 +5132,22 @@ function collectEditableTargetsInTable(table, tablePath, context, targets, cache
5109
5132
  }
5110
5133
  }
5111
5134
  }
5135
+ function normalizeEditableTargetRanges(ranges, blockCount) {
5136
+ const normalized = [];
5137
+ const sortedRanges = [...ranges].sort((left, right) => left.start - right.start || left.end - right.end);
5138
+ for (const range of sortedRanges) {
5139
+ const start = Math.max(0, Math.min(blockCount, Math.floor(range.start)));
5140
+ const end = Math.max(start, Math.min(blockCount, Math.ceil(range.end)));
5141
+ if (start === end) continue;
5142
+ const previous = normalized[normalized.length - 1];
5143
+ if (previous && start <= previous.end) {
5144
+ previous.end = Math.max(previous.end, end);
5145
+ } else {
5146
+ normalized.push({ start, end });
5147
+ }
5148
+ }
5149
+ return normalized;
5150
+ }
5112
5151
  function findVerticalMergeOwner(owners, gridColumnStart2, gridSpan) {
5113
5152
  return owners.find(
5114
5153
  (owner) => owner.gridColumnStart === gridColumnStart2 && owner.gridSpan === gridSpan
@@ -11061,6 +11100,8 @@ function createSurfaceBlock(block, document2, cursor, counters, formattingContex
11061
11100
  formattingContext,
11062
11101
  promoteSecondaryStoryTextBoxes,
11063
11102
  cullBuild,
11103
+ editableTargetsByBlockPath,
11104
+ blockPath,
11064
11105
  blockPath !== void 0 ? editableTargetsByBlockPath.get(blockPath) : void 0
11065
11106
  );
11066
11107
  }
@@ -11467,7 +11508,7 @@ function getRecursableSdtBlockedReasonCode(block) {
11467
11508
  ].filter(Boolean).join(" ").toLowerCase();
11468
11509
  return searchText.includes("table of contents") || /\btoc\b/u.test(searchText) ? "workflow_preserve_only" : null;
11469
11510
  }
11470
- function createParagraphBlock(paragraphIndex, paragraph, document2, start, formattingContext, promoteSecondaryStoryTextBoxes, cullBuild = false, editableTarget) {
11511
+ function createParagraphBlock(paragraphIndex, paragraph, document2, start, formattingContext, promoteSecondaryStoryTextBoxes, cullBuild = false, editableTargetsByBlockPath = EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH, blockPath, editableTarget) {
11471
11512
  const themeResolver = formattingContext.theme;
11472
11513
  const effectiveNumbering = formattingContext.resolveEffectiveParagraphNumbering(paragraph);
11473
11514
  let resolvedNumbering = null;
@@ -11532,6 +11573,8 @@ function createParagraphBlock(paragraphIndex, paragraph, document2, start, forma
11532
11573
  document2,
11533
11574
  cursor,
11534
11575
  promoteSecondaryStoryTextBoxes,
11576
+ blockPath !== void 0 ? `${blockPath}/inline[${childIndex}]` : void 0,
11577
+ editableTargetsByBlockPath,
11535
11578
  void 0,
11536
11579
  cullBuild,
11537
11580
  themeResolver,
@@ -11588,7 +11631,7 @@ function isVisibleTocResultInline(node) {
11588
11631
  return false;
11589
11632
  }
11590
11633
  }
11591
- function appendInlineSegments(paragraph, node, document2, start, promoteSecondaryStoryTextBoxes, hyperlinkHref, cullBuild = false, themeResolver, formattingContext) {
11634
+ function appendInlineSegments(paragraph, node, document2, start, promoteSecondaryStoryTextBoxes, inlinePath, editableTargetsByBlockPath = EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH, hyperlinkHref, cullBuild = false, themeResolver, formattingContext) {
11592
11635
  switch (node.type) {
11593
11636
  case "text": {
11594
11637
  const cloned = node.marks ? cloneMarks2(node.marks) : { marks: [] };
@@ -11641,13 +11684,16 @@ function appendInlineSegments(paragraph, node, document2, start, promoteSecondar
11641
11684
  return { nextCursor: start + 1, lockedFragmentIds: [] };
11642
11685
  case "hyperlink": {
11643
11686
  let cursor = start;
11644
- for (const child of node.children) {
11687
+ for (let childIndex = 0; childIndex < node.children.length; childIndex += 1) {
11688
+ const child = node.children[childIndex];
11645
11689
  const result = appendInlineSegments(
11646
11690
  paragraph,
11647
11691
  child,
11648
11692
  document2,
11649
11693
  cursor,
11650
11694
  promoteSecondaryStoryTextBoxes,
11695
+ inlinePath !== void 0 ? `${inlinePath}/child[${childIndex}]` : void 0,
11696
+ editableTargetsByBlockPath,
11651
11697
  node.href,
11652
11698
  cullBuild,
11653
11699
  themeResolver,
@@ -11706,6 +11752,33 @@ function appendInlineSegments(paragraph, node, document2, start, promoteSecondar
11706
11752
  if (isMicrosoftSensitivityLabelShape(node)) {
11707
11753
  return { nextCursor: start + 1, lockedFragmentIds: [] };
11708
11754
  }
11755
+ if (node.isTextBox && node.txbxBlocks !== void 0) {
11756
+ const txbxTextSegment = extractTxbxFirstTextSegment(node.txbxBlocks);
11757
+ const txbxText = txbxTextSegment?.text ?? node.text;
11758
+ const txbxBody = surfaceTextBoxBodyFromShape(
11759
+ node,
11760
+ void 0,
11761
+ inlinePath,
11762
+ editableTargetsByBlockPath
11763
+ );
11764
+ paragraph.segments.push({
11765
+ segmentId: `${paragraph.blockId}-segment-${paragraph.segments.length}`,
11766
+ kind: "shape",
11767
+ from: start,
11768
+ to: start + 1,
11769
+ label: "Text box",
11770
+ detail: createShapeDetail(node),
11771
+ ...node.geometry !== void 0 ? { geometry: node.geometry } : {},
11772
+ isTextBox: true,
11773
+ ...node.textBoxBody ? { textBoxBody: node.textBoxBody } : {},
11774
+ ...node.preserveOnlyObject ? { preserveOnlyObject: surfacePreserveOnlyObject(node.preserveOnlyObject) } : {},
11775
+ ...txbxText ? { txbxText } : {},
11776
+ ...txbxBody ? { txbxBody } : {},
11777
+ ...txbxTextSegment?.marks && txbxTextSegment.marks.length > 0 ? { txbxMarks: txbxTextSegment.marks } : {},
11778
+ ...txbxTextSegment?.markAttrs ? { txbxMarkAttrs: txbxTextSegment.markAttrs } : {}
11779
+ });
11780
+ return { nextCursor: start + 1, lockedFragmentIds: [] };
11781
+ }
11709
11782
  if (promoteSecondaryStoryTextBoxes && node.isTextBox && node.text) {
11710
11783
  return appendTextBoxSegment(
11711
11784
  paragraph,
@@ -11765,7 +11838,7 @@ function appendInlineSegments(paragraph, node, document2, start, promoteSecondar
11765
11838
  const anchor = surfaceAnchorFromGeometry(node.anchor);
11766
11839
  const txbxTextSegment = c.isTextBox ? extractTxbxFirstTextSegment(c.txbxBlocks) : void 0;
11767
11840
  const txbxText = txbxTextSegment?.text ?? (c.isTextBox ? c.text : void 0);
11768
- const txbxBody = c.isTextBox ? surfaceTextBoxBodyFromShape(c, node.sourceRef) : void 0;
11841
+ const txbxBody = c.isTextBox ? surfaceTextBoxBodyFromShape(c, node.sourceRef, inlinePath, editableTargetsByBlockPath) : void 0;
11769
11842
  const surfaceFill = c.fill;
11770
11843
  paragraph.segments.push({
11771
11844
  segmentId: `${paragraph.blockId}-segment-${paragraph.segments.length}`,
@@ -11942,13 +12015,16 @@ function appendInlineSegments(paragraph, node, document2, start, promoteSecondar
11942
12015
  const refHyperlinkHref = (node.fieldFamily === "REF" || node.fieldFamily === "PAGEREF" || node.fieldFamily === "NOTEREF") && node.switches?.hyperlink === true && node.fieldTarget ? `#${node.fieldTarget}` : void 0;
11943
12016
  let cursor = start;
11944
12017
  const lockedIds = [];
11945
- for (const child of node.children) {
12018
+ for (let childIndex = 0; childIndex < node.children.length; childIndex += 1) {
12019
+ const child = node.children[childIndex];
11946
12020
  const result = appendInlineSegments(
11947
12021
  paragraph,
11948
12022
  child,
11949
12023
  document2,
11950
12024
  cursor,
11951
12025
  promoteSecondaryStoryTextBoxes,
12026
+ inlinePath !== void 0 ? `${inlinePath}/child[${childIndex}]` : void 0,
12027
+ editableTargetsByBlockPath,
11952
12028
  refHyperlinkHref ?? hyperlinkHref,
11953
12029
  cullBuild,
11954
12030
  themeResolver,
@@ -12195,7 +12271,7 @@ function extractTxbxFirstTextSegment(blocks) {
12195
12271
  }
12196
12272
  return void 0;
12197
12273
  }
12198
- function surfaceTextBoxBodyFromShape(shape, sourceRef) {
12274
+ function surfaceTextBoxBodyFromShape(shape, sourceRef, inlinePath, editableTargetsByBlockPath = EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH) {
12199
12275
  if (!shape.isTextBox && shape.txbxContentXml === void 0 && shape.txbxBlocks === void 0) {
12200
12276
  return void 0;
12201
12277
  }
@@ -12221,9 +12297,12 @@ function surfaceTextBoxBodyFromShape(shape, sourceRef) {
12221
12297
  (run, inlineIndex) => surfaceTextBoxRunFromLegacyRun(run, inlineIndex)
12222
12298
  ) ?? [];
12223
12299
  const text = runs.map((run) => run.text ?? "").join("");
12300
+ const blockPath = inlinePath !== void 0 ? `${inlinePath}/txbx/block[${blockIndex}]` : void 0;
12301
+ const editableTarget = blockPath !== void 0 ? editableTargetsByBlockPath.get(blockPath) : void 0;
12224
12302
  return [{
12225
12303
  ...block.sourceRef !== void 0 ? { sourceRef: block.sourceRef } : {},
12226
12304
  blockIndex,
12305
+ ...editableTarget !== void 0 ? { editableTarget } : {},
12227
12306
  text,
12228
12307
  textLength: Array.from(text).length,
12229
12308
  ...block.borders !== void 0 ? { borders: block.borders } : {},
@@ -12919,6 +12998,7 @@ function applyLinearTextTransaction(document2, selection, intent, options) {
12919
12998
  metadata: {
12920
12999
  affectsComments: true,
12921
13000
  affectsRevisions: true,
13001
+ ...createLocalTextPatchMetadata(story.units, unitFrom, unitTo, insertionUnits),
12922
13002
  ...containsParagraphBoundaryChange(story, normalizedRange, insertionUnits) ? { invalidatesStructures: true } : {}
12923
13003
  }
12924
13004
  },
@@ -12986,6 +13066,21 @@ function tryApplyTableParagraphTransaction(document2, selection, intent, options
12986
13066
  storyText: localResult.storyText
12987
13067
  };
12988
13068
  }
13069
+ function createLocalTextPatchMetadata(units, unitFrom, unitTo, insertionUnits) {
13070
+ if (!insertionUnits.every((unit) => unit.kind === "text")) {
13071
+ return {};
13072
+ }
13073
+ for (let index = unitFrom; index < unitTo; index += 1) {
13074
+ if (units[index]?.kind !== "text") {
13075
+ return {};
13076
+ }
13077
+ }
13078
+ return {
13079
+ localTextPatch: {
13080
+ insertedText: insertionUnits.map((unit) => unit.kind === "text" ? unit.value : "").join("")
13081
+ }
13082
+ };
13083
+ }
12989
13084
  function tryApplyTargetedTextLeafTransaction(document2, selection, intent, options) {
12990
13085
  const scope = resolveTargetedTextLeafScope(document2, selection, options.textTarget);
12991
13086
  if (!scope) {
@@ -19703,8 +19798,8 @@ function isNodeSelectableSegment(segment) {
19703
19798
  }
19704
19799
 
19705
19800
  // src/runtime/edit-ops/index.ts
19706
- function validateResult(result) {
19707
- const maxOffset = result.storyText.length;
19801
+ function validateResult(result, context) {
19802
+ const maxOffset = getPostMutationMaxOffset(result, context);
19708
19803
  const options = result.selection.activeRange.kind === "node" ? {
19709
19804
  isValidNodeTarget: createSurfaceNodeSelectionProbe(
19710
19805
  createEditorSurfaceSnapshot(result.document, result.selection)
@@ -19721,24 +19816,34 @@ function validateResult(result) {
19721
19816
  }
19722
19817
  return { ...result, selection: validated };
19723
19818
  }
19819
+ function getPostMutationMaxOffset(result, context) {
19820
+ if (typeof context.activeStorySize !== "number" || context.textTarget?.kind === "text-leaf") {
19821
+ return result.storyText.length;
19822
+ }
19823
+ let storySize = context.activeStorySize;
19824
+ for (const step of result.mapping.steps) {
19825
+ storySize += step.insertSize - Math.max(0, step.to - step.from);
19826
+ }
19827
+ return Math.max(result.storyText.length, storySize);
19828
+ }
19724
19829
  var editLayer = {
19725
19830
  applyTextInsert(doc, selection, text, context, formatting) {
19726
- return validateResult(insertText(doc, selection, text, context, formatting));
19831
+ return validateResult(insertText(doc, selection, text, context, formatting), context);
19727
19832
  },
19728
19833
  applyDeleteBackward(doc, selection, context) {
19729
- return validateResult(deleteSelectionOrBackward(doc, selection, context));
19834
+ return validateResult(deleteSelectionOrBackward(doc, selection, context), context);
19730
19835
  },
19731
19836
  applyDeleteForward(doc, selection, context) {
19732
- return validateResult(deleteSelectionOrForward(doc, selection, context));
19837
+ return validateResult(deleteSelectionOrForward(doc, selection, context), context);
19733
19838
  },
19734
19839
  applyInsertTab(doc, selection, context) {
19735
- return validateResult(insertTab(doc, selection, context));
19840
+ return validateResult(insertTab(doc, selection, context), context);
19736
19841
  },
19737
19842
  applyInsertHardBreak(doc, selection, context) {
19738
- return validateResult(insertHardBreak(doc, selection, context));
19843
+ return validateResult(insertHardBreak(doc, selection, context), context);
19739
19844
  },
19740
19845
  applySplitParagraph(doc, selection, context) {
19741
- return validateResult(splitParagraph(doc, selection, context));
19846
+ return validateResult(splitParagraph(doc, selection, context), context);
19742
19847
  }
19743
19848
  };
19744
19849
 
@@ -36068,7 +36173,7 @@ function deriveScopeEditableTargetEvidence(document2, scope, entry, options = {}
36068
36173
  facts.push(projectWorkflowBlockerFact(fact));
36069
36174
  factsByTargetKey.set(fact.targetKey, facts);
36070
36175
  }
36071
- const entries = collectEditableTargetRefs(document2).map((target) => {
36176
+ const entries = collectEditableTargetRefs(document2, options.editableTargetCache).map((target) => {
36072
36177
  const relation = relationForTarget(target, scope, entry);
36073
36178
  if (!relation) return null;
36074
36179
  const workflowBlockers = Object.freeze(
@@ -37047,7 +37152,8 @@ function composeEvidence(inputs) {
37047
37152
  scope,
37048
37153
  entry,
37049
37154
  {
37050
- ...inputs.editableTargetBlockerFacts ? { workflowBlockerFacts: inputs.editableTargetBlockerFacts } : {}
37155
+ ...inputs.editableTargetBlockerFacts ? { workflowBlockerFacts: inputs.editableTargetBlockerFacts } : {},
37156
+ ...inputs.editableTargetCache ? { editableTargetCache: inputs.editableTargetCache } : {}
37051
37157
  }
37052
37158
  ) : void 0;
37053
37159
  const contentControls = deriveScopeContentControlEvidence(document2, selfRange);
@@ -37136,7 +37242,8 @@ function compileScopeBundle(scope, inputs) {
37136
37242
  ...inputs.layout ? { layout: inputs.layout } : {},
37137
37243
  ...inputs.adjacentGeometry ? { adjacentGeometry: inputs.adjacentGeometry } : {},
37138
37244
  ...inputs.tableCellTextRange ? { tableCellTextRange: inputs.tableCellTextRange } : {},
37139
- ...inputs.editableTargetBlockerFacts ? { editableTargetBlockerFacts: inputs.editableTargetBlockerFacts } : {}
37245
+ ...inputs.editableTargetBlockerFacts ? { editableTargetBlockerFacts: inputs.editableTargetBlockerFacts } : {},
37246
+ ...inputs.editableTargetCache ? { editableTargetCache: inputs.editableTargetCache } : {}
37140
37247
  });
37141
37248
  return {
37142
37249
  scope,
@@ -38372,7 +38479,7 @@ function createScopeCompilerService(runtime) {
38372
38479
  const interactionGuard = runtime.getInteractionGuardSnapshot?.();
38373
38480
  const activeStory = runtime.getActiveStory?.();
38374
38481
  const editableTargetBlockerFacts = deriveWorkflowEditableTargetBlockerFacts({
38375
- targets: collectEditableTargetRefs(document2),
38482
+ targets: collectEditableTargetRefs(document2, runtime.getEditableTargetCache?.()),
38376
38483
  ...interactionGuard ? { guard: interactionGuard } : {},
38377
38484
  ...runtime.getProtectionSnapshot ? { protectionSnapshot: runtime.getProtectionSnapshot() } : {},
38378
38485
  ...activeStory ? { activeStoryKey: storyKeyForEditableTarget(activeStory) } : {}
@@ -38383,6 +38490,7 @@ function createScopeCompilerService(runtime) {
38383
38490
  runtime.getRenderSnapshot?.()
38384
38491
  )
38385
38492
  }) : void 0;
38493
+ const editableTargetCache = runtime.getEditableTargetCache?.();
38386
38494
  return compileScopeBundleById(scopeId, {
38387
38495
  document: document2,
38388
38496
  ...overlay ? { overlay } : {},
@@ -38392,7 +38500,8 @@ function createScopeCompilerService(runtime) {
38392
38500
  editableTargetBlockerFacts,
38393
38501
  ...runtime.geometry ? { geometry: runtime.geometry } : {},
38394
38502
  ...layout ? { layout } : {},
38395
- tableCellTextRange
38503
+ tableCellTextRange,
38504
+ ...editableTargetCache ? { editableTargetCache } : {}
38396
38505
  });
38397
38506
  },
38398
38507
  buildReplacementScope(targetHandle, input) {
@@ -42145,6 +42254,7 @@ function buildPageGraph(inputOrPages, sectionsArg, storiesArg) {
42145
42254
  regions,
42146
42255
  divergences: frameDivergences,
42147
42256
  subParts: input.subParts,
42257
+ anchors: input.anchors,
42148
42258
  pageFieldCounts
42149
42259
  });
42150
42260
  const divergences = builtFrame.divergences;
@@ -42311,6 +42421,7 @@ function buildPageFrame(input) {
42311
42421
  stories: input.stories,
42312
42422
  regions,
42313
42423
  subParts: input.subParts,
42424
+ anchors: input.anchors,
42314
42425
  pageFieldCounts: input.pageFieldCounts
42315
42426
  });
42316
42427
  const divergences = [...input.divergences, ...pageLocalStoryResult.divergences];
@@ -42348,6 +42459,7 @@ function buildPageLocalStoryInstances(input) {
42348
42459
  input.stories.header,
42349
42460
  input.regions.header,
42350
42461
  findHeaderFooterPart(input.subParts?.headers, input.stories.header),
42462
+ input.anchors,
42351
42463
  input.pageFieldCounts
42352
42464
  );
42353
42465
  instances.push(built.instance);
@@ -42364,6 +42476,7 @@ function buildPageLocalStoryInstances(input) {
42364
42476
  input.stories.footer,
42365
42477
  input.regions.footer,
42366
42478
  findHeaderFooterPart(input.subParts?.footers, input.stories.footer),
42479
+ input.anchors,
42367
42480
  input.pageFieldCounts
42368
42481
  );
42369
42482
  instances.push(built.instance);
@@ -42371,7 +42484,7 @@ function buildPageLocalStoryInstances(input) {
42371
42484
  }
42372
42485
  return { instances, divergences };
42373
42486
  }
42374
- function buildPageLocalStoryInstance(frameId, pageId, pageIndex, sectionIndex, displayPageNumber, layout, target, region, source, pageFieldCounts) {
42487
+ function buildPageLocalStoryInstance(frameId, pageId, pageIndex, sectionIndex, displayPageNumber, layout, target, region, source, anchors, pageFieldCounts) {
42375
42488
  const measuredFrameHeightTwips = region?.heightTwips ?? 0;
42376
42489
  const sectionPart = target.sectionIndex === void 0 ? "section-unknown" : `section-${target.sectionIndex}`;
42377
42490
  const instanceId = `${frameId}:${target.kind}:${target.variant}:${target.relationshipId}`;
@@ -42392,7 +42505,9 @@ function buildPageLocalStoryInstance(frameId, pageId, pageIndex, sectionIndex, d
42392
42505
  kind: target.kind,
42393
42506
  variant: target.variant,
42394
42507
  relationshipId: target.relationshipId,
42395
- region
42508
+ region,
42509
+ storyBasePath: `${target.kind}:${source.partPath ?? `word/${target.kind}${target.relationshipId}.xml`}`,
42510
+ anchorsByInlinePath: buildAnchorsByInlinePath(anchors)
42396
42511
  }) : { objects: [], divergences: [] };
42397
42512
  const signature = buildPageLocalStorySignature({
42398
42513
  kind: target.kind,
@@ -42446,6 +42561,23 @@ function buildPageLocalStorySignature(input) {
42446
42561
  object.anchorRectTwips?.yTwips ?? "",
42447
42562
  object.anchorRectTwips?.widthTwips ?? "",
42448
42563
  object.anchorRectTwips?.heightTwips ?? "",
42564
+ object.textBoxBody?.bodyKey ?? "",
42565
+ object.textBoxBody?.status ?? "",
42566
+ object.textBoxBody?.unavailableReason ?? "",
42567
+ object.textBoxBody?.contentRectTwips?.xTwips ?? "",
42568
+ object.textBoxBody?.contentRectTwips?.yTwips ?? "",
42569
+ object.textBoxBody?.contentRectTwips?.widthTwips ?? "",
42570
+ object.textBoxBody?.contentRectTwips?.heightTwips ?? "",
42571
+ object.textBoxBody?.paragraphs.map(
42572
+ (paragraph) => [
42573
+ paragraph.paragraphKey,
42574
+ paragraph.rectTwips?.xTwips ?? "",
42575
+ paragraph.rectTwips?.yTwips ?? "",
42576
+ paragraph.rectTwips?.widthTwips ?? "",
42577
+ paragraph.rectTwips?.heightTwips ?? "",
42578
+ paragraph.unavailableReason ?? ""
42579
+ ].join("/")
42580
+ ).join(",") ?? "",
42449
42581
  object.relationshipIds?.join(",") ?? "",
42450
42582
  object.mediaIds?.join(",") ?? "",
42451
42583
  object.wrapMode ?? "",
@@ -42590,6 +42722,10 @@ function truncatePageLocalStoryPreview(text) {
42590
42722
  if (text.length <= MAX_PAGE_LOCAL_STORY_PREVIEW_CHARS) return text;
42591
42723
  return `${text.slice(0, MAX_PAGE_LOCAL_STORY_PREVIEW_CHARS - 1).trimEnd()}\u2026`;
42592
42724
  }
42725
+ function buildAnchorsByInlinePath(anchors) {
42726
+ if (!anchors || anchors.length === 0) return void 0;
42727
+ return new Map(anchors.map((anchor) => [anchor.inlinePath, anchor]));
42728
+ }
42593
42729
  function collectStoryAnchoredObjects(blocks, context) {
42594
42730
  const objects = [];
42595
42731
  const divergences = [];
@@ -42633,26 +42769,45 @@ function collectStoryAnchoredObjects(blocks, context) {
42633
42769
  });
42634
42770
  ordinal += 1;
42635
42771
  };
42636
- const visitBlock = (block) => {
42772
+ const visitBlocks = (blocksToVisit, basePath) => {
42773
+ for (let blockIndex = 0; blockIndex < blocksToVisit.length; blockIndex += 1) {
42774
+ const block = blocksToVisit[blockIndex];
42775
+ if (!block) continue;
42776
+ visitBlock(block, `${basePath}/block[${blockIndex}]`);
42777
+ }
42778
+ };
42779
+ const visitBlock = (block, blockPath) => {
42637
42780
  switch (block.type) {
42638
42781
  case "paragraph":
42639
- for (const child of block.children) visitInline(child);
42782
+ visitInlines(block.children, blockPath, `${blockPath}/inline`);
42640
42783
  break;
42641
42784
  case "table":
42642
- for (const row2 of block.rows) {
42643
- for (const cell of row2.cells) {
42644
- for (const child of cell.children) visitBlock(child);
42785
+ for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex += 1) {
42786
+ const row2 = block.rows[rowIndex];
42787
+ if (!row2) continue;
42788
+ for (let cellIndex = 0; cellIndex < row2.cells.length; cellIndex += 1) {
42789
+ const cell = row2.cells[cellIndex];
42790
+ if (!cell) continue;
42791
+ visitBlocks(cell.children, `${blockPath}/row[${rowIndex}]/cell[${cellIndex}]`);
42645
42792
  }
42646
42793
  }
42647
42794
  break;
42648
42795
  case "sdt":
42649
- for (const child of block.children) visitBlock(child);
42796
+ case "custom_xml":
42797
+ visitBlocks(block.children, blockPath);
42650
42798
  break;
42651
42799
  default:
42652
42800
  break;
42653
42801
  }
42654
42802
  };
42655
- const visitInline = (inline) => {
42803
+ const visitInlines = (inlines, blockPath, basePath) => {
42804
+ for (let inlineIndex = 0; inlineIndex < inlines.length; inlineIndex += 1) {
42805
+ const inline = inlines[inlineIndex];
42806
+ if (!inline) continue;
42807
+ visitInline(inline, blockPath, `${basePath}[${inlineIndex}]`);
42808
+ }
42809
+ };
42810
+ const visitInline = (inline, blockPath, inlinePath) => {
42656
42811
  switch (inline.type) {
42657
42812
  case "image": {
42658
42813
  pushObject({
@@ -42673,17 +42828,27 @@ function collectStoryAnchoredObjects(blocks, context) {
42673
42828
  inline.anchor.extent.widthEmu,
42674
42829
  inline.anchor.extent.heightEmu
42675
42830
  );
42831
+ const anchorRectTwips = resolveObjectAnchorRectTwips(
42832
+ context.region,
42833
+ extentTwips,
42834
+ inline.anchor.positionH,
42835
+ inline.anchor.positionV
42836
+ );
42837
+ const canonicalAnchor = context.anchorsByInlinePath?.get(inlinePath);
42838
+ const textBoxBody = buildDrawingFrameTextBoxBodyFacts(
42839
+ inline,
42840
+ canonicalAnchor,
42841
+ inlinePath,
42842
+ display,
42843
+ anchorRectTwips
42844
+ );
42676
42845
  pushObject({
42677
42846
  objectId: getDrawingFrameObjectId(inline, context.storyKey, ordinal),
42678
42847
  sourceType: "drawing-frame",
42679
42848
  display,
42680
42849
  extentTwips,
42681
- anchorRectTwips: resolveObjectAnchorRectTwips(
42682
- context.region,
42683
- extentTwips,
42684
- inline.anchor.positionH,
42685
- inline.anchor.positionV
42686
- ),
42850
+ anchorRectTwips,
42851
+ ...textBoxBody ? { textBoxBody } : {},
42687
42852
  ...relationshipIds.length > 0 ? { relationshipIds } : {},
42688
42853
  ...inline.content.type === "picture" && inline.content.mediaId ? { mediaIds: [inline.content.mediaId] } : {},
42689
42854
  preserveOnly: Boolean(preserveHint),
@@ -42691,7 +42856,7 @@ function collectStoryAnchoredObjects(blocks, context) {
42691
42856
  wrapMode: inline.anchor.wrapMode
42692
42857
  });
42693
42858
  if (inline.content.type === "shape") {
42694
- for (const child of inline.content.txbxBlocks ?? []) visitBlock(child);
42859
+ visitBlocks(inline.content.txbxBlocks ?? [], `${inlinePath}/txbx`);
42695
42860
  }
42696
42861
  break;
42697
42862
  }
@@ -42718,10 +42883,11 @@ function collectStoryAnchoredObjects(blocks, context) {
42718
42883
  } : {},
42719
42884
  ...preserveHint?.relationshipIds ? { relationshipIds: [...preserveHint.relationshipIds] } : {},
42720
42885
  preserveOnly: Boolean(preserveHint),
42721
- ...preserveHint ? { preserveHint } : {}
42886
+ ...preserveHint ? { preserveHint } : {},
42887
+ ...inline.type === "vml_shape" && inline.text ? { textBoxBody: buildUnsupportedVmlTextBoxFacts(inline, inlinePath) } : {}
42722
42888
  });
42723
42889
  if (inline.type === "shape") {
42724
- for (const child of inline.txbxBlocks ?? []) visitBlock(child);
42890
+ visitBlocks(inline.txbxBlocks ?? [], `${inlinePath}/txbx`);
42725
42891
  }
42726
42892
  break;
42727
42893
  }
@@ -42743,16 +42909,16 @@ function collectStoryAnchoredObjects(blocks, context) {
42743
42909
  });
42744
42910
  break;
42745
42911
  case "field":
42746
- for (const child of inline.children) visitInline(child);
42912
+ visitInlines(inline.children, blockPath, `${inlinePath}/child`);
42747
42913
  break;
42748
42914
  case "hyperlink":
42749
- for (const child of inline.children) visitInline(child);
42915
+ visitInlines(inline.children, blockPath, `${inlinePath}/child`);
42750
42916
  break;
42751
42917
  default:
42752
42918
  break;
42753
42919
  }
42754
42920
  };
42755
- for (const block of blocks) visitBlock(block);
42921
+ visitBlocks(blocks, context.storyBasePath);
42756
42922
  return { objects, divergences };
42757
42923
  }
42758
42924
  function getDrawingFramePreserveHint(inline) {
@@ -42760,6 +42926,170 @@ function getDrawingFramePreserveHint(inline) {
42760
42926
  if (content.type === "picture") return void 0;
42761
42927
  return content.preserveOnlyObject;
42762
42928
  }
42929
+ function buildDrawingFrameTextBoxBodyFacts(inline, canonicalAnchor, inlinePath, display, anchorRectTwips) {
42930
+ if (inline.content.type !== "shape") return void 0;
42931
+ const content = inline.content;
42932
+ const canonicalBody = canonicalAnchor?.textBoxBody;
42933
+ const hasTextBoxContent = Boolean(
42934
+ canonicalBody || content.isTextBox || content.textBoxBody || content.txbxBlocks?.length
42935
+ );
42936
+ if (!hasTextBoxContent) return void 0;
42937
+ if (!canonicalBody) {
42938
+ return unavailableTextBoxBodyFacts(
42939
+ `${canonicalAnchor?.objectKey ?? inlinePath}:txbx`,
42940
+ "unmodeled-txbx-blocks",
42941
+ content.textBoxBody,
42942
+ content.txbxBlocks?.length ?? 0,
42943
+ countParagraphBlocks(content.txbxBlocks ?? []),
42944
+ 0
42945
+ );
42946
+ }
42947
+ if (display !== "floating") {
42948
+ return unavailableTextBoxBodyFactsFromCanonical(canonicalBody, "inline-textbox");
42949
+ }
42950
+ if (!anchorRectTwips) {
42951
+ return unavailableTextBoxBodyFactsFromCanonical(canonicalBody, "missing-anchor-rect");
42952
+ }
42953
+ if (canonicalBody.status !== "modeled") {
42954
+ return unavailableTextBoxBodyFactsFromCanonical(
42955
+ canonicalBody,
42956
+ normalizeTextBoxBodyUnavailableReason(canonicalBody.unavailableReason)
42957
+ );
42958
+ }
42959
+ const bodyInsetsTwips = textBoxInsetsTwips(canonicalBody.bodyProperties);
42960
+ if (!bodyInsetsTwips) {
42961
+ return unavailableTextBoxBodyFactsFromCanonical(canonicalBody, "missing-body-insets");
42962
+ }
42963
+ const contentRectTwips = rect(
42964
+ anchorRectTwips.xTwips + bodyInsetsTwips.leftTwips,
42965
+ anchorRectTwips.yTwips + bodyInsetsTwips.topTwips,
42966
+ Math.max(0, anchorRectTwips.widthTwips - bodyInsetsTwips.leftTwips - bodyInsetsTwips.rightTwips),
42967
+ Math.max(0, anchorRectTwips.heightTwips - bodyInsetsTwips.topTwips - bodyInsetsTwips.bottomTwips)
42968
+ );
42969
+ return {
42970
+ bodyKey: canonicalBody.bodyKey,
42971
+ status: "modeled",
42972
+ ...canonicalBody.bodyProperties ? { bodyProperties: { ...canonicalBody.bodyProperties } } : {},
42973
+ bodyInsetsTwips,
42974
+ contentRectTwips,
42975
+ blockCount: canonicalBody.blockCount,
42976
+ paragraphCount: canonicalBody.paragraphCount,
42977
+ unsupportedBlockCount: canonicalBody.unsupportedBlockCount,
42978
+ paragraphs: buildTextBoxParagraphFacts(canonicalBody, contentRectTwips)
42979
+ };
42980
+ }
42981
+ function unavailableTextBoxBodyFactsFromCanonical(body, reason) {
42982
+ return {
42983
+ bodyKey: body.bodyKey,
42984
+ status: body.status === "preserve-only" ? "preserve-only" : "unavailable",
42985
+ unavailableReason: reason,
42986
+ ...body.bodyProperties ? { bodyProperties: { ...body.bodyProperties } } : {},
42987
+ blockCount: body.blockCount,
42988
+ paragraphCount: body.paragraphCount,
42989
+ unsupportedBlockCount: body.unsupportedBlockCount,
42990
+ paragraphs: body.paragraphs.map((paragraph) => ({
42991
+ paragraphKey: paragraph.paragraphKey,
42992
+ blockPath: paragraph.blockPath,
42993
+ blockIndex: paragraph.blockIndex,
42994
+ unavailableReason: reason,
42995
+ ...paragraph.styleId !== void 0 ? { styleId: paragraph.styleId } : {},
42996
+ ...paragraph.alignment !== void 0 ? { alignment: paragraph.alignment } : {},
42997
+ textLength: paragraph.textLength,
42998
+ runCount: paragraph.runCount
42999
+ }))
43000
+ };
43001
+ }
43002
+ function unavailableTextBoxBodyFacts(bodyKey, reason, bodyProperties, blockCount, paragraphCount, unsupportedBlockCount) {
43003
+ return {
43004
+ bodyKey,
43005
+ status: "unavailable",
43006
+ unavailableReason: reason,
43007
+ ...bodyProperties ? { bodyProperties: { ...bodyProperties } } : {},
43008
+ blockCount,
43009
+ paragraphCount,
43010
+ unsupportedBlockCount,
43011
+ paragraphs: []
43012
+ };
43013
+ }
43014
+ function buildUnsupportedVmlTextBoxFacts(inline, inlinePath) {
43015
+ const hasText = Boolean(inline.text?.length);
43016
+ return {
43017
+ bodyKey: `${inline.preserveOnlyObject?.sourceId ?? inlinePath}:vml-textbox`,
43018
+ status: "unavailable",
43019
+ unavailableReason: "unsupported-vml-textbox",
43020
+ blockCount: hasText ? 1 : 0,
43021
+ paragraphCount: hasText ? 1 : 0,
43022
+ unsupportedBlockCount: hasText ? 1 : 0,
43023
+ paragraphs: []
43024
+ };
43025
+ }
43026
+ function buildTextBoxParagraphFacts(body, contentRectTwips) {
43027
+ const paragraphCount = body.paragraphs.length;
43028
+ if (paragraphCount === 0) return [];
43029
+ const baseHeight = Math.floor(contentRectTwips.heightTwips / paragraphCount);
43030
+ return body.paragraphs.map((paragraph, index) => {
43031
+ const yTwips = contentRectTwips.yTwips + baseHeight * index;
43032
+ const heightTwips = index === paragraphCount - 1 ? Math.max(0, contentRectTwips.yTwips + contentRectTwips.heightTwips - yTwips) : Math.max(0, baseHeight);
43033
+ return {
43034
+ paragraphKey: paragraph.paragraphKey,
43035
+ blockPath: paragraph.blockPath,
43036
+ blockIndex: paragraph.blockIndex,
43037
+ rectTwips: rect(
43038
+ contentRectTwips.xTwips,
43039
+ yTwips,
43040
+ contentRectTwips.widthTwips,
43041
+ heightTwips
43042
+ ),
43043
+ ...paragraph.styleId !== void 0 ? { styleId: paragraph.styleId } : {},
43044
+ ...paragraph.alignment !== void 0 ? { alignment: paragraph.alignment } : {},
43045
+ textLength: paragraph.textLength,
43046
+ runCount: paragraph.runCount
43047
+ };
43048
+ });
43049
+ }
43050
+ function textBoxInsetsTwips(bodyProperties) {
43051
+ if (!bodyProperties || bodyProperties.insetLeftEmu === void 0 || bodyProperties.insetTopEmu === void 0 || bodyProperties.insetRightEmu === void 0 || bodyProperties.insetBottomEmu === void 0) {
43052
+ return void 0;
43053
+ }
43054
+ return {
43055
+ leftTwips: Math.max(0, Math.round(bodyProperties.insetLeftEmu / EMUS_PER_TWIP2)),
43056
+ topTwips: Math.max(0, Math.round(bodyProperties.insetTopEmu / EMUS_PER_TWIP2)),
43057
+ rightTwips: Math.max(0, Math.round(bodyProperties.insetRightEmu / EMUS_PER_TWIP2)),
43058
+ bottomTwips: Math.max(0, Math.round(bodyProperties.insetBottomEmu / EMUS_PER_TWIP2))
43059
+ };
43060
+ }
43061
+ function normalizeTextBoxBodyUnavailableReason(reason) {
43062
+ switch (reason) {
43063
+ case "txbx-blocks-unavailable":
43064
+ case "empty-body":
43065
+ case "unsupported-content":
43066
+ return reason;
43067
+ default:
43068
+ return "unmodeled-txbx-blocks";
43069
+ }
43070
+ }
43071
+ function countParagraphBlocks(blocks) {
43072
+ let count = 0;
43073
+ const visit = (block) => {
43074
+ if (block.type === "paragraph") {
43075
+ count += 1;
43076
+ return;
43077
+ }
43078
+ if (block.type === "table") {
43079
+ for (const row2 of block.rows) {
43080
+ for (const cell of row2.cells) {
43081
+ for (const child of cell.children) visit(child);
43082
+ }
43083
+ }
43084
+ return;
43085
+ }
43086
+ if (block.type === "sdt" || block.type === "custom_xml") {
43087
+ for (const child of block.children) visit(child);
43088
+ }
43089
+ };
43090
+ for (const block of blocks) visit(block);
43091
+ return count;
43092
+ }
42763
43093
  function collectDrawingRelationshipIds(inline) {
42764
43094
  const content = inline.content;
42765
43095
  if (content.type === "picture") return [content.blipRef];
@@ -43088,12 +43418,34 @@ function freezePageFrame(frame) {
43088
43418
  for (const story of frame.pageLocalStories) {
43089
43419
  Object.freeze(story.resolvedFields);
43090
43420
  Object.freeze(story.previewParts);
43421
+ for (const object of story.anchoredObjects) {
43422
+ freezeStoryAnchoredObject(object);
43423
+ }
43091
43424
  Object.freeze(story.anchoredObjects);
43092
43425
  Object.freeze(story);
43093
43426
  }
43094
43427
  Object.freeze(frame.pageLocalStories);
43095
43428
  Object.freeze(frame);
43096
43429
  }
43430
+ function freezeStoryAnchoredObject(object) {
43431
+ if (object.extentTwips) Object.freeze(object.extentTwips);
43432
+ if (object.anchorRectTwips) Object.freeze(object.anchorRectTwips);
43433
+ if (object.relationshipIds) Object.freeze(object.relationshipIds);
43434
+ if (object.mediaIds) Object.freeze(object.mediaIds);
43435
+ if (object.textBoxBody) {
43436
+ if (object.textBoxBody.bodyProperties) Object.freeze(object.textBoxBody.bodyProperties);
43437
+ if (object.textBoxBody.bodyInsetsTwips) Object.freeze(object.textBoxBody.bodyInsetsTwips);
43438
+ if (object.textBoxBody.contentRectTwips) Object.freeze(object.textBoxBody.contentRectTwips);
43439
+ for (const paragraph of object.textBoxBody.paragraphs) {
43440
+ if (paragraph.rectTwips) Object.freeze(paragraph.rectTwips);
43441
+ Object.freeze(paragraph);
43442
+ }
43443
+ Object.freeze(object.textBoxBody.paragraphs);
43444
+ Object.freeze(object.textBoxBody);
43445
+ }
43446
+ Object.freeze(object.divergenceIds);
43447
+ Object.freeze(object);
43448
+ }
43097
43449
  function normalizePageLocalStoryFieldsForPages(pages) {
43098
43450
  const pageFieldCounts = buildPageFieldCounts(pages);
43099
43451
  return pages.map((page) => {
@@ -44776,7 +45128,8 @@ function createLayoutEngine(options = {}) {
44776
45128
  fragmentsByPageIndex,
44777
45129
  lineBoxesByPageIndex,
44778
45130
  noteAllocationsByPageIndex: pageStack.noteAllocationsByPageIndex,
44779
- subParts: document2.subParts
45131
+ subParts: document2.subParts,
45132
+ anchors: layoutInputs.anchors
44780
45133
  });
44781
45134
  const graph = applyViewportWindowMaterialization(
44782
45135
  measuredGraph,
@@ -44911,7 +45264,8 @@ function createLayoutEngine(options = {}) {
44911
45264
  fragmentsByPageIndex: freshFragmentsByPageIndex,
44912
45265
  lineBoxesByPageIndex: freshLineBoxesByPageIndex,
44913
45266
  noteAllocationsByPageIndex: freshResult.noteAllocationsByPageIndex,
44914
- subParts: document2.subParts
45267
+ subParts: document2.subParts,
45268
+ anchors: layoutInputs.anchors
44915
45269
  });
44916
45270
  const freshNodes = freshGraph.pages;
44917
45271
  const splicedGraph = spliceGraph(priorGraph, freshNodes, firstDirty, convergedTailStart);
@@ -48637,12 +48991,37 @@ function toPublicStoryAnchoredObject(object) {
48637
48991
  }
48638
48992
  } : {},
48639
48993
  ...object.anchorRectTwips ? { anchorRectTwips: toPublicTwipsRect(object.anchorRectTwips) } : {},
48994
+ ...object.textBoxBody ? { textBoxBody: toPublicTextBoxBodyFacts(object.textBoxBody) } : {},
48640
48995
  ...object.relationshipIds ? { relationshipIds: [...object.relationshipIds] } : {},
48641
48996
  ...object.mediaIds ? { mediaIds: [...object.mediaIds] } : {},
48642
48997
  preserveOnly: object.preserveOnly,
48643
48998
  divergenceIds: [...object.divergenceIds]
48644
48999
  };
48645
49000
  }
49001
+ function toPublicTextBoxBodyFacts(textBoxBody) {
49002
+ return {
49003
+ bodyKey: textBoxBody.bodyKey,
49004
+ status: textBoxBody.status,
49005
+ ...textBoxBody.unavailableReason !== void 0 ? { unavailableReason: textBoxBody.unavailableReason } : {},
49006
+ ...textBoxBody.bodyProperties ? { bodyProperties: { ...textBoxBody.bodyProperties } } : {},
49007
+ ...textBoxBody.bodyInsetsTwips ? { bodyInsetsTwips: { ...textBoxBody.bodyInsetsTwips } } : {},
49008
+ ...textBoxBody.contentRectTwips ? { contentRectTwips: toPublicTwipsRect(textBoxBody.contentRectTwips) } : {},
49009
+ blockCount: textBoxBody.blockCount,
49010
+ paragraphCount: textBoxBody.paragraphCount,
49011
+ unsupportedBlockCount: textBoxBody.unsupportedBlockCount,
49012
+ paragraphs: textBoxBody.paragraphs.map((paragraph) => ({
49013
+ paragraphKey: paragraph.paragraphKey,
49014
+ blockPath: paragraph.blockPath,
49015
+ blockIndex: paragraph.blockIndex,
49016
+ ...paragraph.rectTwips ? { rectTwips: toPublicTwipsRect(paragraph.rectTwips) } : {},
49017
+ ...paragraph.unavailableReason !== void 0 ? { unavailableReason: paragraph.unavailableReason } : {},
49018
+ ...paragraph.styleId !== void 0 ? { styleId: paragraph.styleId } : {},
49019
+ ...paragraph.alignment !== void 0 ? { alignment: paragraph.alignment } : {},
49020
+ textLength: paragraph.textLength,
49021
+ runCount: paragraph.runCount
49022
+ }))
49023
+ };
49024
+ }
48646
49025
  function toPublicLayoutDivergence(divergence) {
48647
49026
  return {
48648
49027
  divergenceId: divergence.divergenceId,
@@ -51696,7 +52075,7 @@ function resolveEditableTextTarget(input) {
51696
52075
  "Editable target ref does not belong to the active story."
51697
52076
  );
51698
52077
  }
51699
- const currentTargets = collectEditableTargetRefs(input.document);
52078
+ const currentTargets = collectEditableTargetRefs(input.document, input.editableTargetCache);
51700
52079
  const current = currentTargets.find(
51701
52080
  (candidate) => candidate.targetKey === input.target.targetKey
51702
52081
  );
@@ -51805,7 +52184,7 @@ function resolveEditableCommandTarget(input) {
51805
52184
  `Editable target kind "${input.target.kind}" is not supported by this command.`
51806
52185
  );
51807
52186
  }
51808
- const currentTargets = collectEditableTargetRefs(input.document);
52187
+ const currentTargets = collectEditableTargetRefs(input.document, input.editableTargetCache);
51809
52188
  const current = currentTargets.find(
51810
52189
  (candidate) => candidate.targetKey === input.target?.targetKey
51811
52190
  );
@@ -51880,7 +52259,13 @@ function rejectCommand(code, message) {
51880
52259
  };
51881
52260
  }
51882
52261
  function sameResolvedTarget2(left, right) {
51883
- return left.kind === right.kind && left.storyKey === right.storyKey && left.blockPath === right.blockPath && left.leafPath === right.leafPath && left.commandFamily === right.commandFamily && left.editability === right.editability && left.staleCheck.paragraphTextHash === right.staleCheck.paragraphTextHash && left.staleCheck.paragraphTextLength === right.staleCheck.paragraphTextLength && left.staleCheck.inlineCount === right.staleCheck.inlineCount && left.staleCheck.targetHash === right.staleCheck.targetHash && left.staleCheck.targetTextLength === right.staleCheck.targetTextLength && left.staleCheck.childCount === right.staleCheck.childCount && left.staleCheck.blockType === right.staleCheck.blockType && left.staleCheck.wordParaId === right.staleCheck.wordParaId && left.staleCheck.wordTextId === right.staleCheck.wordTextId && jsonStable(left.staleCheck.sourceRef) === jsonStable(right.staleCheck.sourceRef) && jsonStable(left.sourceRef) === jsonStable(right.sourceRef) && jsonStable(left.table) === jsonStable(right.table) && jsonStable(left.editableOwner) === jsonStable(right.editableOwner);
52262
+ return left.kind === right.kind && left.storyKey === right.storyKey && left.blockPath === right.blockPath && left.leafPath === right.leafPath && left.commandFamily === right.commandFamily && left.editability === right.editability && sameTextTargetStaleCheck(left, right) && left.staleCheck.inlineCount === right.staleCheck.inlineCount && left.staleCheck.targetHash === right.staleCheck.targetHash && left.staleCheck.targetTextLength === right.staleCheck.targetTextLength && left.staleCheck.childCount === right.staleCheck.childCount && left.staleCheck.blockType === right.staleCheck.blockType && left.staleCheck.wordParaId === right.staleCheck.wordParaId && left.staleCheck.wordTextId === right.staleCheck.wordTextId && jsonStable(left.staleCheck.sourceRef) === jsonStable(right.staleCheck.sourceRef) && jsonStable(left.sourceRef) === jsonStable(right.sourceRef) && jsonStable(left.table) === jsonStable(right.table) && jsonStable(left.editableOwner) === jsonStable(right.editableOwner);
52263
+ }
52264
+ function sameTextTargetStaleCheck(left, right) {
52265
+ if (left.staleCheck.paragraphTextHash === right.staleCheck.paragraphTextHash && left.staleCheck.paragraphTextLength === right.staleCheck.paragraphTextLength) {
52266
+ return true;
52267
+ }
52268
+ return left.commandFamily === "text-leaf" && left.staleCheck.paragraphTextLength !== void 0 && right.staleCheck.paragraphTextLength !== void 0 && left.staleCheck.paragraphTextLength !== right.staleCheck.paragraphTextLength;
51884
52269
  }
51885
52270
  function locateTargetRange(document2, surface, target) {
51886
52271
  if (target.kind === "hyperlink-text") {
@@ -52199,7 +52584,7 @@ function resolveEditableTableStructureTarget(input) {
52199
52584
  `Editable target is not editable${input.target.posture.blockers.length > 0 ? `: ${input.target.posture.blockers.join(", ")}` : "."}`
52200
52585
  );
52201
52586
  }
52202
- const current = collectEditableTargetRefs(input.document).find(
52587
+ const current = collectEditableTargetRefs(input.document, input.editableTargetCache).find(
52203
52588
  (candidate) => candidate.targetKey === input.target?.targetKey
52204
52589
  );
52205
52590
  if (!current) {
@@ -52319,6 +52704,26 @@ function sortJson(value) {
52319
52704
  }
52320
52705
 
52321
52706
  // src/runtime/document-runtime.ts
52707
+ var CANONICAL_BLOCK_REFS_SYMBOL2 = /* @__PURE__ */ Symbol.for("wre.canonical-block-refs");
52708
+ function getLocalTextPatchMetadata(mapping) {
52709
+ const metadata = mapping.metadata?.localTextPatch;
52710
+ if (!metadata || typeof metadata !== "object") {
52711
+ return null;
52712
+ }
52713
+ const insertedText = metadata.insertedText;
52714
+ return typeof insertedText === "string" ? { insertedText } : null;
52715
+ }
52716
+ function getSurfaceCanonicalBlockRefs(snapshot) {
52717
+ return snapshot[CANONICAL_BLOCK_REFS_SYMBOL2];
52718
+ }
52719
+ function attachSurfaceCanonicalBlockRefs(snapshot, refs) {
52720
+ Object.defineProperty(snapshot, CANONICAL_BLOCK_REFS_SYMBOL2, {
52721
+ value: refs,
52722
+ enumerable: false,
52723
+ configurable: true,
52724
+ writable: false
52725
+ });
52726
+ }
52322
52727
  function normalizeViewportRanges(ranges) {
52323
52728
  const cleaned = ranges.filter((r) => Number.isFinite(r.start) && Number.isFinite(r.end) && r.end > r.start).map((r) => ({ start: r.start, end: r.end }));
52324
52729
  if (cleaned.length === 0) return Object.freeze([]);
@@ -52682,6 +53087,22 @@ function createDocumentRuntime(options) {
52682
53087
  cachedEditableTargetMap = { document: document2, map: byBlockPath };
52683
53088
  return byBlockPath;
52684
53089
  }
53090
+ function getEditableTargetsByBlockPathForRanges(document2, storyKey2, ranges) {
53091
+ if (ranges === null) return getEditableTargetsByBlockPath(document2);
53092
+ perfCounters.increment("runtime.editableTargets.boundedBuilds");
53093
+ const targets = collectEditableTargetRefsForStoryBlockRanges(
53094
+ document2,
53095
+ storyKey2,
53096
+ ranges,
53097
+ editableTargetBlockCache
53098
+ );
53099
+ if (targets.length === 0) return /* @__PURE__ */ new Map();
53100
+ const byBlockPath = /* @__PURE__ */ new Map();
53101
+ for (const target of targets) {
53102
+ byBlockPath.set(target.blockPath, target);
53103
+ }
53104
+ return byBlockPath;
53105
+ }
52685
53106
  function invalidateEditableTargetMap() {
52686
53107
  cachedEditableTargetMap = null;
52687
53108
  }
@@ -52732,7 +53153,7 @@ function createDocumentRuntime(options) {
52732
53153
  }
52733
53154
  const snapshot = createEditorSurfaceSnapshot(document2, state.selection, nextActiveStory, {
52734
53155
  viewportBlockRanges: surfaceViewportRanges,
52735
- editableTargetsByBlockPath: getEditableTargetsByBlockPath(document2),
53156
+ editableTargetsByBlockPath: options2.editableTargetsByBlockPathOverride ?? getEditableTargetsByBlockPath(document2),
52736
53157
  ...effectiveMarkupModeProvider ? { getEffectiveMarkupMode: effectiveMarkupModeProvider } : {}
52737
53158
  });
52738
53159
  recordPerfSample("snapshot.surface");
@@ -52795,6 +53216,180 @@ function createDocumentRuntime(options) {
52795
53216
  }
52796
53217
  return -1;
52797
53218
  }
53219
+ function cachePatchedLocalTextSurface(surface) {
53220
+ const activeStoryKey = storyTargetKey(activeStory);
53221
+ const rangesKey = serializeViewportRanges(surface.viewportBlockRanges);
53222
+ cachedSurface = {
53223
+ content: state.document.content,
53224
+ subParts: state.document.subParts,
53225
+ styles: state.document.styles,
53226
+ numbering: state.document.numbering,
53227
+ media: state.document.media,
53228
+ preservation: state.document.preservation,
53229
+ review: state.document.review,
53230
+ effectiveMarkupModeProvider,
53231
+ activeStoryKey,
53232
+ viewportRangesKey: rangesKey,
53233
+ snapshot: surface
53234
+ };
53235
+ if (surface.viewportBlockRanges === null) {
53236
+ cachedFullSurface = {
53237
+ content: state.document.content,
53238
+ subParts: state.document.subParts,
53239
+ styles: state.document.styles,
53240
+ numbering: state.document.numbering,
53241
+ media: state.document.media,
53242
+ preservation: state.document.preservation,
53243
+ review: state.document.review,
53244
+ effectiveMarkupModeProvider,
53245
+ activeStoryKey,
53246
+ snapshot: surface
53247
+ };
53248
+ }
53249
+ cachedSurfaceFingerprint = `${activeStoryKey}|${rangesKey}|${String(state.selection.anchor)}:${String(state.selection.head)}`;
53250
+ }
53251
+ function tryPatchLocalTextSurface(previousSurface, mapping) {
53252
+ const tTotal0 = performance.now();
53253
+ try {
53254
+ if (!previousSurface || activeStory.kind !== "main") {
53255
+ perfCounters.increment("surface.localText.patchMiss");
53256
+ return null;
53257
+ }
53258
+ const patch = getLocalTextPatchMetadata(mapping);
53259
+ if (!patch || mapping.steps.length !== 1) {
53260
+ perfCounters.increment("surface.localText.patchMiss");
53261
+ return null;
53262
+ }
53263
+ const step = mapping.steps[0];
53264
+ if (patch.insertedText.length !== step.insertSize) {
53265
+ perfCounters.increment("surface.localText.patchMiss");
53266
+ return null;
53267
+ }
53268
+ const editFrom = step.from;
53269
+ const editTo = step.to;
53270
+ if (editTo < editFrom || editFrom < 0) {
53271
+ perfCounters.increment("surface.localText.patchMiss");
53272
+ return null;
53273
+ }
53274
+ const blockIndex = previousSurface.blocks.findIndex(
53275
+ (block2) => block2.kind === "paragraph" && editFrom >= block2.from && editTo <= block2.to
53276
+ );
53277
+ if (blockIndex < 0) {
53278
+ perfCounters.increment("surface.localText.patchMiss");
53279
+ return null;
53280
+ }
53281
+ const block = previousSurface.blocks[blockIndex];
53282
+ if (block.kind !== "paragraph") {
53283
+ perfCounters.increment("surface.localText.patchMiss");
53284
+ return null;
53285
+ }
53286
+ const segmentIndex = block.segments.findIndex(
53287
+ (segment2) => segment2.kind === "text" && editFrom >= segment2.from && editTo <= segment2.to
53288
+ );
53289
+ if (segmentIndex < 0) {
53290
+ perfCounters.increment("surface.localText.patchMiss");
53291
+ return null;
53292
+ }
53293
+ const segment = block.segments[segmentIndex];
53294
+ if (segment.kind !== "text") {
53295
+ perfCounters.increment("surface.localText.patchMiss");
53296
+ return null;
53297
+ }
53298
+ if (segment.text.length !== segment.to - segment.from) {
53299
+ perfCounters.increment("surface.localText.patchMiss");
53300
+ return null;
53301
+ }
53302
+ const localFrom = editFrom - segment.from;
53303
+ const localTo = editTo - segment.from;
53304
+ const delta = patch.insertedText.length - (editTo - editFrom);
53305
+ const nextText = segment.text.slice(0, localFrom) + patch.insertedText + segment.text.slice(localTo);
53306
+ const nextSegments = block.segments.map((candidate, index) => {
53307
+ if (index < segmentIndex) return candidate;
53308
+ if (index === segmentIndex) {
53309
+ return {
53310
+ ...segment,
53311
+ text: nextText,
53312
+ to: segment.to + delta
53313
+ };
53314
+ }
53315
+ return shiftSurfaceInlineSegment(candidate, delta);
53316
+ });
53317
+ const nextBlock = {
53318
+ ...block,
53319
+ to: block.to + delta,
53320
+ segments: nextSegments
53321
+ };
53322
+ const nextBlocks = previousSurface.blocks.map((candidate, index) => {
53323
+ if (index < blockIndex) return candidate;
53324
+ if (index === blockIndex) return nextBlock;
53325
+ return shiftSurfaceBlock(candidate, delta);
53326
+ });
53327
+ const nextPlainText = previousSurface.plainText.slice(0, editFrom) + patch.insertedText + previousSurface.plainText.slice(editTo);
53328
+ const nextSurface = {
53329
+ ...previousSurface,
53330
+ storySize: previousSurface.storySize + delta,
53331
+ plainText: nextPlainText,
53332
+ blocks: nextBlocks
53333
+ };
53334
+ const refs = getSurfaceCanonicalBlockRefs(previousSurface);
53335
+ if (refs) {
53336
+ const nextRefs = [...refs];
53337
+ nextRefs[blockIndex] = state.document.content.children[blockIndex] ?? null;
53338
+ attachSurfaceCanonicalBlockRefs(nextSurface, nextRefs);
53339
+ }
53340
+ perfCounters.increment("surface.localText.patchHit");
53341
+ perfCounters.increment("surface.localText.patchDelta", delta);
53342
+ return nextSurface;
53343
+ } finally {
53344
+ perfCounters.increment("surface.localText.total.us", Math.round((performance.now() - tTotal0) * 1e3));
53345
+ }
53346
+ }
53347
+ function shiftSurfaceInlineSegment(segment, delta) {
53348
+ if (delta === 0) return segment;
53349
+ return {
53350
+ ...segment,
53351
+ from: segment.from + delta,
53352
+ to: segment.to + delta
53353
+ };
53354
+ }
53355
+ function shiftSurfaceBlock(block, delta) {
53356
+ if (delta === 0) return block;
53357
+ switch (block.kind) {
53358
+ case "paragraph":
53359
+ return {
53360
+ ...block,
53361
+ from: block.from + delta,
53362
+ to: block.to + delta,
53363
+ segments: block.segments.map((segment) => shiftSurfaceInlineSegment(segment, delta))
53364
+ };
53365
+ case "table":
53366
+ return {
53367
+ ...block,
53368
+ from: block.from + delta,
53369
+ to: block.to + delta,
53370
+ rows: block.rows.map((row2) => ({
53371
+ ...row2,
53372
+ cells: row2.cells.map((cell) => ({
53373
+ ...cell,
53374
+ content: cell.content.map((child) => shiftSurfaceBlock(child, delta))
53375
+ }))
53376
+ }))
53377
+ };
53378
+ case "sdt_block":
53379
+ return {
53380
+ ...block,
53381
+ from: block.from + delta,
53382
+ to: block.to + delta,
53383
+ children: block.children.map((child) => shiftSurfaceBlock(child, delta))
53384
+ };
53385
+ case "opaque_block":
53386
+ return {
53387
+ ...block,
53388
+ from: block.from + delta,
53389
+ to: block.to + delta
53390
+ };
53391
+ }
53392
+ }
52798
53393
  function enrichCulledPlaceholdersWithHeights(snapshot) {
52799
53394
  let heights;
52800
53395
  try {
@@ -53680,7 +54275,8 @@ function createDocumentRuntime(options) {
53680
54275
  document: document2,
53681
54276
  target: command.editableTarget,
53682
54277
  activeStoryKey: canonicalEditableTargetStoryKey(storyTarget),
53683
- selectionDescriptor: command.selectionDescriptor
54278
+ selectionDescriptor: command.selectionDescriptor,
54279
+ editableTargetCache: editableTargetBlockCache
53684
54280
  });
53685
54281
  if (resolution.kind === "rejected") {
53686
54282
  emit({
@@ -53743,7 +54339,8 @@ function createDocumentRuntime(options) {
53743
54339
  document: document2,
53744
54340
  surface,
53745
54341
  target,
53746
- activeStoryKey: canonicalEditableTargetStoryKey(storyTarget)
54342
+ activeStoryKey: canonicalEditableTargetStoryKey(storyTarget),
54343
+ editableTargetCache: editableTargetBlockCache
53747
54344
  });
53748
54345
  if (resolution.kind === "rejected") {
53749
54346
  emit({
@@ -53773,7 +54370,8 @@ function createDocumentRuntime(options) {
53773
54370
  document: document2,
53774
54371
  surface,
53775
54372
  target: command.editableTarget,
53776
- activeStoryKey: canonicalEditableTargetStoryKey(storyTarget)
54373
+ activeStoryKey: canonicalEditableTargetStoryKey(storyTarget),
54374
+ editableTargetCache: editableTargetBlockCache
53777
54375
  });
53778
54376
  if (resolution.kind === "rejected") {
53779
54377
  emit({
@@ -53801,7 +54399,8 @@ function createDocumentRuntime(options) {
53801
54399
  activeStoryKey: canonicalEditableTargetStoryKey(storyTarget),
53802
54400
  commandFamilies: command.type === "field.refresh" || command.type === "toc.refresh" ? ["field"] : ["link-bookmark"],
53803
54401
  targetKinds: targetKindsForModeledCommand(command.type),
53804
- allowGeneratedPosture: true
54402
+ allowGeneratedPosture: true,
54403
+ editableTargetCache: editableTargetBlockCache
53805
54404
  });
53806
54405
  if (resolution.kind === "rejected") {
53807
54406
  emit({
@@ -53843,7 +54442,8 @@ function createDocumentRuntime(options) {
53843
54442
  baseState.selection.head,
53844
54443
  storyTarget,
53845
54444
  getFullPageGraph(),
53846
- command.options
54445
+ command.options,
54446
+ command.editableTarget
53847
54447
  );
53848
54448
  if (!refreshed2.changed) return null;
53849
54449
  cachedFieldSnapshotEntry = null;
@@ -53885,6 +54485,9 @@ function createDocumentRuntime(options) {
53885
54485
  );
53886
54486
  }
53887
54487
  const runtime = {
54488
+ getEditableTargetCache() {
54489
+ return editableTargetBlockCache;
54490
+ },
53888
54491
  subscribe(listener) {
53889
54492
  listeners.add(listener);
53890
54493
  return () => {
@@ -56088,6 +56691,12 @@ function createDocumentRuntime(options) {
56088
56691
  }
56089
56692
  return !effects.commentAdded && !effects.commentResolved && !effects.commentReopened && !effects.commentReplyAdded && !effects.commentBodyEdited && !effects.changeAccepted && !effects.changeRejected && !effects.revisionAuthored && !effects.commandBlocked;
56090
56693
  }
56694
+ function canSkipOverlaySyncForLocalText(transaction) {
56695
+ if (transaction.mapping.steps.length !== 1) return false;
56696
+ if (transaction.mapping.metadata?.invalidatesStructures) return false;
56697
+ if (transaction.mapping.metadata?.scopeTagTouches) return false;
56698
+ return getLocalTextPatchMetadata(transaction.mapping) !== null;
56699
+ }
56091
56700
  function applyTransactionToState(transaction, options2 = {}) {
56092
56701
  const effects = transaction.effects;
56093
56702
  const selectionUnchanged = transaction.nextState.selection === state.selection;
@@ -56109,9 +56718,28 @@ function createDocumentRuntime(options) {
56109
56718
  state = finalizeState(transaction.nextState, transaction.markDirty, clock());
56110
56719
  perfCounters.increment("commit.finalizeState.us", Math.round((performance.now() - tFinalize0) * 1e3));
56111
56720
  storySelections.set(storyTargetKey(activeStory), state.selection);
56721
+ const tClassify0 = performance.now();
56722
+ const useLocalTextCommitSnapshot = options2.allowLocalTextFastPath === true && shouldUseLocalTextCommitSnapshot(
56723
+ previous,
56724
+ state,
56725
+ transaction,
56726
+ transaction.effects
56727
+ );
56728
+ perfCounters.increment("commit.refreshClassify.us", Math.round((performance.now() - tClassify0) * 1e3));
56112
56729
  const tOverlay0 = performance.now();
56113
- overlayStore.replaceOverlay(overlayStore.getOverlay(), state.document);
56114
- const detachedWorkflowScopeWarnings = syncDetachedWorkflowScopeWarningsInState();
56730
+ const skipOverlaySync = useLocalTextCommitSnapshot && canSkipOverlaySyncForLocalText(transaction);
56731
+ const detachedWorkflowScopeWarnings = skipOverlaySync ? { added: [], cleared: [] } : (() => {
56732
+ const tReplace0 = performance.now();
56733
+ overlayStore.replaceOverlay(overlayStore.getOverlay(), state.document);
56734
+ perfCounters.increment("commit.overlaySync.replaceOverlay.us", Math.round((performance.now() - tReplace0) * 1e3));
56735
+ const tWarnings0 = performance.now();
56736
+ const result = syncDetachedWorkflowScopeWarningsInState();
56737
+ perfCounters.increment("commit.overlaySync.detachedWarnings.us", Math.round((performance.now() - tWarnings0) * 1e3));
56738
+ return result;
56739
+ })();
56740
+ if (skipOverlaySync) {
56741
+ perfCounters.increment("commit.overlaySync.skipped");
56742
+ }
56115
56743
  perfCounters.increment("commit.overlaySync.us", Math.round((performance.now() - tOverlay0) * 1e3));
56116
56744
  const tInvalidate0 = performance.now();
56117
56745
  if (transaction.markDirty && transaction.mapping.steps.length > 0) {
@@ -56145,22 +56773,34 @@ function createDocumentRuntime(options) {
56145
56773
  ...detachedWorkflowScopeWarnings.cleared
56146
56774
  ]
56147
56775
  };
56148
- const tClassify0 = performance.now();
56149
- const useLocalTextCommitSnapshot = options2.allowLocalTextFastPath === true && shouldUseLocalTextCommitSnapshot(
56150
- previous,
56151
- state,
56152
- transaction,
56153
- notifyEffects
56154
- );
56155
- perfCounters.increment("commit.refreshClassify.us", Math.round((performance.now() - tClassify0) * 1e3));
56156
56776
  if (!useLocalTextCommitSnapshot && transaction.markDirty && previous.document !== state.document) {
56157
56777
  applyViewportRanges(getSelectionCorridorViewportRanges(cachedRenderSnapshot.surface));
56158
56778
  }
56159
56779
  const tValidation0 = performance.now();
56160
- const surfaceForValidation = useLocalTextCommitSnapshot ? getCachedSurface(state.document, activeStory, {
56161
- viewportBlockRangesOverride: getSelectionCorridorViewportRanges(cachedRenderSnapshot.surface),
56162
- enrichCulledPlaceholders: false
56163
- }) : getCachedSurface(state.document, activeStory);
56780
+ const patchedLocalTextSurface = useLocalTextCommitSnapshot ? tryPatchLocalTextSurface(cachedRenderSnapshot.surface, transaction.mapping) : null;
56781
+ if (patchedLocalTextSurface) {
56782
+ cachePatchedLocalTextSurface(patchedLocalTextSurface);
56783
+ perfCounters.increment("commit.localTextValidation.storySizeOnly");
56784
+ }
56785
+ const localTextViewportRanges = useLocalTextCommitSnapshot && !patchedLocalTextSurface ? getSelectionCorridorViewportRanges(cachedRenderSnapshot.surface) : void 0;
56786
+ const localTextEditableTargetsByBlockPath = useLocalTextCommitSnapshot && !patchedLocalTextSurface ? getEditableTargetsByBlockPathForRanges(
56787
+ state.document,
56788
+ storyTargetKey(activeStory),
56789
+ localTextViewportRanges ?? null
56790
+ ) : void 0;
56791
+ const surfaceForValidation = patchedLocalTextSurface ? patchedLocalTextSurface : useLocalTextCommitSnapshot ? (() => {
56792
+ const tSurface0 = performance.now();
56793
+ try {
56794
+ perfCounters.increment("surface.localText.fullProjectionFallback");
56795
+ return getCachedSurface(state.document, activeStory, {
56796
+ viewportBlockRangesOverride: localTextViewportRanges,
56797
+ enrichCulledPlaceholders: false,
56798
+ editableTargetsByBlockPathOverride: localTextEditableTargetsByBlockPath
56799
+ });
56800
+ } finally {
56801
+ perfCounters.increment("surface.localText.fullProjection.us", Math.round((performance.now() - tSurface0) * 1e3));
56802
+ }
56803
+ })() : getCachedSurface(state.document, activeStory);
56164
56804
  const validationOptions = state.selection.activeRange.kind === "node" ? {
56165
56805
  isValidNodeTarget: createSurfaceNodeSelectionProbe(surfaceForValidation)
56166
56806
  } : void 0;
@@ -56427,7 +57067,8 @@ function createDocumentRuntime(options) {
56427
57067
  selection,
56428
57068
  surface: cachedRenderSnapshot.surface?.blocks ?? [],
56429
57069
  target: editableTarget,
56430
- activeStoryKey: canonicalEditableTargetStoryKey(activeStory)
57070
+ activeStoryKey: canonicalEditableTargetStoryKey(activeStory),
57071
+ editableTargetCache: editableTargetBlockCache
56431
57072
  }) : null;
56432
57073
  if (targetResolution?.kind === "rejected") {
56433
57074
  const blockedReason = targetResolution.blockedReason;
@@ -56479,6 +57120,7 @@ function createDocumentRuntime(options) {
56479
57120
  documentMode: textOptions.documentModeOverride ?? workflowCoordinator.getEffectiveDocumentMode(selection),
56480
57121
  defaultAuthorId: defaultAuthorId ?? void 0,
56481
57122
  renderSnapshot: cachedRenderSnapshot,
57123
+ activeStorySize: cachedRenderSnapshot.surface?.storySize,
56482
57124
  textTarget,
56483
57125
  rejectTargetlessTableStructureInsert: true
56484
57126
  };
@@ -57893,15 +58535,12 @@ function flattenInlineDisplayText(children) {
57893
58535
  }
57894
58536
  }).join("");
57895
58537
  }
57896
- function refreshDocumentFields(document2, selectionHead, activeStory, pageGraph, options) {
58538
+ function refreshDocumentFields(document2, selectionHead, activeStory, pageGraph, options, target) {
57897
58539
  const supportedOnly = options?.supportedOnly ?? true;
57898
58540
  const bookmarkMap = buildBookmarkNameMap(document2);
57899
58541
  const paragraphs = collectParagraphContexts(document2.content.children);
57900
- const activePageIndex = resolveActivePageIndexFromPageGraph(
57901
- pageGraph,
57902
- selectionHead,
57903
- activeStory
57904
- );
58542
+ void selectionHead;
58543
+ void activeStory;
57905
58544
  let updatedCount = 0;
57906
58545
  let changed = false;
57907
58546
  let changedFrom;
@@ -57911,19 +58550,27 @@ function refreshDocumentFields(document2, selectionHead, activeStory, pageGraph,
57911
58550
  let storyChangedFrom;
57912
58551
  let storyChangedTo;
57913
58552
  const refreshed = refreshBlocksWithCursor(blocks, (field, range) => {
58553
+ if (target !== void 0 && !fieldMatchesRefreshTarget(field, target)) {
58554
+ return field;
58555
+ }
57914
58556
  if (!field.fieldFamily || !isSupportedFieldFamily(field.fieldFamily)) {
57915
58557
  return field;
57916
58558
  }
57917
58559
  if (supportedOnly && field.fieldFamily === "TOC") {
57918
58560
  return field;
57919
58561
  }
58562
+ const fieldPageIndex = resolveActivePageIndexFromPageGraph(
58563
+ pageGraph,
58564
+ range.from,
58565
+ storyTarget
58566
+ );
57920
58567
  const display = resolveSupportedFieldDisplay(
57921
58568
  field,
57922
58569
  document2,
57923
58570
  bookmarkMap,
57924
58571
  paragraphs,
57925
58572
  pageGraph,
57926
- activePageIndex,
58573
+ fieldPageIndex,
57927
58574
  storyTarget
57928
58575
  );
57929
58576
  if (!display) {
@@ -58073,6 +58720,34 @@ function refreshDocumentFields(document2, selectionHead, activeStory, pageGraph,
58073
58720
  ...protectionSelection ? { protectionSelection } : {}
58074
58721
  };
58075
58722
  }
58723
+ function fieldMatchesRefreshTarget(field, target) {
58724
+ if (target.kind !== "field-result-text" && target.kind !== "field-region-refresh") {
58725
+ return false;
58726
+ }
58727
+ const targetField = target.field;
58728
+ if (targetField?.canonicalFieldId !== void 0) {
58729
+ return field.canonicalFieldId === targetField.canonicalFieldId;
58730
+ }
58731
+ const resultText = flattenInlineDisplayText(field.children);
58732
+ const fieldResultHash = sha256TextHex(`${field.instruction}\0${resultText}`);
58733
+ if (target.kind === "field-result-text" && target.staleCheck.targetHash !== void 0) {
58734
+ return target.staleCheck.targetHash === fieldResultHash;
58735
+ }
58736
+ if (targetField?.fieldFamily !== void 0 && targetField.fieldFamily !== field.fieldFamily) {
58737
+ return false;
58738
+ }
58739
+ if (targetField?.fieldTarget !== void 0 && targetField.fieldTarget !== field.fieldTarget) {
58740
+ return false;
58741
+ }
58742
+ if (target.staleCheck.sourceRef !== void 0 || target.sourceRef !== void 0) {
58743
+ return sourceRefsEqual(target.staleCheck.sourceRef ?? target.sourceRef, field.sourceRef);
58744
+ }
58745
+ return false;
58746
+ }
58747
+ function sourceRefsEqual(left, right) {
58748
+ if (left === void 0 || right === void 0) return false;
58749
+ return left.sourceId === right.sourceId && left.partPath === right.partPath && left.storyKind === right.storyKind && left.element === right.element && left.xmlPath === right.xmlPath && left.tableCellPath === right.tableCellPath && left.tableDepth === right.tableDepth && left.ordinal === right.ordinal && left.startOffset === right.startOffset && left.endOffset === right.endOffset;
58750
+ }
58076
58751
  function refreshDocumentTableOfContents(document2, selectionHead, activeStory, options, resolveDisplayPageNumber, navigationSnapshot) {
58077
58752
  const selectedRegion = selectTocRegion(document2.fieldRegistry?.tocRegions, options?.tocId);
58078
58753
  const refreshMode = options?.mode ?? "regenerate";