@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
@@ -255,7 +255,7 @@ function collectCanonicalLayoutInputs(doc) {
255
255
  editableTargets: collectEditableTargetRefs(doc)
256
256
  };
257
257
  }
258
- function collectEditableTargetRefs(doc) {
258
+ function collectEditableTargetRefs(doc, cache) {
259
259
  const targets = [];
260
260
  for (const context of collectStoryBlockContexts(doc)) {
261
261
  collectEditableTargetsInBlocks(
@@ -267,17 +267,64 @@ function collectEditableTargetRefs(doc) {
267
267
  insideTextBox: false,
268
268
  tableDepth: 0
269
269
  },
270
- targets
270
+ targets,
271
+ cache
271
272
  );
272
273
  }
274
+ collectFieldRegionRefreshTargets(doc, targets);
275
+ collectBookmarkContentRangeTargets(doc, targets);
273
276
  collectReviewEditableTargets(doc, targets);
274
277
  return targets;
275
278
  }
276
- function collectEditableTargetsInBlocks(blocks, context, targets) {
279
+ function createEditableTargetBlockCache() {
280
+ const map = /* @__PURE__ */ new WeakMap();
281
+ return {
282
+ get(block) {
283
+ return map.get(block);
284
+ },
285
+ set(block, entry) {
286
+ map.set(block, entry);
287
+ }
288
+ };
289
+ }
290
+ function buildBlockCacheSignature(context, blockIndex) {
291
+ const cc = context.contentControl;
292
+ const tt = context.tableTarget;
293
+ const owner = tt?.editableOwnersByChildIndex?.get(blockIndex);
294
+ return [
295
+ context.storyKey,
296
+ context.insideSdt ? "1" : "0",
297
+ context.insideTextBox ? "1" : "0",
298
+ String(context.tableDepth),
299
+ cc?.sdtId ?? "",
300
+ cc?.tag ?? "",
301
+ cc?.alias ?? "",
302
+ cc?.sdtType ?? "",
303
+ cc?.lock ?? "",
304
+ tt?.tablePath ?? "",
305
+ tt?.tableDepth ?? "",
306
+ tt?.rowIndex ?? "",
307
+ tt?.cellIndex ?? "",
308
+ tt?.gridColumnStart ?? "",
309
+ tt?.cell?.verticalMerge ?? "",
310
+ tt?.cell?.gridSpan ?? "",
311
+ owner?.targetKey ?? ""
312
+ ].join("|");
313
+ }
314
+ function collectEditableTargetsInBlocks(blocks, context, targets, cache) {
277
315
  for (let blockIndex = 0; blockIndex < blocks.length; blockIndex += 1) {
278
316
  const block = blocks[blockIndex];
279
317
  if (!block) continue;
280
318
  const blockPath = `${context.basePath}/block[${blockIndex}]`;
319
+ const signature = cache !== void 0 ? buildBlockCacheSignature(context, blockIndex) : "";
320
+ if (cache !== void 0) {
321
+ const cached = cache.get(block);
322
+ if (cached !== void 0 && cached.blockPath === blockPath && cached.signature === signature) {
323
+ for (const target of cached.targets) targets.push(target);
324
+ continue;
325
+ }
326
+ }
327
+ const blockStart = targets.length;
281
328
  if (block.type === "paragraph") {
282
329
  const targetKind = editableParagraphTargetKind(context);
283
330
  if (targetKind !== null) {
@@ -289,14 +336,13 @@ function collectEditableTargetsInBlocks(blocks, context, targets) {
289
336
  blockPath,
290
337
  editableParagraphTargetPosture(targetKind),
291
338
  context.contentControl,
292
- context.tableTarget
339
+ context.tableTarget,
340
+ context.tableTarget?.editableOwnersByChildIndex?.get(blockIndex)
293
341
  )
294
342
  );
295
343
  }
296
344
  collectEditableTargetsInInlines(block.children ?? [], `${blockPath}/inline`, context, targets);
297
- continue;
298
- }
299
- if (block.type === "sdt") {
345
+ } else if (block.type === "sdt") {
300
346
  const contentControl = contentControlIdentityForSdt(block, context.contentControl);
301
347
  collectEditableTargetsInBlocks(
302
348
  block.children,
@@ -306,11 +352,10 @@ function collectEditableTargetsInBlocks(blocks, context, targets) {
306
352
  insideSdt: true,
307
353
  contentControl
308
354
  },
309
- targets
355
+ targets,
356
+ cache
310
357
  );
311
- continue;
312
- }
313
- if (block.type === "custom_xml") {
358
+ } else if (block.type === "custom_xml") {
314
359
  targets.push(createCustomXmlEditableTarget(block, context.storyKey, blockPath));
315
360
  collectEditableTargetsInBlocks(
316
361
  block.children,
@@ -318,25 +363,29 @@ function collectEditableTargetsInBlocks(blocks, context, targets) {
318
363
  ...context,
319
364
  basePath: blockPath
320
365
  },
321
- targets
366
+ targets,
367
+ cache
322
368
  );
323
- continue;
324
- }
325
- if (block.type === "opaque_block") {
369
+ } else if (block.type === "opaque_block") {
326
370
  targets.push(createOpaqueBlockEditableTarget(block, context.storyKey, blockPath));
327
- continue;
328
- }
329
- if (block.type === "alt_chunk") {
371
+ } else if (block.type === "alt_chunk") {
330
372
  targets.push(createAltChunkEditableTarget(block.relationshipId, context.storyKey, blockPath));
331
- continue;
373
+ } else if (block.type === "table") {
374
+ collectEditableTargetsInTable(block, blockPath, context, targets, cache);
332
375
  }
333
- if (block.type === "table") {
334
- collectEditableTargetsInTable(block, blockPath, context, targets);
376
+ if (cache !== void 0) {
377
+ const blockTargets = targets.slice(blockStart);
378
+ cache.set(block, {
379
+ blockPath,
380
+ signature,
381
+ targets: blockTargets
382
+ });
335
383
  }
336
384
  }
337
385
  }
338
- function collectEditableTargetsInTable(table, tablePath, context, targets) {
386
+ function collectEditableTargetsInTable(table, tablePath, context, targets, cache) {
339
387
  const tableDepth = context.tableDepth + 1;
388
+ const verticalMergeOwners = [];
340
389
  targets.push(createTableStructureTarget({
341
390
  scope: "table",
342
391
  kind: "table-structure-table",
@@ -375,6 +424,10 @@ function collectEditableTargetsInTable(table, tablePath, context, targets) {
375
424
  const cell = row.cells[cellIndex];
376
425
  if (!cell) continue;
377
426
  const gridSpan = cell.gridSpan ?? 1;
427
+ const continuationOwner = cell.verticalMerge === "continue" ? findVerticalMergeOwner(verticalMergeOwners, gridColumnStart, gridSpan) : null;
428
+ if (cell.verticalMerge !== "continue") {
429
+ clearVerticalMergeOwners(verticalMergeOwners, gridColumnStart, gridSpan);
430
+ }
378
431
  targets.push(createTableStructureTarget({
379
432
  scope: "cell",
380
433
  kind: "table-structure-cell",
@@ -417,15 +470,136 @@ function collectEditableTargetsInTable(table, tablePath, context, targets) {
417
470
  row,
418
471
  cellIndex,
419
472
  cell,
420
- gridColumnStart
473
+ gridColumnStart,
474
+ ...continuationOwner ? {
475
+ editableOwnersByChildIndex: continuationOwnerTargetsByChildIndex(
476
+ continuationOwner,
477
+ cell.children.length
478
+ )
479
+ } : {}
421
480
  }
422
481
  },
423
- targets
482
+ targets,
483
+ cache
424
484
  );
485
+ if (cell.verticalMerge === "restart") {
486
+ verticalMergeOwners.push(createVerticalMergeOwnerState({
487
+ context,
488
+ table,
489
+ tablePath,
490
+ tableDepth,
491
+ rowIndex,
492
+ row,
493
+ cellIndex,
494
+ cell,
495
+ gridColumnStart,
496
+ gridSpan
497
+ }));
498
+ }
425
499
  gridColumnStart += gridSpan;
426
500
  }
427
501
  }
428
502
  }
503
+ function findVerticalMergeOwner(owners, gridColumnStart, gridSpan) {
504
+ return owners.find(
505
+ (owner) => owner.gridColumnStart === gridColumnStart && owner.gridSpan === gridSpan
506
+ ) ?? null;
507
+ }
508
+ function clearVerticalMergeOwners(owners, gridColumnStart, gridSpan) {
509
+ const gridColumnEnd = gridColumnStart + gridSpan;
510
+ for (let index = owners.length - 1; index >= 0; index -= 1) {
511
+ const owner = owners[index];
512
+ if (!owner) continue;
513
+ const ownerEnd = owner.gridColumnStart + owner.gridSpan;
514
+ if (gridColumnStart < ownerEnd && owner.gridColumnStart < gridColumnEnd) {
515
+ owners.splice(index, 1);
516
+ }
517
+ }
518
+ }
519
+ function continuationOwnerTargetsByChildIndex(owner, childCount) {
520
+ if (!owner.fallbackOwnerTarget) return void 0;
521
+ const targets = /* @__PURE__ */ new Map();
522
+ for (let childIndex = 0; childIndex < childCount; childIndex += 1) {
523
+ targets.set(
524
+ childIndex,
525
+ owner.ownerTargetsByChildIndex.get(childIndex) ?? owner.fallbackOwnerTarget
526
+ );
527
+ }
528
+ return targets;
529
+ }
530
+ function createVerticalMergeOwnerState(input) {
531
+ const ownerTargetsByChildIndex = /* @__PURE__ */ new Map();
532
+ for (let childIndex = 0; childIndex < input.cell.children.length; childIndex += 1) {
533
+ const owner = createVerticalMergeEditableOwner({ ...input, childIndex });
534
+ if (owner) ownerTargetsByChildIndex.set(childIndex, owner);
535
+ }
536
+ return {
537
+ gridColumnStart: input.gridColumnStart,
538
+ gridSpan: input.gridSpan,
539
+ ownerTargetsByChildIndex,
540
+ ...ownerTargetsByChildIndex.size > 0 ? { fallbackOwnerTarget: ownerTargetsByChildIndex.values().next().value } : {}
541
+ };
542
+ }
543
+ function createVerticalMergeEditableOwner(input) {
544
+ const child = input.cell.children[input.childIndex];
545
+ if (child?.type !== "paragraph") return null;
546
+ const ownerTableTarget = {
547
+ table: input.table,
548
+ tablePath: input.tablePath,
549
+ tableDepth: input.tableDepth,
550
+ rowIndex: input.rowIndex,
551
+ row: input.row,
552
+ cellIndex: input.cellIndex,
553
+ cell: input.cell,
554
+ gridColumnStart: input.gridColumnStart
555
+ };
556
+ const kind = editableParagraphTargetKind({
557
+ ...input.context,
558
+ basePath: `${input.tablePath}/row[${input.rowIndex}]/cell[${input.cellIndex}]`,
559
+ tableDepth: input.tableDepth,
560
+ tableTarget: ownerTableTarget
561
+ });
562
+ if (!kind) return null;
563
+ const blockPath = `${input.tablePath}/row[${input.rowIndex}]/cell[${input.cellIndex}]/block[${input.childIndex}]`;
564
+ const paragraphTextHash = hashText(collectParagraphText(child));
565
+ const table = createTableIdentity({
566
+ scope: "text",
567
+ context: {
568
+ storyKey: input.context.storyKey,
569
+ insideSdt: input.context.contentControl !== void 0
570
+ },
571
+ ...ownerTableTarget
572
+ });
573
+ return {
574
+ targetKey: `${input.context.storyKey}:${blockPath}:text`,
575
+ kind,
576
+ storyKey: input.context.storyKey,
577
+ blockPath,
578
+ leafPath: `${blockPath}/inline`,
579
+ commandFamily: "text-leaf",
580
+ reason: "vertical-merge-restart-cell",
581
+ canonicalAddress: ownerRoutingFromAddress(
582
+ createTableTargetCanonicalAddress(
583
+ table,
584
+ "paragraph",
585
+ paragraphTextHash,
586
+ { rangeBoundary: { boundaryKind: "cell-fragment" } }
587
+ )
588
+ ),
589
+ table: {
590
+ tableKey: table.tableKey,
591
+ tablePath: table.tablePath,
592
+ ...table.sourceRef !== void 0 ? { sourceRef: table.sourceRef } : {},
593
+ ...table.rowSourceRef !== void 0 ? { rowSourceRef: table.rowSourceRef } : {},
594
+ ...table.cellSourceRef !== void 0 ? { cellSourceRef: table.cellSourceRef } : {},
595
+ ...table.rowIndex !== void 0 ? { rowIndex: table.rowIndex } : {},
596
+ ...table.cellIndex !== void 0 ? { cellIndex: table.cellIndex } : {},
597
+ ...table.gridColumnStart !== void 0 ? { gridColumnStart: table.gridColumnStart } : {},
598
+ ...table.gridSpan !== void 0 ? { gridSpan: table.gridSpan } : {},
599
+ ...table.verticalMerge !== void 0 ? { verticalMerge: table.verticalMerge } : {}
600
+ }
601
+ };
602
+ }
429
603
  function computeTableStructureColumnCount(table) {
430
604
  let columnCount = table.gridColumns.length;
431
605
  for (const row of table.rows) {
@@ -445,6 +619,7 @@ function createTableStructureTarget(input) {
445
619
  const columnPath = input.columnIndex !== void 0 ? `${input.tablePath}/column[${input.columnIndex}]` : void 0;
446
620
  const blockPath = cellPath ?? rowPath ?? columnPath ?? input.tablePath;
447
621
  const tableIdentity = createTableIdentity(input);
622
+ const targetHash = hashTableStructureTarget(input);
448
623
  return {
449
624
  targetKey: `${tableKey}:structure:${tableIdentity.operationScope}${tableTargetSuffix(tableIdentity)}`,
450
625
  kind: input.kind,
@@ -456,8 +631,14 @@ function createTableStructureTarget(input) {
456
631
  ...input.table.sourceRef !== void 0 ? { sourceRef: input.table.sourceRef } : {},
457
632
  ...input.context.contentControl !== void 0 ? { contentControl: input.context.contentControl } : {},
458
633
  table: tableIdentity,
634
+ canonicalAddress: createTableTargetCanonicalAddress(
635
+ tableIdentity,
636
+ tableStructureBlockType(input.scope),
637
+ targetHash,
638
+ { rangeBoundary: { boundaryKind: "table-grid" } }
639
+ ),
459
640
  staleCheck: {
460
- targetHash: hashTableStructureTarget(input),
641
+ targetHash,
461
642
  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),
462
643
  blockType: tableStructureBlockType(input.scope),
463
644
  ...input.table.sourceRef !== void 0 ? { sourceRef: input.table.sourceRef } : {}
@@ -468,10 +649,15 @@ function createTableStructureTarget(input) {
468
649
  function createTableIdentity(input) {
469
650
  const tableKey = `${input.context.storyKey}:${input.tablePath}`;
470
651
  const columnCount = computeTableStructureColumnCount(input.table);
652
+ const rowRange = tableFragmentRowRange(input).rowRange;
653
+ const columnRange = tableFragmentColumnRange(input, columnCount).columnRange;
471
654
  const base = {
472
655
  operationScope: input.scope,
473
656
  tableKey,
474
657
  tablePath: input.tablePath,
658
+ ...input.table.sourceRef !== void 0 ? { sourceRef: input.table.sourceRef } : {},
659
+ ...input.row?.sourceRef !== void 0 ? { rowSourceRef: input.row.sourceRef } : {},
660
+ ...input.cell?.sourceRef !== void 0 ? { cellSourceRef: input.cell.sourceRef } : {},
475
661
  ...tablePathIndexes(input.tablePath),
476
662
  tableDepth: input.tableDepth,
477
663
  ...input.tableDepth >= 2 ? { nestedTable: true } : {},
@@ -479,7 +665,10 @@ function createTableIdentity(input) {
479
665
  ...input.context.storyKey !== MAIN_STORY_KEY ? { secondaryStory: true } : {},
480
666
  rowCount: input.table.rows.length,
481
667
  columnCount,
482
- fragment: createTableFragmentIdentity(input, tableKey, columnCount)
668
+ fragment: createTableFragmentIdentity(input, tableKey, columnCount),
669
+ ...input.cell !== void 0 ? {
670
+ cellFragment: createTableCellFragmentIdentity(input, tableKey, rowRange, columnRange)
671
+ } : {}
483
672
  };
484
673
  return {
485
674
  ...base,
@@ -493,6 +682,25 @@ function createTableIdentity(input) {
493
682
  ...input.cell !== void 0 ? { blockCount: input.cell.children.length } : {}
494
683
  };
495
684
  }
685
+ function createTableCellFragmentIdentity(input, tableKey, rowRange, columnRange) {
686
+ const text = (input.cell?.children ?? []).map(blockTextForTargetHash).join("");
687
+ return {
688
+ fragmentKey: hashText(JSON.stringify({
689
+ tableKey,
690
+ rowIndex: input.rowIndex ?? null,
691
+ cellIndex: input.cellIndex ?? null,
692
+ gridColumnStart: input.gridColumnStart ?? null,
693
+ gridSpan: input.cell?.gridSpan ?? 1,
694
+ verticalMerge: input.cell?.verticalMerge ?? null,
695
+ sourceId: input.cell?.sourceRef?.sourceId ?? null
696
+ })),
697
+ textHash: hashText(text),
698
+ blockCount: input.cell?.children.length ?? 0,
699
+ ...rowRange !== void 0 ? { rowRange } : {},
700
+ ...columnRange !== void 0 ? { columnRange } : {},
701
+ ...sourceJoinHashForRefs(input.table.sourceRef, input.row?.sourceRef, input.cell?.sourceRef)
702
+ };
703
+ }
496
704
  function tablePathIndexes(tablePath) {
497
705
  const blockIndexes = [...tablePath.matchAll(/\/block\[(\d+)\]/gu)].map((match) => Number(match[1]));
498
706
  const storyBlockIndex = blockIndexes[0];
@@ -658,13 +866,39 @@ function collectEditableTargetsInInlines(inlines, basePath, context, targets) {
658
866
  }
659
867
  }
660
868
  }
661
- function createParagraphEditableTarget(paragraph, kind, storyKey, blockPath, targetPosture = { editability: "editable", posture: { blockers: [] } }, contentControl, tableTarget) {
869
+ function createParagraphEditableTarget(paragraph, kind, storyKey, blockPath, targetPosture = { editability: "editable", posture: { blockers: [] } }, contentControl, tableTarget, editableOwner) {
662
870
  const paragraphText = collectParagraphText(paragraph);
871
+ const paragraphTextHash = hashText(paragraphText);
663
872
  const sourceRef = paragraph.sourceRef;
664
873
  const lockedContentControl = contentControlLocksContent(contentControl);
665
- const posture = lockedContentControl ? mergeTargetPosture(targetPosture.posture, ["locked-content-control"], {
874
+ const syntheticLayoutCell = tableTarget?.cell?.verticalMerge === "continue";
875
+ const tableIdentity = tableTarget !== void 0 ? createTableIdentity({
876
+ scope: "text",
877
+ context: { storyKey, insideSdt: contentControl !== void 0 },
878
+ ...tableTarget
879
+ }) : void 0;
880
+ const listAddress = tableIdentity === void 0 && paragraph.numbering !== void 0 ? createCanonicalAddress({
881
+ addressKind: "list-item-text",
882
+ storyKey,
883
+ staleCheckKind: "paragraph",
884
+ operationScope: "list-text",
885
+ sourceRefs: [sourceRef],
886
+ staleHash: paragraphTextHash,
887
+ rangeBoundary: { boundaryKind: "list-item-text" },
888
+ discriminator: {
889
+ blockPath,
890
+ numberingInstanceId: paragraph.numbering.numberingInstanceId,
891
+ level: paragraph.numbering.level,
892
+ sourceId: sourceRef?.sourceId ?? null,
893
+ paraId: paragraph.wordExtensionIds?.paraId ?? null,
894
+ textId: paragraph.wordExtensionIds?.textId ?? null
895
+ }
896
+ }) : void 0;
897
+ const tableAwarePosture = syntheticLayoutCell ? mergeTargetPosture(targetPosture.posture, ["synthetic-layout-cell"]) : targetPosture.posture;
898
+ const posture = lockedContentControl ? mergeTargetPosture(tableAwarePosture, ["locked-content-control"], {
666
899
  lockedContentControl: true
667
- }) : targetPosture.posture;
900
+ }) : tableAwarePosture;
901
+ const editability = lockedContentControl || syntheticLayoutCell ? "non-editable" : targetPosture.editability;
668
902
  return {
669
903
  targetKey: `${storyKey}:${blockPath}:text`,
670
904
  kind,
@@ -672,12 +906,24 @@ function createParagraphEditableTarget(paragraph, kind, storyKey, blockPath, tar
672
906
  blockPath,
673
907
  leafPath: `${blockPath}/inline`,
674
908
  commandFamily: "text-leaf",
675
- editability: lockedContentControl ? "non-editable" : targetPosture.editability,
909
+ editability,
676
910
  ...sourceRef !== void 0 ? { sourceRef } : {},
677
911
  ...contentControl !== void 0 ? { contentControl } : {},
678
- ...tableTarget !== void 0 ? { table: createTableIdentity({ scope: "text", context: { storyKey, insideSdt: contentControl !== void 0 }, ...tableTarget }) } : {},
912
+ ...tableIdentity !== void 0 ? { table: tableIdentity } : {},
913
+ ...editableOwner !== void 0 ? { editableOwner } : {},
914
+ ...tableIdentity !== void 0 ? {
915
+ canonicalAddress: createTableTargetCanonicalAddress(
916
+ tableIdentity,
917
+ "paragraph",
918
+ paragraphTextHash,
919
+ {
920
+ rangeBoundary: { boundaryKind: "cell-fragment" },
921
+ owner: editableOwner?.canonicalAddress
922
+ }
923
+ )
924
+ } : listAddress !== void 0 ? { canonicalAddress: listAddress } : {},
679
925
  staleCheck: {
680
- paragraphTextHash: hashText(paragraphText),
926
+ paragraphTextHash,
681
927
  paragraphTextLength: Array.from(paragraphText).length,
682
928
  inlineCount: paragraph.children?.length ?? 0,
683
929
  blockType: "paragraph",
@@ -708,12 +954,27 @@ function collectInlineTarget(inline, storyKey, inlinePath, targets) {
708
954
  return;
709
955
  case "hyperlink":
710
956
  targets.push(createHyperlinkEditableTarget(inline, storyKey, inlinePath));
957
+ targets.push(createHyperlinkDestinationEditableTarget(inline, storyKey, inlinePath));
711
958
  return;
712
959
  case "bookmark_start":
713
- targets.push(createBookmarkEditableTarget(inline.bookmarkId, inline.name, storyKey, inlinePath, "start"));
960
+ targets.push(createBookmarkEditableTarget(
961
+ inline.bookmarkId,
962
+ inline.name,
963
+ storyKey,
964
+ inlinePath,
965
+ "start",
966
+ inline.sourceRef
967
+ ));
714
968
  return;
715
969
  case "bookmark_end":
716
- targets.push(createBookmarkEditableTarget(inline.bookmarkId, void 0, storyKey, inlinePath, "end"));
970
+ targets.push(createBookmarkEditableTarget(
971
+ inline.bookmarkId,
972
+ void 0,
973
+ storyKey,
974
+ inlinePath,
975
+ "end",
976
+ inline.sourceRef
977
+ ));
717
978
  return;
718
979
  case "image":
719
980
  targets.push(createImageEditableTarget(inline, storyKey, inlinePath));
@@ -737,6 +998,7 @@ function collectInlineTarget(inline, storyKey, inlinePath, targets) {
737
998
  function createFieldEditableTarget(field, storyKey, inlinePath) {
738
999
  const resultText = field.children.map(inlineTextForTargetHash).join("");
739
1000
  const sourceRef = field.sourceRef;
1001
+ const targetHash = hashText(`${field.instruction}\0${resultText}`);
740
1002
  const preserveOnly = field.refreshStatus === "preserve-only" || field.fieldFamily === "UNKNOWN";
741
1003
  const blockers = preserveOnly ? ["field-generated-text", "preserve-only"] : ["field-generated-text", "unmodeled-target"];
742
1004
  return {
@@ -756,9 +1018,28 @@ function createFieldEditableTarget(field, storyKey, inlinePath) {
756
1018
  ...field.locked !== void 0 ? { locked: field.locked } : {},
757
1019
  ...field.dirty !== void 0 ? { dirty: field.dirty } : {}
758
1020
  },
1021
+ canonicalAddress: createCanonicalAddress({
1022
+ addressKind: "field-result",
1023
+ storyKey,
1024
+ staleCheckKind: "field",
1025
+ operationScope: "field-refresh",
1026
+ sourceRefs: [sourceRef],
1027
+ staleHash: targetHash,
1028
+ rangeBoundary: {
1029
+ boundaryKind: "field-result",
1030
+ from: 0,
1031
+ to: Array.from(resultText).length
1032
+ },
1033
+ discriminator: {
1034
+ canonicalFieldId: field.canonicalFieldId ?? null,
1035
+ fieldFamily: field.fieldFamily ?? null,
1036
+ fieldTarget: field.fieldTarget ?? null,
1037
+ sourceId: sourceRef?.sourceId ?? null
1038
+ }
1039
+ }),
759
1040
  staleCheck: {
760
1041
  blockType: "field",
761
- targetHash: hashText(`${field.instruction}\0${resultText}`),
1042
+ targetHash,
762
1043
  targetTextLength: Array.from(resultText).length,
763
1044
  childCount: field.children.length,
764
1045
  ...sourceRef !== void 0 ? { sourceRef } : {}
@@ -772,6 +1053,7 @@ function createFieldEditableTarget(field, storyKey, inlinePath) {
772
1053
  function createHyperlinkEditableTarget(hyperlink, storyKey, inlinePath) {
773
1054
  const text = hyperlink.children.map(inlineTextForTargetHash).join("");
774
1055
  const sourceRef = hyperlink.sourceRef ?? hyperlink.fieldCarrier?.sourceRef;
1056
+ const targetHash = hashText(`${hyperlink.href}\0${text}`);
775
1057
  return {
776
1058
  targetKey: `${storyKey}:${inlinePath}:hyperlink`,
777
1059
  kind: "hyperlink-text",
@@ -782,9 +1064,25 @@ function createHyperlinkEditableTarget(hyperlink, storyKey, inlinePath) {
782
1064
  editability: "editable",
783
1065
  ...sourceRef !== void 0 ? { sourceRef } : {},
784
1066
  link: { href: hyperlink.href },
1067
+ canonicalAddress: createCanonicalAddress({
1068
+ addressKind: "hyperlink-display-text",
1069
+ storyKey,
1070
+ staleCheckKind: "hyperlink",
1071
+ sourceRefs: [sourceRef],
1072
+ staleHash: targetHash,
1073
+ rangeBoundary: {
1074
+ boundaryKind: "hyperlink-display",
1075
+ from: 0,
1076
+ to: Array.from(text).length
1077
+ },
1078
+ discriminator: {
1079
+ href: hyperlink.href,
1080
+ sourceId: sourceRef?.sourceId ?? null
1081
+ }
1082
+ }),
785
1083
  staleCheck: {
786
1084
  blockType: "hyperlink",
787
- targetHash: hashText(`${hyperlink.href}\0${text}`),
1085
+ targetHash,
788
1086
  targetTextLength: Array.from(text).length,
789
1087
  childCount: hyperlink.children.length,
790
1088
  ...sourceRef !== void 0 ? { sourceRef } : {}
@@ -792,7 +1090,52 @@ function createHyperlinkEditableTarget(hyperlink, storyKey, inlinePath) {
792
1090
  posture: { blockers: [] }
793
1091
  };
794
1092
  }
795
- function createBookmarkEditableTarget(bookmarkId, bookmarkName, storyKey, inlinePath, edge) {
1093
+ function createHyperlinkDestinationEditableTarget(hyperlink, storyKey, inlinePath) {
1094
+ const sourceRef = hyperlink.sourceRef ?? hyperlink.fieldCarrier?.sourceRef;
1095
+ const destinationKind = hyperlink.href.startsWith("#") ? "internal-anchor" : "external";
1096
+ const targetHash = hashText(`destination\0${hyperlink.href}`);
1097
+ return {
1098
+ targetKey: `${storyKey}:${inlinePath}:hyperlink-destination`,
1099
+ kind: "hyperlink-destination",
1100
+ storyKey,
1101
+ blockPath: inlinePath,
1102
+ leafPath: `${inlinePath}/destination`,
1103
+ commandFamily: "link-bookmark",
1104
+ editability: "non-editable",
1105
+ ...sourceRef !== void 0 ? { sourceRef } : {},
1106
+ link: {
1107
+ href: hyperlink.href,
1108
+ destinationKind
1109
+ },
1110
+ canonicalAddress: createCanonicalAddress({
1111
+ addressKind: "hyperlink-destination",
1112
+ storyKey,
1113
+ staleCheckKind: "hyperlink",
1114
+ operationScope: "link-destination",
1115
+ sourceRefs: [sourceRef],
1116
+ staleHash: targetHash,
1117
+ rangeBoundary: {
1118
+ boundaryKind: "hyperlink-destination",
1119
+ ...sourceRef !== void 0 ? { startSourceJoinHash: sourceJoinHash([sourceRef]) } : {},
1120
+ ...sourceRef !== void 0 ? { endSourceJoinHash: sourceJoinHash([sourceRef]) } : {}
1121
+ },
1122
+ discriminator: {
1123
+ href: hyperlink.href,
1124
+ destinationKind,
1125
+ sourceId: sourceRef?.sourceId ?? null
1126
+ }
1127
+ }),
1128
+ staleCheck: {
1129
+ blockType: "hyperlink",
1130
+ targetHash,
1131
+ childCount: hyperlink.children.length,
1132
+ ...sourceRef !== void 0 ? { sourceRef } : {}
1133
+ },
1134
+ posture: { blockers: ["unmodeled-target"] }
1135
+ };
1136
+ }
1137
+ function createBookmarkEditableTarget(bookmarkId, bookmarkName, storyKey, inlinePath, edge, sourceRef) {
1138
+ const targetHash = hashText(`${edge}\0${bookmarkId}\0${bookmarkName ?? ""}`);
796
1139
  return {
797
1140
  targetKey: `${storyKey}:${inlinePath}:bookmark:${edge}:${bookmarkId}`,
798
1141
  kind: "bookmark-anchor",
@@ -801,14 +1144,34 @@ function createBookmarkEditableTarget(bookmarkId, bookmarkName, storyKey, inline
801
1144
  leafPath: inlinePath,
802
1145
  commandFamily: "link-bookmark",
803
1146
  editability: "non-editable",
1147
+ ...sourceRef !== void 0 ? { sourceRef } : {},
804
1148
  link: {
805
1149
  bookmarkId,
806
1150
  ...bookmarkName !== void 0 ? { bookmarkName } : {}
807
1151
  },
1152
+ canonicalAddress: createCanonicalAddress({
1153
+ addressKind: "bookmark-anchor",
1154
+ storyKey,
1155
+ staleCheckKind: "bookmark",
1156
+ sourceRefs: [sourceRef],
1157
+ staleHash: targetHash,
1158
+ rangeBoundary: {
1159
+ boundaryKind: "bookmark-anchor",
1160
+ ...sourceRef !== void 0 ? { startSourceJoinHash: sourceJoinHash([sourceRef]) } : {},
1161
+ ...sourceRef !== void 0 ? { endSourceJoinHash: sourceJoinHash([sourceRef]) } : {}
1162
+ },
1163
+ discriminator: {
1164
+ bookmarkId,
1165
+ bookmarkName: bookmarkName ?? null,
1166
+ edge,
1167
+ sourceId: sourceRef?.sourceId ?? null
1168
+ }
1169
+ }),
808
1170
  staleCheck: {
809
1171
  blockType: "bookmark",
810
- targetHash: hashText(`${edge}\0${bookmarkId}\0${bookmarkName ?? ""}`),
811
- childCount: 0
1172
+ targetHash,
1173
+ childCount: 0,
1174
+ ...sourceRef !== void 0 ? { sourceRef } : {}
812
1175
  },
813
1176
  posture: { blockers: ["unmodeled-target"] }
814
1177
  };
@@ -856,6 +1219,7 @@ function createObjectEditableTarget(inline, storyKey, inlinePath) {
856
1219
  storyKey,
857
1220
  inlinePath,
858
1221
  objectKind: "ole",
1222
+ sourceRef: inline.sourceRef,
859
1223
  targetHash: `${inline.id}\0${inline.relationshipId}`,
860
1224
  object: {
861
1225
  objectKind: "ole",
@@ -977,6 +1341,167 @@ function createOpaqueEditableTarget(input) {
977
1341
  }
978
1342
  };
979
1343
  }
1344
+ function collectFieldRegionRefreshTargets(doc, targets) {
1345
+ for (const region of collectCanonicalFieldRegionIdentities(doc)) {
1346
+ targets.push(createFieldRegionRefreshEditableTarget(region));
1347
+ }
1348
+ }
1349
+ function createFieldRegionRefreshEditableTarget(region) {
1350
+ const isToc = region.kind === "toc-region" || region.fieldFamily === "TOC";
1351
+ const sourceRef = region.sourceRef;
1352
+ const targetHash = hashText(JSON.stringify({
1353
+ regionId: region.regionId,
1354
+ canonicalFieldId: region.canonicalFieldId,
1355
+ fieldFamily: region.fieldFamily,
1356
+ refreshStatus: region.refreshStatus,
1357
+ tocId: region.tocId ?? null,
1358
+ resultRange: region.resultRange ?? null,
1359
+ status: region.status ?? null
1360
+ }));
1361
+ return {
1362
+ targetKey: `${region.storyKey}:field-region:${region.regionId}:refresh`,
1363
+ kind: isToc ? "toc-region-refresh" : "field-region-refresh",
1364
+ storyKey: region.storyKey,
1365
+ blockPath: `${region.storyKey}/field-region[${region.regionId}]`,
1366
+ leafPath: `${region.storyKey}/field-region[${region.regionId}]/refresh`,
1367
+ commandFamily: "field",
1368
+ editability: "non-editable",
1369
+ ...sourceRef !== void 0 ? { sourceRef } : {},
1370
+ field: {
1371
+ canonicalFieldId: region.canonicalFieldId,
1372
+ regionId: region.regionId,
1373
+ fieldFamily: region.fieldFamily,
1374
+ refreshStatus: region.refreshStatus,
1375
+ ...region.sourcePath !== void 0 ? { sourcePath: region.sourcePath } : {},
1376
+ ...region.tocId !== void 0 ? { tocId: region.tocId } : {},
1377
+ ...region.resultRange !== void 0 ? {
1378
+ resultRangeFromParagraphIndex: region.resultRange.fromParagraphIndex,
1379
+ resultRangeToParagraphIndex: region.resultRange.toParagraphIndex
1380
+ } : {},
1381
+ ...region.status !== void 0 ? { status: region.status } : {},
1382
+ ...region.cachedEntryCount !== void 0 ? { cachedEntryCount: region.cachedEntryCount } : {},
1383
+ ...region.generatedEntryCount !== void 0 ? { generatedEntryCount: region.generatedEntryCount } : {}
1384
+ },
1385
+ canonicalAddress: createCanonicalAddress({
1386
+ addressKind: isToc ? "toc-region-refresh" : "field-region-refresh",
1387
+ storyKey: region.storyKey,
1388
+ staleCheckKind: "field",
1389
+ operationScope: isToc ? "toc-refresh" : "field-refresh",
1390
+ sourceRefs: [sourceRef],
1391
+ staleHash: targetHash,
1392
+ rangeBoundary: {
1393
+ boundaryKind: "field-region",
1394
+ ...region.resultRange !== void 0 ? {
1395
+ from: region.resultRange.fromParagraphIndex,
1396
+ to: region.resultRange.toParagraphIndex
1397
+ } : { from: region.paragraphIndex, to: region.paragraphIndex }
1398
+ },
1399
+ discriminator: {
1400
+ regionId: region.regionId,
1401
+ canonicalFieldId: region.canonicalFieldId,
1402
+ fieldIndex: region.fieldIndex,
1403
+ fieldFamily: region.fieldFamily,
1404
+ tocId: region.tocId ?? null
1405
+ }
1406
+ }),
1407
+ staleCheck: {
1408
+ blockType: "field",
1409
+ targetHash,
1410
+ childCount: region.cachedEntryCount ?? 0,
1411
+ ...sourceRef !== void 0 ? { sourceRef } : {}
1412
+ },
1413
+ posture: {
1414
+ blockers: ["field-generated-text", "unmodeled-target"]
1415
+ }
1416
+ };
1417
+ }
1418
+ function collectBookmarkContentRangeTargets(doc, targets) {
1419
+ const candidates = /* @__PURE__ */ new Map();
1420
+ for (const context of collectStoryBlockContexts(doc)) {
1421
+ walkBlocks(context.blocks, context.storyKey, context.basePath, {
1422
+ inline(inline, _blockPath, inlinePath) {
1423
+ if (inline.type !== "bookmark_start" && inline.type !== "bookmark_end") return;
1424
+ const key = `${context.storyKey}:${inline.bookmarkId}`;
1425
+ const previous = candidates.get(key);
1426
+ if (inline.type === "bookmark_start") {
1427
+ candidates.set(key, {
1428
+ ...previous ?? { storyKey: context.storyKey, bookmarkId: inline.bookmarkId },
1429
+ bookmarkName: inline.name,
1430
+ startPath: inlinePath,
1431
+ startSourceRef: inline.sourceRef
1432
+ });
1433
+ return;
1434
+ }
1435
+ candidates.set(key, {
1436
+ ...previous ?? { storyKey: context.storyKey, bookmarkId: inline.bookmarkId },
1437
+ endPath: inlinePath,
1438
+ endSourceRef: inline.sourceRef
1439
+ });
1440
+ }
1441
+ });
1442
+ }
1443
+ for (const candidate of candidates.values()) {
1444
+ if (candidate.startPath === void 0 || candidate.endPath === void 0) continue;
1445
+ targets.push(createBookmarkContentRangeEditableTarget({
1446
+ ...candidate,
1447
+ startPath: candidate.startPath,
1448
+ endPath: candidate.endPath
1449
+ }));
1450
+ }
1451
+ }
1452
+ function createBookmarkContentRangeEditableTarget(candidate) {
1453
+ const startSourceJoinHash = sourceJoinHash([candidate.startSourceRef]);
1454
+ const endSourceJoinHash = sourceJoinHash([candidate.endSourceRef]);
1455
+ const rangeKey = hashText(JSON.stringify({
1456
+ storyKey: candidate.storyKey,
1457
+ bookmarkId: candidate.bookmarkId,
1458
+ bookmarkName: candidate.bookmarkName ?? null,
1459
+ startSourceId: candidate.startSourceRef?.sourceId ?? null,
1460
+ endSourceId: candidate.endSourceRef?.sourceId ?? null
1461
+ }));
1462
+ const targetHash = hashText(`range\0${candidate.bookmarkId}\0${candidate.bookmarkName ?? ""}\0${candidate.startPath}\0${candidate.endPath}`);
1463
+ return {
1464
+ targetKey: `${candidate.storyKey}:bookmark:${candidate.bookmarkId}:content-range`,
1465
+ kind: "bookmark-content-range",
1466
+ storyKey: candidate.storyKey,
1467
+ blockPath: `${candidate.storyKey}/bookmark[${candidate.bookmarkId}]`,
1468
+ leafPath: `${candidate.storyKey}/bookmark[${candidate.bookmarkId}]/content-range`,
1469
+ commandFamily: "link-bookmark",
1470
+ editability: "non-editable",
1471
+ ...candidate.startSourceRef !== void 0 ? { sourceRef: candidate.startSourceRef } : {},
1472
+ link: {
1473
+ bookmarkId: candidate.bookmarkId,
1474
+ ...candidate.bookmarkName !== void 0 ? { bookmarkName: candidate.bookmarkName } : {},
1475
+ rangeKey
1476
+ },
1477
+ canonicalAddress: createCanonicalAddress({
1478
+ addressKind: "bookmark-content-range",
1479
+ storyKey: candidate.storyKey,
1480
+ staleCheckKind: "bookmark",
1481
+ operationScope: "bookmark-range",
1482
+ sourceRefs: [candidate.startSourceRef, candidate.endSourceRef],
1483
+ staleHash: targetHash,
1484
+ rangeBoundary: {
1485
+ boundaryKind: "bookmark-content",
1486
+ ...startSourceJoinHash !== void 0 ? { startSourceJoinHash } : {},
1487
+ ...endSourceJoinHash !== void 0 ? { endSourceJoinHash } : {}
1488
+ },
1489
+ discriminator: {
1490
+ bookmarkId: candidate.bookmarkId,
1491
+ bookmarkName: candidate.bookmarkName ?? null,
1492
+ startSourceId: candidate.startSourceRef?.sourceId ?? null,
1493
+ endSourceId: candidate.endSourceRef?.sourceId ?? null
1494
+ }
1495
+ }),
1496
+ staleCheck: {
1497
+ blockType: "bookmark",
1498
+ targetHash,
1499
+ childCount: 2,
1500
+ ...candidate.startSourceRef !== void 0 ? { sourceRef: candidate.startSourceRef } : {}
1501
+ },
1502
+ posture: { blockers: ["unmodeled-target"] }
1503
+ };
1504
+ }
980
1505
  function inlineObjectKind(inline) {
981
1506
  switch (inline.type) {
982
1507
  case "chart_preview":
@@ -1099,6 +1624,16 @@ function collectParagraphText(paragraph) {
1099
1624
  }
1100
1625
  return text;
1101
1626
  }
1627
+ function blockTextForTargetHash(block) {
1628
+ if (block.type === "paragraph") return collectParagraphText(block);
1629
+ if (block.type === "sdt" || block.type === "custom_xml") {
1630
+ return block.children.map(blockTextForTargetHash).join("");
1631
+ }
1632
+ if (block.type === "table") {
1633
+ return block.rows.flatMap((row) => row.cells).flatMap((cell) => cell.children).map(blockTextForTargetHash).join("");
1634
+ }
1635
+ return "";
1636
+ }
1102
1637
  function inlineTextForTargetHash(inline) {
1103
1638
  if (inline.type === "text") return inline.text;
1104
1639
  if (inline.type === "symbol") return inline.char;
@@ -1114,6 +1649,93 @@ function inlineTextForTargetHash(inline) {
1114
1649
  }
1115
1650
  return "";
1116
1651
  }
1652
+ function createTableTargetCanonicalAddress(table, staleCheckKind, staleHash, resolver = {}) {
1653
+ return createCanonicalAddress({
1654
+ addressKind: "table-target",
1655
+ storyKey: tableStoryKey(table),
1656
+ staleCheckKind,
1657
+ operationScope: table.operationScope,
1658
+ rowRange: table.fragment?.rowRange,
1659
+ columnRange: table.fragment?.columnRange,
1660
+ sourceRefs: [table.sourceRef, table.rowSourceRef, table.cellSourceRef],
1661
+ staleHash,
1662
+ ...resolver,
1663
+ discriminator: {
1664
+ operationScope: table.operationScope,
1665
+ tableDepth: table.tableDepth,
1666
+ rowIndex: table.rowIndex ?? null,
1667
+ columnIndex: table.columnIndex ?? null,
1668
+ cellIndex: table.cellIndex ?? null,
1669
+ gridColumnStart: table.gridColumnStart ?? null,
1670
+ gridSpan: table.gridSpan ?? null,
1671
+ verticalMerge: table.verticalMerge ?? null,
1672
+ sourceId: table.sourceRef?.sourceId ?? null,
1673
+ rowSourceId: table.rowSourceRef?.sourceId ?? null,
1674
+ cellSourceId: table.cellSourceRef?.sourceId ?? null
1675
+ },
1676
+ secondaryStory: table.secondaryStory,
1677
+ nestedTable: table.nestedTable,
1678
+ insideSdt: table.insideSdt
1679
+ });
1680
+ }
1681
+ function tableStoryKey(table) {
1682
+ const suffix = `:${table.tablePath}`;
1683
+ return table.tableKey.endsWith(suffix) ? table.tableKey.slice(0, -suffix.length) : MAIN_STORY_KEY;
1684
+ }
1685
+ function createCanonicalAddress(input) {
1686
+ const sourceHash = sourceJoinHash(input.sourceRefs ?? []);
1687
+ const payload = {
1688
+ addressKind: input.addressKind,
1689
+ storyKey: input.storyKey,
1690
+ operationScope: input.operationScope ?? null,
1691
+ rowRange: input.rowRange ?? null,
1692
+ columnRange: input.columnRange ?? null,
1693
+ sourceHash: sourceHash ?? null,
1694
+ discriminator: input.discriminator
1695
+ };
1696
+ return {
1697
+ addressKey: `editable-address:${hashText(JSON.stringify(payload))}`,
1698
+ addressKind: input.addressKind,
1699
+ storyKey: input.storyKey,
1700
+ staleCheckKind: input.staleCheckKind,
1701
+ ...input.operationScope !== void 0 ? { operationScope: input.operationScope } : {},
1702
+ ...input.rowRange !== void 0 ? { rowRange: input.rowRange } : {},
1703
+ ...input.columnRange !== void 0 ? { columnRange: input.columnRange } : {},
1704
+ ...sourceHash !== void 0 ? { sourceJoinHash: sourceHash } : {},
1705
+ ...input.secondaryStory === true ? { secondaryStory: true } : {},
1706
+ ...input.nestedTable === true ? { nestedTable: true } : {},
1707
+ ...input.insideSdt === true ? { insideSdt: true } : {},
1708
+ resolver: {
1709
+ staleHash: input.staleHash,
1710
+ ...sourceHash !== void 0 ? { sourceJoinHash: sourceHash } : {},
1711
+ ...input.rowRange !== void 0 ? { rowRange: input.rowRange } : {},
1712
+ ...input.columnRange !== void 0 ? { columnRange: input.columnRange } : {},
1713
+ ...input.rangeBoundary !== void 0 ? { rangeBoundary: input.rangeBoundary } : {},
1714
+ ...input.owner !== void 0 ? { owner: input.owner } : {}
1715
+ }
1716
+ };
1717
+ }
1718
+ function ownerRoutingFromAddress(address) {
1719
+ return {
1720
+ addressKey: address.addressKey,
1721
+ addressKind: address.addressKind,
1722
+ storyKey: address.storyKey,
1723
+ ...address.operationScope !== void 0 ? { operationScope: address.operationScope } : {},
1724
+ ...address.sourceJoinHash !== void 0 ? { sourceJoinHash: address.sourceJoinHash } : {},
1725
+ staleHash: address.resolver?.staleHash ?? "",
1726
+ ...address.rowRange !== void 0 ? { rowRange: address.rowRange } : {},
1727
+ ...address.columnRange !== void 0 ? { columnRange: address.columnRange } : {}
1728
+ };
1729
+ }
1730
+ function sourceJoinHashForRefs(...refs) {
1731
+ const sourceHash = sourceJoinHash(refs);
1732
+ return sourceHash === void 0 ? {} : { sourceJoinHash: sourceHash };
1733
+ }
1734
+ function sourceJoinHash(refs) {
1735
+ const sourceIds = refs.map((ref) => ref?.sourceId).filter((sourceId) => sourceId !== void 0);
1736
+ if (sourceIds.length === 0) return void 0;
1737
+ return hashText(sourceIds.join("\0"));
1738
+ }
1117
1739
  function validateEditableTargetRef(value, path = "$") {
1118
1740
  const issues = [];
1119
1741
  const record = asPlainObject(value, path, issues);
@@ -1146,6 +1768,12 @@ function validateEditableTargetRef(value, path = "$") {
1146
1768
  if (record.table !== void 0) {
1147
1769
  validateTargetTable(record.table, `${path}.table`, issues);
1148
1770
  }
1771
+ if (record.editableOwner !== void 0) {
1772
+ validateTargetEditableOwner(record.editableOwner, `${path}.editableOwner`, issues);
1773
+ }
1774
+ if (record.canonicalAddress !== void 0) {
1775
+ validateTargetCanonicalAddress(record.canonicalAddress, `${path}.canonicalAddress`, issues);
1776
+ }
1149
1777
  const staleCheck = asPlainObject(record.staleCheck, `${path}.staleCheck`, issues);
1150
1778
  if (staleCheck) {
1151
1779
  if (staleCheck.paragraphTextHash !== void 0) {
@@ -1288,6 +1916,11 @@ function validateTargetTable(value, path, issues) {
1288
1916
  validateEnum(record.operationScope, EDITABLE_TARGET_TABLE_OPERATION_SCOPES, `${path}.operationScope`, issues);
1289
1917
  expectString(record.tableKey, `${path}.tableKey`, issues);
1290
1918
  expectString(record.tablePath, `${path}.tablePath`, issues);
1919
+ for (const key of ["sourceRef", "rowSourceRef", "cellSourceRef"]) {
1920
+ if (record[key] !== void 0) {
1921
+ validateTargetSourceRef(record[key], `${path}.${key}`, issues);
1922
+ }
1923
+ }
1291
1924
  for (const key of [
1292
1925
  "tableDepth",
1293
1926
  "storyBlockIndex",
@@ -1318,6 +1951,46 @@ function validateTargetTable(value, path, issues) {
1318
1951
  if (record.fragment !== void 0) {
1319
1952
  validateTargetTableFragment(record.fragment, `${path}.fragment`, issues);
1320
1953
  }
1954
+ if (record.cellFragment !== void 0) {
1955
+ validateTargetCellFragment(record.cellFragment, `${path}.cellFragment`, issues);
1956
+ }
1957
+ }
1958
+ function validateTargetEditableOwner(value, path, issues) {
1959
+ const record = asPlainObject(value, path, issues);
1960
+ if (!record) return;
1961
+ expectString(record.targetKey, `${path}.targetKey`, issues);
1962
+ validateEnum(record.kind, EDITABLE_TARGET_KINDS, `${path}.kind`, issues);
1963
+ expectString(record.storyKey, `${path}.storyKey`, issues);
1964
+ expectString(record.blockPath, `${path}.blockPath`, issues);
1965
+ expectString(record.leafPath, `${path}.leafPath`, issues);
1966
+ validateEnum(record.commandFamily, /* @__PURE__ */ new Set(["text-leaf"]), `${path}.commandFamily`, issues);
1967
+ validateEnum(record.reason, /* @__PURE__ */ new Set(["vertical-merge-restart-cell"]), `${path}.reason`, issues);
1968
+ if (record.canonicalAddress !== void 0) {
1969
+ validateTargetOwnerAddressRouting(record.canonicalAddress, `${path}.canonicalAddress`, issues);
1970
+ }
1971
+ if (record.table !== void 0) {
1972
+ validateTargetEditableOwnerTable(record.table, `${path}.table`, issues);
1973
+ }
1974
+ }
1975
+ function validateTargetEditableOwnerTable(value, path, issues) {
1976
+ const record = asPlainObject(value, path, issues);
1977
+ if (!record) return;
1978
+ expectString(record.tableKey, `${path}.tableKey`, issues);
1979
+ expectString(record.tablePath, `${path}.tablePath`, issues);
1980
+ for (const key of ["sourceRef", "rowSourceRef", "cellSourceRef"]) {
1981
+ if (record[key] !== void 0) {
1982
+ validateTargetSourceRef(record[key], `${path}.${key}`, issues);
1983
+ }
1984
+ }
1985
+ for (const key of ["rowIndex", "cellIndex", "gridColumnStart", "gridSpan"]) {
1986
+ const valueForKey = record[key];
1987
+ if (valueForKey !== void 0 && (typeof valueForKey !== "number" || !Number.isInteger(valueForKey) || valueForKey < 0)) {
1988
+ issues.push({ path: `${path}.${key}`, message: "must be a non-negative integer when present." });
1989
+ }
1990
+ }
1991
+ if (record.verticalMerge !== void 0) {
1992
+ validateEnum(record.verticalMerge, /* @__PURE__ */ new Set(["restart", "continue"]), `${path}.verticalMerge`, issues);
1993
+ }
1321
1994
  }
1322
1995
  function validateTargetTableFragment(value, path, issues) {
1323
1996
  const record = asPlainObject(value, path, issues);
@@ -1335,6 +2008,118 @@ function validateTargetTableFragment(value, path, issues) {
1335
2008
  }
1336
2009
  }
1337
2010
  }
2011
+ function validateTargetCellFragment(value, path, issues) {
2012
+ const record = asPlainObject(value, path, issues);
2013
+ if (!record) return;
2014
+ validateSha256(record.fragmentKey, `${path}.fragmentKey`, issues);
2015
+ validateSha256(record.textHash, `${path}.textHash`, issues);
2016
+ const blockCount = record.blockCount;
2017
+ if (typeof blockCount !== "number" || !Number.isInteger(blockCount) || blockCount < 0) {
2018
+ issues.push({ path: `${path}.blockCount`, message: "blockCount must be a non-negative integer." });
2019
+ }
2020
+ if (record.rowRange !== void 0) {
2021
+ validateTargetTableRange(record.rowRange, `${path}.rowRange`, issues);
2022
+ }
2023
+ if (record.columnRange !== void 0) {
2024
+ validateTargetTableRange(record.columnRange, `${path}.columnRange`, issues);
2025
+ }
2026
+ if (record.sourceJoinHash !== void 0) {
2027
+ validateSha256(record.sourceJoinHash, `${path}.sourceJoinHash`, issues);
2028
+ }
2029
+ }
2030
+ function validateTargetCanonicalAddress(value, path, issues) {
2031
+ const record = asPlainObject(value, path, issues);
2032
+ if (!record) return;
2033
+ const addressKey = expectString(record.addressKey, `${path}.addressKey`, issues);
2034
+ if (addressKey && !/^editable-address:[A-Fa-f0-9]{64}$/u.test(addressKey)) {
2035
+ issues.push({ path: `${path}.addressKey`, message: "must be an editable-address SHA-256 key." });
2036
+ }
2037
+ validateEnum(record.addressKind, EDITABLE_TARGET_CANONICAL_ADDRESS_KINDS, `${path}.addressKind`, issues);
2038
+ expectString(record.storyKey, `${path}.storyKey`, issues);
2039
+ validateEnum(record.staleCheckKind, EDITABLE_TARGET_STALE_BLOCK_TYPES, `${path}.staleCheckKind`, issues);
2040
+ if (record.operationScope !== void 0) {
2041
+ validateEnum(record.operationScope, EDITABLE_TARGET_CANONICAL_ADDRESS_OPERATION_SCOPES, `${path}.operationScope`, issues);
2042
+ }
2043
+ if (record.rowRange !== void 0) {
2044
+ validateTargetTableRange(record.rowRange, `${path}.rowRange`, issues);
2045
+ }
2046
+ if (record.columnRange !== void 0) {
2047
+ validateTargetTableRange(record.columnRange, `${path}.columnRange`, issues);
2048
+ }
2049
+ if (record.sourceJoinHash !== void 0) {
2050
+ validateSha256(record.sourceJoinHash, `${path}.sourceJoinHash`, issues);
2051
+ }
2052
+ if (record.resolver !== void 0) {
2053
+ validateTargetCanonicalAddressResolver(record.resolver, `${path}.resolver`, issues);
2054
+ }
2055
+ for (const key of ["secondaryStory", "nestedTable", "insideSdt"]) {
2056
+ if (record[key] !== void 0 && typeof record[key] !== "boolean") {
2057
+ issues.push({ path: `${path}.${key}`, message: "must be a boolean when present." });
2058
+ }
2059
+ }
2060
+ }
2061
+ function validateTargetCanonicalAddressResolver(value, path, issues) {
2062
+ const record = asPlainObject(value, path, issues);
2063
+ if (!record) return;
2064
+ validateSha256(record.staleHash, `${path}.staleHash`, issues);
2065
+ if (record.sourceJoinHash !== void 0) {
2066
+ validateSha256(record.sourceJoinHash, `${path}.sourceJoinHash`, issues);
2067
+ }
2068
+ if (record.rowRange !== void 0) {
2069
+ validateTargetTableRange(record.rowRange, `${path}.rowRange`, issues);
2070
+ }
2071
+ if (record.columnRange !== void 0) {
2072
+ validateTargetTableRange(record.columnRange, `${path}.columnRange`, issues);
2073
+ }
2074
+ if (record.rangeBoundary !== void 0) {
2075
+ validateTargetAddressRangeBoundary(record.rangeBoundary, `${path}.rangeBoundary`, issues);
2076
+ }
2077
+ if (record.owner !== void 0) {
2078
+ validateTargetOwnerAddressRouting(record.owner, `${path}.owner`, issues);
2079
+ }
2080
+ }
2081
+ function validateTargetAddressRangeBoundary(value, path, issues) {
2082
+ const record = asPlainObject(value, path, issues);
2083
+ if (!record) return;
2084
+ validateEnum(record.boundaryKind, EDITABLE_TARGET_ADDRESS_BOUNDARY_KINDS, `${path}.boundaryKind`, issues);
2085
+ for (const key of ["from", "to"]) {
2086
+ const valueForKey = record[key];
2087
+ if (valueForKey !== void 0 && (typeof valueForKey !== "number" || !Number.isInteger(valueForKey) || valueForKey < 0)) {
2088
+ issues.push({ path: `${path}.${key}`, message: "must be a non-negative integer when present." });
2089
+ }
2090
+ }
2091
+ if (typeof record.from === "number" && typeof record.to === "number" && Number.isInteger(record.from) && Number.isInteger(record.to) && record.to < record.from) {
2092
+ issues.push({ path: `${path}.to`, message: "must be greater than or equal to from." });
2093
+ }
2094
+ for (const key of ["startSourceJoinHash", "endSourceJoinHash"]) {
2095
+ if (record[key] !== void 0) {
2096
+ validateSha256(record[key], `${path}.${key}`, issues);
2097
+ }
2098
+ }
2099
+ }
2100
+ function validateTargetOwnerAddressRouting(value, path, issues) {
2101
+ const record = asPlainObject(value, path, issues);
2102
+ if (!record) return;
2103
+ const addressKey = expectString(record.addressKey, `${path}.addressKey`, issues);
2104
+ if (addressKey && !/^editable-address:[A-Fa-f0-9]{64}$/u.test(addressKey)) {
2105
+ issues.push({ path: `${path}.addressKey`, message: "must be an editable-address SHA-256 key." });
2106
+ }
2107
+ validateEnum(record.addressKind, EDITABLE_TARGET_CANONICAL_ADDRESS_KINDS, `${path}.addressKind`, issues);
2108
+ expectString(record.storyKey, `${path}.storyKey`, issues);
2109
+ if (record.operationScope !== void 0) {
2110
+ validateEnum(record.operationScope, EDITABLE_TARGET_CANONICAL_ADDRESS_OPERATION_SCOPES, `${path}.operationScope`, issues);
2111
+ }
2112
+ if (record.sourceJoinHash !== void 0) {
2113
+ validateSha256(record.sourceJoinHash, `${path}.sourceJoinHash`, issues);
2114
+ }
2115
+ validateSha256(record.staleHash, `${path}.staleHash`, issues);
2116
+ if (record.rowRange !== void 0) {
2117
+ validateTargetTableRange(record.rowRange, `${path}.rowRange`, issues);
2118
+ }
2119
+ if (record.columnRange !== void 0) {
2120
+ validateTargetTableRange(record.columnRange, `${path}.columnRange`, issues);
2121
+ }
2122
+ }
1338
2123
  function validateTargetTableRange(value, path, issues) {
1339
2124
  const record = asPlainObject(value, path, issues);
1340
2125
  if (!record) return;
@@ -1361,12 +2146,12 @@ function validateTargetSourceRef(value, path, issues) {
1361
2146
  const record = asPlainObject(value, path, issues);
1362
2147
  if (!record) return;
1363
2148
  expectString(record.sourceId, `${path}.sourceId`, issues);
1364
- for (const key of ["partPath", "storyKind", "element"]) {
2149
+ for (const key of ["partPath", "storyKind", "element", "xmlPath", "tableCellPath"]) {
1365
2150
  if (record[key] !== void 0) {
1366
2151
  expectString(record[key], `${path}.${key}`, issues);
1367
2152
  }
1368
2153
  }
1369
- for (const key of ["ordinal", "startOffset", "endOffset"]) {
2154
+ for (const key of ["ordinal", "startOffset", "endOffset", "tableDepth"]) {
1370
2155
  const numberValue = record[key];
1371
2156
  if (numberValue !== void 0 && (typeof numberValue !== "number" || !Number.isInteger(numberValue) || numberValue < 0)) {
1372
2157
  issues.push({ path: `${path}.${key}`, message: `${key} must be a non-negative integer when present.` });
@@ -1387,8 +2172,12 @@ var EDITABLE_TARGET_KINDS = /* @__PURE__ */ new Set([
1387
2172
  "secondary-story-paragraph-text",
1388
2173
  "textbox-paragraph-text",
1389
2174
  "field-result-text",
2175
+ "field-region-refresh",
2176
+ "toc-region-refresh",
1390
2177
  "hyperlink-text",
2178
+ "hyperlink-destination",
1391
2179
  "bookmark-anchor",
2180
+ "bookmark-content-range",
1392
2181
  "comment-anchor",
1393
2182
  "revision-anchor",
1394
2183
  "object-anchor",
@@ -1439,6 +2228,41 @@ var EDITABLE_TARGET_TABLE_OPERATION_SCOPES = /* @__PURE__ */ new Set([
1439
2228
  "cell",
1440
2229
  "span"
1441
2230
  ]);
2231
+ var EDITABLE_TARGET_CANONICAL_ADDRESS_KINDS = /* @__PURE__ */ new Set([
2232
+ "table-target",
2233
+ "list-item-text",
2234
+ "field-result",
2235
+ "field-region-refresh",
2236
+ "toc-region-refresh",
2237
+ "hyperlink-display-text",
2238
+ "hyperlink-destination",
2239
+ "bookmark-anchor",
2240
+ "bookmark-content-range"
2241
+ ]);
2242
+ var EDITABLE_TARGET_CANONICAL_ADDRESS_OPERATION_SCOPES = /* @__PURE__ */ new Set([
2243
+ "text",
2244
+ "table",
2245
+ "row",
2246
+ "column",
2247
+ "cell",
2248
+ "span",
2249
+ "list-text",
2250
+ "field-refresh",
2251
+ "toc-refresh",
2252
+ "link-destination",
2253
+ "bookmark-range"
2254
+ ]);
2255
+ var EDITABLE_TARGET_ADDRESS_BOUNDARY_KINDS = /* @__PURE__ */ new Set([
2256
+ "table-grid",
2257
+ "cell-fragment",
2258
+ "list-item-text",
2259
+ "field-result",
2260
+ "field-region",
2261
+ "hyperlink-display",
2262
+ "bookmark-content",
2263
+ "hyperlink-destination",
2264
+ "bookmark-anchor"
2265
+ ]);
1442
2266
  function collectCanonicalStoryIdentities(doc) {
1443
2267
  const stories = [
1444
2268
  {
@@ -1804,7 +2628,7 @@ function walkBlocks(blocks, storyKey, basePath, visitor) {
1804
2628
  }
1805
2629
  if (block.type === "paragraph") {
1806
2630
  visitor.paragraph?.(block, blockPath);
1807
- walkInlines(block.children, storyKey, blockPath, `${blockPath}/inline`, visitor);
2631
+ walkInlines(block.children ?? [], storyKey, blockPath, `${blockPath}/inline`, visitor);
1808
2632
  continue;
1809
2633
  }
1810
2634
  if (block.type === "sdt" || block.type === "custom_xml") {
@@ -1841,6 +2665,7 @@ function projectTableLayoutInput(table, storyKey, blockPath) {
1841
2665
  storyKey,
1842
2666
  blockPath,
1843
2667
  ...table.sourceRef !== void 0 ? { sourceRef: table.sourceRef } : {},
2668
+ ...table.styleId !== void 0 ? { styleId: table.styleId } : {},
1844
2669
  rowCount: table.rows.length,
1845
2670
  columnCount: table.gridColumns.length,
1846
2671
  gridColumns: [...table.gridColumns],
@@ -1867,6 +2692,7 @@ function projectTableRowLayoutInput(row, tableKey, rowIndex) {
1867
2692
  });
1868
2693
  return {
1869
2694
  rowKey,
2695
+ ...row.sourceRef !== void 0 ? { sourceRef: row.sourceRef } : {},
1870
2696
  rowIndex,
1871
2697
  cellCount: row.cells.length,
1872
2698
  ...row.gridBefore !== void 0 ? { gridBefore: row.gridBefore } : {},
@@ -1886,6 +2712,7 @@ function projectTableCellLayoutInput(cell, rowKey, rowIndex, cellIndex, gridColu
1886
2712
  const gridSpan = cell.gridSpan ?? 1;
1887
2713
  return {
1888
2714
  cellKey: `${rowKey}:cell[${cellIndex}]`,
2715
+ ...cell.sourceRef !== void 0 ? { sourceRef: cell.sourceRef } : {},
1889
2716
  rowIndex,
1890
2717
  cellIndex,
1891
2718
  gridColumnStart,
@@ -1918,8 +2745,10 @@ function projectDrawingFrameAnchor(node, storyKey, blockPath, inlinePath) {
1918
2745
  const shapeBlocks = content.type === "shape" ? content.txbxBlocks : void 0;
1919
2746
  const objectKind = drawingContentKind(content);
1920
2747
  const sourceRef = node.sourceRef ?? drawingContentSourceRef(content);
2748
+ const objectKey = `${storyKey}:${inlinePath}`;
2749
+ const textBoxBody = projectTextBoxBodyLayoutInput(content, objectKey, sourceRef, `${inlinePath}/txbx`);
1921
2750
  return {
1922
- objectKey: `${storyKey}:${inlinePath}`,
2751
+ objectKey,
1923
2752
  storyKey,
1924
2753
  blockPath,
1925
2754
  inlinePath,
@@ -1949,9 +2778,95 @@ function projectDrawingFrameAnchor(node, storyKey, blockPath, inlinePath) {
1949
2778
  ...content.type === "picture" && content.isLinked !== void 0 ? { isLinked: content.isLinked } : {},
1950
2779
  ...shapeBlocks !== void 0 ? { hasTextBoxBlocks: true } : {},
1951
2780
  ...shapeBlocks !== void 0 ? { textBoxBlockCount: shapeBlocks.length } : {},
2781
+ ...textBoxBody !== void 0 ? { textBoxBody } : {},
1952
2782
  rawXmlPreserved: content.type !== "picture" || content.rawXml !== void 0
1953
2783
  };
1954
2784
  }
2785
+ function projectTextBoxBodyLayoutInput(content, objectKey, sourceRef, basePath) {
2786
+ if (content.type !== "shape") return void 0;
2787
+ if (!content.isTextBox && content.txbxContentXml === void 0 && content.txbxBlocks === void 0) {
2788
+ return void 0;
2789
+ }
2790
+ const bodyKey = `${objectKey}:txbx`;
2791
+ const blockCount = content.txbxBlocks?.length ?? 0;
2792
+ if (content.txbxBlocks === void 0) {
2793
+ return {
2794
+ bodyKey,
2795
+ ...sourceRef !== void 0 ? { sourceRef } : {},
2796
+ status: content.txbxContentXml !== void 0 ? "preserve-only" : "unavailable",
2797
+ unavailableReason: "txbx-blocks-unavailable",
2798
+ ...content.textBoxBody !== void 0 ? { bodyProperties: content.textBoxBody } : {},
2799
+ blockCount,
2800
+ paragraphCount: 0,
2801
+ unsupportedBlockCount: 0,
2802
+ paragraphs: []
2803
+ };
2804
+ }
2805
+ const paragraphs = content.txbxBlocks.flatMap(
2806
+ (block, index) => block.type === "paragraph" ? [projectTextBoxParagraphLayoutInput(block, bodyKey, `${basePath}/block[${index}]`, index)] : []
2807
+ );
2808
+ const unsupportedBlockCount = content.txbxBlocks.length - paragraphs.length;
2809
+ const unavailableReason = content.txbxBlocks.length === 0 ? "empty-body" : paragraphs.length === 0 ? "unsupported-content" : void 0;
2810
+ return {
2811
+ bodyKey,
2812
+ ...sourceRef !== void 0 ? { sourceRef } : {},
2813
+ status: unavailableReason === void 0 ? "modeled" : "unavailable",
2814
+ ...unavailableReason !== void 0 ? { unavailableReason } : {},
2815
+ ...content.textBoxBody !== void 0 ? { bodyProperties: content.textBoxBody } : {},
2816
+ blockCount,
2817
+ paragraphCount: paragraphs.length,
2818
+ unsupportedBlockCount,
2819
+ paragraphs
2820
+ };
2821
+ }
2822
+ function projectTextBoxParagraphLayoutInput(paragraph, bodyKey, blockPath, blockIndex) {
2823
+ const runs = paragraph.children.map(
2824
+ (inline, inlineIndex) => projectTextBoxRunLayoutInput(inline, `${bodyKey}:block[${blockIndex}]`, inlineIndex)
2825
+ );
2826
+ const text = runs.map((run) => run.text ?? "").join("");
2827
+ return {
2828
+ paragraphKey: `${bodyKey}:block[${blockIndex}]`,
2829
+ blockPath,
2830
+ blockIndex,
2831
+ ...paragraph.sourceRef !== void 0 ? { sourceRef: paragraph.sourceRef } : {},
2832
+ ...paragraph.styleId !== void 0 ? { styleId: paragraph.styleId } : {},
2833
+ ...paragraph.alignment !== void 0 ? { alignment: paragraph.alignment } : {},
2834
+ ...paragraph.borders !== void 0 ? { borders: paragraph.borders } : {},
2835
+ text,
2836
+ textLength: Array.from(text).length,
2837
+ runCount: runs.length,
2838
+ runs
2839
+ };
2840
+ }
2841
+ function projectTextBoxRunLayoutInput(inline, paragraphKey, inlineIndex) {
2842
+ const runKey = `${paragraphKey}:inline[${inlineIndex}]`;
2843
+ if (inline.type === "text") {
2844
+ return {
2845
+ runKey,
2846
+ inlineIndex,
2847
+ kind: "text",
2848
+ text: inline.text,
2849
+ textLength: Array.from(inline.text).length,
2850
+ ...inline.marks !== void 0 ? { marks: inline.marks } : {}
2851
+ };
2852
+ }
2853
+ if (inline.type === "tab") {
2854
+ return { runKey, inlineIndex, kind: "tab", text: " ", textLength: 1 };
2855
+ }
2856
+ if (inline.type === "hard_break") {
2857
+ return { runKey, inlineIndex, kind: "hard-break", text: "\n", textLength: 1 };
2858
+ }
2859
+ if (inline.type === "symbol") {
2860
+ return {
2861
+ runKey,
2862
+ inlineIndex,
2863
+ kind: "symbol",
2864
+ text: inline.char,
2865
+ textLength: Array.from(inline.char).length
2866
+ };
2867
+ }
2868
+ return { runKey, inlineIndex, kind: "unsupported" };
2869
+ }
1955
2870
  function projectLegacyImageAnchor(doc, node, storyKey, blockPath, inlinePath) {
1956
2871
  const media = doc.media.items[node.mediaId];
1957
2872
  return {
@@ -2142,6 +3057,7 @@ export {
2142
3057
  createNoteStoryKey,
2143
3058
  collectCanonicalLayoutInputs,
2144
3059
  collectEditableTargetRefs,
3060
+ createEditableTargetBlockCache,
2145
3061
  validateEditableTargetRef,
2146
3062
  collectCanonicalFieldRegionIdentities,
2147
3063
  createCanonicalFieldId,