@beyondwork/docx-react-component 1.0.134 → 1.0.136

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 (89) hide show
  1. package/dist/api/public-types.cjs +20 -2
  2. package/dist/api/public-types.d.cts +2 -2
  3. package/dist/api/public-types.d.ts +2 -2
  4. package/dist/api/public-types.js +2 -2
  5. package/dist/api/v3.cjs +203 -41
  6. package/dist/api/v3.d.cts +3 -3
  7. package/dist/api/v3.d.ts +3 -3
  8. package/dist/api/v3.js +4 -4
  9. package/dist/{canonical-document-CfZIc-fC.d.cts → canonical-document-COmM7v11.d.cts} +1 -1
  10. package/dist/{canonical-document-CfZIc-fC.d.ts → canonical-document-COmM7v11.d.ts} +1 -1
  11. package/dist/{chunk-REFHJ2FN.js → chunk-2BNXARVO.js} +3 -3
  12. package/dist/{chunk-INLRCC4N.js → chunk-4CIHTMCH.js} +2 -2
  13. package/dist/{chunk-MQ5GAJ54.js → chunk-BJXSMPHD.js} +1 -1
  14. package/dist/{chunk-XBQFDBXE.js → chunk-EZFF6GKF.js} +9 -2
  15. package/dist/{chunk-3YR47WTD.js → chunk-FGJTOFZY.js} +21 -9
  16. package/dist/{chunk-74R5B2EZ.js → chunk-H4HI6RUE.js} +1 -1
  17. package/dist/{chunk-IJD6D7HU.js → chunk-HUWZ7AHE.js} +125 -2
  18. package/dist/{chunk-7Y6JCIK3.js → chunk-HWMPNLEF.js} +1 -1
  19. package/dist/{chunk-EBSI6VQX.js → chunk-JZZKTL7K.js} +800 -93
  20. package/dist/{chunk-VA24T4EB.js → chunk-NEMOQ4QR.js} +1 -1
  21. package/dist/{chunk-ESEEWELA.js → chunk-NX7W6T7L.js} +171 -39
  22. package/dist/{chunk-O4EDZR44.js → chunk-P7XDEVS6.js} +12 -1
  23. package/dist/{chunk-QTRJLKR2.js → chunk-TSNK4ECL.js} +1 -1
  24. package/dist/{chunk-WDDFU2N2.js → chunk-UR2LW63N.js} +1 -1
  25. package/dist/compare.d.cts +1 -1
  26. package/dist/compare.d.ts +1 -1
  27. package/dist/core/commands/formatting-commands.d.cts +2 -2
  28. package/dist/core/commands/formatting-commands.d.ts +2 -2
  29. package/dist/core/commands/image-commands.cjs +9 -2
  30. package/dist/core/commands/image-commands.d.cts +2 -2
  31. package/dist/core/commands/image-commands.d.ts +2 -2
  32. package/dist/core/commands/image-commands.js +4 -4
  33. package/dist/core/commands/section-layout-commands.d.cts +2 -2
  34. package/dist/core/commands/section-layout-commands.d.ts +2 -2
  35. package/dist/core/commands/style-commands.d.cts +2 -2
  36. package/dist/core/commands/style-commands.d.ts +2 -2
  37. package/dist/core/commands/table-structure-commands.cjs +9 -2
  38. package/dist/core/commands/table-structure-commands.d.cts +2 -2
  39. package/dist/core/commands/table-structure-commands.d.ts +2 -2
  40. package/dist/core/commands/table-structure-commands.js +3 -3
  41. package/dist/core/commands/text-commands.cjs +9 -2
  42. package/dist/core/commands/text-commands.d.cts +2 -2
  43. package/dist/core/commands/text-commands.d.ts +2 -2
  44. package/dist/core/commands/text-commands.js +4 -4
  45. package/dist/core/selection/mapping.d.cts +2 -2
  46. package/dist/core/selection/mapping.d.ts +2 -2
  47. package/dist/core/state/editor-state.d.cts +2 -2
  48. package/dist/core/state/editor-state.d.ts +2 -2
  49. package/dist/index.cjs +1287 -198
  50. package/dist/index.d.cts +5 -5
  51. package/dist/index.d.ts +5 -5
  52. package/dist/index.js +135 -34
  53. package/dist/io/docx-session.d.cts +4 -4
  54. package/dist/io/docx-session.d.ts +4 -4
  55. package/dist/legal.d.cts +1 -1
  56. package/dist/legal.d.ts +1 -1
  57. package/dist/{loader-CK3lZy4h.d.cts → loader-Cr35kVUi.d.cts} +3 -3
  58. package/dist/{loader-CQXplstv.d.ts → loader-uGY6nDZP.d.ts} +3 -3
  59. package/dist/{public-types-DXNZVKrS.d.ts → public-types-8kVIB5HW.d.ts} +22 -8
  60. package/dist/{public-types-BR1SYK2F.d.cts → public-types-CSSH2Whc.d.cts} +22 -8
  61. package/dist/public-types.cjs +20 -2
  62. package/dist/public-types.d.cts +2 -2
  63. package/dist/public-types.d.ts +2 -2
  64. package/dist/public-types.js +2 -2
  65. package/dist/runtime/collab.d.cts +3 -3
  66. package/dist/runtime/collab.d.ts +3 -3
  67. package/dist/runtime/document-runtime.cjs +929 -83
  68. package/dist/runtime/document-runtime.d.cts +2 -2
  69. package/dist/runtime/document-runtime.d.ts +2 -2
  70. package/dist/runtime/document-runtime.js +10 -10
  71. package/dist/{session-CSbwkgII.d.cts → session-Beg8ihOi.d.cts} +3 -3
  72. package/dist/{session-C9UjrhJF.d.ts → session-Dgp-2uYw.d.ts} +3 -3
  73. package/dist/session.d.cts +5 -5
  74. package/dist/session.d.ts +5 -5
  75. package/dist/tailwind.cjs +27 -8
  76. package/dist/tailwind.d.cts +2 -2
  77. package/dist/tailwind.d.ts +2 -2
  78. package/dist/tailwind.js +5 -5
  79. package/dist/{types-RzkCXDNV.d.ts → types-Cin_abw3.d.ts} +2 -2
  80. package/dist/{types-CZtAueri.d.cts → types-qsS39ZkQ.d.cts} +2 -2
  81. package/dist/ui-tailwind/editor-surface/search-plugin.cjs +11 -0
  82. package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +3 -3
  83. package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +3 -3
  84. package/dist/ui-tailwind/editor-surface/search-plugin.js +3 -3
  85. package/dist/ui-tailwind.cjs +27 -8
  86. package/dist/ui-tailwind.d.cts +3 -3
  87. package/dist/ui-tailwind.d.ts +3 -3
  88. package/dist/ui-tailwind.js +5 -5
  89. package/package.json +1 -1
@@ -22,7 +22,7 @@ import {
22
22
  insertText,
23
23
  outdentParagraphAtSelection,
24
24
  splitParagraph
25
- } from "./chunk-REFHJ2FN.js";
25
+ } from "./chunk-2BNXARVO.js";
26
26
  import {
27
27
  applyFormattingOperationToDocument,
28
28
  applyTextMarkOperationToDocumentRange,
@@ -32,23 +32,23 @@ import {
32
32
  insertImage,
33
33
  repositionFloatingImage,
34
34
  resizeImage
35
- } from "./chunk-INLRCC4N.js";
35
+ } from "./chunk-4CIHTMCH.js";
36
36
  import {
37
37
  applyTextTransaction
38
- } from "./chunk-MQ5GAJ54.js";
38
+ } from "./chunk-BJXSMPHD.js";
39
39
  import {
40
40
  applyTableStructureOperationForEditableTarget,
41
41
  removeCellFromRow,
42
42
  removeTableRowPure
43
- } from "./chunk-WDDFU2N2.js";
43
+ } from "./chunk-UR2LW63N.js";
44
44
  import {
45
45
  resolveParagraphScope
46
- } from "./chunk-QTRJLKR2.js";
46
+ } from "./chunk-TSNK4ECL.js";
47
47
  import {
48
48
  buildGeometryDebugEntry,
49
49
  collectLineBoxesForRegion,
50
50
  createGeometryFacet
51
- } from "./chunk-74R5B2EZ.js";
51
+ } from "./chunk-H4HI6RUE.js";
52
52
  import {
53
53
  AI_ACTION_POLICIES,
54
54
  allocateNumberingInstance,
@@ -72,6 +72,7 @@ import {
72
72
  findTextWithStyleMatches,
73
73
  getListKind,
74
74
  inlineLengthForScopeCoordinates,
75
+ mergeFragmentNumberingCatalog,
75
76
  rebuildFieldRegistry,
76
77
  removeScopeMarkersFromBlockList,
77
78
  replaceParagraphChildrenAtPath,
@@ -83,7 +84,7 @@ import {
83
84
  sameScopeParagraphPath,
84
85
  serializeFragmentToWordML,
85
86
  setStartOverride
86
- } from "./chunk-IJD6D7HU.js";
87
+ } from "./chunk-HUWZ7AHE.js";
87
88
  import {
88
89
  ISSUE_METADATA_ID,
89
90
  LAYOUT_ENGINE_VERSION,
@@ -121,7 +122,7 @@ import {
121
122
  setWorkspaceMode,
122
123
  setZoomLevel,
123
124
  snapCommentAnchorAwayFromTable
124
- } from "./chunk-O4EDZR44.js";
125
+ } from "./chunk-P7XDEVS6.js";
125
126
  import {
126
127
  countLogicalPositions,
127
128
  createPlainText,
@@ -141,7 +142,7 @@ import {
141
142
  replaceStoryBlocks,
142
143
  resolvePageFieldDisplayText,
143
144
  storyTargetKey
144
- } from "./chunk-XBQFDBXE.js";
145
+ } from "./chunk-EZFF6GKF.js";
145
146
  import {
146
147
  createCommentSidebarProjection,
147
148
  createCommentStoreFromRuntimeComments
@@ -1195,7 +1196,7 @@ function splitListParagraph(document, paragraphIndex, paragraphIsEmpty, context,
1195
1196
  action: "split"
1196
1197
  };
1197
1198
  }
1198
- const target = paragraphs[resolvedParagraphIndex];
1199
+ const target = paragraphs[resolvedParagraphIndex]?.paragraph;
1199
1200
  if (!target?.numbering) {
1200
1201
  return {
1201
1202
  document: working,
@@ -1247,7 +1248,7 @@ function backspaceAtListStart(document, paragraphIndex, context, options = {}) {
1247
1248
  handled: false
1248
1249
  };
1249
1250
  }
1250
- const target = paragraphs[resolvedParagraphIndex];
1251
+ const target = paragraphs[resolvedParagraphIndex]?.paragraph;
1251
1252
  if (!target?.numbering) {
1252
1253
  return {
1253
1254
  document: working,
@@ -1293,7 +1294,7 @@ function restartNumbering(document, paragraphIndex, context, startAt = 1, option
1293
1294
  affectedParagraphIndexes: []
1294
1295
  };
1295
1296
  }
1296
- const target = paragraphs[resolvedParagraphIndex];
1297
+ const target = paragraphs[resolvedParagraphIndex]?.paragraph;
1297
1298
  if (!target?.numbering) {
1298
1299
  return {
1299
1300
  document: working,
@@ -1315,8 +1316,13 @@ function restartNumbering(document, paragraphIndex, context, startAt = 1, option
1315
1316
  );
1316
1317
  setStartOverride(catalog, numberingInstanceId, target.numbering.level, startAt);
1317
1318
  const affectedParagraphIndexes = [];
1319
+ const targetStoryKey = paragraphs[resolvedParagraphIndex]?.storyKey;
1318
1320
  for (let index = resolvedParagraphIndex; index < paragraphs.length; index += 1) {
1319
- const paragraph = paragraphs[index];
1321
+ const entry = paragraphs[index];
1322
+ if (entry?.storyKey !== targetStoryKey) {
1323
+ break;
1324
+ }
1325
+ const paragraph = entry.paragraph;
1320
1326
  if (!paragraph?.numbering) {
1321
1327
  break;
1322
1328
  }
@@ -1360,7 +1366,7 @@ function continueNumbering(document, paragraphIndex, context, options = {}) {
1360
1366
  affectedParagraphIndexes: []
1361
1367
  };
1362
1368
  }
1363
- const target = paragraphs[resolvedParagraphIndex];
1369
+ const target = paragraphs[resolvedParagraphIndex]?.paragraph;
1364
1370
  if (!target?.numbering) {
1365
1371
  return {
1366
1372
  document: working,
@@ -1389,8 +1395,13 @@ function continueNumbering(document, paragraphIndex, context, options = {}) {
1389
1395
  };
1390
1396
  }
1391
1397
  const affectedParagraphIndexes = [];
1398
+ const targetStoryKey = paragraphs[resolvedParagraphIndex]?.storyKey;
1392
1399
  for (let index = resolvedParagraphIndex; index < paragraphs.length; index += 1) {
1393
- const paragraph = paragraphs[index];
1400
+ const entry = paragraphs[index];
1401
+ if (entry?.storyKey !== targetStoryKey) {
1402
+ break;
1403
+ }
1404
+ const paragraph = entry.paragraph;
1394
1405
  if (!paragraph?.numbering) {
1395
1406
  break;
1396
1407
  }
@@ -1436,12 +1447,13 @@ function toggleListKind(document, paragraphIndexes, kind, context, options) {
1436
1447
  }
1437
1448
  const catalog = cloneNumberingCatalog(working.numbering);
1438
1449
  const allAlreadyKind = normalizedIndexes.every((index) => {
1439
- const paragraph = paragraphs[index];
1440
- return paragraph.numbering ? getListKind(catalog, paragraph.numbering.numberingInstanceId) === kind : false;
1450
+ const paragraph = paragraphs[index]?.paragraph;
1451
+ return paragraph?.numbering ? getListKind(catalog, paragraph.numbering.numberingInstanceId) === kind : false;
1441
1452
  });
1442
1453
  if (allAlreadyKind) {
1443
1454
  for (const index of normalizedIndexes) {
1444
- delete paragraphs[index].numbering;
1455
+ const paragraph = paragraphs[index]?.paragraph;
1456
+ if (paragraph) delete paragraph.numbering;
1445
1457
  }
1446
1458
  working.numbering = catalog;
1447
1459
  return {
@@ -1451,7 +1463,8 @@ function toggleListKind(document, paragraphIndexes, kind, context, options) {
1451
1463
  }
1452
1464
  const numberingInstanceId = findAdjacentCompatibleInstance(paragraphs, catalog, normalizedIndexes[0], kind) ?? ensureDefaultListInstance(catalog, kind);
1453
1465
  for (const index of normalizedIndexes) {
1454
- const paragraph = paragraphs[index];
1466
+ const paragraph = paragraphs[index]?.paragraph;
1467
+ if (!paragraph) continue;
1455
1468
  paragraph.numbering = {
1456
1469
  numberingInstanceId,
1457
1470
  level: clampLevel(paragraph.numbering?.level ?? 0)
@@ -1482,10 +1495,11 @@ function adjustListLevels(document, paragraphIndexes, delta, context, options) {
1482
1495
  };
1483
1496
  }
1484
1497
  const affectedParagraphIndexes = resolved.paragraphIndexes.filter(
1485
- (index) => Boolean(paragraphs[index]?.numbering)
1498
+ (index) => Boolean(paragraphs[index]?.paragraph.numbering)
1486
1499
  );
1487
1500
  for (const index of affectedParagraphIndexes) {
1488
- const paragraph = paragraphs[index];
1501
+ const paragraph = paragraphs[index]?.paragraph;
1502
+ if (!paragraph) continue;
1489
1503
  if (!paragraph.numbering) {
1490
1504
  continue;
1491
1505
  }
@@ -1505,17 +1519,21 @@ function normalizeListCommandTargets(options) {
1505
1519
  }
1506
1520
  function resolveListCommandParagraphIndexes(document, paragraphs, paragraphIndexes, context, editableTargets) {
1507
1521
  if (editableTargets.length === 0) {
1508
- return { paragraphIndexes: normalizeParagraphIndexes(paragraphs, paragraphIndexes) };
1522
+ return {
1523
+ paragraphIndexes: normalizeParagraphIndexesForStory(
1524
+ paragraphs,
1525
+ paragraphIndexes,
1526
+ context.activeStoryKey
1527
+ )
1528
+ };
1509
1529
  }
1510
1530
  const currentTargets = collectEditableTargetRefs(document, context.editableTargetCache);
1511
- const paragraphIndexByTargetKey = /* @__PURE__ */ new Map();
1512
- let paragraphIndex = 0;
1513
- for (const target of currentTargets) {
1514
- if (!isParagraphTextTarget(target)) continue;
1515
- if (!paragraphIndexByTargetKey.has(target.targetKey)) {
1516
- paragraphIndexByTargetKey.set(target.targetKey, paragraphIndex);
1517
- paragraphIndex += 1;
1518
- }
1531
+ const paragraphIndexByAddress = /* @__PURE__ */ new Map();
1532
+ for (let index = 0; index < paragraphs.length; index += 1) {
1533
+ const entry = paragraphs[index];
1534
+ if (!entry) continue;
1535
+ paragraphIndexByAddress.set(`${entry.storyKey}
1536
+ ${entry.blockPath}`, index);
1519
1537
  }
1520
1538
  const resolvedIndexes = [];
1521
1539
  for (const target of editableTargets) {
@@ -1540,7 +1558,8 @@ function resolveListCommandParagraphIndexes(document, paragraphs, paragraphIndex
1540
1558
  }
1541
1559
  };
1542
1560
  }
1543
- const currentIndex = paragraphIndexByTargetKey.get(current.targetKey);
1561
+ const currentIndex = paragraphIndexByAddress.get(`${current.storyKey}
1562
+ ${current.blockPath}`);
1544
1563
  if (currentIndex === void 0) {
1545
1564
  return {
1546
1565
  paragraphIndexes: [],
@@ -1615,18 +1634,28 @@ function sortJson(value) {
1615
1634
  return value;
1616
1635
  }
1617
1636
  function findAdjacentCompatibleInstance(paragraphs, catalog, fromIndex, kind) {
1637
+ const current = paragraphs[fromIndex];
1618
1638
  const previous = paragraphs[fromIndex - 1];
1619
- if (previous?.numbering) {
1620
- const previousKind = getListKind(catalog, previous.numbering.numberingInstanceId);
1639
+ if (previous?.storyKey !== current?.storyKey) {
1640
+ return void 0;
1641
+ }
1642
+ const previousParagraph = previous?.paragraph;
1643
+ if (previousParagraph?.numbering) {
1644
+ const previousKind = getListKind(catalog, previousParagraph.numbering.numberingInstanceId);
1621
1645
  if (previousKind === kind) {
1622
- return previous.numbering.numberingInstanceId;
1646
+ return previousParagraph.numbering.numberingInstanceId;
1623
1647
  }
1624
1648
  }
1625
1649
  return void 0;
1626
1650
  }
1627
1651
  function findPreviousCompatibleInstance(paragraphs, catalog, fromIndex, kind) {
1652
+ const storyKey = paragraphs[fromIndex]?.storyKey;
1628
1653
  for (let index = fromIndex - 1; index >= 0; index -= 1) {
1629
- const paragraph = paragraphs[index];
1654
+ const entry = paragraphs[index];
1655
+ if (entry?.storyKey !== storyKey) {
1656
+ break;
1657
+ }
1658
+ const paragraph = entry.paragraph;
1630
1659
  if (!paragraph?.numbering) {
1631
1660
  continue;
1632
1661
  }
@@ -1645,7 +1674,14 @@ function cloneEnvelope(document, timestamp) {
1645
1674
  function captureEditableParagraphs(document) {
1646
1675
  if (isDocumentRoot(document.content)) {
1647
1676
  const paragraphs = [];
1648
- collectEditableParagraphs(document.content.children, paragraphs);
1677
+ for (const context of collectStoryBlockContexts(document)) {
1678
+ collectEditableParagraphs(
1679
+ context.blocks,
1680
+ paragraphs,
1681
+ context.storyKey,
1682
+ context.basePath
1683
+ );
1684
+ }
1649
1685
  return paragraphs;
1650
1686
  }
1651
1687
  const fallback = {
@@ -1653,23 +1689,39 @@ function captureEditableParagraphs(document) {
1653
1689
  children: [{ type: "paragraph", children: [] }]
1654
1690
  };
1655
1691
  document.content = fallback;
1656
- return fallback.children;
1657
- }
1658
- function collectEditableParagraphs(blocks, output) {
1659
- for (const block of blocks) {
1692
+ return [{
1693
+ paragraph: fallback.children[0],
1694
+ storyKey: "main",
1695
+ blockPath: "main/block[0]"
1696
+ }];
1697
+ }
1698
+ function collectEditableParagraphs(blocks, output, storyKey, basePath) {
1699
+ for (let blockIndex = 0; blockIndex < blocks.length; blockIndex += 1) {
1700
+ const block = blocks[blockIndex];
1701
+ if (!block) continue;
1702
+ const blockPath = `${basePath}/block[${blockIndex}]`;
1660
1703
  switch (block.type) {
1661
1704
  case "paragraph":
1662
- output.push(block);
1705
+ output.push({ paragraph: block, storyKey, blockPath });
1663
1706
  break;
1664
1707
  case "table":
1665
- for (const row2 of block.rows) {
1666
- for (const cell of row2.cells) {
1667
- collectEditableParagraphs(cell.children, output);
1708
+ for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex += 1) {
1709
+ const row2 = block.rows[rowIndex];
1710
+ if (!row2) continue;
1711
+ for (let cellIndex = 0; cellIndex < row2.cells.length; cellIndex += 1) {
1712
+ const cell = row2.cells[cellIndex];
1713
+ if (!cell) continue;
1714
+ collectEditableParagraphs(
1715
+ cell.children,
1716
+ output,
1717
+ storyKey,
1718
+ `${blockPath}/row[${rowIndex}]/cell[${cellIndex}]`
1719
+ );
1668
1720
  }
1669
1721
  }
1670
1722
  break;
1671
1723
  case "sdt":
1672
- collectEditableParagraphs(block.children, output);
1724
+ collectEditableParagraphs(block.children, output, storyKey, blockPath);
1673
1725
  break;
1674
1726
  case "custom_xml":
1675
1727
  break;
@@ -1681,6 +1733,18 @@ function collectEditableParagraphs(blocks, output) {
1681
1733
  function normalizeParagraphIndexes(paragraphs, paragraphIndexes) {
1682
1734
  return [...new Set(paragraphIndexes)].filter((index) => Number.isInteger(index) && index >= 0 && index < paragraphs.length).sort((left, right) => left - right);
1683
1735
  }
1736
+ function normalizeParagraphIndexesForStory(paragraphs, paragraphIndexes, storyKey) {
1737
+ if (storyKey === void 0) {
1738
+ return normalizeParagraphIndexes(paragraphs, paragraphIndexes);
1739
+ }
1740
+ const storyParagraphIndexes = [];
1741
+ for (let index = 0; index < paragraphs.length; index += 1) {
1742
+ if (paragraphs[index]?.storyKey === storyKey) {
1743
+ storyParagraphIndexes.push(index);
1744
+ }
1745
+ }
1746
+ return [...new Set(paragraphIndexes)].filter((index) => Number.isInteger(index) && index >= 0 && index < storyParagraphIndexes.length).map((index) => storyParagraphIndexes[index]).sort((left, right) => left - right);
1747
+ }
1684
1748
  function clampLevel(level) {
1685
1749
  return Math.max(0, Math.min(8, level));
1686
1750
  }
@@ -1825,8 +1889,9 @@ function applyFragmentInsert(document, selection, fragment, context) {
1825
1889
  workingDocument = collapseResult.document;
1826
1890
  workingSelection = collapseResult.selection;
1827
1891
  if (context.textTarget?.kind === "table-paragraph" || context.textTarget?.kind === "text-leaf") {
1892
+ const { precomputedSurface: _precomputedSurface, ...contextWithoutPrecomputedSurface } = context;
1828
1893
  workingContext = {
1829
- ...context,
1894
+ ...contextWithoutPrecomputedSurface,
1830
1895
  textTarget: {
1831
1896
  ...context.textTarget,
1832
1897
  paragraphEnd: Math.max(
@@ -1838,7 +1903,11 @@ function applyFragmentInsert(document, selection, fragment, context) {
1838
1903
  }
1839
1904
  }
1840
1905
  const splitResult = splitParagraph(workingDocument, workingSelection, workingContext);
1841
- const splitRoot = splitResult.document.content;
1906
+ const preparedFragment = prepareFragmentNumberingForInsertion(
1907
+ splitResult.document,
1908
+ fragment
1909
+ );
1910
+ const splitRoot = preparedFragment.document.content;
1842
1911
  if (!splitRoot || splitRoot.type !== "doc") {
1843
1912
  return {
1844
1913
  changed: false,
@@ -1849,9 +1918,9 @@ function applyFragmentInsert(document, selection, fragment, context) {
1849
1918
  const targetedBlockPath = workingContext.textTarget?.kind === "table-paragraph" || workingContext.textTarget?.kind === "text-leaf" ? workingContext.textTarget.blockPath : void 0;
1850
1919
  if (targetedBlockPath) {
1851
1920
  const targeted = insertFragmentBlocksAfterPath(
1852
- splitResult.document,
1921
+ preparedFragment.document,
1853
1922
  targetedBlockPath,
1854
- fragment.blocks
1923
+ preparedFragment.blocks
1855
1924
  );
1856
1925
  if (targeted) {
1857
1926
  return {
@@ -1883,7 +1952,7 @@ function applyFragmentInsert(document, selection, fragment, context) {
1883
1952
  const rightHalfIndex = scope.blockIndex + 1;
1884
1953
  const splicedChildren = [
1885
1954
  ...splitRoot.children.slice(0, rightHalfIndex),
1886
- ...fragment.blocks.map((block) => cloneBlock(block)),
1955
+ ...preparedFragment.blocks.map((block) => cloneBlock(block)),
1887
1956
  ...splitRoot.children.slice(rightHalfIndex)
1888
1957
  ];
1889
1958
  const nextRoot = {
@@ -1891,7 +1960,7 @@ function applyFragmentInsert(document, selection, fragment, context) {
1891
1960
  children: splicedChildren
1892
1961
  };
1893
1962
  const nextDocument = {
1894
- ...splitResult.document,
1963
+ ...preparedFragment.document,
1895
1964
  updatedAt: context.timestamp,
1896
1965
  content: nextRoot
1897
1966
  };
@@ -1903,14 +1972,47 @@ function applyFragmentInsert(document, selection, fragment, context) {
1903
1972
  mapping: createEmptyMapping()
1904
1973
  };
1905
1974
  }
1906
- function cloneBlock(block) {
1907
- if (block.type === "paragraph") {
1908
- return {
1909
- ...block,
1910
- children: block.children.map((child) => ({ ...child }))
1975
+ function prepareFragmentNumberingForInsertion(document, fragment) {
1976
+ if (!fragment.numbering) {
1977
+ return { document, blocks: fragment.blocks };
1978
+ }
1979
+ const merged = mergeFragmentNumberingCatalog(document.numbering, fragment.numbering);
1980
+ return {
1981
+ document: {
1982
+ ...document,
1983
+ numbering: merged.catalog
1984
+ },
1985
+ blocks: fragment.blocks.map((block) => cloneBlock(block, merged.instanceIdMap))
1986
+ };
1987
+ }
1988
+ function cloneBlock(block, numberingInstanceIdMap) {
1989
+ const cloned = structuredClone(block);
1990
+ remapNumberingReferences(cloned, numberingInstanceIdMap);
1991
+ return cloned;
1992
+ }
1993
+ function remapNumberingReferences(value, numberingInstanceIdMap) {
1994
+ if (!numberingInstanceIdMap?.size || !value || typeof value !== "object") {
1995
+ return;
1996
+ }
1997
+ if (Array.isArray(value)) {
1998
+ for (const entry of value) {
1999
+ remapNumberingReferences(entry, numberingInstanceIdMap);
2000
+ }
2001
+ return;
2002
+ }
2003
+ const record = value;
2004
+ if (record.numbering?.numberingInstanceId) {
2005
+ const mappedId = numberingInstanceIdMap.get(record.numbering.numberingInstanceId) ?? record.numbering.numberingInstanceId;
2006
+ record.numbering = {
2007
+ ...record.numbering,
2008
+ numberingInstanceId: mappedId
1911
2009
  };
1912
2010
  }
1913
- return JSON.parse(JSON.stringify(block));
2011
+ remapNumberingReferences(record.children, numberingInstanceIdMap);
2012
+ remapNumberingReferences(record.rows, numberingInstanceIdMap);
2013
+ remapNumberingReferences(record.cells, numberingInstanceIdMap);
2014
+ remapNumberingReferences(record.txbxBlocks, numberingInstanceIdMap);
2015
+ remapNumberingReferences(record.content, numberingInstanceIdMap);
1914
2016
  }
1915
2017
  function insertFragmentBlocksAfterPath(document, blockPath, fragmentBlocks) {
1916
2018
  const tokens = parseCanonicalBlockPath(blockPath);
@@ -7402,6 +7504,16 @@ function coerceIssueValue(value) {
7402
7504
  function insertScopeMarkers(document, params) {
7403
7505
  const { scopeId } = params;
7404
7506
  const root = document.content;
7507
+ if (!Number.isFinite(params.from) || !Number.isFinite(params.to)) {
7508
+ const from = Number.isFinite(params.from) ? params.from : 0;
7509
+ const to = Number.isFinite(params.to) ? params.to : from;
7510
+ return {
7511
+ status: "non-finite-range",
7512
+ scopeId,
7513
+ from,
7514
+ to
7515
+ };
7516
+ }
7405
7517
  const normalizedFrom = Math.min(params.from, params.to);
7406
7518
  const normalizedTo = Math.max(params.from, params.to);
7407
7519
  if (!root || root.type !== "doc" || root.children.length === 0) {
@@ -7854,6 +7966,14 @@ function isRecord(value) {
7854
7966
  }
7855
7967
 
7856
7968
  // src/runtime/workflow/coordinator.ts
7969
+ function createScopeMarkerMutationMapping() {
7970
+ return {
7971
+ steps: [],
7972
+ metadata: {
7973
+ layoutNeutralScopeMarkers: true
7974
+ }
7975
+ };
7976
+ }
7857
7977
  var MODE_RESTRICTIVENESS = {
7858
7978
  edit: 0,
7859
7979
  suggest: 1,
@@ -8161,6 +8281,60 @@ function createWorkflowCoordinator(deps) {
8161
8281
  activeStory: deps.getActiveStory()
8162
8282
  };
8163
8283
  }
8284
+ function createPlantFailureResult(input) {
8285
+ const { scopeId, anchor, assoc, plantResult } = input;
8286
+ return {
8287
+ scopeId: "",
8288
+ anchor: {
8289
+ kind: "range",
8290
+ from: anchor.from,
8291
+ to: anchor.to,
8292
+ assoc
8293
+ },
8294
+ plantStatus: {
8295
+ planted: false,
8296
+ reason: plantResult.status,
8297
+ ...plantResult.status === "non-paragraph-target" ? {
8298
+ blockIndex: plantResult.blockIndex,
8299
+ blockKind: plantResult.blockKind
8300
+ } : {},
8301
+ ...plantResult.status === "range-out-of-bounds" ? { storyLength: plantResult.storyLength } : {},
8302
+ requestedFrom: plantResult.from,
8303
+ requestedTo: plantResult.to
8304
+ }
8305
+ };
8306
+ }
8307
+ function buildWorkflowScope(input) {
8308
+ const { params, scopeId, publicAnchor } = input;
8309
+ return {
8310
+ scopeId,
8311
+ mode: params.mode ?? "comment",
8312
+ anchor: publicAnchor,
8313
+ ...params.storyTarget ? { storyTarget: params.storyTarget } : {},
8314
+ ...params.label ? { label: params.label } : {},
8315
+ ...params.visibility ? { visibility: params.visibility } : {},
8316
+ ...params.guardPolicy ? { guardPolicy: params.guardPolicy } : {},
8317
+ ...params.scopeMetadataFields && params.scopeMetadataFields.length > 0 ? { metadata: [...params.scopeMetadataFields] } : {}
8318
+ };
8319
+ }
8320
+ function buildWorkflowMetadataEntry(input) {
8321
+ const { params, scopeId, publicAnchor } = input;
8322
+ if (!params.persistence || params.persistence === "runtime-only") return null;
8323
+ const requestedMetadata = params.metadata ?? {};
8324
+ const entryPersistence = requestedMetadata.metadataPersistence ?? (params.persistence === "session" ? "external" : "internal");
8325
+ return {
8326
+ entryId: requestedMetadata.entryId ?? `scope-metadata-${scopeId}`,
8327
+ metadataId: requestedMetadata.metadataId ?? "workflow.scope",
8328
+ anchor: publicAnchor,
8329
+ ...params.storyTarget ? { storyTarget: params.storyTarget } : {},
8330
+ scopeId,
8331
+ ...requestedMetadata.workItemId ? { workItemId: requestedMetadata.workItemId } : {},
8332
+ ...requestedMetadata.value !== void 0 ? { value: requestedMetadata.value } : params.persistence === "document-metadata" && params.label ? { value: { label: params.label } } : {},
8333
+ metadataPersistence: entryPersistence,
8334
+ ...requestedMetadata.storageRef !== void 0 ? { storageRef: requestedMetadata.storageRef } : {},
8335
+ ...requestedMetadata.metadataVersion !== void 0 ? { metadataVersion: requestedMetadata.metadataVersion } : {}
8336
+ };
8337
+ }
8164
8338
  function addScope(params) {
8165
8339
  const state = deps.getState();
8166
8340
  const scopeId = params.scopeId ?? `scope-${clock().replace(/[^0-9]/gu, "")}-${Math.floor(Math.random() * 1e6)}`;
@@ -8203,6 +8377,7 @@ function createWorkflowCoordinator(deps) {
8203
8377
  deps.dispatch({
8204
8378
  type: "document.replace",
8205
8379
  document: nextDocument,
8380
+ mapping: createScopeMarkerMutationMapping(),
8206
8381
  origin: { source: "api", at: clock() }
8207
8382
  });
8208
8383
  const callerAssoc = params.anchor.kind === "range" ? params.anchor.assoc : { start: -1, end: 1 };
@@ -8259,6 +8434,84 @@ function createWorkflowCoordinator(deps) {
8259
8434
  }
8260
8435
  return { scopeId, anchor: publicAnchor };
8261
8436
  }
8437
+ function addScopes(paramsList) {
8438
+ if (paramsList.length === 0) return [];
8439
+ let nextDocument = deps.getDocument();
8440
+ let documentChanged = false;
8441
+ const results = [];
8442
+ const scopesToAdd = [];
8443
+ const metadataEntriesToAdd = [];
8444
+ const newScopeIds = /* @__PURE__ */ new Set();
8445
+ for (const params of paramsList) {
8446
+ const scopeId = params.scopeId ?? `scope-${clock().replace(/[^0-9]/gu, "")}-${Math.floor(Math.random() * 1e6)}`;
8447
+ const anchor = params.anchor.kind === "range" ? { from: params.anchor.from, to: params.anchor.to } : null;
8448
+ if (!anchor) {
8449
+ results.push({ scopeId, anchor: params.anchor });
8450
+ continue;
8451
+ }
8452
+ const callerAssoc = params.anchor.kind === "range" ? params.anchor.assoc : { start: -1, end: 1 };
8453
+ const plantResult = insertScopeMarkers(nextDocument, {
8454
+ scopeId,
8455
+ from: anchor.from,
8456
+ to: anchor.to
8457
+ });
8458
+ if (plantResult.status !== "planted") {
8459
+ results.push(
8460
+ createPlantFailureResult({
8461
+ scopeId,
8462
+ anchor,
8463
+ assoc: callerAssoc,
8464
+ plantResult
8465
+ })
8466
+ );
8467
+ continue;
8468
+ }
8469
+ nextDocument = plantResult.document;
8470
+ documentChanged = true;
8471
+ const publicAnchor = {
8472
+ kind: "range",
8473
+ from: plantResult.plantedRange.from,
8474
+ to: plantResult.plantedRange.to,
8475
+ assoc: callerAssoc
8476
+ };
8477
+ newScopeIds.add(scopeId);
8478
+ scopesToAdd.push(buildWorkflowScope({ params, scopeId, publicAnchor }));
8479
+ const entry = buildWorkflowMetadataEntry({ params, scopeId, publicAnchor });
8480
+ if (entry) metadataEntriesToAdd.push(entry);
8481
+ results.push({ scopeId, anchor: publicAnchor });
8482
+ }
8483
+ if (documentChanged) {
8484
+ deps.dispatch({
8485
+ type: "document.replace",
8486
+ document: nextDocument,
8487
+ mapping: createScopeMarkerMutationMapping(),
8488
+ origin: { source: "api", at: clock() }
8489
+ });
8490
+ }
8491
+ if (scopesToAdd.length > 0) {
8492
+ const currentOverlay = overlayStore.getOverlay() ?? {
8493
+ overlayVersion: "workflow-overlay/1",
8494
+ scopes: []
8495
+ };
8496
+ const existingScopes = currentOverlay.scopes.filter(
8497
+ (existing) => !newScopeIds.has(existing.scopeId)
8498
+ );
8499
+ deps.dispatch({
8500
+ type: "workflow.set-overlay",
8501
+ overlay: { ...currentOverlay, scopes: [...existingScopes, ...scopesToAdd] },
8502
+ origin: { source: "api", at: clock() }
8503
+ });
8504
+ }
8505
+ if (metadataEntriesToAdd.length > 0) {
8506
+ const priorEntries = overlayStore.getMetadataEntries();
8507
+ deps.dispatch({
8508
+ type: "workflow.set-metadata-entries",
8509
+ entries: [...priorEntries, ...metadataEntriesToAdd],
8510
+ origin: { source: "api", at: clock() }
8511
+ });
8512
+ }
8513
+ return results;
8514
+ }
8262
8515
  function removeScope(scopeId) {
8263
8516
  const overlay = overlayStore.getOverlay();
8264
8517
  if (overlay) {
@@ -8276,6 +8529,7 @@ function createWorkflowCoordinator(deps) {
8276
8529
  deps.dispatch({
8277
8530
  type: "document.replace",
8278
8531
  document: nextDocument,
8532
+ mapping: createScopeMarkerMutationMapping(),
8279
8533
  origin: { source: "api", at: clock() }
8280
8534
  });
8281
8535
  }
@@ -8669,6 +8923,7 @@ function createWorkflowCoordinator(deps) {
8669
8923
  }
8670
8924
  return {
8671
8925
  addScope,
8926
+ addScopes,
8672
8927
  removeScope,
8673
8928
  addInvisibleScope,
8674
8929
  setScopeVisibility,
@@ -12800,6 +13055,36 @@ function createDocumentRuntime(options) {
12800
13055
  let viewportBlockRanges = null;
12801
13056
  let viewportRangesKey = serializeViewportRanges(viewportBlockRanges);
12802
13057
  let viewportBlocksPerPageEstimate = null;
13058
+ let fullSurfaceWarmupScheduled = false;
13059
+ let fullSurfaceWarmupCompleted = false;
13060
+ function scheduleFullSurfaceWarmupAfterCull() {
13061
+ if (fullSurfaceWarmupScheduled || fullSurfaceWarmupCompleted) return;
13062
+ fullSurfaceWarmupScheduled = true;
13063
+ perfCounters.increment("surface.fullSurfaceWarmup.scheduled");
13064
+ runOnIdle(() => {
13065
+ fullSurfaceWarmupScheduled = false;
13066
+ if (cachedFullSurface) {
13067
+ perfCounters.increment("surface.fullSurfaceWarmup.alreadyCached");
13068
+ fullSurfaceWarmupCompleted = true;
13069
+ return;
13070
+ }
13071
+ const t0 = performance.now();
13072
+ try {
13073
+ getCachedFullSurface(state.document, activeStory);
13074
+ fullSurfaceWarmupCompleted = true;
13075
+ perfCounters.increment("surface.fullSurfaceWarmup.committed");
13076
+ } catch (error) {
13077
+ perfCounters.increment("surface.fullSurfaceWarmup.failed");
13078
+ fullSurfaceWarmupCompleted = false;
13079
+ void error;
13080
+ } finally {
13081
+ perfCounters.increment(
13082
+ "surface.fullSurfaceWarmup.us",
13083
+ Math.round((performance.now() - t0) * 1e3)
13084
+ );
13085
+ }
13086
+ });
13087
+ }
12803
13088
  const getRuntimeForLayoutFacet = () => {
12804
13089
  if (!runtimeRef) {
12805
13090
  throw new Error("Document runtime viewport methods are not initialized");
@@ -12992,6 +13277,15 @@ function createDocumentRuntime(options) {
12992
13277
  let cachedSurface;
12993
13278
  let cachedFullSurface;
12994
13279
  const editableTargetBlockCache = createEditableTargetBlockCache();
13280
+ let paragraphCascadeCache = /* @__PURE__ */ new WeakMap();
13281
+ let paragraphCascadeCacheStylesRef = null;
13282
+ function ensureParagraphCascadeCacheForStyles(nextStyles) {
13283
+ if (paragraphCascadeCacheStylesRef !== nextStyles) {
13284
+ paragraphCascadeCache = /* @__PURE__ */ new WeakMap();
13285
+ paragraphCascadeCacheStylesRef = nextStyles;
13286
+ }
13287
+ return paragraphCascadeCache;
13288
+ }
12995
13289
  let cachedEditableTargetMap = null;
12996
13290
  function getEditableTargetsByBlockPath(document) {
12997
13291
  if (cachedEditableTargetMap !== null && cachedEditableTargetMap.document === document) {
@@ -13045,6 +13339,7 @@ function createDocumentRuntime(options) {
13045
13339
  const snapshot = createEditorSurfaceSnapshot(document, state.selection, nextActiveStory, {
13046
13340
  viewportBlockRanges: null,
13047
13341
  editableTargetsByBlockPath: getEditableTargetsByBlockPath(document),
13342
+ paragraphCascadeCache: ensureParagraphCascadeCacheForStyles(document.styles),
13048
13343
  ...effectiveMarkupModeProvider ? { getEffectiveMarkupMode: effectiveMarkupModeProvider } : {}
13049
13344
  });
13050
13345
  recordPerfSample("snapshot.surface");
@@ -13085,6 +13380,7 @@ function createDocumentRuntime(options) {
13085
13380
  activeStoryKey,
13086
13381
  surfaceViewportRanges
13087
13382
  ),
13383
+ paragraphCascadeCache: ensureParagraphCascadeCacheForStyles(document.styles),
13088
13384
  ...effectiveMarkupModeProvider ? { getEffectiveMarkupMode: effectiveMarkupModeProvider } : {}
13089
13385
  });
13090
13386
  recordPerfSample("snapshot.surface");
@@ -13296,7 +13592,17 @@ function createDocumentRuntime(options) {
13296
13592
  }
13297
13593
  }
13298
13594
  function tryPatchNestedLocalTextSurface(previousSurface, editFrom, editTo, insertedText) {
13299
- const shiftBudget = estimateLocalTextPatchShiftBudget(previousSurface.blocks, 0);
13595
+ const containerIndex = previousSurface.blocks.findIndex(
13596
+ (block) => editFrom >= block.from && editTo <= block.to
13597
+ );
13598
+ if (containerIndex < 0) {
13599
+ perfCounters.increment("surface.localText.patchMiss");
13600
+ return null;
13601
+ }
13602
+ const shiftBudget = estimateLocalTextPatchShiftBudget(
13603
+ previousSurface.blocks,
13604
+ containerIndex + 1
13605
+ );
13300
13606
  perfCounters.increment("surface.localText.shiftedBlocks", shiftBudget.shiftedBlocks);
13301
13607
  perfCounters.increment("surface.localText.shiftedNodes", shiftBudget.shiftedNodes);
13302
13608
  if (!shiftBudget.withinBudget) {
@@ -13376,19 +13682,9 @@ function createDocumentRuntime(options) {
13376
13682
  for (let index = startIndex; index < blocks.length; index += 1) {
13377
13683
  const shiftedBlockNodes = countSurfaceShiftNodesUpTo(
13378
13684
  blocks[index],
13379
- Math.min(
13380
- policy.maxShiftedNodesPerBlock,
13381
- policy.maxShiftedSurfaceNodes - shiftedNodes
13382
- ) + 1
13685
+ policy.maxShiftedSurfaceNodes - shiftedNodes + 1
13383
13686
  );
13384
13687
  shiftedNodes += shiftedBlockNodes;
13385
- if (shiftedBlockNodes > policy.maxShiftedNodesPerBlock) {
13386
- return {
13387
- shiftedBlocks,
13388
- shiftedNodes,
13389
- withinBudget: false
13390
- };
13391
- }
13392
13688
  if (shiftedNodes > policy.maxShiftedSurfaceNodes) {
13393
13689
  return {
13394
13690
  shiftedBlocks,
@@ -14060,6 +14356,9 @@ function createDocumentRuntime(options) {
14060
14356
  viewportBlockRangesOverride: firstSurfaceViewportBlockRanges
14061
14357
  }) : getCachedSurface(state.document, activeStory)
14062
14358
  );
14359
+ if (firstSurfaceViewportBlockRanges) {
14360
+ scheduleFullSurfaceWarmupAfterCull();
14361
+ }
14063
14362
  const snapshot = {
14064
14363
  documentId: state.documentId,
14065
14364
  sessionId: state.sessionId,
@@ -14173,6 +14472,9 @@ function createDocumentRuntime(options) {
14173
14472
  activeStoryKey,
14174
14473
  viewportBlockRanges
14175
14474
  ),
14475
+ paragraphCascadeCache: ensureParagraphCascadeCacheForStyles(
14476
+ state.document.styles
14477
+ ),
14176
14478
  ...effectiveMarkupModeProvider ? { getEffectiveMarkupMode: effectiveMarkupModeProvider } : {}
14177
14479
  }
14178
14480
  );
@@ -14824,6 +15126,17 @@ function createDocumentRuntime(options) {
14824
15126
  };
14825
15127
  resolvedReplayTextTarget = prepared.textTarget;
14826
15128
  } else {
15129
+ const listBoundaryJoinCommand = createListItemBoundaryJoinReplayCommand({
15130
+ command,
15131
+ document: replayState.document,
15132
+ selection: replayState.selection,
15133
+ surface: replaySnapshot.surface?.blocks ?? [],
15134
+ storyTarget: replayStory,
15135
+ timestamp: context.timestamp
15136
+ });
15137
+ if (listBoundaryJoinCommand) {
15138
+ executableCommand = listBoundaryJoinCommand;
15139
+ }
14827
15140
  const selectedListItemDeleteCommand = createSelectedListItemDeleteReplayCommand({
14828
15141
  command,
14829
15142
  document: replayState.document,
@@ -14981,6 +15294,17 @@ function createDocumentRuntime(options) {
14981
15294
  };
14982
15295
  resolvedReplayTextTarget = prepared.textTarget;
14983
15296
  } else {
15297
+ const listBoundaryJoinCommand = createListItemBoundaryJoinReplayCommand({
15298
+ command,
15299
+ document: stateForCommand.document,
15300
+ selection: stateForCommand.selection,
15301
+ surface: snapshotForCommand.surface?.blocks ?? [],
15302
+ storyTarget: replayStory,
15303
+ timestamp: context.timestamp
15304
+ });
15305
+ if (listBoundaryJoinCommand) {
15306
+ executableCommand = listBoundaryJoinCommand;
15307
+ }
14984
15308
  const selectedListItemDeleteCommand = createSelectedListItemDeleteReplayCommand({
14985
15309
  command,
14986
15310
  document: stateForCommand.document,
@@ -16010,6 +16334,9 @@ function createDocumentRuntime(options) {
16010
16334
  addScope(params) {
16011
16335
  return workflowCoordinator.addScope(params);
16012
16336
  },
16337
+ addScopes(params) {
16338
+ return workflowCoordinator.addScopes(params);
16339
+ },
16013
16340
  getScope(scopeId) {
16014
16341
  return workflowCoordinator.getScope(scopeId);
16015
16342
  },
@@ -16993,6 +17320,9 @@ function createDocumentRuntime(options) {
16993
17320
  if (transaction.mapping.metadata?.scopeTagTouches) return false;
16994
17321
  return getLocalTextPatchMetadata(transaction.mapping) !== null;
16995
17322
  }
17323
+ function isLayoutNeutralScopeMarkerCommit(previous, next, transaction) {
17324
+ return transaction.markDirty && previous.document !== next.document && transaction.mapping.steps.length === 0 && transaction.mapping.metadata?.layoutNeutralScopeMarkers === true;
17325
+ }
16996
17326
  function applyTransactionToState(transaction, options2 = {}) {
16997
17327
  const effects = transaction.effects;
16998
17328
  const selectionUnchanged = transaction.nextState.selection === state.selection;
@@ -17021,6 +17351,11 @@ function createDocumentRuntime(options) {
17021
17351
  transaction,
17022
17352
  transaction.effects
17023
17353
  );
17354
+ const layoutNeutralScopeMarkerCommit = isLayoutNeutralScopeMarkerCommit(
17355
+ previous,
17356
+ state,
17357
+ transaction
17358
+ );
17024
17359
  perfCounters.increment("commit.refreshClassify.us", Math.round((performance.now() - tClassify0) * 1e3));
17025
17360
  const tOverlay0 = performance.now();
17026
17361
  const skipOverlaySync = useLocalTextCommitSnapshot && canSkipOverlaySyncForLocalText(transaction);
@@ -17069,9 +17404,12 @@ function createDocumentRuntime(options) {
17069
17404
  ...detachedWorkflowScopeWarnings.cleared
17070
17405
  ]
17071
17406
  };
17072
- if (!useLocalTextCommitSnapshot && transaction.markDirty && previous.document !== state.document) {
17407
+ if (!useLocalTextCommitSnapshot && !layoutNeutralScopeMarkerCommit && transaction.markDirty && previous.document !== state.document) {
17073
17408
  applyViewportRanges(getSelectionCorridorViewportRanges(cachedRenderSnapshot.surface));
17074
17409
  }
17410
+ if (layoutNeutralScopeMarkerCommit && viewportBlockRanges !== null) {
17411
+ getCachedFullSurface(state.document, activeStory);
17412
+ }
17075
17413
  const tValidation0 = performance.now();
17076
17414
  const patchSourceSurface = getReusableCachedFullSurface(previous.document, activeStory) ?? cachedRenderSnapshot.surface;
17077
17415
  const patchedFullLocalTextSurface = useLocalTextCommitSnapshot ? tryPatchLocalTextSurface(patchSourceSurface, transaction.mapping) : null;
@@ -17440,15 +17778,49 @@ function createDocumentRuntime(options) {
17440
17778
  const preSelection = selection;
17441
17779
  const preActiveStory = activeStory;
17442
17780
  const priorDocument = state.document;
17781
+ const listBoundaryJoin = createListItemBoundaryJoinReplacement({
17782
+ command: commandForDispatch,
17783
+ document: state.document,
17784
+ editableTarget,
17785
+ selection,
17786
+ storyTarget: activeStory,
17787
+ targetResolution,
17788
+ timestamp
17789
+ });
17790
+ if (listBoundaryJoin && context.documentMode !== "suggesting") {
17791
+ const replacementCommand = {
17792
+ type: "document.replace",
17793
+ document: listBoundaryJoin.document,
17794
+ selection: listBoundaryJoin.selection,
17795
+ mapping: listBoundaryJoin.mapping,
17796
+ protectionSelection: selection,
17797
+ origin: commandForDispatch.origin
17798
+ };
17799
+ const transaction = executeEditorCommand(baseState, replacementCommand, context);
17800
+ commit(transaction);
17801
+ options.onCommandApplied?.(commandForDispatch, transaction, context, {
17802
+ preSelection,
17803
+ activeStory: preActiveStory,
17804
+ priorDocument
17805
+ });
17806
+ return completeDispatch(classifyAck({
17807
+ command: commandForDispatch,
17808
+ opId,
17809
+ priorState: baseState,
17810
+ transaction,
17811
+ newRevisionToken: state.revisionToken
17812
+ }));
17813
+ }
17443
17814
  const selectedListItemDelete = createSelectedListItemDeleteReplacement({
17444
17815
  command: commandForDispatch,
17445
17816
  document: state.document,
17446
17817
  editableTarget,
17447
17818
  selection,
17819
+ storyTarget: activeStory,
17448
17820
  targetResolution,
17449
17821
  timestamp
17450
17822
  });
17451
- if (selectedListItemDelete && activeStory.kind === "main" && context.documentMode !== "suggesting") {
17823
+ if (selectedListItemDelete && context.documentMode !== "suggesting") {
17452
17824
  const replacementCommand = {
17453
17825
  type: "document.replace",
17454
17826
  document: selectedListItemDelete.document,
@@ -17713,6 +18085,9 @@ function createDocumentRuntime(options) {
17713
18085
  });
17714
18086
  }
17715
18087
  function scheduleIdleContextAnalytics(callback) {
18088
+ runOnIdle(callback);
18089
+ }
18090
+ function runOnIdle(callback) {
17716
18091
  const requestIdle = globalThis.requestIdleCallback;
17717
18092
  if (typeof requestIdle === "function") {
17718
18093
  requestIdle(callback, { timeout: 250 });
@@ -20352,8 +20727,58 @@ function stripStoryTarget(selection) {
20352
20727
  function isTopLevelMainStoryBlockPath(blockPath) {
20353
20728
  return typeof blockPath === "string" && /^main\/block\[\d+\]$/u.test(blockPath);
20354
20729
  }
20730
+ function createListItemBoundaryJoinReplacement(input) {
20731
+ const { command, document, editableTarget, selection, storyTarget, targetResolution, timestamp } = input;
20732
+ const direction = listItemBoundaryJoinDirection(command, selection, targetResolution);
20733
+ if (!direction || editableTarget?.listAddress?.operationScope !== "list-text" || targetResolution?.kind !== "accepted") {
20734
+ return null;
20735
+ }
20736
+ const storyBlocks = getStoryBlocks(document, storyTarget);
20737
+ const replacement = joinNumberedParagraphAtStoryPath(
20738
+ storyBlocks,
20739
+ editableTarget.blockPath,
20740
+ storyTarget,
20741
+ direction
20742
+ );
20743
+ if (!replacement) {
20744
+ return null;
20745
+ }
20746
+ const nextDocument = replaceStoryBlocks({
20747
+ ...document,
20748
+ updatedAt: timestamp
20749
+ }, storyTarget, replacement.blocks);
20750
+ const deletedFrom = direction === "backward" ? Math.max(0, selection.anchor - 1) : selection.anchor;
20751
+ const deletedTo = direction === "backward" ? selection.anchor : selection.anchor + 1;
20752
+ const nextAnchor = direction === "backward" ? deletedFrom : selection.anchor;
20753
+ return {
20754
+ document: nextDocument,
20755
+ selection: createSelectionSnapshot(nextAnchor, nextAnchor),
20756
+ mapping: {
20757
+ steps: [{
20758
+ from: deletedFrom,
20759
+ to: deletedTo,
20760
+ insertSize: 0
20761
+ }],
20762
+ metadata: {
20763
+ invalidatesStructures: true
20764
+ }
20765
+ }
20766
+ };
20767
+ }
20768
+ function listItemBoundaryJoinDirection(command, selection, targetResolution) {
20769
+ if (selection.isCollapsed !== true || targetResolution?.kind !== "accepted") {
20770
+ return null;
20771
+ }
20772
+ if (command.type === "text.delete-backward" && selection.anchor === targetResolution.range.from) {
20773
+ return "backward";
20774
+ }
20775
+ if (command.type === "text.delete-forward" && selection.anchor === targetResolution.range.to) {
20776
+ return "forward";
20777
+ }
20778
+ return null;
20779
+ }
20355
20780
  function createSelectedListItemDeleteReplacement(input) {
20356
- const { command, document, editableTarget, selection, targetResolution, timestamp } = input;
20781
+ const { command, document, editableTarget, selection, storyTarget, targetResolution, timestamp } = input;
20357
20782
  if (command.type !== "text.delete-backward" && command.type !== "text.delete-forward") {
20358
20783
  return null;
20359
20784
  }
@@ -20365,20 +20790,19 @@ function createSelectedListItemDeleteReplacement(input) {
20365
20790
  if (selectionFrom !== targetResolution.range.from || selectionTo !== targetResolution.range.to) {
20366
20791
  return null;
20367
20792
  }
20368
- const root = document.content;
20369
- const replacement = removeNumberedParagraphAtMainStoryPath(root.children, editableTarget.blockPath);
20793
+ const storyBlocks = getStoryBlocks(document, storyTarget);
20794
+ const replacement = removeNumberedParagraphAtStoryPath(storyBlocks, editableTarget.blockPath, storyTarget);
20370
20795
  if (!replacement) {
20371
20796
  return null;
20372
20797
  }
20373
- const nextDocument = {
20798
+ const nextDocument = replaceStoryBlocks({
20374
20799
  ...document,
20375
- updatedAt: timestamp,
20376
- content: {
20377
- ...root,
20378
- children: replacement.blocks
20379
- }
20380
- };
20381
- const nextStorySize = parseTextStory(nextDocument.content).size;
20800
+ updatedAt: timestamp
20801
+ }, storyTarget, replacement.blocks);
20802
+ const nextStorySize = parseTextStory({
20803
+ type: "doc",
20804
+ children: [...getStoryBlocks(nextDocument, storyTarget)]
20805
+ }).size;
20382
20806
  const nextAnchor = Math.min(selectionFrom, nextStorySize);
20383
20807
  return {
20384
20808
  document: nextDocument,
@@ -20395,11 +20819,157 @@ function createSelectedListItemDeleteReplacement(input) {
20395
20819
  }
20396
20820
  };
20397
20821
  }
20398
- function removeNumberedParagraphAtMainStoryPath(blocks, blockPath) {
20399
- const tokens = parseMainStoryBlockPathTokens(blockPath);
20822
+ function removeNumberedParagraphAtStoryPath(blocks, blockPath, storyTarget) {
20823
+ const tokens = parseStoryBlockPathTokens(blockPath, storyTarget);
20400
20824
  if (!tokens) return null;
20401
20825
  return removeNumberedParagraphFromBlocks(blocks, tokens);
20402
20826
  }
20827
+ function joinNumberedParagraphAtStoryPath(blocks, blockPath, storyTarget, direction) {
20828
+ const tokens = parseStoryBlockPathTokens(blockPath, storyTarget);
20829
+ if (!tokens) return null;
20830
+ return joinNumberedParagraphFromBlocks(blocks, tokens, direction);
20831
+ }
20832
+ function joinNumberedParagraphFromBlocks(blocks, tokens, direction) {
20833
+ const [token, ...rest] = tokens;
20834
+ if (!token || token.kind !== "block") return null;
20835
+ const block = blocks[token.index];
20836
+ if (!block) return null;
20837
+ if (rest.length === 0) {
20838
+ return joinAdjacentNumberedParagraphs(blocks, token.index, direction);
20839
+ }
20840
+ const next = rest[0];
20841
+ if (block.type === "table" && next?.kind === "row") {
20842
+ const updatedTable = joinNumberedParagraphInTable(block, rest, direction);
20843
+ if (!updatedTable) return null;
20844
+ return {
20845
+ blocks: [
20846
+ ...blocks.slice(0, token.index),
20847
+ updatedTable,
20848
+ ...blocks.slice(token.index + 1)
20849
+ ]
20850
+ };
20851
+ }
20852
+ if ((block.type === "sdt" || block.type === "custom_xml") && next?.kind === "block") {
20853
+ const updatedChildren = joinNumberedParagraphFromBlocks(block.children, rest, direction);
20854
+ if (!updatedChildren) return null;
20855
+ return {
20856
+ blocks: [
20857
+ ...blocks.slice(0, token.index),
20858
+ { ...block, children: updatedChildren.blocks },
20859
+ ...blocks.slice(token.index + 1)
20860
+ ]
20861
+ };
20862
+ }
20863
+ if (block.type === "paragraph" && next?.kind === "inline") {
20864
+ const updatedParagraph = joinNumberedParagraphInTextBoxInline(block, rest, direction);
20865
+ if (!updatedParagraph) return null;
20866
+ return {
20867
+ blocks: [
20868
+ ...blocks.slice(0, token.index),
20869
+ updatedParagraph,
20870
+ ...blocks.slice(token.index + 1)
20871
+ ]
20872
+ };
20873
+ }
20874
+ return null;
20875
+ }
20876
+ function joinAdjacentNumberedParagraphs(blocks, targetIndex, direction) {
20877
+ const target = blocks[targetIndex];
20878
+ if (target?.type !== "paragraph" || !target.numbering) {
20879
+ return null;
20880
+ }
20881
+ if (direction === "backward") {
20882
+ const previousIndex = targetIndex - 1;
20883
+ const previous = blocks[previousIndex];
20884
+ if (previous?.type !== "paragraph" || !previous.numbering) {
20885
+ return null;
20886
+ }
20887
+ const merged2 = {
20888
+ ...previous,
20889
+ children: [...previous.children, ...target.children]
20890
+ };
20891
+ return {
20892
+ blocks: [
20893
+ ...blocks.slice(0, previousIndex),
20894
+ merged2,
20895
+ ...blocks.slice(targetIndex + 1)
20896
+ ]
20897
+ };
20898
+ }
20899
+ const nextIndex = targetIndex + 1;
20900
+ const next = blocks[nextIndex];
20901
+ if (next?.type !== "paragraph" || !next.numbering) {
20902
+ return null;
20903
+ }
20904
+ const merged = {
20905
+ ...target,
20906
+ children: [...target.children, ...next.children]
20907
+ };
20908
+ return {
20909
+ blocks: [
20910
+ ...blocks.slice(0, targetIndex),
20911
+ merged,
20912
+ ...blocks.slice(nextIndex + 1)
20913
+ ]
20914
+ };
20915
+ }
20916
+ function joinNumberedParagraphInTable(table, tokens, direction) {
20917
+ const [rowToken, cellToken, ...childTokens] = tokens;
20918
+ if (rowToken?.kind !== "row" || cellToken?.kind !== "cell" || childTokens[0]?.kind !== "block") {
20919
+ return null;
20920
+ }
20921
+ const row2 = table.rows[rowToken.index];
20922
+ const cell = row2?.cells[cellToken.index];
20923
+ if (!row2 || !cell) return null;
20924
+ const updatedChildren = joinNumberedParagraphFromBlocks(cell.children, childTokens, direction);
20925
+ if (!updatedChildren) return null;
20926
+ const nextCells = [
20927
+ ...row2.cells.slice(0, cellToken.index),
20928
+ { ...cell, children: updatedChildren.blocks },
20929
+ ...row2.cells.slice(cellToken.index + 1)
20930
+ ];
20931
+ const nextRows = [
20932
+ ...table.rows.slice(0, rowToken.index),
20933
+ { ...row2, cells: nextCells },
20934
+ ...table.rows.slice(rowToken.index + 1)
20935
+ ];
20936
+ return { ...table, rows: nextRows };
20937
+ }
20938
+ function joinNumberedParagraphInTextBoxInline(paragraph, tokens, direction) {
20939
+ const [inlineToken, textBoxToken, ...childTokens] = tokens;
20940
+ if (inlineToken?.kind !== "inline" || textBoxToken?.kind !== "txbx" || childTokens[0]?.kind !== "block") {
20941
+ return null;
20942
+ }
20943
+ const inline = paragraph.children[inlineToken.index];
20944
+ if (!inline) return null;
20945
+ const updatedInline = joinNumberedParagraphInInlineTextBox(inline, childTokens, direction);
20946
+ if (!updatedInline) return null;
20947
+ return {
20948
+ ...paragraph,
20949
+ children: [
20950
+ ...paragraph.children.slice(0, inlineToken.index),
20951
+ updatedInline,
20952
+ ...paragraph.children.slice(inlineToken.index + 1)
20953
+ ]
20954
+ };
20955
+ }
20956
+ function joinNumberedParagraphInInlineTextBox(inline, tokens, direction) {
20957
+ if (inline.type === "shape" && inline.txbxBlocks) {
20958
+ const updatedBlocks = joinNumberedParagraphFromBlocks(inline.txbxBlocks, tokens, direction);
20959
+ return updatedBlocks ? { ...inline, txbxBlocks: updatedBlocks.blocks } : null;
20960
+ }
20961
+ if (inline.type === "drawing_frame" && inline.content.type === "shape" && inline.content.txbxBlocks) {
20962
+ const updatedBlocks = joinNumberedParagraphFromBlocks(inline.content.txbxBlocks, tokens, direction);
20963
+ return updatedBlocks ? {
20964
+ ...inline,
20965
+ content: {
20966
+ ...inline.content,
20967
+ txbxBlocks: updatedBlocks.blocks
20968
+ }
20969
+ } : null;
20970
+ }
20971
+ return null;
20972
+ }
20403
20973
  function removeNumberedParagraphFromBlocks(blocks, tokens) {
20404
20974
  const [token, ...rest] = tokens;
20405
20975
  if (!token || token.kind !== "block") return null;
@@ -20442,6 +21012,52 @@ function removeNumberedParagraphFromBlocks(blocks, tokens) {
20442
21012
  ]
20443
21013
  };
20444
21014
  }
21015
+ if (block.type === "paragraph" && next?.kind === "inline") {
21016
+ const updatedParagraph = removeNumberedParagraphFromTextBoxInline(block, rest);
21017
+ if (!updatedParagraph) return null;
21018
+ return {
21019
+ blocks: [
21020
+ ...blocks.slice(0, token.index),
21021
+ updatedParagraph,
21022
+ ...blocks.slice(token.index + 1)
21023
+ ]
21024
+ };
21025
+ }
21026
+ return null;
21027
+ }
21028
+ function removeNumberedParagraphFromTextBoxInline(paragraph, tokens) {
21029
+ const [inlineToken, textBoxToken, ...childTokens] = tokens;
21030
+ if (inlineToken?.kind !== "inline" || textBoxToken?.kind !== "txbx" || childTokens[0]?.kind !== "block") {
21031
+ return null;
21032
+ }
21033
+ const inline = paragraph.children[inlineToken.index];
21034
+ if (!inline) return null;
21035
+ const updatedInline = removeNumberedParagraphFromInlineTextBox(inline, childTokens);
21036
+ if (!updatedInline) return null;
21037
+ return {
21038
+ ...paragraph,
21039
+ children: [
21040
+ ...paragraph.children.slice(0, inlineToken.index),
21041
+ updatedInline,
21042
+ ...paragraph.children.slice(inlineToken.index + 1)
21043
+ ]
21044
+ };
21045
+ }
21046
+ function removeNumberedParagraphFromInlineTextBox(inline, tokens) {
21047
+ if (inline.type === "shape" && inline.txbxBlocks) {
21048
+ const updatedBlocks = removeNumberedParagraphFromBlocks(inline.txbxBlocks, tokens);
21049
+ return updatedBlocks ? { ...inline, txbxBlocks: updatedBlocks.blocks } : null;
21050
+ }
21051
+ if (inline.type === "drawing_frame" && inline.content.type === "shape" && inline.content.txbxBlocks) {
21052
+ const updatedBlocks = removeNumberedParagraphFromBlocks(inline.content.txbxBlocks, tokens);
21053
+ return updatedBlocks ? {
21054
+ ...inline,
21055
+ content: {
21056
+ ...inline.content,
21057
+ txbxBlocks: updatedBlocks.blocks
21058
+ }
21059
+ } : null;
21060
+ }
20445
21061
  return null;
20446
21062
  }
20447
21063
  function removeNumberedParagraphFromTable(table, tokens) {
@@ -20482,15 +21098,79 @@ function createSelectedListItemDeleteReplayCommand(input) {
20482
21098
  target: editableTarget,
20483
21099
  activeStoryKey: canonicalEditableTargetStoryKey(storyTarget)
20484
21100
  });
21101
+ const resolvedEditableTarget = targetResolution.kind === "accepted" ? editableTarget : storyTarget.kind !== "main" && blockPathBelongsToStoryTarget(editableTarget.blockPath, storyTarget) ? resolveEditableCommandTarget({
21102
+ document,
21103
+ target: editableTarget,
21104
+ activeStoryKey: canonicalEditableTargetStoryKey(storyTarget),
21105
+ commandFamilies: ["text-leaf"]
21106
+ }) : null;
21107
+ const selectedRange = {
21108
+ from: Math.min(selection.anchor, selection.head),
21109
+ to: Math.max(selection.anchor, selection.head)
21110
+ };
20485
21111
  const replacement = createSelectedListItemDeleteReplacement({
20486
21112
  command,
20487
21113
  document,
20488
- editableTarget,
21114
+ editableTarget: resolvedEditableTarget && resolvedEditableTarget.kind === "accepted" ? resolvedEditableTarget.target : editableTarget,
21115
+ selection,
21116
+ storyTarget,
21117
+ targetResolution: resolvedEditableTarget && resolvedEditableTarget.kind === "accepted" ? {
21118
+ kind: "accepted",
21119
+ range: selectedRange
21120
+ } : targetResolution,
21121
+ timestamp
21122
+ });
21123
+ if (!replacement) {
21124
+ return null;
21125
+ }
21126
+ return {
21127
+ type: "document.replace",
21128
+ document: replacement.document,
21129
+ selection: replacement.selection,
21130
+ mapping: replacement.mapping,
21131
+ protectionSelection: selection,
21132
+ origin: command.origin
21133
+ };
21134
+ }
21135
+ function createListItemBoundaryJoinReplayCommand(input) {
21136
+ const { command, document, selection, surface, storyTarget, timestamp } = input;
21137
+ if (command.type !== "text.delete-backward" && command.type !== "text.delete-forward") {
21138
+ return null;
21139
+ }
21140
+ const editableTarget = command.editableTarget;
21141
+ if (!editableTarget) {
21142
+ return null;
21143
+ }
21144
+ const targetResolution = resolveEditableTextTarget({
21145
+ document,
21146
+ selection,
21147
+ surface,
21148
+ target: editableTarget,
21149
+ activeStoryKey: canonicalEditableTargetStoryKey(storyTarget)
21150
+ });
21151
+ const resolvedEditableTarget = targetResolution.kind === "accepted" ? editableTarget : storyTarget.kind !== "main" && blockPathBelongsToStoryTarget(editableTarget.blockPath, storyTarget) ? resolveEditableCommandTarget({
21152
+ document,
21153
+ target: editableTarget,
21154
+ activeStoryKey: canonicalEditableTargetStoryKey(storyTarget),
21155
+ commandFamilies: ["text-leaf"]
21156
+ }) : null;
21157
+ const selectedRange = {
21158
+ from: Math.min(selection.anchor, selection.head),
21159
+ to: Math.max(selection.anchor, selection.head)
21160
+ };
21161
+ const replacement = createListItemBoundaryJoinReplacement({
21162
+ command,
21163
+ document,
21164
+ editableTarget: resolvedEditableTarget && resolvedEditableTarget.kind === "accepted" ? resolvedEditableTarget.target : editableTarget,
20489
21165
  selection,
20490
- targetResolution,
21166
+ storyTarget,
21167
+ targetResolution: resolvedEditableTarget && resolvedEditableTarget.kind === "accepted" ? {
21168
+ kind: "accepted",
21169
+ range: selectedRange
21170
+ } : targetResolution,
20491
21171
  timestamp
20492
21172
  });
20493
- if (!replacement || storyTarget.kind !== "main") {
21173
+ if (!replacement) {
20494
21174
  return null;
20495
21175
  }
20496
21176
  return {
@@ -20502,22 +21182,49 @@ function createSelectedListItemDeleteReplayCommand(input) {
20502
21182
  origin: command.origin
20503
21183
  };
20504
21184
  }
20505
- function parseMainStoryBlockPathTokens(blockPath) {
20506
- const parts = blockPath?.split("/") ?? [];
20507
- if (parts[0] !== "main" || parts.length < 2) {
21185
+ function parseStoryBlockPathTokens(blockPath, storyTarget) {
21186
+ if (!blockPath) {
21187
+ return null;
21188
+ }
21189
+ const firstTokenMatch = /\/(?:block|row|cell)\[\d+\]/u.exec(blockPath);
21190
+ if (!firstTokenMatch?.index) {
21191
+ return null;
21192
+ }
21193
+ const storyPrefix = blockPath.slice(0, firstTokenMatch.index);
21194
+ if (!blockPathBelongsToStoryTarget(storyPrefix, storyTarget)) {
20508
21195
  return null;
20509
21196
  }
21197
+ const parts = blockPath.slice(firstTokenMatch.index + 1).split("/");
20510
21198
  const tokens = [];
20511
- for (const part of parts.slice(1)) {
20512
- const match = /^(block|row|cell)\[(\d+)\]$/u.exec(part);
21199
+ for (const part of parts) {
21200
+ if (part === "txbx") {
21201
+ tokens.push({ kind: "txbx" });
21202
+ continue;
21203
+ }
21204
+ const match = /^(block|row|cell|inline)\[(\d+)\]$/u.exec(part);
20513
21205
  if (!match) return null;
21206
+ const kind = match[1];
20514
21207
  tokens.push({
20515
- kind: match[1],
21208
+ kind,
20516
21209
  index: Number.parseInt(match[2], 10)
20517
21210
  });
20518
21211
  }
20519
21212
  return tokens;
20520
21213
  }
21214
+ function blockPathBelongsToStoryTarget(storyPrefix, storyTarget) {
21215
+ switch (storyTarget.kind) {
21216
+ case "main":
21217
+ return storyPrefix === "main" || storyPrefix.startsWith("main/");
21218
+ case "header":
21219
+ return storyPrefix.startsWith("header:");
21220
+ case "footer":
21221
+ return storyPrefix.startsWith("footer:");
21222
+ case "footnote":
21223
+ return storyPrefix === `footnote:${storyTarget.noteId}` || storyPrefix.startsWith(`footnote:${storyTarget.noteId}/`);
21224
+ case "endnote":
21225
+ return storyPrefix === `endnote:${storyTarget.noteId}` || storyPrefix.startsWith(`endnote:${storyTarget.noteId}/`);
21226
+ }
21227
+ }
20521
21228
  function toInternalSelectionSnapshot(selection) {
20522
21229
  return {
20523
21230
  anchor: selection.anchor,