@beyondwork/docx-react-component 1.0.120 → 1.0.122

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
@@ -258,7 +258,7 @@ function createHeaderFooterStoryKey(input) {
258
258
  function createNoteStoryKey(kind, noteId) {
259
259
  return `${kind}:${noteId}`;
260
260
  }
261
- function collectEditableTargetRefs(doc) {
261
+ function collectEditableTargetRefs(doc, cache) {
262
262
  const targets = [];
263
263
  for (const context of collectStoryBlockContexts(doc)) {
264
264
  collectEditableTargetsInBlocks(
@@ -270,17 +270,53 @@ function collectEditableTargetRefs(doc) {
270
270
  insideTextBox: false,
271
271
  tableDepth: 0
272
272
  },
273
- targets
273
+ targets,
274
+ cache
274
275
  );
275
276
  }
277
+ collectFieldRegionRefreshTargets(doc, targets);
278
+ collectBookmarkContentRangeTargets(doc, targets);
276
279
  collectReviewEditableTargets(doc, targets);
277
280
  return targets;
278
281
  }
279
- function collectEditableTargetsInBlocks(blocks, context, targets) {
282
+ function buildBlockCacheSignature(context, blockIndex) {
283
+ const cc = context.contentControl;
284
+ const tt = context.tableTarget;
285
+ const owner = tt?.editableOwnersByChildIndex?.get(blockIndex);
286
+ return [
287
+ context.storyKey,
288
+ context.insideSdt ? "1" : "0",
289
+ context.insideTextBox ? "1" : "0",
290
+ String(context.tableDepth),
291
+ cc?.sdtId ?? "",
292
+ cc?.tag ?? "",
293
+ cc?.alias ?? "",
294
+ cc?.sdtType ?? "",
295
+ cc?.lock ?? "",
296
+ tt?.tablePath ?? "",
297
+ tt?.tableDepth ?? "",
298
+ tt?.rowIndex ?? "",
299
+ tt?.cellIndex ?? "",
300
+ tt?.gridColumnStart ?? "",
301
+ tt?.cell?.verticalMerge ?? "",
302
+ tt?.cell?.gridSpan ?? "",
303
+ owner?.targetKey ?? ""
304
+ ].join("|");
305
+ }
306
+ function collectEditableTargetsInBlocks(blocks, context, targets, cache) {
280
307
  for (let blockIndex = 0; blockIndex < blocks.length; blockIndex += 1) {
281
308
  const block = blocks[blockIndex];
282
309
  if (!block) continue;
283
310
  const blockPath = `${context.basePath}/block[${blockIndex}]`;
311
+ const signature = cache !== void 0 ? buildBlockCacheSignature(context, blockIndex) : "";
312
+ if (cache !== void 0) {
313
+ const cached = cache.get(block);
314
+ if (cached !== void 0 && cached.blockPath === blockPath && cached.signature === signature) {
315
+ for (const target of cached.targets) targets.push(target);
316
+ continue;
317
+ }
318
+ }
319
+ const blockStart = targets.length;
284
320
  if (block.type === "paragraph") {
285
321
  const targetKind = editableParagraphTargetKind(context);
286
322
  if (targetKind !== null) {
@@ -292,14 +328,13 @@ function collectEditableTargetsInBlocks(blocks, context, targets) {
292
328
  blockPath,
293
329
  editableParagraphTargetPosture(targetKind),
294
330
  context.contentControl,
295
- context.tableTarget
331
+ context.tableTarget,
332
+ context.tableTarget?.editableOwnersByChildIndex?.get(blockIndex)
296
333
  )
297
334
  );
298
335
  }
299
336
  collectEditableTargetsInInlines(block.children ?? [], `${blockPath}/inline`, context, targets);
300
- continue;
301
- }
302
- if (block.type === "sdt") {
337
+ } else if (block.type === "sdt") {
303
338
  const contentControl = contentControlIdentityForSdt(block, context.contentControl);
304
339
  collectEditableTargetsInBlocks(
305
340
  block.children,
@@ -309,11 +344,10 @@ function collectEditableTargetsInBlocks(blocks, context, targets) {
309
344
  insideSdt: true,
310
345
  contentControl
311
346
  },
312
- targets
347
+ targets,
348
+ cache
313
349
  );
314
- continue;
315
- }
316
- if (block.type === "custom_xml") {
350
+ } else if (block.type === "custom_xml") {
317
351
  targets.push(createCustomXmlEditableTarget(block, context.storyKey, blockPath));
318
352
  collectEditableTargetsInBlocks(
319
353
  block.children,
@@ -321,25 +355,29 @@ function collectEditableTargetsInBlocks(blocks, context, targets) {
321
355
  ...context,
322
356
  basePath: blockPath
323
357
  },
324
- targets
358
+ targets,
359
+ cache
325
360
  );
326
- continue;
327
- }
328
- if (block.type === "opaque_block") {
361
+ } else if (block.type === "opaque_block") {
329
362
  targets.push(createOpaqueBlockEditableTarget(block, context.storyKey, blockPath));
330
- continue;
331
- }
332
- if (block.type === "alt_chunk") {
363
+ } else if (block.type === "alt_chunk") {
333
364
  targets.push(createAltChunkEditableTarget(block.relationshipId, context.storyKey, blockPath));
334
- continue;
335
- }
336
- if (block.type === "table") {
337
- collectEditableTargetsInTable(block, blockPath, context, targets);
365
+ } else if (block.type === "table") {
366
+ collectEditableTargetsInTable(block, blockPath, context, targets, cache);
367
+ }
368
+ if (cache !== void 0) {
369
+ const blockTargets = targets.slice(blockStart);
370
+ cache.set(block, {
371
+ blockPath,
372
+ signature,
373
+ targets: blockTargets
374
+ });
338
375
  }
339
376
  }
340
377
  }
341
- function collectEditableTargetsInTable(table, tablePath, context, targets) {
378
+ function collectEditableTargetsInTable(table, tablePath, context, targets, cache) {
342
379
  const tableDepth = context.tableDepth + 1;
380
+ const verticalMergeOwners = [];
343
381
  targets.push(createTableStructureTarget({
344
382
  scope: "table",
345
383
  kind: "table-structure-table",
@@ -378,6 +416,10 @@ function collectEditableTargetsInTable(table, tablePath, context, targets) {
378
416
  const cell = row.cells[cellIndex];
379
417
  if (!cell) continue;
380
418
  const gridSpan = cell.gridSpan ?? 1;
419
+ const continuationOwner = cell.verticalMerge === "continue" ? findVerticalMergeOwner(verticalMergeOwners, gridColumnStart, gridSpan) : null;
420
+ if (cell.verticalMerge !== "continue") {
421
+ clearVerticalMergeOwners(verticalMergeOwners, gridColumnStart, gridSpan);
422
+ }
381
423
  targets.push(createTableStructureTarget({
382
424
  scope: "cell",
383
425
  kind: "table-structure-cell",
@@ -420,15 +462,136 @@ function collectEditableTargetsInTable(table, tablePath, context, targets) {
420
462
  row,
421
463
  cellIndex,
422
464
  cell,
423
- gridColumnStart
465
+ gridColumnStart,
466
+ ...continuationOwner ? {
467
+ editableOwnersByChildIndex: continuationOwnerTargetsByChildIndex(
468
+ continuationOwner,
469
+ cell.children.length
470
+ )
471
+ } : {}
424
472
  }
425
473
  },
426
- targets
474
+ targets,
475
+ cache
427
476
  );
477
+ if (cell.verticalMerge === "restart") {
478
+ verticalMergeOwners.push(createVerticalMergeOwnerState({
479
+ context,
480
+ table,
481
+ tablePath,
482
+ tableDepth,
483
+ rowIndex,
484
+ row,
485
+ cellIndex,
486
+ cell,
487
+ gridColumnStart,
488
+ gridSpan
489
+ }));
490
+ }
428
491
  gridColumnStart += gridSpan;
429
492
  }
430
493
  }
431
494
  }
495
+ function findVerticalMergeOwner(owners, gridColumnStart, gridSpan) {
496
+ return owners.find(
497
+ (owner) => owner.gridColumnStart === gridColumnStart && owner.gridSpan === gridSpan
498
+ ) ?? null;
499
+ }
500
+ function clearVerticalMergeOwners(owners, gridColumnStart, gridSpan) {
501
+ const gridColumnEnd = gridColumnStart + gridSpan;
502
+ for (let index = owners.length - 1; index >= 0; index -= 1) {
503
+ const owner = owners[index];
504
+ if (!owner) continue;
505
+ const ownerEnd = owner.gridColumnStart + owner.gridSpan;
506
+ if (gridColumnStart < ownerEnd && owner.gridColumnStart < gridColumnEnd) {
507
+ owners.splice(index, 1);
508
+ }
509
+ }
510
+ }
511
+ function continuationOwnerTargetsByChildIndex(owner, childCount) {
512
+ if (!owner.fallbackOwnerTarget) return void 0;
513
+ const targets = /* @__PURE__ */ new Map();
514
+ for (let childIndex = 0; childIndex < childCount; childIndex += 1) {
515
+ targets.set(
516
+ childIndex,
517
+ owner.ownerTargetsByChildIndex.get(childIndex) ?? owner.fallbackOwnerTarget
518
+ );
519
+ }
520
+ return targets;
521
+ }
522
+ function createVerticalMergeOwnerState(input) {
523
+ const ownerTargetsByChildIndex = /* @__PURE__ */ new Map();
524
+ for (let childIndex = 0; childIndex < input.cell.children.length; childIndex += 1) {
525
+ const owner = createVerticalMergeEditableOwner({ ...input, childIndex });
526
+ if (owner) ownerTargetsByChildIndex.set(childIndex, owner);
527
+ }
528
+ return {
529
+ gridColumnStart: input.gridColumnStart,
530
+ gridSpan: input.gridSpan,
531
+ ownerTargetsByChildIndex,
532
+ ...ownerTargetsByChildIndex.size > 0 ? { fallbackOwnerTarget: ownerTargetsByChildIndex.values().next().value } : {}
533
+ };
534
+ }
535
+ function createVerticalMergeEditableOwner(input) {
536
+ const child = input.cell.children[input.childIndex];
537
+ if (child?.type !== "paragraph") return null;
538
+ const ownerTableTarget = {
539
+ table: input.table,
540
+ tablePath: input.tablePath,
541
+ tableDepth: input.tableDepth,
542
+ rowIndex: input.rowIndex,
543
+ row: input.row,
544
+ cellIndex: input.cellIndex,
545
+ cell: input.cell,
546
+ gridColumnStart: input.gridColumnStart
547
+ };
548
+ const kind = editableParagraphTargetKind({
549
+ ...input.context,
550
+ basePath: `${input.tablePath}/row[${input.rowIndex}]/cell[${input.cellIndex}]`,
551
+ tableDepth: input.tableDepth,
552
+ tableTarget: ownerTableTarget
553
+ });
554
+ if (!kind) return null;
555
+ const blockPath = `${input.tablePath}/row[${input.rowIndex}]/cell[${input.cellIndex}]/block[${input.childIndex}]`;
556
+ const paragraphTextHash = hashText(collectParagraphText(child));
557
+ const table = createTableIdentity({
558
+ scope: "text",
559
+ context: {
560
+ storyKey: input.context.storyKey,
561
+ insideSdt: input.context.contentControl !== void 0
562
+ },
563
+ ...ownerTableTarget
564
+ });
565
+ return {
566
+ targetKey: `${input.context.storyKey}:${blockPath}:text`,
567
+ kind,
568
+ storyKey: input.context.storyKey,
569
+ blockPath,
570
+ leafPath: `${blockPath}/inline`,
571
+ commandFamily: "text-leaf",
572
+ reason: "vertical-merge-restart-cell",
573
+ canonicalAddress: ownerRoutingFromAddress(
574
+ createTableTargetCanonicalAddress(
575
+ table,
576
+ "paragraph",
577
+ paragraphTextHash,
578
+ { rangeBoundary: { boundaryKind: "cell-fragment" } }
579
+ )
580
+ ),
581
+ table: {
582
+ tableKey: table.tableKey,
583
+ tablePath: table.tablePath,
584
+ ...table.sourceRef !== void 0 ? { sourceRef: table.sourceRef } : {},
585
+ ...table.rowSourceRef !== void 0 ? { rowSourceRef: table.rowSourceRef } : {},
586
+ ...table.cellSourceRef !== void 0 ? { cellSourceRef: table.cellSourceRef } : {},
587
+ ...table.rowIndex !== void 0 ? { rowIndex: table.rowIndex } : {},
588
+ ...table.cellIndex !== void 0 ? { cellIndex: table.cellIndex } : {},
589
+ ...table.gridColumnStart !== void 0 ? { gridColumnStart: table.gridColumnStart } : {},
590
+ ...table.gridSpan !== void 0 ? { gridSpan: table.gridSpan } : {},
591
+ ...table.verticalMerge !== void 0 ? { verticalMerge: table.verticalMerge } : {}
592
+ }
593
+ };
594
+ }
432
595
  function computeTableStructureColumnCount(table) {
433
596
  let columnCount = table.gridColumns.length;
434
597
  for (const row of table.rows) {
@@ -448,6 +611,7 @@ function createTableStructureTarget(input) {
448
611
  const columnPath = input.columnIndex !== void 0 ? `${input.tablePath}/column[${input.columnIndex}]` : void 0;
449
612
  const blockPath = cellPath ?? rowPath ?? columnPath ?? input.tablePath;
450
613
  const tableIdentity = createTableIdentity(input);
614
+ const targetHash = hashTableStructureTarget(input);
451
615
  return {
452
616
  targetKey: `${tableKey}:structure:${tableIdentity.operationScope}${tableTargetSuffix(tableIdentity)}`,
453
617
  kind: input.kind,
@@ -459,8 +623,14 @@ function createTableStructureTarget(input) {
459
623
  ...input.table.sourceRef !== void 0 ? { sourceRef: input.table.sourceRef } : {},
460
624
  ...input.context.contentControl !== void 0 ? { contentControl: input.context.contentControl } : {},
461
625
  table: tableIdentity,
626
+ canonicalAddress: createTableTargetCanonicalAddress(
627
+ tableIdentity,
628
+ tableStructureBlockType(input.scope),
629
+ targetHash,
630
+ { rangeBoundary: { boundaryKind: "table-grid" } }
631
+ ),
462
632
  staleCheck: {
463
- targetHash: hashTableStructureTarget(input),
633
+ targetHash,
464
634
  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),
465
635
  blockType: tableStructureBlockType(input.scope),
466
636
  ...input.table.sourceRef !== void 0 ? { sourceRef: input.table.sourceRef } : {}
@@ -471,10 +641,15 @@ function createTableStructureTarget(input) {
471
641
  function createTableIdentity(input) {
472
642
  const tableKey = `${input.context.storyKey}:${input.tablePath}`;
473
643
  const columnCount = computeTableStructureColumnCount(input.table);
644
+ const rowRange = tableFragmentRowRange(input).rowRange;
645
+ const columnRange = tableFragmentColumnRange(input, columnCount).columnRange;
474
646
  const base = {
475
647
  operationScope: input.scope,
476
648
  tableKey,
477
649
  tablePath: input.tablePath,
650
+ ...input.table.sourceRef !== void 0 ? { sourceRef: input.table.sourceRef } : {},
651
+ ...input.row?.sourceRef !== void 0 ? { rowSourceRef: input.row.sourceRef } : {},
652
+ ...input.cell?.sourceRef !== void 0 ? { cellSourceRef: input.cell.sourceRef } : {},
478
653
  ...tablePathIndexes(input.tablePath),
479
654
  tableDepth: input.tableDepth,
480
655
  ...input.tableDepth >= 2 ? { nestedTable: true } : {},
@@ -482,7 +657,10 @@ function createTableIdentity(input) {
482
657
  ...input.context.storyKey !== MAIN_STORY_KEY ? { secondaryStory: true } : {},
483
658
  rowCount: input.table.rows.length,
484
659
  columnCount,
485
- fragment: createTableFragmentIdentity(input, tableKey, columnCount)
660
+ fragment: createTableFragmentIdentity(input, tableKey, columnCount),
661
+ ...input.cell !== void 0 ? {
662
+ cellFragment: createTableCellFragmentIdentity(input, tableKey, rowRange, columnRange)
663
+ } : {}
486
664
  };
487
665
  return {
488
666
  ...base,
@@ -496,6 +674,25 @@ function createTableIdentity(input) {
496
674
  ...input.cell !== void 0 ? { blockCount: input.cell.children.length } : {}
497
675
  };
498
676
  }
677
+ function createTableCellFragmentIdentity(input, tableKey, rowRange, columnRange) {
678
+ const text = (input.cell?.children ?? []).map(blockTextForTargetHash).join("");
679
+ return {
680
+ fragmentKey: hashText(JSON.stringify({
681
+ tableKey,
682
+ rowIndex: input.rowIndex ?? null,
683
+ cellIndex: input.cellIndex ?? null,
684
+ gridColumnStart: input.gridColumnStart ?? null,
685
+ gridSpan: input.cell?.gridSpan ?? 1,
686
+ verticalMerge: input.cell?.verticalMerge ?? null,
687
+ sourceId: input.cell?.sourceRef?.sourceId ?? null
688
+ })),
689
+ textHash: hashText(text),
690
+ blockCount: input.cell?.children.length ?? 0,
691
+ ...rowRange !== void 0 ? { rowRange } : {},
692
+ ...columnRange !== void 0 ? { columnRange } : {},
693
+ ...sourceJoinHashForRefs(input.table.sourceRef, input.row?.sourceRef, input.cell?.sourceRef)
694
+ };
695
+ }
499
696
  function tablePathIndexes(tablePath) {
500
697
  const blockIndexes = [...tablePath.matchAll(/\/block\[(\d+)\]/gu)].map((match) => Number(match[1]));
501
698
  const storyBlockIndex = blockIndexes[0];
@@ -661,13 +858,39 @@ function collectEditableTargetsInInlines(inlines, basePath, context, targets) {
661
858
  }
662
859
  }
663
860
  }
664
- function createParagraphEditableTarget(paragraph, kind, storyKey, blockPath, targetPosture = { editability: "editable", posture: { blockers: [] } }, contentControl, tableTarget) {
861
+ function createParagraphEditableTarget(paragraph, kind, storyKey, blockPath, targetPosture = { editability: "editable", posture: { blockers: [] } }, contentControl, tableTarget, editableOwner) {
665
862
  const paragraphText = collectParagraphText(paragraph);
863
+ const paragraphTextHash = hashText(paragraphText);
666
864
  const sourceRef = paragraph.sourceRef;
667
865
  const lockedContentControl = contentControlLocksContent(contentControl);
668
- const posture = lockedContentControl ? mergeTargetPosture(targetPosture.posture, ["locked-content-control"], {
866
+ const syntheticLayoutCell = tableTarget?.cell?.verticalMerge === "continue";
867
+ const tableIdentity = tableTarget !== void 0 ? createTableIdentity({
868
+ scope: "text",
869
+ context: { storyKey, insideSdt: contentControl !== void 0 },
870
+ ...tableTarget
871
+ }) : void 0;
872
+ const listAddress = tableIdentity === void 0 && paragraph.numbering !== void 0 ? createCanonicalAddress({
873
+ addressKind: "list-item-text",
874
+ storyKey,
875
+ staleCheckKind: "paragraph",
876
+ operationScope: "list-text",
877
+ sourceRefs: [sourceRef],
878
+ staleHash: paragraphTextHash,
879
+ rangeBoundary: { boundaryKind: "list-item-text" },
880
+ discriminator: {
881
+ blockPath,
882
+ numberingInstanceId: paragraph.numbering.numberingInstanceId,
883
+ level: paragraph.numbering.level,
884
+ sourceId: sourceRef?.sourceId ?? null,
885
+ paraId: paragraph.wordExtensionIds?.paraId ?? null,
886
+ textId: paragraph.wordExtensionIds?.textId ?? null
887
+ }
888
+ }) : void 0;
889
+ const tableAwarePosture = syntheticLayoutCell ? mergeTargetPosture(targetPosture.posture, ["synthetic-layout-cell"]) : targetPosture.posture;
890
+ const posture = lockedContentControl ? mergeTargetPosture(tableAwarePosture, ["locked-content-control"], {
669
891
  lockedContentControl: true
670
- }) : targetPosture.posture;
892
+ }) : tableAwarePosture;
893
+ const editability = lockedContentControl || syntheticLayoutCell ? "non-editable" : targetPosture.editability;
671
894
  return {
672
895
  targetKey: `${storyKey}:${blockPath}:text`,
673
896
  kind,
@@ -675,12 +898,24 @@ function createParagraphEditableTarget(paragraph, kind, storyKey, blockPath, tar
675
898
  blockPath,
676
899
  leafPath: `${blockPath}/inline`,
677
900
  commandFamily: "text-leaf",
678
- editability: lockedContentControl ? "non-editable" : targetPosture.editability,
901
+ editability,
679
902
  ...sourceRef !== void 0 ? { sourceRef } : {},
680
903
  ...contentControl !== void 0 ? { contentControl } : {},
681
- ...tableTarget !== void 0 ? { table: createTableIdentity({ scope: "text", context: { storyKey, insideSdt: contentControl !== void 0 }, ...tableTarget }) } : {},
904
+ ...tableIdentity !== void 0 ? { table: tableIdentity } : {},
905
+ ...editableOwner !== void 0 ? { editableOwner } : {},
906
+ ...tableIdentity !== void 0 ? {
907
+ canonicalAddress: createTableTargetCanonicalAddress(
908
+ tableIdentity,
909
+ "paragraph",
910
+ paragraphTextHash,
911
+ {
912
+ rangeBoundary: { boundaryKind: "cell-fragment" },
913
+ owner: editableOwner?.canonicalAddress
914
+ }
915
+ )
916
+ } : listAddress !== void 0 ? { canonicalAddress: listAddress } : {},
682
917
  staleCheck: {
683
- paragraphTextHash: hashText(paragraphText),
918
+ paragraphTextHash,
684
919
  paragraphTextLength: Array.from(paragraphText).length,
685
920
  inlineCount: paragraph.children?.length ?? 0,
686
921
  blockType: "paragraph",
@@ -711,12 +946,27 @@ function collectInlineTarget(inline, storyKey, inlinePath, targets) {
711
946
  return;
712
947
  case "hyperlink":
713
948
  targets.push(createHyperlinkEditableTarget(inline, storyKey, inlinePath));
949
+ targets.push(createHyperlinkDestinationEditableTarget(inline, storyKey, inlinePath));
714
950
  return;
715
951
  case "bookmark_start":
716
- targets.push(createBookmarkEditableTarget(inline.bookmarkId, inline.name, storyKey, inlinePath, "start"));
952
+ targets.push(createBookmarkEditableTarget(
953
+ inline.bookmarkId,
954
+ inline.name,
955
+ storyKey,
956
+ inlinePath,
957
+ "start",
958
+ inline.sourceRef
959
+ ));
717
960
  return;
718
961
  case "bookmark_end":
719
- targets.push(createBookmarkEditableTarget(inline.bookmarkId, void 0, storyKey, inlinePath, "end"));
962
+ targets.push(createBookmarkEditableTarget(
963
+ inline.bookmarkId,
964
+ void 0,
965
+ storyKey,
966
+ inlinePath,
967
+ "end",
968
+ inline.sourceRef
969
+ ));
720
970
  return;
721
971
  case "image":
722
972
  targets.push(createImageEditableTarget(inline, storyKey, inlinePath));
@@ -740,6 +990,7 @@ function collectInlineTarget(inline, storyKey, inlinePath, targets) {
740
990
  function createFieldEditableTarget(field, storyKey, inlinePath) {
741
991
  const resultText = field.children.map(inlineTextForTargetHash).join("");
742
992
  const sourceRef = field.sourceRef;
993
+ const targetHash = hashText(`${field.instruction}\0${resultText}`);
743
994
  const preserveOnly = field.refreshStatus === "preserve-only" || field.fieldFamily === "UNKNOWN";
744
995
  const blockers = preserveOnly ? ["field-generated-text", "preserve-only"] : ["field-generated-text", "unmodeled-target"];
745
996
  return {
@@ -759,9 +1010,28 @@ function createFieldEditableTarget(field, storyKey, inlinePath) {
759
1010
  ...field.locked !== void 0 ? { locked: field.locked } : {},
760
1011
  ...field.dirty !== void 0 ? { dirty: field.dirty } : {}
761
1012
  },
1013
+ canonicalAddress: createCanonicalAddress({
1014
+ addressKind: "field-result",
1015
+ storyKey,
1016
+ staleCheckKind: "field",
1017
+ operationScope: "field-refresh",
1018
+ sourceRefs: [sourceRef],
1019
+ staleHash: targetHash,
1020
+ rangeBoundary: {
1021
+ boundaryKind: "field-result",
1022
+ from: 0,
1023
+ to: Array.from(resultText).length
1024
+ },
1025
+ discriminator: {
1026
+ canonicalFieldId: field.canonicalFieldId ?? null,
1027
+ fieldFamily: field.fieldFamily ?? null,
1028
+ fieldTarget: field.fieldTarget ?? null,
1029
+ sourceId: sourceRef?.sourceId ?? null
1030
+ }
1031
+ }),
762
1032
  staleCheck: {
763
1033
  blockType: "field",
764
- targetHash: hashText(`${field.instruction}\0${resultText}`),
1034
+ targetHash,
765
1035
  targetTextLength: Array.from(resultText).length,
766
1036
  childCount: field.children.length,
767
1037
  ...sourceRef !== void 0 ? { sourceRef } : {}
@@ -775,6 +1045,7 @@ function createFieldEditableTarget(field, storyKey, inlinePath) {
775
1045
  function createHyperlinkEditableTarget(hyperlink, storyKey, inlinePath) {
776
1046
  const text = hyperlink.children.map(inlineTextForTargetHash).join("");
777
1047
  const sourceRef = hyperlink.sourceRef ?? hyperlink.fieldCarrier?.sourceRef;
1048
+ const targetHash = hashText(`${hyperlink.href}\0${text}`);
778
1049
  return {
779
1050
  targetKey: `${storyKey}:${inlinePath}:hyperlink`,
780
1051
  kind: "hyperlink-text",
@@ -785,9 +1056,25 @@ function createHyperlinkEditableTarget(hyperlink, storyKey, inlinePath) {
785
1056
  editability: "editable",
786
1057
  ...sourceRef !== void 0 ? { sourceRef } : {},
787
1058
  link: { href: hyperlink.href },
1059
+ canonicalAddress: createCanonicalAddress({
1060
+ addressKind: "hyperlink-display-text",
1061
+ storyKey,
1062
+ staleCheckKind: "hyperlink",
1063
+ sourceRefs: [sourceRef],
1064
+ staleHash: targetHash,
1065
+ rangeBoundary: {
1066
+ boundaryKind: "hyperlink-display",
1067
+ from: 0,
1068
+ to: Array.from(text).length
1069
+ },
1070
+ discriminator: {
1071
+ href: hyperlink.href,
1072
+ sourceId: sourceRef?.sourceId ?? null
1073
+ }
1074
+ }),
788
1075
  staleCheck: {
789
1076
  blockType: "hyperlink",
790
- targetHash: hashText(`${hyperlink.href}\0${text}`),
1077
+ targetHash,
791
1078
  targetTextLength: Array.from(text).length,
792
1079
  childCount: hyperlink.children.length,
793
1080
  ...sourceRef !== void 0 ? { sourceRef } : {}
@@ -795,7 +1082,52 @@ function createHyperlinkEditableTarget(hyperlink, storyKey, inlinePath) {
795
1082
  posture: { blockers: [] }
796
1083
  };
797
1084
  }
798
- function createBookmarkEditableTarget(bookmarkId, bookmarkName, storyKey, inlinePath, edge) {
1085
+ function createHyperlinkDestinationEditableTarget(hyperlink, storyKey, inlinePath) {
1086
+ const sourceRef = hyperlink.sourceRef ?? hyperlink.fieldCarrier?.sourceRef;
1087
+ const destinationKind = hyperlink.href.startsWith("#") ? "internal-anchor" : "external";
1088
+ const targetHash = hashText(`destination\0${hyperlink.href}`);
1089
+ return {
1090
+ targetKey: `${storyKey}:${inlinePath}:hyperlink-destination`,
1091
+ kind: "hyperlink-destination",
1092
+ storyKey,
1093
+ blockPath: inlinePath,
1094
+ leafPath: `${inlinePath}/destination`,
1095
+ commandFamily: "link-bookmark",
1096
+ editability: "non-editable",
1097
+ ...sourceRef !== void 0 ? { sourceRef } : {},
1098
+ link: {
1099
+ href: hyperlink.href,
1100
+ destinationKind
1101
+ },
1102
+ canonicalAddress: createCanonicalAddress({
1103
+ addressKind: "hyperlink-destination",
1104
+ storyKey,
1105
+ staleCheckKind: "hyperlink",
1106
+ operationScope: "link-destination",
1107
+ sourceRefs: [sourceRef],
1108
+ staleHash: targetHash,
1109
+ rangeBoundary: {
1110
+ boundaryKind: "hyperlink-destination",
1111
+ ...sourceRef !== void 0 ? { startSourceJoinHash: sourceJoinHash([sourceRef]) } : {},
1112
+ ...sourceRef !== void 0 ? { endSourceJoinHash: sourceJoinHash([sourceRef]) } : {}
1113
+ },
1114
+ discriminator: {
1115
+ href: hyperlink.href,
1116
+ destinationKind,
1117
+ sourceId: sourceRef?.sourceId ?? null
1118
+ }
1119
+ }),
1120
+ staleCheck: {
1121
+ blockType: "hyperlink",
1122
+ targetHash,
1123
+ childCount: hyperlink.children.length,
1124
+ ...sourceRef !== void 0 ? { sourceRef } : {}
1125
+ },
1126
+ posture: { blockers: ["unmodeled-target"] }
1127
+ };
1128
+ }
1129
+ function createBookmarkEditableTarget(bookmarkId, bookmarkName, storyKey, inlinePath, edge, sourceRef) {
1130
+ const targetHash = hashText(`${edge}\0${bookmarkId}\0${bookmarkName ?? ""}`);
799
1131
  return {
800
1132
  targetKey: `${storyKey}:${inlinePath}:bookmark:${edge}:${bookmarkId}`,
801
1133
  kind: "bookmark-anchor",
@@ -804,14 +1136,34 @@ function createBookmarkEditableTarget(bookmarkId, bookmarkName, storyKey, inline
804
1136
  leafPath: inlinePath,
805
1137
  commandFamily: "link-bookmark",
806
1138
  editability: "non-editable",
1139
+ ...sourceRef !== void 0 ? { sourceRef } : {},
807
1140
  link: {
808
1141
  bookmarkId,
809
1142
  ...bookmarkName !== void 0 ? { bookmarkName } : {}
810
1143
  },
1144
+ canonicalAddress: createCanonicalAddress({
1145
+ addressKind: "bookmark-anchor",
1146
+ storyKey,
1147
+ staleCheckKind: "bookmark",
1148
+ sourceRefs: [sourceRef],
1149
+ staleHash: targetHash,
1150
+ rangeBoundary: {
1151
+ boundaryKind: "bookmark-anchor",
1152
+ ...sourceRef !== void 0 ? { startSourceJoinHash: sourceJoinHash([sourceRef]) } : {},
1153
+ ...sourceRef !== void 0 ? { endSourceJoinHash: sourceJoinHash([sourceRef]) } : {}
1154
+ },
1155
+ discriminator: {
1156
+ bookmarkId,
1157
+ bookmarkName: bookmarkName ?? null,
1158
+ edge,
1159
+ sourceId: sourceRef?.sourceId ?? null
1160
+ }
1161
+ }),
811
1162
  staleCheck: {
812
1163
  blockType: "bookmark",
813
- targetHash: hashText(`${edge}\0${bookmarkId}\0${bookmarkName ?? ""}`),
814
- childCount: 0
1164
+ targetHash,
1165
+ childCount: 0,
1166
+ ...sourceRef !== void 0 ? { sourceRef } : {}
815
1167
  },
816
1168
  posture: { blockers: ["unmodeled-target"] }
817
1169
  };
@@ -859,6 +1211,7 @@ function createObjectEditableTarget(inline, storyKey, inlinePath) {
859
1211
  storyKey,
860
1212
  inlinePath,
861
1213
  objectKind: "ole",
1214
+ sourceRef: inline.sourceRef,
862
1215
  targetHash: `${inline.id}\0${inline.relationshipId}`,
863
1216
  object: {
864
1217
  objectKind: "ole",
@@ -980,6 +1333,167 @@ function createOpaqueEditableTarget(input) {
980
1333
  }
981
1334
  };
982
1335
  }
1336
+ function collectFieldRegionRefreshTargets(doc, targets) {
1337
+ for (const region of collectCanonicalFieldRegionIdentities(doc)) {
1338
+ targets.push(createFieldRegionRefreshEditableTarget(region));
1339
+ }
1340
+ }
1341
+ function createFieldRegionRefreshEditableTarget(region) {
1342
+ const isToc = region.kind === "toc-region" || region.fieldFamily === "TOC";
1343
+ const sourceRef = region.sourceRef;
1344
+ const targetHash = hashText(JSON.stringify({
1345
+ regionId: region.regionId,
1346
+ canonicalFieldId: region.canonicalFieldId,
1347
+ fieldFamily: region.fieldFamily,
1348
+ refreshStatus: region.refreshStatus,
1349
+ tocId: region.tocId ?? null,
1350
+ resultRange: region.resultRange ?? null,
1351
+ status: region.status ?? null
1352
+ }));
1353
+ return {
1354
+ targetKey: `${region.storyKey}:field-region:${region.regionId}:refresh`,
1355
+ kind: isToc ? "toc-region-refresh" : "field-region-refresh",
1356
+ storyKey: region.storyKey,
1357
+ blockPath: `${region.storyKey}/field-region[${region.regionId}]`,
1358
+ leafPath: `${region.storyKey}/field-region[${region.regionId}]/refresh`,
1359
+ commandFamily: "field",
1360
+ editability: "non-editable",
1361
+ ...sourceRef !== void 0 ? { sourceRef } : {},
1362
+ field: {
1363
+ canonicalFieldId: region.canonicalFieldId,
1364
+ regionId: region.regionId,
1365
+ fieldFamily: region.fieldFamily,
1366
+ refreshStatus: region.refreshStatus,
1367
+ ...region.sourcePath !== void 0 ? { sourcePath: region.sourcePath } : {},
1368
+ ...region.tocId !== void 0 ? { tocId: region.tocId } : {},
1369
+ ...region.resultRange !== void 0 ? {
1370
+ resultRangeFromParagraphIndex: region.resultRange.fromParagraphIndex,
1371
+ resultRangeToParagraphIndex: region.resultRange.toParagraphIndex
1372
+ } : {},
1373
+ ...region.status !== void 0 ? { status: region.status } : {},
1374
+ ...region.cachedEntryCount !== void 0 ? { cachedEntryCount: region.cachedEntryCount } : {},
1375
+ ...region.generatedEntryCount !== void 0 ? { generatedEntryCount: region.generatedEntryCount } : {}
1376
+ },
1377
+ canonicalAddress: createCanonicalAddress({
1378
+ addressKind: isToc ? "toc-region-refresh" : "field-region-refresh",
1379
+ storyKey: region.storyKey,
1380
+ staleCheckKind: "field",
1381
+ operationScope: isToc ? "toc-refresh" : "field-refresh",
1382
+ sourceRefs: [sourceRef],
1383
+ staleHash: targetHash,
1384
+ rangeBoundary: {
1385
+ boundaryKind: "field-region",
1386
+ ...region.resultRange !== void 0 ? {
1387
+ from: region.resultRange.fromParagraphIndex,
1388
+ to: region.resultRange.toParagraphIndex
1389
+ } : { from: region.paragraphIndex, to: region.paragraphIndex }
1390
+ },
1391
+ discriminator: {
1392
+ regionId: region.regionId,
1393
+ canonicalFieldId: region.canonicalFieldId,
1394
+ fieldIndex: region.fieldIndex,
1395
+ fieldFamily: region.fieldFamily,
1396
+ tocId: region.tocId ?? null
1397
+ }
1398
+ }),
1399
+ staleCheck: {
1400
+ blockType: "field",
1401
+ targetHash,
1402
+ childCount: region.cachedEntryCount ?? 0,
1403
+ ...sourceRef !== void 0 ? { sourceRef } : {}
1404
+ },
1405
+ posture: {
1406
+ blockers: ["field-generated-text", "unmodeled-target"]
1407
+ }
1408
+ };
1409
+ }
1410
+ function collectBookmarkContentRangeTargets(doc, targets) {
1411
+ const candidates = /* @__PURE__ */ new Map();
1412
+ for (const context of collectStoryBlockContexts(doc)) {
1413
+ walkBlocks(context.blocks, context.storyKey, context.basePath, {
1414
+ inline(inline, _blockPath, inlinePath) {
1415
+ if (inline.type !== "bookmark_start" && inline.type !== "bookmark_end") return;
1416
+ const key = `${context.storyKey}:${inline.bookmarkId}`;
1417
+ const previous = candidates.get(key);
1418
+ if (inline.type === "bookmark_start") {
1419
+ candidates.set(key, {
1420
+ ...previous ?? { storyKey: context.storyKey, bookmarkId: inline.bookmarkId },
1421
+ bookmarkName: inline.name,
1422
+ startPath: inlinePath,
1423
+ startSourceRef: inline.sourceRef
1424
+ });
1425
+ return;
1426
+ }
1427
+ candidates.set(key, {
1428
+ ...previous ?? { storyKey: context.storyKey, bookmarkId: inline.bookmarkId },
1429
+ endPath: inlinePath,
1430
+ endSourceRef: inline.sourceRef
1431
+ });
1432
+ }
1433
+ });
1434
+ }
1435
+ for (const candidate of candidates.values()) {
1436
+ if (candidate.startPath === void 0 || candidate.endPath === void 0) continue;
1437
+ targets.push(createBookmarkContentRangeEditableTarget({
1438
+ ...candidate,
1439
+ startPath: candidate.startPath,
1440
+ endPath: candidate.endPath
1441
+ }));
1442
+ }
1443
+ }
1444
+ function createBookmarkContentRangeEditableTarget(candidate) {
1445
+ const startSourceJoinHash = sourceJoinHash([candidate.startSourceRef]);
1446
+ const endSourceJoinHash = sourceJoinHash([candidate.endSourceRef]);
1447
+ const rangeKey = hashText(JSON.stringify({
1448
+ storyKey: candidate.storyKey,
1449
+ bookmarkId: candidate.bookmarkId,
1450
+ bookmarkName: candidate.bookmarkName ?? null,
1451
+ startSourceId: candidate.startSourceRef?.sourceId ?? null,
1452
+ endSourceId: candidate.endSourceRef?.sourceId ?? null
1453
+ }));
1454
+ const targetHash = hashText(`range\0${candidate.bookmarkId}\0${candidate.bookmarkName ?? ""}\0${candidate.startPath}\0${candidate.endPath}`);
1455
+ return {
1456
+ targetKey: `${candidate.storyKey}:bookmark:${candidate.bookmarkId}:content-range`,
1457
+ kind: "bookmark-content-range",
1458
+ storyKey: candidate.storyKey,
1459
+ blockPath: `${candidate.storyKey}/bookmark[${candidate.bookmarkId}]`,
1460
+ leafPath: `${candidate.storyKey}/bookmark[${candidate.bookmarkId}]/content-range`,
1461
+ commandFamily: "link-bookmark",
1462
+ editability: "non-editable",
1463
+ ...candidate.startSourceRef !== void 0 ? { sourceRef: candidate.startSourceRef } : {},
1464
+ link: {
1465
+ bookmarkId: candidate.bookmarkId,
1466
+ ...candidate.bookmarkName !== void 0 ? { bookmarkName: candidate.bookmarkName } : {},
1467
+ rangeKey
1468
+ },
1469
+ canonicalAddress: createCanonicalAddress({
1470
+ addressKind: "bookmark-content-range",
1471
+ storyKey: candidate.storyKey,
1472
+ staleCheckKind: "bookmark",
1473
+ operationScope: "bookmark-range",
1474
+ sourceRefs: [candidate.startSourceRef, candidate.endSourceRef],
1475
+ staleHash: targetHash,
1476
+ rangeBoundary: {
1477
+ boundaryKind: "bookmark-content",
1478
+ ...startSourceJoinHash !== void 0 ? { startSourceJoinHash } : {},
1479
+ ...endSourceJoinHash !== void 0 ? { endSourceJoinHash } : {}
1480
+ },
1481
+ discriminator: {
1482
+ bookmarkId: candidate.bookmarkId,
1483
+ bookmarkName: candidate.bookmarkName ?? null,
1484
+ startSourceId: candidate.startSourceRef?.sourceId ?? null,
1485
+ endSourceId: candidate.endSourceRef?.sourceId ?? null
1486
+ }
1487
+ }),
1488
+ staleCheck: {
1489
+ blockType: "bookmark",
1490
+ targetHash,
1491
+ childCount: 2,
1492
+ ...candidate.startSourceRef !== void 0 ? { sourceRef: candidate.startSourceRef } : {}
1493
+ },
1494
+ posture: { blockers: ["unmodeled-target"] }
1495
+ };
1496
+ }
983
1497
  function inlineObjectKind(inline) {
984
1498
  switch (inline.type) {
985
1499
  case "chart_preview":
@@ -1102,6 +1616,16 @@ function collectParagraphText(paragraph) {
1102
1616
  }
1103
1617
  return text;
1104
1618
  }
1619
+ function blockTextForTargetHash(block) {
1620
+ if (block.type === "paragraph") return collectParagraphText(block);
1621
+ if (block.type === "sdt" || block.type === "custom_xml") {
1622
+ return block.children.map(blockTextForTargetHash).join("");
1623
+ }
1624
+ if (block.type === "table") {
1625
+ return block.rows.flatMap((row) => row.cells).flatMap((cell) => cell.children).map(blockTextForTargetHash).join("");
1626
+ }
1627
+ return "";
1628
+ }
1105
1629
  function inlineTextForTargetHash(inline) {
1106
1630
  if (inline.type === "text") return inline.text;
1107
1631
  if (inline.type === "symbol") return inline.char;
@@ -1117,6 +1641,93 @@ function inlineTextForTargetHash(inline) {
1117
1641
  }
1118
1642
  return "";
1119
1643
  }
1644
+ function createTableTargetCanonicalAddress(table, staleCheckKind, staleHash, resolver = {}) {
1645
+ return createCanonicalAddress({
1646
+ addressKind: "table-target",
1647
+ storyKey: tableStoryKey(table),
1648
+ staleCheckKind,
1649
+ operationScope: table.operationScope,
1650
+ rowRange: table.fragment?.rowRange,
1651
+ columnRange: table.fragment?.columnRange,
1652
+ sourceRefs: [table.sourceRef, table.rowSourceRef, table.cellSourceRef],
1653
+ staleHash,
1654
+ ...resolver,
1655
+ discriminator: {
1656
+ operationScope: table.operationScope,
1657
+ tableDepth: table.tableDepth,
1658
+ rowIndex: table.rowIndex ?? null,
1659
+ columnIndex: table.columnIndex ?? null,
1660
+ cellIndex: table.cellIndex ?? null,
1661
+ gridColumnStart: table.gridColumnStart ?? null,
1662
+ gridSpan: table.gridSpan ?? null,
1663
+ verticalMerge: table.verticalMerge ?? null,
1664
+ sourceId: table.sourceRef?.sourceId ?? null,
1665
+ rowSourceId: table.rowSourceRef?.sourceId ?? null,
1666
+ cellSourceId: table.cellSourceRef?.sourceId ?? null
1667
+ },
1668
+ secondaryStory: table.secondaryStory,
1669
+ nestedTable: table.nestedTable,
1670
+ insideSdt: table.insideSdt
1671
+ });
1672
+ }
1673
+ function tableStoryKey(table) {
1674
+ const suffix = `:${table.tablePath}`;
1675
+ return table.tableKey.endsWith(suffix) ? table.tableKey.slice(0, -suffix.length) : MAIN_STORY_KEY;
1676
+ }
1677
+ function createCanonicalAddress(input) {
1678
+ const sourceHash = sourceJoinHash(input.sourceRefs ?? []);
1679
+ const payload = {
1680
+ addressKind: input.addressKind,
1681
+ storyKey: input.storyKey,
1682
+ operationScope: input.operationScope ?? null,
1683
+ rowRange: input.rowRange ?? null,
1684
+ columnRange: input.columnRange ?? null,
1685
+ sourceHash: sourceHash ?? null,
1686
+ discriminator: input.discriminator
1687
+ };
1688
+ return {
1689
+ addressKey: `editable-address:${hashText(JSON.stringify(payload))}`,
1690
+ addressKind: input.addressKind,
1691
+ storyKey: input.storyKey,
1692
+ staleCheckKind: input.staleCheckKind,
1693
+ ...input.operationScope !== void 0 ? { operationScope: input.operationScope } : {},
1694
+ ...input.rowRange !== void 0 ? { rowRange: input.rowRange } : {},
1695
+ ...input.columnRange !== void 0 ? { columnRange: input.columnRange } : {},
1696
+ ...sourceHash !== void 0 ? { sourceJoinHash: sourceHash } : {},
1697
+ ...input.secondaryStory === true ? { secondaryStory: true } : {},
1698
+ ...input.nestedTable === true ? { nestedTable: true } : {},
1699
+ ...input.insideSdt === true ? { insideSdt: true } : {},
1700
+ resolver: {
1701
+ staleHash: input.staleHash,
1702
+ ...sourceHash !== void 0 ? { sourceJoinHash: sourceHash } : {},
1703
+ ...input.rowRange !== void 0 ? { rowRange: input.rowRange } : {},
1704
+ ...input.columnRange !== void 0 ? { columnRange: input.columnRange } : {},
1705
+ ...input.rangeBoundary !== void 0 ? { rangeBoundary: input.rangeBoundary } : {},
1706
+ ...input.owner !== void 0 ? { owner: input.owner } : {}
1707
+ }
1708
+ };
1709
+ }
1710
+ function ownerRoutingFromAddress(address) {
1711
+ return {
1712
+ addressKey: address.addressKey,
1713
+ addressKind: address.addressKind,
1714
+ storyKey: address.storyKey,
1715
+ ...address.operationScope !== void 0 ? { operationScope: address.operationScope } : {},
1716
+ ...address.sourceJoinHash !== void 0 ? { sourceJoinHash: address.sourceJoinHash } : {},
1717
+ staleHash: address.resolver?.staleHash ?? "",
1718
+ ...address.rowRange !== void 0 ? { rowRange: address.rowRange } : {},
1719
+ ...address.columnRange !== void 0 ? { columnRange: address.columnRange } : {}
1720
+ };
1721
+ }
1722
+ function sourceJoinHashForRefs(...refs) {
1723
+ const sourceHash = sourceJoinHash(refs);
1724
+ return sourceHash === void 0 ? {} : { sourceJoinHash: sourceHash };
1725
+ }
1726
+ function sourceJoinHash(refs) {
1727
+ const sourceIds = refs.map((ref) => ref?.sourceId).filter((sourceId) => sourceId !== void 0);
1728
+ if (sourceIds.length === 0) return void 0;
1729
+ return hashText(sourceIds.join("\0"));
1730
+ }
1120
1731
  function collectCanonicalFieldRegionIdentities(doc) {
1121
1732
  const registry = doc.fieldRegistry;
1122
1733
  const byFieldIndex = new Map(
@@ -1314,7 +1925,7 @@ function walkBlocks(blocks, storyKey, basePath, visitor) {
1314
1925
  }
1315
1926
  if (block.type === "paragraph") {
1316
1927
  visitor.paragraph?.(block, blockPath);
1317
- walkInlines(block.children, storyKey, blockPath, `${blockPath}/inline`, visitor);
1928
+ walkInlines(block.children ?? [], storyKey, blockPath, `${blockPath}/inline`, visitor);
1318
1929
  continue;
1319
1930
  }
1320
1931
  if (block.type === "sdt" || block.type === "custom_xml") {
@@ -4275,7 +4886,7 @@ function createEditorSurfaceSnapshot(document, _selection, activeStory = { kind:
4275
4886
  ...options.getEffectiveMarkupMode ? { getEffectiveMarkupMode: options.getEffectiveMarkupMode } : {},
4276
4887
  ...options.authorColorPalette ? { authorColorPalette: options.authorColorPalette } : {}
4277
4888
  });
4278
- const editableTargetsByBlockPath = indexEditableTargetsByBlockPath(document);
4889
+ const editableTargetsByBlockPath = options.editableTargetsByBlockPath ?? indexEditableTargetsByBlockPath(document);
4279
4890
  const activeStoryBlockPathBase = getActiveStoryBlockPathBase(document, activeStory);
4280
4891
  chartModelStore.beginBuildPass(document);
4281
4892
  const unsupportedNumberingFormatsSeen = options.emitFormattingTelemetry ? /* @__PURE__ */ new Set() : null;
@@ -4556,6 +5167,7 @@ function createTableBlock(tableIndex, table, document, cursor, counters, formatt
4556
5167
  from: cursor,
4557
5168
  to: innerCursor,
4558
5169
  styleId: table.styleId,
5170
+ ...table.sourceRef !== void 0 ? { sourceRef: table.sourceRef } : {},
4559
5171
  gridColumns: table.gridColumns,
4560
5172
  rows: []
4561
5173
  },
@@ -4625,6 +5237,7 @@ function createTableBlock(tableIndex, table, document, cursor, counters, formatt
4625
5237
  resolvedTable.table?.cellMargins
4626
5238
  );
4627
5239
  cells.push({
5240
+ ...cell.sourceRef !== void 0 ? { sourceRef: cell.sourceRef } : {},
4628
5241
  gridSpan: cell.gridSpan ?? 1,
4629
5242
  verticalMerge: cell.verticalMerge ?? null,
4630
5243
  colspan: cell.gridSpan ?? 1,
@@ -4648,6 +5261,7 @@ function createTableBlock(tableIndex, table, document, cursor, counters, formatt
4648
5261
  }
4649
5262
  const headerLike = row.isHeader === true || resolvedRow?.style.isHeader === true;
4650
5263
  rows.push({
5264
+ ...row.sourceRef !== void 0 ? { sourceRef: row.sourceRef } : {},
4651
5265
  cells,
4652
5266
  ...row.gridBefore !== void 0 ? { gridBefore: row.gridBefore } : {},
4653
5267
  ...row.gridAfter !== void 0 ? { gridAfter: row.gridAfter } : {},
@@ -4678,6 +5292,7 @@ function createTableBlock(tableIndex, table, document, cursor, counters, formatt
4678
5292
  from: cursor,
4679
5293
  to: innerCursor,
4680
5294
  styleId: table.styleId,
5295
+ ...table.sourceRef !== void 0 ? { sourceRef: table.sourceRef } : {},
4681
5296
  gridColumns: table.gridColumns,
4682
5297
  ...gridColumnsRelative ? { gridColumnsRelative } : {},
4683
5298
  ...resolvedTable.table?.alignment ? { alignment: resolvedTable.table.alignment } : {},
@@ -5222,6 +5837,7 @@ function appendInlineSegments(paragraph, node, document, start, promoteSecondary
5222
5837
  const anchor = surfaceAnchorFromGeometry(node.anchor);
5223
5838
  const txbxTextSegment = c.isTextBox ? extractTxbxFirstTextSegment(c.txbxBlocks) : void 0;
5224
5839
  const txbxText = txbxTextSegment?.text ?? (c.isTextBox ? c.text : void 0);
5840
+ const txbxBody = c.isTextBox ? surfaceTextBoxBodyFromShape(c, node.sourceRef) : void 0;
5225
5841
  const surfaceFill = c.fill;
5226
5842
  paragraph.segments.push({
5227
5843
  segmentId: `${paragraph.blockId}-segment-${paragraph.segments.length}`,
@@ -5238,6 +5854,7 @@ function appendInlineSegments(paragraph, node, document, start, promoteSecondary
5238
5854
  ...c.textBoxBody ? { textBoxBody: c.textBoxBody } : {},
5239
5855
  ...c.preserveOnlyObject ? { preserveOnlyObject: surfacePreserveOnlyObject(c.preserveOnlyObject) } : {},
5240
5856
  ...txbxText ? { txbxText } : {},
5857
+ ...txbxBody ? { txbxBody } : {},
5241
5858
  ...txbxTextSegment?.marks && txbxTextSegment.marks.length > 0 ? { txbxMarks: txbxTextSegment.marks } : {},
5242
5859
  ...txbxTextSegment?.markAttrs ? { txbxMarkAttrs: txbxTextSegment.markAttrs } : {}
5243
5860
  });
@@ -5650,6 +6267,97 @@ function extractTxbxFirstTextSegment(blocks) {
5650
6267
  }
5651
6268
  return void 0;
5652
6269
  }
6270
+ function surfaceTextBoxBodyFromShape(shape, sourceRef) {
6271
+ if (!shape.isTextBox && shape.txbxContentXml === void 0 && shape.txbxBlocks === void 0) {
6272
+ return void 0;
6273
+ }
6274
+ if (shape.txbxBlocks === void 0) {
6275
+ return {
6276
+ ...sourceRef !== void 0 ? { sourceRef } : {},
6277
+ status: shape.txbxContentXml !== void 0 ? "preserve-only" : "unavailable",
6278
+ unavailableReason: "txbx-blocks-unavailable",
6279
+ ...shape.textBoxBody !== void 0 ? { bodyProperties: shape.textBoxBody } : {},
6280
+ blockCount: 0,
6281
+ paragraphCount: 0,
6282
+ unsupportedBlockCount: 0,
6283
+ paragraphs: []
6284
+ };
6285
+ }
6286
+ const paragraphs = shape.txbxBlocks.flatMap((block, blockIndex) => {
6287
+ if (block.type !== "paragraph") return [];
6288
+ const children = block.children;
6289
+ const legacyRuns = block.runs;
6290
+ const runs = children !== void 0 ? children.map(
6291
+ (inline, inlineIndex) => surfaceTextBoxRunFromInline(inline, inlineIndex)
6292
+ ) : legacyRuns?.map(
6293
+ (run, inlineIndex) => surfaceTextBoxRunFromLegacyRun(run, inlineIndex)
6294
+ ) ?? [];
6295
+ const text = runs.map((run) => run.text ?? "").join("");
6296
+ return [{
6297
+ ...block.sourceRef !== void 0 ? { sourceRef: block.sourceRef } : {},
6298
+ blockIndex,
6299
+ text,
6300
+ textLength: Array.from(text).length,
6301
+ ...block.borders !== void 0 ? { borders: block.borders } : {},
6302
+ runs
6303
+ }];
6304
+ });
6305
+ const unsupportedBlockCount = shape.txbxBlocks.length - paragraphs.length;
6306
+ const unavailableReason = shape.txbxBlocks.length === 0 ? "empty-body" : paragraphs.length === 0 ? "unsupported-content" : void 0;
6307
+ return {
6308
+ ...sourceRef !== void 0 ? { sourceRef } : {},
6309
+ status: unavailableReason === void 0 ? "modeled" : "unavailable",
6310
+ ...unavailableReason !== void 0 ? { unavailableReason } : {},
6311
+ ...shape.textBoxBody !== void 0 ? { bodyProperties: shape.textBoxBody } : {},
6312
+ blockCount: shape.txbxBlocks.length,
6313
+ paragraphCount: paragraphs.length,
6314
+ unsupportedBlockCount,
6315
+ paragraphs
6316
+ };
6317
+ }
6318
+ function surfaceTextBoxRunFromLegacyRun(run, inlineIndex) {
6319
+ const text = run.text ?? "";
6320
+ const cloned = run.marks ? cloneMarks(run.marks) : void 0;
6321
+ return {
6322
+ inlineIndex,
6323
+ kind: "text",
6324
+ text,
6325
+ textLength: Array.from(text).length,
6326
+ ...cloned?.marks && cloned.marks.length > 0 ? { marks: cloned.marks } : {},
6327
+ ...cloned?.markAttrs ? { markAttrs: cloned.markAttrs } : {}
6328
+ };
6329
+ }
6330
+ function surfaceTextBoxRunFromInline(inline, inlineIndex) {
6331
+ if (inline.type === "text") {
6332
+ const cloned = inline.marks ? cloneMarks(inline.marks) : void 0;
6333
+ return {
6334
+ inlineIndex,
6335
+ kind: "text",
6336
+ text: inline.text,
6337
+ textLength: Array.from(inline.text).length,
6338
+ ...cloned?.marks && cloned.marks.length > 0 ? { marks: cloned.marks } : {},
6339
+ ...cloned?.markAttrs ? { markAttrs: cloned.markAttrs } : {}
6340
+ };
6341
+ }
6342
+ if (inline.type === "tab") {
6343
+ return { inlineIndex, kind: "tab", text: " ", textLength: 1 };
6344
+ }
6345
+ if (inline.type === "hard_break") {
6346
+ return { inlineIndex, kind: "hard-break", text: "\n", textLength: 1 };
6347
+ }
6348
+ if (inline.type === "symbol") {
6349
+ const cloned = inline.marks ? cloneMarks(inline.marks) : void 0;
6350
+ return {
6351
+ inlineIndex,
6352
+ kind: "symbol",
6353
+ text: inline.char,
6354
+ textLength: Array.from(inline.char).length,
6355
+ ...cloned?.marks && cloned.marks.length > 0 ? { marks: cloned.marks } : {},
6356
+ ...cloned?.markAttrs ? { markAttrs: cloned.markAttrs } : {}
6357
+ };
6358
+ }
6359
+ return { inlineIndex, kind: "unsupported" };
6360
+ }
5653
6361
  function appendComplexPreviewSegment(paragraph, node, start, label, detail, extras = {}) {
5654
6362
  const preserveOnlyObject = node.preserveOnlyObject ? surfacePreserveOnlyObject(node.preserveOnlyObject) : void 0;
5655
6363
  paragraph.segments.push({