@beyondwork/docx-react-component 1.0.120 → 1.0.121

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 (116) hide show
  1. package/README.md +1 -0
  2. package/dist/api/public-types.cjs +1713 -55
  3. package/dist/api/public-types.d.cts +2 -2
  4. package/dist/api/public-types.d.ts +2 -2
  5. package/dist/api/public-types.js +6 -6
  6. package/dist/api/v3.cjs +4958 -406
  7. package/dist/api/v3.d.cts +3 -3
  8. package/dist/api/v3.d.ts +3 -3
  9. package/dist/api/v3.js +14 -14
  10. package/dist/{canonical-document-fNawStsc.d.cts → canonical-document-ByIqTd4s.d.cts} +9 -1
  11. package/dist/{canonical-document-fNawStsc.d.ts → canonical-document-ByIqTd4s.d.ts} +9 -1
  12. package/dist/{chunk-5RNMPLXU.js → chunk-37SEJQ3G.js} +4 -4
  13. package/dist/{chunk-FXGQM2JB.js → chunk-3OFSP2IX.js} +11 -5
  14. package/dist/{chunk-U5BSQXF4.js → chunk-3OHVK2D6.js} +70 -12
  15. package/dist/{chunk-AUQDC5BD.js → chunk-3TUQCHYT.js} +101 -2
  16. package/dist/{chunk-SJSMYEMU.js → chunk-B4YHWFE3.js} +3 -3
  17. package/dist/{chunk-XC56YLIS.js → chunk-C2LWJ4CZ.js} +4 -0
  18. package/dist/{chunk-VDIUVT46.js → chunk-CX42VC67.js} +1 -1
  19. package/dist/{chunk-KCHEAX4Z.js → chunk-EMDH4IQN.js} +148 -70
  20. package/dist/{chunk-TMQGWF7R.js → chunk-G3B2OBCZ.js} +352 -17
  21. package/dist/{chunk-VCL5MJMZ.js → chunk-GON2DNTE.js} +149 -28
  22. package/dist/{chunk-WVZX4NYG.js → chunk-GZW2ERUO.js} +601 -47
  23. package/dist/{chunk-WDNEPRFW.js → chunk-ICX54W4U.js} +1 -1
  24. package/dist/{chunk-FIGWJ43K.js → chunk-IT2DK3A7.js} +1883 -90
  25. package/dist/{chunk-2ZWFQ74R.js → chunk-OBCP6VTG.js} +1 -1
  26. package/dist/{chunk-FLNQY74K.js → chunk-OYGMRRR7.js} +1 -1
  27. package/dist/{chunk-MPYYBRVN.js → chunk-PCXTMEGY.js} +782 -124
  28. package/dist/{chunk-4JNUMMM7.js → chunk-PGGPPZ65.js} +17 -2
  29. package/dist/{chunk-KHZNNBTN.js → chunk-QFU7ZOAD.js} +43 -39
  30. package/dist/{chunk-4ZNQFWFM.js → chunk-QIO6V46H.js} +84 -4
  31. package/dist/{chunk-IQ2VJEF6.js → chunk-QNGJRZ2D.js} +1 -1
  32. package/dist/{chunk-BM5NSDII.js → chunk-S4ANOS2M.js} +2 -2
  33. package/dist/{chunk-AQA7OZ2R.js → chunk-TFSXOIAI.js} +959 -43
  34. package/dist/{chunk-NQZUGMLW.js → chunk-TMU7JMXX.js} +184 -32
  35. package/dist/{chunk-KD5K5XIA.js → chunk-UHQOUTAX.js} +568 -88
  36. package/dist/{chunk-327AIUXL.js → chunk-UWDWGQH5.js} +11 -4
  37. package/dist/{chunk-BBB4GSDB.js → chunk-XVFENXLK.js} +2 -2
  38. package/dist/{chunk-MUEN2WOG.js → chunk-ZKSDVHGH.js} +6 -3
  39. package/dist/compare.cjs +17 -2
  40. package/dist/compare.d.cts +1 -1
  41. package/dist/compare.d.ts +1 -1
  42. package/dist/compare.js +3 -3
  43. package/dist/core/commands/formatting-commands.d.cts +2 -2
  44. package/dist/core/commands/formatting-commands.d.ts +2 -2
  45. package/dist/core/commands/image-commands.cjs +814 -45
  46. package/dist/core/commands/image-commands.d.cts +2 -2
  47. package/dist/core/commands/image-commands.d.ts +2 -2
  48. package/dist/core/commands/image-commands.js +8 -8
  49. package/dist/core/commands/section-layout-commands.d.cts +2 -2
  50. package/dist/core/commands/section-layout-commands.d.ts +2 -2
  51. package/dist/core/commands/style-commands.d.cts +2 -2
  52. package/dist/core/commands/style-commands.d.ts +2 -2
  53. package/dist/core/commands/table-structure-commands.cjs +750 -42
  54. package/dist/core/commands/table-structure-commands.d.cts +2 -2
  55. package/dist/core/commands/table-structure-commands.d.ts +2 -2
  56. package/dist/core/commands/table-structure-commands.js +6 -6
  57. package/dist/core/commands/text-commands.cjs +910 -57
  58. package/dist/core/commands/text-commands.d.cts +2 -2
  59. package/dist/core/commands/text-commands.d.ts +2 -2
  60. package/dist/core/commands/text-commands.js +8 -8
  61. package/dist/core/selection/mapping.d.cts +2 -2
  62. package/dist/core/selection/mapping.d.ts +2 -2
  63. package/dist/core/state/editor-state.cjs +17 -2
  64. package/dist/core/state/editor-state.d.cts +2 -2
  65. package/dist/core/state/editor-state.d.ts +2 -2
  66. package/dist/core/state/editor-state.js +2 -2
  67. package/dist/index.cjs +6203 -625
  68. package/dist/index.d.cts +5 -5
  69. package/dist/index.d.ts +5 -5
  70. package/dist/index.js +299 -67
  71. package/dist/io/docx-session.cjs +354 -102
  72. package/dist/io/docx-session.d.cts +4 -4
  73. package/dist/io/docx-session.d.ts +4 -4
  74. package/dist/io/docx-session.js +5 -5
  75. package/dist/legal.cjs +183 -31
  76. package/dist/legal.d.cts +1 -1
  77. package/dist/legal.d.ts +1 -1
  78. package/dist/legal.js +3 -3
  79. package/dist/{loader-CaohrhNl.d.ts → loader-BF8ju_LK.d.ts} +22 -4
  80. package/dist/{loader-BpCyGnZl.d.cts → loader-g54WRvj1.d.cts} +22 -4
  81. package/dist/{public-types-Dpch9JG0.d.cts → public-types-D_y4Ptcj.d.cts} +747 -21
  82. package/dist/{public-types-C948HNVF.d.ts → public-types-Dl1jiWjk.d.ts} +747 -21
  83. package/dist/public-types.cjs +1713 -55
  84. package/dist/public-types.d.cts +2 -2
  85. package/dist/public-types.d.ts +2 -2
  86. package/dist/public-types.js +6 -6
  87. package/dist/runtime/collab.cjs +4 -0
  88. package/dist/runtime/collab.d.cts +3 -3
  89. package/dist/runtime/collab.d.ts +3 -3
  90. package/dist/runtime/collab.js +2 -2
  91. package/dist/runtime/document-runtime.cjs +3699 -507
  92. package/dist/runtime/document-runtime.d.cts +2 -2
  93. package/dist/runtime/document-runtime.d.ts +2 -2
  94. package/dist/runtime/document-runtime.js +18 -18
  95. package/dist/{session-Dqg17V3s.d.ts → session-C1EPAkcI.d.ts} +3 -3
  96. package/dist/{session-BlXE5zxz.d.cts → session-D15QOO0Q.d.cts} +3 -3
  97. package/dist/session.cjs +951 -104
  98. package/dist/session.d.cts +5 -5
  99. package/dist/session.d.ts +5 -5
  100. package/dist/session.js +10 -8
  101. package/dist/tailwind.cjs +1752 -91
  102. package/dist/tailwind.d.cts +2 -2
  103. package/dist/tailwind.d.ts +2 -2
  104. package/dist/tailwind.js +10 -10
  105. package/dist/{types-C9vZVpKy.d.cts → types-BoSRp2Vg.d.cts} +2 -2
  106. package/dist/{types-B1tlF1bq.d.ts → types-DEvRwq9C.d.ts} +2 -2
  107. package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +3 -3
  108. package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +3 -3
  109. package/dist/ui-tailwind/editor-surface/search-plugin.js +7 -7
  110. package/dist/ui-tailwind/theme/editor-theme.css +5 -5
  111. package/dist/ui-tailwind.cjs +1752 -91
  112. package/dist/ui-tailwind.d.cts +8 -8
  113. package/dist/ui-tailwind.d.ts +8 -8
  114. package/dist/ui-tailwind.js +10 -10
  115. package/package.json +17 -5
  116. package/dist/ui-tailwind/theme/tokens.css +0 -382
@@ -69,7 +69,7 @@ function parseTextStory(content) {
69
69
  function countLogicalPositions(units) {
70
70
  let size = 0;
71
71
  for (const unit of units) {
72
- if (unit.kind !== "scope_marker") size += 1;
72
+ size += unitLogicalSize(unit);
73
73
  }
74
74
  return size;
75
75
  }
@@ -201,6 +201,9 @@ function serializeTextStory(story) {
201
201
  warningId: unit.warningId
202
202
  });
203
203
  break;
204
+ case "protected_inline":
205
+ pushInlineNode(structuredClone(unit.node));
206
+ break;
204
207
  case "scope_marker":
205
208
  pushInlineNode({
206
209
  type: unit.boundary === "start" ? "scope_marker_start" : "scope_marker_end",
@@ -249,6 +252,13 @@ function cloneStoryUnit(unit) {
249
252
  fragmentId: unit.fragmentId,
250
253
  warningId: unit.warningId
251
254
  };
255
+ case "protected_inline":
256
+ return {
257
+ kind: "protected_inline",
258
+ node: structuredClone(unit.node),
259
+ logicalSize: unit.logicalSize,
260
+ reason: unit.reason
261
+ };
252
262
  case "opaque_block":
253
263
  return {
254
264
  kind: "opaque_block",
@@ -331,7 +341,29 @@ function flattenInlineNodes(nodes, hyperlinkHref) {
331
341
  });
332
342
  break;
333
343
  case "hyperlink":
334
- units.push(...flattenInlineNodes(node.children, node.href));
344
+ units.push({
345
+ kind: "protected_inline",
346
+ node: structuredClone(node),
347
+ logicalSize: inlineLogicalLength(node),
348
+ reason: "hyperlink"
349
+ });
350
+ break;
351
+ case "field":
352
+ units.push({
353
+ kind: "protected_inline",
354
+ node: structuredClone(node),
355
+ logicalSize: inlineLogicalLength(node),
356
+ reason: "field"
357
+ });
358
+ break;
359
+ case "bookmark_start":
360
+ case "bookmark_end":
361
+ units.push({
362
+ kind: "protected_inline",
363
+ node: structuredClone(node),
364
+ logicalSize: 0,
365
+ reason: "bookmark"
366
+ });
335
367
  break;
336
368
  case "image":
337
369
  units.push({
@@ -365,6 +397,32 @@ function flattenInlineNodes(nodes, hyperlinkHref) {
365
397
  }
366
398
  return units;
367
399
  }
400
+ function unitLogicalSize(unit) {
401
+ switch (unit.kind) {
402
+ case "scope_marker":
403
+ return 0;
404
+ case "protected_inline":
405
+ return unit.logicalSize;
406
+ default:
407
+ return 1;
408
+ }
409
+ }
410
+ function inlineLogicalLength(node) {
411
+ switch (node.type) {
412
+ case "text":
413
+ return Array.from(node.text).length;
414
+ case "hyperlink":
415
+ case "field":
416
+ return node.children.reduce((total, child) => total + inlineLogicalLength(child), 0);
417
+ case "bookmark_start":
418
+ case "bookmark_end":
419
+ case "scope_marker_start":
420
+ case "scope_marker_end":
421
+ return 0;
422
+ default:
423
+ return 1;
424
+ }
425
+ }
368
426
  function extractParagraphProperties(paragraph) {
369
427
  return {
370
428
  ...paragraph.styleId ? { styleId: paragraph.styleId } : {},
@@ -795,7 +853,7 @@ function createHeaderFooterStoryKey(input) {
795
853
  function createNoteStoryKey(kind, noteId) {
796
854
  return `${kind}:${noteId}`;
797
855
  }
798
- function collectEditableTargetRefs(doc) {
856
+ function collectEditableTargetRefs(doc, cache) {
799
857
  const targets = [];
800
858
  for (const context of collectStoryBlockContexts(doc)) {
801
859
  collectEditableTargetsInBlocks(
@@ -807,17 +865,53 @@ function collectEditableTargetRefs(doc) {
807
865
  insideTextBox: false,
808
866
  tableDepth: 0
809
867
  },
810
- targets
868
+ targets,
869
+ cache
811
870
  );
812
871
  }
872
+ collectFieldRegionRefreshTargets(doc, targets);
873
+ collectBookmarkContentRangeTargets(doc, targets);
813
874
  collectReviewEditableTargets(doc, targets);
814
875
  return targets;
815
876
  }
816
- function collectEditableTargetsInBlocks(blocks, context, targets) {
877
+ function buildBlockCacheSignature(context, blockIndex) {
878
+ const cc = context.contentControl;
879
+ const tt = context.tableTarget;
880
+ const owner = tt?.editableOwnersByChildIndex?.get(blockIndex);
881
+ return [
882
+ context.storyKey,
883
+ context.insideSdt ? "1" : "0",
884
+ context.insideTextBox ? "1" : "0",
885
+ String(context.tableDepth),
886
+ cc?.sdtId ?? "",
887
+ cc?.tag ?? "",
888
+ cc?.alias ?? "",
889
+ cc?.sdtType ?? "",
890
+ cc?.lock ?? "",
891
+ tt?.tablePath ?? "",
892
+ tt?.tableDepth ?? "",
893
+ tt?.rowIndex ?? "",
894
+ tt?.cellIndex ?? "",
895
+ tt?.gridColumnStart ?? "",
896
+ tt?.cell?.verticalMerge ?? "",
897
+ tt?.cell?.gridSpan ?? "",
898
+ owner?.targetKey ?? ""
899
+ ].join("|");
900
+ }
901
+ function collectEditableTargetsInBlocks(blocks, context, targets, cache) {
817
902
  for (let blockIndex = 0; blockIndex < blocks.length; blockIndex += 1) {
818
903
  const block = blocks[blockIndex];
819
904
  if (!block) continue;
820
905
  const blockPath = `${context.basePath}/block[${blockIndex}]`;
906
+ const signature = cache !== void 0 ? buildBlockCacheSignature(context, blockIndex) : "";
907
+ if (cache !== void 0) {
908
+ const cached = cache.get(block);
909
+ if (cached !== void 0 && cached.blockPath === blockPath && cached.signature === signature) {
910
+ for (const target of cached.targets) targets.push(target);
911
+ continue;
912
+ }
913
+ }
914
+ const blockStart = targets.length;
821
915
  if (block.type === "paragraph") {
822
916
  const targetKind = editableParagraphTargetKind(context);
823
917
  if (targetKind !== null) {
@@ -829,14 +923,13 @@ function collectEditableTargetsInBlocks(blocks, context, targets) {
829
923
  blockPath,
830
924
  editableParagraphTargetPosture(targetKind),
831
925
  context.contentControl,
832
- context.tableTarget
926
+ context.tableTarget,
927
+ context.tableTarget?.editableOwnersByChildIndex?.get(blockIndex)
833
928
  )
834
929
  );
835
930
  }
836
931
  collectEditableTargetsInInlines(block.children ?? [], `${blockPath}/inline`, context, targets);
837
- continue;
838
- }
839
- if (block.type === "sdt") {
932
+ } else if (block.type === "sdt") {
840
933
  const contentControl = contentControlIdentityForSdt(block, context.contentControl);
841
934
  collectEditableTargetsInBlocks(
842
935
  block.children,
@@ -846,11 +939,10 @@ function collectEditableTargetsInBlocks(blocks, context, targets) {
846
939
  insideSdt: true,
847
940
  contentControl
848
941
  },
849
- targets
942
+ targets,
943
+ cache
850
944
  );
851
- continue;
852
- }
853
- if (block.type === "custom_xml") {
945
+ } else if (block.type === "custom_xml") {
854
946
  targets.push(createCustomXmlEditableTarget(block, context.storyKey, blockPath));
855
947
  collectEditableTargetsInBlocks(
856
948
  block.children,
@@ -858,25 +950,29 @@ function collectEditableTargetsInBlocks(blocks, context, targets) {
858
950
  ...context,
859
951
  basePath: blockPath
860
952
  },
861
- targets
953
+ targets,
954
+ cache
862
955
  );
863
- continue;
864
- }
865
- if (block.type === "opaque_block") {
956
+ } else if (block.type === "opaque_block") {
866
957
  targets.push(createOpaqueBlockEditableTarget(block, context.storyKey, blockPath));
867
- continue;
868
- }
869
- if (block.type === "alt_chunk") {
958
+ } else if (block.type === "alt_chunk") {
870
959
  targets.push(createAltChunkEditableTarget(block.relationshipId, context.storyKey, blockPath));
871
- continue;
872
- }
873
- if (block.type === "table") {
874
- collectEditableTargetsInTable(block, blockPath, context, targets);
960
+ } else if (block.type === "table") {
961
+ collectEditableTargetsInTable(block, blockPath, context, targets, cache);
962
+ }
963
+ if (cache !== void 0) {
964
+ const blockTargets = targets.slice(blockStart);
965
+ cache.set(block, {
966
+ blockPath,
967
+ signature,
968
+ targets: blockTargets
969
+ });
875
970
  }
876
971
  }
877
972
  }
878
- function collectEditableTargetsInTable(table, tablePath, context, targets) {
973
+ function collectEditableTargetsInTable(table, tablePath, context, targets, cache) {
879
974
  const tableDepth = context.tableDepth + 1;
975
+ const verticalMergeOwners = [];
880
976
  targets.push(createTableStructureTarget({
881
977
  scope: "table",
882
978
  kind: "table-structure-table",
@@ -915,6 +1011,10 @@ function collectEditableTargetsInTable(table, tablePath, context, targets) {
915
1011
  const cell = row.cells[cellIndex];
916
1012
  if (!cell) continue;
917
1013
  const gridSpan = cell.gridSpan ?? 1;
1014
+ const continuationOwner = cell.verticalMerge === "continue" ? findVerticalMergeOwner(verticalMergeOwners, gridColumnStart, gridSpan) : null;
1015
+ if (cell.verticalMerge !== "continue") {
1016
+ clearVerticalMergeOwners(verticalMergeOwners, gridColumnStart, gridSpan);
1017
+ }
918
1018
  targets.push(createTableStructureTarget({
919
1019
  scope: "cell",
920
1020
  kind: "table-structure-cell",
@@ -957,15 +1057,136 @@ function collectEditableTargetsInTable(table, tablePath, context, targets) {
957
1057
  row,
958
1058
  cellIndex,
959
1059
  cell,
960
- gridColumnStart
1060
+ gridColumnStart,
1061
+ ...continuationOwner ? {
1062
+ editableOwnersByChildIndex: continuationOwnerTargetsByChildIndex(
1063
+ continuationOwner,
1064
+ cell.children.length
1065
+ )
1066
+ } : {}
961
1067
  }
962
1068
  },
963
- targets
1069
+ targets,
1070
+ cache
964
1071
  );
1072
+ if (cell.verticalMerge === "restart") {
1073
+ verticalMergeOwners.push(createVerticalMergeOwnerState({
1074
+ context,
1075
+ table,
1076
+ tablePath,
1077
+ tableDepth,
1078
+ rowIndex,
1079
+ row,
1080
+ cellIndex,
1081
+ cell,
1082
+ gridColumnStart,
1083
+ gridSpan
1084
+ }));
1085
+ }
965
1086
  gridColumnStart += gridSpan;
966
1087
  }
967
1088
  }
968
1089
  }
1090
+ function findVerticalMergeOwner(owners, gridColumnStart, gridSpan) {
1091
+ return owners.find(
1092
+ (owner) => owner.gridColumnStart === gridColumnStart && owner.gridSpan === gridSpan
1093
+ ) ?? null;
1094
+ }
1095
+ function clearVerticalMergeOwners(owners, gridColumnStart, gridSpan) {
1096
+ const gridColumnEnd = gridColumnStart + gridSpan;
1097
+ for (let index = owners.length - 1; index >= 0; index -= 1) {
1098
+ const owner = owners[index];
1099
+ if (!owner) continue;
1100
+ const ownerEnd = owner.gridColumnStart + owner.gridSpan;
1101
+ if (gridColumnStart < ownerEnd && owner.gridColumnStart < gridColumnEnd) {
1102
+ owners.splice(index, 1);
1103
+ }
1104
+ }
1105
+ }
1106
+ function continuationOwnerTargetsByChildIndex(owner, childCount) {
1107
+ if (!owner.fallbackOwnerTarget) return void 0;
1108
+ const targets = /* @__PURE__ */ new Map();
1109
+ for (let childIndex = 0; childIndex < childCount; childIndex += 1) {
1110
+ targets.set(
1111
+ childIndex,
1112
+ owner.ownerTargetsByChildIndex.get(childIndex) ?? owner.fallbackOwnerTarget
1113
+ );
1114
+ }
1115
+ return targets;
1116
+ }
1117
+ function createVerticalMergeOwnerState(input) {
1118
+ const ownerTargetsByChildIndex = /* @__PURE__ */ new Map();
1119
+ for (let childIndex = 0; childIndex < input.cell.children.length; childIndex += 1) {
1120
+ const owner = createVerticalMergeEditableOwner({ ...input, childIndex });
1121
+ if (owner) ownerTargetsByChildIndex.set(childIndex, owner);
1122
+ }
1123
+ return {
1124
+ gridColumnStart: input.gridColumnStart,
1125
+ gridSpan: input.gridSpan,
1126
+ ownerTargetsByChildIndex,
1127
+ ...ownerTargetsByChildIndex.size > 0 ? { fallbackOwnerTarget: ownerTargetsByChildIndex.values().next().value } : {}
1128
+ };
1129
+ }
1130
+ function createVerticalMergeEditableOwner(input) {
1131
+ const child = input.cell.children[input.childIndex];
1132
+ if (child?.type !== "paragraph") return null;
1133
+ const ownerTableTarget = {
1134
+ table: input.table,
1135
+ tablePath: input.tablePath,
1136
+ tableDepth: input.tableDepth,
1137
+ rowIndex: input.rowIndex,
1138
+ row: input.row,
1139
+ cellIndex: input.cellIndex,
1140
+ cell: input.cell,
1141
+ gridColumnStart: input.gridColumnStart
1142
+ };
1143
+ const kind = editableParagraphTargetKind({
1144
+ ...input.context,
1145
+ basePath: `${input.tablePath}/row[${input.rowIndex}]/cell[${input.cellIndex}]`,
1146
+ tableDepth: input.tableDepth,
1147
+ tableTarget: ownerTableTarget
1148
+ });
1149
+ if (!kind) return null;
1150
+ const blockPath = `${input.tablePath}/row[${input.rowIndex}]/cell[${input.cellIndex}]/block[${input.childIndex}]`;
1151
+ const paragraphTextHash = hashText(collectParagraphText(child));
1152
+ const table = createTableIdentity({
1153
+ scope: "text",
1154
+ context: {
1155
+ storyKey: input.context.storyKey,
1156
+ insideSdt: input.context.contentControl !== void 0
1157
+ },
1158
+ ...ownerTableTarget
1159
+ });
1160
+ return {
1161
+ targetKey: `${input.context.storyKey}:${blockPath}:text`,
1162
+ kind,
1163
+ storyKey: input.context.storyKey,
1164
+ blockPath,
1165
+ leafPath: `${blockPath}/inline`,
1166
+ commandFamily: "text-leaf",
1167
+ reason: "vertical-merge-restart-cell",
1168
+ canonicalAddress: ownerRoutingFromAddress(
1169
+ createTableTargetCanonicalAddress(
1170
+ table,
1171
+ "paragraph",
1172
+ paragraphTextHash,
1173
+ { rangeBoundary: { boundaryKind: "cell-fragment" } }
1174
+ )
1175
+ ),
1176
+ table: {
1177
+ tableKey: table.tableKey,
1178
+ tablePath: table.tablePath,
1179
+ ...table.sourceRef !== void 0 ? { sourceRef: table.sourceRef } : {},
1180
+ ...table.rowSourceRef !== void 0 ? { rowSourceRef: table.rowSourceRef } : {},
1181
+ ...table.cellSourceRef !== void 0 ? { cellSourceRef: table.cellSourceRef } : {},
1182
+ ...table.rowIndex !== void 0 ? { rowIndex: table.rowIndex } : {},
1183
+ ...table.cellIndex !== void 0 ? { cellIndex: table.cellIndex } : {},
1184
+ ...table.gridColumnStart !== void 0 ? { gridColumnStart: table.gridColumnStart } : {},
1185
+ ...table.gridSpan !== void 0 ? { gridSpan: table.gridSpan } : {},
1186
+ ...table.verticalMerge !== void 0 ? { verticalMerge: table.verticalMerge } : {}
1187
+ }
1188
+ };
1189
+ }
969
1190
  function computeTableStructureColumnCount(table) {
970
1191
  let columnCount = table.gridColumns.length;
971
1192
  for (const row of table.rows) {
@@ -985,6 +1206,7 @@ function createTableStructureTarget(input) {
985
1206
  const columnPath = input.columnIndex !== void 0 ? `${input.tablePath}/column[${input.columnIndex}]` : void 0;
986
1207
  const blockPath = cellPath ?? rowPath ?? columnPath ?? input.tablePath;
987
1208
  const tableIdentity = createTableIdentity(input);
1209
+ const targetHash = hashTableStructureTarget(input);
988
1210
  return {
989
1211
  targetKey: `${tableKey}:structure:${tableIdentity.operationScope}${tableTargetSuffix(tableIdentity)}`,
990
1212
  kind: input.kind,
@@ -996,8 +1218,14 @@ function createTableStructureTarget(input) {
996
1218
  ...input.table.sourceRef !== void 0 ? { sourceRef: input.table.sourceRef } : {},
997
1219
  ...input.context.contentControl !== void 0 ? { contentControl: input.context.contentControl } : {},
998
1220
  table: tableIdentity,
1221
+ canonicalAddress: createTableTargetCanonicalAddress(
1222
+ tableIdentity,
1223
+ tableStructureBlockType(input.scope),
1224
+ targetHash,
1225
+ { rangeBoundary: { boundaryKind: "table-grid" } }
1226
+ ),
999
1227
  staleCheck: {
1000
- targetHash: hashTableStructureTarget(input),
1228
+ targetHash,
1001
1229
  childCount: input.scope === "table" ? input.table.rows.length : input.scope === "row" ? input.row?.cells.length ?? 0 : input.scope === "cell" || input.scope === "span" ? input.cell?.children.length ?? 0 : computeTableStructureColumnCount(input.table),
1002
1230
  blockType: tableStructureBlockType(input.scope),
1003
1231
  ...input.table.sourceRef !== void 0 ? { sourceRef: input.table.sourceRef } : {}
@@ -1008,10 +1236,15 @@ function createTableStructureTarget(input) {
1008
1236
  function createTableIdentity(input) {
1009
1237
  const tableKey = `${input.context.storyKey}:${input.tablePath}`;
1010
1238
  const columnCount = computeTableStructureColumnCount(input.table);
1239
+ const rowRange = tableFragmentRowRange(input).rowRange;
1240
+ const columnRange = tableFragmentColumnRange(input, columnCount).columnRange;
1011
1241
  const base = {
1012
1242
  operationScope: input.scope,
1013
1243
  tableKey,
1014
1244
  tablePath: input.tablePath,
1245
+ ...input.table.sourceRef !== void 0 ? { sourceRef: input.table.sourceRef } : {},
1246
+ ...input.row?.sourceRef !== void 0 ? { rowSourceRef: input.row.sourceRef } : {},
1247
+ ...input.cell?.sourceRef !== void 0 ? { cellSourceRef: input.cell.sourceRef } : {},
1015
1248
  ...tablePathIndexes(input.tablePath),
1016
1249
  tableDepth: input.tableDepth,
1017
1250
  ...input.tableDepth >= 2 ? { nestedTable: true } : {},
@@ -1019,7 +1252,10 @@ function createTableIdentity(input) {
1019
1252
  ...input.context.storyKey !== MAIN_STORY_KEY ? { secondaryStory: true } : {},
1020
1253
  rowCount: input.table.rows.length,
1021
1254
  columnCount,
1022
- fragment: createTableFragmentIdentity(input, tableKey, columnCount)
1255
+ fragment: createTableFragmentIdentity(input, tableKey, columnCount),
1256
+ ...input.cell !== void 0 ? {
1257
+ cellFragment: createTableCellFragmentIdentity(input, tableKey, rowRange, columnRange)
1258
+ } : {}
1023
1259
  };
1024
1260
  return {
1025
1261
  ...base,
@@ -1033,6 +1269,25 @@ function createTableIdentity(input) {
1033
1269
  ...input.cell !== void 0 ? { blockCount: input.cell.children.length } : {}
1034
1270
  };
1035
1271
  }
1272
+ function createTableCellFragmentIdentity(input, tableKey, rowRange, columnRange) {
1273
+ const text = (input.cell?.children ?? []).map(blockTextForTargetHash).join("");
1274
+ return {
1275
+ fragmentKey: hashText(JSON.stringify({
1276
+ tableKey,
1277
+ rowIndex: input.rowIndex ?? null,
1278
+ cellIndex: input.cellIndex ?? null,
1279
+ gridColumnStart: input.gridColumnStart ?? null,
1280
+ gridSpan: input.cell?.gridSpan ?? 1,
1281
+ verticalMerge: input.cell?.verticalMerge ?? null,
1282
+ sourceId: input.cell?.sourceRef?.sourceId ?? null
1283
+ })),
1284
+ textHash: hashText(text),
1285
+ blockCount: input.cell?.children.length ?? 0,
1286
+ ...rowRange !== void 0 ? { rowRange } : {},
1287
+ ...columnRange !== void 0 ? { columnRange } : {},
1288
+ ...sourceJoinHashForRefs(input.table.sourceRef, input.row?.sourceRef, input.cell?.sourceRef)
1289
+ };
1290
+ }
1036
1291
  function tablePathIndexes(tablePath) {
1037
1292
  const blockIndexes = [...tablePath.matchAll(/\/block\[(\d+)\]/gu)].map((match) => Number(match[1]));
1038
1293
  const storyBlockIndex = blockIndexes[0];
@@ -1198,13 +1453,39 @@ function collectEditableTargetsInInlines(inlines, basePath, context, targets) {
1198
1453
  }
1199
1454
  }
1200
1455
  }
1201
- function createParagraphEditableTarget(paragraph, kind, storyKey, blockPath, targetPosture = { editability: "editable", posture: { blockers: [] } }, contentControl, tableTarget) {
1456
+ function createParagraphEditableTarget(paragraph, kind, storyKey, blockPath, targetPosture = { editability: "editable", posture: { blockers: [] } }, contentControl, tableTarget, editableOwner) {
1202
1457
  const paragraphText = collectParagraphText(paragraph);
1458
+ const paragraphTextHash = hashText(paragraphText);
1203
1459
  const sourceRef = paragraph.sourceRef;
1204
1460
  const lockedContentControl = contentControlLocksContent(contentControl);
1205
- const posture = lockedContentControl ? mergeTargetPosture(targetPosture.posture, ["locked-content-control"], {
1461
+ const syntheticLayoutCell = tableTarget?.cell?.verticalMerge === "continue";
1462
+ const tableIdentity = tableTarget !== void 0 ? createTableIdentity({
1463
+ scope: "text",
1464
+ context: { storyKey, insideSdt: contentControl !== void 0 },
1465
+ ...tableTarget
1466
+ }) : void 0;
1467
+ const listAddress = tableIdentity === void 0 && paragraph.numbering !== void 0 ? createCanonicalAddress({
1468
+ addressKind: "list-item-text",
1469
+ storyKey,
1470
+ staleCheckKind: "paragraph",
1471
+ operationScope: "list-text",
1472
+ sourceRefs: [sourceRef],
1473
+ staleHash: paragraphTextHash,
1474
+ rangeBoundary: { boundaryKind: "list-item-text" },
1475
+ discriminator: {
1476
+ blockPath,
1477
+ numberingInstanceId: paragraph.numbering.numberingInstanceId,
1478
+ level: paragraph.numbering.level,
1479
+ sourceId: sourceRef?.sourceId ?? null,
1480
+ paraId: paragraph.wordExtensionIds?.paraId ?? null,
1481
+ textId: paragraph.wordExtensionIds?.textId ?? null
1482
+ }
1483
+ }) : void 0;
1484
+ const tableAwarePosture = syntheticLayoutCell ? mergeTargetPosture(targetPosture.posture, ["synthetic-layout-cell"]) : targetPosture.posture;
1485
+ const posture = lockedContentControl ? mergeTargetPosture(tableAwarePosture, ["locked-content-control"], {
1206
1486
  lockedContentControl: true
1207
- }) : targetPosture.posture;
1487
+ }) : tableAwarePosture;
1488
+ const editability = lockedContentControl || syntheticLayoutCell ? "non-editable" : targetPosture.editability;
1208
1489
  return {
1209
1490
  targetKey: `${storyKey}:${blockPath}:text`,
1210
1491
  kind,
@@ -1212,12 +1493,24 @@ function createParagraphEditableTarget(paragraph, kind, storyKey, blockPath, tar
1212
1493
  blockPath,
1213
1494
  leafPath: `${blockPath}/inline`,
1214
1495
  commandFamily: "text-leaf",
1215
- editability: lockedContentControl ? "non-editable" : targetPosture.editability,
1496
+ editability,
1216
1497
  ...sourceRef !== void 0 ? { sourceRef } : {},
1217
1498
  ...contentControl !== void 0 ? { contentControl } : {},
1218
- ...tableTarget !== void 0 ? { table: createTableIdentity({ scope: "text", context: { storyKey, insideSdt: contentControl !== void 0 }, ...tableTarget }) } : {},
1499
+ ...tableIdentity !== void 0 ? { table: tableIdentity } : {},
1500
+ ...editableOwner !== void 0 ? { editableOwner } : {},
1501
+ ...tableIdentity !== void 0 ? {
1502
+ canonicalAddress: createTableTargetCanonicalAddress(
1503
+ tableIdentity,
1504
+ "paragraph",
1505
+ paragraphTextHash,
1506
+ {
1507
+ rangeBoundary: { boundaryKind: "cell-fragment" },
1508
+ owner: editableOwner?.canonicalAddress
1509
+ }
1510
+ )
1511
+ } : listAddress !== void 0 ? { canonicalAddress: listAddress } : {},
1219
1512
  staleCheck: {
1220
- paragraphTextHash: hashText(paragraphText),
1513
+ paragraphTextHash,
1221
1514
  paragraphTextLength: Array.from(paragraphText).length,
1222
1515
  inlineCount: paragraph.children?.length ?? 0,
1223
1516
  blockType: "paragraph",
@@ -1248,12 +1541,27 @@ function collectInlineTarget(inline, storyKey, inlinePath, targets) {
1248
1541
  return;
1249
1542
  case "hyperlink":
1250
1543
  targets.push(createHyperlinkEditableTarget(inline, storyKey, inlinePath));
1544
+ targets.push(createHyperlinkDestinationEditableTarget(inline, storyKey, inlinePath));
1251
1545
  return;
1252
1546
  case "bookmark_start":
1253
- targets.push(createBookmarkEditableTarget(inline.bookmarkId, inline.name, storyKey, inlinePath, "start"));
1547
+ targets.push(createBookmarkEditableTarget(
1548
+ inline.bookmarkId,
1549
+ inline.name,
1550
+ storyKey,
1551
+ inlinePath,
1552
+ "start",
1553
+ inline.sourceRef
1554
+ ));
1254
1555
  return;
1255
1556
  case "bookmark_end":
1256
- targets.push(createBookmarkEditableTarget(inline.bookmarkId, void 0, storyKey, inlinePath, "end"));
1557
+ targets.push(createBookmarkEditableTarget(
1558
+ inline.bookmarkId,
1559
+ void 0,
1560
+ storyKey,
1561
+ inlinePath,
1562
+ "end",
1563
+ inline.sourceRef
1564
+ ));
1257
1565
  return;
1258
1566
  case "image":
1259
1567
  targets.push(createImageEditableTarget(inline, storyKey, inlinePath));
@@ -1277,6 +1585,7 @@ function collectInlineTarget(inline, storyKey, inlinePath, targets) {
1277
1585
  function createFieldEditableTarget(field, storyKey, inlinePath) {
1278
1586
  const resultText = field.children.map(inlineTextForTargetHash).join("");
1279
1587
  const sourceRef = field.sourceRef;
1588
+ const targetHash = hashText(`${field.instruction}\0${resultText}`);
1280
1589
  const preserveOnly = field.refreshStatus === "preserve-only" || field.fieldFamily === "UNKNOWN";
1281
1590
  const blockers = preserveOnly ? ["field-generated-text", "preserve-only"] : ["field-generated-text", "unmodeled-target"];
1282
1591
  return {
@@ -1296,9 +1605,28 @@ function createFieldEditableTarget(field, storyKey, inlinePath) {
1296
1605
  ...field.locked !== void 0 ? { locked: field.locked } : {},
1297
1606
  ...field.dirty !== void 0 ? { dirty: field.dirty } : {}
1298
1607
  },
1608
+ canonicalAddress: createCanonicalAddress({
1609
+ addressKind: "field-result",
1610
+ storyKey,
1611
+ staleCheckKind: "field",
1612
+ operationScope: "field-refresh",
1613
+ sourceRefs: [sourceRef],
1614
+ staleHash: targetHash,
1615
+ rangeBoundary: {
1616
+ boundaryKind: "field-result",
1617
+ from: 0,
1618
+ to: Array.from(resultText).length
1619
+ },
1620
+ discriminator: {
1621
+ canonicalFieldId: field.canonicalFieldId ?? null,
1622
+ fieldFamily: field.fieldFamily ?? null,
1623
+ fieldTarget: field.fieldTarget ?? null,
1624
+ sourceId: sourceRef?.sourceId ?? null
1625
+ }
1626
+ }),
1299
1627
  staleCheck: {
1300
1628
  blockType: "field",
1301
- targetHash: hashText(`${field.instruction}\0${resultText}`),
1629
+ targetHash,
1302
1630
  targetTextLength: Array.from(resultText).length,
1303
1631
  childCount: field.children.length,
1304
1632
  ...sourceRef !== void 0 ? { sourceRef } : {}
@@ -1312,6 +1640,7 @@ function createFieldEditableTarget(field, storyKey, inlinePath) {
1312
1640
  function createHyperlinkEditableTarget(hyperlink, storyKey, inlinePath) {
1313
1641
  const text = hyperlink.children.map(inlineTextForTargetHash).join("");
1314
1642
  const sourceRef = hyperlink.sourceRef ?? hyperlink.fieldCarrier?.sourceRef;
1643
+ const targetHash = hashText(`${hyperlink.href}\0${text}`);
1315
1644
  return {
1316
1645
  targetKey: `${storyKey}:${inlinePath}:hyperlink`,
1317
1646
  kind: "hyperlink-text",
@@ -1322,9 +1651,25 @@ function createHyperlinkEditableTarget(hyperlink, storyKey, inlinePath) {
1322
1651
  editability: "editable",
1323
1652
  ...sourceRef !== void 0 ? { sourceRef } : {},
1324
1653
  link: { href: hyperlink.href },
1654
+ canonicalAddress: createCanonicalAddress({
1655
+ addressKind: "hyperlink-display-text",
1656
+ storyKey,
1657
+ staleCheckKind: "hyperlink",
1658
+ sourceRefs: [sourceRef],
1659
+ staleHash: targetHash,
1660
+ rangeBoundary: {
1661
+ boundaryKind: "hyperlink-display",
1662
+ from: 0,
1663
+ to: Array.from(text).length
1664
+ },
1665
+ discriminator: {
1666
+ href: hyperlink.href,
1667
+ sourceId: sourceRef?.sourceId ?? null
1668
+ }
1669
+ }),
1325
1670
  staleCheck: {
1326
1671
  blockType: "hyperlink",
1327
- targetHash: hashText(`${hyperlink.href}\0${text}`),
1672
+ targetHash,
1328
1673
  targetTextLength: Array.from(text).length,
1329
1674
  childCount: hyperlink.children.length,
1330
1675
  ...sourceRef !== void 0 ? { sourceRef } : {}
@@ -1332,7 +1677,52 @@ function createHyperlinkEditableTarget(hyperlink, storyKey, inlinePath) {
1332
1677
  posture: { blockers: [] }
1333
1678
  };
1334
1679
  }
1335
- function createBookmarkEditableTarget(bookmarkId, bookmarkName, storyKey, inlinePath, edge) {
1680
+ function createHyperlinkDestinationEditableTarget(hyperlink, storyKey, inlinePath) {
1681
+ const sourceRef = hyperlink.sourceRef ?? hyperlink.fieldCarrier?.sourceRef;
1682
+ const destinationKind = hyperlink.href.startsWith("#") ? "internal-anchor" : "external";
1683
+ const targetHash = hashText(`destination\0${hyperlink.href}`);
1684
+ return {
1685
+ targetKey: `${storyKey}:${inlinePath}:hyperlink-destination`,
1686
+ kind: "hyperlink-destination",
1687
+ storyKey,
1688
+ blockPath: inlinePath,
1689
+ leafPath: `${inlinePath}/destination`,
1690
+ commandFamily: "link-bookmark",
1691
+ editability: "non-editable",
1692
+ ...sourceRef !== void 0 ? { sourceRef } : {},
1693
+ link: {
1694
+ href: hyperlink.href,
1695
+ destinationKind
1696
+ },
1697
+ canonicalAddress: createCanonicalAddress({
1698
+ addressKind: "hyperlink-destination",
1699
+ storyKey,
1700
+ staleCheckKind: "hyperlink",
1701
+ operationScope: "link-destination",
1702
+ sourceRefs: [sourceRef],
1703
+ staleHash: targetHash,
1704
+ rangeBoundary: {
1705
+ boundaryKind: "hyperlink-destination",
1706
+ ...sourceRef !== void 0 ? { startSourceJoinHash: sourceJoinHash([sourceRef]) } : {},
1707
+ ...sourceRef !== void 0 ? { endSourceJoinHash: sourceJoinHash([sourceRef]) } : {}
1708
+ },
1709
+ discriminator: {
1710
+ href: hyperlink.href,
1711
+ destinationKind,
1712
+ sourceId: sourceRef?.sourceId ?? null
1713
+ }
1714
+ }),
1715
+ staleCheck: {
1716
+ blockType: "hyperlink",
1717
+ targetHash,
1718
+ childCount: hyperlink.children.length,
1719
+ ...sourceRef !== void 0 ? { sourceRef } : {}
1720
+ },
1721
+ posture: { blockers: ["unmodeled-target"] }
1722
+ };
1723
+ }
1724
+ function createBookmarkEditableTarget(bookmarkId, bookmarkName, storyKey, inlinePath, edge, sourceRef) {
1725
+ const targetHash = hashText(`${edge}\0${bookmarkId}\0${bookmarkName ?? ""}`);
1336
1726
  return {
1337
1727
  targetKey: `${storyKey}:${inlinePath}:bookmark:${edge}:${bookmarkId}`,
1338
1728
  kind: "bookmark-anchor",
@@ -1341,14 +1731,34 @@ function createBookmarkEditableTarget(bookmarkId, bookmarkName, storyKey, inline
1341
1731
  leafPath: inlinePath,
1342
1732
  commandFamily: "link-bookmark",
1343
1733
  editability: "non-editable",
1734
+ ...sourceRef !== void 0 ? { sourceRef } : {},
1344
1735
  link: {
1345
1736
  bookmarkId,
1346
1737
  ...bookmarkName !== void 0 ? { bookmarkName } : {}
1347
1738
  },
1739
+ canonicalAddress: createCanonicalAddress({
1740
+ addressKind: "bookmark-anchor",
1741
+ storyKey,
1742
+ staleCheckKind: "bookmark",
1743
+ sourceRefs: [sourceRef],
1744
+ staleHash: targetHash,
1745
+ rangeBoundary: {
1746
+ boundaryKind: "bookmark-anchor",
1747
+ ...sourceRef !== void 0 ? { startSourceJoinHash: sourceJoinHash([sourceRef]) } : {},
1748
+ ...sourceRef !== void 0 ? { endSourceJoinHash: sourceJoinHash([sourceRef]) } : {}
1749
+ },
1750
+ discriminator: {
1751
+ bookmarkId,
1752
+ bookmarkName: bookmarkName ?? null,
1753
+ edge,
1754
+ sourceId: sourceRef?.sourceId ?? null
1755
+ }
1756
+ }),
1348
1757
  staleCheck: {
1349
1758
  blockType: "bookmark",
1350
- targetHash: hashText(`${edge}\0${bookmarkId}\0${bookmarkName ?? ""}`),
1351
- childCount: 0
1759
+ targetHash,
1760
+ childCount: 0,
1761
+ ...sourceRef !== void 0 ? { sourceRef } : {}
1352
1762
  },
1353
1763
  posture: { blockers: ["unmodeled-target"] }
1354
1764
  };
@@ -1396,6 +1806,7 @@ function createObjectEditableTarget(inline, storyKey, inlinePath) {
1396
1806
  storyKey,
1397
1807
  inlinePath,
1398
1808
  objectKind: "ole",
1809
+ sourceRef: inline.sourceRef,
1399
1810
  targetHash: `${inline.id}\0${inline.relationshipId}`,
1400
1811
  object: {
1401
1812
  objectKind: "ole",
@@ -1517,6 +1928,167 @@ function createOpaqueEditableTarget(input) {
1517
1928
  }
1518
1929
  };
1519
1930
  }
1931
+ function collectFieldRegionRefreshTargets(doc, targets) {
1932
+ for (const region of collectCanonicalFieldRegionIdentities(doc)) {
1933
+ targets.push(createFieldRegionRefreshEditableTarget(region));
1934
+ }
1935
+ }
1936
+ function createFieldRegionRefreshEditableTarget(region) {
1937
+ const isToc = region.kind === "toc-region" || region.fieldFamily === "TOC";
1938
+ const sourceRef = region.sourceRef;
1939
+ const targetHash = hashText(JSON.stringify({
1940
+ regionId: region.regionId,
1941
+ canonicalFieldId: region.canonicalFieldId,
1942
+ fieldFamily: region.fieldFamily,
1943
+ refreshStatus: region.refreshStatus,
1944
+ tocId: region.tocId ?? null,
1945
+ resultRange: region.resultRange ?? null,
1946
+ status: region.status ?? null
1947
+ }));
1948
+ return {
1949
+ targetKey: `${region.storyKey}:field-region:${region.regionId}:refresh`,
1950
+ kind: isToc ? "toc-region-refresh" : "field-region-refresh",
1951
+ storyKey: region.storyKey,
1952
+ blockPath: `${region.storyKey}/field-region[${region.regionId}]`,
1953
+ leafPath: `${region.storyKey}/field-region[${region.regionId}]/refresh`,
1954
+ commandFamily: "field",
1955
+ editability: "non-editable",
1956
+ ...sourceRef !== void 0 ? { sourceRef } : {},
1957
+ field: {
1958
+ canonicalFieldId: region.canonicalFieldId,
1959
+ regionId: region.regionId,
1960
+ fieldFamily: region.fieldFamily,
1961
+ refreshStatus: region.refreshStatus,
1962
+ ...region.sourcePath !== void 0 ? { sourcePath: region.sourcePath } : {},
1963
+ ...region.tocId !== void 0 ? { tocId: region.tocId } : {},
1964
+ ...region.resultRange !== void 0 ? {
1965
+ resultRangeFromParagraphIndex: region.resultRange.fromParagraphIndex,
1966
+ resultRangeToParagraphIndex: region.resultRange.toParagraphIndex
1967
+ } : {},
1968
+ ...region.status !== void 0 ? { status: region.status } : {},
1969
+ ...region.cachedEntryCount !== void 0 ? { cachedEntryCount: region.cachedEntryCount } : {},
1970
+ ...region.generatedEntryCount !== void 0 ? { generatedEntryCount: region.generatedEntryCount } : {}
1971
+ },
1972
+ canonicalAddress: createCanonicalAddress({
1973
+ addressKind: isToc ? "toc-region-refresh" : "field-region-refresh",
1974
+ storyKey: region.storyKey,
1975
+ staleCheckKind: "field",
1976
+ operationScope: isToc ? "toc-refresh" : "field-refresh",
1977
+ sourceRefs: [sourceRef],
1978
+ staleHash: targetHash,
1979
+ rangeBoundary: {
1980
+ boundaryKind: "field-region",
1981
+ ...region.resultRange !== void 0 ? {
1982
+ from: region.resultRange.fromParagraphIndex,
1983
+ to: region.resultRange.toParagraphIndex
1984
+ } : { from: region.paragraphIndex, to: region.paragraphIndex }
1985
+ },
1986
+ discriminator: {
1987
+ regionId: region.regionId,
1988
+ canonicalFieldId: region.canonicalFieldId,
1989
+ fieldIndex: region.fieldIndex,
1990
+ fieldFamily: region.fieldFamily,
1991
+ tocId: region.tocId ?? null
1992
+ }
1993
+ }),
1994
+ staleCheck: {
1995
+ blockType: "field",
1996
+ targetHash,
1997
+ childCount: region.cachedEntryCount ?? 0,
1998
+ ...sourceRef !== void 0 ? { sourceRef } : {}
1999
+ },
2000
+ posture: {
2001
+ blockers: ["field-generated-text", "unmodeled-target"]
2002
+ }
2003
+ };
2004
+ }
2005
+ function collectBookmarkContentRangeTargets(doc, targets) {
2006
+ const candidates = /* @__PURE__ */ new Map();
2007
+ for (const context of collectStoryBlockContexts(doc)) {
2008
+ walkBlocks(context.blocks, context.storyKey, context.basePath, {
2009
+ inline(inline, _blockPath, inlinePath) {
2010
+ if (inline.type !== "bookmark_start" && inline.type !== "bookmark_end") return;
2011
+ const key = `${context.storyKey}:${inline.bookmarkId}`;
2012
+ const previous = candidates.get(key);
2013
+ if (inline.type === "bookmark_start") {
2014
+ candidates.set(key, {
2015
+ ...previous ?? { storyKey: context.storyKey, bookmarkId: inline.bookmarkId },
2016
+ bookmarkName: inline.name,
2017
+ startPath: inlinePath,
2018
+ startSourceRef: inline.sourceRef
2019
+ });
2020
+ return;
2021
+ }
2022
+ candidates.set(key, {
2023
+ ...previous ?? { storyKey: context.storyKey, bookmarkId: inline.bookmarkId },
2024
+ endPath: inlinePath,
2025
+ endSourceRef: inline.sourceRef
2026
+ });
2027
+ }
2028
+ });
2029
+ }
2030
+ for (const candidate of candidates.values()) {
2031
+ if (candidate.startPath === void 0 || candidate.endPath === void 0) continue;
2032
+ targets.push(createBookmarkContentRangeEditableTarget({
2033
+ ...candidate,
2034
+ startPath: candidate.startPath,
2035
+ endPath: candidate.endPath
2036
+ }));
2037
+ }
2038
+ }
2039
+ function createBookmarkContentRangeEditableTarget(candidate) {
2040
+ const startSourceJoinHash = sourceJoinHash([candidate.startSourceRef]);
2041
+ const endSourceJoinHash = sourceJoinHash([candidate.endSourceRef]);
2042
+ const rangeKey = hashText(JSON.stringify({
2043
+ storyKey: candidate.storyKey,
2044
+ bookmarkId: candidate.bookmarkId,
2045
+ bookmarkName: candidate.bookmarkName ?? null,
2046
+ startSourceId: candidate.startSourceRef?.sourceId ?? null,
2047
+ endSourceId: candidate.endSourceRef?.sourceId ?? null
2048
+ }));
2049
+ const targetHash = hashText(`range\0${candidate.bookmarkId}\0${candidate.bookmarkName ?? ""}\0${candidate.startPath}\0${candidate.endPath}`);
2050
+ return {
2051
+ targetKey: `${candidate.storyKey}:bookmark:${candidate.bookmarkId}:content-range`,
2052
+ kind: "bookmark-content-range",
2053
+ storyKey: candidate.storyKey,
2054
+ blockPath: `${candidate.storyKey}/bookmark[${candidate.bookmarkId}]`,
2055
+ leafPath: `${candidate.storyKey}/bookmark[${candidate.bookmarkId}]/content-range`,
2056
+ commandFamily: "link-bookmark",
2057
+ editability: "non-editable",
2058
+ ...candidate.startSourceRef !== void 0 ? { sourceRef: candidate.startSourceRef } : {},
2059
+ link: {
2060
+ bookmarkId: candidate.bookmarkId,
2061
+ ...candidate.bookmarkName !== void 0 ? { bookmarkName: candidate.bookmarkName } : {},
2062
+ rangeKey
2063
+ },
2064
+ canonicalAddress: createCanonicalAddress({
2065
+ addressKind: "bookmark-content-range",
2066
+ storyKey: candidate.storyKey,
2067
+ staleCheckKind: "bookmark",
2068
+ operationScope: "bookmark-range",
2069
+ sourceRefs: [candidate.startSourceRef, candidate.endSourceRef],
2070
+ staleHash: targetHash,
2071
+ rangeBoundary: {
2072
+ boundaryKind: "bookmark-content",
2073
+ ...startSourceJoinHash !== void 0 ? { startSourceJoinHash } : {},
2074
+ ...endSourceJoinHash !== void 0 ? { endSourceJoinHash } : {}
2075
+ },
2076
+ discriminator: {
2077
+ bookmarkId: candidate.bookmarkId,
2078
+ bookmarkName: candidate.bookmarkName ?? null,
2079
+ startSourceId: candidate.startSourceRef?.sourceId ?? null,
2080
+ endSourceId: candidate.endSourceRef?.sourceId ?? null
2081
+ }
2082
+ }),
2083
+ staleCheck: {
2084
+ blockType: "bookmark",
2085
+ targetHash,
2086
+ childCount: 2,
2087
+ ...candidate.startSourceRef !== void 0 ? { sourceRef: candidate.startSourceRef } : {}
2088
+ },
2089
+ posture: { blockers: ["unmodeled-target"] }
2090
+ };
2091
+ }
1520
2092
  function inlineObjectKind(inline) {
1521
2093
  switch (inline.type) {
1522
2094
  case "chart_preview":
@@ -1639,6 +2211,16 @@ function collectParagraphText(paragraph) {
1639
2211
  }
1640
2212
  return text;
1641
2213
  }
2214
+ function blockTextForTargetHash(block) {
2215
+ if (block.type === "paragraph") return collectParagraphText(block);
2216
+ if (block.type === "sdt" || block.type === "custom_xml") {
2217
+ return block.children.map(blockTextForTargetHash).join("");
2218
+ }
2219
+ if (block.type === "table") {
2220
+ return block.rows.flatMap((row) => row.cells).flatMap((cell) => cell.children).map(blockTextForTargetHash).join("");
2221
+ }
2222
+ return "";
2223
+ }
1642
2224
  function inlineTextForTargetHash(inline) {
1643
2225
  if (inline.type === "text") return inline.text;
1644
2226
  if (inline.type === "symbol") return inline.char;
@@ -1654,6 +2236,93 @@ function inlineTextForTargetHash(inline) {
1654
2236
  }
1655
2237
  return "";
1656
2238
  }
2239
+ function createTableTargetCanonicalAddress(table, staleCheckKind, staleHash, resolver = {}) {
2240
+ return createCanonicalAddress({
2241
+ addressKind: "table-target",
2242
+ storyKey: tableStoryKey(table),
2243
+ staleCheckKind,
2244
+ operationScope: table.operationScope,
2245
+ rowRange: table.fragment?.rowRange,
2246
+ columnRange: table.fragment?.columnRange,
2247
+ sourceRefs: [table.sourceRef, table.rowSourceRef, table.cellSourceRef],
2248
+ staleHash,
2249
+ ...resolver,
2250
+ discriminator: {
2251
+ operationScope: table.operationScope,
2252
+ tableDepth: table.tableDepth,
2253
+ rowIndex: table.rowIndex ?? null,
2254
+ columnIndex: table.columnIndex ?? null,
2255
+ cellIndex: table.cellIndex ?? null,
2256
+ gridColumnStart: table.gridColumnStart ?? null,
2257
+ gridSpan: table.gridSpan ?? null,
2258
+ verticalMerge: table.verticalMerge ?? null,
2259
+ sourceId: table.sourceRef?.sourceId ?? null,
2260
+ rowSourceId: table.rowSourceRef?.sourceId ?? null,
2261
+ cellSourceId: table.cellSourceRef?.sourceId ?? null
2262
+ },
2263
+ secondaryStory: table.secondaryStory,
2264
+ nestedTable: table.nestedTable,
2265
+ insideSdt: table.insideSdt
2266
+ });
2267
+ }
2268
+ function tableStoryKey(table) {
2269
+ const suffix = `:${table.tablePath}`;
2270
+ return table.tableKey.endsWith(suffix) ? table.tableKey.slice(0, -suffix.length) : MAIN_STORY_KEY;
2271
+ }
2272
+ function createCanonicalAddress(input) {
2273
+ const sourceHash = sourceJoinHash(input.sourceRefs ?? []);
2274
+ const payload = {
2275
+ addressKind: input.addressKind,
2276
+ storyKey: input.storyKey,
2277
+ operationScope: input.operationScope ?? null,
2278
+ rowRange: input.rowRange ?? null,
2279
+ columnRange: input.columnRange ?? null,
2280
+ sourceHash: sourceHash ?? null,
2281
+ discriminator: input.discriminator
2282
+ };
2283
+ return {
2284
+ addressKey: `editable-address:${hashText(JSON.stringify(payload))}`,
2285
+ addressKind: input.addressKind,
2286
+ storyKey: input.storyKey,
2287
+ staleCheckKind: input.staleCheckKind,
2288
+ ...input.operationScope !== void 0 ? { operationScope: input.operationScope } : {},
2289
+ ...input.rowRange !== void 0 ? { rowRange: input.rowRange } : {},
2290
+ ...input.columnRange !== void 0 ? { columnRange: input.columnRange } : {},
2291
+ ...sourceHash !== void 0 ? { sourceJoinHash: sourceHash } : {},
2292
+ ...input.secondaryStory === true ? { secondaryStory: true } : {},
2293
+ ...input.nestedTable === true ? { nestedTable: true } : {},
2294
+ ...input.insideSdt === true ? { insideSdt: true } : {},
2295
+ resolver: {
2296
+ staleHash: input.staleHash,
2297
+ ...sourceHash !== void 0 ? { sourceJoinHash: sourceHash } : {},
2298
+ ...input.rowRange !== void 0 ? { rowRange: input.rowRange } : {},
2299
+ ...input.columnRange !== void 0 ? { columnRange: input.columnRange } : {},
2300
+ ...input.rangeBoundary !== void 0 ? { rangeBoundary: input.rangeBoundary } : {},
2301
+ ...input.owner !== void 0 ? { owner: input.owner } : {}
2302
+ }
2303
+ };
2304
+ }
2305
+ function ownerRoutingFromAddress(address) {
2306
+ return {
2307
+ addressKey: address.addressKey,
2308
+ addressKind: address.addressKind,
2309
+ storyKey: address.storyKey,
2310
+ ...address.operationScope !== void 0 ? { operationScope: address.operationScope } : {},
2311
+ ...address.sourceJoinHash !== void 0 ? { sourceJoinHash: address.sourceJoinHash } : {},
2312
+ staleHash: address.resolver?.staleHash ?? "",
2313
+ ...address.rowRange !== void 0 ? { rowRange: address.rowRange } : {},
2314
+ ...address.columnRange !== void 0 ? { columnRange: address.columnRange } : {}
2315
+ };
2316
+ }
2317
+ function sourceJoinHashForRefs(...refs) {
2318
+ const sourceHash = sourceJoinHash(refs);
2319
+ return sourceHash === void 0 ? {} : { sourceJoinHash: sourceHash };
2320
+ }
2321
+ function sourceJoinHash(refs) {
2322
+ const sourceIds = refs.map((ref) => ref?.sourceId).filter((sourceId) => sourceId !== void 0);
2323
+ if (sourceIds.length === 0) return void 0;
2324
+ return hashText(sourceIds.join("\0"));
2325
+ }
1657
2326
  function collectCanonicalFieldRegionIdentities(doc) {
1658
2327
  const registry = doc.fieldRegistry;
1659
2328
  const byFieldIndex = new Map(
@@ -1851,7 +2520,7 @@ function walkBlocks(blocks, storyKey, basePath, visitor) {
1851
2520
  }
1852
2521
  if (block.type === "paragraph") {
1853
2522
  visitor.paragraph?.(block, blockPath);
1854
- walkInlines(block.children, storyKey, blockPath, `${blockPath}/inline`, visitor);
2523
+ walkInlines(block.children ?? [], storyKey, blockPath, `${blockPath}/inline`, visitor);
1855
2524
  continue;
1856
2525
  }
1857
2526
  if (block.type === "sdt" || block.type === "custom_xml") {
@@ -4601,6 +5270,7 @@ var PICTURE_EFFECT_SCHEME_ALIASES = {
4601
5270
  bg2: "lt2"
4602
5271
  };
4603
5272
  var EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH = /* @__PURE__ */ new Map();
5273
+ var NO_EDITABLE_TARGETS_INDEX = EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH;
4604
5274
  function indexEditableTargetsByBlockPath(document) {
4605
5275
  const targets = collectEditableTargetRefs(document);
4606
5276
  if (targets.length === 0) return EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH;
@@ -4652,7 +5322,7 @@ function createEditorSurfaceSnapshot(document, _selection, activeStory = { kind:
4652
5322
  ...options.getEffectiveMarkupMode ? { getEffectiveMarkupMode: options.getEffectiveMarkupMode } : {},
4653
5323
  ...options.authorColorPalette ? { authorColorPalette: options.authorColorPalette } : {}
4654
5324
  });
4655
- const editableTargetsByBlockPath = indexEditableTargetsByBlockPath(document);
5325
+ const editableTargetsByBlockPath = options.editableTargetsByBlockPath ?? indexEditableTargetsByBlockPath(document);
4656
5326
  const activeStoryBlockPathBase = getActiveStoryBlockPathBase(document, activeStory);
4657
5327
  chartModelStore.beginBuildPass(document);
4658
5328
  const unsupportedNumberingFormatsSeen = options.emitFormattingTelemetry ? /* @__PURE__ */ new Set() : null;
@@ -4933,6 +5603,7 @@ function createTableBlock(tableIndex, table, document, cursor, counters, formatt
4933
5603
  from: cursor,
4934
5604
  to: innerCursor,
4935
5605
  styleId: table.styleId,
5606
+ ...table.sourceRef !== void 0 ? { sourceRef: table.sourceRef } : {},
4936
5607
  gridColumns: table.gridColumns,
4937
5608
  rows: []
4938
5609
  },
@@ -5002,6 +5673,7 @@ function createTableBlock(tableIndex, table, document, cursor, counters, formatt
5002
5673
  resolvedTable.table?.cellMargins
5003
5674
  );
5004
5675
  cells.push({
5676
+ ...cell.sourceRef !== void 0 ? { sourceRef: cell.sourceRef } : {},
5005
5677
  gridSpan: cell.gridSpan ?? 1,
5006
5678
  verticalMerge: cell.verticalMerge ?? null,
5007
5679
  colspan: cell.gridSpan ?? 1,
@@ -5025,6 +5697,7 @@ function createTableBlock(tableIndex, table, document, cursor, counters, formatt
5025
5697
  }
5026
5698
  const headerLike = row.isHeader === true || resolvedRow?.style.isHeader === true;
5027
5699
  rows.push({
5700
+ ...row.sourceRef !== void 0 ? { sourceRef: row.sourceRef } : {},
5028
5701
  cells,
5029
5702
  ...row.gridBefore !== void 0 ? { gridBefore: row.gridBefore } : {},
5030
5703
  ...row.gridAfter !== void 0 ? { gridAfter: row.gridAfter } : {},
@@ -5055,6 +5728,7 @@ function createTableBlock(tableIndex, table, document, cursor, counters, formatt
5055
5728
  from: cursor,
5056
5729
  to: innerCursor,
5057
5730
  styleId: table.styleId,
5731
+ ...table.sourceRef !== void 0 ? { sourceRef: table.sourceRef } : {},
5058
5732
  gridColumns: table.gridColumns,
5059
5733
  ...gridColumnsRelative ? { gridColumnsRelative } : {},
5060
5734
  ...resolvedTable.table?.alignment ? { alignment: resolvedTable.table.alignment } : {},
@@ -5599,6 +6273,7 @@ function appendInlineSegments(paragraph, node, document, start, promoteSecondary
5599
6273
  const anchor = surfaceAnchorFromGeometry(node.anchor);
5600
6274
  const txbxTextSegment = c.isTextBox ? extractTxbxFirstTextSegment(c.txbxBlocks) : void 0;
5601
6275
  const txbxText = txbxTextSegment?.text ?? (c.isTextBox ? c.text : void 0);
6276
+ const txbxBody = c.isTextBox ? surfaceTextBoxBodyFromShape(c, node.sourceRef) : void 0;
5602
6277
  const surfaceFill = c.fill;
5603
6278
  paragraph.segments.push({
5604
6279
  segmentId: `${paragraph.blockId}-segment-${paragraph.segments.length}`,
@@ -5615,6 +6290,7 @@ function appendInlineSegments(paragraph, node, document, start, promoteSecondary
5615
6290
  ...c.textBoxBody ? { textBoxBody: c.textBoxBody } : {},
5616
6291
  ...c.preserveOnlyObject ? { preserveOnlyObject: surfacePreserveOnlyObject(c.preserveOnlyObject) } : {},
5617
6292
  ...txbxText ? { txbxText } : {},
6293
+ ...txbxBody ? { txbxBody } : {},
5618
6294
  ...txbxTextSegment?.marks && txbxTextSegment.marks.length > 0 ? { txbxMarks: txbxTextSegment.marks } : {},
5619
6295
  ...txbxTextSegment?.markAttrs ? { txbxMarkAttrs: txbxTextSegment.markAttrs } : {}
5620
6296
  });
@@ -6027,6 +6703,97 @@ function extractTxbxFirstTextSegment(blocks) {
6027
6703
  }
6028
6704
  return void 0;
6029
6705
  }
6706
+ function surfaceTextBoxBodyFromShape(shape, sourceRef) {
6707
+ if (!shape.isTextBox && shape.txbxContentXml === void 0 && shape.txbxBlocks === void 0) {
6708
+ return void 0;
6709
+ }
6710
+ if (shape.txbxBlocks === void 0) {
6711
+ return {
6712
+ ...sourceRef !== void 0 ? { sourceRef } : {},
6713
+ status: shape.txbxContentXml !== void 0 ? "preserve-only" : "unavailable",
6714
+ unavailableReason: "txbx-blocks-unavailable",
6715
+ ...shape.textBoxBody !== void 0 ? { bodyProperties: shape.textBoxBody } : {},
6716
+ blockCount: 0,
6717
+ paragraphCount: 0,
6718
+ unsupportedBlockCount: 0,
6719
+ paragraphs: []
6720
+ };
6721
+ }
6722
+ const paragraphs = shape.txbxBlocks.flatMap((block, blockIndex) => {
6723
+ if (block.type !== "paragraph") return [];
6724
+ const children = block.children;
6725
+ const legacyRuns = block.runs;
6726
+ const runs = children !== void 0 ? children.map(
6727
+ (inline, inlineIndex) => surfaceTextBoxRunFromInline(inline, inlineIndex)
6728
+ ) : legacyRuns?.map(
6729
+ (run, inlineIndex) => surfaceTextBoxRunFromLegacyRun(run, inlineIndex)
6730
+ ) ?? [];
6731
+ const text = runs.map((run) => run.text ?? "").join("");
6732
+ return [{
6733
+ ...block.sourceRef !== void 0 ? { sourceRef: block.sourceRef } : {},
6734
+ blockIndex,
6735
+ text,
6736
+ textLength: Array.from(text).length,
6737
+ ...block.borders !== void 0 ? { borders: block.borders } : {},
6738
+ runs
6739
+ }];
6740
+ });
6741
+ const unsupportedBlockCount = shape.txbxBlocks.length - paragraphs.length;
6742
+ const unavailableReason = shape.txbxBlocks.length === 0 ? "empty-body" : paragraphs.length === 0 ? "unsupported-content" : void 0;
6743
+ return {
6744
+ ...sourceRef !== void 0 ? { sourceRef } : {},
6745
+ status: unavailableReason === void 0 ? "modeled" : "unavailable",
6746
+ ...unavailableReason !== void 0 ? { unavailableReason } : {},
6747
+ ...shape.textBoxBody !== void 0 ? { bodyProperties: shape.textBoxBody } : {},
6748
+ blockCount: shape.txbxBlocks.length,
6749
+ paragraphCount: paragraphs.length,
6750
+ unsupportedBlockCount,
6751
+ paragraphs
6752
+ };
6753
+ }
6754
+ function surfaceTextBoxRunFromLegacyRun(run, inlineIndex) {
6755
+ const text = run.text ?? "";
6756
+ const cloned = run.marks ? cloneMarks2(run.marks) : void 0;
6757
+ return {
6758
+ inlineIndex,
6759
+ kind: "text",
6760
+ text,
6761
+ textLength: Array.from(text).length,
6762
+ ...cloned?.marks && cloned.marks.length > 0 ? { marks: cloned.marks } : {},
6763
+ ...cloned?.markAttrs ? { markAttrs: cloned.markAttrs } : {}
6764
+ };
6765
+ }
6766
+ function surfaceTextBoxRunFromInline(inline, inlineIndex) {
6767
+ if (inline.type === "text") {
6768
+ const cloned = inline.marks ? cloneMarks2(inline.marks) : void 0;
6769
+ return {
6770
+ inlineIndex,
6771
+ kind: "text",
6772
+ text: inline.text,
6773
+ textLength: Array.from(inline.text).length,
6774
+ ...cloned?.marks && cloned.marks.length > 0 ? { marks: cloned.marks } : {},
6775
+ ...cloned?.markAttrs ? { markAttrs: cloned.markAttrs } : {}
6776
+ };
6777
+ }
6778
+ if (inline.type === "tab") {
6779
+ return { inlineIndex, kind: "tab", text: " ", textLength: 1 };
6780
+ }
6781
+ if (inline.type === "hard_break") {
6782
+ return { inlineIndex, kind: "hard-break", text: "\n", textLength: 1 };
6783
+ }
6784
+ if (inline.type === "symbol") {
6785
+ const cloned = inline.marks ? cloneMarks2(inline.marks) : void 0;
6786
+ return {
6787
+ inlineIndex,
6788
+ kind: "symbol",
6789
+ text: inline.char,
6790
+ textLength: Array.from(inline.char).length,
6791
+ ...cloned?.marks && cloned.marks.length > 0 ? { marks: cloned.marks } : {},
6792
+ ...cloned?.markAttrs ? { markAttrs: cloned.markAttrs } : {}
6793
+ };
6794
+ }
6795
+ return { inlineIndex, kind: "unsupported" };
6796
+ }
6030
6797
  function appendComplexPreviewSegment(paragraph, node, start, label, detail, extras = {}) {
6031
6798
  const preserveOnlyObject = node.preserveOnlyObject ? surfacePreserveOnlyObject(node.preserveOnlyObject) : void 0;
6032
6799
  paragraph.segments.push({
@@ -6543,7 +7310,9 @@ function resolveParagraphScope(document, selection) {
6543
7310
  if (!root) {
6544
7311
  return null;
6545
7312
  }
6546
- const surface = createEditorSurfaceSnapshot(document, selection);
7313
+ const surface = createEditorSurfaceSnapshot(document, selection, void 0, {
7314
+ editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX
7315
+ });
6547
7316
  const selectionFrom = Math.min(selection.anchor, selection.head);
6548
7317
  const selectionTo = Math.max(selection.anchor, selection.head);
6549
7318
  for (let blockIndex = 0; blockIndex < root.children.length; blockIndex += 1) {