@beyondwork/docx-react-component 1.0.131 → 1.0.133

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 (100) hide show
  1. package/dist/api/public-types.cjs +837 -224
  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 +5 -3
  5. package/dist/api/v3.cjs +9679 -7492
  6. package/dist/api/v3.d.cts +3 -3
  7. package/dist/api/v3.d.ts +3 -3
  8. package/dist/api/v3.js +10 -10
  9. package/dist/{canonical-document-BMtONpgf.d.cts → canonical-document-CfZIc-fC.d.cts} +1 -1
  10. package/dist/{canonical-document-BMtONpgf.d.ts → canonical-document-CfZIc-fC.d.ts} +1 -1
  11. package/dist/{chunk-7G5GR3VV.js → chunk-224TSMEB.js} +635 -89
  12. package/dist/{chunk-YLL7MF5C.js → chunk-3JEE5RJU.js} +103 -135
  13. package/dist/{chunk-35RHOE6I.js → chunk-57HTKX3P.js} +10 -1162
  14. package/dist/{chunk-A66ZVUAT.js → chunk-5KTJKTNE.js} +236 -10
  15. package/dist/{chunk-THVM6EP5.js → chunk-CVSD3UNK.js} +1322 -102
  16. package/dist/{chunk-VRKK2CSZ.js → chunk-EFEW7BTT.js} +2 -2
  17. package/dist/{chunk-KNHMXKC6.js → chunk-INLRCC4N.js} +2 -2
  18. package/dist/{chunk-HYHCRMR7.js → chunk-KL4TZSZV.js} +1 -1
  19. package/dist/{chunk-T5YYFDZB.js → chunk-MQ5GAJ54.js} +68 -39
  20. package/dist/{chunk-CI2TD3T4.js → chunk-NJFKPDNG.js} +216 -2
  21. package/dist/{chunk-WZDKNF37.js → chunk-OTRVGNZQ.js} +2934 -1815
  22. package/dist/{chunk-4YCWECLZ.js → chunk-PZIEOEJZ.js} +1 -1
  23. package/dist/{chunk-PHMWH23E.js → chunk-QTRJLKR2.js} +1 -1
  24. package/dist/{chunk-QXKQPUOM.js → chunk-REFHJ2FN.js} +3 -3
  25. package/dist/{chunk-ZVC23LKV.js → chunk-RP76USJE.js} +1 -1
  26. package/dist/{chunk-3YCQM2RV.js → chunk-S3PEKX6H.js} +249 -45
  27. package/dist/{chunk-M7YRJX6V.js → chunk-T66OS7MN.js} +8 -3
  28. package/dist/{chunk-DGA7M77X.js → chunk-V2JF42SI.js} +2 -2
  29. package/dist/{chunk-Q7Y57KOK.js → chunk-WDDFU2N2.js} +2 -2
  30. package/dist/{chunk-A3GSNB4G.js → chunk-XBQFDBXE.js} +147 -13
  31. package/dist/{chunk-6TBLDBCL.js → chunk-ZFCZ7XXH.js} +1 -1
  32. package/dist/compare.d.cts +1 -1
  33. package/dist/compare.d.ts +1 -1
  34. package/dist/core/commands/formatting-commands.d.cts +2 -2
  35. package/dist/core/commands/formatting-commands.d.ts +2 -2
  36. package/dist/core/commands/image-commands.cjs +344 -20
  37. package/dist/core/commands/image-commands.d.cts +2 -2
  38. package/dist/core/commands/image-commands.d.ts +2 -2
  39. package/dist/core/commands/image-commands.js +5 -5
  40. package/dist/core/commands/section-layout-commands.d.cts +2 -2
  41. package/dist/core/commands/section-layout-commands.d.ts +2 -2
  42. package/dist/core/commands/style-commands.d.cts +2 -2
  43. package/dist/core/commands/style-commands.d.ts +2 -2
  44. package/dist/core/commands/table-structure-commands.cjs +344 -20
  45. package/dist/core/commands/table-structure-commands.d.cts +2 -2
  46. package/dist/core/commands/table-structure-commands.d.ts +2 -2
  47. package/dist/core/commands/table-structure-commands.js +4 -4
  48. package/dist/core/commands/text-commands.cjs +411 -58
  49. package/dist/core/commands/text-commands.d.cts +13 -2
  50. package/dist/core/commands/text-commands.d.ts +13 -2
  51. package/dist/core/commands/text-commands.js +5 -5
  52. package/dist/core/selection/mapping.d.cts +2 -2
  53. package/dist/core/selection/mapping.d.ts +2 -2
  54. package/dist/core/state/editor-state.d.cts +2 -2
  55. package/dist/core/state/editor-state.d.ts +2 -2
  56. package/dist/index.cjs +7199 -4004
  57. package/dist/index.d.cts +5 -5
  58. package/dist/index.d.ts +5 -5
  59. package/dist/index.js +814 -120
  60. package/dist/io/docx-session.cjs +7 -2
  61. package/dist/io/docx-session.d.cts +4 -4
  62. package/dist/io/docx-session.d.ts +4 -4
  63. package/dist/io/docx-session.js +4 -4
  64. package/dist/legal.d.cts +1 -1
  65. package/dist/legal.d.ts +1 -1
  66. package/dist/legal.js +3 -3
  67. package/dist/{loader-DiY_ZgKl.d.cts → loader-B2H99237.d.cts} +3 -3
  68. package/dist/{loader-B-aL5HGD.d.ts → loader-DfTjqVwn.d.ts} +3 -3
  69. package/dist/{public-types-gvubspUI.d.cts → public-types-B5lOUIrP.d.ts} +930 -338
  70. package/dist/{public-types-DyqnxxO9.d.ts → public-types-S8gTYwKo.d.cts} +930 -338
  71. package/dist/public-types.cjs +837 -224
  72. package/dist/public-types.d.cts +2 -2
  73. package/dist/public-types.d.ts +2 -2
  74. package/dist/public-types.js +5 -3
  75. package/dist/runtime/collab.d.cts +3 -3
  76. package/dist/runtime/collab.d.ts +3 -3
  77. package/dist/runtime/document-runtime.cjs +1403 -438
  78. package/dist/runtime/document-runtime.d.cts +2 -2
  79. package/dist/runtime/document-runtime.d.ts +2 -2
  80. package/dist/runtime/document-runtime.js +14 -14
  81. package/dist/{session-CDB0hohT.d.ts → session-CBDIOYXA.d.ts} +3 -3
  82. package/dist/{session-BUN6B-Vj.d.cts → session-CR2A1hGZ.d.cts} +3 -3
  83. package/dist/session.cjs +7 -2
  84. package/dist/session.d.cts +5 -5
  85. package/dist/session.d.ts +5 -5
  86. package/dist/session.js +5 -5
  87. package/dist/tailwind.cjs +905 -322
  88. package/dist/tailwind.d.cts +2 -2
  89. package/dist/tailwind.d.ts +2 -2
  90. package/dist/tailwind.js +7 -7
  91. package/dist/{types-VWH6CRvG.d.ts → types-B-90ywjU.d.ts} +2 -2
  92. package/dist/{types-C4bz3kDU.d.cts → types-yty2K-hk.d.cts} +2 -2
  93. package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +3 -3
  94. package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +3 -3
  95. package/dist/ui-tailwind/editor-surface/search-plugin.js +4 -4
  96. package/dist/ui-tailwind.cjs +905 -322
  97. package/dist/ui-tailwind.d.cts +4 -3
  98. package/dist/ui-tailwind.d.ts +4 -3
  99. package/dist/ui-tailwind.js +7 -7
  100. package/package.json +1 -1
@@ -5041,11 +5041,14 @@ function collectEditableTargetRefs(doc, cache) {
5041
5041
  collectEditableTargetsInBlocks(
5042
5042
  context.blocks,
5043
5043
  {
5044
+ doc,
5044
5045
  storyKey: context.storyKey,
5045
5046
  basePath: context.basePath,
5046
5047
  insideSdt: false,
5047
5048
  insideTextBox: false,
5048
- tableDepth: 0
5049
+ tableDepth: 0,
5050
+ numberingCatalogHash: createNumberingCatalogRevisionHash(doc),
5051
+ numberingTargetRevisionHash: createNumberingTargetRevisionHash(doc)
5049
5052
  },
5050
5053
  targets,
5051
5054
  cache
@@ -5065,11 +5068,14 @@ function collectEditableTargetRefsForStoryBlockRanges(doc, storyKey2, ranges, ca
5065
5068
  collectEditableTargetsInBlocks(
5066
5069
  context.blocks.slice(range.start, range.end),
5067
5070
  {
5071
+ doc,
5068
5072
  storyKey: context.storyKey,
5069
5073
  basePath: context.basePath,
5070
5074
  insideSdt: false,
5071
5075
  insideTextBox: false,
5072
- tableDepth: 0
5076
+ tableDepth: 0,
5077
+ numberingCatalogHash: createNumberingCatalogRevisionHash(doc),
5078
+ numberingTargetRevisionHash: createNumberingTargetRevisionHash(doc)
5073
5079
  },
5074
5080
  targets,
5075
5081
  cache,
@@ -5095,6 +5101,7 @@ function buildBlockCacheSignature(context, blockIndex) {
5095
5101
  const owner = tt?.editableOwnersByChildIndex?.get(blockIndex);
5096
5102
  return [
5097
5103
  context.storyKey,
5104
+ context.numberingTargetRevisionHash,
5098
5105
  context.insideSdt ? "1" : "0",
5099
5106
  context.insideTextBox ? "1" : "0",
5100
5107
  String(context.tableDepth),
@@ -5140,7 +5147,8 @@ function collectEditableTargetsInBlocks(blocks, context, targets, cache, blockIn
5140
5147
  editableParagraphTargetPosture(targetKind),
5141
5148
  context.contentControl,
5142
5149
  context.tableTarget,
5143
- context.tableTarget?.editableOwnersByChildIndex?.get(blockIndex)
5150
+ context.tableTarget?.editableOwnersByChildIndex?.get(blockIndex),
5151
+ resolveEditableParagraphListIdentity(block, context)
5144
5152
  )
5145
5153
  );
5146
5154
  }
@@ -5685,7 +5693,7 @@ function collectEditableTargetsInInlines(inlines, basePath, context, targets) {
5685
5693
  }
5686
5694
  }
5687
5695
  }
5688
- function createParagraphEditableTarget(paragraph, kind, storyKey2, blockPath, targetPosture = { editability: "editable", posture: { blockers: [] } }, contentControl, tableTarget, editableOwner) {
5696
+ function createParagraphEditableTarget(paragraph, kind, storyKey2, blockPath, targetPosture = { editability: "editable", posture: { blockers: [] } }, contentControl, tableTarget, editableOwner, listIdentity) {
5689
5697
  const paragraphText = collectParagraphText(paragraph);
5690
5698
  const paragraphTextHash = hashText(paragraphText);
5691
5699
  const sourceRef = paragraph.sourceRef;
@@ -5696,19 +5704,39 @@ function createParagraphEditableTarget(paragraph, kind, storyKey2, blockPath, ta
5696
5704
  context: { storyKey: storyKey2, insideSdt: contentControl !== void 0 },
5697
5705
  ...tableTarget
5698
5706
  }) : void 0;
5699
- const listAddress = paragraph.numbering !== void 0 ? createCanonicalAddress({
5707
+ const listAddress = listIdentity !== void 0 ? createCanonicalAddress({
5700
5708
  addressKind: "list-item-text",
5701
5709
  storyKey: storyKey2,
5702
5710
  staleCheckKind: "paragraph",
5703
5711
  operationScope: "list-text",
5704
- sourceRefs: [sourceRef],
5712
+ sourceRefs: [
5713
+ sourceRef,
5714
+ listIdentity.paragraphNumberingSourceRef,
5715
+ listIdentity.instanceSourceRef,
5716
+ listIdentity.abstractSourceRef
5717
+ ],
5705
5718
  staleHash: paragraphTextHash,
5706
5719
  rangeBoundary: { boundaryKind: "list-item-text" },
5720
+ list: {
5721
+ numberingOrigin: listIdentity.numberingOrigin,
5722
+ numberingInstanceId: listIdentity.numberingInstanceId,
5723
+ ...listIdentity.abstractNumberingId !== void 0 ? { abstractNumberingId: listIdentity.abstractNumberingId } : {},
5724
+ level: listIdentity.level,
5725
+ ...listIdentity.overrideHash !== void 0 ? { overrideHash: listIdentity.overrideHash } : {},
5726
+ numberingCatalogHash: listIdentity.numberingCatalogHash
5727
+ },
5707
5728
  discriminator: {
5708
5729
  blockPath,
5709
- numberingInstanceId: paragraph.numbering.numberingInstanceId,
5710
- level: paragraph.numbering.level,
5730
+ numberingOrigin: listIdentity.numberingOrigin,
5731
+ numberingInstanceId: listIdentity.numberingInstanceId,
5732
+ abstractNumberingId: listIdentity.abstractNumberingId ?? null,
5733
+ level: listIdentity.level,
5734
+ overrideHash: listIdentity.overrideHash ?? null,
5735
+ numberingCatalogHash: listIdentity.numberingCatalogHash,
5711
5736
  sourceId: sourceRef?.sourceId ?? null,
5737
+ numberingSourceId: listIdentity.paragraphNumberingSourceRef?.sourceId ?? null,
5738
+ numberingInstanceSourceId: listIdentity.instanceSourceRef?.sourceId ?? null,
5739
+ abstractNumberingSourceId: listIdentity.abstractSourceRef?.sourceId ?? null,
5712
5740
  paraId: paragraph.wordExtensionIds?.paraId ?? null,
5713
5741
  textId: paragraph.wordExtensionIds?.textId ?? null
5714
5742
  }
@@ -5749,11 +5777,62 @@ function createParagraphEditableTarget(paragraph, kind, storyKey2, blockPath, ta
5749
5777
  blockType: "paragraph",
5750
5778
  ...paragraph.wordExtensionIds?.paraId !== void 0 ? { wordParaId: paragraph.wordExtensionIds.paraId } : {},
5751
5779
  ...paragraph.wordExtensionIds?.textId !== void 0 ? { wordTextId: paragraph.wordExtensionIds.textId } : {},
5752
- ...sourceRef !== void 0 ? { sourceRef } : {}
5780
+ ...sourceRef !== void 0 ? { sourceRef } : {},
5781
+ ...listIdentity !== void 0 ? {
5782
+ listNumberingOrigin: listIdentity.numberingOrigin,
5783
+ listNumberingInstanceId: listIdentity.numberingInstanceId,
5784
+ ...listIdentity.abstractNumberingId !== void 0 ? { listAbstractNumberingId: listIdentity.abstractNumberingId } : {},
5785
+ listLevel: listIdentity.level,
5786
+ ...listIdentity.overrideHash !== void 0 ? { listOverrideHash: listIdentity.overrideHash } : {},
5787
+ numberingCatalogHash: listIdentity.numberingCatalogHash
5788
+ } : {}
5753
5789
  },
5754
5790
  posture
5755
5791
  };
5756
5792
  }
5793
+ function resolveEditableParagraphListIdentity(paragraph, context) {
5794
+ const directNumbering = paragraph.numbering;
5795
+ const styleNumbering = directNumbering === void 0 && paragraph.styleId !== void 0 ? resolveParagraphStyleNumbering(context.doc, paragraph.styleId) : void 0;
5796
+ const numbering = directNumbering ?? styleNumbering;
5797
+ if (numbering === void 0) return void 0;
5798
+ const numberingCatalog = context.doc.numbering ?? { abstractDefinitions: {}, instances: {} };
5799
+ const instances = numberingCatalog.instances ?? {};
5800
+ const abstractDefinitions = numberingCatalog.abstractDefinitions ?? {};
5801
+ const instance = instances[numbering.numberingInstanceId];
5802
+ const abstractDefinition = instance !== void 0 ? abstractDefinitions[instance.abstractNumberingId] : void 0;
5803
+ const level = numbering.level ?? 0;
5804
+ const override = instance?.overrides.find((entry) => entry.level === level);
5805
+ const overrideHash = override !== void 0 ? hashText(JSON.stringify(numberingOverrideDiscriminator(override))) : void 0;
5806
+ return {
5807
+ numberingOrigin: directNumbering !== void 0 ? "paragraph" : "paragraph-style",
5808
+ numberingInstanceId: numbering.numberingInstanceId,
5809
+ ...instance?.abstractNumberingId !== void 0 ? { abstractNumberingId: instance.abstractNumberingId } : {},
5810
+ level,
5811
+ ...overrideHash !== void 0 ? { overrideHash } : {},
5812
+ numberingCatalogHash: context.numberingCatalogHash,
5813
+ ...directNumbering?.sourceRef !== void 0 ? { paragraphNumberingSourceRef: directNumbering.sourceRef } : {},
5814
+ ...instance?.sourceRef !== void 0 ? { instanceSourceRef: instance.sourceRef } : {},
5815
+ ...abstractDefinition?.sourceRef !== void 0 ? { abstractSourceRef: abstractDefinition.sourceRef } : {}
5816
+ };
5817
+ }
5818
+ function numberingOverrideDiscriminator(override) {
5819
+ return {
5820
+ level: override.level,
5821
+ startAt: override.startAt ?? null,
5822
+ sourceId: override.sourceRef?.sourceId ?? null,
5823
+ levelDefinition: override.levelDefinition === void 0 ? null : {
5824
+ sourceId: override.levelDefinition.sourceRef?.sourceId ?? null,
5825
+ format: override.levelDefinition.format ?? null,
5826
+ text: override.levelDefinition.text ?? null,
5827
+ startAt: override.levelDefinition.startAt ?? null,
5828
+ paragraphStyleId: override.levelDefinition.paragraphStyleId ?? null,
5829
+ isLegalNumbering: override.levelDefinition.isLegalNumbering ?? null,
5830
+ suffix: override.levelDefinition.suffix ?? null,
5831
+ restartAfterLevel: override.levelDefinition.restartAfterLevel ?? null,
5832
+ picBulletId: override.levelDefinition.picBulletId ?? null
5833
+ }
5834
+ };
5835
+ }
5757
5836
  function contentControlLocksContent(contentControl) {
5758
5837
  return contentControl?.lock !== void 0 && contentControl.lock !== "unlocked" && contentControl.lock !== "none";
5759
5838
  }
@@ -6522,6 +6601,7 @@ function createCanonicalAddress(input) {
6522
6601
  ...input.rowRange !== void 0 ? { rowRange: input.rowRange } : {},
6523
6602
  ...input.columnRange !== void 0 ? { columnRange: input.columnRange } : {},
6524
6603
  ...sourceHash !== void 0 ? { sourceJoinHash: sourceHash } : {},
6604
+ ...input.list !== void 0 ? { list: input.list } : {},
6525
6605
  ...input.secondaryStory === true ? { secondaryStory: true } : {},
6526
6606
  ...input.nestedTable === true ? { nestedTable: true } : {},
6527
6607
  ...input.insideSdt === true ? { insideSdt: true } : {},
@@ -6556,6 +6636,103 @@ function sourceJoinHash(refs) {
6556
6636
  if (sourceIds.length === 0) return void 0;
6557
6637
  return hashText(sourceIds.join("\0"));
6558
6638
  }
6639
+ var numberingCatalogHashCache = /* @__PURE__ */ new WeakMap();
6640
+ var numberingTargetHashCache = /* @__PURE__ */ new WeakMap();
6641
+ function createNumberingCatalogRevisionHash(doc) {
6642
+ const numbering = doc.numbering;
6643
+ if (numbering !== void 0) {
6644
+ const cached = numberingCatalogHashCache.get(numbering);
6645
+ if (cached !== void 0) return cached;
6646
+ const fresh = computeNumberingCatalogRevisionHash(doc);
6647
+ numberingCatalogHashCache.set(numbering, fresh);
6648
+ return fresh;
6649
+ }
6650
+ return computeNumberingCatalogRevisionHash(doc);
6651
+ }
6652
+ function computeNumberingCatalogRevisionHash(doc) {
6653
+ const catalog = doc.numbering ?? { abstractDefinitions: {}, instances: {} };
6654
+ const abstractDefinitions = catalog.abstractDefinitions ?? {};
6655
+ const instances = catalog.instances ?? {};
6656
+ const numPicBullets = catalog.numPicBullets ?? {};
6657
+ return hashText(JSON.stringify({
6658
+ abstractDefinitions: Object.keys(abstractDefinitions).sort().map((abstractNumberingId) => {
6659
+ const definition = abstractDefinitions[abstractNumberingId];
6660
+ return {
6661
+ abstractNumberingId,
6662
+ sourceId: definition.sourceRef?.sourceId ?? null,
6663
+ nsid: definition.nsid ?? null,
6664
+ tplc: definition.tplc ?? null,
6665
+ styleLink: definition.styleLink ?? null,
6666
+ numStyleLink: definition.numStyleLink ?? null,
6667
+ levels: definition.levels.map((level) => ({
6668
+ sourceId: level.sourceRef?.sourceId ?? null,
6669
+ level: level.level,
6670
+ format: level.format,
6671
+ text: level.text,
6672
+ startAt: level.startAt ?? null,
6673
+ paragraphStyleId: level.paragraphStyleId ?? null,
6674
+ isLegalNumbering: level.isLegalNumbering ?? null,
6675
+ suffix: level.suffix ?? null,
6676
+ restartAfterLevel: level.restartAfterLevel ?? null,
6677
+ picBulletId: level.picBulletId ?? null
6678
+ }))
6679
+ };
6680
+ }),
6681
+ instances: Object.keys(instances).sort().map((numberingInstanceId) => {
6682
+ const instance = instances[numberingInstanceId];
6683
+ return {
6684
+ numberingInstanceId,
6685
+ sourceId: instance.sourceRef?.sourceId ?? null,
6686
+ abstractNumberingId: instance.abstractNumberingId,
6687
+ overrides: instance.overrides.map(numberingOverrideDiscriminator)
6688
+ };
6689
+ }),
6690
+ numPicBullets: Object.keys(numPicBullets).sort().map((numPicBulletId) => {
6691
+ const picBullet = numPicBullets[numPicBulletId];
6692
+ return {
6693
+ numPicBulletId,
6694
+ sourceId: picBullet.sourceRef?.sourceId ?? null,
6695
+ mediaId: picBullet.mediaId ?? null,
6696
+ widthEmu: picBullet.widthEmu ?? null,
6697
+ heightEmu: picBullet.heightEmu ?? null
6698
+ };
6699
+ })
6700
+ }));
6701
+ }
6702
+ function createNumberingTargetRevisionHash(doc) {
6703
+ const numbering = doc.numbering;
6704
+ const styles = doc.styles;
6705
+ if (numbering !== void 0 && styles !== void 0) {
6706
+ let inner = numberingTargetHashCache.get(numbering);
6707
+ if (inner === void 0) {
6708
+ inner = /* @__PURE__ */ new WeakMap();
6709
+ numberingTargetHashCache.set(numbering, inner);
6710
+ }
6711
+ const cached = inner.get(styles);
6712
+ if (cached !== void 0) return cached;
6713
+ const fresh = computeNumberingTargetRevisionHash(doc);
6714
+ inner.set(styles, fresh);
6715
+ return fresh;
6716
+ }
6717
+ return computeNumberingTargetRevisionHash(doc);
6718
+ }
6719
+ function computeNumberingTargetRevisionHash(doc) {
6720
+ const paragraphStyles = doc.styles?.paragraphs ?? {};
6721
+ return hashText(JSON.stringify({
6722
+ // Reuses the memoized catalog hash on the hot path so a typing edit
6723
+ // pays for the catalog hash at most once across both helpers.
6724
+ numberingCatalogHash: createNumberingCatalogRevisionHash(doc),
6725
+ paragraphStyleNumbering: Object.keys(paragraphStyles).sort().map((styleId) => {
6726
+ const style = paragraphStyles[styleId];
6727
+ return {
6728
+ styleId,
6729
+ basedOn: style.basedOn ?? null,
6730
+ numberingInstanceId: style.numbering?.numberingInstanceId ?? null,
6731
+ level: style.numbering?.level ?? null
6732
+ };
6733
+ })
6734
+ }));
6735
+ }
6559
6736
  function validateEditableTargetRef(value, path = "$") {
6560
6737
  const issues = [];
6561
6738
  const record = asPlainObject(value, path, issues);
@@ -6655,6 +6832,32 @@ function validateEditableTargetRef(value, path = "$") {
6655
6832
  if (staleCheck.sourceRef !== void 0) {
6656
6833
  validateTargetSourceRef(staleCheck.sourceRef, `${path}.staleCheck.sourceRef`, issues);
6657
6834
  }
6835
+ if (staleCheck.listNumberingOrigin !== void 0) {
6836
+ validateEnum(
6837
+ staleCheck.listNumberingOrigin,
6838
+ EDITABLE_TARGET_LIST_NUMBERING_ORIGINS,
6839
+ `${path}.staleCheck.listNumberingOrigin`,
6840
+ issues
6841
+ );
6842
+ }
6843
+ if (staleCheck.listNumberingInstanceId !== void 0) {
6844
+ expectString(staleCheck.listNumberingInstanceId, `${path}.staleCheck.listNumberingInstanceId`, issues);
6845
+ }
6846
+ if (staleCheck.listAbstractNumberingId !== void 0) {
6847
+ expectString(staleCheck.listAbstractNumberingId, `${path}.staleCheck.listAbstractNumberingId`, issues);
6848
+ }
6849
+ if (staleCheck.listLevel !== void 0 && (typeof staleCheck.listLevel !== "number" || !Number.isInteger(staleCheck.listLevel) || staleCheck.listLevel < 0)) {
6850
+ issues.push({
6851
+ path: `${path}.staleCheck.listLevel`,
6852
+ message: "listLevel must be a non-negative integer when present."
6853
+ });
6854
+ }
6855
+ if (staleCheck.listOverrideHash !== void 0) {
6856
+ validateSha256(staleCheck.listOverrideHash, `${path}.staleCheck.listOverrideHash`, issues);
6857
+ }
6858
+ if (staleCheck.numberingCatalogHash !== void 0) {
6859
+ validateSha256(staleCheck.numberingCatalogHash, `${path}.staleCheck.numberingCatalogHash`, issues);
6860
+ }
6658
6861
  }
6659
6862
  const posture = asPlainObject(record.posture, `${path}.posture`, issues);
6660
6863
  if (posture) {
@@ -6872,6 +7075,9 @@ function validateTargetCanonicalAddress(value, path, issues) {
6872
7075
  if (record.sourceJoinHash !== void 0) {
6873
7076
  validateSha256(record.sourceJoinHash, `${path}.sourceJoinHash`, issues);
6874
7077
  }
7078
+ if (record.list !== void 0) {
7079
+ validateTargetListAddressIdentity(record.list, `${path}.list`, issues);
7080
+ }
6875
7081
  if (record.resolver !== void 0) {
6876
7082
  validateTargetCanonicalAddressResolver(record.resolver, `${path}.resolver`, issues);
6877
7083
  }
@@ -6881,6 +7087,22 @@ function validateTargetCanonicalAddress(value, path, issues) {
6881
7087
  }
6882
7088
  }
6883
7089
  }
7090
+ function validateTargetListAddressIdentity(value, path, issues) {
7091
+ const record = asPlainObject(value, path, issues);
7092
+ if (!record) return;
7093
+ validateEnum(record.numberingOrigin, EDITABLE_TARGET_LIST_NUMBERING_ORIGINS, `${path}.numberingOrigin`, issues);
7094
+ expectString(record.numberingInstanceId, `${path}.numberingInstanceId`, issues);
7095
+ if (record.abstractNumberingId !== void 0) {
7096
+ expectString(record.abstractNumberingId, `${path}.abstractNumberingId`, issues);
7097
+ }
7098
+ if (typeof record.level !== "number" || !Number.isInteger(record.level) || record.level < 0) {
7099
+ issues.push({ path: `${path}.level`, message: "level must be a non-negative integer." });
7100
+ }
7101
+ if (record.overrideHash !== void 0) {
7102
+ validateSha256(record.overrideHash, `${path}.overrideHash`, issues);
7103
+ }
7104
+ validateSha256(record.numberingCatalogHash, `${path}.numberingCatalogHash`, issues);
7105
+ }
6884
7106
  function validateTargetCanonicalAddressResolver(value, path, issues) {
6885
7107
  const record = asPlainObject(value, path, issues);
6886
7108
  if (!record) return;
@@ -7018,6 +7240,10 @@ var EDITABLE_TARGET_COMMAND_FAMILIES = /* @__PURE__ */ new Set([
7018
7240
  "preserve-only-refusal"
7019
7241
  ]);
7020
7242
  var EDITABLE_TARGET_EDITABILITY = /* @__PURE__ */ new Set(["editable", "non-editable"]);
7243
+ var EDITABLE_TARGET_LIST_NUMBERING_ORIGINS = /* @__PURE__ */ new Set([
7244
+ "paragraph",
7245
+ "paragraph-style"
7246
+ ]);
7021
7247
  var EDITABLE_TARGET_BLOCKERS = /* @__PURE__ */ new Set([
7022
7248
  "protected-section",
7023
7249
  "protected-range",
@@ -7217,7 +7443,7 @@ function resolveParagraphStyleNumbering(doc, styleId) {
7217
7443
  let currentStyleId = styleId;
7218
7444
  while (currentStyleId !== void 0 && !visited.has(currentStyleId)) {
7219
7445
  visited.add(currentStyleId);
7220
- const style = doc.styles.paragraphs[currentStyleId];
7446
+ const style = doc.styles?.paragraphs?.[currentStyleId];
7221
7447
  if (style === void 0) {
7222
7448
  return void 0;
7223
7449
  }
@@ -9431,6 +9657,10 @@ function createNumberingPrefixResolver(catalog) {
9431
9657
  ])
9432
9658
  ) : resolved.effectiveLevels;
9433
9659
  const picBulletId = resolved.effectiveLevel.picBulletId;
9660
+ const pictureBulletPosture = resolvePictureBulletRenderPosture(
9661
+ picBulletId,
9662
+ picBulletId != null ? catalog.numPicBullets?.[picBulletId] : void 0
9663
+ );
9434
9664
  const text = renderLevelText(
9435
9665
  resolved.effectiveLevel.text,
9436
9666
  workingState.counters,
@@ -9439,14 +9669,20 @@ function createNumberingPrefixResolver(catalog) {
9439
9669
  if (picBulletId == null && resolved.effectiveLevel.format !== "none" && text === null) {
9440
9670
  return null;
9441
9671
  }
9442
- const visibleText = resolved.effectiveLevel.format === "none" ? null : text;
9672
+ const visibleText = resolved.effectiveLevel.format === "none" ? null : text ?? pictureBulletPosture?.fallbackGlyph ?? null;
9673
+ const normalizedMarkerText = normalizeMarkerText(
9674
+ visibleText,
9675
+ resolved.effectiveLevel.format,
9676
+ resolved.geometry.markerRunProperties
9677
+ );
9443
9678
  const formatPosture = getNumberingFormatPosture(
9444
9679
  resolved.effectiveLevel.format,
9445
9680
  currentCounter
9446
9681
  );
9447
- const picBulletMediaId = picBulletId != null ? catalog.numPicBullets?.[picBulletId]?.mediaId : void 0;
9682
+ const picBulletMediaId = pictureBulletPosture?.mediaId;
9448
9683
  return {
9449
- text: visibleText,
9684
+ text: normalizedMarkerText.text,
9685
+ ...normalizedMarkerText.posture !== void 0 ? { markerTextPosture: normalizedMarkerText.posture } : {},
9450
9686
  level: resolved.effectiveLevel.level,
9451
9687
  format: resolved.effectiveLevel.format,
9452
9688
  ...formatPosture !== void 0 ? { formatPosture } : {},
@@ -9456,7 +9692,9 @@ function createNumberingPrefixResolver(catalog) {
9456
9692
  ...resolved.effectiveLevel.isLegalNumbering ? { isLegalNumbering: true } : {},
9457
9693
  ...resolved.geometry.markerRunProperties ? { markerRunProperties: resolved.geometry.markerRunProperties } : {},
9458
9694
  geometry: resolved.geometry,
9459
- ...picBulletMediaId != null ? { picBulletMediaId } : {}
9695
+ ...picBulletId != null ? { picBulletId } : {},
9696
+ ...picBulletMediaId != null ? { picBulletMediaId } : {},
9697
+ ...pictureBulletPosture !== void 0 ? { pictureBulletPosture } : {}
9460
9698
  };
9461
9699
  }
9462
9700
  return {
@@ -9472,6 +9710,69 @@ function createNumberingPrefixResolver(catalog) {
9472
9710
  }
9473
9711
  };
9474
9712
  }
9713
+ function normalizeMarkerText(text, format, markerRunProperties) {
9714
+ if (text === null || format !== "bullet") {
9715
+ return { text };
9716
+ }
9717
+ const fontFamily = getMarkerFontFamily(markerRunProperties);
9718
+ if (!isKnownSymbolBulletFont(fontFamily)) {
9719
+ return { text };
9720
+ }
9721
+ const renderedText = Array.from(text, (char) => SYMBOL_BULLET_GLYPH_MAP.get(char) ?? char).join("");
9722
+ if (renderedText === text) {
9723
+ return { text };
9724
+ }
9725
+ return {
9726
+ text: renderedText,
9727
+ posture: {
9728
+ status: "normalized",
9729
+ sourceText: text,
9730
+ renderedText,
9731
+ reason: "symbol-font-bullet-normalized",
9732
+ ...fontFamily ? { fontFamily } : {}
9733
+ }
9734
+ };
9735
+ }
9736
+ function getMarkerFontFamily(markerRunProperties) {
9737
+ return markerRunProperties?.fontFamilyAscii ?? markerRunProperties?.fontFamilyHAnsi ?? markerRunProperties?.fontFamilyEastAsia ?? markerRunProperties?.fontFamilyCs ?? markerRunProperties?.fontFamily;
9738
+ }
9739
+ function isKnownSymbolBulletFont(fontFamily) {
9740
+ return fontFamily !== void 0 && /^(?:symbol|wingdings|wingdings 2|wingdings 3|webdings)$/iu.test(
9741
+ fontFamily.trim()
9742
+ );
9743
+ }
9744
+ var SYMBOL_BULLET_GLYPH_MAP = /* @__PURE__ */ new Map([
9745
+ ["\uF0B7", "\u2022"],
9746
+ ["\uF0A7", "\u25AA"],
9747
+ ["\uF0FC", "\u2713"]
9748
+ ]);
9749
+ function resolvePictureBulletRenderPosture(picBulletId, picBullet) {
9750
+ if (picBulletId == null) return void 0;
9751
+ if (!picBullet) {
9752
+ return {
9753
+ status: "preserve-only",
9754
+ picBulletId,
9755
+ fallbackGlyph: "\u2022",
9756
+ reason: "picture-bullet-catalog-entry-missing"
9757
+ };
9758
+ }
9759
+ if (picBullet.mediaId) {
9760
+ return {
9761
+ status: "media-rendered",
9762
+ picBulletId,
9763
+ mediaId: picBullet.mediaId,
9764
+ ...picBullet.sourceRef ? { sourceRef: picBullet.sourceRef } : {},
9765
+ reason: "picture-bullet-media-rendered"
9766
+ };
9767
+ }
9768
+ return {
9769
+ status: "glyph-fallback",
9770
+ picBulletId,
9771
+ fallbackGlyph: "\u2022",
9772
+ ...picBullet.sourceRef ? { sourceRef: picBullet.sourceRef } : {},
9773
+ reason: "picture-bullet-media-unavailable"
9774
+ };
9775
+ }
9475
9776
  function getSequenceState(states, numberingInstanceId, options = { create: true }) {
9476
9777
  const existing = states.get(numberingInstanceId);
9477
9778
  if (existing) {
@@ -9534,7 +9835,7 @@ function getNumberingFormatPosture(format, value) {
9534
9835
  reason: registryEntry?.fallbackReason ?? "unsupported-numbering-format-decimal-fallback"
9535
9836
  };
9536
9837
  }
9537
- if (value !== void 0 && ((format === "upperRoman" || format === "lowerRoman") && (value <= 0 || value >= 4e3) || (format === "cardinalText" || format === "ordinalText") && (!Number.isInteger(value) || value < 1 || value > 999) || (format === "upperLetter" || format === "lowerLetter" || format === "chicago") && value < 1)) {
9838
+ if (value !== void 0 && (registryEntry.isInRange !== void 0 && !registryEntry.isInRange(value) || (format === "upperRoman" || format === "lowerRoman") && (value <= 0 || value >= 4e3) || (format === "cardinalText" || format === "ordinalText") && (!Number.isInteger(value) || value < 1 || value > 999) || (format === "upperLetter" || format === "lowerLetter" || format === "chicago") && value < 1)) {
9538
9839
  return {
9539
9840
  status: "approximated",
9540
9841
  requestedFormat: format,
@@ -9628,6 +9929,37 @@ var exactNumberingFormatEntries = [
9628
9929
  supportsMutation: true,
9629
9930
  render: toOrdinal2
9630
9931
  },
9932
+ {
9933
+ format: "decimalFullWidth",
9934
+ renderSupport: "supported",
9935
+ renderedFormat: "decimalFullWidth",
9936
+ supportsMutation: false,
9937
+ render: toFullWidthDecimal
9938
+ },
9939
+ {
9940
+ format: "decimalEnclosedCircle",
9941
+ renderSupport: "supported",
9942
+ renderedFormat: "decimalEnclosedCircle",
9943
+ supportsMutation: false,
9944
+ render: toCircledDecimal,
9945
+ isInRange: (value) => Number.isInteger(value) && value >= 0 && value <= 50
9946
+ },
9947
+ {
9948
+ format: "decimalEnclosedParen",
9949
+ renderSupport: "supported",
9950
+ renderedFormat: "decimalEnclosedParen",
9951
+ supportsMutation: false,
9952
+ render: (value) => Number.isInteger(value) && value > 0 ? `(${value})` : String(value),
9953
+ isInRange: (value) => Number.isInteger(value) && value > 0
9954
+ },
9955
+ {
9956
+ format: "decimalEnclosedFullstop",
9957
+ renderSupport: "supported",
9958
+ renderedFormat: "decimalEnclosedFullstop",
9959
+ supportsMutation: false,
9960
+ render: (value) => Number.isInteger(value) && value > 0 ? `${value}.` : String(value),
9961
+ isInRange: (value) => Number.isInteger(value) && value > 0
9962
+ },
9631
9963
  {
9632
9964
  format: "cardinalText",
9633
9965
  renderSupport: "supported",
@@ -9665,10 +9997,6 @@ var exactNumberingFormatEntries = [
9665
9997
  }
9666
9998
  ];
9667
9999
  var approximatedDecimalFormats = [
9668
- "decimalEnclosedCircle",
9669
- "decimalEnclosedFullstop",
9670
- "decimalEnclosedParen",
9671
- "decimalFullWidth",
9672
10000
  "decimalHalfWidth",
9673
10001
  "aiueo",
9674
10002
  "iroha",
@@ -9720,6 +10048,30 @@ function toOrdinal2(value) {
9720
10048
  return `${value}th`;
9721
10049
  }
9722
10050
  }
10051
+ function toFullWidthDecimal(value) {
10052
+ return String(value).replace(
10053
+ /[0-9]/g,
10054
+ (digit) => String.fromCharCode(65296 + Number.parseInt(digit, 10))
10055
+ );
10056
+ }
10057
+ var CIRCLED_DECIMAL_BY_VALUE = new Map([
10058
+ [0, "\u24EA"],
10059
+ ...Array.from({ length: 20 }, (_, index) => [
10060
+ index + 1,
10061
+ String.fromCodePoint(9312 + index)
10062
+ ]),
10063
+ ...Array.from({ length: 15 }, (_, index) => [
10064
+ index + 21,
10065
+ String.fromCodePoint(12881 + index)
10066
+ ]),
10067
+ ...Array.from({ length: 15 }, (_, index) => [
10068
+ index + 36,
10069
+ String.fromCodePoint(12977 + index)
10070
+ ])
10071
+ ]);
10072
+ function toCircledDecimal(value) {
10073
+ return CIRCLED_DECIMAL_BY_VALUE.get(value) ?? String(value);
10074
+ }
9723
10075
  function toAlphabetic2(value) {
9724
10076
  if (value <= 0) {
9725
10077
  return String(value);
@@ -10470,8 +10822,8 @@ function toLayoutTabStops(tabStops, source) {
10470
10822
  }
10471
10823
  function mergeLayoutTabStops(...groups) {
10472
10824
  const byKey = /* @__PURE__ */ new Map();
10473
- for (const group of groups) {
10474
- for (const tabStop of group ?? []) {
10825
+ for (const group2 of groups) {
10826
+ for (const tabStop of group2 ?? []) {
10475
10827
  const key = [
10476
10828
  tabStop.source,
10477
10829
  tabStop.positionTwips,
@@ -10493,6 +10845,7 @@ function toNumberingLayoutInput(numbering) {
10493
10845
  const hangingTwips = textColumn?.hanging ?? numbering.geometry.indentation?.hanging ?? (typeof numbering.geometry.indentation?.firstLine === "number" && numbering.geometry.indentation.firstLine < 0 ? Math.abs(numbering.geometry.indentation.firstLine) : void 0);
10494
10846
  return {
10495
10847
  markerText: numbering.text,
10848
+ ...numbering.markerTextPosture ? { markerTextPosture: { ...numbering.markerTextPosture } } : {},
10496
10849
  ...numbering.markerRunProperties ? { markerRunFormatting: numbering.markerRunProperties } : {},
10497
10850
  markerSuffix: normalizeNumberingMarkerSuffix(numbering.suffix),
10498
10851
  ...markerLane ? { markerLaneStartTwips: markerLane.start } : {},
@@ -10505,7 +10858,9 @@ function toNumberingLayoutInput(numbering) {
10505
10858
  ...numbering.formatPosture !== void 0 ? { formatPosture: { ...numbering.formatPosture } } : {},
10506
10859
  startAt: numbering.startAt,
10507
10860
  ...numbering.isLegalNumbering ? { isLegalNumbering: true } : {},
10508
- ...numbering.picBulletMediaId ? { pictureBulletMediaId: numbering.picBulletMediaId } : {}
10861
+ ...numbering.picBulletId ? { pictureBulletId: numbering.picBulletId } : {},
10862
+ ...numbering.picBulletMediaId ? { pictureBulletMediaId: numbering.picBulletMediaId } : {},
10863
+ ...numbering.pictureBulletPosture ? { pictureBulletPosture: { ...numbering.pictureBulletPosture } } : {}
10509
10864
  };
10510
10865
  }
10511
10866
  function toFieldLayoutInput(entry, resolved, region) {
@@ -11017,6 +11372,7 @@ function buildEffectiveNumbering(detail) {
11017
11372
  const result = {
11018
11373
  level: detail.level,
11019
11374
  ...detail.text !== null ? { marker: detail.text } : {},
11375
+ ...detail.markerTextPosture ? { markerTextPosture: { ...detail.markerTextPosture } } : {},
11020
11376
  ...detail.markerRunProperties ? { markerRunFormatting: detail.markerRunProperties } : {},
11021
11377
  ...detail.geometry ? {
11022
11378
  indentation: {
@@ -11026,7 +11382,8 @@ function buildEffectiveNumbering(detail) {
11026
11382
  ...detail.geometry.tabStops && detail.geometry.tabStops.length > 0 ? { tab: detail.geometry.tabStops[0].position } : {}
11027
11383
  }
11028
11384
  } : {},
11029
- ...detail.picBulletMediaId ? { pictureBulletRef: detail.picBulletMediaId } : {}
11385
+ ...detail.picBulletMediaId ? { pictureBulletRef: detail.picBulletMediaId } : {},
11386
+ ...detail.pictureBulletPosture ? { pictureBulletPosture: { ...detail.pictureBulletPosture } } : {}
11030
11387
  };
11031
11388
  return result;
11032
11389
  }
@@ -11051,7 +11408,7 @@ function collectParagraphCompatFlags(paragraph) {
11051
11408
  return flags;
11052
11409
  }
11053
11410
  function mergeCompatFlags(...groups) {
11054
- return [...new Set(groups.flatMap((group) => group ?? []))].sort();
11411
+ return [...new Set(groups.flatMap((group2) => group2 ?? []))].sort();
11055
11412
  }
11056
11413
  function buildRevisionRangeIndex(doc) {
11057
11414
  const records = [];
@@ -13024,6 +13381,7 @@ function toSurfaceResolvedNumbering(numbering) {
13024
13381
  format: numbering.format,
13025
13382
  ...numbering.formatPosture !== void 0 ? { formatPosture: { ...numbering.formatPosture } } : {},
13026
13383
  ...numbering.text !== null ? { text: numbering.text } : {},
13384
+ ...numbering.markerTextPosture !== void 0 ? { markerTextPosture: { ...numbering.markerTextPosture } } : {},
13027
13385
  startAt: numbering.startAt,
13028
13386
  ...numbering.paragraphStyleId ? { paragraphStyleId: numbering.paragraphStyleId } : {},
13029
13387
  ...numbering.isLegalNumbering ? { isLegalNumbering: true } : {},
@@ -13036,7 +13394,9 @@ function toSurfaceResolvedNumbering(numbering) {
13036
13394
  ...numbering.geometry.markerLane ? { markerLane: { ...numbering.geometry.markerLane } } : {},
13037
13395
  ...numbering.geometry.textColumn ? { textColumn: { ...numbering.geometry.textColumn } } : {}
13038
13396
  },
13039
- ...numbering.picBulletMediaId ? { picBulletMediaId: numbering.picBulletMediaId } : {}
13397
+ ...numbering.picBulletId ? { picBulletId: numbering.picBulletId } : {},
13398
+ ...numbering.picBulletMediaId ? { picBulletMediaId: numbering.picBulletMediaId } : {},
13399
+ ...numbering.pictureBulletPosture ? { pictureBulletPosture: { ...numbering.pictureBulletPosture } } : {}
13040
13400
  };
13041
13401
  }
13042
13402
  function describePreservedInlinePreview(payloadReference) {
@@ -13258,7 +13618,38 @@ var TextTransactionError = class extends Error {
13258
13618
  this.code = code;
13259
13619
  }
13260
13620
  };
13621
+ function isUsableScopeSurface(surface, document2) {
13622
+ if (surface.viewportBlockRanges !== null) return false;
13623
+ const root = document2.content;
13624
+ if (!root || root.type !== "doc" || !Array.isArray(root.children)) {
13625
+ return false;
13626
+ }
13627
+ return surface.blocks.length === root.children.length;
13628
+ }
13629
+ function createScopeSurfaceCache(document2, selection, precomputedSurface, telemetry) {
13630
+ let cached;
13631
+ if (precomputedSurface && isUsableScopeSurface(precomputedSurface, document2)) {
13632
+ cached = precomputedSurface;
13633
+ telemetry?.onPrecomputedSurfaceHit?.();
13634
+ }
13635
+ return {
13636
+ get() {
13637
+ if (cached) return cached;
13638
+ telemetry?.onScopeSurfaceBuild?.();
13639
+ cached = createEditorSurfaceSnapshot(document2, selection, void 0, {
13640
+ editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX
13641
+ });
13642
+ return cached;
13643
+ }
13644
+ };
13645
+ }
13261
13646
  function applyTextTransaction(document2, selection, intent, options) {
13647
+ const scopeSurfaceCache = createScopeSurfaceCache(
13648
+ document2,
13649
+ selection,
13650
+ options.precomputedSurface,
13651
+ options.surfaceTelemetry
13652
+ );
13262
13653
  if (options.textTarget) {
13263
13654
  if (options.textTarget.kind === "hyperlink-display") {
13264
13655
  const targetedHyperlinkResult = tryApplyHyperlinkDisplayTransaction(
@@ -13294,7 +13685,8 @@ function applyTextTransaction(document2, selection, intent, options) {
13294
13685
  document2,
13295
13686
  selection,
13296
13687
  intent,
13297
- options
13688
+ options,
13689
+ scopeSurfaceCache
13298
13690
  );
13299
13691
  if (targetedTableResult) {
13300
13692
  return targetedTableResult;
@@ -13308,7 +13700,8 @@ function applyTextTransaction(document2, selection, intent, options) {
13308
13700
  const tableStructureRefusal = resolveTargetlessTableStructureInsertRefusal(
13309
13701
  document2,
13310
13702
  selection,
13311
- intent
13703
+ intent,
13704
+ scopeSurfaceCache
13312
13705
  );
13313
13706
  if (tableStructureRefusal) {
13314
13707
  throw new TextTransactionError("unsupported_content", tableStructureRefusal);
@@ -13318,7 +13711,8 @@ function applyTextTransaction(document2, selection, intent, options) {
13318
13711
  document2,
13319
13712
  selection,
13320
13713
  intent,
13321
- options
13714
+ options,
13715
+ scopeSurfaceCache
13322
13716
  );
13323
13717
  if (topLevelParagraphResult) {
13324
13718
  return topLevelParagraphResult;
@@ -13327,7 +13721,8 @@ function applyTextTransaction(document2, selection, intent, options) {
13327
13721
  document2,
13328
13722
  selection,
13329
13723
  intent,
13330
- options
13724
+ options,
13725
+ scopeSurfaceCache
13331
13726
  );
13332
13727
  if (sdtScopedResult) {
13333
13728
  return sdtScopedResult;
@@ -13336,7 +13731,8 @@ function applyTextTransaction(document2, selection, intent, options) {
13336
13731
  document2,
13337
13732
  selection,
13338
13733
  intent,
13339
- options
13734
+ options,
13735
+ scopeSurfaceCache
13340
13736
  );
13341
13737
  if (tableScopedResult) {
13342
13738
  return tableScopedResult;
@@ -13389,9 +13785,9 @@ function applyLinearTextTransaction(document2, selection, intent, options) {
13389
13785
  storyText: createPlainText(nextStory)
13390
13786
  };
13391
13787
  }
13392
- function tryApplyTableParagraphTransaction(document2, selection, intent, options) {
13788
+ function tryApplyTableParagraphTransaction(document2, selection, intent, options, scopeSurfaceCache) {
13393
13789
  const tableTarget = options.textTarget?.kind === "table-paragraph" ? options.textTarget : void 0;
13394
- const scope = resolveTableParagraphScope(document2, selection, tableTarget);
13790
+ const scope = resolveTableParagraphScope(document2, selection, tableTarget, scopeSurfaceCache);
13395
13791
  if (!scope) {
13396
13792
  return null;
13397
13793
  }
@@ -13514,7 +13910,11 @@ function tryApplyTargetedTextLeafTransaction(document2, selection, intent, optio
13514
13910
  };
13515
13911
  }
13516
13912
  function tryApplyHyperlinkDisplayTransaction(document2, selection, intent, options) {
13517
- const scope = resolveTargetedHyperlinkDisplayScope(document2, selection, options.textTarget);
13913
+ const scope = resolveTargetedHyperlinkDisplayScope(
13914
+ document2,
13915
+ selection,
13916
+ options.textTarget
13917
+ );
13518
13918
  if (!scope) {
13519
13919
  return null;
13520
13920
  }
@@ -13572,8 +13972,8 @@ function tryApplyHyperlinkDisplayTransaction(document2, selection, intent, optio
13572
13972
  storyText: localResult.storyText
13573
13973
  };
13574
13974
  }
13575
- function tryApplyTopLevelSdtParagraphTransaction(document2, selection, intent, options) {
13576
- const scope = resolveTopLevelSdtParagraphScope(document2, selection);
13975
+ function tryApplyTopLevelSdtParagraphTransaction(document2, selection, intent, options, scopeSurfaceCache) {
13976
+ const scope = resolveTopLevelSdtParagraphScope(document2, selection, scopeSurfaceCache);
13577
13977
  if (!scope) {
13578
13978
  return null;
13579
13979
  }
@@ -13625,8 +14025,8 @@ function tryApplyTopLevelSdtParagraphTransaction(document2, selection, intent, o
13625
14025
  storyText: localResult.storyText
13626
14026
  };
13627
14027
  }
13628
- function tryApplyTopLevelParagraphTransaction(document2, selection, intent, options) {
13629
- const scope = resolveTopLevelParagraphScope(document2, selection);
14028
+ function tryApplyTopLevelParagraphTransaction(document2, selection, intent, options, scopeSurfaceCache) {
14029
+ const scope = resolveTopLevelParagraphScope(document2, selection, scopeSurfaceCache);
13630
14030
  if (!scope) {
13631
14031
  return null;
13632
14032
  }
@@ -13736,17 +14136,15 @@ function resolveTargetedHyperlinkDisplayScope(document2, selection, target) {
13736
14136
  replace: resolved.replace
13737
14137
  };
13738
14138
  }
13739
- function resolveTableParagraphScope(document2, selection, target) {
14139
+ function resolveTableParagraphScope(document2, selection, target, scopeSurfaceCache) {
13740
14140
  if (target) {
13741
- return resolveTargetedTableParagraphScope(document2, selection, target);
14141
+ return resolveTargetedTableParagraphScope(document2, selection, target, scopeSurfaceCache);
13742
14142
  }
13743
14143
  const root = document2.content;
13744
14144
  if (!root || root.type !== "doc" || !Array.isArray(root.children)) {
13745
14145
  return null;
13746
14146
  }
13747
- const surface = createEditorSurfaceSnapshot(document2, selection, void 0, {
13748
- editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX
13749
- });
14147
+ const surface = scopeSurfaceCache.get();
13750
14148
  const selectionFrom = Math.min(selection.anchor, selection.head);
13751
14149
  const selectionTo = Math.max(selection.anchor, selection.head);
13752
14150
  for (let blockIndex = 0; blockIndex < root.children.length; blockIndex += 1) {
@@ -13851,7 +14249,7 @@ function resolveTableParagraphScope(document2, selection, target) {
13851
14249
  }
13852
14250
  return null;
13853
14251
  }
13854
- function resolveTargetlessTableStructureInsertRefusal(document2, selection, intent) {
14252
+ function resolveTargetlessTableStructureInsertRefusal(document2, selection, intent, scopeSurfaceCache) {
13855
14253
  if (!isCollapsedInsertIntent(intent, selection)) {
13856
14254
  return null;
13857
14255
  }
@@ -13859,9 +14257,7 @@ function resolveTargetlessTableStructureInsertRefusal(document2, selection, inte
13859
14257
  if (!root || root.type !== "doc" || !Array.isArray(root.children)) {
13860
14258
  return null;
13861
14259
  }
13862
- const surface = createEditorSurfaceSnapshot(document2, selection, void 0, {
13863
- editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX
13864
- });
14260
+ const surface = scopeSurfaceCache.get();
13865
14261
  if (!selectionTouchesTableStructureBoundary(surface.blocks, selection.anchor)) {
13866
14262
  return null;
13867
14263
  }
@@ -13875,7 +14271,7 @@ function isCollapsedInsertIntent(intent, selection) {
13875
14271
  const rangeTo = intent.range ? Math.max(intent.range.from, intent.range.to) : Math.max(selection.anchor, selection.head);
13876
14272
  return rangeFrom === rangeTo;
13877
14273
  }
13878
- function resolveTargetedTableParagraphScope(document2, selection, target) {
14274
+ function resolveTargetedTableParagraphScope(document2, selection, target, scopeSurfaceCache) {
13879
14275
  const root = document2.content;
13880
14276
  if (!root || root.type !== "doc" || !Array.isArray(root.children)) {
13881
14277
  return null;
@@ -13888,7 +14284,8 @@ function resolveTargetedTableParagraphScope(document2, selection, target) {
13888
14284
  root,
13889
14285
  document2,
13890
14286
  selection,
13891
- target
14287
+ target,
14288
+ scopeSurfaceCache
13892
14289
  );
13893
14290
  if (targetScope) {
13894
14291
  return targetScope;
@@ -13911,9 +14308,7 @@ function resolveTargetedTableParagraphScope(document2, selection, target) {
13911
14308
  if (cell.verticalMerge === "continue") {
13912
14309
  return "unsupported";
13913
14310
  }
13914
- const surface = createEditorSurfaceSnapshot(document2, selection, void 0, {
13915
- editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX
13916
- });
14311
+ const surface = scopeSurfaceCache.get();
13917
14312
  const surfaceBlock = surface.blocks[target.tableBlockIndex];
13918
14313
  const surfaceRow = surfaceBlock?.kind === "table" ? surfaceBlock.rows[target.rowIndex] : void 0;
13919
14314
  const surfaceCell = surfaceRow?.cells[target.cellIndex];
@@ -13977,16 +14372,14 @@ function resolveTargetedTableParagraphScope(document2, selection, target) {
13977
14372
  }
13978
14373
  };
13979
14374
  }
13980
- function resolveTargetedTableParagraphScopeByPath(root, document2, selection, target) {
14375
+ function resolveTargetedTableParagraphScopeByPath(root, document2, selection, target, scopeSurfaceCache) {
13981
14376
  if (!target.blockPath) return null;
13982
14377
  const tokens = parseCanonicalBlockPath(target.blockPath);
13983
14378
  if (!tokens) return null;
13984
14379
  const resolved = resolveBlockPathInCanonicalBlocks(root.children, tokens, 0);
13985
14380
  if (!resolved || resolved.block.type !== "paragraph") return null;
13986
14381
  if (resolved.hasVerticalMergeContinuation) return null;
13987
- const surface = createEditorSurfaceSnapshot(document2, selection, void 0, {
13988
- editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX
13989
- });
14382
+ const surface = scopeSurfaceCache.get();
13990
14383
  const surfaceResolved = resolveBlockPathInSurfaceBlocks(surface.blocks, tokens, 0);
13991
14384
  if (!surfaceResolved || surfaceResolved.kind !== "paragraph") return null;
13992
14385
  if (surfaceResolved.hasVerticalMergeContinuation) return null;
@@ -14441,14 +14834,12 @@ function resolveBlockPathInSurfaceBlocks(blocks, tokens, tokenIndex, hasVertical
14441
14834
  hasVerticalMergeContinuation || cell.verticalMerge === "continue"
14442
14835
  );
14443
14836
  }
14444
- function resolveTopLevelParagraphScope(document2, selection) {
14837
+ function resolveTopLevelParagraphScope(document2, selection, scopeSurfaceCache) {
14445
14838
  const root = document2.content;
14446
14839
  if (!root || root.type !== "doc" || !Array.isArray(root.children)) {
14447
14840
  return null;
14448
14841
  }
14449
- const surface = createEditorSurfaceSnapshot(document2, selection, void 0, {
14450
- editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX
14451
- });
14842
+ const surface = scopeSurfaceCache.get();
14452
14843
  const selectionFrom = Math.min(selection.anchor, selection.head);
14453
14844
  const selectionTo = Math.max(selection.anchor, selection.head);
14454
14845
  for (let blockIndex = 0; blockIndex < root.children.length; blockIndex += 1) {
@@ -14477,14 +14868,12 @@ function resolveTopLevelParagraphScope(document2, selection) {
14477
14868
  }
14478
14869
  return null;
14479
14870
  }
14480
- function resolveTopLevelSdtParagraphScope(document2, selection) {
14871
+ function resolveTopLevelSdtParagraphScope(document2, selection, scopeSurfaceCache) {
14481
14872
  const root = document2.content;
14482
14873
  if (!root || root.type !== "doc" || !Array.isArray(root.children)) {
14483
14874
  return null;
14484
14875
  }
14485
- const surface = createEditorSurfaceSnapshot(document2, selection, void 0, {
14486
- editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX
14487
- });
14876
+ const surface = scopeSurfaceCache.get();
14488
14877
  const selectionFrom = Math.min(selection.anchor, selection.head);
14489
14878
  const selectionTo = Math.max(selection.anchor, selection.head);
14490
14879
  for (let blockIndex = 0; blockIndex < root.children.length; blockIndex += 1) {
@@ -15236,7 +15625,7 @@ function getTableCellRange(table, cell) {
15236
15625
  function breadcrumbItemsEqual(left, right) {
15237
15626
  return left.kind === right.kind && left.label === right.label && left.from === right.from && left.to === right.to;
15238
15627
  }
15239
- function applyFormattingOperationToDocument(document2, snapshot, operation) {
15628
+ function applyFormattingOperationToDocument(document2, snapshot, operation2) {
15240
15629
  const surface = snapshot.surface;
15241
15630
  if (!surface) {
15242
15631
  return {
@@ -15250,7 +15639,7 @@ function applyFormattingOperationToDocument(document2, snapshot, operation) {
15250
15639
  let changed = false;
15251
15640
  const selectionFrom = Math.min(snapshot.selection.anchor, snapshot.selection.head);
15252
15641
  const selectionTo = Math.max(snapshot.selection.anchor, snapshot.selection.head);
15253
- if (operation.type === "set-alignment" || operation.type === "indent" || operation.type === "outdent") {
15642
+ if (operation2.type === "set-alignment" || operation2.type === "indent" || operation2.type === "outdent") {
15254
15643
  visitParagraphBindings(root.children, surface.blocks, (paragraph, paragraphSurface) => {
15255
15644
  if (!selectionTouchesRange(
15256
15645
  snapshot.selection.anchor,
@@ -15260,7 +15649,7 @@ function applyFormattingOperationToDocument(document2, snapshot, operation) {
15260
15649
  )) {
15261
15650
  return;
15262
15651
  }
15263
- const paragraphChanged = operation.type === "set-alignment" ? applyAlignment(paragraph, operation.alignment) : applyIndentation(paragraph, operation.type === "indent" ? 1 : -1);
15652
+ const paragraphChanged = operation2.type === "set-alignment" ? applyAlignment(paragraph, operation2.alignment) : applyIndentation(paragraph, operation2.type === "indent" ? 1 : -1);
15264
15653
  changed = changed || paragraphChanged;
15265
15654
  });
15266
15655
  return {
@@ -15276,7 +15665,7 @@ function applyFormattingOperationToDocument(document2, snapshot, operation) {
15276
15665
  changed: false
15277
15666
  };
15278
15667
  }
15279
- const nextMarks = resolveMarkUpdater(snapshot, operation);
15668
+ const nextMarks = resolveMarkUpdater(snapshot, operation2);
15280
15669
  visitParagraphBindings(root.children, surface.blocks, (paragraph, paragraphSurface) => {
15281
15670
  if (!rangesOverlap(
15282
15671
  selectionFrom,
@@ -15305,10 +15694,10 @@ function applyFormattingOperationToDocument(document2, snapshot, operation) {
15305
15694
  changed
15306
15695
  };
15307
15696
  }
15308
- function applyTextMarkOperationToDocumentRange(document2, range, operation) {
15697
+ function applyTextMarkOperationToDocumentRange(document2, range, operation2) {
15309
15698
  const inputFrom = Math.min(range.from, range.to);
15310
15699
  const inputTo = Math.max(range.from, range.to);
15311
- const expandedRange = operation.type === "clear-mark" && operation.expandToFullHighlight === true ? expandRangeToCanonicalHighlightExtent(document2, inputFrom, inputTo) : { from: inputFrom, to: inputTo };
15700
+ const expandedRange = operation2.type === "clear-mark" && operation2.expandToFullHighlight === true ? expandRangeToCanonicalHighlightExtent(document2, inputFrom, inputTo) : { from: inputFrom, to: inputTo };
15312
15701
  const selectionFrom = expandedRange.from;
15313
15702
  const selectionTo = expandedRange.to;
15314
15703
  const selection = {
@@ -15327,17 +15716,17 @@ function applyTextMarkOperationToDocumentRange(document2, range, operation) {
15327
15716
  }
15328
15717
  const nextDocument = structuredClone(document2);
15329
15718
  const root = nextDocument.content;
15330
- const updateMarks = resolveTextMarkRangeUpdater(operation);
15719
+ const updateMarks = resolveTextMarkRangeUpdater(operation2);
15331
15720
  let changed = false;
15332
15721
  let cursor = 0;
15333
15722
  for (let blockIndex = 0; blockIndex < root.children.length; blockIndex += 1) {
15334
15723
  const block = root.children[blockIndex];
15335
15724
  const blockFrom = cursor;
15336
- const blockLength = block?.type === "paragraph" ? block.children.reduce(
15725
+ const blockLength2 = block?.type === "paragraph" ? block.children.reduce(
15337
15726
  (total, child) => total + inlineNodeLength(child),
15338
15727
  0
15339
15728
  ) : 1;
15340
- const blockTo = blockFrom + blockLength;
15729
+ const blockTo = blockFrom + blockLength2;
15341
15730
  if (block?.type === "paragraph" && rangesOverlap(selectionFrom, selectionTo, blockFrom, blockTo)) {
15342
15731
  const transformed = transformInlineNodes(
15343
15732
  block.children,
@@ -15370,11 +15759,11 @@ function expandRangeToCanonicalHighlightExtent(document2, inputFrom, inputTo) {
15370
15759
  for (let blockIndex = 0; blockIndex < root.children.length; blockIndex += 1) {
15371
15760
  const block = root.children[blockIndex];
15372
15761
  const blockFrom = cursor;
15373
- const blockLength = block.type === "paragraph" ? block.children.reduce(
15762
+ const blockLength2 = block.type === "paragraph" ? block.children.reduce(
15374
15763
  (total, child) => total + inlineNodeLength(child),
15375
15764
  0
15376
15765
  ) : 1;
15377
- const blockTo = blockFrom + blockLength;
15766
+ const blockTo = blockFrom + blockLength2;
15378
15767
  if (block.type === "paragraph" && rangesOverlap(inputFrom, inputTo, blockFrom, blockTo)) {
15379
15768
  const spans = collectInlineHighlightSpans(block.children, blockFrom).spans;
15380
15769
  const expanded = expandRangeWithinHighlightSpans(spans, inputFrom, inputTo);
@@ -15463,39 +15852,39 @@ function marksHaveVisualHighlight(marks) {
15463
15852
  (mark) => mark.type === "highlight" || mark.type === "backgroundColor"
15464
15853
  ) ?? false;
15465
15854
  }
15466
- function resolveTextMarkRangeUpdater(operation) {
15467
- if (operation.type === "set-mark") {
15855
+ function resolveTextMarkRangeUpdater(operation2) {
15856
+ if (operation2.type === "set-mark") {
15468
15857
  return (marks) => {
15469
15858
  const nextMarks = cloneMarks3(marks).filter(
15470
- (candidate) => candidate.type !== operation.mark.type
15859
+ (candidate) => candidate.type !== operation2.mark.type
15471
15860
  );
15472
- nextMarks.push({ ...operation.mark });
15861
+ nextMarks.push({ ...operation2.mark });
15473
15862
  return nextMarks.length > 0 ? nextMarks : void 0;
15474
15863
  };
15475
15864
  }
15476
15865
  return (marks) => {
15477
15866
  const nextMarks = cloneMarks3(marks).filter((candidate) => {
15478
- if (operation.mark === "visualHighlight") {
15867
+ if (operation2.mark === "visualHighlight") {
15479
15868
  return candidate.type !== "highlight" && candidate.type !== "backgroundColor";
15480
15869
  }
15481
- return candidate.type !== operation.mark;
15870
+ return candidate.type !== operation2.mark;
15482
15871
  });
15483
15872
  return nextMarks.length > 0 ? nextMarks : void 0;
15484
15873
  };
15485
15874
  }
15486
- function resolveMarkUpdater(snapshot, operation) {
15875
+ function resolveMarkUpdater(snapshot, operation2) {
15487
15876
  const formatting = getFormattingStateFromRenderSnapshot(snapshot);
15488
- switch (operation.type) {
15877
+ switch (operation2.type) {
15489
15878
  case "toggle":
15490
- return (marks) => toggleMarks(marks, operation.mark, !formatting[operation.mark]);
15879
+ return (marks) => toggleMarks(marks, operation2.mark, !formatting[operation2.mark]);
15491
15880
  case "set-font-family":
15492
- return (marks) => setMarkValue(marks, "fontFamily", sanitizeFontFamily(operation.fontFamily));
15881
+ return (marks) => setMarkValue(marks, "fontFamily", sanitizeFontFamily(operation2.fontFamily));
15493
15882
  case "set-font-size":
15494
- return (marks) => setMarkValue(marks, "fontSize", sanitizeFontSize(operation.size));
15883
+ return (marks) => setMarkValue(marks, "fontSize", sanitizeFontSize(operation2.size));
15495
15884
  case "set-text-color":
15496
- return (marks) => setMarkValue(marks, "textColor", sanitizeColor(operation.color));
15885
+ return (marks) => setMarkValue(marks, "textColor", sanitizeColor(operation2.color));
15497
15886
  case "set-highlight-color":
15498
- return (marks) => setMarkValue(marks, "backgroundColor", sanitizeColor(operation.color));
15887
+ return (marks) => setMarkValue(marks, "backgroundColor", sanitizeColor(operation2.color));
15499
15888
  }
15500
15889
  }
15501
15890
  function applyAlignment(paragraph, alignment) {
@@ -16830,7 +17219,7 @@ function findCellIndexAtColumn(row2, logicalColumn) {
16830
17219
  }
16831
17220
 
16832
17221
  // src/core/commands/table-structure-commands.ts
16833
- function applyTableStructureOperation(document2, snapshot, selectionDescriptor, operation) {
17222
+ function applyTableStructureOperation(document2, snapshot, selectionDescriptor, operation2) {
16834
17223
  const root = document2.content;
16835
17224
  const fallbackSelection = toInternalSelectionSnapshot(snapshot.selection);
16836
17225
  if (!root || root.type !== "doc") {
@@ -16844,11 +17233,11 @@ function applyTableStructureOperation(document2, snapshot, selectionDescriptor,
16844
17233
  if (!target || target.type !== "table") {
16845
17234
  return createNoopStructuralMutation(document2, fallbackSelection);
16846
17235
  }
16847
- switch (operation.type) {
17236
+ switch (operation2.type) {
16848
17237
  case "delete-table":
16849
17238
  return deleteTableBlock(document2, root, effectiveSelection.tableBlockIndex, fallbackSelection);
16850
17239
  case "set-cell-background":
16851
- return setCellBackground(document2, root, target, effectiveSelection, operation.color, fallbackSelection);
17240
+ return setCellBackground(document2, root, target, effectiveSelection, operation2.color, fallbackSelection);
16852
17241
  case "split-cell":
16853
17242
  return splitSelectedCell(document2, root, target, effectiveSelection, fallbackSelection);
16854
17243
  case "merge-cells":
@@ -16866,20 +17255,20 @@ function applyTableStructureOperation(document2, snapshot, selectionDescriptor,
16866
17255
  case "delete-column":
16867
17256
  return deleteColumn(document2, root, target, effectiveSelection, fallbackSelection);
16868
17257
  case "set-table-width":
16869
- return patchTable(document2, root, target, effectiveSelection, { width: operation.width }, fallbackSelection);
17258
+ return patchTable(document2, root, target, effectiveSelection, { width: operation2.width }, fallbackSelection);
16870
17259
  case "set-table-alignment":
16871
- return patchTable(document2, root, target, effectiveSelection, { alignment: operation.alignment }, fallbackSelection);
17260
+ return patchTable(document2, root, target, effectiveSelection, { alignment: operation2.alignment }, fallbackSelection);
16872
17261
  case "set-table-indent":
16873
- return patchTable(document2, root, target, effectiveSelection, { indent: operation.indent }, fallbackSelection);
17262
+ return patchTable(document2, root, target, effectiveSelection, { indent: operation2.indent }, fallbackSelection);
16874
17263
  case "set-table-layout-mode":
16875
- return patchTable(document2, root, target, effectiveSelection, { layoutMode: operation.mode }, fallbackSelection);
17264
+ return patchTable(document2, root, target, effectiveSelection, { layoutMode: operation2.mode }, fallbackSelection);
16876
17265
  case "set-table-cell-margins":
16877
17266
  return patchTable(
16878
17267
  document2,
16879
17268
  root,
16880
17269
  target,
16881
17270
  effectiveSelection,
16882
- { cellMargins: mergeTableCellMargins(target.cellMargins, operation.margins) },
17271
+ { cellMargins: mergeTableCellMargins(target.cellMargins, operation2.margins) },
16883
17272
  fallbackSelection
16884
17273
  );
16885
17274
  case "set-table-borders":
@@ -16888,7 +17277,7 @@ function applyTableStructureOperation(document2, snapshot, selectionDescriptor,
16888
17277
  root,
16889
17278
  target,
16890
17279
  effectiveSelection,
16891
- { borders: mergeTableBorders(target.borders, operation.borders) },
17280
+ { borders: mergeTableBorders(target.borders, operation2.borders) },
16892
17281
  fallbackSelection
16893
17282
  );
16894
17283
  case "set-table-style":
@@ -16897,7 +17286,7 @@ function applyTableStructureOperation(document2, snapshot, selectionDescriptor,
16897
17286
  root,
16898
17287
  target,
16899
17288
  effectiveSelection,
16900
- { styleId: operation.styleId ?? void 0 },
17289
+ { styleId: operation2.styleId ?? void 0 },
16901
17290
  fallbackSelection
16902
17291
  );
16903
17292
  case "set-table-caption":
@@ -16906,7 +17295,7 @@ function applyTableStructureOperation(document2, snapshot, selectionDescriptor,
16906
17295
  root,
16907
17296
  target,
16908
17297
  effectiveSelection,
16909
- { caption: operation.caption ?? void 0 },
17298
+ { caption: operation2.caption ?? void 0 },
16910
17299
  fallbackSelection
16911
17300
  );
16912
17301
  case "set-table-description":
@@ -16915,82 +17304,82 @@ function applyTableStructureOperation(document2, snapshot, selectionDescriptor,
16915
17304
  root,
16916
17305
  target,
16917
17306
  effectiveSelection,
16918
- { description: operation.description ?? void 0 },
17307
+ { description: operation2.description ?? void 0 },
16919
17308
  fallbackSelection
16920
17309
  );
16921
17310
  case "set-column-width":
16922
- return setColumnWidth(document2, root, target, effectiveSelection, operation.columnIndex, operation.twips, fallbackSelection);
17311
+ return setColumnWidth(document2, root, target, effectiveSelection, operation2.columnIndex, operation2.twips, fallbackSelection);
16923
17312
  case "distribute-columns-evenly":
16924
- return distributeColumnsEvenly(document2, root, target, effectiveSelection, operation.columnRange, fallbackSelection);
17313
+ return distributeColumnsEvenly(document2, root, target, effectiveSelection, operation2.columnRange, fallbackSelection);
16925
17314
  case "set-row-height":
16926
- return patchRow(document2, root, target, effectiveSelection, operation.rowIndex, {
16927
- height: operation.twips,
16928
- heightRule: operation.rule
17315
+ return patchRow(document2, root, target, effectiveSelection, operation2.rowIndex, {
17316
+ height: operation2.twips,
17317
+ heightRule: operation2.rule
16929
17318
  }, fallbackSelection);
16930
17319
  case "set-row-cant-split":
16931
- return patchRow(document2, root, target, effectiveSelection, operation.rowIndex, {
16932
- cantSplit: operation.value
17320
+ return patchRow(document2, root, target, effectiveSelection, operation2.rowIndex, {
17321
+ cantSplit: operation2.value
16933
17322
  }, fallbackSelection);
16934
17323
  case "set-row-is-header":
16935
- return patchRow(document2, root, target, effectiveSelection, operation.rowIndex, {
16936
- isHeader: operation.value
17324
+ return patchRow(document2, root, target, effectiveSelection, operation2.rowIndex, {
17325
+ isHeader: operation2.value
16937
17326
  }, fallbackSelection);
16938
17327
  case "set-row-alignment":
16939
- return patchRow(document2, root, target, effectiveSelection, operation.rowIndex, {
16940
- horizontalAlignment: operation.alignment
17328
+ return patchRow(document2, root, target, effectiveSelection, operation2.rowIndex, {
17329
+ horizontalAlignment: operation2.alignment
16941
17330
  }, fallbackSelection);
16942
17331
  case "insert-rows":
16943
- return insertRows(document2, root, target, effectiveSelection, operation.rowIndex, operation.at, operation.count, fallbackSelection);
17332
+ return insertRows(document2, root, target, effectiveSelection, operation2.rowIndex, operation2.at, operation2.count, fallbackSelection);
16944
17333
  case "insert-columns":
16945
- return insertColumns(document2, root, target, effectiveSelection, operation.columnIndex, operation.at, operation.count, operation.widths, fallbackSelection);
17334
+ return insertColumns(document2, root, target, effectiveSelection, operation2.columnIndex, operation2.at, operation2.count, operation2.widths, fallbackSelection);
16946
17335
  case "set-cell-borders":
16947
- return patchCells(document2, root, target, effectiveSelection, operation.locator, (cell) => ({
17336
+ return patchCells(document2, root, target, effectiveSelection, operation2.locator, (cell) => ({
16948
17337
  ...cell,
16949
- borders: mergeCellBorders(cell.borders, operation.borders)
17338
+ borders: mergeCellBorders(cell.borders, operation2.borders)
16950
17339
  }), fallbackSelection);
16951
17340
  case "set-cell-shading":
16952
- return patchCells(document2, root, target, effectiveSelection, operation.locator, (cell) => {
16953
- if (operation.shading === null) {
17341
+ return patchCells(document2, root, target, effectiveSelection, operation2.locator, (cell) => {
17342
+ if (operation2.shading === null) {
16954
17343
  const { shading: _drop, ...rest } = cell;
16955
17344
  return rest;
16956
17345
  }
16957
- return { ...cell, shading: { ...cell.shading ?? {}, ...operation.shading } };
17346
+ return { ...cell, shading: { ...cell.shading ?? {}, ...operation2.shading } };
16958
17347
  }, fallbackSelection);
16959
17348
  case "clear-cell-shading":
16960
- return patchCells(document2, root, target, effectiveSelection, operation.locator, (cell) => {
17349
+ return patchCells(document2, root, target, effectiveSelection, operation2.locator, (cell) => {
16961
17350
  const { shading: _drop, ...rest } = cell;
16962
17351
  return rest;
16963
17352
  }, fallbackSelection);
16964
17353
  case "set-cell-margins":
16965
- return patchCells(document2, root, target, effectiveSelection, operation.locator, (cell) => ({
17354
+ return patchCells(document2, root, target, effectiveSelection, operation2.locator, (cell) => ({
16966
17355
  ...cell,
16967
- margins: { ...cell.margins ?? {}, ...operation.margins }
17356
+ margins: { ...cell.margins ?? {}, ...operation2.margins }
16968
17357
  }), fallbackSelection);
16969
17358
  case "set-cell-vertical-align":
16970
- return patchCells(document2, root, target, effectiveSelection, operation.locator, (cell) => ({
17359
+ return patchCells(document2, root, target, effectiveSelection, operation2.locator, (cell) => ({
16971
17360
  ...cell,
16972
- verticalAlign: operation.align
17361
+ verticalAlign: operation2.align
16973
17362
  }), fallbackSelection);
16974
17363
  case "set-cell-text-direction":
16975
- return patchCells(document2, root, target, effectiveSelection, operation.locator, (cell) => ({
17364
+ return patchCells(document2, root, target, effectiveSelection, operation2.locator, (cell) => ({
16976
17365
  ...cell,
16977
- textDirection: operation.direction
17366
+ textDirection: operation2.direction
16978
17367
  }), fallbackSelection);
16979
17368
  case "set-cell-no-wrap":
16980
- return patchCells(document2, root, target, effectiveSelection, operation.locator, (cell) => ({
17369
+ return patchCells(document2, root, target, effectiveSelection, operation2.locator, (cell) => ({
16981
17370
  ...cell,
16982
- noWrap: operation.value
17371
+ noWrap: operation2.value
16983
17372
  }), fallbackSelection);
16984
17373
  case "set-cell-fit-text":
16985
- return patchCells(document2, root, target, effectiveSelection, operation.locator, (cell) => ({
17374
+ return patchCells(document2, root, target, effectiveSelection, operation2.locator, (cell) => ({
16986
17375
  ...cell,
16987
- fitText: operation.value
17376
+ fitText: operation2.value
16988
17377
  }), fallbackSelection);
16989
17378
  default:
16990
17379
  return createNoopStructuralMutation(document2, fallbackSelection);
16991
17380
  }
16992
17381
  }
16993
- function applyTableStructureOperationForEditableTarget(document2, snapshot, selectionDescriptor, operation, targetRef) {
17382
+ function applyTableStructureOperationForEditableTarget(document2, snapshot, selectionDescriptor, operation2, targetRef) {
16994
17383
  const tableIdentity = targetRef.table;
16995
17384
  const fallbackSelection = toInternalSelectionSnapshot(snapshot.selection);
16996
17385
  if (!tableIdentity || targetRef.commandFamily !== "table-structure") {
@@ -17025,7 +17414,7 @@ function applyTableStructureOperationForEditableTarget(document2, snapshot, sele
17025
17414
  localDocument,
17026
17415
  snapshot,
17027
17416
  { ...effectiveSelection, tableBlockIndex: 0 },
17028
- operation
17417
+ operation2
17029
17418
  );
17030
17419
  if (!localResult.changed) {
17031
17420
  return createNoopStructuralMutation(document2, fallbackSelection);
@@ -20699,13 +21088,14 @@ function mapRecordAnchor(anchor, mapping) {
20699
21088
  return toPublicAnchorProjection(mapAnchor(toInternalAnchorProjection(anchor), mapping));
20700
21089
  }
20701
21090
  function withCommandTextTarget(context, command) {
20702
- if (!command.textTarget || context.textTarget === command.textTarget) {
20703
- return context;
21091
+ let next = context;
21092
+ if (next.precomputedSurface === void 0 && next.renderSnapshot?.surface !== void 0) {
21093
+ next = { ...next, precomputedSurface: next.renderSnapshot.surface };
20704
21094
  }
20705
- return {
20706
- ...context,
20707
- textTarget: command.textTarget
20708
- };
21095
+ if (command.textTarget && next.textTarget !== command.textTarget) {
21096
+ next = { ...next, textTarget: command.textTarget };
21097
+ }
21098
+ return next;
20709
21099
  }
20710
21100
  function listCommandContext(context) {
20711
21101
  return {
@@ -24099,9 +24489,9 @@ function createSuggestionsSnapshot(trackedChanges) {
24099
24489
  const groups = /* @__PURE__ */ new Map();
24100
24490
  for (const revision of trackedChanges.revisions) {
24101
24491
  const suggestionId = revision.suggestionId ?? revision.revisionId;
24102
- const group = groups.get(suggestionId);
24103
- if (group) {
24104
- group.push(revision);
24492
+ const group2 = groups.get(suggestionId);
24493
+ if (group2) {
24494
+ group2.push(revision);
24105
24495
  } else {
24106
24496
  groups.set(suggestionId, [revision]);
24107
24497
  }
@@ -24148,15 +24538,15 @@ function createSuggestionsSnapshot(trackedChanges) {
24148
24538
  };
24149
24539
  }
24150
24540
 
24151
- // src/runtime/workflow/scope-resolver.ts
24152
- function inlineLength(node) {
24541
+ // src/core/commands/scope-coordinate-walk.ts
24542
+ function inlineLengthForScopeCoordinates(node) {
24153
24543
  switch (node.type) {
24154
24544
  case "text":
24155
24545
  return Array.from(node.text).length;
24156
24546
  case "hyperlink":
24157
24547
  case "field":
24158
24548
  return node.children.reduce(
24159
- (total, child) => total + inlineLength(child),
24549
+ (total, child) => total + inlineLengthForScopeCoordinates(child),
24160
24550
  0
24161
24551
  );
24162
24552
  case "bookmark_start":
@@ -24168,29 +24558,241 @@ function inlineLength(node) {
24168
24558
  return 1;
24169
24559
  }
24170
24560
  }
24171
- function walkParagraphs2(document2) {
24172
- const envelope = document2;
24173
- const root = "content" in envelope ? envelope.content : document2;
24174
- const out = [];
24561
+ function paragraphLengthForScopeCoordinates(paragraph) {
24562
+ return paragraph.children.reduce(
24563
+ (total, child) => total + inlineLengthForScopeCoordinates(child),
24564
+ 0
24565
+ );
24566
+ }
24567
+ function computeScopeStoryLayout(document2) {
24568
+ const root = document2.content;
24569
+ const paragraphSlots = [];
24570
+ const blockSlots = [];
24571
+ if (!root || root.type !== "doc") {
24572
+ return { paragraphSlots, blockSlots, storyLength: 0 };
24573
+ }
24175
24574
  let cursor = 0;
24176
24575
  for (let index = 0; index < root.children.length; index += 1) {
24177
24576
  const block = root.children[index];
24178
- if (block && block.type === "paragraph") {
24179
- out.push({ paragraph: block, from: cursor });
24180
- cursor += block.children.reduce(
24181
- (total, child) => total + inlineLength(child),
24182
- 0
24183
- );
24184
- } else if (block && block.type === "table") {
24185
- cursor += 1;
24186
- } else {
24577
+ if (!block) continue;
24578
+ cursor = walkBlockForScopeCoordinates(
24579
+ block,
24580
+ cursor,
24581
+ [{ kind: "block", index }],
24582
+ index,
24583
+ paragraphSlots,
24584
+ blockSlots
24585
+ );
24586
+ if (index < root.children.length - 1 && root.children[index + 1]?.type === "paragraph") {
24187
24587
  cursor += 1;
24188
24588
  }
24189
- if (index < root.children.length - 1) {
24190
- cursor += 1;
24589
+ }
24590
+ return { paragraphSlots, blockSlots, storyLength: cursor };
24591
+ }
24592
+ function findParagraphSlotAtPosition(layout, position, edge) {
24593
+ const matches = layout.paragraphSlots.filter(
24594
+ (slot) => position >= slot.from && position <= slot.to
24595
+ );
24596
+ if (matches.length === 0) return null;
24597
+ if (edge === "start") {
24598
+ return matches.find((slot) => slot.from === position) ?? matches.find((slot) => position > slot.from && position <= slot.to) ?? matches[0];
24599
+ }
24600
+ return matches.find((slot) => slot.to === position) ?? matches.find((slot) => position >= slot.from && position < slot.to) ?? matches[matches.length - 1];
24601
+ }
24602
+ function findOwningBlockSlotAtPosition(layout, position) {
24603
+ const matches = layout.blockSlots.filter(
24604
+ (slot) => position >= slot.from && position <= slot.to
24605
+ );
24606
+ if (matches.length === 0) return null;
24607
+ return matches.reduce(
24608
+ (best, slot) => slot.path.length >= best.path.length ? slot : best
24609
+ );
24610
+ }
24611
+ function sameScopeParagraphPath(a, b) {
24612
+ return scopeParagraphPathKey(a) === scopeParagraphPathKey(b);
24613
+ }
24614
+ function replaceParagraphChildrenAtPath(root, path, children) {
24615
+ return {
24616
+ ...root,
24617
+ children: replaceInBlockList(root.children, path, children)
24618
+ };
24619
+ }
24620
+ function removeScopeMarkersFromBlockList(blocks, scopeId) {
24621
+ let mutated = false;
24622
+ const nextBlocks = blocks.map((block) => {
24623
+ const result = removeScopeMarkersFromBlock(block, scopeId);
24624
+ if (result.mutated) mutated = true;
24625
+ return result.block;
24626
+ });
24627
+ return { blocks: nextBlocks, mutated };
24628
+ }
24629
+ function walkBlockForScopeCoordinates(block, cursor, path, rootBlockIndex, paragraphSlots, blockSlots) {
24630
+ const from = cursor;
24631
+ if (block.type === "paragraph") {
24632
+ const to2 = cursor + paragraphLengthForScopeCoordinates(block);
24633
+ const slot = { path, rootBlockIndex, kind: block.type, from, to: to2 };
24634
+ blockSlots.push(slot);
24635
+ paragraphSlots.push({ ...slot, paragraph: block });
24636
+ return to2;
24637
+ }
24638
+ if (block.type === "table") {
24639
+ let innerCursor = cursor;
24640
+ for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex += 1) {
24641
+ const row2 = block.rows[rowIndex];
24642
+ for (let cellIndex = 0; cellIndex < row2.cells.length; cellIndex += 1) {
24643
+ const cell = row2.cells[cellIndex];
24644
+ for (let childIndex = 0; childIndex < cell.children.length; childIndex += 1) {
24645
+ const child = cell.children[childIndex];
24646
+ innerCursor = walkBlockForScopeCoordinates(
24647
+ child,
24648
+ innerCursor,
24649
+ [
24650
+ ...path,
24651
+ { kind: "tableCell", rowIndex, cellIndex },
24652
+ { kind: "block", index: childIndex }
24653
+ ],
24654
+ rootBlockIndex,
24655
+ paragraphSlots,
24656
+ blockSlots
24657
+ );
24658
+ }
24659
+ }
24191
24660
  }
24661
+ blockSlots.push({
24662
+ path,
24663
+ rootBlockIndex,
24664
+ kind: block.type,
24665
+ from,
24666
+ to: innerCursor
24667
+ });
24668
+ return innerCursor;
24192
24669
  }
24193
- return out;
24670
+ if (block.type === "sdt") {
24671
+ const descriptor = describeStructuredWrapperBlock(block, {
24672
+ projectVisibleTocContentControls: true
24673
+ });
24674
+ if (descriptor) {
24675
+ const to2 = cursor + 1;
24676
+ blockSlots.push({ path, rootBlockIndex, kind: block.type, from, to: to2 });
24677
+ return to2;
24678
+ }
24679
+ let innerCursor = cursor;
24680
+ for (let childIndex = 0; childIndex < block.children.length; childIndex += 1) {
24681
+ const child = block.children[childIndex];
24682
+ innerCursor = walkBlockForScopeCoordinates(
24683
+ child,
24684
+ innerCursor,
24685
+ [...path, { kind: "sdtChildren" }, { kind: "block", index: childIndex }],
24686
+ rootBlockIndex,
24687
+ paragraphSlots,
24688
+ blockSlots
24689
+ );
24690
+ }
24691
+ blockSlots.push({
24692
+ path,
24693
+ rootBlockIndex,
24694
+ kind: block.type,
24695
+ from,
24696
+ to: innerCursor
24697
+ });
24698
+ return innerCursor;
24699
+ }
24700
+ const to = cursor + 1;
24701
+ blockSlots.push({ path, rootBlockIndex, kind: block.type, from, to });
24702
+ return to;
24703
+ }
24704
+ function replaceInBlockList(blocks, path, children) {
24705
+ const [head, ...rest] = path;
24706
+ if (!head || head.kind !== "block") return [...blocks];
24707
+ return blocks.map((block, index) => {
24708
+ if (index !== head.index) return block;
24709
+ if (rest.length === 0) {
24710
+ return block.type === "paragraph" ? { ...block, children } : block;
24711
+ }
24712
+ return replaceInsideBlock(block, rest, children);
24713
+ });
24714
+ }
24715
+ function replaceInsideBlock(block, path, children) {
24716
+ const [head, ...rest] = path;
24717
+ if (!head) return block;
24718
+ if (block.type === "table" && head.kind === "tableCell") {
24719
+ const rows = block.rows.map((row2, rowIndex) => {
24720
+ if (rowIndex !== head.rowIndex) return row2;
24721
+ const cells = row2.cells.map((cell, cellIndex) => {
24722
+ if (cellIndex !== head.cellIndex) return cell;
24723
+ return {
24724
+ ...cell,
24725
+ children: replaceInBlockList(cell.children, rest, children)
24726
+ };
24727
+ });
24728
+ return { ...row2, cells };
24729
+ });
24730
+ return { ...block, rows };
24731
+ }
24732
+ if (block.type === "sdt" && head.kind === "sdtChildren") {
24733
+ return {
24734
+ ...block,
24735
+ children: replaceInBlockList(block.children, rest, children)
24736
+ };
24737
+ }
24738
+ return block;
24739
+ }
24740
+ function removeScopeMarkersFromBlock(block, scopeId) {
24741
+ if (block.type === "paragraph") {
24742
+ const kept = block.children.filter((child) => {
24743
+ return !((child.type === "scope_marker_start" || child.type === "scope_marker_end") && child.scopeId === scopeId);
24744
+ });
24745
+ if (kept.length === block.children.length) {
24746
+ return { block, mutated: false };
24747
+ }
24748
+ return { block: { ...block, children: kept }, mutated: true };
24749
+ }
24750
+ if (block.type === "table") {
24751
+ let mutated = false;
24752
+ const rows = block.rows.map((row2) => {
24753
+ let rowMutated = false;
24754
+ const cells = row2.cells.map((cell) => {
24755
+ const result = removeScopeMarkersFromBlockList(cell.children, scopeId);
24756
+ if (result.mutated) {
24757
+ mutated = true;
24758
+ rowMutated = true;
24759
+ }
24760
+ return result.mutated ? { ...cell, children: result.blocks } : cell;
24761
+ });
24762
+ return rowMutated ? { ...row2, cells } : row2;
24763
+ });
24764
+ return mutated ? { block: { ...block, rows }, mutated: true } : { block, mutated: false };
24765
+ }
24766
+ if (block.type === "sdt") {
24767
+ const result = removeScopeMarkersFromBlockList(block.children, scopeId);
24768
+ return result.mutated ? { block: { ...block, children: result.blocks }, mutated: true } : { block, mutated: false };
24769
+ }
24770
+ if (block.type === "custom_xml") {
24771
+ const result = removeScopeMarkersFromBlockList(block.children, scopeId);
24772
+ return result.mutated ? { block: { ...block, children: result.blocks }, mutated: true } : { block, mutated: false };
24773
+ }
24774
+ return { block, mutated: false };
24775
+ }
24776
+ function scopeParagraphPathKey(path) {
24777
+ return path.map((step) => {
24778
+ if (step.kind === "block") return `b:${step.index}`;
24779
+ if (step.kind === "tableCell") {
24780
+ return `tc:${step.rowIndex}:${step.cellIndex}`;
24781
+ }
24782
+ return "sdt";
24783
+ }).join("/");
24784
+ }
24785
+
24786
+ // src/runtime/workflow/scope-resolver.ts
24787
+ function walkParagraphs2(document2) {
24788
+ const envelope = document2;
24789
+ return computeScopeStoryLayout(envelope).paragraphSlots.map((slot) => ({
24790
+ paragraph: slot.paragraph,
24791
+ from: slot.from
24792
+ }));
24793
+ }
24794
+ function inlineLength(node) {
24795
+ return inlineLengthForScopeCoordinates(node);
24194
24796
  }
24195
24797
  function collectScopeLocations(document2) {
24196
24798
  const locations = /* @__PURE__ */ new Map();
@@ -25390,7 +25992,7 @@ function buildFormattingDebugEntry(inputs) {
25390
25992
  }
25391
25993
 
25392
25994
  // src/runtime/layout/layout-engine-version.ts
25393
- var LAYOUT_ENGINE_VERSION = 93;
25995
+ var LAYOUT_ENGINE_VERSION = 94;
25394
25996
 
25395
25997
  // src/runtime/layout/compat-input-ledger.ts
25396
25998
  var DEFAULT_COMPATIBILITY_MODE = 15;
@@ -26601,9 +27203,13 @@ function appendFragmentLayoutObjectSemanticEntries(input) {
26601
27203
  numberingCanonicalAddressKey: numbering.canonicalAddressKey,
26602
27204
  numberingListAddressKey: numbering.listAddressKey,
26603
27205
  numberingMarkerText: numbering.markerText,
27206
+ numberingMarkerTextPosture: numbering.markerTextPosture,
26604
27207
  numberingMarkerSuffix: numbering.markerSuffix,
26605
27208
  numberingFormat: numbering.format,
26606
27209
  numberingFormatPosture: numbering.formatPosture,
27210
+ numberingPicBulletId: numbering.picBulletId,
27211
+ numberingPicBulletMediaId: numbering.picBulletMediaId,
27212
+ numberingPictureBulletPosture: numbering.pictureBulletPosture,
26607
27213
  numberingUnavailableReasons: numbering.unavailableReasons,
26608
27214
  markerGlyphRect: markerProjection.rect,
26609
27215
  markerLaneRect: markerProjection.markerLaneRect,
@@ -33521,9 +34127,9 @@ function messageForPostureBlocker(blocker) {
33521
34127
  return void 0;
33522
34128
  }
33523
34129
  }
33524
- function auditFact(target, category, reason, operation) {
34130
+ function auditFact(target, category, reason, operation2) {
33525
34131
  return {
33526
- operation: operation ?? auditOperationForTarget(target),
34132
+ operation: operation2 ?? auditOperationForTarget(target),
33527
34133
  category,
33528
34134
  dispatch: "blocked-before-mutation",
33529
34135
  reason
@@ -33614,25 +34220,43 @@ function computeBlockPositions(document2) {
33614
34220
  let cursor = 0;
33615
34221
  for (let index = 0; index < root.children.length; index += 1) {
33616
34222
  const block = root.children[index];
34223
+ if (!block) continue;
33617
34224
  const from = cursor;
33618
- let length = 0;
33619
- if (block && block.type === "paragraph") {
33620
- length = block.children.reduce(
33621
- (total, child) => total + inlineLength2(child),
33622
- 0
33623
- );
33624
- } else {
33625
- length = 1;
33626
- }
33627
- cursor += length;
33628
- const to = cursor;
33629
- out.push({ blockIndex: index, from, to });
33630
- if (index < root.children.length - 1) {
34225
+ cursor += blockLength(block);
34226
+ out.push({ blockIndex: index, from, to: cursor });
34227
+ if (index < root.children.length - 1 && root.children[index + 1]?.type === "paragraph") {
33631
34228
  cursor += 1;
33632
34229
  }
33633
34230
  }
33634
34231
  return out;
33635
34232
  }
34233
+ function blockLength(block) {
34234
+ if (block.type === "paragraph") {
34235
+ return block.children.reduce(
34236
+ (total, child) => total + inlineLength2(child),
34237
+ 0
34238
+ );
34239
+ }
34240
+ if (block.type === "table") {
34241
+ let total = 0;
34242
+ for (const row2 of block.rows) {
34243
+ for (const cell of row2.cells) {
34244
+ for (const child of cell.children) {
34245
+ total += blockLength(child);
34246
+ }
34247
+ }
34248
+ }
34249
+ return total;
34250
+ }
34251
+ if (block.type === "sdt") {
34252
+ const descriptor = describeStructuredWrapperBlock(block, {
34253
+ projectVisibleTocContentControls: true
34254
+ });
34255
+ if (descriptor) return 1;
34256
+ return block.children.reduce((total, child) => total + blockLength(child), 0);
34257
+ }
34258
+ return 1;
34259
+ }
33636
34260
  function computeInlinePositions(document2, blocks) {
33637
34261
  const envelope = document2;
33638
34262
  const root = "content" in envelope ? envelope.content : document2;
@@ -33849,8 +34473,8 @@ function deriveReplaceability(kind, provenance) {
33849
34473
  if (kind === "scope") {
33850
34474
  if (provenance === "marker-backed") {
33851
34475
  return {
33852
- level: "preserve-only",
33853
- reason: "multi-paragraph-replace-not-implemented"
34476
+ level: "text-only",
34477
+ reason: "marker-backed-multi-paragraph-preserves-anchor"
33854
34478
  };
33855
34479
  }
33856
34480
  return {
@@ -35012,6 +35636,54 @@ function compileScopeKind(entry, options) {
35012
35636
  partial: true
35013
35637
  };
35014
35638
  }
35639
+ function compileScopeReplacement(entry, proposed, options) {
35640
+ if (entry.handle.provenance !== "marker-backed" || proposed.operation !== "replace" || options.posture !== "direct-edit") {
35641
+ return null;
35642
+ }
35643
+ const markerRange = buildScopePositionMap(options.document).markerScopes.get(
35644
+ entry.handle.scopeId
35645
+ );
35646
+ if (!markerRange) return null;
35647
+ if (proposed.proposedContent.kind === "text") {
35648
+ const text = proposed.proposedContent.text ?? "";
35649
+ return {
35650
+ scopeId: entry.handle.scopeId,
35651
+ targetKind: "scope",
35652
+ operation: proposed.operation,
35653
+ steps: Object.freeze([
35654
+ {
35655
+ kind: "text-replace",
35656
+ summary: `replace multi-paragraph scope ${entry.handle.scopeId} text [${markerRange.from}..${markerRange.to}] (len ${text.length})`,
35657
+ range: { from: markerRange.from, to: markerRange.to },
35658
+ text,
35659
+ ...proposed.formatting ? { formatting: proposed.formatting } : {}
35660
+ }
35661
+ ]),
35662
+ ...proposed.preserve ? { preserve: proposed.preserve } : {},
35663
+ posture: options.posture
35664
+ };
35665
+ }
35666
+ if (proposed.proposedContent.kind === "structured") {
35667
+ const fragment = proposed.proposedContent.structured;
35668
+ if (!isStructuredReplacementContent(fragment)) return null;
35669
+ return {
35670
+ scopeId: entry.handle.scopeId,
35671
+ targetKind: "scope",
35672
+ operation: proposed.operation,
35673
+ steps: Object.freeze([
35674
+ {
35675
+ kind: "fragment-replace",
35676
+ summary: `replace multi-paragraph scope ${entry.handle.scopeId} with structured fragment [${markerRange.from}..${markerRange.to}] (${fragment.blocks.length} block(s))`,
35677
+ range: { from: markerRange.from, to: markerRange.to },
35678
+ fragment
35679
+ }
35680
+ ]),
35681
+ ...proposed.preserve ? { preserve: proposed.preserve } : {},
35682
+ posture: options.posture
35683
+ };
35684
+ }
35685
+ return null;
35686
+ }
35015
35687
 
35016
35688
  // src/runtime/scopes/scope-kinds/table.ts
35017
35689
  function compileTableScope(entry, options = {}) {
@@ -35916,31 +36588,6 @@ function deriveScopeAdjacentGeometryEvidence(scope, entry, provider) {
35916
36588
  };
35917
36589
  }
35918
36590
 
35919
- // src/runtime/scopes/multi-paragraph-refusal.ts
35920
- var MULTI_PARAGRAPH_REPLACEMENT_REFUSAL = "compile-refused:scope:multi-paragraph-replace-not-implemented";
35921
- function shapeBlocker(shape) {
35922
- switch (shape) {
35923
- case "text":
35924
- return "compile-refused:scope:multi-paragraph-text-replace-not-implemented";
35925
- case "fragment":
35926
- return "compile-refused:scope:multi-paragraph-fragment-replace-not-implemented";
35927
- default:
35928
- return "compile-refused:scope:multi-paragraph-replace-shape-not-implemented";
35929
- }
35930
- }
35931
- function multiParagraphReplacementBlockers(shape = "unknown") {
35932
- return Object.freeze([
35933
- MULTI_PARAGRAPH_REPLACEMENT_REFUSAL,
35934
- shapeBlocker(shape),
35935
- "capability:scope:block-granular-replacement-lowering-required",
35936
- "capability:scope:provenance:marker-backed-required",
35937
- "capability:scope:layout-completeness-required",
35938
- "capability:scope:geometry-completeness-required",
35939
- "capability:scope:continuation-state-required",
35940
- "capability:scope:preservation-verdict-required"
35941
- ]);
35942
- }
35943
-
35944
36591
  // src/runtime/scopes/capabilities.ts
35945
36592
  var PARAGRAPH_LIKE = /* @__PURE__ */ new Set([
35946
36593
  "paragraph",
@@ -36157,10 +36804,9 @@ function replaceTextCapability(scope, context) {
36157
36804
  if (guard) return blocked(guard);
36158
36805
  if (scope.kind === "list-item") {
36159
36806
  return blocked(
36160
- "compile-blocked:list-text:authoritative-readback-required",
36807
+ "compile-blocked:list-text:exact-list-text-handle-required",
36161
36808
  [
36162
- "capability:list-item:authoritative-readback-required",
36163
- "capability:list-text:export-persistent-target-required"
36809
+ "capability:list-item:exact-list-text-handle-required"
36164
36810
  ]
36165
36811
  );
36166
36812
  }
@@ -36175,6 +36821,19 @@ function replaceTextCapability(scope, context) {
36175
36821
  generatedOrLinked
36176
36822
  );
36177
36823
  }
36824
+ if (scope.kind === "scope") {
36825
+ if (scope.workflow.effectiveMode === "suggest") {
36826
+ return unsupported(
36827
+ "compile-refused:scope:multi-paragraph-suggesting-not-implemented",
36828
+ ["compile-refused:scope:multi-paragraph-suggesting-not-implemented"],
36829
+ ["guard:suggest-mode", ...evidenceWarnings(context)]
36830
+ );
36831
+ }
36832
+ return supported(
36833
+ "compile-supported:scope:multi-paragraph-text-replace",
36834
+ evidenceWarnings(context)
36835
+ );
36836
+ }
36178
36837
  if (!PARAGRAPH_LIKE.has(scope.kind)) {
36179
36838
  if (scope.kind === "table-cell") {
36180
36839
  if (context?.tableCellTextRange?.status === "ok") {
@@ -36196,12 +36855,8 @@ function replaceTextCapability(scope, context) {
36196
36855
  ]
36197
36856
  );
36198
36857
  }
36199
- const reason = scope.kind === "scope" && scope.replaceability.reason ? MULTI_PARAGRAPH_REPLACEMENT_REFUSAL : `compile-refused:${scope.kind}`;
36200
- return unsupported(
36201
- reason,
36202
- scope.kind === "scope" ? multiParagraphReplacementBlockers("text") : [reason],
36203
- evidenceWarnings(context)
36204
- );
36858
+ const reason = `compile-refused:${scope.kind}`;
36859
+ return unsupported(reason, [reason], evidenceWarnings(context));
36205
36860
  }
36206
36861
  if (scope.replaceability.level === "blocked" || scope.replaceability.level === "preserve-only" || scope.replaceability.level === "formatting-only") {
36207
36862
  const reason = scope.replaceability.reason ? `replaceability:${scope.replaceability.reason}` : `replaceability:${scope.replaceability.level}`;
@@ -36229,14 +36884,25 @@ function replaceFragmentCapability(scope, context) {
36229
36884
  generatedOrLinked
36230
36885
  );
36231
36886
  }
36232
- if (!PARAGRAPH_LIKE.has(scope.kind)) {
36233
- const reason = scope.kind === "scope" && scope.replaceability.reason ? MULTI_PARAGRAPH_REPLACEMENT_REFUSAL : `compile-refused:${scope.kind}`;
36234
- return unsupported(
36235
- reason,
36236
- scope.kind === "scope" ? multiParagraphReplacementBlockers("fragment") : [reason],
36887
+ if (scope.kind === "scope") {
36888
+ if (scope.workflow.effectiveMode === "suggest") {
36889
+ return unsupported(
36890
+ "compile-refused:scope:multi-paragraph-structured-suggesting-not-implemented",
36891
+ [
36892
+ "compile-refused:scope:multi-paragraph-structured-suggesting-not-implemented"
36893
+ ],
36894
+ ["guard:suggest-mode", ...evidenceWarnings(context)]
36895
+ );
36896
+ }
36897
+ return supported(
36898
+ "compile-supported:scope:multi-paragraph-fragment-replace",
36237
36899
  evidenceWarnings(context)
36238
36900
  );
36239
36901
  }
36902
+ if (!PARAGRAPH_LIKE.has(scope.kind)) {
36903
+ const reason = `compile-refused:${scope.kind}`;
36904
+ return unsupported(reason, [reason], evidenceWarnings(context));
36905
+ }
36240
36906
  if (scope.workflow.effectiveMode === "suggest") {
36241
36907
  return unsupported(
36242
36908
  `compile-refused:${scope.kind}:structured-suggesting-not-implemented`,
@@ -38827,6 +39493,231 @@ function compileScopeBundleById(scopeId, inputs) {
38827
39493
  return compileScopeBundle(compiled, { ...inputs, scopes });
38828
39494
  }
38829
39495
 
39496
+ // src/runtime/scopes/editable-graph.ts
39497
+ function uniq(values) {
39498
+ return Object.freeze([...new Set(values.filter(Boolean))]);
39499
+ }
39500
+ function commandFamilyForTarget(target) {
39501
+ const intents = target.runtimeCommand.intents;
39502
+ if (target.table?.operationScope === "text" && target.runtimeCommand.commandFamily === "text-leaf") {
39503
+ return "table-text";
39504
+ }
39505
+ if (intents.some((intent) => intent.startsWith("table-"))) {
39506
+ if (intents.some((intent) => intent.includes("structure"))) {
39507
+ return "table-structure";
39508
+ }
39509
+ return "table-text";
39510
+ }
39511
+ if (intents.some((intent) => intent.startsWith("list-"))) {
39512
+ if (intents.some((intent) => intent.includes("structure"))) {
39513
+ return "list-structure";
39514
+ }
39515
+ return "list-text";
39516
+ }
39517
+ return target.runtimeCommand.commandFamily;
39518
+ }
39519
+ function familyForTarget(target) {
39520
+ if (target.runtimeCommand.intents.some(
39521
+ (intent) => intent === "table-structure-action" || intent === "table-merge-cells" || intent === "table-split-cell" || intent === "list-structure-action"
39522
+ )) {
39523
+ return "structure";
39524
+ }
39525
+ if (target.runtimeCommand.intents.some(
39526
+ (intent) => intent === "field-update" || intent === "toc-refresh" || intent === "hyperlink-update" || intent === "bookmark-update" || intent === "custom-xml-update"
39527
+ )) {
39528
+ return "value";
39529
+ }
39530
+ if (target.runtimeCommand.commandFamily === "object" || target.runtimeCommand.intents.some(
39531
+ (intent) => intent === "object-edit" || intent === "image-layout" || intent === "image-frame" || intent === "chart-edit" || intent === "embedded-content-update"
39532
+ )) {
39533
+ return "object";
39534
+ }
39535
+ if (target.runtimeCommand.commandFamily === "metadata") return "metadata";
39536
+ if (target.runtimeCommand.commandFamily === "preserve-only-refusal" || target.posture.preserveOnly || target.kind === "opaque-content") {
39537
+ return "preservation";
39538
+ }
39539
+ return "text";
39540
+ }
39541
+ function statusForTarget(target, family) {
39542
+ if (family === "preservation") return "preserve";
39543
+ if (target.runtimeCommand.status === "supported" && target.runtimeCommand.actionHandle) {
39544
+ return "ready";
39545
+ }
39546
+ if (target.runtimeCommand.status === "supported") return "diagnostic";
39547
+ return "needs-command";
39548
+ }
39549
+ function blockersForTarget(target) {
39550
+ return uniq([
39551
+ ...target.posture.blockers,
39552
+ ...target.runtimeTextCommand.blockers ?? [],
39553
+ ...target.runtimeCommand.blockers ?? [],
39554
+ ...target.workflowBlockers?.map((blocker) => blocker.blocker) ?? []
39555
+ ]);
39556
+ }
39557
+ function projectEditableTarget(target) {
39558
+ const family = familyForTarget(target);
39559
+ const commandFamily = commandFamilyForTarget(target);
39560
+ return Object.freeze({
39561
+ targetId: target.targetKey,
39562
+ family,
39563
+ kind: target.kind,
39564
+ relation: target.relation,
39565
+ status: statusForTarget(target, family),
39566
+ commandFamily,
39567
+ ...target.runtimeCommand.actionHandle ? { actionHandle: target.runtimeCommand.actionHandle } : {},
39568
+ ...target.runtimeCommand.canonicalAddress ? { canonicalAddress: target.runtimeCommand.canonicalAddress } : {},
39569
+ ...target.readback ? { readback: target.readback } : {},
39570
+ blockers: blockersForTarget(target),
39571
+ warnings: Object.freeze([]),
39572
+ intents: Object.freeze([...target.runtimeCommand.intents])
39573
+ });
39574
+ }
39575
+ function projectTableAction(action) {
39576
+ const family = action.family === "table-structure" ? "structure" : "text";
39577
+ const blockers = uniq(action.blockers ?? []);
39578
+ return Object.freeze({
39579
+ targetId: action.handle,
39580
+ family,
39581
+ kind: action.targetKind,
39582
+ relation: action.relation,
39583
+ status: action.status === "supported" && action.actionHandle ? "ready" : action.status === "supported" ? "diagnostic" : "needs-command",
39584
+ commandFamily: action.family,
39585
+ ...action.actionHandle ? { actionHandle: action.actionHandle } : {},
39586
+ ...action.canonicalAddress ? { canonicalAddress: action.canonicalAddress } : {},
39587
+ ...action.readback ? { readback: action.readback } : {},
39588
+ blockers,
39589
+ warnings: Object.freeze([...action.warnings ?? []]),
39590
+ intents: Object.freeze([...action.intents])
39591
+ });
39592
+ }
39593
+ function metadataTarget(bundle) {
39594
+ return Object.freeze({
39595
+ targetId: `${bundle.scope.handle.scopeId}:metadata`,
39596
+ family: "metadata",
39597
+ kind: "scope-metadata",
39598
+ status: "ready",
39599
+ commandFamily: "metadata",
39600
+ actionHandle: `scope-metadata:${bundle.scope.handle.scopeId}`,
39601
+ blockers: Object.freeze([]),
39602
+ warnings: Object.freeze([]),
39603
+ intents: Object.freeze(["metadata-update"])
39604
+ });
39605
+ }
39606
+ function scopeReplacementTarget(bundle) {
39607
+ const verdict = bundle.evidence.capabilities?.canReplaceText;
39608
+ if (!verdict?.supported) return null;
39609
+ return Object.freeze({
39610
+ targetId: `${bundle.scope.handle.scopeId}:scope-replace-text`,
39611
+ family: "text",
39612
+ kind: `${bundle.scope.kind}:scope-replacement`,
39613
+ relation: "exact-scope",
39614
+ status: "ready",
39615
+ commandFamily: "scope-replacement",
39616
+ blockers: Object.freeze([]),
39617
+ warnings: Object.freeze([...verdict.warnings ?? []]),
39618
+ intents: Object.freeze(["text-leaf-edit"])
39619
+ });
39620
+ }
39621
+ function group(targets, family) {
39622
+ return Object.freeze(targets.filter((target) => target.family === family));
39623
+ }
39624
+ function operation(kind, targets) {
39625
+ const ready = targets.filter((target) => target.status === "ready");
39626
+ const pending = targets.filter((target) => target.status === "needs-command");
39627
+ return Object.freeze({
39628
+ kind,
39629
+ status: ready.length > 0 ? "ready" : pending.length > 0 ? "needs-command" : "needs-target",
39630
+ targetIds: Object.freeze(ready.map((target) => target.targetId)),
39631
+ commandFamilies: uniq(ready.map((target) => target.commandFamily ?? ""))
39632
+ });
39633
+ }
39634
+ function contentModelFor(textTargets, valueTargets, structureTargets, objectTargets) {
39635
+ const families = [
39636
+ textTargets.length > 0 ? "text" : "",
39637
+ valueTargets.length > 0 ? "value" : "",
39638
+ structureTargets.length > 0 ? "structure" : "",
39639
+ objectTargets.length > 0 ? "object" : ""
39640
+ ].filter(Boolean);
39641
+ if (families.length === 0) return "metadata";
39642
+ if (families.length > 1) return "mixed";
39643
+ return families[0];
39644
+ }
39645
+ function summaryFor(model, targets) {
39646
+ const ready = targets.filter((target) => target.status === "ready").length;
39647
+ const needsCommand = targets.filter(
39648
+ (target) => target.status === "needs-command"
39649
+ ).length;
39650
+ const preserve = targets.filter((target) => target.status === "preserve").length;
39651
+ return `${model} scope editable graph: ${ready} ready target(s), ${needsCommand} target(s) needing command, ${preserve} preserve target(s)`;
39652
+ }
39653
+ function compileScopeEditableGraph(bundle) {
39654
+ const scopeTextTarget = scopeReplacementTarget(bundle);
39655
+ const projected = [
39656
+ ...bundle.evidence.editableTargets?.entries.map(projectEditableTarget) ?? [],
39657
+ ...bundle.evidence.table?.actions.map(projectTableAction) ?? [],
39658
+ ...scopeTextTarget ? [scopeTextTarget] : [],
39659
+ metadataTarget(bundle)
39660
+ ];
39661
+ const byId = /* @__PURE__ */ new Map();
39662
+ for (const target of projected) {
39663
+ const existing = byId.get(target.targetId);
39664
+ if (!existing || existing.status !== "ready") {
39665
+ byId.set(target.targetId, target);
39666
+ }
39667
+ }
39668
+ const targets = Object.freeze([...byId.values()]);
39669
+ const textTargets = group(targets, "text");
39670
+ const valueTargets = group(targets, "value");
39671
+ const structureTargets = group(targets, "structure");
39672
+ const objectTargets = group(targets, "object");
39673
+ const metadataTargets = group(targets, "metadata");
39674
+ const preservationTargets = group(targets, "preservation");
39675
+ const contentModel = contentModelFor(
39676
+ textTargets,
39677
+ valueTargets,
39678
+ structureTargets,
39679
+ objectTargets
39680
+ );
39681
+ const operations = Object.freeze([
39682
+ operation("replace-text", textTargets),
39683
+ operation("replace-value", valueTargets),
39684
+ operation("edit-structure", structureTargets),
39685
+ operation("edit-object", objectTargets),
39686
+ operation("attach-metadata", metadataTargets)
39687
+ ]);
39688
+ const readyTargetCount = targets.filter((target) => target.status === "ready").length;
39689
+ const needsCommandTargetCount = targets.filter(
39690
+ (target) => target.status === "needs-command"
39691
+ ).length;
39692
+ const preserveTargetCount = targets.filter(
39693
+ (target) => target.status === "preserve"
39694
+ ).length;
39695
+ const blockers = uniq(targets.flatMap((target) => target.blockers));
39696
+ const warnings = uniq(targets.flatMap((target) => target.warnings));
39697
+ const readiness = Object.freeze({
39698
+ status: readyTargetCount > metadataTargets.length ? needsCommandTargetCount > 0 || preserveTargetCount > 0 ? "partial" : "ready" : "metadata-only",
39699
+ readyTargetCount,
39700
+ needsCommandTargetCount,
39701
+ preserveTargetCount,
39702
+ blockers,
39703
+ warnings
39704
+ });
39705
+ return Object.freeze({
39706
+ scope: bundle.scope.handle,
39707
+ contentModel,
39708
+ targets,
39709
+ textTargets,
39710
+ valueTargets,
39711
+ structureTargets,
39712
+ objectTargets,
39713
+ metadataTargets,
39714
+ preservationTargets,
39715
+ operations,
39716
+ readiness,
39717
+ summary: summaryFor(contentModel, targets)
39718
+ });
39719
+ }
39720
+
38830
39721
  // src/runtime/scopes/issue-lifecycle.ts
38831
39722
  function documentHash(doc) {
38832
39723
  let textLength = 0;
@@ -38979,11 +39870,11 @@ function computePreservationVerdict(document2, range, positionMap) {
38979
39870
  }
38980
39871
 
38981
39872
  // src/runtime/scopes/action-validation.ts
38982
- function inferActionId(operation, content) {
38983
- if (operation === "formatting") {
39873
+ function inferActionId(operation2, content) {
39874
+ if (operation2 === "formatting") {
38984
39875
  return "fix_formatting";
38985
39876
  }
38986
- switch (operation) {
39877
+ switch (operation2) {
38987
39878
  case "replace":
38988
39879
  return content.kind === "text" ? "rewrite_paragraph" : "generate_text";
38989
39880
  case "insert-before":
@@ -39134,11 +40025,11 @@ function collectCapabilityVerdict(inputs, blockedReasons, warnings) {
39134
40025
  }
39135
40026
  }
39136
40027
  if (inputs.scope.kind === "list-item" && inputs.operation === "replace" && inputs.proposedContent.kind === "text") {
39137
- const code = "capability:list-item:authoritative-readback-required";
40028
+ const code = "capability:list-item:exact-list-text-handle-required";
39138
40029
  blockedReasons.push(code);
39139
40030
  warnings.push({
39140
40031
  code,
39141
- message: "list-item flat text replacement is blocked until the runtime validates an export-persistent list text command path",
40032
+ message: "list-item flat text replacement is blocked unless the caller uses an exact list-text action handle",
39142
40033
  source: "capability"
39143
40034
  });
39144
40035
  }
@@ -39375,11 +40266,44 @@ function compileReplacement(inputs) {
39375
40266
  inputs.posture,
39376
40267
  inputs.tableCellTextRange
39377
40268
  );
40269
+ case "scope":
40270
+ if (inputs.enumeratedScope.kind === "scope") {
40271
+ return compileScopeReplacement(inputs.enumeratedScope, inputs.proposed, {
40272
+ document: inputs.document,
40273
+ posture: inputs.posture
40274
+ });
40275
+ }
40276
+ return null;
39378
40277
  default:
39379
40278
  return null;
39380
40279
  }
39381
40280
  }
39382
40281
 
40282
+ // src/runtime/scopes/multi-paragraph-refusal.ts
40283
+ var MULTI_PARAGRAPH_REPLACEMENT_REFUSAL = "compile-refused:scope:multi-paragraph-replace-not-implemented";
40284
+ function shapeBlocker(shape) {
40285
+ switch (shape) {
40286
+ case "text":
40287
+ return "compile-refused:scope:multi-paragraph-text-replace-not-implemented";
40288
+ case "fragment":
40289
+ return "compile-refused:scope:multi-paragraph-fragment-replace-not-implemented";
40290
+ default:
40291
+ return "compile-refused:scope:multi-paragraph-replace-shape-not-implemented";
40292
+ }
40293
+ }
40294
+ function multiParagraphReplacementBlockers(shape = "unknown") {
40295
+ return Object.freeze([
40296
+ MULTI_PARAGRAPH_REPLACEMENT_REFUSAL,
40297
+ shapeBlocker(shape),
40298
+ "capability:scope:block-granular-replacement-lowering-required",
40299
+ "capability:scope:provenance:marker-backed-required",
40300
+ "capability:scope:layout-completeness-required",
40301
+ "capability:scope:geometry-completeness-required",
40302
+ "capability:scope:continuation-state-required",
40303
+ "capability:scope:preservation-verdict-required"
40304
+ ]);
40305
+ }
40306
+
39383
40307
  // src/runtime/scopes/replacement/apply.ts
39384
40308
  function documentHash2(doc) {
39385
40309
  let hash = 2166136261;
@@ -39542,14 +40466,18 @@ function applyScopeReplacement(inputs) {
39542
40466
  });
39543
40467
  if (!plan) {
39544
40468
  const paragraphLike = resolvedScope.kind === "paragraph" || resolvedScope.kind === "heading" || resolvedScope.kind === "list-item";
39545
- const blockers = resolvedScope.kind === "scope" ? multiParagraphReplacementBlockers(
40469
+ const blockers = resolvedScope.kind === "scope" && posture === "suggest-mode" ? [
40470
+ proposed.proposedContent.kind === "structured" ? "compile-refused:scope:multi-paragraph-structured-suggesting-not-implemented" : "compile-refused:scope:multi-paragraph-suggesting-not-implemented"
40471
+ ] : resolvedScope.kind === "scope" && proposed.operation !== "replace" ? [
40472
+ `compile-refused:scope:operation-not-implemented:${proposed.operation}`
40473
+ ] : resolvedScope.kind === "scope" ? multiParagraphReplacementBlockers(
39546
40474
  proposed.proposedContent.kind === "structured" ? "fragment" : "text"
39547
40475
  ) : paragraphLike && proposed.operation === "replace" && proposed.preserve?.opaqueFragments === true ? [
39548
40476
  `compile-refused:${resolvedScope.kind}:opaque-preserving-text-target-unavailable`
39549
40477
  ] : resolvedScope.kind === "table-cell" ? [tableCellRefusalBlocker(tableCellTextRange)] : paragraphLike && proposed.operation !== "replace" ? [
39550
40478
  `compile-refused:${resolvedScope.kind}:operation-not-implemented:${proposed.operation}`
39551
40479
  ] : [`compile-refused:${resolvedScope.kind}`];
39552
- const blocker = resolvedScope.kind === "scope" ? MULTI_PARAGRAPH_REPLACEMENT_REFUSAL : blockers[0] ?? `compile-refused:${resolvedScope.kind}`;
40480
+ const blocker = blockers[0] ?? `compile-refused:${resolvedScope.kind}`;
39553
40481
  const refused = {
39554
40482
  safe: false,
39555
40483
  posture: "hard-refusal",
@@ -40028,10 +40956,10 @@ function createScopeCompilerService(runtime) {
40028
40956
  emitMetadataAudit(request) {
40029
40957
  try {
40030
40958
  const snapshot = request.targetScopeSnapshot;
40031
- const operation = "annotate";
40959
+ const operation2 = "annotate";
40032
40960
  const proposed = {
40033
40961
  targetHandle: snapshot.handle,
40034
- operation,
40962
+ operation: operation2,
40035
40963
  proposedContent: {
40036
40964
  kind: "structured",
40037
40965
  structured: {
@@ -40106,6 +41034,10 @@ function createScopeCompilerService(runtime) {
40106
41034
  ...editableTargetCache ? { editableTargetCache } : {}
40107
41035
  });
40108
41036
  },
41037
+ compileEditableGraphById(scopeId, nowUtc) {
41038
+ const bundle = this.compileBundleById(scopeId, nowUtc);
41039
+ return bundle ? compileScopeEditableGraph(bundle) : null;
41040
+ },
40109
41041
  buildReplacementScope(targetHandle, input) {
40110
41042
  return proposeReplacement({
40111
41043
  targetHandle,
@@ -45010,6 +45942,11 @@ function freezeNumberingLayoutFacts(numbering) {
45010
45942
  if (numbering.numberingSourceRef) Object.freeze(numbering.numberingSourceRef);
45011
45943
  if (numbering.numberingInstanceSourceRef) Object.freeze(numbering.numberingInstanceSourceRef);
45012
45944
  if (numbering.abstractNumberingSourceRef) Object.freeze(numbering.abstractNumberingSourceRef);
45945
+ if (numbering.markerTextPosture) Object.freeze(numbering.markerTextPosture);
45946
+ if (numbering.pictureBulletPosture) {
45947
+ if (numbering.pictureBulletPosture.sourceRef) Object.freeze(numbering.pictureBulletPosture.sourceRef);
45948
+ Object.freeze(numbering.pictureBulletPosture);
45949
+ }
45013
45950
  if (numbering.markerLane) Object.freeze(numbering.markerLane);
45014
45951
  if (numbering.textColumn) Object.freeze(numbering.textColumn);
45015
45952
  if (numbering.tabStops) {
@@ -45985,8 +46922,17 @@ function collectNumberingLayoutFacts(block) {
45985
46922
  ...block.resolvedNumbering?.format !== void 0 ? { format: block.resolvedNumbering.format } : {},
45986
46923
  ...block.resolvedNumbering?.formatPosture !== void 0 ? { formatPosture: { ...block.resolvedNumbering.formatPosture } } : {},
45987
46924
  ...block.numberingPrefix !== void 0 ? { markerText: block.numberingPrefix } : {},
46925
+ ...block.resolvedNumbering?.markerTextPosture !== void 0 ? { markerTextPosture: { ...block.resolvedNumbering.markerTextPosture } } : {},
45988
46926
  ...block.numberingSuffix !== void 0 ? { markerSuffix: block.numberingSuffix } : {},
45989
46927
  ...block.resolvedNumbering?.geometry.markerJustification !== void 0 ? { markerJustification: block.resolvedNumbering.geometry.markerJustification } : {},
46928
+ ...block.resolvedNumbering?.picBulletId !== void 0 ? { picBulletId: block.resolvedNumbering.picBulletId } : {},
46929
+ ...block.resolvedNumbering?.picBulletMediaId !== void 0 ? { picBulletMediaId: block.resolvedNumbering.picBulletMediaId } : {},
46930
+ ...block.resolvedNumbering?.pictureBulletPosture !== void 0 ? {
46931
+ pictureBulletPosture: {
46932
+ ...block.resolvedNumbering.pictureBulletPosture,
46933
+ ...block.resolvedNumbering.pictureBulletPosture.sourceRef !== void 0 ? { sourceRef: { ...block.resolvedNumbering.pictureBulletPosture.sourceRef } } : {}
46934
+ }
46935
+ } : {},
45990
46936
  ...markerLane ? {
45991
46937
  markerLane: {
45992
46938
  startTwips: markerLane.start,
@@ -47026,11 +47972,45 @@ function createLayoutEngine(options = {}) {
47026
47972
  const telemetryBus = options.telemetryBus;
47027
47973
  const dirtyFieldFamilies = /* @__PURE__ */ new Set();
47028
47974
  const listeners = /* @__PURE__ */ new Set();
47029
- let cachedKey = null;
47030
- let cachedGraph = null;
47031
- let cachedFormatting = null;
47032
- let cachedMapper = null;
47975
+ let cachedFull = null;
47976
+ let cachedWindowed = null;
47033
47977
  let previousPageCount = 0;
47978
+ function isFullViewportKey(key) {
47979
+ return key === FULL_VIEWPORT_WINDOW_KEY;
47980
+ }
47981
+ function getCachedSlot(viewportWindowKeyValue) {
47982
+ return isFullViewportKey(viewportWindowKeyValue) ? cachedFull : cachedWindowed;
47983
+ }
47984
+ function preferredCachedGraph() {
47985
+ return cachedFull?.graph ?? cachedWindowed?.graph ?? null;
47986
+ }
47987
+ function clearAllSlots() {
47988
+ cachedFull = null;
47989
+ cachedWindowed = null;
47990
+ }
47991
+ function clearWindowedSlot() {
47992
+ cachedWindowed = null;
47993
+ }
47994
+ function evictStaleSiblingSlot(freshKey) {
47995
+ const sibling = isFullViewportKey(freshKey.viewportWindowKey) ? cachedWindowed : cachedFull;
47996
+ if (sibling === null) return;
47997
+ if (sibling.key.content === freshKey.content && sibling.key.styles === freshKey.styles && sibling.key.subParts === freshKey.subParts) {
47998
+ return;
47999
+ }
48000
+ if (isFullViewportKey(freshKey.viewportWindowKey)) {
48001
+ cachedWindowed = null;
48002
+ } else {
48003
+ cachedFull = null;
48004
+ }
48005
+ }
48006
+ function commitSlot(slot) {
48007
+ if (isFullViewportKey(slot.key.viewportWindowKey)) {
48008
+ cachedFull = slot;
48009
+ } else {
48010
+ cachedWindowed = slot;
48011
+ }
48012
+ evictStaleSiblingSlot(slot.key);
48013
+ }
47034
48014
  let pendingInvalidation = null;
47035
48015
  function emit(event) {
47036
48016
  for (const listener of listeners) {
@@ -47176,27 +48156,31 @@ function createLayoutEngine(options = {}) {
47176
48156
  subParts: document2.subParts,
47177
48157
  anchors: layoutInputs.anchors
47178
48158
  });
48159
+ const priorGraphForMaterialization = preferredCachedGraph();
47179
48160
  const graph = applyViewportWindowMaterialization(
47180
48161
  measuredGraph,
47181
48162
  viewportWindow,
47182
- cachedGraph
48163
+ priorGraphForMaterialization
47183
48164
  );
47184
- const dirtyFamilies = computeFieldDirtiness(cachedGraph, graph);
48165
+ const priorGraphForFieldDirtiness = preferredCachedGraph();
48166
+ const dirtyFamilies = computeFieldDirtiness(priorGraphForFieldDirtiness, graph);
47185
48167
  for (const family of dirtyFamilies) {
47186
48168
  dirtyFieldFamilies.add(family);
47187
48169
  }
47188
48170
  const formatting = buildResolvedFormattingState(document2, mainSurface);
47189
48171
  const currentPageCount = graph.contentPageCount;
47190
48172
  const pageCountDelta = currentPageCount !== previousPageCount ? { previous: previousPageCount, current: currentPageCount } : void 0;
47191
- cachedKey = {
47192
- content: document2.content,
47193
- styles: document2.styles,
47194
- subParts: document2.subParts,
47195
- viewportWindowKey: viewportWindowKey(viewportWindow)
47196
- };
47197
- cachedGraph = graph;
47198
- cachedFormatting = formatting;
47199
- cachedMapper = createPageFragmentMapper(graph);
48173
+ commitSlot({
48174
+ key: {
48175
+ content: document2.content,
48176
+ styles: document2.styles,
48177
+ subParts: document2.subParts,
48178
+ viewportWindowKey: viewportWindowKey(viewportWindow)
48179
+ },
48180
+ graph,
48181
+ formatting,
48182
+ mapper: createPageFragmentMapper(graph)
48183
+ });
47200
48184
  if (pageCountDelta) {
47201
48185
  emit({
47202
48186
  kind: "page_count_changed",
@@ -47237,7 +48221,7 @@ function createLayoutEngine(options = {}) {
47237
48221
  return graph;
47238
48222
  }
47239
48223
  function incrementalRelayout(input, pending) {
47240
- const priorGraph = cachedGraph;
48224
+ const priorGraph = cachedFull?.graph ?? null;
47241
48225
  const range = pending.result.dirtyPageRange;
47242
48226
  if (!priorGraph || !range) return null;
47243
48227
  const telemetryOn = telemetryBus?.isEnabled("layout") ?? false;
@@ -47330,6 +48314,22 @@ function createLayoutEngine(options = {}) {
47330
48314
  deriveDocumentPageSnapshots(splicedGraph)
47331
48315
  );
47332
48316
  const pageCountDelta = currentPageCount !== previousPageCount ? { previous: previousPageCount, current: currentPageCount } : void 0;
48317
+ const priorMapper = cachedFull?.mapper ?? null;
48318
+ commitSlot({
48319
+ key: {
48320
+ content: document2.content,
48321
+ styles: document2.styles,
48322
+ subParts: document2.subParts,
48323
+ viewportWindowKey: FULL_VIEWPORT_WINDOW_KEY
48324
+ },
48325
+ graph: splicedGraph,
48326
+ formatting,
48327
+ mapper: rebuildMapper(
48328
+ priorMapper ?? createPageFragmentMapper(splicedGraph),
48329
+ splicedGraph,
48330
+ firstDirty
48331
+ )
48332
+ });
47333
48333
  if (pageCountDelta) {
47334
48334
  emit({
47335
48335
  kind: "page_count_changed",
@@ -47359,19 +48359,6 @@ function createLayoutEngine(options = {}) {
47359
48359
  ...dirtyFamilies.length > 0 ? { dirtyFieldFamilies: dirtyFamilies } : {},
47360
48360
  ...pageCountDelta ? { pageCountDelta } : {}
47361
48361
  });
47362
- cachedKey = {
47363
- content: document2.content,
47364
- styles: document2.styles,
47365
- subParts: document2.subParts,
47366
- viewportWindowKey: FULL_VIEWPORT_WINDOW_KEY
47367
- };
47368
- cachedGraph = splicedGraph;
47369
- cachedFormatting = formatting;
47370
- cachedMapper = rebuildMapper(
47371
- cachedMapper ?? createPageFragmentMapper(splicedGraph),
47372
- splicedGraph,
47373
- firstDirty
47374
- );
47375
48362
  if (telemetryOn) {
47376
48363
  emitRecomputeCompleted(
47377
48364
  "bounded",
@@ -47388,13 +48375,14 @@ function createLayoutEngine(options = {}) {
47388
48375
  const document2 = input.document;
47389
48376
  const normalizedWindow = normalizeViewportPageWindow(input.viewportPageWindow);
47390
48377
  const currentViewportWindowKey = viewportWindowKey(normalizedWindow);
47391
- const keyEqual = cachedGraph !== null && cachedKey !== null && cachedKey.content === document2.content && cachedKey.styles === document2.styles && cachedKey.subParts === document2.subParts && cachedKey.viewportWindowKey === currentViewportWindowKey;
48378
+ const slot = getCachedSlot(currentViewportWindowKey);
48379
+ const keyEqual = slot !== null && slot.key.content === document2.content && slot.key.styles === document2.styles && slot.key.subParts === document2.subParts && slot.key.viewportWindowKey === currentViewportWindowKey;
47392
48380
  if (keyEqual && pendingInvalidation === null) {
47393
- return cachedGraph;
48381
+ return slot.graph;
47394
48382
  }
47395
48383
  const pending = pendingInvalidation;
47396
48384
  pendingInvalidation = null;
47397
- if (pending !== null && pending.result.scope === "bounded" && cachedGraph !== null && normalizedWindow === void 0) {
48385
+ if (pending !== null && pending.result.scope === "bounded" && cachedFull !== null && normalizedWindow === void 0) {
47398
48386
  const spliced = incrementalRelayout(input, pending);
47399
48387
  if (spliced !== null) {
47400
48388
  return spliced;
@@ -47403,16 +48391,39 @@ function createLayoutEngine(options = {}) {
47403
48391
  }
47404
48392
  return fullRebuild(input, pending?.reason);
47405
48393
  }
48394
+ function ensureSlotMapperAndFormatting(slot, document2) {
48395
+ if (slot.mapper === null) {
48396
+ slot.mapper = createPageFragmentMapper(slot.graph);
48397
+ }
48398
+ if (slot.formatting === null) {
48399
+ const mainSurface = createEditorSurfaceSnapshot(
48400
+ document2,
48401
+ createSelectionSnapshot(0, 0),
48402
+ MAIN_STORY_TARGET
48403
+ );
48404
+ slot.formatting = buildResolvedFormattingState(document2, mainSurface);
48405
+ }
48406
+ }
47406
48407
  function getMapper(input) {
47407
48408
  getGraphInternal(input);
47408
- return cachedMapper;
48409
+ const currentViewportWindowKey = viewportWindowKey(
48410
+ normalizeViewportPageWindow(input.viewportPageWindow)
48411
+ );
48412
+ const slot = getCachedSlot(currentViewportWindowKey);
48413
+ ensureSlotMapperAndFormatting(slot, input.document);
48414
+ return slot.mapper;
47409
48415
  }
47410
48416
  function getFormatting(input) {
47411
48417
  getGraphInternal(input);
47412
- return cachedFormatting;
48418
+ const currentViewportWindowKey = viewportWindowKey(
48419
+ normalizeViewportPageWindow(input.viewportPageWindow)
48420
+ );
48421
+ const slot = getCachedSlot(currentViewportWindowKey);
48422
+ ensureSlotMapperAndFormatting(slot, input.document);
48423
+ return slot.formatting;
47413
48424
  }
47414
48425
  if (autoUpgradeToCanvas && options.measurementProvider === void 0 && typeof document !== "undefined" && typeof HTMLCanvasElement !== "undefined") {
47415
- const readCachedRevision = () => cachedGraph?.revision ?? 0;
48426
+ const readCachedRevision = () => preferredCachedGraph()?.revision ?? 0;
47416
48427
  void (async () => {
47417
48428
  try {
47418
48429
  const mod = await Promise.resolve().then(() => (init_measurement_backend_canvas(), measurement_backend_canvas_exports));
@@ -47422,10 +48433,7 @@ function createLayoutEngine(options = {}) {
47422
48433
  options.measurementCache,
47423
48434
  telemetryBus
47424
48435
  );
47425
- cachedKey = null;
47426
- cachedGraph = null;
47427
- cachedFormatting = null;
47428
- cachedMapper = null;
48436
+ clearAllSlots();
47429
48437
  emit({
47430
48438
  kind: "measurement_backend_ready",
47431
48439
  revision: readCachedRevision(),
@@ -47469,22 +48477,19 @@ function createLayoutEngine(options = {}) {
47469
48477
  return getMapper(input);
47470
48478
  },
47471
48479
  invalidate(reason) {
47472
- const result = analyzeInvalidation(reason, cachedGraph);
48480
+ const result = analyzeInvalidation(reason, preferredCachedGraph());
47473
48481
  for (const family of result.dirtyFieldFamilies) {
47474
48482
  dirtyFieldFamilies.add(family);
47475
48483
  }
47476
48484
  if (result.scope === "bounded") {
47477
48485
  pendingInvalidation = { reason, result };
47478
48486
  } else {
47479
- cachedKey = null;
47480
- cachedGraph = null;
47481
- cachedFormatting = null;
47482
- cachedMapper = null;
48487
+ clearAllSlots();
47483
48488
  pendingInvalidation = { reason, result };
47484
48489
  }
47485
48490
  },
47486
48491
  analyzeInvalidation(reason) {
47487
- return analyzeInvalidation(reason, cachedGraph);
48492
+ return analyzeInvalidation(reason, preferredCachedGraph());
47488
48493
  },
47489
48494
  getDirtyFieldFamilies() {
47490
48495
  return Array.from(dirtyFieldFamilies);
@@ -47512,14 +48517,11 @@ function createLayoutEngine(options = {}) {
47512
48517
  telemetryBus
47513
48518
  );
47514
48519
  if (previousFidelity !== provider.fidelity) {
47515
- cachedKey = null;
47516
- cachedGraph = null;
47517
- cachedFormatting = null;
47518
- cachedMapper = null;
48520
+ clearAllSlots();
47519
48521
  }
47520
48522
  emit({
47521
48523
  kind: "measurement_backend_ready",
47522
- revision: cachedGraph?.revision ?? 0,
48524
+ revision: preferredCachedGraph()?.revision ?? 0,
47523
48525
  fidelity: provider.fidelity
47524
48526
  });
47525
48527
  },
@@ -47534,30 +48536,33 @@ function createLayoutEngine(options = {}) {
47534
48536
  */
47535
48537
  invalidateMeasurementCache() {
47536
48538
  measurementProvider.invalidateCache();
47537
- cachedKey = null;
47538
- cachedGraph = null;
47539
- cachedFormatting = null;
47540
- cachedMapper = null;
48539
+ clearAllSlots();
47541
48540
  },
47542
48541
  getMeasurementCacheStats() {
47543
48542
  if (!isCachedLayoutMeasurementProvider(measurementProvider)) return null;
47544
48543
  return measurementProvider.measurementCacheStats();
47545
48544
  },
47546
48545
  /**
47547
- * L7 Phase 2.5 — seed the cached graph from a prerender envelope.
47548
- * Populates both `cachedGraph` and `cachedKey` (keyed on the provided
47549
- * document's identity-equal slots) so the next getPageGraph query
47550
- * returns the seeded graph directly. Any subsequent mutation
47551
- * invalidates normally through the existing path.
48546
+ * L7 Phase 2.5 — seed the full-slot cached graph from a prerender
48547
+ * envelope. Populates the full slot (graph + key, with formatting and
48548
+ * mapper computed lazily on first read) so the next viewport-
48549
+ * independent `getPageGraph` query returns the seeded graph directly.
48550
+ * Any subsequent mutation invalidates normally through the existing
48551
+ * path; sibling eviction in `commitSlot` clears `cachedWindowed` if
48552
+ * it carried a different document tuple.
47552
48553
  */
47553
48554
  seedCachedGraph(graph, document2) {
47554
- cachedGraph = graph;
47555
- cachedKey = {
47556
- content: document2.content,
47557
- styles: document2.styles,
47558
- subParts: document2.subParts,
47559
- viewportWindowKey: FULL_VIEWPORT_WINDOW_KEY
47560
- };
48555
+ commitSlot({
48556
+ key: {
48557
+ content: document2.content,
48558
+ styles: document2.styles,
48559
+ subParts: document2.subParts,
48560
+ viewportWindowKey: FULL_VIEWPORT_WINDOW_KEY
48561
+ },
48562
+ graph,
48563
+ formatting: null,
48564
+ mapper: null
48565
+ });
47561
48566
  previousPageCount = graph.contentPageCount;
47562
48567
  }
47563
48568
  };
@@ -47825,7 +48830,7 @@ function attachScopeCardModel(input) {
47825
48830
  primaryAnchorRect: null,
47826
48831
  ...anchor ? { anchor } : {},
47827
48832
  ...issue ? { issue } : {},
47828
- suggestionGroupIds: suggestionGroups.map((group) => group.groupId),
48833
+ suggestionGroupIds: suggestionGroups.map((group2) => group2.groupId),
47829
48834
  suggestionGroups,
47830
48835
  reviewActionCount: reviewActions.length,
47831
48836
  reviewActions,
@@ -47836,7 +48841,7 @@ function attachScopeCardModel(input) {
47836
48841
  }
47837
48842
  function resolveSuggestionGroupsForIssue(issueId, suggestions) {
47838
48843
  if (!issueId || !suggestions?.groups) return [];
47839
- return suggestions.groups.filter((group) => group.issueId === issueId);
48844
+ return suggestions.groups.filter((group2) => group2.issueId === issueId);
47840
48845
  }
47841
48846
  function resolveReviewActionsForIssue(issueId, metadata, externalResolutions) {
47842
48847
  if (!issueId || !metadata || metadata.length === 0) return [];
@@ -47911,39 +48916,8 @@ function insertScopeMarkers(document2, params) {
47911
48916
  to: normalizedTo
47912
48917
  };
47913
48918
  }
47914
- const paraSlots = [];
47915
- let cursor = 0;
47916
- let fromBlockIndex = -1;
47917
- let fromBlockKind = null;
47918
- let toBlockIndex = -1;
47919
- let toBlockKind = null;
47920
- let storyLength = 0;
47921
- for (let i = 0; i < root.children.length; i += 1) {
47922
- const block = root.children[i];
47923
- const blockFrom = cursor;
47924
- let blockLength;
47925
- if (block.type === "paragraph") {
47926
- blockLength = block.children.reduce(
47927
- (total, child) => total + inlineLength4(child),
47928
- 0
47929
- );
47930
- paraSlots.push({ index: i, from: blockFrom, to: blockFrom + blockLength });
47931
- } else {
47932
- blockLength = 1;
47933
- }
47934
- const blockTo = blockFrom + blockLength;
47935
- if (fromBlockIndex === -1 && normalizedFrom >= blockFrom && normalizedFrom <= blockTo) {
47936
- fromBlockIndex = i;
47937
- fromBlockKind = block.type;
47938
- }
47939
- if (toBlockIndex === -1 && normalizedTo >= blockFrom && normalizedTo <= blockTo) {
47940
- toBlockIndex = i;
47941
- toBlockKind = block.type;
47942
- }
47943
- cursor = blockTo;
47944
- if (i < root.children.length - 1) cursor += 1;
47945
- storyLength = cursor;
47946
- }
48919
+ const layout = computeScopeStoryLayout(document2);
48920
+ const storyLength = layout.storyLength;
47947
48921
  if (normalizedFrom < 0 || normalizedTo > storyLength) {
47948
48922
  return {
47949
48923
  status: "range-out-of-bounds",
@@ -47953,73 +48927,71 @@ function insertScopeMarkers(document2, params) {
47953
48927
  storyLength
47954
48928
  };
47955
48929
  }
47956
- if (fromBlockIndex === -1 || toBlockIndex === -1) {
47957
- return {
47958
- status: "range-out-of-bounds",
47959
- scopeId,
47960
- from: normalizedFrom,
47961
- to: normalizedTo,
47962
- storyLength
47963
- };
47964
- }
47965
- if (fromBlockKind !== "paragraph" || toBlockKind !== "paragraph") {
47966
- const nonParaIndex = fromBlockKind !== "paragraph" ? fromBlockIndex : toBlockIndex;
47967
- const nonParaKind = fromBlockKind !== "paragraph" ? fromBlockKind : toBlockKind;
48930
+ const startSlot = findParagraphSlotAtPosition(
48931
+ layout,
48932
+ normalizedFrom,
48933
+ "start"
48934
+ );
48935
+ const endSlot = findParagraphSlotAtPosition(layout, normalizedTo, "end");
48936
+ if (!startSlot || !endSlot) {
48937
+ const offenderPosition = !startSlot ? normalizedFrom : normalizedTo;
48938
+ const owner = findOwningBlockSlotAtPosition(layout, offenderPosition);
47968
48939
  return {
47969
48940
  status: "non-paragraph-target",
47970
48941
  scopeId,
47971
48942
  from: normalizedFrom,
47972
48943
  to: normalizedTo,
47973
- blockIndex: nonParaIndex,
47974
- blockKind: nonParaKind ?? "unknown"
48944
+ blockIndex: owner?.rootBlockIndex ?? -1,
48945
+ blockKind: owner?.kind ?? "unknown"
47975
48946
  };
47976
48947
  }
47977
- const startSlot = paraSlots.find((s) => s.index === fromBlockIndex);
47978
- const endSlot = paraSlots.find((s) => s.index === toBlockIndex);
47979
- if (startSlot.index === endSlot.index) {
48948
+ if (sameScopeParagraphPath(startSlot.path, endSlot.path)) {
47980
48949
  const newChildren = injectMarkersIntoInlineList(
47981
- root.children[startSlot.index].children,
48950
+ startSlot.paragraph.children,
47982
48951
  scopeId,
47983
48952
  normalizedFrom - startSlot.from,
47984
48953
  normalizedTo - startSlot.from,
47985
48954
  "both"
47986
48955
  );
47987
- const children2 = root.children.map(
47988
- (block, i) => i === startSlot.index ? { ...block, children: newChildren } : block
48956
+ const nextRoot = replaceParagraphChildrenAtPath(
48957
+ root,
48958
+ startSlot.path,
48959
+ newChildren
47989
48960
  );
47990
48961
  return {
47991
48962
  status: "planted",
47992
- document: { ...document2, content: { ...root, children: children2 } },
48963
+ document: { ...document2, content: nextRoot },
47993
48964
  scopeId,
47994
48965
  plantedRange: { from: normalizedFrom, to: normalizedTo }
47995
48966
  };
47996
48967
  }
47997
- const children = root.children.map((block, i) => {
47998
- if (i === startSlot.index) {
47999
- const newChildren = injectMarkersIntoInlineList(
48000
- block.children,
48001
- scopeId,
48002
- normalizedFrom - startSlot.from,
48003
- Number.POSITIVE_INFINITY,
48004
- "start-only"
48005
- );
48006
- return { ...block, children: newChildren };
48007
- }
48008
- if (i === endSlot.index) {
48009
- const newChildren = injectMarkersIntoInlineList(
48010
- block.children,
48011
- scopeId,
48012
- Number.NEGATIVE_INFINITY,
48013
- normalizedTo - endSlot.from,
48014
- "end-only"
48015
- );
48016
- return { ...block, children: newChildren };
48017
- }
48018
- return block;
48019
- });
48968
+ const startChildren = injectMarkersIntoInlineList(
48969
+ startSlot.paragraph.children,
48970
+ scopeId,
48971
+ normalizedFrom - startSlot.from,
48972
+ Number.POSITIVE_INFINITY,
48973
+ "start-only"
48974
+ );
48975
+ const endChildren = injectMarkersIntoInlineList(
48976
+ endSlot.paragraph.children,
48977
+ scopeId,
48978
+ Number.NEGATIVE_INFINITY,
48979
+ normalizedTo - endSlot.from,
48980
+ "end-only"
48981
+ );
48982
+ const rootWithStart = replaceParagraphChildrenAtPath(
48983
+ root,
48984
+ startSlot.path,
48985
+ startChildren
48986
+ );
48987
+ const rootWithBoth = replaceParagraphChildrenAtPath(
48988
+ rootWithStart,
48989
+ endSlot.path,
48990
+ endChildren
48991
+ );
48020
48992
  return {
48021
48993
  status: "planted",
48022
- document: { ...document2, content: { ...root, children } },
48994
+ document: { ...document2, content: rootWithBoth },
48023
48995
  scopeId,
48024
48996
  plantedRange: { from: normalizedFrom, to: normalizedTo }
48025
48997
  };
@@ -48027,43 +48999,15 @@ function insertScopeMarkers(document2, params) {
48027
48999
  function removeScopeMarkers(document2, scopeId) {
48028
49000
  const root = document2.content;
48029
49001
  if (!root || root.type !== "doc") return document2;
48030
- let mutated = false;
48031
- const children = root.children.map((block) => {
48032
- if (block.type !== "paragraph") return block;
48033
- const kept = block.children.filter((child) => {
48034
- if ((child.type === "scope_marker_start" || child.type === "scope_marker_end") && child.scopeId === scopeId) {
48035
- mutated = true;
48036
- return false;
48037
- }
48038
- return true;
48039
- });
48040
- if (kept.length === block.children.length) return block;
48041
- return { ...block, children: kept };
48042
- });
48043
- if (!mutated) return document2;
49002
+ const result = removeScopeMarkersFromBlockList(root.children, scopeId);
49003
+ if (!result.mutated) return document2;
48044
49004
  return {
48045
49005
  ...document2,
48046
- content: { ...root, children }
49006
+ content: { ...root, children: result.blocks }
48047
49007
  };
48048
49008
  }
48049
49009
  function inlineLength4(node) {
48050
- switch (node.type) {
48051
- case "text":
48052
- return Array.from(node.text).length;
48053
- case "hyperlink":
48054
- case "field":
48055
- return node.children.reduce(
48056
- (total, child) => total + inlineLength4(child),
48057
- 0
48058
- );
48059
- case "bookmark_start":
48060
- case "bookmark_end":
48061
- case "scope_marker_start":
48062
- case "scope_marker_end":
48063
- return 0;
48064
- default:
48065
- return 1;
48066
- }
49010
+ return inlineLengthForScopeCoordinates(node);
48067
49011
  }
48068
49012
  function injectMarkersIntoInlineList(inlines, scopeId, startOffset, endOffset, mode) {
48069
49013
  const start = { type: "scope_marker_start", scopeId };
@@ -48331,11 +49275,11 @@ function projectEntries(kind, input) {
48331
49275
  }
48332
49276
  function projectIssueEntries(input) {
48333
49277
  const suggestionGroupsByIssueId = /* @__PURE__ */ new Map();
48334
- for (const group of input.suggestions?.groups ?? []) {
48335
- if (!group.issueId) continue;
48336
- const ids = suggestionGroupsByIssueId.get(group.issueId) ?? [];
48337
- ids.push(group.groupId);
48338
- suggestionGroupsByIssueId.set(group.issueId, ids);
49278
+ for (const group2 of input.suggestions?.groups ?? []) {
49279
+ if (!group2.issueId) continue;
49280
+ const ids = suggestionGroupsByIssueId.get(group2.issueId) ?? [];
49281
+ ids.push(group2.groupId);
49282
+ suggestionGroupsByIssueId.set(group2.issueId, ids);
48339
49283
  }
48340
49284
  return (input.workflowMarkup?.metadata ?? []).filter((entry) => entry.metadataId === ISSUE_METADATA_ID).map((entry) => {
48341
49285
  const issueValue = isRecord3(entry.value) ? entry.value : void 0;
@@ -50696,13 +51640,13 @@ function createLayoutFacet(input) {
50696
51640
  createSelectionSnapshot(0, 0)
50697
51641
  );
50698
51642
  let cursor = 0;
50699
- for (const group of groups) {
50700
- for (let i = 0; i < group.count; i += 1) {
51643
+ for (const group2 of groups) {
51644
+ for (let i = 0; i < group2.count; i += 1) {
50701
51645
  const blockSnapshot = surface.blocks[cursor + i];
50702
51646
  if (!blockSnapshot) continue;
50703
51647
  blocks.push({
50704
51648
  blockId: blockSnapshot.blockId,
50705
- fragmentId: `endnote-${group.noteId}-${i}`,
51649
+ fragmentId: `endnote-${group2.noteId}-${i}`,
50706
51650
  pageIndex: -1,
50707
51651
  regionKind: "endnote-area",
50708
51652
  runtimeFromOffset: blockSnapshot.from,
@@ -50711,7 +51655,7 @@ function createLayoutFacet(input) {
50711
51655
  blockSnapshot
50712
51656
  });
50713
51657
  }
50714
- cursor += group.count;
51658
+ cursor += group2.count;
50715
51659
  }
50716
51660
  }
50717
51661
  }
@@ -51540,6 +52484,13 @@ function cloneNumberingLayoutFacts(numbering) {
51540
52484
  ...numbering.numberingSourceRef !== void 0 ? { numberingSourceRef: { ...numbering.numberingSourceRef } } : {},
51541
52485
  ...numbering.numberingInstanceSourceRef !== void 0 ? { numberingInstanceSourceRef: { ...numbering.numberingInstanceSourceRef } } : {},
51542
52486
  ...numbering.abstractNumberingSourceRef !== void 0 ? { abstractNumberingSourceRef: { ...numbering.abstractNumberingSourceRef } } : {},
52487
+ ...numbering.markerTextPosture !== void 0 ? { markerTextPosture: { ...numbering.markerTextPosture } } : {},
52488
+ ...numbering.pictureBulletPosture !== void 0 ? {
52489
+ pictureBulletPosture: {
52490
+ ...numbering.pictureBulletPosture,
52491
+ ...numbering.pictureBulletPosture.sourceRef !== void 0 ? { sourceRef: { ...numbering.pictureBulletPosture.sourceRef } } : {}
52492
+ }
52493
+ } : {},
51543
52494
  ...numbering.markerLane !== void 0 ? { markerLane: { ...numbering.markerLane } } : {},
51544
52495
  ...numbering.textColumn !== void 0 ? { textColumn: { ...numbering.textColumn } } : {},
51545
52496
  ...numbering.tabStops !== void 0 ? { tabStops: numbering.tabStops.map((tab) => ({ ...tab })) } : {}
@@ -52099,9 +53050,9 @@ function resolveFootnoteAreaRegionBlocks(node, document2) {
52099
53050
  );
52100
53051
  const blocks = [];
52101
53052
  let cursor = 0;
52102
- for (const group of groups) {
52103
- const fragmentBase = group.allocation.fragmentId ?? `note-${node.pageIndex}-${group.allocation.noteId}`;
52104
- for (let i = 0; i < group.count; i += 1) {
53053
+ for (const group2 of groups) {
53054
+ const fragmentBase = group2.allocation.fragmentId ?? `note-${node.pageIndex}-${group2.allocation.noteId}`;
53055
+ for (let i = 0; i < group2.count; i += 1) {
52105
53056
  const blockSnapshot = surface.blocks[cursor + i];
52106
53057
  if (!blockSnapshot) continue;
52107
53058
  blocks.push({
@@ -52111,11 +53062,11 @@ function resolveFootnoteAreaRegionBlocks(node, document2) {
52111
53062
  regionKind: "footnote-area",
52112
53063
  runtimeFromOffset: blockSnapshot.from,
52113
53064
  runtimeToOffset: blockSnapshot.to,
52114
- heightTwips: group.allocation.reservedHeightTwips,
53065
+ heightTwips: group2.allocation.reservedHeightTwips,
52115
53066
  blockSnapshot
52116
53067
  });
52117
53068
  }
52118
- cursor += group.count;
53069
+ cursor += group2.count;
52119
53070
  }
52120
53071
  return Object.freeze(blocks);
52121
53072
  }
@@ -54902,6 +55853,14 @@ function createDocumentRuntime(options) {
54902
55853
  let effectiveMarkupModeProvider;
54903
55854
  const perfCounters = new PerfCounters();
54904
55855
  const hotEditTraces = new HotEditTraceRecorder();
55856
+ const scopeSurfaceTelemetry = {
55857
+ onPrecomputedSurfaceHit: () => {
55858
+ perfCounters.increment("surface.scope.precomputedSurfaceHit");
55859
+ },
55860
+ onScopeSurfaceBuild: () => {
55861
+ perfCounters.increment("surface.scope.builds");
55862
+ }
55863
+ };
54905
55864
  let cachedHotEditPolicy = null;
54906
55865
  function getHotEditPolicy() {
54907
55866
  if (cachedHotEditPolicy?.document === state.document) {
@@ -55350,7 +56309,7 @@ function createDocumentRuntime(options) {
55350
56309
  viewportRangesKey: rangesKey,
55351
56310
  snapshot: surface
55352
56311
  };
55353
- const fullSurface = fullSurfaceForCache ?? (surface.viewportBlockRanges === null ? surface : void 0);
56312
+ const fullSurface = fullSurfaceForCache?.viewportBlockRanges === null ? fullSurfaceForCache : surface.viewportBlockRanges === null ? surface : void 0;
55354
56313
  if (fullSurface) {
55355
56314
  cachedFullSurface = {
55356
56315
  content: state.document.content,
@@ -56913,6 +57872,7 @@ function createDocumentRuntime(options) {
56913
57872
  documentMode: workflowCoordinator.getEffectiveDocumentMode(commandSelection),
56914
57873
  defaultAuthorId: defaultAuthorId ?? void 0,
56915
57874
  renderSnapshot: cachedRenderSnapshot,
57875
+ surfaceTelemetry: scopeSurfaceTelemetry,
56916
57876
  activeStoryKey: canonicalEditableTargetStoryKey(activeStory),
56917
57877
  editableTargetCache: editableTargetBlockCache,
56918
57878
  ...resolvedFragmentTextTarget ? { textTarget: resolvedFragmentTextTarget } : {}
@@ -57282,9 +58242,9 @@ function createDocumentRuntime(options) {
57282
58242
  emitError(toRuntimeError(error));
57283
58243
  }
57284
58244
  },
57285
- applyFormattingOperation(operation) {
58245
+ applyFormattingOperation(operation2) {
57286
58246
  try {
57287
- const commandName = getFormattingOperationCommandName(operation);
58247
+ const commandName = getFormattingOperationCommandName(operation2);
57288
58248
  const snapshot = cachedRenderSnapshot;
57289
58249
  if (!snapshot.isReady || snapshot.readOnly || snapshot.fatalError) {
57290
58250
  return;
@@ -57312,11 +58272,11 @@ function createDocumentRuntime(options) {
57312
58272
  };
57313
58273
  const suggesting = workflowCoordinator.getEffectiveDocumentMode(state.selection) === "suggesting";
57314
58274
  const timestamp = clock();
57315
- if (snapshot.selection.isCollapsed && operation.type !== "set-alignment" && operation.type !== "indent" && operation.type !== "outdent") {
58275
+ if (snapshot.selection.isCollapsed && operation2.type !== "set-alignment" && operation2.type !== "indent" && operation2.type !== "outdent") {
57316
58276
  const storyKey2 = storyTargetKey(activeStory);
57317
58277
  const nextMarks = updatePendingInsertionMarks(
57318
58278
  pendingInsertionMarksByStory.get(storyKey2)?.marks ?? marksFromFormattingState(getFormattingStateFromRenderSnapshot(snapshot)),
57319
- operation
58279
+ operation2
57320
58280
  );
57321
58281
  if (nextMarks && nextMarks.length > 0) {
57322
58282
  pendingInsertionMarksByStory.set(storyKey2, {
@@ -57331,7 +58291,7 @@ function createDocumentRuntime(options) {
57331
58291
  return;
57332
58292
  }
57333
58293
  if (suggesting) {
57334
- if (operation.type === "set-alignment" || operation.type === "indent" || operation.type === "outdent") {
58294
+ if (operation2.type === "set-alignment" || operation2.type === "indent" || operation2.type === "outdent") {
57335
58295
  const paragraphContext = resolveActiveParagraphContext(localSnapshot);
57336
58296
  if (!paragraphContext) {
57337
58297
  return;
@@ -57340,7 +58300,7 @@ function createDocumentRuntime(options) {
57340
58300
  const result3 = applyFormattingOperationToDocument(
57341
58301
  localDocument,
57342
58302
  localSnapshot,
57343
- operation
58303
+ operation2
57344
58304
  );
57345
58305
  if (!result3.changed) {
57346
58306
  return;
@@ -57387,7 +58347,7 @@ function createDocumentRuntime(options) {
57387
58347
  const result2 = applyFormattingOperationToDocument(
57388
58348
  localDocument,
57389
58349
  localSnapshot,
57390
- operation
58350
+ operation2
57391
58351
  );
57392
58352
  if (!result2.changed) {
57393
58353
  return;
@@ -57422,7 +58382,7 @@ function createDocumentRuntime(options) {
57422
58382
  const result = applyFormattingOperationToDocument(
57423
58383
  localDocument,
57424
58384
  localSnapshot,
57425
- operation
58385
+ operation2
57426
58386
  );
57427
58387
  if (!result.changed) {
57428
58388
  return;
@@ -57669,7 +58629,7 @@ function createDocumentRuntime(options) {
57669
58629
  if (step.kind !== "formatting-apply" || !step.range || !step.formattingAction) {
57670
58630
  continue;
57671
58631
  }
57672
- const operation = step.formattingAction.kind === "clear-mark" ? {
58632
+ const operation2 = step.formattingAction.kind === "clear-mark" ? {
57673
58633
  type: "clear-mark",
57674
58634
  mark: step.formattingAction.mark,
57675
58635
  ...step.formattingAction.expandToFullHighlight === true ? { expandToFullHighlight: true } : {}
@@ -57680,7 +58640,7 @@ function createDocumentRuntime(options) {
57680
58640
  const result = applyTextMarkOperationToDocumentRange(
57681
58641
  state.document,
57682
58642
  step.range,
57683
- operation
58643
+ operation2
57684
58644
  );
57685
58645
  if (!result.changed) {
57686
58646
  continue;
@@ -59185,7 +60145,8 @@ function createDocumentRuntime(options) {
59185
60145
  applyViewportRanges(getSelectionCorridorViewportRanges(cachedRenderSnapshot.surface));
59186
60146
  }
59187
60147
  const tValidation0 = performance.now();
59188
- const patchedFullLocalTextSurface = useLocalTextCommitSnapshot ? tryPatchLocalTextSurface(cachedRenderSnapshot.surface, transaction.mapping) : null;
60148
+ const patchSourceSurface = getReusableCachedFullSurface(previous.document, activeStory) ?? cachedRenderSnapshot.surface;
60149
+ const patchedFullLocalTextSurface = useLocalTextCommitSnapshot ? tryPatchLocalTextSurface(patchSourceSurface, transaction.mapping) : null;
59189
60150
  const patchedLocalTextSurface = patchedFullLocalTextSurface ? createLocalTextCorridorSurfaceFromFullSurface(patchedFullLocalTextSurface) : null;
59190
60151
  if (patchedLocalTextSurface) {
59191
60152
  cachePatchedLocalTextSurface(
@@ -59529,11 +60490,14 @@ function createDocumentRuntime(options) {
59529
60490
  }
59530
60491
  const listBoundaryDeleteUsesStoryText = targetResolution?.kind === "accepted" && editableTarget?.listAddress?.operationScope === "list-text" && isTopLevelMainStoryBlockPath(editableTarget.blockPath) && selection.isCollapsed && (commandForDispatch.type === "text.delete-backward" && selection.anchor === targetResolution.range.from || commandForDispatch.type === "text.delete-forward" && selection.anchor === targetResolution.range.to);
59531
60492
  const textTarget = targetResolution?.kind === "accepted" && !listBoundaryDeleteUsesStoryText ? targetResolution.textTarget : legacyTextTarget;
60493
+ const fullScopeSurface = cachedFullSurface?.snapshot;
59532
60494
  const context = {
59533
60495
  timestamp,
59534
60496
  documentMode: textOptions.documentModeOverride ?? workflowCoordinator.getEffectiveDocumentMode(selection),
59535
60497
  defaultAuthorId: defaultAuthorId ?? void 0,
59536
60498
  renderSnapshot: cachedRenderSnapshot,
60499
+ surfaceTelemetry: scopeSurfaceTelemetry,
60500
+ ...fullScopeSurface ? { precomputedSurface: fullScopeSurface } : {},
59537
60501
  activeStoryKey: canonicalEditableTargetStoryKey(activeStory),
59538
60502
  editableTargetCache: editableTargetBlockCache,
59539
60503
  activeStorySize: cachedRenderSnapshot.surface?.storySize,
@@ -59859,6 +60823,7 @@ function createDocumentRuntime(options) {
59859
60823
  documentMode: workflowCoordinator.getEffectiveDocumentMode(state.selection),
59860
60824
  defaultAuthorId: defaultAuthorId ?? void 0,
59861
60825
  renderSnapshot: cachedRenderSnapshot,
60826
+ surfaceTelemetry: scopeSurfaceTelemetry,
59862
60827
  activeStoryKey: canonicalEditableTargetStoryKey(activeStory),
59863
60828
  editableTargetCache: editableTargetBlockCache
59864
60829
  };
@@ -60263,22 +61228,22 @@ function marksFromFormattingState(formatting) {
60263
61228
  }
60264
61229
  return marks;
60265
61230
  }
60266
- function updatePendingInsertionMarks(currentMarks, operation) {
60267
- switch (operation.type) {
61231
+ function updatePendingInsertionMarks(currentMarks, operation2) {
61232
+ switch (operation2.type) {
60268
61233
  case "toggle":
60269
- return togglePendingMark(currentMarks, operation.mark);
61234
+ return togglePendingMark(currentMarks, operation2.mark);
60270
61235
  case "set-font-family":
60271
- return setPendingMarkValue(currentMarks, "fontFamily", operation.fontFamily?.trim() || null);
61236
+ return setPendingMarkValue(currentMarks, "fontFamily", operation2.fontFamily?.trim() || null);
60272
61237
  case "set-font-size":
60273
61238
  return setPendingMarkValue(
60274
61239
  currentMarks,
60275
61240
  "fontSize",
60276
- typeof operation.size === "number" && Number.isFinite(operation.size) ? Math.round(operation.size * 2) : null
61241
+ typeof operation2.size === "number" && Number.isFinite(operation2.size) ? Math.round(operation2.size * 2) : null
60277
61242
  );
60278
61243
  case "set-text-color":
60279
- return setPendingMarkValue(currentMarks, "textColor", normalizePendingColor(operation.color));
61244
+ return setPendingMarkValue(currentMarks, "textColor", normalizePendingColor(operation2.color));
60280
61245
  case "set-highlight-color":
60281
- return setPendingMarkValue(currentMarks, "backgroundColor", normalizePendingColor(operation.color));
61246
+ return setPendingMarkValue(currentMarks, "backgroundColor", normalizePendingColor(operation2.color));
60282
61247
  }
60283
61248
  }
60284
61249
  function togglePendingMark(marks, mark) {
@@ -62441,10 +63406,10 @@ function toInternalSelectionSnapshot2(selection) {
62441
63406
  )
62442
63407
  };
62443
63408
  }
62444
- function getFormattingOperationCommandName(operation) {
62445
- switch (operation.type) {
63409
+ function getFormattingOperationCommandName(operation2) {
63410
+ switch (operation2.type) {
62446
63411
  case "toggle":
62447
- return `toggle${operation.mark.charAt(0).toUpperCase()}${operation.mark.slice(1)}`;
63412
+ return `toggle${operation2.mark.charAt(0).toUpperCase()}${operation2.mark.slice(1)}`;
62448
63413
  case "set-font-family":
62449
63414
  return "setFontFamily";
62450
63415
  case "set-font-size":