@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
@@ -117,7 +117,7 @@ function parseTextStory(content) {
117
117
  function countLogicalPositions(units) {
118
118
  let size = 0;
119
119
  for (const unit of units) {
120
- if (unit.kind !== "scope_marker") size += 1;
120
+ size += unitLogicalSize(unit);
121
121
  }
122
122
  return size;
123
123
  }
@@ -129,11 +129,15 @@ function logicalPositionToUnitIndex(units, logicalPos, startBias = "after") {
129
129
  return unitIndex;
130
130
  }
131
131
  const unit = units[unitIndex];
132
- if (unit.kind !== "scope_marker") {
132
+ const unitSize = unitLogicalSize(unit);
133
+ if (unitSize > 0) {
133
134
  if (logicalCursor === logicalPos && startBias === "after") {
134
135
  return unitIndex;
135
136
  }
136
- logicalCursor += 1;
137
+ if (logicalPos > logicalCursor && logicalPos < logicalCursor + unitSize) {
138
+ return unitIndex;
139
+ }
140
+ logicalCursor += unitSize;
137
141
  }
138
142
  unitIndex += 1;
139
143
  }
@@ -267,6 +271,9 @@ function serializeTextStory(story) {
267
271
  warningId: unit.warningId
268
272
  });
269
273
  break;
274
+ case "protected_inline":
275
+ pushInlineNode(structuredClone(unit.node));
276
+ break;
270
277
  case "scope_marker":
271
278
  pushInlineNode({
272
279
  type: unit.boundary === "start" ? "scope_marker_start" : "scope_marker_end",
@@ -299,6 +306,8 @@ function createPlainText(story) {
299
306
  return "\uFFFC";
300
307
  case "opaque_inline":
301
308
  return "\uFFF9";
309
+ case "protected_inline":
310
+ return protectedInlineText(unit.node);
302
311
  case "opaque_block":
303
312
  return "\uFFFA";
304
313
  case "structural_block":
@@ -339,6 +348,13 @@ function cloneStoryUnit(unit) {
339
348
  fragmentId: unit.fragmentId,
340
349
  warningId: unit.warningId
341
350
  };
351
+ case "protected_inline":
352
+ return {
353
+ kind: "protected_inline",
354
+ node: structuredClone(unit.node),
355
+ logicalSize: unit.logicalSize,
356
+ reason: unit.reason
357
+ };
342
358
  case "opaque_block":
343
359
  return {
344
360
  kind: "opaque_block",
@@ -421,7 +437,29 @@ function flattenInlineNodes(nodes, hyperlinkHref) {
421
437
  });
422
438
  break;
423
439
  case "hyperlink":
424
- units.push(...flattenInlineNodes(node.children, node.href));
440
+ units.push({
441
+ kind: "protected_inline",
442
+ node: structuredClone(node),
443
+ logicalSize: inlineLogicalLength(node),
444
+ reason: "hyperlink"
445
+ });
446
+ break;
447
+ case "field":
448
+ units.push({
449
+ kind: "protected_inline",
450
+ node: structuredClone(node),
451
+ logicalSize: inlineLogicalLength(node),
452
+ reason: "field"
453
+ });
454
+ break;
455
+ case "bookmark_start":
456
+ case "bookmark_end":
457
+ units.push({
458
+ kind: "protected_inline",
459
+ node: structuredClone(node),
460
+ logicalSize: 0,
461
+ reason: "bookmark"
462
+ });
425
463
  break;
426
464
  case "image":
427
465
  units.push({
@@ -455,6 +493,48 @@ function flattenInlineNodes(nodes, hyperlinkHref) {
455
493
  }
456
494
  return units;
457
495
  }
496
+ function unitLogicalSize(unit) {
497
+ switch (unit.kind) {
498
+ case "scope_marker":
499
+ return 0;
500
+ case "protected_inline":
501
+ return unit.logicalSize;
502
+ default:
503
+ return 1;
504
+ }
505
+ }
506
+ function inlineLogicalLength(node) {
507
+ switch (node.type) {
508
+ case "text":
509
+ return Array.from(node.text).length;
510
+ case "hyperlink":
511
+ case "field":
512
+ return node.children.reduce((total, child) => total + inlineLogicalLength(child), 0);
513
+ case "bookmark_start":
514
+ case "bookmark_end":
515
+ case "scope_marker_start":
516
+ case "scope_marker_end":
517
+ return 0;
518
+ default:
519
+ return 1;
520
+ }
521
+ }
522
+ function protectedInlineText(node) {
523
+ switch (node.type) {
524
+ case "text":
525
+ return node.text;
526
+ case "hyperlink":
527
+ case "field":
528
+ return node.children.map((child) => protectedInlineText(child)).join("");
529
+ case "bookmark_start":
530
+ case "bookmark_end":
531
+ case "scope_marker_start":
532
+ case "scope_marker_end":
533
+ return "";
534
+ default:
535
+ return "\uFFF9";
536
+ }
537
+ }
458
538
  function extractParagraphProperties(paragraph) {
459
539
  return {
460
540
  ...paragraph.styleId ? { styleId: paragraph.styleId } : {},
@@ -848,7 +928,7 @@ function createHeaderFooterStoryKey(input) {
848
928
  function createNoteStoryKey(kind, noteId) {
849
929
  return `${kind}:${noteId}`;
850
930
  }
851
- function collectEditableTargetRefs(doc) {
931
+ function collectEditableTargetRefs(doc, cache) {
852
932
  const targets = [];
853
933
  for (const context of collectStoryBlockContexts(doc)) {
854
934
  collectEditableTargetsInBlocks(
@@ -860,17 +940,53 @@ function collectEditableTargetRefs(doc) {
860
940
  insideTextBox: false,
861
941
  tableDepth: 0
862
942
  },
863
- targets
943
+ targets,
944
+ cache
864
945
  );
865
946
  }
947
+ collectFieldRegionRefreshTargets(doc, targets);
948
+ collectBookmarkContentRangeTargets(doc, targets);
866
949
  collectReviewEditableTargets(doc, targets);
867
950
  return targets;
868
951
  }
869
- function collectEditableTargetsInBlocks(blocks, context, targets) {
952
+ function buildBlockCacheSignature(context, blockIndex) {
953
+ const cc = context.contentControl;
954
+ const tt = context.tableTarget;
955
+ const owner = tt?.editableOwnersByChildIndex?.get(blockIndex);
956
+ return [
957
+ context.storyKey,
958
+ context.insideSdt ? "1" : "0",
959
+ context.insideTextBox ? "1" : "0",
960
+ String(context.tableDepth),
961
+ cc?.sdtId ?? "",
962
+ cc?.tag ?? "",
963
+ cc?.alias ?? "",
964
+ cc?.sdtType ?? "",
965
+ cc?.lock ?? "",
966
+ tt?.tablePath ?? "",
967
+ tt?.tableDepth ?? "",
968
+ tt?.rowIndex ?? "",
969
+ tt?.cellIndex ?? "",
970
+ tt?.gridColumnStart ?? "",
971
+ tt?.cell?.verticalMerge ?? "",
972
+ tt?.cell?.gridSpan ?? "",
973
+ owner?.targetKey ?? ""
974
+ ].join("|");
975
+ }
976
+ function collectEditableTargetsInBlocks(blocks, context, targets, cache) {
870
977
  for (let blockIndex = 0; blockIndex < blocks.length; blockIndex += 1) {
871
978
  const block = blocks[blockIndex];
872
979
  if (!block) continue;
873
980
  const blockPath = `${context.basePath}/block[${blockIndex}]`;
981
+ const signature = cache !== void 0 ? buildBlockCacheSignature(context, blockIndex) : "";
982
+ if (cache !== void 0) {
983
+ const cached = cache.get(block);
984
+ if (cached !== void 0 && cached.blockPath === blockPath && cached.signature === signature) {
985
+ for (const target of cached.targets) targets.push(target);
986
+ continue;
987
+ }
988
+ }
989
+ const blockStart = targets.length;
874
990
  if (block.type === "paragraph") {
875
991
  const targetKind = editableParagraphTargetKind(context);
876
992
  if (targetKind !== null) {
@@ -882,14 +998,13 @@ function collectEditableTargetsInBlocks(blocks, context, targets) {
882
998
  blockPath,
883
999
  editableParagraphTargetPosture(targetKind),
884
1000
  context.contentControl,
885
- context.tableTarget
1001
+ context.tableTarget,
1002
+ context.tableTarget?.editableOwnersByChildIndex?.get(blockIndex)
886
1003
  )
887
1004
  );
888
1005
  }
889
1006
  collectEditableTargetsInInlines(block.children ?? [], `${blockPath}/inline`, context, targets);
890
- continue;
891
- }
892
- if (block.type === "sdt") {
1007
+ } else if (block.type === "sdt") {
893
1008
  const contentControl = contentControlIdentityForSdt(block, context.contentControl);
894
1009
  collectEditableTargetsInBlocks(
895
1010
  block.children,
@@ -899,11 +1014,10 @@ function collectEditableTargetsInBlocks(blocks, context, targets) {
899
1014
  insideSdt: true,
900
1015
  contentControl
901
1016
  },
902
- targets
1017
+ targets,
1018
+ cache
903
1019
  );
904
- continue;
905
- }
906
- if (block.type === "custom_xml") {
1020
+ } else if (block.type === "custom_xml") {
907
1021
  targets.push(createCustomXmlEditableTarget(block, context.storyKey, blockPath));
908
1022
  collectEditableTargetsInBlocks(
909
1023
  block.children,
@@ -911,25 +1025,29 @@ function collectEditableTargetsInBlocks(blocks, context, targets) {
911
1025
  ...context,
912
1026
  basePath: blockPath
913
1027
  },
914
- targets
1028
+ targets,
1029
+ cache
915
1030
  );
916
- continue;
917
- }
918
- if (block.type === "opaque_block") {
1031
+ } else if (block.type === "opaque_block") {
919
1032
  targets.push(createOpaqueBlockEditableTarget(block, context.storyKey, blockPath));
920
- continue;
921
- }
922
- if (block.type === "alt_chunk") {
1033
+ } else if (block.type === "alt_chunk") {
923
1034
  targets.push(createAltChunkEditableTarget(block.relationshipId, context.storyKey, blockPath));
924
- continue;
925
- }
926
- if (block.type === "table") {
927
- collectEditableTargetsInTable(block, blockPath, context, targets);
1035
+ } else if (block.type === "table") {
1036
+ collectEditableTargetsInTable(block, blockPath, context, targets, cache);
1037
+ }
1038
+ if (cache !== void 0) {
1039
+ const blockTargets = targets.slice(blockStart);
1040
+ cache.set(block, {
1041
+ blockPath,
1042
+ signature,
1043
+ targets: blockTargets
1044
+ });
928
1045
  }
929
1046
  }
930
1047
  }
931
- function collectEditableTargetsInTable(table, tablePath, context, targets) {
1048
+ function collectEditableTargetsInTable(table, tablePath, context, targets, cache) {
932
1049
  const tableDepth = context.tableDepth + 1;
1050
+ const verticalMergeOwners = [];
933
1051
  targets.push(createTableStructureTarget({
934
1052
  scope: "table",
935
1053
  kind: "table-structure-table",
@@ -968,6 +1086,10 @@ function collectEditableTargetsInTable(table, tablePath, context, targets) {
968
1086
  const cell = row.cells[cellIndex];
969
1087
  if (!cell) continue;
970
1088
  const gridSpan = cell.gridSpan ?? 1;
1089
+ const continuationOwner = cell.verticalMerge === "continue" ? findVerticalMergeOwner(verticalMergeOwners, gridColumnStart, gridSpan) : null;
1090
+ if (cell.verticalMerge !== "continue") {
1091
+ clearVerticalMergeOwners(verticalMergeOwners, gridColumnStart, gridSpan);
1092
+ }
971
1093
  targets.push(createTableStructureTarget({
972
1094
  scope: "cell",
973
1095
  kind: "table-structure-cell",
@@ -1010,15 +1132,136 @@ function collectEditableTargetsInTable(table, tablePath, context, targets) {
1010
1132
  row,
1011
1133
  cellIndex,
1012
1134
  cell,
1013
- gridColumnStart
1135
+ gridColumnStart,
1136
+ ...continuationOwner ? {
1137
+ editableOwnersByChildIndex: continuationOwnerTargetsByChildIndex(
1138
+ continuationOwner,
1139
+ cell.children.length
1140
+ )
1141
+ } : {}
1014
1142
  }
1015
1143
  },
1016
- targets
1144
+ targets,
1145
+ cache
1017
1146
  );
1147
+ if (cell.verticalMerge === "restart") {
1148
+ verticalMergeOwners.push(createVerticalMergeOwnerState({
1149
+ context,
1150
+ table,
1151
+ tablePath,
1152
+ tableDepth,
1153
+ rowIndex,
1154
+ row,
1155
+ cellIndex,
1156
+ cell,
1157
+ gridColumnStart,
1158
+ gridSpan
1159
+ }));
1160
+ }
1018
1161
  gridColumnStart += gridSpan;
1019
1162
  }
1020
1163
  }
1021
1164
  }
1165
+ function findVerticalMergeOwner(owners, gridColumnStart, gridSpan) {
1166
+ return owners.find(
1167
+ (owner) => owner.gridColumnStart === gridColumnStart && owner.gridSpan === gridSpan
1168
+ ) ?? null;
1169
+ }
1170
+ function clearVerticalMergeOwners(owners, gridColumnStart, gridSpan) {
1171
+ const gridColumnEnd = gridColumnStart + gridSpan;
1172
+ for (let index = owners.length - 1; index >= 0; index -= 1) {
1173
+ const owner = owners[index];
1174
+ if (!owner) continue;
1175
+ const ownerEnd = owner.gridColumnStart + owner.gridSpan;
1176
+ if (gridColumnStart < ownerEnd && owner.gridColumnStart < gridColumnEnd) {
1177
+ owners.splice(index, 1);
1178
+ }
1179
+ }
1180
+ }
1181
+ function continuationOwnerTargetsByChildIndex(owner, childCount) {
1182
+ if (!owner.fallbackOwnerTarget) return void 0;
1183
+ const targets = /* @__PURE__ */ new Map();
1184
+ for (let childIndex = 0; childIndex < childCount; childIndex += 1) {
1185
+ targets.set(
1186
+ childIndex,
1187
+ owner.ownerTargetsByChildIndex.get(childIndex) ?? owner.fallbackOwnerTarget
1188
+ );
1189
+ }
1190
+ return targets;
1191
+ }
1192
+ function createVerticalMergeOwnerState(input) {
1193
+ const ownerTargetsByChildIndex = /* @__PURE__ */ new Map();
1194
+ for (let childIndex = 0; childIndex < input.cell.children.length; childIndex += 1) {
1195
+ const owner = createVerticalMergeEditableOwner({ ...input, childIndex });
1196
+ if (owner) ownerTargetsByChildIndex.set(childIndex, owner);
1197
+ }
1198
+ return {
1199
+ gridColumnStart: input.gridColumnStart,
1200
+ gridSpan: input.gridSpan,
1201
+ ownerTargetsByChildIndex,
1202
+ ...ownerTargetsByChildIndex.size > 0 ? { fallbackOwnerTarget: ownerTargetsByChildIndex.values().next().value } : {}
1203
+ };
1204
+ }
1205
+ function createVerticalMergeEditableOwner(input) {
1206
+ const child = input.cell.children[input.childIndex];
1207
+ if (child?.type !== "paragraph") return null;
1208
+ const ownerTableTarget = {
1209
+ table: input.table,
1210
+ tablePath: input.tablePath,
1211
+ tableDepth: input.tableDepth,
1212
+ rowIndex: input.rowIndex,
1213
+ row: input.row,
1214
+ cellIndex: input.cellIndex,
1215
+ cell: input.cell,
1216
+ gridColumnStart: input.gridColumnStart
1217
+ };
1218
+ const kind = editableParagraphTargetKind({
1219
+ ...input.context,
1220
+ basePath: `${input.tablePath}/row[${input.rowIndex}]/cell[${input.cellIndex}]`,
1221
+ tableDepth: input.tableDepth,
1222
+ tableTarget: ownerTableTarget
1223
+ });
1224
+ if (!kind) return null;
1225
+ const blockPath = `${input.tablePath}/row[${input.rowIndex}]/cell[${input.cellIndex}]/block[${input.childIndex}]`;
1226
+ const paragraphTextHash = hashText(collectParagraphText(child));
1227
+ const table = createTableIdentity({
1228
+ scope: "text",
1229
+ context: {
1230
+ storyKey: input.context.storyKey,
1231
+ insideSdt: input.context.contentControl !== void 0
1232
+ },
1233
+ ...ownerTableTarget
1234
+ });
1235
+ return {
1236
+ targetKey: `${input.context.storyKey}:${blockPath}:text`,
1237
+ kind,
1238
+ storyKey: input.context.storyKey,
1239
+ blockPath,
1240
+ leafPath: `${blockPath}/inline`,
1241
+ commandFamily: "text-leaf",
1242
+ reason: "vertical-merge-restart-cell",
1243
+ canonicalAddress: ownerRoutingFromAddress(
1244
+ createTableTargetCanonicalAddress(
1245
+ table,
1246
+ "paragraph",
1247
+ paragraphTextHash,
1248
+ { rangeBoundary: { boundaryKind: "cell-fragment" } }
1249
+ )
1250
+ ),
1251
+ table: {
1252
+ tableKey: table.tableKey,
1253
+ tablePath: table.tablePath,
1254
+ ...table.sourceRef !== void 0 ? { sourceRef: table.sourceRef } : {},
1255
+ ...table.rowSourceRef !== void 0 ? { rowSourceRef: table.rowSourceRef } : {},
1256
+ ...table.cellSourceRef !== void 0 ? { cellSourceRef: table.cellSourceRef } : {},
1257
+ ...table.rowIndex !== void 0 ? { rowIndex: table.rowIndex } : {},
1258
+ ...table.cellIndex !== void 0 ? { cellIndex: table.cellIndex } : {},
1259
+ ...table.gridColumnStart !== void 0 ? { gridColumnStart: table.gridColumnStart } : {},
1260
+ ...table.gridSpan !== void 0 ? { gridSpan: table.gridSpan } : {},
1261
+ ...table.verticalMerge !== void 0 ? { verticalMerge: table.verticalMerge } : {}
1262
+ }
1263
+ };
1264
+ }
1022
1265
  function computeTableStructureColumnCount(table) {
1023
1266
  let columnCount = table.gridColumns.length;
1024
1267
  for (const row of table.rows) {
@@ -1038,6 +1281,7 @@ function createTableStructureTarget(input) {
1038
1281
  const columnPath = input.columnIndex !== void 0 ? `${input.tablePath}/column[${input.columnIndex}]` : void 0;
1039
1282
  const blockPath = cellPath ?? rowPath ?? columnPath ?? input.tablePath;
1040
1283
  const tableIdentity = createTableIdentity(input);
1284
+ const targetHash = hashTableStructureTarget(input);
1041
1285
  return {
1042
1286
  targetKey: `${tableKey}:structure:${tableIdentity.operationScope}${tableTargetSuffix(tableIdentity)}`,
1043
1287
  kind: input.kind,
@@ -1049,8 +1293,14 @@ function createTableStructureTarget(input) {
1049
1293
  ...input.table.sourceRef !== void 0 ? { sourceRef: input.table.sourceRef } : {},
1050
1294
  ...input.context.contentControl !== void 0 ? { contentControl: input.context.contentControl } : {},
1051
1295
  table: tableIdentity,
1296
+ canonicalAddress: createTableTargetCanonicalAddress(
1297
+ tableIdentity,
1298
+ tableStructureBlockType(input.scope),
1299
+ targetHash,
1300
+ { rangeBoundary: { boundaryKind: "table-grid" } }
1301
+ ),
1052
1302
  staleCheck: {
1053
- targetHash: hashTableStructureTarget(input),
1303
+ targetHash,
1054
1304
  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),
1055
1305
  blockType: tableStructureBlockType(input.scope),
1056
1306
  ...input.table.sourceRef !== void 0 ? { sourceRef: input.table.sourceRef } : {}
@@ -1061,10 +1311,15 @@ function createTableStructureTarget(input) {
1061
1311
  function createTableIdentity(input) {
1062
1312
  const tableKey = `${input.context.storyKey}:${input.tablePath}`;
1063
1313
  const columnCount = computeTableStructureColumnCount(input.table);
1314
+ const rowRange = tableFragmentRowRange(input).rowRange;
1315
+ const columnRange = tableFragmentColumnRange(input, columnCount).columnRange;
1064
1316
  const base = {
1065
1317
  operationScope: input.scope,
1066
1318
  tableKey,
1067
1319
  tablePath: input.tablePath,
1320
+ ...input.table.sourceRef !== void 0 ? { sourceRef: input.table.sourceRef } : {},
1321
+ ...input.row?.sourceRef !== void 0 ? { rowSourceRef: input.row.sourceRef } : {},
1322
+ ...input.cell?.sourceRef !== void 0 ? { cellSourceRef: input.cell.sourceRef } : {},
1068
1323
  ...tablePathIndexes(input.tablePath),
1069
1324
  tableDepth: input.tableDepth,
1070
1325
  ...input.tableDepth >= 2 ? { nestedTable: true } : {},
@@ -1072,7 +1327,10 @@ function createTableIdentity(input) {
1072
1327
  ...input.context.storyKey !== MAIN_STORY_KEY ? { secondaryStory: true } : {},
1073
1328
  rowCount: input.table.rows.length,
1074
1329
  columnCount,
1075
- fragment: createTableFragmentIdentity(input, tableKey, columnCount)
1330
+ fragment: createTableFragmentIdentity(input, tableKey, columnCount),
1331
+ ...input.cell !== void 0 ? {
1332
+ cellFragment: createTableCellFragmentIdentity(input, tableKey, rowRange, columnRange)
1333
+ } : {}
1076
1334
  };
1077
1335
  return {
1078
1336
  ...base,
@@ -1086,6 +1344,25 @@ function createTableIdentity(input) {
1086
1344
  ...input.cell !== void 0 ? { blockCount: input.cell.children.length } : {}
1087
1345
  };
1088
1346
  }
1347
+ function createTableCellFragmentIdentity(input, tableKey, rowRange, columnRange) {
1348
+ const text = (input.cell?.children ?? []).map(blockTextForTargetHash).join("");
1349
+ return {
1350
+ fragmentKey: hashText(JSON.stringify({
1351
+ tableKey,
1352
+ rowIndex: input.rowIndex ?? null,
1353
+ cellIndex: input.cellIndex ?? null,
1354
+ gridColumnStart: input.gridColumnStart ?? null,
1355
+ gridSpan: input.cell?.gridSpan ?? 1,
1356
+ verticalMerge: input.cell?.verticalMerge ?? null,
1357
+ sourceId: input.cell?.sourceRef?.sourceId ?? null
1358
+ })),
1359
+ textHash: hashText(text),
1360
+ blockCount: input.cell?.children.length ?? 0,
1361
+ ...rowRange !== void 0 ? { rowRange } : {},
1362
+ ...columnRange !== void 0 ? { columnRange } : {},
1363
+ ...sourceJoinHashForRefs(input.table.sourceRef, input.row?.sourceRef, input.cell?.sourceRef)
1364
+ };
1365
+ }
1089
1366
  function tablePathIndexes(tablePath) {
1090
1367
  const blockIndexes = [...tablePath.matchAll(/\/block\[(\d+)\]/gu)].map((match) => Number(match[1]));
1091
1368
  const storyBlockIndex = blockIndexes[0];
@@ -1251,13 +1528,39 @@ function collectEditableTargetsInInlines(inlines, basePath, context, targets) {
1251
1528
  }
1252
1529
  }
1253
1530
  }
1254
- function createParagraphEditableTarget(paragraph, kind, storyKey, blockPath, targetPosture = { editability: "editable", posture: { blockers: [] } }, contentControl, tableTarget) {
1531
+ function createParagraphEditableTarget(paragraph, kind, storyKey, blockPath, targetPosture = { editability: "editable", posture: { blockers: [] } }, contentControl, tableTarget, editableOwner) {
1255
1532
  const paragraphText = collectParagraphText(paragraph);
1533
+ const paragraphTextHash = hashText(paragraphText);
1256
1534
  const sourceRef = paragraph.sourceRef;
1257
1535
  const lockedContentControl = contentControlLocksContent(contentControl);
1258
- const posture = lockedContentControl ? mergeTargetPosture(targetPosture.posture, ["locked-content-control"], {
1536
+ const syntheticLayoutCell = tableTarget?.cell?.verticalMerge === "continue";
1537
+ const tableIdentity = tableTarget !== void 0 ? createTableIdentity({
1538
+ scope: "text",
1539
+ context: { storyKey, insideSdt: contentControl !== void 0 },
1540
+ ...tableTarget
1541
+ }) : void 0;
1542
+ const listAddress = tableIdentity === void 0 && paragraph.numbering !== void 0 ? createCanonicalAddress({
1543
+ addressKind: "list-item-text",
1544
+ storyKey,
1545
+ staleCheckKind: "paragraph",
1546
+ operationScope: "list-text",
1547
+ sourceRefs: [sourceRef],
1548
+ staleHash: paragraphTextHash,
1549
+ rangeBoundary: { boundaryKind: "list-item-text" },
1550
+ discriminator: {
1551
+ blockPath,
1552
+ numberingInstanceId: paragraph.numbering.numberingInstanceId,
1553
+ level: paragraph.numbering.level,
1554
+ sourceId: sourceRef?.sourceId ?? null,
1555
+ paraId: paragraph.wordExtensionIds?.paraId ?? null,
1556
+ textId: paragraph.wordExtensionIds?.textId ?? null
1557
+ }
1558
+ }) : void 0;
1559
+ const tableAwarePosture = syntheticLayoutCell ? mergeTargetPosture(targetPosture.posture, ["synthetic-layout-cell"]) : targetPosture.posture;
1560
+ const posture = lockedContentControl ? mergeTargetPosture(tableAwarePosture, ["locked-content-control"], {
1259
1561
  lockedContentControl: true
1260
- }) : targetPosture.posture;
1562
+ }) : tableAwarePosture;
1563
+ const editability = lockedContentControl || syntheticLayoutCell ? "non-editable" : targetPosture.editability;
1261
1564
  return {
1262
1565
  targetKey: `${storyKey}:${blockPath}:text`,
1263
1566
  kind,
@@ -1265,12 +1568,24 @@ function createParagraphEditableTarget(paragraph, kind, storyKey, blockPath, tar
1265
1568
  blockPath,
1266
1569
  leafPath: `${blockPath}/inline`,
1267
1570
  commandFamily: "text-leaf",
1268
- editability: lockedContentControl ? "non-editable" : targetPosture.editability,
1571
+ editability,
1269
1572
  ...sourceRef !== void 0 ? { sourceRef } : {},
1270
1573
  ...contentControl !== void 0 ? { contentControl } : {},
1271
- ...tableTarget !== void 0 ? { table: createTableIdentity({ scope: "text", context: { storyKey, insideSdt: contentControl !== void 0 }, ...tableTarget }) } : {},
1574
+ ...tableIdentity !== void 0 ? { table: tableIdentity } : {},
1575
+ ...editableOwner !== void 0 ? { editableOwner } : {},
1576
+ ...tableIdentity !== void 0 ? {
1577
+ canonicalAddress: createTableTargetCanonicalAddress(
1578
+ tableIdentity,
1579
+ "paragraph",
1580
+ paragraphTextHash,
1581
+ {
1582
+ rangeBoundary: { boundaryKind: "cell-fragment" },
1583
+ owner: editableOwner?.canonicalAddress
1584
+ }
1585
+ )
1586
+ } : listAddress !== void 0 ? { canonicalAddress: listAddress } : {},
1272
1587
  staleCheck: {
1273
- paragraphTextHash: hashText(paragraphText),
1588
+ paragraphTextHash,
1274
1589
  paragraphTextLength: Array.from(paragraphText).length,
1275
1590
  inlineCount: paragraph.children?.length ?? 0,
1276
1591
  blockType: "paragraph",
@@ -1301,12 +1616,27 @@ function collectInlineTarget(inline, storyKey, inlinePath, targets) {
1301
1616
  return;
1302
1617
  case "hyperlink":
1303
1618
  targets.push(createHyperlinkEditableTarget(inline, storyKey, inlinePath));
1619
+ targets.push(createHyperlinkDestinationEditableTarget(inline, storyKey, inlinePath));
1304
1620
  return;
1305
1621
  case "bookmark_start":
1306
- targets.push(createBookmarkEditableTarget(inline.bookmarkId, inline.name, storyKey, inlinePath, "start"));
1622
+ targets.push(createBookmarkEditableTarget(
1623
+ inline.bookmarkId,
1624
+ inline.name,
1625
+ storyKey,
1626
+ inlinePath,
1627
+ "start",
1628
+ inline.sourceRef
1629
+ ));
1307
1630
  return;
1308
1631
  case "bookmark_end":
1309
- targets.push(createBookmarkEditableTarget(inline.bookmarkId, void 0, storyKey, inlinePath, "end"));
1632
+ targets.push(createBookmarkEditableTarget(
1633
+ inline.bookmarkId,
1634
+ void 0,
1635
+ storyKey,
1636
+ inlinePath,
1637
+ "end",
1638
+ inline.sourceRef
1639
+ ));
1310
1640
  return;
1311
1641
  case "image":
1312
1642
  targets.push(createImageEditableTarget(inline, storyKey, inlinePath));
@@ -1330,6 +1660,7 @@ function collectInlineTarget(inline, storyKey, inlinePath, targets) {
1330
1660
  function createFieldEditableTarget(field, storyKey, inlinePath) {
1331
1661
  const resultText = field.children.map(inlineTextForTargetHash).join("");
1332
1662
  const sourceRef = field.sourceRef;
1663
+ const targetHash = hashText(`${field.instruction}\0${resultText}`);
1333
1664
  const preserveOnly = field.refreshStatus === "preserve-only" || field.fieldFamily === "UNKNOWN";
1334
1665
  const blockers = preserveOnly ? ["field-generated-text", "preserve-only"] : ["field-generated-text", "unmodeled-target"];
1335
1666
  return {
@@ -1349,9 +1680,28 @@ function createFieldEditableTarget(field, storyKey, inlinePath) {
1349
1680
  ...field.locked !== void 0 ? { locked: field.locked } : {},
1350
1681
  ...field.dirty !== void 0 ? { dirty: field.dirty } : {}
1351
1682
  },
1683
+ canonicalAddress: createCanonicalAddress({
1684
+ addressKind: "field-result",
1685
+ storyKey,
1686
+ staleCheckKind: "field",
1687
+ operationScope: "field-refresh",
1688
+ sourceRefs: [sourceRef],
1689
+ staleHash: targetHash,
1690
+ rangeBoundary: {
1691
+ boundaryKind: "field-result",
1692
+ from: 0,
1693
+ to: Array.from(resultText).length
1694
+ },
1695
+ discriminator: {
1696
+ canonicalFieldId: field.canonicalFieldId ?? null,
1697
+ fieldFamily: field.fieldFamily ?? null,
1698
+ fieldTarget: field.fieldTarget ?? null,
1699
+ sourceId: sourceRef?.sourceId ?? null
1700
+ }
1701
+ }),
1352
1702
  staleCheck: {
1353
1703
  blockType: "field",
1354
- targetHash: hashText(`${field.instruction}\0${resultText}`),
1704
+ targetHash,
1355
1705
  targetTextLength: Array.from(resultText).length,
1356
1706
  childCount: field.children.length,
1357
1707
  ...sourceRef !== void 0 ? { sourceRef } : {}
@@ -1365,6 +1715,7 @@ function createFieldEditableTarget(field, storyKey, inlinePath) {
1365
1715
  function createHyperlinkEditableTarget(hyperlink, storyKey, inlinePath) {
1366
1716
  const text = hyperlink.children.map(inlineTextForTargetHash).join("");
1367
1717
  const sourceRef = hyperlink.sourceRef ?? hyperlink.fieldCarrier?.sourceRef;
1718
+ const targetHash = hashText(`${hyperlink.href}\0${text}`);
1368
1719
  return {
1369
1720
  targetKey: `${storyKey}:${inlinePath}:hyperlink`,
1370
1721
  kind: "hyperlink-text",
@@ -1375,9 +1726,25 @@ function createHyperlinkEditableTarget(hyperlink, storyKey, inlinePath) {
1375
1726
  editability: "editable",
1376
1727
  ...sourceRef !== void 0 ? { sourceRef } : {},
1377
1728
  link: { href: hyperlink.href },
1729
+ canonicalAddress: createCanonicalAddress({
1730
+ addressKind: "hyperlink-display-text",
1731
+ storyKey,
1732
+ staleCheckKind: "hyperlink",
1733
+ sourceRefs: [sourceRef],
1734
+ staleHash: targetHash,
1735
+ rangeBoundary: {
1736
+ boundaryKind: "hyperlink-display",
1737
+ from: 0,
1738
+ to: Array.from(text).length
1739
+ },
1740
+ discriminator: {
1741
+ href: hyperlink.href,
1742
+ sourceId: sourceRef?.sourceId ?? null
1743
+ }
1744
+ }),
1378
1745
  staleCheck: {
1379
1746
  blockType: "hyperlink",
1380
- targetHash: hashText(`${hyperlink.href}\0${text}`),
1747
+ targetHash,
1381
1748
  targetTextLength: Array.from(text).length,
1382
1749
  childCount: hyperlink.children.length,
1383
1750
  ...sourceRef !== void 0 ? { sourceRef } : {}
@@ -1385,7 +1752,52 @@ function createHyperlinkEditableTarget(hyperlink, storyKey, inlinePath) {
1385
1752
  posture: { blockers: [] }
1386
1753
  };
1387
1754
  }
1388
- function createBookmarkEditableTarget(bookmarkId, bookmarkName, storyKey, inlinePath, edge) {
1755
+ function createHyperlinkDestinationEditableTarget(hyperlink, storyKey, inlinePath) {
1756
+ const sourceRef = hyperlink.sourceRef ?? hyperlink.fieldCarrier?.sourceRef;
1757
+ const destinationKind = hyperlink.href.startsWith("#") ? "internal-anchor" : "external";
1758
+ const targetHash = hashText(`destination\0${hyperlink.href}`);
1759
+ return {
1760
+ targetKey: `${storyKey}:${inlinePath}:hyperlink-destination`,
1761
+ kind: "hyperlink-destination",
1762
+ storyKey,
1763
+ blockPath: inlinePath,
1764
+ leafPath: `${inlinePath}/destination`,
1765
+ commandFamily: "link-bookmark",
1766
+ editability: "non-editable",
1767
+ ...sourceRef !== void 0 ? { sourceRef } : {},
1768
+ link: {
1769
+ href: hyperlink.href,
1770
+ destinationKind
1771
+ },
1772
+ canonicalAddress: createCanonicalAddress({
1773
+ addressKind: "hyperlink-destination",
1774
+ storyKey,
1775
+ staleCheckKind: "hyperlink",
1776
+ operationScope: "link-destination",
1777
+ sourceRefs: [sourceRef],
1778
+ staleHash: targetHash,
1779
+ rangeBoundary: {
1780
+ boundaryKind: "hyperlink-destination",
1781
+ ...sourceRef !== void 0 ? { startSourceJoinHash: sourceJoinHash([sourceRef]) } : {},
1782
+ ...sourceRef !== void 0 ? { endSourceJoinHash: sourceJoinHash([sourceRef]) } : {}
1783
+ },
1784
+ discriminator: {
1785
+ href: hyperlink.href,
1786
+ destinationKind,
1787
+ sourceId: sourceRef?.sourceId ?? null
1788
+ }
1789
+ }),
1790
+ staleCheck: {
1791
+ blockType: "hyperlink",
1792
+ targetHash,
1793
+ childCount: hyperlink.children.length,
1794
+ ...sourceRef !== void 0 ? { sourceRef } : {}
1795
+ },
1796
+ posture: { blockers: ["unmodeled-target"] }
1797
+ };
1798
+ }
1799
+ function createBookmarkEditableTarget(bookmarkId, bookmarkName, storyKey, inlinePath, edge, sourceRef) {
1800
+ const targetHash = hashText(`${edge}\0${bookmarkId}\0${bookmarkName ?? ""}`);
1389
1801
  return {
1390
1802
  targetKey: `${storyKey}:${inlinePath}:bookmark:${edge}:${bookmarkId}`,
1391
1803
  kind: "bookmark-anchor",
@@ -1394,14 +1806,34 @@ function createBookmarkEditableTarget(bookmarkId, bookmarkName, storyKey, inline
1394
1806
  leafPath: inlinePath,
1395
1807
  commandFamily: "link-bookmark",
1396
1808
  editability: "non-editable",
1809
+ ...sourceRef !== void 0 ? { sourceRef } : {},
1397
1810
  link: {
1398
1811
  bookmarkId,
1399
1812
  ...bookmarkName !== void 0 ? { bookmarkName } : {}
1400
1813
  },
1814
+ canonicalAddress: createCanonicalAddress({
1815
+ addressKind: "bookmark-anchor",
1816
+ storyKey,
1817
+ staleCheckKind: "bookmark",
1818
+ sourceRefs: [sourceRef],
1819
+ staleHash: targetHash,
1820
+ rangeBoundary: {
1821
+ boundaryKind: "bookmark-anchor",
1822
+ ...sourceRef !== void 0 ? { startSourceJoinHash: sourceJoinHash([sourceRef]) } : {},
1823
+ ...sourceRef !== void 0 ? { endSourceJoinHash: sourceJoinHash([sourceRef]) } : {}
1824
+ },
1825
+ discriminator: {
1826
+ bookmarkId,
1827
+ bookmarkName: bookmarkName ?? null,
1828
+ edge,
1829
+ sourceId: sourceRef?.sourceId ?? null
1830
+ }
1831
+ }),
1401
1832
  staleCheck: {
1402
1833
  blockType: "bookmark",
1403
- targetHash: hashText(`${edge}\0${bookmarkId}\0${bookmarkName ?? ""}`),
1404
- childCount: 0
1834
+ targetHash,
1835
+ childCount: 0,
1836
+ ...sourceRef !== void 0 ? { sourceRef } : {}
1405
1837
  },
1406
1838
  posture: { blockers: ["unmodeled-target"] }
1407
1839
  };
@@ -1449,6 +1881,7 @@ function createObjectEditableTarget(inline, storyKey, inlinePath) {
1449
1881
  storyKey,
1450
1882
  inlinePath,
1451
1883
  objectKind: "ole",
1884
+ sourceRef: inline.sourceRef,
1452
1885
  targetHash: `${inline.id}\0${inline.relationshipId}`,
1453
1886
  object: {
1454
1887
  objectKind: "ole",
@@ -1570,6 +2003,167 @@ function createOpaqueEditableTarget(input) {
1570
2003
  }
1571
2004
  };
1572
2005
  }
2006
+ function collectFieldRegionRefreshTargets(doc, targets) {
2007
+ for (const region of collectCanonicalFieldRegionIdentities(doc)) {
2008
+ targets.push(createFieldRegionRefreshEditableTarget(region));
2009
+ }
2010
+ }
2011
+ function createFieldRegionRefreshEditableTarget(region) {
2012
+ const isToc = region.kind === "toc-region" || region.fieldFamily === "TOC";
2013
+ const sourceRef = region.sourceRef;
2014
+ const targetHash = hashText(JSON.stringify({
2015
+ regionId: region.regionId,
2016
+ canonicalFieldId: region.canonicalFieldId,
2017
+ fieldFamily: region.fieldFamily,
2018
+ refreshStatus: region.refreshStatus,
2019
+ tocId: region.tocId ?? null,
2020
+ resultRange: region.resultRange ?? null,
2021
+ status: region.status ?? null
2022
+ }));
2023
+ return {
2024
+ targetKey: `${region.storyKey}:field-region:${region.regionId}:refresh`,
2025
+ kind: isToc ? "toc-region-refresh" : "field-region-refresh",
2026
+ storyKey: region.storyKey,
2027
+ blockPath: `${region.storyKey}/field-region[${region.regionId}]`,
2028
+ leafPath: `${region.storyKey}/field-region[${region.regionId}]/refresh`,
2029
+ commandFamily: "field",
2030
+ editability: "non-editable",
2031
+ ...sourceRef !== void 0 ? { sourceRef } : {},
2032
+ field: {
2033
+ canonicalFieldId: region.canonicalFieldId,
2034
+ regionId: region.regionId,
2035
+ fieldFamily: region.fieldFamily,
2036
+ refreshStatus: region.refreshStatus,
2037
+ ...region.sourcePath !== void 0 ? { sourcePath: region.sourcePath } : {},
2038
+ ...region.tocId !== void 0 ? { tocId: region.tocId } : {},
2039
+ ...region.resultRange !== void 0 ? {
2040
+ resultRangeFromParagraphIndex: region.resultRange.fromParagraphIndex,
2041
+ resultRangeToParagraphIndex: region.resultRange.toParagraphIndex
2042
+ } : {},
2043
+ ...region.status !== void 0 ? { status: region.status } : {},
2044
+ ...region.cachedEntryCount !== void 0 ? { cachedEntryCount: region.cachedEntryCount } : {},
2045
+ ...region.generatedEntryCount !== void 0 ? { generatedEntryCount: region.generatedEntryCount } : {}
2046
+ },
2047
+ canonicalAddress: createCanonicalAddress({
2048
+ addressKind: isToc ? "toc-region-refresh" : "field-region-refresh",
2049
+ storyKey: region.storyKey,
2050
+ staleCheckKind: "field",
2051
+ operationScope: isToc ? "toc-refresh" : "field-refresh",
2052
+ sourceRefs: [sourceRef],
2053
+ staleHash: targetHash,
2054
+ rangeBoundary: {
2055
+ boundaryKind: "field-region",
2056
+ ...region.resultRange !== void 0 ? {
2057
+ from: region.resultRange.fromParagraphIndex,
2058
+ to: region.resultRange.toParagraphIndex
2059
+ } : { from: region.paragraphIndex, to: region.paragraphIndex }
2060
+ },
2061
+ discriminator: {
2062
+ regionId: region.regionId,
2063
+ canonicalFieldId: region.canonicalFieldId,
2064
+ fieldIndex: region.fieldIndex,
2065
+ fieldFamily: region.fieldFamily,
2066
+ tocId: region.tocId ?? null
2067
+ }
2068
+ }),
2069
+ staleCheck: {
2070
+ blockType: "field",
2071
+ targetHash,
2072
+ childCount: region.cachedEntryCount ?? 0,
2073
+ ...sourceRef !== void 0 ? { sourceRef } : {}
2074
+ },
2075
+ posture: {
2076
+ blockers: ["field-generated-text", "unmodeled-target"]
2077
+ }
2078
+ };
2079
+ }
2080
+ function collectBookmarkContentRangeTargets(doc, targets) {
2081
+ const candidates = /* @__PURE__ */ new Map();
2082
+ for (const context of collectStoryBlockContexts(doc)) {
2083
+ walkBlocks(context.blocks, context.storyKey, context.basePath, {
2084
+ inline(inline, _blockPath, inlinePath) {
2085
+ if (inline.type !== "bookmark_start" && inline.type !== "bookmark_end") return;
2086
+ const key = `${context.storyKey}:${inline.bookmarkId}`;
2087
+ const previous = candidates.get(key);
2088
+ if (inline.type === "bookmark_start") {
2089
+ candidates.set(key, {
2090
+ ...previous ?? { storyKey: context.storyKey, bookmarkId: inline.bookmarkId },
2091
+ bookmarkName: inline.name,
2092
+ startPath: inlinePath,
2093
+ startSourceRef: inline.sourceRef
2094
+ });
2095
+ return;
2096
+ }
2097
+ candidates.set(key, {
2098
+ ...previous ?? { storyKey: context.storyKey, bookmarkId: inline.bookmarkId },
2099
+ endPath: inlinePath,
2100
+ endSourceRef: inline.sourceRef
2101
+ });
2102
+ }
2103
+ });
2104
+ }
2105
+ for (const candidate of candidates.values()) {
2106
+ if (candidate.startPath === void 0 || candidate.endPath === void 0) continue;
2107
+ targets.push(createBookmarkContentRangeEditableTarget({
2108
+ ...candidate,
2109
+ startPath: candidate.startPath,
2110
+ endPath: candidate.endPath
2111
+ }));
2112
+ }
2113
+ }
2114
+ function createBookmarkContentRangeEditableTarget(candidate) {
2115
+ const startSourceJoinHash = sourceJoinHash([candidate.startSourceRef]);
2116
+ const endSourceJoinHash = sourceJoinHash([candidate.endSourceRef]);
2117
+ const rangeKey = hashText(JSON.stringify({
2118
+ storyKey: candidate.storyKey,
2119
+ bookmarkId: candidate.bookmarkId,
2120
+ bookmarkName: candidate.bookmarkName ?? null,
2121
+ startSourceId: candidate.startSourceRef?.sourceId ?? null,
2122
+ endSourceId: candidate.endSourceRef?.sourceId ?? null
2123
+ }));
2124
+ const targetHash = hashText(`range\0${candidate.bookmarkId}\0${candidate.bookmarkName ?? ""}\0${candidate.startPath}\0${candidate.endPath}`);
2125
+ return {
2126
+ targetKey: `${candidate.storyKey}:bookmark:${candidate.bookmarkId}:content-range`,
2127
+ kind: "bookmark-content-range",
2128
+ storyKey: candidate.storyKey,
2129
+ blockPath: `${candidate.storyKey}/bookmark[${candidate.bookmarkId}]`,
2130
+ leafPath: `${candidate.storyKey}/bookmark[${candidate.bookmarkId}]/content-range`,
2131
+ commandFamily: "link-bookmark",
2132
+ editability: "non-editable",
2133
+ ...candidate.startSourceRef !== void 0 ? { sourceRef: candidate.startSourceRef } : {},
2134
+ link: {
2135
+ bookmarkId: candidate.bookmarkId,
2136
+ ...candidate.bookmarkName !== void 0 ? { bookmarkName: candidate.bookmarkName } : {},
2137
+ rangeKey
2138
+ },
2139
+ canonicalAddress: createCanonicalAddress({
2140
+ addressKind: "bookmark-content-range",
2141
+ storyKey: candidate.storyKey,
2142
+ staleCheckKind: "bookmark",
2143
+ operationScope: "bookmark-range",
2144
+ sourceRefs: [candidate.startSourceRef, candidate.endSourceRef],
2145
+ staleHash: targetHash,
2146
+ rangeBoundary: {
2147
+ boundaryKind: "bookmark-content",
2148
+ ...startSourceJoinHash !== void 0 ? { startSourceJoinHash } : {},
2149
+ ...endSourceJoinHash !== void 0 ? { endSourceJoinHash } : {}
2150
+ },
2151
+ discriminator: {
2152
+ bookmarkId: candidate.bookmarkId,
2153
+ bookmarkName: candidate.bookmarkName ?? null,
2154
+ startSourceId: candidate.startSourceRef?.sourceId ?? null,
2155
+ endSourceId: candidate.endSourceRef?.sourceId ?? null
2156
+ }
2157
+ }),
2158
+ staleCheck: {
2159
+ blockType: "bookmark",
2160
+ targetHash,
2161
+ childCount: 2,
2162
+ ...candidate.startSourceRef !== void 0 ? { sourceRef: candidate.startSourceRef } : {}
2163
+ },
2164
+ posture: { blockers: ["unmodeled-target"] }
2165
+ };
2166
+ }
1573
2167
  function inlineObjectKind(inline) {
1574
2168
  switch (inline.type) {
1575
2169
  case "chart_preview":
@@ -1692,6 +2286,16 @@ function collectParagraphText(paragraph) {
1692
2286
  }
1693
2287
  return text;
1694
2288
  }
2289
+ function blockTextForTargetHash(block) {
2290
+ if (block.type === "paragraph") return collectParagraphText(block);
2291
+ if (block.type === "sdt" || block.type === "custom_xml") {
2292
+ return block.children.map(blockTextForTargetHash).join("");
2293
+ }
2294
+ if (block.type === "table") {
2295
+ return block.rows.flatMap((row) => row.cells).flatMap((cell) => cell.children).map(blockTextForTargetHash).join("");
2296
+ }
2297
+ return "";
2298
+ }
1695
2299
  function inlineTextForTargetHash(inline) {
1696
2300
  if (inline.type === "text") return inline.text;
1697
2301
  if (inline.type === "symbol") return inline.char;
@@ -1707,6 +2311,93 @@ function inlineTextForTargetHash(inline) {
1707
2311
  }
1708
2312
  return "";
1709
2313
  }
2314
+ function createTableTargetCanonicalAddress(table, staleCheckKind, staleHash, resolver = {}) {
2315
+ return createCanonicalAddress({
2316
+ addressKind: "table-target",
2317
+ storyKey: tableStoryKey(table),
2318
+ staleCheckKind,
2319
+ operationScope: table.operationScope,
2320
+ rowRange: table.fragment?.rowRange,
2321
+ columnRange: table.fragment?.columnRange,
2322
+ sourceRefs: [table.sourceRef, table.rowSourceRef, table.cellSourceRef],
2323
+ staleHash,
2324
+ ...resolver,
2325
+ discriminator: {
2326
+ operationScope: table.operationScope,
2327
+ tableDepth: table.tableDepth,
2328
+ rowIndex: table.rowIndex ?? null,
2329
+ columnIndex: table.columnIndex ?? null,
2330
+ cellIndex: table.cellIndex ?? null,
2331
+ gridColumnStart: table.gridColumnStart ?? null,
2332
+ gridSpan: table.gridSpan ?? null,
2333
+ verticalMerge: table.verticalMerge ?? null,
2334
+ sourceId: table.sourceRef?.sourceId ?? null,
2335
+ rowSourceId: table.rowSourceRef?.sourceId ?? null,
2336
+ cellSourceId: table.cellSourceRef?.sourceId ?? null
2337
+ },
2338
+ secondaryStory: table.secondaryStory,
2339
+ nestedTable: table.nestedTable,
2340
+ insideSdt: table.insideSdt
2341
+ });
2342
+ }
2343
+ function tableStoryKey(table) {
2344
+ const suffix = `:${table.tablePath}`;
2345
+ return table.tableKey.endsWith(suffix) ? table.tableKey.slice(0, -suffix.length) : MAIN_STORY_KEY;
2346
+ }
2347
+ function createCanonicalAddress(input) {
2348
+ const sourceHash = sourceJoinHash(input.sourceRefs ?? []);
2349
+ const payload = {
2350
+ addressKind: input.addressKind,
2351
+ storyKey: input.storyKey,
2352
+ operationScope: input.operationScope ?? null,
2353
+ rowRange: input.rowRange ?? null,
2354
+ columnRange: input.columnRange ?? null,
2355
+ sourceHash: sourceHash ?? null,
2356
+ discriminator: input.discriminator
2357
+ };
2358
+ return {
2359
+ addressKey: `editable-address:${hashText(JSON.stringify(payload))}`,
2360
+ addressKind: input.addressKind,
2361
+ storyKey: input.storyKey,
2362
+ staleCheckKind: input.staleCheckKind,
2363
+ ...input.operationScope !== void 0 ? { operationScope: input.operationScope } : {},
2364
+ ...input.rowRange !== void 0 ? { rowRange: input.rowRange } : {},
2365
+ ...input.columnRange !== void 0 ? { columnRange: input.columnRange } : {},
2366
+ ...sourceHash !== void 0 ? { sourceJoinHash: sourceHash } : {},
2367
+ ...input.secondaryStory === true ? { secondaryStory: true } : {},
2368
+ ...input.nestedTable === true ? { nestedTable: true } : {},
2369
+ ...input.insideSdt === true ? { insideSdt: true } : {},
2370
+ resolver: {
2371
+ staleHash: input.staleHash,
2372
+ ...sourceHash !== void 0 ? { sourceJoinHash: sourceHash } : {},
2373
+ ...input.rowRange !== void 0 ? { rowRange: input.rowRange } : {},
2374
+ ...input.columnRange !== void 0 ? { columnRange: input.columnRange } : {},
2375
+ ...input.rangeBoundary !== void 0 ? { rangeBoundary: input.rangeBoundary } : {},
2376
+ ...input.owner !== void 0 ? { owner: input.owner } : {}
2377
+ }
2378
+ };
2379
+ }
2380
+ function ownerRoutingFromAddress(address) {
2381
+ return {
2382
+ addressKey: address.addressKey,
2383
+ addressKind: address.addressKind,
2384
+ storyKey: address.storyKey,
2385
+ ...address.operationScope !== void 0 ? { operationScope: address.operationScope } : {},
2386
+ ...address.sourceJoinHash !== void 0 ? { sourceJoinHash: address.sourceJoinHash } : {},
2387
+ staleHash: address.resolver?.staleHash ?? "",
2388
+ ...address.rowRange !== void 0 ? { rowRange: address.rowRange } : {},
2389
+ ...address.columnRange !== void 0 ? { columnRange: address.columnRange } : {}
2390
+ };
2391
+ }
2392
+ function sourceJoinHashForRefs(...refs) {
2393
+ const sourceHash = sourceJoinHash(refs);
2394
+ return sourceHash === void 0 ? {} : { sourceJoinHash: sourceHash };
2395
+ }
2396
+ function sourceJoinHash(refs) {
2397
+ const sourceIds = refs.map((ref) => ref?.sourceId).filter((sourceId) => sourceId !== void 0);
2398
+ if (sourceIds.length === 0) return void 0;
2399
+ return hashText(sourceIds.join("\0"));
2400
+ }
1710
2401
  function collectCanonicalFieldRegionIdentities(doc) {
1711
2402
  const registry = doc.fieldRegistry;
1712
2403
  const byFieldIndex = new Map(
@@ -1904,7 +2595,7 @@ function walkBlocks(blocks, storyKey, basePath, visitor) {
1904
2595
  }
1905
2596
  if (block.type === "paragraph") {
1906
2597
  visitor.paragraph?.(block, blockPath);
1907
- walkInlines(block.children, storyKey, blockPath, `${blockPath}/inline`, visitor);
2598
+ walkInlines(block.children ?? [], storyKey, blockPath, `${blockPath}/inline`, visitor);
1908
2599
  continue;
1909
2600
  }
1910
2601
  if (block.type === "sdt" || block.type === "custom_xml") {
@@ -4654,6 +5345,7 @@ var PICTURE_EFFECT_SCHEME_ALIASES = {
4654
5345
  bg2: "lt2"
4655
5346
  };
4656
5347
  var EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH = /* @__PURE__ */ new Map();
5348
+ var NO_EDITABLE_TARGETS_INDEX = EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH;
4657
5349
  function indexEditableTargetsByBlockPath(document) {
4658
5350
  const targets = collectEditableTargetRefs(document);
4659
5351
  if (targets.length === 0) return EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH;
@@ -4705,7 +5397,7 @@ function createEditorSurfaceSnapshot(document, _selection, activeStory = { kind:
4705
5397
  ...options.getEffectiveMarkupMode ? { getEffectiveMarkupMode: options.getEffectiveMarkupMode } : {},
4706
5398
  ...options.authorColorPalette ? { authorColorPalette: options.authorColorPalette } : {}
4707
5399
  });
4708
- const editableTargetsByBlockPath = indexEditableTargetsByBlockPath(document);
5400
+ const editableTargetsByBlockPath = options.editableTargetsByBlockPath ?? indexEditableTargetsByBlockPath(document);
4709
5401
  const activeStoryBlockPathBase = getActiveStoryBlockPathBase(document, activeStory);
4710
5402
  chartModelStore.beginBuildPass(document);
4711
5403
  const unsupportedNumberingFormatsSeen = options.emitFormattingTelemetry ? /* @__PURE__ */ new Set() : null;
@@ -4986,6 +5678,7 @@ function createTableBlock(tableIndex, table, document, cursor, counters, formatt
4986
5678
  from: cursor,
4987
5679
  to: innerCursor,
4988
5680
  styleId: table.styleId,
5681
+ ...table.sourceRef !== void 0 ? { sourceRef: table.sourceRef } : {},
4989
5682
  gridColumns: table.gridColumns,
4990
5683
  rows: []
4991
5684
  },
@@ -5055,6 +5748,7 @@ function createTableBlock(tableIndex, table, document, cursor, counters, formatt
5055
5748
  resolvedTable.table?.cellMargins
5056
5749
  );
5057
5750
  cells.push({
5751
+ ...cell.sourceRef !== void 0 ? { sourceRef: cell.sourceRef } : {},
5058
5752
  gridSpan: cell.gridSpan ?? 1,
5059
5753
  verticalMerge: cell.verticalMerge ?? null,
5060
5754
  colspan: cell.gridSpan ?? 1,
@@ -5078,6 +5772,7 @@ function createTableBlock(tableIndex, table, document, cursor, counters, formatt
5078
5772
  }
5079
5773
  const headerLike = row.isHeader === true || resolvedRow?.style.isHeader === true;
5080
5774
  rows.push({
5775
+ ...row.sourceRef !== void 0 ? { sourceRef: row.sourceRef } : {},
5081
5776
  cells,
5082
5777
  ...row.gridBefore !== void 0 ? { gridBefore: row.gridBefore } : {},
5083
5778
  ...row.gridAfter !== void 0 ? { gridAfter: row.gridAfter } : {},
@@ -5108,6 +5803,7 @@ function createTableBlock(tableIndex, table, document, cursor, counters, formatt
5108
5803
  from: cursor,
5109
5804
  to: innerCursor,
5110
5805
  styleId: table.styleId,
5806
+ ...table.sourceRef !== void 0 ? { sourceRef: table.sourceRef } : {},
5111
5807
  gridColumns: table.gridColumns,
5112
5808
  ...gridColumnsRelative ? { gridColumnsRelative } : {},
5113
5809
  ...resolvedTable.table?.alignment ? { alignment: resolvedTable.table.alignment } : {},
@@ -5652,6 +6348,7 @@ function appendInlineSegments(paragraph, node, document, start, promoteSecondary
5652
6348
  const anchor = surfaceAnchorFromGeometry(node.anchor);
5653
6349
  const txbxTextSegment = c.isTextBox ? extractTxbxFirstTextSegment(c.txbxBlocks) : void 0;
5654
6350
  const txbxText = txbxTextSegment?.text ?? (c.isTextBox ? c.text : void 0);
6351
+ const txbxBody = c.isTextBox ? surfaceTextBoxBodyFromShape(c, node.sourceRef) : void 0;
5655
6352
  const surfaceFill = c.fill;
5656
6353
  paragraph.segments.push({
5657
6354
  segmentId: `${paragraph.blockId}-segment-${paragraph.segments.length}`,
@@ -5668,6 +6365,7 @@ function appendInlineSegments(paragraph, node, document, start, promoteSecondary
5668
6365
  ...c.textBoxBody ? { textBoxBody: c.textBoxBody } : {},
5669
6366
  ...c.preserveOnlyObject ? { preserveOnlyObject: surfacePreserveOnlyObject(c.preserveOnlyObject) } : {},
5670
6367
  ...txbxText ? { txbxText } : {},
6368
+ ...txbxBody ? { txbxBody } : {},
5671
6369
  ...txbxTextSegment?.marks && txbxTextSegment.marks.length > 0 ? { txbxMarks: txbxTextSegment.marks } : {},
5672
6370
  ...txbxTextSegment?.markAttrs ? { txbxMarkAttrs: txbxTextSegment.markAttrs } : {}
5673
6371
  });
@@ -6080,6 +6778,97 @@ function extractTxbxFirstTextSegment(blocks) {
6080
6778
  }
6081
6779
  return void 0;
6082
6780
  }
6781
+ function surfaceTextBoxBodyFromShape(shape, sourceRef) {
6782
+ if (!shape.isTextBox && shape.txbxContentXml === void 0 && shape.txbxBlocks === void 0) {
6783
+ return void 0;
6784
+ }
6785
+ if (shape.txbxBlocks === void 0) {
6786
+ return {
6787
+ ...sourceRef !== void 0 ? { sourceRef } : {},
6788
+ status: shape.txbxContentXml !== void 0 ? "preserve-only" : "unavailable",
6789
+ unavailableReason: "txbx-blocks-unavailable",
6790
+ ...shape.textBoxBody !== void 0 ? { bodyProperties: shape.textBoxBody } : {},
6791
+ blockCount: 0,
6792
+ paragraphCount: 0,
6793
+ unsupportedBlockCount: 0,
6794
+ paragraphs: []
6795
+ };
6796
+ }
6797
+ const paragraphs = shape.txbxBlocks.flatMap((block, blockIndex) => {
6798
+ if (block.type !== "paragraph") return [];
6799
+ const children = block.children;
6800
+ const legacyRuns = block.runs;
6801
+ const runs = children !== void 0 ? children.map(
6802
+ (inline, inlineIndex) => surfaceTextBoxRunFromInline(inline, inlineIndex)
6803
+ ) : legacyRuns?.map(
6804
+ (run, inlineIndex) => surfaceTextBoxRunFromLegacyRun(run, inlineIndex)
6805
+ ) ?? [];
6806
+ const text = runs.map((run) => run.text ?? "").join("");
6807
+ return [{
6808
+ ...block.sourceRef !== void 0 ? { sourceRef: block.sourceRef } : {},
6809
+ blockIndex,
6810
+ text,
6811
+ textLength: Array.from(text).length,
6812
+ ...block.borders !== void 0 ? { borders: block.borders } : {},
6813
+ runs
6814
+ }];
6815
+ });
6816
+ const unsupportedBlockCount = shape.txbxBlocks.length - paragraphs.length;
6817
+ const unavailableReason = shape.txbxBlocks.length === 0 ? "empty-body" : paragraphs.length === 0 ? "unsupported-content" : void 0;
6818
+ return {
6819
+ ...sourceRef !== void 0 ? { sourceRef } : {},
6820
+ status: unavailableReason === void 0 ? "modeled" : "unavailable",
6821
+ ...unavailableReason !== void 0 ? { unavailableReason } : {},
6822
+ ...shape.textBoxBody !== void 0 ? { bodyProperties: shape.textBoxBody } : {},
6823
+ blockCount: shape.txbxBlocks.length,
6824
+ paragraphCount: paragraphs.length,
6825
+ unsupportedBlockCount,
6826
+ paragraphs
6827
+ };
6828
+ }
6829
+ function surfaceTextBoxRunFromLegacyRun(run, inlineIndex) {
6830
+ const text = run.text ?? "";
6831
+ const cloned = run.marks ? cloneMarks2(run.marks) : void 0;
6832
+ return {
6833
+ inlineIndex,
6834
+ kind: "text",
6835
+ text,
6836
+ textLength: Array.from(text).length,
6837
+ ...cloned?.marks && cloned.marks.length > 0 ? { marks: cloned.marks } : {},
6838
+ ...cloned?.markAttrs ? { markAttrs: cloned.markAttrs } : {}
6839
+ };
6840
+ }
6841
+ function surfaceTextBoxRunFromInline(inline, inlineIndex) {
6842
+ if (inline.type === "text") {
6843
+ const cloned = inline.marks ? cloneMarks2(inline.marks) : void 0;
6844
+ return {
6845
+ inlineIndex,
6846
+ kind: "text",
6847
+ text: inline.text,
6848
+ textLength: Array.from(inline.text).length,
6849
+ ...cloned?.marks && cloned.marks.length > 0 ? { marks: cloned.marks } : {},
6850
+ ...cloned?.markAttrs ? { markAttrs: cloned.markAttrs } : {}
6851
+ };
6852
+ }
6853
+ if (inline.type === "tab") {
6854
+ return { inlineIndex, kind: "tab", text: " ", textLength: 1 };
6855
+ }
6856
+ if (inline.type === "hard_break") {
6857
+ return { inlineIndex, kind: "hard-break", text: "\n", textLength: 1 };
6858
+ }
6859
+ if (inline.type === "symbol") {
6860
+ const cloned = inline.marks ? cloneMarks2(inline.marks) : void 0;
6861
+ return {
6862
+ inlineIndex,
6863
+ kind: "symbol",
6864
+ text: inline.char,
6865
+ textLength: Array.from(inline.char).length,
6866
+ ...cloned?.marks && cloned.marks.length > 0 ? { marks: cloned.marks } : {},
6867
+ ...cloned?.markAttrs ? { markAttrs: cloned.markAttrs } : {}
6868
+ };
6869
+ }
6870
+ return { inlineIndex, kind: "unsupported" };
6871
+ }
6083
6872
  function appendComplexPreviewSegment(paragraph, node, start, label, detail, extras = {}) {
6084
6873
  const preserveOnlyObject = node.preserveOnlyObject ? surfacePreserveOnlyObject(node.preserveOnlyObject) : void 0;
6085
6874
  paragraph.segments.push({
@@ -6681,7 +7470,7 @@ function applyLinearTextTransaction(document, selection, intent, options) {
6681
7470
  const insertionUnits = createInsertionUnits(intent, story, normalizedRange.from, resolvedMarks);
6682
7471
  const unitFrom = logicalPositionToUnitIndex(story.units, normalizedRange.from, "after");
6683
7472
  const unitTo = logicalPositionToUnitIndex(story.units, normalizedRange.to, "before");
6684
- ensureEditableRange(story.units.slice(unitFrom, unitTo));
7473
+ ensureEditableTransactionRange(story.units, normalizedRange, unitFrom, unitTo);
6685
7474
  const nextUnits = [
6686
7475
  ...story.units.slice(0, unitFrom).map(cloneStoryUnit),
6687
7476
  ...insertionUnits.map(cloneStoryUnit),
@@ -7059,7 +7848,9 @@ function resolveTableParagraphScope(document, selection, target) {
7059
7848
  if (!root || root.type !== "doc" || !Array.isArray(root.children)) {
7060
7849
  return null;
7061
7850
  }
7062
- const surface = createEditorSurfaceSnapshot(document, selection);
7851
+ const surface = createEditorSurfaceSnapshot(document, selection, void 0, {
7852
+ editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX
7853
+ });
7063
7854
  const selectionFrom = Math.min(selection.anchor, selection.head);
7064
7855
  const selectionTo = Math.max(selection.anchor, selection.head);
7065
7856
  for (let blockIndex = 0; blockIndex < root.children.length; blockIndex += 1) {
@@ -7172,7 +7963,9 @@ function resolveTargetlessTableStructureInsertRefusal(document, selection, inten
7172
7963
  if (!root || root.type !== "doc" || !Array.isArray(root.children)) {
7173
7964
  return null;
7174
7965
  }
7175
- const surface = createEditorSurfaceSnapshot(document, selection);
7966
+ const surface = createEditorSurfaceSnapshot(document, selection, void 0, {
7967
+ editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX
7968
+ });
7176
7969
  if (!selectionTouchesTableStructureBoundary(surface.blocks, selection.anchor)) {
7177
7970
  return null;
7178
7971
  }
@@ -7222,7 +8015,9 @@ function resolveTargetedTableParagraphScope(document, selection, target) {
7222
8015
  if (cell.verticalMerge === "continue") {
7223
8016
  return "unsupported";
7224
8017
  }
7225
- const surface = createEditorSurfaceSnapshot(document, selection);
8018
+ const surface = createEditorSurfaceSnapshot(document, selection, void 0, {
8019
+ editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX
8020
+ });
7226
8021
  const surfaceBlock = surface.blocks[target.tableBlockIndex];
7227
8022
  const surfaceRow = surfaceBlock?.kind === "table" ? surfaceBlock.rows[target.rowIndex] : void 0;
7228
8023
  const surfaceCell = surfaceRow?.cells[target.cellIndex];
@@ -7293,7 +8088,9 @@ function resolveTargetedTableParagraphScopeByPath(root, document, selection, tar
7293
8088
  const resolved = resolveBlockPathInCanonicalBlocks(root.children, tokens, 0);
7294
8089
  if (!resolved || resolved.block.type !== "paragraph") return null;
7295
8090
  if (resolved.hasVerticalMergeContinuation) return null;
7296
- const surface = createEditorSurfaceSnapshot(document, selection);
8091
+ const surface = createEditorSurfaceSnapshot(document, selection, void 0, {
8092
+ editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX
8093
+ });
7297
8094
  const surfaceResolved = resolveBlockPathInSurfaceBlocks(surface.blocks, tokens, 0);
7298
8095
  if (!surfaceResolved || surfaceResolved.kind !== "paragraph") return null;
7299
8096
  if (surfaceResolved.hasVerticalMergeContinuation) return null;
@@ -7753,7 +8550,9 @@ function resolveTopLevelParagraphScope(document, selection) {
7753
8550
  if (!root || root.type !== "doc" || !Array.isArray(root.children)) {
7754
8551
  return null;
7755
8552
  }
7756
- const surface = createEditorSurfaceSnapshot(document, selection);
8553
+ const surface = createEditorSurfaceSnapshot(document, selection, void 0, {
8554
+ editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX
8555
+ });
7757
8556
  const selectionFrom = Math.min(selection.anchor, selection.head);
7758
8557
  const selectionTo = Math.max(selection.anchor, selection.head);
7759
8558
  for (let blockIndex = 0; blockIndex < root.children.length; blockIndex += 1) {
@@ -7787,7 +8586,9 @@ function resolveTopLevelSdtParagraphScope(document, selection) {
7787
8586
  if (!root || root.type !== "doc" || !Array.isArray(root.children)) {
7788
8587
  return null;
7789
8588
  }
7790
- const surface = createEditorSurfaceSnapshot(document, selection);
8589
+ const surface = createEditorSurfaceSnapshot(document, selection, void 0, {
8590
+ editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX
8591
+ });
7791
8592
  const selectionFrom = Math.min(selection.anchor, selection.head);
7792
8593
  const selectionTo = Math.max(selection.anchor, selection.head);
7793
8594
  for (let blockIndex = 0; blockIndex < root.children.length; blockIndex += 1) {
@@ -8054,16 +8855,61 @@ function normalizeStoryUnits(units) {
8054
8855
  }
8055
8856
  function ensureEditableRange(units) {
8056
8857
  const protectedUnit = units.find(
8057
- (unit) => unit.kind === "opaque_inline" || unit.kind === "opaque_block" || unit.kind === "structural_block" || unit.kind === "image"
8858
+ (unit) => unit.kind === "opaque_inline" || unit.kind === "opaque_block" || unit.kind === "structural_block" || unit.kind === "image" || unit.kind === "protected_inline"
8058
8859
  );
8059
8860
  if (!protectedUnit) {
8060
8861
  return;
8061
8862
  }
8062
8863
  throw new TextTransactionError(
8063
8864
  "unsupported_content",
8064
- `Text transaction crosses protected ${protectedUnit.kind} content.`
8865
+ `Text transaction crosses protected ${protectedUnit.kind === "protected_inline" ? protectedUnit.reason : protectedUnit.kind} content.`
8065
8866
  );
8066
8867
  }
8868
+ function ensureEditableTransactionRange(units, range, unitFrom, unitTo) {
8869
+ ensureEditableRange(units.slice(unitFrom, unitTo));
8870
+ const protectedUnit = range.from === range.to ? protectedInlineAtPosition(units, range.from) : protectedInlineOverlappingRange(units, range);
8871
+ if (!protectedUnit) {
8872
+ return;
8873
+ }
8874
+ throw new TextTransactionError(
8875
+ "unsupported_content",
8876
+ `Text transaction crosses protected ${protectedUnit.reason} content.`
8877
+ );
8878
+ }
8879
+ function protectedInlineOverlappingRange(units, range) {
8880
+ let cursor = 0;
8881
+ for (const unit of units) {
8882
+ if (unit.kind === "scope_marker") continue;
8883
+ if (unit.kind === "protected_inline") {
8884
+ const size = Math.max(0, unit.logicalSize);
8885
+ const start = cursor;
8886
+ const end = cursor + size;
8887
+ if (size > 0 && range.from < end && range.to > start || size === 0 && range.from <= start && range.to >= start) {
8888
+ return unit;
8889
+ }
8890
+ cursor = end;
8891
+ continue;
8892
+ }
8893
+ cursor += 1;
8894
+ }
8895
+ return null;
8896
+ }
8897
+ function protectedInlineAtPosition(units, position) {
8898
+ let cursor = 0;
8899
+ for (const unit of units) {
8900
+ if (unit.kind === "scope_marker") continue;
8901
+ if (unit.kind === "protected_inline") {
8902
+ const size = Math.max(0, unit.logicalSize);
8903
+ if (size > 0 && position > cursor && position < cursor + size) {
8904
+ return unit;
8905
+ }
8906
+ cursor += size;
8907
+ continue;
8908
+ }
8909
+ cursor += 1;
8910
+ }
8911
+ return null;
8912
+ }
8067
8913
  function containsParagraphBoundaryChange(story, range, insertionUnits) {
8068
8914
  if (insertionUnits.some((unit) => unit.kind === "paragraph_break")) {
8069
8915
  return true;
@@ -8085,7 +8931,9 @@ function resolveParagraphScope(document, selection) {
8085
8931
  if (!root) {
8086
8932
  return null;
8087
8933
  }
8088
- const surface = createEditorSurfaceSnapshot(document, selection);
8934
+ const surface = createEditorSurfaceSnapshot(document, selection, void 0, {
8935
+ editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX
8936
+ });
8089
8937
  const selectionFrom = Math.min(selection.anchor, selection.head);
8090
8938
  const selectionTo = Math.max(selection.anchor, selection.head);
8091
8939
  for (let blockIndex = 0; blockIndex < root.children.length; blockIndex += 1) {
@@ -8313,7 +9161,12 @@ function applyNextStyleToNewParagraph(result, nextStyleId) {
8313
9161
  return result;
8314
9162
  }
8315
9163
  const head = result.selection.head;
8316
- const surface = createEditorSurfaceSnapshot(result.document, result.selection);
9164
+ const surface = createEditorSurfaceSnapshot(
9165
+ result.document,
9166
+ result.selection,
9167
+ void 0,
9168
+ { editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX }
9169
+ );
8317
9170
  let targetBlockIndex = -1;
8318
9171
  for (let i = 0; i < surface.blocks.length; i += 1) {
8319
9172
  const surfaceBlock = surface.blocks[i];